Merged with 4.4lite.

Changed to conform to NetBSD's new RCS Id convention.
Changed to use err(),errx(),warn(),warnx().
This commit is contained in:
jtc 1994-11-14 04:57:16 +00:00
parent 06f0d0a77d
commit 12ee8ea259
4 changed files with 222 additions and 158 deletions

View File

@ -1,14 +1,13 @@
# from: @(#)Makefile 5.5 (Berkeley) 6/24/90
# $Id: Makefile,v 1.5 1993/07/30 22:14:18 mycroft Exp $
# $NetBSD: Makefile,v 1.6 1994/11/14 04:57:16 jtc Exp $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= xinstall
SRCS= stat_flags.c xinstall.c
MAN1= install.0
CLEANFILES=xinstall
.PATH: ${.CURDIR}/../../bin/ls
realinstall:
install ${COPY} ${STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${PROG} ${DESTDIR}${BINDIR}/install
.include <bsd.prog.mk>

View File

@ -1,5 +1,7 @@
.\" Copyright (c) 1987, 1990 The Regents of the University of California.
.\" All rights reserved.
.\" $NetBSD: install.1,v 1.4 1994/11/14 04:57:17 jtc 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
@ -29,10 +31,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)install.1 6.11 (Berkeley) 5/31/91
.\" $Id: install.1,v 1.3 1993/08/01 07:25:49 mycroft Exp $
.\" @(#)install.1 8.1 (Berkeley) 6/6/93
.\"
.Dd May 31, 1991
.Dd June 6, 1993
.Dt INSTALL 1
.Os BSD 4.2
.Sh NAME
@ -41,15 +42,17 @@
.Sh SYNOPSIS
.Nm install
.Op Fl cs
.Op Fl f Ar flags
.Op Fl g Ar group
.Op Fl m Ar mode
.Op Fl o Ar owner
.Op Fl g Ar group
.Ar file1 file2
.Nm install
.Op Fl cs
.Op Fl f Ar flags
.Op Fl g Ar group
.Op Fl m Ar mode
.Op Fl o Ar owner
.Op Fl g Ar group
.Ar file1
\&...
.Ar fileN directory
@ -73,16 +76,26 @@ If the target file already exists, it is overwritten if permissions
allow.
.Pp
.Bl -tag -width Ds
.It Fl c
Copy the file.
This flag turns off the default behavior of
.Nm install
where it deletes the original file after creating the target.
.It Fl f
Specify the target's file flags.
(See
.Xr chflags 1
for a list of possible flags and their meanings.)
.It Fl g
Specify a group.
.It Fl m
Specify an alternate mode.
The default mode is set to 755.
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 o
Specify an owner.
.It Fl g
Specify a group.
.It Fl s
.Nm Install
exec's the command
@ -94,8 +107,13 @@ Create directories.
Missing parent directories are created as required.
.El
.Pp
.Nm Install
refuses to move a file onto itself.
By default,
.Nm install
preserves all file flags, with the exception of the ``nodump'' flag.
.Pp
The
.Nm install
utility attempts to prevent moving a file onto itself.
.Pp
Installing
.Pa /dev/null
@ -104,12 +122,12 @@ creates an empty file.
Upon successful completion a value of 0 is returned.
Otherwise, a value of 1 is returned.
.Sh SEE ALSO
.Xr chflags 1 ,
.Xr chgrp 1 ,
.Xr chmod 1 ,
.Xr cp 1 ,
.Xr mv 1 ,
.Xr strip 1 ,
.Xr a.out 5 ,
.Xr chown 8
.Sh HISTORY
The

View File

@ -1,6 +1,8 @@
/* $NetBSD: pathnames.h,v 1.3 1994/11/14 04:57:18 jtc Exp $ */
/*
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
* 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
@ -30,8 +32,8 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: @(#)pathnames.h 5.2 (Berkeley) 6/1/90
* $Id: pathnames.h,v 1.2 1993/08/01 18:00:57 mycroft Exp $
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
* $NetBSD: pathnames.h,v 1.3 1994/11/14 04:57:18 jtc Exp $
*/
#define _PATH_STRIP "/usr/bin/strip"

