Print this page
6128 tar should check prefix field when detecting EOT
6129 tar debug output should be available in all builds
Reviewed by: Robert Mustacchi <rm@joyent.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012 Milan Jurik. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  25  */
  26 
  27 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  28 /*        All Rights Reserved   */
  29 
  30 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  31 /*        All Rights Reserved   */
  32 
  33 /*
  34  * Portions of this source code were derived from Berkeley 4.3 BSD
  35  * under license from the Regents of the University of California.
  36  */
  37 
  38 #include <unistd.h>
  39 #include <sys/types.h>
  40 #include <sys/param.h>
  41 #include <sys/stat.h>
  42 #include <sys/mkdev.h>
  43 #include <sys/wait.h>
  44 #include <dirent.h>


 107 static int openat();
 108 static int fchownat();
 109 static int futimesat();
 110 #endif
 111 
 112 /*
 113  * Compiling with -D_XPG4_2 gets this but produces other problems, so
 114  * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
 115  * explicitly doing the declaration here.
 116  */
 117 int utimes(const char *path, const struct timeval timeval_ptr[]);
 118 
 119 #ifndef MINSIZE
 120 #define MINSIZE 250
 121 #endif
 122 #define DEF_FILE "/etc/default/tar"
 123 
 124 #define min(a, b)  ((a) < (b) ? (a) : (b))
 125 #define max(a, b)  ((a) > (b) ? (a) : (b))
 126 
 127 /* -DDEBUG      ONLY for debugging */
 128 #ifdef  DEBUG
 129 #undef  DEBUG
 130 #define DEBUG(a, b, c)\
 131         (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c)
 132 #endif
 133 
 134 #define TBLOCK  512     /* tape block size--should be universal */
 135 
 136 #ifdef  BSIZE
 137 #define SYS_BLOCK BSIZE /* from sys/param.h:  secondary block size */
 138 #else   /* BSIZE */
 139 #define SYS_BLOCK 512   /* default if no BSIZE in param.h */
 140 #endif  /* BSIZE */
 141 
 142 #define NBLOCK  20
 143 #define NAMSIZ  100
 144 #define PRESIZ  155
 145 #define MAXNAM  256
 146 #define MODEMASK 0777777        /* file creation mode mask */
 147 #define POSIXMODES 07777        /* mask for POSIX mode bits */
 148 #define MAXEXT  9       /* reasonable max # extents for a file */
 149 #define EXTMIN  50      /* min blks left on floppy to split a file */
 150 
 151 /* max value dblock.dbuf.efsize can store */
 152 #define TAR_EFSIZE_MAX   0777777777
 153 


 465 static void seekdisk(blkcnt_t blocks);
 466 static void setPathTimes(int dirfd, char *path, timestruc_t modTime);
 467 static void setbytes_to_skip(struct stat *st, int err);
 468 static void splitfile(char *longname, int ifd, char *name,
 469         char *prefix, int filetype);
 470 static void tomodes(struct stat *sp);
 471 static void usage(void);
 472 static int xblocks(int issysattr, off_t bytes, int ofile);
 473 static int xsfile(int issysattr, int ofd);
 474 static void resugname(int dirfd, char *name, int symflag);
 475 static int bcheck(char *bstr);
 476 static int checkdir(char *name);
 477 static int checksum(union hblock *dblockp);
 478 #ifdef  EUC
 479 static int checksum_signed(union hblock *dblockp);
 480 #endif  /* EUC */
 481 static int checkupdate(char *arg);
 482 static int checkw(char c, char *name);
 483 static int cmp(char *b, char *s, int n);
 484 static int defset(char *arch);
 485 static int endtape(void);
 486 static int is_in_table(file_list_t *table[], char *str);
 487 static int notsame(void);
 488 static int is_prefix(char *s1, char *s2);
 489 static int response(void);
 490 static int build_dblock(const char *, const char *, const char,
 491         const int filetype, const struct stat *, const dev_t, const char *);
 492 static unsigned int hash(char *str);
 493 
 494 static blkcnt_t kcheck(char *kstr);
 495 static off_t bsrch(char *s, int n, off_t l, off_t h);
 496 static void onintr(int sig);
 497 static void onquit(int sig);
 498 static void onhup(int sig);
 499 static uid_t getuidbyname(char *);
 500 static gid_t getgidbyname(char *);
 501 static char *getname(gid_t);
 502 static char *getgroup(gid_t);
 503 static int checkf(char *name, int mode, int howmuch);
 504 static int writetbuf(char *buffer, int n);
 505 static int wantit(char *argv[], char **namep, char **dirp, char **comp,


 541 
 542 static void get_parent(char *path, char *dir);
 543 static char *get_component(char *path);
 544 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr,
 545     char *name, int oflag, mode_t mode);
 546 static char *skipslashes(char *string, char *start);
 547 static void chop_endslashes(char *path);
 548 static pid_t compress_file(void);
 549 static void compress_back(void);
 550 static void decompress_file(void);
 551 static pid_t uncompress_file(void);
 552 static void *compress_malloc(size_t);
 553 static void check_compression(void);
 554 static char *bz_suffix(void);
 555 static char *gz_suffix(void);
 556 static char *xz_suffix(void);
 557 static char *add_suffix();
 558 static void wait_pid(pid_t);
 559 static void verify_compress_opt(const char *t);
 560 static void detect_compress(void);


 561 
 562 static  struct stat stbuf;
 563 
 564 static  char    *myname;
 565 static  char    *xtract_chdir = NULL;
 566 static  int     checkflag = 0;
 567 static  int     Xflag, Fflag, iflag, hflag, Bflag, Iflag;
 568 static  int     rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag;
 569 static  int     uflag;
 570 static  int     errflag;
 571 static  int     oflag;
 572 static  int     bflag, Aflag;
 573 static  int     Pflag;                  /* POSIX conformant archive */
 574 static  int     Eflag;                  /* Allow files greater than 8GB */
 575 static  int     atflag;                 /* traverse extended attributes */
 576 static  int     saflag;                 /* traverse extended sys attributes */
 577 static  int     Dflag;                  /* Data change flag */
 578 static  int     jflag;                  /* flag to use 'bzip2' */
 579 static  int     zflag;                  /* flag to use 'gzip' */
 580 static  int     Zflag;                  /* flag to use 'compress' */


 616 
 617 static  FILE    *tfile;
 618 static  FILE    *vfile = stdout;
 619 static  char    *tmpdir;
 620 static  char    *tmp_suffix = "/tarXXXXXX";
 621 static  char    *tname;
 622 static  char    archive[] = "archive0=";
 623 static  char    *Xfile;
 624 static  char    *usefile;
 625 static  char    tfname[1024];
 626 
 627 static  int     mulvol;         /* multi-volume option selected */
 628 static  blkcnt_t        blocklim; /* number of blocks to accept per volume */
 629 static  blkcnt_t        tapepos; /* current block number to be written */
 630 static  int     NotTape;        /* true if tape is a disk */
 631 static  int     dumping;        /* true if writing a tape or other archive */
 632 static  int     extno;          /* number of extent:  starts at 1 */
 633 static  int     extotal;        /* total extents in this file */
 634 static  off_t   extsize;        /* size of current extent during extraction */
 635 static  ushort_t        Oumask = 0;     /* old umask value */
 636 static  int is_posix;   /* true if archive we're reading is POSIX-conformant */
 637 static  const   char    *magic_type = "ustar";
 638 static  size_t  xrec_size = 8 * PATH_MAX;       /* extended rec initial size */
 639 static  char    *xrec_ptr;
 640 static  off_t   xrec_offset = 0;
 641 static  int     Xhdrflag;
 642 static  int     charset_type = 0;
 643 
 644 static  u_longlong_t    xhdr_flgs;      /* Bits set determine which items */
 645                                         /*   need to be in extended header. */
 646 static  pid_t   comp_pid = 0;
 647 


 648 #define _X_DEVMAJOR     0x1
 649 #define _X_DEVMINOR     0x2
 650 #define _X_GID          0x4
 651 #define _X_GNAME        0x8
 652 #define _X_LINKPATH     0x10
 653 #define _X_PATH         0x20
 654 #define _X_SIZE         0x40
 655 #define _X_UID          0x80
 656 #define _X_UNAME        0x100
 657 #define _X_ATIME        0x200
 658 #define _X_CTIME        0x400
 659 #define _X_MTIME        0x800
 660 #define _X_XHDR         0x1000  /* Bit flag that determines whether 'X' */
 661                                 /* typeflag was followed by 'A' or non 'A' */
 662                                 /* typeflag. */
 663 #define _X_LAST         0x40000000
 664 
 665 #define PID_MAX_DIGITS          (10 * sizeof (pid_t) / 4)
 666 #define TIME_MAX_DIGITS         (10 * sizeof (time_t) / 4)
 667 #define LONG_MAX_DIGITS         (10 * sizeof (long) / 4)


 719 static  char            *bsuffix[] = {".bz2", ".bz", ".tbz2", ".tbz"};
 720 static  char            *xsuffix[] = {".xz"};
 721 static  char            *suffix;
 722 
 723 
 724 int
 725 main(int argc, char *argv[])
 726 {
 727         char            *cp;
 728         char            *tmpdirp;
 729         pid_t           thispid;
 730 
 731         (void) setlocale(LC_ALL, "");
 732 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 733 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 734 #endif
 735         (void) textdomain(TEXT_DOMAIN);
 736         if (argc < 2)
 737                 usage();
 738 


 739         tfile = NULL;
 740         if ((myname = strdup(argv[0])) == NULL) {
 741                 (void) fprintf(stderr, gettext(
 742                     "tar: cannot allocate program name\n"));
 743                 exit(1);
 744         }
 745 
 746         if (init_yes() < 0) {
 747                 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
 748                     strerror(errno));
 749                 exit(2);
 750         }
 751 
 752         /*
 753          *  For XPG4 compatibility, we must be able to accept the "--"
 754          *  argument normally recognized by getopt; it is used to delimit
 755          *  the end opt the options section, and so can only appear in
 756          *  the position of the first argument.  We simply skip it.
 757          */
 758 


