From 3d000fd59ca95cf7f95d5c19904263830b647b54 Mon Sep 17 00:00:00 2001 From: lukem Date: Tue, 19 Mar 2002 14:17:04 +0000 Subject: [PATCH] - Add "-a afterinstallcommand", which runs "sh -c afterinstallcmd target" after target has been installed and possibly stripped with -s, but before ownership, permissions or timestamps are set, and before renaming (with -r) occurs. Per discussion with simonb. - When metalogging hardlinks, log the mode of the existing target (rather than the default 0755), and ignore owner/group/fflags. - Improve man page description of various options to include argument name. - Clean up usage() to use getprogname(), etc. --- usr.bin/xinstall/install.1 | 48 +++++++++++---- usr.bin/xinstall/xinstall.c | 115 +++++++++++++++++++++++++++++++----- 2 files changed, 138 insertions(+), 25 deletions(-) diff --git a/usr.bin/xinstall/install.1 b/usr.bin/xinstall/install.1 index 7c483c69b4fd..c7483457c385 100644 --- a/usr.bin/xinstall/install.1 +++ b/usr.bin/xinstall/install.1 @@ -1,4 +1,4 @@ -.\" $NetBSD: install.1,v 1.29 2002/02/08 01:36:38 ross Exp $ +.\" $NetBSD: install.1,v 1.30 2002/03/19 14:17:04 lukem Exp $ .\" .\" Copyright (c) 1987, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -33,7 +33,7 @@ .\" .\" @(#)install.1 8.1 (Berkeley) 6/6/93 .\" -.Dd October 26, 2001 +.Dd March 20, 2002 .Dt INSTALL 1 .Os .Sh NAME @@ -55,6 +55,9 @@ .Op Fl T Ar tags .Ek .Bk -words +.Op Fl a Ar command +.Ek +.Bk -words .Op Fl m Ar mode .Ek .Bk -words @@ -85,6 +88,9 @@ .Op Fl T Ar tags .Ek .Bk -words +.Op Fl a Ar command +.Ek +.Bk -words .Op Fl m Ar mode .Ek .Bk -words @@ -102,8 +108,8 @@ .Ar file1 ...\& .Ar fileN directory .Nm "" -.Op Fl Up .Fl d +.Op Fl Up .Bk -words .Op Fl M Ar metalog .Ek @@ -111,6 +117,9 @@ .Op Fl T Ar tags .Ek .Bk -words +.Op Fl a Ar command +.Ek +.Bk -words .Op Fl m Ar mode .Ek .Bk -words @@ -143,6 +152,23 @@ if permissions allow, An alternate backup suffix may be specified via the option's argument. .Pp .Bl -tag -width Ds +.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 Backup any existing files before overwriting them by renaming them to @@ -167,12 +193,15 @@ Copy the file. This flag turns off the default behavior of .Nm where it deletes the original file after creating the target. -.It Fl f +.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 +.It Fl g Ar group Specify a group. .It Fl M Ar metalog Write the metadata associated with each item installed to @@ -183,7 +212,7 @@ in an 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 +.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 @@ -207,7 +236,7 @@ are: .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 o +.It Fl o Ar owner Specify an owner. .It Fl p Preserve the source files access and modification times. @@ -238,7 +267,7 @@ is used, is invoked via the .Xr sh 1 shell, allowing a single -Fl S +.Fl S argument be to specified to .Nm which the shell can then tokenize. Normally, @@ -252,9 +281,6 @@ Specify the .Xr mtree 8 tags to write out for the file when using .Fl M Ar metalog . -.It Fl d -Create directories. -Missing parent directories are created as required. .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. diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 4aadcbf88e0e..9bcf34f123e7 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -1,4 +1,4 @@ -/* $NetBSD: xinstall.c,v 1.68 2002/02/28 00:22:51 lukem Exp $ */ +/* $NetBSD: xinstall.c,v 1.69 2002/03/19 14:17:04 lukem Exp $ */ /* * Copyright (c) 1987, 1993 @@ -50,7 +50,7 @@ __COPYRIGHT("@(#) Copyright (c) 1987, 1993\n\ #if 0 static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93"; #else -__RCSID("$NetBSD: xinstall.c,v 1.68 2002/02/28 00:22:51 lukem Exp $"); +__RCSID("$NetBSD: xinstall.c,v 1.69 2002/03/19 14:17:04 lukem Exp $"); #endif #endif /* not lint */ @@ -90,6 +90,7 @@ FILE *metafp; char *metafile; u_long fileflags; char *stripArgs; +char *afterinstallcmd; char *suffix = BACKUP_SUFFIX; #define LN_ABSOLUTE 0x01 @@ -103,6 +104,7 @@ char *suffix = BACKUP_SUFFIX; #define HASUID 0x04 /* Tell install the uid was given */ #define HASGID 0x08 /* Tell install the gid was given */ +void afterinstall(const char *, const char *, int); void backup(const char *); void copy(int, char *, int, char *, off_t); int do_link(char *, char *); @@ -130,8 +132,13 @@ main(int argc, char *argv[]) setprogname(argv[0]); iflags = 0; - while ((ch = getopt(argc, argv, "cbB:df:g:l:m:M:o:prsS:T:U")) != -1) + while ((ch = getopt(argc, argv, "a:cbB:df:g:l:m:M: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; @@ -422,9 +429,26 @@ makelink(char *from_name, char *to_name) } else { if (stat(to_name, &to_sb)) err(1, "%s: stat", to_name); - if (S_ISREG(to_sb.st_mode)) - metadata_log(to_name, "file", NULL, NULL); + if (S_ISREG(to_sb.st_mode)) { /* XXX: only metalog hardlinked files */ + int omode; + char *oowner, *ogroup, *offlags; + + /* XXX: use underlying perms */ + omode = mode; + mode = (to_sb.st_mode & 0777); + oowner = owner; + owner = NULL; + ogroup = group; + group = NULL; + offlags = fflags; + fflags = NULL; + metadata_log(to_name, "file", NULL, NULL); + mode = omode; + owner = oowner; + group = ogroup; + fflags = offlags; + } return; } } @@ -580,7 +604,19 @@ install(char *from_name, char *to_name, u_int flags) */ close(to_fd); if ((to_fd = open(to_name, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) - err(1, "stripping %s", to_name); + err(1, "stripping %s", to_name); + } + + if (afterinstallcmd != NULL) { + afterinstall(afterinstallcmd, to_name, 1); + + /* + * Re-open our fd on the target, in case we used an + * after-install command that does not work in-place + */ + close(to_fd); + if ((to_fd = open(to_name, O_RDONLY, S_IRUSR | S_IWUSR)) < 0) + err(1, "running after install command on %s", to_name); } /* @@ -761,6 +797,49 @@ strip(char *to_name) } } +/* + * afterinstall -- + * run provided command on the target file or directory after it's been + * installed and stripped, but before permissions are set or it's renamed + */ +void +afterinstall(const char *command, const char *to_name, int errunlink) +{ + int serrno, status; + char *cmd; + + switch (vfork()) { + case -1: + serrno = errno; + if (errunlink) + (void)unlink(to_name); + errx(1, "vfork: %s", strerror(serrno)); + /*NOTREACHED*/ + case 0: + /* + * build up a command line and let /bin/sh + * parse the arguments + */ + cmd = (char*)malloc(sizeof(char)* + (2+strlen(command)+ + strlen(to_name))); + + if (cmd == NULL) + errx(1, "%s", strerror(ENOMEM)); + + sprintf(cmd, "%s %s", command, to_name); + + execl(_PATH_BSHELL, "sh", "-c", cmd, NULL); + + warn("%s: exec of after install command", command); + _exit(1); + /*NOTREACHED*/ + default: + if ((wait(&status) == -1 || status) && errunlink) + (void)unlink(to_name); + } +} + /* * backup -- * backup file "to_name" to to_name.suffix @@ -817,6 +896,9 @@ install_dir(char *path, u_int flags) break; } + if (afterinstallcmd != NULL) + afterinstall(afterinstallcmd, path, 0); + if (!dounpriv && ( ((flags & (HASUID | HASGID)) && chown(path, uid, gid) == -1) || chmod(path, mode) == -1 )) { @@ -907,14 +989,19 @@ xdirname(char *path) void usage(void) { + const char *prog; - (void)fprintf(stderr, "\ -usage: install [-Ubcprs] [-M log] [-T tags] [-B suffix] [-f flags] [-m mode]\n\ - [-o owner] [-g group] [-l linkflags] [-S stripflags] file1 file2\n\ - install [-Ubcprs] [-M log] [-T tags] [-B suffix] [-f flags] [-m mode]\n\ - [-o owner] [-g group] [-l linkflags] [-S stripflags]\n\ - file1 ... fileN directory\n\ - install [-Up] [-M log] [-T tags] -d [-m mode]\n\ - [-o owner] [-g group] directory ...\n"); + prog = getprogname(); + + (void)fprintf(stderr, +"usage: %s [-Ubcprs] [-M log] [-T tags] [-B suffix] [-a afterinstallcmd]\n" +" [-f flags] [-m mode] [-o owner] [-g group] [-l linkflags]\n" +" [-S stripflags] file1 file2\n" +" %s [-Ubcprs] [-M log] [-T tags] [-B suffix] [-a afterinstallcmd]\n" +" [-f flags] [-m mode] [-o owner] [-g group] [-l linkflags]\n" +" [-S stripflags] file1 ... fileN directory\n" +" %s -d [-Up] [-M log] [-T tags] [-a afterinstallcmd] [-m mode]\n" +" [-o owner] [-g group] directory ...\n", + prog, prog, prog); exit(1); }