Annotation of coherent/d/usr/bin/pax/public/part03.sh, revision 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.