Date: Tue, 25 Sep 2012 20:27:42 +0000 (UTC) From: Brooks Davis <brooks@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r240925 - projects/mtree/contrib/install Message-ID: <201209252027.q8PKRgmM090268@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: brooks Date: Tue Sep 25 20:27:42 2012 New Revision: 240925 URL: http://svn.freebsd.org/changeset/base/240925 Log: Virgin import of NetBSD's install(1). Added: projects/mtree/contrib/install/ projects/mtree/contrib/install/Makefile projects/mtree/contrib/install/install.1 projects/mtree/contrib/install/pathnames.h projects/mtree/contrib/install/xinstall.c Added: projects/mtree/contrib/install/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/Makefile Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,23 @@ +# $NetBSD: Makefile,v 1.22 2011/08/17 14:00:30 christos Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +.include <bsd.own.mk> + +PROG= xinstall +SRCS= xinstall.c getid.c +MAN= install.1 + +.PATH: ${NETBSDSRCDIR}/usr.sbin/mtree +CPPFLAGS+= -I${NETBSDSRCDIR}/usr.sbin/mtree + +.if (${HOSTPROG:U} == "") +DPADD+= ${LIBUTIL} +LDADD+= -lutil +.endif + +COPTS.xinstall.c += -Wno-format-nonliteral + + +PROGNAME=install + +.include <bsd.prog.mk> Added: projects/mtree/contrib/install/install.1 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/install.1 Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,338 @@ +.\" $NetBSD: install.1,v 1.47 2012/04/08 22:00:40 wiz Exp $ +.\" +.\" Copyright (c) 1987, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)install.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd May 1, 2009 +.Dt INSTALL 1 +.Os +.Sh NAME +.Nm install +.Nd install binaries +.Sh SYNOPSIS +.Nm +.Op Fl bcprsU +.Op Fl a Ar command +.Op Fl B Ar suffix +.Op Fl D Ar destdir +.Op Fl f Ar flags +.Op Fl g Ar group +.Op Fl h Ar hash +.Op Fl l Ar linkflags +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl S Ar stripflag +.Op Fl T Ar tags +.Ar file1 file2 +.Nm +.Op Fl bcprsU +.Op Fl a Ar command +.Op Fl B Ar suffix +.Op Fl D Ar destdir +.Op Fl f Ar flags +.Op Fl g Ar group +.Op Fl h Ar hash +.Op Fl l Ar linkflags +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl S Ar stripflag +.Op Fl T Ar tags +.Ar file1 ...\& +.Ar fileN directory +.Nm +.Fl d +.Op Fl pU +.Op Fl a Ar command +.Op Fl D Ar destdir +.Op Fl g Ar group +.Op Fl M Ar metalog +.Op Fl m Ar mode +.Op Fl N Ar dbdir +.Op Fl o Ar owner +.Op Fl T Ar tags +.Ar directory ...\& +.Sh DESCRIPTION +The file(s) are copied +(or linked if the +.Fl l +option is specified) to the target file or directory. +If the destination is a directory, then the +.Ar file +is copied into +.Ar directory +with its original filename. +If the target file already exists, it is +either renamed to +.Ar file.old +if the +.Fl b +option is given +or overwritten +if permissions allow; an alternate backup suffix may be specified via the +.Fl B +option's argument. +.Pp +.Bl -tag -width XsXXstripflagsXX +.It Fl a Ar command +Run +.Ar command +on the target after installation and stripping +.Pq Fl s , +but before +ownership, permissions or timestamps are set and before renaming +.Pq Fl r +occurs. +.Ar command +is invoked via the +.Xr sh 1 +shell, allowing a single +.Fl a +argument be to specified to +.Nm +which the shell can then tokenize. +.It Fl B Ar suffix +Use +.Ar suffix +as the backup suffix if +.Fl b +is given. +If +.Ar suffix +contains a '%' sign, a numbered backup will be performed, and the +%-pattern will be expanded using +.Xr sprintf 3 , +given an integer counter as the backup number. +The counter used starts from 0, and the first available name resulting +from the expansion is used. +.It Fl b +Backup any existing files before overwriting them by renaming +them to +.Ar file.old . See +.Fl B +for specifying a different backup suffix. +.It Fl c +Copy the file. +This is the default behavior; the flag is maintained for backwards +compatibility only. +.It Fl D Ar destdir +Specify the +.Ev DESTDIR +(top of the file hierarchy) that the items are installed in to. +If +.Fl M Ar metalog +is in use, a leading string of +.Dq Ar destdir +will be removed from the file names logged to the +.Ar metalog . +This option does not affect where the actual files are installed. +.It Fl d +Create directories. +Missing parent directories are created as required. +.It Fl f Ar flags +Specify the target's file flags. +(See +.Xr chflags 1 +for a list of possible flags and their meanings.) +.It Fl g Ar group +Specify a group. +.It Fl h Ar hash +When copying, calculate the digest of the files with +.Ar hash +to store in the +.Fl M Ar metalog . +Supported digests: +.Bl -tag -width rmd160 -offset indent +.It Sy none +No hash. +This is the default. +.It Sy md5 +The MD5 cryptographic message digest. +.It Sy rmd160 +The RMD-160 cryptographic message digest. +.It Sy sha1 +The SHA-1 cryptographic message digest. +.It Sy sha256 +The 256-bits +.Tn SHA-2 +cryptographic message digest of the file. +.It Sy sha384 +The 384-bits +.Tn SHA-2 +cryptographic message digest of the file. +.It Sy sha512 +The 512-bits +.Tn SHA-2 +cryptographic message digest of the file. +.El +.It Fl l Ar linkflags +Instead of copying the file make a link to the source. +The type of the link is determined by the +.Ar linkflags +argument. +Valid +.Ar linkflags +are: +.Ar a +(absolute), +.Ar r +(relative), +.Ar h +(hard), +.Ar s +(symbolic), +.Ar m +(mixed). +Absolute and relative have effect only for symbolic links. +Mixed links +are hard links for files on the same filesystem, symbolic otherwise. +.It Fl M Ar metalog +Write the metadata associated with each item installed to +.Ar metalog +in an +.Xr mtree 8 +.Dq full path +specification line. +The metadata includes: the file name and file type, and depending upon +other options, the owner, group, file flags, modification time, and tags. +.It Fl m Ar mode +Specify an alternative mode. +The default mode is set to rwxr-xr-x (0755). +The specified mode may be either an octal or symbolic value; see +.Xr chmod 1 +for a description of possible mode values. +.It Fl N Ar dbdir +Use the user database text file +.Pa master.passwd +and group database text file +.Pa group +from +.Ar dbdir , +rather than using the results from the system's +.Xr getpwnam 3 +and +.Xr getgrnam 3 +(and related) library calls. +.It Fl o Ar owner +Specify an owner. +.It Fl p +Preserve the source files access and modification times. +.It Fl r +Install to a temporary file and then rename the file to its final destination +name. +This can be used for precious files, to avoid truncation of the original +when error conditions (filesystem full etc.) occur. +.It Fl S Ar stripflags +.Nm +passes +.Ar stripflags +as option arguments to +.Xr strip 1 . +When +.Fl S +is used, +.Xr strip 1 +is invoked via the +.Xr sh 1 +shell, allowing a single +.Fl S +argument be to specified to +.Nm +which the shell can then tokenize. +Normally, +.Nm +invokes +.Xr strip 1 +directly. +This flag implies +.Fl s . +.It Fl s +.Nm +exec's the command +.Xr strip 1 +to strip binaries so that install can be portable over a large +number of systems and binary types. +If the environment variable +.Ev STRIP +is set, it is used as the +.Xr strip 1 +program. +.It Fl T Ar tags +Specify the +.Xr mtree 8 +tags to write out for the file when using +.Fl M Ar metalog . +.It Fl U +Indicate that install is running unprivileged, and that it should not +try to change the owner, the group, or the file flags of the destination. +The information that would have been updated can be stored in a log +file with +.Fl M Ar metalog . +.El +.Pp +By default, +.Nm +preserves all file flags, with the exception of the ``nodump'' flag. +.Pp +The +.Nm +utility attempts to prevent copying a file onto itself. +.Pp +Installing +.Pa /dev/null +creates an empty file. +.Sh ENVIRONMENT +.Bl -tag -width Fl +.It Ev STRIP +The program used to strip installed binaries when the +.Fl s +option is used. +If unspecified, +.Pa /usr/bin/strip +is used. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr chflags 1 , +.Xr chgrp 1 , +.Xr chmod 1 , +.Xr cp 1 , +.Xr mv 1 , +.Xr strip 1 , +.Xr chown 8 , +.Xr mtree 8 +.Sh HISTORY +The +.Nm +utility appeared in +.Bx 4.2 . Added: projects/mtree/contrib/install/pathnames.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/pathnames.h Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,36 @@ +/* $NetBSD: pathnames.h,v 1.6 2003/08/07 11:17:50 agc Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#ifndef _PATH_STRIP +#define _PATH_STRIP "/usr/bin/strip" +#endif Added: projects/mtree/contrib/install/xinstall.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/mtree/contrib/install/xinstall.c Tue Sep 25 20:27:42 2012 (r240925) @@ -0,0 +1,1273 @@ +/* $NetBSD: xinstall.c,v 1.115 2011/09/06 18:50:32 joerg Exp $ */ + +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#else +#define HAVE_FUTIMES 1 +#define HAVE_STRUCT_STAT_ST_FLAGS 1 +#endif + +#include <sys/cdefs.h> +#if defined(__COPYRIGHT) && !defined(lint) +__COPYRIGHT("@(#) Copyright (c) 1987, 1993\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#if defined(__RCSID) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; +#else +__RCSID("$NetBSD: xinstall.c,v 1.115 2011/09/06 18:50:32 joerg Exp $"); +#endif +#endif /* not lint */ + +#define __MKTEMP_OK__ /* All uses of mktemp have been checked */ +#include <sys/param.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/time.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <grp.h> +#include <libgen.h> +#include <paths.h> +#include <pwd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <util.h> +#include <vis.h> + +#include <md5.h> +#include <rmd160.h> +#include <sha1.h> +#include <sha2.h> + +#include "pathnames.h" +#include "mtree.h" + +#define STRIP_ARGS_MAX 32 +#define BACKUP_SUFFIX ".old" + +static int dobackup, dodir, dostrip, dolink, dopreserve, dorename, dounpriv; +static int haveopt_f, haveopt_g, haveopt_m, haveopt_o; +static int numberedbackup; +static int mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; +static char pathbuf[MAXPATHLEN]; +static uid_t uid = -1; +static gid_t gid = -1; +static char *group, *owner, *fflags, *tags; +static FILE *metafp; +static char *metafile; +static u_long fileflags; +static char *stripArgs; +static char *afterinstallcmd; +static const char *suffix = BACKUP_SUFFIX; +static char *destdir; + +enum { + DIGEST_NONE = 0, + DIGEST_MD5, + DIGEST_RMD160, + DIGEST_SHA1, + DIGEST_SHA256, + DIGEST_SHA384, + DIGEST_SHA512, +} digesttype = DIGEST_NONE; + +static char *digest; + +#define LN_ABSOLUTE 0x01 +#define LN_RELATIVE 0x02 +#define LN_HARD 0x04 +#define LN_SYMBOLIC 0x08 +#define LN_MIXED 0x10 + +#define DIRECTORY 0x01 /* Tell install it's a directory. */ +#define SETFLAGS 0x02 /* Tell install to set flags. */ +#define HASUID 0x04 /* Tell install the uid was given */ +#define HASGID 0x08 /* Tell install the gid was given */ + +static void afterinstall(const char *, const char *, int); +static void backup(const char *); +static char *copy(int, char *, int, char *, off_t); +static int do_link(char *, char *); +static void do_symlink(char *, char *); +static void install(char *, char *, u_int); +static void install_dir(char *, u_int); +static void makelink(char *, char *); +static void metadata_log(const char *, const char *, struct timeval *, + const char *, const char *, off_t); +static int parseid(char *, id_t *); +static void strip(char *); +__dead static void usage(void); +static char *xbasename(char *); +static char *xdirname(char *); + +int +main(int argc, char *argv[]) +{ + struct stat from_sb, to_sb; + void *set; + u_int iflags; + int ch, no_target; + char *p, *to_name; + + setprogname(argv[0]); + + iflags = 0; + while ((ch = getopt(argc, argv, "a:cbB:dD:f:g:h:l:m:M:N:o:prsS:T:U")) + != -1) + switch((char)ch) { + case 'a': + afterinstallcmd = strdup(optarg); + if (afterinstallcmd == NULL) + errx(1, "%s", strerror(ENOMEM)); + break; + case 'B': + suffix = optarg; + numberedbackup = 0; + { + /* Check if given suffix really generates + different suffixes - catch e.g. ".%" */ + char suffix_expanded0[FILENAME_MAX], + suffix_expanded1[FILENAME_MAX]; + (void)snprintf(suffix_expanded0, FILENAME_MAX, + suffix, 0); + (void)snprintf(suffix_expanded1, FILENAME_MAX, + suffix, 1); + if (strcmp(suffix_expanded0, suffix_expanded1) + != 0) + numberedbackup = 1; + } + /* fall through; -B implies -b */ + /*FALLTHROUGH*/ + case 'b': + dobackup = 1; + break; + case 'c': + /* ignored; was "docopy" which is now the default. */ + break; + case 'd': + dodir = 1; + break; + case 'D': + destdir = optarg; + break; +#if ! HAVE_NBTOOL_CONFIG_H + case 'f': + haveopt_f = 1; + fflags = optarg; + break; +#endif + case 'g': + haveopt_g = 1; + group = optarg; + break; + case 'h': + digest = optarg; + break; + case 'l': + for (p = optarg; *p; p++) + switch (*p) { + case 's': + dolink &= ~(LN_HARD|LN_MIXED); + dolink |= LN_SYMBOLIC; + break; + case 'h': + dolink &= ~(LN_SYMBOLIC|LN_MIXED); + dolink |= LN_HARD; + break; + case 'm': + dolink &= ~(LN_SYMBOLIC|LN_HARD); + dolink |= LN_MIXED; + break; + case 'a': + dolink &= ~LN_RELATIVE; + dolink |= LN_ABSOLUTE; + break; + case 'r': + dolink &= ~LN_ABSOLUTE; + dolink |= LN_RELATIVE; + break; + default: + errx(1, "%c: invalid link type", *p); + /* NOTREACHED */ + } + break; + case 'm': + haveopt_m = 1; + if (!(set = setmode(optarg))) + err(1, "Cannot set file mode `%s'", optarg); + mode = getmode(set, 0); + free(set); + break; + case 'M': + metafile = optarg; + break; + case 'N': + if (! setup_getid(optarg)) + errx(1, + "Unable to use user and group databases in `%s'", + optarg); + break; + case 'o': + haveopt_o = 1; + owner = optarg; + break; + case 'p': + dopreserve = 1; + break; + case 'r': + dorename = 1; + break; + case 'S': + stripArgs = strdup(optarg); + if (stripArgs == NULL) + errx(1, "%s", strerror(ENOMEM)); + /* fall through; -S implies -s */ + /*FALLTHROUGH*/ + case 's': + dostrip = 1; + break; + case 'T': + tags = optarg; + break; + case 'U': + dounpriv = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* strip and link options make no sense when creating directories */ + if ((dostrip || dolink) && dodir) + usage(); + + /* strip and flags make no sense with links */ + if ((dostrip || fflags) && dolink) + usage(); + + /* must have at least two arguments, except when creating directories */ + if (argc < 2 && !dodir) + usage(); + + if (digest) { + if (0) { + } else if (strcmp(digest, "none") == 0) { + digesttype = DIGEST_NONE; + } else if (strcmp(digest, "md5") == 0) { + digesttype = DIGEST_MD5; + } else if (strcmp(digest, "rmd160") == 0) { + digesttype = DIGEST_RMD160; + } else if (strcmp(digest, "sha1") == 0) { + digesttype = DIGEST_SHA1; + } else if (strcmp(digest, "sha256") == 0) { + digesttype = DIGEST_SHA256; + } else if (strcmp(digest, "sha384") == 0) { + digesttype = DIGEST_SHA384; + } else if (strcmp(digest, "sha512") == 0) { + digesttype = DIGEST_SHA512; + } else { + warnx("unknown digest `%s'", digest); + usage(); + } + } + + /* get group and owner id's */ + if (group && !dounpriv) { + if (gid_from_group(group, &gid) == -1) { + id_t id; + if (!parseid(group, &id)) + errx(1, "unknown group %s", group); + gid = id; + } + iflags |= HASGID; + } + if (owner && !dounpriv) { + if (uid_from_user(owner, &uid) == -1) { + id_t id; + if (!parseid(owner, &id)) + errx(1, "unknown user %s", owner); + uid = id; + } + iflags |= HASUID; + } + +#if ! HAVE_NBTOOL_CONFIG_H + if (fflags && !dounpriv) { + if (string_to_flags(&fflags, &fileflags, NULL)) + errx(1, "%s: invalid flag", fflags); + /* restore fflags since string_to_flags() changed it */ + fflags = flags_to_string(fileflags, "-"); + iflags |= SETFLAGS; + } +#endif + + if (metafile) { + if ((metafp = fopen(metafile, "a")) == NULL) + warn("open %s", metafile); + } else + digesttype = DIGEST_NONE; + + if (dodir) { + for (; *argv != NULL; ++argv) + install_dir(*argv, iflags); + exit (0); + } + + no_target = stat(to_name = argv[argc - 1], &to_sb); + if (!no_target && S_ISDIR(to_sb.st_mode)) { + for (; *argv != to_name; ++argv) + install(*argv, to_name, iflags | DIRECTORY); + exit(0); + } + + /* can't do file1 file2 directory/file */ + if (argc != 2) { + errx(EXIT_FAILURE, "the last argument (%s) " + "must name an existing directory", argv[argc - 1]); + /* NOTREACHED */ + } + + if (!no_target) { + /* makelink() handles checks for links */ + if (!dolink) { + if (stat(*argv, &from_sb)) + err(1, "%s: stat", *argv); + if (!S_ISREG(to_sb.st_mode)) + errx(1, "%s: not a regular file", to_name); + if (to_sb.st_dev == from_sb.st_dev && + to_sb.st_ino == from_sb.st_ino) + errx(1, "%s and %s are the same file", *argv, + to_name); + } + /* + * Unlink now... avoid ETXTBSY errors later. Try and turn + * off the append/immutable bits -- if we fail, go ahead, + * it might work. + */ +#if ! HAVE_NBTOOL_CONFIG_H +#define NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND) + if (to_sb.st_flags & NOCHANGEBITS) + (void)chflags(to_name, + to_sb.st_flags & ~(NOCHANGEBITS)); +#endif + if (dobackup) + backup(to_name); + else if (!dorename) + (void)unlink(to_name); + } + install(*argv, to_name, iflags); + exit(0); +} + +/* + * parseid -- + * parse uid or gid from arg into id, returning non-zero if successful + */ +static int +parseid(char *name, id_t *id) +{ + char *ep; + + errno = 0; + *id = (id_t)strtoul(name, &ep, 10); + if (errno || *ep != '\0') + return (0); + return (1); +} + +/* + * do_link -- + * make a hard link, obeying dorename if set + * return -1 on failure + */ +static int +do_link(char *from_name, char *to_name) +{ + char tmpl[MAXPATHLEN]; + int ret; + + if (dorename) { + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); + /* This usage is safe. */ + if (mktemp(tmpl) == NULL) + err(1, "%s: mktemp", tmpl); + ret = link(from_name, tmpl); + if (ret == 0) { + ret = rename(tmpl, to_name); + /* If rename has posix semantics, then the temporary + * file may still exist when from_name and to_name point + * to the same file, so unlink it unconditionally. + */ + (void)unlink(tmpl); + } + return (ret); + } else + return (link(from_name, to_name)); +} + +/* + * do_symlink -- + * make a symbolic link, obeying dorename if set + * exit on failure + */ +static void +do_symlink(char *from_name, char *to_name) +{ + char tmpl[MAXPATHLEN]; + + if (dorename) { + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name); + /* This usage is safe. */ + if (mktemp(tmpl) == NULL) + err(1, "%s: mktemp", tmpl); + + if (symlink(from_name, tmpl) == -1) + err(1, "symlink %s -> %s", from_name, tmpl); + if (rename(tmpl, to_name) == -1) { + /* remove temporary link before exiting */ + (void)unlink(tmpl); + err(1, "%s: rename", to_name); + } + } else { + if (symlink(from_name, to_name) == -1) + err(1, "symlink %s -> %s", from_name, to_name); + } +} + +/* + * makelink -- + * make a link from source to destination + */ +static void +makelink(char *from_name, char *to_name) +{ + char src[MAXPATHLEN], dst[MAXPATHLEN], lnk[MAXPATHLEN]; + struct stat to_sb; + + /* Try hard links first */ + if (dolink & (LN_HARD|LN_MIXED)) { + if (do_link(from_name, to_name) == -1) { + if ((dolink & LN_HARD) || errno != EXDEV) + err(1, "link %s -> %s", from_name, to_name); + } else { + if (stat(to_name, &to_sb)) + err(1, "%s: stat", to_name); + if (S_ISREG(to_sb.st_mode)) { + /* XXX: hard links to anything + * other than plain files are not + * metalogged + */ + int omode; + char *oowner, *ogroup, *offlags; + char *dres; + + /* XXX: use underlying perms, + * unless overridden on command line. + */ + omode = mode; + if (!haveopt_m) + mode = (to_sb.st_mode & 0777); + oowner = owner; + if (!haveopt_o) + owner = NULL; + ogroup = group; + if (!haveopt_g) + group = NULL; + offlags = fflags; + if (!haveopt_f) + fflags = NULL; + switch (digesttype) { + case DIGEST_MD5: + dres = MD5File(from_name, NULL); + break; + case DIGEST_RMD160: + dres = RMD160File(from_name, NULL); + break; + case DIGEST_SHA1: + dres = SHA1File(from_name, NULL); + break; + case DIGEST_SHA256: + dres = SHA256_File(from_name, NULL); + break; + case DIGEST_SHA384: + dres = SHA384_File(from_name, NULL); + break; + case DIGEST_SHA512: + dres = SHA512_File(from_name, NULL); + break; + default: + dres = NULL; + } + metadata_log(to_name, "file", NULL, NULL, + dres, to_sb.st_size); + free(dres); + mode = omode; + owner = oowner; + group = ogroup; + fflags = offlags; + } + return; + } + } + + /* Symbolic links */ + if (dolink & LN_ABSOLUTE) { + /* Convert source path to absolute */ + if (realpath(from_name, src) == NULL) + err(1, "%s: realpath", from_name); + do_symlink(src, to_name); + /* XXX: src may point outside of destdir */ + metadata_log(to_name, "link", NULL, src, NULL, 0); + return; + } + + if (dolink & LN_RELATIVE) { + char *cp, *d, *s; + + /* Resolve pathnames */ + if (realpath(from_name, src) == NULL) + err(1, "%s: realpath", from_name); + + /* + * The last component of to_name may be a symlink, + * so use realpath to resolve only the directory. + */ + cp = xdirname(to_name); + if (realpath(cp, dst) == NULL) + err(1, "%s: realpath", cp); + /* .. and add the last component */ + if (strcmp(dst, "/") != 0) { + if (strlcat(dst, "/", sizeof(dst)) > sizeof(dst)) + errx(1, "resolved pathname too long"); + } + cp = xbasename(to_name); + if (strlcat(dst, cp, sizeof(dst)) > sizeof(dst)) + errx(1, "resolved pathname too long"); + + /* trim common path components */ + for (s = src, d = dst; *s == *d; s++, d++) + continue; + while (*s != '/') + s--, d--; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209252027.q8PKRgmM090268>