View File

@ -1,6 +1,8 @@
/* $NetBSD: xinstall.c,v 1.5 1994/11/14 04:57:19 jtc Exp $ */
/*
* Copyright (c) 1987 Regents of the University of California.
* All rights reserved.
* 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
@ -32,57 +34,82 @@
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1987 Regents of the University of California.\n\
All rights reserved.\n";
static char copyright[] =
"@(#) Copyright (c) 1987, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
/*static char sccsid[] = "from: @(#)xinstall.c 5.24 (Berkeley) 7/1/90";*/
static char rcsid[] = "$Id: xinstall.c,v 1.4 1994/10/02 21:32:31 cgd Exp $";
#if 0
static char sccsid[] = "@(#)xinstall.c 8.1 (Berkeley) 7/21/93";
#endif
static char rcsid[] = "$NetBSD: xinstall.c,v 1.5 1994/11/14 04:57:19 jtc Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include "pathnames.h"
static struct passwd *pp;
static struct group *gp;
static int docopy, dostrip, dodir, mode = 0755;
static char *group, *owner, pathbuf[MAXPATHLEN];
struct passwd *pp;
struct group *gp;
int docopy, dodir, dostrip;
int mode = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
char *group, *owner, pathbuf[MAXPATHLEN];
#define DIRECTORY 0x01 /* Tell install it's a directory. */
#define SETFLAGS 0x02 /* Tell install to set flags. */
void copy __P((int, char *, int, char *, off_t));
void install __P((char *, char *, u_long, u_int));
u_long string_to_flags __P((char **, u_long *, u_long *));
void strip __P((char *));
void usage __P((void));
int
main(argc, argv)
int argc;
char **argv;
char *argv[];
{
extern char *optarg;
extern int optind;
struct stat from_sb, to_sb;
mode_t *set, *setmode();
mode_t *set;
u_long fset;
u_int iflags;
int ch, no_target;
char *to_name;
char *flags, *to_name;
while ((ch = getopt(argc, argv, "cg:m:o:sd")) != EOF)
iflags = 0;
while ((ch = getopt(argc, argv, "cf:g:m:o:sd")) != EOF)
switch((char)ch) {
case 'c':
docopy = 1;
break;
case 'f':
flags = optarg;
if (string_to_flags(&flags, &fset, NULL))
errx(1, "%s: invalid flag", flags);
iflags |= SETFLAGS;
break;
case 'g':
group = optarg;
break;
case 'm':
if (!(set = setmode(optarg))) {
(void)fprintf(stderr,
"install: invalid file mode.\n");
exit(1);
}
if (!(set = setmode(optarg)))
errx(1, "%s: invalid file mode", optarg);
mode = getmode(set, 0);
break;
case 'o':
@ -110,26 +137,22 @@ main(argc, argv)
usage();
/* get group and owner id's */
if (group && !(gp = getgrnam(group))) {
fprintf(stderr, "install: unknown group %s.\n", group);
exit(1);
}
if (owner && !(pp = getpwnam(owner))) {
fprintf(stderr, "install: unknown user %s.\n", owner);
exit(1);
}
if (group && !(gp = getgrnam(group)))
errx(1, "unknown group %s", group);
if (owner && !(pp = getpwnam(owner)))
errx(1, "unknown user %s", owner);
if (dodir) {
for (; *argv != NULL; ++argv)
build(*argv);
install_dir(*argv);
exit (0);
/* NOTREACHED */
}
}
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, 1);
install(*argv, to_name, fset, iflags | DIRECTORY);
exit(0);
}
@ -138,22 +161,25 @@ main(argc, argv)
usage();
if (!no_target) {
if (stat(*argv, &from_sb)) {
fprintf(stderr, "install: can't find %s.\n", *argv);
exit(1);
}
if (!S_ISREG(to_sb.st_mode)) {
fprintf(stderr, "install: %s isn't a regular file.\n", to_name);
exit(1);
}
if (to_sb.st_dev == from_sb.st_dev && to_sb.st_ino == from_sb.st_ino) {
fprintf(stderr, "install: %s and %s are the same file.\n", *argv, to_name);
exit(1);
}
/* unlink now... avoid ETXTBSY errors later */
if (stat(*argv, &from_sb))
err(1, "%s", *argv);
if (!S_ISREG(to_sb.st_mode))
errx(1, "%s: %s", to_name, strerror(EFTYPE));
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.
*/
#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));
(void)unlink(to_name);
}
install(*argv, to_name, 0);
install(*argv, to_name, fset, iflags);
exit(0);
}
@ -161,88 +187,129 @@ main(argc, argv)
* install --
* build a path name and install the file
*/
install(from_name, to_name, isdir)
void
install(from_name, to_name, fset, flags)
char *from_name, *to_name;
int isdir;
u_long fset;
u_int flags;
{
struct stat from_sb;
int devnull, from_fd, to_fd;
char *C, *rindex();
struct stat from_sb, to_sb;
int devnull, from_fd, to_fd, serrno;
char *p;
/* if try to install NULL file to a directory, fails */
if (isdir || strcmp(from_name, _PATH_DEVNULL)) {
if (stat(from_name, &from_sb)) {
fprintf(stderr, "install: can't find %s.\n", from_name);
exit(1);
}
if (!S_ISREG(from_sb.st_mode)) {
fprintf(stderr, "install: %s isn't a regular file.\n", from_name);
exit(1);
}
/* build the target path */
if (isdir) {
(void)sprintf(pathbuf, "%s/%s", to_name, (C = rindex(from_name, '/')) ? ++C : from_name);
/* 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(1, "%s", from_name);
if (!S_ISREG(from_sb.st_mode))
errx(1, "%s: %s", from_name, strerror(EFTYPE));
/* Build the target path. */
if (flags & DIRECTORY) {
(void)snprintf(pathbuf, sizeof(pathbuf), "%s/%s",
to_name,
(p = rindex(from_name, '/')) ? ++p : from_name);
to_name = pathbuf;
}
devnull = 0;
} else
} else {
from_sb.st_flags = 0; /* XXX */
devnull = 1;
}
/* unlink now... avoid ETXTBSY errors later */
/*
* Unlink now... avoid ETXTBSY errors later. Try and turn
* off the append/immutable bits -- if we fail, go ahead,
* it might work.
*/
if (stat(to_name, &to_sb) == 0 &&
to_sb.st_flags & (NOCHANGEBITS))
(void)chflags(to_name, to_sb.st_flags & ~(NOCHANGEBITS));
(void)unlink(to_name);
/* create target */
if ((to_fd = open(to_name, O_CREAT|O_WRONLY|O_TRUNC, 0600)) < 0) {
error(to_name);
exit(1);
}
/* Create target. */
if ((to_fd = open(to_name,
O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)) < 0)
err(1, "%s", to_name);
if (!devnull) {
if ((from_fd = open(from_name, O_RDONLY, 0)) < 0) {
(void)unlink(to_name);
error(from_name);
exit(1);
err(1, "%s", from_name);
}
copy(from_fd, from_name, to_fd, to_name);
copy(from_fd, from_name, to_fd, to_name, from_sb.st_size);
(void)close(from_fd);
}
if (dostrip)
strip(to_name);
/*
* set owner, group, mode for target; do the chown first,
* Set owner, group, mode for target; do the chown first,
* chown may lose the setuid bits.
*/
if ((group || owner) &&
fchown(to_fd, owner ? pp->pw_uid : -1, group ? gp->gr_gid : -1) ||
fchmod(to_fd, mode)) {
error(to_name);
bad(to_name);
fchown(to_fd, owner ? pp->pw_uid : -1, group ? gp->gr_gid : -1)) {
serrno = errno;
(void)unlink(to_name);
errx(1, "%s: chown/chgrp: %s", to_name, strerror(serrno));
}
if (fchmod(to_fd, mode)) {
serrno = errno;
(void)unlink(to_name);
errx(1, "%s: chmod: %s", to_name, strerror(serrno));
}
/*
* If provided a set of flags, set them, otherwise, preserve the
* flags, except for the dump flag.
*/
if (fchflags(to_fd,
flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
serrno = errno;
(void)unlink(to_name);
errx(1, "%s: chflags: %s", to_name, strerror(serrno));
}
(void)close(to_fd);
if (!docopy && !devnull && unlink(from_name)) {
error(from_name);
exit(1);
}
if (!docopy && !devnull && unlink(from_name))
err(1, "%s", from_name);
}
/*
* copy --
* copy from one file to another
*/
copy(from_fd, from_name, to_fd, to_name)
void
copy(from_fd, from_name, to_fd, to_name, size)
register int from_fd, to_fd;
char *from_name, *to_name;
off_t size;
{
register int n;
char buf[MAXBSIZE];
register int nr, nw;
int serrno;
char *p, buf[MAXBSIZE];
while ((n = read(from_fd, buf, sizeof(buf))) > 0)
if (write(to_fd, buf, n) != n) {
error(to_name);
bad(to_name);
/*
* Mmap and write if less than 8M (the limit is so we don't totally
* trash memory on big files. This is really a minor hack, but it
* wins some CPU back.
*/
if (size <= 8 * 1048576) {
if ((p = mmap(NULL, (size_t)size, PROT_READ,
0, from_fd, (off_t)0)) == (char *)-1)
err(1, "%s", from_name);
if (write(to_fd, p, size) != size)
err(1, "%s", to_name);
} else {
while ((nr = read(from_fd, buf, sizeof(buf))) > 0)
if ((nw = write(to_fd, buf, nr)) != nr) {
serrno = errno;
(void)unlink(to_name);
errx(1, "%s: %s",
to_name, strerror(nw > 0 ? EIO : serrno));
}
if (nr != 0) {
serrno = errno;
(void)unlink(to_name);
errx(1, "%s: %s", from_name, strerror(serrno));
}
if (n == -1) {
error(from_name);
bad(to_name);
}
}
@ -250,30 +317,32 @@ copy(from_fd, from_name, to_fd, to_name)
* strip --
* use strip(1) to strip the target file
*/
void
strip(to_name)
char *to_name;
{
int status;
int serrno, status;
switch (vfork()) {
case -1:
error("fork");
bad(to_name);
serrno = errno;
(void)unlink(to_name);
errx(1, "forks: %s", strerror(errno));
case 0:
execl(_PATH_STRIP, "strip", to_name, (char *)NULL);
error(_PATH_STRIP);
_exit(1);
execl(_PATH_STRIP, "strip", to_name, NULL);
err(1, "%s", _PATH_STRIP);
default:
if (wait(&status) == -1 || status)
bad(to_name);
(void)unlink(to_name);
}
}
/*
* build --
* install_dir --
* build directory heirarchy
*/
build(path)
int
install_dir(path)
char *path;
{
register char *p;
@ -286,7 +355,7 @@ build(path)
*p = '\0';
if (stat(path, &sb)) {
if (errno != ENOENT || mkdir(path, 0777) < 0) {
error(path);
warn("%s", path);
return(1);
}
}
@ -297,45 +366,21 @@ build(path)
if ((group || owner) &&
chown(path, owner ? pp->pw_uid : -1, group ? gp->gr_gid : -1) ||
chmod(path, mode)) {
error(path);
warn("%s", path);
}
return(0);
}
/*
* error --
* print out an error message
*/
error(s)
char *s;
{
extern int errno;
char *strerror();
(void)fprintf(stderr, "install: %s: %s\n", s, strerror(errno));
}
/*
* bad --
* remove created target and die
*/
bad(fname)
char *fname;
{
(void)unlink(fname);
exit(1);
}
/*
* usage --
* print a usage message and die
*/
void
usage()
{
(void)fprintf(stderr, "\
usage: install [-cs] [-g group] [-m mode] [-o owner] file1 file2\n\
install [-cs] [-g group] [-m mode] [-o owner] file1 ... fileN directory\n\
usage: install [-cs] [-f flags] [-g group] [-m mode] [-o owner] file1 file2\n\
install [-cs] [-f flags] [-g group] [-m mode] [-o owner] file1 ... fileN directory\n\
install -d [-g group] [-m mode] [-o owner] directory ...\n");
exit(1);
}