svn: stable/9: . usr.bin/xinstall

Brooks Davis brooks at FreeBSD.org
Mon Jun 3 16:48:25 UTC 2013


On Sat, Jun 01, 2013 at 01:01:01PM -0700, Maxim Sobolev wrote:
> Hmm, I believe this breaks build for me. Any ideas why?

Presumably you are building in some less common way since this change
has been working for months.  What command line resulted in this error?
Is this tree fully up to date?  Do you have anything in src.conf or
make.conf?  From the error, it looks like you haven't bootstrapped a new
libc properly.

-- Brooks

> ===> 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 ***
> >
> >
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 188 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/svn-src-all/attachments/20130603/2a3a901b/attachment-0001.sig>


More information about the svn-src-all mailing list