# 2.11BSD#431 - /usr/src/bin/ar/archive.c

##### Functions

    close_archive     X
    copy_ar           X
    get_arobj         X
    open_archive      X
    put_arobj         X
    skip_arobj        X

##### Macros

    AR_ATOI           X
    DECIMAL           X
    OCTAL             X

##### typedef's

    HDR               X

       1: /*-
       2:  * Copyright (c) 1990 The Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * This code is derived from software contributed to Berkeley by
       6:  * Hugh Smith at The University of Guelph.
       7:  *
       8:  * Redistribution and use in source and binary forms, with or without
       9:  * modification, are permitted provided that the following conditions
      10:  * are met:
      11:  * 1. Redistributions of source code must retain the above copyright
      12:  *    notice, this list of conditions and the following disclaimer.
      13:  * 2. Redistributions in binary form must reproduce the above copyright
      14:  *    notice, this list of conditions and the following disclaimer in the
      15:  *    documentation and/or other materials provided with the distribution.
      16:  * 3. All advertising materials mentioning features or use of this software
      17:  *    must display the following acknowledgement:
      18:  *	This product includes software developed by the University of
      19:  *	California, Berkeley and its contributors.
      20:  * 4. Neither the name of the University nor the names of its contributors
      21:  *    may be used to endorse or promote products derived from this software
      22:  *    without specific prior written permission.
      23:  *
      24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34:  * SUCH DAMAGE.
      35:  */
      36:
      37: #if defined(DOSCCS) && !defined(lint)
      38: static char sccsid[] = "@(#)archive.c	5.7 (Berkeley) 3/21/91";
      39: #endif
      40:
      41: #include <sys/param.h>
      42: #include <sys/stat.h>
      43: #include <errno.h>
      44: #include <sys/dir.h>
      45: #include <sys/file.h>
      46: #include <ar.h>
      47: #include <stdio.h>
      48: #include <string.h>
      49: #include "archive.h"
      50: #include "extern.h"
      51:
      52: extern CHDR chdr;           /* converted header */
      53: extern char *archive;           /* archive name */
      54: extern int errno;
      55:
      56: typedef struct ar_hdr HDR;
      57: static char hb[sizeof(HDR) + 1];    /* real header */
      58:
      59: open_archive(mode)
      60:     int mode;
      61: {
      62:     int created, fd, nr;
      63:     char buf[SARMAG];
      64:
      65:     created = 0;
      66:     if (mode & O_CREAT) {
      67:         mode |= O_EXCL;
      68:         if ((fd = open(archive, mode, 0666)) >= 0) {
      69:             /* POSIX.2 puts create message on stderr. */
      70:             if (!(options & AR_C))
      71:                 (void)fprintf(stderr,
      72:                     "ar: creating archive %s.\n", archive);
      73:             created = 1;
      74:             goto opened;
      75:         }
      76:         if (errno != EEXIST)
      77:             error(archive);
      78:         mode &= ~O_EXCL;
      79:     }
      80:     if ((fd = open(archive, mode, 0666)) < 0)
      81:         error(archive);
      82:
      83:     /*
      84: 	 * Attempt to place a lock on the opened file - if we get an
      85: 	 * error then someone is already working on this library (or
      86: 	 * it's going across NFS).
      87: 	 */
      88: opened: if (flock(fd, LOCK_EX|LOCK_NB) && errno != EOPNOTSUPP)
      89:         error(archive);
      90:
      91:     /*
      92: 	 * If not created, O_RDONLY|O_RDWR indicates that it has to be
      93: 	 * in archive format.
      94: 	 */
      95:     if (!created &&
      96:         ((mode & 3) == O_RDONLY || (mode & 3) == O_RDWR)) {
      97:         if ((nr = read(fd, buf, SARMAG) != SARMAG)) {
      98:             if (nr >= 0)
      99:                 badfmt();
     100:             error(archive);
     101:         } else if (bcmp(buf, ARMAG, SARMAG))
     102:             badfmt();
     103:     } else if (write(fd, ARMAG, SARMAG) != SARMAG)
     104:         error(archive);
     105:     return(fd);
     106: }
     107:
     108: void
     109: close_archive(fd)
     110:     int fd;
     111: {
     112:     (void)close(fd);            /* Implicit unlock. */
     113: }
     114:
     115: /* Convert ar header field to an integer. */
     116: #define AR_ATOI(from, to, len, base) { \
     117:     bcopy(from, buf, len); \
     118:     buf[len] = '\0'; \
     119:     to = strtol(buf, (char **)NULL, base); \
     120: }
     121:
     122: /*
     123:  * get_arobj --
     124:  *	read the archive header for this member
     125:  */
     126: get_arobj(fd)
     127:     int fd;
     128: {
     129:     struct ar_hdr *hdr;
     130:     register int len, nr;
     131:     register char *p;
     132:     char buf[20];
     133:
     134:     nr = read(fd, hb, sizeof(HDR));
     135:     if (nr != sizeof(HDR)) {
     136:         if (!nr)
     137:             return(0);
     138:         if (nr < 0)
     139:             error(archive);
     140:         badfmt();
     141:     }
     142:
     143:     hdr = (struct ar_hdr *)hb;
     144:     if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1))
     145:         badfmt();
     146:
     147:     /* Convert the header into the internal format. */
     148: #define DECIMAL 10
     149: #define OCTAL    8
     150:
     151:     AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL);
     152:     AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL);
     153:     AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL);
     154:     AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL);
     155:     AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL);
     156:
     157:     /* Leading spaces should never happen. */
     158:     if (hdr->ar_name[0] == ' ')
     159:         badfmt();
     160:
     161:     /*
     162: 	 * Long name support.  Set the "real" size of the file, and the
     163: 	 * long name flag/size.
     164: 	 */
     165:     if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) {
     166:         chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1);
     167:         if (len <= 0 || len > MAXNAMLEN)
     168:             badfmt();
     169:         nr = read(fd, chdr.name, (size_t)len);
     170:         if (nr != len) {
     171:             if (nr < 0)
     172:                 error(archive);
     173:             badfmt();
     174:         }
     175:         chdr.name[len] = 0;
     176:         chdr.size -= len;
     177:     } else {
     178:         chdr.lname = 0;
     179:         bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name));
     180:
     181:         /* Strip trailing spaces, null terminate. */
     182:         for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p);
     183:         *++p = '\0';
     184:     }
     185:     return(1);
     186: }
     187:
     188: static int already_written;
     189:
     190: /*
     191:  * put_arobj --
     192:  *	Write an archive member to a file.
     193:  */
     194: put_arobj(cfp, sb)
     195:     CF *cfp;
     196:     struct stat *sb;
     197: {
     198:     register int lname;
     199:     register char *name;
     200:     struct ar_hdr *hdr;
     201:     off_t size;
     202:
     203:     /*
     204: 	 * If passed an sb structure, reading a file from disk.  Get stat(2)
     205: 	 * information, build a name and construct a header.  (Files are named
     206: 	 * by their last component in the archive.)  If not, then just write
     207: 	 * the last header read.
     208: 	 */
     209:     if (sb) {
     210:         name = rname(cfp->rname);
     211:         (void)fstat(cfp->rfd, sb);
     212:
     213:         /*
     214: 		 * If not truncating names and the name is too long or contains
     215: 		 * a space, use extended format 1.
     216: 		 */
     217:         lname = strlen(name);
     218:         if (options & AR_TR) {
     219:             if (lname > OLDARMAXNAME) {
     220:                 (void)fflush(stdout);
     221:                 (void)fprintf(stderr,
     222:                     "ar: warning: %s truncated to %.*s\n",
     223:                     name, OLDARMAXNAME, name);
     224:                 (void)fflush(stderr);
     225:             }
     226:             (void)sprintf(hb, HDR3, name, sb->st_mtime, sb->st_uid,
     227:                 sb->st_gid, sb->st_mode, sb->st_size, ARFMAG);
     228:             lname = 0;
     229:         } else if (lname > sizeof(hdr->ar_name) || index(name, ' '))
     230:             (void)sprintf(hb, HDR1, AR_EFMT1, lname, sb->st_mtime,
     231:                 sb->st_uid, sb->st_gid, sb->st_mode,
     232:                 sb->st_size + lname, ARFMAG);
     233:         else {
     234:             lname = 0;
     235:             (void)sprintf(hb, HDR2, name, sb->st_mtime, sb->st_uid,
     236:                 sb->st_gid, sb->st_mode, sb->st_size, ARFMAG);
     237:         }
     238:         size = sb->st_size;
     239:     } else {
     240:         lname = chdr.lname;
     241:         name = chdr.name;
     242:         size = chdr.size;
     243:     }
     244:
     245:     if (write(cfp->wfd, hb, sizeof(HDR)) != sizeof(HDR))
     246:         error(cfp->wname);
     247:     if (lname) {
     248:         if (write(cfp->wfd, name, (size_t)lname) != lname)
     249:             error(cfp->wname);
     250:         already_written = lname;
     251:     }
     252:     copy_ar(cfp, size);
     253:     already_written = 0;
     254: }
     255:
     256: /*
     257:  * copy_ar --
     258:  *	Copy size bytes from one file to another - taking care to handle the
     259:  *	extra byte (for odd size files) when reading archives and writing an
     260:  *	extra byte if necessary when adding files to archive.  The length of
     261:  *	the object is the long name plus the object itself; the variable
     262:  *	already_written gets set if a long name was written.
     263:  *
     264:  *	The padding is really unnecessary, and is almost certainly a remnant
     265:  *	of early archive formats where the header included binary data which
     266:  *	a PDP-11 required to start on an even byte boundary.  (Or, perhaps,
     267:  *	because 16-bit word addressed copies were faster?)  Anyhow, it should
     268:  *	have been ripped out long ago.
     269:  */
     270: copy_ar(cfp, size)
     271:     CF *cfp;
     272:     off_t size;
     273: {
     274:     static char pad = '\n';
     275:     off_t sz;
     276:     register int from, nr, nw, off, to;
     277: #ifdef  pdp11
     278:     char buf[2*1024];
     279: #else
     280:     char buf[8*1024];
     281: #endif
     282:
     283:     if (!(sz = size))
     284:         return;
     285:
     286:     from = cfp->rfd;
     287:     to = cfp->wfd;
     288:     while (sz && (nr = read(from, buf, (size_t)(MIN(sz, sizeof(buf))))) > 0) {
     289:         sz -= nr;
     290:         for (off = 0; off < nr; nr -= off, off += nw)
     291:             if ((nw = write(to, buf + off, (size_t)nr)) < 0)
     292:                 error(cfp->wname);
     293:     }
     294:     if (sz) {
     295:         if (nr == 0)
     296:             badfmt();
     297:         error(cfp->rname);
     298:     }
     299:
     300:     if (cfp->flags & RPAD && size & 1 && (nr = read(from, buf, 1)) != 1) {
     301:         if (nr == 0)
     302:             badfmt();
     303:         error(cfp->rname);
     304:     }
     305:     if (cfp->flags & WPAD && (size + already_written) & 1 &&
     306:         write(to, &pad, 1) != 1)
     307:         error(cfp->wname);
     308: }
     309:
     310: /*
     311:  * skip_arobj -
     312:  *	Skip over an object -- taking care to skip the pad bytes.
     313:  */
     314: void
     315: skip_arobj(fd)
     316:     int fd;
     317: {
     318:     off_t len;
     319:
     320:     len = chdr.size + (chdr.size + chdr.lname & 1);
     321:     if (lseek(fd, len, L_INCR) == (off_t)-1)
     322:         error(archive);
     323: }

