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;
|