1176                                             "directories to %s"), xtract_chdir);
1177                                 }
1178                         }
1179                         if (Aflag && vflag)
1180                                 (void) printf(gettext(
1181                                     "Suppressing absolute pathnames.\n"));
1182 
1183                         doxtract(argv);
1184                 } else if (tflag)
1185                         dotable(argv);
1186         }
1187         else
1188                 usage();
1189 
1190         done(Errflg);
1191 
1192         /* Not reached:  keep compiler quiet */
1193         return (1);
1194 }
1195 




























1196 static void















1197 usage(void)
1198 {
1199         (void) fprintf(stderr, gettext(
1200 #if defined(O_XATTR)
1201 #if defined(_PC_SATTR_ENABLED)
1202             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw@/[0-7]][bf][X...] "
1203 #else
1204             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw@[0-7]][bf][X...] "
1205 #endif  /* _PC_SATTR_ENABLED */
1206 #else
1207             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw[0-7]][bf][X...] "
1208 #endif  /* O_XATTR */
1209             "[j|J|z|Z] "
1210             "[blocksize] [tarfile] [size] [exclude-file...] "
1211             "{file | -I include-file | -C directory file}...\n"));
1212         done(1);
1213 }
1214 
1215 /*
1216  * dorep - do "replacements"


1410                         if (errflag)
1411                                 done(1);
1412                         else
1413                                 Errflg = 1;
1414                 }
1415 }
1416 
1417 
1418 /*
1419  * endtape - check for tape at end
1420  *
1421  *      endtape checks the entry in dblock.dbuf to see if its the
1422  *      special EOT entry.  Endtape is usually called after getdir().
1423  *
1424  *      endtape used to call backtape; it no longer does, he who
1425  *      wants it backed up must call backtape himself
1426  *      RETURNS:        0 if not EOT, tape position unaffected
1427  *                      1 if     EOT, tape position unaffected
1428  */
1429 
1430 static int
1431 endtape(void)
1432 {
1433         if (dblock.dbuf.name[0] == '\0') {      /* null header = EOT */
1434                 return (1);
1435         } else
1436                 return (0);













1437 }
1438 
1439 /*
1440  *      getdir - get directory entry from tar tape
1441  *
1442  *      getdir reads the next tarblock off the tape and cracks
1443  *      it as a directory. The checksum must match properly.
1444  *
1445  *      If tfile is non-null getdir writes the file name and mod date
1446  *      to tfile.
1447  */
1448 
1449 static void
1450 getdir(void)
1451 {
1452         struct stat *sp;
1453 #ifdef EUC
1454         static int warn_chksum_sign = 0;
1455 #endif /* EUC */
1456 
1457 top:
1458         readtape((char *)&dblock);
1459         if (dblock.dbuf.name[0] == '\0')
1460                 return;
1461         sp = &stbuf;
1462         (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode);
1463         (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid);
1464         (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid);
1465         (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz);
1466         (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime);
1467         (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum);
1468         (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor);
1469         (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor);
1470 
1471         is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
1472 
1473         sp->st_mode = Gen.g_mode;
1474         if (is_posix && (sp->st_mode & S_IFMT) == 0)
1475                 switch (dblock.dbuf.typeflag) {
1476                 case '0': case 0: case _XATTR_HDRTYPE:


1477                         sp->st_mode |= S_IFREG;
1478                         break;
1479                 case '1':       /* hard link */
1480                         break;
1481                 case '2':
1482                         sp->st_mode |= S_IFLNK;
1483                         break;
1484                 case '3':
1485                         sp->st_mode |= S_IFCHR;
1486                         break;
1487                 case '4':
1488                         sp->st_mode |= S_IFBLK;
1489                         break;
1490                 case '5':
1491                         sp->st_mode |= S_IFDIR;
1492                         break;
1493                 case '6':
1494                         sp->st_mode |= S_IFIFO;
1495                         break;
1496                 default:
1497                         if (convtoreg(Gen.g_filesz))
1498                                 sp->st_mode |= S_IFREG;
1499                         break;
1500                 }

1501 
1502         if ((dblock.dbuf.typeflag == 'X') || (dblock.dbuf.typeflag == 'L')) {
1503                 Xhdrflag = 1;   /* Currently processing extended header */
1504         } else {
1505                 Xhdrflag = 0;
1506         }
1507 
1508         sp->st_uid = Gen.g_uid;
1509         sp->st_gid = Gen.g_gid;
1510         sp->st_size = Gen.g_filesz;
1511         sp->st_mtime = Gen.g_mtime;
1512         chksum = Gen.g_cksum;
1513 
1514         if (dblock.dbuf.extno != '\0') {        /* split file? */
1515                 extno = dblock.dbuf.extno;
1516                 extsize = Gen.g_filesz;
1517                 extotal = dblock.dbuf.extotal;
1518         } else {
1519                 extno = 0;      /* tell others file not split */
1520                 extsize = 0;


1588                             xattrapath[xindex + 1] == '\0' &&
1589                             xattrp->h_typeflag == '5') {
1590                                 Hiddendir = 1;
1591                                 sp->st_mode =
1592                                     (S_IFDIR | (sp->st_mode & POSIXMODES));
1593                         }
1594                         dblock.dbuf.typeflag = xattrp->h_typeflag;
1595                 }
1596         }
1597 #endif
1598 }
1599 
1600 
1601 /*
1602  *      passtape - skip over a file on the tape
1603  *
1604  *      passtape skips over the next data file on the tape.
1605  *      The tape directory entry must be in dblock.dbuf. This
1606  *      routine just eats the number of blocks computed from the
1607  *      directory size entry; the tape must be (logically) positioned
1608  *      right after thee directory info.
1609  */
1610 
1611 static void
1612 passtape(void)
1613 {
1614         blkcnt_t blocks;
1615         char buf[TBLOCK];
1616 
1617         /*












1618          * Types link(1), sym-link(2), char special(3), blk special(4),
1619          *  directory(5), and FIFO(6) do not have data blocks associated
1620          *  with them so just skip reading the data block.
1621          */
1622         if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' ||
1623             dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' ||
1624             dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6')
1625                 return;
1626         blocks = TBLOCKS(stbuf.st_size);
1627 


1628         /* if operating on disk, seek instead of reading */
1629         if (NotTape)
1630                 seekdisk(blocks);
1631         else
1632                 while (blocks-- > 0)
1633                         readtape(buf);
1634 }
1635 
1636 #if defined(O_XATTR)
1637 static int
1638 is_sysattr(char *name)
1639 {
1640         return ((strcmp(name, VIEW_READONLY) == 0) ||
1641             (strcmp(name, VIEW_READWRITE) == 0));
1642 }
1643 #endif
1644 
1645 #if defined(O_XATTR)
1646 /*
1647  * Verify the attribute, attrname, is an attribute we want to restore.


2053 #if defined(O_XATTR)
2054                         /*
2055                          * Reset header typeflag when archiving directory, since
2056                          * build_dblock changed it on us.
2057                          */
2058                         if (filetype == XATTR_FILE) {
2059                                 dblock.dbuf.typeflag = _XATTR_HDRTYPE;
2060                         } else {
2061                                 dblock.dbuf.typeflag = '5';
2062                         }
2063 #else
2064                         dblock.dbuf.typeflag = '5';
2065 #endif
2066 
2067                         (void) sprintf(dblock.dbuf.chksum, "%07o",
2068                             checksum(&dblock));
2069 
2070                         (void) writetbuf((char *)&dblock, 1);
2071                 }
2072                 if (vflag) {
2073 #ifdef DEBUG
2074                         if (NotTape)
2075                                 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2076                                     0);
2077 #endif
2078                         if (filetype == XATTR_FILE && Hiddendir) {
2079                                 (void) fprintf(vfile,
2080                                     gettext("a %s attribute %s "),
2081                                     longname, longattrname);
2082 
2083                         } else {
2084                                 (void) fprintf(vfile, "a %s/ ", longname);
2085                         }
2086                         if (NotTape)
2087                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2088                                     K(blocks));
2089                         else
2090                                 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t
2091                                     " tape blocks\n"), blocks);
2092                 }

