Annotation of coherent/d/usr/bin/pax/public/part03.sh, revision 1.1.1.1

1.1       root        1: # This is a shell archive.  Remove anything before this line, then unpack
                      2: # it by saving it into a file and typing "sh file".  To overwrite existing
                      3: # files, type "sh file -c".  You can also feed this as standard input via
                      4: # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
                      5: # will see the following message at the end:
                      6: #              "End of archive 3 (of 6)."
                      7: # Contents:  fileio.c namelist.c pax.c pax.h tar.c
                      8: # Wrapped by mark@jhereg on Tue Dec 27 19:37:45 1988
                      9: PATH=/bin:/usr/bin:/usr/ucb ; export PATH
                     10: if test -f fileio.c -a "${1}" != "-c" ; then 
                     11:   echo shar: Will not over-write existing file \"fileio.c\"
                     12: else
                     13: echo shar: Extracting \"fileio.c\" \(10596 characters\)
                     14: sed "s/^X//" >fileio.c <<'END_OF_fileio.c'
                     15: X/* $Source: /u/mark/src/pax/RCS/fileio.c,v $
                     16: X *
                     17: X * $Revision: 1.1 $
                     18: X *
                     19: X * fileio.c - file I/O functions for all archive interfaces
                     20: X *
                     21: X * DESCRIPTION
                     22: X *
                     23: X *    These function all do I/O of some form or another.  They are
                     24: X *    grouped here mainly for convienence.
                     25: X *
                     26: X * AUTHOR
                     27: X *
                     28: X *    Mark H. Colburn, NAPS International ([email protected])
                     29: X *
                     30: X * Sponsored by The USENIX Association for public distribution. 
                     31: X *
                     32: X * Copyright (c) 1989 Mark H. Colburn.
                     33: X * All rights reserved.
                     34: X *
                     35: X * Redistribution and use in source and binary forms are permitted
                     36: X * provided that the above copyright notice is duplicated in all such 
                     37: X * forms and that any documentation, advertising materials, and other 
                     38: X * materials related to such distribution and use acknowledge that the 
                     39: X * software was developed * by Mark H. Colburn and sponsored by The 
                     40: X * USENIX Association. 
                     41: X *
                     42: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     43: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     44: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     45: X *
                     46: X * $Log:      fileio.c,v $
                     47: X * Revision 1.1  88/12/23  18:02:09  mark
                     48: X * Initial revision
                     49: X * 
                     50: X */
                     51: X
                     52: X#ifndef lint
                     53: Xstatic char *ident = "$Id: fileio.c,v 1.1 88/12/23 18:02:09 mark Rel $";
                     54: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     55: X#endif /* ! lint */
                     56: X
                     57: X
                     58: X/* Headers */
                     59: X
                     60: X#include "pax.h"
                     61: X
                     62: X
                     63: X/* open_archive -  open an archive file.  
                     64: X *
                     65: X * DESCRIPTION
                     66: X *
                     67: X *    Open_archive will open an archive file for reading or writing,
                     68: X *    setting the proper file mode, depending on the "mode" passed to
                     69: X *    it.  All buffer pointers are reset according to the mode
                     70: X *    specified.
                     71: X *
                     72: X * PARAMETERS
                     73: X *
                     74: X *    int     mode    - specifies whether we are reading or writing.   
                     75: X *
                     76: X * RETURNS
                     77: X *
                     78: X *    Returns a zero if successfull, or -1 if an error occured during 
                     79: X *    the open.
                     80: X */
                     81: X
                     82: X#ifdef __STDC__
                     83: X    
                     84: Xint open_archive(int mode)
                     85: X
                     86: X#else
                     87: X    
                     88: Xint open_archive(mode)
                     89: Xint             mode;
                     90: X
                     91: X#endif
                     92: X{
                     93: X    if (ar_file[0] == '-' && ar_file[1] == '\0') {
                     94: X      if (mode == AR_READ) {
                     95: X          archivefd = STDIN;
                     96: X          bufend = bufidx = bufstart;
                     97: X      } else {
                     98: X          archivefd = STDOUT;
                     99: X      }
                    100: X    } else if (mode == AR_READ) {
                    101: X      archivefd = open(ar_file, O_RDONLY | O_BINARY);
                    102: X      bufend = bufidx = bufstart;     /* set up for initial read */
                    103: X    } else if (mode == AR_WRITE) {
                    104: X      archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
                    105: X    } else if (mode == AR_APPEND) {
                    106: X      archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
                    107: X      bufend = bufidx = bufstart;     /* set up for initial read */
                    108: X    }
                    109: X
                    110: X    if (archivefd < 0) {
                    111: X      warnarch(syserr(), (OFFSET) 0);
                    112: X      return (-1);
                    113: X    }
                    114: X    ++arvolume;
                    115: X    return (0);
                    116: X}
                    117: X
                    118: X
                    119: X/* close_archive - close the archive file
                    120: X *
                    121: X * DESCRIPTION
                    122: X *
                    123: X *    Closes the current archive and resets the archive end of file
                    124: X *    marker.
                    125: X */
                    126: X
                    127: X#ifdef __STDC__
                    128: X
                    129: Xvoid close_archive(void)
                    130: X
                    131: X#else
                    132: X    
                    133: Xvoid close_archive()
                    134: X
                    135: X#endif
                    136: X{
                    137: X    if (archivefd != STDIN && archivefd != STDOUT) {
                    138: X      close(archivefd);
                    139: X    }
                    140: X    areof = 0;
                    141: X}
                    142: X
                    143: X
                    144: X/* openo - open an output file
                    145: X *
                    146: X * DESCRIPTION
                    147: X *
                    148: X *    Openo opens the named file for output.  The file mode and type are
                    149: X *    set based on the values stored in the stat structure for the file.
                    150: X *    If the file is a special file, then no data will be written, the
                    151: X *    file/directory/Fifo, etc., will just be created.  Appropriate
                    152: X *    permission may be required to create special files.
                    153: X *
                    154: X * PARAMETERS
                    155: X *
                    156: X *    char    *name           - The name of the file to create
                    157: X *    Stat    *asb            - Stat structure for the file
                    158: X *    Link    *linkp;         - pointer to link chain for this file
                    159: X *    int      ispass         - true if we are operating in "pass" mode
                    160: X *
                    161: X * RETURNS
                    162: X *
                    163: X *    Returns the output file descriptor, 0 if no data is required or -1 
                    164: X *    if unsuccessful. Note that UNIX open() will never return 0 because 
                    165: X *    the standard input is in use. 
                    166: X */
                    167: X
                    168: X#ifdef __STDC__
                    169: X
                    170: Xint openo(char *name, Stat *asb, Link *linkp, int ispass)
                    171: X
                    172: X#else
                    173: X    
                    174: Xint openo(name, asb, linkp, ispass)
                    175: Xchar           *name;
                    176: XStat           *asb;
                    177: XLink           *linkp;
                    178: Xint             ispass;
                    179: X
                    180: X#endif
                    181: X{
                    182: X    int             exists;
                    183: X    int             fd;
                    184: X    ushort          perm;
                    185: X    ushort          operm = 0;
                    186: X    Stat            osb;
                    187: X#ifdef        S_IFLNK
                    188: X    int             ssize;
                    189: X    char            sname[PATH_MAX + 1];
                    190: X#endif        /* S_IFLNK */
                    191: X
                    192: X    if (exists = (LSTAT(name, &osb) == 0)) {
                    193: X      if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
                    194: X          warn(name, "Same file");
                    195: X          return (-1);
                    196: X      } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
                    197: X          operm = osb.sb_mode & S_IPERM;
                    198: X      } else if (REMOVE(name, &osb) < 0) {
                    199: X          warn(name, syserr());
                    200: X          return (-1);
                    201: X      } else {
                    202: X          exists = 0;
                    203: X      }
                    204: X    }
                    205: X    if (linkp) {
                    206: X      if (exists) {
                    207: X          if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
                    208: X              return (0);
                    209: X          } else if (unlink(name) < 0) {
                    210: X              warn(name, syserr());
                    211: X              return (-1);
                    212: X          } else {
                    213: X              exists = 0;
                    214: X          }
                    215: X      }
                    216: X      if (link(linkp->l_name, name) != 0) {
                    217: X          if (errno == ENOENT) {
                    218: X              if (f_create_dirs) {
                    219: X                  if (dirneed(name) != 0 ||
                    220: X                          link(linkp->l_name, name) != 0) {
                    221: X                          warn(name, syserr());
                    222: X                      return (-1);
                    223: X                  }
                    224: X              } else {
                    225: X                  warn(name, 
                    226: X                           "Directories are not being created (-d option)");
                    227: X              }
                    228: X              return(0);
                    229: X          } else if (errno != EXDEV) {
                    230: X              warn(name, syserr());
                    231: X              return (-1);
                    232: X          }
                    233: X      } else {
                    234: X          return(0);
                    235: X      } 
                    236: X    }
                    237: X    perm = asb->sb_mode & S_IPERM;
                    238: X    switch (asb->sb_mode & S_IFMT) {
                    239: X    case S_IFBLK:
                    240: X    case S_IFCHR:
                    241: X      fd = 0;
                    242: X      if (exists) {
                    243: X          if (asb->sb_rdev == osb.sb_rdev) {
                    244: X              if (perm != operm && chmod(name, (int) perm) < 0) {
                    245: X                  warn(name, syserr());
                    246: X                  return (-1);
                    247: X              } else {
                    248: X                  break;
                    249: X              }
                    250: X          } else if (REMOVE(name, &osb) < 0) {
                    251: X              warn(name, syserr());
                    252: X              return (-1);
                    253: X          } else {
                    254: X              exists = 0;
                    255: X          }
                    256: X      }
                    257: X      if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
                    258: X          if (errno == ENOENT) {
                    259: X              if (f_create_dirs) {
                    260: X                  if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode, 
                    261: X                         (int) asb->sb_rdev) < 0) {
                    262: X                      warn(name, syserr());
                    263: X                      return (-1);
                    264: X                  }
                    265: X              } else {
                    266: X                  warn(name, "Directories are not being created (-d option)");
                    267: X              }
                    268: X          } else {
                    269: X              warn(name, syserr());
                    270: X              return (-1);
                    271: X          }
                    272: X      }
                    273: X      return(0);
                    274: X      break;
                    275: X    case S_IFDIR:
                    276: X      if (exists) {
                    277: X          if (perm != operm && chmod(name, (int) perm) < 0) {
                    278: X              warn(name, syserr());
                    279: X              return (-1);
                    280: X          }
                    281: X      } else if (f_create_dirs) {
                    282: X          if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
                    283: X              warn(name, syserr());
                    284: X              return (-1);
                    285: X          }
                    286: X      } else {
                    287: X          warn(name, "Directories are not being created (-d option)");
                    288: X      }
                    289: X      return (0);
                    290: X#ifdef        S_IFIFO
                    291: X    case S_IFIFO:
                    292: X      fd = 0;
                    293: X      if (exists) {
                    294: X          if (perm != operm && chmod(name, (int) perm) < 0) {
                    295: X              warn(name, syserr());
                    296: X              return (-1);
                    297: X          }
                    298: X      } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
                    299: X          if (errno == ENOENT) {
                    300: X              if (f_create_dirs) {
                    301: X                  if (dirneed(name) < 0
                    302: X                     || mknod(name, (int) asb->sb_mode, 0) < 0) {
                    303: X                      warn(name, syserr());
                    304: X                      return (-1);
                    305: X                  }
                    306: X              } else {
                    307: X                  warn(name, "Directories are not being created (-d option)");
                    308: X              }
                    309: X          } else {
                    310: X              warn(name, syserr());
                    311: X              return (-1);
                    312: X          }
                    313: X      }
                    314: X      return(0);
                    315: X      break;
                    316: X#endif                                /* S_IFIFO */
                    317: X#ifdef        S_IFLNK
                    318: X    case S_IFLNK:
                    319: X      if (exists) {
                    320: X          if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
                    321: X              warn(name, syserr());
                    322: X              return (-1);
                    323: X          } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
                    324: X              return (0);
                    325: X          } else if (REMOVE(name, &osb) < 0) {
                    326: X              warn(name, syserr());
                    327: X              return (-1);
                    328: X          } else {
                    329: X              exists = 0;
                    330: X          }
                    331: X      }
                    332: X      if (symlink(asb->sb_link, name) < 0) {
                    333: X          if (errno == ENOENT) {
                    334: X              if (f_create_dirs) {
                    335: X                  if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
                    336: X                      warn(name, syserr());
                    337: X                      return (-1);
                    338: X                  }
                    339: X              } else {
                    340: X                  warn(name, "Directories are not being created (-d option)");
                    341: X              }
                    342: X          } else {
                    343: X              warn(name, syserr());
                    344: X              return (-1);
                    345: X          }
                    346: X      }
                    347: X      return (0);             /* Can't chown()/chmod() a symbolic link */
                    348: X#endif                                /* S_IFLNK */
                    349: X    case S_IFREG:
                    350: X      if (exists) {
                    351: X          if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
                    352: X              warn(name, "Newer file exists");
                    353: X              return (-1);
                    354: X          } else if (unlink(name) < 0) {
                    355: X              warn(name, syserr());
                    356: X              return (-1);
                    357: X          } else {
                    358: X              exists = 0;
                    359: X          }
                    360: X      }
                    361: X      if ((fd = creat(name, (int) perm)) < 0) {
                    362: X          if (errno == ENOENT) {
                    363: X              if (f_create_dirs) {
                    364: X                  if (dirneed(name) < 0 || 
                    365: X                          (fd = creat(name, (int) perm)) < 0) {
                    366: X                      warn(name, syserr());
                    367: X                      return (-1);
                    368: X                  }
                    369: X              } else {
                    370: X                  /* 
                    371: X                   * the file requires a directory which does not exist
                    372: X                   * and which the user does not want created, so skip
                    373: X                   * the file...
                    374: X                   */
                    375: X                  warn(name, "Directories are not being created (-d option)");
                    376: X                  return(0);
                    377: X              }
                    378: X          } else {
                    379: X              warn(name, syserr());
                    380: X              return (-1);
                    381: X          }
                    382: X      }
                    383: X      break;
                    384: X    default:
                    385: X      warn(name, "Unknown filetype");
                    386: X      return (-1);
                    387: X    }
                    388: X    if (f_owner) {
                    389: X      if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
                    390: X          chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
                    391: X      }
                    392: X    }
                    393: X    return (fd);
                    394: X}
                    395: X
                    396: X
                    397: X/* openi - open the next input file
                    398: X *
                    399: X * DESCRIPTION
                    400: X *
                    401: X *    Openi will attempt to open the next file for input.  If the file is
                    402: X *    a special file, such as a directory, FIFO, link, character- or
                    403: X *    block-special file, then the file size field of the stat structure
                    404: X *    is zeroed to make sure that no data is written out for the file.
                    405: X *    If the file is a special file, then a file descriptor of 0 is
                    406: X *    returned to the caller, which is handled specially.  If the file
                    407: X *    is a regular file, then the file is opened and a file descriptor
                    408: X *    to the open file is returned to the caller.
                    409: X *
                    410: X * PARAMETERS
                    411: X *
                    412: X *    char   *name    - pointer to the name of the file to open
                    413: X *    Stat   *asb     - pointer to the stat block for the file to open
                    414: X *
                    415: X * RETURNS
                    416: X *
                    417: X *    Returns a file descriptor, 0 if no data exists, or -1 at EOF. This 
                    418: X *    kludge works because standard input is in use, preventing open() from 
                    419: X *    returning zero. 
                    420: X */
                    421: X
                    422: X#ifdef __STDC__
                    423: X
                    424: Xint openi(char *name, Stat *asb)
                    425: X
                    426: X#else
                    427: X    
                    428: Xint openi(name, asb)
                    429: Xchar           *name;         /* name of file to open */
                    430: XStat           *asb;          /* pointer to stat structure for file */
                    431: X
                    432: X#endif
                    433: X{
                    434: X    int             fd;
                    435: X
                    436: X    switch (asb->sb_mode & S_IFMT) {
                    437: X    case S_IFDIR:
                    438: X      asb->sb_nlink = 1;
                    439: X      asb->sb_size = 0;
                    440: X      return (0);
                    441: X#ifdef        S_IFLNK
                    442: X    case S_IFLNK:
                    443: X      if ((asb->sb_size = readlink(name,
                    444: X                           asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
                    445: X          warn(name, syserr());
                    446: X          return(0);
                    447: X      }
                    448: X      asb->sb_link[asb->sb_size] = '\0';
                    449: X      return (0);
                    450: X#endif                                /* S_IFLNK */
                    451: X    case S_IFREG:
                    452: X      if (asb->sb_size == 0) {
                    453: X          return (0);
                    454: X      }
                    455: X      if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
                    456: X          warn(name, syserr());
                    457: X      }
                    458: X      return (fd);
                    459: X    default:
                    460: X      asb->sb_size = 0;
                    461: X      return (0);
                    462: X    }
                    463: X}
                    464: END_OF_fileio.c
                    465: if test 10596 -ne `wc -c <fileio.c`; then
                    466:     echo shar: \"fileio.c\" unpacked with wrong size!
                    467: fi
                    468: # end of overwriting check
                    469: fi
                    470: if test -f namelist.c -a "${1}" != "-c" ; then 
                    471:   echo shar: Will not over-write existing file \"namelist.c\"
                    472: else
                    473: echo shar: Extracting \"namelist.c\" \(11056 characters\)
                    474: sed "s/^X//" >namelist.c <<'END_OF_namelist.c'
                    475: X/* $Source: /u/mark/src/pax/RCS/namelist.c,v $
                    476: X *
                    477: X * $Revision: 1.1 $
                    478: X *
                    479: X * namelist.c - track filenames given as arguments to tar/cpio/pax
                    480: X *
                    481: X * DESCRIPTION
                    482: X *
                    483: X *    Arguments may be regular expressions, therefore all agurments will
                    484: X *    be treated as if they were regular expressions, even if they are
                    485: X *    not.
                    486: X *
                    487: X * AUTHOR
                    488: X *
                    489: X *    Mark H. Colburn, NAPS International ([email protected])
                    490: X *
                    491: X * Sponsored by The USENIX Association for public distribution. 
                    492: X *
                    493: X * Copyright (c) 1989 Mark H. Colburn.
                    494: X * All rights reserved.
                    495: X *
                    496: X * Redistribution and use in source and binary forms are permitted
                    497: X * provided that the above copyright notice is duplicated in all such 
                    498: X * forms and that any documentation, advertising materials, and other 
                    499: X * materials related to such distribution and use acknowledge that the 
                    500: X * software was developed * by Mark H. Colburn and sponsored by The 
                    501: X * USENIX Association. 
                    502: X *
                    503: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                    504: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                    505: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                    506: X *
                    507: X * $Log:      namelist.c,v $
                    508: X * Revision 1.1  88/12/23  18:02:17  mark
                    509: X * Initial revision
                    510: X * 
                    511: X */
                    512: X
                    513: X#ifndef lint
                    514: Xstatic char *ident = "$Id: namelist.c,v 1.1 88/12/23 18:02:17 mark Rel $";
                    515: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                    516: X#endif /* ! lint */
                    517: X
                    518: X
                    519: X/* Headers */
                    520: X
                    521: X#include "pax.h"
                    522: X
                    523: X
                    524: X/* Type Definitions */
                    525: X
                    526: X/*
                    527: X * Structure for keeping track of filenames and lists thereof. 
                    528: X */
                    529: Xstruct nm_list {
                    530: X    struct nm_list *next;
                    531: X    short           length;   /* cached strlen(name) */
                    532: X    char            found;    /* A matching file has been found */
                    533: X    char            firstch;  /* First char is literally matched */
                    534: X    char            regexp;   /* regexp pattern for item */
                    535: X    char            name[1];  /* name of file or rexexp */
                    536: X};
                    537: X
                    538: Xstruct dirinfo {
                    539: X    char            dirname[PATH_MAX + 1];    /* name of directory */
                    540: X    OFFSET        where;      /* current location in directory */
                    541: X    struct dirinfo *next;
                    542: X};
                    543: X
                    544: X
                    545: X/* Function Prototypes */
                    546: X
                    547: X#ifndef __STDC__
                    548: X
                    549: Xstatic void pushdir();
                    550: Xstatic struct dirinfo *popdir();
                    551: X
                    552: X#else
                    553: X
                    554: Xstatic void pushdir(struct dirinfo *info);
                    555: Xstatic struct dirinfo *popdir(void);
                    556: X
                    557: X#endif
                    558: X
                    559: X
                    560: X/* Internal Identifiers */
                    561: X
                    562: Xstatic struct nm_list *namelast;      /* Points to last name in list */
                    563: Xstatic struct nm_list *namelist;      /* Points to first name in list */
                    564: X
                    565: X
                    566: X/* addname -  add a name to the namelist. 
                    567: X *
                    568: X * DESCRIPTION
                    569: X *
                    570: X *    Addname adds the name given to the name list.  Memory for the
                    571: X *    namelist structure is dynamically allocated.  If the space for 
                    572: X *    the structure cannot be allocated, then the program will exit
                    573: X *    the an out of memory error message and a non-zero return code
                    574: X *    will be returned to the caller.
                    575: X *
                    576: X * PARAMETERS
                    577: X *
                    578: X *    char *name      - A pointer to the name to add to the list
                    579: X */
                    580: X
                    581: X#ifdef __STDC__
                    582: X
                    583: Xvoid add_name(char *name)
                    584: X
                    585: X#else
                    586: X    
                    587: Xvoid add_name(name)
                    588: Xchar           *name;         /* pointer to name */
                    589: X
                    590: X#endif
                    591: X{
                    592: X    int             i;                /* Length of string */
                    593: X    struct nm_list *p;                /* Current struct pointer */
                    594: X
                    595: X    i = strlen(name);
                    596: X    p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
                    597: X    if (!p) {
                    598: X      fatal("cannot allocate memory for namelist entry\n");
                    599: X    }
                    600: X    p->next = (struct nm_list *) NULL;
                    601: X    p->length = i;
                    602: X    strncpy(p->name, name, i);
                    603: X    p->name[i] = '\0';                /* Null term */
                    604: X    p->found = 0;
                    605: X    p->firstch = isalpha(name[0]);
                    606: X    if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
                    607: X        p->regexp = 1;
                    608: X    }
                    609: X    if (namelast) {
                    610: X      namelast->next = p;
                    611: X    }
                    612: X    namelast = p;
                    613: X    if (!namelist) {
                    614: X      namelist = p;
                    615: X    }
                    616: X}
                    617: X
                    618: X
                    619: X/* name_match - match a name from an archive with a name from the namelist 
                    620: X *
                    621: X * DESCRIPTION
                    622: X *
                    623: X *    Name_match attempts to find a name pointed at by p in the namelist.
                    624: X *    If no namelist is available, then all filenames passed in are
                    625: X *    assumed to match the filename criteria.  Name_match knows how to
                    626: X *    match names with regular expressions, etc.
                    627: X *
                    628: X * PARAMETERS
                    629: X *
                    630: X *    char    *p      - the name to match
                    631: X *
                    632: X * RETURNS
                    633: X *
                    634: X *    Returns 1 if the name is in the namelist, or no name list is
                    635: X *    available, otherwise returns 0
                    636: X *
                    637: X */
                    638: X
                    639: X#ifdef __STDC__
                    640: X
                    641: Xint name_match(char *p)
                    642: X
                    643: X#else
                    644: X    
                    645: Xint name_match(p)
                    646: Xchar           *p;
                    647: X
                    648: X#endif
                    649: X{
                    650: X    struct nm_list *nlp;
                    651: X    int             len;
                    652: X
                    653: X    if ((nlp = namelist) == 0) {/* Empty namelist is easy */
                    654: X      return (1);
                    655: X    }
                    656: X    len = strlen(p);
                    657: X    for (; nlp != 0; nlp = nlp->next) {
                    658: X      /* If first chars don't match, quick skip */
                    659: X      if (nlp->firstch && nlp->name[0] != p[0]) {
                    660: X          continue;
                    661: X      }
                    662: X      /* Regular expressions */
                    663: X      if (nlp->regexp) {
                    664: X          if (wildmat(nlp->name, p)) {
                    665: X              nlp->found = 1; /* Remember it matched */
                    666: X              return (1);     /* We got a match */
                    667: X          }
                    668: X          continue;
                    669: X      }
                    670: X      /* Plain Old Strings */
                    671: X      if (nlp->length <= len  /* Archive len >= specified */
                    672: X          && (p[nlp->length] == '\0' || p[nlp->length] == '/')
                    673: X          && strncmp(p, nlp->name, nlp->length) == 0) {
                    674: X          /* Name compare */
                    675: X          nlp->found = 1;     /* Remember it matched */
                    676: X          return (1);         /* We got a match */
                    677: X      }
                    678: X    }
                    679: X    return (0);
                    680: X}
                    681: X
                    682: X
                    683: X/* names_notfound - print names of files in namelist that were not found 
                    684: X *
                    685: X * DESCRIPTION
                    686: X *
                    687: X *    Names_notfound scans through the namelist for any files which were
                    688: X *    named, but for which a matching file was not processed by the
                    689: X *    archive.  Each of the files is listed on the standard error.
                    690: X *
                    691: X */
                    692: X
                    693: X#ifdef __STDC__
                    694: X
                    695: Xvoid names_notfound(void)
                    696: X
                    697: X#else
                    698: X    
                    699: Xvoid names_notfound()
                    700: X
                    701: X#endif
                    702: X{
                    703: X    struct nm_list *nlp;
                    704: X
                    705: X    for (nlp = namelist; nlp != 0; nlp = nlp->next) {
                    706: X      if (!nlp->found) {
                    707: X          fprintf(stderr, "%s: %s not found in archive\n",
                    708: X                         myname, nlp->name);
                    709: X      }
                    710: X      free(nlp);
                    711: X    }
                    712: X    namelist = (struct nm_list *) NULL;
                    713: X    namelast = (struct nm_list *) NULL;
                    714: X}
                    715: X
                    716: X
                    717: X/* name_init - set up to gather file names 
                    718: X *
                    719: X * DESCRIPTION
                    720: X *
                    721: X *    Name_init sets up the namelist pointers so that we may access the
                    722: X *    command line arguments.  At least the first item of the command
                    723: X *    line (argv[0]) is assumed to be stripped off, prior to the
                    724: X *    name_init call.
                    725: X *
                    726: X * PARAMETERS
                    727: X *
                    728: X *    int     argc    - number of items in argc
                    729: X *    char    **argv  - pointer to the command line arguments
                    730: X */
                    731: X
                    732: X#ifdef __STDC__
                    733: X
                    734: Xvoid name_init(int argc, char **argv)
                    735: X
                    736: X#else
                    737: X    
                    738: Xvoid name_init(argc, argv)
                    739: Xint             argc;
                    740: Xchar          **argv;
                    741: X
                    742: X#endif
                    743: X{
                    744: X    /* Get file names from argv, after options. */
                    745: X    n_argc = argc;
                    746: X    n_argv = argv;
                    747: X}
                    748: X
                    749: X
                    750: X/* name_next - get the next name from argv or the name file. 
                    751: X *
                    752: X * DESCRIPTION
                    753: X *
                    754: X *    Name next finds the next name which is to be processed in the
                    755: X *    archive.  If the named file is a directory, then the directory
                    756: X *    is recursively traversed for additional file names.  Directory
                    757: X *    names and locations within the directory are kept track of by
                    758: X *    using a directory stack.  See the pushdir/popdir function for
                    759: X *    more details.
                    760: X *
                    761: X *    The names come from argv, after options or from the standard input.  
                    762: X *
                    763: X * PARAMETERS
                    764: X *
                    765: X *    name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
                    766: X *    statbuf - a pointer to a stat structure
                    767: X *
                    768: X * RETURNS
                    769: X *
                    770: X *    Returns -1 if there are no names left, (e.g. EOF), otherwise returns 
                    771: X *    0 
                    772: X */
                    773: X
                    774: X#ifdef __STDC__
                    775: X
                    776: Xint name_next(char *name, Stat *statbuf)
                    777: X
                    778: X#else
                    779: X    
                    780: Xint name_next(name, statbuf)
                    781: Xchar           *name;
                    782: XStat           *statbuf;
                    783: X
                    784: X#endif
                    785: X{
                    786: X    int             err = -1;
                    787: X    static int      in_subdir = 0;
                    788: X    static DIR     *dirp;
                    789: X    struct dirent  *d;
                    790: X    static struct dirinfo *curr_dir;
                    791: X    int                       len;
                    792: X
                    793: X    do {
                    794: X      if (names_from_stdin) {
                    795: X          if (lineget(stdin, name) < 0) {
                    796: X              return (-1);
                    797: X          }
                    798: X          if (nameopt(name) < 0) {
                    799: X              continue;
                    800: X          }
                    801: X      } else {
                    802: X          if (in_subdir) {
                    803: X              if ((d = readdir(dirp)) != NULL) {
                    804: X                  /* Skip . and .. */
                    805: X                  if (strcmp(d->d_name, ".") == 0 ||
                    806: X                      strcmp(d->d_name, "..") == 0) {
                    807: X                          continue;
                    808: X                  }
                    809: X                  if (strlen(d->d_name) + 
                    810: X                      strlen(curr_dir->dirname) >= PATH_MAX) {
                    811: X                      warn("name too long", d->d_name);
                    812: X                      continue;
                    813: X                  }
                    814: X                  strcpy(name, curr_dir->dirname);
                    815: X                  strcat(name, d->d_name);
                    816: X              } else {
                    817: X                  closedir(dirp);
                    818: X                  in_subdir--;
                    819: X                  curr_dir = popdir();
                    820: X                  if (in_subdir) {
                    821: X                      errno = 0;
                    822: X                      if ((dirp = opendir(curr_dir->dirname)) == NULL) {
                    823: X                          warn(curr_dir->dirname, "error opening directory (1)");
                    824: X                          in_subdir--;
                    825: X                      }
                    826: X                      seekdir(dirp, curr_dir->where);
                    827: X                  }
                    828: X                  continue;
                    829: X              }
                    830: X          } else if (optind >= n_argc) {
                    831: X              return (-1);
                    832: X          } else {
                    833: X              strcpy(name, n_argv[optind++]);
                    834: X          }
                    835: X      }
                    836: X      if ((err = LSTAT(name, statbuf)) < 0) {
                    837: X          warn(name, syserr());
                    838: X          continue;
                    839: X      }
                    840: X      if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
                    841: X          if (in_subdir) {
                    842: X              curr_dir->where = telldir(dirp);
                    843: X              pushdir(curr_dir);
                    844: X              close(dirp);
                    845: X          } 
                    846: X          in_subdir++;
                    847: X
                    848: X          /* Build new prototype name */
                    849: X          if ((curr_dir = (struct dirinfo *) 
                    850: X                  mem_get(sizeof(struct dirinfo))) == NULL) {
                    851: X              exit(2);
                    852: X          }
                    853: X          strcpy(curr_dir->dirname, name);
                    854: X          len = strlen(curr_dir->dirname);
                    855: X          while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
                    856: X              len--;          /* Delete trailing slashes */
                    857: X          }
                    858: X          curr_dir->dirname[len++] = '/';     /* Now add exactly one back */
                    859: X          curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
                    860: X
                    861: X          errno = 0;
                    862: X          if ((dirp = opendir(curr_dir->dirname)) == NULL) {
                    863: X              warn(curr_dir->dirname, "error opening directory (2)");
                    864: X          }
                    865: X      }
                    866: X    } while (err < 0);
                    867: X    return (0);
                    868: X}
                    869: X
                    870: X
                    871: X/* name_gather - gather names in a list for scanning. 
                    872: X *
                    873: X * DESCRIPTION
                    874: X *
                    875: X *    Name_gather takes names from the command line and adds them to
                    876: X *    the name list.
                    877: X *
                    878: X * FIXME
                    879: X *
                    880: X *    We could hash the names if we really care about speed here.
                    881: X */
                    882: X
                    883: X#ifdef __STDC__
                    884: X
                    885: Xvoid name_gather(void)
                    886: X
                    887: X#else
                    888: X    
                    889: Xvoid name_gather()
                    890: X
                    891: X#endif
                    892: X{
                    893: X     while (optind < n_argc) { 
                    894: X       add_name(n_argv[optind++]); 
                    895: X     } 
                    896: X}
                    897: X
                    898: X
                    899: Xstatic struct dirinfo *stack_head = NULL;
                    900: X
                    901: X
                    902: X/* pushdir - pushes a directory name on the directory stack
                    903: X *
                    904: X * DESCRIPTION
                    905: X *
                    906: X *    The pushdir function puses the directory structure which is pointed
                    907: X *    to by "info" onto a stack for later processing.  The information
                    908: X *    may be retrieved later with a call to popdir().
                    909: X *
                    910: X * PARAMETERS
                    911: X *
                    912: X *    dirinfo *info   - pointer to directory structure to save
                    913: X */
                    914: X
                    915: X#ifdef __STDC__
                    916: X
                    917: Xstatic void pushdir(struct dirinfo *info)
                    918: X
                    919: X#else
                    920: X    
                    921: Xstatic void pushdir(info)
                    922: Xstruct dirinfo        *info;
                    923: X
                    924: X#endif
                    925: X{
                    926: X    if  (stack_head == NULL) {
                    927: X      stack_head = info;
                    928: X      stack_head->next = NULL;
                    929: X    } else {
                    930: X      info->next = stack_head;
                    931: X      stack_head = info;
                    932: X    } 
                    933: X}
                    934: X
                    935: X
                    936: X/* popdir - pop a directory structure off the directory stack.
                    937: X *
                    938: X * DESCRIPTION
                    939: X *
                    940: X *    The popdir function pops the most recently pushed directory
                    941: X *    structure off of the directory stack and returns it to the calling
                    942: X *    function.
                    943: X *
                    944: X * RETURNS
                    945: X *
                    946: X *    Returns a pointer to the most recently pushed directory structure
                    947: X *    or NULL if the stack is empty.
                    948: X */
                    949: X
                    950: X#ifdef __STDC__
                    951: X
                    952: Xstatic struct dirinfo *popdir(void)
                    953: X
                    954: X#else
                    955: X    
                    956: Xstatic struct dirinfo *popdir()
                    957: X
                    958: X#endif
                    959: X{
                    960: X    struct dirinfo    *tmp;
                    961: X
                    962: X    if (stack_head == NULL) {
                    963: X      return(NULL);
                    964: X    } else {
                    965: X      tmp = stack_head;
                    966: X      stack_head = stack_head->next;
                    967: X    }
                    968: X    return(tmp);
                    969: X}
                    970: END_OF_namelist.c
                    971: if test 11056 -ne `wc -c <namelist.c`; then
                    972:     echo shar: \"namelist.c\" unpacked with wrong size!
                    973: fi
                    974: # end of overwriting check
                    975: fi
                    976: if test -f pax.c -a "${1}" != "-c" ; then 
                    977:   echo shar: Will not over-write existing file \"pax.c\"
                    978: else
                    979: echo shar: Extracting \"pax.c\" \(13026 characters\)
                    980: sed "s/^X//" >pax.c <<'END_OF_pax.c'
                    981: X/* $Source: /u/mark/src/pax/RCS/pax.c,v $
                    982: X *
                    983: X * $Revision: 1.1 $
                    984: X *
                    985: X * DESCRIPTION
                    986: X *
                    987: X *    Pax is the archiver described in IEEE P1003.2.  It is an archiver
                    988: X *    which understands both tar and cpio archives and has a new interface.
                    989: X *
                    990: X * SYNOPSIS
                    991: X *
                    992: X *    pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
                    993: X *    pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
                    994: X *    pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
                    995: X *           [-t device][-x format][pathname...]
                    996: X *    pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
                    997: X *
                    998: X * DESCRIPTION
                    999: X *
                   1000: X *    PAX - POSIX conforming tar and cpio archive handler.  This
                   1001: X *    program implements POSIX conformant versions of tar, cpio and pax
                   1002: X *    archive handlers for UNIX.  These handlers have defined befined
                   1003: X *    by the IEEE P1003.2 commitee.
                   1004: X *
                   1005: X * COMPILATION
                   1006: X *
                   1007: X *    A number of different compile time configuration options are
                   1008: X *    available, please see the Makefile and config.h for more details.
                   1009: X *
                   1010: X * AUTHOR
                   1011: X *
                   1012: X *     Mark H. Colburn, NAPS International ([email protected])
                   1013: X *
                   1014: X *
                   1015: X * Sponsored by The USENIX Association for public distribution. 
                   1016: X *
                   1017: X * Copyright (c) 1989 Mark H. Colburn.
                   1018: X * All rights reserved.
                   1019: X *
                   1020: X * Redistribution and use in source and binary forms are permitted
                   1021: X * provided that the above copyright notice is duplicated in all such 
                   1022: X * forms and that any documentation, advertising materials, and other 
                   1023: X * materials related to such distribution and use acknowledge that the 
                   1024: X * software was developed * by Mark H. Colburn and sponsored by The 
                   1025: X * USENIX Association. 
                   1026: X *
                   1027: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                   1028: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                   1029: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                   1030: X *
                   1031: X * $Log:      pax.c,v $
                   1032: X * Revision 1.1  88/12/23  18:02:23  mark
                   1033: X * Initial revision
                   1034: X * 
                   1035: X */
                   1036: X
                   1037: X#ifndef lint
                   1038: Xstatic char *ident = "$Id: pax.c,v 1.1 88/12/23 18:02:23 mark Rel $";
                   1039: Xstatic char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                   1040: X#endif /* ! lint */
                   1041: X
                   1042: X
                   1043: X/* Headers */
                   1044: X
                   1045: X#define NO_EXTERN
                   1046: X#include "pax.h"
                   1047: X
                   1048: X
                   1049: X/* Globally Available Identifiers */
                   1050: X
                   1051: Xchar           *ar_file;              /* File containing name of archive */
                   1052: Xchar           *bufend;                       /* End of data within archive buffer */
                   1053: Xchar           *bufstart;             /* Archive buffer */
                   1054: Xchar           *bufidx;                       /* Archive buffer index */
                   1055: Xchar           *myname;                       /* name of executable (argv[0]) */
                   1056: Xchar          **n_argv;                       /* Argv used by name routines */
                   1057: Xint             n_argc;                       /* Argc used by name routines */
                   1058: Xint             archivefd;            /* Archive file descriptor */
                   1059: Xint             blocking;             /* Size of each block, in records */
                   1060: Xint             gid;                  /* Group ID */
                   1061: Xint             head_standard;                /* true if archive is POSIX format */
                   1062: Xint             ar_interface;         /* defines interface we are using */
                   1063: Xint             ar_format;            /* defines current archve format */
                   1064: Xint             mask;                 /* File creation mask */
                   1065: Xint             ttyf;                 /* For interactive queries */
                   1066: Xint             uid;                  /* User ID */
                   1067: Xint           names_from_stdin;       /* names for files are from stdin */
                   1068: XOFFSET          total;                        /* Total number of bytes transferred */
                   1069: Xshort           f_access_time;                /* Reset access times of input files */
                   1070: Xshort           areof;                        /* End of input volume reached */
                   1071: Xshort           f_create_dirs;                /* Create missing directories */
                   1072: Xshort           f_append;             /* Add named files to end of archive */
                   1073: Xshort           f_create;             /* create a new archive */
                   1074: Xshort           f_extract;            /* Extract named files from archive */
                   1075: Xshort           f_follow_links;               /* follow symbolic links */
                   1076: Xshort           f_interactive;                /* Interactivly extract files */
                   1077: Xshort           f_linksleft;          /* Report on unresolved links */
                   1078: Xshort           f_list;                       /* List files on the archive */
                   1079: Xshort           f_modified;           /* Don't restore modification times */
                   1080: Xshort           f_verbose;            /* Turn on verbose mode */
                   1081: Xshort         f_link;                 /* link files where possible */
                   1082: Xshort         f_owner;                /* extract files as the user */
                   1083: Xshort         f_pass;                 /* pass files between directories */
                   1084: Xshort           f_newer;              /* append files to archive if newer */
                   1085: Xshort         f_disposition;          /* ask for file disposition */
                   1086: Xshort           f_reverse_match;      /* Reverse sense of pattern match */
                   1087: Xshort           f_modification_time;  /* Retain file modification time */
                   1088: Xshort           f_unconditional;      /* Copy unconditionally */
                   1089: Xtime_t          now = 0;              /* Current time */
                   1090: Xuint            arvolume;             /* Volume number */
                   1091: Xuint            blocksize = BLOCKSIZE;        /* Archive block size */
                   1092: XFILE         *msgfile;                /* message outpu file stdout/stderr */
                   1093: XReplstr        *rplhead = NULL;               /* pointer to head of replstr list */
                   1094: XReplstr        *rpltail;              /* pointer to tail of replstr list */
                   1095: X
                   1096: X
                   1097: X/* Function Prototypes */
                   1098: X
                   1099: X#ifdef __STDC__
                   1100: X
                   1101: Xstatic void   usage(void);
                   1102: Xstatic OFFSET   pax_optsize(char *);
                   1103: X
                   1104: X#else /* !__STDC__ */
                   1105: X
                   1106: Xstatic void   usage();
                   1107: Xstatic OFFSET   pax_optsize();
                   1108: X
                   1109: X#endif /* __STDC__ */
                   1110: X
                   1111: X
                   1112: X/* main - main routine for handling all archive formats.
                   1113: X *
                   1114: X * DESCRIPTION
                   1115: X *
                   1116: X *    Set up globals and call the proper interface as specified by the user.
                   1117: X *
                   1118: X * PARAMETERS
                   1119: X *
                   1120: X *    int argc        - count of user supplied arguments
                   1121: X *    char **argv     - user supplied arguments 
                   1122: X *
                   1123: X * RETURNS
                   1124: X *
                   1125: X *    Returns an exit code of 0 to the parent process.
                   1126: X */
                   1127: X
                   1128: X#ifdef __STDC__
                   1129: X
                   1130: Xint main(int argc, char **argv)
                   1131: X
                   1132: X#else
                   1133: X
                   1134: Xint main(argc, argv)
                   1135: Xint             argc;
                   1136: Xchar          **argv;
                   1137: X
                   1138: X#endif
                   1139: X{
                   1140: X    /* strip the pathname off of the name of the executable */
                   1141: X    if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
                   1142: X      myname++;
                   1143: X    } else {
                   1144: X      myname = argv[0];
                   1145: X    }
                   1146: X
                   1147: X    /* set upt for collecting other command line arguments */
                   1148: X    name_init(argc, argv);
                   1149: X
                   1150: X    /* get all our necessary information */
                   1151: X    mask = umask(0);
                   1152: X    uid = getuid();
                   1153: X    gid = getgid();
                   1154: X    now = time((time_t *) 0);
                   1155: X
                   1156: X    /* open terminal for interactive queries */
                   1157: X    ttyf = open_tty();
                   1158: X
                   1159: X    if (strcmp(myname, "tar")==0) {
                   1160: X      do_tar(argc, argv);
                   1161: X    } else if (strcmp(myname, "cpio")==0) {
                   1162: X      do_cpio(argc, argv);
                   1163: X    } else {
                   1164: X      do_pax(argc, argv);
                   1165: X    }
                   1166: X    exit(0);
                   1167: X    /* NOTREACHED */
                   1168: X}
                   1169: X
                   1170: X
                   1171: X/* do_pax - provide a PAX conformant user interface for archive handling
                   1172: X *
                   1173: X * DESCRIPTION
                   1174: X *
                   1175: X *    Process the command line parameters given, doing some minimal sanity
                   1176: X *    checking, and then launch the specified archiving functions.
                   1177: X *
                   1178: X * PARAMETERS
                   1179: X *
                   1180: X *    int ac          - A count of arguments in av.  Should be passed argc 
                   1181: X *                      from main
                   1182: X *    char **av               - A pointer to an argument list.  Should be passed 
                   1183: X *                      argv from main
                   1184: X *
                   1185: X * RETURNS
                   1186: X *
                   1187: X *    Normally returns 0.  If an error occurs, -1 is returned 
                   1188: X *    and state is set to reflect the error.
                   1189: X *
                   1190: X */
                   1191: X
                   1192: X#ifdef __STDC__
                   1193: X
                   1194: Xint do_pax(int ac, char **av)
                   1195: X
                   1196: X#else
                   1197: X
                   1198: Xint do_pax(ac, av)
                   1199: Xint             ac;           /* argument counter */
                   1200: Xchar          **av;           /* arguments */
                   1201: X
                   1202: X#endif
                   1203: X{
                   1204: X    int             c;
                   1205: X    char         *dirname;
                   1206: X    Stat          st;
                   1207: X
                   1208: X    /* default input/output file for PAX is STDIN/STDOUT */
                   1209: X    ar_file = "-";
                   1210: X
                   1211: X    /*
                   1212: X     * set up the flags to reflect the default pax inteface.  Unfortunately
                   1213: X     * the pax interface has several options which are completely opposite
                   1214: X     * of the tar and/or cpio interfaces...
                   1215: X     */
                   1216: X    f_unconditional = 1;
                   1217: X    f_modification_time = 1;
                   1218: X    f_create_dirs = 1;
                   1219: X    f_list = 1;
                   1220: X    blocksize = 0;
                   1221: X    blocking = 0;
                   1222: X    ar_interface = PAX;
                   1223: X    ar_format = TAR;  /* default interface if none given for -w */
                   1224: X    msgfile=stdout;
                   1225: X
                   1226: X    while ((c = getopt(ac, av, "ab:cdf:ilmoprs:t:uvwx:y")) != EOF) {
                   1227: X      switch (c) {
                   1228: X      case 'a':
                   1229: X          f_append = 1;
                   1230: X          f_list = 0;
                   1231: X          break;
                   1232: X      case 'b':
                   1233: X          if ((blocksize = pax_optsize(optarg)) == 0) {
                   1234: X              fatal("Bad block size");
                   1235: X          }
                   1236: X          break;
                   1237: X      case 'c':
                   1238: X          f_reverse_match = 1;
                   1239: X          break;
                   1240: X      case 'd':
                   1241: X          f_create_dirs = 0;
                   1242: X          break;
                   1243: X      case 'f':
                   1244: X          if (blocksize == 0) {
                   1245: X              blocking = 1;
                   1246: X              blocksize = 1 * BLOCKSIZE;
                   1247: X          }
                   1248: X          ar_file = optarg;
                   1249: X          break;
                   1250: X      case 'i':
                   1251: X          f_interactive = 1;
                   1252: X          break;
                   1253: X      case 'l':
                   1254: X          f_link = 1;
                   1255: X          break;
                   1256: X      case 'm':
                   1257: X          f_modification_time = 0;
                   1258: X          break;
                   1259: X      case 'o':
                   1260: X          f_owner = 1;
                   1261: X          break;
                   1262: X      case 'p':
                   1263: X          f_access_time = 1;
                   1264: X          break;
                   1265: X      case 'r':
                   1266: X          if (f_create) {
                   1267: X              f_create = 0;
                   1268: X              f_pass = 1;
                   1269: X          } else {
                   1270: X              f_list = 0;
                   1271: X              f_extract = 1;
                   1272: X          } 
                   1273: X          msgfile=stderr;
                   1274: X          break;
                   1275: X      case 's':
                   1276: X          add_replstr(optarg);
                   1277: X          break;
                   1278: X      case 't':
                   1279: X          if (blocksize == 0) {
                   1280: X              blocking = 1;
                   1281: X              blocksize = 10 * BLOCKSIZE;
                   1282: X          }
                   1283: X          ar_file = optarg;
                   1284: X          break;
                   1285: X      case 'u':
                   1286: X          f_unconditional = 1;
                   1287: X          break;
                   1288: X      case 'v':
                   1289: X          f_verbose = 1;
                   1290: X          break;
                   1291: X      case 'w':
                   1292: X          if (f_extract) {
                   1293: X              f_extract = 0;
                   1294: X              f_pass = 1;
                   1295: X          } else {
                   1296: X              f_list = 0;
                   1297: X              f_create = 1;
                   1298: X          } 
                   1299: X          msgfile=stderr;
                   1300: X          break;
                   1301: X      case 'x':
                   1302: X          if (strcmp(optarg, "ustar") == 0) {
                   1303: X              ar_format = TAR;
                   1304: X          } else if (strcmp(optarg, "cpio") == 0) {
                   1305: X              ar_format = CPIO;
                   1306: X          } else {
                   1307: X              usage();
                   1308: X          }
                   1309: X          break;
                   1310: X      case 'y':
                   1311: X          f_disposition = 1;
                   1312: X          break;
                   1313: X      default:
                   1314: X          usage();
                   1315: X      }
                   1316: X    }
                   1317: X
                   1318: X    if (blocksize == 0) {
                   1319: X      blocking = 1;
                   1320: X      blocksize = blocking * BLOCKSIZE;
                   1321: X    }
                   1322: X    buf_allocate((OFFSET) blocksize);
                   1323: X
                   1324: X    if (f_extract || f_list) {
                   1325: X      open_archive(AR_READ);
                   1326: X      get_archive_type();
                   1327: X      read_archive();
                   1328: X    } else if (f_create) {
                   1329: X      if (optind >= n_argc) {
                   1330: X          names_from_stdin++;         /* args from stdin */
                   1331: X      }
                   1332: X      open_archive(AR_WRITE);
                   1333: X      create_archive();
                   1334: X    } else if (f_append) {
                   1335: X      open_archive(AR_APPEND);
                   1336: X      get_archive_type();
                   1337: X      append_archive();
                   1338: X    } else if (f_pass && optind < n_argc) {
                   1339: X      dirname = n_argv[--n_argc];
                   1340: X      if (LSTAT(dirname, &st) < 0) {
                   1341: X          fatal(syserr());
                   1342: X      }
                   1343: X      if ((st.sb_mode & S_IFMT) != S_IFDIR) {
                   1344: X          fatal("Not a directory");
                   1345: X      }
                   1346: X      if (optind >= n_argc) {
                   1347: X          names_from_stdin++;         /* args from stdin */
                   1348: X      }
                   1349: X      pass(dirname);
                   1350: X    } else {
                   1351: X      usage();
                   1352: X    }
                   1353: X
                   1354: X    return (0);
                   1355: X}
                   1356: X
                   1357: X
                   1358: X/* get_archive_type - determine input archive type from archive header
                   1359: X *
                   1360: X * DESCRIPTION
                   1361: X *
                   1362: X *    reads the first block of the archive and determines the archive 
                   1363: X *    type from the data.  If the archive type cannot be determined, 
                   1364: X *    processing stops, and a 1 is returned to the caller.  If verbose
                   1365: X *    mode is on, then the archive type will be printed on the standard
                   1366: X *    error device as it is determined.
                   1367: X *
                   1368: X * FIXME 
                   1369: X *
                   1370: X *    be able to understand TAR and CPIO magic numbers
                   1371: X */
                   1372: X
                   1373: X#ifdef __STDC__
                   1374: X
                   1375: Xvoid get_archive_type(void)
                   1376: X
                   1377: X#else
                   1378: X
                   1379: Xvoid get_archive_type()
                   1380: X
                   1381: X#endif
                   1382: X{
                   1383: X    if (ar_read() != 0) {
                   1384: X      fatal("Unable to determine archive type.");
                   1385: X    }
                   1386: X    if (strncmp(bufstart, "070707", 6) == 0) {
                   1387: X      ar_format = CPIO;
                   1388: X      if (f_verbose) {
                   1389: X          fputs("CPIO format archive\n", stderr);
                   1390: X      }
                   1391: X    } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
                   1392: X      ar_format = TAR;
                   1393: X      if (f_verbose) {
                   1394: X          fputs("USTAR format archive\n", stderr);
                   1395: X      }
                   1396: X    } else {
                   1397: X      ar_format = TAR;
                   1398: X    }
                   1399: X}
                   1400: X
                   1401: X
                   1402: X/* pax_optsize - interpret a size argument
                   1403: X *
                   1404: X * DESCRIPTION
                   1405: X *
                   1406: X *    Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.  
                   1407: X *    Also handles simple expressions containing '+' for addition.
                   1408: X *
                   1409: X * PARAMETERS
                   1410: X *
                   1411: X *    char    *str    - A pointer to the string to interpret
                   1412: X *
                   1413: X * RETURNS
                   1414: X *
                   1415: X *    Normally returns the value represented by the expression in the 
                   1416: X *    the string.
                   1417: X *
                   1418: X * ERRORS
                   1419: X *
                   1420: X *    If the string cannot be interpretted, the program will fail, since
                   1421: X *    the buffering will be incorrect.
                   1422: X *
                   1423: X */
                   1424: X
                   1425: X#ifdef __STDC__
                   1426: X
                   1427: Xstatic OFFSET pax_optsize(char *str)
                   1428: X
                   1429: X#else
                   1430: X
                   1431: Xstatic OFFSET pax_optsize(str)
                   1432: Xchar           *str;          /* pointer to string to interpret */
                   1433: X
                   1434: X#endif
                   1435: X{
                   1436: X    char           *idx;
                   1437: X    OFFSET          number;   /* temporary storage for current number */
                   1438: X    OFFSET          result;   /* cumulative total to be returned to caller */
                   1439: X
                   1440: X    result = 0;
                   1441: X    idx = str;
                   1442: X    for (;;) {
                   1443: X      number = 0;
                   1444: X      while (*idx >= '0' && *idx <= '9')
                   1445: X          number = number * 10 + *idx++ - '0';
                   1446: X      switch (*idx++) {
                   1447: X      case 'b':
                   1448: X          result += number * 512;
                   1449: X          continue;
                   1450: X      case 'k':
                   1451: X          result += number * 1024;
                   1452: X          continue;
                   1453: X      case 'm':
                   1454: X          result += number * 1024 * 1024;
                   1455: X          continue;
                   1456: X      case '+':
                   1457: X          result += number;
                   1458: X          continue;
                   1459: X      case '\0':
                   1460: X          result += number;
                   1461: X          break;
                   1462: X      default:
                   1463: X          break;
                   1464: X      }
                   1465: X      break;
                   1466: X    }
                   1467: X    if (*--idx) {
                   1468: X      fatal("Unrecognizable value");
                   1469: X    }
                   1470: X    return (result);
                   1471: X}
                   1472: X
                   1473: X
                   1474: X/* usage - print a helpful message and exit
                   1475: X *
                   1476: X * DESCRIPTION
                   1477: X *
                   1478: X *    Usage prints out the usage message for the PAX interface and then
                   1479: X *    exits with a non-zero termination status.  This is used when a user
                   1480: X *    has provided non-existant or incompatible command line arguments.
                   1481: X *
                   1482: X * RETURNS
                   1483: X *
                   1484: X *    Returns an exit status of 1 to the parent process.
                   1485: X *
                   1486: X */
                   1487: X
                   1488: X#ifdef __STDC__
                   1489: X
                   1490: Xstatic void usage(void)
                   1491: X
                   1492: X#else
                   1493: X
                   1494: Xstatic void usage()
                   1495: X
                   1496: X#endif
                   1497: X{
                   1498: X    fprintf(stderr, "\
                   1499: XUsage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
                   1500: X      myname);
                   1501: X    fprintf(stderr, "\
                   1502: X       %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
                   1503: X      myname);
                   1504: X    fprintf(stderr, "\
                   1505: X       %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n\
                   1506: X         [-t device] [-x format] [pathname...]\n",
                   1507: X      myname);
                   1508: X    fprintf(stderr, "\
                   1509: X       %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
                   1510: X      myname);
                   1511: X    exit(1);
                   1512: X}
                   1513: END_OF_pax.c
                   1514: if test 13026 -ne `wc -c <pax.c`; then
                   1515:     echo shar: \"pax.c\" unpacked with wrong size!
                   1516: fi
                   1517: # end of overwriting check
                   1518: fi
                   1519: if test -f pax.h -a "${1}" != "-c" ; then 
                   1520:   echo shar: Will not over-write existing file \"pax.h\"
                   1521: else
                   1522: echo shar: Extracting \"pax.h\" \(9317 characters\)
                   1523: sed "s/^X//" >pax.h <<'END_OF_pax.h'
                   1524: X/* $Source: /u/mark/src/pax/RCS/pax.h,v $
                   1525: X *
                   1526: X * $Revision: 1.1 $
                   1527: X *
                   1528: X * pax.h - defnitions for entire program
                   1529: X *
                   1530: X * DESCRIPTION
                   1531: X *
                   1532: X *    This file contains most all of the definitions required by the PAX
                   1533: X *    software.  This header is included in every source file.
                   1534: X *
                   1535: X * AUTHOR
                   1536: X *
                   1537: X *     Mark H. Colburn, NAPS International ([email protected])
                   1538: X *
                   1539: X * Sponsored by The USENIX Association for public distribution. 
                   1540: X *
                   1541: X * Copyright (c) 1989 Mark H. Colburn.
                   1542: X * All rights reserved.
                   1543: X *
                   1544: X * Redistribution and use in source and binary forms are permitted
                   1545: X * provided that the above copyright notice and this paragraph are
                   1546: X * duplicated in all such forms and that any documentation,
                   1547: X * advertising materials, and other materials related to such
                   1548: X * distribution and use acknowledge that the software was developed
                   1549: X * by Mark H. Colburn and sponsored by The USENIX Association. 
                   1550: X *
                   1551: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                   1552: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                   1553: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                   1554: X */
                   1555: X
                   1556: X#ifndef _PAX_H
                   1557: X#define _PAX_H
                   1558: X
                   1559: X/* Headers */
                   1560: X
                   1561: X#include "config.h"
                   1562: X#include "limits.h"
                   1563: X#include <stdio.h>
                   1564: X#include <errno.h>
                   1565: X#include <signal.h>
                   1566: X#include <ctype.h>
                   1567: X#include <sys/types.h>
                   1568: X#include <sys/ioctl.h>
                   1569: X#include <sys/stat.h>
                   1570: X#include "regexp.h"
                   1571: X
                   1572: X#if defined(DIRENT) || defined(_POSIX_SOURCE)
                   1573: X# ifdef PAXDIR
                   1574: X#  include "paxdir.h"
                   1575: X# else
                   1576: X#  include <dirent.h>
                   1577: X# endif
                   1578: X#else
                   1579: X# include <sys/dir.h>
                   1580: X# define dirent direct
                   1581: X#endif
                   1582: X
                   1583: X#ifndef       major
                   1584: X#   include <sys/sysmacros.h>
                   1585: X#endif                                /* major */
                   1586: X
                   1587: X#ifdef        SYSTIME
                   1588: X#   include <sys/time.h>
                   1589: X#else                         /* SYSTIME */
                   1590: X#   include <time.h>
                   1591: X#endif                                /* SYSTIME */
                   1592: X
                   1593: X#ifndef V7
                   1594: X#   include <fcntl.h>
                   1595: X#endif
                   1596: X
                   1597: X#ifdef XENIX
                   1598: X#   include <sys/inode.h>
                   1599: X#endif
                   1600: X
                   1601: X#include <pwd.h>
                   1602: X#include <grp.h>
                   1603: X#include <sys/file.h>
                   1604: X
                   1605: X/* Defines */
                   1606: X
                   1607: X#define       STDIN   0               /* Standard input  file descriptor */
                   1608: X#define       STDOUT  1               /* Standard output file descriptor */
                   1609: X
                   1610: X/*
                   1611: X * Open modes; there is no <fcntl.h> with v7 UNIX and other versions of
                   1612: X * UNIX may not have all of these defined...
                   1613: X */
                   1614: X
                   1615: X#ifndef O_RDONLY
                   1616: X#   define    O_RDONLY        0
                   1617: X#endif
                   1618: X
                   1619: X#ifndef O_WRONLY
                   1620: X#   define    O_WRONLY        1
                   1621: X#endif
                   1622: X
                   1623: X#ifndef O_RDWR
                   1624: X#   define    O_WRONLY        2
                   1625: X#endif
                   1626: X
                   1627: X#ifndef       O_BINARY
                   1628: X#   define    O_BINARY        0
                   1629: X#endif
                   1630: X
                   1631: X#ifndef NULL
                   1632: X#   define    NULL            0
                   1633: X#endif
                   1634: X
                   1635: X#define TMAGIC                "ustar"         /* ustar and a null */
                   1636: X#define TMAGLEN               6
                   1637: X#define TVERSION      "00"            /* 00 and no null */
                   1638: X#define TVERSLEN      2
                   1639: X
                   1640: X/* Values used in typeflag field */
                   1641: X#define REGTYPE               '0'             /* Regular File */
                   1642: X#define AREGTYPE      '\0'            /* Regular File */
                   1643: X#define LNKTYPE               '1'             /* Link */
                   1644: X#define SYMTYPE               '2'             /* Reserved */
                   1645: X#define CHRTYPE               '3'             /* Character Special File */
                   1646: X#define BLKTYPE               '4'             /* Block Special File */
                   1647: X#define DIRTYPE               '5'             /* Directory */
                   1648: X#define FIFOTYPE      '6'             /* FIFO */
                   1649: X#define CONTTYPE      '7'             /* Reserved */
                   1650: X
                   1651: X#define BLOCKSIZE     512     /* all output is padded to 512 bytes */
                   1652: X#define       uint    unsigned int    /* Not always in types.h */
                   1653: X#define       ushort  unsigned short  /* Not always in types.h */
                   1654: X#define       BLOCK   5120            /* Default archive block size */
                   1655: X#define       H_COUNT 10              /* Number of items in ASCII header */
                   1656: X#define       H_PRINT "%06o%06o%06o%06o%06o%06o%06o%011lo%06o%011lo"
                   1657: X#define       H_SCAN  "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6o%11lo"
                   1658: X#define       H_STRLEN 70             /* ASCII header string length */
                   1659: X#define       M_ASCII "070707"        /* ASCII magic number */
                   1660: X#define       M_BINARY 070707         /* Binary magic number */
                   1661: X#define       M_STRLEN 6              /* ASCII magic number length */
                   1662: X#define       PATHELEM 256            /* Pathname element count limit */
                   1663: X#define       S_IFSHF 12              /* File type shift (shb in stat.h) */
                   1664: X#define       S_IPERM 07777           /* File permission bits (shb in stat.h) */
                   1665: X#define       S_IPEXE 07000           /* Special execution bits (shb in stat.h) */
                   1666: X#define       S_IPOPN 0777            /* Open access bits (shb in stat.h) */
                   1667: X
                   1668: X/*
                   1669: X * Trailer pathnames. All must be of the same length. 
                   1670: X */
                   1671: X#define       TRAILER "TRAILER!!!"    /* Archive trailer (cpio compatible) */
                   1672: X#define       TRAILZ  11              /* Trailer pathname length (including null) */
                   1673: X
                   1674: X#include "port.h"
                   1675: X
                   1676: X
                   1677: X#define       TAR             1
                   1678: X#define       CPIO            2
                   1679: X#define       PAX             3
                   1680: X
                   1681: X#define AR_READ       0
                   1682: X#define AR_WRITE      1
                   1683: X#define AR_EXTRACT    2
                   1684: X#define AR_APPEND     4
                   1685: X
                   1686: X/*
                   1687: X * Header block on tape. 
                   1688: X */
                   1689: X#define       NAMSIZ          100
                   1690: X#define       PFIXSIZ         155
                   1691: X#define       TUNMLEN         32
                   1692: X#define       TGNMLEN         32
                   1693: X
                   1694: X/* The checksum field is filled with this while the checksum is computed. */
                   1695: X#define       CHKBLANKS       "        "      /* 8 blanks, no null */
                   1696: X
                   1697: X/*
                   1698: X * Exit codes from the "tar" program 
                   1699: X */
                   1700: X#define       EX_SUCCESS      0       /* success! */
                   1701: X#define       EX_ARGSBAD      1       /* invalid args */
                   1702: X#define       EX_BADFILE      2       /* invalid filename */
                   1703: X#define       EX_BADARCH      3       /* bad archive */
                   1704: X#define       EX_SYSTEM       4       /* system gave unexpected error */
                   1705: X
                   1706: X#define       ROUNDUP(a,b)    (((a) % (b)) == 0 ? (a) : ((a) + ((b) - ((a) % (b)))))
                   1707: X
                   1708: X/*
                   1709: X * Mininum value. 
                   1710: X */
                   1711: X#define       MIN(a, b)       (((a) < (b)) ? (a) : (b))
                   1712: X
                   1713: X/*
                   1714: X * Remove a file or directory. 
                   1715: X */
                   1716: X#define       REMOVE(name, asb) \
                   1717: X      (((asb)->sb_mode & S_IFMT) == S_IFDIR ? rmdir(name) : unlink(name))
                   1718: X
                   1719: X/*
                   1720: X * Cast and reduce to unsigned short. 
                   1721: X */
                   1722: X#define       USH(n)          (((ushort) (n)) & 0177777)
                   1723: X
                   1724: X
                   1725: X/* Type Definitions */
                   1726: X
                   1727: X/*
                   1728: X * Binary archive header (obsolete). 
                   1729: X */
                   1730: Xtypedef struct {
                   1731: X    short           b_dev;    /* Device code */
                   1732: X    ushort          b_ino;    /* Inode number */
                   1733: X    ushort          b_mode;   /* Type and permissions */
                   1734: X    ushort          b_uid;    /* Owner */
                   1735: X    ushort          b_gid;    /* Group */
                   1736: X    short           b_nlink;  /* Number of links */
                   1737: X    short           b_rdev;   /* Real device */
                   1738: X    ushort          b_mtime[2];       /* Modification time (hi/lo) */
                   1739: X    ushort          b_name;   /* Length of pathname (with null) */
                   1740: X    ushort          b_size[2];        /* Length of data */
                   1741: X} Binary;
                   1742: X
                   1743: X/*
                   1744: X * File status with symbolic links. Kludged to hold symbolic link pathname
                   1745: X * within structure. 
                   1746: X */
                   1747: Xtypedef struct {
                   1748: X    struct stat     sb_stat;
                   1749: X    char            sb_link[PATH_MAX + 1];
                   1750: X} Stat;
                   1751: X
                   1752: X#define       STAT(name, asb)         stat(name, &(asb)->sb_stat)
                   1753: X#define       FSTAT(fd, asb)          fstat(fd, &(asb)->sb_stat)
                   1754: X
                   1755: X#define       sb_dev          sb_stat.st_dev
                   1756: X#define       sb_ino          sb_stat.st_ino
                   1757: X#define       sb_mode         sb_stat.st_mode
                   1758: X#define       sb_nlink        sb_stat.st_nlink
                   1759: X#define       sb_uid          sb_stat.st_uid
                   1760: X#define       sb_gid          sb_stat.st_gid
                   1761: X#define       sb_rdev         sb_stat.st_rdev
                   1762: X#define       sb_size         sb_stat.st_size
                   1763: X#define       sb_atime        sb_stat.st_atime
                   1764: X#define       sb_mtime        sb_stat.st_mtime
                   1765: X#define       sb_ctime        sb_stat.st_ctime
                   1766: X
                   1767: X#ifdef        S_IFLNK
                   1768: X#     define  LSTAT(name, asb)        lstat(name, &(asb)->sb_stat)
                   1769: X#     define  sb_blksize      sb_stat.st_blksize
                   1770: X#     define  sb_blocks       sb_stat.st_blocks
                   1771: X#else                         /* S_IFLNK */
                   1772: X/*
                   1773: X * File status without symbolic links. 
                   1774: X */
                   1775: X#     define  LSTAT(name, asb)        stat(name, &(asb)->sb_stat)
                   1776: X#endif                                /* S_IFLNK */
                   1777: X
                   1778: X/*
                   1779: X * Hard link sources. One or more are chained from each link structure. 
                   1780: X */
                   1781: Xtypedef struct name {
                   1782: X    struct name    *p_forw;   /* Forward chain (terminated) */
                   1783: X    struct name    *p_back;   /* Backward chain (circular) */
                   1784: X    char           *p_name;   /* Pathname to link from */
                   1785: X} Path;
                   1786: X
                   1787: X/*
                   1788: X * File linking information. One entry exists for each unique file with with
                   1789: X * outstanding hard links. 
                   1790: X */
                   1791: Xtypedef struct link {
                   1792: X    struct link    *l_forw;   /* Forward chain (terminated) */
                   1793: X    struct link    *l_back;   /* Backward chain (terminated) */
                   1794: X    dev_t           l_dev;    /* Device */
                   1795: X    ino_t           l_ino;    /* Inode */
                   1796: X    ushort          l_nlink;  /* Unresolved link count */
                   1797: X    OFFSET          l_size;   /* Length */
                   1798: X    char         *l_name;     /* pathname to link from */
                   1799: X    Path           *l_path;   /* Pathname which link to l_name */
                   1800: X} Link;
                   1801: X
                   1802: X/*
                   1803: X * Structure for ed-style replacement strings (-s option).
                   1804: X*/
                   1805: Xtypedef struct replstr {
                   1806: X    regexp       *comp;       /* compiled regular expression */
                   1807: X    char         *replace;    /* replacement string */
                   1808: X    char          print;      /* >0 if we are to print replacement */
                   1809: X    char          global;     /* >0 if we are to replace globally */
                   1810: X    struct replstr *next;     /* pointer to next record */
                   1811: X} Replstr;
                   1812: X
                   1813: X
                   1814: X/*
                   1815: X * This has to be included here to insure that all of the type 
                   1816: X * delcarations are declared for the prototypes.
                   1817: X */
                   1818: X#include "func.h"
                   1819: X
                   1820: X
                   1821: X#ifndef NO_EXTERN
                   1822: X/* Globally Available Identifiers */
                   1823: X
                   1824: Xextern char    *ar_file;
                   1825: Xextern char    *bufend;
                   1826: Xextern char    *bufstart;
                   1827: Xextern char    *bufidx;
                   1828: Xextern char    *myname;
                   1829: Xextern int      archivefd;
                   1830: Xextern int      blocking;
                   1831: Xextern uint     blocksize;
                   1832: Xextern int      gid;
                   1833: Xextern int      head_standard;
                   1834: Xextern int      ar_interface;
                   1835: Xextern int      ar_format;
                   1836: Xextern int      mask;
                   1837: Xextern int      ttyf;
                   1838: Xextern int      uid;
                   1839: Xextern OFFSET    total;
                   1840: Xextern short    areof;
                   1841: Xextern short    f_append;
                   1842: Xextern short    f_create;
                   1843: Xextern short    f_extract;
                   1844: Xextern short    f_follow_links;
                   1845: Xextern short    f_interactive;
                   1846: Xextern short    f_linksleft;
                   1847: Xextern short    f_list;
                   1848: Xextern short    f_modified;
                   1849: Xextern short    f_verbose;
                   1850: Xextern short  f_link;
                   1851: Xextern short  f_owner;
                   1852: Xextern short  f_access_time;
                   1853: Xextern short  f_pass;
                   1854: Xextern short  f_pass;
                   1855: Xextern short  f_disposition;
                   1856: Xextern short    f_reverse_match;
                   1857: Xextern short    f_modification_time;
                   1858: Xextern short    f_create_dirs;
                   1859: Xextern short    f_unconditional;
                   1860: Xextern short    f_newer;
                   1861: Xextern time_t   now;
                   1862: Xextern uint     arvolume;
                   1863: Xextern int    names_from_stdin;
                   1864: Xextern Replstr *rplhead;
                   1865: Xextern Replstr *rpltail;
                   1866: Xextern char   **n_argv;
                   1867: Xextern int      n_argc;
                   1868: Xextern FILE    *msgfile;
                   1869: X#endif /* NO_EXTERN */
                   1870: X
                   1871: Xextern char    *optarg;
                   1872: Xextern int      optind;
                   1873: Xextern int      sys_nerr;
                   1874: Xextern char    *sys_errlist[];
                   1875: Xextern int      errno;
                   1876: X
                   1877: X#endif /* _PAX_H */
                   1878: END_OF_pax.h
                   1879: if test 9317 -ne `wc -c <pax.h`; then
                   1880:     echo shar: \"pax.h\" unpacked with wrong size!
                   1881: fi
                   1882: # end of overwriting check
                   1883: fi
                   1884: if test -f tar.c -a "${1}" != "-c" ; then 
                   1885:   echo shar: Will not over-write existing file \"tar.c\"
                   1886: else
                   1887: echo shar: Extracting \"tar.c\" \(7881 characters\)
                   1888: sed "s/^X//" >tar.c <<'END_OF_tar.c'
                   1889: X/* $Source: /u/mark/src/pax/RCS/tar.c,v $
                   1890: X *
                   1891: X * $Revision: 1.1 $
                   1892: X *
                   1893: X * tar.c - tar specific functions for archive handling
                   1894: X *
                   1895: X * DESCRIPTION
                   1896: X *
                   1897: X *    These routines provide a tar conforming interface to the pax
                   1898: X *    program.
                   1899: X *
                   1900: X * AUTHOR
                   1901: X *
                   1902: X *    Mark H. Colburn, NAPS International ([email protected])
                   1903: X *
                   1904: X * Sponsored by The USENIX Association for public distribution. 
                   1905: X *
                   1906: X * Copyright (c) 1989 Mark H. Colburn.
                   1907: X * All rights reserved.
                   1908: X *
                   1909: X * Redistribution and use in source and binary forms are permitted
                   1910: X * provided that the above copyright notice is duplicated in all such 
                   1911: X * forms and that any documentation, advertising materials, and other 
                   1912: X * materials related to such distribution and use acknowledge that the 
                   1913: X * software was developed by Mark H. Colburn and sponsored by The 
                   1914: X * USENIX Association. 
                   1915: X *
                   1916: X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                   1917: X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                   1918: X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                   1919: X *
                   1920: X * $Log:      tar.c,v $
                   1921: X * Revision 1.1  88/12/23  18:02:38  mark
                   1922: X * Initial revision
                   1923: X * 
                   1924: X */
                   1925: X
                   1926: X#ifndef lint
                   1927: Xstatic char *ident = "$Id: tar.c,v 1.1 88/12/23 18:02:38 mark Rel $";
                   1928: Xstatic char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
                   1929: X#endif /* not lint */
                   1930: X
                   1931: X/* Headers */
                   1932: X
                   1933: X#include "pax.h"
                   1934: X
                   1935: X
                   1936: X/* Defines */
                   1937: X
                   1938: X#define DEF_BLOCKING  20      /* default blocking factor for extract */
                   1939: X
                   1940: X
                   1941: X/* Function Prototypes */
                   1942: X
                   1943: X#ifdef __STDC__
                   1944: X
                   1945: Xstatic int taropt(int , char **, char *);
                   1946: Xstatic void usage(void);
                   1947: X
                   1948: X#else /* !__STDC__ */
                   1949: X
                   1950: Xstatic int taropt();
                   1951: Xstatic void usage();
                   1952: X
                   1953: X#endif /* __STDC__ */
                   1954: X
                   1955: X
                   1956: X/* do_tar - main routine for tar. 
                   1957: X *
                   1958: X * DESCRIPTION
                   1959: X *
                   1960: X *    Provides a tar interface to the PAX program.  All tar standard
                   1961: X *    command line options are supported.
                   1962: X *
                   1963: X * PARAMETERS
                   1964: X *
                   1965: X *    int argc        - argument count (argc from main) 
                   1966: X *    char **argv     - argument list (argv from main) 
                   1967: X *
                   1968: X * RETURNS
                   1969: X *
                   1970: X *    zero
                   1971: X */
                   1972: X
                   1973: X#ifdef __STDC__
                   1974: X
                   1975: Xint do_tar(int argc, char **argv)
                   1976: X
                   1977: X#else
                   1978: X
                   1979: Xint do_tar(argc, argv)
                   1980: Xint             argc;         /* argument count (argc from main) */
                   1981: Xchar          **argv;         /* argument list (argv from main) */
                   1982: X
                   1983: X#endif
                   1984: X{
                   1985: X    int             c;                /* Option letter */
                   1986: X
                   1987: X    /* Set default option values */
                   1988: X    names_from_stdin = 0;
                   1989: X    ar_file = getenv("TAPE"); /* From environment, or */
                   1990: X    if (ar_file == 0) {
                   1991: X      ar_file = DEF_AR_FILE;  /* From Makefile */
                   1992: X    }
                   1993: X
                   1994: X    /*
                   1995: X     * set up the flags to reflect the default pax inteface.  Unfortunately
                   1996: X     * the pax interface has several options which are completely opposite
                   1997: X     * of the tar and/or cpio interfaces...
                   1998: X     */
                   1999: X    f_unconditional = 1;
                   2000: X    f_modification_time = 1;
                   2001: X    f_create_dirs = 1;
                   2002: X    blocking = 0;
                   2003: X    ar_interface = TAR;
                   2004: X    ar_format = TAR;
                   2005: X    msgfile=stdout;
                   2006: X
                   2007: X    /* Parse options */
                   2008: X    while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
                   2009: X      switch (c) {
                   2010: X      case 'b':               /* specify blocking factor */
                   2011: X          /* 
                   2012: X           * FIXME - we should use a conversion routine that does
                   2013: X           * some kind of reasonable error checking, but...
                   2014: X           */
                   2015: X          blocking = atoi(optarg);
                   2016: X          break;
                   2017: X      case 'c':               /* create a new archive */
                   2018: X          f_create = 1;
                   2019: X          break;
                   2020: X      case 'f':               /* specify input/output file */
                   2021: X          ar_file = optarg;
                   2022: X          break;
                   2023: X      case 'h':
                   2024: X          f_follow_links = 1; /* follow symbolic links */
                   2025: X          break;
                   2026: X      case 'l':               /* report unresolved links */
                   2027: X          f_linksleft = 1;
                   2028: X          break;
                   2029: X      case 'm':               /* don't restore modification times */
                   2030: X          f_modified = 1;
                   2031: X          break;
                   2032: X      case 'o':               /* take on user's group rather than
                   2033: X                               * archives */
                   2034: X          break;
                   2035: X      case 'r':               /* named files are appended to archive */
                   2036: X          f_append = 1;
                   2037: X          break;
                   2038: X      case 't':
                   2039: X          f_list = 1;         /* list files in archive */
                   2040: X          break;
                   2041: X      case 'u':               /* named files are added to archive */
                   2042: X          f_newer = 1;
                   2043: X          break;
                   2044: X      case 'v':               /* verbose mode */
                   2045: X          f_verbose = 1;
                   2046: X          break;
                   2047: X      case 'w':               /* user interactive mode */
                   2048: X          f_disposition = 1;
                   2049: X          break;
                   2050: X      case 'x':               /* named files are extracted from archive */
                   2051: X          f_extract = 1;
                   2052: X          break;
                   2053: X      case '?':
                   2054: X          usage();
                   2055: X          exit(EX_ARGSBAD);
                   2056: X      }
                   2057: X    }
                   2058: X
                   2059: X    /* check command line argument sanity */
                   2060: X    if (f_create + f_extract + f_list + f_append + f_newer != 1) {
                   2061: X      (void) fprintf(stderr,
                   2062: X         "%s: you must specify exactly one of the c, t, r, u or x options\n",
                   2063: X                     myname);
                   2064: X      usage();
                   2065: X      exit(EX_ARGSBAD);
                   2066: X    }
                   2067: X
                   2068: X    /* set the blocking factor, if not set by the user */
                   2069: X    if (blocking == 0) {
                   2070: X#ifdef USG
                   2071: X      if (f_extract || f_list) {
                   2072: X          blocking = DEF_BLOCKING;
                   2073: X          fprintf(stderr, "Tar: blocksize = %d\n", blocking);
                   2074: X      } else {
                   2075: X          blocking = 1;
                   2076: X      }
                   2077: X#else /* !USG */
                   2078: X      blocking = 20;
                   2079: X#endif /* USG */
                   2080: X    }
                   2081: X    blocksize = blocking * BLOCKSIZE;
                   2082: X    buf_allocate((OFFSET) blocksize);
                   2083: X
                   2084: X    if (f_create) {
                   2085: X      open_archive(AR_WRITE);
                   2086: X      create_archive();       /* create the archive */
                   2087: X    } else if (f_extract) {
                   2088: X      open_archive(AR_READ);
                   2089: X      read_archive();         /* extract files from archive */
                   2090: X    } else if (f_list) {
                   2091: X      open_archive(AR_READ);
                   2092: X      read_archive();         /* read and list contents of archive */
                   2093: X    } else if (f_append) {
                   2094: X      open_archive(AR_APPEND);
                   2095: X      append_archive();       /* append files to archive */
                   2096: X    }
                   2097: X    
                   2098: X    if (f_linksleft) {                
                   2099: X      linkleft();             /* report any unresolved links */ 
                   2100: X    }
                   2101: X    
                   2102: X    return (0);
                   2103: X}
                   2104: X
                   2105: X
                   2106: X/* taropt -  tar specific getopt
                   2107: X *
                   2108: X * DESCRIPTION
                   2109: X *
                   2110: X *    Plug-compatible replacement for getopt() for parsing tar-like
                   2111: X *    arguments.  If the first argument begins with "-", it uses getopt;
                   2112: X *    otherwise, it uses the old rules used by tar, dump, and ps.
                   2113: X *
                   2114: X * PARAMETERS
                   2115: X *
                   2116: X *    int argc        - argument count (argc from main) 
                   2117: X *    char **argv     - argument list (argv from main) 
                   2118: X *    char *optstring - sring which describes allowable options
                   2119: X *
                   2120: X * RETURNS
                   2121: X *
                   2122: X *    Returns the next option character in the option string(s).  If the
                   2123: X *    option requires an argument and an argument was given, the argument
                   2124: X *    is pointed to by "optarg".  If no option character was found,
                   2125: X *    returns an EOF.
                   2126: X *
                   2127: X */
                   2128: X
                   2129: X#ifdef __STDC__
                   2130: X
                   2131: Xstatic int taropt(int argc, char **argv, char *optstring)
                   2132: X
                   2133: X#else
                   2134: X
                   2135: Xstatic int taropt(argc, argv, optstring)
                   2136: Xint             argc;
                   2137: Xchar          **argv;
                   2138: Xchar           *optstring;
                   2139: X
                   2140: X#endif
                   2141: X{
                   2142: X    extern char    *optarg;   /* Points to next arg */
                   2143: X    extern int      optind;   /* Global argv index */
                   2144: X    static char    *key;      /* Points to next keyletter */
                   2145: X    static char     use_getopt;       /* !=0 if argv[1][0] was '-' */
                   2146: X    char            c;
                   2147: X    char           *place;
                   2148: X
                   2149: X    optarg = NULL;
                   2150: X
                   2151: X    if (key == NULL) {                /* First time */
                   2152: X      if (argc < 2)
                   2153: X          return EOF;
                   2154: X      key = argv[1];
                   2155: X      if (*key == '-')
                   2156: X          use_getopt++;
                   2157: X      else
                   2158: X          optind = 2;
                   2159: X    }
                   2160: X    if (use_getopt) {
                   2161: X      return getopt(argc, argv, optstring);
                   2162: X    }
                   2163: X
                   2164: X    c = *key++;
                   2165: X    if (c == '\0') {
                   2166: X      key--;
                   2167: X      return EOF;
                   2168: X    }
                   2169: X    place = strchr(optstring, c);
                   2170: X
                   2171: X    if (place == NULL || c == ':') {
                   2172: X      fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
                   2173: X      return ('?');
                   2174: X    }
                   2175: X    place++;
                   2176: X    if (*place == ':') {
                   2177: X      if (optind < argc) {
                   2178: X          optarg = argv[optind];
                   2179: X          optind++;
                   2180: X      } else {
                   2181: X          fprintf(stderr, "%s: %c argument missing\n",
                   2182: X                  argv[0], c);
                   2183: X          return ('?');
                   2184: X      }
                   2185: X    }
                   2186: X    return (c);
                   2187: X}
                   2188: X
                   2189: X
                   2190: X/* usage - print a helpful message and exit
                   2191: X *
                   2192: X * DESCRIPTION
                   2193: X *
                   2194: X *    Usage prints out the usage message for the TAR interface and then
                   2195: X *    exits with a non-zero termination status.  This is used when a user
                   2196: X *    has provided non-existant or incompatible command line arguments.
                   2197: X *
                   2198: X * RETURNS
                   2199: X *
                   2200: X *    Returns an exit status of 1 to the parent process.
                   2201: X *
                   2202: X */
                   2203: X
                   2204: X#ifdef __STDC__
                   2205: X
                   2206: Xstatic void usage(void)
                   2207: X
                   2208: X#else
                   2209: X
                   2210: Xstatic void usage()
                   2211: X
                   2212: X#endif
                   2213: X{
                   2214: X    fprintf(stderr, "\
                   2215: XUsage: %s -c[bfvw] device block filename..\n", myname);
                   2216: X    fprintf(stderr, "\
                   2217: X       %s -r[bvw] device block [filename...]\n", myname);
                   2218: X    fprintf(stderr, "\
                   2219: X       %s -t[vf] device\n", myname);
                   2220: X    fprintf(stderr, "\
                   2221: X       %s -u[bvw] device block [filename...]\n", myname);
                   2222: X    fprintf(stderr, "\
                   2223: X       %s -x[flmovw] device [filename...]\n", myname);
                   2224: X    exit(1);
                   2225: X}
                   2226: END_OF_tar.c
                   2227: if test 7881 -ne `wc -c <tar.c`; then
                   2228:     echo shar: \"tar.c\" unpacked with wrong size!
                   2229: fi
                   2230: # end of overwriting check
                   2231: fi
                   2232: echo shar: End of archive 3 \(of 6\).
                   2233: cp /dev/null ark3isdone
                   2234: MISSING=""
                   2235: for I in 1 2 3 4 5 6 ; do
                   2236:     if test ! -f ark${I}isdone ; then
                   2237:        MISSING="${MISSING} ${I}"
                   2238:     fi
                   2239: done
                   2240: if test "${MISSING}" = "" ; then
                   2241:     echo You have unpacked all 6 archives.
                   2242:     rm -f ark[1-9]isdone
                   2243: else
                   2244:     echo You still need to unpack the following archives:
                   2245:     echo "        " ${MISSING}
                   2246: fi
                   2247: ##  End of shell archive.
                   2248: exit 0
                   2249: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.