386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 12 Apr 1991 21:27:40 +0000 (13:27 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 12 Apr 1991 21:27:40 +0000 (13:27 -0800)
Work on file usr/src/usr.bin/ar/append.c
Work on file usr/src/usr.bin/ar/archive.c
Work on file usr/src/usr.bin/ar/ar.c
Work on file usr/src/usr.bin/ar/delete.c
Work on file usr/src/usr.bin/ar/contents.c
Work on file usr/src/usr.bin/ar/extern.h
Work on file usr/src/usr.bin/ar/extract.c
Work on file usr/src/usr.bin/ar/print.c
Work on file usr/src/usr.bin/ar/move.c
Work on file usr/src/usr.bin/ar/replace.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/usr.bin/ar/append.c [new file with mode: 0644]
usr/src/usr.bin/ar/ar.c [new file with mode: 0644]
usr/src/usr.bin/ar/archive.c [new file with mode: 0644]
usr/src/usr.bin/ar/contents.c [new file with mode: 0644]
usr/src/usr.bin/ar/delete.c [new file with mode: 0644]
usr/src/usr.bin/ar/extern.h [new file with mode: 0644]
usr/src/usr.bin/ar/extract.c [new file with mode: 0644]
usr/src/usr.bin/ar/move.c [new file with mode: 0644]
usr/src/usr.bin/ar/print.c [new file with mode: 0644]
usr/src/usr.bin/ar/replace.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/ar/append.c b/usr/src/usr.bin/ar/append.c
new file mode 100644 (file)
index 0000000..7dcfa8e
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)append.c   5.6 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include "archive.h"
+#include "extern.h"
+
+extern char *archive;                  /* archive name */
+
+/*
+ * append --
+ *     Append files to the archive - modifies original archive or creates
+ *     a new archive if named archive does not exist.
+ */
+append(argv)
+       char **argv;
+{
+       register int fd, afd;
+       register char *file;
+       struct stat sb;
+       CF cf;
+       int eval;
+
+       afd = open_archive(O_CREAT|O_RDWR);
+       if (lseek(afd, (off_t)0, SEEK_END) == (off_t)-1)
+               error(archive);
+
+       /* Read from disk, write to an archive; pad on write. */
+       SETCF(0, 0, afd, archive, WPAD);
+       for (eval = 0; file = *argv++;) {
+               if ((fd = open(file, O_RDONLY)) < 0) {
+                       (void)fprintf(stderr,
+                           "ar: %s: %s.\n", file, strerror(errno));
+                       eval = 1;
+                       continue;
+               }
+               if (options & AR_V)
+                       (void)printf("q - %s\n", file);
+               cf.rfd = fd;
+               cf.rname = file;
+               put_arobj(&cf, &sb);
+               (void)close(fd);
+       }
+       close_archive(afd);
+       return(eval);   
+}
diff --git a/usr/src/usr.bin/ar/ar.c b/usr/src/usr.bin/ar/ar.c
new file mode 100644 (file)
index 0000000..cb6c583
--- /dev/null
@@ -0,0 +1,238 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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
+char copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ar.c       5.11 (Berkeley) 3/21/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <ar.h>
+#include <string.h>
+#include <stdlib.h>
+#include <paths.h>
+#include "archive.h"
+#include "extern.h"
+
+CHDR chdr;
+u_int options;
+char *archive, *envtmp, *posarg, *posname;
+static void badoptions(), usage();
+
+/*
+ * main --
+ *     main basically uses getopt to parse options and calls the appropriate
+ *     functions.  Some hacks that let us be backward compatible with 4.3 ar
+ *     option parsing and sanity checking.
+ */
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       extern int optind;
+       int c;
+       char *p;
+       int (*fcall)(), append(), contents(), delete(), extract(),
+           move(), print(), replace();
+
+       if (argc < 3)
+               usage();
+
+       /*
+        * Historic versions didn't require a '-' in front of the options.
+        * Fix it, if necessary.
+       */
+       if (*argv[1] != '-') {
+               if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) {
+                       (void)fprintf(stderr, "ar: %s.\n", strerror(errno));
+                       exit(1);
+               }
+               *p = '-';
+               (void)strcpy(p + 1, argv[1]);
+               argv[1] = p;
+       }
+
+       while ((c = getopt(argc, argv, "abcdilmopqrTtuvx")) != EOF) {
+               switch(c) {
+               case 'a':
+                       options |= AR_A;
+                       break;
+               case 'b':
+               case 'i':
+                       options |= AR_B;
+                       break;
+               case 'c':
+                       options |= AR_C;
+                       break;
+               case 'd':
+                       options |= AR_D;
+                       fcall = delete;
+                       break;
+               case 'l':               /* not documented, compatibility only */
+                       envtmp = ".";
+                       break;
+               case 'm':
+                       options |= AR_M;
+                       fcall = move;
+                       break;
+               case 'o':
+                       options |= AR_O;
+                       break;
+               case 'p':
+                       options |= AR_P;
+                       fcall = print;
+                       break;
+               case 'q':
+                       options |= AR_Q;
+                       fcall = append;
+                       break;
+               case 'r':
+                       options |= AR_R;
+                       fcall = replace;
+                       break;
+               case 'T':
+                       options |= AR_TR;
+                       break;
+               case 't':
+                       options |= AR_T;
+                       fcall = contents;
+                       break;
+               case 'u':
+                       options |= AR_U;
+                       break;
+               case 'v':
+                       options |= AR_V;
+                       break;
+               case 'x':
+                       options |= AR_X;
+                       fcall = extract;
+                       break;
+               default:
+                       usage();
+               }
+       }
+
+       argv += optind;
+       argc -= optind;
+
+       /* One of -dmpqrtx required. */
+       if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_T|AR_X))) {
+               (void)fprintf(stderr,
+                   "ar: one of options -dmpqrtx is required.\n");
+               usage();
+       }
+       /* Only one of -a and -bi allowed. */
+       if (options & AR_A && options & AR_B) {
+               (void)fprintf(stderr,
+                   "ar: only one of -a and -[bi] options allowed.\n");
+               usage();
+       }
+       /* -ab require a position argument. */
+       if (options & (AR_A|AR_B)) {
+               if (!(posarg = *argv++)) {
+                       (void)fprintf(stderr,
+                           "ar: no position operand specified.\n");
+                       usage();
+               }
+               posname = rname(posarg);
+       }
+       /* -d only valid with -Tv. */
+       if (options & AR_D && options & ~(AR_D|AR_TR|AR_V))
+               badoptions("-d");
+       /* -m only valid with -abiTv. */
+       if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_V))
+               badoptions("-m");
+       /* -p only valid with -Tv. */
+       if (options & AR_P && options & ~(AR_P|AR_TR|AR_V))
+               badoptions("-p");
+       /* -q only valid with -cTv. */
+       if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_V))
+               badoptions("-q");
+       /* -r only valid with -abcuTv. */
+       if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_V))
+               badoptions("-r");
+       /* -t only valid with -Tv. */
+       if (options & AR_T && options & ~(AR_T|AR_TR|AR_V))
+               badoptions("-t");
+       /* -x only valid with -ouTv. */
+       if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_V|AR_X))
+               badoptions("-x");
+
+       if (!(archive = *argv++)) {
+               (void)fprintf(stderr, "ar: no archive specified.\n");
+               usage();
+       }
+
+       /* -dmqr require a list of archive elements. */
+       if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) {
+               (void)fprintf(stderr, "ar: no archive members specified.\n");
+               usage();
+       }
+
+       exit((*fcall)(argv));
+}
+
+static void
+badoptions(arg)
+       char *arg;
+{
+       (void)fprintf(stderr,
+           "ar: illegal option combination for %s.\n", arg);
+       usage();
+}
+
+static void
+usage()
+{
+       (void)fprintf(stderr, "usage:  ar -d [-Tv] archive file ...\n");
+       (void)fprintf(stderr, "\tar -m [-Tv] archive file ...\n");
+       (void)fprintf(stderr, "\tar -m [-abiTv] position archive file ...\n");
+       (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n");
+       (void)fprintf(stderr, "\tar -q [-cTv] archive file ...\n");
+       (void)fprintf(stderr, "\tar -r [-cuTv] archive file ...\n");
+       (void)fprintf(stderr, "\tar -r [-abciuTv] position archive file ...\n");
+       (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n");
+       (void)fprintf(stderr, "\tar -x [-ouTv] archive [file ...]\n");
+       exit(1);
+}      
diff --git a/usr/src/usr.bin/ar/archive.c b/usr/src/usr.bin/ar/archive.c
new file mode 100644 (file)
index 0000000..1ba6bb6
--- /dev/null
@@ -0,0 +1,320 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)archive.c  5.7 (Berkeley) 3/21/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <ar.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "archive.h"
+#include "extern.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+
+typedef struct ar_hdr HDR;
+static char hb[sizeof(HDR) + 1];       /* real header */
+
+open_archive(mode)
+       int mode;
+{
+       int created, fd, nr;
+       char buf[SARMAG];
+       
+       created = 0;
+       if (mode & O_CREAT) {
+               mode |= O_EXCL;
+               if ((fd = open(archive, mode, DEFFILEMODE)) >= 0) {
+                       /* POSIX.2 puts create message on stderr. */
+                       if (!(options & AR_C))
+                               (void)fprintf(stderr,
+                                   "ar: creating archive %s.\n", archive);
+                       created = 1;
+                       goto opened;
+               }
+               if (errno != EEXIST)
+                       error(archive);
+               mode &= ~O_EXCL;
+       }
+       if ((fd = open(archive, mode, DEFFILEMODE)) < 0)
+               error(archive);
+
+       /* 
+        * Attempt to place a lock on the opened file - if we get an 
+        * error then someone is already working on this library (or
+        * it's going across NFS).
+        */
+opened:        if (flock(fd, LOCK_EX|LOCK_NB) && errno != EOPNOTSUPP)
+               error(archive);
+       
+       /*
+        * If not created, O_RDONLY|O_RDWR indicates that it has to be
+        * in archive format.
+        */
+       if (!created &&
+           ((mode & O_ACCMODE) == O_RDONLY || (mode & O_ACCMODE) == O_RDWR)) {
+               if ((nr = read(fd, buf, SARMAG) != SARMAG)) {
+                       if (nr >= 0)
+                               badfmt();
+                       error(archive);
+               } else if (bcmp(buf, ARMAG, SARMAG))
+                       badfmt();
+       } else if (write(fd, ARMAG, SARMAG) != SARMAG)
+               error(archive);
+       return(fd);
+}
+
+void
+close_archive(fd)
+       int fd;
+{
+       (void)close(fd);                        /* Implicit unlock. */
+}
+
+/* Convert ar header field to an integer. */
+#define        AR_ATOI(from, to, len, base) { \
+       bcopy(from, buf, len); \
+       buf[len] = '\0'; \
+       to = strtol(buf, (char **)NULL, base); \
+}
+
+/*
+ * get_arobj --
+ *     read the archive header for this member
+ */
+get_arobj(fd)
+       int fd;
+{
+       struct ar_hdr *hdr;
+       register int len, nr;
+       register char *p, buf[20];
+
+       nr = read(fd, hb, sizeof(HDR));
+       if (nr != sizeof(HDR)) {
+               if (!nr)
+                       return(0);
+               if (nr < 0)
+                       error(archive);
+               badfmt();
+       }
+
+       hdr = (struct ar_hdr *)hb;
+       if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))
+               badfmt();
+
+       /* Convert the header into the internal format. */
+#define        DECIMAL 10
+#define        OCTAL    8
+
+       AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL);
+       AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL);
+       AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL);
+       AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL);
+       AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL);
+
+       /* Leading spaces should never happen. */
+       if (hdr->ar_name[0] == ' ')
+               badfmt();
+
+       /*
+        * Long name support.  Set the "real" size of the file, and the
+        * long name flag/size.
+        */
+       if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) {
+               chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1);
+               if (len <= 0 || len > MAXNAMLEN)
+                       badfmt();
+               nr = read(fd, chdr.name, len);
+               if (nr != len) {
+                       if (nr < 0)
+                               error(archive);
+                       badfmt();
+               }
+               chdr.name[len] = 0;
+               chdr.size -= len;
+       } else {
+               chdr.lname = 0;
+               bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name));
+
+               /* Strip trailing spaces, null terminate. */
+               for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p);
+               *++p = '\0';
+       }
+       return(1);
+}
+
+static int already_written;
+
+/*
+ * put_arobj --
+ *     Write an archive member to a file.
+ */
+put_arobj(cfp, sb)
+       CF *cfp;
+       struct stat *sb;
+{
+       register int lname;
+       register char *name;
+       struct ar_hdr *hdr;
+       off_t size;
+
+       /*
+        * If passed an sb structure, reading a file from disk.  Get stat(2)
+        * information, build a name and construct a header.  (Files are named
+        * by their last component in the archive.)  If not, then just write
+        * the last header read.
+        */
+       if (sb) {
+               name = rname(cfp->rname);
+               (void)fstat(cfp->rfd, sb);
+
+               /*
+                * If not truncating names and the name is too long or contains
+                * a space, use extended format 1.
+                */
+               lname = strlen(name);
+               if (options & AR_TR) {
+                       if (lname > OLDARMAXNAME) {
+                               (void)fflush(stdout);
+                               (void)fprintf(stderr,
+                                   "ar: warning: %s truncated to %.*s\n",
+                                   name, OLDARMAXNAME, name);
+                               (void)fflush(stderr);
+                       }
+                       (void)sprintf(hb, HDR3, name, sb->st_mtime, sb->st_uid,
+                           sb->st_gid, sb->st_mode, sb->st_size, ARFMAG);
+                       lname = 0;
+               } else if (lname > sizeof(hdr->ar_name) || index(name, ' '))
+                       (void)sprintf(hb, HDR1, AR_EFMT1, lname, sb->st_mtime,
+                           sb->st_uid, sb->st_gid, sb->st_mode,
+                           sb->st_size + lname, ARFMAG);
+               else {
+                       lname = 0;
+                       (void)sprintf(hb, HDR2, name, sb->st_mtime, sb->st_uid,
+                           sb->st_gid, sb->st_mode, sb->st_size, ARFMAG);
+               }
+               size = sb->st_size;
+       } else {
+               lname = chdr.lname;
+               name = chdr.name;
+               size = chdr.size;
+       }
+
+       if (write(cfp->wfd, hb, sizeof(HDR)) != sizeof(HDR))
+               error(cfp->wname);
+       if (lname) {
+               if (write(cfp->wfd, name, lname) != lname)
+                       error(cfp->wname);
+               already_written = lname;
+       }
+       copy_ar(cfp, size);
+       already_written = 0;
+}
+
+/*
+ * copy_ar --
+ *     Copy size bytes from one file to another - taking care to handle the
+ *     extra byte (for odd size files) when reading archives and writing an
+ *     extra byte if necessary when adding files to archive.  The length of
+ *     the object is the long name plus the object itself; the variable
+ *     already_written gets set if a long name was written.
+ *
+ *     The padding is really unnecessary, and is almost certainly a remnant
+ *     of early archive formats where the header included binary data which
+ *     a PDP-11 required to start on an even byte boundary.  (Or, perhaps,
+ *     because 16-bit word addressed copies were faster?)  Anyhow, it should
+ *     have been ripped out long ago.
+ */
+copy_ar(cfp, size)
+       CF *cfp;
+       off_t size;
+{
+       static char pad = '\n';
+       register off_t sz;
+       register int from, nr, nw, off, to;
+       char buf[8*1024];
+       
+       if (!(sz = size))
+               return;
+
+       from = cfp->rfd;
+       to = cfp->wfd;
+       sz = size;
+       while (sz && (nr = read(from, buf, MIN(sz, sizeof(buf)))) > 0) {
+               sz -= nr;
+               for (off = 0; off < nr; nr -= off, off += nw)
+                       if ((nw = write(to, buf + off, nr)) < 0)
+                               error(cfp->wname);
+       }
+       if (sz) {
+               if (nr == 0)
+                       badfmt();
+               error(cfp->rname);
+       }
+
+       if (cfp->flags & RPAD && size & 1 && (nr = read(from, buf, 1)) != 1) {
+               if (nr == 0)
+                       badfmt();
+               error(cfp->rname);
+       }
+       if (cfp->flags & WPAD && (size + already_written) & 1 &&
+           write(to, &pad, 1) != 1)
+               error(cfp->wname);
+}
+
+/*
+ * skip_arobj -
+ *     Skip over an object -- taking care to skip the pad bytes.
+ */
+void
+skip_arobj(fd)
+       int fd;
+{
+       off_t len;
+
+       len = chdr.size + (chdr.size + chdr.lname & 1);
+       if (lseek(fd, len, SEEK_CUR) == (off_t)-1)
+               error(archive);
+}
diff --git a/usr/src/usr.bin/ar/contents.c b/usr/src/usr.bin/ar/contents.c
new file mode 100644 (file)
index 0000000..995a800
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)contents.c 5.6 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <tzfile.h>
+#include <dirent.h>
+#include <ar.h>
+#include <stdio.h>
+#include <string.h>
+#include "archive.h"
+#include "extern.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+
+/*
+ * contents --
+ *     Handles t[v] option - opens the archive and then reads headers,
+ *     skipping member contents.
+ */
+contents(argv)
+       register char **argv;
+{
+       register int afd, all;
+       struct tm *tp;
+       char *file, buf[25];
+       
+       afd = open_archive(O_RDONLY);
+
+       for (all = !*argv; get_arobj(afd);) {
+               if (all)
+                       file = chdr.name;
+               else if (!(file = files(argv)))
+                       goto next;
+               if (options & AR_V) {
+                       (void)strmode(chdr.mode, buf);
+                       (void)printf("%s %6d/%-6d %8ld ",
+                           buf + 1, chdr.uid, chdr.gid, chdr.size);
+                       tp = localtime(&chdr.date);
+                       (void)strftime(buf, sizeof(buf), "%b %e %H:%M %Y", tp);
+                       (void)printf("%s %s\n", buf, file);
+               } else
+                       (void)printf("%s\n", file);
+               if (!all && !*argv)
+                       break;
+next:          skip_arobj(afd);
+       } 
+       close_archive(afd);
+
+       if (*argv) {
+               orphans(argv);
+               return(1);
+       }
+       return(0);
+}
diff --git a/usr/src/usr.bin/ar/delete.c b/usr/src/usr.bin/ar/delete.c
new file mode 100644 (file)
index 0000000..7acfcd0
--- /dev/null
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)delete.c   5.6 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ar.h>
+#include "archive.h"
+#include "extern.h"
+#include "pathnames.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+extern char *tname;                     /* temporary file "name" */
+
+/*-
+ * delete --
+ *     Deletes named members from the archive.
+ */
+delete(argv)
+       register char **argv;
+{
+       CF cf;
+       off_t size;
+       int afd, tfd;
+       char *file;
+
+       afd = open_archive(O_RDWR);
+       tfd = tmp();
+
+       /* Read and write to an archive; pad on both. */
+       SETCF(afd, archive, tfd, tname, RPAD|WPAD);
+       while (get_arobj(afd)) {
+               if (*argv && (file = files(argv))) {
+                       if (options & AR_V)
+                               (void)printf("d - %s\n", file);
+                       skip_arobj(afd);
+                       continue;
+               }
+               put_arobj(&cf, (struct stat *)NULL);
+       }
+
+       size = lseek(tfd, (off_t)0, SEEK_CUR);
+       (void)lseek(tfd, (off_t)0, SEEK_SET);
+       (void)lseek(afd, (off_t)SARMAG, SEEK_SET);
+       SETCF(tfd, tname, afd, archive, NOPAD);
+       copy_ar(&cf, size);
+       (void)close(tfd);
+       (void)ftruncate(afd, size + SARMAG);
+       close_archive(afd);
+
+       if (*argv) {
+               orphans(argv);
+               return(1);
+       }
+       return(0);
+}      
diff --git a/usr/src/usr.bin/ar/extern.h b/usr/src/usr.bin/ar/extern.h
new file mode 100644 (file)
index 0000000..a52acc1
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1991 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    5.1 (Berkeley) 4/3/91
+ */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+void    badfmt __P((void));
+void    error __P((char *));
+void    orphans __P((char **argv));
+int     compare __P((char *));
+int     tmp __P((void));
+char   *files __P((char **argv));
+char   *rname __P((char *));
+__END_DECLS
diff --git a/usr/src/usr.bin/ar/extract.c b/usr/src/usr.bin/ar/extract.c
new file mode 100644 (file)
index 0000000..24b081c
--- /dev/null
@@ -0,0 +1,132 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)extract.c  5.5 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include "archive.h"
+#include "extern.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+
+/*
+ * extract --
+ *     Extract files from the named archive - if member names given only
+ *     extract those members otherwise extract all members.  If 'o' option
+ *     selected modify date of newly created file to be same as archive
+ *     members date otherwise date is time of extraction.  Does not modify
+ *     archive.
+ */
+extract(argv)
+       char **argv;
+{
+       register int afd, all, tfd;
+       struct timeval tv[2];
+       struct stat sb;
+       CF cf;
+       int eval;
+       char *file;
+
+       eval = 0;
+       tv[0].tv_usec = tv[1].tv_usec = 0;
+
+       afd = open_archive(O_RDONLY);
+
+       /* Read from an archive, write to disk; pad on read. */
+       SETCF(afd, archive, 0, 0, RPAD);
+       for (all = !*argv; get_arobj(afd);) {
+               if (all)
+                       file = chdr.name;
+               else if (!(file = files(argv))) {
+                       skip_arobj(afd);
+                       continue;
+               }
+
+               if (options & AR_U && !stat(file, &sb) &&
+                   sb.st_mtime > chdr.date)
+                       continue;
+
+               if ((tfd = open(file, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR)) < 0) {
+                       (void)fprintf(stderr, "ar: %s: %s.\n",
+                           file, strerror(errno));
+                       skip_arobj(afd);
+                       eval = 1;
+                       continue;
+               }
+
+               if (options & AR_V)
+                       (void)printf("x - %s\n", file);
+
+               cf.wfd = tfd;
+               cf.wname = file;
+               copy_ar(&cf, chdr.size);
+
+               if (fchmod(tfd, (short)chdr.mode)) {
+                       (void)fprintf(stderr, "ar: %s: chmod: %s\n",
+                           file, strerror(errno));
+                       eval = 1;
+               }
+               if (options & AR_O) {
+                       tv[0].tv_sec = tv[1].tv_sec = chdr.date;
+                       if (utimes(file, tv)) {
+                               (void)fprintf(stderr, "ar: %s: utimes: %s\n",
+                                   file, strerror(errno));
+                               eval = 1;
+                       }
+               }
+               (void)close(tfd);
+               if (!all && !*argv)
+                       break;
+       }
+       close_archive(afd);
+
+       if (*argv) {
+               orphans(argv);
+               return(1);
+       }
+       return(0);
+}      
diff --git a/usr/src/usr.bin/ar/move.c b/usr/src/usr.bin/ar/move.c
new file mode 100644 (file)
index 0000000..e7fbaa7
--- /dev/null
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)move.c     5.6 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ar.h>
+#include "archive.h"
+#include "extern.h"
+#include "pathnames.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+extern char *tname;                     /* temporary file "name" */
+
+/*
+ * move --
+ *     Change location of named members in archive - if 'b' or 'i' option
+ *     selected then named members are placed before 'posname'.  If 'a'
+ *     option selected members go after 'posname'.  If no options, members
+ *     are moved to end of archive.
+ */
+move(argv)
+       char **argv;
+{
+       extern char *posarg, *posname;  /* positioning file names */
+       CF cf;
+       off_t size, tsize;
+       int afd, curfd, mods, tfd1, tfd2, tfd3;
+       char *file;
+
+       afd = open_archive(O_RDWR);
+       mods = options & (AR_A|AR_B);
+
+       tfd1 = tmp();                   /* Files before key file. */
+       tfd2 = tmp();                   /* Files selected by user. */
+       tfd3 = tmp();                   /* Files after key file. */
+
+       /*
+        * Break archive into three parts -- selected entries and entries
+        * before and after the key entry.  If positioning before the key,
+        * place the key at the beginning of the after key entries and if
+        * positioning after the key, place the key at the end of the before
+        * key entries.  Put it all back together at the end.
+        */
+
+       /* Read and write to an archive; pad on both. */
+       SETCF(afd, archive, 0, tname, RPAD|WPAD);
+       for (curfd = tfd1; get_arobj(afd);) {   
+               if (*argv && (file = files(argv))) {
+                       if (options & AR_V)
+                               (void)printf("m - %s\n", file);
+                       cf.wfd = tfd2;
+                       put_arobj(&cf, (struct stat *)NULL);
+                       continue;
+               }
+               if (mods && compare(posname)) {
+                       mods = 0;
+                       if (options & AR_B)
+                               curfd = tfd3;
+                       cf.wfd = curfd;
+                       put_arobj(&cf, (struct stat *)NULL);
+                       if (options & AR_A)
+                               curfd = tfd3;
+               } else {
+                       cf.wfd = curfd;
+                       put_arobj(&cf, (struct stat *)NULL);
+               }
+       }
+
+       if (mods) {
+               (void)fprintf(stderr, "ar: %s: archive member not found.\n",
+                   posarg);
+               close_archive(afd);
+               return(1);
+       }
+       (void)lseek(afd, (off_t)SARMAG, SEEK_SET);
+
+       SETCF(tfd1, tname, afd, archive, NOPAD);
+       tsize = size = lseek(tfd1, (off_t)0, SEEK_CUR);
+       (void)lseek(tfd1, (off_t)0, SEEK_SET);
+       copy_ar(&cf, size);
+
+       tsize += size = lseek(tfd2, (off_t)0, SEEK_CUR);
+       (void)lseek(tfd2, (off_t)0, SEEK_SET);
+       cf.rfd = tfd2;
+       copy_ar(&cf, size);
+
+       tsize += size = lseek(tfd3, (off_t)0, SEEK_CUR);
+       (void)lseek(tfd3, (off_t)0, SEEK_SET);
+       cf.rfd = tfd3;
+       copy_ar(&cf, size);
+
+       (void)ftruncate(afd, tsize + SARMAG);
+       close_archive(afd);
+
+       if (*argv) {
+               orphans(argv);
+               return(1);
+       }
+       return(0);
+}      
diff --git a/usr/src/usr.bin/ar/print.c b/usr/src/usr.bin/ar/print.c
new file mode 100644 (file)
index 0000000..ca33ab3
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)print.c    5.6 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include "archive.h"
+#include "extern.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+
+/*
+ * print --
+ *     Prints archive members on stdout - if member names given only
+ *     print those members, otherwise print all members.
+ */
+print(argv)
+       char **argv;
+{
+       CF cf;
+       register int afd, all;
+       char *file;
+
+       afd = open_archive(O_RDONLY);
+
+       /* Read from an archive, write to stdout; pad on read. */
+       SETCF(afd, archive, STDOUT_FILENO, "stdout", RPAD);
+       for (all = !*argv; get_arobj(afd);) {
+               if (all)
+                       file = chdr.name;
+               else if (!(file = files(argv))) {
+                       skip_arobj(afd);
+                       continue;
+               }
+               if (options & AR_V) {
+                       (void)printf("\n<%s>\n\n", file);
+                       (void)fflush(stdout);
+               }
+               copy_ar(&cf, chdr.size);
+               if (!all && !*argv)
+                       break;
+       }
+       close_archive(afd);
+
+       if (*argv) {
+               orphans(argv);
+               return(1);
+       }
+       return(0);
+}
diff --git a/usr/src/usr.bin/ar/replace.c b/usr/src/usr.bin/ar/replace.c
new file mode 100644 (file)
index 0000000..9f56a93
--- /dev/null
@@ -0,0 +1,183 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 char sccsid[] = "@(#)replace.c  5.8 (Berkeley) 3/15/91";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <ar.h>
+#include <stdio.h>
+#include <string.h>
+#include "archive.h"
+#include "extern.h"
+
+extern CHDR chdr;                      /* converted header */
+extern char *archive;                  /* archive name */
+extern char *tname;                     /* temporary file "name" */
+
+/*
+ * replace --
+ *     Replace or add named members to archive.  Entries already in the
+ *     archive are swapped in place.  Others are added before or after 
+ *     the key entry, based on the a, b and i options.  If the u option
+ *     is specified, modification dates select for replacement.
+ */
+replace(argv)
+       char **argv;
+{
+       extern char *posarg, *posname;  /* positioning file name */
+       register char *file;
+       register int afd, curfd, mods, sfd;
+       struct stat sb;
+       CF cf;
+       off_t size, tsize;
+       int err, exists, tfd1, tfd2;
+       char *rname();
+
+       err = 0;
+       /*
+        * If doesn't exist, simply append to the archive.  There's
+        * a race here, but it's pretty short, and not worth fixing.
+        */
+       exists = !stat(archive, &sb);
+       afd = open_archive(O_CREAT|O_RDWR);
+
+       if (!exists) {
+               tfd1 = -1;
+               tfd2 = tmp();
+               goto append;
+       } 
+
+       tfd1 = tmp();                   /* Files before key file. */
+       tfd2 = tmp();                   /* Files after key file. */
+
+       /*
+        * Break archive into two parts -- entries before and after the key
+        * entry.  If positioning before the key, place the key at the
+        * beginning of the after key entries and if positioning after the
+        * key, place the key at the end of the before key entries.  Put it
+        * all back together at the end.
+        */
+       mods = (options & (AR_A|AR_B));
+       for (curfd = tfd1; get_arobj(afd);) {
+               if (*argv && (file = files(argv))) {
+                       if ((sfd = open(file, O_RDONLY)) < 0) {
+                               err = 1;
+                               (void)fprintf(stderr, "ar: %s: %s.\n",
+                                   file, strerror(errno));
+                               goto useold;
+                       }
+                       (void)fstat(sfd, &sb);
+                       if (options & AR_U && sb.st_mtime <= chdr.date)
+                               goto useold;
+
+                       if (options & AR_V)
+                            (void)printf("r - %s\n", file);
+
+                       /* Read from disk, write to an archive; pad on write */
+                       SETCF(sfd, file, curfd, tname, WPAD);
+                       put_arobj(&cf, &sb);
+                       (void)close(sfd);
+                       skip_arobj(afd);
+                       continue;
+               }
+
+               if (mods && compare(posname)) {
+                       mods = 0;
+                       if (options & AR_B)
+                               curfd = tfd2;
+                       /* Read and write to an archive; pad on both. */
+                       SETCF(afd, archive, curfd, tname, RPAD|WPAD);
+                       put_arobj(&cf, (struct stat *)NULL);
+                       if (options & AR_A)
+                               curfd = tfd2;
+               } else {
+                       /* Read and write to an archive; pad on both. */
+useold:                        SETCF(afd, archive, curfd, tname, RPAD|WPAD);
+                       put_arobj(&cf, (struct stat *)NULL);
+               }
+       }
+
+       if (mods) {
+               (void)fprintf(stderr, "ar: %s: archive member not found.\n",
+                   posarg);
+                close_archive(afd);
+                return(1);
+        }
+
+       /* Append any left-over arguments to the end of the after file. */
+append:        while (file = *argv++) {
+               if (options & AR_V)
+                       (void)printf("a - %s\n", file);
+               if ((sfd = open(file, O_RDONLY)) < 0) {
+                       err = 1;
+                       (void)fprintf(stderr, "ar: %s: %s.\n",
+                           file, strerror(errno));
+                       continue;
+               }
+               (void)fstat(sfd, &sb);
+               /* Read from disk, write to an archive; pad on write. */
+               SETCF(sfd, file,
+                   options & (AR_A|AR_B) ? tfd1 : tfd2, tname, WPAD);
+               put_arobj(&cf, &sb);
+               (void)close(sfd);
+       }
+       
+       (void)lseek(afd, (off_t)SARMAG, SEEK_SET);
+
+       SETCF(tfd1, tname, afd, archive, NOPAD);
+       if (tfd1 != -1) {
+               tsize = size = lseek(tfd1, (off_t)0, SEEK_CUR);
+               (void)lseek(tfd1, (off_t)0, SEEK_SET);
+               copy_ar(&cf, size);
+       } else
+               tsize = 0;
+
+       tsize += size = lseek(tfd2, (off_t)0, SEEK_CUR);
+       (void)lseek(tfd2, (off_t)0, SEEK_SET);
+       cf.rfd = tfd2;
+       copy_ar(&cf, size);
+
+       (void)ftruncate(afd, tsize + SARMAG);
+       close_archive(afd);
+       return(err);
+}