2093 
2094                 /*
2095                  * If hidden dir then break now since xattrs_put() will do
2096                  * the iterating of the directory.
2097                  *
2098                  * At the moment, there can only be system attributes on
2099                  * attributes.  There can be no attributes on attributes or
2100                  * directories within the attributes hidden directory hierarchy.
2101                  */
2102                 if (filetype == XATTR_FILE)
2103                         break;
2104 
2105                 if (*shortname != '/')
2106                         (void) sprintf(newparent, "%s/%s", parent, shortname);
2107                 else
2108                         (void) sprintf(newparent, "%s", shortname);
2109 
2110                 if (tar_chdir(shortname) < 0) {
2111                         vperror(0, "%s", newparent);
2112                         goto out;


2253                         (void) close(infile);
2254                         rc = PUT_AS_LINK;
2255                         goto out;
2256                 }
2257 
2258                 tomodes(&stbuf);
2259 
2260                 /* correctly handle end of volume */
2261                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2262                         /* split if floppy has some room and file is large */
2263                         if (((blocklim - tapepos) >= EXTMIN) &&
2264                             ((blocks + 1) >= blocklim/10)) {
2265                                 splitfile(longname, infile,
2266                                     name, prefix, filetype);
2267                                 (void) close(dirfd);
2268                                 (void) close(infile);
2269                                 goto out;
2270                         }
2271                         newvol();       /* not worth it--just get new volume */
2272                 }
2273 #ifdef DEBUG
2274                 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2275                     blocks);
2276 #endif
2277                 if (build_dblock(name, tchar, '0', filetype,
2278                     &stbuf, stbuf.st_dev, prefix) != 0) {
2279                         goto out;
2280                 }
2281                 if (vflag) {
2282 #ifdef DEBUG
2283                         if (NotTape)
2284                                 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2285                                     0);
2286 #endif
2287                         (void) fprintf(vfile, "a %s%s%s%s ", longname,
2288                             rw_sysattr ? gettext(" system") : "",
2289                             (filetype == XATTR_FILE) ? gettext(
2290                             " attribute ") : "",
2291                             (filetype == XATTR_FILE) ?
2292                             longattrname : "");
2293                         if (NotTape)
2294                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2295                                     K(blocks));
2296                         else
2297                                 (void) fprintf(vfile,
2298                                     gettext("%" FMT_blkcnt_t " tape blocks\n"),
2299                                     blocks);
2300                 }
2301 
2302                 if (put_extra_attributes(longname, shortname, longattrname,
2303                     prefix, filetype, '0') != 0)
2304                         goto out;
2305 
2306                 /*


2350                 stbuf.st_size = (off_t)0;
2351 
2352                 if (put_link(name, longname, shortname, longattrname,
2353                     prefix, filetype, '6') == 0) {
2354                         rc = PUT_AS_LINK;
2355                         goto out;
2356                 }
2357                 tomodes(&stbuf);
2358 
2359                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2360                         if (((blocklim - tapepos) >= EXTMIN) &&
2361                             ((blocks + 1) >= blocklim/10)) {
2362                                 splitfile(longname, infile, name,
2363                                     prefix, filetype);
2364                                 (void) close(dirfd);
2365                                 (void) close(infile);
2366                                 goto out;
2367                         }
2368                         newvol();
2369                 }
2370 #ifdef DEBUG
2371                 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2372                     blocks);
2373 #endif
2374                 if (vflag) {
2375 #ifdef DEBUG
2376                         if (NotTape)
2377                                 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2378                                     0);
2379 #endif
2380                         if (NotTape)
2381                                 (void) fprintf(vfile, gettext("a %s %"
2382                                     FMT_blkcnt_t "K\n "), longname, K(blocks));
2383                         else
2384                                 (void) fprintf(vfile, gettext(
2385                                     "a %s %" FMT_blkcnt_t " tape blocks\n"),
2386                                     longname, blocks);
2387                 }

2388                 if (build_dblock(name, tchar, '6', filetype,
2389                     &stbuf, stbuf.st_dev, prefix) != 0)
2390                         goto out;
2391 
2392                 if (put_extra_attributes(longname, shortname, longattrname,
2393                     prefix, filetype, '6') != 0)
2394                         goto out;
2395 
2396                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2397                 dblock.dbuf.typeflag = '6';
2398 
2399                 (void) writetbuf((char *)&dblock, 1);
2400                 break;
2401         case S_IFCHR:
2402                 stbuf.st_size = (off_t)0;
2403                 blocks = TBLOCKS(stbuf.st_size);
2404                 if (put_link(name, longname, shortname, longattrname,
2405                     prefix, filetype, '3') == 0) {
2406                         rc = PUT_AS_LINK;
2407                         goto out;
2408                 }
2409                 tomodes(&stbuf);
2410 
2411                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2412                         if (((blocklim - tapepos) >= EXTMIN) &&
2413                             ((blocks + 1) >= blocklim/10)) {
2414                                 splitfile(longname, infile, name,
2415                                     prefix, filetype);
2416                                 (void) close(dirfd);
2417                                 goto out;
2418                         }
2419                         newvol();
2420                 }
2421 #ifdef DEBUG
2422                 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2423                     blocks);
2424 #endif
2425                 if (vflag) {
2426 #ifdef DEBUG
2427                         if (NotTape)
2428                                 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2429                                     0);
2430 #endif
2431                         if (NotTape)
2432                                 (void) fprintf(vfile, gettext("a %s %"
2433                                     FMT_blkcnt_t "K\n"), longname, K(blocks));
2434                         else
2435                                 (void) fprintf(vfile, gettext("a %s %"
2436                                     FMT_blkcnt_t " tape blocks\n"), longname,
2437                                     blocks);
2438                 }

2439                 if (build_dblock(name, tchar, '3',
2440                     filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2441                         goto out;
2442 
2443                 if (put_extra_attributes(longname, shortname, longattrname,
2444                     prefix, filetype, '3') != 0)
2445                         goto out;
2446 
2447                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2448                 dblock.dbuf.typeflag = '3';
2449 
2450                 (void) writetbuf((char *)&dblock, 1);
2451                 break;
2452         case S_IFBLK:
2453                 stbuf.st_size = (off_t)0;
2454                 blocks = TBLOCKS(stbuf.st_size);
2455                 if (put_link(name, longname, shortname, longattrname,
2456                     prefix, filetype, '4') == 0) {
2457                         rc = PUT_AS_LINK;
2458                         goto out;
2459                 }
2460                 tomodes(&stbuf);
2461 
2462                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2463                         if (((blocklim - tapepos) >= EXTMIN) &&
2464                             ((blocks + 1) >= blocklim/10)) {
2465                                 splitfile(longname, infile,
2466                                     name, prefix, filetype);
2467                                 (void) close(dirfd);
2468                                 goto out;
2469                         }
2470                         newvol();
2471                 }
2472 #ifdef DEBUG
2473                 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,
2474                     blocks);
2475 #endif
2476                 if (vflag) {
2477 #ifdef DEBUG
2478                         if (NotTape)
2479                                 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos),
2480                                     0);
2481 #endif
2482                         (void) fprintf(vfile, "a %s ", longname);
2483                         if (NotTape)
2484                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2485                                     K(blocks));
2486                         else
2487                                 (void) fprintf(vfile, gettext("%"
2488                                     FMT_blkcnt_t " tape blocks\n"), blocks);
2489                 }
2490                 if (build_dblock(name, tchar, '4',
2491                     filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2492                         goto out;
2493 
2494                 if (put_extra_attributes(longname, shortname, longattrname,
2495                     prefix, filetype, '4') != 0)
2496                         goto out;
2497 
2498                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2499                 dblock.dbuf.typeflag = '4';
2500 
2501                 (void) writetbuf((char *)&dblock, 1);


4773             ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs)))
4774                 return (0);
4775         return (1);
4776 }
4777 
4778 
4779 /*
4780  *      newvol  get new floppy (or tape) volume
4781  *
4782  *      newvol();               resets tapepos and first to TRUE, prompts for
4783  *                              for new volume, and waits.
4784  *      if dumping, end-of-file is written onto the tape.
4785  */
4786 
4787 static void
4788 newvol(void)
4789 {
4790         int c;
4791 
4792         if (dumping) {
4793 #ifdef DEBUG
4794                 DEBUG("newvol called with 'dumping' set\n", 0, 0);
4795 #endif
4796                 putempty((blkcnt_t)2);  /* 2 EOT marks */
4797                 closevol();
4798                 flushtape();
4799                 sync();
4800                 tapepos = 0;
4801         } else
4802                 first = TRUE;
4803         if (close(mt) != 0)
4804                 vperror(2, gettext("close error"));
4805         mt = 0;
4806         (void) fprintf(stderr, gettext(
4807             "tar: \007please insert new volume, then press RETURN."));
4808         (void) fseek(stdin, (off_t)0, 2);       /* scan over read-ahead */
4809         while ((c = getchar()) != '\n' && ! term)
4810                 if (c == EOF)
4811                         done(Errflg);
4812         if (term)
4813                 done(Errflg);
4814 
4815         errno = 0;
4816 
4817         if (strcmp(usefile, "-") == 0) {
4818                 mt = dup(1);
4819         } else {
4820                 mt = open(usefile, dumping ? update : 0);
4821         }
4822 
4823         if (mt < 0) {
4824                 (void) fprintf(stderr, gettext(
4825                     "tar: cannot reopen %s (%s)\n"),
4826                     dumping ? gettext("output") : gettext("input"), usefile);
4827 
4828 #ifdef DEBUG
4829                 DEBUG("update=%d, usefile=%s ", update, usefile);
4830                 DEBUG("mt=%d, [%s]\n", mt, strerror(errno));
4831 #endif
4832 
4833                 done(2);
4834         }
4835 }
4836 
4837 /*
4838  * Write a trailer portion to close out the current output volume.
4839  */
4840 
4841 static void
4842 closevol(void)
4843 {
4844         if (mulvol) {
4845                 /*
4846                  * blocklim does not count the 2 EOT marks;
4847                  * tapepos  does count the 2 EOT marks;
4848                  * therefore we need the +2 below.
4849                  */
4850                 putempty(blocklim + (blkcnt_t)2 - tapepos);
4851         }


4996  *      called by passtape() only
4997  *
4998  *      WARNING: expects "nblock" to be set, that is, readtape() to have
4999  *              already been called.  Since passtape() is only called
5000  *              after a file header block has been read (why else would
5001  *              we skip to next file?), this is currently safe.
5002  *
5003  *      changed to guarantee SYS_BLOCK boundary
5004  */
5005 
5006 static void
5007 seekdisk(blkcnt_t blocks)
5008 {
5009         off_t seekval;
5010 #if SYS_BLOCK > TBLOCK
5011         /* handle non-multiple of SYS_BLOCK */
5012         blkcnt_t nxb;   /* # extra blocks */
5013 #endif
5014 
5015         tapepos += blocks;
5016 #ifdef DEBUG
5017         DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0);
5018 #endif
5019         if (recno + blocks <= nblock) {
5020                 recno += blocks;
5021                 return;
5022         }
5023         if (recno > nblock)
5024                 recno = nblock;
5025         seekval = (off_t)blocks - (nblock - recno);
5026         recno = nblock; /* so readtape() reads next time through */
5027 #if SYS_BLOCK > TBLOCK
5028         nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK));
5029 #ifdef DEBUG
5030         DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n",
5031             nxb, seekval);
5032 #endif
5033         if (nxb && nxb > seekval) /* don't seek--we'll read */
5034                 goto noseek;
5035         seekval -=  nxb;        /* don't seek quite so far */
5036 #endif
5037         if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) {
5038                 (void) fprintf(stderr, gettext(
5039                     "tar: device seek error\n"));
5040                 done(3);
5041         }
5042 #if SYS_BLOCK > TBLOCK
5043         /* read those extra blocks */
5044 noseek:
5045         if (nxb) {
5046 #ifdef DEBUG
5047                 DEBUG("reading extra blocks\n", 0, 0);
5048 #endif
5049                 if (read(mt, tbuf, TBLOCK*nblock) < 0) {
5050                         (void) fprintf(stderr, gettext(
5051                             "tar: read error while skipping file\n"));
5052                         done(8);
5053                 }
5054                 recno = nxb;    /* so we don't read in next readtape() */
5055         }
5056 #endif
5057 }
5058 
5059 static void
5060 readtape(char *buffer)
5061 {
5062         int i, j;
5063 
5064         ++tapepos;
5065         if (recno >= nblock || first) {
5066                 if (first) {
5067                         /*
5068                          * set the number of blocks to read initially, based on


5200 
5201 /*
5202  *      backtape - reposition tape after reading soft "EOF" record
5203  *
5204  *      Backtape tries to reposition the tape back over the EOF
5205  *      record.  This is for the 'u' and 'r' function letters so that the
5206  *      tape can be extended.  This code is not well designed, but
5207  *      I'm confident that the only callers who care about the
5208  *      backspace-over-EOF feature are those involved in 'u' and 'r'.
5209  *
5210  *      The proper way to backup the tape is through the use of mtio.
5211  *      Earlier spins used lseek combined with reads in a confusing
5212  *      maneuver that only worked on 4.x, but shouldn't have, even
5213  *      there.  Lseeks are explicitly not supported for tape devices.
5214  */
5215 
5216 static void
5217 backtape(void)
5218 {
5219         struct mtop mtcmd;
5220 #ifdef DEBUG
5221         DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno,
5222             nblock);
5223 #endif
5224         /*
5225          * Backup to the position in the archive where the record
5226          * currently sitting in the tbuf buffer is situated.
5227          */
5228 
5229         if (NotTape) {
5230                 /*
5231                  * For non-tape devices, this means lseeking to the
5232                  * correct position.  The absolute location tapepos-recno
5233                  * should be the beginning of the current record.
5234                  */
5235 
5236                 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) ==
5237                     (off_t)-1) {
5238                         (void) fprintf(stderr,
5239                             gettext("tar: lseek to end of archive failed\n"));
5240                         done(4);
5241                 }
5242         } else {
5243                 /*


5261          */
5262 
5263         recno--;
5264         tapepos--;
5265 }
5266 
5267 
5268 /*
5269  *      flushtape  write buffered block(s) onto tape
5270  *
5271  *      recno points to next free block in tbuf.  If nonzero, a write is done.
5272  *      Care is taken to write in multiples of SYS_BLOCK when device is
5273  *      non-magtape in case raw i/o is used.
5274  *
5275  *      NOTE: this is called by writetape() to do the actual writing
5276  */
5277 
5278 static void
5279 flushtape(void)
5280 {
5281 #ifdef DEBUG
5282         DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0);
5283 #endif
5284         if (recno > 0) {     /* anything buffered? */
5285                 if (NotTape) {
5286 #if SYS_BLOCK > TBLOCK
5287                         int i;
5288 
5289                         /*
5290                          * an odd-block write can only happen when
5291                          * we are at the end of a volume that is not a tape.
5292                          * Here we round recno up to an even SYS_BLOCK
5293                          * boundary.
5294                          */
5295                         if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) {
5296 #ifdef DEBUG
5297                                 DEBUG("flushtape() %d rounding blocks\n", i, 0);
5298 #endif
5299                                 recno += i;     /* round up to even SYS_BLOCK */
5300                         }
5301 #endif
5302                         if (recno > nblock)
5303                                 recno = nblock;
5304                 }
5305 #ifdef DEBUG
5306                 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t
5307                     " bytes\n", (blkcnt_t)(NotTape ? recno : nblock),
5308                     (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK);
5309 #endif
5310                 if (write(mt, tbuf,
5311                     (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) {
5312                         (void) fprintf(stderr, gettext(
5313                             "tar: tape write error\n"));
5314                         done(2);
5315                 }
5316                 recno = 0;
5317         }
5318 }
5319 
5320 static void
5321 copy(void *dst, void *src)
5322 {
5323         (void) memcpy(dst, src, TBLOCK);
5324 }
5325 
5326 /*
5327  * kcheck()
5328  *      - checks the validity of size values for non-tape devices
5329  *      - if size is zero, mulvol tar is disabled and size is


5419         }
5420         if ((bp = strtok(NULL, " \t")) == NULL) {
5421                 (void) fprintf(stderr, gettext(
5422                     "tar: block component missing in '%s' entry in %s.\n"),
5423                     arch, DEF_FILE);
5424                 return (FALSE);
5425         }
5426         nblock = bcheck(bp);
5427         if ((bp = strtok(NULL, " \t")) == NULL) {
5428                 (void) fprintf(stderr, gettext(
5429                     "tar: size component missing in '%s' entry in %s.\n"),
5430                     arch, DEF_FILE);
5431                 return (FALSE);
5432         }
5433         blocklim = kcheck(bp);
5434         if ((bp = strtok(NULL, " \t")) != NULL)
5435                 NotTape = (*bp == 'n' || *bp == 'N');
5436         else
5437                 NotTape = (blocklim != 0);
5438         (void) defopen(NULL);
5439 #ifdef DEBUG
5440         DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile);
5441         DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n",
5442             nblock, blocklim);
5443         DEBUG("defset: not tape = %d\n", NotTape, 0);
5444 #endif
5445         return (TRUE);
5446 }
5447 
5448 
5449 /*
5450  * Following code handles excluded and included files.
5451  * A hash table of file names to be {in,ex}cluded is built.
5452  * For excluded files, before writing or extracting a file
5453  * check to see if it is in the exclude_tbl.
5454  * For included files, the wantit() procedure will check to
5455  * see if the named file is in the include_tbl.
5456  */
5457 
5458 static void
5459 build_table(file_list_t *table[], char *file)
5460 {
5461         FILE    *fp;
5462         char    buf[PATH_MAX + 1];
5463 
5464         if ((fp = fopen(file, "r")) == (FILE *)NULL)


5735                 if (!tflag &&
5736                     ((!atflag && !saflag) ||
5737                     (atflag && !saflag && ((ainfo->attr_parent != NULL) ||
5738                     ainfo->attr_rw_sysattr)) ||
5739                     (!atflag && saflag && ((ainfo->attr_parent != NULL) ||
5740                     !ainfo->attr_rw_sysattr)))) {
5741                         passtape();
5742                         return (0);
5743                 }
5744         }
5745 #endif
5746 
5747         /* sets *namep to point at the proper name */
5748         if (check_prefix(namep, dirp, component) != 0) {
5749                 passtape();
5750                 return (0);
5751         }
5752 
5753         if (endtape()) {
5754                 if (Bflag) {



5755                         /*
5756                          * Logically at EOT - consume any extra blocks
5757                          * so that write to our stdin won't fail and
5758                          * emit an error message; otherwise something
5759                          * like "dd if=foo.tar | (cd bar; tar xvf -)"
5760                          * will produce a bogus error message from "dd".
5761                          */
5762 
5763                         while (read(mt, tbuf, TBLOCK*nblock) > 0) {
5764                                 /* empty body */
5765                         }


5766                 }

5767                 return (-1);
5768         }
5769 
5770         gotit = 0;
5771 
5772         if ((Iflag && is_in_table(include_tbl, *namep)) ||
5773             (! Iflag && *argv == NULL)) {
5774                 gotit = 1;
5775         } else {
5776                 for (cp = argv; *cp; cp++) {
5777                         if (is_prefix(*cp, *namep)) {
5778                                 gotit = 1;
5779                                 break;
5780                         }
5781                 }
5782         }
5783 
5784         if (! gotit) {
5785                 passtape();
5786                 return (0);


7999                         if (filetype != XATTR_FILE) {
8000                                 tomodes(&stbuf);
8001                                 if (chk_path_build(name, longname, lp->pathname,
8002                                     prefix, type, filetype) > 0) {
8003                                         goto out;
8004                                 }
8005                         }
8006 
8007                         if (mulvol && tapepos + 1 >= blocklim)
8008                                 newvol();
8009                         (void) writetbuf((char *)&dblock, 1);
8010                         /*
8011                          * write_ancillary() is not needed here.
8012                          * The first link is handled in the following
8013                          * else statement. No need to process ACLs
8014                          * for other hard links since they are the
8015                          * same file.
8016                          */
8017 
8018                         if (vflag) {
8019 #ifdef DEBUG
8020                                 if (NotTape)
8021                                         DEBUG("seek = %" FMT_blkcnt_t
8022                                             "K\t", K(tapepos), 0);
8023 #endif
8024                                 if (filetype == XATTR_FILE) {
8025                                         (void) fprintf(vfile, gettext(
8026                                             "a %s attribute %s link to "
8027                                             "%s attribute %s\n"),
8028                                             name, component, name,
8029                                             lp->attrname);
8030                                 } else {
8031                                         (void) fprintf(vfile, gettext(
8032                                             "a %s link to %s\n"),
8033                                             longname, lp->pathname);
8034                                 }
8035                         }
8036                         lp->count--;
8037                         return (0);
8038                 } else {
8039                         lp = (struct linkbuf *)getmem(sizeof (*lp));
8040                         if (lp != (struct linkbuf *)NULL) {
8041                                 lp->nextp = ihead;
8042                                 ihead = lp;
8043                                 lp->inum = stbuf.st_ino;




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2012 Milan Jurik. All rights reserved.
  24  * Copyright 2015 Joyent, Inc.
  25  */
  26 
  27 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  28 /*        All Rights Reserved   */
  29 
  30 /*      Copyright (c) 1987, 1988 Microsoft Corporation  */
  31 /*        All Rights Reserved   */
  32 
  33 /*
  34  * Portions of this source code were derived from Berkeley 4.3 BSD
  35  * under license from the Regents of the University of California.
  36  */
  37 
  38 #include <unistd.h>
  39 #include <sys/types.h>
  40 #include <sys/param.h>
  41 #include <sys/stat.h>
  42 #include <sys/mkdev.h>
  43 #include <sys/wait.h>
  44 #include <dirent.h>


 107 static int openat();
 108 static int fchownat();
 109 static int futimesat();
 110 #endif
 111 
 112 /*
 113  * Compiling with -D_XPG4_2 gets this but produces other problems, so
 114  * instead of including sys/time.h and compiling with -D_XPG4_2, I'm
 115  * explicitly doing the declaration here.
 116  */
 117 int utimes(const char *path, const struct timeval timeval_ptr[]);
 118 
 119 #ifndef MINSIZE
 120 #define MINSIZE 250
 121 #endif
 122 #define DEF_FILE "/etc/default/tar"
 123 
 124 #define min(a, b)  ((a) < (b) ? (a) : (b))
 125 #define max(a, b)  ((a) > (b) ? (a) : (b))
 126 







 127 #define TBLOCK  512     /* tape block size--should be universal */
 128 
 129 #ifdef  BSIZE
 130 #define SYS_BLOCK BSIZE /* from sys/param.h:  secondary block size */
 131 #else   /* BSIZE */
 132 #define SYS_BLOCK 512   /* default if no BSIZE in param.h */
 133 #endif  /* BSIZE */
 134 
 135 #define NBLOCK  20
 136 #define NAMSIZ  100
 137 #define PRESIZ  155
 138 #define MAXNAM  256
 139 #define MODEMASK 0777777        /* file creation mode mask */
 140 #define POSIXMODES 07777        /* mask for POSIX mode bits */
 141 #define MAXEXT  9       /* reasonable max # extents for a file */
 142 #define EXTMIN  50      /* min blks left on floppy to split a file */
 143 
 144 /* max value dblock.dbuf.efsize can store */
 145 #define TAR_EFSIZE_MAX   0777777777
 146 


 458 static void seekdisk(blkcnt_t blocks);
 459 static void setPathTimes(int dirfd, char *path, timestruc_t modTime);
 460 static void setbytes_to_skip(struct stat *st, int err);
 461 static void splitfile(char *longname, int ifd, char *name,
 462         char *prefix, int filetype);
 463 static void tomodes(struct stat *sp);
 464 static void usage(void);
 465 static int xblocks(int issysattr, off_t bytes, int ofile);
 466 static int xsfile(int issysattr, int ofd);
 467 static void resugname(int dirfd, char *name, int symflag);
 468 static int bcheck(char *bstr);
 469 static int checkdir(char *name);
 470 static int checksum(union hblock *dblockp);
 471 #ifdef  EUC
 472 static int checksum_signed(union hblock *dblockp);
 473 #endif  /* EUC */
 474 static int checkupdate(char *arg);
 475 static int checkw(char c, char *name);
 476 static int cmp(char *b, char *s, int n);
 477 static int defset(char *arch);
 478 static boolean_t endtape(void);
 479 static int is_in_table(file_list_t *table[], char *str);
 480 static int notsame(void);
 481 static int is_prefix(char *s1, char *s2);
 482 static int response(void);
 483 static int build_dblock(const char *, const char *, const char,
 484         const int filetype, const struct stat *, const dev_t, const char *);
 485 static unsigned int hash(char *str);
 486 
 487 static blkcnt_t kcheck(char *kstr);
 488 static off_t bsrch(char *s, int n, off_t l, off_t h);
 489 static void onintr(int sig);
 490 static void onquit(int sig);
 491 static void onhup(int sig);
 492 static uid_t getuidbyname(char *);
 493 static gid_t getgidbyname(char *);
 494 static char *getname(gid_t);
 495 static char *getgroup(gid_t);
 496 static int checkf(char *name, int mode, int howmuch);
 497 static int writetbuf(char *buffer, int n);
 498 static int wantit(char *argv[], char **namep, char **dirp, char **comp,


 534 
 535 static void get_parent(char *path, char *dir);
 536 static char *get_component(char *path);
 537 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr,
 538     char *name, int oflag, mode_t mode);
 539 static char *skipslashes(char *string, char *start);
 540 static void chop_endslashes(char *path);
 541 static pid_t compress_file(void);
 542 static void compress_back(void);
 543 static void decompress_file(void);
 544 static pid_t uncompress_file(void);
 545 static void *compress_malloc(size_t);
 546 static void check_compression(void);
 547 static char *bz_suffix(void);
 548 static char *gz_suffix(void);
 549 static char *xz_suffix(void);
 550 static char *add_suffix();
 551 static void wait_pid(pid_t);
 552 static void verify_compress_opt(const char *t);
 553 static void detect_compress(void);
 554 static void dlog(const char *, ...);
 555 static boolean_t should_enable_debug(void);
 556 
 557 static  struct stat stbuf;
 558 
 559 static  char    *myname;
 560 static  char    *xtract_chdir = NULL;
 561 static  int     checkflag = 0;
 562 static  int     Xflag, Fflag, iflag, hflag, Bflag, Iflag;
 563 static  int     rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag;
 564 static  int     uflag;
 565 static  int     errflag;
 566 static  int     oflag;
 567 static  int     bflag, Aflag;
 568 static  int     Pflag;                  /* POSIX conformant archive */
 569 static  int     Eflag;                  /* Allow files greater than 8GB */
 570 static  int     atflag;                 /* traverse extended attributes */
 571 static  int     saflag;                 /* traverse extended sys attributes */
 572 static  int     Dflag;                  /* Data change flag */
 573 static  int     jflag;                  /* flag to use 'bzip2' */
 574 static  int     zflag;                  /* flag to use 'gzip' */
 575 static  int     Zflag;                  /* flag to use 'compress' */


 611 
 612 static  FILE    *tfile;
 613 static  FILE    *vfile = stdout;
 614 static  char    *tmpdir;
 615 static  char    *tmp_suffix = "/tarXXXXXX";
 616 static  char    *tname;
 617 static  char    archive[] = "archive0=";
 618 static  char    *Xfile;
 619 static  char    *usefile;
 620 static  char    tfname[1024];
 621 
 622 static  int     mulvol;         /* multi-volume option selected */
 623 static  blkcnt_t        blocklim; /* number of blocks to accept per volume */
 624 static  blkcnt_t        tapepos; /* current block number to be written */
 625 static  int     NotTape;        /* true if tape is a disk */
 626 static  int     dumping;        /* true if writing a tape or other archive */
 627 static  int     extno;          /* number of extent:  starts at 1 */
 628 static  int     extotal;        /* total extents in this file */
 629 static  off_t   extsize;        /* size of current extent during extraction */
 630 static  ushort_t        Oumask = 0;     /* old umask value */
 631 static  boolean_t is_posix;     /* true if archive is POSIX-conformant */
 632 static  const   char    *magic_type = "ustar";
 633 static  size_t  xrec_size = 8 * PATH_MAX;       /* extended rec initial size */
 634 static  char    *xrec_ptr;
 635 static  off_t   xrec_offset = 0;
 636 static  int     Xhdrflag;
 637 static  int     charset_type = 0;
 638 
 639 static  u_longlong_t    xhdr_flgs;      /* Bits set determine which items */
 640                                         /*   need to be in extended header. */
 641 static  pid_t   comp_pid = 0;
 642 
 643 static boolean_t debug_output = B_FALSE;
 644 
 645 #define _X_DEVMAJOR     0x1
 646 #define _X_DEVMINOR     0x2
 647 #define _X_GID          0x4
 648 #define _X_GNAME        0x8
 649 #define _X_LINKPATH     0x10
 650 #define _X_PATH         0x20
 651 #define _X_SIZE         0x40
 652 #define _X_UID          0x80
 653 #define _X_UNAME        0x100
 654 #define _X_ATIME        0x200
 655 #define _X_CTIME        0x400
 656 #define _X_MTIME        0x800
 657 #define _X_XHDR         0x1000  /* Bit flag that determines whether 'X' */
 658                                 /* typeflag was followed by 'A' or non 'A' */
 659                                 /* typeflag. */
 660 #define _X_LAST         0x40000000
 661 
 662 #define PID_MAX_DIGITS          (10 * sizeof (pid_t) / 4)
 663 #define TIME_MAX_DIGITS         (10 * sizeof (time_t) / 4)
 664 #define LONG_MAX_DIGITS         (10 * sizeof (long) / 4)


 716 static  char            *bsuffix[] = {".bz2", ".bz", ".tbz2", ".tbz"};
 717 static  char            *xsuffix[] = {".xz"};
 718 static  char            *suffix;
 719 
 720 
 721 int
 722 main(int argc, char *argv[])
 723 {
 724         char            *cp;
 725         char            *tmpdirp;
 726         pid_t           thispid;
 727 
 728         (void) setlocale(LC_ALL, "");
 729 #if !defined(TEXT_DOMAIN)       /* Should be defined by cc -D */
 730 #define TEXT_DOMAIN "SYS_TEST"  /* Use this only if it weren't */
 731 #endif
 732         (void) textdomain(TEXT_DOMAIN);
 733         if (argc < 2)
 734                 usage();
 735 
 736         debug_output = should_enable_debug();
 737 
 738         tfile = NULL;
 739         if ((myname = strdup(argv[0])) == NULL) {
 740                 (void) fprintf(stderr, gettext(
 741                     "tar: cannot allocate program name\n"));
 742                 exit(1);
 743         }
 744 
 745         if (init_yes() < 0) {
 746                 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES),
 747                     strerror(errno));
 748                 exit(2);
 749         }
 750 
 751         /*
 752          *  For XPG4 compatibility, we must be able to accept the "--"
 753          *  argument normally recognized by getopt; it is used to delimit
 754          *  the end opt the options section, and so can only appear in
 755          *  the position of the first argument.  We simply skip it.
 756          */
 757 


1175                                             "directories to %s"), xtract_chdir);
1176                                 }
1177                         }
1178                         if (Aflag && vflag)
1179                                 (void) printf(gettext(
1180                                     "Suppressing absolute pathnames.\n"));
1181 
1182                         doxtract(argv);
1183                 } else if (tflag)
1184                         dotable(argv);
1185         }
1186         else
1187                 usage();
1188 
1189         done(Errflg);
1190 
1191         /* Not reached:  keep compiler quiet */
1192         return (1);
1193 }
1194 
1195 static boolean_t
1196 should_enable_debug(void)
1197 {
1198         const char *val;
1199         const char *truth[] = {
1200                 "true",
1201                 "1",
1202                 "yes",
1203                 "y",
1204                 "please",
1205                 NULL
1206         };
1207         unsigned int i;
1208 
1209         if ((val = getenv("DEBUG_TAR")) == NULL) {
1210                 return (B_FALSE);
1211         }
1212 
1213         for (i = 0; truth[i] != NULL; i++) {
1214                 if (strcmp(val, truth[i]) == 0) {
1215                         return (B_TRUE);
1216                 }
1217         }
1218 
1219         return (B_FALSE);
1220 }
1221 
1222 /*PRINTFLIKE1*/
1223 static void
1224 dlog(const char *format, ...)
1225 {
1226         va_list ap;
1227 
1228         if (!debug_output) {
1229                 return;
1230         }
1231 
1232         va_start(ap, format);
1233         (void) fprintf(stderr, "tar: DEBUG: ");
1234         (void) vfprintf(stderr, format, ap);
1235         va_end(ap);
1236 }
1237 
1238 static void
1239 usage(void)
1240 {
1241         (void) fprintf(stderr, gettext(
1242 #if defined(O_XATTR)
1243 #if defined(_PC_SATTR_ENABLED)
1244             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw@/[0-7]][bf][X...] "
1245 #else
1246             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw@[0-7]][bf][X...] "
1247 #endif  /* _PC_SATTR_ENABLED */
1248 #else
1249             "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPTvw[0-7]][bf][X...] "
1250 #endif  /* O_XATTR */
1251             "[j|J|z|Z] "
1252             "[blocksize] [tarfile] [size] [exclude-file...] "
1253             "{file | -I include-file | -C directory file}...\n"));
1254         done(1);
1255 }
1256 
1257 /*
1258  * dorep - do "replacements"


1452                         if (errflag)
1453                                 done(1);
1454                         else
1455                                 Errflg = 1;
1456                 }
1457 }
1458 
1459 
1460 /*
1461  * endtape - check for tape at end
1462  *
1463  *      endtape checks the entry in dblock.dbuf to see if its the
1464  *      special EOT entry.  Endtape is usually called after getdir().
1465  *
1466  *      endtape used to call backtape; it no longer does, he who
1467  *      wants it backed up must call backtape himself
1468  *      RETURNS:        0 if not EOT, tape position unaffected
1469  *                      1 if     EOT, tape position unaffected
1470  */
1471 
1472 static boolean_t
1473 endtape(void)
1474 {
1475         if (dblock.dbuf.name[0] != '\0') {
1476                 /*
1477                  * The name field is populated.
1478                  */
1479                 return (B_FALSE);
1480         }
1481 
1482         if (is_posix && dblock.dbuf.prefix[0] != '\0') {
1483                 /*
1484                  * This is a ustar/POSIX archive, and although the name
1485                  * field is empty the prefix field is not.
1486                  */
1487                 return (B_FALSE);
1488         }
1489 
1490         dlog("endtape(): found null header; EOT\n");
1491         return (B_TRUE);
1492 }
1493 
1494 /*
1495  *      getdir - get directory entry from tar tape
1496  *
1497  *      getdir reads the next tarblock off the tape and cracks
1498  *      it as a directory. The checksum must match properly.
1499  *
1500  *      If tfile is non-null getdir writes the file name and mod date
1501  *      to tfile.
1502  */
1503 
1504 static void
1505 getdir(void)
1506 {
1507         struct stat *sp;
1508 #ifdef EUC
1509         static int warn_chksum_sign = 0;
1510 #endif /* EUC */
1511 
1512 top:
1513         readtape((char *)&dblock);
1514         if (dblock.dbuf.name[0] == '\0')
1515                 return;
1516         sp = &stbuf;
1517         (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode);
1518         (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid);
1519         (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid);
1520         (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz);
1521         (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime);
1522         (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum);
1523         (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor);
1524         (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor);
1525 
1526         is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0);
1527 
1528         sp->st_mode = Gen.g_mode;
1529         if (is_posix && (sp->st_mode & S_IFMT) == 0) {
1530                 switch (dblock.dbuf.typeflag) {
1531                 case '0':
1532                 case 0:
1533                 case _XATTR_HDRTYPE:
1534                         sp->st_mode |= S_IFREG;
1535                         break;
1536                 case '1':       /* hard link */
1537                         break;
1538                 case '2':
1539                         sp->st_mode |= S_IFLNK;
1540                         break;
1541                 case '3':
1542                         sp->st_mode |= S_IFCHR;
1543                         break;
1544                 case '4':
1545                         sp->st_mode |= S_IFBLK;
1546                         break;
1547                 case '5':
1548                         sp->st_mode |= S_IFDIR;
1549                         break;
1550                 case '6':
1551                         sp->st_mode |= S_IFIFO;
1552                         break;
1553                 default:
1554                         if (convtoreg(Gen.g_filesz))
1555                                 sp->st_mode |= S_IFREG;
1556                         break;
1557                 }
1558         }
1559 
1560         if ((dblock.dbuf.typeflag == 'X') || (dblock.dbuf.typeflag == 'L')) {
1561                 Xhdrflag = 1;   /* Currently processing extended header */
1562         } else {
1563                 Xhdrflag = 0;
1564         }
1565 
1566         sp->st_uid = Gen.g_uid;
1567         sp->st_gid = Gen.g_gid;
1568         sp->st_size = Gen.g_filesz;
1569         sp->st_mtime = Gen.g_mtime;
1570         chksum = Gen.g_cksum;
1571 
1572         if (dblock.dbuf.extno != '\0') {        /* split file? */
1573                 extno = dblock.dbuf.extno;
1574                 extsize = Gen.g_filesz;
1575                 extotal = dblock.dbuf.extotal;
1576         } else {
1577                 extno = 0;      /* tell others file not split */
1578                 extsize = 0;


1646                             xattrapath[xindex + 1] == '\0' &&
1647                             xattrp->h_typeflag == '5') {
1648                                 Hiddendir = 1;
1649                                 sp->st_mode =
1650                                     (S_IFDIR | (sp->st_mode & POSIXMODES));
1651                         }
1652                         dblock.dbuf.typeflag = xattrp->h_typeflag;
1653                 }
1654         }
1655 #endif
1656 }
1657 
1658 
1659 /*
1660  *      passtape - skip over a file on the tape
1661  *
1662  *      passtape skips over the next data file on the tape.
1663  *      The tape directory entry must be in dblock.dbuf. This
1664  *      routine just eats the number of blocks computed from the
1665  *      directory size entry; the tape must be (logically) positioned
1666  *      right after the directory info.
1667  */
1668 
1669 static void
1670 passtape(void)
1671 {
1672         blkcnt_t blocks;
1673         char buf[TBLOCK];
1674 
1675         /*
1676          * Print some debugging information about the directory entry
1677          * we are skipping over:
1678          */
1679         dlog("passtape: typeflag \"%c\"\n", dblock.dbuf.typeflag);
1680         if (dblock.dbuf.name[0] != '\0') {
1681                 dlog("passtape: name \"%s\"\n", dblock.dbuf.name);
1682         }
1683         if (is_posix && dblock.dbuf.prefix[0] != '\0') {
1684                 dlog("passtape: prefix \"%s\"\n", dblock.dbuf.prefix);
1685         }
1686 
1687         /*
1688          * Types link(1), sym-link(2), char special(3), blk special(4),
1689          *  directory(5), and FIFO(6) do not have data blocks associated
1690          *  with them so just skip reading the data block.
1691          */
1692         if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' ||
1693             dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' ||
1694             dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6')
1695                 return;
1696         blocks = TBLOCKS(stbuf.st_size);
1697 
1698         dlog("passtape: block count %" FMT_blkcnt_t "\n", blocks);
1699 
1700         /* if operating on disk, seek instead of reading */
1701         if (NotTape)
1702                 seekdisk(blocks);
1703         else
1704                 while (blocks-- > 0)
1705                         readtape(buf);
1706 }
1707 
1708 #if defined(O_XATTR)
1709 static int
1710 is_sysattr(char *name)
1711 {
1712         return ((strcmp(name, VIEW_READONLY) == 0) ||
1713             (strcmp(name, VIEW_READWRITE) == 0));
1714 }
1715 #endif
1716 
1717 #if defined(O_XATTR)
1718 /*
1719  * Verify the attribute, attrname, is an attribute we want to restore.


2125 #if defined(O_XATTR)
2126                         /*
2127                          * Reset header typeflag when archiving directory, since
2128                          * build_dblock changed it on us.
2129                          */
2130                         if (filetype == XATTR_FILE) {
2131                                 dblock.dbuf.typeflag = _XATTR_HDRTYPE;
2132                         } else {
2133                                 dblock.dbuf.typeflag = '5';
2134                         }
2135 #else
2136                         dblock.dbuf.typeflag = '5';
2137 #endif
2138 
2139                         (void) sprintf(dblock.dbuf.chksum, "%07o",
2140                             checksum(&dblock));
2141 
2142                         (void) writetbuf((char *)&dblock, 1);
2143                 }
2144                 if (vflag) {
2145                         if (NotTape) {
2146                                 dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
2147                         }


2148                         if (filetype == XATTR_FILE && Hiddendir) {
2149                                 (void) fprintf(vfile,
2150                                     gettext("a %s attribute %s "),
2151                                     longname, longattrname);
2152 
2153                         } else {
2154                                 (void) fprintf(vfile, "a %s/ ", longname);
2155                         }
2156                         if (NotTape) {
2157                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2158                                     K(blocks));
2159                         } else {
2160                                 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t
2161                                     " tape blocks\n"), blocks);
2162                         }
2163                 }
2164 
2165                 /*
2166                  * If hidden dir then break now since xattrs_put() will do
2167                  * the iterating of the directory.
2168                  *
2169                  * At the moment, there can only be system attributes on
2170                  * attributes.  There can be no attributes on attributes or
2171                  * directories within the attributes hidden directory hierarchy.
2172                  */
2173                 if (filetype == XATTR_FILE)
2174                         break;
2175 
2176                 if (*shortname != '/')
2177                         (void) sprintf(newparent, "%s/%s", parent, shortname);
2178                 else
2179                         (void) sprintf(newparent, "%s", shortname);
2180 
2181                 if (tar_chdir(shortname) < 0) {
2182                         vperror(0, "%s", newparent);
2183                         goto out;


2324                         (void) close(infile);
2325                         rc = PUT_AS_LINK;
2326                         goto out;
2327                 }
2328 
2329                 tomodes(&stbuf);
2330 
2331                 /* correctly handle end of volume */
2332                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2333                         /* split if floppy has some room and file is large */
2334                         if (((blocklim - tapepos) >= EXTMIN) &&
2335                             ((blocks + 1) >= blocklim/10)) {
2336                                 splitfile(longname, infile,
2337                                     name, prefix, filetype);
2338                                 (void) close(dirfd);
2339                                 (void) close(infile);
2340                                 goto out;
2341                         }
2342                         newvol();       /* not worth it--just get new volume */
2343                 }
2344                 dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,

