From d2fc2cec3cb2cb7e1389ad02000e8223c665069e Mon Sep 17 00:00:00 2001 From: "William F. Jolitz" Date: Fri, 12 Apr 1991 13:27:40 -0800 Subject: [PATCH] 386BSD 0.0 development Work on file usr/src/usr.bin/ar/append.c Work on file usr/src/usr.bin/ar/ar.c Work on file usr/src/usr.bin/ar/archive.c Work on file usr/src/usr.bin/ar/contents.c Work on file usr/src/usr.bin/ar/delete.c Work on file usr/src/usr.bin/ar/extract.c Work on file usr/src/usr.bin/ar/extern.h Work on file usr/src/usr.bin/ar/move.c Work on file usr/src/usr.bin/ar/print.c Work on file usr/src/usr.bin/ar/replace.c Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.0/src --- usr/src/usr.bin/ar/append.c | 90 ++++++++++ usr/src/usr.bin/ar/ar.c | 238 +++++++++++++++++++++++++ usr/src/usr.bin/ar/archive.c | 320 ++++++++++++++++++++++++++++++++++ usr/src/usr.bin/ar/contents.c | 96 ++++++++++ usr/src/usr.bin/ar/delete.c | 97 +++++++++++ usr/src/usr.bin/ar/extern.h | 46 +++++ usr/src/usr.bin/ar/extract.c | 132 ++++++++++++++ usr/src/usr.bin/ar/move.c | 142 +++++++++++++++ usr/src/usr.bin/ar/print.c | 90 ++++++++++ usr/src/usr.bin/ar/replace.c | 183 +++++++++++++++++++ 10 files changed, 1434 insertions(+) create mode 100644 usr/src/usr.bin/ar/append.c create mode 100644 usr/src/usr.bin/ar/ar.c create mode 100644 usr/src/usr.bin/ar/archive.c create mode 100644 usr/src/usr.bin/ar/contents.c create mode 100644 usr/src/usr.bin/ar/delete.c create mode 100644 usr/src/usr.bin/ar/extern.h create mode 100644 usr/src/usr.bin/ar/extract.c create mode 100644 usr/src/usr.bin/ar/move.c create mode 100644 usr/src/usr.bin/ar/print.c create mode 100644 usr/src/usr.bin/ar/replace.c diff --git a/usr/src/usr.bin/ar/append.c b/usr/src/usr.bin/ar/append.c new file mode 100644 index 0000000000..7dcfa8e49c --- /dev/null +++ b/usr/src/usr.bin/ar/append.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000000..cb6c583f8d --- /dev/null +++ b/usr/src/usr.bin/ar/ar.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000000..1ba6bb642b --- /dev/null +++ b/usr/src/usr.bin/ar/archive.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000000..995a800299 --- /dev/null +++ b/usr/src/usr.bin/ar/contents.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000000..7acfcd00e8 --- /dev/null +++ b/usr/src/usr.bin/ar/delete.c @@ -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 +#include +#include +#include +#include +#include +#include +#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 index 0000000000..a52acc14f9 --- /dev/null +++ b/usr/src/usr.bin/ar/extern.h @@ -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 + +__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 index 0000000000..24b081c2c1 --- /dev/null +++ b/usr/src/usr.bin/ar/extract.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 0000000000..e7fbaa7b93 --- /dev/null +++ b/usr/src/usr.bin/ar/move.c @@ -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 +#include +#include +#include +#include +#include +#include +#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 index 0000000000..ca33ab3842 --- /dev/null +++ b/usr/src/usr.bin/ar/print.c @@ -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 +#include +#include +#include +#include +#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 index 0000000000..9f56a93775 --- /dev/null +++ b/usr/src/usr.bin/ar/replace.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#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); +} -- 2.20.1