#### Defined functions

close_archive defined in line 108; used 10 times

- in /usr/src/bin/ar/append.c line 88
- in /usr/src/bin/ar/archive.h line 96
- in /usr/src/bin/ar/contents.c line 106
- in /usr/src/bin/ar/delete.c line 90
- in /usr/src/bin/ar/extract.c line 120
- in /usr/src/bin/ar/move.c line 114, 135
- in /usr/src/bin/ar/print.c line 82
- in /usr/src/bin/ar/replace.c line 146, 184

copy_ar defined in line 270; used 10 times

- in line 252
- in /usr/src/bin/ar/archive.h line 98
- in /usr/src/bin/ar/delete.c line 87
- in /usr/src/bin/ar/extract.c line 103
- in /usr/src/bin/ar/move.c line 122-132(3)
- in /usr/src/bin/ar/print.c line 78
- in /usr/src/bin/ar/replace.c line 174, 181

get_arobj defined in line 126; used 7 times

- in /usr/src/bin/ar/archive.h line 99
- in /usr/src/bin/ar/contents.c line 70
- in /usr/src/bin/ar/delete.c line 73
- in /usr/src/bin/ar/extract.c line 79
- in /usr/src/bin/ar/move.c line 89
- in /usr/src/bin/ar/print.c line 67
- in /usr/src/bin/ar/replace.c line 102