2345                     blocks);

2346                 if (build_dblock(name, tchar, '0', filetype,
2347                     &stbuf, stbuf.st_dev, prefix) != 0) {
2348                         goto out;
2349                 }
2350                 if (vflag) {
2351                         if (NotTape) {
2352                                 dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
2353                         }


2354                         (void) fprintf(vfile, "a %s%s%s%s ", longname,
2355                             rw_sysattr ? gettext(" system") : "",
2356                             (filetype == XATTR_FILE) ? gettext(
2357                             " attribute ") : "",
2358                             (filetype == XATTR_FILE) ?
2359                             longattrname : "");
2360                         if (NotTape)
2361                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2362                                     K(blocks));
2363                         else
2364                                 (void) fprintf(vfile,
2365                                     gettext("%" FMT_blkcnt_t " tape blocks\n"),
2366                                     blocks);
2367                 }
2368 
2369                 if (put_extra_attributes(longname, shortname, longattrname,
2370                     prefix, filetype, '0') != 0)
2371                         goto out;
2372 
2373                 /*


2417                 stbuf.st_size = (off_t)0;
2418 
2419                 if (put_link(name, longname, shortname, longattrname,
2420                     prefix, filetype, '6') == 0) {
2421                         rc = PUT_AS_LINK;
2422                         goto out;
2423                 }
2424                 tomodes(&stbuf);
2425 
2426                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2427                         if (((blocklim - tapepos) >= EXTMIN) &&
2428                             ((blocks + 1) >= blocklim/10)) {
2429                                 splitfile(longname, infile, name,
2430                                     prefix, filetype);
2431                                 (void) close(dirfd);
2432                                 (void) close(infile);
2433                                 goto out;
2434                         }
2435                         newvol();
2436                 }
2437                 dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,

2438                     blocks);

2439                 if (vflag) {
2440                         if (NotTape) {
2441                                 dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
2442 



2443                                 (void) fprintf(vfile, gettext("a %s %"
2444                                     FMT_blkcnt_t "K\n "), longname, K(blocks));
2445                         } else {
2446                                 (void) fprintf(vfile, gettext(
2447                                     "a %s %" FMT_blkcnt_t " tape blocks\n"),
2448                                     longname, blocks);
2449                         }
2450                 }
2451                 if (build_dblock(name, tchar, '6', filetype,
2452                     &stbuf, stbuf.st_dev, prefix) != 0)
2453                         goto out;
2454 
2455                 if (put_extra_attributes(longname, shortname, longattrname,
2456                     prefix, filetype, '6') != 0)
2457                         goto out;
2458 
2459                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2460                 dblock.dbuf.typeflag = '6';
2461 
2462                 (void) writetbuf((char *)&dblock, 1);
2463                 break;
2464         case S_IFCHR:
2465                 stbuf.st_size = (off_t)0;
2466                 blocks = TBLOCKS(stbuf.st_size);
2467                 if (put_link(name, longname, shortname, longattrname,
2468                     prefix, filetype, '3') == 0) {
2469                         rc = PUT_AS_LINK;
2470                         goto out;
2471                 }
2472                 tomodes(&stbuf);
2473 
2474                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2475                         if (((blocklim - tapepos) >= EXTMIN) &&
2476                             ((blocks + 1) >= blocklim/10)) {
2477                                 splitfile(longname, infile, name,
2478                                     prefix, filetype);
2479                                 (void) close(dirfd);
2480                                 goto out;
2481                         }
2482                         newvol();
2483                 }
2484                 dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,

2485                     blocks);

2486                 if (vflag) {
2487                         if (NotTape) {
2488                                 dlog("seek = %" FMT_blkcnt_t "K\t", K(tapepos));
2489 



2490                                 (void) fprintf(vfile, gettext("a %s %"
2491                                     FMT_blkcnt_t "K\n"), longname, K(blocks));
2492                         } else {
2493                                 (void) fprintf(vfile, gettext("a %s %"
2494                                     FMT_blkcnt_t " tape blocks\n"), longname,
2495                                     blocks);
2496                         }
2497                 }
2498                 if (build_dblock(name, tchar, '3',
2499                     filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2500                         goto out;
2501 
2502                 if (put_extra_attributes(longname, shortname, longattrname,
2503                     prefix, filetype, '3') != 0)
2504                         goto out;
2505 
2506                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2507                 dblock.dbuf.typeflag = '3';
2508 
2509                 (void) writetbuf((char *)&dblock, 1);
2510                 break;
2511         case S_IFBLK:
2512                 stbuf.st_size = (off_t)0;
2513                 blocks = TBLOCKS(stbuf.st_size);
2514                 if (put_link(name, longname, shortname, longattrname,
2515                     prefix, filetype, '4') == 0) {
2516                         rc = PUT_AS_LINK;
2517                         goto out;
2518                 }
2519                 tomodes(&stbuf);
2520 
2521                 while (mulvol && tapepos + blocks + 1 > blocklim) {
2522                         if (((blocklim - tapepos) >= EXTMIN) &&
2523                             ((blocks + 1) >= blocklim/10)) {
2524                                 splitfile(longname, infile,
2525                                     name, prefix, filetype);
2526                                 (void) close(dirfd);
2527                                 goto out;
2528                         }
2529                         newvol();
2530                 }
2531                 dlog("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname,

2532                     blocks);

2533                 if (vflag) {
2534                         if (NotTape) {
2535                                 dlog("seek = %" FMT_blkcnt_t "K\n", K(tapepos));
2536                         }
2537 

2538                         (void) fprintf(vfile, "a %s ", longname);
2539                         if (NotTape)
2540                                 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n",
2541                                     K(blocks));
2542                         else
2543                                 (void) fprintf(vfile, gettext("%"
2544                                     FMT_blkcnt_t " tape blocks\n"), blocks);
2545                 }
2546                 if (build_dblock(name, tchar, '4',
2547                     filetype, &stbuf, stbuf.st_rdev, prefix) != 0)
2548                         goto out;
2549 
2550                 if (put_extra_attributes(longname, shortname, longattrname,
2551                     prefix, filetype, '4') != 0)
2552                         goto out;
2553 
2554                 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock));
2555                 dblock.dbuf.typeflag = '4';
2556 
2557                 (void) writetbuf((char *)&dblock, 1);


4829             ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs)))
4830                 return (0);
4831         return (1);
4832 }
4833 
4834 
4835 /*
4836  *      newvol  get new floppy (or tape) volume
4837  *
4838  *      newvol();               resets tapepos and first to TRUE, prompts for
4839  *                              for new volume, and waits.
4840  *      if dumping, end-of-file is written onto the tape.
4841  */
4842 
4843 static void
4844 newvol(void)
4845 {
4846         int c;
4847 
4848         if (dumping) {
4849                 dlog("newvol called with 'dumping' set\n");


4850                 putempty((blkcnt_t)2);  /* 2 EOT marks */
4851                 closevol();
4852                 flushtape();
4853                 sync();
4854                 tapepos = 0;
4855         } else
4856                 first = TRUE;
4857         if (close(mt) != 0)
4858                 vperror(2, gettext("close error"));
4859         mt = 0;
4860         (void) fprintf(stderr, gettext(
4861             "tar: \007please insert new volume, then press RETURN."));
4862         (void) fseek(stdin, (off_t)0, 2);       /* scan over read-ahead */
4863         while ((c = getchar()) != '\n' && ! term)
4864                 if (c == EOF)
4865                         done(Errflg);
4866         if (term)
4867                 done(Errflg);
4868 
4869         errno = 0;
4870 
4871         if (strcmp(usefile, "-") == 0) {
4872                 mt = dup(1);
4873         } else {
4874                 mt = open(usefile, dumping ? update : 0);
4875         }
4876 
4877         if (mt < 0) {
4878                 (void) fprintf(stderr, gettext(
4879                     "tar: cannot reopen %s (%s)\n"),
4880                     dumping ? gettext("output") : gettext("input"), usefile);
4881 
4882                 dlog("update=%d, usefile=%s ", update, usefile);
4883                 dlog("mt=%d, [%s]\n", mt, strerror(errno));


4884 
4885                 done(2);
4886         }
4887 }
4888 
4889 /*
4890  * Write a trailer portion to close out the current output volume.
4891  */
4892 
4893 static void
4894 closevol(void)
4895 {
4896         if (mulvol) {
4897                 /*
4898                  * blocklim does not count the 2 EOT marks;
4899                  * tapepos  does count the 2 EOT marks;
4900                  * therefore we need the +2 below.
4901                  */
4902                 putempty(blocklim + (blkcnt_t)2 - tapepos);
4903         }


5048  *      called by passtape() only
5049  *
5050  *      WARNING: expects "nblock" to be set, that is, readtape() to have
5051  *              already been called.  Since passtape() is only called
5052  *              after a file header block has been read (why else would
5053  *              we skip to next file?), this is currently safe.
5054  *
5055  *      changed to guarantee SYS_BLOCK boundary
5056  */
5057 
5058 static void
5059 seekdisk(blkcnt_t blocks)
5060 {
5061         off_t seekval;
5062 #if SYS_BLOCK > TBLOCK
5063         /* handle non-multiple of SYS_BLOCK */
5064         blkcnt_t nxb;   /* # extra blocks */
5065 #endif
5066 
5067         tapepos += blocks;
5068         dlog("seekdisk(%" FMT_blkcnt_t ") called\n", blocks);


5069         if (recno + blocks <= nblock) {
5070                 recno += blocks;
5071                 return;
5072         }
5073         if (recno > nblock)
5074                 recno = nblock;
5075         seekval = (off_t)blocks - (nblock - recno);
5076         recno = nblock; /* so readtape() reads next time through */
5077 #if SYS_BLOCK > TBLOCK
5078         nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK));
5079         dlog("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n",

5080             nxb, seekval);

