]> git.saurik.com Git - apple/file_cmds.git/commitdiff
file_cmds-184.tar.gz mac-os-x-105 mac-os-x-1051 mac-os-x-1052 v184
authorApple <opensource@apple.com>
Sat, 14 Jul 2007 22:31:12 +0000 (22:31 +0000)
committerApple <opensource@apple.com>
Sat, 14 Jul 2007 22:31:12 +0000 (22:31 +0000)
120 files changed:
Makefile
chflags/Makefile
chflags/chflags.1
chflags/chflags.c
chmod/chmod.1
chmod/chmod.c
chmod/chmod_acl.c
chmod/chmod_acl.h
chown/chgrp.1
chown/chown.8
chown/chown.c
cksum/Makefile [new file with mode: 0644]
cksum/Makefile.postamble [new file with mode: 0644]
cksum/Makefile.preamble [new file with mode: 0644]
cksum/PB.project [new file with mode: 0644]
cksum/cksum.1 [new file with mode: 0644]
cksum/cksum.c [new file with mode: 0644]
cksum/crc.c
cksum/crc32.c [new file with mode: 0644]
cksum/extern.h [new file with mode: 0644]
cksum/print.c [new file with mode: 0644]
cksum/sum1.c [new file with mode: 0644]
cksum/sum2.c [new file with mode: 0644]
compress/Makefile
compress/compress.c
cp/Makefile
cp/cp.1
cp/cp.c
cp/extern.h
cp/utils.c
dd/conv.c
df/Makefile
df/Makefile.postamble
df/df.1
df/df.c
df/vfslist.c
du/Makefile
du/du.1
du/du.c
install/install.1
install/xinstall.c
ipcrm/ipcrm.1
ipcrm/ipcrm.c
ipcs/Makefile
ipcs/Makefile.postamble
ipcs/ipcs.1
ipcs/ipcs.c
ln/Makefile
ln/ln.1
ln/ln.c
ln/symlink.7
ls/Makefile
ls/extern.h
ls/humanize_number.c [new file with mode: 0644]
ls/ls.1
ls/ls.c
ls/ls.h
ls/print.c
ls/util.c
mkdir/mkdir.c
mkfifo/mkfifo.1
mkfifo/mkfifo.c
mknod/mknod.8
mknod/mknod.c
mtree/Makefile
mtree/compare.c
mtree/create.c
mtree/excludes.c
mtree/extern.h
mtree/misc.c
mtree/mtree.8
mtree/mtree.c
mtree/mtree.h
mtree/spec.c
mtree/specspec.c [new file with mode: 0644]
mtree/verify.c
mv/mv.1
mv/mv.c
pax/Makefile
pax/ar_io.c
pax/ar_subs.c
pax/buf_subs.c
pax/cache.c
pax/cache.h
pax/cpio.1
pax/cpio.c
pax/cpio.h
pax/extern.h
pax/file_subs.c
pax/ftree.c
pax/ftree.h
pax/gen_subs.c
pax/getoldopt.c
pax/options.c
pax/options.h
pax/pat_rep.c
pax/pat_rep.h
pax/pax.1
pax/pax.c
pax/pax.h
pax/pax_format.c [new file with mode: 0644]
pax/sel_subs.c
pax/sel_subs.h
pax/tables.c
pax/tables.h
pax/tar.c
pax/tar.h
pax/tty_subs.c
rm/rm.c
shar/shar.1
stat/Makefile
stat/stat.1
stat/stat.c
tcopy/Makefile [deleted file]
tcopy/Makefile.postamble [deleted file]
tcopy/Makefile.preamble [deleted file]
tcopy/PB.project [deleted file]
tcopy/tcopy.1 [deleted file]
tcopy/tcopy.c [deleted file]
touch/touch.c

index 20e69e6c996eb3741781c2ca59f23cd42c436a0e..30a7cc94b2f4d0202efa24dff87cd8b76aac4896 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,8 +12,8 @@ NAME = file_cmds
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Aggregate
 
-TOOLS = chflags chmod chown compress cp dd df du install ipcrm ipcs ln ls\
-        mkdir mkfifo mknod mtree mv pathchk pax rm rmdir rmt shar stat tcopy\
+TOOLS = chflags chmod chown cksum compress cp dd df du install ipcrm ipcs ln ls\
+        mkdir mkfifo mknod mtree mv pathchk pax rm rmdir rmt shar stat\
         touch
 
 OTHERSRCS = PROJECT Makefile.preamble Makefile Makefile.postamble
index 4f9911857d1fd5e88ab4b81db6f981fa7945854d..aeeabe47a234115a4877f802d7af5b1dc253590e 100644 (file)
@@ -16,6 +16,7 @@ CFILES = chflags.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble chflags.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 3205110cb277810bd8ff90bf0f00adcd3d3e1288..45d65a434f95daf5110825a8039d1fe513ed4dd7 100644 (file)
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1989, 1990, 1993, 1994
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. 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.
@@ -33,9 +30,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)chflags.1   8.4 (Berkeley) 5/2/95
-.\" $FreeBSD: src/usr.bin/chflags/chflags.1,v 1.14 2001/08/15 09:09:39 ru Exp $
+.\" $FreeBSD: src/bin/chflags/chflags.1,v 1.25 2005/06/14 08:25:54 ru Exp $
 .\"
-.Dd May 2, 1995
+.Dd May 14, 2005
 .Dt CHFLAGS 1
 .Os
 .Sh NAME
@@ -82,46 +79,54 @@ The flags are specified as an octal number or a comma separated list
 of keywords.
 The following keywords are currently defined:
 .Pp
-.Bl -tag -offset indent -width "opaque" -compact
-.It Ar arch
+.Bl -tag -offset indent -width ".Ar opaque"
+.It Ar arch , archived
 set the archived flag (super-user only)
 .It Ar opaque
-set the opaque flag (owner or super-user only)
+set the opaque flag (owner or super-user only).
+[Directory is opaque when viewed through a union mount]
 .It Ar nodump
 set the nodump flag (owner or super-user only)
-.It Ar sappnd
+.It Ar sappnd , sappend
 set the system append-only flag (super-user only)
-.It Ar schg
+.It Ar schg , schange , simmutable
 set the system immutable flag (super-user only)
-.It Ar sunlnk
-set the system undeletable flag (super-user only)
-.It Ar uappnd
+.It Ar uappnd , uappend
 set the user append-only flag (owner or super-user only)
-.It Ar uchg
+.It Ar uchg , uchange , uimmutable
 set the user immutable flag (owner or super-user only)
-.It Ar uunlnk
-set the user undeletable flag (owner or super-user only)
-.It Ar archived , sappend , schange , Xo
-.Ar simmutable , uappend , uchange , uimmutable ,
-.Ar sunlink , uunlink
-.Xc
-aliases for the above
+.It Ar hidden
+set the hidden flag
+[Hide item from GUI]
 .El
 .Pp
+As discussed in
+.Xr chflags 2 ,
+the
+.Ar sappnd
+and
+.Ar schg
+flags may only be unset when the system is in single-user mode.
+.Pp
 Putting the letters
 .Dq Ar no
-before an option causes the flag to be turned off.
+before or removing the letters
+.Dq Ar no
+from a keyword causes the flag to be cleared.
 For example:
-.Bl -tag -offset indent -width "nouchg"
+.Pp
+.Bl -tag -offset indent -width "nouchg" -compact
 .It Ar nouchg
-the immutable bit should be cleared
+clear the user immutable flag (owner or super-user only)
+.It Ar dump
+clear the nodump flag (owner or super-user only)
 .El
 .Pp
-Symbolic links do not have flags, so unless the
+Unless the
 .Fl H
 or
 .Fl L
-option is set,
+options are given,
 .Nm
 on a symbolic link always succeeds and has no effect.
 The
@@ -135,8 +140,8 @@ option is specified.
 In addition, these options override each other and the
 command's actions are determined by the last one specified.
 .Pp
-You can use "ls -lo" to see the flags of existing files.
-.Sh DIAGNOSTICS
+You can use "ls -lO" to see the flags of existing files.
+.Sh EXIT STATUS
 .Ex -std
 .Sh SEE ALSO
 .Xr ls 1 ,
@@ -149,3 +154,20 @@ The
 .Nm
 command first appeared in
 .Bx 4.4 .
+.Sh BUGS
+Only a limited number of utilities are
+.Nm
+aware.
+Some of these tools include
+.Xr ls 1 ,
+.Xr cp 1 ,
+.Xr find 1 ,
+.Xr install 1 ,
+.Xr dump 8 ,
+and
+.Xr restore 8 .
+In particular a tool which is not currently
+.Nm
+aware is the
+.Xr pax 1
+utility.
index a7777cb7aad3a2f67b1394d1e0f330730de8698f..d90a339c11dfbebbb95dbb99ba4994ef209878f1 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1992, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
  * SUCH DAMAGE.
  */
 
+#if 0
 #ifndef lint
 static const char copyright[] =
 "@(#) Copyright (c) 1992, 1993, 1994\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif
 
-#if 0
 #ifndef lint
 static char sccsid[] = "@(#)chflags.c  8.5 (Berkeley) 4/1/94";
 #endif
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/usr.bin/chflags/chflags.c,v 1.16 2002/09/04 23:28:58 dwmalone Exp $");
+__FBSDID("$FreeBSD: src/bin/chflags/chflags.c,v 1.23 2005/05/14 23:23:10 dd Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -66,27 +62,36 @@ main(int argc, char *argv[])
        FTSENT *p;
        u_long clear, set;
        long val;
-       int Hflag, Lflag, Pflag, Rflag, ch, fts_options, oct, rval;
+       int Hflag, Lflag, Rflag, hflag, ch, fts_options, oct, rval;
        char *flags, *ep;
+       int (*change_flags)(const char *, unsigned long);
 
-       Hflag = Lflag = Pflag = Rflag = 0;
+       Hflag = Lflag = Rflag = hflag = 0;
+#ifdef __APPLE__
        while ((ch = getopt(argc, argv, "HLPR")) != -1)
+#else /* !__APPLE__ */
+       while ((ch = getopt(argc, argv, "HLPRh")) != -1)
+#endif /* __APPLE__ */
                switch (ch) {
                case 'H':
                        Hflag = 1;
-                       Lflag = Pflag = 0;
+                       Lflag = 0;
                        break;
                case 'L':
                        Lflag = 1;
-                       Hflag = Pflag = 0;
+                       Hflag = 0;
                        break;
                case 'P':
-                       Pflag = 1;
                        Hflag = Lflag = 0;
                        break;
                case 'R':
                        Rflag = 1;
                        break;
+#ifndef __APPLE__
+               case 'h':
+                       hflag = 1;
+                       break;
+#endif /* !__APPLE__ */
                case '?':
                default:
                        usage();
@@ -99,6 +104,9 @@ main(int argc, char *argv[])
 
        if (Rflag) {
                fts_options = FTS_PHYSICAL;
+               if (hflag)
+                       errx(1, "the -R and -h options "
+                               "may not be specified together");
                if (Hflag)
                        fts_options |= FTS_COMFOLLOW;
                if (Lflag) {
@@ -108,6 +116,14 @@ main(int argc, char *argv[])
        } else
                fts_options = FTS_LOGICAL;
 
+       /* XXX: Why don't chflags and lchflags have compatible prototypes? */
+#ifndef __APPLE__
+       if (hflag)
+               change_flags = (int (*)(const char *, unsigned long))lchflags;
+       else
+#endif /* !__APPLE__ */
+               change_flags = chflags;
+
        flags = *argv;
        if (*flags >= '0' && *flags <= '7') {
                errno = 0;
@@ -132,11 +148,10 @@ main(int argc, char *argv[])
 
        for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
                switch (p->fts_info) {
-               case FTS_D:
-                       if (Rflag)              /* Change it at FTS_DP. */
-                               continue;
-                       fts_set(ftsp, p, FTS_SKIP);
-                       break;
+               case FTS_D:     /* Change it at FTS_DP if we're recursive. */
+                       if (!Rflag)
+                               fts_set(ftsp, p, FTS_SKIP);
+                       continue;
                case FTS_DNR:                   /* Warn, chflag, continue. */
                        warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
                        rval = 1;
@@ -153,17 +168,20 @@ main(int argc, char *argv[])
                         * don't point to anything and ones that we found
                         * doing a physical walk.
                         */
-                       continue;
+                       if (!hflag)
+                               continue;
+                       /* FALLTHROUGH */
                default:
                        break;
                }
                if (oct) {
-                       if (!chflags(p->fts_accpath, set))
+                       if (!(*change_flags)(p->fts_accpath, set))
                                continue;
                } else {
                        p->fts_statp->st_flags |= set;
                        p->fts_statp->st_flags &= clear;
-                       if (!chflags(p->fts_accpath, (u_long)p->fts_statp->st_flags))
+                       if (!(*change_flags)(p->fts_accpath,
+                                   (u_long)p->fts_statp->st_flags))
                                continue;
                }
                warn("%s", p->fts_path);
@@ -178,6 +196,10 @@ void
 usage(void)
 {
        (void)fprintf(stderr,
+#ifdef __APPLE__
            "usage: chflags [-R [-H | -L | -P]] flags file ...\n");
+#else /* !__APPLE__ */
+           "usage: chflags [-h] [-R [-H | -L | -P]] flags file ...\n");
+#endif /* __APPLE__ */
        exit(1);
 }
index 9cafe9cf1f1fabe98b58f3b90162e7f8b7d0b09e..ec6e2fd24636cb0ab87fa5f49bbc184c25b8fb0e 100644 (file)
 .Nm chmod
 .Nd change file modes or Access Control Lists
 .Sh SYNOPSIS
-.Nm
+.Nm chmod
 .Op Fl fv
 .Op Fl R Op Fl H | L | P
 .Ar mode
 .Ar
-.Nm
+.Nm chmod
 .Op Fl fv
 .Op Fl R Op Fl H | L | P 
 .Op -a | +a | =a
 .Ar ACE
 .Ar
-.Nm
-.Op Fl fv
+.Nm chmod
+.Op Fl fhv
 .Op Fl R Op Fl H | L | P 
 .Op Fl E
 .Ar
-.Nm
-.Op Fl fv
+.Nm chmod
+.Op Fl fhv
 .Op Fl R Op Fl H | L | P 
 .Op Fl C
 .Ar
 .Nm chmod
-.Op Fl fv
-.Op Fl R Op Fl H | L | P
+.Op Fl fhv
+.Op Fl R Op Fl H | L | P 
 .Op Fl N
 .Ar
 .Sh DESCRIPTION
 The
-.Nm
+.Nm chmod
 utility modifies the file mode bits of the listed files
 as specified by the
 .Ar mode
@@ -79,12 +79,20 @@ Lists (ACLs) associated with the listed files.
 .Pp
 The generic options are as follows:
 .Bl -tag -width Ds
+.It Fl f
+Do not display a diagnostic message if
+.Nm chmod
+could not modify the mode for
+.Va file .
 .It Fl H
 If the
 .Fl R
 option is specified, symbolic links on the command line are followed.
 (Symbolic links encountered in the tree traversal are not followed by
 default.)
+.It Fl h
+If the file is a symbolic link, change the mode of the link itself
+rather than the file that the link points to.
 .It Fl L
 If the
 .Fl R
@@ -97,14 +105,9 @@ This is the default.
 .It Fl R
 Change the modes of the file hierarchies rooted in the files
 instead of just the files themselves.
-.It Fl f
-Do not display a diagnostic message if
-.Nm
-could not modify the mode for
-.Va file .
 .It Fl v
 Cause
-.Nm
+.Nm chmod
 to be verbose, showing filenames as the mode is modified.
 If the
 .Fl v
@@ -328,6 +331,9 @@ ACLs are manipulated using extensions to the symbolic mode
 grammar.  Each file has one ACL, containing an ordered list of entries.
 Each entry refers to a user or group, and grants or denies a set of
 permissions.
+In cases where a user and a group exist with the same name, the
+user/group name can be prefixed with "user:" or "group:" in order to
+specify the type of name.
 .Pp
 The following permissions are applicable to all filesystem objects:
 .Bl -tag -width 6n -compact -offset indent
@@ -443,7 +449,7 @@ allow lists. Inherited entries are added by using the +ai mode.
    4: admin inherited allow delete
    5: backup inherited deny read
    6: admin inherited allow write-security
- # chmod +ai "others allow write" file1
+ # chmod +ai "others allow read" file1
  # ls -le
  -rw-r--r--+ 1 juser  wheel  0 Apr 28 14:06 file1
    owner: juser
@@ -534,6 +540,7 @@ The
 option is non-standard and its use in scripts is not recommended.
 .Sh SEE ALSO
 .Xr chflags 1 ,
+.Xr fsaclctl 1 ,
 .Xr install 1 ,
 .Xr chmod 2 ,
 .Xr stat 2 ,
@@ -546,7 +553,7 @@ option is non-standard and its use in scripts is not recommended.
 .Xr sticky 8
 .Sh STANDARDS
 The
-.Nm
+.Nm chmod
 utility is expected to be
 .St -p1003.2
 compatible with the exception of the
@@ -556,6 +563,6 @@ symbol
 which is not included in that standard.
 .Sh HISTORY
 A
-.Nm
+.Nm chmod
 command appeared in
 .At v1 .
index c256ecdd46bba005ebe0a193172b60be3e910fe9..78013406f1b088781c556b2a25ade47f5e0c052b 100644 (file)
@@ -93,7 +93,7 @@ main(int argc, char *argv[])
 #ifndef __APPLE__
        while ((ch = getopt(argc, argv, "HLPRXfghorstuvwx")) != -1)
 #else
-       while ((ch = getopt(argc, argv, "ACEHILNPRVXafginorstuvwx")) != -1)
+       while ((ch = getopt(argc, argv, "ACEHILNPRVXafghinorstuvwx")) != -1)
 #endif
                switch (ch) {
                case 'H':
@@ -113,7 +113,6 @@ main(int argc, char *argv[])
                case 'f':
                        fflag = 1;
                        break;
-#ifndef __APPLE__
                case 'h':
                        /*
                         * In System V (and probably POSIX.2) the -h option
@@ -125,12 +124,17 @@ main(int argc, char *argv[])
                         */
                        hflag = 1;
                        break;
-#else
+#ifdef __APPLE__
                case 'a':
                        if (argv[optind - 1][0] == '-' &&
                            argv[optind - 1][1] == ch)
                                --optind;
                        goto done;
+               case 'A':
+                       acloptflags |= ACL_FLAG | ACL_TO_STDOUT;
+                       ace_arg_not_required = 1;
+                       errx(1, "-A not implemented");
+                       goto done;
                case 'E':
                        acloptflags |= ACL_FLAG | ACL_FROM_STDIN;
                        goto done;
@@ -156,6 +160,7 @@ main(int argc, char *argv[])
                case 'V':
                        acloptflags |= ACL_FLAG | ACL_INVOKE_EDITOR;
                        ace_arg_not_required = 1;
+                       errx(1, "-V not implemented");
                        goto done;
 #endif /* __APPLE__ */
                /*
@@ -272,14 +277,10 @@ apnoacl:
        } else
                fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
 
-#ifndef __APPLE__
        if (hflag)
                change_mode = lchmod;
        else
                change_mode = chmod;
-#else
-       change_mode = chmod;
-#endif /* __APPLE__ */
 #ifdef __APPLE__
        if (acloptflags & ACL_FROM_STDIN) {
                int readval = 0, readtotal = 0;
@@ -350,16 +351,20 @@ apnoacl:
                err(1, "fts_open");
        for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
                switch (p->fts_info) {
-               case FTS_D:                     /* Change it at FTS_DP. */
+               case FTS_D:
                        if (!Rflag)
-                               fts_set(ftsp, p, FTS_SKIP);
-                       continue;
+                               (void)fts_set(ftsp, p, FTS_SKIP);
+                       break;
                case FTS_DNR:                   /* Warn, chmod, continue. */
                        warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
                        rval = 1;
                        break;
-               case FTS_ERR:                   /* Warn, continue. */
+               case FTS_DP:                    /* Already changed at FTS_D. */
+                       continue;
                case FTS_NS:
+                       if (acloptflags & ACL_FLAG) /* don't need stat for -N */
+                               break;
+               case FTS_ERR:                   /* Warn, continue. */
                        warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
                        rval = 1;
                        continue;
@@ -434,7 +439,8 @@ usage(void)
 {
 #ifdef __APPLE__
        (void)fprintf(stderr,
-           "usage: chmod [-fv] [-R [-H | -L | -P]] [-a | +a | =a  [i][# [ n]]] mode|entry file ...\n");
+                     "usage:\tchmod [-fhv] [-R [-H | -L | -P]] [-a | +a | =a  [i][# [ n]]] mode|entry file ...\n"
+                     "\tchmod [-fhv] [-R [-H | -L | -P]] [-E | -C | -i | -I] file ...\n"); /* add -A and -V when implemented */
 #else
        (void)fprintf(stderr,
            "usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n");
index effc4c0716e95b0261b80b78cafd292c3ae9a9ad..f09f304cb5075d4462a1113c46ffe9e4d9000bdd 100644 (file)
@@ -92,40 +92,37 @@ static struct {
  * or use err_set_exit() and make various structures globals.
  */
 
+#define NAME_USER   (1)
+#define NAME_GROUP  (2)
+#define NAME_EITHER (NAME_USER | NAME_GROUP)
+
 /* Perform a name to uuid mapping - calls through to memberd */
 
 uuid_t *
-name_to_uuid(char *tok) {
+name_to_uuid(char *tok, int nametype) {
        struct passwd *tpass = NULL;
        struct group *tgrp = NULL;
        uuid_t *entryg = NULL;
-       char is_uid = 1;
 
        if ((entryg = (uuid_t *) calloc(1,sizeof(uuid_t))) == NULL)
                err(1, "Unable to allocate a uuid");
-       
-       tpass = getpwnam(tok);
 
-       if (tpass == NULL) {
+       if (nametype & NAME_USER)
+               tpass = getpwnam(tok);
+
+       if (NULL == tpass && (nametype & NAME_GROUP))
                tgrp = getgrnam(tok);
-               if (tgrp == NULL) {
-                       errno = EINVAL;
-                       err(1, "Unable to translate %s to a UID/GID", tok);
-               }
-               is_uid = 0;
-       }
-       
+
        if (tpass) {
-               if (0 != mbr_uid_to_uuid(tpass->pw_uid, entryg)) {
-                       errno = EINVAL;
-                       err(1, "mbr_uid_to_uuid(): Unable to translate");
+               if (0 != mbr_uid_to_uuid(tpass->pw_uid, *entryg)) {
+                       errx(1, "mbr_uid_to_uuid(): Unable to translate uid %d", tpass->pw_uid);
                }
-       }
-       else {
-               if (0 != mbr_gid_to_uuid(tgrp->gr_gid, entryg)) {
-                       errno = EINVAL;
-                       err(1, "mbr_gid_to_uuid(): Unable to translate");
+       } else if (tgrp) {
+               if (0 != mbr_gid_to_uuid(tgrp->gr_gid, *entryg)) {
+                       errx(1, "mbr_gid_to_uuid(): Unable to translate gid %d", tgrp->gr_gid);
                }
+       } else {
+               errx(1, "Unable to translate '%s' to a UID/GID", tok);
        }
        return entryg;
 }
@@ -142,26 +139,36 @@ parse_entry(char *entrybuf, acl_entry_t newent) {
        acl_flagset_t   flags;
        unsigned permcount = 0;
        unsigned pindex = 0;
+       char *delimiter = " ";
+       int nametype = NAME_EITHER;
 
        acl_get_permset(newent, &perms);
        acl_get_flagset_np(newent, &flags);
 
        pebuf = entrybuf;
 
-       tok = strsep(&pebuf, " ");
+       if (0 == strncmp(entrybuf, "user:", 5)) {
+               nametype = NAME_USER;
+               pebuf += 5;
+       } else if (0 == strncmp(entrybuf, "group:", 6)) {
+               nametype = NAME_GROUP;
+               pebuf += 6;
+       }
+
+       if (strchr(pebuf, ':')) /* User/Group names can have spaces */
+               delimiter = ":";
+       tok = strsep(&pebuf, delimiter);
        
        if ((tok == NULL) || *tok == '\0') {
-               errno = EINVAL;
-               err(1, "Invalid entry format");
+               errx(1, "Invalid entry format -- expected user or group name");
        }
 
        /* parse the name into a qualifier */
-       entryg = name_to_uuid(tok);
+       entryg = name_to_uuid(tok, nametype);
 
-       tok = strsep(&pebuf, " ");
+       tok = strsep(&pebuf, ": "); /* Stick with delimiter? */
        if ((tok == NULL) || *tok == '\0') {
-               errno = EINVAL;
-               err(1, "Invalid entry format");
+               errx(1, "Invalid entry format -- expected allow or deny");
        }
 
        /* is the verb 'allow' or 'deny'? */
@@ -170,8 +177,7 @@ parse_entry(char *entrybuf, acl_entry_t newent) {
        } else if (!strcmp(tok, "deny")) {
                tag = ACL_EXTENDED_DENY;
        } else {
-               errno = EINVAL;
-               err(1, "Unknown tag type '%s'", tok);
+               errx(1, "Unknown tag type '%s'", tok);
        }
 
        /* parse permissions */
@@ -195,15 +201,13 @@ parse_entry(char *entrybuf, acl_entry_t newent) {
                                        goto found;
                                }
                        }
-                       errno = EINVAL;
-                       err(1,"Invalid permission type %s", tok);
+                       errx(1,"Invalid permission type '%s'", tok);
                found:
                        continue;
                }
        }
        if (0 == permcount) {
-               errno = EINVAL;
-               err(1, "No permissions specified");
+               errx(1, "No permissions specified");
        }
        acl_set_tag_type(newent, tag);
        acl_set_qualifier(newent, entryg);
@@ -248,12 +252,10 @@ parse_acl_entries(const char *input) {
                        if (0 != acl_create_entry(&acl_input, &newent))
                                err(1, "acl_create_entry() failed");
                        if (0 != parse_entry(*bufp, newent)) {
-                               errno = EINVAL;
-                               err(1, "Failed parsing entry %s", *bufp);
+                               errx(1, "Failed parsing entry '%s'", *bufp);
                        }
                        if (++bufp >= &entryv[ACL_MAX_ENTRIES - 1]) {
-                               errno = ERANGE;
-                               err(1, "Too many entries");
+                               errx(1, "Too many entries");
                        }
                }
        
@@ -302,8 +304,7 @@ score_acl_entry(acl_entry_t entry) {
                score++;
                break;
        default:
-               errno = EINVAL;
-               err(1, "Unknown tag type present in ACL entry");
+               errx(1, "Unknown tag type %d present in ACL entry", tag);
                /* NOTREACHED */
        }
 
@@ -476,15 +477,14 @@ find_matching_entry (acl_t acl, acl_entry_t modifier, acl_entry_t *rentryp,
                if ((cmp == MATCH_EXACT) || (cmp == MATCH_PARTIAL)) {
                        if (match_inherited) {
                                acl_flagset_t eflags, mflags;
-                               
+
                                if (0 != acl_get_flagset_np(modifier, &mflags))
                                        err(1, "Unable to get flagset");
                                
                                if (0 != acl_get_flagset_np(entry, &eflags))
                                        err(1, "Unable to get flagset");
                                        
-                               if (acl_get_flag_np(mflags, ACL_ENTRY_INHERITED) ==
-                                   acl_get_flag_np(eflags, ACL_ENTRY_INHERITED)) {
+                               if (compare_acl_flagsets(mflags, eflags) == MATCH_EXACT) {
                                        *rentryp = entry;
                                        fcmp = cmp;
                                }
@@ -609,8 +609,7 @@ modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags,
                if (optflags & ACL_DELETE_FLAG) {
 
                        if (flag_new_acl) {
-                               errno = EINVAL;
-                               err(1, "No ACL present");
+                               errx(1, "No ACL present");
                        }
                        if (position != -1 ) {
                                if (0 != acl_get_entry(oacl, position, &rentry))
@@ -639,8 +638,7 @@ modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags,
                                        }
                                }
                                if (0 == match_found) {
-                                       errno = EINVAL;
-                                       warn("Entry not found when attempting delete");
+                                       warnx("Entry not found when attempting delete");
                                        retval = 1;
                                }
                        }
@@ -759,40 +757,43 @@ modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int pos
                        if (oacl)
                                acl_free(oacl);
                        oacl = facl;
-               }
-               else
-               if (optflags & ACL_CHECK_CANONICITY) {
+               } else if (optflags & ACL_TO_STDOUT) {
+                       ssize_t len; /* need to get printacl() from ls(1) */
+                       char *text = acl_to_text(oacl, &len);
+                       puts(text);
+                       acl_free(text);
+               } else if (optflags & ACL_CHECK_CANONICITY) {
                        if (flag_new_acl) {
-                               errno = EINVAL;
-                               warn("No ACL currently associated with file %s", path);
+                               warnx("No ACL currently associated with file '%s'", path);
                        }
-                       return(is_canonical(oacl));
-               }
-               else
-               if ((optflags & ACL_SET_FLAG) && (position == -1) && 
+                       retval = is_canonical(oacl);
+               } else if ((optflags & ACL_SET_FLAG) && (position == -1) && 
                    (!is_canonical(oacl))) {
-                       errno = EINVAL;
-                       warn("The specified file %s does not have an ACL in canonical order, please specify a position with +a# ", path);
+                       warnx("The specified file '%s' does not have an ACL in canonical order, please specify a position with +a# ", path);
                        retval = 1;
-               }
-               else
-               if (((optflags & ACL_DELETE_FLAG) && (position != -1))
+               } else if (((optflags & ACL_DELETE_FLAG) && (position != -1))
                    || (optflags & ACL_CHECK_CANONICITY)) {
                        retval = modify_acl(&oacl, NULL, optflags, position, 
                                   inheritance_level, flag_new_acl);
-               }
-               else
+               } else if ((optflags & (ACL_REMOVE_INHERIT_FLAG|ACL_REMOVE_INHERITED_ENTRIES)) && flag_new_acl) {
+                       warnx("No ACL currently associated with file '%s'", path);
+                       retval = 1;
+               } else {
+                       if (!modifier) { /* avoid bus error in acl_get_entry */
+                               errx(1, "Internal error: modifier should not be NULL");
+                       }
                        for (aindex = 0; 
                             acl_get_entry(modifier, 
                                           (entry == NULL ? ACL_FIRST_ENTRY : 
                                            ACL_NEXT_ENTRY), &entry) == 0; 
                             aindex++) {
 
-                                           retval += modify_acl(&oacl, entry, optflags, 
-                                                                position, inheritance_level, 
-                                                                flag_new_acl);
-                                   }
+                               retval += modify_acl(&oacl, entry, optflags, 
+                                                    position, inheritance_level, 
+                                                    flag_new_acl);
                        }
+               }
+       }
 
 /* XXX Potential race here, since someone else could've modified or
  * read the ACL on this file (with the intention of modifying it) in
@@ -802,10 +803,10 @@ modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int pos
  * "changeset" mechanism, common locking  strategy, or kernel
  * supplied reservation mechanism to prevent this race.
  */
-       if (!(optflags & ACL_CHECK_CANONICITY) && 
+       if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY)) && 
            (0 != acl_set_file(path, ACL_TYPE_EXTENDED, oacl))){
                if (!fflag)
-                       warn("Failed to set ACL on file %s", path);
+                       warn("Failed to set ACL on file '%s'", path);
                retval = 1;
        }
        
index 8ca16beb8d3ef3b86acbe86f2d784544ae899495..0833be4092e33ea1effb71182356250b84debaa9 100644 (file)
@@ -52,6 +52,7 @@
 #define ACL_REMOVE_INHERITED_ENTRIES (1<<10)
 #define ACL_NO_TRANSLATE (1<<11)
 #define ACL_INVOKE_EDITOR (1<<12)
+#define ACL_TO_STDOUT (1<<13)
 #define ACL_CLEAR_FLAG (1<<14)
 
 #define INHERITANCE_TIER (-5)
@@ -80,5 +81,5 @@ extern unsigned find_canonical_position(acl_t acl, acl_entry_t modifier);
 extern int subtract_from_entry(acl_entry_t rentry, acl_entry_t  modifier);
 extern int modify_acl(acl_t *oaclp, acl_entry_t modifier, unsigned int optflags, int position, int inheritance_level, unsigned flag_new_acl);
 extern int modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level);
-extern uuid_t *name_to_uuid(char *tok);
+extern uuid_t *name_to_uuid(char *tok, int nametype);
 #endif /* __APPLE__*/
index 9407995f29385dac6e6a1e47ebfe2db7dc51dd6d..6621698957e49984de34e8727f5038287f265f73 100644 (file)
@@ -42,7 +42,7 @@
 .Nm chgrp
 .Nd change group
 .Sh SYNOPSIS
-.Nm
+.Nm chgrp
 .Op Fl fhv
 .Oo
 .Fl R
@@ -52,7 +52,7 @@
 .Ar
 .Sh DESCRIPTION
 The
-.Nm
+.Nm chgrp
 utility sets the group ID of the file named by each
 .Ar file
 operand to the
@@ -61,32 +61,39 @@ ID specified by the group operand.
 .Pp
 The following options are available:
 .Bl -tag -width indent
+.\" ==========
+.It Fl f
+The force option ignores errors, except for usage errors and doesn't
+query about strange modes (unless the user does not have proper permissions).
+.\" ==========
 .It Fl H
 If the
 .Fl R
 option is specified, symbolic links on the command line are followed.
 (Symbolic links encountered in the tree traversal are not followed).
+.\" ==========
+.It Fl h
+If the file is a symbolic link, the group ID of the link itself is changed
+rather than the file that is pointed to.
+.\" ==========
 .It Fl L
 If the
 .Fl R
 option is specified, all symbolic links are followed.
+.\" ==========
 .It Fl P
 If the
 .Fl R
 option is specified, no symbolic links are followed.
 This is the default.
+.\" ==========
 .It Fl R
 Change the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
-.It Fl f
-The force option ignores errors, except for usage errors and doesn't
-query about strange modes (unless the user does not have proper permissions).
-.It Fl h
-If the file is a symbolic link, the group ID of the link itself is changed
-rather than the file that is pointed to.
+.\" ==========
 .It Fl v
 Cause
-.Nm
+.Nm chgrp
 to be verbose, showing files as the group is modified.
 .El
 .Pp
@@ -109,7 +116,7 @@ If a group name is also a numeric group ID, the operand is used as a
 group name.
 .Pp
 The user invoking
-.Nm
+.Nm chgrp
 must belong to the specified group and be the owner of the file,
 or be the super-user.
 .Sh DIAGNOSTICS
@@ -134,7 +141,7 @@ group ID file
 .Xr chown 8
 .Sh STANDARDS
 The
-.Nm
+.Nm chgrp
 utility is expected to be
 .St -p1003.2
 compatible.
index 18d467ddd347eb6ac4cf1680799021c3d8c4a31a..fc991cea6d5342050c175a95f35b30e65e4ee574 100644 (file)
@@ -39,7 +39,7 @@
 .Nm chown
 .Nd change file owner and group
 .Sh SYNOPSIS
-.Nm
+.Nm chown
 .Op Fl fhv
 .Oo
 .Fl R
@@ -47,7 +47,7 @@
 .Oc
 .Ar owner Ns Op : Ns Ar group
 .Ar
-.Nm
+.Nm chown
 .Op Fl fhv
 .Oo
 .Fl R
@@ -57,7 +57,7 @@
 .Ar
 .Sh DESCRIPTION
 The
-.Nm
+.Nm chown
 utility changes the user ID and/or the group ID of the specified files.
 Symbolic links named by arguments are silently left unchanged unless
 .Fl h
@@ -65,11 +65,17 @@ is used.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
+.It Fl f
+Don't report any failure to change file owner or group, nor modify
+the exit status to reflect such failures.
 .It Fl H
 If the
 .Fl R
 option is specified, symbolic links on the command line are followed.
 (Symbolic links encountered in the tree traversal are not followed.)
+.It Fl h
+If the file is a symbolic link, change the user ID and/or the
+group ID of the link itself.
 .It Fl L
 If the
 .Fl R
@@ -78,19 +84,14 @@ option is specified, all symbolic links are followed.
 If the
 .Fl R
 option is specified, no symbolic links are followed.
+Instead, the user and/or group ID of the link itself are modified.
 This is the default.
 .It Fl R
 Change the user ID and/or the group ID for the file hierarchies rooted
 in the files instead of just the files themselves.
-.It Fl f
-Don't report any failure to change file owner or group, nor modify
-the exit status to reflect such failures.
-.It Fl h
-If the file is a symbolic link, change the user ID and/or the
-group ID of the link itself.
 .It Fl v
 Cause
-.Nm
+.Nm chown
 to be verbose, showing files as the owner is modified.
 .El
 .Pp
@@ -109,7 +110,8 @@ The
 .Ar owner
 and
 .Ar group
-operands are both optional, however, one must be specified.
+operands are both optional;
+however, at least one must be specified.
 If the
 .Ar group
 operand is specified, it must be preceded by a colon (``:'') character.
@@ -125,37 +127,47 @@ may be either 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.
 .Pp
-The ownership of a file may only be altered by a super-user for
-obvious security reasons.
+For obvious security reasons,
+the ownership of a file may only be altered by a super-user.
+Similarly, only a member of a group can change a file's group ID
+to that group.
 .Sh DIAGNOSTICS
 .Ex -std
 .Sh COMPATIBILITY
 Previous versions of the
-.Nm
+.Nm chown
 utility used the dot (``.'') character to distinguish the group name.
-This has been changed to be a colon (``:'') character so that user and
-group names may contain the dot character.
+This has been changed to be a colon (``:'') character,
+so that user and group names may contain the dot character.
 .Pp
-On previous versions of this system, symbolic links did not have
-owners.
+On previous versions of this system,
+symbolic links did not have owners.
 .Pp
 The
 .Fl v
 option is non-standard and its use in scripts is not recommended.
+.Sh LEGACY DESCRIPTION
+In legacy mode, the
+.Fl R
+and
+.Fl RP
+options do not change the user ID
+or the group ID of symbolic links.
 .Sh SEE ALSO
 .Xr chgrp 1 ,
 .Xr find 1 ,
 .Xr chown 2 ,
 .Xr fts 3 ,
+.Xr compat 5 ,
 .Xr symlink 7
 .Sh STANDARDS
 The
-.Nm
+.Nm chown
 utility is expected to be
 .St -p1003.2
 compliant.
 .Sh HISTORY
 A
-.Nm
+.Nm chown
 utility appeared in
 .At v1 .
index 44a0f4317b7bef64f5488e67b139c8567db0f7f9..8af78c536adf13a3232edcf994ceb25a9c9368f3 100644 (file)
@@ -58,6 +58,13 @@ __RCSID("$FreeBSD: src/usr.sbin/chown/chown.c,v 1.24 2002/07/17 16:22:24 dwmalon
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/time.h>
+
+#ifdef __APPLE__
+#include <get_compat.h>
+#else
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
 
 void   a_gid(const char *);
 void   a_uid(const char *);
@@ -78,7 +85,11 @@ main(int argc, char **argv)
        int Hflag, Lflag, Rflag, fflag, hflag, vflag;
        int ch, fts_options, rval;
        char *cp;
+       int unix2003_compat = 0;
+       int symlink_found = 0;
 
+       if (argc < 1)
+               usage();
        cp = strrchr(argv[0], '/');
        cp = (cp != NULL) ? cp + 1 : argv[0];
        ischown = (strcmp(cp, "chown") == 0);
@@ -136,6 +147,7 @@ main(int argc, char **argv)
        uid = (uid_t)-1;
        gid = (gid_t)-1;
        if (ischown) {
+               unix2003_compat = COMPAT_MODE("bin/chown", "Unix2003");
                if ((cp = strchr(*argv, ':')) != NULL) {
                        *cp++ = '\0';
                        a_gid(cp);
@@ -148,13 +160,16 @@ main(int argc, char **argv)
                }
 #endif
                a_uid(*argv);
-       } else
+       } else {
+               unix2003_compat = COMPAT_MODE("bin/chgrp", "Unix2003");
                a_gid(*argv);
+       }
 
        if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
                err(1, NULL);
 
        for (rval = 0; (p = fts_read(ftsp)) != NULL;) {
+               symlink_found = 0;
                switch (p->fts_info) {
                case FTS_D:                     /* Change it at FTS_DP. */
                        if (!Rflag)
@@ -178,15 +193,33 @@ main(int argc, char **argv)
                         */
                        if (hflag)
                                break;
-                       else
+                       else {
+                               symlink_found = 1;
+                               if (unix2003_compat) {
+                                       if (Hflag || Lflag) {       /* -H or -L was specified */
+                                               if (p->fts_errno) {
+                                                       warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
+                                                       rval = 1;
+                                                       continue;
+                                               }
+                                       }
+                                       break; /* Otherwise symlinks keep going */
+                               }
                                continue;
+                       }
                default:
                        break;
                }
-               if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
-                   (gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
-                       continue;
-               if ((hflag ? lchown : chown)(p->fts_accpath, uid, gid) == -1) {
+               if (unix2003_compat) {
+                       /* Can only avoid updating times if both uid and gid are -1 */
+                       if ((uid == (uid_t)-1) && (gid == (gid_t)-1))
+                               continue;
+               } else {
+                       if ((uid == (uid_t)-1 || uid == p->fts_statp->st_uid) &&
+                           (gid == (gid_t)-1 || gid == p->fts_statp->st_gid))
+                               continue;
+               }
+               if (((hflag || symlink_found) ? lchown : chown)(p->fts_accpath, uid, gid) == -1) {
                        if (!fflag) {
                                chownerr(p->fts_path);
                                rval = 1;
diff --git a/cksum/Makefile b/cksum/Makefile
new file mode 100644 (file)
index 0000000..24e3168
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# Generated by the NeXT Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = cksum
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h
+
+CFILES = cksum.c crc.c print.c sum1.c sum2.c crc32.c
+
+OTHERSRCS = Makefile Makefile.preamble Makefile.postamble cksum.1
+
+OTHER_CFLAGS=-D__FBSDID=__RCSID
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/doc_cmds/Build
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/cksum/Makefile.postamble b/cksum/Makefile.postamble
new file mode 100644 (file)
index 0000000..a0b1af9
--- /dev/null
@@ -0,0 +1,5 @@
+include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
+
+after_install::
+       $(LINKPRODUCT) $(DSTROOT)$(INSTALLDIR)/sum
+       $(LN) -f $(DSTROOT)/usr/share/man/man1/cksum.1 $(DSTROOT)/usr/share/man/man1/sum.1
diff --git a/cksum/Makefile.preamble b/cksum/Makefile.preamble
new file mode 100644 (file)
index 0000000..9e10e90
--- /dev/null
@@ -0,0 +1 @@
+include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Preamble.Common
diff --git a/cksum/PB.project b/cksum/PB.project
new file mode 100644 (file)
index 0000000..63b0f64
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (extern.h); 
+        OTHER_LINKED = (cksum.c, crc.c, print.c, sum1.c, sum2.c); 
+        OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, cksum.1, sum.1); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = /tmp/doc_cmds/Build; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = cksum; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/cksum/cksum.1 b/cksum/cksum.1
new file mode 100644 (file)
index 0000000..b4161fe
--- /dev/null
@@ -0,0 +1,182 @@
+.\" Copyright (c) 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" 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. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. 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.
+.\"
+.\"    @(#)cksum.1     8.2 (Berkeley) 4/28/95
+.\" $FreeBSD: src/usr.bin/cksum/cksum.1,v 1.19 2005/01/17 07:44:13 ru Exp $
+.\"
+.Dd April 28, 1995
+.Dt CKSUM 1
+.Os
+.Sh NAME
+.Nm cksum ,
+.Nm sum
+.Nd display file checksums and block counts
+.Sh SYNOPSIS
+.Nm
+.Op Fl o Ar 1 | 2 | 3
+.Op Ar
+.Nm sum
+.Op Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility writes to the standard output three whitespace separated
+fields for each input file.
+These fields are a checksum
+.Tn CRC ,
+the total number of octets in the file and the file name.
+If no file name is specified, the standard input is used and no file name
+is written.
+.Pp
+The
+.Nm sum
+utility is identical to the
+.Nm
+utility, except that it defaults to using historic algorithm 1, as
+described below.
+It is provided for compatibility only.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Use historic algorithms instead of the (superior) default one.
+.Pp
+Algorithm 1 is the algorithm used by historic
+.Bx
+systems as the
+.Xr sum 1
+algorithm and by historic
+.At V
+systems as the
+.Xr sum 1
+algorithm when using the
+.Fl r
+option.
+This is a 16-bit checksum, with a right rotation before each addition;
+overflow is discarded.
+.Pp
+Algorithm 2 is the algorithm used by historic
+.At V
+systems as the
+default
+.Xr sum 1
+algorithm.
+This is a 32-bit checksum, and is defined as follows:
+.Bd -unfilled -offset indent
+s = sum of all bytes;
+r = s % 2^16 + (s % 2^32) / 2^16;
+cksum = (r % 2^16) + r / 2^16;
+.Ed
+.Pp
+Algorithm 3 is what is commonly called the
+.Ql 32bit CRC
+algorithm.
+This is a 32-bit checksum.
+.Pp
+Both algorithm 1 and 2 write to the standard output the same fields as
+the default algorithm except that the size of the file in bytes is
+replaced with the size of the file in blocks.
+For historic reasons, the block size is 1024 for algorithm 1 and 512
+for algorithm 2.
+Partial blocks are rounded up.
+.El
+.Pp
+The default
+.Tn CRC
+used is based on the polynomial used for
+.Tn CRC
+error checking
+in the networking standard
+.St -iso8802-3 .
+The
+.Tn CRC
+checksum encoding is defined by the generating polynomial:
+.Pp
+.Bd -unfilled -offset indent
+G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 +
+     x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
+.Ed
+.Pp
+Mathematically, the
+.Tn CRC
+value corresponding to a given file is defined by
+the following procedure:
+.Bd -ragged -offset indent
+The
+.Ar n
+bits to be evaluated are considered to be the coefficients of a mod 2
+polynomial M(x) of degree
+.Ar n Ns \-1 .
+These
+.Ar n
+bits are the bits from the file, with the most significant bit being the most
+significant bit of the first octet of the file and the last bit being the least
+significant bit of the last octet, padded with zero bits (if necessary) to
+achieve an integral number of octets, followed by one or more octets
+representing the length of the file as a binary value, least significant octet
+first.
+The smallest number of octets capable of representing this integer are used.
+.Pp
+M(x) is multiplied by x^32 (i.e., shifted left 32 bits) and divided by
+G(x) using mod 2 division, producing a remainder R(x) of degree <= 31.
+.Pp
+The coefficients of R(x) are considered to be a 32-bit sequence.
+.Pp
+The bit sequence is complemented and the result is the CRC.
+.Ed
+.Sh EXIT STATUS
+.Ex -std cksum sum
+.Sh SEE ALSO
+.Xr md5 1
+.Pp
+The default calculation is identical to that given in pseudo-code
+in the following
+.Tn ACM
+article.
+.Rs
+.%T "Computation of Cyclic Redundancy Checks Via Table Lookup"
+.%A Dilip V. Sarwate
+.%J "Communications of the" Tn ACM
+.%D "August 1988"
+.Re
+.Sh STANDARDS
+The
+.Nm
+utility is expected to conform to
+.St -p1003.2-92 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Bx 4.4 .
diff --git a/cksum/cksum.c b/cksum/cksum.c
new file mode 100644 (file)
index 0000000..51fdd17
--- /dev/null
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)cksum.c    8.2 (Berkeley) 4/28/95";
+#endif
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/cksum.c,v 1.17 2003/03/13 23:32:28 robert Exp $");
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+static void usage(void);
+
+int
+main(int argc, char **argv)
+{
+       uint32_t val;
+       int ch, fd, rval;
+       off_t len;
+       char *fn, *p;
+       int (*cfncn)(int, uint32_t *, off_t *);
+       void (*pfncn)(char *, u_int32_t, off_t);
+       
+       cfncn=NULL;
+
+       if(*argv) {
+         if ((p = rindex(argv[0], '/')) == NULL)
+           p = argv[0];
+         else
+           ++p;
+         if (!strcmp(p, "sum")) {
+           cfncn = csum1;
+           pfncn = psum1;
+           ++argv;
+         }
+       } 
+       
+       if(!cfncn) {
+               cfncn = crc;
+               pfncn = pcrc;
+
+               while ((ch = getopt(argc, argv, "o:")) != -1)
+                       switch (ch) {
+                       case 'o':
+                               if (!strcmp(optarg, "1")) {
+                                       cfncn = csum1;
+                                       pfncn = psum1;
+                               } else if (!strcmp(optarg, "2")) {
+                                       cfncn = csum2;
+                                       pfncn = psum2;
+                               } else if (!strcmp(optarg, "3")) {
+                                       cfncn = crc32;
+                                       pfncn = pcrc;
+                               } else {
+                                       warnx("illegal argument to -o option");
+                                       usage();
+                               }
+                               break;
+                       case '?':
+                       default:
+                               usage();
+                       }
+               argc -= optind;
+               argv += optind;
+       }
+
+       fd = STDIN_FILENO;
+       fn = NULL;
+       rval = 0;
+       do {
+               if (*argv) {
+                       fn = *argv++;
+                       if ((fd = open(fn, O_RDONLY, 0)) < 0) {
+                               warn("%s", fn);
+                               rval = 1;
+                               continue;
+                       }
+               }
+               if (cfncn(fd, &val, &len)) {
+                       warn("%s", fn ? fn : "stdin");
+                       rval = 1;
+               } else
+                       pfncn(fn, val, len);
+               (void)close(fd);
+       } while (*argv);
+       exit(rval);
+}
+
+static void
+usage(void)
+{
+       (void)fprintf(stderr, "usage: cksum [-o 1 | 2 | 3] [file ...]\n");
+       (void)fprintf(stderr, "       sum [file ...]\n");
+       exit(1);
+}
index b1a2f856bbdec6baa16debd4bb0cd59447b8c005..92693e8014d6839a42892bdab4e0c8bffb2ee4ff 100644 (file)
 #if 0
 static char sccsid[] = "@(#)crc.c      8.1 (Berkeley) 6/17/93";
 #endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.bin/cksum/crc.c,v 1.4 1999/12/05 20:03:21 charnier Exp $";
 #endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/crc.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
 
 #include <sys/types.h>
+
+#include <stdint.h>
 #include <unistd.h>
 
-static const u_int32_t crctab[] = {
+#include "extern.h"
+
+static const uint32_t crctab[] = {
        0x0,
        0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
        0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
@@ -106,25 +110,24 @@ 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.
  */
-u_int32_t crc_total = ~0;                      /* The crc over a number of files. */
+uint32_t crc_total = ~0;               /* The crc over a number of files. */
 
 int
-crc(fd, cval, clen)
-       register int fd;
-       u_int32_t *cval, *clen;
+crc(int fd, uint32_t *cval, off_t *clen)
 {
-       register u_char *p;
-       register int nr;
-       register u_int32_t crc, len;
+       uint32_t lcrc;
+       int nr;
+       off_t len;
+       u_char *p;
        u_char buf[16 * 1024];
 
 #define        COMPUTE(var, ch)        (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
 
-       crc = len = 0;
+       lcrc = len = 0;
        crc_total = ~crc_total;
        while ((nr = read(fd, buf, sizeof(buf))) > 0)
                for (len += nr, p = buf; nr--; ++p) {
-                       COMPUTE(crc, *p);
+                       COMPUTE(lcrc, *p);
                        COMPUTE(crc_total, *p);
                }
        if (nr < 0)
@@ -134,11 +137,11 @@ crc(fd, cval, clen)
 
        /* Include the length of the file. */
        for (; len != 0; len >>= 8) {
-               COMPUTE(crc, len & 0xff);
+               COMPUTE(lcrc, len & 0xff);
                COMPUTE(crc_total, len & 0xff);
        }
 
-       *cval = ~crc;
+       *cval = ~lcrc;
        crc_total = ~crc_total;
        return (0);
 }
diff --git a/cksum/crc32.c b/cksum/crc32.c
new file mode 100644 (file)
index 0000000..fa8f900
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This code implements the AUTODIN II polynomial used by Ethernet,
+ * and can be used to calculate multicast address hash indices.
+ * It assumes that the low order bits will be transmitted first,
+ * and consequently the low byte should be sent first when
+ * the crc computation is finished.  The crc should be complemented
+ * before transmission.
+ * The variable corresponding to the macro argument "crc" should
+ * be an unsigned long and should be preset to all ones for Ethernet
+ * use.  An error-free packet will leave 0xDEBB20E3 in the crc.
+ *                     Spencer Garrett <srg@quick.com>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/crc32.c,v 1.9 2003/03/13 23:32:28 robert Exp $");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#define CRC(crc, ch)    (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
+
+/* generated using the AUTODIN II polynomial
+ *     x^32 + x^26 + x^23 + x^22 + x^16 +
+ *     x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
+ */
+static const uint32_t crctab[256] = {
+       0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+       0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+       0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+       0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+       0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+       0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+       0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+       0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+       0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+       0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+       0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+       0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+       0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+       0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+       0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+       0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+       0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+       0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+       0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+       0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+       0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+       0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+       0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+       0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+       0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+       0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+       0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+       0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+       0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+       0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+       0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+       0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+       0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+       0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+       0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+       0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+       0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+       0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+       0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+       0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+       0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+       0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+       0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+       0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+       0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+       0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+       0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+       0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+       0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+       0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+       0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+       0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+       0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+       0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+       0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+       0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+       0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+       0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+       0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+       0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+       0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+       0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+       0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+       0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+uint32_t crc32_total = 0;
+
+int
+crc32(int fd, uint32_t *cval, off_t *clen)
+{
+    uint32_t lcrc = ~0;
+    int nr ;
+    off_t len ;
+    char buf[BUFSIZ], *p ;
+       
+    len = 0 ;
+    crc32_total = ~crc32_total ;
+    while ((nr = read(fd, buf, sizeof(buf))) > 0)
+        for (len += nr, p = buf; nr--; ++p) {
+           CRC(lcrc, *p) ;
+           CRC(crc32_total, *p) ;
+       }
+    if (nr < 0)
+        return 1 ;
+
+    *clen = len ;
+    *cval = ~lcrc ;
+    crc32_total = ~crc32_total ;
+    return 0 ;
+}
diff --git a/cksum/extern.h b/cksum/extern.h
new file mode 100644 (file)
index 0000000..e9b594a
--- /dev/null
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ *     @(#)extern.h    8.1 (Berkeley) 6/6/93
+ * $FreeBSD: src/usr.bin/cksum/extern.h,v 1.6 2003/03/13 23:32:28 robert Exp $
+ */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int    crc(int, uint32_t *, off_t *);
+void   pcrc(char *, uint32_t, off_t);
+void   psum1(char *, uint32_t, off_t);
+void   psum2(char *, uint32_t, off_t);
+int    csum1(int, uint32_t *, off_t *);
+int    csum2(int, uint32_t *, off_t *);
+int    crc32(int, uint32_t *, off_t *);
+__END_DECLS
diff --git a/cksum/print.c b/cksum/print.c
new file mode 100644 (file)
index 0000000..4d732d9
--- /dev/null
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)print.c    8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/print.c,v 1.7 2003/03/13 23:32:28 robert Exp $");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+void
+pcrc(char *fn, uint32_t val, off_t len)
+{
+       (void)printf("%lu %jd", (u_long)val, (intmax_t)len);
+       if (fn != NULL)
+               (void)printf(" %s", fn);
+       (void)printf("\n");
+}
+
+void
+psum1(char *fn, uint32_t val, off_t len)
+{
+       (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 1023) / 1024);
+       if (fn != NULL)
+               (void)printf(" %s", fn);
+       (void)printf("\n");
+}
+
+void
+psum2(char *fn, uint32_t val, off_t len)
+{
+       (void)printf("%lu %jd", (u_long)val, (intmax_t)(len + 511) / 512);
+       if (fn != NULL)
+               (void)printf(" %s", fn);
+       (void)printf("\n");
+}
diff --git a/cksum/sum1.c b/cksum/sum1.c
new file mode 100644 (file)
index 0000000..f3c05ce
--- /dev/null
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sum1.c     8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/sum1.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
+
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+int
+csum1(int fd, uint32_t *cval, off_t *clen)
+{
+       int nr;
+       u_int lcrc;
+       off_t total;
+       u_char *p;
+       u_char buf[8192];
+
+       /*
+        * 16-bit checksum, rotating right before each addition;
+        * overflow is discarded.
+        */
+       lcrc = total = 0;
+       while ((nr = read(fd, buf, sizeof(buf))) > 0)
+               for (total += nr, p = buf; nr--; ++p) {
+                       if (lcrc & 1)
+                               lcrc |= 0x10000;
+                       lcrc = ((lcrc >> 1) + *p) & 0xffff;
+               }
+       if (nr < 0)
+               return (1);
+
+       *cval = lcrc;
+       *clen = total;
+       return (0);
+}
diff --git a/cksum/sum2.c b/cksum/sum2.c
new file mode 100644 (file)
index 0000000..83ca362
--- /dev/null
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)sum2.c     8.1 (Berkeley) 6/6/93";
+#endif
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.bin/cksum/sum2.c,v 1.8 2003/03/13 23:32:28 robert Exp $");
+
+#include <sys/types.h>
+
+#include <unistd.h>
+#include <stdint.h>
+
+#include "extern.h"
+
+int
+csum2(int fd, uint32_t *cval, off_t *clen)
+{
+       uint32_t lcrc;
+       int nr;
+       off_t total;
+       u_char *p;
+       u_char buf[8192];
+
+       /*
+        * Draft 8 POSIX 1003.2:
+        *
+        *   s = sum of all bytes
+        *   r = s % 2^16 + (s % 2^32) / 2^16
+        * lcrc = (r % 2^16) + r / 2^16
+        */
+       lcrc = total = 0;
+       while ((nr = read(fd, buf, sizeof(buf))) > 0)
+               for (total += nr, p = buf; nr--; ++p)
+                       lcrc += *p;
+       if (nr < 0)
+               return (1);
+
+       lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+       lcrc = (lcrc & 0xffff) + (lcrc >> 16);
+
+       *cval = lcrc;
+       *clen = total;
+       return (0);
+}
index 9478ad1d8e20228ced707eff6ff5d4e6b209afb0..f312cf5bcf75d936f6951cd4cc126cbc7570bb1b 100644 (file)
@@ -17,7 +17,7 @@ CFILES = compress.c zopen.c
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble compress.1\
             zopen.3 uncompress.1 zopen.h
 
-NEXTSTEP_PB_CFLAGS += -D__FBSDID=__RCSID -D"__printflike(a,b)="
+NEXTSTEP_PB_CFLAGS += -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 14b509fe84cdd397a391daa9803db76327d1e448..03311f911959657e6f5e78489343017a5f92cc55 100644 (file)
@@ -78,6 +78,8 @@ main(int argc, char *argv[])
        int bits, ch;
        char *p, newname[MAXPATHLEN];
 
+       if (argc < 1)
+               usage(1);
        cat = 0;
        if ((p = rindex(argv[0], '/')) == NULL)
                p = argv[0];
@@ -402,10 +404,10 @@ setfile(const char *name, struct stat *fs)
                        cwarn("chown: %s", name);
                fs->st_mode &= ~(S_ISUID|S_ISGID);
        }
-       if (chmod(name, fs->st_mode) && errno != EOPNOTSUPP)
+       if (chmod(name, fs->st_mode) && errno != ENOTSUP)
                cwarn("chmod: %s", name);
 
-       if (chflags(name, fs->st_flags) && errno != EOPNOTSUPP)
+       if (chflags(name, fs->st_flags) && errno != ENOTSUP)
                cwarn("chflags: %s", name);
 }
 
index e12876649751df8a5e78283f1161bb47e460c5d4..774bbfd19e1d9b0bea408091faf67223c6419a10 100644 (file)
@@ -18,6 +18,7 @@ CFILES = cp.c utils.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble cp.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
diff --git a/cp/cp.1 b/cp/cp.1
index 81825dde4057c7a8008d38d33fdc80629481120a..17ecd81ce9514d74913a598a4874df94b2264255 100644 (file)
--- a/cp/cp.1
+++ b/cp/cp.1
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1989, 1990, 1993, 1994
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. 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.
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)cp.1        8.3 (Berkeley) 4/18/94
-.\" $FreeBSD: src/bin/cp/cp.1,v 1.25 2002/08/16 03:13:59 johan Exp $
+.\" $FreeBSD: src/bin/cp/cp.1,v 1.33 2005/02/25 00:40:46 trhodes Exp $
 .\"
-.Dd July 23, 2002
+.Dd February 23, 2005
 .Dt CP 1
 .Os
 .Sh NAME
 .Nm cp
 .Nd copy files
 .Sh SYNOPSIS
-.Nm
+.Nm cp
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
 .Oc
-.Op Fl f | i | n
-.Op Fl pv
+.Op Fl fi | n
+.Op Fl pvX
 .Ar source_file target_file
-.Nm
+.Nm cp
 .Oo
 .Fl R
 .Op Fl H | Fl L | Fl P
 .Oc
-.Op Fl f | i | n
-.Op Fl pv
+.Op Fl fi | n
+.Op Fl pvX
 .Ar source_file ... target_directory
 .Sh DESCRIPTION
 In the first synopsis form, the
-.Nm
+.Nm cp
 utility copies the contents of the
 .Ar source_file
 to the
@@ -72,47 +69,11 @@ is copied to the destination
 .Ar target_directory .
 The names of the files themselves are not changed.
 If
-.Nm
+.Nm cp
 detects an attempt to copy a file to itself, the copy will fail.
 .Pp
 The following options are available:
 .Bl -tag -width flag
-.It Fl H
-If the
-.Fl R
-option is specified, symbolic links on the command line are followed.
-(Symbolic links encountered in the tree traversal are not followed.)
-.It Fl L
-If the
-.Fl R
-option is specified, all symbolic links are followed.
-.It Fl P
-If the
-.Fl R
-option is specified, no symbolic links are followed.
-This is the default.
-.It Fl R
-If
-.Ar source_file
-designates a directory,
-.Nm
-copies the directory and the entire subtree connected at that point.
-This option also causes symbolic links to be copied, rather than
-indirected through, and for
-.Nm
-to create special files rather than copying them as normal files.
-Created directories have the same mode as the corresponding source
-directory, unmodified by the process' umask.
-.Pp
-Note that
-.Nm
-copies hard linked files as separate files.
-If you need to preserve hard links, consider using
-.Xr tar 1 ,
-.Xr cpio 1 ,
-or
-.Xr pax 1
-instead.
 .It Fl f
 For each existing destination pathname, remove it and
 create a new file, without prompting for confirmation
@@ -121,12 +82,18 @@ regardless of its permissions.
 .Fl f
 option overrides any previous
 .Fl n
-option, but not
-.Fl i
-option. See also the legacy section.)
+option.)
+.Pp
+The target file is not unlinked before the copy.
+Thus, any existing access rights will be retained.
+.It Fl H
+If the
+.Fl R
+option is specified, symbolic links on the command line are followed.
+(Symbolic links encountered in the tree traversal are not followed.)
 .It Fl i
 Cause
-.Nm
+.Nm cp
 to write a prompt to the standard error output before copying a file
 that would overwrite an existing file.
 If the response from the standard input begins with the character
@@ -137,10 +104,12 @@ the file copy is attempted.
 (The
 .Fl i
 option overrides any previous
-.Fl f
-or
 .Fl n
-options.)
+option.)
+.It Fl L
+If the
+.Fl R
+option is specified, all symbolic links are followed.
 .It Fl n
 Do not overwrite an existing file.
 (The
@@ -150,33 +119,77 @@ option overrides any previous
 or
 .Fl i
 options.)
+.It Fl P
+If the
+.Fl R
+option is specified, no symbolic links are followed.
+This is the default.
 .It Fl p
 Cause
-.Nm
-to preserve in the copy as many of the modification time, access time,
-file flags, file mode, user ID, and group ID as allowed by permissions.
+.Nm cp
+to preserve the following attributes of each source
+file in the copy: modification time, access time,
+file flags, file mode, user ID, and group ID, as allowed by permissions.
+Access Control Lists (ACLs) will also be preserved.
 .Pp
 If the user ID and group ID cannot be preserved, no error message
 is displayed and the exit value is not altered.
 .Pp
-If the source file has its set user ID bit on and the user ID cannot
-be preserved, the set user ID bit is not preserved
+If the source file has its set-user-ID bit on and the user ID cannot
+be preserved, the set-user-ID bit is not preserved
 in the copy's permissions.
-If the source file has its set group ID bit on and the group ID cannot
-be preserved, the set group ID bit is not preserved
+If the source file has its set-group-ID bit on and the group ID cannot
+be preserved, the set-group-ID bit is not preserved
 in the copy's permissions.
-If the source file has both its set user ID and set group ID bits on,
+If the source file has both its set-user-ID and set-group-ID bits on,
 and either the user ID or group ID cannot be preserved, neither
-the set user ID nor set group ID bits are preserved in the copy's
+the set-user-ID nor set-group-ID bits are preserved in the copy's
 permissions.
+.It Fl R
+If
+.Ar source_file
+designates a directory,
+.Nm cp
+copies the directory and the entire subtree connected at that point.
+If the
+.Ar source_file
+ends in a
+.Pa / ,
+the contents of the directory are copied rather than the
+directory itself.
+This option also causes symbolic links to be copied, rather than
+indirected through, and for
+.Nm cp
+to create special files rather than copying them as normal files.
+Created directories have the same mode as the corresponding source
+directory, unmodified by the process' umask.
+.Pp
+In
+.Fl R
+mode,
+.Nm cp
+will continue copying even if errors are detected. 
+.Pp
+Note that
+.Nm cp
+copies hard-linked files as separate files.
+If you need to preserve hard links, consider using
+.Xr tar 1 ,
+.Xr cpio 1 ,
+or
+.Xr pax 1
+instead.
 .It Fl v
 Cause
-.Nm
+.Nm cp
 to be verbose, showing files as they are copied.
+.It Fl X
+Do not copy Extended Attributes (EAs) or resource forks.
 .El
 .Pp
 For each destination file that already exists, its contents are
-overwritten if permissions allow.  Its mode, user ID, and group
+overwritten if permissions allow.
+Its mode, user ID, and group
 ID are unchanged unless the
 .Fl p
 option was specified.
@@ -194,13 +207,13 @@ used as modified by the file mode creation mask
 .Pf ( Ic umask ,
 see
 .Xr csh 1 ) .
-If the source file has its set user ID bit on, that bit is removed
+If the source file has its set-user-ID bit on, that bit is removed
 unless both the source file and the destination file are owned by the
 same user.
-If the source file has its set group ID bit on, that bit is removed
+If the source file has its set-group-ID bit on, that bit is removed
 unless both the source file and the destination file are in the same
 group and the user is a member of that group.
-If both the set user ID and set group ID bits are set, all of the above
+If both the set-user-ID and set-group-ID bits are set, all of the above
 conditions must be fulfilled or both bits are removed.
 .Pp
 Appropriate permissions are required for file creation or overwriting.
@@ -225,17 +238,28 @@ options are ignored unless the
 option is specified.
 In addition, these options override each other and the
 command's actions are determined by the last one specified.
-.Sh DIAGNOSTICS
+.Pp
+If
+.Nm cp
+receives a
+.Dv SIGINFO
+(see the
+.Cm status
+argument for
+.Xr stty 1 )
+signal, the current input and output file and the percentage complete
+will be written to the standard output.
+.Sh EXIT STATUS
 .Ex -std
 .Sh COMPATIBILITY
 Historic versions of the
-.Nm
+.Nm cp
 utility had a
 .Fl r
 option.
-This implementation supports that option, however, its use is strongly
-discouraged, as it does not correctly copy special files, symbolic links
-or fifo's.
+This implementation supports that option;
+however, its use is strongly discouraged,
+as it does not correctly copy special files, symbolic links, or fifo's.
 .Pp
 The
 .Fl v
@@ -243,12 +267,18 @@ and
 .Fl n
 options are non-standard and their use in scripts is not recommended.
 .Sh LEGACY DESCRIPTION
-When invoked in legacy mode, both 
-.Fl n ,
-.Fl i
-options are overridden by the
+In legacy mode,
 .Fl f
-option.
+will override
+.Fl i .
+Also, under the
+.Fl f
+option, the target file is always unlinked before the copy.
+Thus, new access rights will always be set.
+.Pp
+In
+.Fl R
+mode, copying will terminate if an error is encountered.
 .Sh SEE ALSO
 .Xr mv 1 ,
 .Xr rcp 1 ,
@@ -258,14 +288,12 @@ option.
 .Xr symlink 7
 .Sh STANDARDS
 The
-.Nm
+.Nm cp
 command is expected to be
 .St -p1003.2
-compatible. It is also
-.St -susv3
-conformant.
+compatible.
 .Sh HISTORY
 A
-.Nm
+.Nm cp
 command appeared in
 .At v1 .
diff --git a/cp/cp.c b/cp/cp.c
index 7e9dc8f5c31a400606192cd2e5648f9bf25e53c4..f421cc9383ead6c51e7b104d8af6e52456cc4a80 100644 (file)
--- a/cp/cp.c
+++ b/cp/cp.c
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1988, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
@@ -34,6 +30,7 @@
  * SUCH DAMAGE.
  */
 
+#if 0
 #ifndef lint
 static char const copyright[] =
 "@(#) Copyright (c) 1988, 1993, 1994\n\
@@ -41,12 +38,11 @@ static char const copyright[] =
 #endif /* not lint */
 
 #ifndef lint
-#if 0
 static char sccsid[] = "@(#)cp.c       8.2 (Berkeley) 4/1/94";
-#endif
 #endif /* not lint */
+#endif
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/bin/cp/cp.c,v 1.42 2002/09/22 11:15:56 mckay Exp $");
+__FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.52 2005/09/05 04:36:08 csjp Exp $");
 
 /*
  * Cp copies source files to target files.
@@ -63,13 +59,14 @@ __RCSID("$FreeBSD: src/bin/cp/cp.c,v 1.42 2002/09/22 11:15:56 mckay Exp $");
  * in "to") to form the final target path.
  */
 
-#include <sys/param.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 
 #include <err.h>
 #include <errno.h>
 #include <fts.h>
 #include <limits.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -77,9 +74,11 @@ __RCSID("$FreeBSD: src/bin/cp/cp.c,v 1.42 2002/09/22 11:15:56 mckay Exp $");
 
 #ifdef __APPLE__
 #include <copyfile.h>
-#endif
+#include <get_compat.h>
+#else /* !__APPLE__ */
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
 
-#include "get_compat.h"
 #include "extern.h"
 
 #define        STRIP_TRAILING_SLASH(p) {                                       \
@@ -92,12 +91,17 @@ static char emptystring[] = "";
 PATH_T to = { to.p_path, emptystring, "" };
 
 int fflag, iflag, nflag, pflag, vflag;
+#ifdef __APPLE__
+int Xflag;
+#endif /* __APPLE__ */
 static int Rflag, rflag;
+volatile sig_atomic_t info;
 
 enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
 
 static int copy(char *[], enum op, int);
 static int mastercmp(const FTSENT * const *, const FTSENT * const *);
+static void siginfo(int __unused);
 
 int
 main(int argc, char *argv[])
@@ -108,7 +112,7 @@ main(int argc, char *argv[])
        char *target;
 
        Hflag = Lflag = Pflag = 0;
-       while ((ch = getopt(argc, argv, "HLPRfinprv")) != -1)
+       while ((ch = getopt(argc, argv, "HLPRXfinprv")) != -1)
                switch (ch) {
                case 'H':
                        Hflag = 1;
@@ -125,17 +129,23 @@ main(int argc, char *argv[])
                case 'R':
                        Rflag = 1;
                        break;
+               case 'X':
+                       Xflag = 1;
+                       break;
                case 'f':
                        fflag = 1;
                        /* Determine if the STD is SUSv3 or Legacy */
-                       if (compat_mode("bin/cp", "unix2003"))
+                       if (COMPAT_MODE("bin/cp", "unix2003"))
                                nflag = 0;      /* reset nflag, but not iflag */
                        else
                                iflag = nflag = 0;      /* reset both */
                        break;
                case 'i':
                        iflag = 1;
-                       fflag = nflag = 0;
+                       if (COMPAT_MODE("bin/cp", "unix2003"))
+                               nflag = 0;      /* reset nflag, but not fflag */
+                       else
+                               fflag = nflag = 0;
                        break;
                case 'n':
                        nflag = 1;
@@ -182,6 +192,7 @@ main(int argc, char *argv[])
                fts_options &= ~FTS_PHYSICAL;
                fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
        }
+       (void)signal(SIGINFO, siginfo);
 
        /* Save the target base in "to". */
        target = argv[--argc];
@@ -261,7 +272,7 @@ main(int argc, char *argv[])
        exit (copy(argv, type, fts_options));
 }
 
-int
+static int
 copy(char *argv[], enum op type, int fts_options)
 {
        struct stat to_stat;
@@ -371,11 +382,17 @@ copy(char *argv[], enum op type, int fts_options)
                         * normally want to preserve them on directories.
                         */
                        if (pflag) {
+                               if (setfile(curr->fts_statp, -1))
+                                       rval = 1;
 #ifdef __APPLE__
-                               copyfile(curr->fts_path, to.p_path, 0, COPYFILE_ACL);
-#endif
-                               if (setfile(curr->fts_statp, 0))
-                                   rval = 1;
+                               /* setfile will fail if writeattr is denied */
+                               if (copyfile(curr->fts_path, to.p_path, NULL, COPYFILE_ACL)<0)
+                                       warn("%s: unable to copy ACL to %s", curr->fts_path, to.p_path);
+#else  /* !__APPLE__ */
+                               if (preserve_dir_acls(curr->fts_statp,
+                                   curr->fts_accpath, to.p_path) != 0)
+                                       rval = 1;
+#endif /* __APPLE__ */
                        } else {
                                mode = curr->fts_statp->st_mode;
                                if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
@@ -428,7 +445,7 @@ copy(char *argv[], enum op type, int fts_options)
                case S_IFDIR:
                        if (!Rflag && !rflag) {
                                warnx("%s is a directory (not copied).",
-                                        curr->fts_path);
+                                   curr->fts_path);
                                (void)fts_set(ftsp, curr, FTS_SKIP);
                                badcp = rval = 1;
                                break;
@@ -444,10 +461,18 @@ copy(char *argv[], enum op type, int fts_options)
                        if (dne) {
                                if (mkdir(to.p_path,
                                    curr->fts_statp->st_mode | S_IRWXU) < 0)
-                                       err(1, "%s", to.p_path);
+                                       if (COMPAT_MODE("bin/cp", "unix2003")) {
+                                               warn("%s", to.p_path);
+                                       } else {
+                                               err(1, "%s", to.p_path);
+                                       }
                        } else if (!S_ISDIR(to_stat.st_mode)) {
                                errno = ENOTDIR;
-                               err(1, "%s", to.p_path);
+                               if (COMPAT_MODE("bin/cp", "unix2003")) {
+                                       warn("%s", to.p_path);
+                               } else {
+                                       err(1, "%s", to.p_path);
+                               }
                        }
                        /*
                         * Arrange to correct directory attributes later
@@ -456,8 +481,12 @@ copy(char *argv[], enum op type, int fts_options)
                         */
                        curr->fts_number = pflag || dne;
 #ifdef __APPLE__
-                       copyfile(curr->fts_path, to.p_path, 0, COPYFILE_XATTR);
-#endif
+                       if (!Xflag) {
+                               if (copyfile(curr->fts_path, to.p_path, NULL, COPYFILE_XATTR) < 0)
+                                       warn("%s: unable to copy extended attributes to %s", curr->fts_path, to.p_path);
+                               /* ACL and mtime set in postorder traversal */
+                       }
+#endif /* __APPLE__ */
                        break;
                case S_IFBLK:
                case S_IFCHR:
@@ -488,6 +517,7 @@ copy(char *argv[], enum op type, int fts_options)
        }
        if (errno)
                err(1, "fts_read");
+       fts_close(ftsp);
        return (rval);
 }
 
@@ -499,7 +529,7 @@ copy(char *argv[], enum op type, int fts_options)
  *     parent directory, whereas directories tend not to be.  Copying the
  *     files first reduces seeking.
  */
-int
+static int
 mastercmp(const FTSENT * const *a, const FTSENT * const *b)
 {
        int a_info, b_info;
@@ -516,3 +546,10 @@ mastercmp(const FTSENT * const *a, const FTSENT * const *b)
                return (1);
        return (0);
 }
+
+static void
+siginfo(int sig __unused)
+{
+
+       info = 1;
+}
index 66fea9947db77ecde3dfa79884bc8f623c9b5501..10a52117f36112717557462b4e17c3b4488b3cc7 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
@@ -31,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)extern.h    8.2 (Berkeley) 4/1/94
- * $FreeBSD: src/bin/cp/extern.h,v 1.15 2002/07/23 00:42:56 johan Exp $
+ * $FreeBSD: src/bin/cp/extern.h,v 1.20 2005/09/05 04:36:08 csjp Exp $
  */
 
 typedef struct {
@@ -42,12 +38,18 @@ typedef struct {
 
 extern PATH_T to;
 extern int fflag, iflag, nflag, pflag, vflag;
+#ifdef __APPLE__
+extern int Xflag;
+#endif /* __APPLE__ */
+extern volatile sig_atomic_t info;
 
 __BEGIN_DECLS
 int    copy_fifo(struct stat *, int);
-int    copy_file(FTSENT *, int);
-int    copy_link(FTSENT *, int);
+int    copy_file(const FTSENT *, int);
+int    copy_link(const FTSENT *, int);
 int    copy_special(struct stat *, int);
 int    setfile(struct stat *, int);
+int    preserve_dir_acls(struct stat *, char *, char *);
+int    preserve_fd_acls(int, int);
 void   usage(void);
 __END_DECLS
index 70dc376d6c371ae70bed52b47e4da023289c9d75..2235939e248eb745f731929c671f595fc68ebfca 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
@@ -37,10 +33,11 @@ static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/bin/cp/utils.c,v 1.38 2002/07/31 16:52:16 markm Exp $");
+__FBSDID("$FreeBSD: src/bin/cp/utils.c,v 1.46 2005/09/05 04:36:08 csjp Exp $");
 
+#include <sys/types.h>
+#include <sys/acl.h>
 #include <sys/param.h>
-#include <sys/time.h>
 #include <sys/stat.h>
 #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
 #include <sys/mman.h>
@@ -57,21 +54,27 @@ __RCSID("$FreeBSD: src/bin/cp/utils.c,v 1.38 2002/07/31 16:52:16 markm Exp $");
 #include <unistd.h>
 
 #ifdef __APPLE__
+#include <sys/time.h>
 #include <copyfile.h>
 #include <string.h>
 #include <sys/mount.h>
-#endif
+#include <get_compat.h> 
+#else 
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
 
 #include "extern.h"
+#define        cp_pct(x,y)     (int)(100.0 * (double)(x) / (double)(y))
 
 int
-copy_file(FTSENT *entp, int dne)
+copy_file(const FTSENT *entp, int dne)
 {
        static char buf[MAXBSIZE];
        struct stat *fs;
        int ch, checkch, from_fd, rcount, rval, to_fd;
        ssize_t wcount;
        size_t wresid;
+       off_t wtotal;
        char *bufp;
 #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
        char *p;
@@ -97,8 +100,8 @@ copy_file(FTSENT *entp, int dne)
                if (nflag) {
                        if (vflag)
                                printf("%s not overwritten\n", to.p_path);
-                       close(from_fd);
-                       return (0);
+                       (void)close(from_fd);
+                       return (1);
                } else if (iflag) {
                        (void)fprintf(stderr, "overwrite %s? %s", 
                                        to.p_path, YESNO);
@@ -112,15 +115,28 @@ copy_file(FTSENT *entp, int dne)
                        }
                }
                
-               if (fflag) {
-                   /* remove existing destination file name, 
-                    * create a new file  */
-                   (void)unlink(to.p_path);
-                   to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
-                                fs->st_mode & ~(S_ISUID | S_ISGID));
-               } else 
-                   /* overwrite existing destination file name */
+               if (COMPAT_MODE("bin/cp", "unix2003")) {
+                   /* first try to overwrite existing destination file name */
                    to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+                   if (to_fd == -1) {
+                       if (fflag) {
+                           /* Only if it fails remove file and create a new one */
+                           (void)unlink(to.p_path);
+                           to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+                                        fs->st_mode & ~(S_ISUID | S_ISGID));
+                       }
+                   }
+               } else {
+                       if (fflag) {
+                           /* remove existing destination file name, 
+                            * create a new file  */
+                           (void)unlink(to.p_path);
+                           to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
+                                        fs->st_mode & ~(S_ISUID | S_ISGID));
+                       } else 
+                           /* overwrite existing destination file name */
+                           to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
+               }
        } else
                to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
                    fs->st_mode & ~(S_ISUID | S_ISGID));
@@ -134,25 +150,25 @@ copy_file(FTSENT *entp, int dne)
        rval = 0;
 
 #ifdef __APPLE__
-       if (S_ISREG(fs->st_mode)) {
-               struct statfs sfs;
-
-               /*
-                * Pre-allocate blocks for the destination file if it
-                * resides on Xsan.
-                */
-               if (fstatfs(to_fd, &sfs) == 0 &&
-                   strcmp(sfs.f_fstypename, "acfs") == 0) {
-                       fstore_t fst;
-
-                       fst.fst_flags = 0;
-                       fst.fst_posmode = F_PEOFPOSMODE;
-                       fst.fst_offset = 0;
-                       fst.fst_length = fs->st_size;
-
-                       (void) fcntl(to_fd, F_PREALLOCATE, &fst);
-               }
-       }
+       if (S_ISREG(fs->st_mode)) {
+               struct statfs sfs;
+
+               /*
+                * Pre-allocate blocks for the destination file if it
+                * resides on Xsan.
+                */
+               if (fstatfs(to_fd, &sfs) == 0 &&
+                   strcmp(sfs.f_fstypename, "acfs") == 0) {
+                       fstore_t fst;
+
+                       fst.fst_flags = 0;
+                       fst.fst_posmode = F_PEOFPOSMODE;
+                       fst.fst_offset = 0;
+                       fst.fst_length = fs->st_size;
+
+                       (void) fcntl(to_fd, F_PREALLOCATE, &fst);
+               }
+       }
 #endif /* __APPLE__ */
 
        /*
@@ -161,15 +177,26 @@ copy_file(FTSENT *entp, int dne)
         * wins some CPU back.
         */
 #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
-       if (S_ISREG(fs->st_mode) && fs->st_size <= 8 * 1048576) {
+       if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
+           fs->st_size <= 8 * 1048576) {
                if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
                    MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
                        warn("%s", entp->fts_path);
                        rval = 1;
                } else {
+                       wtotal = 0;
                        for (bufp = p, wresid = fs->st_size; ;
                            bufp += wcount, wresid -= (size_t)wcount) {
                                wcount = write(to_fd, bufp, wresid);
+                               wtotal += wcount;
+                               if (info) {
+                                       info = 0;
+                                       (void)fprintf(stderr,
+                                               "%s -> %s %3d%%\n",
+                                               entp->fts_path, to.p_path,
+                                               cp_pct(wtotal, fs->st_size));
+                                               
+                               }
                                if (wcount >= (ssize_t)wresid || wcount <= 0)
                                        break;
                        }
@@ -186,10 +213,20 @@ copy_file(FTSENT *entp, int dne)
        } else
 #endif
        {
+               wtotal = 0;
                while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
                        for (bufp = buf, wresid = rcount; ;
                            bufp += wcount, wresid -= wcount) {
                                wcount = write(to_fd, bufp, wresid);
+                               wtotal += wcount;
+                               if (info) {
+                                       info = 0;
+                                       (void)fprintf(stderr,
+                                               "%s -> %s %3d%%\n",
+                                               entp->fts_path, to.p_path,
+                                               cp_pct(wtotal, fs->st_size));
+                                               
+                               }
                                if (wcount >= (ssize_t)wresid || wcount <= 0)
                                        break;
                        }
@@ -205,12 +242,6 @@ copy_file(FTSENT *entp, int dne)
                }
        }
 
-#ifdef __APPLE__
-       if (pflag)
-               copyfile(entp->fts_path, to.p_path, 0, COPYFILE_XATTR | COPYFILE_ACL);
-       else
-               copyfile(entp->fts_path, to.p_path, 0, COPYFILE_XATTR);
-#endif
        /*
         * Don't remove the target even after an error.  The target might
         * not be a regular file, or its attributes might be important,
@@ -218,8 +249,25 @@ copy_file(FTSENT *entp, int dne)
         * to remove it if we created it and its length is 0.
         */
 
+#ifdef __APPLE__
+       /* do these before setfile in case copyfile changes mtime */
+       if (!Xflag && S_ISREG(fs->st_mode)) { /* skip devices, etc */
+               if (fcopyfile(from_fd, to_fd, NULL, COPYFILE_XATTR) < 0)
+                       warn("%s: could not copy extended attributes to %s", entp->fts_path, to.p_path);
+       }
        if (pflag && setfile(fs, to_fd))
                rval = 1;
+       if (pflag) {
+               /* If this ACL denies writeattr then setfile will fail... */
+               if (fcopyfile(from_fd, to_fd, NULL, COPYFILE_ACL) < 0)
+                       warn("%s: could not copy ACL to %s", entp->fts_path, to.p_path);
+       }
+#else  /* !__APPLE__ */
+       if (pflag && setfile(fs, to_fd))
+               rval = 1;
+       if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
+               rval = 1;
+#endif /* __APPLE__ */
        (void)close(from_fd);
        if (close(to_fd)) {
                warn("%s", to.p_path);
@@ -229,7 +277,7 @@ copy_file(FTSENT *entp, int dne)
 }
 
 int
-copy_link(FTSENT *p, int exists)
+copy_link(const FTSENT *p, int exists)
 {
        int len;
        char llink[PATH_MAX];
@@ -248,9 +296,12 @@ copy_link(FTSENT *p, int exists)
                return (1);
        }
 #ifdef __APPLE__
-           copyfile(p->fts_path, to.p_path, 0, COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC);
+       if (!Xflag)
+               if (copyfile(p->fts_path, to.p_path, NULL, COPYFILE_XATTR | COPYFILE_NOFOLLOW_SRC) <0)
+                       warn("%s: could not copy extended attributes to %s",
+                            p->fts_path, to.p_path);
 #endif
-       return (0);
+       return (pflag ? setfile(p->fts_statp, -1) : 0);
 }
 
 int
@@ -264,7 +315,7 @@ copy_fifo(struct stat *from_stat, int exists)
                warn("mkfifo: %s", to.p_path);
                return (1);
        }
-       return (pflag ? setfile(from_stat, 0) : 0);
+       return (pflag ? setfile(from_stat, -1) : 0);
 }
 
 int
@@ -278,7 +329,7 @@ copy_special(struct stat *from_stat, int exists)
                warn("mknod: %s", to.p_path);
                return (1);
        }
-       return (pflag ? setfile(from_stat, 0) : 0);
+       return (pflag ? setfile(from_stat, -1) : 0);
 }
 
 int
@@ -286,20 +337,26 @@ setfile(struct stat *fs, int fd)
 {
        static struct timeval tv[2];
        struct stat ts;
-       int rval;
-       int gotstat;
+       int rval, gotstat, islink, fdval;
 
        rval = 0;
+       fdval = fd != -1;
+       islink = !fdval && S_ISLNK(fs->st_mode);
        fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
                       S_IRWXU | S_IRWXG | S_IRWXO;
 
        TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
        TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
-       if (utimes(to.p_path, tv)) {
-               warn("utimes: %s", to.p_path);
+#ifdef __APPLE__
+       if (islink ? 0 : utimes(to.p_path, tv)) {
+#else
+       if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
+#endif /* __APPLE__ */
+               warn("%sutimes: %s", islink ? "l" : "", to.p_path);
                rval = 1;
        }
-       if (fd ? fstat(fd, &ts) : stat(to.p_path, &ts))
+       if (fdval ? fstat(fd, &ts) :
+           (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
                gotstat = 0;
        else {
                gotstat = 1;
@@ -313,37 +370,128 @@ setfile(struct stat *fs, int fd)
         * chown.  If chown fails, lose setuid/setgid bits.
         */
        if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
-               if (fd ? fchown(fd, fs->st_uid, fs->st_gid) :
-                   chown(to.p_path, fs->st_uid, fs->st_gid)) {
+               if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
+                   (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
+                   chown(to.p_path, fs->st_uid, fs->st_gid))) {
                        if (errno != EPERM) {
-                               warn("chown: %s", to.p_path);
+                               warn("%schown: %s", islink ? "l" : "", to.p_path);
                                rval = 1;
                        }
                        fs->st_mode &= ~(S_ISUID | S_ISGID);
                }
 
        if (!gotstat || fs->st_mode != ts.st_mode)
-               if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) {
-                       warn("chmod: %s", to.p_path);
+               if (fdval ? fchmod(fd, fs->st_mode) :
+                   (islink ? lchmod(to.p_path, fs->st_mode) :
+                   chmod(to.p_path, fs->st_mode))) {
+                       warn("%schmod: %s", islink ? "l" : "", to.p_path);
                        rval = 1;
                }
 
        if (!gotstat || fs->st_flags != ts.st_flags)
-               if (fd ?
-                   fchflags(fd, fs->st_flags) : chflags(to.p_path, fs->st_flags)) {
-                       warn("chflags: %s", to.p_path);
+               if (fdval ?
+                   fchflags(fd, fs->st_flags) :
+                   (islink ? lchflags(to.p_path, fs->st_flags) :
+                   chflags(to.p_path, fs->st_flags))) {
+                       warn("%schflags: %s", islink ? "l" : "", to.p_path);
                        rval = 1;
                }
 
        return (rval);
 }
 
+#ifndef __APPLE__
+int
+preserve_fd_acls(int source_fd, int dest_fd)
+{
+       struct acl *aclp;
+       acl_t acl;
+
+       if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
+           fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
+               return (0);
+       acl = acl_get_fd(source_fd);
+       if (acl == NULL) {
+               warn("failed to get acl entries while setting %s", to.p_path);
+               return (1);
+       }
+       aclp = &acl->ats_acl;
+       if (aclp->acl_cnt == 3)
+               return (0);
+       if (acl_set_fd(dest_fd, acl) < 0) {
+               warn("failed to set acl entries for %s", to.p_path);
+               return (1);
+       }
+       return (0);
+}
+
+int
+preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir)
+{
+       acl_t (*aclgetf)(const char *, acl_type_t);
+       int (*aclsetf)(const char *, acl_type_t, acl_t);
+       struct acl *aclp;
+       acl_t acl;
+
+       if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
+           pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
+               return (0);
+       /*
+        * If the file is a link we will not follow it
+        */
+       if (S_ISLNK(fs->st_mode)) {
+               aclgetf = acl_get_link_np;
+               aclsetf = acl_set_link_np;
+       } else {
+               aclgetf = acl_get_file;
+               aclsetf = acl_set_file;
+       }
+       /*
+        * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
+        * size ACL will be returned. So it is not safe to simply
+        * check the pointer to see if the default ACL is present.
+        */
+       acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
+       if (acl == NULL) {
+               warn("failed to get default acl entries on %s",
+                   source_dir);
+               return (1);
+       }
+       aclp = &acl->ats_acl;
+       if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
+           ACL_TYPE_DEFAULT, acl) < 0) {
+               warn("failed to set default acl entries on %s",
+                   dest_dir);
+               return (1);
+       }
+       acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
+       if (acl == NULL) {
+               warn("failed to get acl entries on %s", source_dir);
+               return (1);
+       }
+       aclp = &acl->ats_acl;
+       if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
+               warn("failed to set acl entries on %s", dest_dir);
+               return (1);
+       }
+       return (0);
+}
+#endif /* !__APPLE__ */
+
 void
 usage(void)
 {
 
+       if (COMPAT_MODE("bin/cp", "unix2003")) {
+       (void)fprintf(stderr, "%s\n%s\n",
+"usage: cp [-R [-H | -L | -P]] [-fi | -n] [-pvX] source_file target_file",
+"       cp [-R [-H | -L | -P]] [-fi | -n] [-pvX] source_file ... "
+"target_directory");
+       } else {
        (void)fprintf(stderr, "%s\n%s\n",
-"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] src target",
-"       cp [-R [-H | -L | -P]] [-f | -i | -n] [-pv] src1 ... srcN directory");
+"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-pvX] source_file target_file",
+"       cp [-R [-H | -L | -P]] [-f | -i | -n] [-pvX] source_file ... "
+"target_directory");
+       }
        exit(EX_USAGE);
 }
index 855a7943de252ae234594ba4d588490bbf1ea1f4..cb80edcd2d14fba03b5ddd5e6936b3be04aa796c 100644 (file)
--- a/dd/conv.c
+++ b/dd/conv.c
@@ -223,8 +223,10 @@ unblock(void)
 
        /* Translation and case conversion. */
        if ((t = ctab) != NULL)
-               for (cnt = in.dbrcnt, inp = in.dbp; cnt--;)
-                       *--inp = t[*inp];
+               for (cnt = in.dbrcnt, inp = in.dbp; cnt--;) {
+                       *inp = t[*inp];
+                       --inp;
+               }
        /*
         * Copy records (max cbsz size chunks) into the output buffer.  The
         * translation has to already be done or we might not recognize the
index 101cda15fd121e102e67ccb79f4a4c12d873fa7d..5156e6f207eafcf3a042b0fbfde66d09dcd55c1a 100644 (file)
@@ -21,7 +21,7 @@ MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
 MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /bin
-LIBS = 
+LIBS = -lutil
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
@@ -47,4 +47,4 @@ include $(MAKEFILEDIR)/$(MAKEFILE)
 
 -include Makefile.dependencies
 
-ALL_CFLAGS += -I/System/Library/Frameworks/System.framework/PrivateHeaders
+ALL_CFLAGS += -I/System/Library/Frameworks/System.framework/PrivateHeaders -D_DARWIN_USE_64_BIT_INODE
index 234330d62019a62b9d0d449c6dcb845adb10194b..a480e490c21676abdf1b142006c89a90d57c3a49 100644 (file)
@@ -1,4 +1,2 @@
 include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
 
-INSTALL_AS_GROUP    = operator
-INSTALL_PERMISSIONS = 2555
diff --git a/df/df.1 b/df/df.1
index 93a445dd26d138bf8f9ea79fd1f5fc2773ce6656..7dd8624cce9245d6e1a873f4fa87fbefe7acdfe8 100644 (file)
--- a/df/df.1
+++ b/df/df.1
@@ -39,7 +39,7 @@
 .Nm df
 .Nd display free disk space
 .Sh SYNOPSIS
-.Nm
+.Nm df
 .Oo
 .Fl b | h | H | k |
 .Fl m | P
@@ -49,7 +49,7 @@
 .Op Fl T Ar type
 .Op Ar file | filesystem ...
 .Sh LEGACY SYNOPSIS
-.Nm
+.Nm df
 .Oo
 .Fl b | h | H | k |
 .Fl m | P
@@ -60,7 +60,7 @@
 .Op Ar file | filesystem ...
 .Sh DESCRIPTION
 The
-.Nm
+.Nm df
 utility
 displays statistics about the amount of free disk space on the specified
 .Ar filesystem
@@ -80,13 +80,13 @@ The following options are available:
 Show all mount points, including those that were mounted with the MNT_IGNORE
 flag.
 .It Fl b
-Use 512-byte blocks rather than the default.  Note that
-this overrides the
+Use (the default) 512-byte blocks.
+This is only useful as a way to override an
 .Ev BLOCKSIZE
 specification from the environment.
 .It Fl g
-Use 1073741824-byte (1-Gbyte) blocks rather than the default.  Note that
-this overrides the
+Use 1073741824-byte (1-Gbyte) blocks rather than the default.
+Note that this overrides the
 .Ev BLOCKSIZE
 specification from the environment.
 .It Fl H
@@ -100,8 +100,8 @@ digits to three or less using base 2 for sizes.
 .It Fl i
 Include statistics on the number of free inodes.
 .It Fl k
-Use 1024-byte (1-Kbyte) blocks rather than the default.  Note that
-this overrides the
+Use 1024-byte (1-Kbyte) blocks, rather than the default.
+Note that this overrides the
 .Ev BLOCKSIZE
 specification from the environment.
 .It Fl l
@@ -117,20 +117,14 @@ This option should be used if it is possible that one or more
 filesystems are in a state such that they will not be able to provide
 statistics without a long delay.
 When this option is specified,
-.Nm
+.Nm df
 will not request new statistics from the filesystems, but will respond
 with the possibly stale statistics that were previously obtained.
 .It Fl P
-Use POSIX compliant output of 512-byte blocks rather than the default.
-Note that this overrides the
+Use (the default) 512-byte blocks.
+This is only useful as a way to override an
 .Ev BLOCKSIZE
 specification from the environment.
-.It Fl t
-In legacy mode (see
-.Xr compat 5
-for details) acts like
-.Fl T
-otherwise it is a no-op.
 .It Fl T
 Only print out statistics for filesystems of the specified types.
 More than one type may be specified in a comma separated list.
@@ -140,10 +134,10 @@ to specify the filesystem types for which action should
 .Em not
 be taken.
 For example, the
-.Nm
+.Nm df
 command:
 .Bd -literal -offset indent
-df -t nonfs,mfs
+df -T nonfs,mfs
 .Ed
 .Pp
 lists all filesystems except those of type
@@ -154,6 +148,13 @@ The
 .Xr lsvfs 1
 command can be used to find out the types of filesystems
 that are available on the system.
+.It Fl t
+If used with no arguments,
+this option is a no-op
+(Mac OS X already prints the total allocated-space figures).
+If used with an argument, it acts like
+.Fl T ,
+but this usage is deprecated and should not be relied upon.
 .El
 .Sh ENVIRONMENT
 .Bl -tag -width BLOCKSIZE
@@ -168,6 +169,29 @@ The
 and
 .Fl t
 flags are ignored if a file or filesystem is specified.
+.Sh LEGACY DESCRIPTION
+The "capacity" percentage is normally rounded up to the next higher integer.
+In legacy mode, it is rounded down to the next lower integer.
+.Pp
+When the
+.Fl P
+option and the
+.Fl k
+option are used together,
+sizes are reported in 1024-blocks.
+In legacy mode, when the
+.Fl P
+option and
+.Fl k
+option are used together,
+the last option specified dictates the reported block size.
+.Pp
+The
+.Fl t
+option is normally a no-op
+(Mac OS X already prints the total allocated-space figures).
+In legacy mode, it is equivalent to
+.Fl T .
 .Sh SEE ALSO
 .Xr lsvfs 1 ,
 .Xr quota 1 ,
@@ -175,12 +199,12 @@ flags are ignored if a file or filesystem is specified.
 .Xr getfsstat 2 ,
 .Xr statfs 2 ,
 .Xr getmntinfo 3 ,
-.Xr compat 5
+.Xr compat 5 ,
 .Xr fstab 5 ,
 .Xr mount 8 ,
 .Xr quot 8
 .Sh HISTORY
 A
-.Nm
+.Nm df
 command appeared in
 .At v1 .
diff --git a/df/df.c b/df/df.c
index dda262ccf9c791d635062bfe0400c117919c87cf..3438bca095571aa428b159a62d8711fadefd0b5d 100644 (file)
--- a/df/df.c
+++ b/df/df.c
@@ -53,8 +53,6 @@ static const char rcsid[] =
 
 #ifdef __APPLE__
 #define MNT_IGNORE 0
-#include <sys/types.h> 
-typedef int32_t ufs_daddr_t;
 #endif
 
 #include <sys/cdefs.h>
@@ -62,8 +60,6 @@ typedef int32_t ufs_daddr_t;
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <sys/sysctl.h>
-#include <ufs/ufs/ufsmount.h>
-#include <ufs/ffs/fs.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -74,6 +70,7 @@ typedef int32_t ufs_daddr_t;
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <libutil.h>
 
 #ifdef __APPLE__
 #include "get_compat.h"
@@ -125,18 +122,16 @@ int         checkvfsname(const char *, char **);
 char    *getmntpt(char *);
 int      longwidth(long long);
 char    *makenetvfslist(void);
-char   **makevfslist(char *);
-void     prthuman(struct statfs *, long);
-void     prthumanval(double);
+char   **makevfslist(const char *);
+void     prthuman(struct statfs *, uint64_t);
+void     prthumanval(int64_t);
 void     prtstat(struct statfs *, struct maxwidths *);
 long     regetmntinfo(struct statfs **, long, char **);
-int      ufs_df(char *, struct maxwidths *);
 unit_t   unit_adjust(double *);
 void     update_maxwidths(struct maxwidths *, struct statfs *);
 void     usage(void);
 
 int    aflag = 0, hflag, iflag, nflag;
-struct ufs_args mdev;
 
 static __inline int imax(int a, int b)
 {
@@ -150,19 +145,20 @@ main(int argc, char *argv[])
        struct statfs statfsbuf, *mntbuf;
        struct maxwidths maxwidths;
        const char *fstype;
-       char *mntpath, *mntpt, **vfslist;
+       char *mntpt, **vfslist;
        long mntsize;
        int ch, i, rv, tflag = 0, kludge_tflag = 0;
+       int kflag = 0;
        const char *options = "abgHhiklmnPt:T:";
        if (COMPAT_MODE("bin/df", "unix2003")) {
-               /* Unix2003 requires -t be "include total capicity". which df
-                 already does, but it conflits with the old -t so we need to
+               /* Unix2003 requires -t be "include total capacity". which df
+                 already does, but it conflicts with the old -t so we need to
                  *not* expect a string after -t (we provide -T in both cases
                  to cover the old use of -t) */
                options = "abgHhiklmnPtT:";
        }
 
-       fstype = "ufs";
+       fstype = "hfs";
 
        vfslist = NULL;
        while ((ch = getopt(argc, argv, options)) != -1)
@@ -173,7 +169,14 @@ main(int argc, char *argv[])
                case 'b':
                                /* FALLTHROUGH */
                case 'P':
-                       putenv("BLOCKSIZE=512");
+                       if (COMPAT_MODE("bin/df", "unix2003")) {
+                               if (!kflag) {
+                                       /* -k overrides -P */
+                                       putenv("BLOCKSIZE=512");
+                               }
+                       } else {
+                               putenv("BLOCKSIZE=512");
+                       }
                        hflag = 0;
                        break;
                case 'g':
@@ -192,7 +195,12 @@ main(int argc, char *argv[])
                        iflag = 1;
                        break;
                case 'k':
-                       putenv("BLOCKSIZE=1k");
+                       if (COMPAT_MODE("bin/df", "unix2003")) {
+                               putenv("BLOCKSIZE=1024");
+                       } else {
+                               putenv("BLOCKSIZE=1k");
+                       }
+                       kflag = 1;
                        hflag = 0;
                        break;
                case 'l':
@@ -269,39 +277,9 @@ main(int argc, char *argv[])
                                continue;
                        }
                } else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
-                       if ((mntpt = getmntpt(*argv)) == 0) {
-                               mdev.fspec = *argv;
-                               mntpath = strdup("/tmp/df.XXXXXX");
-                               if (mntpath == NULL) {
-                                       warn("strdup failed");
-                                       rv = 1;
-                                       continue;
-                               }
-                               mntpt = mkdtemp(mntpath);
-                               if (mntpt == NULL) {
-                                       warn("mkdtemp(\"%s\") failed", mntpath);
-                                       rv = 1;
-                                       free(mntpath);
-                                       continue;
-                               }
-                               if (mount(fstype, mntpt, MNT_RDONLY,
-                                   &mdev) != 0) {
-                                       rv = ufs_df(*argv, &maxwidths) || rv;
-                                       (void)rmdir(mntpt);
-                                       free(mntpath);
-                                       continue;
-                               } else if (statfs(mntpt, &statfsbuf) == 0) {
-                                       statfsbuf.f_mntonname[0] = '\0';
-                                       prtstat(&statfsbuf, &maxwidths);
-                               } else {
-                                       warn("%s", *argv);
-                                       rv = 1;
-                               }
-                               (void)unmount(mntpt, 0);
-                               (void)rmdir(mntpt);
-                               free(mntpath);
-                               continue;
-                       }
+                       warnx("%s: Raw devices not supported", *argv);
+                       rv = 1;
+                       continue;
                } else
                        mntpt = *argv;
                /*
@@ -322,8 +300,9 @@ main(int argc, char *argv[])
                        rv++;
                        continue;
                }
+
                if (argc == 1) {
-                       bzero(&maxwidths, sizeof(maxwidths));
+                       bzero(&maxwidths, sizeof(maxwidths));
                        update_maxwidths(&maxwidths, &statfsbuf);
                }
                prtstat(&statfsbuf, &maxwidths);
@@ -400,36 +379,56 @@ unit_adjust(double *val)
 }
 
 void
-prthuman(struct statfs *sfsp, long used)
+prthuman(struct statfs *sfsp, uint64_t used)
 {
-
-       prthumanval((double)sfsp->f_blocks * (double)sfsp->f_bsize);
-       prthumanval((double)used * (double)sfsp->f_bsize);
-       prthumanval((double)sfsp->f_bavail * (double)sfsp->f_bsize);
+       int64_t value;
+
+       value = sfsp->f_blocks;
+       value *= sfsp->f_bsize;
+        prthumanval(value);
+       value = used;
+       value *= sfsp->f_bsize;
+        prthumanval(value);
+       value = sfsp->f_bavail;
+       value *= sfsp->f_bsize;
+       prthumanval(value);
 }
 
 void
-prthumanval(double bytes)
+prthumanval(int64_t bytes)
 {
+        char buf[6];
+        int flags;
 
-       unit_t unit;
-       unit = unit_adjust(&bytes);
+        flags = HN_B | HN_NOSPACE | HN_DECIMAL;
+        if (hflag == UNITS_SI)
+                flags |= HN_DIVISOR_1000;
+
+        humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
+                       bytes, "", HN_AUTOSCALE, flags);
 
-       if (bytes == 0)
-               (void)printf("     0B");
-       else if (bytes > 10)
-               (void)printf(" %5.0f%c", bytes, "BKMGTPE"[unit]);
+       if (hflag == UNITS_SI)
+               (void)printf(" %6s", buf);
        else
-               (void)printf(" %5.1f%c", bytes, "BKMGTPE"[unit]);
+               (void)printf("%6si", buf);
+           
 }
 
 /*
  * Convert statfs returned filesystem size into BLOCKSIZE units.
  * Attempts to avoid overflow for large filesystems.
  */
-#define fsbtoblk(num, fsbs, bs) \
-       (((fsbs) != 0 && (fsbs) < (bs)) ? \
-               ((off_t)((unsigned)num)) / ((unsigned)(bs) / ((off_t)((unsigned)fsbs))) : ((off_t)((unsigned)num)) * ((off_t)((unsigned)fsbs)) / (bs))
+static intmax_t fsbtoblk(int64_t num, uint64_t fsbs, u_long bs, char *fs) 
+{
+       if (num < 0) {
+               warnx("negative filesystem block count/size from fs %s", fs);
+               return 0;
+       } else if ((fsbs != 0) && (fsbs < bs)) {
+               return (num / (intmax_t) (bs / fsbs));
+       } else {
+               return (num * (intmax_t) (fsbs / bs));
+       }
+}
 
 /*
  * Print out status about a filesystem.
@@ -440,7 +439,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
        static long blocksize;
        static int headerlen, timesthrough;
        static const char *header;
-       unsigned long used, availblks, inodes;
+       uint64_t used, availblks, inodes;
+       char * avail_str;
 
        if (++timesthrough == 1) {
                mwp->mntfrom = imax(mwp->mntfrom, strlen("Filesystem"));
@@ -452,11 +452,16 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
                        mwp->total = imax(mwp->total, headerlen);
                }
                mwp->used = imax(mwp->used, strlen("Used"));
-               mwp->avail = imax(mwp->avail, strlen("Avail"));
+               if (COMPAT_MODE("bin/df", "unix2003") && !hflag) {
+                       avail_str = "Available";
+               } else {
+                       avail_str = "Avail";
+               }
+               mwp->avail = imax(mwp->avail, strlen(avail_str));
 
-               (void)printf("%-*s %-*s %*s %*s Capacity", mwp->mntfrom,
+               (void)printf("%-*s %*s %*s %*s Capacity", mwp->mntfrom,
                    "Filesystem", mwp->total, header, mwp->used, "Used",
-                   mwp->avail, "Avail");
+                   mwp->avail, avail_str);
                if (iflag) {
                        mwp->iused = imax(mwp->iused, strlen("  iused"));
                        mwp->ifree = imax(mwp->ifree, strlen("ifree"));
@@ -467,23 +472,38 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
        }
 
        (void)printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname);
-       used = (off_t)((unsigned)sfsp->f_blocks) - (off_t)((unsigned)sfsp->f_bfree);
+       if (sfsp->f_blocks > sfsp->f_bfree)
+               used = sfsp->f_blocks - sfsp->f_bfree;
+       else
+               used = 0;
        availblks = sfsp->f_bavail + used;
        if (hflag) {
                prthuman(sfsp, used);
        } else {
                (void)printf(" %*lld %*lld %*lld", mwp->total,
-                   fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
-                   mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize),
-                   mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize,
-                   blocksize));
+                            fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+                            mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+                            mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize, sfsp->f_mntonname));
+       }
+       if (COMPAT_MODE("bin/df", "unix2003")) {
+               /* Standard says percentage must be rounded UP to next
+                  integer value, not truncated */
+               double value;
+               if (availblks == 0)
+                       value = 100.0;
+               else {
+                       value = (double)used / (double)availblks * 100.0;
+                       if ((value-(int)value) > 0.0) value = value + 1.0;
+               }
+               (void)printf(" %5.0f%%", trunc(value));
+       } else {
+               (void)printf(" %5.0f%%",
+                   availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
        }
-       (void)printf(" %5.0f%%",
-           availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
        if (iflag) {
-               inodes = (unsigned)sfsp->f_files;
+               inodes = sfsp->f_files;
                used = inodes - sfsp->f_ffree;
-               (void)printf(" %*lu %*lu %4.0f%% ", mwp->iused, used,
+               (void)printf(" %*llu %*lu %4.0f%% ", mwp->iused, used,
                    mwp->ifree, (unsigned long)sfsp->f_ffree, inodes == 0 ? 100.0 :
                    (double)used / (double)inodes * 100.0);
        } else
@@ -506,13 +526,13 @@ update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp)
 
        mwp->mntfrom = imax(mwp->mntfrom, strlen(sfsp->f_mntfromname));
        mwp->total = imax(mwp->total, longwidth(fsbtoblk(sfsp->f_blocks,
-           sfsp->f_bsize, blocksize)));
-       mwp->used = imax(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
-           sfsp->f_bfree, sfsp->f_bsize, blocksize)));
+                                                        sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+       if (sfsp->f_blocks >= sfsp->f_bfree)
+               mwp->used = imax(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
+                                                              sfsp->f_bfree, sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
        mwp->avail = imax(mwp->avail, longwidth(fsbtoblk(sfsp->f_bavail,
-           sfsp->f_bsize, blocksize)));
-       mwp->iused = imax(mwp->iused, longwidth((unsigned)(sfsp->f_files -
-           sfsp->f_ffree)));
+                                                        sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+       mwp->iused = imax(mwp->iused, longwidth((unsigned)(sfsp->f_files - sfsp->f_ffree)));
        mwp->ifree = imax(mwp->ifree, longwidth((unsigned)(sfsp->f_ffree)));
 }
 
@@ -536,84 +556,13 @@ longwidth(long long val)
        return (len);
 }
 
-/*
- * This code constitutes the pre-system call Berkeley df code for extracting
- * information from filesystem superblocks.
- */
-
-union {
-       struct fs iu_fs;
-       char dummy[SBSIZE];
-} sb;
-#define sblock sb.iu_fs
-
-int    rfd;
-
-int
-ufs_df(char *file, struct maxwidths *mwp)
-{
-       struct statfs statfsbuf;
-       struct statfs *sfsp;
-       const char *mntpt;
-       static int synced;
-
-       if (synced++ == 0)
-               sync();
-
-       if ((rfd = open(file, O_RDONLY)) < 0) {
-               warn("%s", file);
-               return (1);
-       }
-       if (bread((off_t)SBOFF, &sblock, SBSIZE) == 0) {
-               (void)close(rfd);
-               return (1);
-       }
-       sfsp = &statfsbuf;
-       sfsp->f_type = 1;
-       strcpy(sfsp->f_fstypename, "ufs");
-       sfsp->f_flags = 0;
-       sfsp->f_bsize = sblock.fs_fsize;
-       sfsp->f_iosize = sblock.fs_bsize;
-       sfsp->f_blocks = sblock.fs_dsize;
-       sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
-               sblock.fs_cstotal.cs_nffree;
-       sfsp->f_bavail = freespace(&sblock, sblock.fs_minfree);
-       sfsp->f_files =  sblock.fs_ncg * sblock.fs_ipg;
-       sfsp->f_ffree = sblock.fs_cstotal.cs_nifree;
-       sfsp->f_fsid.val[0] = 0;
-       sfsp->f_fsid.val[1] = 0;
-       if ((mntpt = getmntpt(file)) == 0)
-               mntpt = "";
-       memmove(&sfsp->f_mntonname[0], mntpt, (size_t)MNAMELEN);
-       memmove(&sfsp->f_mntfromname[0], file, (size_t)MNAMELEN);
-       prtstat(sfsp, mwp);
-       (void)close(rfd);
-       return (0);
-}
-
-int
-bread(off_t off, void *buf, int cnt)
-{
-       ssize_t nr;
-
-       (void)lseek(rfd, off, SEEK_SET);
-       if ((nr = read(rfd, buf, (size_t)cnt)) != (ssize_t)cnt) {
-               /* Probably a dismounted disk if errno == EIO. */
-               if (errno != EIO)
-                       (void)fprintf(stderr, "\ndf: %lld: %s\n",
-                           (long long)off, strerror(nr > 0 ? EIO : errno));
-               return (0);
-       }
-       return (1);
-}
-
 void
 usage(void)
 {
 
        char *t_flag = COMPAT_MODE("bin/df", "unix2003") ? "[-t]" : "[-t type]";
        (void)fprintf(stderr,
-           "usage: df [-b | -H | -h | -k | -m | -P] [-ailn] [-T type] %s [file | filesystem ...]\n", t_flag);
+           "usage: df [-b | -H | -h | -k | -m | -P] [-ailn] [-T type] %s [filesystem ...]\n", t_flag);
        exit(EX_USAGE);
 }
 
index c53ffe7e4068168b5d39ba3811460740556b1b93..91e8577eefbaedebda8ef7c73de2eda148ef6046 100644 (file)
@@ -67,10 +67,11 @@ checkvfsname(vfsname, vfslist)
 
 const char **
 makevfslist(fslist)
-       char *fslist;
+       const char *fslist;
 {
        const char **av;
        int i;
+       const char *cnextcp;
        char *nextcp;
 
        if (fslist == NULL)
@@ -79,14 +80,14 @@ makevfslist(fslist)
                fslist += 2;
                skipvfs = 1;
        }
-       for (i = 0, nextcp = fslist; *nextcp; nextcp++)
-               if (*nextcp == ',')
+       for (i = 0, cnextcp = fslist; *cnextcp; cnextcp++)
+               if (*cnextcp == ',')
                        i++;
        if ((av = malloc((size_t)(i + 2) * sizeof(char *))) == NULL) {
                warnx("malloc failed");
                return (NULL);
        }
-       nextcp = fslist;
+       nextcp = strdup(fslist);
        i = 0;
        av[i++] = nextcp;
        while ((nextcp = strchr(nextcp, ',')) != NULL) {
index d4a2b7577e50091969bc1985cbe1575970b9abfd..c6c7ead6eb97cdd0d30887d54ba0f433e1d0d543 100644 (file)
@@ -16,6 +16,7 @@ CFILES = du.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble du.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
@@ -28,7 +29,7 @@ PROF_LIBS = $(LIBS)
 
 
 
-NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/developer_cmds/Build
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/file_cmds/Build
 
 NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
 WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
diff --git a/du/du.1 b/du/du.1
index 39fe7bdef0a8f8a6aa85562e0a81fe6abb707bce..51427a87f0d128dbbd97964ceed98d98b6f6542b 100644 (file)
--- a/du/du.1
+++ b/du/du.1
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)du.1        8.2 (Berkeley) 4/1/94
-.\" $FreeBSD: src/usr.bin/du/du.1,v 1.25 2002/12/12 17:26:00 ru Exp $
+.\" $FreeBSD: src/usr.bin/du/du.1,v 1.30 2005/05/21 09:55:05 ru Exp $
 .\"
-.Dd April 1, 1994
+.Dd June 2, 2004
 .Dt DU 1
 .Os
 .Sh NAME
 .Nm du
 .Nd display disk usage statistics
 .Sh SYNOPSIS
-.Nm
+.Nm du
 .Op Fl H | L | P
-.Op Fl I Ar mask
 .Op Fl a | s | d Ar depth
 .Op Fl c
-.Op Fl h | k
+.Op Fl h | k | m
 .Op Fl x
+.Op Fl I Ar mask
 .Op Ar
 .Sh DESCRIPTION
 The
-.Nm
+.Nm du
 utility displays the file system block usage for each file argument
 and for each directory in the file hierarchy rooted in each directory
 argument.
 If no file is specified, the block usage of the hierarchy rooted in
 the current directory is displayed.
-If the
-.Fl k
-flag is specified, the number of 1024-byte
-blocks used by the file is displayed, otherwise
-.Xr getbsize 3
-is used to determine the preferred block size.
-Partial numbers of blocks are rounded up.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.It Fl a
+Display an entry for each file in a file hierarchy.
+.It Fl c
+Display a grand total.
+.It Fl d Ar depth
+Display an entry for all files and directories
+.Ar depth
+directories deep.
 .It Fl H
 Symbolic links on the command line are followed, symbolic links in file
 hierarchies are not followed.
-.It Fl L
-Symbolic links on the command line and in file hierarchies are followed.
+.It Fl h
+"Human-readable" output.
+Use unit suffixes: Byte, Kilobyte, Megabyte,
+Gigabyte, Terabyte and Petabyte.
 .It Fl I Ar mask
 Ignore files and directories matching the specified
 .Ar mask .
+.It Fl k
+Display block counts in 1024-byte (1-Kbyte) blocks.
+.It Fl L
+Symbolic links on the command line and in file hierarchies are followed.
+.It Fl m
+Display block counts in 1048576-byte (1-Mbyte) blocks.
 .It Fl P
 No symbolic links are followed.
 This is the default.
-.It Fl a
-Display an entry for each file in a file hierarchy.
-.It Fl h
-"Human-readable" output.  Use unit suffixes: Byte, Kilobyte, Megabyte,
-Gigabyte, Terabyte and Petabyte
 .It Fl r
 Generate messages about directories that cannot be read, files
-that cannot be opened, and so on.  This is the default case.
+that cannot be opened, and so on.
+This is the default case.
 This option exists solely for conformance with
 .St -xpg4 .
 .It Fl s
 Display an entry for each specified file.
 (Equivalent to
 .Fl d Li 0 )
-.It Fl d Ar depth
-Display an entry for all files and directories
-.Ar depth
-directories deep.
-.It Fl c
-Display a grand total.
-.It Fl k
-Display block counts in 1024-byte (1-Kbyte) blocks.
 .It Fl x
 File system mount points are not traversed.
 .El
 .Pp
 The
-.Nm
+.Nm du
 utility counts the storage used by symbolic links and not the files they
 reference unless the
 .Fl H
@@ -116,10 +113,16 @@ or
 .Fl L
 options are specified, storage used by any symbolic links which are
 followed is not counted or displayed.
+If more than one of the
+.Fl H ,
+.Fl L ,
+and
+.Fl P
+options is specified, the last one given is used.
 .Pp
 Files having multiple hard links are counted (and displayed) a single
 time per
-.Nm
+.Nm du
 execution.
 .Sh ENVIRONMENT
 .Bl -tag -width BLOCKSIZE
@@ -136,13 +139,25 @@ is not set, and the
 .Fl k
 option is not specified, the block counts will be displayed in 512-byte blocks.
 .El
+.Sh LEGACY DESCRIPTION
+In legacy mode, only one of the
+.Fl H ,
+.Fl L ,
+or
+.Fl P
+options may be specified.
+.Pp
+The command will detect and report a SYMLOOP error
+(loop involving symbolic links).
+In legacy mode, this is not the case.
 .Sh SEE ALSO
 .Xr df 1 ,
 .Xr fts 3 ,
+.Xr compat 5 ,
 .Xr symlink 7 ,
 .Xr quot 8
 .Sh HISTORY
 A
-.Nm
+.Nm du
 command appeared in
 .At v1 .
diff --git a/du/du.c b/du/du.c
index 8b1c46b045a5f18895f62725662ce07240583d25..4a426eef05075b0cc9590b00f93dac6d2b88e64d 100644 (file)
--- a/du/du.c
+++ b/du/du.c
@@ -46,8 +46,9 @@ static const char sccsid[] = "@(#)du.c        8.5 (Berkeley) 5/4/95";
 #endif
 #endif /* not lint */
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/usr.bin/du/du.c,v 1.28 2002/12/30 18:13:07 mike Exp $");
+__FBSDID("$FreeBSD: src/usr.bin/du/du.c,v 1.38 2005/04/09 14:31:40 stefanf Exp $");
 
+#include <sys/mount.h>
 #include <sys/param.h>
 #include <sys/queue.h>
 #include <sys/stat.h>
@@ -56,19 +57,19 @@ __RCSID("$FreeBSD: src/usr.bin/du/du.c,v 1.28 2002/12/30 18:13:07 mike Exp $");
 #include <errno.h>
 #include <fnmatch.h>
 #include <fts.h>
+#include <locale.h>
 #include <math.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
-#include <sys/param.h>
-#include <sys/mount.h>
 
 #ifdef __APPLE__
-#include "get_compat.h"
+#include <get_compat.h>
 #else
-#define COMPAT_MODE(func, mode) 1
+#define COMPAT_MODE(func, mode) (1)
 #endif
 
 #define        KILO_SZ(n) (n)
@@ -105,7 +106,7 @@ struct ignentry {
        SLIST_ENTRY(ignentry)   next;
 };
 
-int            linkchk(FTSENT *);
+static int     linkchk(FTSENT *);
 static void    usage(void);
 void           prthumanval(double);
 unit_t         unit_adjust(double *);
@@ -118,6 +119,7 @@ main(int argc, char *argv[])
 {
        FTS             *fts;
        FTSENT          *p;
+       off_t           savednumber = 0;
        long            blocksize;
        int             ftsoptions;
        int             listall;
@@ -125,38 +127,32 @@ main(int argc, char *argv[])
        int             Hflag, Lflag, Pflag, aflag, sflag, dflag, cflag, hflag, ch, notused, rval;
        char            **save;
        static char     dot[] = ".";
-       off_t           *ftsnum, *ftsparnum, savednumber = 0;
+       off_t           *ftsnum, *ftsparnum;
+
+       setlocale(LC_ALL, "");
 
        Hflag = Lflag = Pflag = aflag = sflag = dflag = cflag = hflag = 0;
-       
+
        save = argv;
        ftsoptions = 0;
        depth = INT_MAX;
        SLIST_INIT(&ignores);
-       
-       while ((ch = getopt(argc, argv, "HI:LPasd:chkrx")) != -1)
+
+       while ((ch = getopt(argc, argv, "HI:LPasd:chkmrx")) != -1)
                switch (ch) {
                        case 'H':
+                               Lflag = Pflag = 0;
                                Hflag = 1;
-                               Pflag = Lflag = 0;
                                break;
                        case 'I':
                                ignoreadd(optarg);
                                break;
                        case 'L':
-                               if (Pflag && COMPAT_MODE("bin/du", "legacy")) {
-                                       usage();
-                               } else {
-                                       Hflag = Pflag = 0;
-                               }
+                               Hflag = Pflag = 0;
                                Lflag = 1;
                                break;
                        case 'P':
-                               if (Lflag && COMPAT_MODE("bin/du", "legacy")) {
-                                       usage();
-                               } else {
-                                       Hflag = Lflag = 0;
-                               }
+                               Hflag = Lflag = 0;
                                Pflag = 1;
                                break;
                        case 'a':
@@ -183,8 +179,12 @@ main(int argc, char *argv[])
                                valp = vals_base2;
                                break;
                        case 'k':
-                               if (!hflag)
-                                       putenv("BLOCKSIZE=1024");
+                               hflag = 0;
+                               putenv("BLOCKSIZE=1024");
+                               break;
+                       case 'm':
+                               hflag = 0;
+                               putenv("BLOCKSIZE=1048576");
                                break;
                        case 'r':                /* Compatibility. */
                                break;
@@ -249,7 +249,7 @@ main(int argc, char *argv[])
        blocksize /= 512;
 
        rval = 0;
-       
+
        if ((fts = fts_open(argv, ftsoptions, NULL)) == NULL)
                err(1, "fts_open");
 
@@ -270,14 +270,14 @@ main(int argc, char *argv[])
                                } else {
                                    ftsparnum[0] += ftsnum[0] += howmany(p->fts_statp->st_size, 512LL);
                                }
-                               
+
                                if (p->fts_level <= depth) {
                                        if (hflag) {
                                                (void) prthumanval(howmany(*ftsnum, blocksize));
                                                (void) printf("\t%s\n", p->fts_path);
                                        } else {
-                                       (void) printf("%lld\t%s\n",
-                                           howmany(*ftsnum, blocksize),
+                                       (void) printf("%jd\t%s\n",
+                                           (intmax_t)howmany(*ftsnum, blocksize),
                                            p->fts_path);
                                        }
                                }
@@ -307,7 +307,7 @@ main(int argc, char *argv[])
 
                                if (p->fts_statp->st_nlink > 1 && linkchk(p))
                                        break;
-                               
+
                                if (listall || p->fts_level == 0) {
                                        if (hflag) {
                                            if (p->fts_statp->st_size < TWO_TB) {
@@ -320,12 +320,12 @@ main(int argc, char *argv[])
                                                (void) printf("\t%s\n", p->fts_path);
                                        } else {
                                            if (p->fts_statp->st_size < TWO_TB) {
-                                               (void) printf("%qd\t%s\n",
-                                                       (long long)howmany(p->fts_statp->st_blocks, blocksize),
+                                               (void) printf("%jd\t%s\n",
+                                                       (intmax_t)howmany(p->fts_statp->st_blocks, blocksize),
                                                        p->fts_path);
                                            } else {
-                                               (void) printf("%qd\t%s\n",
-                                                       (long long)howmany(howmany(p->fts_statp->st_size, 512LL), blocksize),
+                                               (void) printf("%jd\t%s\n",
+                                                       (intmax_t)howmany(howmany(p->fts_statp->st_size, 512LL), blocksize),
                                                        p->fts_path);
                                            }
                                        }
@@ -349,7 +349,7 @@ main(int argc, char *argv[])
                        (void) prthumanval(howmany(savednumber, blocksize));
                        (void) printf("\ttotal\n");
                } else {
-                       (void) printf("%lld\ttotal\n", howmany(savednumber, blocksize));
+                       (void) printf("%jd\ttotal\n", (intmax_t)howmany(savednumber, blocksize));
                }
        }
 
@@ -357,36 +357,136 @@ main(int argc, char *argv[])
        exit(rval);
 }
 
+static int
+linkchk(FTSENT *p)
+{
+       struct links_entry {
+               struct links_entry *next;
+               struct links_entry *previous;
+               int      links;
+               dev_t    dev;
+               ino_t    ino;
+       };
+       static const size_t links_hash_initial_size = 8192;
+       static struct links_entry **buckets;
+       static struct links_entry *free_list;
+       static size_t number_buckets;
+       static unsigned long number_entries;
+       static char stop_allocating;
+       struct links_entry *le, **new_buckets;
+       struct stat *st;
+       size_t i, new_size;
+       int hash;
+
+       st = p->fts_statp;
+
+       /* If necessary, initialize the hash table. */
+       if (buckets == NULL) {
+               number_buckets = links_hash_initial_size;
+               buckets = malloc(number_buckets * sizeof(buckets[0]));
+               if (buckets == NULL)
+                       errx(1, "No memory for hardlink detection");
+               for (i = 0; i < number_buckets; i++)
+                       buckets[i] = NULL;
+       }
 
-typedef struct _ID {
-       dev_t   dev;
-       ino_t   inode;
-} ID;
+       /* If the hash table is getting too full, enlarge it. */
+       if (number_entries > number_buckets * 10 && !stop_allocating) {
+               new_size = number_buckets * 2;
+               new_buckets = malloc(new_size * sizeof(struct links_entry *));
+
+               /* Try releasing the free list to see if that helps. */
+               if (new_buckets == NULL && free_list != NULL) {
+                       while (free_list != NULL) {
+                               le = free_list;
+                               free_list = le->next;
+                               free(le);
+                       }
+                       new_buckets = malloc(new_size * sizeof(new_buckets[0]));
+               }
 
+               if (new_buckets == NULL) {
+                       stop_allocating = 1;
+                       warnx("No more memory for tracking hard links");
+               } else {
+                       memset(new_buckets, 0,
+                           new_size * sizeof(struct links_entry *));
+                       for (i = 0; i < number_buckets; i++) {
+                               while (buckets[i] != NULL) {
+                                       /* Remove entry from old bucket. */
+                                       le = buckets[i];
+                                       buckets[i] = le->next;
+
+                                       /* Add entry to new bucket. */
+                                       hash = (le->dev ^ le->ino) % new_size;
+
+                                       if (new_buckets[hash] != NULL)
+                                               new_buckets[hash]->previous =
+                                                   le;
+                                       le->next = new_buckets[hash];
+                                       le->previous = NULL;
+                                       new_buckets[hash] = le;
+                               }
+                       }
+                       free(buckets);
+                       buckets = new_buckets;
+                       number_buckets = new_size;
+               }
+       }
 
-int
-linkchk(FTSENT *p)
-{
-       static ID *files;
-       static int maxfiles, nfiles;
-       ID *fp, *start;
-       ino_t ino;
-       dev_t dev;
-
-       ino = p->fts_statp->st_ino;
-       dev = p->fts_statp->st_dev;
-       if ((start = files) != NULL)
-               for (fp = start + nfiles - 1; fp >= start; --fp)
-                       if (ino == fp->inode && dev == fp->dev) {
-                               return (1);
+       /* Try to locate this entry in the hash table. */
+       hash = ( st->st_dev ^ st->st_ino ) % number_buckets;
+       for (le = buckets[hash]; le != NULL; le = le->next) {
+               if (le->dev == st->st_dev && le->ino == st->st_ino) {
+                       /*
+                        * Save memory by releasing an entry when we've seen
+                        * all of it's links.
+                        */
+                       if (--le->links <= 0) {
+                               if (le->previous != NULL)
+                                       le->previous->next = le->next;
+                               if (le->next != NULL)
+                                       le->next->previous = le->previous;
+                               if (buckets[hash] == le)
+                                       buckets[hash] = le->next;
+                               number_entries--;
+                               /* Recycle this node through the free list */
+                               if (stop_allocating) {
+                                       free(le);
+                               } else {
+                                       le->next = free_list;
+                                       free_list = le;
+                               }
                        }
+                       return (1);
+               }
+       }
 
-       if (nfiles == maxfiles && (files = realloc((char *)files,
-           (u_int)(sizeof(ID) * (maxfiles += 128)))) == NULL)
-               errx(1, "can't allocate memory");
-       files[nfiles].inode = ino;
-       files[nfiles].dev = dev;
-       ++nfiles;
+       if (stop_allocating)
+               return (0);
+
+       /* Add this entry to the links cache. */
+       if (free_list != NULL) {
+               /* Pull a node from the free list if we can. */
+               le = free_list;
+               free_list = le->next;
+       } else
+               /* Malloc one if we have to. */
+               le = malloc(sizeof(struct links_entry));
+       if (le == NULL) {
+               stop_allocating = 1;
+               warnx("No more memory for tracking hard links");
+               return (0);
+       }
+       le->dev = st->st_dev;
+       le->ino = st->st_ino;
+       le->links = st->st_nlink - 1;
+       number_entries++;
+       le->next = buckets[hash];
+       le->previous = NULL;
+       if (buckets[hash] != NULL)
+               buckets[hash]->previous = le;
+       buckets[hash] = le;
        return (0);
 }
 
@@ -437,7 +537,7 @@ static void
 usage(void)
 {
        (void)fprintf(stderr,
-               "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k] [-x] [-I mask] [file ...]\n");
+               "usage: du [-H | -L | -P] [-a | -s | -d depth] [-c] [-h | -k | -m] [-x] [-I mask] [file ...]\n");
        exit(EX_USAGE);
 }
 
@@ -473,6 +573,7 @@ ignorep(FTSENT *ent)
 {
        struct ignentry *ign;
 
+#ifdef __APPLE__
        if (S_ISDIR(ent->fts_statp->st_mode) && !strcmp("fd", ent->fts_name)) {
                struct statfs sfsb;
                int rc = statfs(ent->fts_accpath, &sfsb);
@@ -483,6 +584,7 @@ ignorep(FTSENT *ent)
                        return 1;
                }
        }
+#endif /* __APPLE__ */
        SLIST_FOREACH(ign, &ignores, next)
                if (fnmatch(ign->mask, ent->fts_name, 0) != FNM_NOMATCH)
                        return 1;
index b3e62413d631f4dc8572d01a1893b307b8523d93..76f36978cfc71b1c5e157a8fa5e02ddf6609e6dd 100644 (file)
@@ -39,7 +39,7 @@
 .Nm install
 .Nd install binaries
 .Sh SYNOPSIS
-.Nm
+.Nm install
 .Op Fl bCcMpSsv
 .Op Fl B Ar suffix
 .Op Fl f Ar flags
@@ -47,7 +47,7 @@
 .Op Fl m Ar mode
 .Op Fl o Ar owner
 .Ar file1 file2
-.Nm
+.Nm install
 .Op Fl bCcMpSsv
 .Op Fl B Ar suffix
 .Op Fl f Ar flags
@@ -55,7 +55,7 @@
 .Op Fl m Ar mode
 .Op Fl o Ar owner
 .Ar file1 ... fileN directory
-.Nm
+.Nm install
 .Fl d
 .Op Fl v
 .Op Fl g Ar group
@@ -84,6 +84,14 @@ option's argument.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.\" ==========
+.It Fl B Ar suffix
+Use
+.Ar suffix
+as the backup suffix if
+.Fl b
+is given.
+.\" ==========
 .It Fl b
 Back up any existing files before overwriting them by renaming
 them to
@@ -91,44 +99,47 @@ them to
 See
 .Fl B
 for specifying a different backup suffix.
-.It Fl B Ar suffix
-Use
-.Ar suffix
-as the backup suffix if
-.Fl b
-is given.
+.\" ==========
 .It Fl C
 Copy the file.
 If the target file already exists and the files are the same,
 then don't change the modification time of the target.
+.\" ==========
 .It Fl c
 Copy the file.
 This is actually the default.
 The
 .Fl c
 option is only included for backwards compatibility.
+.\" ==========
 .It Fl d
 Create directories.
 Missing parent directories are created as required.
+.\" ==========
 .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.
 A numeric GID is allowed.
+.\" ==========
 .It Fl M
 Disable all use of
 .Xr mmap 2 .
+.\" ==========
 .It Fl m
 Specify an alternate mode.
 The default mode is set to rwxr-xr-x (0755).
 The specified mode may be either an octal or symbolic value; see
 .Xr chmod 1
 for a description of possible mode values.
+.\" ==========
 .It Fl o
 Specify an owner.
 A numeric UID is allowed.
+.\" ==========
 .It Fl p
 Preserve the modification time.
 Copy the file, as if the
@@ -136,10 +147,11 @@ Copy the file, as if the
 (compare and copy) option is specified,
 except if the target file doesn't already exist or is different,
 then preserve the modification time of the file.
+.\" ==========
 .It Fl S
 Safe copy.
 Normally,
-.Nm
+.Nm install
 unlinks an existing target before installing the new file.
 With the
 .Fl S
@@ -147,30 +159,32 @@ flag a temporary file is used and then renamed to be
 the target.
 The reason this is safer is that if the copy or
 rename fails, the existing target is left untouched.
+.\" ==========
 .It Fl s
-.Nm
+.Nm install
 exec's the command
 .Xr strip 1
 to strip binaries so that
-.Nm
+.Nm install
 can be portable over a large
 number of systems and binary types.
+.\" ==========
 .It Fl v
 Causes
-.Nm
+.Nm install
 to show when
 .Fl C
 actually installs something.
 .El
 .Pp
 By default,
-.Nm
+.Nm install
 preserves all file flags, with the exception of the
 .Dq nodump
 flag.
 .Pp
 The
-.Nm
+.Nm install
 utility attempts to prevent moving a file onto itself.
 .Pp
 Installing
@@ -178,7 +192,7 @@ Installing
 creates an empty file.
 .Sh DIAGNOSTICS
 The
-.Nm
+.Nm install
 utility exits 0 on success, and 1 otherwise.
 .Sh FILES
 .Bl -tag -width INS@XXXX -compact
@@ -201,7 +215,7 @@ are created in the target directory.
 .El
 .Sh COMPATIBILITY
 Historically
-.Nm
+.Nm install
 moved files by default.
 The default was changed to copy in
 .Fx 4.4 .
@@ -216,22 +230,22 @@ The default was changed to copy in
 .Xr chown 8
 .Sh HISTORY
 The
-.Nm
+.Nm install
 utility appeared in
 .Bx 4.2 .
 .Sh BUGS
 Temporary files may be left in the target directory if
-.Nm
+.Nm install
 exits abnormally.
 .Pp
 File flags cannot be set by
 .Xr fchflags 2
 over a NFS file system.  Other file systems do not have a concept of flags.
-.Nm
+.Nm install
 will only warn when flags could not be set on a file system
 that does not support them.
 .Pp
-.Nm
+.Nm install
 with
 .Fl v
 falsely says a file is copied when
index 31e542dcbc88077949aa32d9d03c8f34ab07a62c..d5b41a12d97ae6739aab3f17186a5528eb8080f2 100644 (file)
@@ -67,7 +67,7 @@ static const char rcsid[] =
 
 #ifdef __APPLE__
 #include <copyfile.h>
-#endif
+#endif /* __APPLE__ */
 
 #include "pathnames.h"
 
@@ -442,6 +442,13 @@ install(from_name, to_name, fset, flags)
                        err(EX_OSERR, "%s", to_name);
        }
 
+#ifdef __APPLE__
+       /* in case mtime is modified */
+       if (!devnull && (S_ISLNK(from_sb.st_mode) || S_ISREG(from_sb.st_mode)) &&
+           fcopyfile(from_fd, to_fd, NULL, COPYFILE_XATTR) < 0) {
+               warn("%s: unable to copy extended attributes from %s", to_name, from_name);
+       }
+#endif /* __APPLE__ */
        /*
         * Preserve the timestamp of the source file if necessary.
         */
@@ -490,14 +497,14 @@ install(from_name, to_name, fset, flags)
        /*
         * If provided a set of flags, set them, otherwise, preserve the
         * flags, except for the dump flag.
-        * NFS does not support flags.  Ignore EOPNOTSUPP flags if we're just
+        * NFS does not support flags.  Ignore ENOTSUP flags if we're just
         * trying to turn off UF_NODUMP.  If we're trying to set real flags,
         * then warn if the the fs doesn't support it, otherwise fail.
         */
        if (!devnull && fchflags(to_fd,
            flags & SETFLAGS ? fset : from_sb.st_flags & ~UF_NODUMP)) {
                if (flags & SETFLAGS) {
-                       if (errno == EOPNOTSUPP)
+                       if (errno == ENOTSUP)
                                warn("%s: chflags", to_name);
                        else {
                                serrno = errno;
@@ -507,15 +514,13 @@ install(from_name, to_name, fset, flags)
                        }
                }
        }
-
-#if __APPLE__
-       {
-           if (copyfile(from_name, to_name, NULL, COPYFILE_ACL | COPYFILE_XATTR) < 0)
-           {
-               warn("%s: copyfile", to_name);
-           }
+#ifdef __APPLE__
+       /* the ACL could prevent credential/permission system calls later on... */
+       if (!devnull && (S_ISLNK(from_sb.st_mode) || S_ISREG(from_sb.st_mode)) &&
+           (fcopyfile(from_fd, to_fd, NULL, COPYFILE_ACL) < 0)) {
+               warn("%s: unable to copy ACL from %s", to_name, from_name);
        }
-#endif
+#endif /* __APPLE__ */
 
        (void)close(to_fd);
        if (!devnull)
index 4cf67c2e5836b678beb6ca69bbae97d14047f71e..55ff23cab7b4fddeb68bfffbd62699e13149bcf9 100644 (file)
@@ -21,7 +21,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\" 
-.\" $Id: ipcrm.1,v 1.2.32.1 2005/02/26 03:36:38 nicolai Exp $
+.\" $Id: ipcrm.1,v 1.3 2005/04/12 23:51:24 nicolai Exp $
 .\""
 .Dd August 8, 1994
 .Dt ipcrm 1
 .Nd remove the specified message queues, semaphore sets, and shared memory
 segments
 .Sh SYNOPSIS
-.Nm
-.Op Fl q Ar msqid
+.Nm ipcrm
+.Op Fl M Ar shmkey
 .Op Fl m Ar shmid
-.Op Fl s Ar semid
 .Op Fl Q Ar msgkey
-.Op Fl M Ar shmkey
+.Op Fl q Ar msqid
 .Op Fl S Ar semkey
+.Op Fl s Ar semid
 .Ar ...
 .Sh DESCRIPTION
 .Nm Ipcrm
@@ -45,34 +45,35 @@ removes the specified message queues, semaphores and shared memory
 segments.  These System V IPC objects can be specified by their
 creation id or any associated key.
 .Pp
-The following options are used to specify which IPC objects will be removed.  Any number and combination of these options can be used:
+The following options are used to specify which IPC objects will be removed.
+Any number and combination of these options can be used:
 .Bl -tag -width indent
-.It Fl q Ar msqid
-Remove the message queue associated with the id
-.Nm msqid
-from the system.
+.It Fl M Ar shmkey
+Mark the shared memory segment associated with key 
+.Nm shmkey
+for removal.
+This marked segment will be destroyed after the last detach.
 .It Fl m Ar shmid
 Mark the shared memory segment associated with id 
 .Nm shmid
 for removal.
 This marked segment will be destroyed after the last detach.
-.It Fl s Ar semid
-Removes the semaphore set associated with id
-.Nm semid
-from the system.
 .It Fl Q Ar msgkey
 Remove the message queue associated with key 
 .Nm msgkey
 from the system.
-.It Fl M Ar shmkey
-Mark the shared memory segment associated with key 
-.Nm shmkey
-for removal.
-This marked segment will be destroyed after the last detach.
+.It Fl q Ar msqid
+Remove the message queue associated with the id
+.Nm msqid
+from the system.
 .It Fl S Ar semkey
 Remove the semaphore set associated with key
 .Nm semkey
 from the system.
+.It Fl s Ar semid
+Removes the semaphore set associated with id
+.Nm semid
+from the system.
 .El
 .Pp
 The identifiers and keys associated with these System V IPC objects can be
index 567cfcbfbe602aa0243183f3a0ed762030a22ecd..be2d3becdd4545508cdd5463be749b32c7777327 100644 (file)
@@ -31,7 +31,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: ipcrm.c,v 1.2.30.1 2005/02/26 03:36:38 nicolai Exp $";
+       "$Id: ipcrm.c,v 1.3 2005/02/03 07:31:33 josborne Exp $";
 #endif /* not lint */
 
 #include <ctype.h>
@@ -42,10 +42,8 @@ static const char rcsid[] =
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/ipc.h>
-#if 0
 #include <sys/msg.h>
 #include <sys/sem.h>
-#endif
 #include <sys/shm.h>
 
 #define IPC_TO_STR(x) (x == 'Q' ? "msq" : (x == 'M' ? "shm" : "sem"))
@@ -66,13 +64,11 @@ int msgrm(key, id)
     key_t key;
     int id;
 {
-#if 0
     if (key) {
        id = msgget(key, 0);
        if (id == -1)
            return -1;
     }
-#endif
     return msgctl(id, IPC_RMID, NULL);
 }
 
@@ -92,7 +88,6 @@ int semrm(key, id)
     key_t key;
     int id;
 {
-#if 0
     union semun arg;
 
     if (key) {
@@ -101,7 +96,6 @@ int semrm(key, id)
            return -1;
     }
     return semctl(id, 0, IPC_RMID, arg);
-#endif
 }
 
 void not_configured()
@@ -116,6 +110,7 @@ int main(argc, argv)
 {
     int c, result, errflg, target_id;
     key_t target_key;
+    char *en;
 
     errflg = 0;
     signal(SIGSYS, not_configured);
@@ -126,7 +121,12 @@ int main(argc, argv)
        case 'q':
        case 'm':
        case 's':
-           target_id = atoi(optarg);
+           target_id = strtol(optarg, &en, 0);
+           if (*en) {
+               warnx("%s: '%s' is not a number",
+                   IPC_TO_STRING(toupper(c)), optarg);
+               continue;
+           }
            if (c == 'q')
                result = msgrm(0, target_id);
            else if (c == 'm')
@@ -145,7 +145,11 @@ int main(argc, argv)
        case 'Q':
        case 'M':
        case 'S':
-           target_key = atol(optarg);
+           target_key = strtol(optarg, &en, 0);
+           if (*en) {
+               warnx("%s: '%s' is not a number", IPC_TO_STRING(c), optarg);
+               continue;
+           }
            if (target_key == IPC_PRIVATE) {
                warnx("can't remove private %ss", IPC_TO_STRING(c));
                continue;
@@ -159,7 +163,7 @@ int main(argc, argv)
            if (result < 0) {
                errflg++;
                if (!signaled)
-                   warn("%key(%ld): ", IPC_TO_STR(c), target_key);
+                   warn("%s key(%ld): ", IPC_TO_STRING(c), target_key);
                else
                    warnx("%ss are not configured in the running kernel",
                          IPC_TO_STRING(c));
@@ -180,4 +184,3 @@ int main(argc, argv)
     }
     exit(errflg);
 }
-
index 2dd46561bf79664abd4db54033dff11e5e5d002d..ea77822b79512f5117e3bd8cea9cf97f707a59fd 100644 (file)
@@ -24,8 +24,7 @@ LIBS =
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
-NEXTSTEP_PB_CFLAGS =
-
+NEXTSTEP_PB_CFLAGS = -iquote /System/Library/Frameworks/System.framework/PrivateHeaders -iquote /System/Library/Frameworks/Kernel.framework/PrivateHeaders
 NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(NAME)/Build
 
 NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
@@ -44,6 +43,3 @@ include $(MAKEFILEDIR)/$(MAKEFILE)
 -include Makefile.postamble
 
 -include Makefile.dependencies
-
-ALL_CFLAGS += -I/System/Library/Frameworks/System.framework/PrivateHeaders
-
index 013b558de882142e966c538876f25f5726df1f43..54e04810d74a794b303af0ed8b4727f8a030df26 100644 (file)
@@ -1 +1,4 @@
 include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
+
+INSTALL_AS_USER     = root
+INSTALL_PERMISSIONS = 4511
index 6b057e28535fd2fca6dfb4ac51e467ee4155c2d5..f0a6df4bbe3430b3a9156fb6449d8875f4f80b41 100644 (file)
 .Nm ipcs
 .Nd report System V interprocess communication facilities status
 .Sh SYNOPSIS
-.Nm
-.Op Fl abcmopqstMQST
+.Nm ipcs
+.Op Fl abcMmopQqSsTt
 .Sh DESCRIPTION
 The
-.Nm
+.Nm ipcs
 utility provides information on System V interprocess communication
 (IPC) facilities on the system.
 .Pp
@@ -68,6 +68,8 @@ or the number of semaphores in a set of semaphores.
 .It Fl c
 Show the creator's name and group for active semaphores, message queues,
 and shared memory segments.
+.It Fl M
+Display system information about shared memory.
 .It Fl m
 Display information about active shared memory segments.
 .It Fl o
@@ -84,10 +86,17 @@ is the last process to send a message to or receive a message from
 a message queue,
 the process that created a semaphore, or the last process to attach
 or detach a shared memory segment.
+.It Fl Q
+Display system information about messages queues.
 .It Fl q
 Display information about active message queues.
+.It Fl S
+Display system information about semaphores.
 .It Fl s
 Display information about active semaphores.
+.It Fl T
+Display system information about shared memory, message queues
+and semaphores.
 .It Fl t
 Show access times for active semaphores, message queues,
 and shared memory segments.  The access times is the time
@@ -95,15 +104,6 @@ of the last control operation on an IPC object,
 the last send or receive of a message,
 the last attach or detach of a shared memory segment,
 or the last operation on a semaphore.
-.It Fl M
-Display system information about shared memory.
-.It Fl Q
-Display system information about messages queues.
-.It Fl S
-Display system information about semaphores.
-.It Fl T
-Display system information about shared memory, message queues
-and semaphores.
 .El
 .Pp
 If none of the
@@ -118,14 +118,14 @@ options are specified, information about all active IPC facilities is
 listed.
 .Sh RESTRICTIONS
 System data structures may change while
-.Nm
+.Nm ipcs
 is running; the output of
-.Nm
+.Nm ipcs
 is not guaranteed to be consistent.
 .Sh BUGS
 This manual page is woefully incomplete, because it does not
 at all attempt to explain the information printed by
-.Nm .
+.Nm ipcs .
 .Sh SEE ALSO
 .Xr ipcrm 1
 .Sh AUTHORS
index 5094d695108b5c48bb60838367618838393f6378..480a3c6d98a8ab9adfe45f5cdc840044a6072c2e 100644 (file)
@@ -31,7 +31,6 @@
 #include <err.h>
 #include <fcntl.h>
 #include <grp.h>
-#include <kvm.h>
 #include <nlist.h>
 #include <limits.h>
 #include <paths.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sysexits.h>
 
 #include <sys/types.h>
 #include <sys/ucred.h>
+#include <sys/time.h>
 #include <sys/proc.h>
 #include <sys/param.h>
-#include <sys/time.h>
 #include <sys/sysctl.h>
-
-#define KERNEL
-
-#include <sys/ipc.h>
-#include <sys/sem_internal.h>
-#include <sys/shm_internal.h>
-#include <sys/msg.h>
-
+#include <errno.h>
 #include "sys/ipcs.h"
+#define KERNEL 1               /* To get new ipc_perm and __(sem|shm|msg)ds_new */
+#include "sys/ipc.h"
+#include "sys/sem_internal.h"
+#include "sys/shm_internal.h"
+#include "sys/msg.h"
+
 
 /* The following is a kludge, until the problem of multiple inclusions
    of ipc.h is taken care of. */
 #ifndef IXSEQ_TO_IPCID
-#define IXSEQ_TO_IPCID(ix,perm) (((perm.seq) << 16) | (ix & 0xffff))
+#define IXSEQ_TO_IPCID(ix,perm) (((perm._seq) << 16L) | (ix & 0xffff))
 #endif
 
 char   *
-fmt_perm(mode)
-       u_short mode;
+fmt_perm(u_short mode, char write_char)
 {
        static char buffer[100];
 
        buffer[0] = '-';
        buffer[1] = '-';
        buffer[2] = ((mode & 0400) ? 'r' : '-');
-       buffer[3] = ((mode & 0200) ? 'w' : '-');
-       buffer[4] = ((mode & 0100) ? 'a' : '-');
+       buffer[3] = ((mode & 0200) ? write_char : '-');
+       buffer[4] = '-';
        buffer[5] = ((mode & 0040) ? 'r' : '-');
-       buffer[6] = ((mode & 0020) ? 'w' : '-');
-       buffer[7] = ((mode & 0010) ? 'a' : '-');
+       buffer[6] = ((mode & 0020) ? write_char : '-');
+       buffer[7] = '-';
        buffer[8] = ((mode & 0004) ? 'r' : '-');
-       buffer[9] = ((mode & 0002) ? 'w' : '-');
-       buffer[10] = ((mode & 0001) ? 'a' : '-');
+       buffer[9] = ((mode & 0002) ? write_char : '-');
+       buffer[10] = '-';
        buffer[11] = '\0';
        return (&buffer[0]);
 }
 
 void
-cvt_time(t, buf)
-       time_t  t;
-       char   *buf;
+cvt_time(time_t t, char *buf)
 {
        struct tm *tm;
 
@@ -113,15 +109,46 @@ cvt_time(t, buf)
 #define PID            8
 #define TIME           16
 
+void usage()
+{
+       errx(EX_USAGE, "%s","usage: ipcs [-abcmopqstMQST]\n");
+}
+
+int safe_sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,                 
+                     size_t newlen)
+
+{
+       int rv, sv_errno=0;
+
+       if (seteuid(0)) /* iterator needs root write access to sysctl */
+               err(1, "seteuid(0) failed");
+
+       rv = sysctlbyname(name, oldp, oldlenp, newp, newlen);
+       if (rv < 0)
+               sv_errno = errno;
+
+       if (seteuid(getuid()))
+               err(1, "seteuid(%d) failed", getuid());
+
+       if (rv < 0)
+               errno = sv_errno;
+       return rv;
+}
+
 int
 main(argc, argv)
        int     argc;
        char   *argv[];
 {
-       int     display = SHMINFO | MSGINFO | SEMINFO;
+       int     display = 0;
        int     option = 0;
-       char    kvmoferr[_POSIX2_LINE_MAX];  /* Error buf for kvm_openfiles. */
-       int     i;
+       int     exit_val = 0;
+       time_t  now;
+       char    datestring[100];
+       int     i;
+
+       if (seteuid(getuid()))  /* run as user */
+               err(1, "seteuid(%d) failed", getuid());
 
        while ((i = getopt(argc, argv, "MmQqSsabcoptT")) != -1)
                switch (i) {
@@ -129,19 +156,19 @@ main(argc, argv)
                        display = SHMTOTAL;
                        break;
                case 'm':
-                       display = SHMINFO;
+                       display |= SHMINFO;
                        break;
                case 'Q':
                        display = MSGTOTAL;
                        break;
                case 'q':
-                       display = MSGINFO;
+                       display |= MSGINFO;
                        break;
                case 'S':
                        display = SEMTOTAL;
                        break;
                case 's':
-                       display = SEMINFO;
+                       display |= SEMINFO;
                        break;
                case 'T':
                        display = SHMTOTAL | MSGTOTAL | SEMTOTAL;
@@ -167,7 +194,12 @@ main(argc, argv)
                default:
                        usage();
                }
-
+       if (display == 0)
+               display = SHMINFO | MSGINFO | SEMINFO;
+       now = time(0);
+       if (0 == strftime(datestring, sizeof(datestring), "%a %b %e %H:%M:%S %Z %Y", localtime(&now)))
+           errx(1, "strftime failed\n");
+       printf("IPC status from <running system> as of %s\n", datestring);
        if ((display & (MSGINFO | MSGTOTAL))) {
                if (display & MSGTOTAL) {
                        struct IPCS_command ic;
@@ -180,7 +212,16 @@ main(argc, argv)
                        ic.ipcs_data = &msginfo;
                        ic.ipcs_datalen = sizeof(msginfo);
 
-                       sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size);
+                       if (safe_sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                               if (errno != EPERM) {
+                                       char buffer[1024];
+                                       snprintf(buffer, 1024, "sysctlbyname(IPCS_MSG_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
+                                                sizeof(ic), ic.ipcs_datalen);
+                                       perror(buffer);
+                               } else
+                                       perror("sysctlbyname IPCS_MSG_SYSCTL");
+                       }
+
                        printf("msginfo:\n");
                        printf("\tmsgmax: %6d\t(max characters in a message)\n",
                            msginfo.msgmax);
@@ -197,11 +238,10 @@ main(argc, argv)
                }
                if (display & MSGINFO) {
                        struct IPCS_command ic;
-                       struct msqid_ds ds;
-                       struct msqid_ds *msqptr = &ds;
+                       struct __msqid_ds_new ds;
+                       struct __msqid_ds_new *msqptr = &ds;
                        size_t ic_size = sizeof(ic);
 
-                       printf("Message Queues:\n");
                        printf("T     ID     KEY        MODE       OWNER    GROUP");
                        if (option & CREATOR)
                                printf("  CREATOR   CGROUP");
@@ -213,15 +253,19 @@ main(argc, argv)
                                printf(" LSPID LRPID");
                        if (option & TIME)
                                printf("   STIME    RTIME    CTIME");
-                       printf("\n");
+                       printf("\nMessage Queues:\n");
 
                        ic.ipcs_magic = IPCS_MAGIC;
                        ic.ipcs_op = IPCS_MSG_ITER;
                        ic.ipcs_cursor = 0;     /* start */
-                       ic.ipcs_data = msqptr;
                        ic.ipcs_datalen = sizeof(*msqptr);
+                       ic.ipcs_data = msqptr;
+
+                       memset(msqptr, 0, sizeof(*msqptr));
+
+                       while(!(safe_sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                               ic.ipcs_data = msqptr;
 
-                       while(!(sysctlbyname(IPCS_MSG_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                if (msqptr->msg_qbytes != 0) {
                                        char    stime_buf[100], rtime_buf[100],
                                                ctime_buf[100];
@@ -230,10 +274,10 @@ main(argc, argv)
                                        cvt_time(msqptr->msg_rtime, rtime_buf);
                                        cvt_time(msqptr->msg_ctime, ctime_buf);
 
-                                       printf("q %6d %10d %s %8s %8s",
-                                           IXSEQ_TO_IPCID(i, msqptr->msg_perm),
-                                           (int)msqptr->msg_perm.key,
-                                           fmt_perm(msqptr->msg_perm.mode),
+                                       printf("q %6d 0x%08x %s %8s %8s",
+                                           IXSEQ_TO_IPCID(ic.ipcs_cursor-1, msqptr->msg_perm),
+                                           (int)msqptr->msg_perm._key,
+                                           fmt_perm(msqptr->msg_perm.mode, 'w'),
                                            user_from_uid(msqptr->msg_perm.uid, 0),
                                            group_from_gid(msqptr->msg_perm.gid, 0));
 
@@ -264,13 +308,22 @@ main(argc, argv)
 
                                        printf("\n");
                                }
+                               memset(msqptr, 0, sizeof(*msqptr));
+                               errno = 0;
+                       }
+
+                       if (errno != ENOENT && errno != ERANGE) {
+                               if (errno != EPERM) {
+                                       errx(1, "sysctlbyname(IPCS_MSG_SYSCTL, op=ITER, &ic, &%ld) datalen=%d failed:%s\n",
+                                                sizeof(ic), ic.ipcs_datalen, strerror(errno));
+                               } else
+                                       errx(1, "sysctlbyname IPCS_MSG_SYSCTL: %s", strerror(errno));
                        }
                        printf("\n");
                }
        } else
                if (display & (MSGINFO | MSGTOTAL)) {
-                       fprintf(stderr,
-                           "SVID messages facility not configured in the system\n");
+                       errx(1, "%s", "SVID messages facility not configured in the system\n");
                }
 
        if ((display & (SHMINFO | SHMTOTAL))) {
@@ -285,26 +338,31 @@ main(argc, argv)
                        ic.ipcs_data = &shminfo;
                        ic.ipcs_datalen = sizeof(shminfo);
 
-                       sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size);
+                       if (safe_sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                               if (errno != EPERM) {
+                                       errx(1, "sysctlbyname(IPCS_SHM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d failed: %s\n",
+                                            sizeof(ic), ic.ipcs_datalen, strerror(errno));
+                               } else
+                                       errx(1, "sysctlbyname: %s", strerror(errno));
+                       }
                        printf("shminfo:\n");
-                       printf("\tshmmax: %7d\t(max shared memory segment size)\n",
+                       printf("\tshmmax: %7lld\t(max shared memory segment size)\n",
                            shminfo.shmmax);
-                       printf("\tshmmin: %7d\t(min shared memory segment size)\n",
+                       printf("\tshmmin: %7lld\t(min shared memory segment size)\n",
                            shminfo.shmmin);
-                       printf("\tshmmni: %7d\t(max number of shared memory identifiers)\n",
+                       printf("\tshmmni: %7lld\t(max number of shared memory identifiers)\n",
                            shminfo.shmmni);
-                       printf("\tshmseg: %7d\t(max shared memory segments per process)\n",
+                       printf("\tshmseg: %7lld\t(max shared memory segments per process)\n",
                            shminfo.shmseg);
-                       printf("\tshmall: %7d\t(max amount of shared memory in pages)\n\n",
+                       printf("\tshmall: %7lld\t(max amount of shared memory in pages)\n\n",
                            shminfo.shmall);
                }
                if (display & SHMINFO) {
                        struct IPCS_command ic;
-                       struct shmid_ds ds;
-                       struct shmid_ds *shmptr = &ds;
+                       struct __shmid_ds_new ds;
+                       struct __shmid_ds_new *shmptr = &ds;
                        size_t ic_size = sizeof(ic);
 
-                       printf("Shared Memory:\n");
                        printf("T     ID     KEY        MODE       OWNER    GROUP");
                        if (option & CREATOR)
                                printf("  CREATOR   CGROUP");
@@ -316,16 +374,19 @@ main(argc, argv)
                                printf("  CPID  LPID");
                        if (option & TIME)
                                printf("   ATIME    DTIME    CTIME");
-                       printf("\n");
+                       printf("\nShared Memory:\n");
                {       /* XXX */
 
                        ic.ipcs_magic = IPCS_MAGIC;
                        ic.ipcs_op = IPCS_SHM_ITER;
                        ic.ipcs_cursor = 0;     /* start */
-                       ic.ipcs_data = shmptr;
                        ic.ipcs_datalen = sizeof(*shmptr);
+                       ic.ipcs_data = shmptr;
+                       memset(shmptr, 0, sizeof(shmptr));
+
+                       while(!(safe_sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                               ic.ipcs_data = shmptr; /* xnu workaround */
 
-                       while(!(sysctlbyname(IPCS_SHM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                if (shmptr->shm_perm.mode & 0x0800) {
                                        char    atime_buf[100], dtime_buf[100],
                                                ctime_buf[100];
@@ -334,10 +395,10 @@ main(argc, argv)
                                        cvt_time(shmptr->shm_dtime, dtime_buf);
                                        cvt_time(shmptr->shm_ctime, ctime_buf);
 
-                                       printf("m %6d %10d %s %8s %8s",
-                                           IXSEQ_TO_IPCID(i, shmptr->shm_perm),
-                                           (int)shmptr->shm_perm.key,
-                                           fmt_perm(shmptr->shm_perm.mode),
+                                       printf("m %6d 0x%08x %s %8s %8s",
+                                           IXSEQ_TO_IPCID(ic.ipcs_cursor-1, shmptr->shm_perm),
+                                           (int)shmptr->shm_perm._key,
+                                           fmt_perm(shmptr->shm_perm.mode, 'w'),
                                            user_from_uid(shmptr->shm_perm.uid, 0),
                                            group_from_gid(shmptr->shm_perm.gid, 0));
 
@@ -351,7 +412,7 @@ main(argc, argv)
                                                    shmptr->shm_nattch);
 
                                        if (option & BIGGEST)
-                                               printf(" %6d",
+                                               printf(" %6ld",
                                                    shmptr->shm_segsz);
 
                                        if (option & PID)
@@ -367,6 +428,16 @@ main(argc, argv)
 
                                        printf("\n");
                                }
+                               memset(shmptr, 0, sizeof(*shmptr));
+                               errno = 0;
+                       }
+
+                       if (errno != ENOENT && errno != ERANGE) {
+                               if (errno != EPERM) {
+                                       errx(1, "sysctlbyname(IPCS_SHM_SYSCTL, op=ITER, &ic, &%ld) datalen=%d failed:%s\n",
+                                                sizeof(ic), ic.ipcs_datalen, strerror(errno));
+                               } else
+                                       errx(1, "sysctlbyname: %s", strerror(errno));
                        }
                }       /* XXX */
                        printf("\n");
@@ -374,8 +445,7 @@ main(argc, argv)
        }
 else
                if (display & (SHMINFO | SHMTOTAL)) {
-                       fprintf(stderr,
-                           "SVID shared memory facility not configured in the system\n");
+                       errx(1, "%s", "SVID shared memory facility not configured in the system\n");
                }
 
        if ((display & (SEMINFO | SEMTOTAL))) {
@@ -390,7 +460,16 @@ else
                        ic.ipcs_data = &seminfo;
                        ic.ipcs_datalen = sizeof(seminfo);
 
-                       sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size);
+                       if (safe_sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size)) {
+                               if (errno != EPERM) {
+                                       char buffer[1024];
+                                       snprintf(buffer, 1024, "sysctlbyname(IPCS_SEM_SYSCTL, op=CONF, &ic, &%ld) datalen=%d",
+                                                sizeof(ic), ic.ipcs_datalen);
+                                       perror(buffer);
+                               } else
+                                       perror("sysctlbyname IPCS_SEM_SYSCTL/SEM_CONF");
+                       }
+
                        printf("seminfo:\n");
                        printf("\tsemmap: %6d\t(# of entries in semaphore map)\n",
                            seminfo.semmap);
@@ -415,11 +494,10 @@ else
                }
                if (display & SEMINFO) {
                        struct IPCS_command ic;
-                       struct semid_ds ds;
-                       struct semid_ds *semaptr = &ds;
+                       struct __semid_ds_new ds;
+                       struct __semid_ds_new *semaptr = &ds;
                        size_t ic_size = sizeof(ic);
 
-                       printf("Semaphores:\n");
                        printf("T     ID     KEY        MODE       OWNER    GROUP");
                        if (option & CREATOR)
                                printf("  CREATOR   CGROUP");
@@ -427,25 +505,29 @@ else
                                printf(" NSEMS");
                        if (option & TIME)
                                printf("   OTIME    CTIME");
-                       printf("\n");
+                       printf("\nSemaphores:\n");
 
                        ic.ipcs_magic = IPCS_MAGIC;
                        ic.ipcs_op = IPCS_SEM_ITER;
                        ic.ipcs_cursor = 0;     /* start */
-                       ic.ipcs_data = semaptr;
                        ic.ipcs_datalen = sizeof(*semaptr);
+                       ic.ipcs_data = semaptr;
+
+                       memset(semaptr, 0, sizeof(*semaptr));
+
+                       while(!(safe_sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
+                               ic.ipcs_data = semaptr; /* xnu workaround */
 
-                       while(!(sysctlbyname(IPCS_SEM_SYSCTL, &ic, &ic_size, &ic, ic_size))) {
                                if ((semaptr->sem_perm.mode & SEM_ALLOC) != 0) {
                                        char    ctime_buf[100], otime_buf[100];
 
                                        cvt_time(semaptr->sem_otime, otime_buf);
                                        cvt_time(semaptr->sem_ctime, ctime_buf);
 
-                                       printf("s %6d %10d %s %8s %8s",
-                                           IXSEQ_TO_IPCID(i, semaptr->sem_perm),
-                                           (int)semaptr->sem_perm.key,
-                                           fmt_perm(semaptr->sem_perm.mode),
+                                       printf("s %6d 0x%08x %s %8s %8s",
+                                           IXSEQ_TO_IPCID(ic.ipcs_cursor-1, semaptr->sem_perm),
+                                           (int)semaptr->sem_perm._key,
+                                           fmt_perm(semaptr->sem_perm.mode, 'a'),
                                            user_from_uid(semaptr->sem_perm.uid, 0),
                                            group_from_gid(semaptr->sem_perm.gid, 0));
 
@@ -465,22 +547,23 @@ else
 
                                        printf("\n");
                                }
+                               memset(semaptr, 0, sizeof(*semaptr));
+                               errno = 0;
                        }
 
+                       if (errno != ENOENT && errno != ERANGE) {
+                               if (errno != EPERM) {
+                                       errx(1, "sysctlbyname(IPCS_SEM_SYSCTL/ITER, op=ITER, &ic, &%ld) datalen=%d failed: %s\n",
+                                                sizeof(ic), ic.ipcs_datalen, strerror(errno));
+                               } else
+                                       errx(1, "sysctlbyname: IPCS_SEM_SYSCTL %s", strerror(errno));
+                       }
                        printf("\n");
                }
        } else
                if (display & (SEMINFO | SEMTOTAL)) {
-                       fprintf(stderr, "SVID semaphores facility not configured in the system\n");
+                       errx(1, "%s", "SVID semaphores facility not configured in the system\n");
                }
 
-       exit(0);
-}
-
-usage()
-{
-
-       fprintf(stderr,
-           "usage: ipcs [-abcmopqstMQST]\n");
-       exit(1);
+       exit(exit_val);
 }
index 15d04bde6fd9276e996e53b2b4bbc6bdc5dd1ea7..db22a08052a4c71ae9be8656e516f6683160307b 100644 (file)
@@ -17,6 +17,7 @@ CFILES = ln.c
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble ln.1\
             symlink.7
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
diff --git a/ln/ln.1 b/ln/ln.1
index 1dac859fb614b6ca30b952f9ca7374a0580583d0..37100d3787375683595449d2b9ce8d53a33f7e33 100644 (file)
--- a/ln/ln.1
+++ b/ln/ln.1
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1980, 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. 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.
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)ln.1        8.2 (Berkeley) 12/30/93
-.\" $FreeBSD: src/bin/ln/ln.1,v 1.25 2002/08/21 17:32:32 trhodes Exp $
+.\" $FreeBSD: src/bin/ln/ln.1,v 1.31 2006/02/14 11:08:05 glebius Exp $
 .\"
-.Dd December 30, 1993
+.Dd February 14, 2006
 .Dt LN 1
 .Os
 .Sh NAME
-.Nm ln ,
-.Nm link
+.Nm link ,
+.Nm ln
 .Nd make links
 .Sh SYNOPSIS
-.Nm
-.Op Fl fhinsv
+.Nm ln
+.Op Fl Ffhinsv
 .Ar source_file
 .Op Ar target_file
-.Nm
-.Op Fl fhinsv
+.Nm ln
+.Op Fl Ffhinsv
 .Ar source_file ...
 .Ar target_dir
 .Nm link
 .Ar source_file Ar target_file
 .Sh DESCRIPTION
 The
-.Nm
+.Nm ln
 utility creates a new directory entry (linked file) which has the
 same modes as the original file.
 It is useful for maintaining multiple copies of a file in many places
@@ -71,25 +68,47 @@ to a file is one of the differences between a hard and symbolic link.
 .Pp
 The options are as follows:
 .Bl -tag -width flag
-.It Fl f
-If the target file already exists,
-then unlink it so that the link may occur.
-(The
+.\" ==========
+.It Fl F
+If the target file already exists and is a directory, then remove it
+so that the link may occur.
+The
+.Fl F
+option should be used with either
 .Fl f
-option overrides any previous
+or
 .Fl i
-options.)
+options.
+If none is specified,
+.Fl f
+is implied.
+The
+.Fl F
+option is a no-op unless
+.Fl s
+option is specified.
 .It Fl h
 If the
 .Ar target_file
 or
 .Ar target_dir
-is a symbolic link, do not follow it.  This is most useful with the
+is a symbolic link, do not follow it.
+This is most useful with the
 .Fl f
 option, to replace a symlink which may point to a directory.
+.\" ==========
+.It Fl f
+If the target file already exists,
+then unlink it so that the link may occur.
+(The
+.Fl f
+option overrides any previous
+.Fl i
+options.)
+.\" ==========
 .It Fl i
 Cause
-.Nm
+.Nm ln
 to write a prompt to standard error if the target file exists.
 If the response from the standard input begins with the character
 .Sq Li y
@@ -102,22 +121,25 @@ Otherwise, do not attempt the link.
 option overrides any previous
 .Fl f
 options.)
+.\" ==========
 .It Fl n
 Same as
 .Fl h ,
 for compatibility with other
-.Nm
+.Nm ln
 implementations.
+.\" ==========
 .It Fl s
 Create a symbolic link.
+.\" ==========
 .It Fl v
 Cause
-.Nm
+.Nm ln
 to be verbose, showing files as they are processed.
 .El
 .Pp
 By default,
-.Nm
+.Nm ln
 makes
 .Em hard
 links.
@@ -127,23 +149,24 @@ the file.
 Hard links may not normally refer to directories and may not span file systems.
 .Pp
 A symbolic link contains the name of the file to
-which it is linked.  The referenced file is used when an
-.Xr open  2
+which it is linked.
+The referenced file is used when an
+.Xr open 2
 operation is performed on the link.
 A
-.Xr stat  2
+.Xr stat 2
 on a symbolic link will return the linked-to file; an
-.Xr lstat  2
+.Xr lstat 2
 must be done to obtain information about the link.
 The
-.Xr readlink  2
+.Xr readlink 2
 call may be used to read the contents of a symbolic link.
 Symbolic links may span file systems and may refer to directories.
 .Pp
 Given one or two arguments,
-.Nm
+.Nm ln
 creates a link to an existing file
-.Ar source_file  .
+.Ar source_file .
 If
 .Ar target_file
 is given, the link has that name;
@@ -152,10 +175,10 @@ may also be a directory in which to place the link;
 otherwise it is placed in the current directory.
 If only the directory is specified, the link will be made
 to the last component of
-.Ar source_file  .
+.Ar source_file .
 .Pp
 Given more than two arguments,
-.Nm
+.Nm ln
 makes links in
 .Ar target_dir
 to all the named source files.
@@ -169,13 +192,6 @@ No options may be supplied in this simple mode of operation,
 which performs a
 .Xr link 2
 operation using the two passed arguments.
-.Sh SEE ALSO
-.Xr link 2 ,
-.Xr lstat 2 ,
-.Xr readlink 2 ,
-.Xr stat 2 ,
-.Xr symlink 2 ,
-.Xr symlink 7
 .Sh COMPATIBILITY
 The
 .Fl h ,
@@ -185,11 +201,24 @@ and
 .Fl v
 options are non-standard and their use in scripts is not recommended.
 They are provided solely for compatibility with other
-.Nm
+.Nm ln
 implementations.
+.Pp
+The
+.Fl F
+option is
+.Fx
+extention and should not be used in portable scripts.
+.Sh SEE ALSO
+.Xr link 2 ,
+.Xr lstat 2 ,
+.Xr readlink 2 ,
+.Xr stat 2 ,
+.Xr symlink 2 ,
+.Xr symlink 7
 .Sh STANDARDS
 The
-.Nm
+.Nm ln
 utility conforms to
 .St -p1003.2-92 .
 .Pp
@@ -199,6 +228,6 @@ command conforms to
 .St -susv2 .
 .Sh HISTORY
 An
-.Nm
+.Nm ln
 command appeared in
 .At v1 .
diff --git a/ln/ln.c b/ln/ln.c
index ffe399d438665ffab82f0853e694df0f14e30c4d..f7bdc7ad08927a3b6f66803e6aeadd667b847c53 100644 (file)
--- a/ln/ln.c
+++ b/ln/ln.c
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1987, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
@@ -31,6 +27,7 @@
  * SUCH DAMAGE.
  */
 
+#if 0
 #ifndef lint
 static char const copyright[] =
 "@(#) Copyright (c) 1987, 1993, 1994\n\
@@ -38,12 +35,11 @@ static char const copyright[] =
 #endif /* not lint */
 
 #ifndef lint
-#if 0
 static char sccsid[] = "@(#)ln.c       8.2 (Berkeley) 3/31/94";
-#endif
 #endif /* not lint */
+#endif
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD: src/bin/ln/ln.c,v 1.29 2002/07/31 16:53:59 markm Exp $");
+__FBSDID("$FreeBSD: src/bin/ln/ln.c,v 1.34 2006/02/14 11:08:05 glebius Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -57,6 +53,7 @@ __RCSID("$FreeBSD: src/bin/ln/ln.c,v 1.29 2002/07/31 16:53:59 markm Exp $");
 #include <unistd.h>
 
 int    fflag;                          /* Unlink existing files. */
+int    Fflag;                          /* Remove empty directories also. */
 int    hflag;                          /* Check new name for symlink first. */
 int    iflag;                          /* Interactive mode. */
 int    sflag;                          /* Symbolic, not hard, link. */
@@ -75,6 +72,8 @@ main(int argc, char *argv[])
        char *p, *sourcedir;
        int ch, exitval;
 
+       if (argc < 1)
+               usage();
        /*
         * Test for the special case where the utility is called as
         * "link", for which the functionality provided is greatly
@@ -95,8 +94,11 @@ main(int argc, char *argv[])
                exit(linkit(argv[0], argv[1], 0));
        }
 
-       while ((ch = getopt(argc, argv, "fhinsv")) != -1)
+       while ((ch = getopt(argc, argv, "Ffhinsv")) != -1)
                switch (ch) {
+               case 'F':
+                       Fflag = 1;
+                       break;
                case 'f':
                        fflag = 1;
                        iflag = 0;
@@ -125,6 +127,10 @@ main(int argc, char *argv[])
 
        linkf = sflag ? symlink : link;
        linkch = sflag ? '-' : '=';
+       if (sflag == 0)
+               Fflag = 0;
+       if (Fflag == 1 && iflag == 0)
+               fflag = 1;
 
        switch(argc) {
        case 0:
@@ -204,7 +210,12 @@ linkit(const char *target, const char *source, int isdir)
         * and interactively if -i was specified.
         */
        if (fflag && exists) {
-               if (unlink(source)) {
+               if (Fflag && S_ISDIR(sb.st_mode)) {
+                       if (rmdir(source)) {
+                               warn("%s", source);
+                               return (1);
+                       }
+               } else if (unlink(source)) {
                        warn("%s", source);
                        return (1);
                }
@@ -220,7 +231,12 @@ linkit(const char *target, const char *source, int isdir)
                        return (1);
                }
 
-               if (unlink(source)) {
+               if (Fflag && S_ISDIR(sb.st_mode)) {
+                       if (rmdir(source)) {
+                               warn("%s", source);
+                               return (1);
+                       }
+               } else if (unlink(source)) {
                        warn("%s", source);
                        return (1);
                }
@@ -240,8 +256,8 @@ void
 usage(void)
 {
        (void)fprintf(stderr, "%s\n%s\n%s\n",
-           "usage: ln [-fhinsv] file1 file2",
-           "       ln [-fhinsv] file ... directory",
-           "       link file1 file2");
+           "usage: ln [-Ffhinsv] source_file [target_file]",
+           "       ln [-Ffhinsv] source_file ... target_dir",
+           "       link source_file target_file");
        exit(1);
 }
index dc9f7022952d36194a912622192cb5dd1488397a..726f583809ac55e246ef96ce1a0af575aff9ad0f 100644 (file)
@@ -1,3 +1,4 @@
+.\"-
 .\" Copyright (c) 1992, 1993, 1994
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -9,10 +10,6 @@
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. 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.
@@ -30,7 +27,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)symlink.7   8.3 (Berkeley) 3/31/94
-.\" $FreeBSD: src/bin/ln/symlink.7,v 1.25 2002/08/21 17:32:32 trhodes Exp $
+.\" $FreeBSD: src/bin/ln/symlink.7,v 1.30 2005/02/13 22:25:09 ru Exp $
 .\"
 .Dd March 31, 1994
 .Dt SYMLINK 7
@@ -49,7 +46,7 @@ file.
 Hard links may not refer to directories and may not reference files
 on different file systems.
 A symbolic link contains the name of the file to which it is linked,
-i.e. it is a pointer to another name, and not to an underlying object.
+i.e., it is a pointer to another name, and not to an underlying object.
 For this reason, symbolic links may reference directories and may span
 file systems.
 .Pp
@@ -72,7 +69,7 @@ the link.
 Symbolic links may reference other symbolic links,
 in which case the links are dereferenced until an object that is
 not a symbolic link is found,
-a symbolic link which references a file which doesn't exist is found,
+a symbolic link which references a file which does not exist is found,
 or a loop is detected.
 (Loop detection is done by placing an upper limit on the number of
 links that may be followed, and an error results if this limit is
@@ -138,7 +135,7 @@ an existing symbolic link can be changed by means of the
 .Xr lchflags 2 ,
 .Xr lchmod 2 ,
 .Xr lchown 2 ,
-and 
+and
 .Xr lutimes 2
 system calls, respectively.
 Of these, only the flags are used by the system;
@@ -172,7 +169,7 @@ would display the contents of the file
 .Dq Li afile .
 .Pp
 It is important to realize that this rule includes commands which may
-optionally traverse file trees, e.g. the command
+optionally traverse file trees, e.g.\& the command
 .Dq Li "chown file"
 is included in this rule, while the command
 .Dq Li "chown -R file"
@@ -213,7 +210,7 @@ The
 command is also an exception to this rule.
 For compatibility with historic systems (when
 .Nm ls
-is not doing a tree walk, i.e. the
+is not doing a tree walk, i.e., the
 .Fl R
 option is not specified),
 the
@@ -228,7 +225,8 @@ or if the
 .Fl d
 or
 .Fl l
-options are not specified.  (The
+options are not specified.
+(The
 .Nm ls
 command is the only command where the
 .Fl H
@@ -416,14 +414,16 @@ options.
 To maintain compatibility with historic systems,
 the
 .Nm ls
-command acts a little differently.  If you do not specify the
+command acts a little differently.
+If you do not specify the
 .Fl F ,
 .Fl d
 or
 .Fl l
 options,
 .Nm ls
-will follow symbolic links specified on the command line.  If the
+will follow symbolic links specified on the command line.
+If the
 .Fl L
 flag is specified,
 .Nm ls
index 35bb9ccd44ae51548b2c3e7de14a56a6f7de2b62..f593549c563fa36e5e21136375a4d3765b11f39e 100644 (file)
@@ -14,11 +14,11 @@ PROJECT_TYPE = Tool
 
 HFILES = extern.h ls.h
 
-CFILES = cmp.c ls.c print.c util.c
+CFILES = cmp.c ls.c print.c util.c humanize_number.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble ls.1
 
-OTHER_CFLAGS = -DCOLORLS -I/System/Library/Frameworks/System.framework/PrivateHeaders
+OTHER_CFLAGS = -DCOLORLS -I/System/Library/Frameworks/System.framework/PrivateHeaders -D__FBSDID=__RCSID -D_DARWIN_USE_64_BIT_INODE
 OTHER_LDFLAGS = -lncurses
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
index 273719c1b61166ada6ab18ae9e59682a6f006125..9d16436f76e7b9fcf2fae7a1b92bc66dd77b5bd6 100644 (file)
@@ -44,12 +44,14 @@ int  statcmp(const FTSENT *, const FTSENT *);
 int     revstatcmp(const FTSENT *, const FTSENT *);
 int     sizecmp (const FTSENT *, const FTSENT *);
 int     revsizecmp (const FTSENT *, const FTSENT *);
+int      humanize_number(char *, size_t, int64_t, const char *, int, int);
 
 void    printcol(DISPLAY *);
 void    printlong(DISPLAY *);
 void    printscol(DISPLAY *);
 void    printstream(DISPLAY *);
 void    usage(void);
+int      prn_normal(const char *);
 size_t  len_octal(const char *, int);
 int     prn_octal(const char *);
 int     prn_printable(const char *);
diff --git a/ls/humanize_number.c b/ls/humanize_number.c
new file mode 100644 (file)
index 0000000..f855a4b
--- /dev/null
@@ -0,0 +1,148 @@
+/*     $NetBSD: humanize_number.c,v 1.8 2004/07/27 01:56:24 enami Exp $        */
+
+/*
+ * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the NetBSD
+ *      Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 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.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <fts.h>
+
+#include "ls.h"
+
+int
+humanize_number(char *buf, size_t len, int64_t bytes,
+    const char *suffix, int scale, int flags)
+{
+       const char *prefixes, *sep;
+       int     b, i, r, maxscale, s1, s2, sign;
+       int64_t divisor, max;
+       size_t  baselen;
+
+       assert(buf != NULL);
+       assert(suffix != NULL);
+       assert(scale >= 0);
+
+       if (flags & HN_DIVISOR_1000) {
+               /* SI for decimal multiplies */
+               divisor = 1000;
+               if (flags & HN_B)
+                       prefixes = "B\0k\0M\0G\0T\0P\0E";
+               else
+                       prefixes = "\0\0k\0M\0G\0T\0P\0E";
+       } else {
+               /*
+                * binary multiplies
+                * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+                */
+               divisor = 1024;
+               if (flags & HN_B)
+                       prefixes = "B\0K\0M\0G\0T\0P\0E";
+               else
+                       prefixes = "\0\0K\0M\0G\0T\0P\0E";
+       }
+
+#define        SCALE2PREFIX(scale)     (&prefixes[(scale) << 1])
+       maxscale = 7;
+
+       if (scale >= maxscale &&
+           (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
+               return (-1);
+
+       if (buf == NULL || suffix == NULL)
+               return (-1);
+
+       if (len > 0)
+               buf[0] = '\0';
+       if (bytes < 0) {
+               sign = -1;
+               bytes *= -100;
+               baselen = 3;            /* sign, digit, prefix */
+       } else {
+               sign = 1;
+               bytes *= 100;
+               baselen = 2;            /* digit, prefix */
+       }
+       if (flags & HN_NOSPACE)
+               sep = "";
+       else {
+               sep = " ";
+               baselen++;
+       }
+       baselen += strlen(suffix);
+
+       /* Check if enough room for `x y' + suffix + `\0' */
+       if (len < baselen + 1)
+               return (-1);
+
+       if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
+               /* See if there is additional columns can be used. */
+               for (max = 100, i = len - baselen; i-- > 0;)
+                       max *= 10;
+
+               for (i = 0; bytes >= max && i < maxscale; i++)
+                       bytes /= divisor;
+
+               if (scale & HN_GETSCALE)
+                       return (i);
+       } else
+               for (i = 0; i < scale && i < maxscale; i++)
+                       bytes /= divisor;
+
+       /* If a value <= 9.9 after rounding and ... */
+       if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
+               /* baselen + \0 + .N */
+               if (len < baselen + 1 + 2)
+                       return (-1);
+               b = ((int)bytes + 5) / 10;
+               s1 = b / 10;
+               s2 = b % 10;
+               r = snprintf(buf, len, "%d%s%d%s%s%s",
+                   sign * s1, localeconv()->decimal_point, s2,
+                   sep, SCALE2PREFIX(i), suffix);
+       } else
+               r = snprintf(buf, len, "%lld%s%s%s",
+                   /* LONGLONG */
+                   (long long)(sign * ((bytes + 50) / 100)),
+                   sep, SCALE2PREFIX(i), suffix);
+
+       return (r);
+}
diff --git a/ls/ls.1 b/ls/ls.1
index dad0f657e60c7dad892dd67e290779de842f1455..c59ac1fe628e1ce694d47d9d484f2bf8231f3765 100644 (file)
--- a/ls/ls.1
+++ b/ls/ls.1
 .Nm ls
 .Nd list directory contents
 .Sh SYNOPSIS
-.Nm
-.Op Fl ABCFGHLPRTWZabcdefghiklmnopqrstuwx1
+.Nm ls
+.Op Fl ABCFGHLPRSTW@abcdefghiklmnopqrstuwx1
 .Op Ar
 .Sh DESCRIPTION
 For each operand that names a
 .Ar file
 of a type other than
 directory,
-.Nm
+.Nm ls
 displays its name as well as any requested,
 associated information.
 For each operand that names a
 .Ar file
 of type directory,
-.Nm
+.Nm ls
 displays the names of files contained
 within that directory, as well as any requested, associated
 information.
@@ -70,12 +70,29 @@ lexicographical order.
 .Pp
 The following options are available:
 .Bl -tag -width indent
+.\" ==========
+.It Fl @
+Display extended attribute keys and sizes.
+.It Fl 1
+(The numeric digit
+.Dq one . )
+Force output to be
+one entry per line.
+This is the default when
+output is not to a terminal.
+.\" ==========
 .It Fl A
 List all entries except for
 .Pa \&.
 and
 .Pa .. .
 Always set for the super-user.
+.\" ==========
+.It Fl a
+Include directory entries whose names begin with a
+dot
+.Pq Pa \&. .
+.\" ==========
 .It Fl B
 Force printing of non-printable characters (as defined by
 .Xr ctype 3
@@ -84,8 +101,26 @@ and current locale settings) in file names as
 where
 .Va xxx
 is the numeric value of the character in octal.
+.\" ==========
+.It Fl b
+As
+.Fl B ,
+but use
+.Tn C
+escape codes whenever possible.
+.\" ==========
 .It Fl C
 Force multi-column output; this is the default when output is to a terminal.
+.\" ==========
+.It Fl c
+Use time when file status was last changed for sorting or printing.
+.\" ==========
+.It Fl d
+Directories are listed as plain files (not searched recursively).
+.\" ==========
+.It Fl e
+Print the Access Control List (ACL) associated with the file, if present.
+.\" ==========
 .It Fl F
 Display a slash
 .Pq Ql /
@@ -106,12 +141,26 @@ and a vertical bar
 .Pq Ql \&|
 after each that is a
 .Tn FIFO .
+.\" ==========
+.It Fl f
+Output is not sorted.
+This option turns on the
+.Fl a
+option.
+.\" ==========
 .It Fl G
 Enable colorized output.
 This option is equivalent to defining
 .Ev CLICOLOR
 in the environment.
 (See below.)
+.\" ==========
+.It Fl g
+This option is only available for compatibility with POSIX;
+it is used to display the group name in the long
+.Pq Fl l
+format output (the owner name is suppressed).
+.\" ==========
 .It Fl H
 Symbolic links on the command line are followed.
 This option is assumed if
@@ -120,65 +169,17 @@ none of the
 or
 .Fl l
 options are specified.
-.It Fl L
-If argument is a symbolic link, list the file or directory the link references
-rather than the link itself.
-This option cancels the
-.Fl P
-option.
-.It Fl P
-If argument is a symbolic link, list the link itself rather than the
-object the link references.
-This option cancels the
-.Fl H
-and
-.Fl L
-options.
-.It Fl R
-Recursively list subdirectories encountered.
-.It Fl S
-Sort files by size
-.It Fl T
-When used with the
-.Fl l
-(lowercase letter
-.Dq ell )
-option, display complete time information for the file, including
-month, day, hour, minute, second, and year.
-.It Fl W
-Display whiteouts when scanning directories.
-.It Fl a
-Include directory entries whose names begin with a
-dot
-.Pq Pa \&. .
-.It Fl b
-As
-.Fl B ,
-but use
-.Tn C
-escape codes whenever possible.
-.It Fl c
-Use time when file status was last changed for sorting or printing.
-.It Fl d
-Directories are listed as plain files (not searched recursively).
-.It Fl e
-Print the Access Control List (ACL) associated with the file, if present.
-.It Fl f
-Output is not sorted.
-.It Fl g
-This option is only available for compatibility
-with POSIX;
-it is used to display the group name in the long
-.Pq Fl l
-format output.
+.\" ==========
 .It Fl h
 When used with the
 .Fl l
 option, use unit suffixes: Byte, Kilobyte, Megabyte, Gigabyte, Terabyte
 and Petabyte in order to reduce the number of digits to three or less
 using base 2 for sizes.
+.\" ==========
 .It Fl i
 For each file, print the file's file serial number (inode number).
+.\" ==========
 .It Fl k
 If the
 .Fl s
@@ -186,6 +187,14 @@ option is specified, print the file size allocation in kilobytes,
 not blocks.
 This option overrides the environment variable
 .Ev BLOCKSIZE .
+.\" ==========
+.It Fl L
+If argument is a symbolic link, list the file or directory the link references
+rather than the link itself.
+This option cancels the
+.Fl P
+option.
+.\" ==========
 .It Fl l
 (The lowercase letter
 .Dq ell . )
@@ -193,32 +202,58 @@ List in long format.
 (See below.)
 If the output is to a terminal, a total sum for all the file
 sizes is output on a line before the long listing.
+.\" ==========
 .It Fl m
 Stream output format; list files across the page, separated by commas.
+.\" ==========
 .It Fl n
-Display user and group IDs numerically rather than converting to a user
-or group name in a long
+Display user and group IDs numerically,
+rather than converting to a user or group name in a long
 .Pq Fl l
 output.
-.It Fl o
+This option turns on the
+.Fl l
+option.
+.\" ==========
+.It Fl O
 Include the file flags in a long
 .Pq Fl l
 output.
+.\" ==========
+.It Fl o
+List in long format, but omit the group id.
+.\" ==========
+.It Fl P
+If argument is a symbolic link, list the link itself rather than the
+object the link references.
+This option cancels the
+.Fl H
+and
+.Fl L
+options.
+.\" ==========
 .It Fl p
 Write a slash
 .Pq Ql /
 after each filename if that file is a directory.
+.\" ==========
 .It Fl q
 Force printing of non-graphic characters in file names as
 the character
 .Ql \&? ;
 this is the default when output is to a terminal.
+.\" ==========
+.It Fl R
+Recursively list subdirectories encountered.
+.\" ==========
 .It Fl r
 Reverse the order of the sort to get reverse
 lexicographical order or the oldest entries first (or largest files
 last, if combined with sort by size
-.Pq Fl S
-flag).
+.\" ==========
+.It Fl S
+Sort files by size
+.\" ==========
 .It Fl s
 Display the number of file system blocks actually used by each file, in units
 of 512 bytes, where partial units are rounded up to the next integer value.
@@ -227,10 +262,20 @@ sizes is output on a line before the listing.
 The environment variable
 .Ev BLOCKSIZE
 overrides the unit size of 512 bytes.
+.\" ==========
+.It Fl T
+When used with the
+.Fl l
+(lowercase letter
+.Dq ell )
+option, display complete time information for the file, including
+month, day, hour, minute, second, and year.
+.\" ==========
 .It Fl t
 Sort by time modified (most recently modified
 first) before sorting the operands by lexicographical
 order.
+.\" ==========
 .It Fl u
 Use time of last access,
 instead of last modification
@@ -238,33 +283,34 @@ of the file for sorting
 .Pq Fl t
 or printing
 .Pq Fl l .
+.\" ==========
+.It Fl v
+Force unedited printing of non-graphic characters; this is the default when
+output is not to a terminal.
+.\" ==========
+.It Fl W
+Display whiteouts when scanning directories.
+.Pq Fl S
+flag).
+.\" ==========
 .It Fl w
 Force raw printing of non-printable characters.
 This is the default
 when output is not to a terminal.
+.\" ==========
 .It Fl x
 The same as
 .Fl C ,
 except that the multi-column output is produced with entries sorted
 across, rather than down, the columns.
-.It Fl v
-Force unedited printing of non-graphic characters; this is the default when
-output is not to a terminal.
-.It Fl 1
-(The numeric digit
-.Dq one . )
-Force output to be
-one entry per line.
-This is the default when
-output is not to a terminal.
 .El
 .Pp
 The
 .Fl 1 , C , x ,
 and
 .Fl l
-options all override each other; the last one specified determines
-the format used.
+options all override each other;
+the last one specified determines the format used.
 .Pp
 The
 .Fl c
@@ -277,8 +323,9 @@ The
 .Fl B , b , w ,
 and
 .Fl q
-options all override each other; the last one specified determines
-the format used for non-printable characters.
+options all override each other;
+the last one specified determines the format used
+for non-printable characters.
 .Pp
 The
 .Fl H , L
@@ -288,7 +335,7 @@ options all override each other (either partially or fully); they
 are applied in the order specified.
 .Pp
 By default,
-.Nm
+.Nm ls
 lists one entry per line to standard
 output; the exceptions are to terminals or when the
 .Fl C
@@ -314,17 +361,22 @@ number of bytes in the file, abbreviated
 month, day-of-month file was last modified,
 hour file last modified, minute file last
 modified, and the pathname.
-In addition, for each directory whose contents are displayed, the total
-number of 512-byte blocks used by the files in the directory is displayed
-on a line by itself immediately before the information for the files in the
-directory.
-If the file or directory has extended security information, the permissions
-field printed by the 
+In addition, for each directory whose contents are displayed,
+the total number of 512-byte blocks used by the files in the directory
+is displayed on a line by itself,
+immediately before the information for the files in the directory.
+If the file or directory has extended attributes,
+the permissions field printed by the
+.Fl l
+option is followed by a '@' character.
+Otherwise, if the file or directory has extended security information,
+the permissions field printed by the 
 .Fl l
 option is followed by a '+' character.
 .Pp
-If the modification time of the file is more than 6 months
-in the past or future, then the year of the last modification
+If the modification time of the file
+is more than 6 months in the past or future,
+then the year of the last modification
 is displayed in place of the hour and minute fields.
 .Pp
 If the owner or group names are not a known user or group name,
@@ -336,16 +388,16 @@ the numeric ID's are displayed.
 If the file is a character special or block special file,
 the major and minor device numbers for the file are displayed
 in the size field.
-If the file is a symbolic link the pathname of the
-linked-to file is preceded by
+If the file is a symbolic link,
+the pathname of the linked-to file is preceded by
 .Dq Li -> .
 .Pp
 The file mode printed under the
 .Fl l
 option consists of the
 entry type, owner permissions, and group permissions.
-The entry type character describes the type of file, as
-follows:
+The entry type character describes the type of file,
+as follows:
 .Pp
 .Bl -tag -width 4n -offset indent -compact
 .It Sy b
@@ -429,24 +481,15 @@ or
 .El
 .Sh EXAMPLES
 The following is how to do an
-.Nm
-listing sorted by size (and shows why
-.Nm
-does not need a separate option for this):
-.Pp
-.Dl "ls -l | sort -n +4"
+.Nm ls
+listing sorted by increasing size 
 .Pp
-Additionally, the
-.Fl r
-flag to
-.Xr sort 1
-may be used
-to get the results sorted from largest to smallest (a reverse sort).
+.Dl "ls -lrS"
 .Sh DIAGNOSTICS
 .Ex -std
 .Sh ENVIRONMENT
 The following environment variables affect the execution of
-.Nm :
+.Nm ls :
 .Bl -tag -width ".Ev CLICOLOR_FORCE"
 .It Ev BLOCKSIZE
 If the environment variable
@@ -499,7 +542,7 @@ decimal integer, it is used as the
 column position width for displaying
 multiple-text-column output.
 The
-.Nm
+.Nm ls
 utility calculates how
 many pathname text columns to display
 based on the width provided.
@@ -628,6 +671,38 @@ The group field is now automatically included in the long listing for
 files in order to be compatible with the
 .St -p1003.2
 specification.
+.Sh LEGACY DESCRIPTION
+In legacy mode, the
+.Fl f
+option does not turn on the
+.Fl a
+option and the
+.Fl g ,
+.Fl n ,
+and
+.Fl o
+options do not turn on the
+.Fl l
+option.
+.Pp
+Also, the
+.Fl o
+option causes the file flags to be included in a long (-l) output;
+there is no
+.Fl O
+option.
+.Pp
+When
+.Fl H
+is specified (and not overridden by
+.Fl L
+or
+.Fl P )
+and a file argument is a symlink
+that resolves to a non-directory file,
+the output will reflect the nature of the link,
+rather than that of the file.
+In legacy operation, the output will describe the file.
 .Sh SEE ALSO
 .Xr chflags 1 ,
 .Xr chmod 1 ,
@@ -639,12 +714,12 @@ specification.
 .Xr sticky 8
 .Sh STANDARDS
 The
-.Nm
+.Nm ls
 utility conforms to
 .St -p1003.1-2001 .
 .Sh HISTORY
 An
-.Nm
+.Nm ls
 command appeared in
 .At v1 .
 .Sh BUGS
diff --git a/ls/ls.c b/ls/ls.c
index f00991711d25fe10fd2736e8b9709c5d859aa568..749af9860cf684a9db4ff925acbb72a88799e7ab 100644 (file)
--- a/ls/ls.c
+++ b/ls/ls.c
@@ -84,8 +84,8 @@ __RCSID("$FreeBSD: src/bin/ls/ls.c,v 1.66 2002/09/21 01:28:36 wollman Exp $");
 #define        STRBUF_SIZEOF(t)        (1 + CHAR_BIT * sizeof(t) / 3 + 1)
 
 static void     display(FTSENT *, FTSENT *);
-static u_quad_t         makenines(u_long);
-static int      mastercmp(const FTSENT * const *, const FTSENT * const *);
+static u_quad_t         makenines(u_quad_t);
+static int      mastercmp(const FTSENT **, const FTSENT **);
 static void     traverse(int, char **, int);
 
 static void (*printfcn)(DISPLAY *);
@@ -106,7 +106,7 @@ static int f_listdot;               /* list files beginning with . */
        int f_nonprint;         /* show unprintables as ? */
 static int f_nosort;           /* don't sort output */
        int f_notabs;           /* don't use tab-separated multi-col output */
-static int f_numericonly;      /* don't convert uid/gid to name */
+       int f_numericonly;      /* don't convert uid/gid to name */
        int f_octal;            /* show unprintables as \xxx */
        int f_octal_escape;     /* like f_octal but use C escapes if possible */
 static int f_recursive;                /* ls subdirectories also */
@@ -123,7 +123,9 @@ static int f_sizesort;              /* sort by size */
        int f_type;             /* add type character for non-regular files */
 static int f_whiteout;         /* show whiteout entries */
        int f_acl;              /* show ACLs in long listing */
+       int f_xattr;            /* show extended attributes in long listing */
        int f_group;            /* show group */
+       int f_owner;            /* show owner */
 #ifdef COLORLS
        int f_color;            /* add type in color for non-regular files */
 
@@ -149,6 +151,8 @@ main(int argc, char *argv[])
        char *bp = tcapbuf;
 #endif
 
+       if (argc < 1)
+               usage();
        (void)setlocale(LC_ALL, "");
 
        /* Terminal defaults to -Cq, non-terminal defaults to -1. */
@@ -173,7 +177,7 @@ main(int argc, char *argv[])
                f_listdot = 1;
 
        fts_options = FTS_PHYSICAL;
-       while ((ch = getopt(argc, argv, "1ABCFGHLPRSTWabcdefghiklmnopqrstuvwx")) 
+       while ((ch = getopt(argc, argv, "1@ABCFGHLOPRSTWabcdefghiklmnopqrstuvwx")) 
            != -1) {
                switch (ch) {
                /*
@@ -217,7 +221,12 @@ main(int argc, char *argv[])
                        f_slash = 0;
                        break;
                case 'H':
-                       fts_options |= FTS_COMFOLLOW;
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               fts_options &= ~FTS_LOGICAL;
+                               fts_options |= FTS_PHYSICAL;
+                               fts_options |= FTS_COMFOLLOWDIR;
+                       } else
+                               fts_options |= FTS_COMFOLLOW;
                        break;
                case 'G':
                        setenv("CLICOLOR", "", 1);
@@ -225,9 +234,12 @@ main(int argc, char *argv[])
                case 'L':
                        fts_options &= ~FTS_PHYSICAL;
                        fts_options |= FTS_LOGICAL;
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               fts_options &= ~(FTS_COMFOLLOW|FTS_COMFOLLOWDIR);
+                       }
                        break;
                case 'P':
-                       fts_options &= ~FTS_COMFOLLOW;
+                       fts_options &= ~(FTS_COMFOLLOW|FTS_COMFOLLOWDIR);
                        fts_options &= ~FTS_LOGICAL;
                        fts_options |= FTS_PHYSICAL;
                        break;
@@ -247,6 +259,10 @@ main(int argc, char *argv[])
                        break;
                case 'f':
                        f_nosort = 1;
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               fts_options |= FTS_SEEDOT;
+                               f_listdot = 1;
+                       }
                        break;
                case 'g':       /* Compatibility with Unix03 */
                        if (COMPAT_MODE("bin/ls", "Unix2003")) {
@@ -272,9 +288,21 @@ main(int argc, char *argv[])
                        break;
                case 'n':
                        f_numericonly = 1;
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               f_longform = 1;
+                               f_singlecol = 0;
+                               f_stream = 0;
+                       }
                        break;
                case 'o':
-                       f_flags = 1;
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               f_owner = 1;
+                               f_longform = 1;
+                               f_singlecol = 0;
+                               f_stream = 0;
+                       } else {
+                               f_flags = 1;
+                       }
                        break;
                case 'p':
                        f_slash = 1;
@@ -321,6 +349,12 @@ main(int argc, char *argv[])
                case 'e':
                        f_acl = 1;
                        break;
+               case '@':
+                       f_xattr = 1;
+                       break;
+               case 'O':
+                       f_flags = 1;
+                       break;
                default:
                case '?':
                        usage();
@@ -382,7 +416,7 @@ main(int argc, char *argv[])
         * If not -F, -d or -l options, follow any symbolic links listed on
         * the command line.
         */
-       if (!f_longform && !f_listdir && !f_type)
+       if (!f_longform && !f_listdir && !f_type && !f_inode)
                fts_options |= FTS_COMFOLLOW;
 
        /*
@@ -457,15 +491,17 @@ traverse(int argc, char *argv[], int options)
 {
        FTS *ftsp;
        FTSENT *p, *chp;
-       int ch_options;
+       int ch_options, error;
 
        if ((ftsp =
            fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
                err(1, "fts_open");
 
        display(NULL, fts_children(ftsp, 0));
-       if (f_listdir)
+       if (f_listdir) {
+               fts_close(ftsp);
                return;
+       }
 
        /*
         * If not recursing down this tree and don't need stat info, just get
@@ -477,6 +513,9 @@ traverse(int argc, char *argv[], int options)
                switch (p->fts_info) {
                case FTS_DC:
                        warnx("%s: directory causes a cycle", p->fts_name);
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               rval = 1;
+                       }
                        break;
                case FTS_DNR:
                case FTS_ERR:
@@ -505,9 +544,23 @@ traverse(int argc, char *argv[], int options)
                        if (!f_recursive && chp != NULL)
                                (void)fts_set(ftsp, p, FTS_SKIP);
                        break;
+               case FTS_SLNONE:        /* Same as default unless Unix conformance */
+                       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+                               if ((options & FTS_LOGICAL)!=0) {       /* -L was specified */
+                                       if (p->fts_errno) {
+                                               warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
+                                               rval = 1;
+                                       }
+                               }
+                       }
+                       break;
                default:
                        break;
                }
+       error = errno;
+       fts_close(ftsp);
+       errno = error;
+
        if (errno)
                err(1, "fts_read");
 }
@@ -526,7 +579,8 @@ display(FTSENT *p, FTSENT *list)
        NAMES *np;
        off_t maxsize;
        u_int64_t btotal, maxblock;
-       u_long lattrlen, maxinode, maxlen, maxnlink, maxlattr;
+       u_long lattrlen, maxlen, maxnlink, maxlattr;
+       ino_t maxinode;
        int bcfile, maxflags;
        gid_t maxgroup;
        uid_t maxuser;
@@ -582,7 +636,11 @@ display(FTSENT *p, FTSENT *list)
                        strcpy(initmax2, "0");
 
                ninitmax = sscanf(jinitmax,
+#if _DARWIN_FEATURE_64_BIT_INODE
+                   " %llu : %qu : %lu : %i : %i : %i : %qu : %lu : %lu ",
+#else
                    " %lu : %qu : %lu : %i : %i : %i : %qu : %lu : %lu ",
+#endif
                    &maxinode, &maxblock, &maxnlink, &maxuser,
                    &maxgroup, &maxflags, &maxsize, &maxlen, &maxlattr);
                f_notabs = 1;
@@ -744,7 +802,11 @@ display(FTSENT *p, FTSENT *list)
                d.s_flags = maxflags;
                d.s_lattr = maxlattr;
                d.s_group = maxgroup;
+#if _DARWIN_FEATURE_64_BIT_INODE
+               (void)snprintf(buf, sizeof(buf), "%llu", maxinode);
+#else
                (void)snprintf(buf, sizeof(buf), "%lu", maxinode);
+#endif
                d.s_inode = strlen(buf);
                (void)snprintf(buf, sizeof(buf), "%lu", maxnlink);
                d.s_nlink = strlen(buf);
@@ -767,7 +829,7 @@ display(FTSENT *p, FTSENT *list)
  * All other levels use the sort function.  Error entries remain unsorted.
  */
 static int
-mastercmp(const FTSENT * const *a, const FTSENT * const *b)
+mastercmp(const FTSENT **a, const FTSENT **b)
 {
        int a_info, b_info;
 
@@ -796,7 +858,7 @@ mastercmp(const FTSENT * const *a, const FTSENT * const *b)
  * into a number that wide in decimal.
  */
 static u_quad_t
-makenines(u_long n)
+makenines(u_quad_t n)
 {
        u_long i;
        u_quad_t reg;
diff --git a/ls/ls.h b/ls/ls.h
index 73e264d1a488e1135848250b4cc6f924abd8c032..6bb1aa2170a3f802e341f7bdd549f6d9f44af6f2 100644 (file)
--- a/ls/ls.h
+++ b/ls/ls.h
 
 #define NO_PRINT       1
 
+#define HN_DECIMAL 0x01
+#define HN_NOSPACE 0x02
+#define HN_B 0x04
+#define HN_DIVISOR_1000 0x08
+
+#define HN_GETSCALE 0x10
+#define HN_AUTOSCALE 0x20
+
 extern long blocksize;         /* block size units */
 
 extern int f_accesstime;       /* use time of last access */
@@ -58,10 +66,13 @@ extern int f_statustime;    /* use time of last mode change */
 extern int f_notabs;           /* don't use tab-separated multi-col output */
 extern int f_type;             /* add type character for non-regular files */
 extern int f_acl;              /* print ACLs in long format */
+extern int f_xattr;            /* print extended attributes in long format  */
 extern int f_group;            /* list group without owner */
+extern int f_owner;            /* list owner without group */
 #ifdef COLORLS
 extern int f_color;            /* add type in color for non-regular files */
 #endif
+extern int f_numericonly;      /* don't convert uid/gid to name */
 
 typedef struct {
        FTSENT *list;
index a9d651e96f8655e6b26d65f8620669dbd0b67b5a..02b1211afa3daff5bc1b051f6625bf45fbc0fae1 100644 (file)
@@ -46,6 +46,7 @@ __RCSID("$FreeBSD: src/bin/ls/print.c,v 1.57 2002/08/29 14:29:09 keramida Exp $"
 #include <sys/stat.h>
 #ifdef __APPLE__
 #include <sys/acl.h>
+#include <sys/xattr.h>
 #include <sys/types.h>
 #include <grp.h>
 #include <pwd.h>
@@ -70,6 +71,12 @@ __RCSID("$FreeBSD: src/bin/ls/print.c,v 1.57 2002/08/29 14:29:09 keramida Exp $"
 #include <signal.h>
 #endif
 
+#ifdef __APPLE__ 
+#include <get_compat.h>
+#else 
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
+
 #include "ls.h"
 #include "extern.h"
 
@@ -85,27 +92,6 @@ static int   colortype(mode_t);
 
 #define        IS_NOPRINT(p)   ((p)->fts_number == NO_PRINT)
 
-#define KILO_SZ(n) (n)
-#define MEGA_SZ(n) ((n) * (n))
-#define GIGA_SZ(n) ((n) * (n) * (n))
-#define TERA_SZ(n) ((n) * (n) * (n) * (n))
-#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
-
-#define KILO_2_SZ (KILO_SZ(1024ULL))
-#define MEGA_2_SZ (MEGA_SZ(1024ULL))
-#define GIGA_2_SZ (GIGA_SZ(1024ULL))
-#define TERA_2_SZ (TERA_SZ(1024ULL))
-#define PETA_2_SZ (PETA_SZ(1024ULL))
-
-static u_int64_t vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
-
-typedef enum {
-       NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX
-} unit_t;
-static unit_t unit_adjust(off_t *);
-
-static int unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA};
-
 #ifdef COLORLS
 /* Most of these are taken from <sys/stat.h> */
 typedef enum Colors {
@@ -139,6 +125,11 @@ printscol(DISPLAY *dp)
 {
        FTSENT *p;
 
+       if (COMPAT_MODE("bin/ls", "Unix2003")) {
+               if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
+                       (void)printf("total %qu\n", (u_int64_t)howmany(dp->btotal, blocksize));
+       }
+
        for (p = dp->list; p; p = p->fts_link) {
                if (IS_NOPRINT(p))
                        continue;
@@ -158,7 +149,7 @@ printname(const char *name)
        else if (f_nonprint)
                return prn_printable(name);
        else
-               return printf("%s", name);
+               return prn_normal(name);
 }
 
 /*
@@ -219,8 +210,10 @@ uuid_to_name(uuid_t *uu)
   if (NULL == name)
          err(1, "malloc");
 
-  if (0 != mbr_uuid_to_id(uu, &id, &is_gid))
+       if (!f_numericonly) {
+  if (0 != mbr_uuid_to_id(*uu, &id, &is_gid))
          goto errout;
+       }
   
   switch (is_gid) {
   case ID_TYPE_UID:
@@ -238,20 +231,43 @@ uuid_to_name(uuid_t *uu)
          snprintf(name, MAXNAMETAG, "%s:%s", "group", tgrp->gr_name);
          break;
   default:
-         if (0 != mbr_uuid_to_string(uu, name))
-                 goto errout;
+               goto errout;
   }
   return name;
  errout:
-  fprintf(stderr, "Unable to translate qualifier on ACL\n");
-  strcpy(name, "<UNKNOWN>");
+       if (0 != mbr_uuid_to_string(*uu, name)) {
+               fprintf(stderr, "Unable to translate qualifier on ACL\n");
+               strcpy(name, "<UNKNOWN>");
+       }
   return name;
 }
 
+static void
+printxattr(DISPLAY *dp, char *filename, ssize_t xattr)
+{
+       int flags = XATTR_NOFOLLOW;
+       char *buf = malloc(xattr);
+
+       if (NULL == buf)
+               err(1, "malloc");
+       if (listxattr(filename, buf, xattr, flags) > 0) {
+               char *name;
+               for (name = buf; name < buf+xattr; name += strlen(name) + 1) {
+                       ssize_t size = getxattr(filename, name, 0, 0, 0, flags);
+                       putchar('\t');
+                       printname(name);
+                       putchar('\t');
+                       printsize(dp->s_size, size);
+                       putchar('\n');
+               }
+       }
+       free(buf);
+}
+
 static void
 printacl(acl_t acl, int isdir)
 {
-       acl_entry_t     entry;
+       acl_entry_t     entry = NULL;
        int             index;
        uuid_t          *applicable;
        char            *name = NULL;
@@ -326,7 +342,11 @@ printlong(DISPLAY *dp)
        char buf[20];
 #ifdef __APPLE__
        acl_t acl = NULL;
+       acl_entry_t dummy;
        char full_path[MAXPATHLEN];
+       char *filename;
+       ssize_t xattr = 0;
+       char str[2];
 #endif
 #ifdef COLORLS
        int color_printed = 0;
@@ -339,34 +359,73 @@ printlong(DISPLAY *dp)
                if (IS_NOPRINT(p))
                        continue;
                sp = p->fts_statp;
-               if (f_inode)
+               if (f_inode) 
+#if _DARWIN_FEATURE_64_BIT_INODE
+                       (void)printf("%*llu ", dp->s_inode, (u_quad_t)sp->st_ino);
+#else
                        (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
+#endif
                if (f_size)
                        (void)printf("%*qu ",
                            dp->s_block, (u_int64_t)howmany(sp->st_blocks, blocksize));
                strmode(sp->st_mode, buf);
                np = p->fts_pointer;
 #ifdef __APPLE__
-               if (p->fts_parent->fts_name && *p->fts_parent->fts_name)
+               buf[10] = '\0'; /* make +/@ abut the mode */
+               filename = p->fts_name;
+               if (p->fts_level != FTS_ROOTLEVEL)
                {
                    snprintf(full_path, sizeof full_path, "%s/%s",
-                           p->fts_parent->fts_accpath, p->fts_accpath);
-                   acl = acl_get_file(full_path, ACL_TYPE_EXTENDED);
-               } else
-                   acl = acl_get_file(p->fts_accpath, ACL_TYPE_EXTENDED);
+                           p->fts_parent->fts_accpath, p->fts_name);
+                   filename = full_path;
+               }
+               /* symlinks can not have ACLs */
+               acl = acl_get_link_np(filename, ACL_TYPE_EXTENDED);
+               if (acl && acl_get_entry(acl, ACL_FIRST_ENTRY, &dummy) == -1) {
+                       acl_free(acl);
+                       acl = NULL;
+               }
+               xattr = listxattr(filename, NULL, 0, XATTR_NOFOLLOW);
+               if (xattr < 0)
+                       xattr = 0;
+               str[1] = '\0';
+               if (xattr > 0)
+                       str[0] = '@';
+               else if (acl != NULL)
+                       str[0] = '+';
+               else
+                       str[0] = ' ';
+#endif /* __APPLE__ */
+               if (f_group && f_owner) {       /* means print neither */
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u   ", buf, str, dp->s_nlink,
+                                    sp->st_nlink);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u   ", buf, dp->s_nlink,
+                                    sp->st_nlink);
 #endif /* __APPLE__ */
-               if (f_group) {
+               }
+               else if (f_group) {
 #ifdef __APPLE__
-                       (void)printf("%s%s %*u %-*s  ", buf, acl == NULL ? " " : "+", dp->s_nlink,
+                       (void)printf("%s%s %*u %-*s  ", buf, str, dp->s_nlink,
                                     sp->st_nlink, dp->s_group, np->group);
 #else  /* ! __APPLE__ */
                        (void)printf("%s %*u %-*s  ", buf, dp->s_nlink,
                                     sp->st_nlink, dp->s_group, np->group);
+#endif /* __APPLE__ */
+               }
+               else if (f_owner) {
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u %-*s  ", buf, str, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u %-*s  ", buf, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user);
 #endif /* __APPLE__ */
                }
                else {
 #ifdef __APPLE__
-                       (void)printf("%s%s %*u %-*s  %-*s  ", buf, acl == NULL ? " " : "+", dp->s_nlink,
+                       (void)printf("%s%s %*u %-*s  %-*s  ", buf, str, dp->s_nlink,
                                     sp->st_nlink, dp->s_user, np->user, dp->s_group,
                                     np->group);
 #else  /* ! __APPLE__ */
@@ -411,9 +470,15 @@ printlong(DISPLAY *dp)
                        printlink(p);
                (void)putchar('\n');
 #ifdef __APPLE__
-               if (f_acl && (acl != NULL))
-                       printacl(acl, S_ISDIR(sp->st_mode));
-               acl_free(acl);
+               if (f_xattr && xattr) {
+                       printxattr(dp, filename, xattr);
+               }
+               if (acl != NULL) {
+                       if (f_acl)
+                               printacl(acl, S_ISDIR(sp->st_mode));
+                       acl_free(acl);
+                       acl = NULL;
+               }
 #endif /* __APPLE__ */
        }
 }
@@ -582,6 +647,14 @@ printtime(time_t ftime)
        if (f_sectime)
                /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
                format = d_first ? "%e %b %T %Y " : "%b %e %T %Y ";
+       else if (COMPAT_MODE("bin/ls", "Unix2003")) {
+               if (ftime + SIXMONTHS > now && ftime <= now)
+                       /* mmm dd hh:mm || dd mmm hh:mm */
+                       format = d_first ? "%e %b %R " : "%b %e %R ";
+               else
+                       /* mmm dd  yyyy || dd mmm  yyyy */
+                       format = d_first ? "%e %b  %Y " : "%b %e  %Y ";
+       }
        else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS)
                /* mmm dd hh:mm || dd mmm hh:mm */
                format = d_first ? "%e %b %R " : "%b %e %R ";
@@ -800,43 +873,13 @@ printlink(FTSENT *p)
 static void
 printsize(size_t width, off_t bytes)
 {
-       unit_t unit;
 
-       if (f_humanval) {
-               unit = unit_adjust(&bytes);
-
-               if (bytes == 0)
-                       (void)printf("%*s ", (int)width, "0B");
-               else
-                       (void)printf("%*lld%c ", (int)width - 1, bytes,
-                           "BKMGTPE"[unit]);
-       } else
-               (void)printf("%*lld ", (int)width, bytes);
-}
-
-/*
- * Output in "human-readable" format.  Uses 3 digits max and puts
- * unit suffixes at the end.  Makes output compact and easy to read,
- * especially on huge disks.
- *
- */
-unit_t
-unit_adjust(off_t *val)
-{
-       double abval;
-       unit_t unit;
-       unsigned int unit_sz;
-
-       abval = fabs((double)*val);
-
-       unit_sz = abval ? ilogb(abval) / 10 : 0;
-
-       if (unit_sz >= UNIT_MAX) {
-               unit = NONE;
-       } else {
-               unit = unitp[unit_sz];
-               *val /= (double)vals_base2[unit_sz];
-       }
+  if (f_humanval) {
+    char buf[5];
 
-       return (unit);
+    humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
+                   HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+    (void)printf("%5s ", buf);
+  } else
+    (void)printf("%*jd ", (u_int)width, bytes);
 }
index e74fa61be5fec638306c7ff42e08149f08c7d914..7f8830ab5353d8fdd7c20a37a72cac58d333e352 100644 (file)
--- a/ls/util.c
+++ b/ls/util.c
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 1989, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
  * 4. 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.
@@ -39,8 +35,8 @@
 static char sccsid[] = "@(#)util.c     8.3 (Berkeley) 4/2/94";
 #endif /* not lint */
 #endif
-#include <sys/types.h>
-__RCSID("$FreeBSD: src/bin/ls/util.c,v 1.30 2002/06/30 05:13:54 obrien Exp $");
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/bin/ls/util.c,v 1.38 2005/06/03 11:05:58 dd Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -48,25 +44,82 @@ __RCSID("$FreeBSD: src/bin/ls/util.c,v 1.30 2002/06/30 05:13:54 obrien Exp $");
 #include <ctype.h>
 #include <err.h>
 #include <fts.h>
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #include "ls.h"
 #include "extern.h"
 
+int
+prn_normal(const char *s)
+{
+       mbstate_t mbs;
+       wchar_t wc;
+       int i, n;
+       size_t clen;
+
+       memset(&mbs, 0, sizeof(mbs));
+       n = 0;
+       while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
+               if (clen == (size_t)-2) {
+                       n += printf("%s", s);
+                       break;
+               }
+               if (clen == (size_t)-1) {
+                       memset(&mbs, 0, sizeof(mbs));
+                       putchar((unsigned char)*s);
+                       s++;
+                       n++;
+                       continue;
+               }
+               for (i = 0; i < (int)clen; i++)
+                       putchar((unsigned char)s[i]);
+               s += clen;
+               if (iswprint(wc))
+                       n += wcwidth(wc);
+       }
+       return (n);
+}
+
 int
 prn_printable(const char *s)
 {
-       char c;
-       int n;
+       mbstate_t mbs;
+       wchar_t wc;
+       int i, n;
+       size_t clen;
 
-       for (n = 0; (c = *s) != '\0'; ++s, ++n)
-               if (isprint((unsigned char)c))
-                       putchar(c);
-               else
+       memset(&mbs, 0, sizeof(mbs));
+       n = 0;
+       while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
+               if (clen == (size_t)-1) {
                        putchar('?');
-       return n;
+                       s++;
+                       n++;
+                       memset(&mbs, 0, sizeof(mbs));
+                       continue;
+               }
+               if (clen == (size_t)-2) {
+                       putchar('?');
+                       n++;
+                       break;
+               }
+               if (!iswprint(wc)) {
+                       putchar('?');
+                       s += clen;
+                       n++;
+                       continue;
+               }
+               for (i = 0; i < (int)clen; i++)
+                       putchar((unsigned char)s[i]);
+               s += clen;
+               n += wcwidth(wc);
+       }
+       return (n);
 }
 
 /*
@@ -85,70 +138,83 @@ prn_printable(const char *s)
 size_t
 len_octal(const char *s, int len)
 {
-       size_t r = 0;
+       mbstate_t mbs;
+       wchar_t wc;
+       size_t clen, r;
 
-       while (len--)
-               if (isprint((unsigned const char)*s++)) r++; else r += 4;
-       return r;
+       memset(&mbs, 0, sizeof(mbs));
+       r = 0;
+       while (len != 0 && (clen = mbrtowc(&wc, s, len, &mbs)) != 0) {
+               if (clen == (size_t)-1) {
+                       r += 4;
+                       s++;
+                       len--;
+                       memset(&mbs, 0, sizeof(mbs));
+                       continue;
+               }
+               if (clen == (size_t)-2) {
+                       r += 4 * len;
+                       break;
+               }
+               if (iswprint(wc))
+                       r++;
+               else
+                       r += 4 * clen;
+               s += clen;
+       }
+       return (r);
 }
 
 int
 prn_octal(const char *s)
 {
-        unsigned char ch;
-       int len = 0;
+       static const char esc[] = "\\\\\"\"\aa\bb\ff\nn\rr\tt\vv";
+       const char *p;
+       mbstate_t mbs;
+       wchar_t wc;
+       size_t clen;
+       unsigned char ch;
+       int goodchar, i, len, prtlen;
        
-        while ((ch = (unsigned char)*s++)) {
-               if (isprint(ch) && (ch != '\"') && (ch != '\\'))
-                       putchar(ch), len++;
-               else if (f_octal_escape) {
-                       putchar('\\');
-                       switch (ch) {
-                       case '\\':
-                               putchar('\\');
-                               break;
-                       case '\"':
-                               putchar('"');
-                               break;
-                       case '\a':
-                               putchar('a');
-                               break;
-                       case '\b':
-                               putchar('b');
-                               break;
-                       case '\f':
-                               putchar('f');
-                               break;
-                       case '\n':
-                               putchar('n');
-                               break;
-                       case '\r':
-                               putchar('r');
-                               break;
-                       case '\t':
-                               putchar('t');
-                               break;
-                       case '\v':
-                               putchar('v');
-                               break;
-                       default:
+       memset(&mbs, 0, sizeof(mbs));
+       len = 0;
+       while ((clen = mbrtowc(&wc, s, MB_LEN_MAX, &mbs)) != 0) {
+               goodchar = clen != (size_t)-1 && clen != (size_t)-2;
+               if (goodchar && iswprint(wc) && wc != L'\"' && wc != L'\\') {
+                       for (i = 0; i < (int)clen; i++)
+                               putchar((unsigned char)s[i]);
+                       len += wcwidth(wc);
+               } else if (goodchar && f_octal_escape && wc >= 0 &&
+                   wc <= (wchar_t)UCHAR_MAX &&
+                   (p = strchr(esc, (char)wc)) != NULL) {
+                       putchar('\\');
+                       putchar(p[1]);
+                       len += 2;
+               } else {
+                       if (goodchar)
+                               prtlen = clen;
+                       else if (clen == (size_t)-1)
+                               prtlen = 1;
+                       else
+                               prtlen = strlen(s);
+                       for (i = 0; i < prtlen; i++) {
+                               ch = (unsigned char)s[i];
+                               putchar('\\');
                                putchar('0' + (ch >> 6));
                                putchar('0' + ((ch >> 3) & 7));
                                putchar('0' + (ch & 7));
-                               len += 2;
-                               break;
-                       }
-                       len += 2;
-               }
-               else {
-                       putchar('\\');
-                       putchar('0' + (ch >> 6));
-                       putchar('0' + ((ch >> 3) & 7));
-                       putchar('0' + (ch & 7));
-                       len += 4;
+                               len += 4;
+                       }
                }
+               if (clen == (size_t)-2)
+                       break;
+               if (clen == (size_t)-1) {
+                       memset(&mbs, 0, sizeof(mbs));
+                       s++;
+               } else
+                       s += clen;
        }
-       return len;
+       return (len);
 }
 
 void
@@ -156,9 +222,9 @@ usage(void)
 {
        (void)fprintf(stderr,
 #ifdef COLORLS
-       "usage: ls [-ABCFGHLPRSTWZabcdefghiklmnopqrstuwx1]"
+       "usage: ls [-ABCFGHLPRSTWabcdefghiklmnopqrstuwx1]"
 #else
-       "usage: ls [-ABCFHLPRSTWZabcdefghiklmnopqrstuwx1]"
+       "usage: ls [-ABCFHLPRSTWabcdefghiklmnopqrstuwx1]"
 #endif
                      " [file ...]\n");
        exit(1);
index 1bb430d2e8430fc0cdaaf4abb44356e0226dcf0f..e76e92b65556e8aeeecbe402677debe7954c7981 100644 (file)
@@ -113,7 +113,7 @@ main(int argc, char *argv[])
                                warn("%s", *argv);
                        success = 0;
                } else if (vflag)
-                       (void)printf("%s\n", *argv);
+                       (void)printf("mkdir: created directory '%s'\n", *argv);
                
                if (!success)
                        exitval = 1;
index f8a0e1610e47cbcd5acb547a293566a968acf1b9..16565032d81d2a30aae16fb005bfc6c2b18e6a58 100644 (file)
 .Nm mkfifo
 .Nd make fifos
 .Sh SYNOPSIS
-.Nm
+.Nm mkfifo
 .Op Fl m Ar mode
 .Ar fifo_name  ...
 .Sh DESCRIPTION
-.Nm
-creates the fifos requested, in the order specified,
-using mode
-.Li \&0666 
-modified by the current
+.Nm mkfifo
+creates the fifos requested, in the order specified.
+By default,
+the resulting fifos have mode
+.Li \&0666
+(rw-rw-rw-), limited by the current
 .Xr umask 2 .
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl m
-Set the file permission bits of newly-created directories to
-.Ar mode .
+Set the file permission bits of newly-created fifos to
+.Ar mode ,
+without respect to the current umask.
+.Pp
 The mode is specified as in 
 .Xr chmod 1 .
 In symbolic mode strings, the 
@@ -69,23 +72,29 @@ operators are interpreted relative to an assumed initial mode of
 .Dq a=rw
 .El
 .Pp
-.Nm
+.Nm mkfifo
 requires write permission in the parent directory.
 .Pp
-.Nm
-exits 0 if successful, and >0 if an error occurred.
+.Nm mkfifo
+exits with 0 if successful, and with >0 if an error occurred.
+.Sh LEGACY DESCRIPTION
+In legacy mode, the fifo's file permission bits
+are always limited by the current umask.
 .Sh SEE ALSO
 .Xr mkdir 1 ,
 .Xr rm 1 ,
+.Xr umask 1 ,
 .Xr mkfifo 2 ,
+.Xr umask 2 ,
+.Xr compat 5 ,
 .Xr mknod 8
 .Sh STANDARDS
 The
-.Nm
+.Nm mkfifo
 utility is expected to be
 .St -p1003.2-92
 compliant.
 .Sh HISTORY
-.Nm
+.Nm mkfifo
 command appeared in
 .Bx 4.4 .
index 6bd45b0dfdd4c51dc676341e05e0c743659f97f9..0abbd7048b9cf80ebb37596b8d082a32d95e6807 100644 (file)
@@ -55,6 +55,11 @@ __RCSID("$NetBSD: mkfifo.c,v 1.8 1997/10/19 05:11:54 lukem Exp $");
 #include <sys/stat.h>
 #include <unistd.h>
 #include <err.h>
+#ifdef __APPLE__
+#include <get_compat.h>
+#else 
+#define COMPAT_MODE(a,b) (1) 
+#endif /* __APPLE__ */ 
 
 int    main __P((int, char **));
 static void usage __P((void));
@@ -67,17 +72,21 @@ main(argc, argv)
        int ch, exitval;
        void * set;
        mode_t mode;
+       int m_used = 0;
 
        setlocale (LC_ALL, "");
 
        /* The default mode is the value of the bitwise inclusive or of
           S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH
           modified by the file creation mask */
-       mode = 0666 & ~umask(0);
+       if (!COMPAT_MODE("bin/mkfifo", "Unix2003")) {
+               mode = 0666 & ~umask(0);
+       }
 
        while ((ch = getopt(argc, argv, "m:")) != -1)
                switch(ch) {
                case 'm':
+                       m_used = 1;
                        if (!(set = setmode(optarg))) {
                                errx(1, "invalid file mode.");
                                /* NOTREACHED */
@@ -96,6 +105,12 @@ main(argc, argv)
        if (argv[0] == NULL)
                usage();
 
+       if (COMPAT_MODE("bin/mkfifo", "Unix2003")) {
+               mode_t maskbits = umask(0);     /* now must disable umask so -m mode won't be masked again */
+               if (!m_used)
+                       mode = 0666 & ~maskbits;
+       }
+
        for (exitval = 0; *argv; ++argv) {
                if (mkfifo(*argv, mode) < 0) {
                        warn("%s", *argv);
index d68dab1f4b17ee24a390dd73a155e207b39a3d79..9e5e9ebc6c0834148e8f28ce21af88a80323f435 100644 (file)
@@ -54,6 +54,9 @@
 .Ar name
 .Op Cm c | Cm b
 .Ar number
+.Nm
+.Ar name
+.Ar w
 .Sh DESCRIPTION
 The
 .Nm
@@ -74,12 +77,14 @@ Device name, for example
 for a SCSI disk on an HP300 or a
 .Dq pty
 for pseudo-devices.
-.It Cm b | Cm c
+.It Cm b | Cm c | Cm w
 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 .
+Whiteout nodes are type
+.Cm w .
 All other devices are character type devices, such as terminal
 and pseudo devices, and are type
 .Cm c .
index 884b8e5fea7571a558740d1010c9d62e9fbc8471..0f080054efffde61f3fca3f706b42af61f789318 100644 (file)
@@ -348,7 +348,7 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
-       if (argc < 3 || argc > 10)
+       if (argc < 2 || argc > 10)
                usage();
 
        name = *argv;
@@ -360,18 +360,25 @@ main(argc, argv)
                mode |= S_IFCHR;
        else if (*argv[0] == 'b')
                mode |= S_IFBLK;
+       else if (*argv[0] == 'w')
+               mode |= S_IFWHT;
        else
-               errx(1, "node type must be 'b' or 'c'.");
+               errx(1, "node type must be 'b' or 'c' or 'w'.");
        argc--;
        argv++;
 
        for (n = 0; n < argc; n++) {
+               if (S_ISWHT(mode)) {
+                       errx(1, "whiteout nodes have no device numbers.");
+               }
                numbers[n] = strtoul(argv[n], &p, 0);
                if ((p && *p != '\0') || (numbers[n] == ULONG_MAX && errno == ERANGE))
                        errx(1, "invalid number: %s", argv[n]);
        }
 
-       if (argc == 1)
+       if (S_ISWHT(mode))
+               dev = 0;
+       else if (argc == 1)
                dev = numbers[0];
        else
                dev = (*pack)(argc, numbers);
@@ -393,5 +400,6 @@ usage()
        fprintf(stderr, "usage: mknod [-F format] name [b | c] major minor\n");
        fprintf(stderr, "       mknod [-F format] name [b | c] major unit subunit\n");
        fprintf(stderr, "       mknod name [b | c] number\n");
+       fprintf(stderr, "       mknod name w\n");
        exit(1);
 }
index 6917e8fd3f49a6f3a0f17dcd9a660a1c525ebf86..dbee24e7da85f595656080d77ffe9a4f57dad226 100644 (file)
@@ -14,16 +14,17 @@ PROJECT_TYPE = Tool
 
 HFILES = extern.h mtree.h
 
-CFILES = compare.c create.c excludes.c misc.c mtree.c spec.c verify.c
+CFILES = compare.c create.c excludes.c misc.c mtree.c spec.c specspec.c verify.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble mtree.8
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID -DENABLE_MD5 -DENABLE_RMD160 -DENABLE_SHA1
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
 MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/sbin
-LIBS = 
+LIBS = -lmd -lcrypto
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index 8f9591d092410c582137c46477c7e44dad840c31..69cad5f6c46d385c592fea79fd97aaeaa3575856 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)compare.c  8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/compare.c,v 1.15.2.3 2001/01/12 19:17:18 phk Exp $";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/compare.c,v 1.34 2005/03/29 11:44:17 tobez Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/time.h>
+
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fts.h>
-#ifdef MD5
+#ifdef ENABLE_MD5
 #include <md5.h>
 #endif
-#ifdef SHA1
+#ifdef ENABLE_RMD160
+#include <ripemd.h>
+#endif
+#ifdef ENABLE_SHA1
 #include <sha.h>
 #endif
-#ifdef RMD160
-#include <ripemd.h>
+#ifdef ENABLE_SHA256
+#include <sha256.h>
 #endif
+#include <stdint.h>
 #include <stdio.h>
 #include <time.h>
 #include <unistd.h>
+#include <vis.h>
+
 #include "mtree.h"
 #include "extern.h"
 
-extern int uflag;
-extern int lineno;
-
-static char *ftype __P((u_int));
-
 #define        INDENTNAMELEN   8
 #define        LABEL \
        if (!label++) { \
@@ -73,15 +72,14 @@ static char *ftype __P((u_int));
        }
 
 int
-compare(name, s, p)
-       char *name;
-       register NODE *s;
-       register FTSENT *p;
+compare(char *name __unused, NODE *s, FTSENT *p)
 {
-       extern int uflag;
-       u_long len, val;
+       struct timeval tv[2];
+       uint32_t val;
        int fd, label;
-       char *cp, *tab = "";
+       off_t len;
+       char *cp;
+       const char *tab = "";
        char *fflags;
 
        label = 0;
@@ -174,8 +172,8 @@ typeerr:            LABEL;
        if (s->flags & F_SIZE && s->st_size != p->fts_statp->st_size &&
                !S_ISDIR(p->fts_statp->st_mode)) {
                LABEL;
-               (void)printf("%ssize expected %qd found %qd\n",
-                   tab, s->st_size, p->fts_statp->st_size);
+               (void)printf("%ssize expected %jd found %jd\n", tab,
+                   (intmax_t)s->st_size, (intmax_t)p->fts_statp->st_size);
                tab = "\t";
        }
        /*
@@ -188,8 +186,19 @@ typeerr:           LABEL;
                LABEL;
                (void)printf("%smodification time expected %.24s ",
                    tab, ctime(&s->st_mtimespec.tv_sec));
-               (void)printf("found %.24s\n",
+               (void)printf("found %.24s",
                    ctime(&p->fts_statp->st_mtimespec.tv_sec));
+               if (uflag) {
+                       tv[0].tv_sec = s->st_mtimespec.tv_sec;
+                       tv[0].tv_usec = s->st_mtimespec.tv_nsec / 1000;
+                       tv[1] = tv[0];
+                       if (utimes(p->fts_accpath, tv))
+                               (void)printf(" not modified: %s\n",
+                                   strerror(errno));
+                       else
+                               (void)printf(" modified\n");
+               } else
+                       (void)printf("\n");
                tab = "\t";
        }
        if (s->flags & F_CKSUM) {
@@ -209,17 +218,11 @@ typeerr:          LABEL;
                        if (s->cksum != val) {
                                LABEL;
                                (void)printf("%scksum expected %lu found %lu\n",
-                                   tab, s->cksum, val);
+                                   tab, s->cksum, (unsigned long)val);
+                               tab = "\t";
                        }
-                       tab = "\t";
                }
        }
-       /*
-        * XXX
-        * since chflags(2) will reset file times, the utimes() above
-        * may have been useless!  oh well, we'd rather have correct
-        * flags, rather than times?
-        */
        if ((s->flags & F_FLAGS) && s->st_flags != p->fts_statp->st_flags) {
                LABEL;
                fflags = flags_to_string(s->st_flags);
@@ -240,7 +243,7 @@ typeerr:            LABEL;
                        (void)printf("\n");
                tab = "\t";
        }
-#ifdef MD5
+#ifdef ENABLE_MD5
        if (s->flags & F_MD5) {
                char *new_digest, buf[33];
 
@@ -257,8 +260,8 @@ typeerr:            LABEL;
                        tab = "\t";
                }
        }
-#endif /* MD5 */
-#ifdef SHA1
+#endif /* ENABLE_MD5 */
+#ifdef ENABLE_SHA1
        if (s->flags & F_SHA1) {
                char *new_digest, buf[41];
 
@@ -270,13 +273,13 @@ typeerr:          LABEL;
                        tab = "\t";
                } else if (strcmp(new_digest, s->sha1digest)) {
                        LABEL;
-                       printf("%sSHA-1 expected %s found %s\n", 
+                       printf("%sSHA-1 expected %s found %s\n",
                               tab, s->sha1digest, new_digest);
                        tab = "\t";
                }
        }
-#endif /* SHA1 */
-#ifdef RMD160
+#endif /* ENABLE_SHA1 */
+#ifdef ENABLE_RMD160
        if (s->flags & F_RMD160) {
                char *new_digest, buf[41];
 
@@ -293,20 +296,37 @@ typeerr:          LABEL;
                        tab = "\t";
                }
        }
-#endif /* RMD160 */
+#endif /* ENABLE_RMD160 */
+#ifdef ENABLE_SHA256
+       if (s->flags & F_SHA256) {
+               char *new_digest, buf[65];
+
+               new_digest = SHA256_File(p->fts_accpath, buf);
+               if (!new_digest) {
+                       LABEL;
+                       printf("%sSHA-256: %s: %s\n", tab, p->fts_accpath,
+                              strerror(errno));
+                       tab = "\t";
+               } else if (strcmp(new_digest, s->sha256digest)) {
+                       LABEL;
+                       printf("%sSHA-256 expected %s found %s\n",
+                              tab, s->sha256digest, new_digest);
+                       tab = "\t";
+               }
+       }
+#endif /* ENABLE_SHA256 */
 
        if (s->flags & F_SLINK &&
            strcmp(cp = rlink(p->fts_accpath), s->slink)) {
                LABEL;
                (void)printf("%slink_ref expected %s found %s\n",
-                     tab, cp, s->slink);
+                     tab, s->slink, cp);
        }
        return (label);
 }
 
-char *
-inotype(type)
-       u_int type;
+const char *
+inotype(u_int type)
 {
        switch(type & S_IFMT) {
        case S_IFBLK:
@@ -329,9 +349,8 @@ inotype(type)
        /* NOTREACHED */
 }
 
-static char *
-ftype(type)
-       u_int type;
+const char *
+ftype(u_int type)
 {
        switch(type) {
        case F_BLOCK:
@@ -355,14 +374,15 @@ ftype(type)
 }
 
 char *
-rlink(name)
-       char *name;
+rlink(char *name)
 {
-       static char lbuf[MAXPATHLEN];
-       register int len;
+       static char lbuf[MAXPATHLEN * 4];
+       int len;
+       char tbuf[MAXPATHLEN];
 
-       if ((len = readlink(name, lbuf, sizeof(lbuf) - 1)) == -1)
+       if ((len = readlink(name, tbuf, sizeof(tbuf) - 1)) == -1)
                err(1, "line %d: %s", lineno, name);
-       lbuf[len] = '\0';
+       tbuf[len] = '\0';
+       strvis(lbuf, tbuf, VIS_WHITE | VIS_OCTAL);
        return (lbuf);
 }
index f755accadcd99af91df135ea5afb2991da0cccf6..886095558331bf80e63bf9d1fe148f730cdf30fe 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)create.c   8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/create.c,v 1.18.2.3 2001/01/12 19:17:18 phk Exp $";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/create.c,v 1.37 2005/03/29 11:44:17 tobez Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -47,16 +43,20 @@ static const char rcsid[] =
 #include <fcntl.h>
 #include <fts.h>
 #include <grp.h>
-#ifdef MD5
+#ifdef ENABLE_MD5
 #include <md5.h>
 #endif
-#ifdef SHA1
+#ifdef ENABLE_SHA1
 #include <sha.h>
 #endif
-#ifdef RMD160
+#ifdef ENABLE_RMD160
 #include <ripemd.h>
 #endif
+#ifdef ENABLE_SHA256
+#include <sha256.h>
+#endif
 #include <pwd.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <time.h>
 #include <unistd.h>
@@ -67,43 +67,41 @@ static const char rcsid[] =
 #define        INDENTNAMELEN   15
 #define        MAXLINELEN      80
 
-extern long int crc_total;
-extern int ftsoptions;
-extern int dflag, iflag, nflag, sflag;
-extern u_int keys;
-extern char fullpath[MAXPATHLEN];
-extern int lineno;
-
 static gid_t gid;
 static uid_t uid;
 static mode_t mode;
 static u_long flags = 0xffffffff;
 
-static int     dsort __P((const FTSENT **, const FTSENT **));
-static void    output __P((int, int *, const char *, ...));
-static int     statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *,
-                          u_long *));
-static void    statf __P((int, FTSENT *));
+static int     dsort(const FTSENT * const *, const FTSENT * const *);
+static void    output(int, int *, const char *, ...) __printflike(3, 4);
+static int     statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *);
+static void    statf(int, FTSENT *);
 
 void
-cwalk()
+cwalk(void)
 {
-       register FTS *t;
-       register FTSENT *p;
-       time_t clock;
+       FTS *t;
+       FTSENT *p;
+       time_t cl;
        char *argv[2], host[MAXHOSTNAMELEN];
+       char dot[] = ".";
        int indent = 0;
 
-       (void)time(&clock);
-       (void)gethostname(host, sizeof(host));
-       (void)printf(
-           "#\t   user: %s\n#\tmachine: %s\n#\t   tree: %s\n#\t   date: %s",
-           getlogin(), host, fullpath, ctime(&clock));
+       if (!nflag) {
+               (void)time(&cl);
+               (void)gethostname(host, sizeof(host));
+               (void)printf(
+                   "#\t   user: %s\n#\tmachine: %s\n",
+                   getlogin(), host);
+               (void)printf(
+                   "#\t   tree: %s\n#\t   date: %s",
+                   fullpath, ctime(&cl));
+       }
 
-       argv[0] = ".";
+       argv[0] = dot;
        argv[1] = NULL;
        if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
-               err(1, "line %d: fts_open", lineno);
+               err(1, "fts_open()");
        while ((p = fts_read(t))) {
                if (iflag)
                        indent = p->fts_level * 4;
@@ -141,17 +139,16 @@ cwalk()
        }
        (void)fts_close(t);
        if (sflag && keys & F_CKSUM)
-               warnx("%s checksum: %lu", fullpath, crc_total);
+               warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
 }
 
 static void
-statf(indent, p)
-       int indent;
-       FTSENT *p;
+statf(int indent, FTSENT *p)
 {
        struct group *gr;
        struct passwd *pw;
-       u_long len, val;
+       uint32_t val;
+       off_t len;
        int fd, offset;
        char *fflags;
        char *escaped_name;
@@ -159,13 +156,13 @@ statf(indent, p)
        escaped_name = calloc(1, p->fts_namelen * 4  +  1);
        if (escaped_name == NULL)
                errx(1, "statf(): calloc() failed");
-       strvis(escaped_name, p->fts_name, VIS_WHITE | VIS_OCTAL);
+       strvis(escaped_name, p->fts_name, VIS_WHITE | VIS_OCTAL | VIS_GLOB);
 
        if (iflag || S_ISDIR(p->fts_statp->st_mode))
                offset = printf("%*s%s", indent, "", escaped_name);
        else
                offset = printf("%*s    %s", indent, "", escaped_name);
-       
+
        free(escaped_name);
 
        if (offset > (INDENTNAMELEN + indent))
@@ -177,26 +174,32 @@ statf(indent, p)
                output(indent, &offset, "type=%s", inotype(p->fts_statp->st_mode));
        if (p->fts_statp->st_uid != uid) {
                if (keys & F_UNAME) {
-                       if ((pw = getpwuid(p->fts_statp->st_uid)) != NULL) {
+                       pw = getpwuid(p->fts_statp->st_uid);
+                       if (pw != NULL)
                                output(indent, &offset, "uname=%s", pw->pw_name);
-                       } else {
+                       else if (wflag)
+                               warnx("Could not get uname for uid=%u",
+                                   p->fts_statp->st_uid);
+                       else
                                errx(1,
-                               "line %d: could not get uname for uid=%u",
-                               lineno, p->fts_statp->st_uid);
-                       }
+                                   "Could not get uname for uid=%u",
+                                   p->fts_statp->st_uid);
                }
                if (keys & F_UID)
                        output(indent, &offset, "uid=%u", p->fts_statp->st_uid);
        }
        if (p->fts_statp->st_gid != gid) {
                if (keys & F_GNAME) {
-                       if ((gr = getgrgid(p->fts_statp->st_gid)) != NULL) {
+                       gr = getgrgid(p->fts_statp->st_gid);
+                       if (gr != NULL)
                                output(indent, &offset, "gname=%s", gr->gr_name);
-                       } else {
+                       else if (wflag)
+                               warnx("Could not get gname for gid=%u",
+                                   p->fts_statp->st_gid);
+                       else
                                errx(1,
-                               "line %d: could not get gname for gid=%u",
-                               lineno, p->fts_statp->st_gid);
-                       }
+                                   "Could not get gname for gid=%u",
+                                   p->fts_statp->st_gid);
                }
                if (keys & F_GID)
                        output(indent, &offset, "gid=%u", p->fts_statp->st_gid);
@@ -206,54 +209,59 @@ statf(indent, p)
        if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
                output(indent, &offset, "nlink=%u", p->fts_statp->st_nlink);
        if (keys & F_SIZE)
-               output(indent, &offset, "size=%qd", p->fts_statp->st_size);
+               output(indent, &offset, "size=%jd",
+                   (intmax_t)p->fts_statp->st_size);
        if (keys & F_TIME)
                output(indent, &offset, "time=%ld.%ld",
-                   p->fts_statp->st_mtimespec.tv_sec,
+                   (long)p->fts_statp->st_mtimespec.tv_sec,
                    p->fts_statp->st_mtimespec.tv_nsec);
        if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
                if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
                    crc(fd, &val, &len))
-                       err(1, "line %d: %s", lineno, p->fts_accpath);
+                       err(1, "%s", p->fts_accpath);
                (void)close(fd);
-               output(indent, &offset, "cksum=%lu", val);
+               output(indent, &offset, "cksum=%lu", (unsigned long)val);
        }
-#ifdef MD5
+#ifdef ENABLE_MD5
        if (keys & F_MD5 && S_ISREG(p->fts_statp->st_mode)) {
                char *digest, buf[33];
 
                digest = MD5File(p->fts_accpath, buf);
-               if (!digest) {
-                       err(1, "line %d: %s", lineno, p->fts_accpath);
-               } else {
-                       output(indent, &offset, "md5digest=%s", digest);
-               }
+               if (!digest)
+                       err(1, "%s", p->fts_accpath);
+               output(indent, &offset, "md5digest=%s", digest);
        }
-#endif /* MD5 */
-#ifdef SHA1
+#endif /* ENABLE_MD5 */
+#ifdef ENABLE_SHA1
        if (keys & F_SHA1 && S_ISREG(p->fts_statp->st_mode)) {
                char *digest, buf[41];
 
                digest = SHA1_File(p->fts_accpath, buf);
-               if (!digest) {
-                       err(1, "line %d: %s", lineno, p->fts_accpath);
-               } else {
-                       output(indent, &offset, "sha1digest=%s", digest);
-               }
+               if (!digest)
+                       err(1, "%s", p->fts_accpath);
+               output(indent, &offset, "sha1digest=%s", digest);
        }
-#endif /* SHA1 */
-#ifdef RMD160
+#endif /* ENABLE_SHA1 */
+#ifdef ENABLE_RMD160
        if (keys & F_RMD160 && S_ISREG(p->fts_statp->st_mode)) {
                char *digest, buf[41];
 
                digest = RIPEMD160_File(p->fts_accpath, buf);
-               if (!digest) {
-                       err(1, "line %d: %s", lineno, p->fts_accpath);
-               } else {
-                       output(indent, &offset, "ripemd160digest=%s", digest);
-               }
+               if (!digest)
+                       err(1, "%s", p->fts_accpath);
+               output(indent, &offset, "ripemd160digest=%s", digest);
        }
-#endif /* RMD160 */
+#endif /* ENABLE_RMD160 */
+#ifdef ENABLE_SHA256
+       if (keys & F_SHA256 && S_ISREG(p->fts_statp->st_mode)) {
+               char *digest, buf[65];
+
+               digest = SHA256_File(p->fts_accpath, buf);
+               if (!digest)
+                       err(1, "%s", p->fts_accpath);
+               output(indent, &offset, "sha256digest=%s", digest);
+       }
+#endif /* ENABLE_SHA256 */
        if (keys & F_SLINK &&
            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
                output(indent, &offset, "link=%s", rlink(p->fts_accpath));
@@ -272,19 +280,13 @@ statf(indent, p)
 #define        MAXS 16
 
 static int
-statd(t, parent, puid, pgid, pmode, pflags)
-       FTS *t;
-       FTSENT *parent;
-       uid_t *puid;
-       gid_t *pgid;
-       mode_t *pmode;
-       u_long *pflags;
+statd(FTS *t, FTSENT *parent, uid_t *puid, gid_t *pgid, mode_t *pmode, u_long *pflags)
 {
-       register FTSENT *p;
-       register gid_t sgid;
-       register uid_t suid;
-       register mode_t smode;
-       register u_long sflags;
+       FTSENT *p;
+       gid_t sgid;
+       uid_t suid;
+       mode_t smode;
+       u_long sflags;
        struct group *gr;
        struct passwd *pw;
        gid_t savegid = *pgid;
@@ -298,7 +300,7 @@ statd(t, parent, puid, pgid, pmode, pflags)
 
        if ((p = fts_children(t, 0)) == NULL) {
                if (errno)
-                       err(1, "line %d: %s", lineno, RP(parent));
+                       err(1, "%s", RP(parent));
                return (1);
        }
 
@@ -348,7 +350,7 @@ statd(t, parent, puid, pgid, pmode, pflags)
         */
        if ((((keys & F_UNAME) | (keys & F_UID)) && (*puid != saveuid)) ||
            (((keys & F_GNAME) | (keys & F_GID)) && (*pgid != savegid)) ||
-           ((keys & F_MODE) && (*pmode != savemode)) || 
+           ((keys & F_MODE) && (*pmode != savemode)) ||
            ((keys & F_FLAGS) && (*pflags != saveflags)) ||
            (first)) {
                first = 0;
@@ -357,22 +359,24 @@ statd(t, parent, puid, pgid, pmode, pflags)
                else
                        (void)printf("/set type=file");
                if (keys & F_UNAME) {
-                       if ((pw = getpwuid(saveuid)) != NULL)
+                       pw = getpwuid(saveuid);
+                       if (pw != NULL)
                                (void)printf(" uname=%s", pw->pw_name);
+                       else if (wflag)
+                               warnx( "Could not get uname for uid=%u", saveuid);
                        else
-                               errx(1,
-                               "line %d: could not get uname for uid=%u",
-                               lineno, saveuid);
+                               errx(1, "Could not get uname for uid=%u", saveuid);
                }
                if (keys & F_UID)
                        (void)printf(" uid=%lu", (u_long)saveuid);
                if (keys & F_GNAME) {
-                       if ((gr = getgrgid(savegid)) != NULL)
+                       gr = getgrgid(savegid);
+                       if (gr != NULL)
                                (void)printf(" gname=%s", gr->gr_name);
+                       else if (wflag)
+                               warnx("Could not get gname for gid=%u", savegid);
                        else
-                               errx(1,
-                               "line %d: could not get gname for gid=%u",
-                               lineno, savegid);
+                               errx(1, "Could not get gname for gid=%u", savegid);
                }
                if (keys & F_GID)
                        (void)printf(" gid=%lu", (u_long)savegid);
@@ -395,8 +399,7 @@ statd(t, parent, puid, pgid, pmode, pflags)
 }
 
 static int
-dsort(a, b)
-       const FTSENT **a, **b;
+dsort(const FTSENT * const *a, const FTSENT * const *b)
 {
        if (S_ISDIR((*a)->fts_statp->st_mode)) {
                if (!S_ISDIR((*b)->fts_statp->st_mode))
@@ -406,30 +409,14 @@ dsort(a, b)
        return (strcmp((*a)->fts_name, (*b)->fts_name));
 }
 
-#if __STDC__
 #include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 
 void
-#if __STDC__
 output(int indent, int *offset, const char *fmt, ...)
-#else
-output(indent, offset, fmt, va_alist)
-       int indent;
-       int *offset;
-       char *fmt;
-        va_dcl
-#endif
 {
        va_list ap;
        char buf[1024];
-#if __STDC__
        va_start(ap, fmt);
-#else
-       va_start(ap);
-#endif
        (void)vsnprintf(buf, sizeof(buf), fmt, ap);
        va_end(ap);
 
index afdb6e45b71036daea253076108b3b5fb35c0de6..89047711fc109132f9502975c6600e0e6262c21b 100644 (file)
@@ -12,7 +12,7 @@
  * no representations about the suitability of this software for any
  * purpose.  It is provided "as is" without express or implied
  * warranty.
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
  * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@@ -27,8 +27,8 @@
  * SUCH DAMAGE.
  */
 
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/excludes.c,v 1.1.2.4 2001/01/12 19:17:18 phk Exp $";
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/excludes.c,v 1.8 2003/10/21 08:27:05 phk Exp $");
 
 #include <sys/types.h>
 #include <sys/time.h>          /* XXX for mtree.h */
@@ -38,13 +38,14 @@ static const char rcsid[] =
 #include <fnmatch.h>
 #include <fts.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 
 #include "mtree.h"             /* XXX for extern.h */
 #include "extern.h"
 
 /*
- * We're assuming that there won't be a whole lot of excludes, 
+ * We're assuming that there won't be a whole lot of excludes,
  * so it's OK to use a stupid algorithm.
  */
 struct exclude {
@@ -103,7 +104,7 @@ check_excludes(const char *fname, const char *path)
 #define MATCH(g, n) (fnmatch((g), (n), FNM_PATHNAME) == 0)
 
        LIST_FOREACH(e, &excludes, link) {
-               if (e->pathname && MATCH(e->glob, path) 
+               if ((e->pathname && MATCH(e->glob, path))
                    || MATCH(e->glob, fname))
                        return 1;
        }
index c91086a7bbfbd996295be24e55a7bd4c716cce1b..4c7adb2f68f8ebff9d59ddfb7b726812918e0d7f 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  *
  *     @(#)extern.h    8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.sbin/mtree/extern.h,v 1.3.2.2 2000/06/28 02:33:17 joe Exp $
+ * $FreeBSD: src/usr.sbin/mtree/extern.h,v 1.13 2004/01/11 19:38:48 phk Exp $
  */
+extern uint32_t crc_total;
 
-int     compare __P((char *, NODE *, FTSENT *));
-int     crc __P((int, u_long *, u_long *));
-void    cwalk __P((void));
-char   *flags_to_string __P((u_long));
+#ifdef _FTS_H_
+int     compare(char *, NODE *, FTSENT *);
+#endif
+int     crc(int, uint32_t *, off_t *);
+void    cwalk(void);
+char   *flags_to_string(u_long);
 
-char   *inotype __P((u_int));
-u_int   parsekey __P((char *, int *));
-char   *rlink __P((char *));
-NODE   *spec __P((void));
-int     verify __P((void));
+const char     *inotype(u_int);
+u_int   parsekey(char *, int *);
+char   *rlink(char *);
+NODE   *mtree_readspec(FILE *fi);
+int    mtree_verifyspec(FILE *fi);
+int    mtree_specspec(FILE *fi, FILE *fj);
 
-int     check_excludes __P((const char *, const char *));
-void    init_excludes __P((void));
-void    read_excludes_file __P((const char *));
+int     check_excludes(const char *, const char *);
+void    init_excludes(void);
+void    read_excludes_file(const char *);
+const char * ftype(u_int type);
+
+extern int ftsoptions;
+extern u_int keys;
+extern int lineno;
+extern int dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, wflag;
+#ifdef MAXPATHLEN
+extern char fullpath[MAXPATHLEN];
+#endif
index b26bda33647157f16fc7630680daf3e464692e5d..4cf852fd1399a789c9512b56d16dbfd5e27ebaa2 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)misc.c     8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/misc.c,v 1.8.2.1 2000/06/28 02:33:17 joe Exp $";
 #endif /*not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/misc.c,v 1.16 2005/03/29 11:44:17 tobez Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <err.h>
 #include <fts.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <unistd.h>
 #include "mtree.h"
 #include "extern.h"
 
-extern int lineno;
-
 typedef struct _key {
-       char *name;                     /* key name */
+       const char *name;                       /* key name */
        u_int val;                      /* value */
 
 #define        NEEDVALUE       0x01
@@ -66,17 +61,20 @@ static KEY keylist[] = {
        {"gname",       F_GNAME,        NEEDVALUE},
        {"ignore",      F_IGN,          0},
        {"link",        F_SLINK,        NEEDVALUE},
-#ifdef MD5
+#ifdef ENABLE_MD5
        {"md5digest",   F_MD5,          NEEDVALUE},
 #endif
        {"mode",        F_MODE,         NEEDVALUE},
        {"nlink",       F_NLINK,        NEEDVALUE},
        {"nochange",    F_NOCHANGE,     0},
-#ifdef RMD160
+#ifdef ENABLE_RMD160
        {"ripemd160digest", F_RMD160,   NEEDVALUE},
 #endif
-#ifdef SHA1
+#ifdef ENABLE_SHA1
        {"sha1digest",  F_SHA1,         NEEDVALUE},
+#endif
+#ifdef ENABLE_SHA256
+       {"sha256digest",        F_SHA256,               NEEDVALUE},
 #endif
        {"size",        F_SIZE,         NEEDVALUE},
        {"time",        F_TIME,         NEEDVALUE},
@@ -85,13 +83,12 @@ static KEY keylist[] = {
        {"uname",       F_UNAME,        NEEDVALUE},
 };
 
+int keycompare(const void *, const void *);
+
 u_int
-parsekey(name, needvaluep)
-       char *name;
-       int *needvaluep;
+parsekey(char *name, int *needvaluep)
 {
        KEY *k, tmp;
-       int keycompare __P((const void *, const void *));
 
        tmp.name = name;
        k = (KEY *)bsearch(&tmp, keylist, sizeof(keylist) / sizeof(KEY),
@@ -105,15 +102,13 @@ parsekey(name, needvaluep)
 }
 
 int
-keycompare(a, b)
-       const void *a, *b;
+keycompare(const void *a, const void *b)
 {
-       return (strcmp(((KEY *)a)->name, ((KEY *)b)->name));
+       return (strcmp(((const KEY *)a)->name, ((const KEY *)b)->name));
 }
 
 char *
-flags_to_string(fflags)
-       u_long fflags;
+flags_to_string(u_long fflags)
 {
        char *string;
 
index 8b4cb2676b959e6db0b649920d80ab40cdcad8ff..72536d3811ef66ee26a171e3afde71a4386e110e 100644 (file)
@@ -9,10 +9,6 @@
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
 .\" 4. 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.
 .\" SUCH DAMAGE.
 .\"
 .\"     From: @(#)mtree.8      8.2 (Berkeley) 12/11/93
-.\" $FreeBSD: src/usr.sbin/mtree/mtree.8,v 1.16.2.9 2001/08/16 15:56:08 ru Exp $
+.\" $FreeBSD: src/usr.sbin/mtree/mtree.8,v 1.53 2005/07/31 03:30:47 keramida Exp $
 .\"
-.Dd February 26, 1999
+.Dd March 29, 2005
 .Dt MTREE 8
 .Os
 .Sh NAME
 .Nm mtree
 .Nd map a directory hierarchy
 .Sh SYNOPSIS
-.Nm
-.Op Fl LPUcdeinqrux
+.Nm mtree
+.Op Fl LPUcdeinqruxw
+.Bk -words
+.Op Fl f Ar spec
+.Ek
 .Bk -words
 .Op Fl f Ar spec
 .Ek
@@ -60,9 +59,9 @@
 .Op Fl X Ar exclude-list
 .Ek
 .Sh DESCRIPTION
-The utility
-.Nm
-compares the file hierarchy rooted in the current directory against a
+The
+.Nm mtree
+utility compares the file hierarchy rooted in the current directory against a
 specification read from the standard input.
 Messages are written to the standard output for any files whose
 characteristics do not match the specifications, or which are
@@ -70,24 +69,34 @@ missing from either the file hierarchy or the specification.
 .Pp
 The options are as follows:
 .Bl -tag -width flag
-.It Fl L
-Follow all symbolic links in the file hierarchy.
-.It Fl P
-Don't follow symbolic links in the file hierarchy, instead consider
-the symbolic link itself in any comparisons. This is the default.
-.It Fl U
-Modify the owner, group and permissions of existing files to match
-the specification and create any missing directories or symbolic links.
-User, group and permissions must all be specified for missing directories
-to be created.
-Corrected mismatches are not considered errors.
+.\" ==========
 .It Fl c
 Print a specification for the file hierarchy to the standard output.
+.\" ==========
 .It Fl d
 Ignore everything except directory type files.
+.\" ==========
 .It Fl e
-Don't complain about files that are in the file hierarchy, but not in the
+Do not complain about files that are in the file hierarchy, but not in the
 specification.
+.\" ==========
+.It Fl f Ar file
+Read the specification from
+.Ar file ,
+instead of from the standard input.
+.Pp
+If this option is specified twice,
+the two specifications are compared with each other,
+rather than to the file hierarchy.
+The specifications be sorted like output generated using
+.Fl c .
+The output format in this case is somewhat remniscent 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
 Indent the output 4 spaces each time a directory level is descended when
 create a specification with the
@@ -96,49 +105,73 @@ 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.
-.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 q
-Quiet mode.  Do not complain when a
-.Dq missing
-directory cannot be created because it is already exists.
-This occurs when the directory is a symbolic link.
-.It Fl r
-Remove any files in the file hierarchy that are not described in the
-specification.
-.It Fl u
-Same as
-.Fl U
-except a status of 2 is returned if the file hierarchy did not match
-the specification.
-.It Fl x
-Don't descend below mount points in the file hierarchy.
-.It Fl f Ar file
-Read the specification from
-.Ar file  ,
-instead of from the standard input.
+.\" ==========
 .It Fl K Ar keywords
 Add the specified (whitespace or comma separated)
 .Ar keywords
 to the current set of keywords.
+.\" ==========
 .It Fl k Ar keywords
 Use the ``type'' keyword plus the specified (whitespace or comma separated)
 .Ar keywords
 instead of the current set of keywords.
+.\" ==========
+.It Fl L
+Follow all symbolic links in the file hierarchy.
+.\" ==========
+.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 P
+Do not follow symbolic links in the file hierarchy, instead consider
+the symbolic link itself in any comparisons.
+This is the default.
+.\" ==========
 .It Fl p Ar path
 Use the file hierarchy rooted in
-.Ar path  ,
+.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
+Remove any files in the file hierarchy that are not described in the
+specification.
+.\" ==========
 .It Fl s Ar seed
 Display a single checksum to the standard error output that represents all
 of the files for which the keyword
 .Cm cksum
 was specified.
 The checksum is seeded with the specified value.
+.\" ==========
+.It Fl U
+Modify the owner, group, permissions, and modification time of existing
+files to match the specification and create any missing directories or
+symbolic links.
+User, group and permissions must all be specified for missing directories
+to be created.
+Corrected mismatches are not considered errors.
+.\" ==========
+.It Fl u
+Same as
+.Fl U
+except a status of 2 is returned if the file hierarchy did not match
+the specification.
+.\" ==========
+.It Fl w
+Make some error conditions non-fatal warnings.
+.\" ==========
 .It Fl X Ar exclude-list
 The specified file contains
 .Xr fnmatch 3
@@ -148,13 +181,17 @@ If the pattern contains a
 .Ql \&/
 character, it will be matched against entire pathnames (relative to
 the starting directory); otherwise,
-it will be matched against basenames only.  No comments are allowed in
+it will be matched against basenames only.
+No comments are allowed in
 the
 .Ar exclude-list
 file.
+.\" ==========
+.It Fl x
+Do not descend below mount points in the file hierarchy.
 .El
 .Pp
-Specifications are mostly composed of ``keywords'', i.e. strings that
+Specifications are mostly composed of ``keywords'', i.e., strings
 that specify values relating to files.
 No keywords have default values, and if a keyword has no value set, no
 checks based on it are performed.
@@ -167,9 +204,11 @@ the
 .Xr cksum 1
 utility.
 .It Cm flags
-The file flags as a symbolic name.  See
+The file flags as a symbolic name.
+See
 .Xr chflags 1
-for information on these names.  If no flags are to be set the string
+for information on these names.
+If no flags are to be set the string
 .Dq none
 may be used to override the current default.
 .It Cm ignore
@@ -178,18 +217,18 @@ Ignore any file hierarchy below this file.
 The file group as a numeric value.
 .It Cm gname
 The file group as a symbolic name.
-.\" .It Cm md5digest
-.\" The MD5 message digest of the file.
-.\" .It Cm sha1digest
-.\" The
-.\" .Tn FIPS
-.\" 160-1
-.\" .Pq Dq Tn SHA-1
-.\" message digest of the file.
-.\" .It Cm ripemd160digest
-.\" The
-.\" .Tn RIPEMD160
-.\" message digest of the file.
+.It Cm md5digest
+The MD5 message digest of the file.
+.It Cm sha1digest
+The
+.Tn FIPS
+160-1
+.Pq Dq Tn SHA-1
+message digest of the file.
+.It Cm ripemd160digest
+The
+.Tn RIPEMD160
+message digest of the file.
 .It Cm mode
 The current file's permissions as a numeric (octal) or symbolic
 value.
@@ -281,63 +320,43 @@ Empty lines and lines whose first non-whitespace character is a hash
 mark (``#'') are ignored.
 .Pp
 The
-.Nm
+.Nm mtree
 utility exits with a status of 0 on success, 1 if any error occurred,
 and 2 if the file hierarchy did not match the specification.
 A status of 2 is converted to a status of 0 if the
 .Fl U
 option is used.
-.\" .Sh EXAMPLES
-.\" To detect system binaries that have been ``trojan horsed'', it is recommended
-.\" that
-.\" .Nm
-.\" .Fl K
-.\" .Cm sha1digest
-.\" be run on the file systems, and a copy of the results stored on a different
-.\" machine, or, at least, in encrypted form.
-.\" The output file itself should be digested using the
-.\" .Xr md5 1
-.\" utility.
-.\" Then, periodically,
-.\" .Nm
-.\" and
-.\" .Xr md5 1
-.\" should be run against the on-line specifications.
-.\" While it is possible for the bad guys to change the on-line specifications
-.\" to conform to their modified binaries, it is believed to be
-.\" impractical for them to create a modified specification which has
-.\" the same MD5 digest as the original.
-.\" .Pp
-.\" The
-.\" .Fl d
-.\" and
-.\" .Fl u
-.\" options can be used in combination to create directory hierarchies
-.\" for distributions and other such things; the files in
-.\" .Pa /etc/mtree
-.\" were used to create almost all directories in this
-.\" .Fx
-.\" distribution.
 .Sh FILES
 .Bl -tag -width /etc/mtree -compact
 .It Pa /etc/mtree
 system specification directory
 .El
-.Sh DIAGNOSTICS
+.Sh EXIT STATUS
 .Ex -std
+.Sh EXAMPLES
+The
+.Fl d
+and
+.Fl u
+options can be used in combination to create directory hierarchies
+for distributions and other such things; the files in
+.Pa /etc/mtree
+were used to create almost all directories in this
+.Fx
+distribution.
 .Sh SEE ALSO
 .Xr chflags 1 ,
 .Xr chgrp 1 ,
 .Xr chmod 1 ,
 .Xr cksum 1 ,
-.\" .Xr md5 1 ,
+.Xr md5 1 ,
 .Xr stat 2 ,
 .Xr fts 3 ,
-.\" .Xr md5 3 ,
+.Xr md5 3 ,
 .Xr chown 8
 .Sh HISTORY
 The
-.Nm
+.Nm mtree
 utility appeared in
 .Bx 4.3 Reno .
 The
index e43e50c77cc14fbffbcbe343c17ed08a04aea8f5..fe5a8b65681d5c1b5015768f7ba6b9368f2772bb 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -31,6 +27,7 @@
  * SUCH DAMAGE.
  */
 
+#if 0
 #ifndef lint
 static const char copyright[] =
 "@(#) Copyright (c) 1989, 1990, 1993\n\
@@ -38,12 +35,11 @@ static const char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
-#if 0
 static char sccsid[] = "@(#)mtree.c    8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/mtree.c,v 1.8.2.2 2001/01/12 19:17:18 phk Exp $";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/mtree.c,v 1.29 2004/06/04 19:29:28 ru Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -51,33 +47,33 @@ static const char rcsid[] =
 #include <errno.h>
 #include <fts.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <unistd.h>
 #include "mtree.h"
 #include "extern.h"
 
-extern long int crc_total;
-
 int ftsoptions = FTS_PHYSICAL;
-int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag;
+int cflag, dflag, eflag, iflag, nflag, qflag, rflag, sflag, uflag, Uflag, wflag;
 u_int keys;
 char fullpath[MAXPATHLEN];
 
-static void usage __P((void));
+static void usage(void);
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char *argv[])
 {
        int ch;
        char *dir, *p;
        int status;
+       FILE *spec1, *spec2;
 
        dir = NULL;
        keys = KEYDEFAULT;
        init_excludes();
+       spec1 = stdin;
+       spec2 = NULL;
 
-       while ((ch = getopt(argc, argv, "cdef:iK:k:LnPp:qrs:UuxX:")) != -1)
+       while ((ch = getopt(argc, argv, "cdef:iK:k:LnPp:qrs:UuwxX:")) != -1)
                switch((char)ch) {
                case 'c':
                        cflag = 1;
@@ -89,8 +85,16 @@ main(argc, argv)
                        eflag = 1;
                        break;
                case 'f':
-                       if (!(freopen(optarg, "r", stdin)))
-                               err(1, "%s", optarg);
+                       if (spec1 == stdin) {
+                               spec1 = fopen(optarg, "r");
+                               if (spec1 == NULL)
+                                       err(1, "%s", optarg);
+                       } else if (spec2 == NULL) {
+                               spec2 = fopen(optarg, "r");
+                               if (spec2 == NULL)
+                                       err(1, "%s", optarg);
+                       } else
+                               usage();
                        break;
                case 'i':
                        iflag = 1;
@@ -128,9 +132,10 @@ main(argc, argv)
                        break;
                case 's':
                        sflag = 1;
-                       crc_total = ~strtol(optarg, &p, 0);
+                       crc_total = ~strtoul(optarg, &p, 0);
                        if (*p)
                                errx(1, "illegal seed value -- %s", optarg);
+                       break;
                case 'U':
                        Uflag = 1;
                        uflag = 1;
@@ -138,6 +143,9 @@ main(argc, argv)
                case 'u':
                        uflag = 1;
                        break;
+               case 'w':
+                       wflag = 1;
+                       break;
                case 'x':
                        ftsoptions |= FTS_XDEV;
                        break;
@@ -164,17 +172,20 @@ main(argc, argv)
                cwalk();
                exit(0);
        }
-       status = verify();
+       if (spec2 != NULL)
+               status = mtree_specspec(spec1, spec2);
+       else
+               status = mtree_verifyspec(spec1);
        if (Uflag & (status == MISMATCHEXIT))
                status = 0;
        exit(status);
 }
 
 static void
-usage()
+usage(void)
 {
        (void)fprintf(stderr,
-"usage: mtree [-LPUcdeinqrux] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n"
+"usage: mtree [-LPUcdeinqruxw] [-f spec] [-f spec] [-K key] [-k key] [-p path] [-s seed]\n"
 "\t[-X excludes]\n");
        exit(1);
 }
index 3398b05f7531604c875f8317d4c66ea22daec486..2b997975382810a3022213ce4a6f7a9592b7bff5 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -31,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)mtree.h     8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.sbin/mtree/mtree.h,v 1.5 1999/12/09 20:38:35 joe Exp $
+ * $FreeBSD: src/usr.sbin/mtree/mtree.h,v 1.7 2005/03/29 11:44:17 tobez Exp $
  */
 
 #include <string.h>
@@ -50,6 +46,7 @@ typedef struct _node {
        u_long  cksum;                          /* check sum */
        char    *md5digest;                     /* MD5 digest */
        char    *sha1digest;                    /* SHA-1 digest */
+       char    *sha256digest;                  /* SHA-256 digest */
        char    *rmd160digest;                  /* RIPEMD160 digest */
        char    *slink;                         /* symbolic link reference */
        uid_t   st_uid;                         /* uid */
@@ -80,6 +77,7 @@ typedef struct _node {
 #define        F_SHA1  0x20000                         /* SHA-1 digest */
 #define        F_RMD160 0x40000                        /* RIPEMD160 digest */
 #define        F_FLAGS 0x80000                         /* file flags */
+#define        F_SHA256        0x100000                                /* SHA-256 digest */
        u_int   flags;                          /* items set */
 
 #define        F_BLOCK 0x001                           /* block special */
index 2b9dfede2c694322fe26d4e1c9dfb9f02c896e17..ae958ae3c51dce2757e534a60e6a34ed6dce7825 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)spec.c     8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/spec.c,v 1.13.2.1 2000/06/28 02:33:17 joe Exp $";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/spec.c,v 1.22 2005/03/29 11:44:17 tobez Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -48,6 +44,7 @@ static const char rcsid[] =
 #include <grp.h>
 #include <pwd.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <vis.h>
 #include "mtree.h"
@@ -55,14 +52,14 @@ static const char rcsid[] =
 
 int lineno;                            /* Current spec line number. */
 
-static void     set __P((char *, NODE *));
-static void     unset __P((char *, NODE *));
+static void     set(char *, NODE *);
+static void     unset(char *, NODE *);
 
 NODE *
-spec()
+mtree_readspec(FILE *fi)
 {
-       register NODE *centry, *last;
-       register char *p;
+       NODE *centry, *last;
+       char *p;
        NODE ginfo, *root;
        int c_cur, c_next;
        char buf[2048];
@@ -70,7 +67,7 @@ spec()
        centry = last = root = NULL;
        bzero(&ginfo, sizeof(ginfo));
        c_cur = c_next = 0;
-       for (lineno = 1; fgets(buf, sizeof(buf), stdin);
+       for (lineno = 1; fgets(buf, sizeof(buf), fi);
            ++lineno, c_cur = c_next, c_next = 0) {
                /* Skip empty lines. */
                if (buf[0] == '\n')
@@ -147,11 +144,8 @@ noparent:          errx(1, "line %d: no parent node", lineno);
 #define        MAGIC   "?*["
                if (strpbrk(p, MAGIC))
                        centry->flags |= F_MAGIC;
-               if (strunvis(centry->name, p) == -1) {
-                       warnx("filename %s is ill-encoded and literally used",
-                           p);
-                       strcpy(centry->name, p);
-               }
+               if (strunvis(centry->name, p) == -1)
+                       errx(1, "filename %s is ill-encoded", p);
                set(NULL, centry);
 
                if (!root) {
@@ -170,11 +164,9 @@ noparent:          errx(1, "line %d: no parent node", lineno);
 }
 
 static void
-set(t, ip)
-       char *t;
-       NODE *ip;
+set(char *t, NODE *ip)
 {
-       register int type;
+       int type;
        char *kw, *val = NULL;
        struct group *gr;
        struct passwd *pw;
@@ -195,21 +187,23 @@ set(t, ip)
                        break;
                case F_MD5:
                        ip->md5digest = strdup(val);
-                       if(!ip->md5digest) {
+                       if(!ip->md5digest)
                                errx(1, "strdup");
-                       }
                        break;
                case F_SHA1:
                        ip->sha1digest = strdup(val);
-                       if(!ip->sha1digest) {
+                       if(!ip->sha1digest)
+                               errx(1, "strdup");
+                       break;
+               case F_SHA256:
+                       ip->sha256digest = strdup(val);
+                       if(!ip->sha256digest)
                                errx(1, "strdup");
-                       }
                        break;
                case F_RMD160:
                        ip->rmd160digest = strdup(val);
-                       if(!ip->rmd160digest) {
+                       if(!ip->rmd160digest)
                                errx(1, "strdup");
-                       }
                        break;
                case F_FLAGS:
                        if (strcmp("none", val) == 0)
@@ -250,8 +244,11 @@ set(t, ip)
                                lineno, val);
                        break;
                case F_SLINK:
-                       if ((ip->slink = strdup(val)) == NULL)
-                               errx(1, "strdup");
+                       ip->slink = malloc(strlen(val) + 1);
+                       if (ip->slink == NULL)
+                               errx(1, "malloc");
+                       if (strunvis(ip->slink, val) == -1)
+                               errx(1, "symlink %s is ill-encoded", val);
                        break;
                case F_TIME:
                        ip->st_mtimespec.tv_sec = strtoul(val, &ep, 10);
@@ -312,11 +309,9 @@ set(t, ip)
 }
 
 static void
-unset(t, ip)
-       char *t;
-       register NODE *ip;
+unset(char *t, NODE *ip)
 {
-       register char *p;
+       char *p;
 
        while ((p = strtok(t, "\n\t ")))
                ip->flags &= ~parsekey(p, NULL);
diff --git a/mtree/specspec.c b/mtree/specspec.c
new file mode 100644 (file)
index 0000000..9aa66f0
--- /dev/null
@@ -0,0 +1,257 @@
+/*-
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/specspec.c,v 1.6 2005/03/29 11:44:17 tobez Exp $");
+
+#include <sys/param.h>
+#include <err.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#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, ftype(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(" md5digest=%s", n->md5digest);
+       if (f & F_SHA1)
+               printf(" sha1digest=%s", n->sha1digest);
+       if (f & F_RMD160)
+               printf(" rmd160digest=%s", n->rmd160digest);
+       if (f & F_SHA256)
+               printf(" sha256digest=%s", n->sha256digest);
+       if (f & F_FLAGS)
+               printf(" flags=%s", flags_to_string(n->st_flags));
+       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 (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 = mtree_readspec(fi);
+       root2 = mtree_readspec(fj);
+       rval = walk_in_the_forest(root1, root2, "");
+       rval += compare_nodes(root1, root2, "");
+       if (rval > 0)
+               return (MISMATCHEXIT);
+       return (0);
+}
index 201d237543397acf875b04106e8aa0836e40a181..cefdbd596850aa073d16e7b7c2a85fcfbd7984b3 100644 (file)
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#ifndef lint
 #if 0
+#ifndef lint
 static char sccsid[] = "@(#)verify.c   8.1 (Berkeley) 6/6/93";
-#endif
-static const char rcsid[] =
-  "$FreeBSD: src/usr.sbin/mtree/verify.c,v 1.10.2.2 2001/01/12 19:17:18 phk Exp $";
 #endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/usr.sbin/mtree/verify.c,v 1.24 2005/08/11 15:43:55 brian Exp $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -47,43 +43,39 @@ static const char rcsid[] =
 #include <fts.h>
 #include <fnmatch.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <unistd.h>
 #include "mtree.h"
 #include "extern.h"
 
-extern long int crc_total;
-extern int ftsoptions;
-extern int dflag, eflag, qflag, rflag, sflag, uflag;
-extern char fullpath[MAXPATHLEN];
-extern int lineno;
-
 static NODE *root;
 static char path[MAXPATHLEN];
 
-static void    miss __P((NODE *, char *));
-static int     vwalk __P((void));
+static void    miss(NODE *, char *);
+static int     vwalk(void);
 
 int
-verify()
+mtree_verifyspec(FILE *fi)
 {
        int rval;
 
-       root = spec();
+       root = mtree_readspec(fi);
        rval = vwalk();
        miss(root, path);
        return (rval);
 }
 
 static int
-vwalk()
+vwalk(void)
 {
-       register FTS *t;
-       register FTSENT *p;
-       register NODE *ep, *level;
+       FTS *t;
+       FTSENT *p;
+       NODE *ep, *level;
        int specdepth, rval;
        char *argv[2];
+       char dot[] = ".";
 
-       argv[0] = ".";
+       argv[0] = dot;
        argv[1] = NULL;
        if ((t = fts_open(argv, ftsoptions, NULL)) == NULL)
                err(1, "line %d: fts_open", lineno);
@@ -154,18 +146,17 @@ extra:
        }
        (void)fts_close(t);
        if (sflag)
-               warnx("%s checksum: %lu", fullpath, crc_total);
+               warnx("%s checksum: %lu", fullpath, (unsigned long)crc_total);
        return (rval);
 }
 
 static void
-miss(p, tail)
-       register NODE *p;
-       register char *tail;
+miss(NODE *p, char *tail)
 {
-       register int create;
-       register char *tp;
-       const char *type;
+       int create;
+       char *tp;
+       const char *type, *what;
+       int serr;
 
        for (; p; p = p->next) {
                if (p->type != F_DIR && (dflag || p->flags & F_VISIT))
@@ -175,7 +166,7 @@ miss(p, tail)
                        /* 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)
                                p->flags |= F_VISIT;
                        else
@@ -202,11 +193,20 @@ miss(p, tail)
                                            strerror(errno));
                                else
                                        (void)printf(" (created)\n");
-#if 0 /* lchown() does not exist on Darwin. */
-                               if (lchown(path, p->st_uid, p->st_gid))
-                                       (void)printf("%s: user/group not modified: %s\n",
-                                           path, strerror(errno));
-#endif
+                               if (lchown(path, p->st_uid, p->st_gid) == -1) {
+                                       serr = errno;
+                                       if (p->st_uid == (uid_t)-1)
+                                               what = "group";
+                                       else if (lchown(path, (uid_t)-1,
+                                           p->st_gid) == -1)
+                                               what = "user & group";
+                                       else {
+                                               what = "user";
+                                               errno = serr;
+                                       }
+                                       (void)printf("%s: %s not modified: %s"
+                                           "\n", path, what, strerror(errno));
+                               }
                                continue;
                        } else if (!(p->flags & F_MODE))
                            (void)printf(" (directory not created: mode not specified)");
@@ -228,12 +228,18 @@ miss(p, tail)
 
                if (!create)
                        continue;
-               if (chown(path, p->st_uid, p->st_gid)) {
-                       (void)printf("%s: user/group/mode not modified: %s\n",
-                           path, strerror(errno));
-                       (void)printf("%s: warning: file mode %snot set\n", path,
-                           (p->flags & F_FLAGS) ? "and file flags " : "");
-                       continue;
+               if (chown(path, p->st_uid, p->st_gid) == -1) {
+                       serr = errno;
+                       if (p->st_uid == (uid_t)-1)
+                               what = "group";
+                       else if (chown(path, (uid_t)-1, p->st_gid) == -1)
+                               what = "user & group";
+                       else {
+                               what = "user";
+                               errno = serr;
+                       }
+                       (void)printf("%s: %s not modified: %s\n",
+                           path, what, strerror(errno));
                }
                if (chmod(path, p->st_mode))
                        (void)printf("%s: permissions not set: %s\n",
diff --git a/mv/mv.1 b/mv/mv.1
index 64396005312091ca997c50beef3dd3ee4c724cd2..3c57d15f6ad1ce4e8afb9293c4793728848ee611 100644 (file)
--- a/mv/mv.1
+++ b/mv/mv.1
 .Nm mv
 .Nd move files
 .Sh SYNOPSIS
-.Nm
+.Nm mv
 .Op Fl f | i | n
 .Op Fl v
 .Ar source target
-.Nm
+.Nm mv
 .Op Fl f | i | n
 .Op Fl v
 .Ar source ... directory
 .Sh DESCRIPTION
 In its first form, the
-.Nm
+.Nm mv
 utility renames the file named by the
 .Ar source
 operand to the destination path named by the
@@ -62,7 +62,7 @@ This form is assumed when the last operand does not name an already
 existing directory.
 .Pp
 In its second form,
-.Nm
+.Nm mv
 moves each file named by a
 .Ar source
 operand to a destination file in the existing directory named by the
@@ -86,7 +86,7 @@ or
 options.)
 .It Fl i
 Cause
-.Nm
+.Nm mv
 to write a prompt to standard error before moving a file that would
 overwrite an existing file.
 If the response from the standard input begins with the character
@@ -112,7 +112,7 @@ or
 options.)
 .It Fl v
 Cause
-.Nm
+.Nm mv
 to be verbose, showing files after they are moved.
 .El
 .Pp
@@ -121,7 +121,7 @@ It is an error for either the
 operand or the destination path to specify a directory unless both do.
 .Pp
 If the destination path does not have a mode which permits writing,
-.Nm
+.Nm mv
 prompts the user for confirmation as specified for the
 .Fl i
 option.
@@ -129,7 +129,7 @@ option.
 As the
 .Xr rename 2
 call does not work across file systems,
-.Nm
+.Nm mv
 uses
 .Xr cp 1
 and
@@ -143,6 +143,11 @@ rm -rf source_file
 .Ed
 .Sh DIAGNOSTICS
 .Ex -std
+.Pp
+The command "mv dir/afile dir" will abort with an error message.
+.Sh LEGACY DIAGNOSTICS
+In legacy mode, the command "mv dir/afile dir" will fail silently,
+returning an exit code of 0.
 .Sh SEE ALSO
 .Xr cp 1 ,
 .Xr rm 1 ,
@@ -153,14 +158,24 @@ The
 and
 .Fl v
 options are non-standard and their use in scripts is not recommended.
+.Pp
+The
+.Nm mv
+utility now supports HFS+ Finder and Extended Attributes and resource forks.  
+The
+.Nm mv
+utility will no longer strip resource forks off of HFS files.  
+For an alternative method,
+refer to
+.Xr cp 1 .
 .Sh STANDARDS
 The
-.Nm
+.Nm mv
 utility is expected to be
 .St -p1003.2
 compatible.
 .Sh HISTORY
 A
-.Nm
+.Nm mv
 command appeared in
 .At v1 .
diff --git a/mv/mv.c b/mv/mv.c
index b8f275f09c4d920d71dd387b96717a1dbdb14f4a..31acc396c8bf54e9ca0cad9782130dc68a67f4c7 100644 (file)
--- a/mv/mv.c
+++ b/mv/mv.c
@@ -72,6 +72,12 @@ __RCSID("$FreeBSD: src/bin/mv/mv.c,v 1.39 2002/07/09 17:45:13 johan Exp $");
 #include <sys/mount.h>
 #endif
 
+#ifdef __APPLE__ 
+#include <get_compat.h>
+#else   
+#define COMPAT_MODE(a,b) (1) 
+#endif /* __APPLE__ */ 
+
 #include "pathnames.h"
 
 int fflg, iflg, nflg, vflg;
@@ -201,8 +207,27 @@ main(int argc, char *argv[])
                        rval = 1;
                } else {
                        memmove(endp, p, (size_t)len + 1);
-                       if (do_move(*argv, path))
-                               rval = 1;
+                       if (COMPAT_MODE("bin/mv", "unix2003")) {
+                               /* 
+                                * For Unix 2003 compatibility, check if old and new are 
+                                * same file, and produce an error * (like on Sun) that 
+                                * conformance test 66 in mv.ex expects.
+                                */
+                               if (!stat(*argv, &fsb) && !stat(path, &tsb) &&
+                                       fsb.st_ino == tsb.st_ino && 
+                                       fsb.st_dev == tsb.st_dev &&
+                                       fsb.st_gen == tsb.st_gen) {
+                                       (void)fprintf(stderr, "mv: %s and %s are identical\n", 
+                                                               *argv, path);
+                                       rval = 2; /* Like the Sun */
+                               } else {
+                                       if (do_move(*argv, path))
+                                               rval = 1;
+                               }
+                       } else {
+                               if (do_move(*argv, path))
+                                       rval = 1;
+                       }
                }
        }
        exit(rval);
@@ -324,25 +349,25 @@ fastcopy(char *from, char *to, struct stat *sbp)
                return (1);
        }
 #ifdef __APPLE__
-       {
-               struct statfs sfs;
-
-               /*
-                * Pre-allocate blocks for the destination file if it
-                * resides on Xsan.
-                */
-               if (fstatfs(to_fd, &sfs) == 0 &&
-                   strcmp(sfs.f_fstypename, "acfs") == 0) {
-                       fstore_t fst;
-
-                       fst.fst_flags = 0;
-                       fst.fst_posmode = F_PEOFPOSMODE;
-                       fst.fst_offset = 0;
-                       fst.fst_length = sbp->st_size;
-
-                       (void) fcntl(to_fd, F_PREALLOCATE, &fst);
-               }
-       }
+       {
+               struct statfs sfs;
+
+               /*
+                * Pre-allocate blocks for the destination file if it
+                * resides on Xsan.
+                */
+               if (fstatfs(to_fd, &sfs) == 0 &&
+                   strcmp(sfs.f_fstypename, "acfs") == 0) {
+                       fstore_t fst;
+
+                       fst.fst_flags = 0;
+                       fst.fst_posmode = F_PEOFPOSMODE;
+                       fst.fst_offset = 0;
+                       fst.fst_length = sbp->st_size;
+
+                       (void) fcntl(to_fd, F_PREALLOCATE, &fst);
+               }
+       }
 #endif /* __APPLE__ */
        while ((nread = read(from_fd, bp, (size_t)blen)) > 0)
                if (write(to_fd, bp, (size_t)nread) != nread) {
@@ -358,7 +383,11 @@ err:               if (unlink(to))
                return (1);
        }
 #ifdef __APPLE__
-       copyfile(from, to, 0, COPYFILE_ACL | COPYFILE_XATTR);
+       /* XATTR can fail if to_fd has mode 000 */
+       if (fcopyfile(from_fd, to_fd, NULL, COPYFILE_ACL | COPYFILE_XATTR) < 0) {
+               warn("%s: unable to move extended attributes and ACL from %s",
+                    to, from);
+       }
 #endif
        (void)close(from_fd);
 
@@ -384,7 +413,7 @@ err:                if (unlink(to))
         */
        errno = 0;
        if (fchflags(to_fd, (u_long)sbp->st_flags))
-               if (errno != EOPNOTSUPP || sbp->st_flags != 0)
+               if (errno != ENOTSUP || sbp->st_flags != 0)
                        warn("%s: set flags (was: 0%07o)", to, sbp->st_flags);
 
        tval[0].tv_sec = sbp->st_atime;
index 59d1825df4b09874af09b7cc6cefb88284ca9337..85168dfbbf071ad54492bdb8a8e41659d80cf38d 100644 (file)
@@ -17,7 +17,7 @@ HFILES = cache.h cpio.h extern.h ftree.h options.h pat_rep.h pax.h\
 
 CFILES = ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c\
          ftree.c gen_subs.c getoldopt.c options.c pat_rep.c pax.c\
-         sel_subs.c tables.c tar.c tty_subs.c
+         sel_subs.c tables.c tar.c tty_subs.c pax_format.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble pax.1 cpio.1
 
index 74e13ca70a4dd10efedb70a056a647aeb4187b12..caff56c28fc6ce3bf21bbbfe9772a68b792451ee 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt Exp $      */
+/*     $OpenBSD: ar_io.c,v 1.36 2004/06/20 16:22:08 niklas Exp $       */
 /*     $NetBSD: ar_io.c,v 1.5 1996/03/26 23:54:13 mrg Exp $    */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ar_io.c    8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_io.c      8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997/09/01 18:29:42 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.36 2004/06/20 16:22:08 niklas Exp $";
 #endif
 #endif /* not lint */
 
@@ -52,6 +48,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997
 #include <sys/ioctl.h>
 #include <sys/mtio.h>
 #include <sys/param.h>
+#include <sys/wait.h>
 #include <signal.h>
 #include <string.h>
 #include <fcntl.h>
@@ -72,8 +69,8 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_io.c,v 1.17 1997
 #define EXT_MODE       O_RDONLY        /* open mode for list/extract */
 #define AR_MODE                (O_WRONLY | O_CREAT | O_TRUNC)  /* mode for archive */
 #define APP_MODE       O_RDWR          /* mode for append */
-#define STDO           "<STDOUT>"      /* psuedo name for stdout */
-#define STDN           "<STDIN>"       /* psuedo name for stdin */
+#define STDO           "<STDOUT>"      /* pseudo name for stdout */
+#define STDN           "<STDIN>"       /* pseudo name for stdin */
 static int arfd = -1;                  /* archive file descriptor */
 static int artyp = ISREG;              /* archive type: file/FIFO/tape */
 static int arvol = 1;                  /* archive volume number */
@@ -85,12 +82,14 @@ static struct stat arsb;            /* stat of archive device at open */
 static int invld_rec;                  /* tape has out of spec record size */
 static int wr_trail = 1;               /* trailer was rewritten in append */
 static int can_unlnk = 0;              /* do we unlink null archives?  */
-char *arcname;                         /* printable name of archive */
-char *gzip_program;                    /* name of gzip program */
+const char *arcname;                   /* printable name of archive */
+const char *gzip_program;              /* name of gzip program */
+static pid_t zpid = -1;                        /* pid of child process */
+int force_one_volume;                  /* 1 if we ignore volume changes */
 
-static int get_phys __P((void));
+static int get_phys(void);
 extern sigset_t s_mask;
-static void ar_start_gzip __P((int));
+static void ar_start_gzip(int, const char *, int);
 
 /*
  * ar_open()
@@ -101,14 +100,8 @@ static void ar_start_gzip __P((int));
  *     -1 on failure, 0 otherwise
  */
 
-#ifdef __STDC__
 int
-ar_open(char *name)
-#else
-int
-ar_open(name)
-       char *name;
-#endif
+ar_open(const char *name)
 {
        struct mtget mb;
 
@@ -128,32 +121,28 @@ ar_open(name)
                if (name == NULL) {
                        arfd = STDIN_FILENO;
                        arcname = STDN;
-               } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0) {
-                       syswarn(0, errno, "Failed open to read on %s", name);
-                       exit(1);
-               }
-               if (zflag)
-                       ar_start_gzip(arfd);
+               } else if ((arfd = open(name, EXT_MODE, DMOD)) < 0)
+                       syswarn(1, errno, "Failed open to read on %s", name);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 0);
                break;
        case ARCHIVE:
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, AR_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to write on %s", name);
+                       syswarn(1, errno, "Failed open to write on %s", name);
                else
                        can_unlnk = 1;
-               if (zflag)
-                       ar_start_gzip(arfd);
+               if (arfd != -1 && gzip_program != NULL)
+                       ar_start_gzip(arfd, gzip_program, 1);
                break;
        case APPND:
-               if (zflag)
-                       err(1, "can not gzip while appending");
                if (name == NULL) {
                        arfd = STDOUT_FILENO;
                        arcname = STDO;
                } else if ((arfd = open(name, APP_MODE, DMOD)) < 0)
-                       syswarn(0, errno, "Failed open to read/write on %s",
+                       syswarn(1, errno, "Failed open to read/write on %s",
                                name);
                break;
        case COPY:
@@ -168,8 +157,10 @@ ar_open(name)
                return(-1);
 
        if (chdname != NULL)
-               if (chdir(chdname) != 0)
+               if (chdir(chdname) != 0) {
                        syswarn(1, errno, "Failed chdir to %s", chdname);
+                       return(-1);
+               }
        /*
         * set up is based on device type
         */
@@ -216,11 +207,11 @@ ar_open(name)
        /*
         * set default blksz on read. APPNDs writes rdblksz on the last volume
         * On all new archive volumes, we shift to wrblksz (if the user
-        * specified one, otherwize we will continue to use rdblksz). We
-        * must to set blocksize based on what kind of device the archive is
+        * specified one, otherwise we will continue to use rdblksz). We
+        * must set blocksize based on what kind of device the archive is
         * stored.
         */
-       switch(artyp) {
+       switch (artyp) {
        case ISTAPE:
                /*
                 * Tape drives come in at least two flavors. Those that support
@@ -283,7 +274,7 @@ ar_open(name)
                        if ((arsb.st_size % rdblksz) == 0)
                                break;
                /*
-                * When we cannont find a match, we may have a flawed archive.
+                * When we cannot find a match, we may have a flawed archive.
                 */
                if (rdblksz <= 0)
                        rdblksz = FILEBLK;
@@ -297,7 +288,7 @@ ar_open(name)
                break;
        default:
                /*
-                * should never happen, worse case, slow... 
+                * should never happen, worst case, slow...
                 */
                blksz = rdblksz = BLKMULT;
                break;
@@ -310,26 +301,16 @@ ar_open(name)
  * ar_close()
  *     closes archive device, increments volume number, and prints i/o summary
  */
-#ifdef __STDC__
 void
 ar_close(void)
-#else
-void
-ar_close()
-#endif
 {
-       FILE *outf;
+       int status;
 
        if (arfd < 0) {
                did_io = io_ok = flcnt = 0;
                return;
        }
 
-       if (act == LIST)
-               outf = stdout;
-       else
-               outf = stderr;
-
        /*
         * Close archive file. This may take a LONG while on tapes (we may be
         * forced to wait for the rewind to complete) so tell the user what is
@@ -338,11 +319,11 @@ ar_close()
         */
        if (vflag && (artyp == ISTAPE)) {
                if (vfpart)
-                       (void)putc('\n', outf);
-               (void)fprintf(outf,
+                       (void)putc('\n', listf);
+               (void)fprintf(listf,
                        "%s: Waiting for tape drive close to complete...",
                        argv0);
-               (void)fflush(outf);
+               (void)fflush(listf);
        }
 
        /*
@@ -355,12 +336,23 @@ ar_close()
                can_unlnk = 0;
        }
 
+       /*
+        * for a quick extract/list, pax frequently exits before the child
+        * process is done
+        */
+       if ((act == LIST || act == EXTRACT) && nflag && zpid > 0)
+               kill(zpid, SIGINT);
+
        (void)close(arfd);
 
+       /* Do not exit before child to ensure data integrity */
+       if (zpid > 0)
+               waitpid(zpid, &status, 0);
+
        if (vflag && (artyp == ISTAPE)) {
-               (void)fputs("done.\n", outf);
+               (void)fputs("done.\n", listf);
                vfpart = 0;
-               (void)fflush(outf);
+               (void)fflush(listf);
        }
        arfd = -1;
 
@@ -386,7 +378,7 @@ ar_close()
         * Print out a summary of I/O for this archive volume.
         */
        if (vfpart) {
-               (void)putc('\n', outf);
+               (void)putc('\n', listf);
                vfpart = 0;
        }
 
@@ -396,28 +388,28 @@ ar_close()
         * could have written anything yet.
         */
        if (frmt == NULL) {
-#      ifdef NET2_STAT
-               (void)fprintf(outf, "%s: unknown format, %lu bytes skipped.\n",
+#      ifdef LONG_OFF_T
+               (void)fprintf(listf, "%s: unknown format, %lu bytes skipped.\n",
 #      else
-               (void)fprintf(outf, "%s: unknown format, %qu bytes skipped.\n",
+               (void)fprintf(listf, "%s: unknown format, %qu bytes skipped.\n",
 #      endif
                    argv0, rdcnt);
-               (void)fflush(outf);
+               (void)fflush(listf);
                flcnt = 0;
                return;
        }
 
        if (strcmp(NM_CPIO, argv0) == 0)
-               (void)fprintf(outf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
-       else if (strcmp(NM_TAR, argv0) != 0)
-               (void)fprintf(outf,
-#      ifdef NET2_STAT
+               (void)fprintf(listf, "%qu blocks\n", (rdcnt ? rdcnt : wrcnt) / 5120);
+       else if (strcmp(NM_TAR, argv0) != 0 && strcmp(NM_PAX, argv0) != 0)
+               (void)fprintf(listf,
+#      ifdef LONG_OFF_T
                    "%s: %s vol %d, %lu files, %lu bytes read, %lu bytes written.\n",
 #      else
                    "%s: %s vol %d, %lu files, %qu bytes read, %qu bytes written.\n",
 #      endif
                    argv0, frmt->name, arvol-1, flcnt, rdcnt, wrcnt);
-       (void)fflush(outf);
+       (void)fflush(listf);
        flcnt = 0;
 }
 
@@ -428,15 +420,10 @@ ar_close()
  *     other side of the pipe from getting a SIGPIPE (pax will stop
  *     reading an archive once a format dependent trailer is detected).
  */
-#ifdef __STDC__
 void
 ar_drain(void)
-#else
-void
-ar_drain()
-#endif
 {
-       register int res;
+       int res;
        char drbuf[MAXBLK];
 
        /*
@@ -465,13 +452,8 @@ ar_drain()
  *     0 if all ready to write, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ar_set_wr(void)
-#else
-int
-ar_set_wr()
-#endif
 {
        off_t cpos;
 
@@ -481,7 +463,7 @@ ar_set_wr()
         */
        wr_trail = 0;
 
-       /* 
+       /*
         * Add any device dependent code as required here
         */
        if (artyp != ISREG)
@@ -502,19 +484,14 @@ ar_set_wr()
 /*
  * ar_app_ok()
  *     check if the last volume in the archive allows appends. We cannot check
- *     this until we are ready to write since there is no spec that says all 
+ *     this until we are ready to write since there is no spec that says all
  *     volumes in a single archive have to be of the same type...
  * Return:
  *     0 if we can append, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_app_ok(void)
-#else
-int
-ar_app_ok()
-#endif
 {
        if (artyp == ISPIPE) {
                paxwarn(1, "Cannot append to an archive obtained from a pipe.");
@@ -537,17 +514,10 @@ ar_app_ok()
  *     Number of bytes in buffer. 0 for end of file, -1 for a read error.
  */
 
-#ifdef __STDC__
-int
-ar_read(register char *buf, register int cnt)
-#else
 int
-ar_read(buf, cnt)
-       register char *buf;
-       register int cnt;
-#endif
+ar_read(char *buf, int cnt)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * if last i/o was in error, no more reads until reset or new volume
@@ -571,10 +541,10 @@ ar_read(buf, cnt)
                        io_ok = 1;
                        if (res != rdblksz) {
                                /*
-                                * Record size changed. If this is happens on
+                                * Record size changed. If this happens on
                                 * any record after the first, we probably have
                                 * a tape drive which has a fixed record size
-                                * we are getting multiple records in a single
+                                * (we are getting multiple records in a single
                                 * read). Watch out for record blocking that
                                 * violates pax spec (must be a multiple of
                                 * BLKMULT).
@@ -624,20 +594,13 @@ ar_read(buf, cnt)
  * Return:
  *     Number of bytes written. 0 indicates end of volume reached and with no
  *     flaws (as best that can be detected). A -1 indicates an unrecoverable
- *     error in the archive occured.
+ *     error in the archive occurred.
  */
 
-#ifdef __STDC__
-int
-ar_write(register char *buf, register int bsz)
-#else
 int
-ar_write(buf, bsz)
-       register char *buf;
-       register int bsz;
-#endif
+ar_write(char *buf, int bsz)
 {
-       register int res;
+       int res;
        off_t cpos;
 
        /*
@@ -658,7 +621,7 @@ ar_write(buf, bsz)
                arfd = open("/dev/null", AR_MODE, DMOD);
                artyp = ISREG;
                return bsz; 
-       }
+        }
 
        /*
         * write broke, see what we can do with it. We try to send any partial
@@ -673,10 +636,10 @@ ar_write(buf, bsz)
        case ISREG:
                if ((res > 0) && (res % BLKMULT)) {
                        /*
-                        * try to fix up partial writes which are not BLKMULT
+                        * try to fix up partial writes which are not BLKMULT
                         * in size by forcing the runt record to next archive
                         * volume
-                        */
+                        */
                        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) < 0)
                                break;
                        cpos -= (off_t)res;
@@ -721,7 +684,7 @@ ar_write(buf, bsz)
        /*
         * Better tell the user the bad news...
         * if this is a block aligned archive format, we may have a bad archive
-        * if the format wants the header to start at a BLKMULT boundry. While
+        * if the format wants the header to start at a BLKMULT boundary.. While
         * we can deal with the mis-aligned data, it violates spec and other
         * archive readers will likely fail. if the format is not block
         * aligned, the user may be lucky (and the archive is ok).
@@ -760,13 +723,8 @@ ar_write(buf, bsz)
  *     0 when ok to try i/o again, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 ar_rdsync(void)
-#else
-int
-ar_rdsync()
-#endif
 {
        long fsbz;
        off_t cpos;
@@ -774,7 +732,7 @@ ar_rdsync()
        struct mtop mb;
 
        /*
-        * Fail resync attempts at user request (done) or this is going to be
+        * Fail resync attempts at user request (done) or if this is going to be
         * an update/append to a existing archive. if last i/o hit media end,
         * we need to go to the next volume not try a resync
         */
@@ -788,13 +746,13 @@ ar_rdsync()
        if (io_ok)
                did_io = 1;
 
-       switch(artyp) {
+       switch (artyp) {
        case ISTAPE:
                /*
                 * if the last i/o was a successful data transfer, we assume
                 * the fault is just a bad record on the tape that we are now
                 * past. If we did not get any data since the last resync try
-                * to move the tape foward one PHYSICAL record past any
+                * to move the tape forward one PHYSICAL record past any
                 * damaged tape section. Some tape drives are stubborn and need
                 * to be pushed.
                 */
@@ -843,7 +801,7 @@ ar_rdsync()
 
 /*
  * ar_fow()
- *     Move the I/O position within the archive foward the specified number of
+ *     Move the I/O position within the archive forward the specified number of
  *     bytes as supported by the device. If we cannot move the requested
  *     number of bytes, return the actual number of bytes moved in skipped.
  * Return:
@@ -851,15 +809,8 @@ ar_rdsync()
  *     partial move (the amount moved is in skipped)
  */
 
-#ifdef __STDC__
 int
 ar_fow(off_t sksz, off_t *skipped)
-#else
-int
-ar_fow(sksz, skipped)
-       off_t sksz;
-       off_t *skipped;
-#endif
 {
        off_t cpos;
        off_t mpos;
@@ -869,7 +820,7 @@ ar_fow(sksz, skipped)
                return(0);
 
        /*
-        * we cannot move foward at EOF or error
+        * we cannot move forward at EOF or error
         */
        if (lstrval <= 0)
                return(lstrval);
@@ -878,7 +829,7 @@ ar_fow(sksz, skipped)
         * Safer to read forward on devices where it is hard to find the end of
         * the media without reading to it. With tapes we cannot be sure of the
         * number of physical blocks to skip (we do not know physical block
-        * size at this point), so we must only read foward on tapes!
+        * size at this point), so we must only read forward on tapes!
         */
        if (artyp != ISREG)
                return(0);
@@ -887,12 +838,12 @@ ar_fow(sksz, skipped)
         * figure out where we are in the archive
         */
        if ((cpos = lseek(arfd, (off_t)0L, SEEK_CUR)) >= 0) {
-               /* 
-                * we can be asked to move farther than there are bytes in this
+               /*
+                * we can be asked to move farther than there are bytes in this
                 * volume, if so, just go to file end and let normal buf_fill()
                 * deal with the end of file (it will go to next volume by
                 * itself)
-                */
+                */
                if ((mpos = cpos + sksz) > arsb.st_size) {
                        *skipped = arsb.st_size - cpos;
                        mpos = arsb.st_size;
@@ -901,7 +852,7 @@ ar_fow(sksz, skipped)
                if (lseek(arfd, mpos, SEEK_SET) >= 0)
                        return(0);
        }
-       syswarn(1, errno, "Foward positioning operation on archive failed");
+       syswarn(1, errno, "Forward positioning operation on archive failed");
        lstrval = -1;
        return(-1);
 }
@@ -917,18 +868,12 @@ ar_fow(sksz, skipped)
  *     0 if moved the requested distance, -1 on complete failure
  */
 
-#ifdef __STDC__
 int
 ar_rev(off_t sksz)
-#else
-int
-ar_rev(sksz)
-       off_t sksz;
-#endif
 {
        off_t cpos;
        struct mtop mb;
-       register int phyblk;
+       int phyblk;
 
        /*
         * make sure we do not have try to reverse on a flawed archive
@@ -936,7 +881,7 @@ ar_rev(sksz)
        if (lstrval < 0)
                return(lstrval);
 
-       switch(artyp) {
+       switch (artyp) {
        case ISPIPE:
                if (sksz <= 0)
                        break;
@@ -969,8 +914,8 @@ ar_rev(sksz)
 
                /*
                 * we may try to go backwards past the start when the archive
-                * is only a single record. If this hapens and we are on a
-                * multi volume archive, we need to go to the end of the
+                * is only a single record. If this happens and we are on a
+                * multi-volume archive, we need to go to the end of the
                 * previous volume and continue our movement backwards from
                 * there.
                 */
@@ -993,12 +938,12 @@ ar_rev(sksz)
                break;
        case ISTAPE:
                /*
-                * Calculate and move the proper number of PHYSICAL tape
+                * Calculate and move the proper number of PHYSICAL tape
                 * blocks. If the sksz is not an even multiple of the physical
                 * tape size, we cannot do the move (this should never happen).
-                * (We also cannot handler trailers spread over two vols).
+                * (We also cannot handle trailers spread over two vols.)
                 * get_phys() also makes sure we are in front of the filemark.
-                */
+                */
                if ((phyblk = get_phys()) <= 0) {
                        lstrval = -1;
                        return(-1);
@@ -1047,7 +992,7 @@ ar_rev(sksz)
 /*
  * get_phys()
  *     Determine the physical block size on a tape drive. We need the physical
- *     block size so we know how many bytes we skip over when we move with 
+ *     block size so we know how many bytes we skip over when we move with
  *     mtio commands. We also make sure we are BEFORE THE TAPE FILEMARK when
  *     return.
  *     This is one really SLOW routine...
@@ -1055,17 +1000,12 @@ ar_rev(sksz)
  *     physical block size if ok (ok > 0), -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_phys(void)
-#else
-static int
-get_phys()
-#endif
 {
-       register int padsz = 0;
-       register int res;
-       register int phyblk;
+       int padsz = 0;
+       int res;
+       int phyblk;
        struct mtop mb;
        char scbuf[MAXBLK];
 
@@ -1113,7 +1053,7 @@ get_phys()
        }
 
        /*
-        * read foward to the file mark, then back up in front of the filemark
+        * read forward to the file mark, then back up in front of the filemark
         * (this is a bit paranoid, but should be safe to do).
         */
        while ((res = read(arfd, scbuf, sizeof(scbuf))) > 0)
@@ -1173,13 +1113,8 @@ get_phys()
  *     0 when ready to continue, -1 when all done
  */
 
-#ifdef __STDC__
 int
 ar_next(void)
-#else
-int
-ar_next()
-#endif
 {
        char buf[PAXPATHLEN+2];
        static int freeit = 0;
@@ -1197,7 +1132,8 @@ ar_next()
                syswarn(0, errno, "Unable to restore signal mask");
 
        /* Don't query for new volume if format is unknown */
-       if (frmt == NULL || done || !wr_trail || strcmp(NM_TAR, argv0) == 0)
+       if (frmt == NULL || done || !wr_trail || force_one_volume || strcmp(NM_TAR, argv0) == 0 ||
+                                                                    strcmp(NM_PAX, argv0) == 0)
                return(-1);
 
        tty_prnt("\nATTENTION! %s archive volume change required.\n", argv0);
@@ -1223,7 +1159,7 @@ ar_next()
                else
                        tty_prnt("\n");
 
-               for(;;) {
+               for (;;) {
                        tty_prnt("Type \"y\" to continue, \".\" to quit %s,",
                                argv0);
                        tty_prnt(" or \"s\" to switch to new device.\nIf you");
@@ -1302,7 +1238,7 @@ ar_next()
                 */
                if (ar_open(buf) >= 0) {
                        if (freeit) {
-                               (void)free(arcname);
+                               (void)free((char *)arcname);
                                freeit = 0;
                        }
                        if ((arcname = strdup(buf)) == NULL) {
@@ -1326,57 +1262,38 @@ ar_next()
  * to keep the fd the same in the calling function (parent).
  */
 void
-#ifdef __STDC__
-ar_start_gzip(int fd)
-#else
-ar_start_gzip(fd)
-       int fd;
-#endif
+ar_start_gzip(int fd, const char *gzip_program, int wr)
 {
-       pid_t pid;
        int fds[2];
-       char *gzip_flags=NULL;
+       const char *gzip_flags = NULL;
 
        if (pipe(fds) < 0)
                err(1, "could not pipe");
-       pid = fork();
-       if (pid < 0)
+       zpid = fork();
+       if (zpid < 0)
                err(1, "could not fork");
 
        /* parent */
-       if (pid) {
-               switch (act) {
-               case ARCHIVE:
+       if (zpid) {
+               if (wr)
                        dup2(fds[1], fd);
-                       break;
-               case LIST:
-               case EXTRACT:
+               else
                        dup2(fds[0], fd);
-                       break;
-               default:
-                       errx(1, "ar_start_gzip:  impossible");
-               }
                close(fds[0]);
                close(fds[1]);
        } else {
-               switch (act) {
-               case ARCHIVE:
+               if (wr) {
                        dup2(fds[0], STDIN_FILENO);
                        dup2(fd, STDOUT_FILENO);
                        gzip_flags = "-c";
-                       break;
-               case LIST:
-               case EXTRACT:
+               } else {
                        dup2(fds[1], STDOUT_FILENO);
                        dup2(fd, STDIN_FILENO);
                        gzip_flags = "-dc";
-                       break;
-               default:
-                       errx(1, "ar_start_gzip:  impossible");
                }
                close(fds[0]);
                close(fds[1]);
-               if (execlp(gzip_program, gzip_program, gzip_flags, NULL) < 0)
+               if (execlp(gzip_program, gzip_program, gzip_flags, (char *)NULL) < 0)
                        err(1, "could not exec");
                /* NOTREACHED */
        }
index 8a455f29ebca3fa6492a9313039e7f6533babd9f..afa11d23877515c1d33397d9fd723bea4f3f3fc0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ar_subs.c,v 1.13 1997/09/16 21:20:35 niklas Exp $     */
+/*     $OpenBSD: ar_subs.c,v 1.28 2004/04/16 22:50:23 deraadt Exp $    */
 /*     $NetBSD: ar_subs.c,v 1.5 1995/03/21 09:07:06 cgd Exp $  */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ar_subs.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ar_subs.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_subs.c,v 1.13 1997/09/16 21:20:35 niklas Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_subs.c,v 1.28 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -65,9 +61,9 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ar_subs.c,v 1.13 19
 #include "pax.h"
 #include "extern.h"
 
-static void wr_archive __P((register ARCHD *, int is_app));
-static int get_arc __P((void));
-static int next_head __P((register ARCHD *));
+static void wr_archive(ARCHD *, int is_app);
+static int get_arc(void);
+static int next_head(ARCHD *);
 extern sigset_t s_mask;
 
 char *chdname;
@@ -86,16 +82,11 @@ u_long flcnt;                               /* number of files processed */
  *     (no pattern matches all).
  */
 
-#ifdef __STDC__
 void
 list(void)
-#else
-void
-list()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        time_t now;
 
@@ -120,6 +111,17 @@ list()
         * step through the archive until the format says it is done
         */
        while (next_head(arcn) == 0) {
+               if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+                       /*
+                        * we need to read, to get the real filename
+                        */
+                       off_t cnt;
+                       if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
+
                /*
                 * check for pattern, and user specified options match.
                 * When all patterns are matched we are done.
@@ -168,16 +170,11 @@ list()
  *     pattern(s) (no patterns extracts all members)
  */
 
-#ifdef __STDC__
 void
 extract(void)
-#else
-void
-extract()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        off_t cnt;
        ARCHD archd;
        struct stat sb;
@@ -220,6 +217,15 @@ extract()
         * says it is done
         */
        while (next_head(arcn) == 0) {
+               if (arcn->type == PAX_GLL || arcn->type == PAX_GLF) {
+                       /*
+                        * we need to read, to get the real filename
+                        */
+                       if (!(*frmt->rd_data)(arcn, arcn->type == PAX_GLF
+                           ? -1 : -2, &cnt))
+                               (void)rd_skip(cnt + arcn->pad);
+                       continue;
+               }
 
                /*
                 * check for pattern, and user specified options match. When
@@ -239,7 +245,7 @@ extract()
 
                /*
                 * with -u or -D only extract when the archive member is newer
-                * than the file with the same name in the file system (nos
+                * than the file with the same name in the file system (no
                 * test of being the same type is required).
                 * NOTE: this test is done BEFORE name modifications as
                 * specified by pax. this operation can be confusing to the
@@ -280,7 +286,7 @@ extract()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -303,9 +309,9 @@ extract()
 
                if (vflag) {
                        if (vflag > 1)
-                               ls_list(arcn, now, stderr);
+                               ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, stderr);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -337,7 +343,7 @@ extract()
                                purg_lnk(arcn);
 
                        if (vflag && vfpart) {
-                               (void)putc('\n', stderr);
+                               (void)putc('\n', listf);
                                vfpart = 0;
                        }
                        continue;
@@ -358,7 +364,7 @@ extract()
                res = (*frmt->rd_data)(arcn, fd, &cnt);
                file_close(arcn, fd);
                if (vflag && vfpart) {
-                       (void)putc('\n', stderr);
+                       (void)putc('\n', listf);
                        vfpart = 0;
                }
                if (!res)
@@ -394,7 +400,7 @@ extract()
 #ifdef __APPLE__
        LIST_FOREACH(cle, &copyfile_list, link)
        {
-           if(copyfile_disable || copyfile(cle->tmp, cle->dst, 0,
+           if(copyfile_disable || copyfile(cle->tmp, cle->dst, NULL,
                COPYFILE_UNPACK | COPYFILE_XATTR | COPYFILE_ACL))
                rename(cle->tmp, cle->src);
            else
@@ -423,21 +429,14 @@ extract()
  *     previously written archive.
  */
 
-#ifdef __STDC__
-static void
-wr_archive(register ARCHD *arcn, int is_app)
-#else
 static void
-wr_archive(arcn, is_app)
-       register ARCHD *arcn;
-       int is_app;
-#endif
+wr_archive(ARCHD *arcn, int is_app)
 {
-       register int res;
-       register int hlk;
-       register int wr_one;
+       int res;
+       int hlk;
+       int wr_one;
        off_t cnt;
-       int (*wrf)();
+       int (*wrf)(ARCHD *);
        int fd = -1;
        time_t now;
 #ifdef __APPLE__
@@ -453,6 +452,7 @@ wr_archive(arcn, is_app)
         */
        if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
                return;
+       if (hlk && want_linkdata) hlk=0; /* Treat hard links as individual files */
 
        /*
         * start up the file traversal code and format specific write
@@ -469,7 +469,8 @@ wr_archive(arcn, is_app)
                return;
 
        /*
-        * if this not append, and there are no files, we do no write a trailer
+        * if this is not append, and there are no files, we do not write a 
+        * trailer
         */
        wr_one = is_app;
 
@@ -582,6 +583,7 @@ next:
 #else
                        if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {
 #endif
+                               /* suppress set if size==0 ?? */
                                syswarn(1,errno, "Unable to open %s to read",
                                        arcn->org_name);
                                purg_lnk(arcn);
@@ -605,7 +607,7 @@ next:
                if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
                        /*
                         * unable to obtain the crc we need, close the file,
-                        * purge link table entry 
+                        * purge link table entry
                         */
                        rdfile_close(arcn, &fd);
                        purg_lnk(arcn);
@@ -614,9 +616,9 @@ next:
 
                if (vflag) {
                        if (vflag > 1)
-                               ls_list(arcn, now, stderr);
+                               ls_list(arcn, now, listf);
                        else {
-                               (void)fputs(arcn->name, stderr);
+                               (void)safe_print(arcn->name, listf);
                                vfpart = 1;
                        }
                }
@@ -632,12 +634,12 @@ next:
                }
                wr_one = 1;
                if (res > 0) {
-                       /* 
+                       /*
                         * format write says no file data needs to be stored
                         * so we are done messing with this file
                         */
                        if (vflag && vfpart) {
-                               (void)putc('\n', stderr);
+                               (void)putc('\n', listf);
                                vfpart = 0;
                        }
                        rdfile_close(arcn, &fd);
@@ -655,7 +657,7 @@ next:
                res = (*frmt->wr_data)(arcn, fd, &cnt);
                rdfile_close(arcn, &fd);
                if (vflag && vfpart) {
-                       (void)putc('\n', stderr);
+                       (void)putc('\n', listf);
                        vfpart = 0;
                }
                if (res < 0)
@@ -667,14 +669,14 @@ next:
                if (((cnt > 0) && (wr_skip(cnt) < 0)) ||
                    ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0)))
                        break;
-#if __APPLE__
+#ifdef __APPLE__
                if (metadata)
                    goto next;
 #endif
        }
 
        /*
-        * tell format to write trailer; pad to block boundry; reset directory
+        * tell format to write trailer; pad to block boundary; reset directory
         * mode/access times, and check if all patterns supplied by the user
         * were matched. block off signals to avoid chance for multiple entry
         * into the cleanup code
@@ -699,7 +701,7 @@ next:
  *     is called to add the new members.
  *     PAX IMPLEMENTATION DETAIL NOTE:
  *     -u is implemented by adding the new members to the end of the archive.
- *     Care is taken so that these do not end up as links to the older 
+ *     Care is taken so that these do not end up as links to the older
  *     version of the same file already stored in the archive. It is expected
  *     when extraction occurs these newer versions will over-write the older
  *     ones stored "earlier" in the archive (this may be a bad assumption as
@@ -712,16 +714,11 @@ next:
  *     over write existing files that it creates.
  */
 
-#ifdef __STDC__
 void
 append(void)
-#else
-void
-append()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
+       ARCHD *arcn;
+       int res;
        ARCHD archd;
        FSUB *orgfrmt;
        int udev;
@@ -732,7 +729,7 @@ append()
 
        /*
         * Do not allow an append operation if the actual archive is of a
-        * different format than the user specified foramt.
+        * different format than the user specified format.
         */
        if (get_arc() < 0)
                return;
@@ -776,7 +773,7 @@ append()
         * reading the archive may take a long time. If verbose tell the user
         */
        if (vflag) {
-               (void)fprintf(stderr,
+               (void)fprintf(listf,
                        "%s: Reading archive to position at the end...", argv0);
                vfpart = 1;
        }
@@ -828,7 +825,7 @@ append()
        lnk_end();
 
        /*
-        * try to postion for write, if this fails quit. if any error occurs,
+        * try to position for write, if this fails quit. if any error occurs,
         * we will refuse to write
         */
        if (appnd_start(tlen) < 0)
@@ -838,10 +835,10 @@ append()
         * tell the user we are done reading.
         */
        if (vflag && vfpart) {
-               (void)fputs("done.\n", stderr);
+               (void)fputs("done.\n", listf);
                vfpart = 0;
        }
-       
+
        /*
         * go to the writing phase to add the new members
         */
@@ -853,13 +850,8 @@ append()
  *     write a new archive
  */
 
-#ifdef __STDC__
 void
 archive(void)
-#else
-void
-archive()
-#endif
 {
        ARCHD archd;
 
@@ -884,37 +876,45 @@ archive()
  *     (except the files are forced to be under the destination directory).
  */
 
-#ifdef __STDC__
 void
 copy(void)
-#else
-void
-copy()
-#endif
 {
-       register ARCHD *arcn;
-       register int res;
-       register int fddest;
-       register char *dest_pt;
-       register int dlen;
-       register int drem;
+       ARCHD *arcn;
+       int res;
+       int fddest;
+       char *dest_pt;
+       int dlen;
+       int drem;
        int fdsrc = -1;
        struct stat sb;
        ARCHD archd;
        char dirbuf[PAXPATHLEN+1];
 
        arcn = &archd;
+
+       if (frmt && strcmp(frmt->name, "pax")==0) {
+               /* Copy using pax format:  must check if any -o options */
+               if ((*frmt->options)() < 0)
+                       return;
+               if (pax_invalid_action==0)
+                       pax_invalid_action = PAX_INVALID_ACTION_BYPASS;
+       }
        /*
         * set up the destination dir path and make sure it is a directory. We
         * make sure we have a trailing / on the destination
         */
-       dlen = l_strncpy(dirbuf, dirptr, sizeof(dirbuf) - 1);
+       dlen = strlcpy(dirbuf, dirptr, sizeof(dirbuf));
+       if (dlen >= sizeof(dirbuf) ||
+           (dlen == sizeof(dirbuf) - 1 && dirbuf[dlen - 1] != '/')) {
+               paxwarn(1, "directory name is too long %s", dirptr);
+               return;
+       }
        dest_pt = dirbuf + dlen;
        if (*(dest_pt-1) != '/') {
                *dest_pt++ = '/';
+               *dest_pt = '\0';
                ++dlen;
        }
-       *dest_pt = '\0';
        drem = PAXPATHLEN - dlen;
 
        if (stat(dirptr, &sb) < 0) {
@@ -929,7 +929,7 @@ copy()
 
        /*
         * start up the hard link table; file traversal routines and the
-        * modification time and access mode database 
+        * modification time and access mode database
         */
        if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
                return;
@@ -952,6 +952,11 @@ copy()
        while (next_file(arcn) == 0) {
                fdsrc = -1;
 
+               /*
+                * Fill in arcn from any pax options
+                */
+               adjust_copy_for_pax_options(arcn);
+
                /*
                 * check if this file meets user specified options
                 */
@@ -972,17 +977,12 @@ copy()
                        /*
                         * create the destination name
                         */
-                       if (*(arcn->name) == '/')
-                               res = 1;
-                       else
-                               res = 0;
-                       if ((arcn->nlen - res) > drem) {
+                       if (strlcpy(dest_pt, arcn->name + (*arcn->name == '/'),
+                           drem + 1) > drem) {
                                paxwarn(1, "Destination pathname too long %s",
                                        arcn->name);
                                continue;
                        }
-                       (void)strncpy(dest_pt, arcn->name + res, drem);
-                       dirbuf[PAXPATHLEN] = '\0';
 
                        /*
                         * if existing file is same age or newer skip
@@ -990,10 +990,10 @@ copy()
                        res = lstat(dirbuf, &sb);
                        *dest_pt = '\0';
 
-                       if (res == 0) {
+                       if (res == 0) {
                                if (uflag && Dflag) {
                                        if ((arcn->sb.st_mtime<=sb.st_mtime) &&
-                                           (arcn->sb.st_ctime<=sb.st_ctime))
+                                           (arcn->sb.st_ctime<=sb.st_ctime))
                                                continue;
                                } else if (Dflag) {
                                        if (arcn->sb.st_ctime <= sb.st_ctime)
@@ -1020,7 +1020,7 @@ copy()
                }
 
                /*
-                * Non standard -Y and -Z flag. When the exisiting file is
+                * Non standard -Y and -Z flag. When the existing file is
                 * same age or newer skip
                 */
                if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
@@ -1036,7 +1036,7 @@ copy()
                }
 
                if (vflag) {
-                       (void)fputs(arcn->name, stderr);
+                       (void)safe_print(arcn->name, listf);
                        vfpart = 1;
                }
                ++flcnt;
@@ -1051,7 +1051,7 @@ copy()
                        res = chk_same(arcn);
                if (res <= 0) {
                        if (vflag && vfpart) {
-                               (void)putc('\n', stderr);
+                               (void)putc('\n', listf);
                                vfpart = 0;
                        }
                        continue;
@@ -1070,8 +1070,14 @@ copy()
                                res = node_creat(arcn);
                        if (res < 0)
                                purg_lnk(arcn);
+#ifdef __APPLE__
+                       if (res >= 0 &&
+                           arcn->type == PAX_DIR &&
+                           copyfile(arcn->org_name, arcn->name, NULL, COPYFILE_ACL | COPYFILE_XATTR) < 0)
+                               paxwarn(1, "Directory %s had metadata that could not be copied: %s", arcn->org_name, strerror(errno));
+#endif /* __APPLE__ */
                        if (vflag && vfpart) {
-                               (void)putc('\n', stderr);
+                               (void)putc('\n', listf);
                                vfpart = 0;
                        }
                        continue;
@@ -1097,19 +1103,20 @@ copy()
                 * copy source file data to the destination file
                 */
                cp_file(arcn, fdsrc, fddest);
+#ifdef __APPLE__
+               /* do this before file close so that mtimes are correct regardless */
+               if (getenv(COPYFILE_DISABLE_VAR) == NULL) {
+                       if (copyfile(arcn->org_name, arcn->name, NULL, COPYFILE_ACL | COPYFILE_XATTR) < 0)
+                               paxwarn(1, "File %s had metadata that could not be copied", arcn->org_name);
+               }
+#endif
                file_close(arcn, fddest);
                rdfile_close(arcn, &fdsrc);
 
                if (vflag && vfpart) {
-                       (void)putc('\n', stderr);
+                       (void)putc('\n', listf);
                        vfpart = 0;
                }
-#ifdef __APPLE__
-           if (getenv(COPYFILE_DISABLE_VAR) == NULL) {
-                   if (copyfile(arcn->org_name, arcn->name, 0, COPYFILE_ACL | COPYFILE_XATTR) < 0)
-                       paxwarn(1, "File %s had metadata that could not be copied", arcn->org_name);
-           }
-#endif
        }
 
        /*
@@ -1142,21 +1149,15 @@ copy()
  *     the specs for rd_wrbuf() for more details)
  */
 
-#ifdef __STDC__
-static int
-next_head(register ARCHD *arcn)
-#else
 static int
-next_head(arcn)
-       register ARCHD *arcn;
-#endif
+next_head(ARCHD *arcn)
 {
-       register int ret;
-       register char *hdend;
-       register int res;
-       register int shftsz;
-       register int hsz;
-       register int in_resync = 0;     /* set when we are in resync mode */
+       int ret;
+       char *hdend;
+       int res;
+       int shftsz;
+       int hsz;
+       int in_resync = 0;              /* set when we are in resync mode */
        int cnt = 0;                    /* counter for trailer function */
        int first = 1;                  /* on 1st read, EOF isn't premature. */
 
@@ -1167,7 +1168,7 @@ next_head(arcn)
        res = hsz = frmt->hsz;
        hdend = hdbuf;
        shftsz = hsz - 1;
-       for(;;) {
+       for (;;) {
                /*
                 * keep looping until we get a contiguous FULL buffer
                 * (frmt->hsz is the proper size)
@@ -1231,7 +1232,7 @@ next_head(arcn)
                        /*
                         * this format has trailers outside of valid headers
                         */
-                       if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
+                       if ((ret = (*frmt->trail)(arcn,hdbuf,in_resync,&cnt)) == 0){
                                /*
                                 * valid trailer found, drain input as required
                                 */
@@ -1278,7 +1279,7 @@ next_head(arcn)
         * the header. NOTE: the parameters are different than trailer routines
         * which encode trailers outside of the header!
         */
-       if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
+       if (frmt->inhead && ((*frmt->trail)(arcn,NULL,0,NULL) == 0)) {
                /*
                 * valid trailer found, drain input as required
                 */
@@ -1300,18 +1301,13 @@ next_head(arcn)
  *     0 if archive found -1 otherwise
  */
 
-#ifdef __STDC__
 static int
 get_arc(void)
-#else
-static int
-get_arc()
-#endif
 {
-       register int i;
-       register int hdsz = 0;
-       register int res;
-       register int minhd = BLKMULT;
+       int i;
+       int hdsz = 0;
+       int res;
+       int minhd = BLKMULT;
        char *hdend;
        int notice = 0;
 
@@ -1328,7 +1324,7 @@ get_arc()
        res = BLKMULT;
        hdsz = 0;
        hdend = hdbuf;
-       for(;;) {
+       for (;;) {
                for (;;) {
                        /*
                         * fill the buffer with at least the smallest header
@@ -1374,7 +1370,7 @@ get_arc()
                        if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
                                continue;
                        frmt = &(fsub[ford[i]]);
-                       /* 
+                       /*
                         * yuck, to avoid slow special case code in the extract
                         * routines, just push this header back as if it was
                         * not seen. We have left extra space at start of the
index 6e13e8f77d2fd8e306722c1cd986d85e8325cbaf..501b9fba2d1db3e1443e3dc3e51ad5c525e6ecf0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: buf_subs.c,v 1.7 1997/09/01 18:29:46 deraadt Exp $    */
+/*     $OpenBSD: buf_subs.c,v 1.20 2004/04/16 22:50:23 deraadt Exp $   */
 /*     $NetBSD: buf_subs.c,v 1.5 1995/03/21 09:07:08 cgd Exp $ */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)buf_subs.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)buf_subs.c   8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: buf_subs.c,v 1.7 1997/09/01 18:29:46 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: buf_subs.c,v 1.20 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -89,13 +85,8 @@ off_t rdcnt;                         /* # of bytes read on current vol */
  *     0 if ok, -1 if the user specified write block size violates pax spec
  */
 
-#ifdef __STDC__
 int
 wr_start(void)
-#else
-int
-wr_start()
-#endif
 {
        buf = &(bufmem[BLKMULT]);
        /*
@@ -124,7 +115,7 @@ wr_start()
        }
 
        /*
-        * we only allow wrblksz to be used with all archive operations 
+        * we only allow wrblksz to be used with all archive operations
         */
        blksz = rdblksz = wrblksz;
        if ((ar_open(arcname) < 0) && (ar_next() < 0))
@@ -142,13 +133,8 @@ wr_start()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 rd_start(void)
-#else
-int
-rd_start()
-#endif
 {
        /*
         * leave space for the header pushback (see get_arc()). If we are
@@ -164,7 +150,7 @@ rd_start()
                }
                if (wrblksz % BLKMULT) {
                        paxwarn(1, "Write block size %d is not a %d byte multiple",
-                       wrblksz, BLKMULT);
+                       wrblksz, BLKMULT);
                        return(-1);
                }
        }
@@ -185,13 +171,8 @@ rd_start()
  *     set up buffer system for copying within the file system
  */
 
-#ifdef __STDC__
 void
 cp_start(void)
-#else
-void
-cp_start()
-#endif
 {
        buf = &(bufmem[BLKMULT]);
        rdblksz = blksz = MAXBLK;
@@ -206,13 +187,13 @@ cp_start()
  *     the start of the header of the first file added to the archive. The
  *     format specific end read function tells us how many bytes to move
  *     backwards in the archive to be positioned BEFORE the trailer. Two
- *     different postions have to be adjusted, the O.S. file offset (e.g. the
+ *     different position have to be adjusted, the O.S. file offset (e.g. the
  *     position of the tape head) and the write point within the data we have
  *     stored in the read (soon to become write) buffer. We may have to move
  *     back several records (the number depends on the size of the archive
  *     record and the size of the format trailer) to read up the record where
  *     the first byte of the trailer is recorded. Trailers may span (and
- *     overlap) record boundries.
+ *     overlap) record boundaries.
  *     We first calculate which record has the first byte of the trailer. We
  *     move the OS file offset back to the start of this record and read it
  *     up. We set the buffer write pointer to be at this byte (the byte where
@@ -220,25 +201,19 @@ cp_start()
  *     start of this record so a flush of this buffer will replace the record
  *     in the archive.
  *     A major problem is rewriting this last record. For archives stored
- *     on disk files, this is trival. However, many devices are really picky
+ *     on disk files, this is trivial. However, many devices are really picky
  *     about the conditions under which they will allow a write to occur.
- *     Often devices restrict the conditions where writes can be made writes,
- *     so it may not be feasable to append archives stored on all types of
- *     devices. 
+ *     Often devices restrict the conditions where writes can be made,
+ *     so it may not be feasible to append archives stored on all types of
+ *     devices.
  * Return:
  *     0 for success, -1 for failure
  */
 
-#ifdef __STDC__
 int
 appnd_start(off_t skcnt)
-#else
-int
-appnd_start(skcnt)
-       off_t skcnt;
-#endif
 {
-       register int res;
+       int res;
        off_t cnt;
 
        if (exit_val != 0) {
@@ -322,7 +297,7 @@ appnd_start(skcnt)
        paxwarn(1, "Unable to rewrite archive trailer, cannot append.");
        return(-1);
 }
-       
+
 /*
  * rd_sync()
  *     A read error occurred on this archive volume. Resync the buffer and
@@ -334,16 +309,11 @@ appnd_start(skcnt)
  *     0 on success, and -1 on failure
  */
 
-#ifdef __STDC__
 int
 rd_sync(void)
-#else
-int
-rd_sync()
-#endif
 {
-       register int errcnt = 0;
-       register int res;
+       int errcnt = 0;
+       int res;
 
        /*
         * if the user says bail out on first fault, we are out of here...
@@ -400,22 +370,15 @@ rd_sync()
  * pback()
  *     push the data used during the archive id phase back into the I/O
  *     buffer. This is required as we cannot be sure that the header does NOT
- *     overlap a block boundry (as in the case we are trying to recover a
+ *     overlap a block boundary (as in the case we are trying to recover a
  *     flawed archived). This was not designed to be used for any other
  *     purpose. (What software engineering, HA!)
  *     WARNING: do not even THINK of pback greater than BLKMULT, unless the
  *     pback space is increased.
  */
 
-#ifdef __STDC__
 void
 pback(char *pt, int cnt)
-#else
-void
-pback(pt, cnt)
-       char *pt;
-       int cnt;
-#endif
 {
        bufpt -= cnt;
        memcpy(bufpt, pt, cnt);
@@ -424,27 +387,21 @@ pback(pt, cnt)
 
 /*
  * rd_skip()
- *     skip foward in the archive during a archive read. Used to get quickly
+ *     skip forward in the archive during a archive read. Used to get quickly
  *     past file data and padding for files the user did NOT select.
  * Return:
  *     0 if ok, -1 failure, and 1 when EOF on the archive volume was detected.
  */
 
-#ifdef __STDC__
 int
 rd_skip(off_t skcnt)
-#else
-int
-rd_skip(skcnt)
-       off_t skcnt;
-#endif
 {
        off_t res;
        off_t cnt;
        off_t skipped = 0;
 
        /*
-        * consume what data we have in the buffer. If we have to move foward
+        * consume what data we have in the buffer. If we have to move forward
         * whole records, we call the low level skip function to see if we can
         * move within the archive without doing the expensive reads on data we
         * do not want.
@@ -497,21 +454,16 @@ rd_skip(skcnt)
        return(0);
 }
 
-/* 
+/*
  * wr_fin()
  *     flush out any data (and pad if required) the last block. We always pad
  *     with zero (even though we do not have to). Padding with 0 makes it a
- *     lot easier to recover if the archive is damaged. zero paddding SHOULD
+ *     lot easier to recover if the archive is damaged. zero padding SHOULD
  *     BE a requirement....
  */
 
-#ifdef __STDC__
 void
 wr_fin(void)
-#else
-void
-wr_fin()
-#endif
 {
        if (bufpt > buf) {
                memset(bufpt, 0, bufend - bufpt);
@@ -526,22 +478,15 @@ wr_fin()
  *     by format specific write routines to pass a file header). On failure we
  *     punt. We do not allow the user to continue to write flawed archives.
  *     We assume these headers are not very large (the memory copy we use is
- *     a bit expensive). 
+ *     a bit expensive).
  * Return:
  *     0 if buffer was filled ok, -1 o.w. (buffer flush failure)
  */
 
-#ifdef __STDC__
 int
-wr_rdbuf(register char *out, register int outcnt)
-#else
-int
-wr_rdbuf(out, outcnt)
-       register char *out;
-       register int outcnt;
-#endif
+wr_rdbuf(char *out, int outcnt)
 {
-       register int cnt;
+       int cnt;
 
        /*
         * while there is data to copy copy into the write buffer. when the
@@ -574,19 +519,12 @@ wr_rdbuf(out, outcnt)
  *     -1 is a read error
  */
 
-#ifdef __STDC__
 int
-rd_wrbuf(register char *in, register int cpcnt)
-#else
-int
-rd_wrbuf(in, cpcnt)
-       register char *in;
-       register int cpcnt;
-#endif
+rd_wrbuf(char *in, int cpcnt)
 {
-       register int res;
-       register int cnt;
-       register int incnt = cpcnt;
+       int res;
+       int cnt;
+       int incnt = cpcnt;
 
        /*
         * loop until we fill the buffer with the requested number of bytes
@@ -597,7 +535,7 @@ rd_wrbuf(in, cpcnt)
                        /*
                         * read error, return what we got (or the error if
                         * no data was copied). The caller must know that an
-                        * error occured and has the best knowledge what to
+                        * error occurred and has the best knowledge what to
                         * do with it
                         */
                        if ((res = cpcnt - incnt) > 0)
@@ -620,7 +558,7 @@ rd_wrbuf(in, cpcnt)
 
 /*
  * wr_skip()
- *     skip foward during a write. In other words add padding to the file.
+ *     skip forward during a write. In other words add padding to the file.
  *     we add zero filled padding as it makes flawed archives much easier to
  *     recover from. the caller tells us how many bytes of padding to add
  *     This routine was not designed to add HUGE amount of padding, just small
@@ -629,16 +567,10 @@ rd_wrbuf(in, cpcnt)
  *     0 if ok, -1 if there was a buf_flush failure
  */
 
-#ifdef __STDC__
 int
 wr_skip(off_t skcnt)
-#else
-int
-wr_skip(skcnt)
-       off_t skcnt;
-#endif
 {
-       register int cnt;
+       int cnt;
 
        /*
         * loop while there is more padding to add
@@ -673,20 +605,12 @@ wr_skip(skcnt)
  *     0, but "left" is set to be greater than zero.
  */
 
-#ifdef __STDC__
 int
 wr_rdfile(ARCHD *arcn, int ifd, off_t *left)
-#else
-int
-wr_rdfile(arcn, ifd, left)
-       ARCHD *arcn;
-       int ifd;
-       off_t *left;
-#endif
 {
-       register int cnt;
-       register int res = 0;
-       register off_t size = arcn->sb.st_size;
+       int cnt;
+       int res = 0;
+       off_t size = arcn->sb.st_size;
        struct stat sb;
 
        /*
@@ -742,32 +666,26 @@ wr_rdfile(arcn, ifd, left)
  *     we return a 0 but "left" is set to be the amount unwritten
  */
 
-#ifdef __STDC__
 int
 rd_wrfile(ARCHD *arcn, int ofd, off_t *left)
-#else
-int
-rd_wrfile(arcn, ofd, left)
-       ARCHD *arcn;
-       int ofd;
-       off_t *left;
-#endif
 {
-       register int cnt = 0;
-       register off_t size = arcn->sb.st_size;
-       register int res = 0;
-       register char *fnm = arcn->name;
+       int cnt = 0;
+       off_t size = arcn->sb.st_size;
+       int res = 0;
+       char *fnm = arcn->name;
        int isem = 1;
        int rem;
        int sz = MINFBSZ;
-       struct stat sb;
+       struct stat sb;
        u_long crc = 0L;
 
        /*
         * pass the blocksize of the file being written to the write routine,
         * if the size is zero, use the default MINFBSZ
         */
-       if (fstat(ofd, &sb) == 0) {
+       if (ofd < 0)
+               sz = PAXPATHLEN + 1;            /* GNU tar long link/file */
+       else if (fstat(ofd, &sb) == 0) {
                if (sb.st_blksize > 0)
                        sz = (int)sb.st_blksize;
        } else
@@ -810,7 +728,7 @@ rd_wrfile(arcn, ofd, left)
        /*
         * if the last block has a file hole (all zero), we must make sure this
         * gets updated in the file. We force the last block of zeros to be
-        * written. just closing with the file offset moved foward may not put
+        * written. just closing with the file offset moved forward may not put
         * a hole at the end of the file.
         */
        if (isem && (arcn->sb.st_size > 0L))
@@ -838,22 +756,14 @@ rd_wrfile(arcn, ofd, left)
  *     destination file so we can properly copy files with holes.
  */
 
-#ifdef __STDC__
 void
 cp_file(ARCHD *arcn, int fd1, int fd2)
-#else
-void
-cp_file(arcn, fd1, fd2)
-       ARCHD *arcn;
-       int fd1;
-       int fd2;
-#endif
 {
-       register int cnt;
-       register off_t cpcnt = 0L;
-       register int res = 0;
-       register char *fnm = arcn->name;
-       register int no_hole = 0;
+       int cnt;
+       off_t cpcnt = 0L;
+       int res = 0;
+       char *fnm = arcn->name;
+       int no_hole = 0;
        int isem = 1;
        int rem;
        int sz = MINFBSZ;
@@ -880,7 +790,7 @@ cp_file(arcn, fd1, fd2)
        /*
         * read the source file and copy to destination file until EOF
         */
-       for(;;) {
+       for (;;) {
                if ((cnt = read(fd1, buf, blksz)) <= 0)
                        break;
                if (no_hole)
@@ -910,7 +820,7 @@ cp_file(arcn, fd1, fd2)
        /*
         * if the last block has a file hole (all zero), we must make sure this
         * gets updated in the file. We force the last block of zeros to be
-        * written. just closing with the file offset moved foward may not put
+        * written. just closing with the file offset moved forward may not put
         * a hole at the end of the file.
         */
        if (!no_hole && isem && (arcn->sb.st_size > 0L))
@@ -927,21 +837,16 @@ cp_file(arcn, fd1, fd2)
  *     0 when finished (user specified termination in ar_next()).
  */
 
-#ifdef __STDC__
 int
 buf_fill(void)
-#else
-int
-buf_fill()
-#endif
 {
-       register int cnt;
+       int cnt;
        static int fini = 0;
 
        if (fini)
                return(0);
 
-       for(;;) {
+       for (;;) {
                /*
                 * try to fill the buffer. on error the next archive volume is
                 * opened and we try again.
@@ -977,22 +882,16 @@ buf_fill()
  *     0 if all is ok, -1 when a write error occurs.
  */
 
-#ifdef __STDC__
 int
-buf_flush(register int bufcnt)
-#else
-int
-buf_flush(bufcnt)
-       register int bufcnt;
-#endif
+buf_flush(int bufcnt)
 {
-       register int cnt;
-       register int push = 0;
-       register int totcnt = 0;
+       int cnt;
+       int push = 0;
+       int totcnt = 0;
 
        /*
         * if we have reached the user specified byte count for each archive
-        * volume, prompt for the next volume. (The non-standrad -R flag).
+        * volume, prompt for the next volume. (The non-standard -R flag).
         * NOTE: If the wrlimit is smaller than wrcnt, we will always write
         * at least one record. We always round limit UP to next blocksize.
         */
index df58ec43dee6f57e7ae378a28fd4ea52f42b956d..44eda1f518a7c826521d208a4d313f9a1cbb20ac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $        */
+/*     $OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $ */
 /*     $NetBSD: cache.c,v 1.4 1995/03/21 09:07:10 cgd Exp $    */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)cache.c    8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)cache.c      8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: cache.c,v 1.6 1997/07/25 18:58:27 mickey Exp $";
+static const char rcsid[] = "$OpenBSD: cache.c,v 1.17 2004/03/16 03:28:34 tedu Exp $";
 #endif
 #endif /* not lint */
 
@@ -76,18 +72,13 @@ static GIDC **grptb = NULL; /* group name to gid cache */
 
 /*
  * uidtb_start
- *     creates an an empty uidtb
+ *     creates an empty uidtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 uidtb_start(void)
-#else
-int
-uidtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -105,18 +96,13 @@ uidtb_start()
 
 /*
  * gidtb_start
- *     creates an an empty gidtb
+ *     creates an empty gidtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 gidtb_start(void)
-#else
-int
-gidtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -134,18 +120,13 @@ gidtb_start()
 
 /*
  * usrtb_start
- *     creates an an empty usrtb
+ *     creates an empty usrtb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 usrtb_start(void)
-#else
-int
-usrtb_start()
-#endif
 {
        static int fail = 0;
 
@@ -163,18 +144,13 @@ usrtb_start()
 
 /*
  * grptb_start
- *     creates an an empty grptb
+ *     creates an empty grptb
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 grptb_start(void)
-#else
-int
-grptb_start()
-#endif
 {
        static int fail = 0;
 
@@ -198,27 +174,19 @@ grptb_start()
  *     Pointer to stored name (or a empty string)
  */
 
-#ifdef __STDC__
 char *
 name_uid(uid_t uid, int frc)
-#else
-char *
-name_uid(uid, frc)
-       uid_t uid;
-       int frc;
-#endif
 {
-       register struct passwd *pw;
-       register UIDC *ptr;
-       register int hash;
+       struct passwd *pw;
+       UIDC *ptr;
+
        if ((uidtb == NULL) && (uidtb_start() < 0))
                return("");
 
        /*
         * see if we have this uid cached
         */
-       hash = uid % UID_SZ;
-       ptr = uidtb[hash];
+       ptr = uidtb[uid % UID_SZ];
        if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
                /*
                 * have an entry for this uid
@@ -236,24 +204,19 @@ name_uid(uid, frc)
                ++pwopn;
        }
        if (ptr == NULL)
-               ptr = (UIDC *)malloc(sizeof(UIDC));
+               ptr = uidtb[uid % UID_SZ] = malloc(sizeof(UIDC));
 
        if ((pw = getpwuid(uid)) == NULL) {
                /*
                 * no match for this uid in the local password file
-                * a string that is the uid in numberic format
+                * a string that is the uid in numeric format
                 */
                if (ptr == NULL)
                        return("");
                ptr->uid = uid;
                ptr->valid = INVALID;
-#              ifdef NET2_STAT
-               (void)snprintf(ptr->name, sizeof(ptr->name), "%u", uid);
-#              else
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)uid);
-#              endif
-               uidtb[hash] = ptr;
                if (frc == 0)
                        return("");
        } else {
@@ -263,10 +226,8 @@ name_uid(uid, frc)
                if (ptr == NULL)
                        return(pw->pw_name);
                ptr->uid = uid;
-               (void)strncpy(ptr->name, pw->pw_name, UNMLEN-1);
-               ptr->name[UNMLEN-1] = '\0';
+               (void)strlcpy(ptr->name, pw->pw_name, sizeof(ptr->name));
                ptr->valid = VALID;
-               uidtb[hash] = ptr;
        }
        return(ptr->name);
 }
@@ -279,19 +240,11 @@ name_uid(uid, frc)
  *     Pointer to stored name (or a empty string)
  */
 
-#ifdef __STDC__
 char *
 name_gid(gid_t gid, int frc)
-#else
-char *
-name_gid(gid, frc)
-       gid_t gid;
-       int frc;
-#endif
 {
-       register struct group *gr;
-       register GIDC *ptr;
-       register int hash;
+       struct group *gr;
+       GIDC *ptr;
 
        if ((gidtb == NULL) && (gidtb_start() < 0))
                return("");
@@ -299,8 +252,7 @@ name_gid(gid, frc)
        /*
         * see if we have this gid cached
         */
-       hash = gid % GID_SZ;
-       ptr = gidtb[hash];
+       ptr = gidtb[gid % GID_SZ];
        if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
                /*
                 * have an entry for this gid
@@ -318,7 +270,7 @@ name_gid(gid, frc)
                ++gropn;
        }
        if (ptr == NULL)
-               ptr = (GIDC *)malloc(sizeof(GIDC));
+               ptr = gidtb[gid % GID_SZ] = malloc(sizeof(GIDC));
 
        if ((gr = getgrgid(gid)) == NULL) {
                /*
@@ -329,13 +281,8 @@ name_gid(gid, frc)
                        return("");
                ptr->gid = gid;
                ptr->valid = INVALID;
-#              ifdef NET2_STAT
-               (void)snprintf(ptr->name, sizeof(ptr->name), "%u", gid);
-#              else
                (void)snprintf(ptr->name, sizeof(ptr->name), "%lu",
                               (unsigned long)gid);
-#              endif
-               gidtb[hash] = ptr;
                if (frc == 0)
                        return("");
        } else {
@@ -345,10 +292,8 @@ name_gid(gid, frc)
                if (ptr == NULL)
                        return(gr->gr_name);
                ptr->gid = gid;
-               (void)strncpy(ptr->name, gr->gr_name, GNMLEN-1);
-               ptr->name[GNMLEN-1] = '\0';
+               (void)strlcpy(ptr->name, gr->gr_name, sizeof(ptr->name));
                ptr->valid = VALID;
-               gidtb[hash] = ptr;
        }
        return(ptr->name);
 }
@@ -360,20 +305,12 @@ name_gid(gid, frc)
  *     the uid (if any) for a user name, or a -1 if no match can be found
  */
 
-#ifdef __STDC__
 int
 uid_name(char *name, uid_t *uid)
-#else
-int
-uid_name(name, uid)
-       char *name;
-       uid_t *uid;
-#endif
 {
-       register struct passwd *pw;
-       register UIDC *ptr;
-       register int namelen;
-       register int hash;
+       struct passwd *pw;
+       UIDC *ptr;
+       int namelen;
 
        /*
         * return -1 for mangled names
@@ -387,8 +324,7 @@ uid_name(name, uid)
         * look up in hash table, if found and valid return the uid,
         * if found and invalid, return a -1
         */
-       hash = st_hash(name, namelen, UNM_SZ);
-       ptr = usrtb[hash];
+       ptr = usrtb[st_hash(name, namelen, UNM_SZ)];
        if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
                if (ptr->valid == INVALID)
                        return(-1);
@@ -402,7 +338,8 @@ uid_name(name, uid)
        }
 
        if (ptr == NULL)
-               ptr = (UIDC *)malloc(sizeof(UIDC));
+               ptr = usrtb[st_hash(name, namelen, UNM_SZ)] =
+                 (UIDC *)malloc(sizeof(UIDC));
 
        /*
         * no match, look it up, if no match store it as an invalid entry,
@@ -414,9 +351,7 @@ uid_name(name, uid)
                *uid = pw->pw_uid;
                return(0);
        }
-       usrtb[hash] = ptr;
-       (void)strncpy(ptr->name, name, UNMLEN-1);
-       ptr->name[UNMLEN-1] = '\0';
+       (void)strlcpy(ptr->name, name, sizeof(ptr->name));
        if ((pw = getpwnam(name)) == NULL) {
                ptr->valid = INVALID;
                return(-1);
@@ -433,20 +368,12 @@ uid_name(name, uid)
  *     the gid (if any) for a group name, or a -1 if no match can be found
  */
 
-#ifdef __STDC__
 int
 gid_name(char *name, gid_t *gid)
-#else
-int
-gid_name(name, gid)
-       char *name;
-       gid_t *gid;
-#endif
 {
-       register struct group *gr;
-       register GIDC *ptr;
-       register int namelen;
-       register int hash;
+       struct group *gr;
+       GIDC *ptr;
+       int namelen;
 
        /*
         * return -1 for mangled names
@@ -460,8 +387,7 @@ gid_name(name, gid)
         * look up in hash table, if found and valid return the uid,
         * if found and invalid, return a -1
         */
-       hash = st_hash(name, namelen, GID_SZ);
-       ptr = grptb[hash];
+       ptr = grptb[st_hash(name, namelen, GID_SZ)];
        if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
                if (ptr->valid == INVALID)
                        return(-1);
@@ -474,7 +400,8 @@ gid_name(name, gid)
                ++gropn;
        }
        if (ptr == NULL)
-               ptr = (GIDC *)malloc(sizeof(GIDC));
+               ptr = grptb[st_hash(name, namelen, GID_SZ)] =
+                 (GIDC *)malloc(sizeof(GIDC));
 
        /*
         * no match, look it up, if no match store it as an invalid entry,
@@ -487,9 +414,7 @@ gid_name(name, gid)
                return(0);
        }
 
-       grptb[hash] = ptr;
-       (void)strncpy(ptr->name, name, GNMLEN-1);
-       ptr->name[GNMLEN-1] = '\0';
+       (void)strlcpy(ptr->name, name, sizeof(ptr->name));
        if ((gr = getgrnam(name)) == NULL) {
                ptr->valid = INVALID;
                return(-1);
index 01283ef9e5978f206a9481cbab6339f88de8062d..5c7b9b8b5f3c0698a0e8350ee67b95e9e8a71d1a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cache.h,v 1.2 1996/06/23 14:20:31 deraadt Exp $       */
+/*     $OpenBSD: cache.h,v 1.4 2003/10/20 06:22:27 jmc Exp $   */
 /*     $NetBSD: cache.h,v 1.3 1995/03/21 09:07:12 cgd Exp $    */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -45,7 +41,7 @@
  * caches. Traditional passwd/group cache routines perform quite poorly with
  * archives. The chances of hitting a valid lookup with an archive is quite a
  * bit worse than with files already resident on the file system. These misses
- * create a MAJOR performance cost. To adress this problem, these routines
+ * create a MAJOR performance cost. To address this problem, these routines
  * cache both hits and misses.
  *
  * NOTE:  name lengths must be as large as those stored in ANY PROTOCOL and
index 639bc07e67c90b47e579cec74e30282ce15821a0..296205a67b83fdfea3584dcb4173a463be218515 100644 (file)
@@ -1,3 +1,4 @@
+.\"    $OpenBSD: cpio.1,v 1.20 2003/11/21 20:54:02 jmc Exp $
 .\"
 .\" Copyright (c) 1997 SigmaSoft, Th. Lockert
 .\" All rights reserved.
 .\" 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"      This product includes software developed by SigmaSoft, Th. Lockert.
-.\" 4. The name of the author may not be used to endorse or promote products
-.\"    derived from this software without specific prior written permission
 .\"
 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -27,7 +23,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\"    $OpenBSD: cpio.1,v 1.3 1997/04/06 06:11:11 millert Exp $
+.\"    $OpenBSD: cpio.1,v 1.20 2003/11/21 20:54:02 jmc Exp $
 .\"
 .Dd February 16, 1997
 .Dt CPIO 1
@@ -36,7 +32,7 @@
 .Nm cpio
 .Nd copy file archives in and out
 .Sh SYNOPSIS
-.Nm
+.Nm cpio
 .Fl o
 .Op Fl aABcLvzZ
 .Op Fl C Ar bytes
@@ -45,7 +41,7 @@
 .Op Fl O Ar archive
 .Ar "< name-list"
 .Op Ar "> archive"
-.Nm
+.Nm cpio
 .Fl i
 .Op Fl bBcdfmrsStuvzZ6
 .Op Fl C Ar bytes
 .Op Fl I Ar archive
 .Op Ar "pattern ..."
 .Op Ar "< archive"
-.Nm
+.Nm cpio
 .Fl p
 .Op Fl adlLmuv
 .Ar destination-directory
 .Ar "< name-list"
 .Sh DESCRIPTION
 The
-.Nm
+.Nm cpio
 command copies files to and from a
-.Nm
+.Nm cpio
 archive.
 .Pp
-The following options are supported:
-.Bl -tag -width Fl
+The options are as follows:
+.Bl -tag -width Ds
 .It Fl o
-Create an archive.  Reads the list of files to store in the
+Create an archive.
+Reads the list of files to store in the
 archive from standard input, and writes the archive on standard
 output.
-.Bl -tag -width Fl
-.It Fl a
-Reset the access times on files that has been copied to the
-archive.
+.Bl -tag -width Ds
 .It Fl A
 Append to the specified archive.
+.It Fl a
+Reset the access times on files that have been copied to the
+archive.
 .It Fl B
 Set block size of output to 5120 bytes.
-.It Fl c
-Use ASCII format for
-.Nm
-header for portability.
 .It Fl C Ar bytes
 Set the block size of output to
 .Ar bytes .
+.It Fl c
+Use ASCII format for
+.Nm cpio
+header for portability.
 .It Fl F Ar archive
-.It Fl O Ar archive
 Use the specified file name as the archive to write to.
 .It Fl H Ar format
-Write the archive in the specified format.  Recognized
-formats are:
-.Bl -tag -width Ds
+Write the archive in the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
 .It Ar bcpio
-Old binary cpio format.
+Old binary
+.Nm cpio
+format.
 .It Ar cpio
-Old octal character cpio format.
+Old octal character
+.Nm cpio
+format.
 .It Ar sv4cpio
-SVR4 hex cpio format.
+SVR4 hex
+.Nm cpio
+format.
 .It Ar tar
 Old tar format.
 .It Ar ustar
@@ -108,71 +111,86 @@ POSIX ustar format.
 .El
 .It Fl L
 Follow symbolic links.
+.It Fl O Ar archive
+Use the specified file name as the archive to write to.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-written to the archive.
-.It Fl z
-Compress archive using
-.Xr gzip 1
-format.
+Be verbose about operations.
+List filenames as they are written to the archive.
 .It Fl Z
 Compress archive using
 .Xr compress 1
 format.
+.It Fl z
+Compress archive using
+.Xr gzip 1
+format.
 .El
 .It Fl i
-Restore files from an archive.  Reads the archive file from
+Restore files from an archive.
+Reads the archive file from
 standard input and extracts files matching the
 .Ar patterns
 that were specified on the command line.
-.Bl -tag -width Fl
-.It Fl b
-Do byte- and word swapping after reading in data from the
-archive, for restoring archives created on systems with
-different byte order.
+.Bl -tag -width Ds
+.It Fl 6
+Process old-style
+.Nm cpio
+format archives.
 .It Fl B
 Set the block size of the archive being read to 5120 bytes.
-.It Fl c
-Expect the archive headers to be in ASCII format.
+.It Fl b
+Do byte and word swapping after reading in data from the
+archive, for restoring archives created on systems with
+a different byte order.
 .It Fl C Ar bytes
-Read archive written with a blocksize of
+Read archive written with a block size of
 .Ar bytes .
+.It Fl c
+Expect the archive headers to be in ASCII format.
 .It Fl d
 Create any intermediate directories as needed during
 restore.
 .It Fl E Ar file
-Read list of file name patters to extract or list from
+Read list of file name patterns to extract or list from
 .Ar file .
+.It Fl F Ar archive
+Use the specified file as the input for the archive.
 .It Fl f
 Restore all files except those matching the
 .Ar patterns
 given on the command line.
-.It Fl F Ar archive
-.It Fl I Ar archive
-Use the specified file as the input for the archive.
 .It Fl H Ar format
-Read an archive of the specified format.  Recognized
-formats are:
-.Bl -tag -width Ds
+Read an archive of the specified format.
+Recognized formats are:
+.Pp
+.Bl -tag -width sv4cpio -compact
 .It Ar bcpio
-Old binary cpio format.
+Old binary
+.Nm cpio
+format.
 .It Ar cpio
-Old octal character cpio format.
+Old octal character
+.Nm cpio
+format.
 .It Ar sv4cpio
-SVR4 hex cpio format.
+SVR4 hex
+.Nm cpio
+format.
 .It Ar tar
 Old tar format.
 .It Ar ustar
 POSIX ustar format.
 .El
+.It Fl I Ar archive
+Use the specified file as the input for the archive.
 .It Fl m
 Restore modification times on files.
 .It Fl r
 Rename restored files interactively.
-.It Fl s
-Swap bytes after reading data from the archive.
 .It Fl S
 Swap words after reading data from the archive.
+.It Fl s
+Swap bytes after reading data from the archive.
 .It Fl t
 Only list the contents of the archive, no files or
 directories will be created.
@@ -180,73 +198,78 @@ directories will be created.
 Overwrite files even when the file in the archive is
 older than the one that will be overwritten.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-copied in from the archive.
-.It Fl z
-Uncompress archive using
-.Xr gzip 1
-format.
+Be verbose about operations.
+List filenames as they are copied in from the archive.
 .It Fl Z
 Uncompress archive using
 .Xr compress 1
 format.
-.It Fl 6
-Process old-style \*Qcpio\*U format archives.
+.It Fl z
+Uncompress archive using
+.Xr gzip 1
+format.
 .El
 .It Fl p
 Copy files from one location to another in a single pass.
-The list of files to copy are read from standard in and
+The list of files to copy are read from standard input and
 written out to a directory relative to the specified
 .Ar directory
 argument.
-.Bl -tag -width Fl
+By default, an older file will not replace a newer file with the same name.
+.Bl -tag -width Ds
 .It Fl a
-Reset the access times on files that has been copied.
+Reset the access times on files that have been copied.
 .It Fl d
 Create any intermediate directories as needed to write
 the files at the new location.
+.It Fl L
+Follow symbolic links.
 .It Fl l
 When possible, link files rather than creating an
 extra copy.
-.It Fl L
-Follow symbolic links.
 .It Fl m
 Restore modification times on files.
 .It Fl u
 Overwrite files even when the original file being copied is
 older than the one that will be overwritten.
 .It Fl v
-Be verbose about operations.  List filenames as they are
-copied.
+Be verbose about operations.
+List filenames as they are copied.
+.El
 .El
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TMPDIR
+Path in which to store temporary files.
 .El
 .Sh ERRORS
-.Nm
+.Nm cpio
 will exit with one of the following values:
 .Bl -tag -width 2n
 .It 0
 All files were processed successfully.
 .It 1
-An error occured.
+An error occurred.
 .El
 .Pp
 Whenever
-.Nm
+.Nm cpio
 cannot create a file or a link when extracting an archive or cannot
 find a file while writing an archive, or cannot preserve the user
-ID, group ID, file mode or access and modification times when the
+ID, group ID, file mode, or access and modification times when the
 .Fl p
-options is specified, a diagnostic message is written to standard
+option is specified, a diagnostic message is written to standard
 error and a non-zero exit value will be returned, but processing
-will continue.  In the case where
-.Nm
+will continue.
+In the case where
+.Nm cpio
 cannot create a link to a file,
-.Nm
+.Nm cpio
 will not create a second copy of the file.
 .Pp
 If the extraction of a file from an archive is prematurely terminated
 by a signal or error,
-.Nm
+.Nm cpio
 may have only partially extracted the file the user wanted.
 Additionally, the file modes of extracted files and directories may
 have incorrect file bits, and the modification and access times may
@@ -254,17 +277,17 @@ be wrong.
 .Pp
 If the creation of an archive is prematurely terminated by a signal
 or error,
-.Nm
-may have only partially created the archive which may violate the
+.Nm cpio
+may have only partially created the archive, which may violate the
 specific archive format specification.
 .Sh SEE ALSO
 .Xr pax 1 ,
 .Xr tar 1
+.Sh AUTHORS
+Keith Muller at the University of California, San Diego.
 .Sh BUGS
-The 
+The
 .Fl s
 and
 .Fl S
 options are currently not implemented.
-.Sh AUTHOR
-Keith Muller at the University of California, San Diego
index 43feb649a85a45c805c74ca095efa4e05389daec..058b8e3427ab96c2a5373cab51dd054f33c081bd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $ */
+/*     $OpenBSD: cpio.c,v 1.17 2004/04/16 22:50:23 deraadt Exp $       */
 /*     $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $     */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)cpio.c     8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)cpio.c       8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: cpio.c,v 1.5 1997/07/25 18:58:28 mickey Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: cpio.c,v 1.17 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -58,9 +54,9 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: cpio.c,v 1.5 1997/0
 #include "cpio.h"
 #include "extern.h"
 
-static int rd_nm __P((register ARCHD *, int));
-static int rd_ln_nm __P((register ARCHD *));
-static int com_rd __P((register ARCHD *));
+static int rd_nm(ARCHD *, int);
+static int rd_ln_nm(ARCHD *);
+static int com_rd(ARCHD *);
 
 /*
  * Routines which support the different cpio versions
@@ -79,13 +75,8 @@ static int swp_head;         /* binary cpio header byte swap */
  *      0 if ok -1 otherwise (the return values of lnk_start())
  */
 
-#ifdef __STDC__
 int
 cpio_strd(void)
-#else
-int
-cpio_strd()
-#endif
 {
        return(lnk_start());
 }
@@ -97,17 +88,11 @@ cpio_strd()
  *     mode; looking for a valid header), and cnt (which starts at zero)
  *     which is used to count the number of empty blocks we have seen so far.
  * Return:
- *     0 if a valid trailer, -1 if not a valid trailer, 
+ *     0 if a valid trailer, -1 if not a valid trailer,
  */
 
-#ifdef __STDC__
-int
-cpio_trail(register ARCHD *arcn)
-#else
 int
-cpio_trail(arcn)
-       register ARCHD *arcn;
-#endif
+cpio_trail(ARCHD *arcn, char *notused, int notused2, int *notused3)
 {
        /*
         * look for trailer id in file we are about to process
@@ -124,19 +109,13 @@ cpio_trail(arcn)
  *     0
  */
 
-#ifdef __STDC__
-static int
-com_rd(register ARCHD *arcn)
-#else
 static int
-com_rd(arcn)
-       register ARCHD *arcn;
-#endif
+com_rd(ARCHD *arcn)
 {
        arcn->skip = 0;
        arcn->pat = NULL;
        arcn->org_name = arcn->name;
-       switch(arcn->sb.st_mode & C_IFMT) {
+       switch (arcn->sb.st_mode & C_IFMT) {
        case C_ISFIFO:
                arcn->type = PAX_FIF;
                break;
@@ -179,13 +158,8 @@ com_rd(arcn)
  *     result of the write of the trailer from the cpio specific write func
  */
 
-#ifdef __STDC__
 int
 cpio_endwr(void)
-#else
-int
-cpio_endwr()
-#endif
 {
        ARCHD last;
 
@@ -196,7 +170,7 @@ cpio_endwr()
        last.nlen = sizeof(TRAILER) - 1;
        last.type = PAX_REG;
        last.sb.st_nlink = 1;
-       (void)strcpy(last.name, TRAILER);
+       (void)strlcpy(last.name, TRAILER, sizeof(last.name));
        return((*frmt->wr)(&last));
 }
 
@@ -207,15 +181,8 @@ cpio_endwr()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 static int
-rd_nm(register ARCHD *arcn, int nsz)
-#else
-static int
-rd_nm(arcn, nsz)
-       register ARCHD *arcn;
-       int nsz;
-#endif
+rd_nm(ARCHD *arcn, int nsz)
 {
        /*
         * do not even try bogus values
@@ -244,21 +211,15 @@ rd_nm(arcn, nsz)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-rd_ln_nm(register ARCHD *arcn)
-#else
 static int
-rd_ln_nm(arcn)
-       register ARCHD *arcn;
-#endif
+rd_ln_nm(ARCHD *arcn)
 {
        /*
         * check the length specified for bogus values
         */
        if ((arcn->sb.st_size == 0) ||
            (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                paxwarn(1, "Cpio link name length is invalid: %lu",
                    arcn->sb.st_size);
 #              else
@@ -301,15 +262,8 @@ rd_ln_nm(arcn)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 cpio_id(char *blk, int size)
-#else
-int
-cpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_CPIO)) ||
            (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
@@ -325,18 +279,11 @@ cpio_id(blk, size)
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-cpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-cpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+cpio_rd(ARCHD *arcn, char *buf)
 {
-       register int nsz;
-       register HD_CPIO *hd;
+       int nsz;
+       HD_CPIO *hd;
 
        /*
         * check that this is a valid header, if not return -1
@@ -361,7 +308,7 @@ cpio_rd(arcn, buf)
        arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
            OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
            OCT);
 #      else
@@ -381,8 +328,8 @@ cpio_rd(arcn, buf)
 
        if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
                /*
-                * no link name to read for this file
-                */
+                * no link name to read for this file
+                */
                arcn->ln_nlen = 0;
                arcn->ln_name[0] = '\0';
                return(com_rd(arcn));
@@ -408,13 +355,8 @@ cpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 cpio_endrd(void)
-#else
-off_t
-cpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
 }
@@ -426,13 +368,8 @@ cpio_endrd()
  *     0 if ok, -1 otherwise (what dev_start() returns)
  */
 
-#ifdef __STDC__
 int
 cpio_stwr(void)
-#else
-int
-cpio_stwr()
-#endif
 {
        return(dev_start());
 }
@@ -446,17 +383,11 @@ cpio_stwr()
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-cpio_wr(register ARCHD *arcn)
-#else
-int
-cpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+cpio_wr(ARCHD *arcn)
 {
-       register HD_CPIO *hd;
-       register int nsz;
+       HD_CPIO *hd;
+       int nsz;
        char hdblk[sizeof(HD_CPIO)];
 
        /*
@@ -471,14 +402,14 @@ cpio_wr(arcn)
        if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
                arcn->sb.st_rdev = 0;
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
                /*
                 * set data size for file data
                 */
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
                    sizeof(hd->c_filesize), OCT)) {
 #              else
@@ -576,21 +507,14 @@ cpio_wr(arcn)
 /*
  * vcpio_id()
  *      determine if a block given to us is a valid system VR4 cpio header
- *     WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 
+ *     WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
  *     uses HEX
  * Return:
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 vcpio_id(char *blk, int size)
-#else
-int
-vcpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_VCPIO)) ||
            (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
@@ -606,15 +530,8 @@ vcpio_id(blk, size)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 crc_id(char *blk, int size)
-#else
-int
-crc_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if ((size < sizeof(HD_VCPIO)) ||
            (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
@@ -629,13 +546,8 @@ crc_id(blk, size)
  *      0 if ok -1 otherwise (the return values of lnk_start())
  */
 
-#ifdef __STDC__
 int
 crc_strd(void)
-#else
-int
-crc_strd()
-#endif
 {
        docrc = 1;
        return(lnk_start());
@@ -649,20 +561,13 @@ crc_strd()
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-vcpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-vcpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+vcpio_rd(ARCHD *arcn, char *buf)
 {
-       register HD_VCPIO *hd;
+       HD_VCPIO *hd;
        dev_t devminor;
        dev_t devmajor;
-       register int nsz;
+       int nsz;
 
        /*
         * during the id phase it was determined if we were using CRC, use the
@@ -688,7 +593,7 @@ vcpio_rd(arcn, buf)
        arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
        arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
            sizeof(hd->c_filesize), HEX);
 #      else
@@ -716,7 +621,7 @@ vcpio_rd(arcn, buf)
                return(-1);
 
        /*
-        * skip padding. header + filename is aligned to 4 byte boundries
+        * skip padding. header + filename is aligned to 4 byte boundaries
         */
        if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
                return(-1);
@@ -755,13 +660,8 @@ vcpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 vcpio_endrd(void)
-#else
-off_t
-vcpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
                (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
@@ -774,13 +674,8 @@ vcpio_endrd()
  *     0 if ok, -1 otherwise (what dev_start() returns)
  */
 
-#ifdef __STDC__
 int
 crc_stwr(void)
-#else
-int
-crc_stwr()
-#endif
 {
        docrc = 1;
        return(dev_start());
@@ -795,16 +690,10 @@ crc_stwr()
  *     NO data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
-int
-vcpio_wr(register ARCHD *arcn)
-#else
 int
-vcpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+vcpio_wr(ARCHD *arcn)
 {
-       register HD_VCPIO *hd;
+       HD_VCPIO *hd;
        unsigned int nsz;
        char hdblk[sizeof(HD_VCPIO)];
 
@@ -825,18 +714,18 @@ vcpio_wr(arcn)
         */
        if (docrc) {
                if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
-                       OCT) ||
+                       OCT) ||
                    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
-                       HEX))
+                       HEX))
                        goto out;
        } else {
                if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
-                       OCT) ||
+                       OCT) ||
                    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
                        goto out;
        }
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
@@ -845,7 +734,7 @@ vcpio_wr(arcn)
                 * much to pad.
                 */
                arcn->pad = VCPIO_PAD(arcn->sb.st_size);
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
                    sizeof(hd->c_filesize), HEX)) {
 #              else
@@ -888,11 +777,11 @@ vcpio_wr(arcn)
            ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
                HEX) ||
            ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
-               HEX) ||
+               HEX) ||
            ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
                HEX) ||
            ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
@@ -958,15 +847,8 @@ vcpio_wr(arcn)
  *      0 if a valid header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 bcpio_id(char *blk, int size)
-#else
-int
-bcpio_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
        if (size < sizeof(HD_BCPIO))
                return(-1);
@@ -993,18 +875,11 @@ bcpio_id(blk, size)
  *     0 if a valid header, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-bcpio_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-bcpio_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+bcpio_rd(ARCHD *arcn, char *buf)
 {
-       register HD_BCPIO *hd;
-       register int nsz;
+       HD_BCPIO *hd;
+       int nsz;
 
        /*
         * check the header
@@ -1016,7 +891,7 @@ bcpio_rd(arcn, buf)
        hd = (HD_BCPIO *)buf;
        if (swp_head) {
                /*
-                * header has swapped bytes on 16 bit boundries
+                * header has swapped bytes on 16 bit boundaries
                 */
                arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
                arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
@@ -1061,7 +936,7 @@ bcpio_rd(arcn, buf)
                return(-1);
 
        /*
-        * header + file name are aligned to 2 byte boundries, skip if needed
+        * header + file name are aligned to 2 byte boundaries, skip if needed
         */
        if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
                return(-1);
@@ -1097,13 +972,8 @@ bcpio_rd(arcn, buf)
  *      size of trailer header in this format
  */
 
-#ifdef __STDC__
 off_t
 bcpio_endrd(void)
-#else
-off_t
-bcpio_endrd()
-#endif
 {
        return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
                (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
@@ -1113,24 +983,18 @@ bcpio_endrd()
  * bcpio_wr()
  *     copy the data in the ARCHD to buffer in old binary cpio format
  *     There is a real chance of field overflow with this critter. So we
- *     always check the conversion is ok. nobody in his their right mind
- *     should write an achive in this format...
+ *     always check the conversion is ok. nobody in their right mind
+ *     should write an archive in this format...
  * Return
  *      0 if file has data to be written after the header, 1 if file has NO
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
 int
-bcpio_wr(register ARCHD *arcn)
-#else
-int
-bcpio_wr(arcn)
-       register ARCHD *arcn;
-#endif
+bcpio_wr(ARCHD *arcn)
 {
-       register HD_BCPIO *hd;
-       register int nsz;
+       HD_BCPIO *hd;
+       int nsz;
        char hdblk[sizeof(HD_BCPIO)];
        off_t t_offt;
        int t_int;
@@ -1147,7 +1011,7 @@ bcpio_wr(arcn)
                arcn->sb.st_rdev = 0;
        hd = (HD_BCPIO *)hdblk;
 
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_CTG:
        case PAX_REG:
        case PAX_HRG:
index 811f8f3778a46bd8d23fdc939e3269f4327fbbcf..dfbd03f21e3ec7809d0f55e58589775eb01073ce 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: cpio.h,v 1.2 1996/06/23 14:20:32 deraadt Exp $        */
+/*     $OpenBSD: cpio.h,v 1.4 2003/06/02 23:32:08 millert Exp $        */
 /*     $NetBSD: cpio.h,v 1.3 1995/03/21 09:07:15 cgd Exp $     */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -73,7 +69,7 @@ typedef struct {
        char    c_mtime[11];            /* modification time */
        char    c_namesize[6];          /* length of pathname */
        char    c_filesize[11];         /* length of file in bytes */
-} HD_CPIO; 
+} HD_CPIO;
 
 #define        MAGIC           070707          /* transportable archive id */
 
@@ -84,7 +80,7 @@ typedef struct {
 #endif /* _PAX_ */
 
 /*
- * Binary cpio header structure 
+ * Binary cpio header structure
  *
  * CAUTION! CAUTION! CAUTION!
  * Each field really represents a 16 bit short (NOT ASCII). Described as
@@ -104,7 +100,7 @@ typedef struct {
        u_char  h_namesize[2];
        u_char  h_filesize_1[2];
        u_char  h_filesize_2[2];
-} HD_BCPIO; 
+} HD_BCPIO;
 
 #ifdef _PAX_
 /*
@@ -142,7 +138,7 @@ typedef struct {
        char    c_rmin[8];              /* special file minor # */
        char    c_namesize[8];          /* length of pathname */
        char    c_chksum[8];            /* 0 OR CRC of bytes of FILE data */
-} HD_VCPIO; 
+} HD_VCPIO;
 
 #define        VMAGIC          070701          /* sVr4 new portable archive id */
 #define        VCMAGIC         070702          /* sVr4 new portable archive id CRC */
index 478152c00a067d066a4eda715362b31e971aa6de..01f4f2afae667b595bfa7804c8e4fe18ac83cc03 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: extern.h,v 1.14 1997/07/24 23:19:18 millert Exp $     */
+/*     $OpenBSD: extern.h,v 1.29 2004/11/29 16:23:22 otto Exp $        */
 /*     $NetBSD: extern.h,v 1.5 1996/03/26 23:54:16 mrg Exp $   */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
 /*
  * ar_io.c
  */
-extern char *arcname;
-extern char *gzip_program;
-int ar_open __P((char *));
-void ar_close __P((void));
-void ar_drain __P((void));
-int ar_set_wr __P((void));
-int ar_app_ok __P((void));
-int ar_read __P((register char *, register int));
-int ar_write __P((register char *, register int));
-int ar_rdsync __P((void));
-int ar_fow __P((off_t, off_t *));
-int ar_rev __P((off_t ));
-int ar_next __P((void));
+extern const char *arcname;
+extern const char *gzip_program;
+extern int force_one_volume;
+int ar_open(const char *);
+void ar_close(void);
+void ar_drain(void);
+int ar_set_wr(void);
+int ar_app_ok(void);
+int ar_read(char *, int);
+int ar_write(char *, int);
+int ar_rdsync(void);
+int ar_fow(off_t, off_t *);
+int ar_rev(off_t );
+int ar_next(void);
 
 /*
  * ar_subs.c
  */
 extern u_long flcnt;
-void list __P((void));
-void extract __P((void));
-void append __P((void));
-void archive __P((void));
-void copy __P((void));
+void list(void);
+void extract(void);
+void append(void);
+void archive(void);
+void copy(void);
 
 /*
  * buf_subs.c
@@ -83,126 +80,129 @@ extern int rdblksz;
 extern off_t wrlimit;
 extern off_t rdcnt;
 extern off_t wrcnt;
-int wr_start __P((void));
-int rd_start __P((void));
-void cp_start __P((void));
-int appnd_start __P((off_t));
-int rd_sync __P((void));
-void pback __P((char *, int));
-int rd_skip __P((off_t));
-void wr_fin __P((void));
-int wr_rdbuf __P((register char *, register int));
-int rd_wrbuf __P((register char *, register int));
-int wr_skip __P((off_t));
-int wr_rdfile __P((ARCHD *, int, off_t *));
-int rd_wrfile __P((ARCHD *, int, off_t *));
-void cp_file __P((ARCHD *, int, int));
-int buf_fill __P((void));
-int buf_flush __P((register int));
+int wr_start(void);
+int rd_start(void);
+void cp_start(void);
+int appnd_start(off_t);
+int rd_sync(void);
+void pback(char *, int);
+int rd_skip(off_t);
+void wr_fin(void);
+int wr_rdbuf(char *, int);
+int rd_wrbuf(char *, int);
+int wr_skip(off_t);
+int wr_rdfile(ARCHD *, int, off_t *);
+int rd_wrfile(ARCHD *, int, off_t *);
+void cp_file(ARCHD *, int, int);
+int buf_fill(void);
+int buf_flush(int);
 
 /*
  * cache.c
  */
-int uidtb_start __P((void));
-int gidtb_start __P((void));
-int usrtb_start __P((void));
-int grptb_start __P((void));
-char * name_uid __P((uid_t, int));
-char * name_gid __P((gid_t, int));
-int uid_name __P((char *, uid_t *));
-int gid_name __P((char *, gid_t *));
+int uidtb_start(void);
+int gidtb_start(void);
+int usrtb_start(void);
+int grptb_start(void);
+char * name_uid(uid_t, int);
+char * name_gid(gid_t, int);
+int uid_name(char *, uid_t *);
+int gid_name(char *, gid_t *);
 
 /*
  * cpio.c
  */
-int cpio_strd __P((void));
-int cpio_trail __P((register ARCHD *));
-int cpio_endwr __P((void));
-int cpio_id __P((char *, int));
-int cpio_rd __P((register ARCHD *, register char *));
-off_t cpio_endrd __P((void));
-int cpio_stwr __P((void));
-int cpio_wr __P((register ARCHD *));
-int vcpio_id __P((char *, int));
-int crc_id __P((char *, int));
-int crc_strd __P((void));
-int vcpio_rd __P((register ARCHD *, register char *));
-off_t vcpio_endrd __P((void));
-int crc_stwr __P((void));
-int vcpio_wr __P((register ARCHD *));
-int bcpio_id __P((char *, int));
-int bcpio_rd __P((register ARCHD *, register char *));
-off_t bcpio_endrd __P((void));
-int bcpio_wr __P((register ARCHD *));
+int cpio_strd(void);
+int cpio_trail(ARCHD *, char *, int, int *);
+int cpio_endwr(void);
+int cpio_id(char *, int);
+int cpio_rd(ARCHD *, char *);
+off_t cpio_endrd(void);
+int cpio_stwr(void);
+int cpio_wr(ARCHD *);
+int vcpio_id(char *, int);
+int crc_id(char *, int);
+int crc_strd(void);
+int vcpio_rd(ARCHD *, char *);
+off_t vcpio_endrd(void);
+int crc_stwr(void);
+int vcpio_wr(ARCHD *);
+int bcpio_id(char *, int);
+int bcpio_rd(ARCHD *, char *);
+off_t bcpio_endrd(void);
+int bcpio_wr(ARCHD *);
 
 /*
  * file_subs.c
  */
-int file_creat __P((register ARCHD *));
-void file_close __P((register ARCHD *, int));
-int lnk_creat __P((register ARCHD *));
-int cross_lnk __P((register ARCHD *));
-int chk_same __P((register ARCHD *));
-int node_creat __P((register ARCHD *));
-int unlnk_exist __P((register char *, register int));
-int chk_path __P((register char *, uid_t, gid_t));
-void set_ftime __P((char *fnm, time_t mtime, time_t atime, int frc));
-int set_ids __P((char *, uid_t, gid_t));
-int set_lids __P((char *, uid_t, gid_t));
-void set_pmode __P((char *, mode_t));
-int file_write __P((int, char *, register int, int *, int *, int, char *));
-void file_flush __P((int, char *, int));
-void rdfile_close __P((register ARCHD *, register int *));
-int set_crc __P((register ARCHD *, register int));
+extern char *gnu_name_string, *gnu_link_string;
+int file_creat(ARCHD *);
+void file_close(ARCHD *, int);
+int lnk_creat(ARCHD *);
+int cross_lnk(ARCHD *);
+int chk_same(ARCHD *);
+int node_creat(ARCHD *);
+int unlnk_exist(char *, int);
+int chk_path(char *, uid_t, gid_t, char **);
+void set_ftime(char *fnm, time_t mtime, time_t atime, int frc);
+int set_ids(char *, uid_t, gid_t);
+int set_lids(char *, uid_t, gid_t);
+void set_pmode(char *, mode_t);
+int file_write(int, char *, int, int *, int *, int, char *);
+void file_flush(int, char *, int);
+void rdfile_close(ARCHD *, int *);
+int set_crc(ARCHD *, int);
 
 /*
  * ftree.c
  */
-int ftree_start __P((void));
-int ftree_add __P((register char *, int));
-void ftree_sel __P((register ARCHD *));
-void ftree_chk __P((void));
-int next_file __P((register ARCHD *));
+int ftree_start(void);
+int ftree_add(char *, int);
+void ftree_sel(ARCHD *);
+void ftree_chk(void);
+int next_file(ARCHD *);
 
 /*
  * gen_subs.c
  */
-void ls_list __P((register ARCHD *, time_t, FILE *));
-void ls_tty __P((register ARCHD *));
-int l_strncpy __P((register char *, register char *, int));
-u_long asc_ul __P((register char *, int, register int));
-int ul_asc __P((u_long, register char *, register int, register int));
-#ifndef NET2_STAT
-u_quad_t asc_uqd __P((register char *, int, register int));
-int uqd_asc __P((u_quad_t, register char *, register int, register int));
+void ls_list(ARCHD *, time_t, FILE *);
+void ls_tty(ARCHD *);
+void safe_print(const char *, FILE *);
+u_long asc_ul(char *, int, int);
+int ul_asc(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+u_quad_t asc_uqd(char *, int, int);
+int uqd_asc(u_quad_t, char *, int, int);
 #endif
 
-/* 
+/*
  * getoldopt.c
  */
-int getoldopt __P((int, char **, char *));
+int getoldopt(int, char **, const char *);
 
 /*
  * options.c
  */
 extern FSUB fsub[];
 extern int ford[];
-void options __P((register int, register char **));
-OPLIST * opt_next __P((void));
-int opt_add __P((register char *));
-int bad_opt __P((void));
+void options(int, char **);
+OPLIST * opt_next(void);
+int opt_add(const char *);
+int bad_opt(void);
+int pax_format_opt_add (char *);
+int pax_opt(void);
 extern char *chdname;
 
 /*
  * pat_rep.c
  */
-int rep_add __P((register char *));
-int pat_add __P((char *, char *));
-void pat_chk __P((void));
-int pat_sel __P((register ARCHD *));
-int pat_match __P((register ARCHD *));
-int mod_name __P((register ARCHD *));
-int set_dest __P((register ARCHD *, char *, int));
+int rep_add(char *);
+int pat_add(char *, char *);
+void pat_chk(void);
+int pat_sel(ARCHD *);
+int pat_match(ARCHD *);
+int mod_name(ARCHD *);
+int set_dest(ARCHD *, char *, int);
 
 /*
  * pax.c
@@ -219,13 +219,13 @@ extern int nflag;
 extern int tflag;
 extern int uflag;
 extern int vflag;
-extern int zflag;
 extern int Dflag;
 extern int Hflag;
 extern int Lflag;
 extern int Xflag;
 extern int Yflag;
 extern int Zflag;
+extern int zeroflag;
 extern int vfpart;
 extern int patime;
 extern int pmtime;
@@ -238,62 +238,94 @@ extern int docrc;
 extern char *dirptr;
 extern char *ltmfrmt;
 extern char *argv0;
-int main __P((int, char **));
-void sig_cleanup __P((int));
+extern FILE *listf;
+extern char *tempfile;
+extern char *tempbase;
+
+int main(int, char **);
+void sig_cleanup(int);
 
 /*
  * sel_subs.c
  */
-int sel_chk __P((register ARCHD *));
-int grp_add __P((register char *));
-int usr_add __P((register char *));
-int trng_add __P((register char *));
+int sel_chk(ARCHD *);
+int grp_add(char *);
+int usr_add(char *);
+int trng_add(char *);
 
 /*
  * tables.c
  */
-int lnk_start __P((void));
-int chk_lnk __P((register ARCHD *));
-void purg_lnk __P((register ARCHD *));
-void lnk_end __P((void));
-int ftime_start __P((void));
-int chk_ftime __P((register ARCHD *));
-int name_start __P((void));
-int add_name __P((register char *, int, char *));
-void sub_name __P((register char *, int *, size_t));
-int dev_start __P((void));
-int add_dev __P((register ARCHD *));
-int map_dev __P((register ARCHD *, u_long, u_long));
-int atdir_start __P((void));
-void atdir_end __P((void));
-void add_atdir __P((char *, dev_t, ino_t, time_t, time_t));
-int get_atdir __P((dev_t, ino_t, time_t *, time_t *));
-int dir_start __P((void));
-void add_dir __P((char *, int, struct stat *, int));
-void proc_dir __P((void));
-u_int st_hash __P((char *, int, int));
+int lnk_start(void);
+int chk_lnk(ARCHD *);
+void purg_lnk(ARCHD *);
+void lnk_end(void);
+int ftime_start(void);
+int chk_ftime(ARCHD *);
+int name_start(void);
+int add_name(char *, int, char *);
+void sub_name(char *, int *, size_t);
+int dev_start(void);
+int add_dev(ARCHD *);
+int map_dev(ARCHD *, u_long, u_long);
+int atdir_start(void);
+void atdir_end(void);
+void add_atdir(char *, dev_t, ino_t, time_t, time_t);
+int get_atdir(dev_t, ino_t, time_t *, time_t *);
+int dir_start(void);
+void add_dir(char *, struct stat *, int);
+void proc_dir(void);
+u_int st_hash(char *, int, int);
 
 /*
  * tar.c
  */
-int tar_endwr __P((void));
-off_t tar_endrd __P((void));
-int tar_trail __P((register char *, register int, register int *));
-int tar_id __P((register char *, int));
-int tar_opt __P((void));
-int tar_rd __P((register ARCHD *, register char *));
-int tar_wr __P((register ARCHD *));
-int ustar_strd __P((void));
-int ustar_stwr __P((void));
-int ustar_id __P((char *, int));
-int ustar_rd __P((register ARCHD *, register char *));
-int ustar_wr __P((register ARCHD *));
+extern char *gnu_hack_string;
+int tar_endwr(void);
+off_t tar_endrd(void);
+int tar_trail(ARCHD *, char *, int, int *);
+int tar_id(char *, int);
+int tar_opt(void);
+int tar_rd(ARCHD *, char *);
+int tar_wr(ARCHD *);
+int ustar_strd(void);
+int ustar_stwr(void);
+int ustar_id(char *, int);
+int ustar_rd(ARCHD *, char *);
+int ustar_wr(ARCHD *);
+
+/*
+ * pax_format.c
+ */
+extern char *header_name_g;
+extern int pax_read_or_list_mode;
+#define PAX_INVALID_ACTION_BYPASS      1
+#define PAX_INVALID_ACTION_RENAME      2
+#define PAX_INVALID_ACTION_UTF8                3
+#define PAX_INVALID_ACTION_WRITE       4
+extern int want_linkdata;
+extern int pax_invalid_action;
+extern char *  pax_list_opt_format;
+extern char *  pax_invalid_action_write_path;
+extern char *  pax_invalid_action_write_cwd;
+void pax_format_list_output(ARCHD *, time_t, FILE *, int);
+void cleanup_pax_invalid_action(void);
+void record_pax_invalid_action_results(ARCHD *, char *);
+int perform_pax_invalid_action(ARCHD *, int);
+void adjust_copy_for_pax_options(ARCHD *);
+/*
+int pax_strd(void);
+int pax_stwr(void);
+*/
+int pax_id(char *, int);
+int pax_rd(ARCHD *, char *);
+int pax_wr(ARCHD *);
 
 /*
  * tty_subs.c
  */
-int tty_init __P((void));
-void tty_prnt __P((char *, ...));
-int tty_read __P((char *, int));
-void paxwarn __P((int, char *, ...));
-void syswarn __P((int, int, char *, ...));
+int tty_init(void);
+void tty_prnt(const char *, ...);
+int tty_read(char *, int);
+void paxwarn(int, const char *, ...);
+void syswarn(int, int, const char *, ...);
index 234dcc38ae97a09d73b104bf3030ba43ea1e3834..02058f6eb76408374515dab53d7664082afbe1ef 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: file_subs.c,v 1.13 1997/09/01 18:29:48 deraadt Exp $  */
+/*     $OpenBSD: file_subs.c,v 1.28 2004/11/29 16:23:22 otto Exp $     */
 /*     $NetBSD: file_subs.c,v 1.4 1995/03/21 09:07:18 cgd Exp $        */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)file_subs.c        8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)file_subs.c  8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: file_subs.c,v 1.13 1997/09/01 18:29:48 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: file_subs.c,v 1.28 2004/11/29 16:23:22 otto Exp $";
 #endif
 #endif /* not lint */
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/time.h>
 #include <sys/stat.h>
-#include <unistd.h>
-#include <sys/param.h>
+#include <sys/uio.h>
+#include <err.h>
+#include <errno.h>
 #include <fcntl.h>
-#include <string.h>
 #include <stdio.h>
-#include <errno.h>
-#include <sys/uio.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include "pax.h"
 #include "options.h"
 #include "extern.h"
 
 static int
-mk_link __P((register char *,register struct stat *,register char *, int));
+mk_link(char *, struct stat *, char *, int);
 
 /*
  * routines that deal with file operations such as: creating, removing;
@@ -80,26 +76,25 @@ mk_link __P((register char *,register struct stat *,register char *, int));
  *     file descriptor or -1 for failure
  */
 
-#ifdef __STDC__
 int
-file_creat(register ARCHD *arcn)
-#else
-int
-file_creat(arcn)
-       register ARCHD *arcn;
-#endif
+file_creat(ARCHD *arcn)
 {
        int fd = -1;
        mode_t file_mode;
        int oerrno;
+       int rc = 0;
+       char *path_to_open;
+       char *new_path;
+       char *cwd;
+       char cwd_buff[MAXPATHLEN];
 
        /*
-        * assume file doesn't exist, so just try to create it, most times this
+        * Assume file doesn't exist, so just try to create it, most times this
         * works. We have to take special handling when the file does exist. To
         * detect this, we use O_EXCL. For example when trying to create a
         * file and a character device or fifo exists with the same name, we
-        * can accidently open the device by mistake (or block waiting to open)
-        * If we find that the open has failed, then figure spend the effore to
+        * can accidently open the device by mistake (or block waiting to open).
+        * If we find that the open has failed, then spend the effort to
         * figure out why. This strategy was found to have better average
         * performance in common use than checking the file (and the path)
         * first with lstat.
@@ -117,20 +112,44 @@ file_creat(arcn)
        if (unlnk_exist(arcn->name, arcn->type) != 0)
                return(-1);
 
+       path_to_open = arcn->name;
+       new_path = arcn->name;
+       cwd = getcwd(&cwd_buff[0],MAXPATHLEN);
+       if (cwd==NULL) return -1;
        for (;;) {
                /*
                 * try to open it again, if this fails, check all the nodes in
                 * the path and give it a final try. if chk_path() finds that
                 * it cannot fix anything, we will skip the last attempt
                 */
-               if ((fd = open(arcn->name, O_WRONLY | O_CREAT | O_TRUNC,
-                   file_mode)) >= 0)
+               if ((fd = open(path_to_open, O_WRONLY | O_CREAT | O_TRUNC,
+                   file_mode)) >= 0) {
+                       /* clean up the invalid_action */
+                       if (pax_invalid_action>0) {
+                               record_pax_invalid_action_results(arcn, path_to_open);
+                       }
                        break;
+               }
                oerrno = errno;
-               if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
-                       syswarn(1, oerrno, "Unable to create %s", arcn->name);
-                       return(-1);
+               if (pax_invalid_action>0) {
+                       rc = perform_pax_invalid_action(arcn, oerrno);
+                       if (rc == 0) continue;
+                       if (rc == 1) {
+                               fd = -1;
+                               break;
+                       }
                }
+               /* rc == 2 reserved for -o invalid_action=write */
+               if (nodirs || chk_path(path_to_open,arcn->sb.st_uid,arcn->sb.st_gid, 
+                               (rc==2) ? &new_path: NULL) < 0) {
+                       syswarn((pax_invalid_action==0), oerrno, "Unable to create %s", arcn->name);
+                       fd = -1;
+                       break;
+               }
+               if (new_path) path_to_open = new_path; /* try again */
+       }
+       if (strcmp(new_path, arcn->name)!=0) { 
+               chdir(cwd);     /* go back to original directory */
        }
        return(fd);
 }
@@ -143,15 +162,8 @@ file_creat(arcn)
  *     0 for success, -1 for failure
  */
 
-#ifdef __STDC__
-void
-file_close(register ARCHD *arcn, int fd)
-#else
 void
-file_close(arcn, fd)
-       register ARCHD *arcn;
-       int fd;
-#endif
+file_close(ARCHD *arcn, int fd)
 {
        int res = 0;
 
@@ -164,17 +176,19 @@ file_close(arcn, fd)
        /*
         * set owner/groups first as this may strip off mode bits we want
         * then set file permission modes. Then set file access and
-        * modification times. 
+        * modification times.
         */
        if (pids)
                res = set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid);
+       else
+               res = 1; /* without pids, pax should NOT set s bits */
 
        /*
         * IMPORTANT SECURITY NOTE:
         * if not preserving mode or we cannot set uid/gid, then PROHIBIT
         * set uid/gid bits
         */
-       if (!pids || res)
+       if (!pmode || res)
                arcn->sb.st_mode &= ~(SETBITS);
        if (pmode)
                set_pmode(arcn->name, arcn->sb.st_mode);
@@ -185,19 +199,13 @@ file_close(arcn, fd)
 /*
  * lnk_creat()
  *     Create a hard link to arcn->ln_name from arcn->name. arcn->ln_name
- *     must exist; 
+ *     must exist;
  * Return:
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-lnk_creat(register ARCHD *arcn)
-#else
-int
-lnk_creat(arcn)
-       register ARCHD *arcn;
-#endif
+lnk_creat(ARCHD *arcn)
 {
        struct stat sb;
 
@@ -217,6 +225,23 @@ lnk_creat(arcn)
                return(-1);
        }
 
+       if (S_ISLNK(sb.st_mode)) {
+               int res;
+               char buff[NAME_MAX+1];
+               /* 
+                * Conformance: cannot make hard link to symlink - just make a 
+                * symlink to the target of the symlink
+                */
+               if ((res = readlink(arcn->ln_name, buff, sizeof(buff))) < 0) {
+                       syswarn(1,errno,"Unable to symlink to %s from %s", arcn->ln_name,
+                                   arcn->name);
+                       return(-1);
+               }
+               buff[res] = 0;
+               res = symlink(buff, arcn->name);
+               return res;
+       }
+
        return(mk_link(arcn->ln_name, &sb, arcn->name, 0));
 }
 
@@ -230,22 +255,20 @@ lnk_creat(arcn)
  *     0 if cross_lnk() ok, -1 for fatal flaw (like linking to self).
  */
 
-#ifdef __STDC__
-int
-cross_lnk(register ARCHD *arcn)
-#else
 int
-cross_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+cross_lnk(ARCHD *arcn)
 {
        /*
-        * try to make a link to orginal file (-l flag in copy mode). make sure
-        * we do not try to link to directories in case we are running as root
-        * (and it might succeed).
+        * try to make a link to original file (-l flag in copy mode). make
+        * sure we do not try to link to directories in case we are running as
+        * root (and it might succeed).
         */
        if (arcn->type == PAX_DIR)
                return(1);
+       if (arcn->type == PAX_SLK) {    /* for Unix 03 conformance tests 202,203 */
+               if (!Lflag)
+                       return(1);
+       }
        return(mk_link(arcn->org_name, &(arcn->sb), arcn->name, 1));
 }
 
@@ -260,18 +283,12 @@ cross_lnk(arcn)
  *     0 skip it file exists (-k) or may be the same as source file
  */
 
-#ifdef __STDC__
 int
-chk_same(register ARCHD *arcn)
-#else
-int
-chk_same(arcn)
-       register ARCHD *arcn;
-#endif
+chk_same(ARCHD *arcn)
 {
        struct stat sb;
 
-       /* 
+       /*
         * if file does not exist, return. if file exists and -k, skip it
         * quietly
         */
@@ -303,18 +320,8 @@ chk_same(arcn)
  *     allowed option). -1 an error occurred.
  */
 
-#ifdef __STDC__
-static int
-mk_link(register char *to, register struct stat *to_sb, register char *from,
-       int ign)
-#else
 static int
-mk_link(to, to_sb, from, ign)
-       register char *to;
-       register struct stat *to_sb;
-       register char *from;
-       int ign;
-#endif
+mk_link(char *to, struct stat *to_sb, char *from, int ign)
 {
        struct stat sb;
        int oerrno;
@@ -332,7 +339,7 @@ mk_link(to, to_sb, from, ign)
                 */
                if ((to_sb->st_dev==sb.st_dev)&&(to_sb->st_ino == sb.st_ino)) {
                        paxwarn(1, "Unable to link file %s to itself", to);
-                       return(-1);;
+                       return(-1);
                }
 
                /*
@@ -361,7 +368,7 @@ mk_link(to, to_sb, from, ign)
                if (link(to, from) == 0)
                        break;
                oerrno = errno;
-               if (!nodirs && chk_path(from, to_sb->st_uid, to_sb->st_gid) == 0)
+               if (!nodirs && chk_path(from, to_sb->st_uid, to_sb->st_gid, NULL) == 0)
                        continue;
                if (!ign) {
                        syswarn(1, oerrno, "Could not link to %s from %s", to,
@@ -385,21 +392,18 @@ mk_link(to, to_sb, from, ign)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-node_creat(register ARCHD *arcn)
-#else
 int
-node_creat(arcn)
-       register ARCHD *arcn;
-#endif
+node_creat(ARCHD *arcn)
 {
-       register int res;
-       register int ign = 0;
-       register int oerrno;
-       register int pass = 0;
+       int res;
+       int ign = 0;
+       int oerrno;
+       int pass = 0;
        mode_t file_mode;
        struct stat sb;
+       char target[MAXPATHLEN];
+       char *nm = arcn->name;
+       int len;
 
        /*
         * create node based on type, if that fails try to unlink the node and
@@ -410,22 +414,45 @@ node_creat(arcn)
        file_mode = arcn->sb.st_mode & FILEBITS;
 
        for (;;) {
-               switch(arcn->type) {
+               switch (arcn->type) {
                case PAX_DIR:
-                       res = mkdir(arcn->name, file_mode);
+                       /*
+                        * If -h (or -L) was given in tar-mode, follow the
+                        * potential symlink chain before trying to create the
+                        * directory.
+                        */
+                       if (strcmp(NM_TAR, argv0) == 0 && Lflag) {
+                               while (lstat(nm, &sb) == 0 &&
+                                   S_ISLNK(sb.st_mode)) {
+                                       len = readlink(nm, target,
+                                           sizeof target - 1);
+                                       if (len == -1) {
+                                               syswarn(0, errno,
+                                                  "cannot follow symlink %s in chain for %s",
+                                                   nm, arcn->name);
+                                               res = -1;
+                                               goto badlink;
+                                       }
+                                       target[len] = '\0';
+                                       nm = target;
+                               }
+                       }
+                       res = mkdir(nm, file_mode);
+
+badlink:
                        if (ign)
                                res = 0;
                        break;
                case PAX_CHR:
                        file_mode |= S_IFCHR;
-                       res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+                       res = mknod(nm, file_mode, arcn->sb.st_rdev);
                        break;
                case PAX_BLK:
                        file_mode |= S_IFBLK;
-                       res = mknod(arcn->name, file_mode, arcn->sb.st_rdev);
+                       res = mknod(nm, file_mode, arcn->sb.st_rdev);
                        break;
                case PAX_FIF:
-                       res = mkfifo(arcn->name, file_mode);
+                       res = mkfifo(nm, file_mode);
                        break;
                case PAX_SCK:
                        /*
@@ -433,10 +460,10 @@ node_creat(arcn)
                         */
                        paxwarn(0,
                            "%s skipped. Sockets cannot be copied or extracted",
-                           arcn->name);
+                           nm);
                        return(-1);
                case PAX_SLK:
-                       res = symlink(arcn->ln_name, arcn->name);
+                       res = symlink(arcn->ln_name, nm);
                        break;
                case PAX_CTG:
                case PAX_HLK:
@@ -447,7 +474,7 @@ node_creat(arcn)
                         * we should never get here
                         */
                        paxwarn(0, "%s has an unknown file type, skipping",
-                               arcn->name);
+                               nm);
                        return(-1);
                }
 
@@ -463,14 +490,14 @@ node_creat(arcn)
                 * we failed to make the node
                 */
                oerrno = errno;
-               if ((ign = unlnk_exist(arcn->name, arcn->type)) < 0)
+               if ((ign = unlnk_exist(nm, arcn->type)) < 0)
                        return(-1);
 
                if (++pass <= 1)
                        continue;
 
-               if (nodirs || chk_path(arcn->name,arcn->sb.st_uid,arcn->sb.st_gid) < 0) {
-                       syswarn(1, oerrno, "Could not create: %s", arcn->name);
+               if (nodirs || chk_path(nm,arcn->sb.st_uid,arcn->sb.st_gid, NULL) < 0) {
+                       syswarn(1, oerrno, "Could not create: %s", nm);
                        return(-1);
                }
        }
@@ -481,14 +508,14 @@ node_creat(arcn)
        if (pids)
                res = ((arcn->type == PAX_SLK) ?
 #if defined(__APPLE__)
-                   /* Mac OS X doesn't have lchown, so don't bother */
+                   /* Mac OS X doesn't have lchown, so don't bother */
                    0 :
 #else
-                   set_lids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid) :
+                   set_lids(nm, arcn->sb.st_uid, arcn->sb.st_gid) :
 #endif
-                   set_ids(arcn->name, arcn->sb.st_uid, arcn->sb.st_gid));
+                   set_ids(nm, arcn->sb.st_uid, arcn->sb.st_gid));
        else
-               res = 0;
+               res = 1; /* without pids, pax should NOT set s bits */
 
        /*
         * symlinks are done now.
@@ -504,7 +531,7 @@ node_creat(arcn)
        if (!pmode || res)
                arcn->sb.st_mode &= ~(SETBITS);
        if (pmode)
-               set_pmode(arcn->name, arcn->sb.st_mode);
+               set_pmode(nm, arcn->sb.st_mode);
 
        if (arcn->type == PAX_DIR && strcmp(NM_CPIO, argv0) != 0) {
                /*
@@ -516,11 +543,11 @@ node_creat(arcn)
                 * and modes will be fixed after the entire archive is read and
                 * before pax exits.
                 */
-               if (access(arcn->name, R_OK | W_OK | X_OK) < 0) {
-                       if (lstat(arcn->name, &sb) < 0) {
+               if (access(nm, R_OK | W_OK | X_OK) < 0) {
+                       if (lstat(nm, &sb) < 0) {
                                syswarn(0, errno,"Could not access %s (stat)",
                                    arcn->name);
-                               set_pmode(arcn->name,file_mode | S_IRWXU);
+                               set_pmode(nm,file_mode | S_IRWXU);
                        } else {
                                /*
                                 * We have to add rights to the dir, so we make
@@ -528,7 +555,7 @@ node_creat(arcn)
                                 * restored AS CREATED and not as stored if
                                 * pmode is not set.
                                 */
-                               set_pmode(arcn->name,
+                               set_pmode(nm,
                                    ((sb.st_mode & FILEBITS) | S_IRWXU));
                                if (!pmode)
                                        arcn->sb.st_mode = sb.st_mode;
@@ -538,13 +565,13 @@ node_creat(arcn)
                         * we have to force the mode to what was set here,
                         * since we changed it from the default as created.
                         */
-                       add_dir(arcn->name, arcn->nlen, &(arcn->sb), 1);
+                       add_dir(nm, &(arcn->sb), 1);
                } else if (pmode || patime || pmtime)
-                       add_dir(arcn->name, arcn->nlen, &(arcn->sb), 0);
+                       add_dir(nm, &(arcn->sb), 0);
        }
 
        if (patime || pmtime)
-               set_ftime(arcn->name, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
+               set_ftime(nm, arcn->sb.st_mtime, arcn->sb.st_atime, 0);
        return(0);
 }
 
@@ -560,15 +587,8 @@ node_creat(arcn)
  *     1 we found a directory and we were going to create a directory.
  */
 
-#ifdef __STDC__
 int
-unlnk_exist(register char *name, register int type)
-#else
-int
-unlnk_exist(name, type)
-       register char *name;
-       register int type;
-#endif
+unlnk_exist(char *name, int type)
 {
        struct stat sb;
 
@@ -621,18 +641,10 @@ unlnk_exist(name, type)
  *     0 otherwise
  */
 
-#ifdef __STDC__
-int
-chk_path( register char *name, uid_t st_uid, gid_t st_gid)
-#else
 int
-chk_path(name, st_uid, st_gid)
-       register char *name;
-       uid_t st_uid;
-       gid_t st_gid;
-#endif
+chk_path(char *name, uid_t st_uid, gid_t st_gid, char ** new_name)
 {
-       register char *spt = name;
+       char *spt = name;
        struct stat sb;
        int retval = -1;
 
@@ -642,9 +654,9 @@ chk_path(name, st_uid, st_gid)
        if (*spt == '/')
                ++spt;
 
-       for(;;) {
+       for (;;) {
                /*
-                * work foward from the first / and check each part of the path
+                * work forward from the first / and check each part of the path
                 */
                spt = strchr(spt, '/');
                if (spt == NULL)
@@ -662,7 +674,9 @@ chk_path(name, st_uid, st_gid)
                 */
                if (lstat(name, &sb) == 0) {
                        *(spt++) = '/';
-                       continue;
+                       if (new_name==NULL) continue;
+                       retval = 0; /* accept it one directory at a time */
+                       break;
                }
 
                /*
@@ -685,7 +699,7 @@ chk_path(name, st_uid, st_gid)
                        (void)set_ids(name, st_uid, st_gid);
 
                /*
-                * make sure the user doen't have some strange umask that
+                * make sure the user doesn't have some strange umask that
                 * causes this newly created directory to be unusable. We fix
                 * the modes and restore them back to the creation default at
                 * the end of pax
@@ -693,37 +707,45 @@ chk_path(name, st_uid, st_gid)
                if ((access(name, R_OK | W_OK | X_OK) < 0) &&
                    (lstat(name, &sb) == 0)) {
                        set_pmode(name, ((sb.st_mode & FILEBITS) | S_IRWXU));
-                       add_dir(name, spt - name, &sb, 1);
+                       add_dir(name, &sb, 1);
                }
                *(spt++) = '/';
-               continue;
+               if (new_name==NULL) continue;
+               break;
+       }
+
+       if ((new_name != NULL) && retval==0) {
+               /* save the new path */
+               *(--spt) = '\0';
+               /*
+               printf ("chdir to %s\n", name);
+               */
+               if(0==chdir(name)) {
+                       *spt++ = '/';
+                       /*
+                       printf ("remaining path: %s\n",spt);
+                       */
+                       *new_name = spt;
+               } else
+                       *spt++ = '/';
        }
        return(retval);
 }
 
 /*
  * set_ftime()
- *     Set the access time and modification time for a named file. If frc is
- *     non-zero we force these times to be set even if the user did not
+ *     Set the access time and modification time for a named file. If frc
+ *     is non-zero we force these times to be set even if the user did not
  *     request access and/or modification time preservation (this is also
  *     used by -t to reset access times).
- *     When ign is zero, only those times the user has asked for are set, the
+ *     When frc is zero, only those times the user has asked for are set, the
  *     other ones are left alone. We do not assume the un-documented feature
  *     of many utimes() implementations that consider a 0 time value as a do
  *     not set request.
  */
 
-#ifdef __STDC__
 void
 set_ftime(char *fnm, time_t mtime, time_t atime, int frc)
-#else
-void
-set_ftime(fnm, mtime, atime, frc)
-       char *fnm;
-       time_t mtime;
-       time_t atime;
-       int frc;
-#endif
 {
        static struct timeval tv[2] = {{0L, 0L}, {0L, 0L}};
        struct stat sb;
@@ -747,9 +769,22 @@ set_ftime(fnm, mtime, atime, frc)
        /*
         * set the times
         */
-       if (utimes(fnm, tv) < 0)
-               syswarn(1, errno, "Access/modification time set failed on: %s",
-                   fnm);
+
+       if (pax_invalid_action_write_cwd) {
+               char cwd_buff[MAXPATHLEN];
+               char * cwd;
+               cwd = getcwd(&cwd_buff[0],MAXPATHLEN);
+               chdir(pax_invalid_action_write_cwd);
+               if (utimes(pax_invalid_action_write_path, tv) < 0)
+                       syswarn(1, errno, "Access/modification time set failed on: %s",
+                           pax_invalid_action_write_path);
+               chdir(cwd);
+               cleanup_pax_invalid_action();
+       } else {
+               if (utimes(fnm, tv) < 0)
+                       syswarn(1, errno, "Access/modification time set failed on: %s",
+                           fnm);
+       }
        return;
 }
 
@@ -760,16 +795,8 @@ set_ftime(fnm, mtime, atime, frc)
  *     0 when set, -1 on failure
  */
 
-#ifdef __STDC__
 int
 set_ids(char *fnm, uid_t uid, gid_t gid)
-#else
-int
-set_ids(fnm, uid, gid)
-       char *fnm;
-       uid_t uid;
-       gid_t gid;
-#endif
 {
        if (chown(fnm, uid, gid) < 0) {
                /*
@@ -787,7 +814,6 @@ set_ids(fnm, uid, gid)
 
 #if !defined(__APPLE__)
 /* Mac OS X doesn't have lchown */
-
 /*
  * set_lids()
  *     set the uid and gid of a file system node
@@ -795,16 +821,8 @@ set_ids(fnm, uid, gid)
  *     0 when set, -1 on failure
  */
 
-#ifdef __STDC__
 int
 set_lids(char *fnm, uid_t uid, gid_t gid)
-#else
-int
-set_lids(fnm, uid, gid)
-       char *fnm;
-       uid_t uid;
-       gid_t gid;
-#endif
 {
        if (lchown(fnm, uid, gid) < 0) {
                /*
@@ -826,15 +844,8 @@ set_lids(fnm, uid, gid)
  *     Set file access mode
  */
 
-#ifdef __STDC__
 void
 set_pmode(char *fnm, mode_t mode)
-#else
-void
-set_pmode(fnm, mode)
-       char *fnm;
-       mode_t mode;
-#endif
 {
        mode &= ABITS;
        if (chmod(fnm, mode) < 0)
@@ -861,11 +872,11 @@ set_pmode(fnm, mode)
  *     uses lseek whenever it detects the input data is all 0 within that
  *     file block. In more detail, the strategy is as follows:
  *     While the input is all zero keep doing an lseek. Keep track of when we
- *     pass over file block boundries. Only write when we hit a non zero
+ *     pass over file block boundaries. Only write when we hit a non zero
  *     input. once we have written a file block, we continue to write it to
  *     the end (we stop looking at the input). When we reach the start of the
  *     next file block, start checking for zero blocks again. Working on file
- *     block boundries significantly reduces the overhead when copying files
+ *     block boundaries significantly reduces the overhead when copying files
  *     that are NOT very sparse. This overhead (when compared to a write) is
  *     almost below the measurement resolution on many systems. Without it,
  *     files with holes cannot be safely copied. It does has a side effect as
@@ -890,26 +901,15 @@ set_pmode(fnm, mode)
  *     number of bytes written, -1 on write (or lseek) error.
  */
 
-#ifdef __STDC__
 int
-file_write(int fd, char *str, register int cnt, int *rem, int *isempt, int sz,
+file_write(int fd, char *str, int cnt, int *rem, int *isempt, int sz,
        char *name)
-#else
-int
-file_write(fd, str, cnt, rem, isempt, sz, name)
-       int fd;
-       char *str;
-       register int cnt;
-       int *rem;
-       int *isempt;
-       int sz;
-       char *name;
-#endif
 {
-       register char *pt;
-       register char *end;
-       register int wcnt;
-       register char *st = str;
+       char *pt;
+       char *end;
+       int wcnt;
+       char *st = str;
+       char **strp;
 
        /*
         * while we have data to process
@@ -950,7 +950,8 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
                                /*
                                 * skip, buf is empty so far
                                 */
-                               if (lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
+                               if (fd > -1 &&
+                                   lseek(fd, (off_t)wcnt, SEEK_CUR) < 0) {
                                        syswarn(1,errno,"File seek on %s",
                                            name);
                                        return(-1);
@@ -967,7 +968,29 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
                /*
                 * have non-zero data in this file system block, have to write
                 */
-               if (write(fd, st, wcnt) != wcnt) {
+               switch (fd) {
+               case -1:
+                       strp = &gnu_name_string;
+                       break;
+               case -2:
+                       strp = &gnu_link_string;
+                       break;
+               default:
+                       strp = NULL;
+                       break;
+               }
+               if (strp) {
+                       if (*strp)
+                               err(1, "WARNING! Major Internal Error! GNU hack Failing!");
+                       *strp = malloc(wcnt + 1);
+                       if (*strp == NULL) {
+                               paxwarn(1, "Out of memory");
+                               return(-1);
+                       }
+                       memcpy(*strp, st, wcnt);
+                       (*strp)[wcnt] = '\0';
+                       break;
+               } else if (write(fd, st, wcnt) != wcnt) {
                        syswarn(1, errno, "Failed write to file %s", name);
                        return(-1);
                }
@@ -983,16 +1006,8 @@ file_write(fd, str, cnt, rem, isempt, sz, name)
  *     write the last BYTE with a zero (back up one byte and write a zero).
  */
 
-#ifdef __STDC__
 void
 file_flush(int fd, char *fname, int isempt)
-#else
-void
-file_flush(fd, fname, isempt)
-       int fd;
-       char *fname;
-       int isempt;
-#endif
 {
        static char blnk[] = "\0";
 
@@ -1022,15 +1037,8 @@ file_flush(fd, fname, isempt)
  *     reset access time (tflag) do so (the times are stored in arcn).
  */
 
-#ifdef __STDC__
 void
-rdfile_close(register ARCHD *arcn, register int *fd)
-#else
-void
-rdfile_close(arcn, fd)
-       register ARCHD *arcn;
-       register int *fd;
-#endif
+rdfile_close(ARCHD *arcn, int *fd)
 {
        /*
         * make sure the file is open
@@ -1059,18 +1067,11 @@ rdfile_close(arcn, fd)
  *     0 if was able to calculate the crc, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-set_crc(register ARCHD *arcn, register int fd)
-#else
 int
-set_crc(arcn, fd)
-       register ARCHD *arcn;
-       register int fd;
-#endif
+set_crc(ARCHD *arcn, int fd)
 {
-       register int i;
-       register int res;
+       int i;
+       int res;
        off_t cpcnt = 0L;
        u_long size;
        unsigned long crc = 0L;
@@ -1092,7 +1093,7 @@ set_crc(arcn, fd)
         * read all the bytes we think that there are in the file. If the user
         * is trying to archive an active file, forget this file.
         */
-       for(;;) {
+       for (;;) {
                if ((res = read(fd, tbuf, size)) <= 0)
                        break;
                cpcnt += res;
@@ -1102,7 +1103,7 @@ set_crc(arcn, fd)
 
        /*
         * safety check. we want to avoid archiving files that are active as
-        * they can create inconsistant archive copies.
+        * they can create inconsistent archive copies.
         */
        if (cpcnt != arcn->sb.st_size)
                paxwarn(1, "File changed size %s", arcn->org_name);
index c5fcc446d1793984dc13e7571c0eb22d7d221a0d..14d1712860784fa91c184992f8956c7c0ca7f6af 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftree.c,v 1.8 1997/09/01 18:29:49 deraadt Exp $       */
+/*     $OpenBSD: ftree.c,v 1.25 2004/04/16 22:50:23 deraadt Exp $      */
 /*     $NetBSD: ftree.c,v 1.4 1995/03/21 09:07:21 cgd Exp $    */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)ftree.c    8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)ftree.c      8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ftree.c,v 1.8 1997/09/01 18:29:49 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ftree.c,v 1.25 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -74,7 +70,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: ftree.c,v 1.8 1997/
  * pax, they are read from stdin
  */
 
-static FTS *ftsp = NULL;               /* curent FTS handle */
+static FTS *ftsp = NULL;               /* current FTS handle */
 static int ftsopts;                    /* options to be used on fts_open */
 static char *farray[2];                        /* array for passing each arg to fts */
 static FTREE *fthead = NULL;           /* head of linked list of file args */
@@ -83,7 +79,8 @@ static FTREE *ftcur = NULL;           /* current file arg being processed */
 static FTSENT *ftent = NULL;           /* current file tree entry */
 static int ftree_skip;                 /* when set skip to next file arg */
 
-static int ftree_arg __P((void));
+static int ftree_arg(void);
+static char *getpathname(char *, int);
 
 /*
  * ftree_start()
@@ -95,13 +92,8 @@ static int ftree_arg __P((void));
  *     0 if there is at least one valid file arg to process, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ftree_start(void)
-#else
-int
-ftree_start()
-#endif
 {
        /*
         * set up the operation mode of fts, open the first file arg. We must
@@ -126,11 +118,7 @@ ftree_start()
        else
                ftsopts |= FTS_PHYSICAL;
        if (Hflag)
-#      ifdef NET2_FTS
-               paxwarn(0, "The -H flag is not supported on this version");
-#      else
                ftsopts |= FTS_COMFOLLOW;
-#      endif
        if (Xflag)
                ftsopts |= FTS_XDEV;
 
@@ -154,24 +142,17 @@ ftree_start()
  *     0 if added to the linked list, -1 if failed
  */
 
-#ifdef __STDC__
-int
-ftree_add(register char *str, int chflg)
-#else
 int
-ftree_add(str, chflg)
-       register char *str;
-       int chflg;
-#endif
+ftree_add(char *str, int chflg)
 {
-       register FTREE *ft;
-       register int len;
+       FTREE *ft;
+       int len;
 
        /*
         * simple check for bad args
         */
        if ((str == NULL) || (*str == '\0')) {
-               paxwarn(0, "Invalid file name arguement");
+               paxwarn(0, "Invalid file name argument");
                return(-1);
        }
 
@@ -206,14 +187,8 @@ ftree_add(str, chflg)
  *     -n and -d processing.
  */
 
-#ifdef __STDC__
-void
-ftree_sel(register ARCHD *arcn)
-#else
 void
-ftree_sel(arcn)
-       register ARCHD *arcn;
-#endif
+ftree_sel(ARCHD *arcn)
 {
        /*
         * set reference bit for this pattern. This linked list is only used
@@ -245,16 +220,11 @@ ftree_sel(arcn)
  *     have a selected member (reference count still 0)
  */
 
-#ifdef __STDC__
 void
 ftree_chk(void)
-#else
-void
-ftree_chk()
-#endif
 {
-       register FTREE *ft;
-       register int wban = 0;
+       FTREE *ft;
+       int wban = 0;
 
        /*
         * make sure all dir access times were reset.
@@ -287,15 +257,9 @@ ftree_chk()
  *     stdin).
  */
 
-#ifdef __STDC__
 static int
 ftree_arg(void)
-#else
-static int
-ftree_arg()
-#endif
 {
-       register char *pt;
 
        /*
         * close off the current file tree
@@ -309,19 +273,17 @@ ftree_arg()
         * keep looping until we get a valid file tree to process. Stop when we
         * reach the end of the list (or get an eof on stdin)
         */
-       for(;;) {
+       for (;;) {
                if (fthead == NULL) {
                        /*
                         * the user didn't supply any args, get the file trees
-                        * to process from stdin; 
+                        * to process from stdin;
                         */
-                       if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
+                       if (getpathname(farray[0], PAXPATHLEN+1) == NULL)
                                return(-1);
-                       if ((pt = strchr(farray[0], '\n')) != NULL)
-                               *pt = '\0';
                } else {
                        /*
-                        * the user supplied the file args as arguements to pax
+                        * the user supplied the file args as arguments to pax
                         */
                        if (ftcur == NULL)
                                ftcur = fthead;
@@ -348,7 +310,7 @@ ftree_arg()
                 * watch it, fts wants the file arg stored in a array of char
                 * ptrs, with the last one a null. we use a two element array
                 * and set farray[0] to point at the buffer with the file name
-                * in it. We cannnot pass all the file args to fts at one shot
+                * in it. We cannot pass all the file args to fts at one shot
                 * as we need to keep a handle on which file arg generates what
                 * files (the -n and -d flags need this). If the open is
                 * successful, return a 0.
@@ -366,23 +328,17 @@ ftree_arg()
  *     0 when contents of arcn have been set with the next file, -1 when done.
  */
 
-#ifdef __STDC__
-int
-next_file(register ARCHD *arcn)
-#else
 int
-next_file(arcn)
-       register ARCHD *arcn;
-#endif
+next_file(ARCHD *arcn)
 {
-       register int cnt;
+       int cnt;
        time_t atime;
        time_t mtime;
 
        /*
         * ftree_sel() might have set the ftree_skip flag if the user has the
         * -n option and a file was selected from this file arg tree. (-n says
-        * only one member is matched for each pattern) ftree_skip being 1 
+        * only one member is matched for each pattern) ftree_skip being 1
         * forces us to go to the next arg now.
         */
        if (ftree_skip) {
@@ -397,7 +353,7 @@ next_file(arcn)
        /*
         * loop until we get a valid file to process
         */
-       for(;;) {
+       for (;;) {
                if ((ftent = fts_read(ftsp)) == NULL) {
                        /*
                         * out of files in this tree, go to next arg, if none
@@ -411,16 +367,23 @@ next_file(arcn)
                /*
                 * handle each type of fts_read() flag
                 */
-               switch(ftent->fts_info) {
+               switch (ftent->fts_info) {
                case FTS_D:
                case FTS_DEFAULT:
                case FTS_F:
                case FTS_SL:
-               case FTS_SLNONE:
                        /*
                         * these are all ok
                         */
                        break;
+               case FTS_SLNONE:        /* was same as above cases except Unix
+                                          conformance requires this error check */
+                       if (Hflag || Lflag) {       /* -H or -L was specified */
+                               if (ftent->fts_errno)
+                                       paxwarn(1, "%s: %s",
+                                               ftent->fts_name, strerror(ftent->fts_errno));
+                       }
+                       break;
                case FTS_DP:
                        /*
                         * already saw this directory. If the user wants file
@@ -430,13 +393,8 @@ next_file(arcn)
                         * remember to force the time (this is -t on a read
                         * directory, not a created directory).
                         */
-#                      ifdef NET2_FTS
-                       if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
-                           ftent->fts_statb.st_ino, &mtime, &atime) < 0))
-#                      else
                        if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
                            ftent->fts_statp->st_ino, &mtime, &atime) < 0))
-#                      endif
                                continue;
                        set_ftime(ftent->fts_path, mtime, atime, 1);
                        continue;
@@ -447,28 +405,16 @@ next_file(arcn)
                        paxwarn(1,"File system cycle found at %s",ftent->fts_path);
                        continue;
                case FTS_DNR:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "Unable to read directory %s", ftent->fts_path);
                        continue;
                case FTS_ERR:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "File system traversal error");
                        continue;
                case FTS_NS:
                case FTS_NSOK:
-#                      ifdef NET2_FTS
-                       syswarn(1, errno,
-#                      else
                        syswarn(1, ftent->fts_errno,
-#                      endif
                            "Unable to access %s", ftent->fts_path);
                        continue;
                }
@@ -481,11 +427,7 @@ next_file(arcn)
                arcn->pad = 0;
                arcn->ln_nlen = 0;
                arcn->ln_name[0] = '\0';
-#              ifdef NET2_FTS
-               arcn->sb = ftent->fts_statb;
-#              else
-               arcn->sb = *(ftent->fts_statp);
-#              endif
+               memcpy(&arcn->sb, ftent->fts_statp, sizeof(arcn->sb));
 
                /*
                 * file type based set up and copy into the arcn struct
@@ -497,7 +439,7 @@ next_file(arcn)
                 * end in case we cut short a file tree traversal). However
                 * there is no way to reset access times on symlinks.
                 */
-               switch(S_IFMT & arcn->sb.st_mode) {
+               switch (S_IFMT & arcn->sb.st_mode) {
                case S_IFDIR:
                        arcn->type = PAX_DIR;
                        if (!tflag)
@@ -535,7 +477,7 @@ next_file(arcn)
                        }
                        /*
                         * set link name length, watch out readlink does not
-                        * allways null terminate the link path
+                        * always NUL terminate the link path
                         */
                        arcn->ln_name[cnt] = '\0';
                        arcn->ln_nlen = cnt;
@@ -558,8 +500,55 @@ next_file(arcn)
        /*
         * copy file name, set file name length
         */
-       arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
        arcn->org_name = ftent->fts_path;
        return(0);
 }
+
+/*
+ * getpathname()
+ *     Reads a pathname from stdin, handling NUL- or newline-termination.
+ * Return:
+ *     NULL at end of file, otherwise the NUL-terminated buffer.
+ */
+
+static char *
+getpathname(char *buf, int buflen)
+{
+       char *bp, *ep;
+       int ch, term;
+
+       if (zeroflag) {
+               /*
+                * Read a NUL-terminated pathname, being especially
+                * paranoid about proper termination and pathname length.
+                */
+               for (bp = buf, ep = buf + buflen; bp < ep; bp++) {
+                       if ((ch = getchar()) == EOF) {
+                               if (bp != buf)
+                                       paxwarn(1, "Ignoring unterminated "
+                                           "pathname at EOF");
+                               return(NULL);
+                       }
+                       if ((*bp = ch) == '\0')
+                               return(buf);
+               }
+               /* Too long - skip this path */
+               *--bp = '\0';
+               term = '\0';
+       } else {
+               if (fgets(buf, buflen, stdin) == NULL)
+                       return(NULL);
+               if ((bp = strchr(buf, '\n')) != NULL || feof(stdin)) {
+                       if (bp != NULL)
+                               *bp = '\0';
+                       return(buf);
+               }
+               /* Too long - skip this path */
+               term = '\n';
+       }
+       while ((ch = getchar()) != term && ch != EOF)
+               ;
+       paxwarn(1, "Ignoring too-long pathname: %s", buf);
+       return(NULL);
+}
index 5ac8ff9b9b44aef31a37a681383e2a21ec4d03ee..0507aab187321d55acf18577431abe389fe50dfa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ftree.h,v 1.3 1996/10/27 06:45:11 downsj Exp $        */
+/*     $OpenBSD: ftree.h,v 1.4 2003/06/02 23:32:08 millert Exp $       */
 /*     $NetBSD: ftree.h,v 1.3 1995/03/21 09:07:23 cgd Exp $    */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
index 4f5f898b0d559da5170f69dde6cc039289508c1c..36bbb41d55eddee0f298024ac13880ae3b6a7f51 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $    */
+/*     $OpenBSD: gen_subs.c,v 1.17 2003/06/13 17:51:14 millert Exp $   */
 /*     $NetBSD: gen_subs.c,v 1.5 1995/03/21 09:07:26 cgd Exp $ */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)gen_subs.c 8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)gen_subs.c   8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: gen_subs.c,v 1.8 1997/09/01 18:29:51 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: gen_subs.c,v 1.17 2003/06/13 17:51:14 millert Exp $";
 #endif
 #endif /* not lint */
 
@@ -56,6 +52,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: gen_subs.c,v 1.8 19
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <vis.h>
 #include "pax.h"
 #include "extern.h"
 
@@ -71,80 +68,96 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: gen_subs.c,v 1.8 19
 #define SIXMONTHS       ((DAYSPERNYEAR / 2) * SECSPERDAY)
 #define CURFRMT                "%b %e %H:%M"
 #define OLDFRMT                "%b %e  %Y"
-#ifndef UT_NAMESIZE
-#define UT_NAMESIZE    8
-#endif
-#define UT_GRPSIZE     6
+#define NAME_WIDTH     8
+
+/*
+ * format_date
+ *       format date of file for printing
+ */
+
+static void
+format_date(char * f_date, time_t file_time, time_t current)
+{
+       const char *timefrmt;
+
+       if (ltmfrmt == NULL) {
+               /*
+                * no locale specified format. 
+                */
+               /* use the same format that ls -l uses */
+               if ((file_time + SIXMONTHS) <= current || file_time > current)
+                       timefrmt = OLDFRMT;
+               else
+                       timefrmt = CURFRMT;
+       } else
+               timefrmt = ltmfrmt;
+
+       /*
+        * convert time to string for printing
+        */
+       if (strftime(f_date,DATELEN,timefrmt,localtime((const time_t *)&(file_time))) == 0)
+               *f_date = '\0';
+}
 
 /*
  * ls_list()
  *     list the members of an archive in ls format
  */
 
-#ifdef __STDC__
 void
-ls_list(register ARCHD *arcn, time_t now, FILE *fp)
-#else
-void
-ls_list(arcn, now, fp)
-       register ARCHD *arcn;
-       time_t now;
-       FILE *fp;
-#endif
+ls_list(ARCHD *arcn, time_t now, FILE *fp)
 {
-       register struct stat *sbp;
+       struct stat *sbp;
        char f_mode[MODELEN];
        char f_date[DATELEN];
-       char *timefrmt;
+       int term;
+
+       term = zeroflag ? '\0' : '\n';  /* path termination character */
 
        /*
         * if not verbose, just print the file name
         */
        if (!vflag) {
-               (void)fprintf(fp, "%s\n", arcn->name);
+               if (zeroflag)
+                       (void)fputs(arcn->name, fp);
+               else
+                       safe_print(arcn->name, fp);
+               (void)putc(term, fp);
                (void)fflush(fp);
                return;
        }
 
+       if (pax_list_opt_format) {
+               pax_format_list_output(arcn, now, fp, term);
+               return;
+       }
        /*
         * user wants long mode
         */
        sbp = &(arcn->sb);
        strmode(sbp->st_mode, f_mode);
 
-       if (ltmfrmt == NULL) {
-               /*
-                * no locale specified format. time format based on age
-                * compared to the time pax was started.
-                */
-               if ((sbp->st_mtime + SIXMONTHS) <= now)
-                       timefrmt = OLDFRMT;
-               else
-                       timefrmt = CURFRMT;
-       } else
-               timefrmt = ltmfrmt;
+       format_date(&f_date[0], sbp->st_mtime, now);
 
        /*
         * print file mode, link count, uid, gid and time
         */
-       if (strftime(f_date,DATELEN,timefrmt,localtime((const time_t *)&(sbp->st_mtime))) == 0)
-               f_date[0] = '\0';
-       (void)fprintf(fp, "%s%2u %-*s %-*s ", f_mode, sbp->st_nlink,
-               UT_NAMESIZE, name_uid(sbp->st_uid, 1), UT_GRPSIZE,
-               name_gid(sbp->st_gid, 1));
+       (void)fprintf(fp, "%s%2u %-*.*s %-*.*s ", f_mode, sbp->st_nlink,
+               NAME_WIDTH, UT_NAMESIZE, name_uid(sbp->st_uid, 1),
+               NAME_WIDTH, UT_NAMESIZE, name_gid(sbp->st_gid, 1));
 
        /*
         * print device id's for devices, or sizes for other nodes
         */
        if ((arcn->type == PAX_CHR) || (arcn->type == PAX_BLK))
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                (void)fprintf(fp, "%4u,%4u ", MAJOR(sbp->st_rdev),
 #              else
                (void)fprintf(fp, "%4lu,%4lu ", (unsigned long)MAJOR(sbp->st_rdev),
 #              endif
                    (unsigned long)MINOR(sbp->st_rdev));
        else {
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                (void)fprintf(fp, "%9lu ", sbp->st_size);
 #              else
                (void)fprintf(fp, "%9qu ", sbp->st_size);
@@ -154,88 +167,56 @@ ls_list(arcn, now, fp)
        /*
         * print name and link info for hard and soft links
         */
-       (void)fprintf(fp, "%s %s", f_date, arcn->name);
-       if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
-               (void)fprintf(fp, " == %s\n", arcn->ln_name);
-       else if (arcn->type == PAX_SLK)
-               (void)fprintf(fp, " => %s\n", arcn->ln_name);
-       else
-               (void)putc('\n', fp);
+       (void)fputs(f_date, fp);
+       (void)putc(' ', fp);
+       safe_print(arcn->name, fp);
+       if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
+               fputs(" == ", fp);
+               safe_print(arcn->ln_name, fp);
+       } else if (arcn->type == PAX_SLK) {
+               fputs(" => ", fp);
+               safe_print(arcn->ln_name, fp);
+       }
+       (void)putc(term, fp);
        (void)fflush(fp);
        return;
 }
 
 /*
  * tty_ls()
- *     print a short summary of file to tty.
+ *     print a short summary of file to tty.
  */
 
-#ifdef __STDC__
-void
-ls_tty(register ARCHD *arcn)
-#else
 void
-ls_tty(arcn)
-       register ARCHD *arcn;
-#endif
+ls_tty(ARCHD *arcn)
 {
        char f_date[DATELEN];
        char f_mode[MODELEN];
-       char *timefrmt;
 
-       if (ltmfrmt == NULL) {
-               /*
-                * no locale specified format
-                */
-               if ((arcn->sb.st_mtime + SIXMONTHS) <= time(NULL))
-                       timefrmt = OLDFRMT;
-               else
-                       timefrmt = CURFRMT;
-       } else
-               timefrmt = ltmfrmt;
+       format_date(&f_date[0], arcn->sb.st_mtime, time(NULL));
 
-       /*
-        * convert time to string, and print
-        */
-       if (strftime(f_date, DATELEN, timefrmt,
-           localtime((const time_t *)&(arcn->sb.st_mtime))) == 0)
-               f_date[0] = '\0';
        strmode(arcn->sb.st_mode, f_mode);
        tty_prnt("%s%s %s\n", f_mode, f_date, arcn->name);
        return;
 }
 
-/*
- * l_strncpy()
- *     copy src to dest up to len chars (stopping at first '\0').
- *     when src is shorter than len, pads to len with '\0'. 
- * Return:
- *     number of chars copied. (Note this is a real performance win over
- *     doing a strncpy(), a strlen(), and then a possible memset())
- */
-
-#ifdef __STDC__
-int
-l_strncpy(register char *dest, register char *src, int len)
-#else
-int
-l_strncpy(dest, src, len)
-       register char *dest;
-       register char *src;
-       int len;
-#endif
+void
+safe_print(const char *str, FILE *fp)
 {
-       register char *stop;
-       register char *start;
-
-       stop = dest + len;
-       start = dest;
-       while ((dest < stop) && (*src != '\0'))
-               *dest++ = *src++;
-       len = dest - start;
-       while (dest < stop)
-               *dest++ = '\0';
-       return(len);
+       char visbuf[5];
+       const char *cp;
+
+       /*
+        * if printing to a tty, use vis(3) to print special characters.
+        */
+       if (isatty(fileno(fp))) {
+               for (cp = str; *cp; cp++) {
+                       (void)vis(visbuf, cp[0], VIS_CSTYLE, cp[1]);
+                       (void)fputs(visbuf, fp);
+               }
+       } else {
+               (void)fputs(str, fp);
+       }
 }
 
 /*
@@ -248,18 +229,10 @@ l_strncpy(dest, src, len)
  *     unsigned long value
  */
 
-#ifdef __STDC__
-u_long
-asc_ul(register char *str, int len, register int base)
-#else
 u_long
-asc_ul(str, len, base)
-       register char *str;
-       int len;
-       register int base;
-#endif
+asc_ul(char *str, int len, int base)
 {
-       register char *stop;
+       char *stop;
        u_long tval = 0;
 
        stop = str + len;
@@ -286,7 +259,7 @@ asc_ul(str, len, base)
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
@@ -299,19 +272,10 @@ asc_ul(str, len, base)
  *     NOTE: the string created is NOT TERMINATED.
  */
 
-#ifdef __STDC__
 int
-ul_asc(u_long val, register char *str, register int len, register int base)
-#else
-int
-ul_asc(val, str, len, base)
-       u_long val;
-       register char *str;
-       register int len;
-       register int base;
-#endif
+ul_asc(u_long val, char *str, int len, int base)
 {
-       register char *pt;
+       char *pt;
        u_long digit;
 
        /*
@@ -351,7 +315,7 @@ ul_asc(val, str, len, base)
        return(0);
 }
 
-#ifndef NET2_STAT
+#ifndef LONG_OFF_T
 /*
  * asc_uqd()
  *     convert hex/octal character string into a u_quad_t. We do not have to
@@ -362,18 +326,10 @@ ul_asc(val, str, len, base)
  *     u_quad_t value
  */
 
-#ifdef __STDC__
-u_quad_t
-asc_uqd(register char *str, int len, register int base)
-#else
 u_quad_t
-asc_uqd(str, len, base)
-       register char *str;
-       int len;
-       register int base;
-#endif
+asc_uqd(char *str, int len, int base)
 {
-       register char *stop;
+       char *stop;
        u_quad_t tval = 0;
 
        stop = str + len;
@@ -400,7 +356,7 @@ asc_uqd(str, len, base)
                                break;
                }
        } else {
-               while ((str < stop) && (*str >= '0') && (*str <= '7'))
+               while ((str < stop) && (*str >= '0') && (*str <= '7'))
                        tval = (tval << 3) + (*str++ - '0');
        }
        return(tval);
@@ -413,19 +369,10 @@ asc_uqd(str, len, base)
  *     NOTE: the string created is NOT TERMINATED.
  */
 
-#ifdef __STDC__
-int
-uqd_asc(u_quad_t val, register char *str, register int len, register int base)
-#else
 int
-uqd_asc(val, str, len, base)
-       u_quad_t val;
-       register char *str;
-       register int len;
-       register int base;
-#endif
+uqd_asc(u_quad_t val, char *str, int len, int base)
 {
-       register char *pt;
+       char *pt;
        u_quad_t digit;
 
        /*
index 8a15a2f3088f173d5318500ef2279be02c7b56e6..6b62092789a523277143ee577d49c2492aa84c33 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getoldopt.c,v 1.3 1997/09/01 18:29:52 deraadt Exp $   */
+/*     $OpenBSD: getoldopt.c,v 1.8 2003/07/02 21:19:33 deraadt Exp $   */
 /*     $NetBSD: getoldopt.c,v 1.3 1995/03/21 09:07:28 cgd Exp $        */
 
 /*
@@ -7,25 +7,24 @@
  * otherwise, it uses the old rules used by tar, dump, and ps.
  *
  * Written 25 August 1985 by John Gilmore (ihnp4!hoptoad!gnu) and placed
- * in the Pubic Domain for your edification and enjoyment.
+ * in the Public Domain for your edification and enjoyment.
  */
 
 #ifndef lint
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: getoldopt.c,v 1.3 1997/09/01 18:29:52 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: getoldopt.c,v 1.8 2003/07/02 21:19:33 deraadt Exp $";
 #endif /* not lint */
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include "pax.h"
+#include "extern.h"
 
 int
-getoldopt(argc, argv, optstring)
-       int     argc;
-       char    **argv;
-       char    *optstring;
+getoldopt(int argc, char **argv, const char *optstring)
 {
-       extern char     *optarg;        /* Points to next arg */
-       extern int      optind;         /* Global argv index */
        static char     *key;           /* Points to next keyletter */
        static char     use_getopt;     /* !=0 if argv[1][0] was '-' */
        char            c;
@@ -34,7 +33,8 @@ getoldopt(argc, argv, optstring)
        optarg = NULL;
 
        if (key == NULL) {              /* First time */
-               if (argc < 2) return EOF;
+               if (argc < 2)
+                       return (-1);
                key = argv[1];
                if (*key == '-')
                        use_getopt++;
@@ -43,18 +43,18 @@ getoldopt(argc, argv, optstring)
        }
 
        if (use_getopt)
-               return getopt(argc, argv, optstring);
+               return (getopt(argc, argv, optstring));
 
        c = *key++;
        if (c == '\0') {
                key--;
-               return EOF;
+               return (-1);
        }
        place = strchr(optstring, c);
 
        if (place == NULL || c == ':') {
                fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
-               return('?');
+               return ('?');
        }
 
        place++;
@@ -65,9 +65,9 @@ getoldopt(argc, argv, optstring)
                } else {
                        fprintf(stderr, "%s: %c argument missing\n",
                                argv[0], c);
-                       return('?');
+                       return ('?');
                }
        }
 
-       return(c);
+       return (c);
 }
index 0bbcaa9c5ea925420acaa379bee75be68a7748fc..feb97e23508b1b33b26ce75cd9ff3426dad8c7e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.c,v 1.31 1998/01/22 06:21:29 millert Exp $    */
+/*     $OpenBSD: options.c,v 1.61 2004/04/16 22:50:23 deraadt Exp $    */
 /*     $NetBSD: options.c,v 1.6 1996/03/26 23:54:18 mrg Exp $  */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)options.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)options.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: options.c,v 1.31 1998/01/22 06:21:29 millert Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: options.c,v 1.61 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -58,6 +54,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: options.c,v 1.31 19
 #include <stdlib.h>
 #include <limits.h>
 #include <paths.h>
+#include <search.h>
 #include "pax.h"
 #include "options.h"
 #include "cpio.h"
@@ -72,16 +69,23 @@ static char flgch[] = FLGCH;        /* list of all possible flags */
 static OPLIST *ophead = NULL;  /* head for format specific options -x */
 static OPLIST *optail = NULL;  /* option tail */
 
-static int no_op __P((void));
-static void printflg __P((unsigned int));
-static int c_frmt __P((const void *, const void *));
-static off_t str_offt __P((char *));
-static void pax_options __P((register int, register char **));
-static void pax_usage __P((void));
-static void tar_options __P((register int, register char **));
-static void tar_usage __P((void));
-static void cpio_options __P((register int, register char **));
-static void cpio_usage __P((void));
+static int no_op(void);
+static void printflg(unsigned int);
+static int c_frmt(const void *, const void *);
+static off_t str_offt(char *);
+static char *getline(FILE *fp);
+static void pax_options(int, char **);
+void pax_usage(void);
+static void tar_options(int, char **);
+static void tar_usage(void);
+static void cpio_options(int, char **);
+static void cpio_usage(void);
+
+/* errors from getline */
+#define GETLINE_FILE_CORRUPT 1
+#define GETLINE_OUT_OF_MEM 2
+static int getline_error;
+
 
 #define GZIP_CMD       "gzip"          /* command to run as gzip */
 #define COMPRESS_CMD   "compress"      /* command to run as compress */
@@ -125,20 +129,26 @@ FSUB fsub[] = {
        {"ustar", 10240, BLKMULT, 0, 1, BLKMULT, 0, ustar_id, ustar_strd,
        ustar_rd, tar_endrd, ustar_stwr, ustar_wr, tar_endwr, tar_trail,
        rd_wrfile, wr_rdfile, bad_opt},
+
+/* 6: POSIX 3 PAX */
+       {"pax", 5120, BLKMULT, 0, 1, BLKMULT, 0, pax_id, ustar_strd,
+       pax_rd, tar_endrd, ustar_stwr, pax_wr, tar_endwr, tar_trail,
+       rd_wrfile, wr_rdfile, pax_opt},
 };
 #define        F_OCPIO 0       /* format when called as cpio -6 */
 #define        F_ACPIO 1       /* format when called as cpio -c */
 #define        F_CPIO  3       /* format when called as cpio */
 #define F_OTAR 4       /* format when called as tar -o */
 #define F_TAR  5       /* format when called as tar */
+#define F_PAX  6       /* format when called as pax -x pax */
 #define DEFLT  5       /* default write format from list above */
 
 /*
  * ford is the archive search order used by get_arc() to determine what kind
- * of archive we are dealing with. This helps to properly id  archive formats
+ * of archive we are dealing with. This helps to properly id archive formats
  * some formats may be subsets of others....
  */
-int ford[] = {5, 4, 3, 2, 1, 0, -1 };
+int ford[] = {6, 5, 4, 3, 2, 1, 0, -1 };
 
 /*
  * options()
@@ -146,15 +156,8 @@ int ford[] = {5, 4, 3, 2, 1, 0, -1 };
  *     parser
  */
 
-#ifdef __STDC__
 void
-options(register int argc, register char **argv)
-#else
-void
-options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+options(int argc, char **argv)
 {
 
        /*
@@ -165,15 +168,18 @@ options(argc, argv)
        else
                argv0 = argv[0];
 
-       if (strcmp(NM_TAR, argv0) == 0)
-               return(tar_options(argc, argv));
-       else if (strcmp(NM_CPIO, argv0) == 0)
-               return(cpio_options(argc, argv));
+       if (strcmp(NM_TAR, argv0) == 0) {
+               tar_options(argc, argv);
+               return;
+       } else if (strcmp(NM_CPIO, argv0) == 0) {
+               cpio_options(argc, argv);
+               return;
+       }
        /*
         * assume pax as the default
         */
        argv0 = NM_PAX;
-       return(pax_options(argc, argv));
+       pax_options(argc, argv);
 }
 
 /*
@@ -182,30 +188,24 @@ options(argc, argv)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
 static void
-pax_options(register int argc, register char **argv)
-#else
-static void
-pax_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+pax_options(int argc, char **argv)
 {
-       register int c;
-       register int i;
+       int c;
+       int i;
        unsigned int flg = 0;
        unsigned int bflg = 0;
-       register char *pt;
+       char *pt;
        FSUB tmp;
-       extern char *optarg;
-       extern int optind;
+       size_t n_fsub;
+       char * tmp_name;
 
+       listf = stderr;
        /*
         * process option flags
         */
-       while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ"))
-           != EOF) {
+       while ((c=getopt(argc,argv,"ab:cdf:iklno:p:rs:tuvwx:zB:DE:G:HLPT:U:XYZ0"))
+           != -1) {
                switch (c) {
                case 'a':
                        /*
@@ -241,6 +241,13 @@ pax_options(argc, argv)
                        /*
                         * filename where the archive is stored
                         */
+                       if ((optarg[0] == '-') && (optarg[1]== '\0')) {
+                               /*
+                                * treat a - as stdin (like tar)
+                                */
+                               arcname = NULL;
+                               break;
+                       }
                        arcname = optarg;
                        flg |= FF;
                        break;
@@ -277,7 +284,7 @@ pax_options(argc, argv)
                         * pass format specific options
                         */
                        flg |= OF;
-                       if (opt_add(optarg) < 0)
+                       if (pax_format_opt_add(optarg) < 0)
                                pax_usage();
                        break;
                case 'p':
@@ -285,7 +292,7 @@ pax_options(argc, argv)
                         * specify file characteristic options
                         */
                        for (pt = optarg; *pt != '\0'; ++pt) {
-                               switch(*pt) {
+                               switch (*pt) {
                                case 'a':
                                        /*
                                         * do not preserve access time
@@ -316,7 +323,7 @@ pax_options(argc, argv)
                                        break;
                                case 'p':
                                        /*
-                                        * preserver file mode bits
+                                        * preserve file mode bits
                                         */
                                        pmode = 1;
                                        break;
@@ -332,6 +339,7 @@ pax_options(argc, argv)
                        /*
                         * read the archive
                         */
+                       pax_read_or_list_mode=1;
                        flg |= RF;
                        break;
                case 's':
@@ -376,11 +384,13 @@ pax_options(argc, argv)
                         * specify an archive format on write
                         */
                        tmp.name = optarg;
-                       if (0 == strcmp("pax", optarg)) { /* alias for ustar */
-                               tmp.name = "ustar";
-                       }
+/*
                        if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
                            sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL) {
+*/
+                       n_fsub = sizeof(fsub)/sizeof(FSUB);
+                       if ((frmt = (FSUB *)lsearch((void *)&tmp, (void *)fsub,
+                                       &n_fsub, sizeof(FSUB), c_frmt)) != NULL) {
                                flg |= XF;
                                break;
                        }
@@ -395,7 +405,6 @@ pax_options(argc, argv)
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
@@ -453,6 +462,8 @@ pax_options(argc, argv)
                         */
                        Hflag = 1;
                        flg |= CHF;
+                       Lflag = 0;      /* -H and -L are mutually exclusive     */
+                       flg &= ~CLF;    /* only use the last one seen           */
                        break;
                case 'L':
                        /*
@@ -460,6 +471,14 @@ pax_options(argc, argv)
                         */
                        Lflag = 1;
                        flg |= CLF;
+                       Hflag = 0;      /* -H and -L are mutually exclusive     */
+                       flg &= ~CHF;    /* only use the last one seen           */
+                       break;
+               case 'O':
+                       /*
+                        * Force one volume.  Non standard option.
+                        */
+                       force_one_volume = 1;
                        break;
                case 'P':
                        /*
@@ -513,12 +532,28 @@ pax_options(argc, argv)
                        Zflag = 1;
                        flg |= CZF;
                        break;
+               case '0':
+                       /*
+                        * Use \0 as pathname terminator.
+                        * (For use with the -print0 option of find(1).)
+                        */
+                       zeroflag = 1;
+                       flg |= C0F;
+                       break;
                default:
                        pax_usage();
                        break;
                }
        }
 
+       /*
+        * Fix for POSIX.cmd/pax/pax.ex test 132: force -wu options to look
+        * like -wua options were specified.
+       */
+       if (uflag && (flg & WF) && !(flg & RF)) {       /* -w but not -r -w */
+               flg |= AF;
+       }
+
        /*
         * figure out the operation mode of pax read,write,extract,copy,append
         * or list. check that we have not been given a bogus set of flags
@@ -526,6 +561,8 @@ pax_options(argc, argv)
         */
        if (ISLIST(flg)) {
                act = LIST;
+               pax_read_or_list_mode=1;
+               listf = stdout;
                bflg = flg & BDLIST;
        } else if (ISEXTRACT(flg)) {
                act = EXTRACT;
@@ -554,6 +591,23 @@ pax_options(argc, argv)
        if (!(flg & XF) && (act == ARCHIVE))
                frmt = &(fsub[DEFLT]);
 
+       /*
+        * if copying (-r and -w) and there is no -x specified, we act as
+        * if -x pax was specified.
+        */
+       if (!(flg & XF) && (act == COPY))
+               frmt = &(fsub[F_PAX]);
+
+       /*
+        * Initialize the global extended header template.
+        */
+       tmp_name = getenv("TMPDIR");
+       if (tmp_name) {
+               asprintf(&header_name_g, "%s%s", tmp_name, "/GlobalHead.%p.%n");
+       } else {
+               header_name_g = "/tmp/GlobalHead.%p.%n";
+       }
+
        /*
         * process the args as they are interpreted by the operation mode
         */
@@ -592,19 +646,19 @@ pax_options(argc, argv)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
 static void
-tar_options(register int argc, register char **argv)
-#else
-static void
-tar_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+tar_options(int argc, char **argv)
 {
-       register int c;
+       int c;
        int fstdin = 0;
        int Oflag = 0;
+       int nincfiles = 0;
+       int incfiles_max = 0;
+       struct incfile {
+               char *file;
+               char *dir;
+       };
+       struct incfile *incfiles = NULL;
 
        /*
         * Set default values.
@@ -615,9 +669,8 @@ tar_options(argc, argv)
         * process option flags
         */
        while ((c = getoldopt(argc, argv,
-           "b:cef:hmopruts:vwxzBC:HLOPXZ014578"))
-           != EOF) {
-               switch(c) {
+           "b:cef:hmopqruts:vwxzBC:HI:LOPXZ014578")) != -1) {
+               switch (c) {
                case 'b':
                        /*
                         * specify blocksize in 512-byte blocks
@@ -667,21 +720,24 @@ tar_options(argc, argv)
                         */
                        pmtime = 0;
                        break;
-               case 'o':
-                       if (opt_add("write_opt=nodir") < 0)
-                               tar_usage();
                case 'O':
                        Oflag = 1;
                        break;
+               case 'o':
+                       Oflag = 2;
+                       break;
                case 'p':
                        /*
-                        * preserve user id, group id, file
-                        * mode, access/modification times
+                        * preserve uid/gid and file mode, regardless of umask
                         */
-                       pids = 1;
                        pmode = 1;
-                       patime = 1;
-                       pmtime = 1;
+                       pids = 1;
+                       break;
+               case 'q':
+                       /*
+                        * select first match for a pattern only
+                        */
+                       nflag = 1;
                        break;
                case 'r':
                case 'u':
@@ -719,17 +775,16 @@ tar_options(argc, argv)
                        break;
                case 'x':
                        /*
-                        * write an archive, preserve ids if root
+                        * extract an archive, preserving mode,
+                        * and mtime if possible.
                         */
                        act = EXTRACT;
-                       if (geteuid() == 0)
-                               pids = 1;
+                       pmtime = 1;
                        break;
                case 'z':
                        /*
                         * use gzip.  Non standard option.
                         */
-                       zflag = 1;
                        gzip_program = GZIP_CMD;
                        break;
                case 'B':
@@ -746,6 +801,20 @@ tar_options(argc, argv)
                         */
                        Hflag = 1;
                        break;
+               case 'I':
+                       if (++nincfiles > incfiles_max) {
+                               incfiles_max = nincfiles + 3;
+                               incfiles = realloc(incfiles,
+                                   sizeof(*incfiles) * incfiles_max);
+                               if (incfiles == NULL) {
+                                       paxwarn(0, "Unable to allocate space "
+                                           "for option list");
+                                       exit(1);
+                               }
+                       }
+                       incfiles[nincfiles - 1].file = optarg;
+                       incfiles[nincfiles - 1].dir = chdname;
+                       break;
                case 'L':
                        /*
                         * follow symlinks
@@ -768,7 +837,6 @@ tar_options(argc, argv)
                        /*
                         * use compress.
                         */
-                       zflag = 1;
                        gzip_program = COMPRESS_CMD;
                        break;
                case '0':
@@ -797,20 +865,15 @@ tar_options(argc, argv)
        argc -= optind;
        argv += optind;
 
-       /* Traditional tar behaviour (pax wants to read filelist from stdin) */
-       if ((act == ARCHIVE || act == APPND) && argc == 0)
-               exit(0);
+       /* Traditional tar behaviour (pax uses stderr unless in list mode) */
+       if (fstdin == 1 && act == ARCHIVE)
+               listf = stderr;
+       else
+               listf = stdout;
 
-       /*
-        * if we are writing (ARCHIVE) specify tar, otherwise run like pax
-        * (unless -o specified)
-        */
-       if (act == ARCHIVE || act == APPND)
-               frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
-       else if (Oflag) {
-               paxwarn(1, "The -O/-o options are only valid when writing an archive");
-               tar_usage();            /* only valid when writing */
-       }
+       /* Traditional tar behaviour (pax wants to read file list from stdin) */
+       if ((act == ARCHIVE || act == APPND) && argc == 0 && nincfiles == 0)
+               exit(0);
 
        /*
         * process the args as they are interpreted by the operation mode
@@ -821,22 +884,61 @@ tar_options(argc, argv)
        default:
                {
                        int sawpat = 0;
+                       char *file, *dir;
 
-                       while (*argv != NULL) {
-                               if (strcmp(*argv, "-C") == 0) {
-                                       if(*++argv == NULL)
+                       while (nincfiles || *argv != NULL) {
+                               /*
+                                * If we queued up any include files,
+                                * pull them in now.  Otherwise, check
+                                * for -I and -C positional flags.
+                                * Anything else must be a file to
+                                * extract.
+                                */
+                               if (nincfiles) {
+                                       file = incfiles->file;
+                                       dir = incfiles->dir;
+                                       incfiles++;
+                                       nincfiles--;
+                               } else if (strcmp(*argv, "-I") == 0) {
+                                       if (*++argv == NULL)
+                                               break;
+                                       file = *argv++;
+                                       dir = chdname;
+                               } else
+                                       file = NULL;
+                               if (file != NULL) {
+                                       FILE *fp;
+                                       char *str;
+
+                                       if (strcmp(file, "-") == 0)
+                                               fp = stdin;
+                                       else if ((fp = fopen(file, "r")) == NULL) {
+                                               paxwarn(1, "Unable to open file '%s' for read", file);
+                                               tar_usage();
+                                       }
+                                       while ((str = getline(fp)) != NULL) {
+                                               if (pat_add(str, dir) < 0)
+                                                       tar_usage();
+                                               sawpat = 1;
+                                       }
+                                       if (strcmp(file, "-") != 0)
+                                               fclose(fp);
+                                       if (getline_error) {
+                                               paxwarn(1, "Problem with file '%s'", file);
+                                               tar_usage();
+                                       }
+                               } else if (strcmp(*argv, "-C") == 0) {
+                                       if (*++argv == NULL)
                                                break;
                                        chdname = *argv++;
-
-                                       continue;
-                               }
-                               if (pat_add(*argv++, chdname) < 0)
+                               } else if (pat_add(*argv++, chdname) < 0)
                                        tar_usage();
-                               sawpat++;
+                               else
+                                       sawpat = 1;
                        }
                        /*
                         * if patterns were added, we are doing chdir()
-                        * on a file-by-file basis, else, just one 
+                        * on a file-by-file basis, else, just one
                         * global chdir (if any) after opening input.
                         */
                        if (sawpat > 0)
@@ -845,21 +947,71 @@ tar_options(argc, argv)
                break;
        case ARCHIVE:
        case APPND:
+               frmt = &(fsub[Oflag ? F_OTAR : F_TAR]);
+
+               if (Oflag == 2 && opt_add("write_opt=nodir") < 0)
+                       tar_usage();
+
                if (chdname != NULL) {  /* initial chdir() */
                        if (ftree_add(chdname, 1) < 0)
                                tar_usage();
                }
 
-               while (*argv != NULL) {
-                       if (!strcmp(*argv, "-C")) {
+               while (nincfiles || *argv != NULL) {
+                       char *file, *dir;
+
+                       /*
+                        * If we queued up any include files, pull them in
+                        * now.  Otherwise, check for -I and -C positional
+                        * flags.  Anything else must be a file to include
+                        * in the archive.
+                        */
+                       if (nincfiles) {
+                               file = incfiles->file;
+                               dir = incfiles->dir;
+                               incfiles++;
+                               nincfiles--;
+                       } else if (strcmp(*argv, "-I") == 0) {
                                if (*++argv == NULL)
                                        break;
-                               if (ftree_add(*argv++, 1) < 0)
+                               file = *argv++;
+                               dir = NULL;
+                       } else
+                               file = NULL;
+                       if (file != NULL) {
+                               FILE *fp;
+                               char *str;
+
+                               /* Set directory if needed */
+                               if (dir) {
+                                       if (ftree_add(dir, 1) < 0)
+                                               tar_usage();
+                               }
+
+                               if (strcmp(file, "-") == 0)
+                                       fp = stdin;
+                               else if ((fp = fopen(file, "r")) == NULL) {
+                                       paxwarn(1, "Unable to open file '%s' for read", file);
+                                       tar_usage();
+                               }
+                               while ((str = getline(fp)) != NULL) {
+                                       if (ftree_add(str, 0) < 0)
+                                               tar_usage();
+                               }
+                               if (strcmp(file, "-") != 0)
+                                       fclose(fp);
+                               if (getline_error) {
+                                       paxwarn(1, "Problem with file '%s'",
+                                           file);
                                        tar_usage();
-                       } else {
-                               if (ftree_add(*argv++, 0) < 0)
+                               }
+                       } else if (strcmp(*argv, "-C") == 0) {
+                               if (*++argv == NULL)
+                                       break;
+                               if (ftree_add(*argv++, 1) < 0)
                                        tar_usage();
-                       }
+                       } else if (ftree_add(*argv++, 0) < 0)
+                               tar_usage();
                }
                /*
                 * no read errors allowed on updates/append operation!
@@ -874,12 +1026,14 @@ tar_options(argc, argv)
        }
 }
 
+int mkpath(char *);
+
 int
 mkpath(path)
        char *path;
 {
        struct stat sb;
-       register char *slash;
+       char *slash;
        int done = 0;
 
        slash = path;
@@ -913,23 +1067,18 @@ mkpath(path)
  *     the user specified a legal set of flags. If not, complain and exit
  */
 
-#ifdef __STDC__
-static void
-cpio_options(register int argc, register char **argv)
-#else
 static void
-cpio_options(argc, argv)
-       register int argc;
-       register char **argv;
-#endif
+cpio_options(int argc, char **argv)
 {
-       register int c, i;
-       size_t len;
+       int c, i;
        char *str;
        FSUB tmp;
        FILE *fp;
+       size_t n_fsub;
 
-       kflag = 1;
+       listf = stderr;
+       kflag = 0;
+       uflag = 1;
        pids = 1;
        pmode = 1;
        pmtime = 0;
@@ -937,7 +1086,7 @@ cpio_options(argc, argv)
        dflag = 1;
        act = -1;
        nodirs = 1;
-       while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != EOF)
+       while ((c=getopt(argc,argv,"abcdfiklmoprstuvzABC:E:F:H:I:LO:SZ6")) != -1)
                switch (c) {
                        case 'a':
                                /*
@@ -1017,12 +1166,13 @@ cpio_options(argc, argv)
                                 * list contents of archive
                                 */
                                act = LIST;
+                               listf = stdout;
                                break;
                        case 'u':
                                /*
                                 * replace newer files
                                 */
-                               kflag = 0;
+                               uflag = 0;
                                break;
                        case 'v':
                                /*
@@ -1034,7 +1184,6 @@ cpio_options(argc, argv)
                                /*
                                 * use gzip.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = GZIP_CMD;
                                break;
                        case 'A':
@@ -1063,11 +1212,14 @@ cpio_options(argc, argv)
                                        paxwarn(1, "Unable to open file '%s' for read", optarg);
                                        cpio_usage();
                                }
-                               while ((str = fgetln(fp, &len)) != NULL) {
-                                       str[len - 1] = '\0';
+                               while ((str = getline(fp)) != NULL) {
                                        pat_add(str, NULL);
                                }
                                fclose(fp);
+                               if (getline_error) {
+                                       paxwarn(1, "Problem with file '%s'", optarg);
+                                       cpio_usage();
+                               }
                                break;
                        case 'F':
                        case 'I':
@@ -1089,8 +1241,13 @@ cpio_options(argc, argv)
                                 * specify an archive format on write
                                 */
                                tmp.name = optarg;
+/*
                                if ((frmt = (FSUB *)bsearch((void *)&tmp, (void *)fsub,
                                    sizeof(fsub)/sizeof(FSUB), sizeof(FSUB), c_frmt)) != NULL)
+*/
+                               n_fsub = sizeof(fsub)/sizeof(FSUB);
+                               if ((frmt = (FSUB *)lsearch((void *)&tmp, (void *)fsub,
+                                               &n_fsub, sizeof(FSUB), c_frmt)) != NULL)
                                        break;
                                paxwarn(1, "Unknown -H format: %s", optarg);
                                (void)fputs("cpio: Known -H formats are:", stderr);
@@ -1114,7 +1271,6 @@ cpio_options(argc, argv)
                                /*
                                 * use compress.  Non standard option.
                                 */
-                               zflag = 1;
                                gzip_program = COMPRESS_CMD;
                                break;
                        case '6':
@@ -1160,9 +1316,12 @@ cpio_options(argc, argv)
                         * no read errors allowed on updates/append operation!
                         */
                        maxflt = 0;
-                       while ((str = fgetln(stdin, &len)) != NULL) {
-                               str[len - 1] = '\0';
-                               ftree_add(strdup(str), NULL);
+                       while ((str = getline(stdin)) != NULL) {
+                               ftree_add(str, 0);
+                       }
+                       if (getline_error) {
+                               paxwarn(1, "Problem while reading stdin");
+                               cpio_usage();
                        }
                        break;
                default:
@@ -1176,14 +1335,8 @@ cpio_options(argc, argv)
  *     print out those invalid flag sets found to the user
  */
 
-#ifdef __STDC__
 static void
 printflg(unsigned int flg)
-#else
-static void
-printflg(flg)
-       unsigned int flg;
-#endif
 {
        int nxt;
        int pos = 0;
@@ -1203,15 +1356,8 @@ printflg(flg)
  *     by the user
  */
 
-#ifdef __STDC__
 static int
 c_frmt(const void *a, const void *b)
-#else
-static int
-c_frmt(a, b)
-       void *a;
-       void *b;
-#endif
 {
        return(strcmp(((FSUB *)a)->name, ((FSUB *)b)->name));
 }
@@ -1224,13 +1370,8 @@ c_frmt(a, b)
  *     pointer to next OPLIST entry or NULL (end of list).
  */
 
-#ifdef __STDC__
 OPLIST *
 opt_next(void)
-#else
-OPLIST *
-opt_next()
-#endif
 {
        OPLIST *opt;
 
@@ -1245,15 +1386,10 @@ opt_next()
  *     when the format does not support options.
  */
 
-#ifdef __STDC__
 int
 bad_opt(void)
-#else
-int
-bad_opt()
-#endif
 {
-       register OPLIST *opt;
+       OPLIST *opt;
 
        if (ophead == NULL)
                return(0);
@@ -1261,8 +1397,15 @@ bad_opt()
         * print all we were given
         */
        paxwarn(1,"These format options are not supported");
-       while ((opt = opt_next()) != NULL)
-               (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
+       while ((opt = opt_next()) != NULL) {
+               if (opt->separator == SEP_EQ) {
+                       (void)fprintf(stderr, "\t%s = %s\n", opt->name, opt->value);
+               } else if (opt->separator == SEP_COLONEQ ) {
+                       (void)fprintf(stderr, "\t%s := %s\n", opt->name, opt->value);
+               } else {        /* SEP_NONE */
+                       (void)fprintf(stderr, "\t%s\n", opt->name);
+               }
+       }
        pax_usage();
        return(0);
 }
@@ -1271,24 +1414,85 @@ bad_opt()
  * opt_add()
  *     breaks the value supplied to -o into a option name and value. options
  *     are given to -o in the form -o name-value,name=value
- *     mulltiple -o may be specified.
+ *     multiple -o may be specified.
  * Return:
  *     0 if format in name=value format, -1 if -o is passed junk
  */
 
-#ifdef __STDC__
 int
-opt_add(register char *str)
-#else
+opt_add(const char *str)
+{
+       OPLIST *opt;
+       char *frpt;
+       char *pt;
+       char *endpt;
+       char *dstr;
+
+       if ((str == NULL) || (*str == '\0')) {
+               paxwarn(0, "Invalid option name");
+               return(-1);
+       }
+       if ((dstr = strdup(str)) == NULL) {
+               paxwarn(0, "Unable to allocate space for option list");
+               return(-1);
+       }
+       frpt = endpt = dstr;
+
+       /*
+        * break into name and values pieces and stuff each one into a
+        * OPLIST structure. When we know the format, the format specific
+        * option function will go through this list
+        */
+       while ((frpt != NULL) && (*frpt != '\0')) {
+               if ((endpt = strchr(frpt, ',')) != NULL)
+                       *endpt = '\0';
+               if ((pt = strchr(frpt, '=')) == NULL) {
+                       paxwarn(0, "Invalid options format");
+                       free(dstr);
+                       return(-1);
+               }
+               if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
+                       paxwarn(0, "Unable to allocate space for option list");
+                       free(dstr);
+                       return(-1);
+               }
+               *pt++ = '\0';
+               opt->name = frpt;
+               opt->value = pt;
+               opt->separator = SEP_EQ;
+               opt->fow = NULL;
+               if (endpt != NULL)
+                       frpt = endpt + 1;
+               else
+                       frpt = NULL;
+               if (ophead == NULL) {
+                       optail = ophead = opt;
+                       continue;
+               }
+               optail->fow = opt;
+               optail = opt;
+       }
+       return(0);
+}
+
+
+/*
+ * pax_format_opt_add()
+ *     breaks the value supplied to -o into a option name and value. options
+ *     are given to -o in the form -o name-value,name=value
+ *     multiple -o may be specified.
+ * Return:
+ *     0 if format in name=value format, -1 if -o is passed junk
+ */
+
 int
-opt_add(str)
-       register char *str;
-#endif
+pax_format_opt_add(register char *str)
 {
        register OPLIST *opt;
        register char *frpt;
        register char *pt;
        register char *endpt;
+       register int separator;
 
        if ((str == NULL) || (*str == '\0')) {
                paxwarn(0, "Invalid option name");
@@ -1308,19 +1512,25 @@ opt_add(str)
        while ((frpt != NULL) && (*frpt != '\0')) {
                if ((endpt = strchr(frpt, ',')) != NULL)
                        *endpt = '\0';
-               if ((pt = strchr(frpt, '=')) == NULL) {
-                       paxwarn(0, "Invalid options format");
-                       free(str);
-                       return(-1);
+               if ((pt = strstr(frpt, ":=")) != NULL) {
+                       *pt++ = '\0';
+                       pt++;   /* beyond the := */
+                       separator = SEP_COLONEQ;
+               } else if ((pt = strchr(frpt, '=')) != NULL) {
+                       *pt++ = '\0';
+                       separator = SEP_EQ;
+               } else {
+                       /* keyword with no value */
+                       separator = SEP_NONE;
                }
                if ((opt = (OPLIST *)malloc(sizeof(OPLIST))) == NULL) {
                        paxwarn(0, "Unable to allocate space for option list");
                        free(str);
                        return(-1);
                }
-               *pt++ = '\0';
                opt->name = frpt;
                opt->value = pt;
+               opt->separator = separator;
                opt->fow = NULL;
                if (endpt != NULL)
                        frpt = endpt + 1;
@@ -1345,25 +1555,19 @@ opt_add(str)
  *     4) A positive decimal number followed by a m (mult by 512).
  *     5) A positive decimal number followed by a w (mult by sizeof int)
  *     6) Two or more positive decimal numbers (with/without k,b or w).
- *        seperated by x (also * for backwards compatibility), specifying
+ *        separated by x (also * for backwards compatibility), specifying
  *        the product of the indicated values.
  * Return:
  *     0 for an error, a positive value o.w.
  */
 
-#ifdef __STDC__
 static off_t
 str_offt(char *val)
-#else
-static off_t
-str_offt(val)
-       char *val;
-#endif
 {
        char *expr;
        off_t num, t;
 
-#      ifdef NET2_STAT
+#      ifdef LONG_OFF_T
        num = strtol(val, &expr, 0);
        if ((num == LONG_MAX) || (num <= 0) || (expr == val))
 #      else
@@ -1372,7 +1576,7 @@ str_offt(val)
 #      endif
                return(0);
 
-       switch(*expr) {
+       switch (*expr) {
        case 'b':
                t = num;
                num *= 512;
@@ -1403,7 +1607,7 @@ str_offt(val)
                break;
        }
 
-       switch(*expr) {
+       switch (*expr) {
                case '\0':
                        break;
                case '*':
@@ -1419,6 +1623,29 @@ str_offt(val)
        return(num);
 }
 
+char *
+getline(FILE *f)
+{
+       char *name, *temp;
+       size_t len;
+
+       name = fgetln(f, &len);
+       if (!name) {
+               getline_error = ferror(f) ? GETLINE_FILE_CORRUPT : 0;
+               return(0);
+       }
+       if (name[len-1] != '\n')
+               len++;
+       temp = malloc(len);
+       if (!temp) {
+               getline_error = GETLINE_OUT_OF_MEM;
+               return(0);
+       }
+       memcpy(temp, name, len-1);
+       temp[len-1] = 0;
+       return(temp);
+}
+                       
 /*
  * no_op()
  *     for those option functions where the archive format has nothing to do.
@@ -1426,13 +1653,8 @@ str_offt(val)
  *     0
  */
 
-#ifdef __STDC__
 static int
 no_op(void)
-#else
-static int
-no_op()
-#endif
 {
        return(0);
 }
@@ -1442,33 +1664,28 @@ no_op()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 pax_usage(void)
-#else
-void
-pax_usage()
-#endif
 {
-       (void)fputs("usage: pax [-cdnv] [-E limit] [-f archive] ", stderr);
+       (void)fputs("usage: pax [-cdnvzO] [-E limit] [-f archive] ", stderr);
        (void)fputs("[-s replstr] ... [-U user] ...", stderr);
        (void)fputs("\n           [-G group] ... ", stderr);
        (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
        (void)fputs("[pattern ...]\n", stderr);
-       (void)fputs("       pax -r [-cdiknuvDYZ] [-E limit] ", stderr);
+       (void)fputs("       pax -r [-cdiknuvzDOYZ] [-E limit] ", stderr);
        (void)fputs("[-f archive] [-o options] ... \n", stderr);
        (void)fputs("           [-p string] ... [-s replstr] ... ", stderr);
        (void)fputs("[-U user] ... [-G group] ...\n           ", stderr);
        (void)fputs("[-T [from_date][,to_date]] ... ", stderr);
        (void)fputs(" [pattern ...]\n", stderr);
-       (void)fputs("       pax -w [-dituvHLPX] [-b blocksize] ", stderr);
+       (void)fputs("       pax -w [-dituvzHLOPX] [-b blocksize] ", stderr);
        (void)fputs("[ [-a] [-f archive] ] [-x format] \n", stderr);
        (void)fputs("           [-B bytes] [-s replstr] ... ", stderr);
        (void)fputs("[-o options] ... [-U user] ...", stderr);
        (void)fputs("\n           [-G group] ... ", stderr);
        (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
        (void)fputs("[file ...]\n", stderr);
-       (void)fputs("       pax -r -w [-diklntuvDHLPXYZ] ", stderr);
+       (void)fputs("       pax -r -w [-diklntuvDHLOPXYZ] ", stderr);
        (void)fputs("[-p string] ... [-s replstr] ...", stderr);
        (void)fputs("\n           [-U user] ... [-G group] ... ", stderr);
        (void)fputs("[-T [from_date][,to_date][/[c][m]]] ... ", stderr);
@@ -1481,17 +1698,12 @@ pax_usage()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 tar_usage(void)
-#else
-void
-tar_usage()
-#endif
 {
-       (void)fputs("usage: tar -{txru}[cevfbmopswzBHLPXZ014578] [tapefile] ",
+       (void)fputs("usage: tar [-]{crtux}[-befhmopqsvwzHLOPXZ014578] [blocksize] ",
                 stderr);
-       (void)fputs("[blocksize] [replstr] [-C directory] file1 file2...\n",
+       (void)fputs("[archive] [replstr] [-C directory] [-I file] [file ...]\n",
            stderr);
        exit(1);
 }
@@ -1501,13 +1713,8 @@ tar_usage()
  *     print the usage summary to the user
  */
 
-#ifdef __STDC__
 void
 cpio_usage(void)
-#else
-void
-cpio_usage()
-#endif
 {
        (void)fputs("usage: cpio -o [-aABcLvVzZ] [-C bytes] [-H format] [-O archive]\n", stderr);
        (void)fputs("               [-F archive] < name-list [> archive]\n", stderr);
index d45f54afb871530152534bd02727874e741ec980..873d8d559671bb2daedc6b65f6224b2793ec03fd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.h,v 1.2 1996/06/23 14:20:37 deraadt Exp $     */
+/*     $OpenBSD: options.h,v 1.4 2003/06/13 17:51:14 millert Exp $     */
 /*     $NetBSD: options.h,v 1.3 1995/03/21 09:07:32 cgd Exp $  */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
 #define        CXF     0x08000000
 #define        CYF     0x10000000      /* nonstandard extension */
 #define        CZF     0x20000000      /* nonstandard extension */
+#define        C0F     0x40000000      /* nonstandard extension */
 
 /*
  * ascii string indexed by bit position above (alter the above and you must
  * alter this string) used to tell the user what flags caused us to complain
  */
-#define FLGCH  "abcdfiklnoprstuvwxBDEGHLPTUXYZ"
+#define FLGCH  "abcdfiklnoprstuvwxBDEGHLPTUXYZ0"
 
 /*
  * legal pax operation bit patterns
 
 #define        BDEXTR  (AF|BF|LF|TF|WF|XF|CBF|CHF|CLF|CPF|CXF)
 #define        BDARCH  (CF|KF|LF|NF|PF|RF|CDF|CEF|CYF|CZF)
-#define        BDCOPY  (AF|BF|FF|OF|XF|CBF|CEF)
-#define        BDLIST (AF|BF|IF|KF|LF|OF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CPF|CXF|CYF|CZF)
+#define        BDCOPY  (AF|BF|FF|CBF|CEF)
+#define        BDLIST (AF|BF|IF|KF|LF|PF|RF|TF|UF|WF|XF|CBF|CDF|CHF|CLF|CPF|CXF|CYF|CZF)
index 9ff1dca41e057c2a02ec7543ced7f4a81c97664f..5f4686465150dd5b3e0742bcabd093d18a02178e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $    */
+/*     $OpenBSD: pat_rep.c,v 1.28 2004/06/11 03:10:43 millert Exp $    */
 /*     $NetBSD: pat_rep.c,v 1.4 1995/03/21 09:07:33 cgd Exp $  */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)pat_rep.c  8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)pat_rep.c    8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pat_rep.c,v 1.11 1997/09/01 18:29:56 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pat_rep.c,v 1.28 2004/06/11 03:10:43 millert Exp $";
 #endif
 #endif /* not lint */
 
@@ -55,11 +51,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pat_rep.c,v 1.11 19
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
-#ifdef NET2_REGEX
-#include <regexp.h>
-#else
 #include <regex.h>
-#endif
 #include "pax.h"
 #include "pat_rep.h"
 #include "extern.h"
@@ -77,23 +69,19 @@ static PATTERN *pattail = NULL;             /* file pattern match list tail */
 static REPLACE *rephead = NULL;                /* replacement string list head */
 static REPLACE *reptail = NULL;                /* replacement string list tail */
 
-static int rep_name __P((char *, int *, int));
-static int tty_rename __P((register ARCHD *));
-static int fix_path __P((char *, int *, char *, int));
-static int fn_match __P((register char *, register char *, char **));
-static char * range_match __P((register char *, register int));
-#ifdef NET2_REGEX
-static int resub __P((regexp *, char *, char *, register char *));
-#else
-static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
-#endif
+static int rep_name(char *, size_t, int *, int);
+int tty_rename(ARCHD *);
+static int fix_path(char *, int *, char *, int);
+static int fn_match(char *, char *, char **);
+static char * range_match(char *, int);
+static int resub(regex_t *, regmatch_t *, char *, char *, char *, char *);
 
 /*
  * rep_add()
  *     parses the -s replacement string; compiles the regular expression
  *     and stores the compiled value and it's replacement string together in
  *     replacement string list. Input to this function is of the form:
- *             /old/new/pg 
+ *             /old/new/pg
  *     The first char in the string specifies the delimiter used by this
  *     replacement string. "Old" is a regular expression in "ed" format which
  *     is compiled by regcomp() and is applied to filenames. "new" is the
@@ -104,22 +92,14 @@ static int resub __P((regex_t *, regmatch_t *, char *, char *, char *));
  *     the list of replacement patterns; -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-rep_add(register char *str)
-#else
-int
-rep_add(str)
-       register char *str;
-#endif
+rep_add(char *str)
 {
-       register char *pt1;
-       register char *pt2;
-       register REPLACE *rep;
-#      ifndef NET2_REGEX
-       register int res;
+       char *pt1;
+       char *pt2;
+       REPLACE *rep;
+       int res;
        char rebuf[BUFSIZ];
-#      endif
 
        /*
         * throw out the bad parameters
@@ -133,7 +113,15 @@ rep_add(str)
         * first character in the string specifies what the delimiter is for
         * this expression
         */
-       if ((pt1 = strchr(str+1, *str)) == NULL) {
+       for (pt1 = str+1; *pt1; pt1++) {
+               if (*pt1 == '\\') {
+                       pt1++;
+                       continue;
+               }
+               if (*pt1 == *str)
+                       break;
+       }
+       if (*pt1 == '\0') {
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
        }
@@ -148,13 +136,9 @@ rep_add(str)
        }
 
        *pt1 = '\0';
-#      ifdef NET2_REGEX
-       if ((rep->rcmp = regcomp(str+1)) == NULL) {
-#      else
        if ((res = regcomp(&(rep->rcmp), str+1, 0)) != 0) {
                regerror(res, &(rep->rcmp), rebuf, sizeof(rebuf));
                paxwarn(1, "%s while compiling regular expression %s", rebuf, str);
-#      endif
                (void)free((char *)rep);
                return(-1);
        }
@@ -165,12 +149,16 @@ rep_add(str)
         * we then point the node at the new substitution string
         */
        *pt1++ = *str;
-       if ((pt2 = strchr(pt1, *str)) == NULL) {
-#              ifdef NET2_REGEX
-               (void)free((char *)rep->rcmp);
-#              else
+       for (pt2 = pt1; *pt2; pt2++) {
+               if (*pt2 == '\\') {
+                       pt2++;
+                       continue;
+               }
+               if (*pt2 == *str)
+                       break;
+       }
+       if (*pt2 == '\0') {
                regfree(&(rep->rcmp));
-#              endif
                (void)free((char *)rep);
                paxwarn(1, "Invalid replacement string %s", str);
                return(-1);
@@ -185,7 +173,7 @@ rep_add(str)
         * set the options if any
         */
        while (*pt2 != '\0') {
-               switch(*pt2) {
+               switch (*pt2) {
                case 'g':
                case 'G':
                        rep->flgs  |= GLOB;
@@ -195,11 +183,7 @@ rep_add(str)
                        rep->flgs  |= PRNT;
                        break;
                default:
-#                      ifdef NET2_REGEX
-                       (void)free((char *)rep->rcmp);
-#                      else
                        regfree(&(rep->rcmp));
-#                      endif
                        (void)free((char *)rep);
                        *pt1 = *str;
                        paxwarn(1, "Invalid replacement string option %s", str);
@@ -232,17 +216,10 @@ rep_add(str)
  *     0 if the pattern was added to the list, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 pat_add(char *str, char *chdname)
-#else
-int
-pat_add(str, chdname)
-       char *str;
-       char *chdname;
-#endif
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        /*
         * throw out the junk
@@ -284,16 +261,11 @@ pat_add(str, chdname)
  *     a selected archive member.
  */
 
-#ifdef __STDC__
 void
 pat_chk(void)
-#else
-void
-pat_chk()
-#endif
 {
-       register PATTERN *pt;
-       register int wban = 0;
+       PATTERN *pt;
+       int wban = 0;
 
        /*
         * walk down the list checking the flags to make sure MTCH was set,
@@ -318,26 +290,20 @@ pat_chk()
  *
  *     NOTE: When the -c option is used, we are called when there was no match
  *     by pat_match() (that means we did match before the inverted sense of
- *     the logic). Now this seems really strange at first, but with -c  we
- *     need to keep track of those patterns that cause a archive member to NOT
+ *     the logic). Now this seems really strange at first, but with -c we
+ *     need to keep track of those patterns that cause an archive member to NOT
  *     be selected (it found an archive member with a specified pattern)
  * Return:
  *     0 if the pattern pointed at by arcn->pat was tagged as creating a
  *     match, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
-pat_sel(register ARCHD *arcn)
-#else
-int
-pat_sel(arcn)
-       register ARCHD *arcn;
-#endif
+pat_sel(ARCHD *arcn)
 {
-       register PATTERN *pt;
-       register PATTERN **ppt;
-       register int len;
+       PATTERN *pt;
+       PATTERN **ppt;
+       int len;
 
        /*
         * if no patterns just return
@@ -356,7 +322,7 @@ pat_sel(arcn)
 
        /*
         * we reach this point only when we allow a single selected match per
-        * pattern, if the pattern matches a directory and we do not have -d 
+        * pattern, if the pattern matches a directory and we do not have -d
         * (dflag) we are done with this pattern. We may also be handed a file
         * in the subtree of a directory. in that case when we are operating
         * with -d, this pattern was already selected and we are done
@@ -415,7 +381,7 @@ pat_sel(arcn)
         * we are then done with this pattern, so we delete it from the list
         * because it can never be used for another match.
         * Seems kind of strange to do for a -c, but the pax spec is really
-        * vague on the interaction of -c -n and -d. We assume that when -c
+        * vague on the interaction of -c, -n and -d. We assume that when -c
         * and the pattern rejects a member (i.e. it matched it) it is done.
         * In effect we place the order of the flags as having -c last.
         */
@@ -430,7 +396,7 @@ pat_sel(arcn)
                /*
                 * should never happen....
                 */
-               paxwarn(1, "Pattern list inconsistant");
+               paxwarn(1, "Pattern list inconsistent");
                return(-1);
        }
        *ppt = pt->fow;
@@ -446,21 +412,15 @@ pat_sel(arcn)
  *     this archive member is "selected" we process and mark the pattern as
  *     one which matched a selected archive member (see pat_sel())
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  */
 
-#ifdef __STDC__
-int
-pat_match(register ARCHD *arcn)
-#else
 int
-pat_match(arcn)
-       register ARCHD *arcn;
-#endif
+pat_match(ARCHD *arcn)
 {
-       register PATTERN *pt;
+       PATTERN *pt;
 
        arcn->pat = NULL;
 
@@ -523,24 +483,16 @@ pat_match(arcn)
 /*
  * fn_match()
  * Return:
- *     0 if this archive member should be processed, 1 if it should be 
+ *     0 if this archive member should be processed, 1 if it should be
  *     skipped and -1 if we are done with all patterns (and pax should quit
  *     looking for more members)
  *     Note: *pend may be changed to show where the prefix ends.
  */
 
-#ifdef __STDC__
 static int
-fn_match(register char *pattern, register char *string, char **pend)
-#else
-static int
-fn_match(pattern, string, pend)
-       register char *pattern;
-       register char *string;
-       char **pend;
-#endif
+fn_match(char *pattern, char *string, char **pend)
 {
-       register char c;
+       char c;
        char test;
 
        *pend = NULL;
@@ -572,7 +524,7 @@ fn_match(pattern, string, pend)
                case '*':
                        c = *pattern;
                        /*
-                        * Collapse multiple *'s. 
+                        * Collapse multiple *'s.
                         */
                        while (c == '*')
                                c = *++pattern;
@@ -610,18 +562,11 @@ fn_match(pattern, string, pend)
        /* NOTREACHED */
 }
 
-#ifdef __STDC__
 static char *
-range_match(register char *pattern, register int test)
-#else
-static char *
-range_match(pattern, test)
-       register char *pattern;
-       register int test;
-#endif
+range_match(char *pattern, int test)
 {
-       register char c;
-       register char c2;
+       char c;
+       char c2;
        int negate;
        int ok = 0;
 
@@ -657,19 +602,13 @@ range_match(pattern, test)
  *     if we spot any file links to the old file name in the future, we will
  *     know exactly how to fix the file link.
  * Return:
- *     0 continue to  process file, 1 skip this file, -1 pax is finished 
+ *     0 continue to  process file, 1 skip this file, -1 pax is finished
  */
 
-#ifdef __STDC__
 int
-mod_name(register ARCHD *arcn)
-#else
-int
-mod_name(arcn)
-       register ARCHD *arcn;
-#endif
+mod_name(ARCHD *arcn)
 {
-       register int res = 0;
+       int res = 0;
 
        /*
         * Strip off leading '/' if appropriate.
@@ -727,12 +666,12 @@ mod_name(arcn)
                 * we have replacement strings, modify the name and the link
                 * name if any.
                 */
-               if ((res = rep_name(arcn->name, &(arcn->nlen), 1)) != 0)
+               if ((res = rep_name(arcn->name, sizeof(arcn->name), &(arcn->nlen), 1)) != 0)
                        return(res);
 
                if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
                    (arcn->type == PAX_HRG)) &&
-                   ((res = rep_name(arcn->ln_name, &(arcn->ln_nlen), 0)) != 0))
+                   ((res = rep_name(arcn->ln_name, sizeof(arcn->ln_name), &(arcn->ln_nlen), 0)) != 0))
                        return(res);
        }
 
@@ -759,14 +698,8 @@ mod_name(arcn)
  *     0 process this file, 1 skip this file, -1 we need to exit pax
  */
 
-#ifdef __STDC__
-static int
-tty_rename(register ARCHD *arcn)
-#else
-static int
-tty_rename(arcn)
-       register ARCHD *arcn;
-#endif
+int
+tty_rename(ARCHD *arcn)
 {
        char tmpname[PAXPATHLEN+2];
        int res;
@@ -816,8 +749,7 @@ tty_rename(arcn)
         */
        tty_prnt("Processing continues, name changed to: %s\n", tmpname);
        res = add_name(arcn->name, arcn->nlen, tmpname);
-       arcn->nlen = l_strncpy(arcn->name, tmpname, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       arcn->nlen = strlcpy(arcn->name, tmpname, sizeof(arcn->name));
        if (res < 0)
                return(-1);
        return(0);
@@ -831,16 +763,8 @@ tty_rename(arcn)
  *     0 if ok, -1 if failure (name too long)
  */
 
-#ifdef __STDC__
-int
-set_dest(register ARCHD *arcn, char *dest_dir, int dir_len)
-#else
 int
-set_dest(arcn, dest_dir, dir_len)
-       register ARCHD *arcn;
-       char *dest_dir;
-       int dir_len;
-#endif
+set_dest(ARCHD *arcn, char *dest_dir, int dir_len)
 {
        if (fix_path(arcn->name, &(arcn->nlen), dest_dir, dir_len) < 0)
                return(-1);
@@ -866,21 +790,12 @@ set_dest(arcn, dest_dir, dir_len)
  *     0 if ok, -1 if the final name is too long
  */
 
-#ifdef __STDC__
-static int
-fix_path( char *or_name, int *or_len, char *dir_name, int dir_len)
-#else
 static int
-fix_path(or_name, or_len, dir_name, dir_len)
-       char *or_name;
-       int *or_len;
-       char *dir_name;
-       int dir_len;
-#endif
+fix_path(char *or_name, int *or_len, char *dir_name, int dir_len)
 {
-       register char *src;
-       register char *dest;
-       register char *start;
+       char *src;
+       char *dest;
+       char *start;
        int len;
 
        /*
@@ -903,7 +818,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
        *or_len = len;
 
        /*
-        * enough space, shift 
+        * enough space, shift
         */
        while (src >= start)
                *dest-- = *src--;
@@ -930,6 +845,7 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     --Parameters--
  *     name is the file name we are going to apply the regular expressions to
  *     (and may be modified)
+ *     nsize is the size of the name buffer.
  *     nlen is the length of this name (and is modified to hold the length of
  *     the final string).
  *     prnt is a flag that says whether to print the final result.
@@ -938,27 +854,17 @@ fix_path(or_name, or_len, dir_name, dir_len)
  *     ended up empty)
  */
 
-#ifdef __STDC__
-static int
-rep_name(char *name, int *nlen, int prnt)
-#else
 static int
-rep_name(name, nlen, prnt)
-       char *name;
-       int *nlen;
-       int prnt;
-#endif
+rep_name(char *name, size_t nsize, int *nlen, int prnt)
 {
-       register REPLACE *pt;
-       register char *inpt;
-       register char *outpt;
-       register char *endpt;
-       register char *rpt;
-       register int found = 0;
-       register int res;
-#      ifndef NET2_REGEX
+       REPLACE *pt;
+       char *inpt;
+       char *outpt;
+       char *endpt;
+       char *rpt;
+       int found = 0;
+       int res;
        regmatch_t pm[MAXSUBEXP];
-#      endif
        char nname[PAXPATHLEN+1];       /* final result of all replacements */
        char buf1[PAXPATHLEN+1];        /* where we work on the name */
 
@@ -971,7 +877,7 @@ rep_name(name, nlen, prnt)
         * (the user already saw that substitution go by)
         */
        pt = rephead;
-       (void)strcpy(buf1, name);
+       (void)strlcpy(buf1, name, sizeof(buf1));
        inpt = buf1;
        outpt = nname;
        endpt = outpt + PAXPATHLEN;
@@ -981,15 +887,12 @@ rep_name(name, nlen, prnt)
         */
        while (pt != NULL) {
                do {
+                       char *oinpt = inpt;
                        /*
                         * check for a successful substitution, if not go to
                         * the next pattern, or cleanup if we were global
                         */
-#                      ifdef NET2_REGEX
-                       if (regexec(pt->rcmp, inpt) == 0)
-#                      else
                        if (regexec(&(pt->rcmp), inpt, MAXSUBEXP, pm, 0) != 0)
-#                      endif
                                break;
 
                        /*
@@ -1000,11 +903,7 @@ rep_name(name, nlen, prnt)
                         * do not create a string too long).
                         */
                        found = 1;
-#                      ifdef NET2_REGEX
-                       rpt = pt->rcmp->startp[0];
-#                      else
                        rpt = inpt + pm[0].rm_so;
-#                      endif
 
                        while ((inpt < rpt) && (outpt < endpt))
                                *outpt++ = *inpt++;
@@ -1017,12 +916,8 @@ rep_name(name, nlen, prnt)
                         * replacement string and place it the prefix in the
                         * final output. If we have problems, skip it.
                         */
-#                      ifdef NET2_REGEX
-                       if ((res = resub(pt->rcmp,pt->nstr,outpt,endpt)) < 0) {
-#                      else
-                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,outpt,endpt))
+                       if ((res = resub(&(pt->rcmp),pm,pt->nstr,oinpt,outpt,endpt))
                            < 0) {
-#                      endif
                                if (prnt)
                                        paxwarn(1, "Replacement name error %s",
                                            name);
@@ -1040,11 +935,7 @@ rep_name(name, nlen, prnt)
                         * the final result. Make sure we do not overrun the
                         * output buffer
                         */
-#                      ifdef NET2_REGEX
-                       inpt = pt->rcmp->endp[0];
-#                      else
                        inpt += pm[0].rm_eo - pm[0].rm_so;
-#                      endif
 
                        if ((outpt == endpt) || (*inpt == '\0'))
                                break;
@@ -1097,98 +988,28 @@ rep_name(name, nlen, prnt)
                 */
                if (*nname == '\0')
                        return(1);
-               *nlen = l_strncpy(name, nname, PAXPATHLEN + 1);
-               name[PAXPATHLEN] = '\0';
+               *nlen = strlcpy(name, nname, nsize);
        }
        return(0);
 }
 
-#ifdef NET2_REGEX
 /*
  * resub()
  *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
+ *     style ed(1) subexpression expansion.
  * Return:
  *     -1 if error, or the number of characters added to the destination.
  */
 
-#ifdef __STDC__
-static int
-resub(regexp *prog, char *src, char *dest, register char *destend)
-#else
 static int
-resub(prog, src, dest, destend)
-       regexp *prog;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
+resub(regex_t *rp, regmatch_t *pm, char *src, char *inpt, char *dest,
+       char *destend)
 {
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register int no;
-       register int len;
-
-       spt = src;
-       dpt = dest;
-       while ((dpt < destend) && ((c = *spt++) != '\0')) {
-               if (c == '&')
-                       no = 0;
-               else if ((c == '\\') && (*spt >= '0') && (*spt <= '9'))
-                       no = *spt++ - '0';
-               else {
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
-                       continue;
-               }
-               if ((prog->startp[no] == NULL) || (prog->endp[no] == NULL) ||
-                   ((len = prog->endp[no] - prog->startp[no]) <= 0))
-                       continue;
-
-               /*
-                * copy the subexpression to the destination.
-                * fail if we run out of space or the match string is damaged
-                */
-               if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, prog->startp[no], len) != len)
-                       return(-1);
-               dpt += len;
-       }
-       return(dpt - dest);
-}
-
-#else
-
-/*
- * resub()
- *     apply the replacement to the matched expression. expand out the old
- *     style ed(1) subexpression expansion.
- * Return:
- *     -1 if error, or the number of characters added to the destination.
- */
-
-#ifdef __STDC__
-static int
-resub(regex_t *rp, register regmatch_t *pm, char *src, char *dest,
-       register char *destend)
-#else
-static int
-resub(rp, pm, src, dest, destend)
-       regex_t *rp;
-       register regmatch_t *pm;
-       char *src;
-       char *dest;
-       register char *destend;
-#endif
-{
-       register char *spt;
-       register char *dpt;
-       register char c;
-       register regmatch_t *pmpt;
-       register int len;
+       char *spt;
+       char *dpt;
+       char c;
+       regmatch_t *pmpt;
+       int len;
        int subexcnt;
 
        spt =  src;
@@ -1209,12 +1030,12 @@ resub(rp, pm, src, dest, destend)
                                return(-1);
                        pmpt = pm + len;
                } else {
-                       /*
+                       /*
                         * Ordinary character, just copy it
                         */
-                       if ((c == '\\') && ((*spt == '\\') || (*spt == '&')))
-                               c = *spt++;
-                       *dpt++ = c;
+                       if ((c == '\\') && (*spt != '\0'))
+                               c = *spt++;
+                       *dpt++ = c;
                        continue;
                }
 
@@ -1230,11 +1051,9 @@ resub(rp, pm, src, dest, destend)
                 * fail if we run out of space or the match string is damaged
                 */
                if (len > (destend - dpt))
-                       len = destend - dpt;
-               if (l_strncpy(dpt, src + pmpt->rm_so, len) != len)
-                       return(-1);
+                       return (-1);
+               strncpy(dpt, inpt + pmpt->rm_so, len);
                dpt += len;
        }
        return(dpt - dest);
 }
-#endif
index b41f1e12fc405a7368285b60e84023e05ba3c76c..72b8beebd6fd1fdbb2704234bfc09c56cdd92735 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pat_rep.h,v 1.2 1996/06/23 14:20:38 deraadt Exp $     */
+/*     $OpenBSD: pat_rep.h,v 1.4 2003/06/02 23:32:08 millert Exp $     */
 /*     $NetBSD: pat_rep.h,v 1.3 1995/03/21 09:07:35 cgd Exp $  */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  */
 typedef struct replace {
        char            *nstr;  /* the new string we will substitute with */
-#      ifdef NET2_REGEX
-       regexp          *rcmp;  /* compiled regular expression used to match */
-#      else
        regex_t         rcmp;   /* compiled regular expression used to match */
-#      endif
        int             flgs;   /* print conversions? global in operation?  */
 #define        PRNT            0x1
 #define        GLOB            0x2
        struct replace  *fow;   /* pointer to next pattern */
 } REPLACE;
+
+int tty_rename(ARCHD *);       /* Used for -o invalid=rename recovery */
index 8df49bd8f8dd73411e452a3c178863554c198944..0ad62b3d188985be67c2044c2264a29c3d54cef0 100644 (file)
--- a/pax/pax.1
+++ b/pax/pax.1
@@ -1,3 +1,6 @@
+.\"    $OpenBSD: pax.1,v 1.44 2004/02/19 19:15:32 jmc Exp $
+.\"    $NetBSD: pax.1,v 1.3 1995/03/21 09:07:37 cgd Exp $
+.\"
 .\" Copyright (c) 1992 Keith Muller.
 .\" Copyright (c) 1992, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -13,7 +16,7 @@
 .\" 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.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 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.
 .\"
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)pax.1       8.4 (Berkeley) 4/18/94
-.\" $FreeBSD: src/bin/pax/pax.1,v 1.33 2004/07/03 02:03:44 tjr Exp $
 .\"
-.Dd July 3, 2004
+.Dd April 18, 1994
 .Dt PAX 1
 .Os
 .Sh NAME
 .Nm pax
 .Nd read and write file archives and copy directory hierarchies
 .Sh SYNOPSIS
-.Nm
-.Op Fl cdnvz
+.Nm pax
+.Op Fl 0cdnvz
 .Bk -words
 .Op Fl f Ar archive
 .Ek
 .Bk -words
 .Op Fl s Ar replstr
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl U Ar user
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl G Ar group
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Oo
 .Op Ar from_date
 .Op Ar ,to_date
 .Oc
-.Ar ...\&
+.Ar ...
 .Ek
-.Op Ar pattern ...\&
-.Nm
+.Op Ar pattern ...
+.Nm pax
 .Fl r
 .Op Fl cdiknuvzDYZ
 .Bk -words
 .Ek
 .Bk -words
 .Op Fl o Ar options
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl p Ar string
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl s Ar replstr
-.Ar ...\&
+.Ar ...
 .Ek
 .Op Fl E Ar limit
 .Bk -words
 .Op Fl U Ar user
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl G Ar group
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Oo
 .Op Ar from_date
 .Op Ar ,to_date
 .Oc
-.Ar ...\&
+.Ar ...
 .Ek
-.Op Ar pattern ...\&
-.Nm
+.Op Ar pattern ...
+.Nm pax
 .Fl w
-.Op Fl dituvzHLPX
+.Op Fl 0dituvzHLPX
 .Bk -words
 .Op Fl b Ar blocksize
 .Ek
 .Ek
 .Bk -words
 .Op Fl s Ar replstr
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl o Ar options
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl U Ar user
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl G Ar group
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl B Ar bytes
 .Op Ar ,to_date
 .Op Ar /[c][m]
 .Oc
-.Ar ...\&
+.Ar ...
 .Ek
-.Op Ar
-.Nm
+.Op Ar file ...
+.Nm pax
 .Fl r
 .Fl w
-.Op Fl diklntuvDHLPXYZ
+.Op Fl 0diklntuvDHLPXYZ
 .Bk -words
 .Op Fl p Ar string
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl s Ar replstr
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl U Ar user
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Op Fl G Ar group
-.Ar ...\&
+.Ar ...
 .Ek
 .Bk -words
 .Oo
 .Op Ar ,to_date
 .Op Ar /[c][m]
 .Oc
-.Ar ...\&
+.Ar ...
 .Ek
-.Op Ar
+.Op Ar file ...
 .Ar directory
 .Sh DESCRIPTION
-The
-.Nm
-utility will read, write, and list the members of an archive file,
+.Nm pax
+will read, write, and list the members of an archive file,
 and will copy directory hierarchies.
-These operations are independent of the specific archive format,
-and support a wide variety of different archive formats.
+.Nm pax
+operation is independent of the specific archive format,
+and supports a wide variety of different archive formats.
 A list of supported archive formats can be found under the description of the
 .Fl x
 option.
@@ -190,7 +192,7 @@ The presence of the
 and the
 .Fl w
 options specifies which of the following functional modes
-.Nm
+.Nm pax
 will operate under:
 .Em list , read , write ,
 and
@@ -198,18 +200,18 @@ and
 .Bl -tag -width 6n
 .It <none>
 .Em List .
-Write to
-.Dv standard output
+.Nm pax
+will write to standard output
 a table of contents of the members of the archive file read from
-.Dv standard input ,
-whose pathnames match the specified
+standard input, whose pathnames match the specified
 .Ar patterns .
 The table of contents contains one filename per line
 and is written using single line buffering.
+.\" ==========
 .It Fl r
 .Em Read .
-Extract the members of the archive file read from the
-.Dv standard input ,
+.Nm pax
+extracts the members of the archive file read from the standard input,
 with pathnames matching the specified
 .Ar patterns .
 The archive format and blocking is automatically determined on input.
@@ -220,32 +222,34 @@ The setting of ownership, access and modification times, and file mode of
 the extracted files are discussed in more detail under the
 .Fl p
 option.
+.\" ==========
 .It Fl w
 .Em Write .
-Write an archive containing the
+.Nm pax
+writes an archive containing the
 .Ar file
-operands to
-.Dv standard output
+operands to standard output
 using the specified archive format.
 When no
 .Ar file
 operands are specified, a list of files to copy with one per line is read from
-.Dv standard input .
+standard input.
 When a
 .Ar file
 operand is also a directory, the entire file hierarchy rooted
 at that directory will be included.
+.\" ==========
 .It Fl r Fl w
 .Em Copy .
-Copy the
+.Nm pax
+copies the
 .Ar file
 operands to the destination
 .Ar directory .
 When no
 .Ar file
 operands are specified, a list of files to copy with one per line is read from
-the
-.Dv standard input .
+the standard input.
 When a
 .Ar file
 operand is also a directory the entire file
@@ -276,12 +280,12 @@ While processing a damaged archive during a
 or
 .Em list
 operation,
-.Nm
+.Nm pax
 will attempt to recover from media defects and will search through the archive
 to locate and process the largest number of archive members possible (see the
 .Fl E
 option for more details on error handling).
-.Sh OPERANDS
+.Pp
 The
 .Ar directory
 operand specifies a destination directory pathname.
@@ -289,7 +293,7 @@ If the
 .Ar directory
 operand does not exist, or it is not writable by the user,
 or it is not of type directory,
-.Nm
+.Nm pax
 will exit with a non-zero exit status.
 .Pp
 The
@@ -308,11 +312,10 @@ be selected.
 When a
 .Ar pattern
 operand does not select at least one archive member,
-.Nm
+.Nm pax
 will write these
 .Ar pattern
-operands in a diagnostic message to
-.Dv standard error
+operands in a diagnostic message to standard error
 and then exit with a non-zero exit status.
 .Pp
 The
@@ -321,47 +324,32 @@ operand specifies the pathname of a file to be copied or archived.
 When a
 .Ar file
 operand does not select at least one archive member,
-.Nm
+.Nm pax
 will write these
 .Ar file
-operand pathnames in a diagnostic message to
-.Dv standard error
+operand pathnames in a diagnostic message to standard error
 and then exit with a non-zero exit status.
-.Sh OPTIONS
-The following options are supported:
-.Bl -tag -width 4n
-.It Fl r
-Read an archive file from
-.Dv standard input
-and extract the specified
-.Ar files .
-If any intermediate directories are needed in order to extract an archive
-member, these directories will be created as if
-.Xr mkdir 2
-was called with the bitwise inclusive
-.Dv OR
-of
-.Dv S_IRWXU , S_IRWXG ,
-and
-.Dv S_IRWXO
-as the mode argument.
-When the selected archive format supports the specification of linked
-files and these files cannot be linked while the archive is being extracted,
-.Nm
-will write a diagnostic message to
-.Dv standard error
-and exit with a non-zero exit status at the completion of operation.
-.It Fl w
-Write files to the
-.Dv standard output
-in the specified archive format.
-When no
-.Ar file
-operands are specified,
-.Dv standard input
-is read for a list of pathnames with one per line without any leading or
-trailing
-.Aq blanks .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.\" ==========
+.It Fl 0
+Use the NUL
+.Pq Ql \e0
+character as a pathname terminator, instead of newline
+.Pq Ql \en .
+This applies only to the pathnames read from standard input in
+the write and copy modes,
+and to the pathnames written to standard output in list mode.
+This option is expected to be used in concert with the
+.Fl print0
+function in
+.Xr find 1
+or the
+.Fl 0
+flag in
+.Xr xargs 1 .
+.\" ==========
 .It Fl a
 Append
 .Ar files
@@ -371,7 +359,7 @@ If an archive format is not specified with a
 option, the format currently being used in the archive will be selected.
 Any attempt to append to an archive in a format different from the
 format already used in the archive will cause
-.Nm
+.Nm pax
 to exit immediately
 with a non-zero exit status.
 The blocking size used in the archive volume where writing starts
@@ -385,6 +373,30 @@ archive or have other unpredictable results.
 Tape drives in particular are more likely to not support an append operation.
 An archive stored in a regular file system file or on a disk device will
 usually support an append operation.
+.\" ==========
+.It Fl B Ar bytes
+Limit the number of bytes written to a single archive volume to
+.Ar bytes .
+The
+.Ar bytes
+limit can end with
+.Sq Li m ,
+.Sq Li k ,
+or
+.Sq Li b
+to specify multiplication by 1048576 (1M), 1024 (1K) or 512, respectively.
+A pair of
+.Ar bytes
+limits can be separated by
+.Sq Li x
+to indicate a product.
+.Pp
+.Em Warning :
+Only use this option when writing an archive to a device which supports
+an end of file read condition based on last (or largest) write offset
+(such as a regular file or a tape drive).
+The use of this option with a floppy or hard disk is not recommended.
+.\" ==========
 .It Fl b Ar blocksize
 When
 .Em writing
@@ -400,14 +412,14 @@ standard and will not be portable to all systems.
 A
 .Ar blocksize
 can end with
-.Li k
+.Sq Li k
 or
-.Li b
+.Sq Li b
 to specify multiplication by 1024 (1K) or 512, respectively.
 A pair of
 .Ar blocksizes
 can be separated by
-.Li x
+.Sq Li x
 to indicate a product.
 A specific archive device may impose additional restrictions on the size
 of blocking it will support.
@@ -416,6 +428,7 @@ When blocking is not specified, the default
 is dependent on the specific archive format being used (see the
 .Fl x
 option).
+.\" ==========
 .It Fl c
 Match all file or archive members
 .Em except
@@ -424,28 +437,88 @@ those specified by the
 and
 .Ar file
 operands.
+.\" ==========
+.It Fl D
+This option is the same as the
+.Fl u
+option, except that the file inode change time is checked instead of the
+file modification time.
+The file inode change time can be used to select files whose inode information
+(e.g., UID, GID, etc.) is newer than a copy of the file in the destination
+.Ar directory .
+.\" ==========
 .It Fl d
 Cause files of type directory being copied or archived, or archive members of
 type directory being extracted, to match only the directory file or archive
 member and not the file hierarchy rooted at the directory.
+.\" ==========
+.It Fl E Ar limit
+Limit the number of consecutive read faults while trying to read a flawed
+archive to
+.Ar limit .
+With a positive
+.Ar limit ,
+.Nm pax
+will attempt to recover from an archive read error and will
+continue processing starting with the next file stored in the archive.
+A
+.Ar limit
+of 0 will cause
+.Nm pax
+to stop operation after the first read error is detected on an archive volume.
+A
+.Ar limit
+of
+.Li NONE
+will cause
+.Nm pax
+to attempt to recover from read errors forever.
+The default
+.Ar limit
+is a small positive number of retries.
+.Pp
+.Em Warning :
+Using this option with
+.Li NONE
+should be used with extreme caution as
+.Nm pax
+may get stuck in an infinite loop on a very badly flawed archive.
+.\" ==========
 .It Fl f Ar archive
 Specify
 .Ar archive
 as the pathname of the input or output archive, overriding the default
-.Dv standard input
-(for
+standard input (for
 .Em list
 and
 .Em read )
-or
-.Dv standard output
+or standard output
 (for
 .Em write ) .
 A single archive may span multiple files and different archive devices.
 When required,
-.Nm
+.Nm pax
 will prompt for the pathname of the file or device of the next volume in the
 archive.
+.\" ==========
+.It Fl G Ar group
+Select a file based on its
+.Ar group
+name, or when starting with a
+.Cm # ,
+a numeric gid.
+A
+.Ql \e
+can be used to escape the
+.Cm # .
+Multiple
+.Fl G
+options may be supplied and checking stops with the first match.
+.\" ==========
+.It Fl H
+Follow only command-line symbolic links while performing a physical file
+system traversal.
+.\" ==========
 .It Fl i
 Interactively rename files or archive members.
 For each archive member matching a
@@ -453,36 +526,41 @@ For each archive member matching a
 operand or each file matching a
 .Ar file
 operand,
-.Nm
+.Nm pax
 will prompt to
 .Pa /dev/tty
-giving the name of the file, its file mode and its modification time.
-The
-.Nm
-utility will then read a line from
+giving the name of the file, its file mode, and its modification time.
+.Nm pax
+will then read a line from
 .Pa /dev/tty .
 If this line is blank, the file or archive member is skipped.
 If this line consists of a single period, the
 file or archive member is processed with no modification to its name.
 Otherwise, its name is replaced with the contents of the line.
-The
-.Nm
-utility will immediately exit with a non-zero exit status if
-.Dv <EOF>
+.Nm pax
+will immediately exit with a non-zero exit status if
+.Dv EOF
 is encountered when reading a response or if
 .Pa /dev/tty
 cannot be opened for reading and writing.
+.\" ==========
 .It Fl k
 Do not overwrite existing files.
+.\" ==========
+.It Fl L
+Follow all symbolic links to perform a logical file system traversal.
+.\" ==========
 .It Fl l
+(The lowercase letter
+.Dq ell. )
 Link files.
-(The letter ell).
 In the
 .Em copy
 mode
-.Pq Fl r w ,
+.Pq Fl r Fl w ,
 hard links are made between the source and destination file hierarchies
 whenever possible.
+.\" ==========
 .It Fl n
 Select the first archive member that matches each
 .Ar pattern
@@ -493,6 +571,15 @@ When members of type directory are matched, the file hierarchy rooted at that
 directory is also matched (unless
 .Fl d
 is also specified).
+.\" ==========
+.It Fl O
+Force the archive to be one volume.
+If a volume ends prematurely,
+.Nm pax
+will not prompt for a new volume.
+This option can be useful for
+automated tasks where error recovery cannot be performed by a human.
+.\" ==========
 .It Fl o Ar options
 Information to modify the algorithm for extracting or writing archive files
 which is specific to the archive format specified by
@@ -500,7 +587,56 @@ which is specific to the archive format specified by
 In general,
 .Ar options
 take the form:
-.Cm name=value
+.Ar name Ns = Ns Ar value .
+.Pp
+If the "-x pax" option is used,
+the ":=" form of keyword specification is supported.
+Also, the following new keywords are implemented:
+.Bl -bullet
+.It
+delete=<pattern>
+.It
+exthdr.name=<string>
+.It
+globexhdr.name=<string>
+.It
+invalid=<action> for actions
+bypass, rename, utf-8 (recognized, but ignored), and write
+.It
+linkdata
+.It
+listopt=<format>
+for the 'F' conversion specifier 
+(not the 'D', 'T', 'M', or 'L' specifiers)
+.It
+times
+.It
+all keywords in pax Extended Header,
+with the following restrictions:
+.Bl -tag
+.It charset
+keyword recognized, but ignored
+.It realtime.any
+keyword not recognized
+.It security.any
+keyword not recognized
+.El
+.El
+.Pp
+In "copy mode", only the following new keywords are supported:
+.Bl -bullet
+.It
+delete=
+.It
+invalid=
+.It
+path= (from pax Extended Header description)
+.El
+.\" ==========
+.It Fl P
+Do not follow symbolic links, perform a physical file system traversal.
+This is the default mode.
+.\" ==========
 .It Fl p Ar string
 Specify one or more file characteristic options (privileges).
 The
@@ -515,7 +651,7 @@ Multiple characteristics can be concatenated within the same string
 and multiple
 .Fl p
 options can be specified.
-The meaning of the specification characters are as follows:
+The meanings of the specification characters are as follows:
 .Bl -tag -width 2n
 .It Cm a
 Do not preserve file access times.
@@ -543,7 +679,7 @@ Preserve the user ID and group ID.
 .It Cm p
 .Sq Preserve
 the file mode bits.
-This intended to be used by a
+This is intended to be used by a
 .Em user
 with regular privileges who wants to preserve all aspects of the file other
 than the ownership.
@@ -564,7 +700,7 @@ nor the
 .Cm o
 specification character is specified, or the user ID and group ID are not
 preserved for any reason,
-.Nm
+.Nm pax
 will not set the
 .Dv S_ISUID
 .Em ( setuid )
@@ -573,9 +709,8 @@ and
 .Em ( setgid )
 bits of the file mode.
 If the preservation of any of these items fails for any reason,
-.Nm
-will write a diagnostic message to
-.Dv standard error .
+.Nm pax
+will write a diagnostic message to standard error.
 Failure to preserve these items will affect the final exit status,
 but will not cause the extracted file to be deleted.
 If the file characteristic letters in any of the string option-arguments are
@@ -584,6 +719,25 @@ precedence.
 For example, if
 .Dl Fl p Ar eme
 is specified, file modification times are still preserved.
+.It Fl r
+Read an archive file from standard input
+and extract the specified
+.Ar files .
+If any intermediate directories are needed in order to extract an archive
+member, these directories will be created as if
+.Xr mkdir 2
+was called with the bitwise inclusive
+.Tn OR
+of
+.Dv S_IRWXU , S_IRWXG ,
+and
+.Dv S_IRWXO
+as the mode argument.
+When the selected archive format supports the specification of linked
+files and these files cannot be linked while the archive is being extracted,
+.Nm pax
+will write a diagnostic message to standard error
+and exit with a non-zero exit status at the completion of operation.
 .It Fl s Ar replstr
 Modify the file or archive member names specified by the
 .Ar pattern
@@ -594,21 +748,28 @@ operands according to the substitution expression
 using the syntax of the
 .Xr ed 1
 utility regular expressions.
-The format of these regular expressions are:
+The format of these regular expressions is:
 .Dl /old/new/[gp]
 As in
 .Xr ed 1 ,
 .Cm old
 is a basic regular expression and
 .Cm new
-can contain an ampersand (&), \\n (where n is a digit) back-references,
+can contain an ampersand
+.Pq Ql & ,
+.Ql \en
+(where
+.Ar n
+is a digit) back-references,
 or subexpression matching.
 The
 .Cm old
-string may also contain
-.Dv <newline>
-characters.
-Any non-null character can be used as a delimiter (/ is shown here).
+string may also contain newline characters.
+Any non-null character can be used as a delimiter
+.Po
+.Ql /
+is shown here
+.Pc .
 Multiple
 .Fl s
 expressions can be specified.
@@ -616,7 +777,7 @@ The expressions are applied in the order they are specified on the
 command line, terminating with the first successful substitution.
 The optional trailing
 .Cm g
-continues to apply the substitution expression to the pathname substring
+continues to apply the substitution expression to the pathname substring,
 which starts with the first character following the end of the last successful
 substitution.
 The first unsuccessful substitution stops the operation of the
@@ -625,16 +786,127 @@ option.
 The optional trailing
 .Cm p
 will cause the final result of a successful substitution to be written to
-.Dv standard error
-in the following format:
+standard error in the following format:
 .Dl <original pathname> >> <new pathname>
 File or archive member names that substitute to the empty string
 are not selected and will be skipped.
+.It Fl T Ar [from_date][,to_date][/[c][m]]
+Allow files to be selected based on a file modification or inode change
+time falling within a specified time range of
+.Ar from_date
+to
+.Ar to_date
+(the dates are inclusive).
+If only a
+.Ar from_date
+is supplied, all files with a modification or inode change time
+equal to or younger are selected.
+If only a
+.Ar to_date
+is supplied, all files with a modification or inode change time
+equal to or older will be selected.
+When the
+.Ar from_date
+is equal to the
+.Ar to_date ,
+only files with a modification or inode change time of exactly that
+time will be selected.
+.Pp
+When
+.Nm pax
+is in the
+.Em write
+or
+.Em copy
+mode, the optional trailing field
+.Ar [c][m]
+can be used to determine which file time (inode change, file modification or
+both) are used in the comparison.
+If neither is specified, the default is to use file modification time only.
+The
+.Ar m
+specifies the comparison of file modification time (the time when
+the file was last written).
+The
+.Ar c
+specifies the comparison of inode change time (the time when the file
+inode was last changed; e.g., a change of owner, group, mode, etc).
+When
+.Ar c
+and
+.Ar m
+are both specified, then the modification and inode change times are
+both compared.
+The inode change time comparison is useful in selecting files whose
+attributes were recently changed or selecting files which were recently
+created and had their modification time reset to an older time (as what
+happens when a file is extracted from an archive and the modification time
+is preserved).
+Time comparisons using both file times is useful when
+.Nm pax
+is used to create a time based incremental archive (only files that were
+changed during a specified time range will be archived).
+.Pp
+A time range is made up of six different fields and each field must contain two
+digits.
+The format is:
+.Dl [[[[[cc]yy]mm]dd]HH]MM[.SS]
+Where
+.Cm cc
+is the first two digits of the year (the century),
+.Cm yy
+is the last two digits of the year,
+the first
+.Cm mm
+is the month (from 01 to 12),
+.Cm dd
+is the day of the month (from 01 to 31),
+.Cm HH
+is the hour of the day (from 00 to 23),
+.Cm MM
+is the minute (from 00 to 59),
+and
+.Cm SS
+is the seconds (from 00 to 59).
+The minute field
+.Cm MM
+is required, while the other fields are optional and must be added in the
+following order:
+.br
+.Cm \& HH , dd , mm ,
+.Cm yy , cc .
+.br
+The
+.Cm SS
+field may be added independently of the other fields.
+Time ranges are relative to the current time, so
+.Dl Fl T Ar 1234/cm
+would select all files with a modification or inode change time
+of 12:34 PM today or later.
+Multiple
+.Fl T
+time range can be supplied and checking stops with the first match.
+.\" ==========
 .It Fl t
 Reset the access times of any file or directory read or accessed by
-.Nm
+.Nm pax
 to be the same as they were before being read or accessed by
-.Nm .
+.Nm pax .
+.\" ==========
+.It Fl U Ar user
+Select a file based on its
+.Ar user
+name, or when starting with a
+.Cm # ,
+a numeric UID.
+A
+.Ql \e
+can be used to escape the
+.Cm # .
+Multiple
+.Fl U
+options may be supplied and checking stops with the first match.
+.\" ==========
 .It Fl u
 Ignore files that are older (having a less recent file modification time)
 than a pre-existing file or archive member with the same name.
@@ -651,6 +923,7 @@ During
 the file in the destination hierarchy is replaced by the file in the source
 hierarchy or by a link to the file in the source hierarchy if the file in
 the source hierarchy is newer.
+.\" ==========
 .It Fl v
 During a
 .Em list
@@ -670,62 +943,88 @@ utility when used with the
 .Fl l
 option.
 Otherwise for all the other operational modes
-.Em ( read , write ,
-and
-.Em copy ) ,
-pathnames are written and flushed to
-.Dv standard error
-without a trailing
-.Dv <newline>
+.Po Em read , write , Li and Em copy
+.Pc ,
+pathnames are written and flushed to standard error
+without a trailing newline
 as soon as processing begins on that file or
 archive member.
-The trailing
-.Dv <newline> ,
-is not buffered, and is written only after the file has been read or written.
+The trailing newline
+is not buffered and is written only after the file has been read or written.
+.\" ==========
+.It Fl w
+Write files to the standard output
+in the specified archive format.
+When no
+.Ar file
+operands are specified, standard input
+is read for a list of pathnames with one per line without any leading or
+trailing
+.Aq blanks .
+.\" ==========
+.It Fl X
+When traversing the file hierarchy specified by a pathname,
+do not descend into directories that have a different device ID.
+See the
+.Li st_dev
+field as described in
+.Xr stat 2
+for more information about device IDs.
+.\" ==========
 .It Fl x Ar format
 Specify the output archive format, with the default format being
 .Ar ustar .
-The
-.Nm
-utility currently supports the following formats:
+.Nm pax
+currently supports the following formats:
 .Bl -tag -width "sv4cpio"
-.It Ar cpio
-The extended cpio interchange format specified in the
-.St -p1003.2
-standard.
-The default blocksize for this format is 5120 bytes.
-Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm
-and is repaired.
+.\" ==========
 .It Ar bcpio
 The old binary cpio format.
 The default blocksize for this format is 5120 bytes.
 This format is not very portable and should not be used when other formats
 are available.
 Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm
+by this format), which may be truncated by this format, is detected by
+.Nm pax
+and is repaired.
+.\" ==========
+.It Ar cpio
+The extended cpio interchange format specified in the
+.St -p1003.2
+standard.
+The default blocksize for this format is 5120 bytes.
+Inode and device information about a file (used for detecting file hard links
+by this format), which may be truncated by this format, is detected by
+.Nm pax
 and is repaired.
+.\" ==========
+.It Ar pax
+"pax interchange format", described in the
+EXTENDED DESCRIPTION of the pax interchange format
+in The Open Group's SUSv3 specification.
+Includes support for pax Header Block,
+pax Extended Header,
+pax Extended Header Keyword Precedence, and 
+pax Extended Header File Times.
+.\" ==========
 .It Ar sv4cpio
 The System V release 4 cpio.
 The default blocksize for this format is 5120 bytes.
 Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm
+by this format), which may be truncated by this format, is detected by
+.Nm pax
 and is repaired.
+.\" ==========
 .It Ar sv4crc
 The System V release 4 cpio with file crc checksums.
 The default blocksize for this format is 5120 bytes.
 Inode and device information about a file (used for detecting file hard links
-by this format) which may be truncated by this format is detected by
-.Nm
+by this format), which may be truncated by this format, is detected by
+.Nm pax
 and is repaired.
+.\" ==========
 .It Ar tar
-The old
-.Bx
-tar format as found in
-.Bx 4.3 .
+The old BSD tar format as found in BSD4.3.
 The default blocksize for this format is 10240 bytes.
 Pathnames stored by this format must be 100 characters or less in length.
 Only
@@ -740,232 +1039,46 @@ For backwards compatibility with even older tar formats, a
 option can be used when writing an archive to omit the storage of directories.
 This option takes the form:
 .Dl Fl o Cm write_opt=nodir
+.\" ==========
 .It Ar ustar
 The extended tar interchange format specified in the
 .St -p1003.2
 standard.
 The default blocksize for this format is 10240 bytes.
-Pathnames stored by this format must be 250 characters or less in length.
+Filenames stored by this format must be 100 characters or less in length;
+the total pathname must be 255 characters or less.
 .El
 .Pp
-The
-.Nm
-utility will detect and report any file that it is unable to store or extract
+.Nm pax
+will detect and report any file that it is unable to store or extract
 as the result of any specific archive format restrictions.
 The individual archive formats may impose additional restrictions on use.
 Typical archive format restrictions include (but are not limited to):
-file pathname length, file size, link pathname length and the type of the file.
-.It Fl z
-Use
-.Xr gzip 1
-to compress (decompress) the archive while writing (reading).
-Incompatible with
-.Fl a .
-.It Fl B Ar bytes
-Limit the number of bytes written to a single archive volume to
-.Ar bytes .
-The
-.Ar bytes
-limit can end with
-.Li m ,
-.Li k ,
-or
-.Li b
-to specify multiplication by 1048576 (1M), 1024 (1K) or 512, respectively.
-A pair of
-.Ar bytes
-limits can be separated by
-.Li x
-to indicate a product.
-.Pp
-.Em Warning :
-Only use this option when writing an archive to a device which supports
-an end of file read condition based on last (or largest) write offset
-(such as a regular file or a tape drive).
-The use of this option with a floppy or hard disk is not recommended.
-.It Fl D
-This option is the same as the
-.Fl u
-option, except that the file inode change time is checked instead of the
-file modification time.
-The file inode change time can be used to select files whose inode information
-(e.g.\& uid, gid, etc.) is newer than a copy of the file in the destination
-.Ar directory .
-.It Fl E Ar limit
-Limit the number of consecutive read faults while trying to read a flawed
-archives to
-.Ar limit .
-With a positive
-.Ar limit ,
-.Nm
-will attempt to recover from an archive read error and will
-continue processing starting with the next file stored in the archive.
-A
-.Ar limit
-of 0 will cause
-.Nm
-to stop operation after the first read error is detected on an archive volume.
-A
-.Ar limit
-of
-.Li NONE
-will cause
-.Nm
-to attempt to recover from read errors forever.
-The default
-.Ar limit
-is a small positive number of retries.
-.Pp
-.Em Warning :
-Using this option with
-.Li NONE
-should be used with extreme caution as
-.Nm
-may get stuck in an infinite loop on a very badly flawed archive.
-.It Fl G Ar group
-Select a file based on its
-.Ar group
-name, or when starting with a
-.Cm # ,
-a numeric gid.
-A '\\' can be used to escape the
-.Cm # .
-Multiple
-.Fl G
-options may be supplied and checking stops with the first match.
-.It Fl H
-Follow only command line symbolic links while performing a physical file
-system traversal.
-.It Fl L
-Follow all symbolic links to perform a logical file system traversal.
-.It Fl P
-Do not follow symbolic links, perform a physical file system traversal.
-This is the default mode.
-.It Fl T Ar [from_date][,to_date][/[c][m]]
-Allow files to be selected based on a file modification or inode change
-time falling within a specified time range of
-.Ar from_date
-to
-.Ar to_date
-(the dates are inclusive).
-If only a
-.Ar from_date
-is supplied, all files with a modification or inode change time
-equal to or younger are selected.
-If only a
-.Ar to_date
-is supplied, all files with a modification or inode change time
-equal to or older will be selected.
-When the
-.Ar from_date
-is equal to the
-.Ar to_date ,
-only files with a modification or inode change time of exactly that
-time will be selected.
-.Pp
-When
-.Nm
-is in the
-.Em write
-or
-.Em copy
-mode, the optional trailing field
-.Ar [c][m]
-can be used to determine which file time (inode change, file modification or
-both) are used in the comparison.
-If neither is specified, the default is to use file modification time only.
-The
-.Ar m
-specifies the comparison of file modification time (the time when
-the file was last written).
-The
-.Ar c
-specifies the comparison of inode change time (the time when the file
-inode was last changed; e.g.\& a change of owner, group, mode, etc).
-When
-.Ar c
-and
-.Ar m
-are both specified, then the modification and inode change times are
-both compared.
-The inode change time comparison is useful in selecting files whose
-attributes were recently changed or selecting files which were recently
-created and had their modification time reset to an older time (as what
-happens when a file is extracted from an archive and the modification time
-is preserved).
-Time comparisons using both file times is useful when
-.Nm
-is used to create a time based incremental archive (only files that were
-changed during a specified time range will be archived).
-.Pp
-A time range is made up of six different fields and each field must contain two
-digits.
-The format is:
-.Dl [yy[mm[dd[hh]]]]mm[.ss]
-Where
-.Cm yy
-is the last two digits of the year,
-the first
-.Cm mm
-is the month (from 01 to 12),
-.Cm dd
-is the day of the month (from 01 to 31),
-.Cm hh
-is the hour of the day (from 00 to 23),
-the second
-.Cm mm
-is the minute (from 00 to 59),
-and
-.Cm ss
-is the seconds (from 00 to 59).
-The minute field
-.Cm mm
-is required, while the other fields are optional and must be added in the
-following order:
-.Dl Cm hh , dd , mm , yy .
-The
-.Cm ss
-field may be added independently of the other fields.
-Time ranges are relative to the current time, so
-.Dl Fl T Ar 1234/cm
-would select all files with a modification or inode change time
-of 12:34 PM today or later.
-Multiple
-.Fl T
-time range can be supplied and checking stops with the first match.
-.It Fl U Ar user
-Select a file based on its
-.Ar user
-name, or when starting with a
-.Cm # ,
-a numeric uid.
-A '\\' can be used to escape the
-.Cm # .
-Multiple
-.Fl U
-options may be supplied and checking stops with the first match.
-.It Fl X
-When traversing the file hierarchy specified by a pathname,
-do not descend into directories that have a different device ID.
-See the
-.Li st_dev
-field as described in
-.Xr stat 2
-for more information about device ID's.
+file pathname length, file size, link pathname length, and the type of the
+file.
+.\" ==========
 .It Fl Y
 This option is the same as the
 .Fl D
 option, except that the inode change time is checked using the
 pathname created after all the file name modifications have completed.
+.\" ==========
 .It Fl Z
 This option is the same as the
 .Fl u
 option, except that the modification time is checked using the
 pathname created after all the file name modifications have completed.
+.\" ==========
+.It Fl z
+Use
+.Xr gzip 1
+to compress (decompress) the archive while writing (reading).
+Incompatible with
+.Fl a .
 .El
 .Pp
 The options that operate on the names of files or archive members
-.Fl ( c ,
+.Po Fl c ,
 .Fl i ,
 .Fl n ,
 .Fl s ,
@@ -977,7 +1090,8 @@ The options that operate on the names of files or archive members
 .Fl U ,
 .Fl Y ,
 and
-.Fl Z )
+.Fl Z
+.Pc
 interact as follows.
 .Pp
 When extracting files during a
@@ -1003,7 +1117,7 @@ Then the
 and
 .Fl Z
 options will be applied based on the final pathname.
-Finally the
+Finally, the
 .Fl v
 option will write the names resulting from these modifications.
 .Pp
@@ -1036,7 +1150,7 @@ operation the
 and the
 .Fl Z
 options will be applied based on the final pathname.
-Finally the
+Finally, the
 .Fl v
 option will write the names resulting from these modifications.
 .Pp
@@ -1048,102 +1162,65 @@ options are specified along with the
 .Fl n
 option, a file is not considered selected unless it is newer
 than the file to which it is compared.
+.Sh ENVIRONMENT
+.Bl -tag -width Fl
+.It Ev TMPDIR
+Path in which to store temporary files.
+.El
 .Sh EXAMPLES
-The command:
-.Dl "pax -w -f /dev/sa0 ."
-copies the contents of the current directory to the device
-.Pa /dev/sa0 .
+.Li $ pax -w -f /dev/rst0 \&.
 .Pp
-The command:
-.Dl pax -v -f filename
-gives the verbose table of contents for an archive stored in
+Copies the contents of the current directory to the device
+.Pa /dev/rst0 .
+.Pp
+.Li $ pax -v -f filename
+.Pp
+Gives the verbose table of contents for an archive stored in
 .Pa filename .
 .Pp
-The following commands:
-.Dl mkdir /tmp/to
-.Dl cd /tmp/from
-.Dl pax -rw .\ /tmp/to
-will copy the entire
-.Pa /tmp/from
+.Li $ mkdir newdir ;
+.Li cd olddir ;
+.Li pax -rw \&. newdir
+.Pp
+This sequence of commands will copy the entire
+.Pa olddir
 directory hierarchy to
-.Pa /tmp/to .
+.Pa newdir .
+.Pp
+.Li $ pax -r -s ',^//*usr//*,,' -f a.pax
 .Pp
-The command:
-.Dl pax -r -s ',^//*usr//*,,' -f a.pax
-reads the archive
+Reads the archive
 .Pa a.pax ,
-with all files rooted in ``/usr'' into the archive extracted relative to the
-current directory.
+with all files rooted in
+.Pa /usr
+into the archive extracted relative to the current directory.
 .Pp
-The command:
-.Dl pax -rw -i .\ dest_dir
-can be used to interactively select the files to copy from the current
+.Li $ pax -rw -i \&. dest_dir
+.Pp
+Can be used to interactively select the files to copy from the current
 directory to
 .Pa dest_dir .
 .Pp
-The command:
-.Dl pax -r -pe -U root -G bin -f a.pax
-will extract all files from the archive
+.Li "$ pax -r -pe -U root -G bin -f a.pax"
+.Pp
+Extract all files from the archive
 .Pa a.pax
 which are owned by
 .Em root
 with group
 .Em bin
-and will preserve all file permissions.
+and preserve all file permissions.
+.Pp
+.Li "$ pax -r -w -v -Y -Z home /backup"
 .Pp
-The command:
-.Dl pax -r -w -v -Y -Z home /backup
-will update (and list) only those files in the destination directory
+Update (and list) only those files in the destination directory
 .Pa /backup
 which are older (less recent inode change or file modification times) than
 files with the same name found in the source file tree
 .Pa home .
-.Sh STANDARDS
-The
-.Nm
-utility is a superset of the
-.St -p1003.2
-standard.
-The options
-.Fl z ,
-.Fl B ,
-.Fl D ,
-.Fl E ,
-.Fl G ,
-.Fl H ,
-.Fl L ,
-.Fl P ,
-.Fl T ,
-.Fl U ,
-.Fl Y ,
-.Fl Z ,
-the archive formats
-.Ar bcpio ,
-.Ar sv4cpio ,
-.Ar sv4crc ,
-.Ar tar ,
-and the flawed archive handling during
-.Ar list
-and
-.Ar read
-operations are extensions to the
-.Tn POSIX
-standard.
-.Sh SEE ALSO
-.Xr cpio 1 ,
-.Xr tar 1
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Bx 4.4 .
-.Sh AUTHORS
-.An Keith Muller
-at the University of California, San Diego
 .Sh DIAGNOSTICS
-The
-.Nm
-utility will exit with one of the following values:
+.Nm pax
+will exit with one of the following values:
 .Bl -tag -width 2n
 .It 0
 All files were processed successfully.
@@ -1152,41 +1229,79 @@ An error occurred.
 .El
 .Pp
 Whenever
-.Nm
+.Nm pax
 cannot create a file or a link when reading an archive or cannot
 find a file when writing an archive, or cannot preserve the user ID,
 group ID, or file mode when the
 .Fl p
-option is specified, a diagnostic message is written to
-.Dv standard error
+option is specified, a diagnostic message is written to standard error
 and a non-zero exit status will be returned, but processing will continue.
-In the case where pax cannot create a link to a file,
-.Nm
+In the case where
+.Nm pax
+cannot create a link to a file,
+.Nm pax
 will not create a second copy of the file.
 .Pp
 If the extraction of a file from an archive is prematurely terminated by
 a signal or error,
-.Nm
+.Nm pax
 may have only partially extracted a file the user wanted.
 Additionally, the file modes of extracted files and directories
 may have incorrect file bits, and the modification and access times may be
 wrong.
 .Pp
 If the creation of an archive is prematurely terminated by a signal or error,
-.Nm
-may have only partially created the archive which may violate the specific
+.Nm pax
+may have only partially created the archive, which may violate the specific
 archive format specification.
 .Pp
-If while doing a
+If, while doing a
 .Em copy ,
-.Nm
+.Nm pax
 detects a file is about to overwrite itself, the file is not copied,
-a diagnostic message is written to
-.Dv standard error
+a diagnostic message is written to standard error
 and when
-.Nm
+.Nm pax
 completes it will exit with a non-zero exit status.
-.Sh BUGS
+.Sh SEE ALSO
+.Xr cpio 1 ,
+.Xr tar 1
+.Pp
+"Archiving with Pax", Dru Lavigne, ONLamp.com BSD DevCenter,
+http://www.onlamp.com/pub/a/bsd/2002/08/22/FreeBSD_Basics.html
+.Pp
+pax(1) manual page,
+http://heirloom.sourceforge.net/man/pax.1.html
+.Sh STANDARDS
 The
-.Nm
-utility does not recognize multibyte characters.
+.Nm pax
+utility is a superset of the
+.St -p1003.2
+standard.
+The options
+.Fl B ,
+.Fl D ,
+.Fl E ,
+.Fl G ,
+.Fl H ,
+.Fl L ,
+.Fl O ,
+.Fl P ,
+.Fl T ,
+.Fl U ,
+.Fl Y ,
+.Fl Z ,
+the archive formats
+.Ar bcpio ,
+.Ar sv4cpio ,
+.Ar sv4crc ,
+.Ar tar ,
+and the flawed archive handling during
+.Ar list
+and
+.Ar read
+operations are extensions to the
+.Tn POSIX
+standard.
+.Sh AUTHORS
+Keith Muller at the University of California, San Diego.
index 574ed5b43959d15dca2e798fdee50461d901077d..e312833a7ce14a64b8ed5fd60a11a8e1309bc563 100644 (file)
--- a/pax/pax.c
+++ b/pax/pax.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pax.c,v 1.11 1997/09/01 18:29:58 deraadt Exp $        */
+/*     $OpenBSD: pax.c,v 1.27 2004/04/16 22:50:23 deraadt Exp $        */
 /*     $NetBSD: pax.c,v 1.5 1996/03/26 23:54:20 mrg Exp $      */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  */
 
 #ifndef lint
-static char copyright[] __attribute__((__unused__)) =
+static const char copyright[] __attribute__((__unused__)) =
 "@(#) Copyright (c) 1992, 1993\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)pax.c      8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)pax.c        8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pax.c,v 1.11 1997/09/01 18:29:58 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pax.c,v 1.27 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -61,11 +57,14 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: pax.c,v 1.11 1997/0
 #include <signal.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <string.h>
 #include <errno.h>
+#include <err.h>
 #include <fcntl.h>
+#include <paths.h>
 #include "pax.h"
 #include "extern.h"
-static int gen_init __P((void));
+static int gen_init(void);
 
 /*
  * PAX main routines, general globals and some simple start up routines
@@ -86,13 +85,13 @@ int nflag;                  /* select first archive member match */
 int    tflag;                  /* restore access time after read */
 int    uflag;                  /* ignore older modification time files */
 int    vflag;                  /* produce verbose output */
-int    zflag;                  /* use gzip */
 int    Dflag;                  /* same as uflag except inode change time */
 int    Hflag;                  /* follow command line symlinks (write only) */
 int    Lflag;                  /* follow symlinks when writing */
 int    Xflag;                  /* archive files with same device id only */
-int    Yflag;                  /* same as Dflg except after name mode */
-int    Zflag;                  /* same as uflg except after name mode */
+int    Yflag;                  /* same as Dflag except after name mode */
+int    Zflag;                  /* same as uflag except after name mode */
+int    zeroflag;               /* use \0 as pathname terminator */
 int    vfpart;                 /* is partial verbose output in progress */
 int    patime = 1;             /* preserve file access time */
 int    pmtime = 1;             /* preserve file modification times */
@@ -106,11 +105,14 @@ char      *dirptr;                /* destination dir in a copy */
 char   *ltmfrmt;               /* -v locale time format (if any) */
 char   *argv0;                 /* root of argv[0] */
 sigset_t s_mask;               /* signal mask for cleanup critical sect */
+FILE   *listf;                 /* file pointer to print file list to */
+char   *tempfile;              /* tempfile to use for mkstemp(3) */
+char   *tempbase;              /* basename of tempfile to use for mkstemp(3) */
 
 /*
  *     PAX - Portable Archive Interchange
  *
- *     A utility to read, write, and write lists of the members of archive
+ *     A utility to read, write, and write lists of the members of archive
  *     files and copy directory hierarchies. A variety of archive formats
  *     are supported (some are described in POSIX 1003.1 10.1):
  *
@@ -126,7 +128,7 @@ sigset_t s_mask;            /* signal mask for cleanup critical sect */
  *
  * 1   READ ENHANCEMENTS
  * 1.1 Operations which read archives will continue to operate even when
- *     processing archives which may be damaged, truncated, or fail to meet 
+ *     processing archives which may be damaged, truncated, or fail to meet
  *     format specs in several different ways. Damaged sections of archives
  *     are detected and avoided if possible. Attempts will be made to resync
  *     archive read operations even with badly damaged media.
@@ -141,7 +143,7 @@ sigset_t s_mask;            /* signal mask for cleanup critical sect */
  * 1.5 The user is notified whenever something is found during archive
  *     read operations which violates spec (but the read will continue).
  * 1.6 Multiple archive volumes can be read and may span over different
- *     archive devices 
+ *     archive devices
  * 1.7 Rigidly restores all file attributes exactly as they are stored on the
  *     archive.
  * 1.8 Modification change time ranges can be specified via multiple -T
@@ -151,14 +153,14 @@ sigset_t s_mask;          /* signal mask for cleanup critical sect */
  *     -U options.
  * 1.10        Files can be selected based on group (group name or gid) via one o
  *     more -G options.
- * 1.11        File modification time can be checked against exisiting file after
+ * 1.11        File modification time can be checked against existing file after
  *     name modification (-Z)
  *
  * 2   WRITE ENHANCEMENTS
  * 2.1 Write operation will stop instead of allowing a user to create a flawed
  *     flawed archive (due to any problem).
- * 2.2 Archives writtens by pax are forced to strictly conform to both the
- *     archive and pax the spceific format specifications.
+ * 2.2 Archives written by pax are forced to strictly conform to both the
+ *     archive and pax the specific format specifications.
  * 2.3 Blocking size and format is rigidly enforced on writes.
  * 2.4 Formats which may exhibit header overflow problems (they have fields
  *     too small for large file systems, such as inode number storage), use
@@ -167,11 +169,11 @@ sigset_t s_mask;          /* signal mask for cleanup critical sect */
  *     these fields. This removes any restrictions on using these archive
  *     formats on large file systems.
  * 2.5 Multiple archive volumes can be written and may span over different
- *     archive devices 
+ *     archive devices
  * 2.6 A archive volume record limit allows the user to specify the number
  *     of bytes stored on an archive volume. When reached the user is
  *     prompted for the next archive volume. This is specified with the
- *     non-standard -B flag. THe limit is rounded up to the next blocksize.
+ *     non-standard -B flag. The limit is rounded up to the next blocksize.
  * 2.7 All archive padding during write use zero filled sections. This makes
  *     it much easier to pull data out of flawed archive during read
  *     operations.
@@ -206,15 +208,15 @@ sigset_t s_mask;          /* signal mask for cleanup critical sect */
  *     more -G options.
  * 3.8 Symlinks which appear on the command line can be followed (without
  *     following other symlinks; -H flag)
- * 3.9  File inode change time can be checked against exisiting file before
+ * 3.9  File inode change time can be checked against existing file before
  *     name modification (-D)
- * 3.10 File inode change time can be checked against exisiting file after
+ * 3.10 File inode change time can be checked against existing file after
  *     name modification (-Y)
- * 3.11        File modification time can be checked against exisiting file after
+ * 3.11        File modification time can be checked against existing file after
  *     name modification (-Z)
  *
  * 4   GENERAL ENHANCEMENTS
- * 4.1 Internal structure is designed to isolate format dependent and 
+ * 4.1 Internal structure is designed to isolate format dependent and
  *     independent functions. Formats are selected via a format driver table.
  *     This encourages the addition of new archive formats by only having to
  *     write those routines which id, read and write the archive header.
@@ -227,16 +229,16 @@ sigset_t s_mask;          /* signal mask for cleanup critical sect */
  * Return: 0 if ok, 1 otherwise
  */
 
-#ifdef __STDC__
+extern void pax_usage();
+
 int
 main(int argc, char **argv)
-#else
-int
-main(argc, argv)
-       int argc;
-       char **argv;
-#endif
 {
+       char *tmpdir;
+       size_t tdlen;
+
+       if (argc < 1)
+               pax_usage();
        /*
         * Keep a reference to cwd, so we can always come back home.
         */
@@ -246,6 +248,24 @@ main(argc, argv)
                return(exit_val);
        }
 
+       /*
+        * Where should we put temporary files?
+        */
+       if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
+               tmpdir = _PATH_TMP;
+       tdlen = strlen(tmpdir);
+       while (tdlen > 0 && tmpdir[tdlen - 1] == '/')
+               tdlen--;
+       tempfile = malloc(tdlen + 1 + sizeof(_TFILE_BASE));
+       if (tempfile == NULL) {
+               paxwarn(1, "Cannot allocate memory for temp file name.");
+               return(exit_val);
+       }
+       if (tdlen)
+               memcpy(tempfile, tmpdir, tdlen);
+       tempbase = tempfile + tdlen;
+       *tempbase++ = '/';
+
        /*
         * parse options, determine operational mode, general init
         */
@@ -254,9 +274,9 @@ main(argc, argv)
                return(exit_val);
 
        /*
-        * select a primary operation mode 
+        * select a primary operation mode
         */
-       switch(act) {
+       switch (act) {
        case EXTRACT:
                extract();
                break;
@@ -264,6 +284,8 @@ main(argc, argv)
                archive();
                break;
        case APPND:
+               if (gzip_program != NULL)
+                       errx(1, "can not gzip while appending");
                append();
                break;
        case COPY:
@@ -286,15 +308,11 @@ main(argc, argv)
  *     never....
  */
 
-#ifdef __STDC__
 void
 sig_cleanup(int which_sig)
-#else
-void
-sig_cleanup(which_sig)
-       int which_sig;
-#endif
 {
+       /* XXX signal races */
+
        /*
         * restore modes and times for any dirs we may have created
         * or any dirs we may have read. Set vflag and vfpart so the user
@@ -319,13 +337,8 @@ sig_cleanup(which_sig)
  *     when dealing with a medium to large sized archives.
  */
 
-#ifdef __STDC__
 static int
 gen_init(void)
-#else
-static int
-gen_init()
-#endif
 {
        struct rlimit reslimit;
        struct sigaction n_hand;
@@ -368,14 +381,14 @@ gen_init()
        /*
         * Handle posix locale
         *
-        * set user defines time printing format for -v option 
+        * set user defines time printing format for -v option
         */
        ltmfrmt = getenv("LC_TIME");
 
        /*
         * signal handling to reset stored directory times and modes. Since
         * we deal with broken pipes via failed writes we ignore it. We also
-        * deal with any file size limit thorugh failed writes. Cpu time
+        * deal with any file size limit through failed writes. Cpu time
         * limits are caught and a cleanup is forced.
         */
        if ((sigemptyset(&s_mask) < 0) || (sigaddset(&s_mask, SIGTERM) < 0) ||
@@ -385,6 +398,7 @@ gen_init()
                paxwarn(1, "Unable to set up signal mask");
                return(-1);
        }
+       memset(&n_hand, 0, sizeof n_hand);
        n_hand.sa_mask = s_mask;
        n_hand.sa_flags = 0;
        n_hand.sa_handler = sig_cleanup;
index bdf00a47dab19369e2a759b88147468b3bef8c6d..b951b55c09c48bccd84f2e951f80a9bae6a67416 100644 (file)
--- a/pax/pax.h
+++ b/pax/pax.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pax.h,v 1.9 1997/07/23 19:15:58 kstailey Exp $        */
+/*     $OpenBSD: pax.h,v 1.16 2003/10/20 06:22:27 jmc Exp $    */
 /*     $NetBSD: pax.h,v 1.3 1995/03/21 09:07:41 cgd Exp $      */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -52,7 +48,7 @@
                                /* Don't even think of changing this */
 #define DEVBLK         8192    /* default read blksize for devices */
 #define FILEBLK                10240   /* default read blksize for files */
-#define PAXPATHLEN     3072    /* maximium path length for pax. MUST be */
+#define PAXPATHLEN     3072    /* maximum path length for pax. MUST be */
                                /* longer than the system MAXPATHLEN */
 
 /*
@@ -66,7 +62,7 @@
 #define DEFOP          LIST    /* if no flags default is to LIST */
 
 /*
- * Device type of the current archive volume 
+ * Device type of the current archive volume
  */
 #define ISREG          0       /* regular file */
 #define ISCHR          1       /* character device */
 #define ISTAPE         3       /* tape drive */
 #define ISPIPE         4       /* pipe/socket */
 
+/*
+ * Pattern matching structure
+ *
+ * Used to store command line patterns
+ */
+typedef struct pattern {
+       char            *pstr;          /* pattern to match, user supplied */
+       char            *pend;          /* end of a prefix match */
+       char            *chdname;       /* the dir to change to if not NULL.  */
+       int             plen;           /* length of pstr */
+       int             flgs;           /* processing/state flags */
+#define MTCH           0x1             /* pattern has been matched */
+#define DIR_MTCH       0x2             /* pattern matched a directory */
+       struct pattern  *fow;           /* next pattern */
+} PATTERN;
+
+/*
+ * General Archive Structure (used internal to pax)
+ *
+ * This structure is used to pass information about archive members between
+ * the format independent routines and the format specific routines. When
+ * new archive formats are added, they must accept requests and supply info
+ * encoded in a structure of this type. The name fields are declared statically
+ * here, as there is only ONE of these floating around, size is not a major
+ * consideration. Eventually converting the name fields to a dynamic length
+ * may be required if and when the supporting operating system removes all
+ * restrictions on the length of pathnames it will resolve.
+ */
+typedef struct {
+       int nlen;                       /* file name length */
+       char name[PAXPATHLEN+1];        /* file name */
+       int ln_nlen;                    /* link name length */
+       char ln_name[PAXPATHLEN+1];     /* name to link to (if any) */
+       char *org_name;                 /* orig name in file system */
+       PATTERN *pat;                   /* ptr to pattern match (if any) */
+       struct stat sb;                 /* stat buffer see stat(2) */
+       off_t pad;                      /* bytes of padding after file xfer */
+       off_t skip;                     /* bytes of real data after header */
+                                       /* IMPORTANT. The st_size field does */
+                                       /* not always indicate the amount of */
+                                       /* data following the header. */
+       u_long crc;                     /* file crc */
+       int type;                       /* type of file node */
+#define PAX_DIR                1               /* directory */
+#define PAX_CHR                2               /* character device */
+#define PAX_BLK                3               /* block device */
+#define PAX_REG                4               /* regular file */
+#define PAX_SLK                5               /* symbolic link */
+#define PAX_SCK                6               /* socket */
+#define PAX_FIF                7               /* fifo */
+#define PAX_HLK                8               /* hard link */
+#define PAX_HRG                9               /* hard link to a regular file */
+#define PAX_CTG                10              /* high performance file */
+#define PAX_GLL                11              /* GNU long symlink */
+#define PAX_GLF                12              /* GNU long file */
+} ARCHD;
+
 /*
  * Format Specific Routine Table
  *
  * The format specific routine table allows new archive formats to be quickly
  * added. Overall pax operation is independent of the actual format used to
- * form the archive. Only those routines which deal directly with the archive 
- * are tailored to the oddities of the specifc format. All other routines are
+ * form the archive. Only those routines which deal directly with the archive
+ * are tailored to the oddities of the specific format. All other routines are
  * independent of the archive format. Data flow in and out of the format
  * dependent routines pass pointers to ARCHD structure (described below).
  */
@@ -106,17 +159,17 @@ typedef struct {
        int hlk;                /* does archive store hard links info? if */
                                /* not, we do not bother to look for them */
                                /* during archive write operations */
-       int blkalgn;            /* writes must be aligned to blkalgn boundry */
+       int blkalgn;            /* writes must be aligned to blkalgn boundary */
        int inhead;             /* is the trailer encoded in a valid header? */
                                /* if not, trailers are assumed to be found */
                                /* in invalid headers (i.e like tar) */
-       int (*id)();            /* checks if a buffer is a valid header */
-                               /* returns 1 if it is, o.w. returns a 0 */
-       int (*st_rd)();         /* initialize routine for read. so format */
+       int (*id)(char *,       /* checks if a buffer is a valid header */
+           int);               /* returns 1 if it is, o.w. returns a 0 */
+       int (*st_rd)(void);     /* initialize routine for read. so format */
                                /* can set up tables etc before it starts */
                                /* reading an archive */
-       int (*rd)();            /* read header routine. passed a pointer to */
-                               /* ARCHD. It must extract the info from the */
+       int (*rd)(ARCHD *,      /* read header routine. passed a pointer to */
+           char *);            /* ARCHD. It must extract the info from the */
                                /* format and store it in the ARCHD struct. */
                                /* This routine is expected to fill all the */
                                /* fields in the ARCHD (including stat buf) */
@@ -127,12 +180,12 @@ typedef struct {
                                /* padding and the number of bytes of data */
                                /* which follow the header. This info is */
                                /* used skip to the next file header */
-       off_t (*end_rd)();      /* read cleanup. Allows format to clean up */
+       off_t (*end_rd)(void);  /* read cleanup. Allows format to clean up */
                                /* and MUST RETURN THE LENGTH OF THE TRAILER */
                                /* RECORD (so append knows how many bytes */
                                /* to move back to rewrite the trailer) */
-       int (*st_wr)();         /* initialize routine for write operations */
-       int (*wr)();            /* write archive header. Passed an ARCHD */
+       int (*st_wr)(void);     /* initialize routine for write operations */
+       int (*wr)(ARCHD *);     /* write archive header. Passed an ARCHD */
                                /* filled with the specs on the next file to */
                                /* archived. Returns a 1 if no file data is */
                                /* is to be stored; 0 if file data is to be */
@@ -142,78 +195,25 @@ typedef struct {
                                /* the proper padding can be added after */
                                /* file data. This routine must NEVER write */
                                /* a flawed archive header. */
-       int (*end_wr)();        /* end write. write the trailer and do any */
+       int (*end_wr)(void);    /* end write. write the trailer and do any */
                                /* other format specific functions needed */
-                               /* at the ecnd of a archive write */
-       int (*trail)();         /* returns 0 if a valid trailer, -1 if not */
-                               /* For formats which encode the trailer */
-                               /* outside of a valid header, a return value */
+                               /* at the end of an archive write */
+       int (*trail)(ARCHD *,   /* returns 0 if a valid trailer, -1 if not */
+           char *, int,        /* For formats which encode the trailer */
+           int *);             /* outside of a valid header, a return value */
                                /* of 1 indicates that the block passed to */
                                /* it can never contain a valid header (skip */
                                /* this block, no point in looking at it)  */
                                /* CAUTION: parameters to this function are */
                                /* different for trailers inside or outside */
                                /* of headers. See get_head() for details */
-       int (*rd_data)();       /* read/process file data from the archive */
-       int (*wr_data)();       /* write/process file data to the archive */
-       int (*options)();       /* process format specific options (-o) */
+       int (*rd_data)(ARCHD *, /* read/process file data from the archive */
+           int, off_t *);
+       int (*wr_data)(ARCHD *, /* write/process file data to the archive */
+           int, off_t *);
+       int (*options)(void);   /* process format specific options (-o) */
 } FSUB;
 
-/*
- * Pattern matching structure
- *
- * Used to store command line patterns
- */
-typedef struct pattern {
-       char            *pstr;          /* pattern to match, user supplied */
-       char            *pend;          /* end of a prefix match */
-       char            *chdname;       /* the dir to change to if not NULL.  */
-       int             plen;           /* length of pstr */
-       int             flgs;           /* processing/state flags */
-#define MTCH           0x1             /* pattern has been matched */
-#define DIR_MTCH       0x2             /* pattern matched a directory */
-       struct pattern  *fow;           /* next pattern */
-} PATTERN;
-
-/*
- * General Archive Structure (used internal to pax)
- *
- * This structure is used to pass information about archive members between
- * the format independent routines and the format specific routines. When
- * new archive formats are added, they must accept requests and supply info
- * encoded in a structure of this type. The name fields are declared statically
- * here, as there is only ONE of these floating around, size is not a major
- * consideration. Eventually converting the name fields to a dynamic length
- * may be required if and when the supporting operating system removes all
- * restrictions on the length of pathnames it will resolve.
- */
-typedef struct {
-       int nlen;                       /* file name length */
-       char name[PAXPATHLEN+1];        /* file name */
-       int ln_nlen;                    /* link name length */
-       char ln_name[PAXPATHLEN+1];     /* name to link to (if any) */
-       char *org_name;                 /* orig name in file system */
-       PATTERN *pat;                   /* ptr to pattern match (if any) */
-       struct stat sb;                 /* stat buffer see stat(2) */
-       off_t pad;                      /* bytes of padding after file xfer */
-       off_t skip;                     /* bytes of real data after header */
-                                       /* IMPORTANT. The st_size field does */
-                                       /* not always indicate the amount of */
-                                       /* data following the header. */
-       u_long crc;                     /* file crc */
-       int type;                       /* type of file node */
-#define PAX_DIR                1               /* directory */
-#define PAX_CHR                2               /* character device */
-#define PAX_BLK                3               /* block device */
-#define PAX_REG                4               /* regular file */
-#define PAX_SLK                5               /* symbolic link */
-#define PAX_SCK                6               /* socket */
-#define PAX_FIF                7               /* fifo */
-#define PAX_HLK                8               /* hard link */
-#define PAX_HRG                9               /* hard link to a regular file */
-#define PAX_CTG                10              /* high performance file */ 
-} ARCHD;
-
 /*
  * Format Specific Options List
  *
@@ -223,13 +223,18 @@ typedef struct oplist {
        char            *name;          /* option variable name e.g. name= */
        char            *value;         /* value for option variable */
        struct oplist   *fow;           /* next option */
+       int             separator;      /* 2 means := separator; 1 means = separator 
+                                          0 means no separator */
 } OPLIST;
 
+#define SEP_COLONEQ    2
+#define SEP_EQ         1
+#define SEP_NONE       0
 /*
  * General Macros
  */
 #ifndef MIN
-#define               MIN(a,b) (((a)<(b))?(a):(b))
+#define        MIN(a,b) (((a)<(b))?(a):(b))
 #endif
 #define MAJOR(x)       major(x)
 #define MINOR(x)       minor(x)
@@ -238,6 +243,7 @@ typedef struct oplist {
 /*
  * General Defines
  */
-#define HEX    16
-#define OCT    8
-#define _PAX_  1
+#define HEX            16
+#define OCT            8
+#define _PAX_          1
+#define _TFILE_BASE    "paxXXXXXXXXXX"
diff --git a/pax/pax_format.c b/pax/pax_format.c
new file mode 100644 (file)
index 0000000..e98d8a7
--- /dev/null
@@ -0,0 +1,2024 @@
+/*     $OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $   */
+/*     $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $      */
+
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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.
+ */
+
+#ifndef lint
+#if 0
+static const char sccsid[] = "@(#)tar.c        8.2 (Berkeley) 4/18/94";
+#else
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "pax.h"
+#include "extern.h"
+#include "tar.h"
+#include <fnmatch.h>
+#include <regex.h>
+#include "pat_rep.h"
+#include <errno.h>
+
+/* 
+ * This file implements the -x pax format support; it is incomplete.
+ * Known missing features include:
+ *     many -o options for "copy" mode are not implemented (only path=)
+ *     many format specifiers for -o listopt are not implemented
+ *     -o listopt option should work for all archive formats, not just -x pax
+ * This file was originally derived from the file tar.c. You should
+ * 'diff' it to that file to see how much of the -x pax format has been implemented.
+ */
+
+char pax_eh_datablk[4*1024];
+int pax_read_or_list_mode = 0;
+int want_a_m_time_headers = 0;
+int want_linkdata = 0;
+
+int pax_invalid_action = 0;
+char * pax_invalid_action_write_path = NULL;
+char * pax_invalid_action_write_cwd = NULL;
+
+char
+       *path_g,        *path_x,        *path_g_current,        *path_x_current,
+       *uname_g,       *uname_x,       *uname_g_current,       *uname_x_current,
+       *gname_g,       *gname_x,       *gname_g_current,       *gname_x_current,
+       *comment_g,     *comment_x,     *comment_g_current,     *comment_x_current,
+       *charset_g,     *charset_x,     *charset_g_current,     *charset_x_current,
+       *atime_g,       *atime_x,       *atime_g_current,       *atime_x_current,
+       *gid_g,         *gid_x,         *gid_g_current,         *gid_x_current,
+       *linkpath_g,    *linkpath_x,    *linkpath_g_current,    *linkpath_x_current,
+       *mtime_g,       *mtime_x,       *mtime_g_current,       *mtime_x_current,
+       *size_g,        *size_x,        *size_g_current,        *size_x_current,
+       *uid_g,         *uid_x,         *uid_g_current,         *uid_x_current;
+
+char   *header_name_g_requested = NULL,
+       *header_name_x_requested = NULL;
+
+char   *header_name_g = "/tmp/GlobalHead.%p.%n",
+       *header_name_x = "%d/PaxHeaders.%p/%f";
+
+int    nglobal_headers = 0;
+char   *pax_list_opt_format;
+
+#define O_OPTION_ACTION_NOTIMPL                0
+#define O_OPTION_ACTION_INVALID                1
+#define O_OPTION_ACTION_DELETE         2
+#define O_OPTION_ACTION_STORE_HEADER   3
+#define O_OPTION_ACTION_TIMES          4
+#define O_OPTION_ACTION_HEADER_NAME    5
+#define O_OPTION_ACTION_LISTOPT                6
+#define O_OPTION_ACTION_LINKDATA       7
+
+#define O_OPTION_ACTION_IGNORE         8
+#define O_OPTION_ACTION_ERROR          9
+#define O_OPTION_ACTION_STORE_HEADER2  10
+
+#define ATTRSRC_FROM_NOWHERE           0
+#define ATTRSRC_FROM_X_O_OPTION                1
+#define ATTRSRC_FROM_G_O_OPTION                2
+#define ATTRSRC_FROM_X_HEADER          3
+#define ATTRSRC_FROM_G_HEADER          4
+
+#define KW_PATH_CASE   0
+#define KW_SKIP_CASE   -1
+
+typedef struct {
+       char *  name;
+       int     len;
+       int     active;                 /* 1 means active, 0 means deleted via -o delete=               */
+       int     cmdline_action;
+       int     header_action;
+       /* next 2 entries only used by store_header actions                                             */
+       char ** g_value;                /* -o keyword= value                                            */
+       char ** x_value;                /* -o keyword:= value                                           */
+       char ** g_value_current;        /* keyword= value found in Global extended header               */
+       char ** x_value_current;        /* keyword= value found in extended header                      */
+       int     header_inx;             /* starting index of header field this keyword represents       */
+       int     header_len;             /* length of header field this keyword represents               */
+                                       /* If negative, special cases line path=                        */
+} O_OPTION_TYPE;
+
+O_OPTION_TYPE o_option_table[] = {
+       { "atime",      5,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
+       &atime_g,       &atime_x,       &atime_g_current,       &atime_x_current,       0,      KW_SKIP_CASE    },
+       { "charset",    7,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
+       &charset_g,     &charset_x,     &charset_g_current,     &charset_x_current,     0,      KW_SKIP_CASE    },
+       { "comment",    7,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
+       &comment_g,     &comment_x,     &comment_g_current,     &comment_x_current,     0,      KW_SKIP_CASE    },
+       { "gid",        3,      1,      O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
+       &gid_g,         &gid_x,         &gid_g_current,         &gid_x_current  ,       116,    8               },
+       { "gname",      5,      1,      O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
+       &gname_g,       &gname_x,       &gname_g_current,       &gname_x_current,       297,    32              },
+       { "linkpath",   8,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
+       &linkpath_g,    &linkpath_x,    &linkpath_g_current,    &linkpath_x_current,    0,      KW_SKIP_CASE    },
+       { "mtime",      5,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
+       &mtime_g,       &mtime_x,       &mtime_g_current,       &mtime_x_current,       136,    KW_SKIP_CASE    },
+       { "path",       4,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
+       &path_g,        &path_x,        &path_g_current,        &path_x_current,        0,      KW_PATH_CASE    },
+       { "size",       4,      1,      O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
+       &size_g,        &size_x,        &size_g_current,        &size_x_current,        124,    KW_SKIP_CASE    },
+       { "uid",        3,      1,      O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
+       &uid_g,         &uid_x,         &uid_g_current,         &uid_x_current,         108,    8               },
+       { "uname",      5,      1,      O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
+       &uname_g,       &uname_x,       &uname_g_current,       &uname_x_current,       265,    32              },
+
+       { "exthdr.name",  11,   1,      O_OPTION_ACTION_HEADER_NAME,    O_OPTION_ACTION_ERROR,
+       &header_name_x, &header_name_x_requested,       NULL,   NULL,   0,      KW_SKIP_CASE    },
+       { "globexthdr.name", 15, 1,     O_OPTION_ACTION_HEADER_NAME,    O_OPTION_ACTION_ERROR,
+       &header_name_g, &header_name_g_requested,       NULL,   NULL,   0,      KW_SKIP_CASE    },
+
+       { "delete",     6,      1,      O_OPTION_ACTION_DELETE,  O_OPTION_ACTION_ERROR, 
+       NULL,           NULL,           NULL,                   NULL,   0,      KW_SKIP_CASE    },
+       { "invalid",    7,      1,      O_OPTION_ACTION_INVALID,         O_OPTION_ACTION_ERROR, 
+       NULL,           NULL,           NULL,                   NULL,   0,      KW_SKIP_CASE    },
+       { "linkdata",   8,      1,      O_OPTION_ACTION_LINKDATA,        O_OPTION_ACTION_ERROR,
+       NULL,           NULL,           NULL,                   NULL,   0,      KW_SKIP_CASE    }, /* Test 241 */
+       { "listopt",    7,      1,      O_OPTION_ACTION_LISTOPT,         O_OPTION_ACTION_ERROR,
+       &pax_list_opt_format, NULL,     NULL,                   NULL,   0,      KW_SKIP_CASE    }, /* Test 242 */
+               /* Note: listopt is supposed to apply for all formats, not just -x pax only     */
+       { "times",      5,      1,      O_OPTION_ACTION_TIMES,   O_OPTION_ACTION_ERROR,
+       NULL,           NULL,           NULL,                   NULL,   0,      KW_SKIP_CASE    },
+};
+
+int ext_header_inx,
+    global_ext_header_inx;
+
+/* Make these tables big enough to handle lots of -o options, not just one per table entry */
+int ext_header_entry       [4*sizeof(o_option_table)/sizeof(O_OPTION_TYPE)],
+    global_ext_header_entry[4*sizeof(o_option_table)/sizeof(O_OPTION_TYPE)];
+
+/*
+ * Routines for reading, writing and header identify of various versions of pax
+ */
+
+static size_t expandname(char *, size_t, char **, const char *, size_t);
+static u_long pax_chksm(char *, int);
+char *name_split(char *, int);
+static int ul_oct(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+static int uqd_oct(u_quad_t, char *, int, int);
+#endif
+
+static uid_t uid_nobody;
+static uid_t uid_warn;
+static gid_t gid_nobody;
+static gid_t gid_warn;
+
+/*
+ * Routines common to all versions of pax
+ */
+
+#if 0
+static int tar_nodir;                  /* do not write dirs under old tar */
+char *gnu_name_string;                 /* GNU ././@LongLink hackery name */
+char *gnu_link_string;                 /* GNU ././@LongLink hackery link */
+
+/*
+ * tar_endwr()
+ *     add the tar trailer of two null blocks
+ * Return:
+ *     0 if ok, -1 otherwise (what wr_skip returns)
+ */
+
+int
+tar_endwr(void)
+{
+       return(wr_skip((off_t)(NULLCNT*BLKMULT)));
+}
+
+/*
+ * tar_endrd()
+ *     no cleanup needed here, just return size of trailer (for append)
+ * Return:
+ *     size of trailer (2 * BLKMULT)
+ */
+
+off_t
+tar_endrd(void)
+{
+       return((off_t)(NULLCNT*BLKMULT));
+}
+
+/*
+ * tar_trail()
+ *     Called to determine if a header block is a valid trailer. We are passed
+ *     the block, the in_sync flag (which tells us we are in resync mode;
+ *     looking for a valid header), and cnt (which starts at zero) which is
+ *     used to count the number of empty blocks we have seen so far.
+ * Return:
+ *     0 if a valid trailer, -1 if not a valid trailer, or 1 if the block
+ *     could never contain a header.
+ */
+
+int
+tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt)
+{
+       int i;
+
+       /*
+        * look for all zero, trailer is two consecutive blocks of zero
+        */
+       for (i = 0; i < BLKMULT; ++i) {
+               if (buf[i] != '\0')
+                       break;
+       }
+
+       /*
+        * if not all zero it is not a trailer, but MIGHT be a header.
+        */
+       if (i != BLKMULT)
+               return(-1);
+
+       /*
+        * When given a zero block, we must be careful!
+        * If we are not in resync mode, check for the trailer. Have to watch
+        * out that we do not mis-identify file data as the trailer, so we do
+        * NOT try to id a trailer during resync mode. During resync mode we
+        * might as well throw this block out since a valid header can NEVER be
+        * a block of all 0 (we must have a valid file name).
+        */
+       if (!in_resync && (++*cnt >= NULLCNT))
+               return(0);
+       return(1);
+}
+#endif
+
+/*
+ * ul_oct()
+ *     convert an unsigned long to an octal string. many oddball field
+ *     termination characters are used by the various versions of tar in the
+ *     different fields. term selects which kind to use. str is '0' padded
+ *     at the front to len. we are unable to use only one format as many old
+ *     tar readers are very cranky about this.
+ * Return:
+ *     0 if the number fit into the string, -1 otherwise
+ */
+
+static int
+ul_oct(u_long val, char *str, int len, int term)
+{
+       char *pt;
+
+       /*
+        * term selects the appropriate character(s) for the end of the string
+        */
+       pt = str + len - 1;
+       switch (term) {
+       case 3:
+               *pt-- = '\0';
+               break;
+       case 2:
+               *pt-- = ' ';
+               *pt-- = '\0';
+               break;
+       case 1:
+               *pt-- = ' ';
+               break;
+       case 0:
+       default:
+               *pt-- = '\0';
+               *pt-- = ' ';
+               break;
+       }
+
+       /*
+        * convert and blank pad if there is space
+        */
+       while (pt >= str) {
+               *pt-- = '0' + (char)(val & 0x7);
+               if ((val = val >> 3) == (u_long)0)
+                       break;
+       }
+
+       while (pt >= str)
+               *pt-- = '0';
+       if (val != (u_long)0)
+               return(-1);
+       return(0);
+}
+
+#ifndef LONG_OFF_T
+/*
+ * uqd_oct()
+ *     convert an u_quad_t to an octal string. one of many oddball field
+ *     termination characters are used by the various versions of tar in the
+ *     different fields. term selects which kind to use. str is '0' padded
+ *     at the front to len. we are unable to use only one format as many old
+ *     tar readers are very cranky about this.
+ * Return:
+ *     0 if the number fit into the string, -1 otherwise
+ */
+
+static int
+uqd_oct(u_quad_t val, char *str, int len, int term)
+{
+       char *pt;
+
+       /*
+        * term selects the appropriate character(s) for the end of the string
+        */
+       pt = str + len - 1;
+       switch (term) {
+       case 3:
+               *pt-- = '\0';
+               break;
+       case 2:
+               *pt-- = ' ';
+               *pt-- = '\0';
+               break;
+       case 1:
+               *pt-- = ' ';
+               break;
+       case 0:
+       default:
+               *pt-- = '\0';
+               *pt-- = ' ';
+               break;
+       }
+
+       /*
+        * convert and blank pad if there is space
+        */
+       while (pt >= str) {
+               *pt-- = '0' + (char)(val & 0x7);
+               if ((val = val >> 3) == 0)
+                       break;
+       }
+
+       while (pt >= str)
+               *pt-- = '0';
+       if (val != (u_quad_t)0)
+               return(-1);
+       return(0);
+}
+#endif
+
+/*
+ * pax_chksm()
+ *     calculate the checksum for a pax block counting the checksum field as
+ *     all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
+ *     NOTE: we use len to short circuit summing 0's on write since we ALWAYS
+ *     pad headers with 0.
+ * Return:
+ *     unsigned long checksum
+ */
+
+static u_long
+pax_chksm(char *blk, int len)
+{
+       char *stop;
+       char *pt;
+       u_long chksm = BLNKSUM; /* initial value is checksum field sum */
+
+       /*
+        * add the part of the block before the checksum field
+        */
+       pt = blk;
+       stop = blk + CHK_OFFSET;
+       while (pt < stop)
+               chksm += (u_long)(*pt++ & 0xff);
+       /*
+        * move past the checksum field and keep going, spec counts the
+        * checksum field as the sum of 8 blanks (which is pre-computed as
+        * BLNKSUM).
+        * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
+        * starts, no point in summing zero's)
+        */
+       pt += CHK_LEN;
+       stop = blk + len;
+       while (pt < stop)
+               chksm += (u_long)(*pt++ & 0xff);
+       return(chksm);
+}
+
+#if 0
+/*
+ * Routines for old BSD style tar (also made portable to sysV tar)
+ */
+
+/* pax_id must be derived from ustar, NOT tar */
+/*
+ * tar_id()
+ *     determine if a block given to us is a valid tar header (and not a USTAR
+ *     header). We have to be on the lookout for those pesky blocks of all
+ *     zero's.
+ * Return:
+ *     0 if a tar header, -1 otherwise
+ */
+
+int
+tar_id(char *blk, int size)
+{
+       HD_TAR *hd;
+       HD_USTAR *uhd;
+
+       if (size < BLKMULT)
+               return(-1);
+       hd = (HD_TAR *)blk;
+       uhd = (HD_USTAR *)blk;
+
+       /*
+        * check for block of zero's first, a simple and fast test, then make
+        * sure this is not a ustar header by looking for the ustar magic
+        * cookie. We should use TMAGLEN, but some USTAR archive programs are
+        * wrong and create archives missing the \0. Last we check the
+        * checksum. If this is ok we have to assume it is a valid header.
+        */
+       if (hd->name[0] == '\0')
+               return(-1);
+       if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0)
+               return(-1);
+       if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
+               return(-1);
+       force_one_volume = 1;
+       return(0);
+}
+#endif
+
+void
+pax_format_list_output(ARCHD *arcn, time_t now, FILE *fp, int term)
+{
+       /* parse specified listopt format */
+       char *nextpercent, *nextchar;
+       char buf[4*1024];
+       int pos, cpylen;
+       char *fname;
+
+       nextpercent = strchr(pax_list_opt_format,'%');
+       if (nextpercent==NULL) {
+               /* Strange case: no specifiers? */
+               safe_print(pax_list_opt_format, fp);
+               (void)putc(term, fp);
+               (void)fflush(fp);
+               return;
+       }
+       pos = nextpercent-pax_list_opt_format;
+       memcpy(buf,pax_list_opt_format, pos);
+       while (nextpercent++) {
+               switch (*nextpercent) {
+               case 'F':
+                       fname = arcn->name;
+                       cpylen = strlen(fname);
+                       memcpy(&buf[pos],fname,cpylen);
+                       pos+= cpylen;
+                       break;
+               case 'D':
+               case 'T':
+               case 'M':
+               case 'L':
+               default:
+                       paxwarn(1, "Unimplemented listopt format: %c",*nextpercent);
+                       break;
+               }
+               nextpercent++;
+               if (*nextpercent=='\0') {
+                       break;
+               }
+               nextchar = nextpercent;
+               nextpercent = strchr(nextpercent,'%');
+               if (nextpercent==NULL) {
+                       cpylen = strlen(nextchar);
+               } else {
+                       cpylen = nextpercent - nextchar;
+               }
+               memcpy(&buf[pos],nextchar, cpylen);
+               pos += cpylen;
+       }
+       buf[pos]='\0';
+       safe_print(&buf[0], fp);
+       (void)putc(term, fp);
+       (void)fflush(fp);
+       return;
+}
+
+void
+cleanup_pax_invalid_action()
+{
+       switch (pax_invalid_action) {
+       case PAX_INVALID_ACTION_BYPASS:
+       case PAX_INVALID_ACTION_RENAME:
+               break;
+       case PAX_INVALID_ACTION_WRITE:
+               pax_invalid_action_write_path = NULL;
+               if (pax_invalid_action_write_cwd) {
+                       free(pax_invalid_action_write_cwd);
+                       pax_invalid_action_write_cwd = NULL;
+               }
+               break;
+       case PAX_INVALID_ACTION_UTF8:
+       default:
+               paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
+       }
+}
+
+void
+record_pax_invalid_action_results(ARCHD * arcn, char * fixed_path)
+{
+       switch (pax_invalid_action) {
+       case PAX_INVALID_ACTION_BYPASS:
+       case PAX_INVALID_ACTION_RENAME:
+               break;
+       case PAX_INVALID_ACTION_WRITE:
+               pax_invalid_action_write_path = fixed_path;
+               pax_invalid_action_write_cwd  = strdup(arcn->name);
+               pax_invalid_action_write_cwd[fixed_path-arcn->name-1] = '\0';
+               break;
+       case PAX_INVALID_ACTION_UTF8:
+       default:
+               paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
+       }
+}
+
+int
+perform_pax_invalid_action(ARCHD * arcn, int err)
+{
+       int rc = 0;
+       switch (pax_invalid_action) {
+       case PAX_INVALID_ACTION_BYPASS:
+               rc = -1;
+               break;
+       case PAX_INVALID_ACTION_RENAME:
+               rc = tty_rename(arcn);
+               break;
+       case PAX_INVALID_ACTION_WRITE:
+               pax_invalid_action_write_path = NULL;
+               pax_invalid_action_write_cwd = NULL;
+               rc = 2;
+               break;
+       case PAX_INVALID_ACTION_UTF8:
+       default:
+               paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
+               rc = -1;        /* do nothing? */
+       }
+       return rc;
+}
+
+void
+delete_keywords(char * pattern)
+{
+       int i;
+       /* loop over all keywords, marking any matched as deleted */
+       for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
+               if (fnmatch(pattern, o_option_table[i].name, 0) == 0) {
+                       /* Found option: mark deleted */
+                       o_option_table[i].active = 0;
+               }
+       }
+}
+
+/*
+ * pax_opt()
+ *     handle pax format specific -o options
+ * Return:
+ *     0 if ok -1 otherwise
+ */
+
+int
+pax_opt(void)
+{
+       OPLIST *opt;
+       int got_option = 0;
+
+       while ((opt = opt_next()) != NULL) {
+               int i;
+               got_option = -1;
+               pax_invalid_action = PAX_INVALID_ACTION_BYPASS; /* Default for pax format */
+               /* look up opt->name */
+               for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
+                       if (strncasecmp(opt->name, o_option_table[i].name, o_option_table[i].len) == 0) {
+                               /* Found option: see if already set */
+                               /* Save it away */
+                               got_option = 1;
+                               switch (o_option_table[i].cmdline_action) {
+                               case O_OPTION_ACTION_INVALID:
+                                       if (opt->separator != SEP_EQ) {
+                                               paxwarn(1,"-o %s= option requires '=' separator: option ignored",
+                                                               opt->name);
+                                               break;
+                                       }
+                                       if (opt->value) {
+                                               if (strncasecmp(opt->value,"bypass",6) == 0) {
+                                                       pax_invalid_action = PAX_INVALID_ACTION_BYPASS;
+                                               } else if (strncasecmp(opt->value,"rename",6) == 0) {
+                                                       pax_invalid_action = PAX_INVALID_ACTION_RENAME;
+                                               } else if (strncasecmp(opt->value,"UTF-8",5) == 0) {
+                                                       pax_invalid_action = PAX_INVALID_ACTION_UTF8;
+                                               } else if (strncasecmp(opt->value,"write",5) == 0) {
+                                                       pax_invalid_action = PAX_INVALID_ACTION_WRITE;
+                                               } else {
+                                                       paxwarn(1,"Invalid action %s not recognized: option ignored",
+                                                               opt->value);
+                                               }
+                                       } else {
+                                               paxwarn(1,"Invalid action RHS not specified: option ignored");
+                                       }
+                                       break;
+                               case O_OPTION_ACTION_DELETE:
+                                       if (opt->separator != SEP_EQ) {
+                                               paxwarn(1,"-o %s= option requires '=' separator: option ignored",
+                                                               opt->name);
+                                               break;
+                                       }
+                                       /* Mark all matches as deleted */
+                                       /* can have multiple -o delete= patterns */
+                                       delete_keywords(opt->value);
+                                       break;
+                               case O_OPTION_ACTION_STORE_HEADER2:
+                                       if(pax_read_or_list_mode) pids = 1;     /* Force -p o for these options */
+                               case O_OPTION_ACTION_STORE_HEADER:
+                                       if (o_option_table[i].g_value == NULL || 
+                                           o_option_table[i].x_value == NULL ) {
+                                               paxwarn(1,"-o option not implemented: %s=%s",
+                                                               opt->name, opt->value);
+                                       } else {
+                                               if (opt->separator == SEP_EQ) {
+                                                       *(o_option_table[i].g_value) = opt->value;
+                                                       global_ext_header_entry[global_ext_header_inx++] = i;
+                                               } else if (opt->separator == SEP_COLONEQ ) { 
+                                                       *(o_option_table[i].x_value) = opt->value;
+                                                       ext_header_entry       [ext_header_inx++] = i;
+                                               } else {        /* SEP_NONE */
+                                                       paxwarn(1,"-o %s option is missing value", opt->name);
+                                               }
+                                       }
+                                       break;
+                               case O_OPTION_ACTION_TIMES:
+                                       if (opt->separator != SEP_NONE) {
+                                               paxwarn(1,"-o %s option takes no value: option ignored", opt->name);
+                                               break;
+                                       }
+                                       want_a_m_time_headers = 1;
+                                       break;
+                               case O_OPTION_ACTION_LINKDATA:
+                                       if (opt->separator != SEP_NONE) {
+                                               paxwarn(1,"-o %s option takes no value: option ignored", opt->name);
+                                               break;
+                                       }
+                                       want_linkdata = 1;
+                                       break;
+                               case O_OPTION_ACTION_HEADER_NAME:
+                                       if (opt->separator != SEP_EQ) {
+                                               paxwarn(1,"-o %s= option requires '=' separator: option ignored",
+                                                               opt->name);
+                                               break;
+                                       }
+                                       *(o_option_table[i].g_value) = opt->value;
+                                       *(o_option_table[i].x_value) = "YES";
+                                       break;
+                               case O_OPTION_ACTION_LISTOPT:
+                                       if (opt->separator != SEP_EQ) {
+                                               paxwarn(1,"-o %s= option requires '=' separator: option ignored",
+                                                               opt->name);
+                                               break;
+                                       }
+                                       *(o_option_table[i].g_value) = opt->value;
+                                       break;
+                               case O_OPTION_ACTION_NOTIMPL:
+                               default:
+                                       paxwarn(1,"pax format -o option not yet implemented: %s=%s",
+                                                   opt->name, opt->value);
+                                       break;
+                               }
+                               break;
+                       }
+               }
+               if (got_option == -1) {
+                       paxwarn(1,"pax format -o option not recognized: %s=%s",
+                           opt->name, opt->value);
+               }
+       }
+       return(0);
+}
+
+
+#if 0
+/* pax_rd is derived from ustar_rd NOT tar_rd */
+/*
+ * tar_rd()
+ *     extract the values out of block already determined to be a tar header.
+ *     store the values in the ARCHD parameter.
+ * Return:
+ *     0
+ */
+
+int
+tar_rd(ARCHD *arcn, char *buf)
+{
+       HD_TAR *hd;
+       char *pt;
+
+       /*
+        * we only get proper sized buffers passed to us
+        */
+       if (tar_id(buf, BLKMULT) < 0)
+               return(-1);
+       memset(arcn, 0, sizeof(*arcn));
+       arcn->org_name = arcn->name;
+       arcn->sb.st_nlink = 1;
+
+       /*
+        * copy out the name and values in the stat buffer
+        */
+       hd = (HD_TAR *)buf;
+       if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
+               arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
+                   &gnu_name_string, hd->name, sizeof(hd->name));
+               arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                   &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+       }
+       arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
+           0xfff);
+       arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
+       arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
+       arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
+       arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+
+       /*
+        * have to look at the last character, it may be a '/' and that is used
+        * to encode this as a directory
+        */
+       pt = &(arcn->name[arcn->nlen - 1]);
+       arcn->pad = 0;
+       arcn->skip = 0;
+       switch (hd->linkflag) {
+       case SYMTYPE:
+               /*
+                * symbolic link, need to get the link name and set the type in
+                * the st_mode so -v printing will look correct.
+                */
+               arcn->type = PAX_SLK;
+               arcn->sb.st_mode |= S_IFLNK;
+               break;
+       case LNKTYPE:
+               /*
+                * hard link, need to get the link name, set the type in the
+                * st_mode and st_nlink so -v printing will look better.
+                */
+               arcn->type = PAX_HLK;
+               arcn->sb.st_nlink = 2;
+
+               /*
+                * no idea of what type this thing really points at, but
+                * we set something for printing only.
+                */
+               arcn->sb.st_mode |= S_IFREG;
+               break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
+               /*
+                * GNU long link/file; we tag these here and let the
+                * pax internals deal with it -- too ugly otherwise.
+                */
+               arcn->type =
+                   hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
+               break;
+       case DIRTYPE:
+               /*
+                * It is a directory, set the mode for -v printing
+                */
+               arcn->type = PAX_DIR;
+               arcn->sb.st_mode |= S_IFDIR;
+               arcn->sb.st_nlink = 2;
+               break;
+       case AREGTYPE:
+       case REGTYPE:
+       default:
+               /*
+                * If we have a trailing / this is a directory and NOT a file.
+                */
+               arcn->ln_name[0] = '\0';
+               arcn->ln_nlen = 0;
+               if (*pt == '/') {
+                       /*
+                        * it is a directory, set the mode for -v printing
+                        */
+                       arcn->type = PAX_DIR;
+                       arcn->sb.st_mode |= S_IFDIR;
+                       arcn->sb.st_nlink = 2;
+               } else {
+                       /*
+                        * have a file that will be followed by data. Set the
+                        * skip value to the size field and calculate the size
+                        * of the padding.
+                        */
+                       arcn->type = PAX_REG;
+                       arcn->sb.st_mode |= S_IFREG;
+                       arcn->pad = TAR_PAD(arcn->sb.st_size);
+                       arcn->skip = arcn->sb.st_size;
+               }
+               break;
+       }
+
+       /*
+        * strip off any trailing slash.
+        */
+       if (*pt == '/') {
+               *pt = '\0';
+               --arcn->nlen;
+       }
+       return(0);
+}
+
+/* pax_wr is derived from ustar_wr NOT tar_wr */
+/*
+ * tar_wr()
+ *     write a tar header for the file specified in the ARCHD to the archive.
+ *     Have to check for file types that cannot be stored and file names that
+ *     are too long. Be careful of the term (last arg) to ul_oct, each field
+ *     of tar has it own spec for the termination character(s).
+ *     ASSUMED: space after header in header block is zero filled
+ * Return:
+ *     0 if file has data to be written after the header, 1 if file has NO
+ *     data to write after the header, -1 if archive write failed
+ */
+
+int
+tar_wr(ARCHD *arcn)
+{
+       HD_TAR *hd;
+       int len;
+       char hdblk[sizeof(HD_TAR)];
+
+       /*
+        * check for those file system types which tar cannot store
+        */
+       switch (arcn->type) {
+       case PAX_DIR:
+               /*
+                * user asked that dirs not be written to the archive
+                */
+               if (tar_nodir)
+                       return(1);
+               break;
+       case PAX_CHR:
+               paxwarn(1, "Tar cannot archive a character device %s",
+                   arcn->org_name);
+               return(1);
+       case PAX_BLK:
+               paxwarn(1, "Tar cannot archive a block device %s", arcn->org_name);
+               return(1);
+       case PAX_SCK:
+               paxwarn(1, "Tar cannot archive a socket %s", arcn->org_name);
+               return(1);
+       case PAX_FIF:
+               paxwarn(1, "Tar cannot archive a fifo %s", arcn->org_name);
+               return(1);
+       case PAX_SLK:
+       case PAX_HLK:
+       case PAX_HRG:
+               if (arcn->ln_nlen > sizeof(hd->linkname)) {
+                       paxwarn(1,"Link name too long for tar %s", arcn->ln_name);
+                       return(1);
+               }
+               break;
+       case PAX_REG:
+       case PAX_CTG:
+       default:
+               break;
+       }
+
+       /*
+        * check file name len, remember extra char for dirs (the / at the end)
+        */
+       len = arcn->nlen;
+       if (arcn->type == PAX_DIR)
+               ++len;
+       if (len >= sizeof(hd->name)) {
+               paxwarn(1, "File name too long for tar %s", arcn->name);
+               return(1);
+       }
+
+       /*
+        * Copy the data out of the ARCHD into the tar header based on the type
+        * of the file. Remember, many tar readers want all fields to be
+        * padded with zero so we zero the header first.  We then set the
+        * linkflag field (type), the linkname, the size, and set the padding
+        * (if any) to be added after the file data (0 for all other types,
+        * as they only have a header).
+        */
+       memset(hdblk, 0, sizeof(hdblk));
+       hd = (HD_TAR *)hdblk;
+       strlcpy(hd->name, arcn->name, sizeof(hd->name));
+       arcn->pad = 0;
+
+       if (arcn->type == PAX_DIR) {
+               /*
+                * directories are the same as files, except have a filename
+                * that ends with a /, we add the slash here. No data follows
+                * dirs, so no pad.
+                */
+               hd->linkflag = AREGTYPE;
+               hd->name[len-1] = '/';
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+                       goto out;
+       } else if (arcn->type == PAX_SLK) {
+               /*
+                * no data follows this file, so no pad
+                */
+               hd->linkflag = SYMTYPE;
+               strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+                       goto out;
+       } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
+               /*
+                * no data follows this file, so no pad
+                */
+               hd->linkflag = LNKTYPE;
+               strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
+                       goto out;
+       } else {
+               /*
+                * data follows this file, so set the pad
+                */
+               hd->linkflag = AREGTYPE;
+#              ifdef LONG_OFF_T
+               if (ul_oct((u_long)arcn->sb.st_size, hd->size,
+                   sizeof(hd->size), 1)) {
+#              else
+               if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
+                   sizeof(hd->size), 1)) {
+#              endif
+                       paxwarn(1,"File is too large for tar %s", arcn->org_name);
+                       return(1);
+               }
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+       }
+
+       /*
+        * copy those fields that are independent of the type
+        */
+       if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) ||
+           ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) ||
+           ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) ||
+           ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1))
+               goto out;
+
+       /*
+        * calculate and add the checksum, then write the header. A return of
+        * 0 tells the caller to now write the file data, 1 says no data needs
+        * to be written
+        */
+       if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum,
+           sizeof(hd->chksum), 3))
+               goto out;
+       if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0)
+               return(-1);
+       if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0)
+               return(-1);
+       if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
+               return(0);
+       return(1);
+
+    out:
+       /*
+        * header field is out of range
+        */
+       paxwarn(1, "Tar header field is too small for %s", arcn->org_name);
+       return(1);
+}
+#endif
+
+#if 0
+/*
+ * Routines for POSIX ustar
+ */
+
+/*
+ * ustar_strd()
+ *     initialization for ustar read
+ * Return:
+ *     0 if ok, -1 otherwise
+ */
+
+int
+ustar_strd(void)
+{
+       if ((usrtb_start() < 0) || (grptb_start() < 0))
+               return(-1);
+       return(0);
+}
+
+/*
+ * ustar_stwr()
+ *     initialization for ustar write
+ * Return:
+ *     0 if ok, -1 otherwise
+ */
+
+int
+ustar_stwr(void)
+{
+       if ((uidtb_start() < 0) || (gidtb_start() < 0))
+               return(-1);
+       return(0);
+}
+#endif
+
+int
+expand_extended_headers(ARCHD *arcn, HD_USTAR *hd)
+{
+       char mybuf[BLKMULT];
+       HD_USTAR *myhd;
+       char * current_value;
+       int path_replaced = 0;
+       int i, len;
+
+       myhd = hd;
+       while (myhd->typeflag == PAXGTYPE ||  myhd->typeflag == PAXXTYPE) {
+               char *name, *str;
+               int size, nbytes, inx;
+               size = asc_ul(myhd->size, sizeof(myhd->size), OCT);
+               if (size > sizeof(mybuf))
+                       paxwarn(1,"extended header buffer overflow");
+               nbytes = rd_wrbuf(mybuf, size);
+               if (nbytes != size) {
+                       paxwarn(1,"extended header data read failure: nbytes=%d, size=%d\n",
+                               nbytes, size);
+               }
+               /*
+               printf("Read 1 extended header: type=%c, size=%d\n",
+                               myhd->typeflag, size);
+               */
+               inx=0;
+               /* loop over buffer collecting attributes  */
+               while (nbytes > 0) {
+                       int got_option = -1;
+                       int nentries = sscanf(&mybuf[inx],"%d ", &len);
+                       if (nentries != 1) {
+                               paxwarn(1,"Extended header failure: length");
+                       }
+                       if (mybuf[inx+len-1] != '\n')
+                               paxwarn(1,"Extended header failure: missed newline");
+                       else mybuf[inx+len-1] = '\0';
+                       name = strchr(&mybuf[inx],' ');
+                       if (name) name++;
+                       else 
+                               paxwarn(1,"Extended header failure: missing space");
+                       str = strchr(name,'=');
+                       if (str) {
+                               *str++='\0'; /* end of name */
+                       } else
+                               paxwarn(1,"Extended header failure: missing RHS string");
+                       for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
+                               if (strncasecmp(name, o_option_table[i].name, o_option_table[i].len) == 0) {
+                                       /* Found option: see if already set TBD */
+                                       /* Save it away */
+                                       got_option = i;
+                                       break;
+                               }
+                       }
+                       if (got_option == -1) {
+                               paxwarn(1,"Unrecognized header keyword: %s",name);
+                       } else {
+                               /* Determine precedence of -o and header attributes */
+                               int found_value = ATTRSRC_FROM_NOWHERE;
+                               current_value = NULL;
+                               if (myhd->typeflag == PAXXTYPE) {
+                                       if (*o_option_table[got_option].x_value) {
+                                               current_value = *o_option_table[got_option].x_value;
+                                               found_value = ATTRSRC_FROM_X_O_OPTION;
+                                       } else {
+                                               current_value = str;    
+                                               found_value = ATTRSRC_FROM_X_HEADER;
+                                       }
+                               } else if (myhd->typeflag == PAXGTYPE) {
+                                       if (*o_option_table[got_option].g_value) {
+                                               current_value = *o_option_table[got_option].g_value;
+                                               found_value = ATTRSRC_FROM_G_O_OPTION;
+                                       } else {
+                                               current_value = str;    
+                                               found_value = ATTRSRC_FROM_G_HEADER;
+                                       }
+                               } else {
+                                       paxwarn(1,"Unsupported header type:%c",myhd->typeflag);
+                               }
+                               if (current_value) {
+                                       /* Save this attribute value for use later */
+                                       switch (o_option_table[got_option].header_action) {
+                                       case O_OPTION_ACTION_IGNORE:
+                                               paxwarn(1,"ignoring header keyword: %s",name);
+                                               break;
+                                       case O_OPTION_ACTION_STORE_HEADER2:
+                                       case O_OPTION_ACTION_STORE_HEADER:
+                                               switch (found_value) {
+                                               case ATTRSRC_FROM_NOWHERE: /* shouldn't happen */
+                                                       paxwarn(1, "internal error: value from nowhere");
+                                                       break;
+                                               case ATTRSRC_FROM_X_O_OPTION:
+                                               case ATTRSRC_FROM_G_O_OPTION:
+                                                       break;
+                                               case ATTRSRC_FROM_X_HEADER:
+                                                       current_value = strdup(current_value);
+                                                       if(*o_option_table[got_option].x_value_current)
+                                                               free(*o_option_table[got_option].x_value_current);
+                                                       *o_option_table[got_option].x_value_current = current_value;
+                                                       break;
+                                               case ATTRSRC_FROM_G_HEADER:
+                                                       current_value = strdup(current_value);
+                                                       if(*o_option_table[got_option].g_value_current)
+                                                               free(*o_option_table[got_option].g_value_current);
+                                                       *o_option_table[got_option].g_value_current = current_value;
+                                                       break;
+                                               }
+                                               break;
+                                       case O_OPTION_ACTION_ERROR:
+                                       default:
+                                               paxwarn(1,"Unsupported extended header attribute: %s=%s",
+                                                       name, str);
+                                       }
+                               }
+                       }
+                       inx+=len;
+                       nbytes -= len;
+               }
+
+               /* position file at next header */
+               (void)rd_skip(TAR_PAD(size));
+
+               /* read next header */
+               nbytes = rd_wrbuf(mybuf, frmt->hsz);
+               if (nbytes != frmt->hsz) {
+                       paxwarn(1,"extended header read failure: nbytes=%d, size=%d\n",
+                               nbytes, frmt->hsz);
+               }
+               myhd = ((HD_USTAR *)mybuf);
+               /* repeat until no more extended headers */
+       }
+
+       /* The header about to be returned must now be updated using all the extended
+          header values collected and any command line options */
+       /* Acceleration: check during command option processing. If there are no -o
+          options, and no changes from any header, do not need to run through this loop. */
+          
+       current_value = NULL;
+       for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
+               int header_len, free_it;
+               if (!o_option_table[i].active) continue; /* deleted keywords */
+               header_len = o_option_table[i].header_len;
+               free_it = 0;
+               if (header_len >= 0) {  /* Normal keywords */
+                       current_value = *o_option_table[i].x_value;
+                       if (!current_value) {   /* No -o := */
+                               current_value = *o_option_table[i].x_value_current;
+                               if (current_value) {
+                                       /* Must remove it: x header values not valid beyond this header */
+                                       *o_option_table[i].x_value_current = NULL;
+                                       free_it = 1;
+                               } else {        /* No x values, try globals */
+                                       current_value = *o_option_table[i].g_value;
+                                       if (!current_value)
+                                               current_value = *o_option_table[i].g_value_current;
+                               }
+                       }
+                       if (current_value) {
+                               /* Update current header with this value */
+                               /*
+                               printf ("Found current_value:%s for %s,  pids=%d\n",
+                                       current_value, o_option_table[i].name, pids);
+                               */
+                               len = strlen(current_value);
+                               if (header_len == KW_PATH_CASE) {       /* Special case for path keyword */
+                                       path_replaced = 1;
+                                       arcn->nlen = len;
+                                       strlcpy(arcn->name,current_value,sizeof(arcn->name));
+                               } else {
+                                       if (len > header_len) {
+                                               paxwarn(1," length of string from extended header bigger than header field:"
+                                                       " THAT won't work!\n");
+                                       } else {
+                                               char * p = (char *) myhd;
+                                               memcpy(&p[o_option_table[i].header_inx], 
+                                                       current_value, len);
+                                               if (len != header_len) {
+                                                       /* pad with ? */
+                                                       p[o_option_table[i].header_inx+len+1] = '\0';
+                                               }
+                                       }
+                               }
+                       }
+                       if (free_it) free(current_value);
+               }
+       }
+
+       if (myhd==hd) return(path_replaced);
+
+       /* must put new header into memory of original */
+       memcpy(hd, myhd, sizeof(HD_USTAR));
+
+       return(path_replaced);
+}
+
+/*
+ * pax_id()
+ *     determine if a block given to us is a valid pax header. We have to
+ *     be on the lookout for those pesky blocks of all zero's
+ * Return:
+ *     0 if a ustar header, -1 otherwise
+ */
+
+int
+pax_id(char *blk, int size)
+{
+       HD_USTAR *hd;
+
+       if (size < BLKMULT)
+               return(-1);
+       hd = (HD_USTAR *)blk;
+
+       /*
+        * check for block of zero's first, a simple and fast test then check
+        * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
+        * programs are fouled up and create archives missing the \0. Last we
+        * check the checksum. If ok we have to assume it is a valid header.
+        */
+       if (hd->name[0] == '\0')
+               return(-1);
+       if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
+               return(-1);
+       if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != pax_chksm(blk,BLKMULT))
+               return(-1);
+       if ((hd->typeflag != PAXXTYPE) && (hd->typeflag != PAXGTYPE)) {
+               /* Not explicitly pax format, but at least ustar */
+               if (act==LIST || act==EXTRACT) {
+                       /* Although insufficient evidence, call it pax format */
+                       return(0);
+               }
+               return(-1);
+       }
+       pax_invalid_action = PAX_INVALID_ACTION_BYPASS; /* Default for pax format */
+       return(0);
+}
+
+/*
+ * pax_rd()
+ *     extract the values out of block already determined to be a pax header.
+ *     store the values in the ARCHD parameter.
+ * Return:
+ *     0
+ */
+
+int
+pax_rd(ARCHD *arcn, char *buf)
+{
+       HD_USTAR *hd;
+       int cnt = 0;
+       int check_path;
+       dev_t devmajor;
+       dev_t devminor;
+
+       /*
+        * we only get proper sized buffers
+        */
+       if (pax_id(buf, BLKMULT) < 0)
+               return(-1);
+
+       memset(arcn, 0, sizeof(*arcn));
+       arcn->org_name = arcn->name;
+       arcn->sb.st_nlink = 1;
+       hd = (HD_USTAR *)buf;
+
+       check_path = expand_extended_headers(arcn, hd);
+
+       if (check_path) {
+               /* 
+                * pathname derived from extended head or -o option;
+                * full name is in one string, but length may exceed
+                * max path so be careful.
+                */
+               if (arcn->nlen > sizeof(arcn->name)) {
+                       paxwarn(1,"pathname from extended header info  doesn't fit! (len=%d)\n",
+                               arcn->nlen);
+               }
+       } else {
+               /*
+                * see if the filename is split into two parts. if so, join the parts.
+                * we copy the prefix first and add a / between the prefix and name.
+                */
+               char *dest = arcn->name;
+               if (*(hd->prefix) != '\0') {
+                       cnt = strlcpy(dest, hd->prefix, sizeof(arcn->name) - 1);
+                       dest += cnt;
+                       *dest++ = '/';
+                       cnt++;
+               } else {
+                       cnt = 0;
+               }
+       
+               if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
+                       arcn->nlen = expandname(dest, sizeof(arcn->name) - cnt,
+                           &gnu_name_string, hd->name, sizeof(hd->name));
+                       arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                           &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+               }
+       }
+
+       /*
+        * follow the spec to the letter. we should only have mode bits, strip
+        * off all other crud we may be passed.
+        */
+       arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
+           0xfff);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
+       arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
+       arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
+
+       /*
+        * If we can find the ascii names for gname and uname in the password
+        * and group files we will use the uid's and gid they bind. Otherwise
+        * we use the uid and gid values stored in the header. (This is what
+        * the posix spec wants).
+        */
+       hd->gname[sizeof(hd->gname) - 1] = '\0';
+       if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0)
+               arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
+       hd->uname[sizeof(hd->uname) - 1] = '\0';
+       if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
+               arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
+
+       /*
+        * set the defaults, these may be changed depending on the file type
+        */
+       arcn->pad = 0;
+       arcn->skip = 0;
+       arcn->sb.st_rdev = (dev_t)0;
+
+       /*
+        * set the mode and PAX type according to the typeflag in the header
+        */
+       switch (hd->typeflag) {
+       case FIFOTYPE:
+               arcn->type = PAX_FIF;
+               arcn->sb.st_mode |= S_IFIFO;
+               break;
+       case DIRTYPE:
+               arcn->type = PAX_DIR;
+               arcn->sb.st_mode |= S_IFDIR;
+               arcn->sb.st_nlink = 2;
+
+               /*
+                * Some programs that create pax archives append a '/'
+                * to the pathname for directories. This clearly violates
+                * pax specs, but we will silently strip it off anyway.
+                */
+               if (arcn->name[arcn->nlen - 1] == '/')
+                       arcn->name[--arcn->nlen] = '\0';
+               break;
+       case BLKTYPE:
+       case CHRTYPE:
+               /*
+                * this type requires the rdev field to be set.
+                */
+               if (hd->typeflag == BLKTYPE) {
+                       arcn->type = PAX_BLK;
+                       arcn->sb.st_mode |= S_IFBLK;
+               } else {
+                       arcn->type = PAX_CHR;
+                       arcn->sb.st_mode |= S_IFCHR;
+               }
+               devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
+               devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
+               arcn->sb.st_rdev = TODEV(devmajor, devminor);
+               break;
+       case SYMTYPE:
+       case LNKTYPE:
+               if (hd->typeflag == SYMTYPE) {
+                       arcn->type = PAX_SLK;
+                       arcn->sb.st_mode |= S_IFLNK;
+               } else {
+                       arcn->type = PAX_HLK;
+                       /*
+                        * so printing looks better
+                        */
+                       arcn->sb.st_mode |= S_IFREG;
+                       arcn->sb.st_nlink = 2;
+               }
+               break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
+               /*
+                * GNU long link/file; we tag these here and let the
+                * pax internals deal with it -- too ugly otherwise.
+                */
+               arcn->type =
+                   hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
+               break;
+       case CONTTYPE:
+       case AREGTYPE:
+       case REGTYPE:
+       default:
+               /*
+                * these types have file data that follows. Set the skip and
+                * pad fields.
+                */
+               arcn->type = PAX_REG;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
+               arcn->sb.st_mode |= S_IFREG;
+               break;
+       }
+       return(0);
+}
+
+void
+adjust_copy_for_pax_options(ARCHD * arcn)
+{
+       /* Because ext_header options take precedence over global_header options, apply
+          global options first, then override with any extended header options         */
+       int i;
+       if (global_ext_header_inx) {
+               for (i=0; i < global_ext_header_inx; i++) {
+                       if (!o_option_table[global_ext_header_entry[i]].active) continue; /* deleted keywords */
+                       if (strcmp(o_option_table[global_ext_header_entry[i]].name, "path")==0) {
+                               strlcpy(arcn->name,*(o_option_table[global_ext_header_entry[i]].g_value),
+                                               sizeof(arcn->name));
+                               arcn->nlen = strlen(*(o_option_table[global_ext_header_entry[i]].g_value));
+                       } else {        /* only handle path for now: others TBD */
+                               paxwarn(1, "adjust arcn for global extended header options not implemented:%d", i);
+                       }
+               }
+       }
+       if (ext_header_inx) {
+               for (i=0; i < ext_header_inx; i++) {
+                       if (!o_option_table[ext_header_entry[i]].active) continue; /* deleted keywords */
+                       if (strcmp(o_option_table[ext_header_entry[i]].name, "path")==0) {
+                               strlcpy(arcn->name,*(o_option_table[ext_header_entry[i]].x_value),
+                                               sizeof(arcn->name));
+                               arcn->nlen = strlen(*(o_option_table[ext_header_entry[i]].x_value));
+                       } else {        /* only handle path for now: others TBD */
+                               paxwarn(1, "adjust arcn for extended header options not implemented:%d", i);
+                       }
+               }
+       }
+       if (want_a_m_time_headers) {
+               /* TBD */
+       }
+}
+
+static int
+emit_extended_header_record(int len, int total_len, int head_type,
+                               char * name, char * value)
+{
+       if (total_len + len > sizeof(pax_eh_datablk)) {
+               paxwarn(1,"extended header buffer overflow for header type '%c': %d", 
+                               head_type, total_len+len);
+       } else {
+               sprintf(&pax_eh_datablk[total_len],"%d %s=%s\n", len, name, value);
+               total_len += len;
+       }
+       return (total_len);
+}
+
+static char *
+substitute_percent(char * header, char * filename)
+{
+       char *nextpercent, *nextchar;
+       char buf[4*1024];
+       int pos, cpylen;
+       char *dname, *fname;
+
+       nextpercent = strchr(header,'%');
+       if (nextpercent==NULL) return header;
+       pos = nextpercent-header;
+       memcpy(buf,header, pos);
+       while (nextpercent++) {
+               switch (*nextpercent) {
+               case '%':
+                       buf[pos++]='%'; /* just skip it */
+                       break;
+               case 'd':
+                       dname = strrchr(filename,'/');
+                       if (dname==NULL) {
+                               cpylen = 1;
+                               dname = ".";
+                       } else {
+                               cpylen = dname-filename;
+                               dname = filename;
+                       }
+                       memcpy(&buf[pos],dname,cpylen);
+                       pos+= cpylen;
+                       break;
+               case 'f':
+                       fname = strrchr(filename,'/');
+                       if (fname==NULL) {
+                               fname = filename;
+                       } else {
+                               fname++;
+                       }
+                       cpylen = strlen(fname);
+                       memcpy(&buf[pos],fname,cpylen);
+                       pos+= cpylen;
+                       break;
+               case 'n':
+                       pos += sprintf (&buf[pos],"%d",nglobal_headers);
+                       break;
+               case 'p':
+                       pos += sprintf (&buf[pos],"%d",getpid());
+                       break;
+               default:
+                       paxwarn(1,"header format substitution failed: '%c'", *nextpercent);
+                       return (header);
+               }
+               nextpercent++;
+               if (*nextpercent=='\0') {
+                       break;
+               }
+               nextchar = nextpercent;
+               nextpercent = strchr(nextpercent,'%');
+               if (nextpercent==NULL) {
+                       cpylen = strlen(nextchar);
+               } else {
+                       cpylen = nextpercent - nextchar;
+               }
+               memcpy(&buf[pos],nextchar, cpylen);
+               pos += cpylen;
+       }
+       buf[pos]='\0';
+       return (strdup(&buf[0]));
+}
+
+int
+generate_pax_ext_header_and_data(ARCHD *arcn, int nfields, int *table, 
+                               char header_type, char * header_name, char * header_name_requested)
+{
+       HD_USTAR *hd;
+       char hdblk[sizeof(HD_USTAR)];
+       u_long  records_size;
+       int term_char, i, len, total_len;
+       char * str, *name;
+
+       if (nfields == 0 && (header_name_requested == NULL)) {
+               if (header_type==PAXXTYPE) {
+                       if (!want_a_m_time_headers) return (0);
+               } else
+                       return (0);
+       }
+
+       /* There might be no fields but a header with a specific name or
+          times might be wanted */
+
+       term_char = 1;
+       records_size = 0;
+       memset(hdblk, 0, sizeof(hdblk));
+       hd = (HD_USTAR *)hdblk;
+       memset(pax_eh_datablk, 0, sizeof(pax_eh_datablk));
+
+       /* generate header */
+       hd->typeflag = header_type;
+
+       /* These fields appear to be necessary to be able to treat extended headers 
+          like files in older versions of pax */
+       ul_oct((u_long)0444, hd->mode, sizeof(hd->mode), term_char);
+       strncpy(hd->magic, TMAGIC, TMAGLEN);
+       strncpy(hd->version, TVERSION, TVERSLEN);
+       ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char);
+
+       /* compute size of data */
+       total_len = 0;
+       for (i=0; i < nfields; i++) {
+               if (!o_option_table[table[i]].active) continue; /* deleted keywords */
+               name = o_option_table[table[i]].name;
+               if (header_type == PAXXTYPE) {
+                       str = *(o_option_table[table[i]].x_value);
+               } else {
+                       str = *(o_option_table[table[i]].g_value);
+               }
+               if (str==NULL) {
+                       paxwarn(1,"Missing option value for %s", name);
+                       continue;
+               }
+               len = strlen(str) + o_option_table[table[i]].len + 3;
+               if (len < 9) len++;
+               else if (len < 98)      len = len + 2;
+               else if (len < 997)     len = len + 3;
+               else if (len < 9996)    len = len + 4;
+               else {
+                       paxwarn(1,"extended header data too long for header type '%c': %d", 
+                                       header_type, len);
+               }
+               total_len = emit_extended_header_record(len, total_len, 
+                                       header_type, name, str);
+       }
+
+       if ((header_type == PAXXTYPE) && want_a_m_time_headers) {
+               char time_buffer[12];
+               memset(time_buffer,0,sizeof(time_buffer));
+               sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_atime);
+               /* 3 chars + strlen("atime") + time + # chars in len */
+               len = 3 + 5 + strlen(&time_buffer[0]) + 2;
+               total_len = emit_extended_header_record(len, total_len, 
+                               header_type, "atime", &time_buffer[0]);
+               memset(time_buffer,0,sizeof(time_buffer));
+               sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_mtime);
+               /* 3 chars + strlen("mtime") + time + # chars in len */
+               len = 3 + 5 + strlen(&time_buffer[0]) + 2;
+               total_len = emit_extended_header_record(len, total_len, 
+                               header_type, "mtime", &time_buffer[0]);
+       }
+
+       /* Check if all fields were deleted: might not need to generate anything */
+       if ((total_len==0) && (header_name_requested == NULL)) return (0);
+
+       if (header_type == PAXGTYPE) nglobal_headers++;
+       /* substitution of fields in header_name */
+       header_name = substitute_percent(header_name, arcn->name);
+       if (strlen(header_name) == sizeof(hd->name)) {  /* must account for name just fits in buffer */
+               strncpy(hd->name, header_name, sizeof(hd->name));
+       } else {
+               strlcpy(hd->name, header_name, sizeof(hd->name));
+       }
+
+       records_size = (u_long)total_len;
+       if (ul_oct(records_size, hd->size, sizeof(hd->size), term_char)) {
+               paxwarn(1,"extended header data too long for header type '%c'", header_type);
+               return(1);
+       }
+
+       if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, sizeof(hd->chksum), term_char)) {
+               paxwarn(1,"extended header data checksum failed: header type '%c'", header_type);
+               return(1);
+       }
+
+       /* write out header */
+       if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
+               return(-1);
+       if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
+               return(-1);
+       /* write out header data */
+       if (total_len > 0) {
+               if (wr_rdbuf(pax_eh_datablk, total_len) < 0)
+                       return(-1);
+               if (wr_skip((off_t)(BLKMULT - total_len)) < 0)
+                       return(-1);
+               /*
+               printf("data written:\n%s",&pax_eh_datablk[0]);
+               */
+       }
+
+       /*
+       paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters",
+                               header_type, nfields, records_size);
+       */
+       return (0);
+}
+
+/*
+ * pax_wr()
+ *     write a pax header for the file specified in the ARCHD to the archive
+ *     Have to check for file types that cannot be stored and file names that
+ *     are too long. Be careful of the term (last arg) to ul_oct, we only use
+ *     '\0' for the termination character (this is different than picky tar)
+ *     ASSUMED: space after header in header block is zero filled
+ * Return:
+ *     0 if file has data to be written after the header, 1 if file has NO
+ *     data to write after the header, -1 if archive write failed
+ */
+
+int
+pax_wr(ARCHD *arcn)
+{
+       HD_USTAR *hd;
+       char *pt;
+       char hdblk[sizeof(HD_USTAR)];
+       mode_t mode12only;
+       int term_char=3;        /* orignal setting */
+       term_char=1;            /* To pass conformance tests 274, 301 */
+
+       /*
+        * check for those file system types pax cannot store
+        */
+       if (arcn->type == PAX_SCK) {
+               paxwarn(1, "Pax cannot archive a socket %s", arcn->org_name);
+               return(1);
+       }
+
+       /*
+        * check the length of the linkname
+        */
+       if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
+           (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
+               paxwarn(1, "Link name too long for pax %s", arcn->ln_name);
+               /*
+                * Conformance: test pax:285 wants error code to be non-zero, and
+                * test tar:12 wants error code from pax to be 0
+                */
+               return(1);
+       }
+
+       /*
+        * split the path name into prefix and name fields (if needed). if
+        * pt != arcn->name, the name has to be split
+        */
+       if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
+               paxwarn(1, "File name too long for pax %s", arcn->name);
+               return(1);
+       }
+
+       generate_pax_ext_header_and_data(arcn, global_ext_header_inx, &global_ext_header_entry[0],
+                                       PAXGTYPE, header_name_g, header_name_g_requested);
+       generate_pax_ext_header_and_data(arcn, ext_header_inx, &ext_header_entry[0],
+                                       PAXXTYPE, header_name_x, header_name_x_requested);
+
+       /*
+        * zero out the header so we don't have to worry about zero fill below
+        */
+       memset(hdblk, 0, sizeof(hdblk));
+       hd = (HD_USTAR *)hdblk;
+       arcn->pad = 0L;
+       /* To pass conformance tests 274/301, always set these fields to "zero" */
+       ul_oct(0, hd->devmajor, sizeof(hd->devmajor), term_char);
+       ul_oct(0, hd->devminor, sizeof(hd->devminor), term_char);
+
+       /*
+        * split the name, or zero out the prefix
+        */
+       if (pt != arcn->name) {
+               /*
+                * name was split, pt points at the / where the split is to
+                * occur, we remove the / and copy the first part to the prefix
+                */
+               *pt = '\0';
+               strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix));
+               *pt++ = '/';
+       }
+
+       /*
+        * copy the name part. this may be the whole path or the part after
+        * the prefix
+        */
+       if (strlen(pt) == sizeof(hd->name)) {   /* must account for name just fits in buffer */
+               strncpy(hd->name, pt, sizeof(hd->name));
+       } else {
+               strlcpy(hd->name, pt, sizeof(hd->name));
+       }
+
+       /*
+        * set the fields in the header that are type dependent
+        */
+       switch (arcn->type) {
+       case PAX_DIR:
+               hd->typeflag = DIRTYPE;
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
+                       goto out;
+               break;
+       case PAX_CHR:
+       case PAX_BLK:
+               if (arcn->type == PAX_CHR)
+                       hd->typeflag = CHRTYPE;
+               else
+                       hd->typeflag = BLKTYPE;
+               if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
+                  sizeof(hd->devmajor), term_char) ||
+                  ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
+                  sizeof(hd->devminor), term_char) ||
+                  ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
+                       goto out;
+               break;
+       case PAX_FIF:
+               hd->typeflag = FIFOTYPE;
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
+                       goto out;
+               break;
+       case PAX_SLK:
+       case PAX_HLK:
+       case PAX_HRG:
+               if (arcn->type == PAX_SLK)
+                       hd->typeflag = SYMTYPE;
+               else
+                       hd->typeflag = LNKTYPE;
+               if (strlen(arcn->ln_name) == sizeof(hd->linkname)) {    /* must account for name just fits in buffer */
+                       strncpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               } else {
+                       strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               }
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
+                       goto out;
+               break;
+       case PAX_REG:
+       case PAX_CTG:
+       default:
+               /*
+                * file data with this type, set the padding
+                */
+               if (arcn->type == PAX_CTG)
+                       hd->typeflag = CONTTYPE;
+               else
+                       hd->typeflag = REGTYPE;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+#              ifdef LONG_OFF_T
+               if (ul_oct((u_long)arcn->sb.st_size, hd->size,
+                   sizeof(hd->size), term_char)) {
+#              else
+               if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
+                   sizeof(hd->size), term_char)) {
+#              endif
+                       paxwarn(1,"File is too long for pax %s",arcn->org_name);
+                       return(1);
+               }
+               break;
+       }
+
+       strncpy(hd->magic, TMAGIC, TMAGLEN);
+       strncpy(hd->version, TVERSION, TVERSLEN);
+
+       /*
+        * set the remaining fields. Some versions want all 16 bits of mode
+        * we better humor them (they really do not meet spec though)....
+        */
+       if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), term_char)) {
+               if (uid_nobody == 0) {
+                       if (uid_name("nobody", &uid_nobody) == -1)
+                               goto out;
+               }
+               if (uid_warn != arcn->sb.st_uid) {
+                       uid_warn = arcn->sb.st_uid;
+                       paxwarn(1,
+                           "Pax header field is too small for uid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_uid);
+               }
+               if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), term_char))
+                       goto out;
+       }
+       if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), term_char)) {
+               if (gid_nobody == 0) {
+                       if (gid_name("nobody", &gid_nobody) == -1)
+                               goto out;
+               }
+               if (gid_warn != arcn->sb.st_gid) {
+                       gid_warn = arcn->sb.st_gid;
+                       paxwarn(1,
+                           "Pax header field is too small for gid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_gid);
+               }
+               if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), term_char))
+                       goto out;
+       }
+       /* However, Unix conformance tests do not like MORE than 12 mode bits:
+          remove all beyond (see definition of stat.st_mode structure)         */
+       mode12only = ((u_long)arcn->sb.st_mode) & 0x00000fff;
+       if (ul_oct((u_long)mode12only, hd->mode, sizeof(hd->mode), term_char) ||
+           ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char))
+               goto out;
+       strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
+       strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
+
+       /*
+        * calculate and store the checksum write the header to the archive
+        * return 0 tells the caller to now write the file data, 1 says no data
+        * needs to be written
+        */
+       if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
+          sizeof(hd->chksum), term_char))
+               goto out;
+       if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
+               return(-1);
+       if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
+               return(-1);
+       if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
+               return(0);
+       return(1);
+
+    out:
+       /*
+        * header field is out of range
+        */
+       paxwarn(1, "Pax header field is too small for %s", arcn->org_name);
+       return(1);
+}
+
+#if 0
+/*
+ * name_split()
+ *     see if the name has to be split for storage in a ustar header. We try
+ *     to fit the entire name in the name field without splitting if we can.
+ *     The split point is always at a /
+ * Return
+ *     character pointer to split point (always the / that is to be removed
+ *     if the split is not needed, the points is set to the start of the file
+ *     name (it would violate the spec to split there). A NULL is returned if
+ *     the file name is too long
+ */
+
+static char *
+name_split(char *name, int len)
+{
+       char *start;
+
+       /*
+        * check to see if the file name is small enough to fit in the name
+        * field. if so just return a pointer to the name.
+        */
+       if (len <= TNMSZ)
+               return(name);
+       if (len > (TPFSZ + TNMSZ))
+               return(NULL);
+
+       /*
+        * we start looking at the biggest sized piece that fits in the name
+        * field. We walk forward looking for a slash to split at. The idea is
+        * to find the biggest piece to fit in the name field (or the smallest
+        * prefix we can find)
+        */
+       start = name + len - TNMSZ -1;
+       while ((*start != '\0') && (*start != '/'))
+               ++start;
+
+       /*
+        * if we hit the end of the string, this name cannot be split, so we
+        * cannot store this file.
+        */
+       if (*start == '\0')
+               return(NULL);
+       len = start - name;
+
+       /*
+        * NOTE: /str where the length of str == TNMSZ can not be stored under
+        * the p1003.1-1990 spec for ustar. We could force a prefix of / and
+        * the file would then expand on extract to //str. The len == 0 below
+        * makes this special case follow the spec to the letter.
+        */
+       if ((len >= TPFSZ) || (len == 0))
+               return(NULL);
+
+       /*
+        * ok have a split point, return it to the caller
+        */
+       return(start);
+}
+#endif /* if 0 */
+
+static size_t
+expandname(char *buf, size_t len, char **gnu_name, const char *name, size_t name_len)
+{
+       size_t nlen;
+
+       if (*gnu_name) {
+               if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
+                       nlen = len - 1;
+               free(*gnu_name);
+               *gnu_name = NULL;
+       } else {
+               if (name_len < len) {
+                       /* name may not be null terminated: it might be as big as the
+                          field,  so copy is limited to the max size of the header field */
+                       if ((nlen = strlcpy(buf, name, name_len+1)) >= name_len+1)
+                               nlen = name_len;
+               } else {
+                       if ((nlen = strlcpy(buf, name, len)) >= len)
+                               nlen = len - 1;
+               }
+       }
+       return(nlen);
+}
index a4e1c2271ef8436abeec0709427073dcda57088e..86ba9ed587bde12639de9ae847d553a06449b0f5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $    */
+/*     $OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $   */
 /*     $NetBSD: sel_subs.c,v 1.5 1995/03/21 09:07:42 cgd Exp $ */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)sel_subs.c 8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)sel_subs.c   8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: sel_subs.c,v 1.7 1997/08/17 23:05:09 millert Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: sel_subs.c,v 1.18 2004/04/16 22:50:23 deraadt Exp $";
 #endif
 #endif /* not lint */
 
@@ -50,20 +46,22 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: sel_subs.c,v 1.7 19
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/param.h>
-#include <pwd.h>
+#include <ctype.h>
 #include <grp.h>
+#include <pwd.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <tzfile.h>
 #include <unistd.h>
-#include <stdlib.h>
 #include "pax.h"
 #include "sel_subs.h"
 #include "extern.h"
 
-static int str_sec __P((register char *, time_t *));
-static int usr_match __P((register ARCHD *));
-static int grp_match __P((register ARCHD *));
-static int trng_match __P((register ARCHD *));
+static int str_sec(const char *, time_t *);
+static int usr_match(ARCHD *);
+static int grp_match(ARCHD *);
+static int trng_match(ARCHD *);
 
 static TIME_RNG *trhead = NULL;                /* time range list head */
 static TIME_RNG *trtail = NULL;                /* time range list tail */
@@ -76,19 +74,13 @@ static GRPT **grptb = NULL;         /* group selection table */
 
 /*
  * sel_chk()
- *     check if this file matches a specfied uid, gid or time range
+ *     check if this file matches a specified uid, gid or time range
  * Return:
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
 int
-sel_chk(register ARCHD *arcn)
-#else
-int
-sel_chk(arcn)
-       register ARCHD *arcn;
-#endif
+sel_chk(ARCHD *arcn)
 {
        if (((usrtb != NULL) && usr_match(arcn)) ||
            ((grptb != NULL) && grp_match(arcn)) ||
@@ -101,8 +93,8 @@ sel_chk(arcn)
  * User/group selection routines
  *
  * Routines to handle user selection of files based on the file uid/gid. To
- * add an entry, the user supplies either then name or the uid/gid starting with
- * a # on the command line. A \# will eascape the #.
+ * add an entry, the user supplies either the name or the uid/gid starting with
+ * a # on the command line. A \# will escape the #.
  */
 
 /*
@@ -112,19 +104,13 @@ sel_chk(arcn)
  *     0 if added ok, -1 otherwise;
  */
 
-#ifdef __STDC__
 int
-usr_add(register char *str)
-#else
-int
-usr_add(str)
-       register char *str;
-#endif
+usr_add(char *str)
 {
-       register u_int indx;
-       register USRT *pt;
-       register struct passwd *pw;
-       register uid_t uid;
+       u_int indx;
+       USRT *pt;
+       struct passwd *pw;
+       uid_t uid;
 
        /*
         * create the table if it doesn't exist
@@ -152,11 +138,7 @@ usr_add(str)
                }
                uid = (uid_t)pw->pw_uid;
        } else
-#              ifdef NET2_STAT
-               uid = (uid_t)atoi(str+1);
-#              else
                uid = (uid_t)strtoul(str+1, NULL, 10);
-#              endif
        endpwent();
 
        /*
@@ -191,16 +173,10 @@ usr_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
 static int
-usr_match(register ARCHD *arcn)
-#else
-static int
-usr_match(arcn)
-       register ARCHD *arcn;
-#endif
+usr_match(ARCHD *arcn)
 {
-       register USRT *pt;
+       USRT *pt;
 
        /*
         * hash and look for it in the table
@@ -225,19 +201,13 @@ usr_match(arcn)
  *     0 if added ok, -1 otherwise;
  */
 
-#ifdef __STDC__
 int
-grp_add(register char *str)
-#else
-int
-grp_add(str)
-       register char *str;
-#endif
+grp_add(char *str)
 {
-       register u_int indx;
-       register GRPT *pt;
-       register struct group *gr;
-       register gid_t gid;
+       u_int indx;
+       GRPT *pt;
+       struct group *gr;
+       gid_t gid;
 
        /*
         * create the table if it doesn't exist
@@ -265,11 +235,7 @@ grp_add(str)
                }
                gid = (gid_t)gr->gr_gid;
        } else
-#              ifdef NET2_STAT
-               gid = (gid_t)atoi(str+1);
-#              else
                gid = (gid_t)strtoul(str+1, NULL, 10);
-#              endif
        endgrent();
 
        /*
@@ -304,16 +270,10 @@ grp_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
-static int
-grp_match(register ARCHD *arcn)
-#else
 static int
-grp_match(arcn)
-       register ARCHD *arcn;
-#endif
+grp_match(ARCHD *arcn)
 {
-       register GRPT *pt;
+       GRPT *pt;
 
        /*
         * hash and look for it in the table
@@ -353,27 +313,21 @@ grp_match(arcn)
  * trng_add()
  *     add a time range match to the time range list.
  *     This is a non-standard pax option. Lower and upper ranges are in the
- *     format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
+ *     format: [[[[[cc]yy]mm]dd]HH]MM[.SS] and are comma separated.
  *     Time ranges are based on current time, so 1234 would specify a time of
  *     12:34 today.
  * Return:
  *     0 if the time range was added to the list, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-trng_add(register char *str)
-#else
 int
-trng_add(str)
-       register char *str;
-#endif
+trng_add(char *str)
 {
-       register TIME_RNG *pt;
-       register char *up_pt = NULL;
-       register char *stpt;
-       register char *flgpt;
-       register int dot = 0;
+       TIME_RNG *pt;
+       char *up_pt = NULL;
+       char *stpt;
+       char *flgpt;
+       int dot = 0;
 
        /*
         * throw out the badly formed time ranges
@@ -419,7 +373,7 @@ trng_add(str)
        }
 
        /*
-        * by default we only will check file mtime, but usee can specify
+        * by default we only will check file mtime, but user can specify
         * mtime, ctime (inode change time) or both.
         */
        if ((flgpt == NULL) || (*flgpt == '\0'))
@@ -427,7 +381,7 @@ trng_add(str)
        else {
                pt->flgs = 0;
                while (*flgpt != '\0') {
-                       switch(*flgpt) {
+                       switch (*flgpt) {
                        case 'M':
                        case 'm':
                                pt->flgs |= CMPMTME;
@@ -495,7 +449,7 @@ trng_add(str)
        return(0);
 
     out:
-       paxwarn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
+       paxwarn(1, "Time range format is: [[[[[cc]yy]mm]dd]HH]MM[.SS][/[c][m]]");
        return(-1);
 }
 
@@ -506,16 +460,10 @@ trng_add(str)
  *     0 if this archive member should be processed, 1 if it should be skipped
  */
 
-#ifdef __STDC__
-static int
-trng_match(register ARCHD *arcn)
-#else
 static int
-trng_match(arcn)
-       register ARCHD *arcn;
-#endif
+trng_match(ARCHD *arcn)
 {
-       register TIME_RNG *pt;
+       TIME_RNG *pt;
 
        /*
         * have to search down the list one at a time looking for a match.
@@ -523,7 +471,7 @@ trng_match(arcn)
         */
        pt = trhead;
        while (pt != NULL) {
-               switch(pt->flgs & CMPBOTH) {
+               switch (pt->flgs & CMPBOTH) {
                case CMPBOTH:
                        /*
                         * user wants both mtime and ctime checked for this
@@ -575,87 +523,89 @@ trng_match(arcn)
 
 /*
  * str_sec()
- *     Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
- *     seconds. Tval already has current time loaded into it at entry.
+ *     Convert a time string in the format of [[[[[cc]yy]mm]dd]HH]MM[.SS] to
+ *     seconds UTC. Tval already has current time loaded into it at entry.
  * Return:
  *     0 if converted ok, -1 otherwise
  */
 
-#ifdef __STDC__
-static int
-str_sec(register char *str, time_t *tval)
-#else
 static int
-str_sec(str, tval)
-       register char *str;
-       time_t *tval;
-#endif
+str_sec(const char *p, time_t *tval)
 {
-       register struct tm *lt;
-       register char *dot = NULL;
+       struct tm *lt;
+       const char *dot, *t;
+       size_t len;
+       int bigyear;
+       int yearset;
+
+       yearset = 0;
+       len = strlen(p);
+
+       for (t = p, dot = NULL; *t; ++t) {
+               if (isdigit(*t))
+                       continue;
+               if (*t == '.' && dot == NULL) {
+                       dot = t;
+                       continue;
+               }
+               return(-1);
+       }
 
        lt = localtime(tval);
-       if ((dot = strchr(str, '.')) != NULL) {
-               /*
-                * seconds (.ss)
-                */
-               *dot++ = '\0';
-               if (strlen(dot) != 2)
+
+       if (dot != NULL) {                      /* .SS */
+               if (strlen(++dot) != 2)
                        return(-1);
-               if ((lt->tm_sec = ATOI2(dot)) > 61)
+               lt->tm_sec = ATOI2(dot);
+               if (lt->tm_sec > 61)
                        return(-1);
+               len -= 3;
        } else
                lt->tm_sec = 0;
 
-       switch (strlen(str)) {
-       case 10:
-               /*
-                * year (yy)
-                * watch out for year 2000
-                */
-               if ((lt->tm_year = ATOI2(str)) < 69)
-                       lt->tm_year += 100;
-               str += 2;
+       switch (len) {
+       case 12:                                /* cc */
+               bigyear = ATOI2(p);
+               lt->tm_year = (bigyear * 100) - TM_YEAR_BASE;
+               yearset = 1;
                /* FALLTHROUGH */
-       case 8:
-               /*
-                * month (mm)
-                * watch out months are from 0 - 11 internally
-                */
-               if ((lt->tm_mon = ATOI2(str)) > 12)
+       case 10:                                /* yy */
+               if (yearset) {
+                       lt->tm_year += ATOI2(p);
+               } else {
+                       lt->tm_year = ATOI2(p);
+                       if (lt->tm_year < 69)           /* hack for 2000 ;-} */
+                               lt->tm_year += (2000 - TM_YEAR_BASE);
+                       else
+                               lt->tm_year += (1900 - TM_YEAR_BASE);
+               }
+               /* FALLTHROUGH */
+       case 8:                                 /* mm */
+               lt->tm_mon = ATOI2(p);
+               if ((lt->tm_mon > 12) || !lt->tm_mon)
                        return(-1);
-               --lt->tm_mon;
-               str += 2;
+               --lt->tm_mon;                   /* time struct is 0 - 11 */
                /* FALLTHROUGH */
-       case 6:
-               /*
-                * day (dd)
-                */
-               if ((lt->tm_mday = ATOI2(str)) > 31)
+       case 6:                                 /* dd */
+               lt->tm_mday = ATOI2(p);
+               if ((lt->tm_mday > 31) || !lt->tm_mday)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 4:
-               /*
-                * hour (hh)
-                */
-               if ((lt->tm_hour = ATOI2(str)) > 23)
+       case 4:                                 /* HH */
+               lt->tm_hour = ATOI2(p);
+               if (lt->tm_hour > 23)
                        return(-1);
-               str += 2;
                /* FALLTHROUGH */
-       case 2:
-               /*
-                * minute (mm)
-                */
-               if ((lt->tm_min = ATOI2(str)) > 59)
+       case 2:                                 /* MM */
+               lt->tm_min = ATOI2(p);
+               if (lt->tm_min > 59)
                        return(-1);
                break;
        default:
                return(-1);
        }
-       /*
-        * convert broken-down time to GMT clock time seconds
-        */
+
+       /* convert broken-down time to UTC clock time seconds */
        if ((*tval = mktime(lt)) == -1)
                return(-1);
        return(0);
index fc86e9dfa236362632865f01dd647186ce7c027a..b699ee83ef353f35de8ce769f6601b566f12652e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sel_subs.h,v 1.2 1996/06/23 14:20:41 deraadt Exp $    */
+/*     $OpenBSD: sel_subs.h,v 1.4 2003/06/02 23:32:09 millert Exp $    */
 /*     $NetBSD: sel_subs.h,v 1.3 1995/03/21 09:07:44 cgd Exp $ */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -61,7 +57,7 @@ typedef struct grpt {
  * data structure for storing user supplied time ranges (-T option)
  */
 
-#define ATOI2(s)       ((((s)[0] - '0') * 10) + ((s)[1] - '0'))
+#define ATOI2(ar)      ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
 
 typedef struct time_rng {
        time_t          low_time;       /* lower inclusive time limit */
index a0a964e43d79add1dbb860b737e82d2114d1d87a..6b067e86b70603de6849dba3ce7b2b8a1d840d0e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tables.c,v 1.9 1997/09/01 18:30:00 deraadt Exp $      */
+/*     $OpenBSD: tables.c,v 1.22 2004/11/29 16:23:22 otto Exp $        */
 /*     $NetBSD: tables.c,v 1.4 1995/03/21 09:07:45 cgd Exp $   */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tables.c   8.1 (Berkeley) 5/31/93";
+static const char sccsid[] = "@(#)tables.c     8.1 (Berkeley) 5/31/93";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tables.c,v 1.9 1997/09/01 18:30:00 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tables.c,v 1.22 2004/11/29 16:23:22 otto Exp $";
 #endif
 #endif /* not lint */
 
@@ -71,7 +67,7 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tables.c,v 1.9 1997
  * large archives. These database routines carefully combine memory usage and
  * temporary file storage in ways which will not significantly impact runtime
  * performance while allowing the largest possible archives to be handled.
- * Trying to force the fit to the posix databases routines was not considered
+ * Trying to force the fit to the posix database routines was not considered
  * time well spent.
  */
 
@@ -80,11 +76,12 @@ static FTM **ftab = NULL;   /* file time table for updating arch */
 static NAMT **ntab = NULL;     /* interactive rename storage table */
 static DEVT **dtab = NULL;     /* device/inode mapping tables */
 static ATDIR **atab = NULL;    /* file tree directory time reset table */
-static int dirfd = -1;         /* storage for setting created dir time/mode */
-static u_long dircnt;          /* entries in dir time/mode storage */
+static DIRDATA *dirp = NULL;   /* storage for setting created dir time/mode */
+static size_t dirsize;         /* size of dirp table */
+static long dircnt = 0;                /* entries in dir time/mode storage */
 static int ffd = -1;           /* tmp file for file time table name storage */
 
-static DEVT *chk_dev __P((dev_t, int));
+static DEVT *chk_dev(dev_t, int);
 
 /*
  * hard link table routines
@@ -109,13 +106,8 @@ static DEVT *chk_dev __P((dev_t, int));
  *     0 if created, -1 if failure
  */
 
-#ifdef __STDC__
 int
 lnk_start(void)
-#else
-int
-lnk_start()
-#endif
 {
        if (ltab != NULL)
                return(0);
@@ -138,18 +130,12 @@ lnk_start()
  *     if found returns 1; if not found returns 0; -1 on error
  */
 
-#ifdef __STDC__
 int
-chk_lnk(register ARCHD *arcn)
-#else
-int
-chk_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+chk_lnk(ARCHD *arcn)
 {
-       register HRDLNK *pt;
-       register HRDLNK **ppt;
-       register u_int indx;
+       HRDLNK *pt;
+       HRDLNK **ppt;
+       u_int indx;
 
        if (ltab == NULL)
                return(-1);
@@ -159,6 +145,12 @@ chk_lnk(arcn)
        if ((arcn->type == PAX_DIR) || (arcn->sb.st_nlink <= 1))
                return(0);
 
+       /*
+        * Conformance tests: ignore symlink because cannot create hard link to it 
+        */
+       if ((arcn->type == PAX_SLK))
+               return(0);
+
        /*
         * hash inode number and look for this file
         */
@@ -183,9 +175,8 @@ chk_lnk(arcn)
                         * handle hardlinks to regular files differently than
                         * other links.
                         */
-                       arcn->ln_nlen = l_strncpy(arcn->ln_name, pt->name,
-                               sizeof(arcn->ln_name) - 1);
-                       arcn->ln_name[arcn->ln_nlen] = '\0';
+                       arcn->ln_nlen = strlcpy(arcn->ln_name, pt->name,
+                               sizeof(arcn->ln_name));
                        if (arcn->type == PAX_REG)
                                arcn->type = PAX_HRG;
                        else
@@ -231,18 +222,12 @@ chk_lnk(arcn)
  *     we do not want to accidently point another file at it later on.
  */
 
-#ifdef __STDC__
-void
-purg_lnk(register ARCHD *arcn)
-#else
 void
-purg_lnk(arcn)
-       register ARCHD *arcn;
-#endif
+purg_lnk(ARCHD *arcn)
 {
-       register HRDLNK *pt;
-       register HRDLNK **ppt;
-       register u_int indx;
+       HRDLNK *pt;
+       HRDLNK **ppt;
+       u_int indx;
 
        if (ltab == NULL)
                return;
@@ -291,17 +276,12 @@ purg_lnk(arcn)
  *     write phase
  */
 
-#ifdef __STDC__
 void
 lnk_end(void)
-#else
-void
-lnk_end()
-#endif
 {
-       register int i;
-       register HRDLNK *pt;
-       register HRDLNK *ppt;
+       int i;
+       HRDLNK *pt;
+       HRDLNK *ppt;
 
        if (ltab == NULL)
                return;
@@ -336,14 +316,14 @@ lnk_end()
  * An append with an -u must read the archive and store the modification time
  * for every file on that archive before starting the write phase. It is clear
  * that this is one HUGE database. To save memory space, the actual file names
- * are stored in a scatch file and indexed by an in memory hash table. The
+ * are stored in a scratch file and indexed by an in-memory hash table. The
  * hash table is indexed by hashing the file path. The nodes in the table store
  * the length of the filename and the lseek offset within the scratch file
- * where the actual name is stored. Since there are never any deletions to this
- * table, fragmentation of the scratch file is never a issue. Lookups seem to
- * not exhibit any locality at all (files in the database are rarely
- * looked up more than once...). So caching is just a waste of memory. The
- * only limitation is the amount of scatch file space available to store the
+ * where the actual name is stored. Since there are never any deletions from
+ * this table, fragmentation of the scratch file is never a issue. Lookups 
+ * seem to not exhibit any locality at all (files in the database are rarely
+ * looked up more than once...), so caching is just a waste of memory. The
+ * only limitation is the amount of scratch file space available to store the
  * path names.
  */
 
@@ -356,15 +336,9 @@ lnk_end()
  *     0 if the table and file was created ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ftime_start(void)
-#else
-int
-ftime_start()
-#endif
 {
-       char *pt;
 
        if (ftab != NULL)
                return(0);
@@ -377,14 +351,13 @@ ftime_start()
         * get random name and create temporary scratch file, unlink name
         * so it will get removed on exit
         */
-       pt = strdup("/tmp/paxXXXXXX");
-       if ((ffd = mkstemp(pt)) < 0) {
-               syswarn(1, errno, "Unable to create temporary file: %s", pt);
-               free(pt);
+       memcpy(tempbase, _TFILE_BASE, sizeof(_TFILE_BASE));
+       if ((ffd = mkstemp(tempfile)) < 0) {
+               syswarn(1, errno, "Unable to create temporary file: %s",
+                   tempfile);
                return(-1);
        }
-       (void)unlink(pt);
-       free(pt);
+       (void)unlink(tempfile);
 
        return(0);
 }
@@ -401,18 +374,12 @@ ftime_start()
  *     -1 on error
  */
 
-#ifdef __STDC__
-int
-chk_ftime(register ARCHD *arcn)
-#else
 int
-chk_ftime(arcn)
-       register ARCHD *arcn;
-#endif
+chk_ftime(ARCHD *arcn)
 {
-       register FTM *pt;
-       register int namelen;
-       register u_int indx;
+       FTM *pt;
+       int namelen;
+       u_int indx;
        char ckname[PAXPATHLEN+1];
 
        /*
@@ -511,7 +478,7 @@ chk_ftime(arcn)
  * Interactive rename table routines
  *
  * The interactive rename table keeps track of the new names that the user
- * assignes to files from tty input. Since this map is unique for each file
+ * assigns to files from tty input. Since this map is unique for each file
  * we must store it in case there is a reference to the file later in archive
  * (a link). Otherwise we will be unable to find the file we know was
  * extracted. The remapping of these files is stored in a memory based hash
@@ -526,13 +493,8 @@ chk_ftime(arcn)
  *     0 if successful, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 name_start(void)
-#else
-int
-name_start()
-#endif
 {
        if (ntab != NULL)
                return(0);
@@ -552,25 +514,17 @@ name_start()
  *     0 if added, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-add_name(register char *oname, int onamelen, char *nname)
-#else
 int
-add_name(oname, onamelen, nname)
-       register char *oname;
-       int onamelen;
-       char *nname;
-#endif
+add_name(char *oname, int onamelen, char *nname)
 {
-       register NAMT *pt;
-       register u_int indx;
+       NAMT *pt;
+       u_int indx;
 
        if (ntab == NULL) {
                /*
                 * should never happen
                 */
-               paxwarn(0, "No interactive rename table, links may fail\n");
+               paxwarn(0, "No interactive rename table, links may fail");
                return(0);
        }
 
@@ -628,19 +582,11 @@ add_name(oname, onamelen, nname)
  *     new name (oname is the link to name)
  */
 
-#ifdef __STDC__
-void
-sub_name(register char *oname, int *onamelen, size_t onamesize)
-#else
 void
-sub_name(oname, onamelen, onamesize)
-       register char *oname;
-       int *onamelen;
-       size_t onamesize;
-#endif
+sub_name(char *oname, int *onamelen, size_t onamesize)
 {
-       register NAMT *pt;
-       register u_int indx;
+       NAMT *pt;
+       u_int indx;
 
        if (ntab == NULL)
                return;
@@ -660,8 +606,7 @@ sub_name(oname, onamelen, onamesize)
                         * found it, replace it with the new name
                         * and return (we know that oname has enough space)
                         */
-                       *onamelen = l_strncpy(oname, pt->nname, onamesize - 1);
-                       oname[*onamelen] = '\0';
+                       *onamelen = strlcpy(oname, pt->nname, onamesize);
                        return;
                }
                pt = pt->fow;
@@ -720,13 +665,8 @@ sub_name(oname, onamelen, onamesize)
  *     0 if successful, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 dev_start(void)
-#else
-int
-dev_start()
-#endif
 {
        if (dtab != NULL)
                return(0);
@@ -747,14 +687,8 @@ dev_start()
  *     0 if added ok, -1 otherwise
  */
 
-#ifdef __STDC__
-int
-add_dev(register ARCHD *arcn)
-#else
 int
-add_dev(arcn)
-       register ARCHD *arcn;
-#endif
+add_dev(ARCHD *arcn)
 {
        if (chk_dev(arcn->sb.st_dev, 1) == NULL)
                return(-1);
@@ -766,7 +700,7 @@ add_dev(arcn)
  *     check for a device value in the device table. If not found and the add
  *     flag is set, it is added. This does NOT assign any mapping values, just
  *     adds the device number as one that need to be remapped. If this device
- *     is alread mapped, just return with a pointer to that entry.
+ *     is already mapped, just return with a pointer to that entry.
  * Return:
  *     pointer to the entry for this device in the device map table. Null
  *     if the add flag is not set and the device is not in the table (it is
@@ -774,18 +708,11 @@ add_dev(arcn)
  *     is returned (indicates an error).
  */
 
-#ifdef __STDC__
 static DEVT *
 chk_dev(dev_t dev, int add)
-#else
-static DEVT *
-chk_dev(dev, add)
-       dev_t dev;
-       int add;
-#endif
 {
-       register DEVT *pt;
-       register u_int indx;
+       DEVT *pt;
+       u_int indx;
 
        if (dtab == NULL)
                return(NULL);
@@ -839,19 +766,11 @@ chk_dev(dev, add)
  *     0 if all ok, -1 otherwise.
  */
 
-#ifdef __STDC__
-int
-map_dev(register ARCHD *arcn, u_long dev_mask, u_long ino_mask)
-#else
 int
-map_dev(arcn, dev_mask, ino_mask)
-       register ARCHD *arcn;
-       u_long dev_mask;
-       u_long ino_mask;
-#endif
+map_dev(ARCHD *arcn, u_long dev_mask, u_long ino_mask)
 {
-       register DEVT *pt;
-       register DLIST *dpt;
+       DEVT *pt;
+       DLIST *dpt;
        static dev_t lastdev = 0;       /* next device number to try */
        int trc_ino = 0;
        int trc_dev = 0;
@@ -968,14 +887,14 @@ map_dev(arcn, dev_mask, ino_mask)
 /*
  * directory access/mod time reset table routines (for directories READ by pax)
  *
- * The pax -t flag requires that access times of archive files to be the same
+ * The pax -t flag requires that access times of archive files be the same
  * before being read by pax. For regular files, access time is restored after
  * the file has been copied. This database provides the same functionality for
  * directories read during file tree traversal. Restoring directory access time
  * is more complex than files since directories may be read several times until
  * all the descendants in their subtree are visited by fts. Directory access
  * and modification times are stored during the fts pre-order visit (done
- * before any descendants in the subtree is visited) and restored after the
+ * before any descendants in the subtree are visited) and restored after the
  * fts post-order visit (after all the descendants have been visited). In the
  * case of premature exit from a subtree (like from the effects of -n), any
  * directory entries left in this database are reset during final cleanup
@@ -989,13 +908,8 @@ map_dev(arcn, dev_mask, ino_mask)
  *     0 is created ok, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 atdir_start(void)
-#else
-int
-atdir_start()
-#endif
 {
        if (atab != NULL)
                return(0);
@@ -1014,16 +928,11 @@ atdir_start()
  *     entries are for directories READ by pax
  */
 
-#ifdef __STDC__
 void
 atdir_end(void)
-#else
-void
-atdir_end()
-#endif
 {
-       register ATDIR *pt;
-       register int i;
+       ATDIR *pt;
+       int i;
 
        if (atab == NULL)
                return;
@@ -1050,21 +959,11 @@ atdir_end()
  *     and chained by inode number. This is for directories READ by pax
  */
 
-#ifdef __STDC__
 void
 add_atdir(char *fname, dev_t dev, ino_t ino, time_t mtime, time_t atime)
-#else
-void
-add_atdir(fname, dev, ino, mtime, atime)
-       char *fname;
-       dev_t dev;
-       ino_t ino;
-       time_t mtime;
-       time_t atime;
-#endif
 {
-       register ATDIR *pt;
-       register u_int indx;
+       ATDIR *pt;
+       u_int indx;
 
        if (atab == NULL)
                return;
@@ -1074,7 +973,7 @@ add_atdir(fname, dev, ino, mtime, atime)
         * return (the older entry always has the correct time). The only
         * way this will happen is when the same subtree can be traversed by
         * different args to pax and the -n option is aborting fts out of a
-        * subtree before all the post-order visits have been made).
+        * subtree before all the post-order visits have been made.
         */
        indx = ((unsigned)ino) % A_TAB_SZ;
        if ((pt = atab[indx]) != NULL) {
@@ -1122,21 +1021,12 @@ add_atdir(fname, dev, ino, mtime, atime)
  *     0 if found, -1 if not found.
  */
 
-#ifdef __STDC__
 int
 get_atdir(dev_t dev, ino_t ino, time_t *mtime, time_t *atime)
-#else
-int
-get_atdir(dev, ino, mtime, atime)
-       dev_t dev;
-       ino_t ino;
-       time_t *mtime;
-       time_t *atime;
-#endif
 {
-       register ATDIR *pt;
-       register ATDIR **ppt;
-       register u_int indx;
+       ATDIR *pt;
+       ATDIR **ppt;
+       u_int indx;
 
        if (atab == NULL)
                return(-1);
@@ -1206,31 +1096,18 @@ get_atdir(dev, ino, mtime, atime)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 dir_start(void)
-#else
-int
-dir_start()
-#endif
 {
-       char *pt;
-
-       if (dirfd != -1)
+       if (dirp != NULL)
                return(0);
 
-       /*
-        * unlink the file so it goes away at termination by itself
-        */
-       pt = strdup("/tmp/paxXXXXXX");
-       if ((dirfd = mkstemp(pt)) >= 0) {
-               (void)unlink(pt);
-               free(pt);
-               return(0);
+       dirsize = DIRP_SIZE;
+       if ((dirp = malloc(dirsize * sizeof(DIRDATA))) == NULL) {
+               paxwarn(1, "Unable to allocate memory for directory times");
+               return(-1);
        }
-       paxwarn(1, "Unable to create temporary file for directory times: %s", pt);
-       free(pt);
-       return(-1);
+       return(0);
 }
 
 /*
@@ -1246,48 +1123,35 @@ dir_start()
  *     pax spec)
  */
 
-#ifdef __STDC__
-void
-add_dir(char *name, int nlen, struct stat *psb, int frc_mode)
-#else
 void
-add_dir(name, nlen, psb, frc_mode)
-       char *name;
-       int nlen;
-       struct stat *psb;
-       int frc_mode;
-#endif
+add_dir(char *name, struct stat *psb, int frc_mode)
 {
-       DIRDATA dblk;
+       DIRDATA *dblk;
 
-       if (dirfd < 0)
+       if (dirp == NULL)
                return;
 
-       /*
-        * get current position (where file name will start) so we can store it
-        * in the trailer
-        */
-       if ((dblk.npos = lseek(dirfd, 0L, SEEK_CUR)) < 0) {
-               paxwarn(1,"Unable to store mode and times for directory: %s",name);
-               return;
+       if (dircnt == dirsize) {
+               dblk = realloc(dirp, 2 * dirsize * sizeof(DIRDATA));
+               if (dblk == NULL) {
+                       paxwarn(1, "Unable to store mode and times for created"
+                           " directory: %s", name);
+                       return;
+               }
+               dirp = dblk;
+               dirsize *= 2;
        }
-
-       /*
-        * write the file name followed by the trailer
-        */
-       dblk.nlen = nlen + 1;
-       dblk.mode = psb->st_mode & 0xffff;
-       dblk.mtime = psb->st_mtime;
-       dblk.atime = psb->st_atime;
-       dblk.frc_mode = frc_mode;
-       if ((write(dirfd, name, dblk.nlen) == dblk.nlen) &&
-           (write(dirfd, (char *)&dblk, sizeof(dblk)) == sizeof(dblk))) {
-               ++dircnt;
+       dblk = &dirp[dircnt];
+       if ((dblk->name = strdup(name)) == NULL) {
+               paxwarn(1, "Unable to store mode and times for created"
+                   " directory: %s", name);
                return;
        }
-
-       paxwarn(1,"Unable to store mode and times for created directory: %s",name);
-       return;
+       dblk->mode = psb->st_mode & 0xffff;
+       dblk->mtime = psb->st_mtime;
+       dblk->atime = psb->st_atime;
+       dblk->frc_mode = frc_mode;
+       ++dircnt;
 }
 
 /*
@@ -1296,54 +1160,34 @@ add_dir(name, nlen, psb, frc_mode)
  *     by pax
  */
 
-#ifdef __STDC__
 void
 proc_dir(void)
-#else
-void
-proc_dir()
-#endif
 {
-       char name[PAXPATHLEN+1];
-       DIRDATA dblk;
-       u_long cnt;
+       DIRDATA *dblk;
+       long cnt;
 
-       if (dirfd < 0)
+       if (dirp == NULL)
                return;
        /*
         * read backwards through the file and process each directory
         */
-       for (cnt = 0; cnt < dircnt; ++cnt) {
-               /*
-                * read the trailer, then the file name, if this fails
-                * just give up.
-                */
-               if (lseek(dirfd, -((off_t)sizeof(dblk)), SEEK_CUR) < 0)
-                       break;
-               if (read(dirfd,(char *)&dblk, sizeof(dblk)) != sizeof(dblk))
-                       break;
-               if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
-                       break;
-               if (read(dirfd, name, dblk.nlen) != dblk.nlen)
-                       break;
-               if (lseek(dirfd, dblk.npos, SEEK_SET) < 0)
-                       break;
-
+       cnt = dircnt;
+       while (--cnt >= 0) {
                /*
                 * frc_mode set, make sure we set the file modes even if
                 * the user didn't ask for it (see file_subs.c for more info)
                 */
-               if (pmode || dblk.frc_mode)
-                       set_pmode(name, dblk.mode);
+               dblk = &dirp[cnt];
+               if (pmode || dblk->frc_mode)
+                       set_pmode(dblk->name, dblk->mode);
                if (patime || pmtime)
-                       set_ftime(name, dblk.mtime, dblk.atime, 0);
+                       set_ftime(dblk->name, dblk->mtime, dblk->atime, 0);
+               free(dblk->name);
        }
 
-       (void)close(dirfd);
-       dirfd = -1;
-       if (cnt != dircnt)
-               paxwarn(1,"Unable to set mode and times for created directories");
-       return;
+       free(dirp);
+       dirp = NULL;
+       dircnt = 0;
 }
 
 /*
@@ -1364,24 +1208,16 @@ proc_dir()
  *     the hash value of the string MOD (%) the table size.
  */
 
-#ifdef __STDC__
 u_int
 st_hash(char *name, int len, int tabsz)
-#else
-u_int
-st_hash(name, len, tabsz)
-       char *name;
-       int len;
-       int tabsz;
-#endif
 {
-       register char *pt;
-       register char *dest;
-       register char *end;
-       register int i;
-       register u_int key = 0;
-       register int steps;
-       register int res;
+       char *pt;
+       char *dest;
+       char *end;
+       int i;
+       u_int key = 0;
+       int steps;
+       int res;
        u_int val;
 
        /*
index 1d9c8130ba660f3938d70b40cec97d8e3f80173d..e065387e4faa4a8ec2481356009676d88259cab1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tables.h,v 1.2 1996/06/23 14:20:43 deraadt Exp $      */
+/*     $OpenBSD: tables.h,v 1.7 2004/11/29 16:23:22 otto Exp $ */
 /*     $NetBSD: tables.h,v 1.3 1995/03/21 09:07:47 cgd Exp $   */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -47,7 +43,7 @@
 /*
  * Hash Table Sizes MUST BE PRIME, if set too small performance suffers.
  * Probably safe to expect 500000 inodes per tape. Assuming good key
- * distribution (inodes) chains of under 50 long (worse case) is ok.
+ * distribution (inodes) chains of under 50 long (worst case) is ok.
  */
 #define L_TAB_SZ       2503            /* hard link hash table size */
 #define F_TAB_SZ       50503           /* file time hash table size */
@@ -55,6 +51,7 @@
 #define D_TAB_SZ       317             /* unique device mapping table */
 #define A_TAB_SZ       317             /* ftree dir access time reset table */
 #define MAXKEYLEN      64              /* max number of chars for hash */
+#define DIRP_SIZE      64              /* initial size of created dir table */
 
 /*
  * file hard link structure (hashed by dev/ino and chained) used to find the
@@ -82,7 +79,7 @@ typedef struct hrdlnk {
 typedef struct ftm {
        int             namelen;        /* file name length */
        time_t          mtime;          /* files last modification time */
-       off_t           seek;           /* loacation in scratch file */
+       off_t           seek;           /* location in scratch file */
        struct ftm      *fow;
 } FTM;
 
@@ -108,7 +105,7 @@ typedef struct namt {
  * this table. (When the inode field in the archive header are too small, we
  * remap the dev on writes to remove accidental collisions).
  *
- * The list is hashed by device number using chain collision resolution. Off of 
+ * The list is hashed by device number using chain collision resolution. Off of
  * each DEVT are linked the various remaps for this device based on those bits
  * in the inode which were truncated. For example if we are just remapping to
  * avoid a device number during an update append, off the DEVT we would have
@@ -161,15 +158,13 @@ typedef struct atdir {
  * times and/or modes). We must reset time in the reverse order of creation,
  * because entries are added  from the top of the file tree to the bottom.
  * We MUST reset times from leaf to root (it will not work the other
- * direction).  Entries are recorded into a spool file to make reverse
- * reading faster.
+ * direction).
  */
 
 typedef struct dirdata {
-       int nlen;       /* length of the directory name (includes \0) */
-       off_t npos;     /* position in file where this dir name starts */
-       mode_t mode;    /* file mode to restore */
+       char *name;     /* file name */
        time_t mtime;   /* mtime to set */
        time_t atime;   /* atime to set */
-       int frc_mode;   /* do we force mode settings? */
+       u_int16_t mode; /* file mode to restore */
+       u_int16_t frc_mode;     /* do we force mode settings? */
 } DIRDATA;
index 11ec0978d0cc5a8227eed950fe6e27ca20adc7d8..b8f9b42b3fee9b721776b7652c8902d5bbf269d2 100644 (file)
--- a/pax/tar.c
+++ b/pax/tar.c
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tar.c,v 1.12 1997/09/01 18:30:03 deraadt Exp $        */
+/*     $OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $   */
 /*     $NetBSD: tar.c,v 1.5 1995/03/21 09:07:49 cgd Exp $      */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tar.c      8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)tar.c        8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.12 1997/09/01 18:30:03 deraadt Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $";
 #endif
 #endif /* not lint */
 
@@ -62,18 +58,26 @@ static char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.12 1997/0
  * Routines for reading, writing and header identify of various versions of tar
  */
 
-static u_long tar_chksm __P((register char *, register int));
-static char *name_split __P((register char *, register int));
-static int ul_oct __P((u_long, register char *, register int, int));
-#ifndef NET2_STAT
-static int uqd_oct __P((u_quad_t, register char *, register int, int));
+static size_t expandname(char *, size_t, char **, const char *, size_t);
+static u_long tar_chksm(char *, int);
+char *name_split(char *, int);
+static int ul_oct(u_long, char *, int, int);
+#ifndef LONG_OFF_T
+static int uqd_oct(u_quad_t, char *, int, int);
 #endif
 
+static uid_t uid_nobody;
+static uid_t uid_warn;
+static gid_t gid_nobody;
+static gid_t gid_warn;
+
 /*
  * Routines common to all versions of tar
  */
 
 static int tar_nodir;                  /* do not write dirs under old tar */
+char *gnu_name_string;                 /* GNU ././@LongLink hackery name */
+char *gnu_link_string;                 /* GNU ././@LongLink hackery link */
 
 /*
  * tar_endwr()
@@ -82,13 +86,8 @@ static int tar_nodir;                        /* do not write dirs under old tar */
  *     0 if ok, -1 otherwise (what wr_skip returns)
  */
 
-#ifdef __STDC__
 int
 tar_endwr(void)
-#else
-int
-tar_endwr()
-#endif
 {
        return(wr_skip((off_t)(NULLCNT*BLKMULT)));
 }
@@ -100,13 +99,8 @@ tar_endwr()
  *     size of trailer (2 * BLKMULT)
  */
 
-#ifdef __STDC__
 off_t
 tar_endrd(void)
-#else
-off_t
-tar_endrd()
-#endif
 {
        return((off_t)(NULLCNT*BLKMULT));
 }
@@ -122,18 +116,10 @@ tar_endrd()
  *     could never contain a header.
  */
 
-#ifdef __STDC__
 int
-tar_trail(register char *buf, register int in_resync, register int *cnt)
-#else
-int
-tar_trail(buf, in_resync, cnt)
-       register char *buf;
-       register int in_resync;
-       register int *cnt;
-#endif
+tar_trail(ARCHD *ignore, char *buf, int in_resync, int *cnt)
 {
-       register int i;
+       int i;
 
        /*
         * look for all zero, trailer is two consecutive blocks of zero
@@ -173,25 +159,16 @@ tar_trail(buf, in_resync, cnt)
  *     0 if the number fit into the string, -1 otherwise
  */
 
-#ifdef __STDC__
 static int
-ul_oct(u_long val, register char *str, register int len, int term)
-#else
-static int
-ul_oct(val, str, len, term)
-       u_long val;
-       register char *str;
-       register int len;
-       int term;
-#endif
+ul_oct(u_long val, char *str, int len, int term)
 {
-       register char *pt;
+       char *pt;
 
        /*
         * term selects the appropriate character(s) for the end of the string
         */
        pt = str + len - 1;
-       switch(term) {
+       switch (term) {
        case 3:
                *pt-- = '\0';
                break;
@@ -225,7 +202,7 @@ ul_oct(val, str, len, term)
        return(0);
 }
 
-#ifndef NET2_STAT
+#ifndef LONG_OFF_T
 /*
  * uqd_oct()
  *     convert an u_quad_t to an octal string. one of many oddball field
@@ -237,25 +214,16 @@ ul_oct(val, str, len, term)
  *     0 if the number fit into the string, -1 otherwise
  */
 
-#ifdef __STDC__
 static int
-uqd_oct(u_quad_t val, register char *str, register int len, int term)
-#else
-static int
-uqd_oct(val, str, len, term)
-       u_quad_t val;
-       register char *str;
-       register int len;
-       int term;
-#endif
+uqd_oct(u_quad_t val, char *str, int len, int term)
 {
-       register char *pt;
+       char *pt;
 
        /*
         * term selects the appropriate character(s) for the end of the string
         */
        pt = str + len - 1;
-       switch(term) {
+       switch (term) {
        case 3:
                *pt-- = '\0';
                break;
@@ -293,26 +261,19 @@ uqd_oct(val, str, len, term)
 /*
  * tar_chksm()
  *     calculate the checksum for a tar block counting the checksum field as
- *     all blanks (BLNKSUM is that value pre-calculated, the sume of 8 blanks).
+ *     all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
  *     NOTE: we use len to short circuit summing 0's on write since we ALWAYS
  *     pad headers with 0.
  * Return:
  *     unsigned long checksum
  */
 
-#ifdef __STDC__
 static u_long
-tar_chksm(register char *blk, register int len)
-#else
-static u_long
-tar_chksm(blk, len)
-       register char *blk;
-       register int len;
-#endif
+tar_chksm(char *blk, int len)
 {
-       register char *stop;
-       register char *pt;
-       u_long chksm = BLNKSUM; /* inital value is checksum field sum */
+       char *stop;
+       char *pt;
+       u_long chksm = BLNKSUM; /* initial value is checksum field sum */
 
        /*
         * add the part of the block before the checksum field
@@ -348,18 +309,11 @@ tar_chksm(blk, len)
  *     0 if a tar header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
-tar_id(register char *blk, int size)
-#else
-int
-tar_id(blk, size)
-       register char *blk;
-       int size;
-#endif
+tar_id(char *blk, int size)
 {
-       register HD_TAR *hd;
-       register HD_USTAR *uhd;
+       HD_TAR *hd;
+       HD_USTAR *uhd;
 
        if (size < BLKMULT)
                return(-1);
@@ -379,6 +333,7 @@ tar_id(blk, size)
                return(-1);
        if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT))
                return(-1);
+       force_one_volume = 1;
        return(0);
 }
 
@@ -389,13 +344,8 @@ tar_id(blk, size)
  *     0 if ok -1 otherwise
  */
 
-#ifdef __STDC__
 int
 tar_opt(void)
-#else
-int
-tar_opt()
-#endif
 {
        OPLIST *opt;
 
@@ -431,39 +381,40 @@ tar_opt()
  *     0
  */
 
-#ifdef __STDC__
 int
-tar_rd(register ARCHD *arcn, register char *buf)
-#else
-int
-tar_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+tar_rd(ARCHD *arcn, char *buf)
 {
-       register HD_TAR *hd;
-       register char *pt;
+       HD_TAR *hd;
+       char *pt;
 
        /*
         * we only get proper sized buffers passed to us
         */
        if (tar_id(buf, BLKMULT) < 0)
                return(-1);
+       memset(arcn, 0, sizeof(*arcn));
        arcn->org_name = arcn->name;
        arcn->sb.st_nlink = 1;
-       arcn->pat = NULL;
 
        /*
         * copy out the name and values in the stat buffer
         */
        hd = (HD_TAR *)buf;
-       arcn->nlen = l_strncpy(arcn->name, hd->name, sizeof(arcn->name) - 1);
-       arcn->name[arcn->nlen] = '\0';
+       if (hd->linkflag != LONGLINKTYPE && hd->linkflag != LONGNAMETYPE) {
+               arcn->nlen = expandname(arcn->name, sizeof(arcn->name),
+                   &gnu_name_string, hd->name, sizeof(hd->name));
+               arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                   &gnu_link_string, hd->linkname, sizeof(hd->linkname));
+       }
        arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) &
            0xfff);
        arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
        arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
-       arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
        arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
 
@@ -474,16 +425,13 @@ tar_rd(arcn, buf)
        pt = &(arcn->name[arcn->nlen - 1]);
        arcn->pad = 0;
        arcn->skip = 0;
-       switch(hd->linkflag) {
+       switch (hd->linkflag) {
        case SYMTYPE:
                /*
                 * symbolic link, need to get the link name and set the type in
                 * the st_mode so -v printing will look correct.
                 */
                arcn->type = PAX_SLK;
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
                arcn->sb.st_mode |= S_IFLNK;
                break;
        case LNKTYPE:
@@ -493,9 +441,6 @@ tar_rd(arcn, buf)
                 */
                arcn->type = PAX_HLK;
                arcn->sb.st_nlink = 2;
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
 
                /*
                 * no idea of what type this thing really points at, but
@@ -503,6 +448,17 @@ tar_rd(arcn, buf)
                 */
                arcn->sb.st_mode |= S_IFREG;
                break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
+               /*
+                * GNU long link/file; we tag these here and let the
+                * pax internals deal with it -- too ugly otherwise.
+                */
+               arcn->type =
+                   hd->linkflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
+               break;
        case DIRTYPE:
                /*
                 * It is a directory, set the mode for -v printing
@@ -510,8 +466,6 @@ tar_rd(arcn, buf)
                arcn->type = PAX_DIR;
                arcn->sb.st_mode |= S_IFDIR;
                arcn->sb.st_nlink = 2;
-               arcn->ln_name[0] = '\0';
-               arcn->ln_nlen = 0;
                break;
        case AREGTYPE:
        case REGTYPE:
@@ -531,7 +485,7 @@ tar_rd(arcn, buf)
                } else {
                        /*
                         * have a file that will be followed by data. Set the
-                        * skip value to the size field and caluculate the size
+                        * skip value to the size field and calculate the size
                         * of the padding.
                         */
                        arcn->type = PAX_REG;
@@ -546,7 +500,7 @@ tar_rd(arcn, buf)
         * strip off any trailing slash.
         */
        if (*pt == '/') {
-               *pt = '\0'; 
+               *pt = '\0';
                --arcn->nlen;
        }
        return(0);
@@ -564,23 +518,17 @@ tar_rd(arcn, buf)
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
-int
-tar_wr(register ARCHD *arcn)
-#else
 int
-tar_wr(arcn)
-       register ARCHD *arcn;
-#endif
+tar_wr(ARCHD *arcn)
 {
-       register HD_TAR *hd;
+       HD_TAR *hd;
        int len;
        char hdblk[sizeof(HD_TAR)];
 
        /*
         * check for those file system types which tar cannot store
         */
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_DIR:
                /*
                 * user asked that dirs not be written to the archive
@@ -627,26 +575,25 @@ tar_wr(arcn)
        }
 
        /*
-        * copy the data out of the ARCHD into the tar header based on the type
-        * of the file. Remember many tar readers want the unused fields to be
-        * padded with zero. We set the linkflag field (type), the linkname
-        * (or zero if not used),the size, and set the padding (if any) to be
-        * added after the file data (0 for all other types, as they only have
-        * a header)
+        * Copy the data out of the ARCHD into the tar header based on the type
+        * of the file. Remember, many tar readers want all fields to be
+        * padded with zero so we zero the header first.  We then set the
+        * linkflag field (type), the linkname, the size, and set the padding
+        * (if any) to be added after the file data (0 for all other types,
+        * as they only have a header).
         */
+       memset(hdblk, 0, sizeof(hdblk));
        hd = (HD_TAR *)hdblk;
-       l_strncpy(hd->name, arcn->name, sizeof(hd->name) - 1);
-       hd->name[sizeof(hd->name) - 1] = '\0';
+       strlcpy(hd->name, arcn->name, sizeof(hd->name));
        arcn->pad = 0;
 
        if (arcn->type == PAX_DIR) {
                /*
                 * directories are the same as files, except have a filename
-                * that ends with a /, we add the slash here. No data follows,
+                * that ends with a /, we add the slash here. No data follows
                 * dirs, so no pad.
                 */
                hd->linkflag = AREGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
                hd->name[len-1] = '/';
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
@@ -655,8 +602,7 @@ tar_wr(arcn)
                 * no data follows this file, so no pad
                 */
                hd->linkflag = SYMTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+               strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
        } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) {
@@ -664,8 +610,7 @@ tar_wr(arcn)
                 * no data follows this file, so no pad
                 */
                hd->linkflag = LNKTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
+               strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
                if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1))
                        goto out;
        } else {
@@ -673,8 +618,7 @@ tar_wr(arcn)
                 * data follows this file, so set the pad
                 */
                hd->linkflag = AREGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_oct((u_long)arcn->sb.st_size, hd->size,
                    sizeof(hd->size), 1)) {
 #              else
@@ -731,13 +675,8 @@ tar_wr(arcn)
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_strd(void)
-#else
-int
-ustar_strd()
-#endif
 {
        if ((usrtb_start() < 0) || (grptb_start() < 0))
                return(-1);
@@ -751,13 +690,8 @@ ustar_strd()
  *     0 if ok, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_stwr(void)
-#else
-int
-ustar_stwr()
-#endif
 {
        if ((uidtb_start() < 0) || (gidtb_start() < 0))
                return(-1);
@@ -772,17 +706,10 @@ ustar_stwr()
  *     0 if a ustar header, -1 otherwise
  */
 
-#ifdef __STDC__
 int
 ustar_id(char *blk, int size)
-#else
-int
-ustar_id(blk, size)
-       char *blk;
-       int size;
-#endif
 {
-       register HD_USTAR *hd;
+       HD_USTAR *hd;
 
        if (size < BLKMULT)
                return(-1);
@@ -811,19 +738,12 @@ ustar_id(blk, size)
  *     0
  */
 
-#ifdef __STDC__
-int
-ustar_rd(register ARCHD *arcn, register char *buf)
-#else
 int
-ustar_rd(arcn, buf)
-       register ARCHD *arcn;
-       register char *buf;
-#endif
+ustar_rd(ARCHD *arcn, char *buf)
 {
-       register HD_USTAR *hd;
-       register char *dest;
-       register int cnt = 0;
+       HD_USTAR *hd;
+       char *dest;
+       int cnt = 0;
        dev_t devmajor;
        dev_t devminor;
 
@@ -832,10 +752,9 @@ ustar_rd(arcn, buf)
         */
        if (ustar_id(buf, BLKMULT) < 0)
                return(-1);
+       memset(arcn, 0, sizeof(*arcn));
        arcn->org_name = arcn->name;
        arcn->sb.st_nlink = 1;
-       arcn->pat = NULL;
-       arcn->nlen = 0;
        hd = (HD_USTAR *)buf;
 
        /*
@@ -844,13 +763,20 @@ ustar_rd(arcn, buf)
         */
        dest = arcn->name;
        if (*(hd->prefix) != '\0') {
-               cnt = l_strncpy(dest, hd->prefix, sizeof(arcn->name) - 2);
+               cnt = strlcpy(dest, hd->prefix, sizeof(arcn->name) - 1);
                dest += cnt;
                *dest++ = '/';
                cnt++;
+       } else {
+               cnt = 0;
+       }
+
+       if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
+               arcn->nlen = expandname(dest, sizeof(arcn->name) - cnt,
+                   &gnu_name_string, hd->name, sizeof(hd->name));
+               arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
+                   &gnu_link_string, hd->linkname, sizeof(hd->linkname));
        }
-       arcn->nlen = cnt + l_strncpy(dest, hd->name, sizeof(arcn->name) - cnt);
-       arcn->name[arcn->nlen] = '\0';
 
        /*
         * follow the spec to the letter. we should only have mode bits, strip
@@ -858,7 +784,11 @@ ustar_rd(arcn, buf)
         */
        arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
            0xfff);
-       arcn->sb.st_size = (size_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#ifdef LONG_OFF_T
+       arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
+#else
+       arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
+#endif
        arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
        arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
 
@@ -878,8 +808,6 @@ ustar_rd(arcn, buf)
        /*
         * set the defaults, these may be changed depending on the file type
         */
-       arcn->ln_name[0] = '\0';
-       arcn->ln_nlen = 0;
        arcn->pad = 0;
        arcn->skip = 0;
        arcn->sb.st_rdev = (dev_t)0;
@@ -887,7 +815,7 @@ ustar_rd(arcn, buf)
        /*
         * set the mode and PAX type according to the typeflag in the header
         */
-       switch(hd->typeflag) {
+       switch (hd->typeflag) {
        case FIFOTYPE:
                arcn->type = PAX_FIF;
                arcn->sb.st_mode |= S_IFIFO;
@@ -934,12 +862,17 @@ ustar_rd(arcn, buf)
                        arcn->sb.st_mode |= S_IFREG;
                        arcn->sb.st_nlink = 2;
                }
+               break;
+       case LONGLINKTYPE:
+       case LONGNAMETYPE:
                /*
-                * copy the link name
+                * GNU long link/file; we tag these here and let the
+                * pax internals deal with it -- too ugly otherwise.
                 */
-               arcn->ln_nlen = l_strncpy(arcn->ln_name, hd->linkname,
-                       sizeof(arcn->ln_name) - 1);
-               arcn->ln_name[arcn->ln_nlen] = '\0';
+               arcn->type =
+                   hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
+               arcn->pad = TAR_PAD(arcn->sb.st_size);
+               arcn->skip = arcn->sb.st_size;
                break;
        case CONTTYPE:
        case AREGTYPE:
@@ -970,18 +903,15 @@ ustar_rd(arcn, buf)
  *     data to write after the header, -1 if archive write failed
  */
 
-#ifdef __STDC__
-int
-ustar_wr(register ARCHD *arcn)
-#else
 int
-ustar_wr(arcn)
-       register ARCHD *arcn;
-#endif
+ustar_wr(ARCHD *arcn)
 {
-       register HD_USTAR *hd;
-       register char *pt;
+       HD_USTAR *hd;
+       char *pt;
        char hdblk[sizeof(HD_USTAR)];
+       mode_t mode12only;
+       int term_char=3;        /* orignal setting */
+       term_char=1;            /* To pass conformance tests 274, 301 */
 
        /*
         * check for those file system types ustar cannot store
@@ -995,8 +925,12 @@ ustar_wr(arcn)
         * check the length of the linkname
         */
        if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
-           (arcn->type == PAX_HRG)) && (arcn->ln_nlen >= sizeof(hd->linkname))){
+           (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
                paxwarn(1, "Link name too long for ustar %s", arcn->ln_name);
+               /*
+                * Conformance: test pax:285 wants error code to be non-zero, and
+                * test tar:12 wants error code from pax to be 0
+                */
                return(1);
        }
 
@@ -1008,8 +942,16 @@ ustar_wr(arcn)
                paxwarn(1, "File name too long for ustar %s", arcn->name);
                return(1);
        }
+
+       /*
+        * zero out the header so we don't have to worry about zero fill below
+        */
+       memset(hdblk, 0, sizeof(hdblk));
        hd = (HD_USTAR *)hdblk;
        arcn->pad = 0L;
+       /* To pass conformance tests 274/301, always set these fields to "zero" */
+       ul_oct(0, hd->devmajor, sizeof(hd->devmajor), term_char);
+       ul_oct(0, hd->devminor, sizeof(hd->devminor), term_char);
 
        /*
         * split the name, or zero out the prefix
@@ -1020,26 +962,27 @@ ustar_wr(arcn)
                 * occur, we remove the / and copy the first part to the prefix
                 */
                *pt = '\0';
-               l_strncpy(hd->prefix, arcn->name, sizeof(hd->prefix) - 1);
+               strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix));
                *pt++ = '/';
-       } else
-               memset(hd->prefix, 0, sizeof(hd->prefix));
+       }
 
        /*
         * copy the name part. this may be the whole path or the part after
         * the prefix
         */
-       l_strncpy(hd->name, pt, sizeof(hd->name) - 1);
-       hd->name[sizeof(hd->name) - 1] = '\0';
+       if (strlen(pt) == sizeof(hd->name)) {   /* must account for name just fits in buffer */
+               strncpy(hd->name, pt, sizeof(hd->name));
+       } else {
+               strlcpy(hd->name, pt, sizeof(hd->name));
+       }
 
        /*
         * set the fields in the header that are type dependent
         */
-       switch(arcn->type) {
+       switch (arcn->type) {
        case PAX_DIR:
                hd->typeflag = DIRTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
                        goto out;
                break;
        case PAX_CHR:
@@ -1048,15 +991,16 @@ ustar_wr(arcn)
                        hd->typeflag = CHRTYPE;
                else
                        hd->typeflag = BLKTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+               if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
+                  sizeof(hd->devmajor), term_char) ||
+                  ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
+                  sizeof(hd->devminor), term_char) ||
+                  ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
                        goto out;
-
                break;
        case PAX_FIF:
                hd->typeflag = FIFOTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
-               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
                        goto out;
                break;
        case PAX_SLK:
@@ -1066,9 +1010,12 @@ ustar_wr(arcn)
                        hd->typeflag = SYMTYPE;
                else
                        hd->typeflag = LNKTYPE;
-               l_strncpy(hd->linkname,arcn->ln_name, sizeof(hd->linkname) - 1);
-               hd->linkname[sizeof(hd->linkname) - 1] = '\0';
-               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3))
+               if (strlen(arcn->ln_name) == sizeof(hd->linkname)) {    /* must account for name just fits in buffer */
+                       strncpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               } else {
+                       strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
+               }
+               if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
                        goto out;
                break;
        case PAX_REG:
@@ -1081,14 +1028,13 @@ ustar_wr(arcn)
                        hd->typeflag = CONTTYPE;
                else
                        hd->typeflag = REGTYPE;
-               memset(hd->linkname, 0, sizeof(hd->linkname));
                arcn->pad = TAR_PAD(arcn->sb.st_size);
-#              ifdef NET2_STAT
+#              ifdef LONG_OFF_T
                if (ul_oct((u_long)arcn->sb.st_size, hd->size,
-                   sizeof(hd->size), 3)) {
+                   sizeof(hd->size), term_char)) {
 #              else
                if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
-                   sizeof(hd->size), 3)) {
+                   sizeof(hd->size), term_char)) {
 #              endif
                        paxwarn(1,"File is too long for ustar %s",arcn->org_name);
                        return(1);
@@ -1096,27 +1042,49 @@ ustar_wr(arcn)
                break;
        }
 
-               /* set devmajor and devminor for all types as per spec */
-       if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
-          sizeof(hd->devmajor), 3) ||
-          ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
-                 sizeof(hd->devminor), 3))
-               goto out;
-
-       l_strncpy(hd->magic, TMAGIC, TMAGLEN);
-       l_strncpy(hd->version, TVERSION, TVERSLEN);
+       strncpy(hd->magic, TMAGIC, TMAGLEN);
+       strncpy(hd->version, TVERSION, TVERSLEN);
 
        /*
         * set the remaining fields. Some versions want all 16 bits of mode
         * we better humor them (they really do not meet spec though)....
         */
-       if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) ||
-           ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3)  ||
-           ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) ||
-           ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3))
+       if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), term_char)) {
+               if (uid_nobody == 0) {
+                       if (uid_name("nobody", &uid_nobody) == -1)
+                               goto out;
+               }
+               if (uid_warn != arcn->sb.st_uid) {
+                       uid_warn = arcn->sb.st_uid;
+                       paxwarn(1,
+                           "Ustar header field is too small for uid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_uid);
+               }
+               if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), term_char))
+                       goto out;
+       }
+       if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), term_char)) {
+               if (gid_nobody == 0) {
+                       if (gid_name("nobody", &gid_nobody) == -1)
+                               goto out;
+               }
+               if (gid_warn != arcn->sb.st_gid) {
+                       gid_warn = arcn->sb.st_gid;
+                       paxwarn(1,
+                           "Ustar header field is too small for gid %lu, "
+                           "using nobody", (u_long)arcn->sb.st_gid);
+               }
+               if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), term_char))
+                       goto out;
+       }
+       /* However, Unix conformance tests do not like MORE than 12 mode bits:
+          remove all beyond (see definition of stat.st_mode structure)         */
+       mode12only = ((u_long)arcn->sb.st_mode) & 0x00000fff;
+       if (ul_oct((u_long)mode12only, hd->mode, sizeof(hd->mode), term_char) ||
+           ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char))
                goto out;
-       l_strncpy(hd->uname,name_uid(arcn->sb.st_uid, 0),sizeof(hd->uname));
-       l_strncpy(hd->gname,name_gid(arcn->sb.st_gid, 0),sizeof(hd->gname));
+       strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
+       strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
 
        /*
         * calculate and store the checksum write the header to the archive
@@ -1124,7 +1092,7 @@ ustar_wr(arcn)
         * needs to be written
         */
        if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
-          sizeof(hd->chksum), 3))
+          sizeof(hd->chksum), term_char))
                goto out;
        if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
                return(-1);
@@ -1135,7 +1103,7 @@ ustar_wr(arcn)
        return(1);
 
     out:
-       /*
+       /*
         * header field is out of range
         */
        paxwarn(1, "Ustar header field is too small for %s", arcn->org_name);
@@ -1154,34 +1122,29 @@ ustar_wr(arcn)
  *     the file name is too long
  */
 
-#ifdef __STDC__
-static char *
-name_split(register char *name, register int len)
-#else
-static char *
-name_split(name, len)
-       register char *name;
-       register int len;
-#endif
+char *
+name_split(char *name, int len)
 {
-       register char *start;
+       char *start;
 
        /*
         * check to see if the file name is small enough to fit in the name
         * field. if so just return a pointer to the name.
         */
-       if (len < TNMSZ)
+       if (len <= TNMSZ)
                return(name);
        if (len > (TPFSZ + TNMSZ))
                return(NULL);
 
        /*
         * we start looking at the biggest sized piece that fits in the name
-        * field. We walk foward looking for a slash to split at. The idea is
+        * field. We walk forward looking for a slash to split at. The idea is
         * to find the biggest piece to fit in the name field (or the smallest
         * prefix we can find)
         */
-       start = name + len - TNMSZ;
+       start = name + len - TNMSZ -1;
+       if ((*start == '/') && (start == name))
+               ++start;        /* 101 byte paths with leading '/' are dinged otherwise */
        while ((*start != '\0') && (*start != '/'))
                ++start;
 
@@ -1207,3 +1170,27 @@ name_split(name, len)
         */
        return(start);
 }
+
+static size_t
+expandname(char *buf, size_t len, char **gnu_name, const char *name, size_t name_len)
+{
+       size_t nlen;
+
+       if (*gnu_name) {
+               if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
+                       nlen = len - 1;
+               free(*gnu_name);
+               *gnu_name = NULL;
+       } else {
+               if (name_len < len) {
+                       /* name may not be null terminated: it might be as big as the
+                          field,  so copy is limited to the max size of the header field */
+                       if ((nlen = strlcpy(buf, name, name_len+1)) >= name_len+1)
+                               nlen = name_len;
+               } else {
+                       if ((nlen = strlcpy(buf, name, len)) >= len)
+                               nlen = len - 1;
+               }
+       }
+       return(nlen);
+}
index 79a8ce49d89b526de40bb5a8ba10cd9444d9532a..61bc6e133366ca0cc110e2b4f0f8e15294c05546 100644 (file)
--- a/pax/tar.h
+++ b/pax/tar.h
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tar.h,v 1.5 1997/04/16 03:50:25 millert Exp $ */
+/*     $OpenBSD: tar.h,v 1.7 2003/06/02 23:32:09 millert Exp $ */
 /*     $NetBSD: tar.h,v 1.3 1995/03/21 09:07:51 cgd Exp $      */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
 #define        FIFOTYPE        '6'             /* FIFO */
 #define        CONTTYPE        '7'             /* high perf file */
 
+#define        PAXXTYPE        'x'             /* pax format extended header */
+#define        PAXGTYPE        'g'             /* pax format global extended header */
+
+/*
+ * GNU tar compatibility;
+ */
+#define        LONGLINKTYPE    'K'             /* Long Symlink */
+#define        LONGNAMETYPE    'L'             /* Long File */
+
 /*
  * Mode field encoding of the different file types - values in octal
  */
index 61f4e78d5655a4d183b61d67dc956d2bf4d7b280..c72ec8eb388c77deb4c414c181cfababefd4a875 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tty_subs.c,v 1.5 1997/07/25 18:58:39 mickey Exp $     */
+/*     $OpenBSD: tty_subs.c,v 1.12 2003/06/02 23:32:09 millert Exp $   */
 /*     $NetBSD: tty_subs.c,v 1.5 1995/03/21 09:07:52 cgd Exp $ */
 
 /*-
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
@@ -40,9 +36,9 @@
 
 #ifndef lint
 #if 0
-static char sccsid[] = "@(#)tty_subs.c 8.2 (Berkeley) 4/18/94";
+static const char sccsid[] = "@(#)tty_subs.c   8.2 (Berkeley) 4/18/94";
 #else
-static char rcsid[] __attribute__((__unused__))  = "$OpenBSD: tty_subs.c,v 1.5 1997/07/25 18:58:39 mickey Exp $";
+static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tty_subs.c,v 1.12 2003/06/02 23:32:09 millert Exp $";
 #endif
 #endif /* not lint */
 
@@ -58,11 +54,7 @@ static char rcsid[] __attribute__((__unused__))  = "$OpenBSD: tty_subs.c,v 1.5 1
 #include <string.h>
 #include "pax.h"
 #include "extern.h"
-#ifdef __STDC__
 #include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
 
 /*
  * routines that deal with I/O to and from the user
@@ -74,17 +66,12 @@ static FILE *ttyinf = NULL;         /* input pointing at control tty */
 
 /*
  * tty_init()
- *     try to open the controlling termina (if any) for this process. if the
+ *     try to open the controlling terminal (if any) for this process. if the
  *     open fails, future ops that require user input will get an EOF
  */
 
-#ifdef __STDC__
 int
 tty_init(void)
-#else
-int
-tty_init()
-#endif
 {
        int ttyfd;
 
@@ -110,24 +97,16 @@ tty_init()
  *     if there is no controlling terminal, just return.
  */
 
-#ifdef __STDC__
 void
-tty_prnt(char *fmt, ...)
-#else
-void
-tty_prnt(fmt, va_alist)
-       char *fmt;
-       va_dcl
-#endif
+tty_prnt(const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
-       if (ttyoutf == NULL)
+       if (ttyoutf == NULL) {
+               va_end(ap);
                return;
+       }
        (void)vfprintf(ttyoutf, fmt, ap);
        va_end(ap);
        (void)fflush(ttyoutf);
@@ -141,17 +120,10 @@ tty_prnt(fmt, va_alist)
  *     0 if data was read, -1 otherwise.
  */
 
-#ifdef __STDC__
 int
 tty_read(char *str, int len)
-#else
-int
-tty_read(str, len)
-       char *str;
-       int len;
-#endif
 {
-       register char *pt;
+       char *pt;
 
        if ((--len <= 0) || (ttyinf == NULL) || (fgets(str,len,ttyinf) == NULL))
                return(-1);
@@ -171,30 +143,20 @@ tty_read(str, len)
  *     will be non-zero.
  */
 
-#ifdef __STDC__
-void
-paxwarn(int set, char *fmt, ...)
-#else
 void
-paxwarn(set, fmt, va_alist)
-       int set;
-       char *fmt;
-       va_dcl
-#endif
+paxwarn(int set, const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
-       if (set)
+       if (set && (pax_invalid_action==0))
                exit_val = 1;
        /*
         * when vflag we better ship out an extra \n to get this message on a
         * line by itself
         */
        if (vflag && vfpart) {
+               (void)fflush(listf);
                (void)fputc('\n', stderr);
                vfpart = 0;
        }
@@ -210,24 +172,12 @@ paxwarn(set, fmt, va_alist)
  *     will be non-zero.
  */
 
-#ifdef __STDC__
-void
-syswarn(int set, int errnum, char *fmt, ...)
-#else
 void
-syswarn(set, errnum, fmt, va_alist)
-       int set;
-       int errnum;
-       char *fmt;
-       va_dcl
-#endif
+syswarn(int set, int errnum, const char *fmt, ...)
 {
        va_list ap;
-#      ifdef __STDC__
+
        va_start(ap, fmt);
-#      else
-       va_start(ap);
-#      endif
        if (set)
                exit_val = 1;
        /*
@@ -235,6 +185,7 @@ syswarn(set, errnum, fmt, va_alist)
         * line by itself
         */
        if (vflag && vfpart) {
+               (void)fflush(listf);
                (void)fputc('\n', stderr);
                vfpart = 0;
        }
@@ -246,6 +197,6 @@ syswarn(set, errnum, fmt, va_alist)
         * format and print the errno
         */
        if (errnum > 0)
-               (void)fprintf(stderr, " <%s>", strerror(errnum));
+               (void)fprintf(stderr, ": %s", strerror(errnum));
        (void)fputc('\n', stderr);
 }
diff --git a/rm/rm.c b/rm/rm.c
index c5c4da57ba28eb3e2ec516867f195686c636ca76..def4a2f30dbc54a7ddaffc8334444e7b10f2de82 100644 (file)
--- a/rm/rm.c
+++ b/rm/rm.c
@@ -61,6 +61,8 @@ static const char rcsid[] =
 #include <unistd.h>
 
 #ifdef __APPLE__
+#include <pwd.h>
+#include <grp.h>
 #include "get_compat.h"
 #else
 #define COMPAT_MODE(func, mode) 1
@@ -93,6 +95,9 @@ main(argc, argv)
        int ch, rflag;
        char *p;
 
+       if (argc < 1)
+               usage();
+
        /*
         * Test for the special case where the utility is called as
         * "unlink", for which the functionality provided is greatly
@@ -310,6 +315,7 @@ err:
        }
        if (errno)
                err(1, "fts_read");
+       fts_close(fts);
 }
 
 void
index e6b0f15c205e5042531025e597c2f5610bce7a72..3f9dac9a3d3d01522f56bb99f9bc96c75c77447f 100644 (file)
@@ -61,8 +61,8 @@ or
 .Sh SEE ALSO
 .Xr compress 1 ,
 .Xr mail 1 ,
-.Xr uuencode 1 ,
-.Xr tar 1
+.Xr tar 1 ,
+.Xr uuencode 1
 .Sh BUGS
 .Nm
 makes no provisions for special types of files or files containing
index 550d1486418e68150163712e79d66facd094710c..5bad274801071e1c69303db6a8b801988f2c836a 100644 (file)
@@ -16,6 +16,7 @@ CFILES = stat.c
 
 OTHERSRCS = Makefile Makefile.preamble Makefile.postamble stat.1
 
+OTHER_CFLAGS = -D__FBSDID=__RCSID
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
 CODE_GEN_STYLE = DYNAMIC
index 4f4a78428867fd6a64dfad4dc663b27e71ac5eb4..79c774fde22c2761b30476d0acce1b81227d1acf 100644 (file)
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/usr.bin/stat/stat.1,v 1.6 2003/06/02 11:19:23 ru Exp $
+.\" $FreeBSD: src/usr.bin/stat/stat.1,v 1.8 2005/06/14 11:50:53 ru Exp $
 .\"
 .Dd May 8, 2003
 .Dt STAT 1
 .Os
 .Sh NAME
-.Nm stat ,
-.Nm readlink
+.Nm readlink ,
+.Nm stat
 .Nd display file status
 .Sh SYNOPSIS
-.Nm
+.Nm stat
 .Op Fl FLnq
 .Op Fl f Ar format | Fl l | r | s | x
 .Op Fl t Ar timefmt
 .Op Ar
 .Sh DESCRIPTION
 The
-.Nm
+.Nm stat
 utility displays information about the file pointed to by
 .Ar file .
 Read, write or execute permissions of the named file are not required, but
 all directories listed in the path name leading to the file must be
 searchable.
 If no argument is given,
-.Nm
+.Nm stat
 displays information about the file descriptor for standard input.
 .Pp
 When invoked as
@@ -77,6 +77,7 @@ with the given argument and evaluating the returned structure.
 .Pp
 The options are as follows:
 .Bl -tag -width indent
+.\" ==========
 .It Fl F
 As in
 .Xr ls 1 ,
@@ -102,20 +103,34 @@ The use of
 .Fl F
 implies
 .Fl l .
+.\" ==========
+.It Fl f Ar format
+Display information using the specified format.
+See the
+.Sx FORMATS
+section for a description of valid formats.
+.\" ==========
 .It Fl L
 Use
 .Xr stat 2
 instead of
 .Xr lstat 2 .
 The information reported by
-.Nm
+.Nm stat
 will refer to the target of
 .Ar file ,
 if file is a symbolic link, and not to
 .Ar file
 itself.
+.\" ==========
+.It Fl l
+Display output in
+.Nm ls Fl lT
+format.
+.\" ==========
 .It Fl n
 Do not force a newline to appear at the end of each piece of output.
+.\" ==========
 .It Fl q
 Suppress failure messages if calls to
 .Xr stat 2
@@ -125,15 +140,7 @@ fail.
 When run as
 .Nm readlink ,
 error messages are automatically suppressed.
-.It Fl f Ar format
-Display information using the specified format.
-See the
-.Sx FORMATS
-section for a description of valid formats.
-.It Fl l
-Display output in
-.Nm ls Fl lT
-format.
+.\" ==========
 .It Fl r
 Display raw information.
 That is, for all the fields in the
@@ -141,19 +148,22 @@ That is, for all the fields in the
 structure,
 display the raw, numerical value (for example, times in seconds since the
 epoch, etc.).
+.\" ==========
 .It Fl s
 Display information in
 .Dq "shell output" ,
 suitable for initializing variables.
-.It Fl x
-Display information in a more verbose way as known from some
-.Tn Linux
-distributions.
+.\" ==========
 .It Fl t Ar timefmt
 Display timestamps using the specified format.
 This format is
 passed directly to
 .Xr strftime 3 .
+.\" ==========
+.It Fl x
+Display information in a more verbose way as known from some
+.Tn Linux
+distributions.
 .El
 .Ss Formats
 Format strings are similar to
@@ -430,7 +440,7 @@ that points from
 to
 .Pa / ,
 you would use
-.Nm
+.Nm stat
 as follows:
 .Bd -literal -offset indent
 \*[Gt] stat -F /tmp/foo
@@ -507,13 +517,15 @@ Apr 24 16:47:35 2002 /tmp/foo
 .Xr strftime 3
 .Sh HISTORY
 The
-.Nm
+.Nm stat
 utility appeared in
-.Nx 1.6 .
+.Nx 1.6
+and
+.Fx 4.10 .
 .Sh AUTHORS
 .An -nosplit
 The
-.Nm
+.Nm stat
 utility was written by
 .An Andrew Brown
 .Aq atatat@NetBSD.org .
index 78f8107b4c663428331c1764e7fb08e25ac36845..5603a0596055d428b0c1e0327cd6822d3d53af12 100644 (file)
@@ -41,16 +41,14 @@ __RCSID("$NetBSD: stat.c,v 1.13 2003/07/25 03:21:17 atatat Exp $");
 #endif
 #endif
 
-/* Commenting FBSDID, as it is not needed in OSX.
 __FBSDID("$FreeBSD: src/usr.bin/stat/stat.c,v 1.6 2003/10/06 01:55:17 dougb Exp $");
-*/
 
 #if HAVE_CONFIG_H
 #include "config.h" 
 #else  /* HAVE_CONFIG_H */
 #define HAVE_STRUCT_STAT_ST_FLAGS 1
 #define HAVE_STRUCT_STAT_ST_GEN 1
-#define HAVE_STRUCT_STAT_ST_BIRTHTIME 0 /* was 1; not needed if ! __BSD_VISIBLE ? */
+#define HAVE_STRUCT_STAT_ST_BIRTHTIME 1
 #define HAVE_STRUCT_STAT_ST_MTIMENSEC 1
 #define HAVE_DEVNAME 1
 #endif /* HAVE_CONFIG_H */
@@ -69,6 +67,12 @@ __FBSDID("$FreeBSD: src/usr.bin/stat/stat.c,v 1.6 2003/10/06 01:55:17 dougb Exp
 #include <time.h>
 #include <unistd.h>
 
+#ifdef __APPLE__
+#define stat stat64
+#define fstat fstat64
+#define lstat lstat64
+#endif /* __APPLE__ */
+
 #if HAVE_STRUCT_STAT_ST_FLAGS
 #define DEF_F "%#Xf "
 #define RAW_F "%f "
@@ -110,7 +114,7 @@ __FBSDID("$FreeBSD: src/usr.bin/stat/stat.c,v 1.6 2003/10/06 01:55:17 dougb Exp
 #define LINUX_FORMAT \
        "  File: \"%N\"%n" \
        "  Size: %-11z  FileType: %HT%n" \
-       "  Mode: (%04OLp/%.10Sp)         Uid: (%5u/%8Su)  Gid: (%5g/%8Sg)%n" \
+       "  Mode: (%04OA/%.10Sp)         Uid: (%5u/%8Su)  Gid: (%5g/%8Sg)%n" \
        "Device: %Hd,%Ld   Inode: %i    Links: %l%n" \
        "Access: %Sa%n" \
        "Modify: %Sm%n" \
@@ -162,6 +166,7 @@ __FBSDID("$FreeBSD: src/usr.bin/stat/stat.c,v 1.6 2003/10/06 01:55:17 dougb Exp
 #define SHOW_st_dev    'd'
 #define SHOW_st_ino    'i'
 #define SHOW_st_mode   'p'
+#define SHOW_st_mode2  'A'
 #define SHOW_st_nlink  'l'
 #define SHOW_st_uid    'u'
 #define SHOW_st_gid    'g'
@@ -487,6 +492,7 @@ output(const struct stat *st, const char *file,
                        fmtcase(what, SHOW_st_dev);
                        fmtcase(what, SHOW_st_ino);
                        fmtcase(what, SHOW_st_mode);
+                       fmtcase(what, SHOW_st_mode2);
                        fmtcase(what, SHOW_st_nlink);
                        fmtcase(what, SHOW_st_uid);
                        fmtcase(what, SHOW_st_gid);
@@ -601,6 +607,7 @@ format1(const struct stat *st,
                        ofmt = FMTF_UNSIGNED;
                break;
        case SHOW_st_mode:
+       case SHOW_st_mode2:
                small = (sizeof(st->st_mode) == 4);
                data = st->st_mode;
                strmode(st->st_mode, smode);
@@ -608,6 +615,8 @@ format1(const struct stat *st,
                l = strlen(sdata);
                if (sdata[l - 1] == ' ')
                        sdata[--l] = '\0';
+               if (what == SHOW_st_mode2)
+                       data &= 07777;
                if (hilo == HIGH_PIECE) {
                        data >>= 12;
                        sdata += 1;
diff --git a/tcopy/Makefile b/tcopy/Makefile
deleted file mode 100644 (file)
index 0d2d6b1..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Generated by the NeXT Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = tcopy
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = tcopy.c
-
-OTHERSRCS = Makefile Makefile.preamble Makefile.postamble tcopy.1
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-
-
-NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/developer_cmds/Build
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/tcopy/Makefile.postamble b/tcopy/Makefile.postamble
deleted file mode 100644 (file)
index 013b558..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Postamble.Common
diff --git a/tcopy/Makefile.preamble b/tcopy/Makefile.preamble
deleted file mode 100644 (file)
index 9e10e90..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include $(CoreOSMakefiles)/ProjectBuilder/Makefile.Preamble.Common
diff --git a/tcopy/PB.project b/tcopy/PB.project
deleted file mode 100644 (file)
index d628535..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (); 
-        OTHER_LINKED = (tcopy.c); 
-        OTHER_SOURCES = (Makefile, Makefile.preamble, Makefile.postamble, tcopy.1); 
-    }; 
-    LANGUAGE = English; 
-    LOCALIZABLE_FILES = {}; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDDIR = /tmp/developer_cmds/Build; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /usr/bin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = tcopy; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/tcopy/tcopy.1 b/tcopy/tcopy.1
deleted file mode 100644 (file)
index 880d18b..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-.\" Copyright (c) 1985, 1990, 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. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. 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.
-.\"
-.\"     @(#)tcopy.1    8.2 (Berkeley) 4/17/94
-.\" $FreeBSD: src/usr.bin/tcopy/tcopy.1,v 1.15 2003/09/05 15:28:09 roam Exp $
-.\"
-.Dd April 17, 1994
-.Dt TCOPY 1
-.Os
-.Sh NAME
-.Nm tcopy
-.Nd copy and/or verify mag tapes
-.Sh SYNOPSIS
-.Nm
-.Op Fl cvx
-.Op Fl s Ar maxblk
-.Oo Ar src Op Ar dest
-.Oc
-.Sh DESCRIPTION
-The
-.Nm
-utility is designed to copy magnetic tapes.  The only assumption made
-about the tape is that there are two tape marks at the end.
-The
-.Nm
-utility with only a source tape
-.Pf ( Ar /dev/sa0
-by default) specified will print
-information about the sizes of records and tape files.  If a destination
-is specified a copy will be made of the source tape.  The blocking on the
-destination tape will be identical to that used on the source tape.  Copying
-a tape will yield the same output as if just printing the sizes.
-.Pp
-Options:
-.Bl -tag -width s_maxblk
-.It Fl c
-Copy
-.Ar src
-to
-.Ar dest
-and then verify that the two tapes are identical.
-.It Fl s Ar maxblk
-Specify a maximum block size,
-.Ar maxblk .
-.It Fl v
-Given the two tapes,
-.Ar src
-and
-.Ar dest
-verify that they are identical.
-.It Fl x
-Output all informational messages to the standard error.
-This option is useful when
-.Ar dest
-is
-.Pa /dev/stdout .
-.El
-.Sh SEE ALSO
-.Xr mtio 4
-.Sh HISTORY
-The
-.Nm
-command appeared in
-.Bx 4.3 .
-.Sh BUGS
-.Bl -item
-.It
-Writing an image of a tape to a file does not preserve much more than
-the raw data.
-Block size(s) and tape EOF marks are lost which would
-otherwise be preserved in a tape-to-tape copy.
-.It
-EOD is determined by two sequential EOF marks with no data between.
-There are old systems which typically wrote three EOF's between tape
-files.
-The
-.Nm
-utility will erroneously stop copying early in this case.
-.It
-When using the copy/verify option \-c
-.Nm
-does not rewind the tapes prior to start.
-A rewind is performed
-after writing prior to the verification stage.
-If one doesn't start
-at BOT then the comparison may not be of the intended data.
-.El
diff --git a/tcopy/tcopy.c b/tcopy/tcopy.c
deleted file mode 100644 (file)
index 8f70cbe..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 1985, 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
- * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. 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.
- */
-
-#include <sys/cdefs.h>
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1985, 1987, 1993\n\
-       The Regents of the University of California.  All rights reserved.\n";
-#endif
-
-#ifndef lint
-static const char sccsid[] = "@(#)tcopy.c      8.2 (Berkeley) 4/17/94";
-#endif
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/mtio.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define        MAXREC  (64 * 1024)
-#define        NOCOUNT (-2)
-
-int    filen, guesslen, maxblk = MAXREC;
-u_int64_t      lastrec, record, size, tsize;
-FILE   *msg;
-
-void   *getspace(int);
-void    intr(int);
-static void     usage(void);
-void    verify(int, int, char *);
-void    writeop(int, int);
-void   rewind_tape(int);
-
-int
-main(argc, argv)
-       int argc;
-       char *argv[];
-{
-       register int lastnread, nread, nw, inp, outp;
-       enum {READ, VERIFY, COPY, COPYVERIFY} op = READ;
-       sig_t oldsig;
-       int ch, needeof;
-       char *buff;
-       const char *inf;
-
-       msg = stdout;
-       guesslen = 1;
-       while ((ch = getopt(argc, argv, "cs:vx")) != -1)
-               switch((char)ch) {
-               case 'c':
-                       op = COPYVERIFY;
-                       break;
-               case 's':
-                       maxblk = atoi(optarg);
-                       if (maxblk <= 0) {
-                               warnx("illegal block size");
-                               usage();
-                       }
-                       guesslen = 0;
-                       break;
-               case 'v':
-                       op = VERIFY;
-                       break;
-               case 'x':
-                       msg = stderr;
-                       break;
-               case '?':
-               default:
-                       usage();
-               }
-       argc -= optind;
-       argv += optind;
-
-       switch(argc) {
-       case 0:
-               if (op != READ)
-                       usage();
-               inf = _PATH_DEFTAPE;
-               break;
-       case 1:
-               if (op != READ)
-                       usage();
-               inf = argv[0];
-               break;
-       case 2:
-               if (op == READ)
-                       op = COPY;
-               inf = argv[0];
-               if ((outp = open(argv[1], op == VERIFY ? O_RDONLY :
-                   op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0)
-                       err(3, "%s", argv[1]);
-               break;
-       default:
-               usage();
-       }
-
-       if ((inp = open(inf, O_RDONLY, 0)) < 0)
-               err(1, "%s", inf);
-
-       buff = getspace(maxblk);
-
-       if (op == VERIFY) {
-               verify(inp, outp, buff);
-               exit(0);
-       }
-
-       if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
-               (void) signal(SIGINT, intr);
-
-       needeof = 0;
-       for (lastnread = NOCOUNT;;) {
-               if ((nread = read(inp, buff, maxblk)) == -1) {
-                       while (errno == EINVAL && (maxblk -= 1024)) {
-                               nread = read(inp, buff, maxblk);
-                               if (nread >= 0)
-                                       goto r1;
-                       }
-                       err(1, "read error, file %d, record %qu", filen, record);
-               } else if (nread != lastnread) {
-                       if (lastnread != 0 && lastnread != NOCOUNT) {
-                               if (lastrec == 0 && nread == 0)
-                                       fprintf(msg, "%qu records\n", record);
-                               else if (record - lastrec > 1)
-                                       fprintf(msg, "records %qu to %qu\n",
-                                           lastrec, record);
-                               else
-                                       fprintf(msg, "record %qu\n", lastrec);
-                       }
-                       if (nread != 0)
-                               fprintf(msg, "file %d: block size %d: ",
-                                   filen, nread);
-                       (void) fflush(stdout);
-                       lastrec = record;
-               }
-r1:            guesslen = 0;
-               if (nread > 0) {
-                       if (op == COPY || op == COPYVERIFY) {
-                               if (needeof) {
-                                       writeop(outp, MTWEOF);
-                                       needeof = 0;
-                               }
-                               nw = write(outp, buff, nread);
-                               if (nw != nread) {
-                                       if (nw == -1) {
-                                       warn("write error, file %d, record %qu", filen, record);
-                                       } else {
-                                       warnx("write error, file %d, record %qu", filen, record);
-                                       warnx("write (%d) != read (%d)", nw, nread);
-                                       }
-                                       errx(5, "copy aborted");
-                               }
-                       }
-                       size += nread;
-                       record++;
-               } else {
-                       if (lastnread <= 0 && lastnread != NOCOUNT) {
-                               fprintf(msg, "eot\n");
-                               break;
-                       }
-                       fprintf(msg,
-                           "file %d: eof after %qu records: %qu bytes\n",
-                           filen, record, size);
-                       needeof = 1;
-                       filen++;
-                       tsize += size;
-                       size = record = lastrec = 0;
-                       lastnread = 0;
-               }
-               lastnread = nread;
-       }
-       fprintf(msg, "total length: %qu bytes\n", tsize);
-       (void)signal(SIGINT, oldsig);
-       if (op == COPY || op == COPYVERIFY) {
-               writeop(outp, MTWEOF);
-               writeop(outp, MTWEOF);
-               if (op == COPYVERIFY) {
-                       rewind_tape(outp);
-                       rewind_tape(inp);
-                       verify(inp, outp, buff);
-               }
-       }
-       exit(0);
-}
-
-void
-verify(inp, outp, outb)
-       register int inp, outp;
-       register char *outb;
-{
-       register int eot, inmaxblk, inn, outmaxblk, outn;
-       register char *inb;
-
-       inb = getspace(maxblk);
-       inmaxblk = outmaxblk = maxblk;
-       for (eot = 0;; guesslen = 0) {
-               if ((inn = read(inp, inb, inmaxblk)) == -1) {
-                       if (guesslen)
-                               while (errno == EINVAL && (inmaxblk -= 1024)) {
-                                       inn = read(inp, inb, inmaxblk);
-                                       if (inn >= 0)
-                                               goto r1;
-                               }
-                       warn("read error");
-                       break;
-               }
-r1:            if ((outn = read(outp, outb, outmaxblk)) == -1) {
-                       if (guesslen)
-                               while (errno == EINVAL && (outmaxblk -= 1024)) {
-                                       outn = read(outp, outb, outmaxblk);
-                                       if (outn >= 0)
-                                               goto r2;
-                               }
-                       warn("read error");
-                       break;
-               }
-r2:            if (inn != outn) {
-                       fprintf(msg,
-                           "%s: tapes have different block sizes; %d != %d.\n",
-                           "tcopy", inn, outn);
-                       break;
-               }
-               if (!inn) {
-                       if (eot++) {
-                               fprintf(msg, "tcopy: tapes are identical.\n");
-                               return;
-                       }
-               } else {
-                       if (bcmp(inb, outb, inn)) {
-                               fprintf(msg,
-                                   "tcopy: tapes have different data.\n");
-                               break;
-                       }
-                       eot = 0;
-               }
-       }
-       exit(1);
-}
-
-void
-intr(signo)
-       int signo __unused;
-{
-       if (record) {
-               if (record - lastrec > 1)
-                       fprintf(msg, "records %qu to %qu\n", lastrec, record);
-               else
-                       fprintf(msg, "record %qu\n", lastrec);
-       }
-       fprintf(msg, "interrupt at file %d: record %qu\n", filen, record);
-       fprintf(msg, "total length: %ju bytes\n", (uintmax_t)(tsize + size));
-       exit(1);
-}
-
-void *
-getspace(blk)
-       int blk;
-{
-       void *bp;
-
-       if ((bp = malloc((size_t)blk)) == NULL)
-               errx(11, "no memory");
-       return (bp);
-}
-
-void
-writeop(fd, type)
-       int fd, type;
-{
-       struct mtop op;
-
-       op.mt_op = type;
-       op.mt_count = (daddr_t)1;
-       if (ioctl(fd, MTIOCTOP, (char *)&op) < 0)
-               err(6, "tape op");
-}
-
-static void
-usage()
-{
-       fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] [src [dest]]\n");
-       exit(1);
-}
-
-void
-rewind_tape(int fd)
-{
-       struct stat sp;
-
-       if(fstat(fd, &sp))
-               errx(12, "fstat in rewind");
-
-       /*
-        * don't want to do tape ioctl on regular files:
-        */
-       if( S_ISREG(sp.st_mode) ) {
-               if( lseek(fd, 0, SEEK_SET) == -1 )
-                       errx(13, "lseek");
-       } else
-               /*  assume its a tape   */
-               writeop(fd, MTREW);
-}
index 77ca8e9922bb8fba938714f71b273db1c6a684f0..8909d791bc6db7c8f8e20f8bd69a13372fb4eade 100644 (file)
@@ -189,11 +189,12 @@ main(int argc, char *argv[])
                        continue;
 
                /* Try reading/writing. */
-               if (!S_ISLNK(sb.st_mode) && !S_ISDIR(sb.st_mode) &&
-                   rw(*argv, &sb, fflag))
-                       rval = 1;
-               else
-                       warn("%s", *argv);
+                if (S_ISLNK(sb.st_mode) || S_ISDIR(sb.st_mode)) {
+                        warn("%s", *argv);
+                        rval = 1;
+                } else if (rw(*argv, &sb, fflag)) {
+                        rval = 1;
+                }
        }
        exit(rval);
 }