From a8ef09103d69c11c99fe50ad80c7cac8bce3133d Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 10 Oct 2012 17:20:17 +0200 Subject: [PATCH] mtree mknod Change-Id: I887437c7b84839fc644da4c55bd59b6a414408ef --- commands/Makefile | 2 +- commands/mknod/Makefile | 4 - commands/mknod/mknod.c | 73 ------- man/man8/Makefile | 2 +- man/man8/mknod.8 | 39 ---- releasetools/nbsd_ports | 2 + sbin/Makefile | 2 +- sbin/mknod/Makefile | 8 + sbin/mknod/mknod.8 | 229 ++++++++++++++++++++++ sbin/mknod/mknod.c | 393 ++++++++++++++++++++++++++++++++++++++ sbin/mknod/pack_dev.c | 290 ++++++++++++++++++++++++++++ sbin/mknod/pack_dev.h | 52 +++++ usr.sbin/Makefile | 2 +- usr.sbin/mtree/Makefile | 8 +- usr.sbin/mtree/compare.c | 92 +++++---- usr.sbin/mtree/crc.c | 5 +- usr.sbin/mtree/create.c | 151 +++++++++------ usr.sbin/mtree/extern.h | 9 +- usr.sbin/mtree/misc.c | 7 +- usr.sbin/mtree/mtree.8 | 80 ++++++-- usr.sbin/mtree/mtree.c | 55 ++++-- usr.sbin/mtree/mtree.h | 21 +- usr.sbin/mtree/spec.c | 33 +++- usr.sbin/mtree/specspec.c | 273 ++++++++++++++++++++++++++ usr.sbin/mtree/verify.c | 39 ++-- 25 files changed, 1580 insertions(+), 291 deletions(-) delete mode 100644 commands/mknod/Makefile delete mode 100644 commands/mknod/mknod.c delete mode 100644 man/man8/mknod.8 create mode 100644 sbin/mknod/Makefile create mode 100644 sbin/mknod/mknod.8 create mode 100644 sbin/mknod/mknod.c create mode 100644 sbin/mknod/pack_dev.c create mode 100644 sbin/mknod/pack_dev.h create mode 100644 usr.sbin/mtree/specspec.c diff --git a/commands/Makefile b/commands/Makefile index c618efa5d..8a697d888 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -15,7 +15,7 @@ SUBDIR= add_route arp ash at backup banner basename btrace cal \ intr ipcrm ipcs irdpd isoread join kill last \ less loadkeys loadramdisk logger look lp \ lpd ls lspci mail MAKEDEV \ - mesg mined mkfifo mknod \ + mesg mined mkfifo \ mkproto mount mt netconf nice acknm nohup \ nonamed od paste patch pax \ ping postinstall poweroff pr prep printf printroot \ diff --git a/commands/mknod/Makefile b/commands/mknod/Makefile deleted file mode 100644 index fe1ab212e..000000000 --- a/commands/mknod/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -PROG= mknod -MAN= - -.include diff --git a/commands/mknod/mknod.c b/commands/mknod/mknod.c deleted file mode 100644 index 43d3b732f..000000000 --- a/commands/mknod/mknod.c +++ /dev/null @@ -1,73 +0,0 @@ -/* mknod - build a special file Author: Andy Tanenbaum */ - -#include -#include -#include -#include -#include -#include -#ifdef __NBSD_LIBC -#include -#endif - -int main(int argc, char *argv []); -void badcomm(void); -void badfifo(void); -void badchar(void); -void badblock(void); - -int main(argc, argv) -int argc; -char *argv[]; -{ -/* Mknod name b/c major minor makes a node. */ - - int mode, major, minor, dev; - - if (argc < 3) badcomm(); - if (*argv[2] != 'b' && *argv[2] != 'c' && *argv[2] != 'p') badcomm(); - if (*argv[2] == 'p' && argc != 3) badfifo(); - if (*argv[2] == 'c' && argc != 5) badchar(); - if (*argv[2] == 'b' && argc != 5) badblock(); - if (*argv[2] == 'p') { - mode = 010666; - dev = 0; - } else { - mode = (*argv[2] == 'b' ? 060666 : 020666); - major = atoi(argv[3]); - minor = atoi(argv[4]); - if (major - 1 > 0xFE || minor > 0xFF) badcomm(); - dev = (major << 8) | minor; - } - if (mknod(argv[1], mode, dev) < 0) { - int err = errno; - std_err("mknod: "); - errno = err; - perror(argv[1]); - } - return(0); -} - -void badcomm() -{ - std_err("Usage: mknod name b/c/p [major minor]\n"); - exit(1); -} - -void badfifo() -{ - std_err("Usage: mknod name p\n"); - exit(1); -} - -void badchar() -{ - std_err("Usage: mknod name c major minor\n"); - exit(1); -} - -void badblock() -{ - std_err("Usage: mknod name b major minor\n"); - exit(1); -} diff --git a/man/man8/Makefile b/man/man8/Makefile index cbcdb079e..ac6cc6cf2 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -3,7 +3,7 @@ MAN= add_route.8 backup.8 boot.8 btrace.8 \ dhcpd.8 diskctl.8 elvprsv.8 fbdctl.8 fdisk.8 fingerd.8 \ getty.8 halt.8 hgfs.8 httpd.8 ifconfig.8 inet.8 init.8 \ intr.8 irdpd.8 loadramdisk.8 MAKEDEV.8 \ - mknod.8 netconf.8 newroot.8 nonamed.8 \ + netconf.8 newroot.8 nonamed.8 \ ossdevlinks.8 part.8 partition.8 \ poweroff.8 printroot.8 pr_routes.8 pwdauth.8 rarpd.8 \ rdate.8 readclock.8 reboot.8 repartition.8 \ diff --git a/man/man8/mknod.8 b/man/man8/mknod.8 deleted file mode 100644 index c28ef1d56..000000000 --- a/man/man8/mknod.8 +++ /dev/null @@ -1,39 +0,0 @@ -.TH MKNOD 8 -.SH NAME -mknod \- create a special file -.SH SYNOPSIS -\fBmknod \fIfile\fR [\fBb\fR] [\fBc\fR] \fImajor \fIminor\fR -.br -\fBmknod \fIfile\fR \fBp\fR\fR -.br -.de FL -.TP -\\fB\\$1\\fR -\\$2 -.. -.de EX -.TP 20 -\\fB\\$1\\fR -# \\$2 -.. -.SH EXAMPLES -.TP 20 -.B mknod /dev/plotter c 7 0 -# Create special file for a plotter -.TP 20 -.B mknod /dev/fd3 b 2 3 -# Create a device for diskette drive 3 -.TP 20 -.B mknod /tmp/stream p -# Create a named pipe -.SH DESCRIPTION -.PP -.I Mknod -creates a special file named -.I file , -with the indicated major and minor device numbers. -The second argument specifies a block special, a character special, or a -named pipe. Named pipes do not have device numbers so they are omitted. -.SH "SEE ALSO" -.BR mkfifo (1), -.BR mknod (2). diff --git a/releasetools/nbsd_ports b/releasetools/nbsd_ports index 17015e0b2..1c5afed4e 100644 --- a/releasetools/nbsd_ports +++ b/releasetools/nbsd_ports @@ -5,6 +5,8 @@ 2012/10/17 12:00:00,tools/cksum 2012/10/17 12:00:00,usr.bin/cksum 2012/10/17 12:00:00,usr.sbin/postinstall +2012/10/10 16:16:12,sbin/mknod +2012/10/10 16:16:12,usr.sbin/mtree 2012/05/01 16:16:12,external/bsd/libarchive 2012/02/10 16:16:12,usr.sbin/chroot 2011/01/17 18:11:10,usr.bin/ldd diff --git a/sbin/Makefile b/sbin/Makefile index 220ff19f3..7f30c293a 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -2,6 +2,6 @@ .include -SUBDIR= fsck fsck_ext2fs newfs_ext2fs +SUBDIR= fsck fsck_ext2fs newfs_ext2fs mknod .include diff --git a/sbin/mknod/Makefile b/sbin/mknod/Makefile new file mode 100644 index 000000000..a7d150555 --- /dev/null +++ b/sbin/mknod/Makefile @@ -0,0 +1,8 @@ +# $NetBSD: Makefile,v 1.13 2009/04/11 07:58:12 lukem Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= mknod +SRCS= mknod.c pack_dev.c +MAN= mknod.8 + +.include diff --git a/sbin/mknod/mknod.8 b/sbin/mknod/mknod.8 new file mode 100644 index 000000000..b0d2a9515 --- /dev/null +++ b/sbin/mknod/mknod.8 @@ -0,0 +1,229 @@ +.\" $NetBSD: mknod.8,v 1.28 2004/06/17 21:30:14 dsl Exp $ +.\" +.\" Copyright (c) 1980, 1991, 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. +.\" +.\" @(#)mknod.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd June 17, 2004 +.Dt MKNOD 8 +.Os +.Sh NAME +.Nm mknod +.Nd make device special file +.Sh SYNOPSIS +.Nm +.Op Fl rR +.Op Fl F Ar fmt +.Op Fl g Ar gid +.Op Fl m Ar mode +.Op Fl u Ar uid +.Ar name +.Op Cm c | Cm b +.Op Ar driver | Ar major +.Ar minor +.Nm +.Op Fl rR +.Op Fl F Ar fmt +.Op Fl g Ar gid +.Op Fl m Ar mode +.Op Fl u Ar uid +.Ar name +.Op Cm c | Cm b +.Ar major unit subunit +.Nm +.Op Fl rR +.Op Fl g Ar gid +.Op Fl m Ar mode +.Op Fl u Ar uid +.Ar name +.Op Cm c | Cm b +.Ar number +.Nm +.Op Fl rR +.Op Fl g Ar gid +.Op Fl m Ar mode +.Op Fl u Ar uid +.Ar name +.Cm p +.Nm +.Fl l +.Sh DESCRIPTION +The +.Nm +command creates device special files, or fifos. +Normally the shell script +.Pa /dev/MAKEDEV +is used to create special files for commonly known devices; it executes +.Nm +with the appropriate arguments and can make all the files required for the +device. +.Pp +To make nodes manually, the arguments are: +.Pp +.Bl -tag -width xmxmode +.It Fl r +Replace an existing file if its type is incorrect. +.It Fl R +Replace an existing file if its type is incorrect. +Correct the mode, user and group. +.It Fl F Ar fmt +Create device nodes that may be used by an operating system which +uses device numbers packed in a different format than +.Nx +uses. +This is necessary when +.Nx +is used as an +.Tn NFS +server for netbooted computers running other operating systems. +.Pp +The following values for the +.Ar fmt +are recognized: +.Sy native , +.Sy 386bsd , +.Sy 4bsd , +.Sy bsdos , +.Sy freebsd , +.Sy hpux , +.Sy isc , +.Sy linux , +.Sy netbsd , +.Sy osf1 , +.Sy sco , +.Sy solaris , +.Sy sunos , +.Sy svr3 , +.Sy svr4 , +and +.Sy ultrix . +.It Fl g Ar gid +Specify the group for the device node. +The +.Ar gid +operand may be a numeric group ID or a group name. +If a group name is also a numeric group ID, +the operand is used as a group name. +Precede a numeric group ID with a +.Cm # +to stop it being treated as a name. +.It Fl m Ar mode +Specify the mode for the device node. +The mode may be absolute or symbolic, see +.Xr chmod 1 . +.It Fl u Ar uid +Specify the user for the device node. +The +.Ar uid +operand may be a numeric user ID or a user name. +If a user name is also a numeric user ID, +the operand is used as a user name. +Precede a numeric user ID with a +.Cm # +to stop it being treated as a name. +.It Ar name +Device name, for example +.Dq sd +for a SCSI disk on an HP300 or a +.Dq pty +for pseudo-devices. +.It Cm b | Cm c | Cm p +Type of device. +If the device is a block type device such as a tape or disk drive +which needs both cooked and raw special files, the type is +.Cm b . +All other devices are character type devices, such as terminal +and pseudo devices, and are type +.Cm c . +Specifying +.Cm p +creates fifo files. +.It Ar driver | Ar major +The major device number is an integer number which tells the kernel +which device driver entry point to use. +If the device driver is configured into the current kernel it may be +specified by driver name or major number. +To find out which major device number to use for a particular device, +use +.Nm +.Fl l , +check the file +.Pa /dev/MAKEDEV +to see if the device is known, or check +the system dependent device configuration file: +.Bd -filled -offset indent +.Dq Pa /usr/src/sys/arch/\*[Lt]arch\*[Gt]/\*[Lt]arch\*[Gt]/conf.c +.Ed +.Pp +.Po +e.g. +.Pa /usr/src/sys/arch/vax/vax/conf.c +.Pc . +.It Ar minor +The minor device number tells the kernel which one of several similar +devices the node corresponds to; for example, it may be a specific serial +port or pty. +.It Ar unit No and Ar subunit +The unit and subunit numbers select a subset of a device; for example, the +unit may specify a particular SCSI disk, and the subunit a partition on +that disk. +(Currently this form of specification is only supported by the +.Ar bsdos +format, for compatibility with the +.Bsx +.Nm ) . +.It Ar number +A single opaque device number. +Useful for netbooted computers which require device numbers packed +in a format that isn't supported by +.Fl F . +.It Fl l +List the device drivers configured into the current kernel together with their +block and character major numbers. +.El +.Sh SEE ALSO +.Xr chmod 1 , +.Xr mkfifo 1 , +.Xr mkfifo 2 , +.Xr mknod 2 , +.Xr MAKEDEV 8 +.Sh HISTORY +A +.Nm +command appeared in +.At v6 . +The +.Fl F +option appeared in +.Nx 1.4 . +The +.Fl g , l , m , r , R , +and +.Fl u +options, and the ability to specify a driver by name appeared in +.Nx 2.0 . diff --git a/sbin/mknod/mknod.c b/sbin/mknod/mknod.c new file mode 100644 index 000000000..3d8bb5ebe --- /dev/null +++ b/sbin/mknod/mknod.c @@ -0,0 +1,393 @@ +/* $NetBSD: mknod.c,v 1.40 2011/08/27 18:37:41 joerg Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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" +#endif + +#include +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1998\ + The NetBSD Foundation, Inc. All rights reserved."); +__RCSID("$NetBSD: mknod.c,v 1.40 2011/08/27 18:37:41 joerg Exp $"); +#endif /* not lint */ + +#include +#include +#include +#if !HAVE_NBTOOL_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pack_dev.h" + +static int gid_name(const char *, gid_t *); +static portdev_t callPack(pack_t *, int, u_long *); + +__dead static void usage(void); + +#ifdef KERN_DRIVERS +static struct kinfo_drivers *kern_drivers; +static int num_drivers; + +static void get_device_info(void); +static void print_device_info(char **); +static int major_from_name(const char *, mode_t); +#endif + +#define MAXARGS 3 /* 3 for bsdos, 2 for rest */ + +int +main(int argc, char **argv) +{ + char *name, *p; + mode_t mode; + portdev_t dev; + pack_t *pack; + u_long numbers[MAXARGS]; + int n, ch, fifo, hasformat; + int r_flag = 0; /* force: delete existing entry */ +#ifdef KERN_DRIVERS + int l_flag = 0; /* list device names and numbers */ + int major; +#endif + void *modes = 0; + uid_t uid = -1; + gid_t gid = -1; + int rval; + + dev = 0; + fifo = hasformat = 0; + pack = pack_native; + +#ifdef KERN_DRIVERS + while ((ch = getopt(argc, argv, "lrRF:g:m:u:")) != -1) { +#else + while ((ch = getopt(argc, argv, "rRF:g:m:u:")) != -1) { +#endif + switch (ch) { + +#ifdef KERN_DRIVERS + case 'l': + l_flag = 1; + break; +#endif + + case 'r': + r_flag = 1; + break; + + case 'R': + r_flag = 2; + break; + + case 'F': + pack = pack_find(optarg); + if (pack == NULL) + errx(1, "invalid format: %s", optarg); + hasformat++; + break; + + case 'g': + if (optarg[0] == '#') { + gid = strtol(optarg + 1, &p, 10); + if (*p == 0) + break; + } + if (gid_name(optarg, &gid) == 0) + break; + gid = strtol(optarg, &p, 10); + if (*p == 0) + break; + errx(1, "%s: invalid group name", optarg); + + case 'm': + modes = setmode(optarg); + if (modes == NULL) + err(1, "Cannot set file mode `%s'", optarg); + break; + + case 'u': + if (optarg[0] == '#') { + uid = strtol(optarg + 1, &p, 10); + if (*p == 0) + break; + } + if (uid_from_user(optarg, &uid) == 0) + break; + uid = strtol(optarg, &p, 10); + if (*p == 0) + break; + errx(1, "%s: invalid user name", optarg); + + default: + case '?': + usage(); + } + } + argc -= optind; + argv += optind; + +#ifdef KERN_DRIVERS + if (l_flag) { + print_device_info(argv); + return 0; + } +#endif + + if (argc < 2 || argc > 10) + usage(); + + name = *argv; + argc--; + argv++; + + umask(mode = umask(0)); + mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) & ~mode; + + if (argv[0][1] != '\0') + goto badtype; + switch (*argv[0]) { + case 'c': + mode |= S_IFCHR; + break; + + case 'b': + mode |= S_IFBLK; + break; + + case 'p': + if (hasformat) + errx(1, "format is meaningless for fifos"); + mode |= S_IFIFO; + fifo = 1; + break; + + default: + badtype: + errx(1, "node type must be 'b', 'c' or 'p'."); + } + argc--; + argv++; + + if (fifo) { + if (argc != 0) + usage(); + } else { + if (argc < 1 || argc > MAXARGS) + usage(); + } + + for (n = 0; n < argc; n++) { + errno = 0; + numbers[n] = strtoul(argv[n], &p, 0); + if (*p == 0 && errno == 0) + continue; +#ifdef KERN_DRIVERS + if (n == 0) { + major = major_from_name(argv[0], mode); + if (major != -1) { + numbers[0] = major; + continue; + } + if (!isdigit(*(unsigned char *)argv[0])) + errx(1, "unknown driver: %s", argv[0]); + } +#endif + errx(1, "invalid number: %s", argv[n]); + } + + switch (argc) { + case 0: + dev = 0; + break; + + case 1: + dev = numbers[0]; + break; + + default: + dev = callPack(pack, argc, numbers); + break; + } + + if (modes != NULL) + mode = getmode(modes, mode); + umask(0); + rval = fifo ? mkfifo(name, mode) : mknod(name, mode, dev); + if (rval < 0 && errno == EEXIST && r_flag) { + struct stat sb; + if (lstat(name, &sb) != 0 || (!fifo && sb.st_rdev != dev)) + sb.st_mode = 0; + + if ((sb.st_mode & S_IFMT) == (mode & S_IFMT)) { + if (r_flag == 1) + /* Ignore permissions and user/group */ + return 0; + if (sb.st_mode != mode) + rval = chmod(name, mode); + else + rval = 0; + } else { + unlink(name); + rval = fifo ? mkfifo(name, mode) + : mknod(name, mode, dev); + } + } + if (rval < 0) + err(1, "%s", name); + if ((uid != (uid_t)-1 || gid != (uid_t)-1) && chown(name, uid, gid) == -1) + /* XXX Should we unlink the files here? */ + warn("%s: uid/gid not changed", name); + + return 0; +} + +static void +usage(void) +{ + const char *progname = getprogname(); + + (void)fprintf(stderr, + "usage: %s [-rR] [-F format] [-m mode] [-u user] [-g group]\n", + progname); + (void)fprintf(stderr, +#ifdef KERN_DRIVERS + " [ name [b | c] [major | driver] minor\n" +#else + " [ name [b | c] major minor\n" +#endif + " | name [b | c] major unit subunit\n" + " | name [b | c] number\n" + " | name p ]\n"); +#ifdef KERN_DRIVERS + (void)fprintf(stderr, " %s -l [driver] ...\n", progname); +#endif + exit(1); +} + +static int +gid_name(const char *name, gid_t *gid) +{ + struct group *g; + + g = getgrnam(name); + if (!g) + return -1; + *gid = g->gr_gid; + return 0; +} + +static portdev_t +callPack(pack_t *f, int n, u_long *numbers) +{ + portdev_t d; + const char *error = NULL; + + d = (*f)(n, numbers, &error); + if (error != NULL) + errx(1, "%s", error); + return d; +} + +#ifdef KERN_DRIVERS +static void +get_device_info(void) +{ + static int mib[2] = {CTL_KERN, KERN_DRIVERS}; + size_t len; + + if (sysctl(mib, 2, NULL, &len, NULL, 0) != 0) + err(1, "kern.drivers" ); + kern_drivers = malloc(len); + if (kern_drivers == NULL) + err(1, "malloc"); + if (sysctl(mib, 2, kern_drivers, &len, NULL, 0) != 0) + err(1, "kern.drivers" ); + + num_drivers = len / sizeof *kern_drivers; +} + +static void +print_device_info(char **names) +{ + int i; + struct kinfo_drivers *kd; + + if (kern_drivers == NULL) + get_device_info(); + + do { + kd = kern_drivers; + for (i = 0; i < num_drivers; kd++, i++) { + if (*names && strcmp(*names, kd->d_name)) + continue; + printf("%s", kd->d_name); + if (kd->d_cmajor != -1) + printf(" character major %d", kd->d_cmajor); + if (kd->d_bmajor != -1) + printf(" block major %d", kd->d_bmajor); + printf("\n"); + } + } while (*names && *++names); +} + +static int +major_from_name(const char *name, mode_t mode) +{ + int i; + struct kinfo_drivers *kd; + + if (kern_drivers == NULL) + get_device_info(); + + kd = kern_drivers; + for (i = 0; i < num_drivers; kd++, i++) { + if (strcmp(name, kd->d_name)) + continue; + if (S_ISCHR(mode)) + return kd->d_cmajor; + return kd->d_bmajor; + } + return -1; +} +#endif diff --git a/sbin/mknod/pack_dev.c b/sbin/mknod/pack_dev.c new file mode 100644 index 000000000..800a56c6e --- /dev/null +++ b/sbin/mknod/pack_dev.c @@ -0,0 +1,290 @@ +/* $NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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" +#endif + +#include +#if !defined(lint) +__RCSID("$NetBSD: pack_dev.c,v 1.11 2011/08/27 18:37:41 joerg Exp $"); +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "pack_dev.h" + +static pack_t pack_netbsd; +static pack_t pack_freebsd; +static pack_t pack_8_8; +static pack_t pack_12_20; +static pack_t pack_14_18; +static pack_t pack_8_24; +static pack_t pack_bsdos; +static int compare_format(const void *, const void *); + +static const char iMajorError[] = "invalid major number"; +static const char iMinorError[] = "invalid minor number"; +static const char tooManyFields[] = "too many fields for format"; + + /* exported */ +portdev_t +pack_native(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev(numbers[0], numbers[1]); + if ((u_long)major(dev) != numbers[0]) + *error = iMajorError; + else if ((u_long)minor(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +static portdev_t +pack_netbsd(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_netbsd(numbers[0], numbers[1]); + if ((u_long)major_netbsd(dev) != numbers[0]) + *error = iMajorError; + else if ((u_long)minor_netbsd(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_freebsd(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) +#define minor_freebsd(x) ((int32_t)(((x) & 0xffff00ff) >> 0)) +#define makedev_freebsd(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ + (((y) << 0) & 0xffff00ff))) + +static portdev_t +pack_freebsd(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_freebsd(numbers[0], numbers[1]); + if ((u_long)major_freebsd(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_freebsd(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_8_8(x) ((int32_t)(((x) & 0x0000ff00) >> 8)) +#define minor_8_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) +#define makedev_8_8(x,y) ((portdev_t)((((x) << 8) & 0x0000ff00) | \ + (((y) << 0) & 0x000000ff))) + +static portdev_t +pack_8_8(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_8_8(numbers[0], numbers[1]); + if ((u_long)major_8_8(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_8_8(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_12_20(x) ((int32_t)(((x) & 0xfff00000) >> 20)) +#define minor_12_20(x) ((int32_t)(((x) & 0x000fffff) >> 0)) +#define makedev_12_20(x,y) ((portdev_t)((((x) << 20) & 0xfff00000) | \ + (((y) << 0) & 0x000fffff))) + +static portdev_t +pack_12_20(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_12_20(numbers[0], numbers[1]); + if ((u_long)major_12_20(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_12_20(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_14_18(x) ((int32_t)(((x) & 0xfffc0000) >> 18)) +#define minor_14_18(x) ((int32_t)(((x) & 0x0003ffff) >> 0)) +#define makedev_14_18(x,y) ((portdev_t)((((x) << 18) & 0xfffc0000) | \ + (((y) << 0) & 0x0003ffff))) + +static portdev_t +pack_14_18(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_14_18(numbers[0], numbers[1]); + if ((u_long)major_14_18(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_14_18(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_8_24(x) ((int32_t)(((x) & 0xff000000) >> 24)) +#define minor_8_24(x) ((int32_t)(((x) & 0x00ffffff) >> 0)) +#define makedev_8_24(x,y) ((portdev_t)((((x) << 24) & 0xff000000) | \ + (((y) << 0) & 0x00ffffff))) + +static portdev_t +pack_8_24(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_8_24(numbers[0], numbers[1]); + if ((u_long)major_8_24(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_8_24(dev) != numbers[1]) + *error = iMinorError; + } else + *error = tooManyFields; + return (dev); +} + + +#define major_12_12_8(x) ((int32_t)(((x) & 0xfff00000) >> 20)) +#define unit_12_12_8(x) ((int32_t)(((x) & 0x000fff00) >> 8)) +#define subunit_12_12_8(x) ((int32_t)(((x) & 0x000000ff) >> 0)) +#define makedev_12_12_8(x,y,z) ((portdev_t)((((x) << 20) & 0xfff00000) | \ + (((y) << 8) & 0x000fff00) | \ + (((z) << 0) & 0x000000ff))) + +static portdev_t +pack_bsdos(int n, u_long numbers[], const char **error) +{ + portdev_t dev = 0; + + if (n == 2) { + dev = makedev_12_20(numbers[0], numbers[1]); + if ((u_long)major_12_20(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)minor_12_20(dev) != numbers[1]) + *error = iMinorError; + } else if (n == 3) { + dev = makedev_12_12_8(numbers[0], numbers[1], numbers[2]); + if ((u_long)major_12_12_8(dev) != numbers[0]) + *error = iMajorError; + if ((u_long)unit_12_12_8(dev) != numbers[1]) + *error = "invalid unit number"; + if ((u_long)subunit_12_12_8(dev) != numbers[2]) + *error = "invalid subunit number"; + } else + *error = tooManyFields; + return (dev); +} + + + /* list of formats and pack functions */ + /* this list must be sorted lexically */ +static struct format { + const char *name; + pack_t *pack; +} formats[] = { + {"386bsd", pack_8_8}, + {"4bsd", pack_8_8}, + {"bsdos", pack_bsdos}, + {"freebsd", pack_freebsd}, + {"hpux", pack_8_24}, + {"isc", pack_8_8}, + {"linux", pack_8_8}, + {"native", pack_native}, + {"netbsd", pack_netbsd}, + {"osf1", pack_12_20}, + {"sco", pack_8_8}, + {"solaris", pack_14_18}, + {"sunos", pack_8_8}, + {"svr3", pack_8_8}, + {"svr4", pack_14_18}, + {"ultrix", pack_8_8}, +}; + +static int +compare_format(const void *key, const void *element) +{ + const char *name; + const struct format *format; + + name = key; + format = element; + + return (strcmp(name, format->name)); +} + + +pack_t * +pack_find(const char *name) +{ + struct format *format; + + format = bsearch(name, formats, + sizeof(formats)/sizeof(formats[0]), + sizeof(formats[0]), compare_format); + if (format == 0) + return (NULL); + return (format->pack); +} diff --git a/sbin/mknod/pack_dev.h b/sbin/mknod/pack_dev.h new file mode 100644 index 000000000..d909df428 --- /dev/null +++ b/sbin/mknod/pack_dev.h @@ -0,0 +1,52 @@ +/* $NetBSD: pack_dev.h,v 1.7 2008/04/28 20:23:09 martin Exp $ */ + +/*- + * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _PACK_DEV_H +#define _PACK_DEV_H + +#ifdef __CYGWIN__ +typedef __dev32_t portdev_t; +#else +typedef dev_t portdev_t; +#endif +typedef portdev_t pack_t(int, u_long [], const char **); + +pack_t *pack_find(const char *); +pack_t pack_native; + +#define major_netbsd(x) ((int32_t)((((x) & 0x000fff00) >> 8))) +#define minor_netbsd(x) ((int32_t)((((x) & 0xfff00000) >> 12) | \ + (((x) & 0x000000ff) >> 0))) +#define makedev_netbsd(x,y) ((dev_t)((((x) << 8) & 0x000fff00) | \ + (((y) << 12) & 0xfff00000) | \ + (((y) << 0) & 0x000000ff))) + +#endif /* _PACK_DEV_H */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index ace631768..d06abea76 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -3,6 +3,6 @@ .include # NetBSD imports -SUBDIR= installboot pwd_mkdb user vipw zic chroot mkfs.mfs +SUBDIR= installboot pwd_mkdb user vipw zic chroot mkfs.mfs mtree .include diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile index 41b7b66f2..bd81e34cc 100644 --- a/usr.sbin/mtree/Makefile +++ b/usr.sbin/mtree/Makefile @@ -1,14 +1,16 @@ -# $NetBSD: Makefile,v 1.32 2009/04/22 15:23:05 lukem Exp $ +# $NetBSD: Makefile,v 1.33 2012/10/05 01:26:56 christos Exp $ # from: @(#)Makefile 8.2 (Berkeley) 4/27/95 .include +CPPFLAGS+= -Dlchown=chown -Dlchmod=chmod + PROG= mtree #CPPFLAGS+=-DDEBUG CPPFLAGS+= -DMTREE MAN= mtree.8 -SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c \ - getid.c pack_dev.c +SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c specspec.c \ + verify.c getid.c pack_dev.c .if (${HOSTPROG:U} == "") DPADD+= ${LIBUTIL} LDADD+= -lutil diff --git a/usr.sbin/mtree/compare.c b/usr.sbin/mtree/compare.c index 8d96ed01f..8b66181ad 100644 --- a/usr.sbin/mtree/compare.c +++ b/usr.sbin/mtree/compare.c @@ -1,4 +1,4 @@ -/* $NetBSD: compare.c,v 1.52 2008/12/28 19:36:30 christos Exp $ */ +/* $NetBSD: compare.c,v 1.55 2012/10/05 00:59:35 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -38,11 +38,12 @@ #if 0 static char sccsid[] = "@(#)compare.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: compare.c,v 1.52 2008/12/28 19:36:30 christos Exp $"); +__RCSID("$NetBSD: compare.c,v 1.55 2012/10/05 00:59:35 christos Exp $"); #endif #endif /* not lint */ #include +#include #include #include @@ -83,6 +84,7 @@ do { \ #if HAVE_STRUCT_STAT_ST_FLAGS + #define CHANGEFLAGS \ if (flags != p->fts_statp->st_flags) { \ char *sf; \ @@ -124,6 +126,28 @@ do { \ } while (0) #endif /* HAVE_STRUCT_STAT_ST_FLAGS */ +#ifdef __minix +#if 0 +int +lchmod(const char *path, mode_t flags) +{ + return -1; +} + +int +lchown(const char *path, uid_t owner, gid_t group) +{ + return -1; +} +#endif + +int +utimes(const char *path, const struct timeval times[2]) +{ + return -1; +} +#endif + int compare(NODE *s, FTSENT *p) { @@ -174,7 +198,7 @@ typeerr: LABEL; } if (mtree_Wflag) goto afterpermwhack; -#if HAVE_STRUCT_STAT_ST_FLAGS && !defined(__minix) +#if HAVE_STRUCT_STAT_ST_FLAGS if (iflag && !uflag) { if (s->flags & F_FLAGS) SETFLAGS(p->fts_statp->st_flags, SP_FLGS); @@ -194,7 +218,6 @@ typeerr: LABEL; tab, (long long)s->st_rdev, (long long)p->fts_statp->st_rdev); if (uflag) { -#ifndef __minix if ((unlink(p->fts_accpath) == -1) || (mknod(p->fts_accpath, s->st_mode | nodetoino(s->type), @@ -205,7 +228,6 @@ typeerr: LABEL; strerror(errno)); else printf(", modified)\n"); -#endif } else printf(")\n"); tab = "\t"; @@ -216,13 +238,11 @@ typeerr: LABEL; printf("%suser (%lu, %lu", tab, (u_long)s->st_uid, (u_long)p->fts_statp->st_uid); if (uflag) { -#ifndef __minix if (lchown(p->fts_accpath, s->st_uid, -1)) printf(", not modified: %s)\n", strerror(errno)); else printf(", modified)\n"); -#endif } else printf(")\n"); tab = "\t"; @@ -232,13 +252,11 @@ typeerr: LABEL; printf("%sgid (%lu, %lu", tab, (u_long)s->st_gid, (u_long)p->fts_statp->st_gid); if (uflag) { -#ifndef __minix if (lchown(p->fts_accpath, -1, s->st_gid)) printf(", not modified: %s)\n", strerror(errno)); else printf(", modified)\n"); -#endif } else printf(")\n"); @@ -267,13 +285,11 @@ typeerr: LABEL; tab, (u_long)s->st_mode, (u_long)p->fts_statp->st_mode & MBITS); if (uflag) { -#ifndef __minix if (lchmod(p->fts_accpath, s->st_mode)) printf(", not modified: %s)\n", strerror(errno)); else printf(", modified)\n"); -#endif } else printf(")\n"); @@ -328,20 +344,18 @@ typeerr: LABEL; tab, ctime(&smtime)); printf("%.24s", ctime(&pmtime)); if (tflag) { -#ifndef __minix tv[1] = tv[0]; if (utimes(p->fts_accpath, tv)) printf(", not modified: %s)\n", strerror(errno)); else printf(", modified)\n"); -#endif } else printf(")\n"); tab = "\t"; } } -#if HAVE_STRUCT_STAT_ST_FLAGS && !defined(__minix) +#if HAVE_STRUCT_STAT_ST_FLAGS /* * XXX * since lchflags(2) will reset file times, the utimes() above @@ -404,14 +418,14 @@ typeerr: LABEL; if (s->flags & F_MD5) { if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%smd5: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, MD5KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->md5digest, digestbuf)) { LABEL; - printf("%smd5 (0x%s, 0x%s)\n", - tab, s->md5digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, MD5KEY, s->md5digest, digestbuf); } tab = "\t"; free(digestbuf); @@ -422,14 +436,14 @@ typeerr: LABEL; if (s->flags & F_RMD160) { if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%srmd160: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, RMD160KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->rmd160digest, digestbuf)) { LABEL; - printf("%srmd160 (0x%s, 0x%s)\n", - tab, s->rmd160digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, RMD160KEY, s->rmd160digest, digestbuf); } tab = "\t"; free(digestbuf); @@ -440,14 +454,14 @@ typeerr: LABEL; if (s->flags & F_SHA1) { if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%ssha1: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, SHA1KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->sha1digest, digestbuf)) { LABEL; - printf("%ssha1 (0x%s, 0x%s)\n", - tab, s->sha1digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, SHA1KEY, s->sha1digest, digestbuf); } tab = "\t"; free(digestbuf); @@ -458,46 +472,48 @@ typeerr: LABEL; if (s->flags & F_SHA256) { if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%ssha256: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, SHA256KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->sha256digest, digestbuf)) { LABEL; - printf("%ssha256 (0x%s, 0x%s)\n", - tab, s->sha256digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, SHA256KEY, s->sha256digest, digestbuf); } tab = "\t"; free(digestbuf); } } +#ifdef SHA384_BLOCK_LENGTH if (s->flags & F_SHA384) { if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%ssha384: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, SHA384KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->sha384digest, digestbuf)) { LABEL; - printf("%ssha384 (0x%s, 0x%s)\n", - tab, s->sha384digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, SHA384KEY, s->sha384digest, digestbuf); } tab = "\t"; free(digestbuf); } } +#endif if (s->flags & F_SHA512) { if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) { LABEL; - printf("%ssha512: %s: %s\n", - tab, p->fts_accpath, strerror(errno)); + printf("%s%s: %s: %s\n", + tab, SHA512KEY, p->fts_accpath, strerror(errno)); tab = "\t"; } else { if (strcmp(s->sha512digest, digestbuf)) { LABEL; - printf("%ssha512 (0x%s, 0x%s)\n", - tab, s->sha512digest, digestbuf); + printf("%s%s (0x%s, 0x%s)\n", + tab, SHA512KEY, s->sha512digest, digestbuf); } tab = "\t"; free(digestbuf); diff --git a/usr.sbin/mtree/crc.c b/usr.sbin/mtree/crc.c index 6e2dfd410..4eac66e5b 100644 --- a/usr.sbin/mtree/crc.c +++ b/usr.sbin/mtree/crc.c @@ -1,4 +1,4 @@ -/* $NetBSD: crc.c,v 1.8 2005/06/02 06:04:46 lukem Exp $ */ +/* $NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)crc.c 8.1 (Berkeley) 6/17/93"; #else -__RCSID("$NetBSD: crc.c,v 1.8 2005/06/02 06:04:46 lukem Exp $"); +__RCSID("$NetBSD: crc.c,v 1.9 2012/10/05 00:40:51 christos Exp $"); #endif #endif /* not lint */ @@ -114,7 +114,6 @@ static const u_int32_t crctab[] = { * locations to store the crc and the number of bytes read. It returns 0 on * success and 1 on failure. Errno is set on failure. */ -extern int sflag; u_int32_t crc_total = ~0; /* The crc over a number of files. */ int diff --git a/usr.sbin/mtree/create.c b/usr.sbin/mtree/create.c index fdc8d6932..b9a3c44ee 100644 --- a/usr.sbin/mtree/create.c +++ b/usr.sbin/mtree/create.c @@ -1,4 +1,4 @@ -/* $NetBSD: create.c,v 1.58 2009/04/03 21:18:59 apb Exp $ */ +/* $NetBSD: create.c,v 1.65 2012/10/05 01:21:44 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)create.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: create.c,v 1.58 2009/04/03 21:18:59 apb Exp $"); +__RCSID("$NetBSD: create.c,v 1.65 2012/10/05 01:21:44 christos Exp $"); #endif #endif /* not lint */ @@ -83,11 +83,17 @@ static uid_t uid; static mode_t mode; static u_long flags; -static int dcmp(const FTSENT **, const FTSENT **); -static void output(int *, const char *, ...) - __attribute__((__format__(__printf__, 2, 3))); +#ifdef __FreeBSD__ +#define FTS_CONST const +#else +#define FTS_CONST +#endif + +static int dcmp(const FTSENT *FTS_CONST *, const FTSENT *FTS_CONST *); +static void output(int, int *, const char *, ...) + __attribute__((__format__(__printf__, 3, 4))); static int statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *); -static void statf(FTSENT *); +static void statf(int, FTSENT *); void cwalk(void) @@ -99,6 +105,7 @@ cwalk(void) const char *user; char *argv[2]; char dot[] = "."; + int indent = 0; argv[0] = dot; argv[1] = NULL; @@ -112,26 +119,32 @@ cwalk(void) ""; } - printf( - "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n#\t date: %s", - user, host, fullpath, ctime(&clocktime)); + if (!nflag) + printf( + "#\t user: %s\n#\tmachine: %s\n#\t tree: %s\n" + "#\t date: %s", + user, host, fullpath, ctime(&clocktime)); if ((t = fts_open(argv, ftsoptions, dcmp)) == NULL) mtree_err("fts_open: %s", strerror(errno)); while ((p = fts_read(t)) != NULL) { + if (jflag) + indent = p->fts_level * 4; if (check_excludes(p->fts_name, p->fts_path)) { fts_set(t, p, FTS_SKIP); continue; } switch(p->fts_info) { case FTS_D: - printf("\n# %s\n", p->fts_path); + if (!nflag) + printf("\n# %s\n", p->fts_path); statd(t, p, &uid, &gid, &mode, &flags); - statf(p); + statf(indent, p); break; case FTS_DP: - if (p->fts_level > 0) - printf("# %s\n..\n\n", p->fts_path); + if (!nflag && p->fts_level > 0) + printf("%*s# %s\n%*s..\n\n", indent, "", + p->fts_path, indent, ""); break; case FTS_DNR: case FTS_ERR: @@ -141,7 +154,7 @@ cwalk(void) break; default: if (!dflag) - statf(p); + statf(indent, p); break; } @@ -152,56 +165,59 @@ cwalk(void) } static void -statf(FTSENT *p) +statf(int indent, FTSENT *p) { u_int32_t len, val; - int fd, indent; - const char *name; + int fd, offset; + const char *name = NULL; #if !defined(NO_MD5) || !defined(NO_RMD160) || !defined(NO_SHA1) || !defined(NO_SHA2) char *digestbuf; #endif - indent = printf("%s%s", + offset = printf("%*s%s%s", indent, "", S_ISDIR(p->fts_statp->st_mode) ? "" : " ", vispath(p->fts_name)); - if (indent > INDENTNAMELEN) - indent = MAXLINELEN; + if (offset > (INDENTNAMELEN + indent)) + offset = MAXLINELEN; else - indent += printf("%*s", INDENTNAMELEN - indent, ""); + offset += printf("%*s", (INDENTNAMELEN + indent) - offset, ""); if (!S_ISREG(p->fts_statp->st_mode)) - output(&indent, "type=%s", inotype(p->fts_statp->st_mode)); + output(indent, &offset, "type=%s", + inotype(p->fts_statp->st_mode)); if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid) { if (keys & F_UNAME && (name = user_from_uid(p->fts_statp->st_uid, 1)) != NULL) - output(&indent, "uname=%s", name); - else /* if (keys & F_UID) */ - output(&indent, "uid=%u", p->fts_statp->st_uid); + output(indent, &offset, "uname=%s", name); + if (keys & F_UID || (keys & F_UNAME && name == NULL)) + output(indent, &offset, "uid=%u", p->fts_statp->st_uid); } if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid) { if (keys & F_GNAME && (name = group_from_gid(p->fts_statp->st_gid, 1)) != NULL) - output(&indent, "gname=%s", name); - else /* if (keys & F_GID) */ - output(&indent, "gid=%u", p->fts_statp->st_gid); + output(indent, &offset, "gname=%s", name); + if (keys & F_GID || (keys & F_GNAME && name == NULL)) + output(indent, &offset, "gid=%u", p->fts_statp->st_gid); } if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode) - output(&indent, "mode=%#o", p->fts_statp->st_mode & MBITS); + output(indent, &offset, "mode=%#o", + p->fts_statp->st_mode & MBITS); if (keys & F_DEV && (S_ISBLK(p->fts_statp->st_mode) || S_ISCHR(p->fts_statp->st_mode))) - output(&indent, "device=%#llx", + output(indent, &offset, "device=%#llx", (long long)p->fts_statp->st_rdev); if (keys & F_NLINK && p->fts_statp->st_nlink != 1) - output(&indent, "nlink=%u", p->fts_statp->st_nlink); + output(indent, &offset, "nlink=%u", p->fts_statp->st_nlink); if (keys & F_SIZE && S_ISREG(p->fts_statp->st_mode)) - output(&indent, "size=%lld", (long long)p->fts_statp->st_size); + output(indent, &offset, "size=%lld", + (long long)p->fts_statp->st_size); if (keys & F_TIME) #if defined(BSD4_4) && !defined(HAVE_NBTOOL_CONFIG_H) - output(&indent, "time=%ld.%ld", + output(indent, &offset, "time=%ld.%09ld", (long)p->fts_statp->st_mtimespec.tv_sec, p->fts_statp->st_mtimespec.tv_nsec); #else - output(&indent, "time=%ld.%ld", + output(indent, &offset, "time=%ld.%09ld", (long)p->fts_statp->st_mtime, (long)0); #endif if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) { @@ -209,59 +225,70 @@ statf(FTSENT *p) crc(fd, &val, &len)) mtree_err("%s: %s", p->fts_accpath, strerror(errno)); close(fd); - output(&indent, "cksum=%lu", (long)val); + output(indent, &offset, "cksum=%lu", (long)val); } #ifndef NO_MD5 if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = MD5File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: MD5File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "md5=%s", digestbuf); + mtree_err("%s: MD5File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", MD5KEY, digestbuf); free(digestbuf); } #endif /* ! NO_MD5 */ #ifndef NO_RMD160 if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = RMD160File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: RMD160File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "rmd160=%s", digestbuf); + mtree_err("%s: RMD160File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", RMD160KEY, digestbuf); free(digestbuf); } #endif /* ! NO_RMD160 */ #ifndef NO_SHA1 if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA1File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: SHA1File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "sha1=%s", digestbuf); + mtree_err("%s: SHA1File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", SHA1KEY, digestbuf); free(digestbuf); } #endif /* ! NO_SHA1 */ #ifndef NO_SHA2 if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA256_File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: SHA256_File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "sha256=%s", digestbuf); + mtree_err("%s: SHA256_File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", SHA256KEY, digestbuf); free(digestbuf); } +#ifdef SHA384_BLOCK_LENGTH if (keys & F_SHA384 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA384_File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: SHA384_File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "sha384=%s", digestbuf); + mtree_err("%s: SHA384_File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", SHA384KEY, digestbuf); free(digestbuf); } +#endif if (keys & F_SHA512 && S_ISREG(p->fts_statp->st_mode)) { if ((digestbuf = SHA512_File(p->fts_accpath, NULL)) == NULL) - mtree_err("%s: SHA512_File failed: %s", p->fts_accpath, strerror(errno)); - output(&indent, "sha512=%s", digestbuf); + mtree_err("%s: SHA512_File failed: %s", p->fts_accpath, + strerror(errno)); + output(indent, &offset, "%s=%s", SHA512KEY, digestbuf); free(digestbuf); } #endif /* ! NO_SHA2 */ if (keys & F_SLINK && (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) - output(&indent, "link=%s", vispath(rlink(p->fts_accpath))); + output(indent, &offset, "link=%s", + vispath(rlink(p->fts_accpath))); #if HAVE_STRUCT_STAT_ST_FLAGS - if (keys & F_FLAGS && p->fts_statp->st_flags != flags) - output(&indent, "flags=%s", - flags_to_string(p->fts_statp->st_flags, "none")); + if (keys & F_FLAGS && p->fts_statp->st_flags != flags) { + char *str = flags_to_string(p->fts_statp->st_flags, "none"); + output(indent, &offset, "flags=%s", str); + free(str); + } #endif putchar('\n'); } @@ -291,7 +318,7 @@ statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, uid_t suid; mode_t smode; u_long sflags = 0; - const char *name; + const char *name = NULL; gid_t savegid; uid_t saveuid; mode_t savemode; @@ -358,23 +385,25 @@ statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, if (keys & F_UNAME && (name = user_from_uid(saveuid, 1)) != NULL) printf(" uname=%s", name); - else /* if (keys & F_UID) */ + if (keys & F_UID || (keys & F_UNAME && name == NULL)) printf(" uid=%lu", (u_long)saveuid); } if (keys & (F_GID | F_GNAME)) { if (keys & F_GNAME && (name = group_from_gid(savegid, 1)) != NULL) printf(" gname=%s", name); - else /* if (keys & F_UID) */ + if (keys & F_GID || (keys & F_GNAME && name == NULL)) printf(" gid=%lu", (u_long)savegid); } if (keys & F_MODE) printf(" mode=%#lo", (u_long)savemode); if (keys & F_NLINK) printf(" nlink=1"); - if (keys & F_FLAGS) - printf(" flags=%s", - flags_to_string(saveflags, "none")); + if (keys & F_FLAGS) { + char *str = flags_to_string(saveflags, "none"); + printf(" flags=%s", str); + free(str); + } printf("\n"); *puid = saveuid; *pgid = savegid; @@ -394,7 +423,7 @@ statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, * Keep this in sync with nodecmp() in spec.c. */ static int -dcmp(const FTSENT **a, const FTSENT **b) +dcmp(const FTSENT *FTS_CONST *a, const FTSENT *FTS_CONST *b) { if (S_ISDIR((*a)->fts_statp->st_mode)) { @@ -406,7 +435,7 @@ dcmp(const FTSENT **a, const FTSENT **b) } void -output(int *offset, const char *fmt, ...) +output(int indent, int *offset, const char *fmt, ...) { va_list ap; char buf[1024]; @@ -416,8 +445,8 @@ output(int *offset, const char *fmt, ...) va_end(ap); if (*offset + strlen(buf) > MAXLINELEN - 3) { - printf(" \\\n%*s", INDENTNAMELEN, ""); - *offset = INDENTNAMELEN; + printf(" \\\n%*s", INDENTNAMELEN + indent, ""); + *offset = INDENTNAMELEN + indent; } *offset += printf(" %s", buf) + 1; } diff --git a/usr.sbin/mtree/extern.h b/usr.sbin/mtree/extern.h index 31d479246..007081684 100644 --- a/usr.sbin/mtree/extern.h +++ b/usr.sbin/mtree/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.32 2011/08/29 20:37:43 joerg Exp $ */ +/* $NetBSD: extern.h,v 1.36 2012/10/05 01:26:56 christos Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -36,8 +36,10 @@ #if HAVE_NBTOOL_CONFIG_H #include "nbtool_config.h" #else +#ifndef __minix #define HAVE_STRUCT_STAT_ST_FLAGS 1 #endif +#endif #include #include @@ -67,9 +69,10 @@ void parsetags(slist_t *, char *); u_int parsetype(const char *); void read_excludes_file(const char *); const char *rlink(const char *); -int verify(void); +int verify(FILE *); -extern int dflag, eflag, iflag, lflag, mflag, rflag, sflag, tflag, uflag; +extern int dflag, eflag, iflag, jflag, lflag, mflag, + nflag, qflag, rflag, sflag, tflag, uflag; extern int mtree_Mflag, mtree_Sflag, mtree_Wflag; extern size_t mtree_lineno; extern u_int32_t crc_total; diff --git a/usr.sbin/mtree/misc.c b/usr.sbin/mtree/misc.c index ba6a5ee1d..4c5e5f6a4 100644 --- a/usr.sbin/mtree/misc.c +++ b/usr.sbin/mtree/misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: misc.c,v 1.30 2009/01/18 12:09:38 lukem Exp $ */ +/* $NetBSD: misc.c,v 1.32 2012/10/05 01:31:05 christos Exp $ */ /*- * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ #include #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: misc.c,v 1.30 2009/01/18 12:09:38 lukem Exp $"); +__RCSID("$NetBSD: misc.c,v 1.32 2012/10/05 01:31:05 christos Exp $"); #endif /* not lint */ #include @@ -71,7 +71,10 @@ static KEY keylist[] = { {"md5digest", F_MD5, NEEDVALUE}, {"mode", F_MODE, NEEDVALUE}, {"nlink", F_NLINK, NEEDVALUE}, + {"nochange", F_NOCHANGE, 0}, {"optional", F_OPT, 0}, + {"ripemd160digest", F_RMD160, NEEDVALUE}, + {"rmd160digest",F_RMD160, NEEDVALUE}, {"rmd160", F_RMD160, NEEDVALUE}, {"rmd160digest",F_RMD160, NEEDVALUE}, {"sha1", F_SHA1, NEEDVALUE}, diff --git a/usr.sbin/mtree/mtree.8 b/usr.sbin/mtree/mtree.8 index 8a150b6a9..67ffb73fc 100644 --- a/usr.sbin/mtree/mtree.8 +++ b/usr.sbin/mtree/mtree.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: mtree.8,v 1.53 2010/01/20 14:00:48 wiz Exp $ +.\" $NetBSD: mtree.8,v 1.63 2012/10/05 09:18:02 wiz Exp $ .\" .\" Copyright (c) 1989, 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -56,7 +56,7 @@ .\" .\" @(#)mtree.8 8.2 (Berkeley) 12/11/93 .\" -.Dd January 20, 2010 +.Dd October 4, 2012 .Dt MTREE 8 .Os .Sh NAME @@ -64,7 +64,7 @@ .Nd map a directory hierarchy .Sh SYNOPSIS .Nm -.Op Fl CcDdeLlMPrSUuWx +.Op Fl CcDdejLlMnPqrSUuWx .Op Fl i | Fl m .Op Fl E Ar tags .Op Fl f Ar spec @@ -104,8 +104,8 @@ The full path name (beginning with .Dq \&./ ) is always printed as the first field; -.Fl k , .Fl K , +.Fl k , and .Fl R can be used to control which other keywords are printed; @@ -113,6 +113,7 @@ can be used to control which other keywords are printed; and .Fl I can be used to control which files are printed; +and the .Fl S option can be used to sort the output. .It Fl c @@ -143,6 +144,17 @@ specification. Read the specification from .Ar file , instead of from the standard input. +.Pp +If this option is specified twice, the two specifications are compared +to each other rather than to the file hierarchy. +The specifications will be sorted like output generated using +.Fl c . +The output format in this case is somewhat reminiscent of +.Xr comm 1 , +having "in first spec only", "in second spec only", and "different" +columns, prefixed by zero, one and two TAB characters respectively. +Each entry in the "different" column occupies two lines, one from each +specification. .It Fl I Ar tags Add the comma separated tags to the .Dq inclusion @@ -154,6 +166,20 @@ and If no inclusion list is provided, the default is to display all files. .It Fl i If specified, set the schg and/or sappnd flags. +.It Fl j +Indent the output 4 spaces each time a directory level is descended when +creating a specification with the +.Fl c +option. +This does not affect either the /set statements or the comment before each +directory. +It does however affect the comment before the close of each directory. +This is the equivalent of the +.Fl i +option in the +.Fx +version of +.Nm . .It Fl K Ar keywords Add the specified (whitespace or comma separated) keywords to the current set of keywords. @@ -187,13 +213,13 @@ particular, if other bits like the sticky bit or suid/sgid bits are set either in the specification or the file, exact checking will be performed. This option may not be set at the same time as the -.Fl u -or .Fl U +or +.Fl u option. .It Fl M Permit merging of specification entries with different types, -with the last entry take precedence. +with the last entry taking precedence. .It Fl m If the schg and/or sappnd flags are specified, reset these flags. Note that this is only possible with securelevel less than 1 (i.e., @@ -202,6 +228,13 @@ mode). See .Xr init 8 for information on security levels. +.It Fl n +Do not emit pathname comments when creating a specification. +Normally +a comment is emitted before each directory and before the close of that +directory when using the +.Fl c +option. .It Fl N Ar dbdir Use the user database text file .Pa master.passwd @@ -222,6 +255,12 @@ This is the default. Use the file hierarchy rooted in .Ar path , instead of the current directory. +.It Fl q +Quiet mode. +Do not complain when a +.Dq missing +directory cannot be created because it already exists. +This occurs when the directory is a symbolic link. .It Fl R Ar keywords Remove the specified (whitespace or comma separated) keywords from the current set of keywords. @@ -287,9 +326,9 @@ Don't attempt to set various file attributes such as the ownership, mode, flags, or time when creating new directories or changing existing entries. This option will be most useful when used in conjunction with -.Fl u +.Fl U or -.Fl U . +.Fl u . .It Fl X Ar exclude-file The specified file contains .Xr fnmatch 3 @@ -329,7 +368,6 @@ or .Sy char file types. The argument must be one of the following forms: -.Pp .Bl -tag -width 4n .It Ar format , Ns Ar major , Ns Ar minor A device with @@ -411,9 +449,14 @@ The current file's permissions as a numeric (octal) or symbolic value. .It Sy nlink The number of hard links the file is expected to have. +.It Sy nochange +Make sure this file or directory exists but otherwise ignore all attributes. .It Sy optional The file is optional; don't complain about the file if it's not in the file hierarchy. +.It Sy ripemd160digest +Synonym for +.Sy rmd160 . .It Sy rmd160 The .Tn RMD-160 @@ -459,7 +502,10 @@ and These may be specified without leading or trailing commas, but will be stored internally with them. .It Sy time -The last modification time of the file. +The last modification time of the file, +in second and nanoseconds. +The value should include a period character and exactly nine digits after +the period. .It Sy type The type of the file; may be set to any one of the following: .Pp @@ -498,7 +544,6 @@ and .Sy uid . .Pp There are four types of lines in a specification: -.Pp .Bl -enum .It Set global values for a keyword. @@ -581,7 +626,7 @@ appropriately. Multiple entries for the same full path are permitted if the types are the same (unless .Fl M -is given, and then the types may differ); +is given, in which case the types may differ); in this case the settings for the last entry take precedence. .Pp A path name that does not contain a slash will be treated as a relative path. @@ -631,10 +676,11 @@ can be used to detect which of the binaries have actually been modified. .Pp The .Fl d -and +option can be used in combination with +.Fl U +or .Fl u -options can be used in combination to create directory hierarchies -for distributions and other such things. +to create directory hierarchies for, for example, distributions. .Sh SEE ALSO .Xr chflags 1 , .Xr chgrp 1 , @@ -681,8 +727,8 @@ keywords, .Fl D , .Fl E , .Fl I , -.Fl l , .Fl L , +.Fl l , .Fl N , .Fl P , .Fl R , diff --git a/usr.sbin/mtree/mtree.c b/usr.sbin/mtree/mtree.c index 31219abfc..2174b3d9d 100644 --- a/usr.sbin/mtree/mtree.c +++ b/usr.sbin/mtree/mtree.c @@ -1,4 +1,4 @@ -/* $NetBSD: mtree.c,v 1.37 2011/08/29 20:37:43 joerg Exp $ */ +/* $NetBSD: mtree.c,v 1.42 2012/10/05 09:18:08 wiz Exp $ */ /*- * Copyright (c) 1989, 1990, 1993 @@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1990, 1993\ #if 0 static char sccsid[] = "@(#)mtree.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: mtree.c,v 1.37 2011/08/29 20:37:43 joerg Exp $"); +__RCSID("$NetBSD: mtree.c,v 1.42 2012/10/05 09:18:08 wiz Exp $"); #endif #endif /* not lint */ @@ -59,8 +59,8 @@ __RCSID("$NetBSD: mtree.c,v 1.37 2011/08/29 20:37:43 joerg Exp $"); #include "extern.h" int ftsoptions = FTS_PHYSICAL; -int cflag, Cflag, dflag, Dflag, eflag, iflag, lflag, mflag, - rflag, sflag, tflag, uflag, Uflag; +int cflag, Cflag, dflag, Dflag, eflag, iflag, jflag, lflag, mflag, + nflag, qflag, rflag, sflag, tflag, uflag, Uflag; char fullpath[MAXPATHLEN]; __dead static void usage(void); @@ -70,14 +70,17 @@ main(int argc, char **argv) { int ch, status; char *dir, *p; + FILE *spec1, *spec2; setprogname(argv[0]); dir = NULL; init_excludes(); + spec1 = stdin; + spec2 = NULL; while ((ch = getopt(argc, argv, - "cCdDeE:f:I:ik:K:lLmMN:p:PrR:s:StuUWxX:")) + "cCdDeE:f:I:ik:K:lLmMnN:p:PqrR:s:StuUWxX:")) != -1) { switch((char)ch) { case 'c': @@ -99,8 +102,18 @@ main(int argc, char **argv) eflag = 1; break; case 'f': - if (!(freopen(optarg, "r", stdin))) - mtree_err("%s: %s", optarg, strerror(errno)); + if (spec1 == stdin) { + spec1 = fopen(optarg, "r"); + if (spec1 == NULL) + mtree_err("%s: %s", optarg, + strerror(errno)); + } else if (spec2 == NULL) { + spec2 = fopen(optarg, "r"); + if (spec2 == NULL) + mtree_err("%s: %s", optarg, + strerror(errno)); + } else + usage(); break; case 'i': iflag = 1; @@ -108,6 +121,9 @@ main(int argc, char **argv) case 'I': parsetags(&includetags, optarg); break; + case 'j': + jflag = 1; + break; case 'k': keys = F_TYPE; while ((p = strsep(&optarg, " \t,")) != NULL) @@ -132,6 +148,9 @@ main(int argc, char **argv) case 'M': mtree_Mflag = 1; break; + case 'n': + nflag = 1; + break; case 'N': if (! setup_getid(optarg)) mtree_err( @@ -145,6 +164,9 @@ main(int argc, char **argv) ftsoptions &= ~FTS_LOGICAL; ftsoptions |= FTS_PHYSICAL; break; + case 'q': + qflag = 1; + break; case 'r': rflag = 1; break; @@ -163,11 +185,9 @@ main(int argc, char **argv) mtree_Sflag = 1; break; case 't': - mtree_err("Minix does not support utimes(2)"); tflag = 1; break; case 'u': - mtree_err("Minix does not support lchmod(3)"); uflag = 1; break; case 'U': @@ -193,6 +213,13 @@ main(int argc, char **argv) if (argc) usage(); + if (spec2 && (cflag || Cflag || Dflag)) + mtree_err("Double -f, -c, -C and -D flags are mutually " + "exclusive"); + + if (dir && spec2) + mtree_err("Double -f and -p flags are mutually exclusive"); + if (dir && chdir(dir)) mtree_err("%s: %s", dir, strerror(errno)); @@ -213,10 +240,13 @@ main(int argc, char **argv) exit(0); } if (Cflag || Dflag) { - dump_nodes("", spec(stdin), Dflag); + dump_nodes("", spec(spec1), Dflag); exit(0); } - status = verify(); + if (spec2 != NULL) + status = mtree_specspec(spec1, spec2); + else + status = verify(spec1); if (Uflag && (status == MISMATCHEXIT)) status = 0; exit(status); @@ -227,7 +257,8 @@ usage(void) { fprintf(stderr, - "usage: %s [-CcDdeLlMPrSUuWx] [-i|-m] [-E tags] [-f spec]\n" + "usage: %s [-CcDdejLlMnPqrSUuWx] [-i|-m] [-E tags]\n" + "\t\t[-f spec] [-f spec]\n" "\t\t[-I tags] [-K keywords] [-k keywords] [-N dbdir] [-p path]\n" "\t\t[-R keywords] [-s seed] [-X exclude-file]\n", getprogname()); diff --git a/usr.sbin/mtree/mtree.h b/usr.sbin/mtree/mtree.h index 81e538675..93d6cdfb0 100644 --- a/usr.sbin/mtree/mtree.h +++ b/usr.sbin/mtree/mtree.h @@ -1,4 +1,4 @@ -/* $NetBSD: mtree.h,v 1.27 2009/04/04 21:49:49 apb Exp $ */ +/* $NetBSD: mtree.h,v 1.31 2012/10/05 09:17:29 wiz Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -86,6 +86,8 @@ typedef struct _node { #define F_UID 0x00080000 /* uid */ #define F_UNAME 0x00100000 /* user name */ #define F_VISIT 0x00200000 /* file visited */ +#define F_NOCHANGE 0x00400000 /* check existence, but not */ + /* other properties */ #define F_SHA256 0x00800000 /* SHA256 digest */ #define F_SHA384 0x01000000 /* SHA384 digest */ #define F_SHA512 0x02000000 /* SHA512 digest */ @@ -120,9 +122,26 @@ const char *inotype(u_int); u_int nodetoino(u_int); int setup_getid(const char *); NODE *spec(FILE *); +int mtree_specspec(FILE *, FILE *); void free_nodes(NODE *); char *vispath(const char *); +#ifdef __FreeBSD__ +#define KEY_DIGEST "digest" +#else +#define KEY_DIGEST +#endif + +#define MD5KEY "md5" KEY_DIGEST +#ifdef __FreeBSD__ +#define RMD160KEY "ripemd160" KEY_DIGEST +#else +#define RMD160KEY "rmd160" KEY_DIGEST +#endif +#define SHA1KEY "sha1" KEY_DIGEST +#define SHA256KEY "sha256" KEY_DIGEST +#define SHA384KEY "sha384" +#define SHA512KEY "sha512" #define RP(p) \ ((p)->fts_path[0] == '.' && (p)->fts_path[1] == '/' ? \ diff --git a/usr.sbin/mtree/spec.c b/usr.sbin/mtree/spec.c index 1d52efd3d..1dcedb434 100644 --- a/usr.sbin/mtree/spec.c +++ b/usr.sbin/mtree/spec.c @@ -1,4 +1,4 @@ -/* $NetBSD: spec.c,v 1.80 2012/03/15 02:02:24 joerg Exp $ */ +/* $NetBSD: spec.c,v 1.84 2012/10/07 18:40:49 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -67,7 +67,7 @@ #if 0 static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: spec.c,v 1.80 2012/03/15 02:02:24 joerg Exp $"); +__RCSID("$NetBSD: spec.c,v 1.84 2012/10/07 18:40:49 christos Exp $"); #endif #endif /* not lint */ @@ -358,23 +358,28 @@ dump_nodes(const char *dir, NODE *root, int pathlast) if (MATCHFLAG(F_SIZE)) appendfield(pathlast, "size=%lld", (long long)cur->st_size); if (MATCHFLAG(F_TIME)) - appendfield(pathlast, "time=%lld.%ld", + appendfield(pathlast, "time=%lld.%09ld", (long long)cur->st_mtimespec.tv_sec, cur->st_mtimespec.tv_nsec); if (MATCHFLAG(F_CKSUM)) appendfield(pathlast, "cksum=%lu", cur->cksum); if (MATCHFLAG(F_MD5)) - appendfield(pathlast, "md5=%s", cur->md5digest); + appendfield(pathlast, "%s=%s", MD5KEY, cur->md5digest); if (MATCHFLAG(F_RMD160)) - appendfield(pathlast, "rmd160=%s", cur->rmd160digest); + appendfield(pathlast, "%s=%s", RMD160KEY, + cur->rmd160digest); if (MATCHFLAG(F_SHA1)) - appendfield(pathlast, "sha1=%s", cur->sha1digest); + appendfield(pathlast, "%s=%s", SHA1KEY, + cur->sha1digest); if (MATCHFLAG(F_SHA256)) - appendfield(pathlast, "sha256=%s", cur->sha256digest); + appendfield(pathlast, "%s=%s", SHA256KEY, + cur->sha256digest); if (MATCHFLAG(F_SHA384)) - appendfield(pathlast, "sha384=%s", cur->sha384digest); + appendfield(pathlast, "%s=%s", SHA384KEY, + cur->sha384digest); if (MATCHFLAG(F_SHA512)) - appendfield(pathlast, "sha512=%s", cur->sha512digest); + appendfield(pathlast, "%s=%s", SHA512KEY, + cur->sha512digest); if (MATCHFLAG(F_FLAGS)) { str = flags_to_string(cur->st_flags, "none"); appendfield(pathlast, "flags=%s", str); @@ -410,7 +415,15 @@ dump_nodes(const char *dir, NODE *root, int pathlast) char * vispath(const char *path) { - const char extra[] = { ' ', '\t', '\n', '\\', '#', '\0' }; + const char extra[] = { ' ', '\t', '\n', '\\', '#', +#ifdef notyet + /* + * We don't encode the globbing characters yet, because they + * get encoded as \c and strunvis fails to decode them + */ + '*', '?', '[', +#endif + '\0' }; static char pathbuf[4*MAXPATHLEN + 1]; strsvis(pathbuf, path, VIS_CSTYLE, extra); diff --git a/usr.sbin/mtree/specspec.c b/usr.sbin/mtree/specspec.c new file mode 100644 index 000000000..2821fd1d8 --- /dev/null +++ b/usr.sbin/mtree/specspec.c @@ -0,0 +1,273 @@ +/* $NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $ */ + +/*- + * Copyright (c) 2003 Poul-Henning Kamp + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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" +#endif + +#include +__RCSID("$NetBSD: specspec.c,v 1.2 2012/10/05 01:27:29 christos Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtree.h" +#include "extern.h" + +#define FF(a, b, c, d) \ + (((a)->flags & (c)) && ((b)->flags & (c)) && ((a)->d) != ((b)->d)) +#define FS(a, b, c, d) \ + (((a)->flags & (c)) && ((b)->flags & (c)) && strcmp((a)->d,(b)->d)) +#define FM(a, b, c, d) \ + (((a)->flags & (c)) && ((b)->flags & (c)) && memcmp(&(a)->d,&(b)->d, sizeof (a)->d)) + +static void +shownode(NODE *n, int f, char const *path) +{ + struct group *gr; + struct passwd *pw; + + printf("%s%s %s", path, n->name, inotype(nodetoino(n->type))); + if (f & F_CKSUM) + printf(" cksum=%lu", n->cksum); + if (f & F_GID) + printf(" gid=%d", n->st_gid); + if (f & F_GNAME) { + gr = getgrgid(n->st_gid); + if (gr == NULL) + printf(" gid=%d", n->st_gid); + else + printf(" gname=%s", gr->gr_name); + } + if (f & F_MODE) + printf(" mode=%o", n->st_mode); + if (f & F_NLINK) + printf(" nlink=%d", n->st_nlink); + if (f & F_SIZE) + printf(" size=%jd", (intmax_t)n->st_size); + if (f & F_UID) + printf(" uid=%d", n->st_uid); + if (f & F_UNAME) { + pw = getpwuid(n->st_uid); + if (pw == NULL) + printf(" uid=%d", n->st_uid); + else + printf(" uname=%s", pw->pw_name); + } + if (f & F_MD5) + printf(" %s=%s", MD5KEY, n->md5digest); + if (f & F_SHA1) + printf(" %s=%s", SHA1KEY, n->sha1digest); + if (f & F_RMD160) + printf(" %s=%s", RMD160KEY, n->rmd160digest); + if (f & F_SHA256) + printf(" %s=%s", SHA256KEY, n->sha256digest); + if (f & F_SHA384) + printf(" %s=%s", SHA384KEY, n->sha384digest); + if (f & F_SHA512) + printf(" %s=%s", SHA512KEY, n->sha512digest); + if (f & F_FLAGS) + printf(" flags=%s", flags_to_string(n->st_flags, "none")); + printf("\n"); +} + +static int +mismatch(NODE *n1, NODE *n2, int differ, char const *path) +{ + + if (n2 == NULL) { + shownode(n1, differ, path); + return (1); + } + if (n1 == NULL) { + printf("\t"); + shownode(n2, differ, path); + return (1); + } + if (!(differ & keys)) + return(0); + printf("\t\t"); + shownode(n1, differ, path); + printf("\t\t"); + shownode(n2, differ, path); + return (1); +} + +static int +compare_nodes(NODE *n1, NODE *n2, char const *path) +{ + int differs; + + if (n1 != NULL && n1->type == F_LINK) + n1->flags &= ~F_MODE; + if (n2 != NULL && n2->type == F_LINK) + n2->flags &= ~F_MODE; + differs = 0; + if (n1 == NULL && n2 != NULL) { + differs = n2->flags; + mismatch(n1, n2, differs, path); + return (1); + } + if (n1 != NULL && n2 == NULL) { + differs = n1->flags; + mismatch(n1, n2, differs, path); + return (1); + } + if (n1->type != n2->type) { + differs = 0; + mismatch(n1, n2, differs, path); + return (1); + } + if (FF(n1, n2, F_CKSUM, cksum)) + differs |= F_CKSUM; + if (FF(n1, n2, F_GID, st_gid)) + differs |= F_GID; + if (FF(n1, n2, F_GNAME, st_gid)) + differs |= F_GNAME; + if (FF(n1, n2, F_MODE, st_mode)) + differs |= F_MODE; + if (FF(n1, n2, F_NLINK, st_nlink)) + differs |= F_NLINK; + if (FF(n1, n2, F_SIZE, st_size)) + differs |= F_SIZE; + if (FS(n1, n2, F_SLINK, slink)) + differs |= F_SLINK; + if (FM(n1, n2, F_TIME, st_mtimespec)) + differs |= F_TIME; + if (FF(n1, n2, F_UID, st_uid)) + differs |= F_UID; + if (FF(n1, n2, F_UNAME, st_uid)) + differs |= F_UNAME; + if (FS(n1, n2, F_MD5, md5digest)) + differs |= F_MD5; + if (FS(n1, n2, F_SHA1, sha1digest)) + differs |= F_SHA1; + if (FS(n1, n2, F_RMD160, rmd160digest)) + differs |= F_RMD160; + if (FS(n1, n2, F_SHA256, sha256digest)) + differs |= F_SHA256; + if (FS(n1, n2, F_SHA384, sha384digest)) + differs |= F_SHA384; + if (FS(n1, n2, F_SHA512, sha512digest)) + differs |= F_SHA512; + if (FF(n1, n2, F_FLAGS, st_flags)) + differs |= F_FLAGS; + if (differs) { + mismatch(n1, n2, differs, path); + return (1); + } + return (0); +} +static int +walk_in_the_forest(NODE *t1, NODE *t2, char const *path) +{ + int r, i; + NODE *c1, *c2, *n1, *n2; + char *np; + + r = 0; + + if (t1 != NULL) + c1 = t1->child; + else + c1 = NULL; + if (t2 != NULL) + c2 = t2->child; + else + c2 = NULL; + while (c1 != NULL || c2 != NULL) { + n1 = n2 = NULL; + if (c1 != NULL) + n1 = c1->next; + if (c2 != NULL) + n2 = c2->next; + if (c1 != NULL && c2 != NULL) { + if (c1->type != F_DIR && c2->type == F_DIR) { + n2 = c2; + c2 = NULL; + } else if (c1->type == F_DIR && c2->type != F_DIR) { + n1 = c1; + c1 = NULL; + } else { + i = strcmp(c1->name, c2->name); + if (i > 0) { + n1 = c1; + c1 = NULL; + } else if (i < 0) { + n2 = c2; + c2 = NULL; + } + } + } + if (c1 == NULL && c2->type == F_DIR) { + asprintf(&np, "%s%s/", path, c2->name); + i = walk_in_the_forest(c1, c2, np); + free(np); + i += compare_nodes(c1, c2, path); + } else if (c2 == NULL && c1->type == F_DIR) { + asprintf(&np, "%s%s/", path, c1->name); + i = walk_in_the_forest(c1, c2, np); + free(np); + i += compare_nodes(c1, c2, path); + } else if (c1 == NULL || c2 == NULL) { + i = compare_nodes(c1, c2, path); + } else if (c1->type == F_DIR && c2->type == F_DIR) { + asprintf(&np, "%s%s/", path, c1->name); + i = walk_in_the_forest(c1, c2, np); + free(np); + i += compare_nodes(c1, c2, path); + } else { + i = compare_nodes(c1, c2, path); + } + r += i; + c1 = n1; + c2 = n2; + } + return (r); +} + +int +mtree_specspec(FILE *fi, FILE *fj) +{ + int rval; + NODE *root1, *root2; + + root1 = spec(fi); + root2 = spec(fj); + rval = walk_in_the_forest(root1, root2, ""); + rval += compare_nodes(root1, root2, ""); + if (rval > 0) + return (MISMATCHEXIT); + return (0); +} diff --git a/usr.sbin/mtree/verify.c b/usr.sbin/mtree/verify.c index 9eb54510d..54b704cbf 100644 --- a/usr.sbin/mtree/verify.c +++ b/usr.sbin/mtree/verify.c @@ -1,4 +1,4 @@ -/* $NetBSD: verify.c,v 1.40 2012/03/25 16:07:04 christos Exp $ */ +/* $NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)verify.c 8.1 (Berkeley) 6/6/93"; #else -__RCSID("$NetBSD: verify.c,v 1.40 2012/03/25 16:07:04 christos Exp $"); +__RCSID("$NetBSD: verify.c,v 1.43 2012/10/05 01:31:05 christos Exp $"); #endif #endif /* not lint */ @@ -64,11 +64,11 @@ static void miss(NODE *, char *); static int vwalk(void); int -verify(void) +verify(FILE *fi) { int rval; - root = spec(stdin); + root = spec(fi); rval = vwalk(); miss(root, path); return (rval); @@ -124,7 +124,8 @@ vwalk(void) !fnmatch(ep->name, p->fts_name, FNM_PATHNAME)) || !strcmp(ep->name, p->fts_name)) { ep->flags |= F_VISIT; - if (compare(ep, p)) + if ((ep->flags & F_NOCHANGE) == 0 && + compare(ep, p)) rval = MISMATCHEXIT; if (!(ep->flags & F_IGN) && ep->type == F_DIR && @@ -175,8 +176,17 @@ miss(NODE *p, char *tail) if (p->type != F_DIR && (dflag || p->flags & F_VISIT)) continue; strcpy(tail, p->name); - if (!(p->flags & F_VISIT)) - printf("missing: %s", path); + if (!(p->flags & F_VISIT)) { + /* Don't print missing message if file exists as a + symbolic link and the -q flag is set. */ + struct stat statbuf; + + if (qflag && stat(path, &statbuf) == 0 && + S_ISDIR(statbuf.st_mode)) + p->flags |= F_VISIT; + else + (void)printf("%s missing", path); + } switch (p->type) { case F_BLOCK: case F_CHAR: @@ -264,7 +274,6 @@ miss(NODE *p, char *tail) if (!create || mtree_Wflag) continue; -#ifndef __minix if ((p->flags & (F_UID | F_UNAME)) && (p->flags & (F_GID | F_GNAME)) && (lchown(path, p->st_uid, p->st_gid))) { @@ -274,24 +283,12 @@ miss(NODE *p, char *tail) (p->flags & F_FLAGS) ? "and file flags " : ""); continue; } -#else - if ((p->flags & (F_UID | F_UNAME)) && - (p->flags & (F_GID | F_GNAME))) { - printf("Warning: unable to change user/group/mode due " - "to lack of lchown(3) support"); - } -#endif if (p->flags & F_MODE) { -#ifndef __minix if (lchmod(path, p->st_mode)) printf("%s: permissions not set: %s\n", path, strerror(errno)); -#else - printf("Warning: unable to set permissions due " - "to lack of lchmod(3) support"); -#endif } -#if HAVE_STRUCT_STAT_ST_FLAGS && !defined(__minix) +#if HAVE_STRUCT_STAT_ST_FLAGS if ((p->flags & F_FLAGS) && p->st_flags) { if (iflag) flags = p->st_flags;