5081         if (nxb && nxb > seekval) /* don't seek--we'll read */
5082                 goto noseek;
5083         seekval -=  nxb;        /* don't seek quite so far */
5084 #endif
5085         if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) {
5086                 (void) fprintf(stderr, gettext(
5087                     "tar: device seek error\n"));
5088                 done(3);
5089         }
5090 #if SYS_BLOCK > TBLOCK
5091         /* read those extra blocks */
5092 noseek:
5093         if (nxb) {
5094                 dlog("reading extra blocks\n", 0, 0);


5095                 if (read(mt, tbuf, TBLOCK*nblock) < 0) {
5096                         (void) fprintf(stderr, gettext(
5097                             "tar: read error while skipping file\n"));
5098                         done(8);
5099                 }
5100                 recno = nxb;    /* so we don't read in next readtape() */
5101         }
5102 #endif
5103 }
5104 
5105 static void
5106 readtape(char *buffer)
5107 {
5108         int i, j;
5109 
5110         ++tapepos;
5111         if (recno >= nblock || first) {
5112                 if (first) {
5113                         /*
5114                          * set the number of blocks to read initially, based on


5246 
5247 /*
5248  *      backtape - reposition tape after reading soft "EOF" record
5249  *
5250  *      Backtape tries to reposition the tape back over the EOF
5251  *      record.  This is for the 'u' and 'r' function letters so that the
5252  *      tape can be extended.  This code is not well designed, but
5253  *      I'm confident that the only callers who care about the
5254  *      backspace-over-EOF feature are those involved in 'u' and 'r'.
5255  *
5256  *      The proper way to backup the tape is through the use of mtio.
5257  *      Earlier spins used lseek combined with reads in a confusing
5258  *      maneuver that only worked on 4.x, but shouldn't have, even
5259  *      there.  Lseeks are explicitly not supported for tape devices.
5260  */
5261 
5262 static void
5263 backtape(void)
5264 {
5265         struct mtop mtcmd;
5266         dlog("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno,

5267             nblock);

5268         /*
5269          * Backup to the position in the archive where the record
5270          * currently sitting in the tbuf buffer is situated.
5271          */
5272 
5273         if (NotTape) {
5274                 /*
5275                  * For non-tape devices, this means lseeking to the
5276                  * correct position.  The absolute location tapepos-recno
5277                  * should be the beginning of the current record.
5278                  */
5279 
5280                 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) ==
5281                     (off_t)-1) {
5282                         (void) fprintf(stderr,
5283                             gettext("tar: lseek to end of archive failed\n"));
5284                         done(4);
5285                 }
5286         } else {
5287                 /*


5305          */
5306 
5307         recno--;
5308         tapepos--;
5309 }
5310 
5311 
5312 /*
5313  *      flushtape  write buffered block(s) onto tape
5314  *
5315  *      recno points to next free block in tbuf.  If nonzero, a write is done.
5316  *      Care is taken to write in multiples of SYS_BLOCK when device is
5317  *      non-magtape in case raw i/o is used.
5318  *
5319  *      NOTE: this is called by writetape() to do the actual writing
5320  */
5321 
5322 static void
5323 flushtape(void)
5324 {
5325         dlog("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno);


5326         if (recno > 0) {     /* anything buffered? */
5327                 if (NotTape) {
5328 #if SYS_BLOCK > TBLOCK
5329                         int i;
5330 
5331                         /*
5332                          * an odd-block write can only happen when
5333                          * we are at the end of a volume that is not a tape.
5334                          * Here we round recno up to an even SYS_BLOCK
5335                          * boundary.
5336                          */
5337                         if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) {
5338                                 dlog("flushtape() %d rounding blocks\n", i);


5339                                 recno += i;     /* round up to even SYS_BLOCK */
5340                         }
5341 #endif
5342                         if (recno > nblock)
5343                                 recno = nblock;
5344                 }
5345                 dlog("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t

5346                     " bytes\n", (blkcnt_t)(NotTape ? recno : nblock),
5347                     (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK);

5348                 if (write(mt, tbuf,
5349                     (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) {
5350                         (void) fprintf(stderr, gettext(
5351                             "tar: tape write error\n"));
5352                         done(2);
5353                 }
5354                 recno = 0;
5355         }
5356 }
5357 
5358 static void
5359 copy(void *dst, void *src)
5360 {
5361         (void) memcpy(dst, src, TBLOCK);
5362 }
5363 
5364 /*
5365  * kcheck()
5366  *      - checks the validity of size values for non-tape devices
5367  *      - if size is zero, mulvol tar is disabled and size is


5457         }
5458         if ((bp = strtok(NULL, " \t")) == NULL) {
5459                 (void) fprintf(stderr, gettext(
5460                     "tar: block component missing in '%s' entry in %s.\n"),
5461                     arch, DEF_FILE);
5462                 return (FALSE);
5463         }
5464         nblock = bcheck(bp);
5465         if ((bp = strtok(NULL, " \t")) == NULL) {
5466                 (void) fprintf(stderr, gettext(
5467                     "tar: size component missing in '%s' entry in %s.\n"),
5468                     arch, DEF_FILE);
5469                 return (FALSE);
5470         }
5471         blocklim = kcheck(bp);
5472         if ((bp = strtok(NULL, " \t")) != NULL)
5473                 NotTape = (*bp == 'n' || *bp == 'N');
5474         else
5475                 NotTape = (blocklim != 0);
5476         (void) defopen(NULL);
5477         dlog("defset: archive='%s'; usefile='%s'\n", arch, usefile);
5478         dlog("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n",

5479             nblock, blocklim);
5480         dlog("defset: not tape = %d\n", NotTape);

5481         return (TRUE);
5482 }
5483 
5484 
5485 /*
5486  * Following code handles excluded and included files.
5487  * A hash table of file names to be {in,ex}cluded is built.
5488  * For excluded files, before writing or extracting a file
5489  * check to see if it is in the exclude_tbl.
5490  * For included files, the wantit() procedure will check to
5491  * see if the named file is in the include_tbl.
5492  */
5493 
5494 static void
5495 build_table(file_list_t *table[], char *file)
5496 {
5497         FILE    *fp;
5498         char    buf[PATH_MAX + 1];
5499 
5500         if ((fp = fopen(file, "r")) == (FILE *)NULL)


5771                 if (!tflag &&
5772                     ((!atflag && !saflag) ||
5773                     (atflag && !saflag && ((ainfo->attr_parent != NULL) ||
5774                     ainfo->attr_rw_sysattr)) ||
5775                     (!atflag && saflag && ((ainfo->attr_parent != NULL) ||
5776                     !ainfo->attr_rw_sysattr)))) {
5777                         passtape();
5778                         return (0);
5779                 }
5780         }
5781 #endif
5782 
5783         /* sets *namep to point at the proper name */
5784         if (check_prefix(namep, dirp, component) != 0) {
5785                 passtape();
5786                 return (0);
5787         }
5788 
5789         if (endtape()) {
5790                 if (Bflag) {
5791                         ssize_t sz;
5792                         size_t extra_blocks = 0;
5793 
5794                         /*
5795                          * Logically at EOT - consume any extra blocks
5796                          * so that write to our stdin won't fail and
5797                          * emit an error message; otherwise something
5798                          * like "dd if=foo.tar | (cd bar; tar xvf -)"
5799                          * will produce a bogus error message from "dd".
5800                          */
5801 
5802                         while ((sz = read(mt, tbuf, TBLOCK*nblock)) > 0) {
5803                                 extra_blocks += sz;
5804                         }
5805                         dlog("wantit(): %d bytes of extra blocks\n",
5806                             extra_blocks);
5807                 }
5808                 dlog("wantit(): at end of tape.\n");
5809                 return (-1);
5810         }
5811 
5812         gotit = 0;
5813 
5814         if ((Iflag && is_in_table(include_tbl, *namep)) ||
5815             (! Iflag && *argv == NULL)) {
5816                 gotit = 1;
5817         } else {
5818                 for (cp = argv; *cp; cp++) {
5819                         if (is_prefix(*cp, *namep)) {
5820                                 gotit = 1;
5821                                 break;
5822                         }
5823                 }
5824         }
5825 
5826         if (! gotit) {
5827                 passtape();
5828                 return (0);


8041                         if (filetype != XATTR_FILE) {
8042                                 tomodes(&stbuf);
8043                                 if (chk_path_build(name, longname, lp->pathname,
8044                                     prefix, type, filetype) > 0) {
8045                                         goto out;
8046                                 }
8047                         }
8048 
8049                         if (mulvol && tapepos + 1 >= blocklim)
8050                                 newvol();
8051                         (void) writetbuf((char *)&dblock, 1);
8052                         /*
8053                          * write_ancillary() is not needed here.
8054                          * The first link is handled in the following
8055                          * else statement. No need to process ACLs
8056                          * for other hard links since they are the
8057                          * same file.
8058                          */
8059 
8060                         if (vflag) {

8061                                 if (NotTape)
8062                                         dlog("seek = %" FMT_blkcnt_t
8063                                             "K\n", K(tapepos));

8064                                 if (filetype == XATTR_FILE) {
8065                                         (void) fprintf(vfile, gettext(
8066                                             "a %s attribute %s link to "
8067                                             "%s attribute %s\n"),
8068                                             name, component, name,
8069                                             lp->attrname);
8070                                 } else {
8071                                         (void) fprintf(vfile, gettext(
8072                                             "a %s link to %s\n"),
8073                                             longname, lp->pathname);
8074                                 }
8075                         }
8076                         lp->count--;
8077                         return (0);
8078                 } else {
8079                         lp = (struct linkbuf *)getmem(sizeof (*lp));
8080                         if (lp != (struct linkbuf *)NULL) {
8081                                 lp->nextp = ihead;
8082                                 ihead = lp;
8083                                 lp->inum = stbuf.st_ino;