svn: stable/9: . usr.bin/xinstall
Maxim Sobolev
sobomax at FreeBSD.org
Sat Jun 1 20:19:17 UTC 2013
Hmm, I believe this breaks build for me. Any ideas why?
===> usr.bin/xinstall (all)
cc -O2 -pipe -I/usr/src/usr.bin/xinstall/../../contrib/mtree
-I/usr/src/usr.bin/xinstall/../../lib/libnetbsd
-I/usr/src/usr.bin/xinstall/../../lib/libmd -std=gnu99 -fstack-protector
-Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter
-Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type
-Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter
-Wcast-align -Wchar-subscripts -Winline -Wnested-externs
-Wredundant-decls -Wold-style-definition -Wno-pointer-sign -c
/usr/src/usr.bin/xinstall/xinstall.c
cc1: warnings being treated as errors
/usr/src/usr.bin/xinstall/xinstall.c: In function 'metadata_log':
/usr/src/usr.bin/xinstall/xinstall.c:1331: warning: implicit declaration
of function 'strsvis'
/usr/src/usr.bin/xinstall/xinstall.c:1331: warning: nested extern
declaration of 'strsvis'
*** [xinstall.o] Error code 1
Stop in /usr/src/usr.bin/xinstall.
*** [all] Error code 1
uname -a
FreeBSD dal09 9.1-RELEASE FreeBSD 9.1-RELEASE #2: Thu Dec 27 09:39:03
UTC 2012 root at pioneer:/usr/obj/usr/src91/sys/SSP-PRODUCTION9_X64 amd64
On 3/15/2013 8:19 AM, Brooks Davis wrote:
> Author: brooks
> Date: Fri Mar 15 15:19:33 2013
> New Revision: 248331
> URL: http://svnweb.freebsd.org/changeset/base/248331
>
> Log:
> MFC all changes to install(1) through r246784. Notable functional
> changes are:
>
> r245617:
> Introduce six new options from NetBSD:
> * -M <metalog> Log metadata in mtree format.
> * -D <destdir> Log paths relative to <destdir>.
> * -h <hash> Log digest of type <hash>.
> * -T <tags> Specify which mtree tags to log.
> * -l <linkflag> Create hard or symbolic links (allows logging).
> * -U Install without root privileges (owner, group, mode,
> and flags can be logged via -M
>
> NOTE: In the interest of compatibility with NetBSD and because it is the
> obvious letter, the nearly useless -M option (disable mmap) has been
> repurposed.
>
> Sponsored by: DARPA, AFRL
> Obtained from: NetBSD
> Reviewed by: bz
>
> r245312:
> Implement the -N <dbdir> option which allows an alternate passwd and
> group file to be used. This is useful for installing on systems where
> a user or group does not currently exist.
>
> Sponsored by: DARPA, AFRL
> Obtained from: NetBSD
>
> Modified:
> stable/9/UPDATING (contents, props changed)
> stable/9/usr.bin/xinstall/Makefile
> stable/9/usr.bin/xinstall/install.1
> stable/9/usr.bin/xinstall/xinstall.c
> Directory Properties:
> stable/9/usr.bin/xinstall/ (props changed)
>
> Modified: stable/9/UPDATING
> ==============================================================================
> --- stable/9/UPDATING Fri Mar 15 14:53:29 2013 (r248330)
> +++ stable/9/UPDATING Fri Mar 15 15:19:33 2013 (r248331)
> @@ -11,6 +11,15 @@ handbook:
> Items affecting the ports and packages system can be found in
> /usr/ports/UPDATING. Please read that file before running portupgrade.
>
> +20130315:
> + The install(1) option -M has changed meaning and now takes an
> + argument that is a file or path to append logs to. In the
> + unlikely event that -M was the last option on the command line
> + and the command line contained at least two files and a target
> + directory the first file will have logs appended to it. The -M
> + option served little practical purpose in the last decade so it's
> + used expected to be extremely rare.
> +
> 20130225:
> A new compression method (lz4) has been merged to. Please refer to
> zpool-features(7) for more information.
>
> Modified: stable/9/usr.bin/xinstall/Makefile
> ==============================================================================
> --- stable/9/usr.bin/xinstall/Makefile Fri Mar 15 14:53:29 2013 (r248330)
> +++ stable/9/usr.bin/xinstall/Makefile Fri Mar 15 15:19:33 2013 (r248331)
> @@ -3,6 +3,16 @@
>
> PROG= xinstall
> PROGNAME= install
> +SRCS= xinstall.c getid.c
> MAN= install.1
>
> +.PATH: ${.CURDIR}/../../contrib/mtree
> +.PATH: ${.CURDIR}/../../lib/libmd
> +CFLAGS+= -I${.CURDIR}/../../contrib/mtree
> +CFLAGS+= -I${.CURDIR}/../../lib/libnetbsd
> +CFLAGS+= -I${.CURDIR}/../../lib/libmd
> +
> +DPADD+= ${LIBMD}
> +LDADD+= -lmd
> +
> .include <bsd.prog.mk>
>
> Modified: stable/9/usr.bin/xinstall/install.1
> ==============================================================================
> --- stable/9/usr.bin/xinstall/install.1 Fri Mar 15 14:53:29 2013 (r248330)
> +++ stable/9/usr.bin/xinstall/install.1 Fri Mar 15 15:19:33 2013 (r248331)
> @@ -28,7 +28,7 @@
> .\" From: @(#)install.1 8.1 (Berkeley) 6/6/93
> .\" $FreeBSD$
> .\"
> -.Dd March 6, 2006
> +.Dd January 18, 2013
> .Dt INSTALL 1
> .Os
> .Sh NAME
> @@ -36,31 +36,50 @@
> .Nd install binaries
> .Sh SYNOPSIS
> .Nm
> -.Op Fl bCcMpSsv
> +.Op Fl bCcpSsUv
> .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 T Ar tags
> .Ar file1 file2
> .Nm
> -.Op Fl bCcMpSsv
> +.Op Fl bCcpSsUv
> .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 T Ar tags
> .Ar file1 ... fileN directory
> .Nm
> .Fl d
> -.Op Fl v
> +.Op Fl Uv
> +.Op Fl D Ar destdir
> .Op Fl g Ar group
> +.Op Fl h Ar hash
> +.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
> -to the target file or directory.
> +(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
> @@ -105,6 +124,17 @@ This is actually the default.
> The
> .Fl c
> option is only included for backwards compatibility.
> +.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.
> @@ -115,15 +145,82 @@ for a list of possible flags and their m
> .It Fl g
> Specify a group.
> A numeric GID is allowed.
> -.It Fl M
> -Disable all use of
> -.Xr mmap 2 .
> +.It Fl h Ar hash
> +When copying, calculate the digest of the files with
> +.Ar hash
> +to store in the
> +.Fl M Ar metalog .
> +When
> +.Fl d
> +is given no hash is emitted.
> +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 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
> Specify an alternate 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
> +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
> Specify an owner.
> A numeric UID is allowed.
> @@ -156,6 +253,17 @@ number of systems and binary types.
> See below for how
> .Nm
> can be instructed to use another program to strip binaries.
> +.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 .
> .It Fl v
> Cause
> .Nm
> @@ -231,6 +339,8 @@ The default was changed to copy in
> .Xr mv 1 ,
> .Xr strip 1 ,
> .Xr mmap 2 ,
> +.Xr getgrnam 3 ,
> +.Xr getpwnam 3 ,
> .Xr chown 8
> .Sh HISTORY
> The
> @@ -238,6 +348,16 @@ The
> utility appeared in
> .Bx 4.2 .
> .Sh BUGS
> +The meaning of the
> +.Fl M
> +option has changed as of
> +.Fx 10
> +and it now takes an argument.
> +Command lines that used the old
> +.Fl M
> +will get an error or in rare cases will append logs to the first of
> +multiple source files rather than installing it.
> +.Pp
> Temporary files may be left in the target directory if
> .Nm
> exits abnormally.
>
> Modified: stable/9/usr.bin/xinstall/xinstall.c
> ==============================================================================
> --- stable/9/usr.bin/xinstall/xinstall.c Fri Mar 15 14:53:29 2013 (r248330)
> +++ stable/9/usr.bin/xinstall/xinstall.c Fri Mar 15 15:19:33 2013 (r248331)
> @@ -1,4 +1,5 @@
> /*
> + * Copyright (c) 2012, 2013 SRI International
> * Copyright (c) 1987, 1993
> * The Regents of the University of California. All rights reserved.
> *
> @@ -53,14 +54,23 @@ __FBSDID("$FreeBSD$");
> #include <errno.h>
> #include <fcntl.h>
> #include <grp.h>
> +#include <libgen.h>
> +#include <md5.h>
> #include <paths.h>
> #include <pwd.h>
> +#include <ripemd.h>
> +#include <sha.h>
> +#include <sha256.h>
> +#include <sha512.h>
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <sysexits.h>
> #include <unistd.h>
> +#include <vis.h>
> +
> +#include "mtree.h"
>
> /* Bootstrap aid - this doesn't exist in most older releases */
> #ifndef MAP_FAILED
> @@ -69,26 +79,63 @@ __FBSDID("$FreeBSD$");
>
> #define MAX_CMP_SIZE (16 * 1024 * 1024)
>
> +#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 NOCHANGEBITS (UF_IMMUTABLE | UF_APPEND | SF_IMMUTABLE | SF_APPEND)
> #define BACKUP_SUFFIX ".old"
>
> -struct passwd *pp;
> -struct group *gp;
> -gid_t gid;
> -uid_t uid;
> -int dobackup, docompare, dodir, dopreserve, dostrip, nommap, safecopy, verbose;
> -mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
> -const char *suffix = BACKUP_SUFFIX;
> -
> -static int compare(int, const char *, size_t, int, const char *, size_t);
> -static void copy(int, const char *, int, const char *, off_t);
> +typedef union {
> + MD5_CTX MD5;
> + RIPEMD160_CTX RIPEMD160;
> + SHA1_CTX SHA1;
> + SHA256_CTX SHA256;
> + SHA512_CTX SHA512;
> +} DIGEST_CTX;
> +
> +static enum {
> + DIGEST_NONE = 0,
> + DIGEST_MD5,
> + DIGEST_RIPEMD160,
> + DIGEST_SHA1,
> + DIGEST_SHA256,
> + DIGEST_SHA512,
> +} digesttype = DIGEST_NONE;
> +
> +static gid_t gid;
> +static uid_t uid;
> +static int dobackup, docompare, dodir, dolink, dopreserve, dostrip, dounpriv,
> + safecopy, verbose;
> +static int haveopt_f, haveopt_g, haveopt_m, haveopt_o;
> +static mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
> +static FILE *metafp;
> +static const char *group, *owner;
> +static const char *suffix = BACKUP_SUFFIX;
> +static char *destdir, *digest, *fflags, *metafile, *tags;
> +
> +static int compare(int, const char *, size_t, int, const char *, size_t,
> + char **);
> +static char *copy(int, const char *, int, const char *, off_t);
> static int create_newfile(const char *, int, struct stat *);
> static int create_tempfile(const char *, char *, size_t);
> +static char *quiet_mktemp(char *template);
> +static char *digest_file(const char *);
> +static void digest_init(DIGEST_CTX *);
> +static void digest_update(DIGEST_CTX *, const unsigned char *, size_t);
> +static char *digest_end(DIGEST_CTX *, char *);
> +static int do_link(const char *, const char *, const struct stat *);
> +static void do_symlink(const char *, const char *, const struct stat *);
> +static void makelink(const char *, const char *, const struct stat *);
> static void install(const char *, const char *, u_long, u_int);
> static void install_dir(char *);
> -static u_long numeric_id(const char *, const char *);
> +static void metadata_log(const char *, const char *, struct timeval *,
> + const char *, const char *, off_t);
> +static int parseid(const char *, id_t *);
> static void strip(const char *);
> static int trymmap(int);
> static void usage(void);
> @@ -101,12 +148,13 @@ main(int argc, char *argv[])
> u_long fset;
> int ch, no_target;
> u_int iflags;
> - char *flags;
> - const char *group, *owner, *to_name;
> + char *p;
> + const char *to_name;
>
> iflags = 0;
> group = owner = NULL;
> - while ((ch = getopt(argc, argv, "B:bCcdf:g:Mm:o:pSsv")) != -1)
> + while ((ch = getopt(argc, argv, "B:bCcD:df:g:h:l:M:m:N:o:pSsT:Uv")) !=
> + -1)
> switch((char)ch) {
> case 'B':
> suffix = optarg;
> @@ -120,29 +168,69 @@ main(int argc, char *argv[])
> case 'c':
> /* For backwards compatibility. */
> break;
> + case 'D':
> + destdir = optarg;
> + break;
> case 'd':
> dodir = 1;
> break;
> case 'f':
> - flags = optarg;
> - if (strtofflags(&flags, &fset, NULL))
> - errx(EX_USAGE, "%s: invalid flag", flags);
> - iflags |= SETFLAGS;
> + haveopt_f = 1;
> + fflags = optarg;
> break;
> case 'g':
> + haveopt_g = 1;
> group = optarg;
> break;
> + case 'h':
> + digest = optarg;
> + break;
> + case 'l':
> + for (p = optarg; *p != '\0'; 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':
> - nommap = 1;
> + metafile = optarg;
> break;
> case 'm':
> + haveopt_m = 1;
> if (!(set = setmode(optarg)))
> errx(EX_USAGE, "invalid file mode: %s",
> optarg);
> mode = getmode(set, 0);
> free(set);
> break;
> + case 'N':
> + if (!setup_getid(optarg))
> + err(EX_OSERR, "Unable to use user and group "
> + "databases in `%s'", optarg);
> + break;
> case 'o':
> + haveopt_o = 1;
> owner = optarg;
> break;
> case 'p':
> @@ -154,6 +242,12 @@ main(int argc, char *argv[])
> case 's':
> dostrip = 1;
> break;
> + case 'T':
> + tags = optarg;
> + break;
> + case 'U':
> + dounpriv = 1;
> + break;
> case 'v':
> verbose = 1;
> break;
> @@ -179,27 +273,62 @@ main(int argc, char *argv[])
> if (argc == 0 || (argc == 1 && !dodir))
> usage();
>
> + if (digest != NULL) {
> + 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_RIPEMD160;
> + } else if (strcmp(digest, "sha1") == 0) {
> + digesttype = DIGEST_SHA1;
> + } else if (strcmp(digest, "sha256") == 0) {
> + digesttype = DIGEST_SHA256;
> + } else if (strcmp(digest, "sha512") == 0) {
> + digesttype = DIGEST_SHA512;
> + } else {
> + warnx("unknown digest `%s'", digest);
> + usage();
> + }
> + }
> +
> /* need to make a temp copy so we can compare stripped version */
> if (docompare && dostrip)
> safecopy = 1;
>
> /* get group and owner id's */
> - if (group != NULL) {
> - if ((gp = getgrnam(group)) != NULL)
> - gid = gp->gr_gid;
> - else
> - gid = (gid_t)numeric_id(group, "group");
> + if (group != NULL && !dounpriv) {
> + if (gid_from_group(group, &gid) == -1) {
> + id_t id;
> + if (!parseid(group, &id))
> + errx(1, "unknown group %s", group);
> + gid = id;
> + }
> } else
> gid = (gid_t)-1;
>
> - if (owner != NULL) {
> - if ((pp = getpwnam(owner)) != NULL)
> - uid = pp->pw_uid;
> - else
> - uid = (uid_t)numeric_id(owner, "user");
> + if (owner != NULL && !dounpriv) {
> + if (uid_from_user(owner, &uid) == -1) {
> + id_t id;
> + if (!parseid(owner, &id))
> + errx(1, "unknown user %s", owner);
> + uid = id;
> + }
> } else
> uid = (uid_t)-1;
>
> + if (fflags != NULL && !dounpriv) {
> + if (strtofflags(&fflags, &fset, NULL))
> + errx(EX_USAGE, "%s: invalid flag", fflags);
> + iflags |= SETFLAGS;
> + }
> +
> + if (metafile != NULL) {
> + if ((metafp = fopen(metafile, "a")) == NULL)
> + warn("open %s", metafile);
> + } else
> + digesttype = DIGEST_NONE;
> +
> if (dodir) {
> for (; *argv != NULL; ++argv)
> install_dir(*argv);
> @@ -207,8 +336,21 @@ main(int argc, char *argv[])
> /* NOTREACHED */
> }
>
> - no_target = stat(to_name = argv[argc - 1], &to_sb);
> + to_name = argv[argc - 1];
> + no_target = stat(to_name, &to_sb);
> if (!no_target && S_ISDIR(to_sb.st_mode)) {
> + if (dolink & LN_SYMBOLIC) {
> + if (lstat(to_name, &to_sb) != 0)
> + err(EX_OSERR, "%s vanished", to_name);
> + if (S_ISLNK(to_sb.st_mode)) {
> + if (argc != 2) {
> + errno = ENOTDIR;
> + err(EX_USAGE, "%s", to_name);
> + }
> + install(*argv, to_name, fset, iflags);
> + exit(EX_OK);
> + }
> + }
> for (; *argv != to_name; ++argv)
> install(*argv, to_name, fset, iflags | DIRECTORY);
> exit(EX_OK);
> @@ -226,7 +368,7 @@ main(int argc, char *argv[])
> usage();
> }
>
> - if (!no_target) {
> + if (!no_target && !dolink) {
> if (stat(*argv, &from_sb))
> err(EX_OSERR, "%s", *argv);
> if (!S_ISREG(to_sb.st_mode)) {
> @@ -243,23 +385,327 @@ main(int argc, char *argv[])
> /* NOTREACHED */
> }
>
> -static u_long
> -numeric_id(const char *name, const char *type)
> +static char *
> +digest_file(const char *name)
> +{
> +
> + switch (digesttype) {
> + case DIGEST_MD5:
> + return (MD5File(name, NULL));
> + case DIGEST_RIPEMD160:
> + return (RIPEMD160_File(name, NULL));
> + case DIGEST_SHA1:
> + return (SHA1_File(name, NULL));
> + case DIGEST_SHA256:
> + return (SHA256_File(name, NULL));
> + case DIGEST_SHA512:
> + return (SHA512_File(name, NULL));
> + default:
> + return (NULL);
> + }
> +}
> +
> +static void
> +digest_init(DIGEST_CTX *c)
> +{
> +
> + switch (digesttype) {
> + case DIGEST_NONE:
> + break;
> + case DIGEST_MD5:
> + MD5Init(&(c->MD5));
> + break;
> + case DIGEST_RIPEMD160:
> + RIPEMD160_Init(&(c->RIPEMD160));
> + break;
> + case DIGEST_SHA1:
> + SHA1_Init(&(c->SHA1));
> + break;
> + case DIGEST_SHA256:
> + SHA256_Init(&(c->SHA256));
> + break;
> + case DIGEST_SHA512:
> + SHA512_Init(&(c->SHA512));
> + break;
> + }
> +}
> +
> +static void
> +digest_update(DIGEST_CTX *c, const unsigned char *data, size_t len)
> +{
> +
> + switch (digesttype) {
> + case DIGEST_NONE:
> + break;
> + case DIGEST_MD5:
> + MD5Update(&(c->MD5), data, len);
> + break;
> + case DIGEST_RIPEMD160:
> + RIPEMD160_Update(&(c->RIPEMD160), data, len);
> + break;
> + case DIGEST_SHA1:
> + SHA1_Update(&(c->SHA1), data, len);
> + break;
> + case DIGEST_SHA256:
> + SHA256_Update(&(c->SHA256), data, len);
> + break;
> + case DIGEST_SHA512:
> + SHA512_Update(&(c->SHA512), data, len);
> + break;
> + }
> +}
> +
> +static char *
> +digest_end(DIGEST_CTX *c, char *buf)
> +{
> +
> + switch (digesttype) {
> + case DIGEST_MD5:
> + return (MD5End(&(c->MD5), buf));
> + case DIGEST_RIPEMD160:
> + return (RIPEMD160_End(&(c->RIPEMD160), buf));
> + case DIGEST_SHA1:
> + return (SHA1_End(&(c->SHA1), buf));
> + case DIGEST_SHA256:
> + return (SHA256_End(&(c->SHA256), buf));
> + case DIGEST_SHA512:
> + return (SHA512_End(&(c->SHA512), buf));
> + default:
> + return (NULL);
> + }
> +}
> +
> +/*
> + * parseid --
> + * parse uid or gid from arg into id, returning non-zero if successful
> + */
> +static int
> +parseid(const char *name, id_t *id)
> +{
> + char *ep;
> + errno = 0;
> + *id = (id_t)strtoul(name, &ep, 10);
> + if (errno || *ep != '\0')
> + return (0);
> + return (1);
> +}
> +
> +/*
> + * quiet_mktemp --
> + * mktemp implementation used mkstemp to avoid mktemp warnings. We
> + * really do need mktemp semantics here as we will be creating a link.
> + */
> +static char *
> +quiet_mktemp(char *template)
> +{
> + int fd;
> +
> + if ((fd = mkstemp(template)) == -1)
> + return (NULL);
> + close (fd);
> + if (unlink(template) == -1)
> + err(EX_OSERR, "unlink %s", template);
> + return (template);
> +}
> +
> +/*
> + * do_link --
> + * make a hard link, obeying dorename if set
> + * return -1 on failure
> + */
> +static int
> +do_link(const char *from_name, const char *to_name,
> + const struct stat *target_sb)
> +{
> + char tmpl[MAXPATHLEN];
> + int ret;
> +
> + if (safecopy && target_sb != NULL) {
> + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
> + /* This usage is safe. */
> + if (quiet_mktemp(tmpl) == NULL)
> + err(EX_OSERR, "%s: mktemp", tmpl);
> + ret = link(from_name, tmpl);
> + if (ret == 0) {
> + if (target_sb->st_mode & S_IFDIR && rmdir(to_name) ==
> + -1) {
> + unlink(tmpl);
> + err(EX_OSERR, "%s", to_name);
> + }
> + if (target_sb->st_flags & NOCHANGEBITS)
> + (void)chflags(to_name, target_sb->st_flags &
> + ~NOCHANGEBITS);
> + unlink(to_name);
> + 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(const char *from_name, const char *to_name,
> + const struct stat *target_sb)
> +{
> + char tmpl[MAXPATHLEN];
> +
> + if (safecopy && target_sb != NULL) {
> + (void)snprintf(tmpl, sizeof(tmpl), "%s.inst.XXXXXX", to_name);
> + /* This usage is safe. */
> + if (quiet_mktemp(tmpl) == NULL)
> + err(EX_OSERR, "%s: mktemp", tmpl);
> +
> + if (symlink(from_name, tmpl) == -1)
> + err(EX_OSERR, "symlink %s -> %s", from_name, tmpl);
> +
> + if (target_sb->st_mode & S_IFDIR && rmdir(to_name) == -1) {
> + (void)unlink(tmpl);
> + err(EX_OSERR, "%s", to_name);
> + }
> + if (target_sb->st_flags & NOCHANGEBITS)
> + (void)chflags(to_name, target_sb->st_flags &
> + ~NOCHANGEBITS);
> + unlink(to_name);
> +
> + if (rename(tmpl, to_name) == -1) {
> + /* Remove temporary link before exiting. */
> + (void)unlink(tmpl);
> + err(EX_OSERR, "%s: rename", to_name);
> + }
> + } else {
> + if (symlink(from_name, to_name) == -1)
> + err(EX_OSERR, "symlink %s -> %s", from_name, to_name);
> + }
> +}
> +
> +/*
> + * makelink --
> + * make a link from source to destination
> + */
> +static void
> +makelink(const char *from_name, const char *to_name,
> + const struct stat *target_sb)
> {
> - u_long val;
> - char *ep;
> + 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, target_sb) == -1) {
> + if ((dolink & LN_HARD) || errno != EXDEV)
> + err(EX_OSERR, "link %s -> %s", from_name, to_name);
> + } else {
> + if (stat(to_name, &to_sb))
> + err(EX_OSERR, "%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;
> + const char *oowner, *ogroup;
> + char *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;
> + dres = digest_file(from_name);
> + 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(EX_OSERR, "%s: realpath", from_name);
> + do_symlink(src, to_name, target_sb);
> + /* 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(EX_OSERR, "%s: realpath", from_name);
> +
> + /*
> + * The last component of to_name may be a symlink,
> + * so use realpath to resolve only the directory.
> + */
> + cp = dirname(to_name);
> + if (realpath(cp, dst) == NULL)
> + err(EX_OSERR, "%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 = basename(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--;
> +
> + /* Count the number of directories we need to backtrack. */
> + for (++d, lnk[0] = '\0'; *d; d++)
> + if (*d == '/')
> + (void)strlcat(lnk, "../", sizeof(lnk));
> +
> + (void)strlcat(lnk, ++s, sizeof(lnk));
> +
> + do_symlink(lnk, to_name, target_sb);
> + /* XXX: Link may point outside of destdir. */
> + metadata_log(to_name, "link", NULL, lnk, NULL, 0);
> + return;
> + }
>
> /*
> - * XXX
> - * We know that uid_t's and gid_t's are unsigned longs.
> + * If absolute or relative was not specified, try the names the
> + * user provided.
> */
> - errno = 0;
> - val = strtoul(name, &ep, 10);
> - if (errno)
> - err(EX_NOUSER, "%s", name);
> - if (*ep != '\0')
> - errx(EX_NOUSER, "unknown %s %s", type, name);
> - return (val);
> + do_symlink(from_name, to_name, target_sb);
> + /* XXX: from_name may point outside of destdir. */
> + metadata_log(to_name, "link", NULL, from_name, NULL, 0);
> }
>
> /*
> @@ -274,6 +720,7 @@ install(const char *from_name, const cha
> int devnull, files_match, from_fd, serrno, target;
> int tempcopy, temp_fd, to_fd;
> char backup[MAXPATHLEN], *p, pathbuf[MAXPATHLEN], tempfile[MAXPATHLEN];
> + char *digestresult;
>
> files_match = 0;
> from_fd = -1;
> @@ -281,11 +728,13 @@ install(const char *from_name, const cha
>
> /* If try to install NULL file to a directory, fails. */
> if (flags & DIRECTORY || strcmp(from_name, _PATH_DEVNULL)) {
> - if (stat(from_name, &from_sb))
> - err(EX_OSERR, "%s", from_name);
> - if (!S_ISREG(from_sb.st_mode)) {
> - errno = EFTYPE;
> - err(EX_OSERR, "%s", from_name);
> + if (!dolink) {
> + if (stat(from_name, &from_sb))
> + err(EX_OSERR, "%s", from_name);
> + if (!S_ISREG(from_sb.st_mode)) {
> + errno = EFTYPE;
> + err(EX_OSERR, "%s", from_name);
> + }
> }
> /* Build the target path. */
> if (flags & DIRECTORY) {
> @@ -299,7 +748,23 @@ install(const char *from_name, const cha
> devnull = 1;
> }
>
> - target = stat(to_name, &to_sb) == 0;
> + if (!dolink)
> + target = (stat(to_name, &to_sb) == 0);
> + else
> + target = (lstat(to_name, &to_sb) == 0);
> +
> + if (dolink) {
> + if (target && !safecopy) {
> + if (to_sb.st_mode & S_IFDIR && rmdir(to_name) == -1)
> + err(EX_OSERR, "%s", to_name);
> + if (to_sb.st_flags & NOCHANGEBITS)
> + (void)chflags(to_name,
> + to_sb.st_flags & ~NOCHANGEBITS);
> + unlink(to_name);
> + }
> + makelink(from_name, to_name, target ? &to_sb : NULL);
> + return;
> + }
>
> /* Only install to regular files. */
> if (target && !S_ISREG(to_sb.st_mode)) {
> @@ -323,7 +788,7 @@ install(const char *from_name, const cha
> else
> files_match = !(compare(from_fd, from_name,
> (size_t)from_sb.st_size, to_fd,
> - to_name, (size_t)to_sb.st_size));
> + to_name, (size_t)to_sb.st_size, &digestresult));
>
> /* Close "to" file unless we match. */
> if (!files_match)
> @@ -345,8 +810,10 @@ install(const char *from_name, const cha
> from_name, to_name);
> }
> if (!devnull)
> - copy(from_fd, from_name, to_fd,
> + digestresult = copy(from_fd, from_name, to_fd,
> tempcopy ? tempfile : to_name, from_sb.st_size);
> + else
> + digestresult = NULL;
> }
>
> if (dostrip) {
> @@ -380,7 +847,8 @@ install(const char *from_name, const cha
> }
>
> if (compare(temp_fd, tempfile, (size_t)temp_sb.st_size, to_fd,
> - to_name, (size_t)to_sb.st_size) == 0) {
> + to_name, (size_t)to_sb.st_size, &digestresult)
> + == 0) {
> /*
> * If target has more than one link we need to
> * replace it in order to snap the extra links.
> @@ -400,6 +868,9 @@ install(const char *from_name, const cha
> }
> }
>
> + if (dostrip && (!docompare || !target))
> + digestresult = digest_file(tempfile);
> +
> /*
>
> *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
>
>
More information about the svn-src-stable-9
mailing list