diff options
| author | Bruce Evans <bde@FreeBSD.org> | 1997-07-06 06:54:14 +0000 |
|---|---|---|
| committer | Bruce Evans <bde@FreeBSD.org> | 1997-07-06 06:54:14 +0000 |
| commit | c44252b6e8da46f58fd1882b9e7305a0f9114c16 (patch) | |
| tree | 29fcabeee2a8db74f376eb75e7c13a0f440c6ce9 /usr.bin/ar | |
| parent | 616fc29f94872d4d502f3d8631885d52a9167322 (diff) | |
Notes
Diffstat (limited to 'usr.bin/ar')
| -rw-r--r-- | usr.bin/ar/ar.1 | 320 | ||||
| -rw-r--r-- | usr.bin/ar/ar.5.5 | 146 | ||||
| -rw-r--r-- | usr.bin/ar/archive.c | 326 | ||||
| -rw-r--r-- | usr.bin/ar/misc.c | 149 | ||||
| -rw-r--r-- | usr.bin/ar/replace.c | 178 |
5 files changed, 1119 insertions, 0 deletions
diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1 new file mode 100644 index 000000000000..fd5ce4f717c9 --- /dev/null +++ b/usr.bin/ar/ar.1 @@ -0,0 +1,320 @@ +.\" Copyright (c) 1990, 1993 +.\" 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. +.\" +.\" @(#)ar.1 8.4 (Berkeley) 4/28/95 +.\" +.Dd "April 28, 1995" +.Dt AR 1 +.Os +.Sh NAME +.Nm ar +.Nd create and maintain library archives +.Sh SYNOPSIS +.Nm ar +.Fl d +.Op Fl \Tv +.Ar archive file ... +.Nm ar +.Fl m +.Op Fl \Tv +.Ar archive file ... +.Nm ar +.Fl m +.Op Fl abiTv +.Ar position archive file ... +.Nm ar +.Fl p +.Op Fl \Tv +.Ar archive +.Op Ar file ... +.Nm ar +.Fl q +.Op Fl cTv +.Ar archive file ... +.Nm ar +.Fl r +.Op Fl cuTv +.Ar archive file ... +.Nm ar +.Fl r +.Op Fl abciuTv +.Ar position archive file ... +.Nm ar +.Fl t +.Op Fl \Tv +.Ar archive +.Op Ar file ... +.Nm ar +.Fl x +.Op Fl ouTv +.Ar archive +.Op Ar file ... +.Sh DESCRIPTION +The +.Nm ar +utility creates and maintains groups of files combined into an archive. +Once an archive has been created, new files can be added and existing +files can be extracted, deleted, or replaced. +.Pp +Files are named in the archive by a single component, i.e., if a file +referenced by a path containing a slash (``/'') is archived it will be +named by the last component of that path. +When matching paths listed on the command line against file names stored +in the archive, only the last component of the path will be compared. +.Pp +All informational and error messages use the path listed on the command +line, if any was specified; otherwise the name in the archive is used. +If multiple files in the archive have the same name, and paths are listed +on the command line to ``select'' archive files for an operation, only the +.Em first +file with a matching name will be selected. +.Pp +The normal use of +.Nm ar +is for the creation and maintenance of libraries suitable for use with +the loader (see +.Xr ld 1 ), +although it is not restricted to this purpose. +The options are as follows: +.Bl -tag -width indent +.It Fl a +A positioning modifier used with the options +.Fl r +and +.Fl m . +The files are entered or moved +.Em after +the archive member +.Ar position , +which must be specified. +.It Fl b +A positioning modifier used with the options +.Fl r +and +.Fl m . +The files are entered or moved +.Em before +the archive member +.Ar position , +which must be specified. +.It Fl c +Whenever an archive is created, an informational message to that effect +is written to standard error. +If the +.Fl c +option is specified, +.Nm ar +creates the archive silently. +.It Fl d +Delete the specified archive files. +.It Fl i +Identical to the +.Fl b +option. +.It Fl m +Move the specified archive files within the archive. +If one of the options +.Fl a , +.Fl b +or +.Fl i +is specified, the files are moved before or after the +.Ar position +file in the archive. +If none of those options are specified, the files are moved +to the end of the archive. +.It Fl o +Set the access and modification times of extracted files to the +modification time of the file when it was entered into the archive. +This will fail if the user is not the owner of the extracted file +or the super-user. +.It Fl p +Write the contents of the specified archive files to the standard output. +If no files are specified, the contents of all the files in the archive +are written in the order they appear in the archive. +.It Fl q +(Quickly) append the specified files to the archive. +If the archive does not exist a new archive file is created. +Much faster than the +.Fl r +option, when creating a large archive +piece-by-piece, as no checking is done to see if the files already +exist in the archive. +.It Fl r +Replace or add the specified files to the archive. +If the archive does not exist a new archive file is created. +Files that replace existing files do not change the order of the files +within the archive. +New files are appended to the archive unless one of the options +.Fl a , +.Fl b +or +.Fl i +is specified. +.It Fl T +Select and/or name archive members using only the first fifteen characters +of the archive member or command line file name. +The historic archive format had sixteen bytes for the name, but some +historic archiver and loader implementations were unable to handle names +that used the entire space. +This means that file names that are not unique in their first fifteen +characters can subsequently be confused. +A warning message is printed to the standard error output if any file +names are truncated. +(See +.Xr ar 5 +for more information.) +.It Fl t +List the specified files in the order in which they appear in the archive, +each on a separate line. +If no files are specified, all files in the archive are listed. +.It Fl u +Update files. +When used with the +.Fl r +option, files in the archive will be replaced +only if the disk file has a newer modification time than the file in +the archive. +When used with the +.Fl x +option, files in the archive will be extracted +only if the archive file has a newer modification time than the file +on disk. +.It Fl v +Provide verbose output. +When used with the +.Fl d , +.Fl m , +.Fl q +or +.Fl x +options, +.Nm ar +gives a file-by-file description of the archive modification. +This description consists of three, white-space separated fields: the +option letter, a dash (``-'') and the file name. +When used with the +.Fl r +option, +.Nm ar +displays the description as above, but the initial letter is an ``a'' if +the file is added to the archive and an ``r'' if the file replaces a file +already in the archive. +.Pp +When used with the +.Fl p +option, +the name of each printed file, +enclosed in less-than (``<'') and greater-than (``>'') characters, +is written to the standard output before +the contents of the file; +it is preceded by a single newline character, and +followed by two newline characters. +.Pp +When used with the +.Fl t +option, +.Nm ar +displays an ``ls -l'' style listing of information about the members of +the archive. +This listing consists of eight, white-space separated fields: +the file permissions (see +.Xr strmode 3 ), +the decimal user and group ID's separated by a single slash (``/''), +the file size (in bytes), the file modification time (in the +.Xr date 1 +format ``%b %e %H:%M %Y''), and the name of the file. +.It Fl x +Extract the specified archive members into the files named by the command +line arguments. +If no members are specified, all the members of the archive are extracted into +the current directory. +.Pp +If the file does not exist, it is created; if it does exist, the owner +and group will be unchanged. +The file access and modification times are the time of the extraction +(but see the +.Fl o +option). +The file permissions will be set to those of the file when it was entered +into the archive; this will fail if the user is not the owner of the +extracted file or the super-user. +.El +.Pp +The +.Nm ar +utility exits 0 on success, and >0 if an error occurs. +.Sh ENVIRONMENT +.Bl -tag -width indent -compact +.It Ev TMPDIR +The pathname of the directory to use when creating temporary files. +.El +.Sh FILES +.Bl -tag -width indent -compact +.It Pa /tmp +default temporary file directory +.It Pa ar.XXXXXX +temporary file names +.El +.Sh COMPATIBILITY +By default, +.Nm ar +writes archives that may be incompatible with historic archives, as +the format used for storing archive members with names longer than +fifteen characters has changed. +This implementation of +.Nm ar +is backward compatible with previous versions of +.Nm ar +in that it can read and write (using the +.Fl T +option) historic archives. +The +.Fl T +option is provided for compatibility only, and will be deleted +in a future release. +See +.Xr ar 5 +for more information. +.SH STANDARDS +The +.Nm ar +utility is expected to offer a superset of the +.St -p1003.2 +functionality. +.Sh SEE ALSO +.Xr ld 1 , +.Xr ranlib 1 , +.Xr strmode 3 , +.Xr ar 5 diff --git a/usr.bin/ar/ar.5.5 b/usr.bin/ar/ar.5.5 new file mode 100644 index 000000000000..2ab5b2d99851 --- /dev/null +++ b/usr.bin/ar/ar.5.5 @@ -0,0 +1,146 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ar.5.5 8.2 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt AR 5 +.Os +.Sh NAME +.Nm ar +.Nd archive (library) file format +.Sh SYNOPSIS +.Fd #include <ar.h> +.Sh DESCRIPTION +The archive command +.Nm ar +combines several files into one. +Archives are mainly used as libraries of object files intended to be +loaded using the link-editor +.Xr ld 1 . +.Pp +A file created with +.Nm ar +begins with the ``magic'' string "!<arch>\en". +The rest of the archive is made up of objects, each of which is composed +of a header for a file, a possible file name, and the file contents. +The header is portable between machine architectures, and, if the file +contents are printable, the archive is itself printable. +.Pp +The header is made up of six variable length +.Tn ASCII +fields, followed by a +two character trailer. +The fields are the object name (16 characters), the file last modification +time (12 characters), the user and group id's (each 6 characters), the file +mode (8 characters) and the file size (10 characters). +All numeric fields are in decimal, except for the file mode which is in +octal. +.Pp +The modification time is the file +.Fa st_mtime +field, i.e., +.Dv CUT +seconds since +the epoch. +The user and group id's are the file +.Fa st_uid +and +.Fa st_gid +fields. +The file mode is the file +.Fa st_mode +field. +The file size is the file +.Fa st_size +field. +The two-byte trailer is the string "\`\en". +.Pp +Only the name field has any provision for overflow. +If any file name is more than 16 characters in length or contains an +embedded space, the string "#1/" followed by the +.Tn ASCII +length of the +name is written in the name field. +The file size (stored in the archive header) is incremented by the length +of the name. +The name is then written immediately following the archive header. +.Pp +Any unused characters in any of these fields are written as space +characters. +If any fields are their particular maximum number of characters in +length, there will be no separation between the fields. +.Pp +Objects in the archive are always an even number of bytes long; files +which are an odd number of bytes long are padded with a newline (``\en'') +character, although the size in the header does not reflect this. +.Sh SEE ALSO +.Xr ar 1 , +.Xr stat 2 +.Sh HISTORY +There have been at least four +.Nm ar +formats. +The first was denoted by the leading ``magic'' number 0177555 (stored as +type int). +These archives were almost certainly created on a 16-bit machine, and +contain headers made up of five fields. +The fields are the object name (8 characters), the file last modification +time (type long), the user id (type char), the file mode (type char) and +the file size (type unsigned int). +Files were padded to an even number of bytes. +.Pp +The second was denoted by the leading ``magic'' number 0177545 (stored as +type int). +These archives may have been created on either 16 or 32-bit machines, and +contain headers made up of six fields. +The fields are the object name (14 characters), the file last modification +time (type long), the user and group id's (each type char), the file mode +(type int) and the file size (type long). +Files were padded to an even number of bytes. +For more information on converting from this format see +.Xr arcv 8 . +.ne 1i +.Pp +The current archive format (without support for long character names and +names with embedded spaces) was introduced in +.Bx 4.0 . +The headers were the same as the current format, with the exception that +names longer than 16 characters were truncated, and names with embedded +spaces (and often trailing spaces) were not supported. +It has been extended for these reasons, +as described above. +This format first appeared in 4.4BSD. +.Sh COMPATIBILITY +No archive format is currently specified by any standard. +.At V +has historically distributed archives in a different format from +all of the above. diff --git a/usr.bin/ar/archive.c b/usr.bin/ar/archive.c new file mode 100644 index 000000000000..9dd6b2077f5a --- /dev/null +++ b/usr.bin/ar/archive.c @@ -0,0 +1,326 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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 8.4 (Berkeley) 4/27/95"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ar.h> +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "archive.h" +#include "extern.h" + +typedef struct ar_hdr HDR; +static char hb[sizeof(HDR) + 1]; /* real header */ + +int +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)) + warnx("creating archive %s", 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) { \ + memmove(buf, from, len); \ + buf[len] = '\0'; \ + to = strtol(buf, (char **)NULL, base); \ +} + +/* + * get_arobj -- + * read the archive header for this member + */ +int +get_arobj(fd) + int fd; +{ + struct ar_hdr *hdr; + int len, nr; + 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; + memmove(chdr.name, hdr->ar_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. + */ +void +put_arobj(cfp, sb) + CF *cfp; + struct stat *sb; +{ + int lname; + 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); + warnx("warning: %s truncated to %.*s", + name, OLDARMAXNAME, name); + (void)fflush(stderr); + } + (void)sprintf(hb, HDR3, name, sb->st_mtimespec.ts_sec, + sb->st_uid, sb->st_gid, sb->st_mode, sb->st_size, + ARFMAG); + lname = 0; + } else if (lname > sizeof(hdr->ar_name) || strchr(name, ' ')) + (void)sprintf(hb, HDR1, AR_EFMT1, lname, + sb->st_mtimespec.ts_sec, sb->st_uid, sb->st_gid, + sb->st_mode, sb->st_size + lname, ARFMAG); + else { + lname = 0; + (void)sprintf(hb, HDR2, name, sb->st_mtimespec.ts_sec, + 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. + */ +void +copy_ar(cfp, size) + CF *cfp; + off_t size; +{ + static char pad = '\n'; + off_t sz; + 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 + chdr.lname) & 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.bin/ar/misc.c b/usr.bin/ar/misc.c new file mode 100644 index 000000000000..f9c0d14578c8 --- /dev/null +++ b/usr.bin/ar/misc.c @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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[] = "@(#)misc.c 8.4 (Berkeley) 4/27/95"; +#endif /* not lint */ + +#include <sys/param.h> + +#include <dirent.h> +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "archive.h" +#include "extern.h" +#include "pathnames.h" + +char *tname = "temporary file"; /* temporary file "name" */ + +int +tmp() +{ + extern char *envtmp; + sigset_t set, oset; + static int first; + int fd; + char path[MAXPATHLEN]; + + if (!first && !envtmp) { + envtmp = getenv("TMPDIR"); + first = 1; + } + + if (envtmp) + (void)sprintf(path, "%s/%s", envtmp, _NAME_ARTMP); + else + strcpy(path, _PATH_ARTMP); + + sigfillset(&set); + (void)sigprocmask(SIG_BLOCK, &set, &oset); + if ((fd = mkstemp(path)) == -1) + error(tname); + (void)unlink(path); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + return (fd); +} + +/* + * files -- + * See if the current file matches any file in the argument list; if it + * does, remove it from the argument list. + */ +char * +files(argv) + char **argv; +{ + char **list, *p; + + for (list = argv; *list; ++list) + if (compare(*list)) { + p = *list; + for (; list[0] = list[1]; ++list) + continue; + return (p); + } + return (NULL); +} + +void +orphans(argv) + char **argv; +{ + + for (; *argv; ++argv) + warnx("%s: not found in archive", *argv); +} + +char * +rname(path) + char *path; +{ + char *ind; + + return ((ind = strrchr(path, '/')) ? ind + 1 : path); +} + +int +compare(dest) + char *dest; +{ + + if (options & AR_TR) + return (!strncmp(chdr.name, rname(dest), OLDARMAXNAME)); + return (!strcmp(chdr.name, rname(dest))); +} + +void +badfmt() +{ + + errno = EFTYPE; + err(1, "%s", archive); +} + +void +error(name) + char *name; +{ + + err(1, "%s", name); +} diff --git a/usr.bin/ar/replace.c b/usr.bin/ar/replace.c new file mode 100644 index 000000000000..4500b9077f66 --- /dev/null +++ b/usr.bin/ar/replace.c @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * 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 8.4 (Berkeley) 4/27/95"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ar.h> +#include <dirent.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "archive.h" +#include "extern.h" + +/* + * 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. + */ +int +replace(argv) + char **argv; +{ + char *file; + int afd, curfd, errflg, exists, mods, sfd, tfd1, tfd2; + struct stat sb; + CF cf; + off_t size, tsize; + + errflg = 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) { + errflg = 1; + warn("%s", file); + goto useold; + } + (void)fstat(sfd, &sb); + if (options & AR_U && sb.st_mtime <= chdr.date) { + (void)close(sfd); + 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) { + warnx("%s: archive member not found", 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) { + errflg = 1; + warn("%s", file); + 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 (errflg); +} |