open_archive defined in line 59; used 8 times

- in /usr/src/bin/ar/append.c line 68
- in /usr/src/bin/ar/archive.h line 100
- in /usr/src/bin/ar/contents.c line 68
- in /usr/src/bin/ar/delete.c line 68
- in /usr/src/bin/ar/extract.c line 75
- in /usr/src/bin/ar/move.c line 72
- in /usr/src/bin/ar/print.c line 63
- in /usr/src/bin/ar/replace.c line 83

put_arobj defined in line 194; used 10 times

- in /usr/src/bin/ar/append.c line 85
- in /usr/src/bin/ar/archive.h line 101
- in /usr/src/bin/ar/delete.c line 80
- in /usr/src/bin/ar/move.c line 94, 102-107(2)
- in /usr/src/bin/ar/replace.c line 121, 133, 139, 164

skip_arobj defined in line 314; used 7 times

- in /usr/src/bin/ar/archive.h line 97
- in /usr/src/bin/ar/contents.c line 104
- in /usr/src/bin/ar/delete.c line 77
- in /usr/src/bin/ar/extract.c line 83, 94
- in /usr/src/bin/ar/print.c line 71
- in /usr/src/bin/ar/replace.c line 123

#### Defined variables

already_written defined in line 188; used 3 times

- in line 250-253(2), 305

hb defined in line 57; used 6 times

- in line 134, 143, 226-235(3), 245

sccsid defined in line 38; never used

#### Defined typedef's

HDR defined in line 56; used 5 times

- in line 57, 134-135(2), 245(2)

#### Defined macros

AR_ATOI defined in line 116; used 5 times

- in line 151-155(5)

DECIMAL defined in line 148; used 4 times

- in line 151-155(4)

OCTAL defined in line 149; used 1 times

- in line 154

Last modified: 1993-09-25 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1726 |