1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 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 #pragma ident "%Z%%M% %I% %E% SMI" 39 40 #include <unistd.h> 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <sys/stat.h> 44 #include <sys/mkdev.h> 45 #include <sys/wait.h> 46 #include <dirent.h> 47 #include <errno.h> 48 #include <stdio.h> 49 #include <signal.h> 50 #include <ctype.h> 51 #include <locale.h> 52 #include <nl_types.h> 53 #include <langinfo.h> 54 #include <pwd.h> 55 #include <grp.h> 56 #include <fcntl.h> 57 #include <string.h> 58 #include <malloc.h> 59 #include <time.h> 60 #include <utime.h> 61 #include <stdlib.h> 62 #include <stdarg.h> 63 #include <widec.h> 64 #include <sys/mtio.h> 65 #include <libintl.h> 66 #include <sys/acl.h> 67 #include <strings.h> 68 #include <deflt.h> 69 #include <limits.h> 70 #include <iconv.h> 71 #include <assert.h> 72 #include <aclutils.h> 73 #if defined(__SunOS_5_6) || defined(__SunOS_5_7) 74 extern int defcntl(); 75 #endif 76 #include <archives.h> 77 78 /* 79 * Source compatibility 80 */ 81 82 /* 83 * These constants come from archives.h and sys/fcntl.h 84 * and were introduced by the extended attributes project 85 * in Solaris 9. 86 */ 87 #if !defined(O_XATTR) 88 #define AT_SYMLINK_NOFOLLOW 0x1000 89 #define AT_REMOVEDIR 0x1 90 #define AT_FDCWD 0xffd19553 91 #define _XATTR_HDRTYPE 'E' 92 static int attropen(); 93 static int fstatat(); 94 static int renameat(); 95 static int unlinkat(); 96 static int openat(); 97 static int fchownat(); 98 static int futimesat(); 99 #endif 100 101 /* 102 * Compiling with -D_XPG4_2 gets this but produces other problems, so 103 * instead of including sys/time.h and compiling with -D_XPG4_2, I'm 104 * explicitly doing the declaration here. 105 */ 106 int utimes(const char *path, const struct timeval timeval_ptr[]); 107 108 #ifndef MINSIZE 109 #define MINSIZE 250 110 #endif 111 #define DEF_FILE "/etc/default/tar" 112 113 #define min(a, b) ((a) < (b) ? (a) : (b)) 114 #define max(a, b) ((a) > (b) ? (a) : (b)) 115 116 /* -DDEBUG ONLY for debugging */ 117 #ifdef DEBUG 118 #undef DEBUG 119 #define DEBUG(a, b, c)\ 120 (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c) 121 #endif 122 123 #define TBLOCK 512 /* tape block size--should be universal */ 124 125 #ifdef BSIZE 126 #define SYS_BLOCK BSIZE /* from sys/param.h: secondary block size */ 127 #else /* BSIZE */ 128 #define SYS_BLOCK 512 /* default if no BSIZE in param.h */ 129 #endif /* BSIZE */ 130 131 #define NBLOCK 20 132 #define NAMSIZ 100 133 #define PRESIZ 155 134 #define MAXNAM 256 135 #define MODEMASK 0777777 /* file creation mode mask */ 136 #define POSIXMODES 07777 /* mask for POSIX mode bits */ 137 #define MAXEXT 9 /* reasonable max # extents for a file */ 138 #define EXTMIN 50 /* min blks left on floppy to split a file */ 139 140 /* max value dblock.dbuf.efsize can store */ 141 #define TAR_EFSIZE_MAX 0777777777 142 143 /* 144 * Symbols which specify the values at which the use of the 'E' function 145 * modifier is required to properly store a file. 146 * 147 * TAR_OFFSET_MAX - the largest file size we can archive 148 * OCTAL7CHAR - the limit for ustar gid, uid, dev 149 */ 150 151 #ifdef XHDR_DEBUG 152 /* tiny values which force the creation of extended header entries */ 153 #define TAR_OFFSET_MAX 9 154 #define OCTAL7CHAR 2 155 #else 156 /* normal values */ 157 #define TAR_OFFSET_MAX 077777777777ULL 158 #define OCTAL7CHAR 07777777 159 #endif 160 161 #define TBLOCKS(bytes) (((bytes) + TBLOCK - 1) / TBLOCK) 162 #define K(tblocks) ((tblocks+1)/2) /* tblocks to Kbytes for printing */ 163 164 #define MAXLEV (PATH_MAX / 2) 165 #define LEV0 1 166 #define SYMLINK_LEV0 0 167 168 #define TRUE 1 169 #define FALSE 0 170 171 #define XATTR_FILE 1 172 #define NORMAL_FILE 0 173 174 #define PUT_AS_LINK 1 175 #define PUT_NOTAS_LINK 0 176 177 #if _FILE_OFFSET_BITS == 64 178 #define FMT_off_t "lld" 179 #define FMT_off_t_o "llo" 180 #define FMT_blkcnt_t "lld" 181 #else 182 #define FMT_off_t "ld" 183 #define FMT_off_t_o "lo" 184 #define FMT_blkcnt_t "ld" 185 #endif 186 187 /* ACL support */ 188 189 static 190 struct sec_attr { 191 char attr_type; 192 char attr_len[7]; 193 char attr_info[1]; 194 } *attr; 195 196 #define ACL_HDR 'A' 197 198 /* 199 * 200 * Tar has been changed to support extended attributes. 201 * 202 * As part of this change tar now uses the new *at() syscalls 203 * such as openat, fchownat(), unlinkat()... 204 * 205 * This was done so that attributes can be handled with as few code changes 206 * as possible. 207 * 208 * What this means is that tar now opens the directory that a file or directory 209 * resides in and then performs *at() functions to manipulate the entry. 210 * 211 * For example a new file is now created like this: 212 * 213 * dfd = open(<some dir path>) 214 * fd = openat(dfd, <name>,....); 215 * 216 * or in the case of an extended attribute 217 * 218 * dfd = attropen(<pathname>, ".", ....) 219 * 220 * Once we have a directory file descriptor all of the *at() functions can 221 * be applied to it. 222 * 223 * unlinkat(dfd, <component name>,...) 224 * fchownat(dfd, <component name>,..) 225 * 226 * This works for both normal namespace files and extended attribute file 227 * 228 */ 229 230 /* 231 * 232 * Extended attribute Format 233 * 234 * Extended attributes are stored in two pieces. 235 * 1. An attribute header which has information about 236 * what file the attribute is for and what the attribute 237 * is named. 238 * 2. The attribute record itself. Stored as a normal file type 239 * of entry. 240 * Both the header and attribute record have special modes/typeflags 241 * associated with them. 242 * 243 * The names of the header in the archive look like: 244 * /dev/null/attr.hdr 245 * 246 * The name of the attribute looks like: 247 * /dev/null/attr 248 * 249 * This is done so that an archiver that doesn't understand these formats 250 * can just dispose of the attribute records. 251 * 252 * The format is composed of a fixed size header followed 253 * by a variable sized xattr_buf. If the attribute is a hard link 254 * to another attribute then another xattr_buf section is included 255 * for the link. 256 * 257 * The xattr_buf is used to define the necessary "pathing" steps 258 * to get to the extended attribute. This is necessary to support 259 * a fully recursive attribute model where an attribute may itself 260 * have an attribute. 261 * 262 * The basic layout looks like this. 263 * 264 * -------------------------------- 265 * | | 266 * | xattr_hdr | 267 * | | 268 * -------------------------------- 269 * -------------------------------- 270 * | | 271 * | xattr_buf | 272 * | | 273 * -------------------------------- 274 * -------------------------------- 275 * | | 276 * | (optional link info) | 277 * | | 278 * -------------------------------- 279 * -------------------------------- 280 * | | 281 * | attribute itself | 282 * | stored as normal tar | 283 * | or cpio data with | 284 * | special mode or | 285 * | typeflag | 286 * | | 287 * -------------------------------- 288 * 289 */ 290 291 /* 292 * xattrhead is a pointer to the xattr_hdr 293 * 294 * xattrp is a pointer to the xattr_buf structure 295 * which contains the "pathing" steps to get to attributes 296 * 297 * xattr_linkp is a pointer to another xattr_buf structure that is 298 * only used when an attribute is actually linked to another attribute 299 * 300 */ 301 302 static struct xattr_hdr *xattrhead; 303 static struct xattr_buf *xattrp; 304 static struct xattr_buf *xattr_linkp; /* pointer to link info, if any */ 305 static char *xattraname; /* attribute name */ 306 static char *xattr_linkaname; /* attribute attribute is linked to */ 307 static char Hiddendir; /* are we processing hidden xattr dir */ 308 static char xattrbadhead; 309 310 /* Was statically allocated tbuf[NBLOCK] */ 311 static 312 union hblock { 313 char dummy[TBLOCK]; 314 struct header { 315 char name[NAMSIZ]; /* If non-null prefix, path is */ 316 /* <prefix>/<name>; otherwise */ 317 /* <name> */ 318 char mode[8]; 319 char uid[8]; 320 char gid[8]; 321 char size[12]; /* size of this extent if file split */ 322 char mtime[12]; 323 char chksum[8]; 324 char typeflag; 325 char linkname[NAMSIZ]; 326 char magic[6]; 327 char version[2]; 328 char uname[32]; 329 char gname[32]; 330 char devmajor[8]; 331 char devminor[8]; 332 char prefix[PRESIZ]; /* Together with "name", the path of */ 333 /* the file: <prefix>/<name> */ 334 char extno; /* extent #, null if not split */ 335 char extotal; /* total extents */ 336 char efsize[10]; /* size of entire file */ 337 } dbuf; 338 } dblock, *tbuf, xhdr_buf; 339 340 static 341 struct xtar_hdr { 342 uid_t x_uid, /* Uid of file */ 343 x_gid; /* Gid of file */ 344 major_t x_devmajor; /* Device major node */ 345 minor_t x_devminor; /* Device minor node */ 346 off_t x_filesz; /* Length of file */ 347 char *x_uname, /* Pointer to name of user */ 348 *x_gname, /* Pointer to gid of user */ 349 *x_linkpath, /* Path for a hard/symbolic link */ 350 *x_path; /* Path of file */ 351 timestruc_t x_mtime; /* Seconds and nanoseconds */ 352 } Xtarhdr; 353 354 static 355 struct gen_hdr { 356 ulong_t g_mode; /* Mode of file */ 357 uid_t g_uid, /* Uid of file */ 358 g_gid; /* Gid of file */ 359 off_t g_filesz; /* Length of file */ 360 time_t g_mtime; /* Modification time */ 361 uint_t g_cksum; /* Checksum of file */ 362 ulong_t g_devmajor, /* File system of file */ 363 g_devminor; /* Major/minor of special files */ 364 } Gen; 365 366 static 367 struct linkbuf { 368 ino_t inum; 369 dev_t devnum; 370 int count; 371 char pathname[MAXNAM+1]; /* added 1 for last NULL */ 372 char attrname[MAXNAM+1]; 373 struct linkbuf *nextp; 374 } *ihead; 375 376 /* see comments before build_table() */ 377 #define TABLE_SIZE 512 378 struct file_list { 379 char *name; /* Name of file to {in,ex}clude */ 380 struct file_list *next; /* Linked list */ 381 }; 382 static struct file_list *exclude_tbl[TABLE_SIZE], 383 *include_tbl[TABLE_SIZE]; 384 385 static int append_secattr(char **, int *, acl_t *); 386 static void write_ancillary(union hblock *, char *, int, char); 387 388 static void add_file_to_table(struct file_list *table[], char *str); 389 static void assert_string(char *s, char *msg); 390 static int istape(int fd, int type); 391 static void backtape(void); 392 static void build_table(struct file_list *table[], char *file); 393 static void check_prefix(char **namep, char **dirp, char **compp); 394 static void closevol(void); 395 static void copy(void *dst, void *src); 396 static int convtoreg(off_t); 397 static void delete_target(int fd, char *namep); 398 static void doDirTimes(char *name, timestruc_t modTime); 399 static void done(int n); 400 static void dorep(char *argv[]); 401 #ifdef _iBCS2 402 static void dotable(char *argv[], int cnt); 403 static void doxtract(char *argv[], int cnt); 404 #else 405 static void dotable(char *argv[]); 406 static void doxtract(char *argv[]); 407 #endif 408 static void fatal(char *format, ...); 409 static void vperror(int exit_status, char *fmt, ...); 410 static void flushtape(void); 411 static void getdir(void); 412 static void *getmem(size_t); 413 static void longt(struct stat *st, char aclchar); 414 static int makeDir(char *name); 415 static void mterr(char *operation, int i, int exitcode); 416 static void newvol(void); 417 static void passtape(void); 418 static void putempty(blkcnt_t n); 419 static int putfile(char *longname, char *shortname, char *parent, 420 int filetype, int lev, int symlink_lev); 421 static void readtape(char *buffer); 422 static void seekdisk(blkcnt_t blocks); 423 static void setPathTimes(int dirfd, char *path, timestruc_t modTime); 424 static void splitfile(char *longname, int ifd, char *name, 425 char *prefix, int filetype); 426 static void tomodes(struct stat *sp); 427 static void usage(void); 428 static void xblocks(off_t bytes, int ofile); 429 static void xsfile(int ofd); 430 static void resugname(int dirfd, char *name, int symflag); 431 static int bcheck(char *bstr); 432 static int checkdir(char *name); 433 static int checksum(union hblock *dblockp); 434 #ifdef EUC 435 static int checksum_signed(union hblock *dblockp); 436 #endif /* EUC */ 437 static int checkupdate(char *arg); 438 static int checkw(char c, char *name); 439 static int cmp(char *b, char *s, int n); 440 static int defset(char *arch); 441 static int endtape(void); 442 static int is_in_table(struct file_list *table[], char *str); 443 static int notsame(void); 444 static int is_prefix(char *s1, char *s2); 445 static int response(void); 446 static int build_dblock(const char *, const char *, const char, 447 const int filetype, const struct stat *, const dev_t, const char *); 448 static wchar_t yesnoresponse(void); 449 static unsigned int hash(char *str); 450 451 #ifdef _iBCS2 452 static void initarg(char *argv[], char *file); 453 static char *nextarg(); 454 #endif 455 static blkcnt_t kcheck(char *kstr); 456 static off_t bsrch(char *s, int n, off_t l, off_t h); 457 static void onintr(int sig); 458 static void onquit(int sig); 459 static void onhup(int sig); 460 static uid_t getuidbyname(char *); 461 static gid_t getgidbyname(char *); 462 static char *getname(gid_t); 463 static char *getgroup(gid_t); 464 static int checkf(char *name, int mode, int howmuch); 465 static int writetbuf(char *buffer, int n); 466 static int wantit(char *argv[], char **namep, char **dirp, char **comp); 467 468 static int get_xdata(void); 469 static void gen_num(const char *keyword, const u_longlong_t number); 470 static void gen_date(const char *keyword, const timestruc_t time_value); 471 static void gen_string(const char *keyword, const char *value); 472 static void get_xtime(char *value, timestruc_t *xtime); 473 static int chk_path_build(char *name, char *longname, char *linkname, 474 char *prefix, char type, int filetype); 475 static int gen_utf8_names(const char *filename); 476 static int utf8_local(char *option, char **Xhdr_ptrptr, char *target, 477 const char *src, int max_val); 478 static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src, 479 iconv_t iconv_cd, int xhdrflg, int max_val); 480 static int c_utf8(char *target, const char *source); 481 static int getstat(int dirfd, char *longname, char *shortname); 482 static void xattrs_put(char *, char *, char *); 483 static void prepare_xattr(char **, char *, char *, 484 char, struct linkbuf *, int *); 485 static int put_link(char *name, char *longname, char *component, char *prefix, 486 int filetype, char typeflag); 487 static int put_extra_attributes(char *longname, char *shortname, 488 char *prefix, int filetype, char typeflag); 489 static int put_xattr_hdr(char *longname, char *shortname, char *prefix, 490 int typeflag, int filetype, struct linkbuf *lp); 491 static int read_xattr_hdr(); 492 static void get_parent(char *path, char *dir); 493 static char *get_component(char *path); 494 static int retry_attrdir_open(char *name); 495 static char *skipslashes(char *string, char *start); 496 static void chop_endslashes(char *path); 497 498 static struct stat stbuf; 499 500 static int checkflag = 0; 501 #ifdef _iBCS2 502 static int Fileflag; 503 char *sysv3_env; 504 #endif 505 static int Xflag, Fflag, iflag, hflag, Bflag, Iflag; 506 static int rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag; 507 static int uflag; 508 static int eflag, errflag, qflag; 509 static int oflag; 510 static int bflag, kflag, Aflag; 511 static int Pflag; /* POSIX conformant archive */ 512 static int Eflag; /* Allow files greater than 8GB */ 513 static int atflag; /* traverse extended attributes */ 514 static int Dflag; /* Data change flag */ 515 static int term, chksum, wflag, 516 first = TRUE, defaults_used = FALSE, linkerrok; 517 static blkcnt_t recno; 518 static int freemem = 1; 519 static int nblock = NBLOCK; 520 static int Errflg = 0; 521 static int exitflag = 0; 522 523 static dev_t mt_dev; /* device containing output file */ 524 static ino_t mt_ino; /* inode number of output file */ 525 static int mt_devtype; /* dev type of archive, from stat structure */ 526 527 static int update = 1; /* for `open' call */ 528 529 static off_t low; 530 static off_t high; 531 532 static FILE *tfile; 533 static FILE *vfile = stdout; 534 static char tname[] = "/tmp/tarXXXXXX"; 535 static char archive[] = "archive0="; 536 static char *Xfile; 537 static char *usefile; 538 static char *Filefile; 539 540 static int mulvol; /* multi-volume option selected */ 541 static blkcnt_t blocklim; /* number of blocks to accept per volume */ 542 static blkcnt_t tapepos; /* current block number to be written */ 543 static int NotTape; /* true if tape is a disk */ 544 static int dumping; /* true if writing a tape or other archive */ 545 static int extno; /* number of extent: starts at 1 */ 546 static int extotal; /* total extents in this file */ 547 static off_t extsize; /* size of current extent during extraction */ 548 static ushort_t Oumask = 0; /* old umask value */ 549 static int is_posix; /* true if archive we're reading is POSIX-conformant */ 550 static const char *magic_type = "ustar"; 551 static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */ 552 static char *xrec_ptr; 553 static off_t xrec_offset = 0; 554 static int Xhdrflag; 555 static int charset_type = 0; 556 557 static u_longlong_t xhdr_flgs; /* Bits set determine which items */ 558 /* need to be in extended header. */ 559 #define _X_DEVMAJOR 0x1 560 #define _X_DEVMINOR 0x2 561 #define _X_GID 0x4 562 #define _X_GNAME 0x8 563 #define _X_LINKPATH 0x10 564 #define _X_PATH 0x20 565 #define _X_SIZE 0x40 566 #define _X_UID 0x80 567 #define _X_UNAME 0x100 568 #define _X_ATIME 0x200 569 #define _X_CTIME 0x400 570 #define _X_MTIME 0x800 571 #define _X_LAST 0x40000000 572 573 #define PID_MAX_DIGITS (10 * sizeof (pid_t) / 4) 574 #define TIME_MAX_DIGITS (10 * sizeof (time_t) / 4) 575 #define LONG_MAX_DIGITS (10 * sizeof (long) / 4) 576 #define ULONGLONG_MAX_DIGITS (10 * sizeof (u_longlong_t) / 4) 577 /* 578 * UTF_8 encoding requires more space than the current codeset equivalent. 579 * Currently a factor of 2-3 would suffice, but it is possible for a factor 580 * of 6 to be needed in the future, so for saftey, we use that here. 581 */ 582 #define UTF_8_FACTOR 6 583 584 static u_longlong_t xhdr_count = 0; 585 static char xhdr_dirname[PRESIZ + 1]; 586 static char pidchars[PID_MAX_DIGITS + 1]; 587 static char *tchar = ""; /* null linkpath */ 588 589 static char local_path[UTF_8_FACTOR * PATH_MAX + 1]; 590 static char local_linkpath[UTF_8_FACTOR * PATH_MAX + 1]; 591 static char local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 592 static char local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 593 594 /* 595 * The following mechanism is provided to allow us to debug tar in complicated 596 * situations, like when it is part of a pipe. The idea is that you compile 597 * with -DWAITAROUND defined, and then add the 'z' function modifier to the 598 * target tar invocation, eg. "tar czf tarfile file". If stderr is available, 599 * it will tell you to which pid to attach the debugger; otherwise, use ps to 600 * find it. Attach to the process from the debugger, and, *PRESTO*, you are 601 * there! 602 * 603 * Simply assign "waitaround = 0" once you attach to the process, and then 604 * proceed from there as usual. 605 */ 606 607 #ifdef WAITAROUND 608 int waitaround = 0; /* wait for rendezvous with the debugger */ 609 #endif 610 611 612 int 613 main(int argc, char *argv[]) 614 { 615 char *cp; 616 char *tmpdirp; 617 pid_t thispid; 618 619 #ifdef _iBCS2 620 int tbl_cnt = 0; 621 sysv3_env = getenv("SYSV3"); 622 #endif 623 (void) setlocale(LC_ALL, ""); 624 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 625 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 626 #endif 627 (void) textdomain(TEXT_DOMAIN); 628 if (argc < 2) 629 usage(); 630 631 tfile = NULL; 632 633 /* 634 * For XPG4 compatibility, we must be able to accept the "--" 635 * argument normally recognized by getopt; it is used to delimit 636 * the end opt the options section, and so can only appear in 637 * the position of the first argument. We simply skip it. 638 */ 639 640 if (strcmp(argv[1], "--") == 0) { 641 argv++; 642 argc--; 643 if (argc < 3) 644 usage(); 645 } 646 647 argv[argc] = NULL; 648 argv++; 649 650 /* 651 * Set up default values. 652 * Search the operand string looking for the first digit or an 'f'. 653 * If you find a digit, use the 'archive#' entry in DEF_FILE. 654 * If 'f' is given, bypass looking in DEF_FILE altogether. 655 * If no digit or 'f' is given, still look in DEF_FILE but use '0'. 656 */ 657 if ((usefile = getenv("TAPE")) == (char *)NULL) { 658 for (cp = *argv; *cp; ++cp) 659 if (isdigit(*cp) || *cp == 'f') 660 break; 661 if (*cp != 'f') { 662 archive[7] = (*cp)? *cp: '0'; 663 if (!(defaults_used = defset(archive))) { 664 usefile = NULL; 665 nblock = 1; 666 blocklim = 0; 667 NotTape = 0; 668 } 669 } 670 } 671 672 for (cp = *argv++; *cp; cp++) 673 switch (*cp) { 674 #ifdef WAITAROUND 675 case 'z': 676 /* rendezvous with the debugger */ 677 waitaround = 1; 678 break; 679 #endif 680 case 'f': 681 assert_string(*argv, gettext( 682 "tar: tarfile must be specified with 'f' " 683 "function modifier\n")); 684 usefile = *argv++; 685 break; 686 case 'F': 687 #ifdef _iBCS2 688 if (sysv3_env) { 689 assert_string(*argv, gettext( 690 "tar: 'F' requires a file name\n")); 691 Filefile = *argv++; 692 Fileflag++; 693 } else 694 #endif /* _iBCS2 */ 695 Fflag++; 696 break; 697 case 'c': 698 cflag++; 699 rflag++; 700 update = 1; 701 break; 702 #if defined(O_XATTR) 703 case '@': 704 atflag++; 705 break; 706 #endif 707 case 'u': 708 uflag++; /* moved code after signals caught */ 709 rflag++; 710 update = 2; 711 break; 712 case 'r': 713 rflag++; 714 update = 2; 715 break; 716 case 'v': 717 vflag++; 718 break; 719 case 'w': 720 wflag++; 721 break; 722 case 'x': 723 xflag++; 724 break; 725 case 'X': 726 assert_string(*argv, gettext( 727 "tar: exclude file must be specified with 'X' " 728 "function modifier\n")); 729 Xflag = 1; 730 Xfile = *argv++; 731 build_table(exclude_tbl, Xfile); 732 break; 733 case 't': 734 tflag++; 735 break; 736 case 'm': 737 mflag++; 738 break; 739 case 'p': 740 pflag++; 741 break; 742 case 'D': 743 Dflag++; 744 break; 745 case '-': 746 /* ignore this silently */ 747 break; 748 case '0': /* numeric entries used only for defaults */ 749 case '1': 750 case '2': 751 case '3': 752 case '4': 753 case '5': 754 case '6': 755 case '7': 756 break; 757 case 'b': 758 assert_string(*argv, gettext( 759 "tar: blocking factor must be specified " 760 "with 'b' function modifier\n")); 761 bflag++; 762 nblock = bcheck(*argv++); 763 break; 764 case 'q': 765 qflag++; 766 break; 767 case 'k': 768 assert_string(*argv, gettext( 769 "tar: size value must be specified with 'k' " 770 "function modifier\n")); 771 kflag++; 772 blocklim = kcheck(*argv++); 773 break; 774 case 'n': /* not a magtape (instead of 'k') */ 775 NotTape++; /* assume non-magtape */ 776 break; 777 case 'l': 778 linkerrok++; 779 break; 780 case 'e': 781 #ifdef _iBCS2 782 /* If sysv3 IS set, don't be as verbose */ 783 if (!sysv3_env) 784 #endif /* _iBCS2 */ 785 errflag++; 786 eflag++; 787 break; 788 case 'o': 789 oflag++; 790 break; 791 case 'h': 792 hflag++; 793 break; 794 case 'i': 795 iflag++; 796 break; 797 case 'B': 798 Bflag++; 799 break; 800 case 'P': 801 Pflag++; 802 break; 803 case 'E': 804 Eflag++; 805 Pflag++; /* Only POSIX archive made */ 806 break; 807 default: 808 (void) fprintf(stderr, gettext( 809 "tar: %c: unknown function modifier\n"), *cp); 810 usage(); 811 } 812 813 #ifdef _iBCS2 814 if (Xflag && Fileflag) { 815 (void) fprintf(stderr, gettext( 816 "tar: specify only one of X or F.\n")); 817 usage(); 818 } 819 #endif /* _iBCS2 */ 820 821 if (!rflag && !xflag && !tflag) 822 usage(); 823 if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) { 824 (void) fprintf(stderr, gettext( 825 "tar: specify only one of [ctxru].\n")); 826 usage(); 827 } 828 if (cflag && *argv == NULL && Filefile == NULL) 829 fatal(gettext("Missing filenames")); 830 if (usefile == NULL) 831 fatal(gettext("device argument required")); 832 833 /* alloc a buffer of the right size */ 834 if ((tbuf = (union hblock *) 835 calloc(sizeof (union hblock) * nblock, sizeof (char))) == 836 (union hblock *)NULL) { 837 (void) fprintf(stderr, gettext( 838 "tar: cannot allocate physio buffer\n")); 839 exit(1); 840 } 841 842 if ((xrec_ptr = malloc(xrec_size)) == NULL) { 843 (void) fprintf(stderr, gettext( 844 "tar: cannot allocate extended header buffer\n")); 845 exit(1); 846 } 847 848 #ifdef WAITAROUND 849 if (waitaround) { 850 (void) fprintf(stderr, gettext("Rendezvous with tar on pid" 851 " %d\n"), getpid()); 852 853 while (waitaround) { 854 (void) sleep(10); 855 } 856 } 857 #endif 858 859 thispid = getpid(); 860 (void) sprintf(pidchars, "%ld", thispid); 861 thispid = strlen(pidchars); 862 863 if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL) 864 (void) strcpy(xhdr_dirname, "/tmp"); 865 else { 866 /* 867 * Make sure that dir is no longer than what can 868 * fit in the prefix part of the header. 869 */ 870 if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) { 871 (void) strcpy(xhdr_dirname, "/tmp"); 872 if ((vflag > 0) && (Eflag > 0)) 873 (void) fprintf(stderr, gettext( 874 "Ignoring TMPDIR\n")); 875 } else 876 (void) strcpy(xhdr_dirname, tmpdirp); 877 } 878 (void) strcat(xhdr_dirname, "/PaxHeaders."); 879 (void) strcat(xhdr_dirname, pidchars); 880 881 if (rflag) { 882 if (cflag && tfile != NULL) 883 usage(); 884 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 885 (void) signal(SIGINT, onintr); 886 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 887 (void) signal(SIGHUP, onhup); 888 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 889 (void) signal(SIGQUIT, onquit); 890 if (uflag) { 891 int tnum; 892 if ((tnum = mkstemp(tname)) == -1) 893 vperror(1, "%s", tname); 894 if ((tfile = fdopen(tnum, "w")) == NULL) 895 vperror(1, "%s", tname); 896 } 897 if (strcmp(usefile, "-") == 0) { 898 if (cflag == 0) 899 fatal(gettext( 900 "can only create standard output archives.")); 901 vfile = stderr; 902 mt = dup(1); 903 ++bflag; 904 } else { 905 if (cflag) 906 mt = open(usefile, 907 O_RDWR|O_CREAT|O_TRUNC, 0666); 908 else 909 mt = open(usefile, O_RDWR); 910 911 if (mt < 0) { 912 if (cflag == 0 || (mt = creat(usefile, 0666)) 913 < 0) 914 vperror(1, "%s", usefile); 915 } 916 } 917 /* Get inode and device number of output file */ 918 (void) fstat(mt, &stbuf); 919 mt_ino = stbuf.st_ino; 920 mt_dev = stbuf.st_dev; 921 mt_devtype = stbuf.st_mode & S_IFMT; 922 NotTape = !istape(mt, mt_devtype); 923 924 if (rflag && !cflag && (mt_devtype == S_IFIFO)) 925 fatal(gettext("cannot append to pipe or FIFO.")); 926 927 if (Aflag && vflag) 928 (void) printf( 929 gettext("Suppressing absolute pathnames\n")); 930 dorep(argv); 931 } else if (xflag || tflag) { 932 /* 933 * for each argument, check to see if there is a "-I file" pair. 934 * if so, move the 3rd argument into "-I"'s place, build_table() 935 * using "file"'s name and increment argc one (the second 936 * increment appears in the for loop) which removes the two 937 * args "-I" and "file" from the argument vector. 938 */ 939 for (argc = 0; argv[argc]; argc++) { 940 if (strcmp(argv[argc], "-I") == 0) { 941 if (!argv[argc+1]) { 942 (void) fprintf(stderr, gettext( 943 "tar: missing argument for -I flag\n")); 944 done(2); 945 } else { 946 Iflag = 1; 947 argv[argc] = argv[argc+2]; 948 build_table(include_tbl, argv[++argc]); 949 #ifdef _iBCS2 950 if (Fileflag) { 951 (void) fprintf(stderr, gettext( 952 "tar: only one of I or F.\n")); 953 usage(); 954 } 955 #endif /* _iBCS2 */ 956 957 } 958 } 959 } 960 if (strcmp(usefile, "-") == 0) { 961 mt = dup(0); 962 ++bflag; 963 /* try to recover from short reads when reading stdin */ 964 ++Bflag; 965 } else if ((mt = open(usefile, 0)) < 0) 966 vperror(1, "%s", usefile); 967 968 if (xflag) { 969 if (Aflag && vflag) 970 (void) printf(gettext 971 ("Suppressing absolute pathnames.\n")); 972 973 #ifdef _iBCS2 974 doxtract(argv, tbl_cnt); 975 #else 976 doxtract(argv); 977 #endif 978 } else if (tflag) 979 980 #ifdef _iBCS2 981 dotable(argv, tbl_cnt); 982 #else 983 dotable(argv); 984 #endif 985 } 986 else 987 usage(); 988 989 done(Errflg); 990 991 /* Not reached: keep compiler quiet */ 992 return (1); 993 } 994 995 static void 996 usage(void) 997 { 998 999 #ifdef _iBCS2 1000 if (sysv3_env) { 1001 (void) fprintf(stderr, gettext( 1002 #if defined(O_XATTR) 1003 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqvw@[0-7]][bfFk][X...] " 1004 #else 1005 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqvw[0-7]][bfFk][X...] " 1006 #endif 1007 "[blocksize] [tarfile] [filename] [size] [exclude-file...] " 1008 "{file | -I include-file | -C directory file}...\n")); 1009 } else 1010 #endif /* _iBCS2 */ 1011 { 1012 (void) fprintf(stderr, gettext( 1013 #if defined(O_XATTR) 1014 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqvw@[0-7]][bfk][X...] " 1015 #else 1016 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqvw[0-7]][bfk][X...] " 1017 #endif 1018 "[blocksize] [tarfile] [size] [exclude-file...] " 1019 "{file | -I include-file | -C directory file}...\n")); 1020 } 1021 done(1); 1022 } 1023 1024 /* 1025 * dorep - do "replacements" 1026 * 1027 * Dorep is responsible for creating ('c'), appending ('r') 1028 * and updating ('u'); 1029 */ 1030 1031 static void 1032 dorep(char *argv[]) 1033 { 1034 char *cp, *cp2, *p; 1035 char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent; 1036 char file[PATH_MAX*2], origdir[PATH_MAX+1]; 1037 FILE *fp = (FILE *)NULL; 1038 FILE *ff = (FILE *)NULL; 1039 int archtype; 1040 1041 1042 if (!cflag) { 1043 xhdr_flgs = 0; 1044 getdir(); /* read header for next file */ 1045 if (Xhdrflag > 0) { 1046 if (!Eflag) 1047 fatal(gettext("Archive contains extended" 1048 " header. -E flag required.\n")); 1049 (void) get_xdata(); /* Get extended header items */ 1050 /* and regular header */ 1051 } else { 1052 if (Eflag) 1053 fatal(gettext("Archive contains no extended" 1054 " header. -E flag not allowed.\n")); 1055 } 1056 while (!endtape()) { /* changed from a do while */ 1057 passtape(); /* skip the file data */ 1058 if (term) 1059 done(Errflg); /* received signal to stop */ 1060 xhdr_flgs = 0; 1061 getdir(); 1062 if (Xhdrflag > 0) 1063 (void) get_xdata(); 1064 } 1065 backtape(); /* was called by endtape */ 1066 if (tfile != NULL) { 1067 char buf[200]; 1068 1069 (void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 " 1070 "!= prev {print; prev=$1}' %s >%sX;mv %sX %s", 1071 tname, tname, tname, tname, tname, tname); 1072 (void) fflush(tfile); 1073 (void) system(buf); 1074 (void) freopen(tname, "r", tfile); 1075 (void) fstat(fileno(tfile), &stbuf); 1076 high = stbuf.st_size; 1077 } 1078 } 1079 1080 dumping = 1; 1081 if (mulvol) { /* SP-1 */ 1082 if (nblock && (blocklim%nblock) != 0) 1083 fatal(gettext( 1084 "Volume size not a multiple of block size.")); 1085 blocklim -= 2; /* for trailer records */ 1086 if (vflag) 1087 (void) fprintf(vfile, gettext("Volume ends at %" 1088 FMT_blkcnt_t "K, blocking factor = %dK\n"), 1089 K((blocklim - 1)), K(nblock)); 1090 } 1091 1092 #ifdef _iBCS2 1093 if (Fileflag) { 1094 if (Filefile != NULL) { 1095 if ((ff = fopen(Filefile, "r")) == NULL) 1096 vperror(0, "%s", Filefile); 1097 } else { 1098 (void) fprintf(stderr, gettext( 1099 "tar: F requires a file name.\n")); 1100 usage(); 1101 } 1102 } 1103 #endif /* _iBCS2 */ 1104 1105 /* 1106 * Save the original directory before it gets 1107 * changed. 1108 */ 1109 if (getcwd(origdir, (PATH_MAX+1)) == NULL) { 1110 vperror(0, gettext("A parent directory cannot be read")); 1111 exit(1); 1112 } 1113 1114 (void) strcpy(wdir, origdir); 1115 1116 while ((*argv || fp || ff) && !term) { 1117 if (fp || (strcmp(*argv, "-I") == 0)) { 1118 #ifdef _iBCS2 1119 if (Fileflag) { 1120 (void) fprintf(stderr, gettext( 1121 "tar: only one of I or F.\n")); 1122 usage(); 1123 } 1124 #endif /* _iBCS2 */ 1125 if (fp == NULL) { 1126 if (*++argv == NULL) 1127 fatal(gettext( 1128 "missing file name for -I flag.")); 1129 else if ((fp = fopen(*argv++, "r")) == NULL) 1130 vperror(0, "%s", argv[-1]); 1131 continue; 1132 } else if ((fgets(file, PATH_MAX-1, fp)) == NULL) { 1133 (void) fclose(fp); 1134 fp = NULL; 1135 continue; 1136 } else { 1137 cp = cp2 = file; 1138 if ((p = strchr(cp2, '\n'))) 1139 *p = 0; 1140 } 1141 } else if ((strcmp(*argv, "-C") == 0) && argv[1]) { 1142 #ifdef _iBCS2 1143 if (Fileflag) { 1144 (void) fprintf(stderr, gettext( 1145 "tar: only one of F or C\n")); 1146 usage(); 1147 } 1148 #endif /* _iBCS2 */ 1149 1150 if (chdir(*++argv) < 0) 1151 vperror(0, gettext( 1152 "can't change directories to %s"), *argv); 1153 else 1154 (void) getcwd(wdir, (sizeof (wdir))); 1155 argv++; 1156 continue; 1157 #ifdef _iBCS2 1158 } else if (Fileflag && (ff != NULL)) { 1159 if ((fgets(file, PATH_MAX-1, ff)) == NULL) { 1160 (void) fclose(ff); 1161 ff = NULL; 1162 continue; 1163 } else { 1164 cp = cp2 = file; 1165 if (p = strchr(cp2, '\n')) 1166 *p = 0; 1167 } 1168 #endif /* _iBCS2 */ 1169 } else 1170 cp = cp2 = strcpy(file, *argv++); 1171 1172 /* 1173 * point cp2 to the last '/' in file, but not 1174 * to a trailing '/' 1175 */ 1176 for (; *cp; cp++) { 1177 if (*cp == '/') { 1178 while (*(cp+1) == '/') { 1179 ++cp; 1180 } 1181 if (*(cp+1) != '\0') { 1182 /* not trailing slash */ 1183 cp2 = cp; 1184 } 1185 } 1186 } 1187 if (cp2 != file) { 1188 *cp2 = '\0'; 1189 if (chdir(file) < 0) { 1190 vperror(0, gettext( 1191 "can't change directories to %s"), file); 1192 continue; 1193 } 1194 *cp2 = '/'; 1195 cp2++; 1196 } 1197 1198 parent = getcwd(tempdir, (sizeof (tempdir))); 1199 archtype = putfile(file, cp2, parent, NORMAL_FILE, 1200 LEV0, SYMLINK_LEV0); 1201 1202 #if defined(O_XATTR) 1203 if (!exitflag) { 1204 if (atflag && archtype == PUT_NOTAS_LINK) { 1205 xattrs_put(file, cp2, parent); 1206 } 1207 } 1208 #endif 1209 1210 if (chdir(origdir) < 0) 1211 vperror(0, gettext("cannot change back?: %s"), origdir); 1212 1213 if (exitflag) { 1214 /* 1215 * If e function modifier has been specified 1216 * write the files (that are listed before the 1217 * file causing the error) to tape. exitflag is 1218 * used because only some of the error conditions 1219 * in putfile() recognize the e function modifier. 1220 */ 1221 break; 1222 } 1223 } 1224 1225 putempty((blkcnt_t)2); 1226 flushtape(); 1227 closevol(); /* SP-1 */ 1228 if (linkerrok == 1) 1229 for (; ihead != NULL; ihead = ihead->nextp) { 1230 if (ihead->count == 0) 1231 continue; 1232 (void) fprintf(stderr, gettext( 1233 "tar: missing links to %s\n"), ihead->pathname); 1234 if (errflag) 1235 done(1); 1236 else 1237 Errflg = 1; 1238 } 1239 } 1240 1241 1242 /* 1243 * endtape - check for tape at end 1244 * 1245 * endtape checks the entry in dblock.dbuf to see if its the 1246 * special EOT entry. Endtape is usually called after getdir(). 1247 * 1248 * endtape used to call backtape; it no longer does, he who 1249 * wants it backed up must call backtape himself 1250 * RETURNS: 0 if not EOT, tape position unaffected 1251 * 1 if EOT, tape position unaffected 1252 */ 1253 1254 static int 1255 endtape(void) 1256 { 1257 if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */ 1258 return (1); 1259 } else 1260 return (0); 1261 } 1262 1263 /* 1264 * getdir - get directory entry from tar tape 1265 * 1266 * getdir reads the next tarblock off the tape and cracks 1267 * it as a directory. The checksum must match properly. 1268 * 1269 * If tfile is non-null getdir writes the file name and mod date 1270 * to tfile. 1271 */ 1272 1273 static void 1274 getdir(void) 1275 { 1276 struct stat *sp; 1277 #ifdef EUC 1278 static int warn_chksum_sign = 0; 1279 #endif /* EUC */ 1280 1281 top: 1282 readtape((char *)&dblock); 1283 if (dblock.dbuf.name[0] == '\0') 1284 return; 1285 sp = &stbuf; 1286 (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode); 1287 (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid); 1288 (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid); 1289 (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz); 1290 (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime); 1291 (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum); 1292 (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor); 1293 (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor); 1294 1295 is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0); 1296 1297 sp->st_mode = Gen.g_mode; 1298 if (is_posix && (sp->st_mode & S_IFMT) == 0) 1299 switch (dblock.dbuf.typeflag) { 1300 case '0': case 0: case _XATTR_HDRTYPE: 1301 sp->st_mode |= S_IFREG; 1302 break; 1303 case '1': /* hard link */ 1304 break; 1305 case '2': 1306 sp->st_mode |= S_IFLNK; 1307 break; 1308 case '3': 1309 sp->st_mode |= S_IFCHR; 1310 break; 1311 case '4': 1312 sp->st_mode |= S_IFBLK; 1313 break; 1314 case '5': 1315 sp->st_mode |= S_IFDIR; 1316 break; 1317 case '6': 1318 sp->st_mode |= S_IFIFO; 1319 break; 1320 default: 1321 if (convtoreg(Gen.g_filesz)) 1322 sp->st_mode |= S_IFREG; 1323 break; 1324 } 1325 1326 if (dblock.dbuf.typeflag == 'X') 1327 Xhdrflag = 1; /* Currently processing extended header */ 1328 else 1329 Xhdrflag = 0; 1330 1331 sp->st_uid = Gen.g_uid; 1332 sp->st_gid = Gen.g_gid; 1333 sp->st_size = Gen.g_filesz; 1334 sp->st_mtime = Gen.g_mtime; 1335 chksum = Gen.g_cksum; 1336 1337 if (dblock.dbuf.extno != '\0') { /* split file? */ 1338 extno = dblock.dbuf.extno; 1339 extsize = Gen.g_filesz; 1340 extotal = dblock.dbuf.extotal; 1341 } else { 1342 extno = 0; /* tell others file not split */ 1343 extsize = 0; 1344 extotal = 0; 1345 } 1346 1347 #ifdef EUC 1348 if (chksum != checksum(&dblock)) { 1349 if (chksum != checksum_signed(&dblock)) { 1350 (void) fprintf(stderr, gettext( 1351 "tar: directory checksum error\n")); 1352 if (iflag) 1353 goto top; 1354 done(2); 1355 } else { 1356 if (! warn_chksum_sign) { 1357 warn_chksum_sign = 1; 1358 (void) fprintf(stderr, gettext( 1359 "tar: warning: tar file made with signed checksum\n")); 1360 } 1361 } 1362 } 1363 #else 1364 if (chksum != checksum(&dblock)) { 1365 (void) fprintf(stderr, gettext( 1366 "tar: directory checksum error\n")); 1367 if (iflag) 1368 goto top; 1369 done(2); 1370 } 1371 #endif /* EUC */ 1372 if (tfile != NULL && Xhdrflag == 0) { 1373 /* 1374 * If an extended header is present, then time is available 1375 * in nanoseconds in the extended header data, so set it. 1376 * Otherwise, give an invalid value so that checkupdate will 1377 * not test beyond seconds. 1378 */ 1379 if ((xhdr_flgs & _X_MTIME)) 1380 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 1381 else 1382 sp->st_mtim.tv_nsec = -1; 1383 1384 if (xhdr_flgs & _X_PATH) 1385 (void) fprintf(tfile, "%s %10ld.%9.9ld\n", 1386 Xtarhdr.x_path, sp->st_mtim.tv_sec, 1387 sp->st_mtim.tv_nsec); 1388 else 1389 (void) fprintf(tfile, "%.*s %10ld.%9.9ld\n", 1390 NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec, 1391 sp->st_mtim.tv_nsec); 1392 } 1393 1394 #if defined(O_XATTR) 1395 Hiddendir = 0; 1396 if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) { 1397 if (xattrbadhead) { 1398 free(xattrhead); 1399 xattrp = NULL; 1400 xattr_linkp = NULL; 1401 xattrhead = NULL; 1402 } else { 1403 if (xattraname[0] == '.' && xattraname[1] == '\0' && 1404 xattrp->h_typeflag == '5') { 1405 Hiddendir = 1; 1406 sp->st_mode = 1407 (S_IFDIR | (sp->st_mode & S_IAMB)); 1408 } 1409 dblock.dbuf.typeflag = xattrp->h_typeflag; 1410 } 1411 } 1412 #endif 1413 } 1414 1415 1416 /* 1417 * passtape - skip over a file on the tape 1418 * 1419 * passtape skips over the next data file on the tape. 1420 * The tape directory entry must be in dblock.dbuf. This 1421 * routine just eats the number of blocks computed from the 1422 * directory size entry; the tape must be (logically) positioned 1423 * right after thee directory info. 1424 */ 1425 1426 static void 1427 passtape(void) 1428 { 1429 blkcnt_t blocks; 1430 char buf[TBLOCK]; 1431 1432 /* 1433 * Types link(1), sym-link(2), char special(3), blk special(4), 1434 * directory(5), and FIFO(6) do not have data blocks associated 1435 * with them so just skip reading the data block. 1436 */ 1437 if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' || 1438 dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' || 1439 dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6') 1440 return; 1441 blocks = TBLOCKS(stbuf.st_size); 1442 1443 /* if operating on disk, seek instead of reading */ 1444 if (NotTape) 1445 seekdisk(blocks); 1446 else 1447 while (blocks-- > 0) 1448 readtape(buf); 1449 } 1450 1451 1452 static int 1453 putfile(char *longname, char *shortname, char *parent, 1454 int filetype, int lev, int symlink_lev) 1455 { 1456 int infile = -1; /* deliberately invalid */ 1457 blkcnt_t blocks; 1458 char buf[PATH_MAX + 2]; /* Add trailing slash and null */ 1459 char *bigbuf; 1460 int maxread; 1461 int hint; /* amount to write to get "in sync" */ 1462 char filetmp[PATH_MAX + 1]; 1463 char *cp; 1464 char *name; 1465 struct dirent *dp; 1466 DIR *dirp; 1467 int i; 1468 long l; 1469 int split; 1470 int dirfd = -1; 1471 int rc = PUT_NOTAS_LINK; 1472 int archtype = 0; 1473 char newparent[PATH_MAX + MAXNAMLEN + 1]; 1474 char *prefix = ""; 1475 char *tmpbuf; 1476 char goodbuf[PRESIZ + 2]; 1477 char junkbuf[MAXNAM+1]; 1478 char *lastslash; 1479 int j; 1480 struct stat sbuf; 1481 int readlink_max; 1482 1483 (void) memset(goodbuf, '\0', sizeof (goodbuf)); 1484 (void) memset(junkbuf, '\0', sizeof (junkbuf)); 1485 1486 xhdr_flgs = 0; 1487 1488 if (filetype == XATTR_FILE) { 1489 dirfd = attropen(get_component(longname), ".", O_RDONLY); 1490 } else { 1491 dirfd = open(".", O_RDONLY); 1492 } 1493 1494 if (dirfd == -1) { 1495 (void) fprintf(stderr, gettext( 1496 "tar: unable to open%sdirectory %s\n"), 1497 (filetype == XATTR_FILE) ? gettext(" attribute ") : " ", 1498 (filetype == XATTR_FILE) ? longname : parent); 1499 goto out; 1500 } 1501 1502 if (filetype == XATTR_FILE) { 1503 if (fchdir(dirfd) < 0) { 1504 (void) fprintf(stderr, gettext( 1505 "tar: unable to fchdir into attribute directory" 1506 " of file %s\n"), longname); 1507 goto out; 1508 } 1509 } 1510 1511 if (lev > MAXLEV) { 1512 (void) fprintf(stderr, 1513 gettext("tar: directory nesting too deep, %s not dumped\n"), 1514 longname); 1515 goto out; 1516 } 1517 1518 if (getstat(dirfd, longname, shortname)) 1519 goto out; 1520 1521 if (hflag) { 1522 /* 1523 * Catch nesting where a file is a symlink to its directory. 1524 */ 1525 j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW); 1526 if (S_ISLNK(sbuf.st_mode)) { 1527 if (symlink_lev++ >= MAXSYMLINKS) { 1528 (void) fprintf(stderr, gettext( 1529 "tar: %s: Number of symbolic links " 1530 "encountered during path name traversal " 1531 "exceeds MAXSYMLINKS\n"), longname); 1532 Errflg = 1; 1533 goto out; 1534 } 1535 } 1536 } 1537 1538 /* 1539 * Check if the input file is the same as the tar file we 1540 * are creating 1541 */ 1542 if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) { 1543 (void) fprintf(stderr, gettext( 1544 "tar: %s same as archive file\n"), longname); 1545 Errflg = 1; 1546 goto out; 1547 } 1548 /* 1549 * Check size limit - we can't archive files that 1550 * exceed TAR_OFFSET_MAX bytes because of header 1551 * limitations. Exclude file types that set 1552 * st_size to zero below because they take no 1553 * archive space to represent contents. 1554 */ 1555 if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) && 1556 !S_ISDIR(stbuf.st_mode) && 1557 !S_ISCHR(stbuf.st_mode) && 1558 !S_ISBLK(stbuf.st_mode) && 1559 (Eflag == 0)) { 1560 (void) fprintf(stderr, gettext( 1561 "tar: %s too large to archive. " 1562 "Use E function modifier.\n"), longname); 1563 if (errflag) 1564 exitflag = 1; 1565 Errflg = 1; 1566 goto out; 1567 } 1568 1569 if (tfile != NULL && checkupdate(longname) == 0) { 1570 goto out; 1571 } 1572 if (checkw('r', longname) == 0) { 1573 goto out; 1574 } 1575 1576 if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 1577 goto out; 1578 1579 if (Xflag) { 1580 if (is_in_table(exclude_tbl, longname)) { 1581 if (vflag) { 1582 (void) fprintf(vfile, gettext( 1583 "a %s excluded\n"), longname); 1584 } 1585 goto out; 1586 } 1587 } 1588 1589 /* 1590 * If the length of the fullname is greater than MAXNAM, 1591 * print out a message and return (unless extended headers are used, 1592 * in which case fullname is limited to PATH_MAX). 1593 */ 1594 1595 if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) || 1596 (split > PATH_MAX)) { 1597 (void) fprintf(stderr, gettext( 1598 "tar: %s: file name too long\n"), longname); 1599 if (errflag) 1600 exitflag = 1; 1601 Errflg = 1; 1602 goto out; 1603 } 1604 1605 /* 1606 * We split the fullname into prefix and name components if any one 1607 * of three conditions holds: 1608 * -- the length of the fullname exceeds NAMSIZ, 1609 * -- the length of the fullname equals NAMSIZ, and the shortname 1610 * is less than NAMSIZ, (splitting in this case preserves 1611 * compatibility with 5.6 and 5.5.1 tar), or 1612 * -- the length of the fullname equals NAMSIZ, the file is a 1613 * directory and we are not in POSIX-conformant mode (where 1614 * trailing slashes are removed from directories). 1615 */ 1616 if ((split > NAMSIZ) || 1617 (split == NAMSIZ && strlen(shortname) < NAMSIZ) || 1618 (split == NAMSIZ && (stbuf.st_mode & S_IFDIR) && !Pflag)) { 1619 /* 1620 * Since path is limited to PRESIZ characters, look for the 1621 * last slash within PRESIZ + 1 characters only. 1622 */ 1623 (void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1)); 1624 tmpbuf = goodbuf; 1625 lastslash = strrchr(tmpbuf, '/'); 1626 if (lastslash == NULL) { 1627 i = split; /* Length of name */ 1628 j = 0; /* Length of prefix */ 1629 goodbuf[0] = '\0'; 1630 } else { 1631 *lastslash = '\0'; /* Terminate the prefix */ 1632 j = strlen(tmpbuf); 1633 i = split - j - 1; 1634 } 1635 /* 1636 * If the filename is greater than NAMSIZ we can't 1637 * archive the file unless we are using extended headers. 1638 */ 1639 if ((i > NAMSIZ) || (i == NAMSIZ && (stbuf.st_mode & S_IFDIR) && 1640 !Pflag)) { 1641 /* Determine which (filename or path) is too long. */ 1642 lastslash = strrchr(longname, '/'); 1643 if (lastslash != NULL) 1644 i = strlen(lastslash + 1); 1645 if (Eflag > 0) { 1646 xhdr_flgs |= _X_PATH; 1647 Xtarhdr.x_path = longname; 1648 if (i <= NAMSIZ) 1649 (void) strcpy(junkbuf, lastslash + 1); 1650 else 1651 (void) sprintf(junkbuf, "%llu", 1652 xhdr_count + 1); 1653 if (split - i - 1 > PRESIZ) 1654 (void) strcpy(goodbuf, xhdr_dirname); 1655 } else { 1656 if ((i > NAMSIZ) || (i == NAMSIZ && 1657 (stbuf.st_mode & S_IFDIR) && !Pflag)) 1658 (void) fprintf(stderr, gettext( 1659 "tar: %s: filename is greater than " 1660 "%d\n"), lastslash == NULL ? 1661 longname : lastslash + 1, NAMSIZ); 1662 else 1663 (void) fprintf(stderr, gettext( 1664 "tar: %s: prefix is greater than %d" 1665 "\n"), longname, PRESIZ); 1666 if (errflag) 1667 exitflag = 1; 1668 Errflg = 1; 1669 goto out; 1670 } 1671 } else 1672 (void) strncpy(&junkbuf[0], longname + j + 1, 1673 strlen(longname + j + 1)); 1674 name = junkbuf; 1675 prefix = goodbuf; 1676 } else { 1677 name = longname; 1678 } 1679 if (Aflag) { 1680 if ((prefix != NULL) && (*prefix != '\0')) 1681 while (*prefix == '/') 1682 ++prefix; 1683 else 1684 while (*name == '/') 1685 ++name; 1686 } 1687 1688 switch (stbuf.st_mode & S_IFMT) { 1689 case S_IFDIR: 1690 stbuf.st_size = (off_t)0; 1691 blocks = TBLOCKS(stbuf.st_size); 1692 1693 if (filetype != XATTR_FILE && Hiddendir == 0) { 1694 i = 0; 1695 cp = buf; 1696 while ((*cp++ = longname[i++])) 1697 ; 1698 *--cp = '/'; 1699 *++cp = 0; 1700 } 1701 if (!oflag) { 1702 tomodes(&stbuf); 1703 if (build_dblock(name, tchar, '5', filetype, 1704 &stbuf, stbuf.st_dev, prefix) != 0) { 1705 goto out; 1706 } 1707 if (!Pflag) { 1708 /* 1709 * Old archives require a slash at the end 1710 * of a directory name. 1711 * 1712 * XXX 1713 * If directory name is too long, will 1714 * slash overfill field? 1715 */ 1716 if (strlen(name) > (unsigned)NAMSIZ-1) { 1717 (void) fprintf(stderr, gettext( 1718 "tar: %s: filename is greater " 1719 "than %d\n"), name, NAMSIZ); 1720 if (errflag) 1721 exitflag = 1; 1722 Errflg = 1; 1723 goto out; 1724 } else { 1725 if (strlen(name) == (NAMSIZ - 1)) { 1726 (void) memcpy(dblock.dbuf.name, 1727 name, NAMSIZ); 1728 dblock.dbuf.name[NAMSIZ-1] 1729 = '/'; 1730 } else 1731 (void) sprintf(dblock.dbuf.name, 1732 "%s/", name); 1733 1734 /* 1735 * need to recalculate checksum 1736 * because the name changed. 1737 */ 1738 (void) sprintf(dblock.dbuf.chksum, 1739 "%07o", checksum(&dblock)); 1740 } 1741 } 1742 1743 if (put_extra_attributes(longname, shortname, prefix, 1744 filetype, '5') != 0) 1745 goto out; 1746 1747 #if defined(O_XATTR) 1748 /* 1749 * Reset header typeflag when archiving directory, since 1750 * build_dblock changed it on us. 1751 */ 1752 if (filetype == XATTR_FILE) { 1753 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 1754 } else { 1755 dblock.dbuf.typeflag = '5'; 1756 } 1757 #else 1758 dblock.dbuf.typeflag = '5'; 1759 #endif 1760 1761 (void) sprintf(dblock.dbuf.chksum, "%07o", 1762 checksum(&dblock)); 1763 1764 (void) writetbuf((char *)&dblock, 1); 1765 } 1766 if (vflag) { 1767 #ifdef DEBUG 1768 if (NotTape) 1769 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 1770 0); 1771 #endif 1772 if (filetype == XATTR_FILE && Hiddendir) { 1773 (void) fprintf(vfile, "a %s attribute . ", 1774 longname); 1775 1776 } else { 1777 (void) fprintf(vfile, "a %s/ ", longname); 1778 } 1779 if (NotTape) 1780 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 1781 K(blocks)); 1782 else 1783 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t 1784 " tape blocks\n"), blocks); 1785 } 1786 1787 /* 1788 * If hidden dir then break now since xattrs_put() will do 1789 * the iterating of the directory. 1790 * 1791 * At the moment, there can't be attributes on attributes 1792 * or directories within the attributes hidden directory 1793 * hierarchy. 1794 */ 1795 if (filetype == XATTR_FILE) 1796 break; 1797 1798 if (*shortname != '/') 1799 (void) sprintf(newparent, "%s/%s", parent, shortname); 1800 else 1801 (void) sprintf(newparent, "%s", shortname); 1802 1803 if (chdir(shortname) < 0) { 1804 vperror(0, "%s", newparent); 1805 goto out; 1806 } 1807 1808 if ((dirp = opendir(".")) == NULL) { 1809 vperror(0, gettext( 1810 "can't open directory %s"), longname); 1811 if (chdir(parent) < 0) 1812 vperror(0, gettext("cannot change back?: %s"), 1813 parent); 1814 goto out; 1815 } 1816 1817 while ((dp = readdir(dirp)) != NULL && !term) { 1818 if ((strcmp(".", dp->d_name) == 0) || 1819 (strcmp("..", dp->d_name) == 0)) 1820 continue; 1821 (void) strcpy(cp, dp->d_name); 1822 if (stat(dp->d_name, &sbuf) < 0 || 1823 (sbuf.st_mode & S_IFMT) == S_IFDIR) { 1824 l = telldir(dirp); 1825 (void) closedir(dirp); 1826 } else 1827 l = -1; 1828 1829 archtype = putfile(buf, cp, newparent, 1830 NORMAL_FILE, lev + 1, symlink_lev); 1831 1832 if (!exitflag) { 1833 if (atflag && archtype == PUT_NOTAS_LINK) { 1834 xattrs_put(buf, cp, newparent); 1835 } 1836 } 1837 if (exitflag) 1838 break; 1839 1840 /* 1841 * If the directory was not closed, then it does 1842 * not need to be reopened. 1843 */ 1844 if (l < 0) 1845 continue; 1846 if ((dirp = opendir(".")) == NULL) { 1847 vperror(0, gettext( 1848 "can't open directory %s"), longname); 1849 if (chdir(parent) < 0) 1850 vperror(0, 1851 gettext("cannot change back?: %s"), 1852 parent); 1853 goto out; 1854 } 1855 seekdir(dirp, l); 1856 1857 } 1858 (void) closedir(dirp); 1859 1860 if (chdir(parent) < 0) { 1861 vperror(0, gettext("cannot change back?: %s"), parent); 1862 } 1863 1864 break; 1865 1866 case S_IFLNK: 1867 readlink_max = NAMSIZ; 1868 if (stbuf.st_size > NAMSIZ) { 1869 if (Eflag > 0) { 1870 xhdr_flgs |= _X_LINKPATH; 1871 readlink_max = PATH_MAX; 1872 } else { 1873 (void) fprintf(stderr, gettext( 1874 "tar: %s: symbolic link too long\n"), 1875 longname); 1876 if (errflag) 1877 exitflag = 1; 1878 Errflg = 1; 1879 goto out; 1880 } 1881 } 1882 /* 1883 * Sym-links need header size of zero since you 1884 * don't store any data for this type. 1885 */ 1886 stbuf.st_size = (off_t)0; 1887 tomodes(&stbuf); 1888 i = readlink(shortname, filetmp, readlink_max); 1889 if (i < 0) { 1890 vperror(0, gettext( 1891 "can't read symbolic link %s"), longname); 1892 goto out; 1893 } else { 1894 filetmp[i] = 0; 1895 } 1896 if (vflag) 1897 (void) fprintf(vfile, gettext( 1898 "a %s symbolic link to %s\n"), 1899 longname, filetmp); 1900 if (xhdr_flgs & _X_LINKPATH) { 1901 Xtarhdr.x_linkpath = filetmp; 1902 if (build_dblock(name, tchar, '2', filetype, &stbuf, 1903 stbuf.st_dev, prefix) != 0) 1904 goto out; 1905 } else 1906 if (build_dblock(name, filetmp, '2', filetype, &stbuf, 1907 stbuf.st_dev, prefix) != 0) 1908 goto out; 1909 (void) writetbuf((char *)&dblock, 1); 1910 /* 1911 * No acls for symlinks: mode is always 777 1912 * dont call write ancillary 1913 */ 1914 rc = PUT_AS_LINK; 1915 break; 1916 case S_IFREG: 1917 if ((infile = openat(dirfd, shortname, 0)) < 0) { 1918 vperror(0, "%s%s%s", longname, 1919 (filetype == XATTR_FILE) ? 1920 gettext(" attribute ") : "", 1921 (filetype == XATTR_FILE) ? 1922 shortname : ""); 1923 goto out; 1924 } 1925 1926 blocks = TBLOCKS(stbuf.st_size); 1927 1928 if (put_link(name, longname, shortname, 1929 prefix, filetype, '1') == 0) { 1930 (void) close(infile); 1931 rc = PUT_AS_LINK; 1932 goto out; 1933 } 1934 1935 tomodes(&stbuf); 1936 1937 /* correctly handle end of volume */ 1938 while (mulvol && tapepos + blocks + 1 > blocklim) { 1939 /* file won't fit */ 1940 if (eflag) { 1941 if (blocks <= blocklim) { 1942 newvol(); 1943 break; 1944 } 1945 (void) fprintf(stderr, gettext( 1946 "tar: Single file cannot fit on volume\n")); 1947 done(3); 1948 } 1949 /* split if floppy has some room and file is large */ 1950 if (((blocklim - tapepos) >= EXTMIN) && 1951 ((blocks + 1) >= blocklim/10)) { 1952 splitfile(longname, infile, 1953 name, prefix, filetype); 1954 (void) close(dirfd); 1955 (void) close(infile); 1956 goto out; 1957 } 1958 newvol(); /* not worth it--just get new volume */ 1959 } 1960 #ifdef DEBUG 1961 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 1962 blocks); 1963 #endif 1964 if (build_dblock(name, tchar, '0', filetype, 1965 &stbuf, stbuf.st_dev, prefix) != 0) { 1966 goto out; 1967 } 1968 if (vflag) { 1969 #ifdef DEBUG 1970 if (NotTape) 1971 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 1972 0); 1973 #endif 1974 (void) fprintf(vfile, "a %s%s%s ", longname, 1975 (filetype == XATTR_FILE) ? 1976 gettext(" attribute ") : "", 1977 (filetype == XATTR_FILE) ? 1978 shortname : ""); 1979 if (NotTape) 1980 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 1981 K(blocks)); 1982 else 1983 (void) fprintf(vfile, 1984 gettext("%" FMT_blkcnt_t " tape blocks\n"), 1985 blocks); 1986 } 1987 1988 if (put_extra_attributes(longname, shortname, prefix, 1989 filetype, '0') != 0) 1990 goto out; 1991 1992 /* 1993 * No need to reset typeflag for extended attribute here, since 1994 * put_extra_attributes already set it and we haven't called 1995 * build_dblock(). 1996 */ 1997 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 1998 hint = writetbuf((char *)&dblock, 1); 1999 maxread = max(stbuf.st_blksize, (nblock * TBLOCK)); 2000 if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2001 maxread = TBLOCK; 2002 bigbuf = buf; 2003 } 2004 2005 while (((i = (int) 2006 read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2007 blocks) { 2008 blkcnt_t nblks; 2009 2010 nblks = ((i-1)/TBLOCK)+1; 2011 if (nblks > blocks) 2012 nblks = blocks; 2013 hint = writetbuf(bigbuf, nblks); 2014 blocks -= nblks; 2015 } 2016 (void) close(infile); 2017 if (bigbuf != buf) 2018 free(bigbuf); 2019 if (i < 0) 2020 vperror(0, gettext("Read error on %s"), longname); 2021 else if (blocks != 0 || i != 0) { 2022 (void) fprintf(stderr, gettext( 2023 "tar: %s: file changed size\n"), longname); 2024 if (errflag) { 2025 exitflag = 1; 2026 Errflg = 1; 2027 } else if (!Dflag) { 2028 Errflg = 1; 2029 } 2030 } 2031 putempty(blocks); 2032 break; 2033 case S_IFIFO: 2034 blocks = TBLOCKS(stbuf.st_size); 2035 stbuf.st_size = (off_t)0; 2036 2037 if (put_link(name, longname, shortname, 2038 prefix, filetype, '6') == 0) { 2039 rc = PUT_AS_LINK; 2040 goto out; 2041 } 2042 tomodes(&stbuf); 2043 2044 while (mulvol && tapepos + blocks + 1 > blocklim) { 2045 if (eflag) { 2046 if (blocks <= blocklim) { 2047 newvol(); 2048 break; 2049 } 2050 (void) fprintf(stderr, gettext( 2051 "tar: Single file cannot fit on volume\n")); 2052 done(3); 2053 } 2054 2055 if (((blocklim - tapepos) >= EXTMIN) && 2056 ((blocks + 1) >= blocklim/10)) { 2057 splitfile(longname, infile, name, 2058 prefix, filetype); 2059 (void) close(dirfd); 2060 (void) close(infile); 2061 goto out; 2062 } 2063 newvol(); 2064 } 2065 #ifdef DEBUG 2066 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2067 blocks); 2068 #endif 2069 if (vflag) { 2070 #ifdef DEBUG 2071 if (NotTape) 2072 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2073 0); 2074 #endif 2075 if (NotTape) 2076 (void) fprintf(vfile, gettext("a %s %" 2077 FMT_blkcnt_t "K\n "), longname, K(blocks)); 2078 else 2079 (void) fprintf(vfile, gettext( 2080 "a %s %" FMT_blkcnt_t " tape blocks\n"), 2081 longname, blocks); 2082 } 2083 if (build_dblock(name, tchar, '6', filetype, 2084 &stbuf, stbuf.st_dev, prefix) != 0) 2085 goto out; 2086 2087 if (put_extra_attributes(longname, shortname, prefix, 2088 filetype, '6') != 0) 2089 goto out; 2090 2091 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2092 dblock.dbuf.typeflag = '6'; 2093 2094 (void) writetbuf((char *)&dblock, 1); 2095 break; 2096 case S_IFCHR: 2097 stbuf.st_size = (off_t)0; 2098 blocks = TBLOCKS(stbuf.st_size); 2099 if (put_link(name, longname, 2100 shortname, prefix, filetype, '3') == 0) { 2101 rc = PUT_AS_LINK; 2102 goto out; 2103 } 2104 tomodes(&stbuf); 2105 2106 while (mulvol && tapepos + blocks + 1 > blocklim) { 2107 if (eflag) { 2108 if (blocks <= blocklim) { 2109 newvol(); 2110 break; 2111 } 2112 (void) fprintf(stderr, gettext( 2113 "tar: Single file cannot fit on volume\n")); 2114 done(3); 2115 } 2116 2117 if (((blocklim - tapepos) >= EXTMIN) && 2118 ((blocks + 1) >= blocklim/10)) { 2119 splitfile(longname, infile, name, 2120 prefix, filetype); 2121 (void) close(dirfd); 2122 goto out; 2123 } 2124 newvol(); 2125 } 2126 #ifdef DEBUG 2127 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2128 blocks); 2129 #endif 2130 if (vflag) { 2131 #ifdef DEBUG 2132 if (NotTape) 2133 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2134 0); 2135 #endif 2136 if (NotTape) 2137 (void) fprintf(vfile, gettext("a %s %" 2138 FMT_blkcnt_t "K\n"), longname, K(blocks)); 2139 else 2140 (void) fprintf(vfile, gettext("a %s %" 2141 FMT_blkcnt_t " tape blocks\n"), longname, 2142 blocks); 2143 } 2144 if (build_dblock(name, tchar, '3', 2145 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2146 goto out; 2147 2148 if (put_extra_attributes(longname, shortname, 2149 prefix, filetype, '3') != 0) 2150 goto out; 2151 2152 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2153 dblock.dbuf.typeflag = '3'; 2154 2155 (void) writetbuf((char *)&dblock, 1); 2156 break; 2157 case S_IFBLK: 2158 stbuf.st_size = (off_t)0; 2159 blocks = TBLOCKS(stbuf.st_size); 2160 if (put_link(name, longname, 2161 shortname, prefix, filetype, '4') == 0) { 2162 rc = PUT_AS_LINK; 2163 goto out; 2164 } 2165 tomodes(&stbuf); 2166 2167 while (mulvol && tapepos + blocks + 1 > blocklim) { 2168 if (eflag) { 2169 if (blocks <= blocklim) { 2170 newvol(); 2171 break; 2172 } 2173 (void) fprintf(stderr, gettext( 2174 "tar: Single file cannot fit on volume\n")); 2175 done(3); 2176 } 2177 2178 if (((blocklim - tapepos) >= EXTMIN) && 2179 ((blocks + 1) >= blocklim/10)) { 2180 splitfile(longname, infile, 2181 name, prefix, filetype); 2182 (void) close(dirfd); 2183 goto out; 2184 } 2185 newvol(); 2186 } 2187 #ifdef DEBUG 2188 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2189 blocks); 2190 #endif 2191 if (vflag) { 2192 #ifdef DEBUG 2193 if (NotTape) 2194 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2195 0); 2196 #endif 2197 (void) fprintf(vfile, "a %s ", longname); 2198 if (NotTape) 2199 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2200 K(blocks)); 2201 else 2202 (void) fprintf(vfile, gettext("%" 2203 FMT_blkcnt_t " tape blocks\n"), blocks); 2204 } 2205 if (build_dblock(name, tchar, '4', 2206 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2207 goto out; 2208 2209 if (put_extra_attributes(longname, shortname, 2210 prefix, filetype, '4') != 0) 2211 goto out; 2212 2213 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2214 dblock.dbuf.typeflag = '4'; 2215 2216 (void) writetbuf((char *)&dblock, 1); 2217 break; 2218 default: 2219 (void) fprintf(stderr, gettext( 2220 "tar: %s is not a file. Not dumped\n"), longname); 2221 if (errflag) 2222 exitflag = 1; 2223 Errflg = 1; 2224 goto out; 2225 } 2226 2227 out: 2228 if (dirfd != -1) { 2229 if (filetype == XATTR_FILE) 2230 (void) chdir(parent); 2231 (void) close(dirfd); 2232 } 2233 return (rc); 2234 } 2235 2236 2237 /* 2238 * splitfile dump a large file across volumes 2239 * 2240 * splitfile(longname, fd); 2241 * char *longname; full name of file 2242 * int ifd; input file descriptor 2243 * 2244 * NOTE: only called by putfile() to dump a large file. 2245 */ 2246 2247 static void 2248 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2249 { 2250 blkcnt_t blocks; 2251 off_t bytes, s; 2252 char buf[TBLOCK]; 2253 int i, extents; 2254 2255 blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2256 2257 /* 2258 * # extents = 2259 * size of file after using up rest of this floppy 2260 * blocks - (blocklim - tapepos) + 1 (for header) 2261 * plus roundup value before divide by blocklim-1 2262 * + (blocklim - 1) - 1 2263 * all divided by blocklim-1 (one block for each header). 2264 * this gives 2265 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2266 * which reduces to the expression used. 2267 * one is added to account for this first extent. 2268 * 2269 * When one is dealing with extremely large archives, one may want 2270 * to allow for a large number of extents. This code should be 2271 * revisited to determine if extents should be changed to something 2272 * larger than an int. 2273 */ 2274 extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2275 2276 if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2277 (void) fprintf(stderr, gettext( 2278 "tar: %s needs unusual number of volumes to split\n" 2279 "tar: %s not dumped\n"), longname, longname); 2280 return; 2281 } 2282 if (build_dblock(name, tchar, '0', filetype, 2283 &stbuf, stbuf.st_dev, prefix) != 0) 2284 return; 2285 2286 dblock.dbuf.extotal = extents; 2287 bytes = stbuf.st_size; 2288 2289 /* 2290 * The value contained in dblock.dbuf.efsize was formerly used when the 2291 * v flag was specified in conjunction with the t flag. Although it is 2292 * no longer used, older versions of tar will expect the former 2293 * behaviour, so we must continue to write it to the archive. 2294 * 2295 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2296 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2297 * store 0. 2298 */ 2299 if (bytes <= TAR_EFSIZE_MAX) 2300 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2301 else 2302 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2303 2304 (void) fprintf(stderr, gettext( 2305 "tar: large file %s needs %d extents.\n" 2306 "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2307 longname, extents, K(tapepos)); 2308 2309 s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2310 for (i = 1; i <= extents; i++) { 2311 if (i > 1) { 2312 newvol(); 2313 if (i == extents) 2314 s = bytes; /* last ext. gets true bytes */ 2315 else 2316 s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2317 } 2318 bytes -= s; 2319 blocks = TBLOCKS(s); 2320 2321 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2322 dblock.dbuf.extno = i; 2323 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2324 (void) writetbuf((char *)&dblock, 1); 2325 2326 if (vflag) 2327 (void) fprintf(vfile, 2328 "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n", 2329 longname, K(blocks), i, extents); 2330 while (blocks && read(ifd, buf, TBLOCK) > 0) { 2331 blocks--; 2332 (void) writetbuf(buf, 1); 2333 } 2334 if (blocks != 0) { 2335 (void) fprintf(stderr, gettext( 2336 "tar: %s: file changed size\n"), longname); 2337 (void) fprintf(stderr, gettext( 2338 "tar: aborting split file %s\n"), longname); 2339 (void) close(ifd); 2340 return; 2341 } 2342 } 2343 (void) close(ifd); 2344 if (vflag) 2345 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2346 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2347 extents); 2348 } 2349 2350 /* 2351 * convtoreg - determines whether the file should be converted to a 2352 * regular file when extracted 2353 * 2354 * Returns 1 when file size > 0 and typeflag is not recognized 2355 * Otherwise returns 0 2356 */ 2357 static int 2358 convtoreg(off_t size) 2359 { 2360 if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2361 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2362 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2363 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2364 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2365 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2366 (dblock.dbuf.typeflag != 'X')) { 2367 return (1); 2368 } 2369 return (0); 2370 } 2371 2372 static void 2373 #ifdef _iBCS2 2374 doxtract(char *argv[], int tbl_cnt) 2375 #else 2376 doxtract(char *argv[]) 2377 #endif 2378 { 2379 struct stat xtractbuf; /* stat on file after extracting */ 2380 blkcnt_t blocks; 2381 off_t bytes; 2382 int ofile; 2383 int newfile; /* Does the file already exist */ 2384 int xcnt = 0; /* count # files extracted */ 2385 int fcnt = 0; /* count # files in argv list */ 2386 int dir; 2387 int dirfd = -1; 2388 uid_t Uid; 2389 char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 2390 char dirname[PATH_MAX+1]; 2391 char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 2392 char origdir[PATH_MAX+1]; 2393 int once = 1; 2394 int error; 2395 int symflag; 2396 int want; 2397 acl_t *aclp = NULL; /* acl info */ 2398 timestruc_t time_zero; /* used for call to doDirTimes */ 2399 int dircreate; 2400 int convflag; 2401 int cnt; 2402 2403 time_zero.tv_sec = 0; 2404 time_zero.tv_nsec = 0; 2405 2406 dumping = 0; /* for newvol(), et al: we are not writing */ 2407 2408 /* 2409 * Count the number of files that are to be extracted 2410 */ 2411 Uid = getuid(); 2412 2413 #ifdef _iBCS2 2414 initarg(argv, Filefile); 2415 while (nextarg() != NULL) 2416 ++fcnt; 2417 fcnt += tbl_cnt; 2418 #endif /* _iBCS2 */ 2419 2420 for (;;) { 2421 convflag = 0; 2422 symflag = 0; 2423 dir = 0; 2424 ofile = -1; 2425 2426 /* namep is set by wantit to point to the full name */ 2427 if ((want = wantit(argv, &namep, &dirp, &comp)) == 0) { 2428 #if defined(O_XATTR) 2429 if (xattrp != (struct xattr_buf *)NULL) { 2430 free(xattrhead); 2431 xattrp = NULL; 2432 xattr_linkp = NULL; 2433 xattrhead = NULL; 2434 } 2435 #endif 2436 continue; 2437 } 2438 if (want == -1) 2439 break; 2440 2441 if (dirfd != -1) 2442 (void) close(dirfd); 2443 2444 (void) strcpy(&dirname[0], namep); 2445 dircreate = checkdir(&dirname[0]); 2446 2447 #if defined(O_XATTR) 2448 if (xattrp != (struct xattr_buf *)NULL) { 2449 dirfd = attropen(dirp, ".", O_RDONLY); 2450 } else { 2451 dirfd = open(dirp, O_RDONLY); 2452 } 2453 #else 2454 dirfd = open(dirp, O_RDONLY); 2455 #endif 2456 2457 if (dirfd == -1) { 2458 #if defined(O_XATTR) 2459 if (xattrp) { 2460 dirfd = retry_attrdir_open(dirp); 2461 } 2462 #endif 2463 if (dirfd == -1) { 2464 (void) fprintf(stderr, gettext( 2465 "tar: cannot open %s %s\n"), dirp, 2466 strerror(errno)); 2467 passtape(); 2468 continue; 2469 } 2470 } 2471 2472 if (xhdr_flgs & _X_LINKPATH) 2473 (void) strcpy(templink, Xtarhdr.x_linkpath); 2474 else { 2475 #if defined(O_XATTR) 2476 if (xattrp && dblock.dbuf.typeflag == '1') { 2477 (void) sprintf(templink, "%.*s", NAMSIZ, 2478 xattrp->h_names); 2479 } else { 2480 (void) sprintf(templink, "%.*s", NAMSIZ, 2481 dblock.dbuf.linkname); 2482 } 2483 #else 2484 (void) sprintf(templink, "%.*s", NAMSIZ, 2485 dblock.dbuf.linkname); 2486 #endif 2487 } 2488 2489 if (Fflag) { 2490 char *s; 2491 2492 if ((s = strrchr(namep, '/')) == 0) 2493 s = namep; 2494 2495 else 2496 s++; 2497 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 2498 passtape(); 2499 continue; 2500 } 2501 } 2502 2503 if (checkw('x', namep) == 0) { 2504 passtape(); 2505 continue; 2506 } 2507 if (once) { 2508 if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 2509 if (geteuid() == (uid_t)0) { 2510 checkflag = 1; 2511 pflag = 1; 2512 } else { 2513 /* get file creation mask */ 2514 Oumask = umask(0); 2515 (void) umask(Oumask); 2516 } 2517 once = 0; 2518 } else { 2519 if (geteuid() == (uid_t)0) { 2520 pflag = 1; 2521 checkflag = 2; 2522 } 2523 if (!pflag) { 2524 /* get file creation mask */ 2525 Oumask = umask(0); 2526 (void) umask(Oumask); 2527 } 2528 once = 0; 2529 } 2530 } 2531 2532 #if defined(O_XATTR) 2533 /* 2534 * Handle extraction of hidden attr dir. 2535 * Dir is automatically created, we only 2536 * need to update mode and perm's. 2537 */ 2538 if ((xattrp != (struct xattr_buf *)NULL) && Hiddendir == 1) { 2539 if (fchownat(dirfd, ".", stbuf.st_uid, 2540 stbuf.st_gid, 0) != 0) { 2541 vperror(0, gettext( 2542 "%s: failed to set ownership of attribute" 2543 " directory"), namep); 2544 } 2545 2546 if (fchmod(dirfd, stbuf.st_mode) != 0) { 2547 vperror(0, gettext( 2548 "%s: failed to set permissions of" 2549 " attribute directory"), namep); 2550 } 2551 goto filedone; 2552 } 2553 #endif 2554 2555 if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 2556 dir = 1; 2557 if (vflag) { 2558 (void) fprintf(vfile, "x %s, 0 bytes, ", 2559 &dirname[0]); 2560 if (NotTape) 2561 (void) fprintf(vfile, "0K\n"); 2562 else 2563 (void) fprintf(vfile, gettext("%" 2564 FMT_blkcnt_t " tape blocks\n"), 2565 (blkcnt_t)0); 2566 } 2567 goto filedone; 2568 } 2569 2570 if (dblock.dbuf.typeflag == '6') { /* FIFO */ 2571 if (rmdir(namep) < 0) { 2572 if (errno == ENOTDIR) 2573 (void) unlink(namep); 2574 } 2575 linkp = templink; 2576 if (*linkp != NULL) { 2577 if (Aflag && *linkp == '/') 2578 linkp++; 2579 if (link(linkp, namep) < 0) { 2580 (void) fprintf(stderr, gettext( 2581 "tar: %s: cannot link\n"), namep); 2582 continue; 2583 } 2584 if (vflag) 2585 (void) fprintf(vfile, gettext( 2586 "%s linked to %s\n"), namep, linkp); 2587 xcnt++; /* increment # files extracted */ 2588 continue; 2589 } 2590 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO), 2591 (int)Gen.g_devmajor) < 0) { 2592 vperror(0, gettext("%s: mknod failed"), namep); 2593 continue; 2594 } 2595 bytes = stbuf.st_size; 2596 blocks = TBLOCKS(bytes); 2597 if (vflag) { 2598 (void) fprintf(vfile, "x %s, %" FMT_off_t 2599 " bytes, ", namep, bytes); 2600 if (NotTape) 2601 (void) fprintf(vfile, "%" FMT_blkcnt_t 2602 "K\n", K(blocks)); 2603 else 2604 (void) fprintf(vfile, gettext("%" 2605 FMT_blkcnt_t " tape blocks\n"), 2606 blocks); 2607 } 2608 goto filedone; 2609 } 2610 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */ 2611 if (rmdir(namep) < 0) { 2612 if (errno == ENOTDIR) 2613 (void) unlink(namep); 2614 } 2615 linkp = templink; 2616 if (*linkp != NULL) { 2617 if (Aflag && *linkp == '/') 2618 linkp++; 2619 if (link(linkp, namep) < 0) { 2620 (void) fprintf(stderr, gettext( 2621 "tar: %s: cannot link\n"), namep); 2622 continue; 2623 } 2624 if (vflag) 2625 (void) fprintf(vfile, gettext( 2626 "%s linked to %s\n"), namep, linkp); 2627 xcnt++; /* increment # files extracted */ 2628 continue; 2629 } 2630 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR), 2631 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 2632 vperror(0, gettext( 2633 "%s: mknod failed"), namep); 2634 continue; 2635 } 2636 bytes = stbuf.st_size; 2637 blocks = TBLOCKS(bytes); 2638 if (vflag) { 2639 (void) fprintf(vfile, "x %s, %" FMT_off_t 2640 " bytes, ", namep, bytes); 2641 if (NotTape) 2642 (void) fprintf(vfile, "%" FMT_blkcnt_t 2643 "K\n", K(blocks)); 2644 else 2645 (void) fprintf(vfile, gettext("%" 2646 FMT_blkcnt_t " tape blocks\n"), 2647 blocks); 2648 } 2649 goto filedone; 2650 } else if (dblock.dbuf.typeflag == '3' && Uid) { 2651 (void) fprintf(stderr, gettext( 2652 "Can't create special %s\n"), namep); 2653 continue; 2654 } 2655 2656 /* BLOCK SPECIAL */ 2657 2658 if (dblock.dbuf.typeflag == '4' && !Uid) { 2659 if (rmdir(namep) < 0) { 2660 if (errno == ENOTDIR) 2661 (void) unlink(namep); 2662 } 2663 linkp = templink; 2664 if (*linkp != NULL) { 2665 if (Aflag && *linkp == '/') 2666 linkp++; 2667 if (link(linkp, namep) < 0) { 2668 (void) fprintf(stderr, gettext( 2669 "tar: %s: cannot link\n"), namep); 2670 continue; 2671 } 2672 if (vflag) 2673 (void) fprintf(vfile, gettext( 2674 "%s linked to %s\n"), namep, linkp); 2675 xcnt++; /* increment # files extracted */ 2676 continue; 2677 } 2678 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK), 2679 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 2680 vperror(0, gettext("%s: mknod failed"), namep); 2681 continue; 2682 } 2683 bytes = stbuf.st_size; 2684 blocks = TBLOCKS(bytes); 2685 if (vflag) { 2686 (void) fprintf(vfile, gettext("x %s, %" 2687 FMT_off_t " bytes, "), namep, bytes); 2688 if (NotTape) 2689 (void) fprintf(vfile, "%" FMT_blkcnt_t 2690 "K\n", K(blocks)); 2691 else 2692 (void) fprintf(vfile, gettext("%" 2693 FMT_blkcnt_t " tape blocks\n"), 2694 blocks); 2695 } 2696 goto filedone; 2697 } else if (dblock.dbuf.typeflag == '4' && Uid) { 2698 (void) fprintf(stderr, 2699 gettext("Can't create special %s\n"), namep); 2700 continue; 2701 } 2702 if (dblock.dbuf.typeflag == '2') { /* symlink */ 2703 linkp = templink; 2704 if (Aflag && *linkp == '/') 2705 linkp++; 2706 if (rmdir(namep) < 0) { 2707 if (errno == ENOTDIR) 2708 (void) unlink(namep); 2709 } 2710 if (symlink(linkp, namep) < 0) { 2711 vperror(0, gettext("%s: symbolic link failed"), 2712 namep); 2713 continue; 2714 } 2715 if (vflag) 2716 (void) fprintf(vfile, gettext( 2717 "x %s symbolic link to %s\n"), 2718 namep, linkp); 2719 2720 symflag = AT_SYMLINK_NOFOLLOW; 2721 goto filedone; 2722 } 2723 if (dblock.dbuf.typeflag == '1') { 2724 linkp = templink; 2725 if (Aflag && *linkp == '/') 2726 linkp++; 2727 if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) { 2728 if (errno == ENOTDIR) 2729 (void) unlinkat(dirfd, comp, 0); 2730 } 2731 #if defined(O_XATTR) 2732 if (xattrp && xattr_linkp) { 2733 if (getcwd(origdir, (PATH_MAX+1)) == 2734 (char *)NULL) { 2735 vperror(0, gettext( 2736 "A parent directory cannot" 2737 " be read")); 2738 exit(1); 2739 } 2740 2741 if (fchdir(dirfd) < 0) { 2742 vperror(0, gettext( 2743 "Cannot fchdir to attribute " 2744 "directory")); 2745 exit(1); 2746 } 2747 2748 error = link(xattr_linkaname, xattraname); 2749 if (chdir(origdir) < 0) { 2750 vperror(0, gettext( 2751 "Cannot chdir out of attribute " 2752 "directory")); 2753 exit(1); 2754 } 2755 } else { 2756 error = link(linkp, namep); 2757 } 2758 #else 2759 error = link(linkp, namep); 2760 #endif 2761 2762 if (error < 0) { 2763 (void) fprintf(stderr, gettext( 2764 "tar: %s%s%s: cannot link\n"), 2765 namep, (xattr_linkp != NULL) ? 2766 gettext(" attribute ") : "", 2767 (xattr_linkp != NULL) ? 2768 xattraname : ""); 2769 continue; 2770 } 2771 if (vflag) 2772 (void) fprintf(vfile, gettext( 2773 "%s%s%s linked to %s%s%s\n"), namep, 2774 (xattr_linkp != NULL) ? 2775 gettext(" attribute ") : "", 2776 (xattr_linkp != NULL) ? 2777 xattr_linkaname : "", 2778 linkp, (xattr_linkp != NULL) ? 2779 gettext(" attribute ") : "", 2780 (xattr_linkp != NULL) ? 2781 xattraname : ""); 2782 xcnt++; /* increment # files extracted */ 2783 #if defined(O_XATTR) 2784 if (xattrp != (struct xattr_buf *)NULL) { 2785 free(xattrhead); 2786 xattrp = NULL; 2787 xattr_linkp = NULL; 2788 xattrhead = NULL; 2789 } 2790 #endif 2791 continue; 2792 } 2793 2794 /* REGULAR FILES */ 2795 2796 if (convtoreg(stbuf.st_size)) { 2797 convflag = 1; 2798 if (errflag) { 2799 (void) fprintf(stderr, gettext( 2800 "tar: %s: typeflag '%c' not recognized\n"), 2801 namep, dblock.dbuf.typeflag); 2802 done(1); 2803 } else { 2804 (void) fprintf(stderr, gettext( 2805 "tar: %s: typeflag '%c' not recognized, " 2806 "converting to regular file\n"), namep, 2807 dblock.dbuf.typeflag); 2808 Errflg = 1; 2809 } 2810 } 2811 if (dblock.dbuf.typeflag == '0' || 2812 dblock.dbuf.typeflag == NULL || convflag) { 2813 delete_target(dirfd, comp); 2814 linkp = templink; 2815 if (*linkp != NULL) { 2816 if (Aflag && *linkp == '/') 2817 linkp++; 2818 if (link(linkp, comp) < 0) { 2819 (void) fprintf(stderr, gettext( 2820 "tar: %s: cannot link\n"), namep); 2821 continue; 2822 } 2823 if (vflag) 2824 (void) fprintf(vfile, gettext( 2825 "%s linked to %s\n"), comp, linkp); 2826 xcnt++; /* increment # files extracted */ 2827 continue; 2828 } 2829 newfile = ((fstatat(dirfd, comp, 2830 &xtractbuf, 0) == -1) ? TRUE : FALSE); 2831 if ((ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC, 2832 stbuf.st_mode & MODEMASK)) < 0) { 2833 (void) fprintf(stderr, gettext( 2834 "tar: %s - cannot create\n"), comp); 2835 if (errflag) 2836 done(1); 2837 else 2838 Errflg = 1; 2839 passtape(); 2840 continue; 2841 } 2842 2843 if (extno != 0) { /* file is in pieces */ 2844 if (extotal < 1 || extotal > MAXEXT) 2845 (void) fprintf(stderr, gettext( 2846 "tar: ignoring bad extent info for %s\n"), 2847 comp); 2848 else { 2849 xsfile(ofile); /* extract it */ 2850 goto filedone; 2851 } 2852 } 2853 extno = 0; /* let everyone know file is not split */ 2854 bytes = stbuf.st_size; 2855 blocks = TBLOCKS(bytes); 2856 if (vflag) { 2857 (void) fprintf(vfile, 2858 "x %s%s%s, %" FMT_off_t " bytes, ", 2859 (xattrp == NULL) ? "" : dirp, 2860 (xattrp == NULL) ? "" : gettext(" attribute "), 2861 (xattrp == NULL) ? namep : comp, bytes); 2862 if (NotTape) 2863 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2864 K(blocks)); 2865 else 2866 (void) fprintf(vfile, gettext("%" 2867 FMT_blkcnt_t " tape blocks\n"), blocks); 2868 } 2869 2870 xblocks(bytes, ofile); 2871 filedone: 2872 if (mflag == 0 && !symflag) { 2873 if (dir) 2874 doDirTimes(namep, stbuf.st_mtim); 2875 else 2876 setPathTimes(dirfd, comp, stbuf.st_mtim); 2877 } 2878 2879 /* moved this code from above */ 2880 if (pflag && !symflag && Hiddendir == 0) { 2881 if (xattrp != (struct xattr_buf *)NULL) 2882 (void) fchmod(ofile, stbuf.st_mode & MODEMASK); 2883 else 2884 (void) chmod(namep, stbuf.st_mode & MODEMASK); 2885 } 2886 2887 2888 /* 2889 * Because ancillary file preceeds the normal file, 2890 * acl info may have been retrieved (in aclp). 2891 * All file types are directed here (go filedone). 2892 * Always restore ACLs if there are ACLs. 2893 */ 2894 if (aclp != NULL) { 2895 int ret; 2896 2897 #if defined(O_XATTR) 2898 if (xattrp != (struct xattr_buf *)NULL) { 2899 if (Hiddendir) 2900 ret = facl_set(dirfd, aclp); 2901 else 2902 ret = facl_set(ofile, aclp); 2903 } else { 2904 ret = acl_set(namep, aclp); 2905 } 2906 #else 2907 ret = acl_set(namep, &aclp); 2908 #endif 2909 if (ret < 0) { 2910 if (pflag) { 2911 (void) fprintf(stderr, gettext( 2912 "%s: failed to set acl entries\n"), 2913 namep); 2914 } 2915 /* else: silent and continue */ 2916 } 2917 acl_free(aclp); 2918 aclp = NULL; 2919 } 2920 2921 #if defined(O_XATTR) 2922 if (xattrp != (struct xattr_buf *)NULL) { 2923 free(xattrhead); 2924 xattrp = NULL; 2925 xattr_linkp = NULL; 2926 xattrhead = NULL; 2927 } 2928 #endif 2929 2930 if (!oflag) 2931 resugname(dirfd, comp, symflag); /* set file ownership */ 2932 2933 if (pflag && newfile == TRUE && !dir && 2934 (dblock.dbuf.typeflag == '0' || 2935 dblock.dbuf.typeflag == NULL || 2936 convflag || dblock.dbuf.typeflag == '1')) { 2937 if (fstat(ofile, &xtractbuf) == -1) 2938 (void) fprintf(stderr, gettext( 2939 "tar: cannot stat extracted file %s\n"), 2940 namep); 2941 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT)) 2942 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) { 2943 (void) fprintf(stderr, gettext( 2944 "tar: warning - file permissions have " 2945 "changed for %s (are 0%o, should be " 2946 "0%o)\n"), 2947 namep, xtractbuf.st_mode, stbuf.st_mode); 2948 } 2949 } 2950 if (ofile != -1) { 2951 (void) close(dirfd); 2952 dirfd = -1; 2953 if (close(ofile) != 0) 2954 vperror(2, gettext("close error")); 2955 } 2956 xcnt++; /* increment # files extracted */ 2957 } 2958 if (dblock.dbuf.typeflag == 'A') { /* acl info */ 2959 char buf[TBLOCK]; 2960 char *secp; 2961 char *tp; 2962 int attrsize; 2963 int cnt; 2964 2965 2966 if (pflag) { 2967 bytes = stbuf.st_size; 2968 if ((secp = malloc((int)bytes)) == NULL) { 2969 (void) fprintf(stderr, gettext( 2970 "Insufficient memory for acl\n")); 2971 passtape(); 2972 continue; 2973 } 2974 tp = secp; 2975 blocks = TBLOCKS(bytes); 2976 while (blocks-- > 0) { 2977 readtape(buf); 2978 if (bytes <= TBLOCK) { 2979 (void) memcpy(tp, buf, 2980 (size_t)bytes); 2981 break; 2982 } else { 2983 (void) memcpy(tp, buf, 2984 TBLOCK); 2985 tp += TBLOCK; 2986 } 2987 bytes -= TBLOCK; 2988 } 2989 bytes = stbuf.st_size; 2990 /* got all attributes in secp */ 2991 tp = secp; 2992 do { 2993 attr = (struct sec_attr *)tp; 2994 switch (attr->attr_type) { 2995 case UFSD_ACL: 2996 case ACE_ACL: 2997 (void) sscanf(attr->attr_len, 2998 "%7o", 2999 (uint_t *) 3000 &cnt); 3001 /* header is 8 */ 3002 attrsize = 8 + (int)strlen( 3003 &attr->attr_info[0]) + 1; 3004 3005 error = 3006 acl_fromtext( 3007 &attr->attr_info[0], &aclp); 3008 3009 if (error != 0) { 3010 (void) fprintf(stderr, 3011 gettext( 3012 "aclfromtext " 3013 "failed: %s\n"), 3014 acl_strerror( 3015 error)); 3016 bytes -= attrsize; 3017 break; 3018 } 3019 if (acl_cnt(aclp) != cnt) { 3020 (void) fprintf(stderr, 3021 gettext( 3022 "aclcnt error\n")); 3023 bytes -= attrsize; 3024 break; 3025 } 3026 bytes -= attrsize; 3027 break; 3028 3029 /* SunFed case goes here */ 3030 3031 default: 3032 (void) fprintf(stderr, gettext( 3033 "unrecognized attr" 3034 " type\n")); 3035 bytes = (off_t)0; 3036 break; 3037 } 3038 3039 /* next attributes */ 3040 tp += attrsize; 3041 } while (bytes != 0); 3042 free(secp); 3043 } else 3044 passtape(); 3045 } /* acl */ 3046 3047 } /* for */ 3048 3049 /* 3050 * Ensure that all the directories still on the directory stack 3051 * get their modification times set correctly by flushing the 3052 * stack. 3053 */ 3054 3055 doDirTimes(NULL, time_zero); 3056 3057 /* 3058 * Check if the number of files extracted is different from the 3059 * number of files listed on the command line 3060 */ 3061 if (fcnt > xcnt) { 3062 (void) fprintf(stderr, 3063 gettext("tar: %d file(s) not extracted\n"), 3064 fcnt-xcnt); 3065 Errflg = 1; 3066 } 3067 } 3068 3069 /* 3070 * xblocks extract file/extent from tape to output file 3071 * 3072 * xblocks(bytes, ofile); 3073 * unsigned long long bytes; size of extent or file to be extracted 3074 * 3075 * called by doxtract() and xsfile() 3076 */ 3077 3078 static void 3079 xblocks(off_t bytes, int ofile) 3080 { 3081 blkcnt_t blocks; 3082 char buf[TBLOCK]; 3083 char tempname[NAMSIZ+1]; 3084 int write_count; 3085 3086 blocks = TBLOCKS(bytes); 3087 while (blocks-- > 0) { 3088 readtape(buf); 3089 if (bytes > TBLOCK) 3090 write_count = TBLOCK; 3091 else 3092 write_count = bytes; 3093 if (write(ofile, buf, write_count) < 0) { 3094 if (xhdr_flgs & _X_PATH) 3095 (void) strcpy(tempname, Xtarhdr.x_path); 3096 else 3097 (void) sprintf(tempname, "%.*s", NAMSIZ, 3098 dblock.dbuf.name); 3099 (void) fprintf(stderr, gettext( 3100 "tar: %s: HELP - extract write error\n"), tempname); 3101 done(2); 3102 } 3103 bytes -= TBLOCK; 3104 } 3105 } 3106 3107 3108 /* 3109 * xsfile extract split file 3110 * 3111 * xsfile(ofd); ofd = output file descriptor 3112 * 3113 * file extracted and put in ofd via xblocks() 3114 * 3115 * NOTE: only called by doxtract() to extract one large file 3116 */ 3117 3118 static union hblock savedblock; /* to ensure same file across volumes */ 3119 3120 static void 3121 xsfile(int ofd) 3122 { 3123 int i, c; 3124 char name[PATH_MAX+1]; /* holds name for diagnostics */ 3125 int extents, totalext; 3126 off_t bytes, totalbytes; 3127 3128 if (xhdr_flgs & _X_PATH) 3129 (void) strcpy(name, Xtarhdr.x_path); 3130 else 3131 (void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name); 3132 3133 totalbytes = (off_t)0; /* in case we read in half the file */ 3134 totalext = 0; /* these keep count */ 3135 3136 (void) fprintf(stderr, gettext( 3137 "tar: %s split across %d volumes\n"), name, extotal); 3138 3139 /* make sure we do extractions in order */ 3140 if (extno != 1) { /* starting in middle of file? */ 3141 wchar_t yeschar; 3142 wchar_t nochar; 3143 (void) mbtowc(&yeschar, nl_langinfo(YESSTR), MB_LEN_MAX); 3144 (void) mbtowc(&nochar, nl_langinfo(NOSTR), MB_LEN_MAX); 3145 (void) printf(gettext( 3146 "tar: first extent read is not #1\n" 3147 "OK to read file beginning with extent #%d (%wc/%wc) ? "), 3148 extno, yeschar, nochar); 3149 if (yesnoresponse() != yeschar) { 3150 canit: 3151 passtape(); 3152 if (close(ofd) != 0) 3153 vperror(2, gettext("close error")); 3154 return; 3155 } 3156 } 3157 extents = extotal; 3158 i = extno; 3159 /*CONSTCOND*/ 3160 while (1) { 3161 if (xhdr_flgs & _X_SIZE) { 3162 bytes = extsize; 3163 } else { 3164 bytes = stbuf.st_size; 3165 } 3166 3167 if (vflag) 3168 (void) fprintf(vfile, "+++ x %s [extent #%d], %" 3169 FMT_off_t " bytes, %ldK\n", name, extno, bytes, 3170 (long)K(TBLOCKS(bytes))); 3171 xblocks(bytes, ofd); 3172 3173 totalbytes += bytes; 3174 totalext++; 3175 if (++i > extents) 3176 break; 3177 3178 /* get next volume and verify it's the right one */ 3179 copy(&savedblock, &dblock); 3180 tryagain: 3181 newvol(); 3182 xhdr_flgs = 0; 3183 getdir(); 3184 if (Xhdrflag > 0) 3185 (void) get_xdata(); /* Get x-header & regular hdr */ 3186 if (endtape()) { /* seemingly empty volume */ 3187 (void) fprintf(stderr, gettext( 3188 "tar: first record is null\n")); 3189 asknicely: 3190 (void) fprintf(stderr, gettext( 3191 "tar: need volume with extent #%d of %s\n"), 3192 i, name); 3193 goto tryagain; 3194 } 3195 if (notsame()) { 3196 (void) fprintf(stderr, gettext( 3197 "tar: first file on that volume is not " 3198 "the same file\n")); 3199 goto asknicely; 3200 } 3201 if (i != extno) { 3202 (void) fprintf(stderr, gettext( 3203 "tar: extent #%d received out of order\ntar: should be #%d\n"), 3204 extno, i); 3205 (void) fprintf(stderr, gettext( 3206 "Ignore error, Abort this file, or " 3207 "load New volume (i/a/n) ? ")); 3208 c = response(); 3209 if (c == 'a') 3210 goto canit; 3211 if (c != 'i') /* default to new volume */ 3212 goto asknicely; 3213 i = extno; /* okay, start from there */ 3214 } 3215 } 3216 if (vflag) 3217 (void) fprintf(vfile, gettext( 3218 "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"), 3219 name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes))); 3220 } 3221 3222 3223 /* 3224 * notsame() check if extract file extent is invalid 3225 * 3226 * returns true if anything differs between savedblock and dblock 3227 * except extno (extent number), checksum, or size (extent size). 3228 * Determines if this header belongs to the same file as the one we're 3229 * extracting. 3230 * 3231 * NOTE: though rather bulky, it is only called once per file 3232 * extension, and it can withstand changes in the definition 3233 * of the header structure. 3234 * 3235 * WARNING: this routine is local to xsfile() above 3236 */ 3237 3238 static int 3239 notsame(void) 3240 { 3241 return ( 3242 (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) || 3243 (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) || 3244 (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) || 3245 (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) || 3246 (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) || 3247 (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) || 3248 (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) || 3249 (savedblock.dbuf.extotal != dblock.dbuf.extotal) || 3250 (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize))); 3251 } 3252 3253 3254 static void 3255 #ifdef _iBCS2 3256 dotable(char *argv[], int tbl_cnt) 3257 #else 3258 dotable(char *argv[]) 3259 #endif 3260 3261 { 3262 int tcnt; /* count # files tabled */ 3263 int fcnt; /* count # files in argv list */ 3264 char *namep, *dirp, *comp; 3265 int want; 3266 char aclchar = ' '; /* either blank or '+' */ 3267 char templink[PATH_MAX+1]; 3268 char *np; 3269 3270 dumping = 0; 3271 3272 /* if not on magtape, maximize seek speed */ 3273 if (NotTape && !bflag) { 3274 #if SYS_BLOCK > TBLOCK 3275 nblock = SYS_BLOCK / TBLOCK; 3276 #else 3277 nblock = 1; 3278 #endif 3279 } 3280 /* 3281 * Count the number of files that are to be tabled 3282 */ 3283 fcnt = tcnt = 0; 3284 3285 #ifdef _iBCS2 3286 initarg(argv, Filefile); 3287 while (nextarg() != NULL) 3288 ++fcnt; 3289 fcnt += tbl_cnt; 3290 #endif /* _iBCS2 */ 3291 3292 for (;;) { 3293 3294 /* namep is set by wantit to point to the full name */ 3295 if ((want = wantit(argv, &namep, &dirp, &comp)) == 0) 3296 continue; 3297 if (want == -1) 3298 break; 3299 if (dblock.dbuf.typeflag != 'A') 3300 ++tcnt; 3301 3302 /* 3303 * ACL support: 3304 * aclchar is introduced to indicate if there are 3305 * acl entries. longt() now takes one extra argument. 3306 */ 3307 if (vflag) { 3308 if (dblock.dbuf.typeflag == 'A') { 3309 aclchar = '+'; 3310 passtape(); 3311 continue; 3312 } 3313 longt(&stbuf, aclchar); 3314 aclchar = ' '; 3315 } 3316 3317 3318 #if defined(O_XATTR) 3319 if (xattrp != (struct xattr_buf *)NULL) { 3320 np = xattrp->h_names + strlen(xattrp->h_names) + 1; 3321 (void) printf(gettext("%s attribute %s"), 3322 xattrp->h_names, np); 3323 3324 } else { 3325 (void) printf("%s", namep); 3326 } 3327 #else 3328 (void) printf("%s", namep); 3329 #endif 3330 3331 if (extno != 0) { 3332 if (vflag) { 3333 /* keep the '\n' for backwards compatibility */ 3334 (void) fprintf(vfile, gettext( 3335 "\n [extent #%d of %d]"), extno, extotal); 3336 } else { 3337 (void) fprintf(vfile, gettext( 3338 " [extent #%d of %d]"), extno, extotal); 3339 } 3340 } 3341 if (xhdr_flgs & _X_LINKPATH) { 3342 (void) strcpy(templink, Xtarhdr.x_linkpath); 3343 } else { 3344 #if defined(O_XATTR) 3345 if (xattrp != (struct xattr_buf *)NULL) { 3346 (void) sprintf(templink, 3347 "file %.*s", NAMSIZ, xattrp->h_names); 3348 } else { 3349 (void) sprintf(templink, "%.*s", NAMSIZ, 3350 dblock.dbuf.linkname); 3351 } 3352 #else 3353 (void) sprintf(templink, "%.*s", NAMSIZ, 3354 dblock.dbuf.linkname); 3355 #endif 3356 templink[NAMSIZ] = '\0'; 3357 } 3358 if (dblock.dbuf.typeflag == '1') { 3359 /* 3360 * TRANSLATION_NOTE 3361 * Subject is omitted here. 3362 * Translate this as if 3363 * <subject> linked to %s 3364 */ 3365 #if defined(O_XATTR) 3366 if (xattrp != (struct xattr_buf *)NULL) { 3367 (void) printf( 3368 gettext(" linked to attribute %s"), 3369 xattr_linkp->h_names + 3370 strlen(xattr_linkp->h_names) + 1); 3371 } else { 3372 (void) printf( 3373 gettext(" linked to %s"), templink); 3374 } 3375 #else 3376 (void) printf( 3377 gettext(" linked to %s"), templink); 3378 3379 #endif 3380 } 3381 if (dblock.dbuf.typeflag == '2') 3382 (void) printf(gettext( 3383 /* 3384 * TRANSLATION_NOTE 3385 * Subject is omitted here. 3386 * Translate this as if 3387 * <subject> symbolic link to %s 3388 */ 3389 " symbolic link to %s"), templink); 3390 (void) printf("\n"); 3391 #if defined(O_XATTR) 3392 if (xattrp != (struct xattr_buf *)NULL) { 3393 free(xattrhead); 3394 xattrp = NULL; 3395 xattrhead = NULL; 3396 } 3397 #endif 3398 passtape(); 3399 } 3400 /* 3401 * Check if the number of files tabled is different from the 3402 * number of files listed on the command line 3403 */ 3404 if (fcnt > tcnt) { 3405 (void) fprintf(stderr, gettext( 3406 "tar: %d file(s) not found\n"), fcnt-tcnt); 3407 Errflg = 1; 3408 } 3409 } 3410 3411 static void 3412 putempty(blkcnt_t n) 3413 { 3414 char buf[TBLOCK]; 3415 char *cp; 3416 3417 for (cp = buf; cp < &buf[TBLOCK]; ) 3418 *cp++ = '\0'; 3419 while (n-- > 0) 3420 (void) writetbuf(buf, 1); 3421 } 3422 3423 static ushort_t Ftype = S_IFMT; 3424 3425 static void 3426 verbose(struct stat *st, char aclchar) 3427 { 3428 int i, j, temp; 3429 mode_t mode; 3430 char modestr[12]; 3431 3432 for (i = 0; i < 11; i++) 3433 modestr[i] = '-'; 3434 modestr[i] = '\0'; 3435 3436 /* a '+' sign is printed if there is ACL */ 3437 modestr[i-1] = aclchar; 3438 3439 mode = st->st_mode; 3440 for (i = 0; i < 3; i++) { 3441 temp = (mode >> (6 - (i * 3))); 3442 j = (i * 3) + 1; 3443 if (S_IROTH & temp) 3444 modestr[j] = 'r'; 3445 if (S_IWOTH & temp) 3446 modestr[j + 1] = 'w'; 3447 if (S_IXOTH & temp) 3448 modestr[j + 2] = 'x'; 3449 } 3450 temp = st->st_mode & Ftype; 3451 switch (temp) { 3452 case (S_IFIFO): 3453 modestr[0] = 'p'; 3454 break; 3455 case (S_IFCHR): 3456 modestr[0] = 'c'; 3457 break; 3458 case (S_IFDIR): 3459 modestr[0] = 'd'; 3460 break; 3461 case (S_IFBLK): 3462 modestr[0] = 'b'; 3463 break; 3464 case (S_IFREG): /* was initialized to '-' */ 3465 break; 3466 case (S_IFLNK): 3467 modestr[0] = 'l'; 3468 break; 3469 default: 3470 /* This field may be zero in old archives. */ 3471 if (is_posix && dblock.dbuf.typeflag != '1') { 3472 /* 3473 * For POSIX compliant archives, the mode field 3474 * consists of 12 bits, ie: the file type bits 3475 * are not stored in dblock.dbuf.mode. 3476 * For files other than hard links, getdir() sets 3477 * the file type bits in the st_mode field of the 3478 * stat structure based upon dblock.dbuf.typeflag. 3479 */ 3480 (void) fprintf(stderr, gettext( 3481 "tar: impossible file type")); 3482 } 3483 } 3484 3485 if ((S_ISUID & Gen.g_mode) == S_ISUID) 3486 modestr[3] = 's'; 3487 if ((S_ISVTX & Gen.g_mode) == S_ISVTX) 3488 modestr[9] = 't'; 3489 if ((S_ISGID & Gen.g_mode) == S_ISGID && modestr[6] == 'x') 3490 modestr[6] = 's'; 3491 else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x') 3492 modestr[6] = 'l'; 3493 (void) fprintf(vfile, "%s", modestr); 3494 } 3495 3496 static void 3497 longt(struct stat *st, char aclchar) 3498 { 3499 char fileDate[30]; 3500 struct tm *tm; 3501 3502 verbose(st, aclchar); 3503 (void) fprintf(vfile, "%3ld/%-3ld", st->st_uid, st->st_gid); 3504 3505 if (dblock.dbuf.typeflag == '2') { 3506 if (xhdr_flgs & _X_LINKPATH) 3507 st->st_size = (off_t)strlen(Xtarhdr.x_linkpath); 3508 else 3509 st->st_size = (off_t)(memchr(dblock.dbuf.linkname, 3510 '\0', NAMSIZ) ? 3511 (strlen(dblock.dbuf.linkname)) : (NAMSIZ)); 3512 } 3513 (void) fprintf(vfile, " %6" FMT_off_t, st->st_size); 3514 3515 tm = localtime(&(st->st_mtime)); 3516 (void) strftime(fileDate, sizeof (fileDate), 3517 dcgettext((const char *)0, "%b %e %R %Y", LC_TIME), tm); 3518 (void) fprintf(vfile, " %s ", fileDate); 3519 } 3520 3521 3522 /* 3523 * checkdir - Attempt to ensure that the path represented in name 3524 * exists, and return 1 if this is true and name itself is a 3525 * directory. 3526 * Return 0 if this path cannot be created or if name is not 3527 * a directory. 3528 */ 3529 3530 static int 3531 checkdir(char *name) 3532 { 3533 char lastChar; /* the last character in name */ 3534 char *cp; /* scratch pointer into name */ 3535 char *firstSlash = NULL; /* first slash in name */ 3536 char *lastSlash = NULL; /* last slash in name */ 3537 int nameLen; /* length of name */ 3538 int trailingSlash; /* true if name ends in slash */ 3539 int leadingSlash; /* true if name begins with slash */ 3540 int markedDir; /* true if name denotes a directory */ 3541 int success; /* status of makeDir call */ 3542 3543 3544 /* 3545 * Scan through the name, and locate first and last slashes. 3546 */ 3547 3548 for (cp = name; *cp; cp++) { 3549 if (*cp == '/') { 3550 if (! firstSlash) { 3551 firstSlash = cp; 3552 } 3553 lastSlash = cp; 3554 } 3555 } 3556 3557 /* 3558 * Determine what you can from the proceeds of the scan. 3559 */ 3560 3561 lastChar = *(cp - 1); 3562 nameLen = (int)(cp - name); 3563 trailingSlash = (lastChar == '/'); 3564 leadingSlash = (*name == '/'); 3565 markedDir = (dblock.dbuf.typeflag == '5' || trailingSlash); 3566 3567 if (! lastSlash && ! markedDir) { 3568 /* 3569 * The named file does not have any subdrectory 3570 * structure; just bail out. 3571 */ 3572 3573 return (0); 3574 } 3575 3576 /* 3577 * Make sure that name doesn`t end with slash for the loop. 3578 * This ensures that the makeDir attempt after the loop is 3579 * meaningful. 3580 */ 3581 3582 if (trailingSlash) { 3583 name[nameLen-1] = '\0'; 3584 } 3585 3586 /* 3587 * Make the path one component at a time. 3588 */ 3589 3590 for (cp = strchr(leadingSlash ? name+1 : name, '/'); 3591 cp; 3592 cp = strchr(cp+1, '/')) { 3593 *cp = '\0'; 3594 success = makeDir(name); 3595 *cp = '/'; 3596 3597 if (!success) { 3598 name[nameLen-1] = lastChar; 3599 return (0); 3600 } 3601 } 3602 3603 /* 3604 * This makes the last component of the name, if it is a 3605 * directory. 3606 */ 3607 3608 if (markedDir) { 3609 if (! makeDir(name)) { 3610 name[nameLen-1] = lastChar; 3611 return (0); 3612 } 3613 } 3614 3615 name[nameLen-1] = (lastChar == '/') ? '\0' : lastChar; 3616 return (markedDir); 3617 } 3618 3619 /* 3620 * resugname - Restore the user name and group name. Search the NIS 3621 * before using the uid and gid. 3622 * (It is presumed that an archive entry cannot be 3623 * simultaneously a symlink and some other type.) 3624 */ 3625 3626 static void 3627 resugname(int dirfd, /* dir fd file resides in */ 3628 char *name, /* name of the file to be modified */ 3629 int symflag) /* true if file is a symbolic link */ 3630 { 3631 uid_t duid; 3632 gid_t dgid; 3633 struct stat *sp = &stbuf; 3634 char *u_g_name; 3635 3636 if (checkflag == 1) { /* Extended tar format and euid == 0 */ 3637 3638 /* 3639 * Try and extract the intended uid and gid from the name 3640 * service before believing the uid and gid in the header. 3641 * 3642 * In the case where we archived a setuid or setgid file 3643 * owned by someone with a large uid, then it will 3644 * have made it into the archive with a uid of nobody. If 3645 * the corresponding username doesn't appear to exist, then we 3646 * want to make sure it *doesn't* end up as setuid nobody! 3647 * 3648 * Our caller will print an error message about the fact 3649 * that the restore didn't work out quite right .. 3650 */ 3651 if (xhdr_flgs & _X_UNAME) 3652 u_g_name = Xtarhdr.x_uname; 3653 else 3654 u_g_name = dblock.dbuf.uname; 3655 if ((duid = getuidbyname(u_g_name)) == -1) { 3656 if (S_ISREG(sp->st_mode) && sp->st_uid == UID_NOBODY && 3657 (sp->st_mode & S_ISUID) == S_ISUID) 3658 (void) chmod(name, 3659 MODEMASK & sp->st_mode & ~S_ISUID); 3660 duid = sp->st_uid; 3661 } 3662 3663 /* (Ditto for gids) */ 3664 3665 if (xhdr_flgs & _X_GNAME) 3666 u_g_name = Xtarhdr.x_gname; 3667 else 3668 u_g_name = dblock.dbuf.gname; 3669 if ((dgid = getgidbyname(u_g_name)) == -1) { 3670 if (S_ISREG(sp->st_mode) && sp->st_gid == GID_NOBODY && 3671 (sp->st_mode & S_ISGID) == S_ISGID) 3672 (void) chmod(name, 3673 MODEMASK & sp->st_mode & ~S_ISGID); 3674 dgid = sp->st_gid; 3675 } 3676 } else if (checkflag == 2) { /* tar format and euid == 0 */ 3677 duid = sp->st_uid; 3678 dgid = sp->st_gid; 3679 } 3680 if ((checkflag == 1) || (checkflag == 2)) 3681 (void) fchownat(dirfd, name, duid, dgid, symflag); 3682 } 3683 3684 /*ARGSUSED*/ 3685 static void 3686 onintr(int sig) 3687 { 3688 (void) signal(SIGINT, SIG_IGN); 3689 term++; 3690 } 3691 3692 /*ARGSUSED*/ 3693 static void 3694 onquit(int sig) 3695 { 3696 (void) signal(SIGQUIT, SIG_IGN); 3697 term++; 3698 } 3699 3700 /*ARGSUSED*/ 3701 static void 3702 onhup(int sig) 3703 { 3704 (void) signal(SIGHUP, SIG_IGN); 3705 term++; 3706 } 3707 3708 static void 3709 tomodes(struct stat *sp) 3710 { 3711 uid_t uid; 3712 gid_t gid; 3713 3714 bzero(dblock.dummy, TBLOCK); 3715 3716 /* 3717 * If the uid or gid is too large, we can't put it into 3718 * the archive. We could fail to put anything in the 3719 * archive at all .. but most of the time the name service 3720 * will save the day when we do a lookup at restore time. 3721 * 3722 * Instead we choose a "safe" uid and gid, and fix up whether 3723 * or not the setuid and setgid bits are left set to extraction 3724 * time. 3725 */ 3726 if (Eflag) { 3727 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) { 3728 xhdr_flgs |= _X_UID; 3729 Xtarhdr.x_uid = uid; 3730 } 3731 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) { 3732 xhdr_flgs |= _X_GID; 3733 Xtarhdr.x_gid = gid; 3734 } 3735 if (sp->st_size > TAR_OFFSET_MAX) { 3736 xhdr_flgs |= _X_SIZE; 3737 Xtarhdr.x_filesz = sp->st_size; 3738 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3739 (off_t)0); 3740 } else 3741 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3742 sp->st_size); 3743 } else { 3744 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3745 sp->st_size); 3746 } 3747 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) 3748 uid = UID_NOBODY; 3749 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) 3750 gid = GID_NOBODY; 3751 (void) sprintf(dblock.dbuf.gid, "%07lo", gid); 3752 (void) sprintf(dblock.dbuf.uid, "%07lo", uid); 3753 (void) sprintf(dblock.dbuf.mode, "%07lo", sp->st_mode & POSIXMODES); 3754 (void) sprintf(dblock.dbuf.mtime, "%011lo", sp->st_mtime); 3755 } 3756 3757 static int 3758 #ifdef EUC 3759 /* 3760 * Warning: the result of this function depends whether 'char' is a 3761 * signed or unsigned data type. This a source of potential 3762 * non-portability among heterogeneous systems. It is retained here 3763 * for backward compatibility. 3764 */ 3765 checksum_signed(union hblock *dblockp) 3766 #else 3767 checksum(union hblock *dblockp) 3768 #endif /* EUC */ 3769 { 3770 int i; 3771 char *cp; 3772 3773 for (cp = dblockp->dbuf.chksum; 3774 cp < &dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]; cp++) 3775 *cp = ' '; 3776 i = 0; 3777 for (cp = dblockp->dummy; cp < &(dblockp->dummy[TBLOCK]); cp++) 3778 i += *cp; 3779 return (i); 3780 } 3781 3782 #ifdef EUC 3783 /* 3784 * Generate unsigned checksum, regardless of what C compiler is 3785 * used. Survives in the face of arbitrary 8-bit clean filenames, 3786 * e.g., internationalized filenames. 3787 */ 3788 static int 3789 checksum(union hblock *dblockp) 3790 { 3791 unsigned i; 3792 unsigned char *cp; 3793 3794 for (cp = (unsigned char *) dblockp->dbuf.chksum; 3795 cp < (unsigned char *) 3796 &(dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]); cp++) 3797 *cp = ' '; 3798 i = 0; 3799 for (cp = (unsigned char *) dblockp->dummy; 3800 cp < (unsigned char *) &(dblockp->dummy[TBLOCK]); cp++) 3801 i += *cp; 3802 3803 return (i); 3804 } 3805 #endif /* EUC */ 3806 3807 /* 3808 * If the w flag is set, output the action to be taken and the name of the 3809 * file. Perform the action if the user response is affirmative. 3810 */ 3811 3812 static int 3813 checkw(char c, char *name) 3814 { 3815 if (wflag) { 3816 (void) fprintf(vfile, "%c ", c); 3817 if (vflag) 3818 longt(&stbuf, ' '); /* do we have acl info here */ 3819 (void) fprintf(vfile, "%s: ", name); 3820 if (response() == 'y') { 3821 return (1); 3822 } 3823 return (0); 3824 } 3825 return (1); 3826 } 3827 3828 /* 3829 * When the F flag is set, exclude RCS and SCCS directories. If F is set 3830 * twice, also exclude .o files, and files names errs, core, and a.out. 3831 */ 3832 3833 static int 3834 checkf(char *name, int mode, int howmuch) 3835 { 3836 int l; 3837 3838 if ((mode & S_IFMT) == S_IFDIR) { 3839 if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0)) 3840 return (0); 3841 return (1); 3842 } 3843 if ((l = (int)strlen(name)) < 3) 3844 return (1); 3845 if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 3846 return (0); 3847 if (howmuch > 1) { 3848 if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 || 3849 strcmp(name, "a.out") == 0) 3850 return (0); 3851 } 3852 3853 /* SHOULD CHECK IF IT IS EXECUTABLE */ 3854 return (1); 3855 } 3856 3857 static int 3858 response(void) 3859 { 3860 int c; 3861 3862 c = getchar(); 3863 if (c != '\n') 3864 while (getchar() != '\n'); 3865 else c = 'n'; 3866 return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c); 3867 } 3868 3869 /* Has file been modified since being put into archive? If so, return > 0. */ 3870 3871 static int 3872 checkupdate(char *arg) 3873 { 3874 char name[PATH_MAX+1]; 3875 time_t mtime; 3876 long nsecs; 3877 off_t seekp; 3878 static off_t lookup(char *); 3879 3880 rewind(tfile); 3881 if ((seekp = lookup(arg)) < 0) 3882 return (1); 3883 (void) fseek(tfile, seekp, 0); 3884 (void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs); 3885 3886 /* 3887 * Unless nanoseconds were stored in the file, only use seconds for 3888 * comparison of time. Nanoseconds are stored when -E is specified. 3889 */ 3890 if (Eflag == 0) 3891 return (stbuf.st_mtime > mtime); 3892 3893 if ((stbuf.st_mtime < mtime) || 3894 ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs))) 3895 return (0); 3896 return (1); 3897 } 3898 3899 3900 /* 3901 * newvol get new floppy (or tape) volume 3902 * 3903 * newvol(); resets tapepos and first to TRUE, prompts for 3904 * for new volume, and waits. 3905 * if dumping, end-of-file is written onto the tape. 3906 */ 3907 3908 static void 3909 newvol(void) 3910 { 3911 int c; 3912 3913 if (dumping) { 3914 #ifdef DEBUG 3915 DEBUG("newvol called with 'dumping' set\n", 0, 0); 3916 #endif 3917 putempty((blkcnt_t)2); /* 2 EOT marks */ 3918 closevol(); 3919 flushtape(); 3920 sync(); 3921 tapepos = 0; 3922 } else 3923 first = TRUE; 3924 if (close(mt) != 0) 3925 vperror(2, gettext("close error")); 3926 mt = 0; 3927 (void) fprintf(stderr, gettext( 3928 "tar: \007please insert new volume, then press RETURN.")); 3929 (void) fseek(stdin, (off_t)0, 2); /* scan over read-ahead */ 3930 while ((c = getchar()) != '\n' && ! term) 3931 if (c == EOF) 3932 done(Errflg); 3933 if (term) 3934 done(Errflg); 3935 3936 errno = 0; 3937 3938 if (strcmp(usefile, "-") == 0) { 3939 mt = dup(1); 3940 } else { 3941 mt = open(usefile, dumping ? update : 0); 3942 } 3943 3944 if (mt < 0) { 3945 (void) fprintf(stderr, gettext( 3946 "tar: cannot reopen %s (%s)\n"), 3947 dumping ? gettext("output") : gettext("input"), usefile); 3948 3949 (void) fprintf(stderr, "update=%d, usefile=%s, mt=%d, [%s]\n", 3950 update, usefile, mt, strerror(errno)); 3951 3952 done(2); 3953 } 3954 } 3955 3956 /* 3957 * Write a trailer portion to close out the current output volume. 3958 */ 3959 3960 static void 3961 closevol(void) 3962 { 3963 if (mulvol) { 3964 /* 3965 * blocklim does not count the 2 EOT marks; 3966 * tapepos does count the 2 EOT marks; 3967 * therefore we need the +2 below. 3968 */ 3969 putempty(blocklim + (blkcnt_t)2 - tapepos); 3970 } 3971 } 3972 3973 static void 3974 done(int n) 3975 { 3976 (void) unlink(tname); 3977 if (mt > 0) { 3978 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 3979 perror(gettext("tar: close error")); 3980 exit(2); 3981 } 3982 } 3983 exit(n); 3984 } 3985 3986 /* 3987 * Determine if s1 is a prefix portion of s2 (or the same as s2). 3988 */ 3989 3990 static int 3991 is_prefix(char *s1, char *s2) 3992 { 3993 while (*s1) 3994 if (*s1++ != *s2++) 3995 return (0); 3996 if (*s2) 3997 return (*s2 == '/'); 3998 return (1); 3999 } 4000 4001 /* 4002 * lookup and bsrch look through tfile entries to find a match for a name. 4003 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 4004 * a pair of newline chars, so the buffer it uses must be long enough for 4005 * two lines: name and modification time as well as period, newline and space. 4006 * 4007 * A kludge was added to bsrch to take care of matching on the first entry 4008 * in the file--there is no leading newline. So, if we are reading from the 4009 * start of the file, read into byte two and set the first byte to a newline. 4010 * Otherwise, the first entry cannot be matched. 4011 * 4012 */ 4013 4014 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 4015 static off_t 4016 lookup(char *s) 4017 { 4018 int i; 4019 off_t a; 4020 4021 for (i = 0; s[i]; i++) 4022 if (s[i] == ' ') 4023 break; 4024 a = bsrch(s, i, low, high); 4025 return (a); 4026 } 4027 4028 static off_t 4029 bsrch(char *s, int n, off_t l, off_t h) 4030 { 4031 int i, j; 4032 char b[N]; 4033 off_t m, m1; 4034 4035 4036 loop: 4037 if (l >= h) 4038 return ((off_t)-1); 4039 m = l + (h-l)/2 - N/2; 4040 if (m < l) 4041 m = l; 4042 (void) fseek(tfile, m, 0); 4043 if (m == 0) { 4044 (void) fread(b+1, 1, N-1, tfile); 4045 b[0] = '\n'; 4046 m--; 4047 } else 4048 (void) fread(b, 1, N, tfile); 4049 for (i = 0; i < N; i++) { 4050 if (b[i] == '\n') 4051 break; 4052 m++; 4053 } 4054 if (m >= h) 4055 return ((off_t)-1); 4056 m1 = m; 4057 j = i; 4058 for (i++; i < N; i++) { 4059 m1++; 4060 if (b[i] == '\n') 4061 break; 4062 } 4063 i = cmp(b+j, s, n); 4064 if (i < 0) { 4065 h = m; 4066 goto loop; 4067 } 4068 if (i > 0) { 4069 l = m1; 4070 goto loop; 4071 } 4072 if (m < 0) 4073 m = 0; 4074 return (m); 4075 } 4076 4077 static int 4078 cmp(char *b, char *s, int n) 4079 { 4080 int i; 4081 4082 assert(b[0] == '\n'); 4083 4084 for (i = 0; i < n; i++) { 4085 if (b[i+1] > s[i]) 4086 return (-1); 4087 if (b[i+1] < s[i]) 4088 return (1); 4089 } 4090 return (b[i+1] == ' '? 0 : -1); 4091 } 4092 4093 4094 /* 4095 * seekdisk seek to next file on archive 4096 * 4097 * called by passtape() only 4098 * 4099 * WARNING: expects "nblock" to be set, that is, readtape() to have 4100 * already been called. Since passtape() is only called 4101 * after a file header block has been read (why else would 4102 * we skip to next file?), this is currently safe. 4103 * 4104 * changed to guarantee SYS_BLOCK boundary 4105 */ 4106 4107 static void 4108 seekdisk(blkcnt_t blocks) 4109 { 4110 off_t seekval; 4111 #if SYS_BLOCK > TBLOCK 4112 /* handle non-multiple of SYS_BLOCK */ 4113 blkcnt_t nxb; /* # extra blocks */ 4114 #endif 4115 4116 tapepos += blocks; 4117 #ifdef DEBUG 4118 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 4119 #endif 4120 if (recno + blocks <= nblock) { 4121 recno += blocks; 4122 return; 4123 } 4124 if (recno > nblock) 4125 recno = nblock; 4126 seekval = (off_t)blocks - (nblock - recno); 4127 recno = nblock; /* so readtape() reads next time through */ 4128 #if SYS_BLOCK > TBLOCK 4129 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 4130 #ifdef DEBUG 4131 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 4132 nxb, seekval); 4133 #endif 4134 if (nxb && nxb > seekval) /* don't seek--we'll read */ 4135 goto noseek; 4136 seekval -= nxb; /* don't seek quite so far */ 4137 #endif 4138 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 4139 (void) fprintf(stderr, gettext( 4140 "tar: device seek error\n")); 4141 done(3); 4142 } 4143 #if SYS_BLOCK > TBLOCK 4144 /* read those extra blocks */ 4145 noseek: 4146 if (nxb) { 4147 #ifdef DEBUG 4148 DEBUG("reading extra blocks\n", 0, 0); 4149 #endif 4150 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 4151 (void) fprintf(stderr, gettext( 4152 "tar: read error while skipping file\n")); 4153 done(8); 4154 } 4155 recno = nxb; /* so we don't read in next readtape() */ 4156 } 4157 #endif 4158 } 4159 4160 static void 4161 readtape(char *buffer) 4162 { 4163 int i, j; 4164 4165 ++tapepos; 4166 if (recno >= nblock || first) { 4167 if (first) { 4168 /* 4169 * set the number of blocks to read initially, based on 4170 * the defined defaults for the device, or on the 4171 * explicit block factor given. 4172 */ 4173 if (bflag || defaults_used) 4174 j = nblock; 4175 else 4176 j = NBLOCK; 4177 } else 4178 j = nblock; 4179 4180 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 4181 (void) fprintf(stderr, gettext( 4182 "tar: tape read error\n")); 4183 done(3); 4184 /* 4185 * i == 0 means EOF reached and !rflag means that when 4186 * tar command uses 'r' as a function letter, we are trying 4187 * to update or replace an empty tar file which will fail. 4188 * So this fix is not for 'r' function letter. 4189 */ 4190 } else if (i == 0 && !rflag) { 4191 if (first) { 4192 (void) fprintf(stderr, gettext( 4193 "tar: blocksize = %d\n"), i); 4194 done(Errflg); 4195 } 4196 else 4197 mterr("read", 0, 2); 4198 } else if ((!first || Bflag) && i != TBLOCK*j) { 4199 /* 4200 * Short read - try to get the remaining bytes. 4201 */ 4202 4203 int remaining = (TBLOCK * j) - i; 4204 char *b = (char *)tbuf + i; 4205 int r; 4206 4207 do { 4208 if ((r = read(mt, b, remaining)) < 0) { 4209 (void) fprintf(stderr, 4210 gettext("tar: tape read error\n")); 4211 done(3); 4212 } 4213 b += r; 4214 remaining -= r; 4215 i += r; 4216 } while (remaining > 0 && r != 0); 4217 } 4218 if (first) { 4219 if ((i % TBLOCK) != 0) { 4220 (void) fprintf(stderr, gettext( 4221 "tar: tape blocksize error\n")); 4222 done(3); 4223 } 4224 i /= TBLOCK; 4225 if (vflag && i != nblock && i != 1) { 4226 if (!NotTape) 4227 (void) fprintf(stderr, gettext( 4228 "tar: blocksize = %d\n"), i); 4229 } 4230 4231 /* 4232 * If we are reading a tape, then a short read is 4233 * understood to signify that the amount read is 4234 * the tape's actual blocking factor. We adapt 4235 * nblock accordingly. There is no reason to do 4236 * this when the device is not blocked. 4237 */ 4238 4239 if (!NotTape) 4240 nblock = i; 4241 } 4242 recno = 0; 4243 } 4244 4245 first = FALSE; 4246 copy(buffer, &tbuf[recno++]); 4247 } 4248 4249 4250 /* 4251 * replacement for writetape. 4252 */ 4253 4254 static int 4255 writetbuf(char *buffer, int n) 4256 { 4257 int i; 4258 4259 tapepos += n; /* output block count */ 4260 4261 if (recno >= nblock) { 4262 i = write(mt, (char *)tbuf, TBLOCK*nblock); 4263 if (i != TBLOCK*nblock) 4264 mterr("write", i, 2); 4265 recno = 0; 4266 } 4267 4268 /* 4269 * Special case: We have an empty tape buffer, and the 4270 * users data size is >= the tape block size: Avoid 4271 * the bcopy and dma direct to tape. BIG WIN. Add the 4272 * residual to the tape buffer. 4273 */ 4274 while (recno == 0 && n >= nblock) { 4275 i = (int)write(mt, buffer, TBLOCK*nblock); 4276 if (i != TBLOCK*nblock) 4277 mterr("write", i, 2); 4278 n -= nblock; 4279 buffer += (nblock * TBLOCK); 4280 } 4281 4282 while (n-- > 0) { 4283 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 4284 buffer += TBLOCK; 4285 if (recno >= nblock) { 4286 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 4287 if (i != TBLOCK*nblock) 4288 mterr("write", i, 2); 4289 recno = 0; 4290 } 4291 } 4292 4293 /* Tell the user how much to write to get in sync */ 4294 return (nblock - recno); 4295 } 4296 4297 /* 4298 * backtape - reposition tape after reading soft "EOF" record 4299 * 4300 * Backtape tries to reposition the tape back over the EOF 4301 * record. This is for the 'u' and 'r' function letters so that the 4302 * tape can be extended. This code is not well designed, but 4303 * I'm confident that the only callers who care about the 4304 * backspace-over-EOF feature are those involved in 'u' and 'r'. 4305 * 4306 * The proper way to backup the tape is through the use of mtio. 4307 * Earlier spins used lseek combined with reads in a confusing 4308 * maneuver that only worked on 4.x, but shouldn't have, even 4309 * there. Lseeks are explicitly not supported for tape devices. 4310 */ 4311 4312 static void 4313 backtape(void) 4314 { 4315 struct mtop mtcmd; 4316 #ifdef DEBUG 4317 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 4318 nblock); 4319 #endif 4320 /* 4321 * Backup to the position in the archive where the record 4322 * currently sitting in the tbuf buffer is situated. 4323 */ 4324 4325 if (NotTape) { 4326 /* 4327 * For non-tape devices, this means lseeking to the 4328 * correct position. The absolute location tapepos-recno 4329 * should be the beginning of the current record. 4330 */ 4331 4332 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 4333 (off_t)-1) { 4334 (void) fprintf(stderr, 4335 gettext("tar: lseek to end of archive failed\n")); 4336 done(4); 4337 } 4338 } else { 4339 /* 4340 * For tape devices, we backup over the most recently 4341 * read record. 4342 */ 4343 4344 mtcmd.mt_op = MTBSR; 4345 mtcmd.mt_count = 1; 4346 4347 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 4348 (void) fprintf(stderr, 4349 gettext("tar: backspace over record failed\n")); 4350 done(4); 4351 } 4352 } 4353 4354 /* 4355 * Decrement the tape and tbuf buffer indices to prepare for the 4356 * coming write to overwrite the soft EOF record. 4357 */ 4358 4359 recno--; 4360 tapepos--; 4361 } 4362 4363 4364 /* 4365 * flushtape write buffered block(s) onto tape 4366 * 4367 * recno points to next free block in tbuf. If nonzero, a write is done. 4368 * Care is taken to write in multiples of SYS_BLOCK when device is 4369 * non-magtape in case raw i/o is used. 4370 * 4371 * NOTE: this is called by writetape() to do the actual writing 4372 */ 4373 4374 static void 4375 flushtape(void) 4376 { 4377 #ifdef DEBUG 4378 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 4379 #endif 4380 if (recno > 0) { /* anything buffered? */ 4381 if (NotTape) { 4382 #if SYS_BLOCK > TBLOCK 4383 int i; 4384 4385 /* 4386 * an odd-block write can only happen when 4387 * we are at the end of a volume that is not a tape. 4388 * Here we round recno up to an even SYS_BLOCK 4389 * boundary. 4390 */ 4391 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 4392 #ifdef DEBUG 4393 DEBUG("flushtape() %d rounding blocks\n", i, 0); 4394 #endif 4395 recno += i; /* round up to even SYS_BLOCK */ 4396 } 4397 #endif 4398 if (recno > nblock) 4399 recno = nblock; 4400 } 4401 #ifdef DEBUG 4402 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 4403 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 4404 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 4405 #endif 4406 if (write(mt, tbuf, 4407 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 4408 (void) fprintf(stderr, gettext( 4409 "tar: tape write error\n")); 4410 done(2); 4411 } 4412 recno = 0; 4413 } 4414 } 4415 4416 static void 4417 copy(void *dst, void *src) 4418 { 4419 (void) memcpy(dst, src, TBLOCK); 4420 } 4421 4422 #ifdef _iBCS2 4423 /* 4424 * initarg -- initialize things for nextarg. 4425 * 4426 * argv filename list, a la argv. 4427 * filefile name of file containing filenames. Unless doing 4428 * a create, seeks must be allowable (e.g. no named pipes). 4429 * 4430 * - if filefile is non-NULL, it will be used first, and argv will 4431 * be used when the data in filefile are exhausted. 4432 * - otherwise argv will be used. 4433 */ 4434 static char **Cmdargv = NULL; 4435 static FILE *FILEFile = NULL; 4436 static long seekFile = -1; 4437 static char *ptrtoFile, *begofFile, *endofFile; 4438 4439 static void 4440 initarg(char *argv[], char *filefile) 4441 { 4442 struct stat statbuf; 4443 char *p; 4444 int nbytes; 4445 4446 Cmdargv = argv; 4447 if (filefile == NULL) 4448 return; /* no -F file */ 4449 if (FILEFile != NULL) { 4450 /* 4451 * need to REinitialize 4452 */ 4453 if (seekFile != -1) 4454 (void) fseek(FILEFile, seekFile, 0); 4455 ptrtoFile = begofFile; 4456 return; 4457 } 4458 /* 4459 * first time initialization 4460 */ 4461 if ((FILEFile = fopen(filefile, "r")) == NULL) 4462 fatal(gettext("cannot open (%s)"), filefile); 4463 (void) fstat(fileno(FILEFile), &statbuf); 4464 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 4465 (void) fprintf(stderr, gettext( 4466 "tar: %s is not a regular file\n"), filefile); 4467 (void) fclose(FILEFile); 4468 done(1); 4469 } 4470 ptrtoFile = begofFile = endofFile; 4471 seekFile = 0; 4472 if (!xflag) 4473 return; /* the file will be read only once anyway */ 4474 nbytes = statbuf.st_size; 4475 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 4476 nbytes -= 20; 4477 if (nbytes < 50) { 4478 free(begofFile); 4479 begofFile = endofFile; 4480 return; /* no room so just do plain reads */ 4481 } 4482 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 4483 fatal(gettext("could not read %s"), filefile); 4484 ptrtoFile = begofFile; 4485 endofFile = begofFile + nbytes; 4486 for (p = begofFile; p < endofFile; ++p) 4487 if (*p == '\n') 4488 *p = '\0'; 4489 if (nbytes != statbuf.st_size) 4490 seekFile = nbytes + 1; 4491 else 4492 (void) fclose(FILEFile); 4493 } 4494 4495 /* 4496 * nextarg -- get next argument of arglist. 4497 * 4498 * The argument is taken from wherever is appropriate. 4499 * 4500 * If the 'F file' function modifier has been specified, the argument 4501 * will be taken from the file, unless EOF has been reached. 4502 * Otherwise the argument will be taken from argv. 4503 * 4504 * WARNING: 4505 * Return value may point to static data, whose contents are over- 4506 * written on each call. 4507 */ 4508 static char * 4509 nextarg(void) 4510 { 4511 static char nameFile[PATH_MAX + 1]; 4512 int n; 4513 char *p; 4514 4515 if (FILEFile) { 4516 if (ptrtoFile < endofFile) { 4517 p = ptrtoFile; 4518 while (*ptrtoFile) 4519 ++ptrtoFile; 4520 ++ptrtoFile; 4521 return (p); 4522 } 4523 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 4524 n = strlen(nameFile); 4525 if (n > 0 && nameFile[n-1] == '\n') 4526 nameFile[n-1] = '\0'; 4527 return (nameFile); 4528 } 4529 } 4530 return (*Cmdargv++); 4531 } 4532 #endif /* _iBCS2 */ 4533 4534 /* 4535 * kcheck() 4536 * - checks the validity of size values for non-tape devices 4537 * - if size is zero, mulvol tar is disabled and size is 4538 * assumed to be infinite. 4539 * - returns volume size in TBLOCKS 4540 */ 4541 4542 static blkcnt_t 4543 kcheck(char *kstr) 4544 { 4545 blkcnt_t kval; 4546 4547 kval = strtoll(kstr, NULL, 0); 4548 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 4549 mulvol = 0; /* definitely not mulvol, but we must */ 4550 return (0); /* took out setting of NotTape */ 4551 } 4552 if (kval < (blkcnt_t)MINSIZE) { 4553 (void) fprintf(stderr, gettext( 4554 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 4555 ").\n"), (ulong_t)MINSIZE, kval); 4556 if (!kflag) 4557 (void) fprintf(stderr, gettext( 4558 "bad size entry for %s in %s.\n"), 4559 archive, DEF_FILE); 4560 done(1); 4561 } 4562 mulvol++; 4563 NotTape++; /* implies non-tape */ 4564 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 4565 } 4566 4567 4568 /* 4569 * bcheck() 4570 * - checks the validity of blocking factors 4571 * - returns blocking factor 4572 */ 4573 4574 static int 4575 bcheck(char *bstr) 4576 { 4577 blkcnt_t bval; 4578 4579 bval = strtoll(bstr, NULL, 0); 4580 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 4581 (void) fprintf(stderr, gettext( 4582 "tar: invalid blocksize \"%s\".\n"), bstr); 4583 if (!bflag) 4584 (void) fprintf(stderr, gettext( 4585 "bad blocksize entry for '%s' in %s.\n"), 4586 archive, DEF_FILE); 4587 done(1); 4588 } 4589 4590 return ((int)bval); 4591 } 4592 4593 4594 /* 4595 * defset() 4596 * - reads DEF_FILE for the set of default values specified. 4597 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 4598 * - 'usefile' points to static data, so will be overwritten 4599 * if this routine is called a second time. 4600 * - the pattern specified by 'arch' must be followed by four 4601 * blank-separated fields (1) device (2) blocking, 4602 * (3) size(K), and (4) tape 4603 * for example: archive0=/dev/fd 1 400 n 4604 */ 4605 4606 static int 4607 defset(char *arch) 4608 { 4609 char *bp; 4610 4611 if (defopen(DEF_FILE) != 0) 4612 return (FALSE); 4613 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 4614 (void) fprintf(stderr, gettext( 4615 "tar: error setting parameters for %s.\n"), DEF_FILE); 4616 return (FALSE); /* & following ones too */ 4617 } 4618 if ((bp = defread(arch)) == NULL) { 4619 (void) fprintf(stderr, gettext( 4620 "tar: missing or invalid '%s' entry in %s.\n"), 4621 arch, DEF_FILE); 4622 return (FALSE); 4623 } 4624 if ((usefile = strtok(bp, " \t")) == NULL) { 4625 (void) fprintf(stderr, gettext( 4626 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 4627 return (FALSE); 4628 } 4629 if ((bp = strtok(NULL, " \t")) == NULL) { 4630 (void) fprintf(stderr, gettext( 4631 "tar: block component missing in '%s' entry in %s.\n"), 4632 arch, DEF_FILE); 4633 return (FALSE); 4634 } 4635 nblock = bcheck(bp); 4636 if ((bp = strtok(NULL, " \t")) == NULL) { 4637 (void) fprintf(stderr, gettext( 4638 "tar: size component missing in '%s' entry in %s.\n"), 4639 arch, DEF_FILE); 4640 return (FALSE); 4641 } 4642 blocklim = kcheck(bp); 4643 if ((bp = strtok(NULL, " \t")) != NULL) 4644 NotTape = (*bp == 'n' || *bp == 'N'); 4645 else 4646 NotTape = (blocklim != 0); 4647 (void) defopen(NULL); 4648 #ifdef DEBUG 4649 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 4650 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 4651 nblock, blocklim); 4652 DEBUG("defset: not tape = %d\n", NotTape, 0); 4653 #endif 4654 return (TRUE); 4655 } 4656 4657 4658 /* 4659 * Following code handles excluded and included files. 4660 * A hash table of file names to be {in,ex}cluded is built. 4661 * For excluded files, before writing or extracting a file 4662 * check to see if it is in the exclude_tbl. 4663 * For included files, the wantit() procedure will check to 4664 * see if the named file is in the include_tbl. 4665 */ 4666 4667 static void 4668 build_table(struct file_list *table[], char *file) 4669 { 4670 FILE *fp; 4671 char buf[PATH_MAX + 1]; 4672 4673 if ((fp = fopen(file, "r")) == (FILE *)NULL) 4674 vperror(1, gettext("could not open %s"), file); 4675 while (fgets(buf, sizeof (buf), fp) != NULL) { 4676 if (buf[strlen(buf) - 1] == '\n') 4677 buf[strlen(buf) - 1] = '\0'; 4678 /* Only add to table if line has something in it */ 4679 if (strspn(buf, " \t") != strlen(buf)) 4680 add_file_to_table(table, buf); 4681 } 4682 (void) fclose(fp); 4683 } 4684 4685 4686 /* 4687 * Add a file name to the the specified table, if the file name has any 4688 * trailing '/'s then delete them before inserting into the table 4689 */ 4690 4691 static void 4692 add_file_to_table(struct file_list *table[], char *str) 4693 { 4694 char name[PATH_MAX + 1]; 4695 unsigned int h; 4696 struct file_list *exp; 4697 4698 (void) strcpy(name, str); 4699 while (name[strlen(name) - 1] == '/') { 4700 name[strlen(name) - 1] = NULL; 4701 } 4702 4703 h = hash(name); 4704 if ((exp = (struct file_list *)calloc(sizeof (struct file_list), 4705 sizeof (char))) == NULL) { 4706 (void) fprintf(stderr, gettext( 4707 "tar: out of memory, exclude/include table(entry)\n")); 4708 exit(1); 4709 } 4710 4711 if ((exp->name = strdup(name)) == NULL) { 4712 (void) fprintf(stderr, gettext( 4713 "tar: out of memory, exclude/include table(file name)\n")); 4714 exit(1); 4715 } 4716 4717 exp->next = table[h]; 4718 table[h] = exp; 4719 } 4720 4721 4722 /* 4723 * See if a file name or any of the file's parent directories is in the 4724 * specified table, if the file name has any trailing '/'s then delete 4725 * them before searching the table 4726 */ 4727 4728 static int 4729 is_in_table(struct file_list *table[], char *str) 4730 { 4731 char name[PATH_MAX + 1]; 4732 unsigned int h; 4733 struct file_list *exp; 4734 char *ptr; 4735 4736 (void) strcpy(name, str); 4737 while (name[strlen(name) - 1] == '/') { 4738 name[strlen(name) - 1] = NULL; 4739 } 4740 4741 /* 4742 * check for the file name in the passed list 4743 */ 4744 h = hash(name); 4745 exp = table[h]; 4746 while (exp != NULL) { 4747 if (strcmp(name, exp->name) == 0) { 4748 return (1); 4749 } 4750 exp = exp->next; 4751 } 4752 4753 /* 4754 * check for any parent directories in the file list 4755 */ 4756 while ((ptr = strrchr(name, '/'))) { 4757 *ptr = NULL; 4758 h = hash(name); 4759 exp = table[h]; 4760 while (exp != NULL) { 4761 if (strcmp(name, exp->name) == 0) { 4762 return (1); 4763 } 4764 exp = exp->next; 4765 } 4766 } 4767 4768 return (0); 4769 } 4770 4771 4772 /* 4773 * Compute a hash from a string. 4774 */ 4775 4776 static unsigned int 4777 hash(char *str) 4778 { 4779 char *cp; 4780 unsigned int h; 4781 4782 h = 0; 4783 for (cp = str; *cp; cp++) { 4784 h += *cp; 4785 } 4786 return (h % TABLE_SIZE); 4787 } 4788 4789 static void * 4790 getmem(size_t size) 4791 { 4792 void *p = calloc((unsigned)size, sizeof (char)); 4793 4794 if (p == NULL && freemem) { 4795 (void) fprintf(stderr, gettext( 4796 "tar: out of memory, link and directory modtime " 4797 "info lost\n")); 4798 freemem = 0; 4799 if (errflag) 4800 done(1); 4801 else 4802 Errflg = 1; 4803 } 4804 return (p); 4805 } 4806 4807 /* 4808 * vperror() --variable argument perror. 4809 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 4810 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 4811 * with the value of whatever "errno" is set to. If exit_status is not 4812 * zero, then tar exits with that error status. If errflag and exit_status 4813 * are both zero, the routine returns to where it was called and sets Errflg 4814 * to errno. 4815 */ 4816 4817 static void 4818 vperror(int exit_status, char *fmt, ...) 4819 { 4820 va_list ap; 4821 4822 va_start(ap, fmt); 4823 (void) fputs("tar: ", stderr); 4824 (void) vfprintf(stderr, fmt, ap); 4825 (void) fprintf(stderr, ": %s\n", strerror(errno)); 4826 va_end(ap); 4827 if (exit_status) 4828 done(exit_status); 4829 else 4830 if (errflag) 4831 done(errno); 4832 else 4833 Errflg = errno; 4834 } 4835 4836 4837 static void 4838 fatal(char *format, ...) 4839 { 4840 va_list ap; 4841 4842 va_start(ap, format); 4843 (void) fprintf(stderr, "tar: "); 4844 (void) vfprintf(stderr, format, ap); 4845 (void) fprintf(stderr, "\n"); 4846 va_end(ap); 4847 done(1); 4848 } 4849 4850 4851 /* 4852 * Check to make sure that argument is a char * ptr. 4853 * Actually, we just check to see that it is non-null. 4854 * If it is null, print out the message and call usage(), bailing out. 4855 */ 4856 4857 static void 4858 assert_string(char *s, char *msg) 4859 { 4860 if (s == NULL) { 4861 (void) fprintf(stderr, msg); 4862 usage(); 4863 } 4864 } 4865 4866 4867 static void 4868 mterr(char *operation, int i, int exitcode) 4869 { 4870 (void) fprintf(stderr, gettext( 4871 "tar: %s error: "), operation); 4872 if (i < 0) 4873 perror(""); 4874 else 4875 (void) fprintf(stderr, gettext("unexpected EOF\n")); 4876 done(exitcode); 4877 } 4878 4879 static int 4880 wantit(char *argv[], char **namep, char **dirp, char **component) 4881 { 4882 char **cp; 4883 int gotit; /* true if we've found a match */ 4884 4885 top: 4886 xhdr_flgs = 0; 4887 getdir(); 4888 if (Xhdrflag > 0) { 4889 if (get_xdata() != 0) { /* Xhdr items and regular header */ 4890 passtape(); 4891 return (0); /* Error--don't want to extract */ 4892 } 4893 } 4894 4895 #if defined(O_XATTR) 4896 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 4897 if (atflag || tflag) { 4898 (void) read_xattr_hdr(); 4899 } else { 4900 passtape(); 4901 } 4902 goto top; 4903 } 4904 #endif 4905 4906 /* sets *namep to point at the proper name */ 4907 check_prefix(namep, dirp, component); 4908 4909 if (endtape()) { 4910 if (Bflag) { 4911 /* 4912 * Logically at EOT - consume any extra blocks 4913 * so that write to our stdin won't fail and 4914 * emit an error message; otherwise something 4915 * like "dd if=foo.tar | (cd bar; tar xvf -)" 4916 * will produce a bogus error message from "dd". 4917 */ 4918 4919 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 4920 /* empty body */ 4921 } 4922 } 4923 return (-1); 4924 } 4925 4926 gotit = 0; 4927 4928 if ((Iflag && is_in_table(include_tbl, *namep)) || 4929 (! Iflag && *argv == NULL)) { 4930 gotit = 1; 4931 } else { 4932 for (cp = argv; *cp; cp++) { 4933 if (is_prefix(*cp, *namep)) { 4934 gotit = 1; 4935 break; 4936 } 4937 } 4938 } 4939 4940 if (! gotit) { 4941 passtape(); 4942 return (0); 4943 } 4944 4945 if (Xflag && is_in_table(exclude_tbl, *namep)) { 4946 if (vflag) { 4947 (void) fprintf(stderr, gettext("%s excluded\n"), 4948 *namep); 4949 } 4950 passtape(); 4951 return (0); 4952 } 4953 4954 return (1); 4955 } 4956 4957 4958 /* 4959 * Return through *namep a pointer to the proper fullname (i.e "<name> | 4960 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 4961 */ 4962 4963 static void 4964 check_prefix(char **namep, char **dirp, char **compp) 4965 { 4966 static char fullname[PATH_MAX + 1]; 4967 static char dir[PATH_MAX + 1]; 4968 static char component[PATH_MAX + 1]; 4969 static char savename[PATH_MAX + 1]; 4970 char *s; 4971 4972 (void) memset(dir, 0, sizeof (dir)); 4973 (void) memset(component, 0, sizeof (component)); 4974 4975 if (xhdr_flgs & _X_PATH) { 4976 (void) strcpy(fullname, Xtarhdr.x_path); 4977 } else { 4978 if (dblock.dbuf.prefix[0] != '\0') 4979 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 4980 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 4981 else 4982 (void) sprintf(fullname, "%.*s", NAMSIZ, 4983 dblock.dbuf.name); 4984 } 4985 4986 /* 4987 * Set dir and component names 4988 */ 4989 4990 get_parent(fullname, dir); 4991 4992 #if defined(O_XATTR) 4993 if (xattrp == (struct xattr_buf *)NULL) { 4994 #endif 4995 /* 4996 * Save of real name since were going to chop off the 4997 * trailing slashes. 4998 */ 4999 (void) strcpy(savename, fullname); 5000 /* 5001 * first strip of trailing slashes. 5002 */ 5003 chop_endslashes(savename); 5004 s = get_component(savename); 5005 (void) strcpy(component, s); 5006 5007 #if defined(O_XATTR) 5008 } else { 5009 (void) strcpy(fullname, xattrp->h_names); 5010 (void) strcpy(dir, fullname); 5011 (void) strcpy(component, xattrp->h_names + 5012 strlen(xattrp->h_names) + 1); 5013 } 5014 #endif 5015 *namep = fullname; 5016 *dirp = dir; 5017 *compp = component; 5018 } 5019 5020 5021 static wchar_t 5022 yesnoresponse(void) 5023 { 5024 wchar_t c; 5025 5026 c = getwchar(); 5027 if (c != '\n') 5028 while (getwchar() != '\n'); 5029 else c = 0; 5030 return (c); 5031 } 5032 5033 5034 /* 5035 * Return true if the object indicated by the file descriptor and type 5036 * is a tape device, false otherwise 5037 */ 5038 5039 static int 5040 istape(int fd, int type) 5041 { 5042 int result = 0; 5043 5044 if (type & S_IFCHR) { 5045 struct mtget mtg; 5046 5047 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 5048 result = 1; 5049 } 5050 } 5051 5052 return (result); 5053 } 5054 5055 #include <utmpx.h> 5056 5057 struct utmpx utmpx; 5058 5059 #define NMAX (sizeof (utmpx.ut_name)) 5060 5061 typedef struct cachenode { /* this struct must be zeroed before using */ 5062 struct cachenode *next; /* next in hash chain */ 5063 int val; /* the uid or gid of this entry */ 5064 int namehash; /* name's hash signature */ 5065 char name[NMAX+1]; /* the string that val maps to */ 5066 } cachenode_t; 5067 5068 #define HASHSIZE 256 5069 5070 static cachenode_t *names[HASHSIZE]; 5071 static cachenode_t *groups[HASHSIZE]; 5072 static cachenode_t *uids[HASHSIZE]; 5073 static cachenode_t *gids[HASHSIZE]; 5074 5075 static int 5076 hash_byname(char *name) 5077 { 5078 int i, c, h = 0; 5079 5080 for (i = 0; i < NMAX; i++) { 5081 c = name[i]; 5082 if (c == '\0') 5083 break; 5084 h = (h << 4) + h + c; 5085 } 5086 return (h); 5087 } 5088 5089 static cachenode_t * 5090 hash_lookup_byval(cachenode_t *table[], int val) 5091 { 5092 int h = val; 5093 cachenode_t *c; 5094 5095 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5096 if (c->val == val) 5097 return (c); 5098 } 5099 return (NULL); 5100 } 5101 5102 static cachenode_t * 5103 hash_lookup_byname(cachenode_t *table[], char *name) 5104 { 5105 int h = hash_byname(name); 5106 cachenode_t *c; 5107 5108 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5109 if (c->namehash == h && strcmp(c->name, name) == 0) 5110 return (c); 5111 } 5112 return (NULL); 5113 } 5114 5115 static cachenode_t * 5116 hash_insert(cachenode_t *table[], char *name, int value) 5117 { 5118 cachenode_t *c; 5119 int signature; 5120 5121 c = calloc(1, sizeof (cachenode_t)); 5122 if (c == NULL) { 5123 perror("malloc"); 5124 exit(1); 5125 } 5126 if (name != NULL) { 5127 (void) strncpy(c->name, name, NMAX); 5128 c->namehash = hash_byname(name); 5129 } 5130 c->val = value; 5131 if (table == uids || table == gids) 5132 signature = c->val; 5133 else 5134 signature = c->namehash; 5135 c->next = table[signature & (HASHSIZE - 1)]; 5136 table[signature & (HASHSIZE - 1)] = c; 5137 return (c); 5138 } 5139 5140 static char * 5141 getname(uid_t uid) 5142 { 5143 cachenode_t *c; 5144 5145 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 5146 struct passwd *pwent = getpwuid(uid); 5147 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 5148 } 5149 return (c->name); 5150 } 5151 5152 static char * 5153 getgroup(gid_t gid) 5154 { 5155 cachenode_t *c; 5156 5157 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 5158 struct group *grent = getgrgid(gid); 5159 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 5160 } 5161 return (c->name); 5162 } 5163 5164 static uid_t 5165 getuidbyname(char *name) 5166 { 5167 cachenode_t *c; 5168 5169 if ((c = hash_lookup_byname(names, name)) == NULL) { 5170 struct passwd *pwent = getpwnam(name); 5171 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 5172 } 5173 return ((uid_t)c->val); 5174 } 5175 5176 static gid_t 5177 getgidbyname(char *group) 5178 { 5179 cachenode_t *c; 5180 5181 if ((c = hash_lookup_byname(groups, group)) == NULL) { 5182 struct group *grent = getgrnam(group); 5183 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 5184 } 5185 return ((gid_t)c->val); 5186 } 5187 5188 /* 5189 * Build the header. 5190 * Determine whether or not an extended header is also needed. If needed, 5191 * create and write the extended header and its data. 5192 * Writing of the extended header assumes that "tomodes" has been called and 5193 * the relevant information has been placed in the header block. 5194 */ 5195 5196 static int 5197 build_dblock( 5198 const char *name, 5199 const char *linkname, 5200 const char typeflag, 5201 const int filetype, 5202 const struct stat *sp, 5203 const dev_t device, 5204 const char *prefix) 5205 { 5206 int nblks; 5207 major_t dev; 5208 const char *filename; 5209 const char *lastslash; 5210 5211 if (filetype == XATTR_FILE) 5212 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 5213 else 5214 dblock.dbuf.typeflag = typeflag; 5215 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 5216 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 5217 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 5218 5219 if (xhdr_flgs & _X_PATH) 5220 filename = Xtarhdr.x_path; 5221 else 5222 filename = name; 5223 5224 if ((dev = major(device)) > OCTAL7CHAR) { 5225 if (Eflag) { 5226 xhdr_flgs |= _X_DEVMAJOR; 5227 Xtarhdr.x_devmajor = dev; 5228 } else { 5229 (void) fprintf(stderr, gettext( 5230 "Device major too large for %s. Use -E flag."), 5231 filename); 5232 if (errflag) 5233 done(1); 5234 else 5235 Errflg = 1; 5236 } 5237 dev = 0; 5238 } 5239 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 5240 if ((dev = minor(device)) > OCTAL7CHAR) { 5241 if (Eflag) { 5242 xhdr_flgs |= _X_DEVMINOR; 5243 Xtarhdr.x_devminor = dev; 5244 } else { 5245 (void) fprintf(stderr, gettext( 5246 "Device minor too large for %s. Use -E flag."), 5247 filename); 5248 if (errflag) 5249 done(1); 5250 else 5251 Errflg = 1; 5252 } 5253 dev = 0; 5254 } 5255 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 5256 5257 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 5258 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 5259 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 5260 (void) sprintf(dblock.dbuf.version, "00"); 5261 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 5262 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 5263 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 5264 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 5265 5266 if (Eflag) { 5267 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 5268 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 5269 lastslash = strrchr(name, '/'); 5270 if (lastslash == NULL) 5271 lastslash = name; 5272 else 5273 lastslash++; 5274 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 5275 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 5276 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 5277 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 5278 xhdr_count++; 5279 xrec_offset = 0; 5280 gen_date("mtime", sp->st_mtim); 5281 xhdr_buf.dbuf.typeflag = 'X'; 5282 if (gen_utf8_names(filename) != 0) 5283 return (1); 5284 5285 #ifdef XHDR_DEBUG 5286 Xtarhdr.x_uname = dblock.dbuf.uname; 5287 Xtarhdr.x_gname = dblock.dbuf.gname; 5288 xhdr_flgs |= (_X_UNAME | _X_GNAME); 5289 #endif 5290 if (xhdr_flgs) { 5291 if (xhdr_flgs & _X_DEVMAJOR) 5292 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 5293 if (xhdr_flgs & _X_DEVMINOR) 5294 gen_num("SUN.devminor", Xtarhdr.x_devminor); 5295 if (xhdr_flgs & _X_GID) 5296 gen_num("gid", Xtarhdr.x_gid); 5297 if (xhdr_flgs & _X_UID) 5298 gen_num("uid", Xtarhdr.x_uid); 5299 if (xhdr_flgs & _X_SIZE) 5300 gen_num("size", Xtarhdr.x_filesz); 5301 if (xhdr_flgs & _X_PATH) 5302 gen_string("path", Xtarhdr.x_path); 5303 if (xhdr_flgs & _X_LINKPATH) 5304 gen_string("linkpath", Xtarhdr.x_linkpath); 5305 if (xhdr_flgs & _X_GNAME) 5306 gen_string("gname", Xtarhdr.x_gname); 5307 if (xhdr_flgs & _X_UNAME) 5308 gen_string("uname", Xtarhdr.x_uname); 5309 } 5310 (void) sprintf(xhdr_buf.dbuf.size, 5311 "%011" FMT_off_t_o, xrec_offset); 5312 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 5313 checksum(&xhdr_buf)); 5314 (void) writetbuf((char *)&xhdr_buf, 1); 5315 nblks = TBLOCKS(xrec_offset); 5316 (void) writetbuf(xrec_ptr, nblks); 5317 } 5318 return (0); 5319 } 5320 5321 5322 /* 5323 * makeDir - ensure that a directory with the pathname denoted by name 5324 * exists, and return 1 on success, and 0 on failure (e.g., 5325 * read-only file system, exists but not-a-directory). 5326 */ 5327 5328 static int 5329 makeDir(char *name) 5330 { 5331 struct stat buf; 5332 5333 if (access(name, 0) < 0) { /* name doesn't exist */ 5334 if (mkdir(name, 0777) < 0) { 5335 vperror(0, "%s", name); 5336 return (0); 5337 } 5338 } else { /* name exists */ 5339 if (stat(name, &buf) < 0) { 5340 vperror(0, "%s", name); 5341 return (0); 5342 } 5343 5344 return ((buf.st_mode & S_IFMT) == S_IFDIR); 5345 } 5346 5347 return (1); 5348 } 5349 5350 5351 /* 5352 * Save this directory and its mtime on the stack, popping and setting 5353 * the mtimes of any stacked dirs which aren't parents of this one. 5354 * A null name causes the entire stack to be unwound and set. 5355 * 5356 * Since all the elements of the directory "stack" share a common 5357 * prefix, we can make do with one string. We keep only the current 5358 * directory path, with an associated array of mtime's. A negative 5359 * mtime means no mtime. 5360 * 5361 * This stack algorithm is not guaranteed to work for tapes created 5362 * with the 'r' function letter, but the vast majority of tapes with 5363 * directories are not. This avoids saving every directory record on 5364 * the tape and setting all the times at the end. 5365 * 5366 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 5367 * environment) 5368 */ 5369 5370 static void 5371 doDirTimes(char *name, timestruc_t modTime) 5372 { 5373 static char dirstack[PATH_MAX+2]; 5374 /* Add spaces for the last slash and last NULL */ 5375 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 5376 char *p = dirstack; 5377 char *q = name; 5378 char *savp; 5379 5380 if (q) { 5381 /* 5382 * Find common prefix 5383 */ 5384 5385 while (*p == *q && *p) { 5386 p++; q++; 5387 } 5388 } 5389 5390 savp = p; 5391 while (*p) { 5392 /* 5393 * Not a child: unwind the stack, setting the times. 5394 * The order we do this doesn't matter, so we go "forward." 5395 */ 5396 5397 if (*p == '/') 5398 if (modtimes[p - dirstack].tv_sec >= 0) { 5399 *p = '\0'; /* zap the slash */ 5400 setPathTimes(AT_FDCWD, dirstack, 5401 modtimes[p - dirstack]); 5402 *p = '/'; 5403 } 5404 ++p; 5405 } 5406 5407 p = savp; 5408 5409 /* 5410 * Push this one on the "stack" 5411 */ 5412 5413 if (q) { 5414 5415 /* 5416 * Since the name parameter points the dir pathname 5417 * which is limited only to contain PATH_MAX chars 5418 * at maximum, we can ignore the overflow case of p. 5419 */ 5420 5421 while ((*p = *q++)) { /* append the rest of the new dir */ 5422 modtimes[p - dirstack].tv_sec = -1; 5423 p++; 5424 } 5425 5426 /* 5427 * If the tar file had used 'P' or 'E' function modifier, 5428 * append the last slash. 5429 */ 5430 if (*(p - 1) != '/') { 5431 *p++ = '/'; 5432 *p = '\0'; 5433 } 5434 /* overwrite the last one */ 5435 modtimes[p - dirstack - 1] = modTime; 5436 } 5437 } 5438 5439 5440 /* 5441 * setPathTimes - set the modification time for given path. Return 1 if 5442 * successful and 0 if not successful. 5443 */ 5444 5445 static void 5446 setPathTimes(int dirfd, char *path, timestruc_t modTime) 5447 5448 { 5449 struct timeval timebuf[2]; 5450 5451 /* 5452 * futimesat takes an array of two timeval structs. 5453 * The first entry contains access time. 5454 * The second entry contains modification time. 5455 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 5456 * microseconds. 5457 */ 5458 timebuf[0].tv_sec = time((time_t *)0); 5459 timebuf[0].tv_usec = 0; 5460 timebuf[1].tv_sec = modTime.tv_sec; 5461 5462 /* Extended header: use microseconds */ 5463 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 5464 5465 if (futimesat(dirfd, path, timebuf) < 0) 5466 vperror(0, "can't set time on %s", path); 5467 } 5468 5469 5470 /* 5471 * If hflag is set then delete the symbolic link's target. 5472 * If !hflag then delete the target. 5473 */ 5474 5475 static void 5476 delete_target(int fd, char *namep) 5477 { 5478 struct stat xtractbuf; 5479 char buf[PATH_MAX + 1]; 5480 int n; 5481 5482 5483 if (unlinkat(fd, namep, AT_REMOVEDIR) < 0) { 5484 if (errno == ENOTDIR && !hflag) { 5485 (void) unlinkat(fd, namep, 0); 5486 } else if (errno == ENOTDIR && hflag) { 5487 if (!lstat(namep, &xtractbuf)) { 5488 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 5489 (void) unlinkat(fd, namep, 0); 5490 } else if ((n = readlink(namep, buf, 5491 PATH_MAX)) != -1) { 5492 buf[n] = (char)NULL; 5493 (void) unlinkat(fd, buf, 5494 AT_REMOVEDIR); 5495 if (errno == ENOTDIR) 5496 (void) unlinkat(fd, buf, 0); 5497 } else { 5498 (void) unlinkat(fd, namep, 0); 5499 } 5500 } else { 5501 (void) unlinkat(fd, namep, 0); 5502 } 5503 } 5504 } 5505 } 5506 5507 5508 /* 5509 * ACL changes: 5510 * putfile(): 5511 * Get acl info after stat. Write out ancillary file 5512 * before the normal file, i.e. directory, regular, FIFO, 5513 * link, special. If acl count is less than 4, no need to 5514 * create ancillary file. (i.e. standard permission is in 5515 * use. 5516 * doxtract(): 5517 * Process ancillary file. Read it in and set acl info. 5518 * watch out for 'o' function modifier. 5519 * 't' function letter to display table 5520 */ 5521 5522 /* 5523 * New functions for ACLs and other security attributes 5524 */ 5525 5526 /* 5527 * The function appends the new security attribute info to the end of 5528 * existing secinfo. 5529 */ 5530 int 5531 append_secattr( 5532 char **secinfo, /* existing security info */ 5533 int *secinfo_len, /* length of existing security info */ 5534 acl_t *aclp) 5535 { 5536 char *new_secinfo; 5537 char *attrtext; 5538 int newattrsize; 5539 int oldsize; 5540 5541 /* no need to add */ 5542 if (aclp == (void *)NULL) 5543 return (0); 5544 5545 switch (acl_type(aclp)) { 5546 case ACLENT_T: 5547 case ACE_T: 5548 attrtext = acl_totext(aclp); 5549 if (attrtext == NULL) { 5550 (void) fprintf(stderr, "acltotext failed\n"); 5551 return (-1); 5552 } 5553 /* header: type + size = 8 */ 5554 newattrsize = 8 + (int)strlen(attrtext) + 1; 5555 attr = (struct sec_attr *)malloc(newattrsize); 5556 if (attr == NULL) { 5557 (void) fprintf(stderr, "can't allocate memory\n"); 5558 return (-1); 5559 } 5560 attr->attr_type = (acl_type(aclp) == ACLENT_T) ? 5561 UFSD_ACL : ACE_ACL; 5562 (void) sprintf(attr->attr_len, 5563 "%06o", acl_cnt(aclp)); /* acl entry count */ 5564 (void) strcpy((char *)&attr->attr_info[0], attrtext); 5565 free(attrtext); 5566 break; 5567 5568 /* SunFed's case goes here */ 5569 5570 default: 5571 (void) fprintf(stderr, "unrecognized attribute type\n"); 5572 return (-1); 5573 } 5574 5575 /* old security info + new attr header(8) + new attr */ 5576 oldsize = *secinfo_len; 5577 *secinfo_len += newattrsize; 5578 new_secinfo = (char *)malloc(*secinfo_len); 5579 if (new_secinfo == NULL) { 5580 (void) fprintf(stderr, "can't allocate memory\n"); 5581 *secinfo_len -= newattrsize; 5582 return (-1); 5583 } 5584 5585 (void) memcpy(new_secinfo, *secinfo, oldsize); 5586 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 5587 5588 free(*secinfo); 5589 *secinfo = new_secinfo; 5590 return (0); 5591 } 5592 5593 /* 5594 * write_ancillary(): write out an ancillary file. 5595 * The file has the same header as normal file except the type and size 5596 * fields. The type is 'A' and size is the sum of all attributes 5597 * in bytes. 5598 * The body contains a list of attribute type, size and info. Currently, 5599 * there is only ACL info. This file is put before the normal file. 5600 */ 5601 void 5602 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 5603 { 5604 long blocks; 5605 int savflag; 5606 int savsize; 5607 5608 /* Just tranditional permissions or no security attribute info */ 5609 if (len == 0 || secinfo == NULL) 5610 return; 5611 5612 /* save flag and size */ 5613 savflag = (dblockp->dbuf).typeflag; 5614 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 5615 5616 /* special flag for ancillary file */ 5617 if (hdrtype == _XATTR_HDRTYPE) 5618 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 5619 else 5620 dblockp->dbuf.typeflag = 'A'; 5621 5622 /* for pre-2.5 versions of tar, need to make sure */ 5623 /* the ACL file is readable */ 5624 (void) sprintf(dblock.dbuf.mode, "%07lo", 5625 (stbuf.st_mode & POSIXMODES) | 0000200); 5626 (void) sprintf(dblockp->dbuf.size, "%011o", len); 5627 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 5628 5629 /* write out the header */ 5630 (void) writetbuf((char *)dblockp, 1); 5631 5632 /* write out security info */ 5633 blocks = TBLOCKS(len); 5634 (void) writetbuf((char *)secinfo, (int)blocks); 5635 5636 /* restore mode, flag and size */ 5637 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 5638 dblockp->dbuf.typeflag = savflag; 5639 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 5640 } 5641 5642 /* 5643 * Read the data record for extended headers and then the regular header. 5644 * The data are read into the buffer and then null-terminated. Entries 5645 * are of the format: 5646 * "%d %s=%s\n" 5647 * 5648 * When an extended header record is found, the extended header must 5649 * be processed and its values used to override the values in the 5650 * normal header. The way this is done is to process the extended 5651 * header data record and set the data values, then call getdir 5652 * to process the regular header, then then to reconcile the two 5653 * sets of data. 5654 */ 5655 5656 static int 5657 get_xdata(void) 5658 { 5659 struct keylist_pair { 5660 int keynum; 5661 char *keylist; 5662 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 5663 _X_DEVMINOR, "SUN.devminor", 5664 _X_GID, "gid", 5665 _X_GNAME, "gname", 5666 _X_LINKPATH, "linkpath", 5667 _X_PATH, "path", 5668 _X_SIZE, "size", 5669 _X_UID, "uid", 5670 _X_UNAME, "uname", 5671 _X_MTIME, "mtime", 5672 _X_LAST, "NULL" }; 5673 char *lineloc; 5674 int length, i; 5675 char *keyword, *value; 5676 blkcnt_t nblocks; 5677 int bufneeded; 5678 struct stat *sp = &stbuf; 5679 int errors; 5680 5681 Xtarhdr.x_uid = 0; 5682 Xtarhdr.x_gid = 0; 5683 Xtarhdr.x_devmajor = 0; 5684 Xtarhdr.x_devminor = 0; 5685 Xtarhdr.x_filesz = 0; 5686 Xtarhdr.x_uname = NULL; 5687 Xtarhdr.x_gname = NULL; 5688 Xtarhdr.x_linkpath = NULL; 5689 Xtarhdr.x_path = NULL; 5690 Xtarhdr.x_mtime.tv_sec = 0; 5691 Xtarhdr.x_mtime.tv_nsec = 0; 5692 xhdr_count++; 5693 errors = 0; 5694 5695 nblocks = TBLOCKS(stbuf.st_size); 5696 bufneeded = nblocks * TBLOCK; 5697 if (bufneeded >= xrec_size) { 5698 free(xrec_ptr); 5699 xrec_size = bufneeded + 1; 5700 if ((xrec_ptr = malloc(xrec_size)) == NULL) 5701 fatal(gettext("cannot allocate buffer")); 5702 } 5703 5704 lineloc = xrec_ptr; 5705 5706 while (nblocks-- > 0) { 5707 readtape(lineloc); 5708 lineloc += TBLOCK; 5709 } 5710 lineloc = xrec_ptr; 5711 xrec_ptr[stbuf.st_size] = '\0'; 5712 while (lineloc < xrec_ptr + stbuf.st_size) { 5713 length = atoi(lineloc); 5714 *(lineloc + length - 1) = '\0'; 5715 keyword = strchr(lineloc, ' ') + 1; 5716 value = strchr(keyword, '=') + 1; 5717 *(value - 1) = '\0'; 5718 i = 0; 5719 lineloc += length; 5720 while (keylist_pair[i].keynum != (int)_X_LAST) { 5721 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 5722 break; 5723 i++; 5724 } 5725 errno = 0; 5726 switch (keylist_pair[i].keynum) { 5727 case _X_DEVMAJOR: 5728 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 5729 if (errno) { 5730 (void) fprintf(stderr, gettext( 5731 "tar: Extended header major value error " 5732 "for file # %llu.\n"), xhdr_count); 5733 errors++; 5734 } else 5735 xhdr_flgs |= _X_DEVMAJOR; 5736 break; 5737 case _X_DEVMINOR: 5738 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 5739 if (errno) { 5740 (void) fprintf(stderr, gettext( 5741 "tar: Extended header minor value error " 5742 "for file # %llu.\n"), xhdr_count); 5743 errors++; 5744 } else 5745 xhdr_flgs |= _X_DEVMINOR; 5746 break; 5747 case _X_GID: 5748 xhdr_flgs |= _X_GID; 5749 Xtarhdr.x_gid = strtol(value, NULL, 0); 5750 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 5751 (void) fprintf(stderr, gettext( 5752 "tar: Extended header gid value error " 5753 "for file # %llu.\n"), xhdr_count); 5754 Xtarhdr.x_gid = GID_NOBODY; 5755 } 5756 break; 5757 case _X_GNAME: 5758 if (utf8_local("gname", &Xtarhdr.x_gname, 5759 local_gname, value, _POSIX_NAME_MAX) == 0) 5760 xhdr_flgs |= _X_GNAME; 5761 break; 5762 case _X_LINKPATH: 5763 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 5764 local_linkpath, value, PATH_MAX) == 0) 5765 xhdr_flgs |= _X_LINKPATH; 5766 else 5767 errors++; 5768 break; 5769 case _X_PATH: 5770 if (utf8_local("path", &Xtarhdr.x_path, 5771 local_path, value, PATH_MAX) == 0) 5772 xhdr_flgs |= _X_PATH; 5773 else 5774 errors++; 5775 break; 5776 case _X_SIZE: 5777 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 5778 if (errno) { 5779 (void) fprintf(stderr, gettext( 5780 "tar: Extended header invalid filesize " 5781 "for file # %llu.\n"), xhdr_count); 5782 errors++; 5783 } else 5784 xhdr_flgs |= _X_SIZE; 5785 break; 5786 case _X_UID: 5787 xhdr_flgs |= _X_UID; 5788 Xtarhdr.x_uid = strtol(value, NULL, 0); 5789 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 5790 (void) fprintf(stderr, gettext( 5791 "tar: Extended header uid value error " 5792 "for file # %llu.\n"), xhdr_count); 5793 Xtarhdr.x_uid = UID_NOBODY; 5794 } 5795 break; 5796 case _X_UNAME: 5797 if (utf8_local("uname", &Xtarhdr.x_uname, 5798 local_uname, value, _POSIX_NAME_MAX) == 0) 5799 xhdr_flgs |= _X_UNAME; 5800 break; 5801 case _X_MTIME: 5802 get_xtime(value, &(Xtarhdr.x_mtime)); 5803 if (errno) 5804 (void) fprintf(stderr, gettext( 5805 "tar: Extended header modification time " 5806 "value error for file # %llu.\n"), 5807 xhdr_count); 5808 else 5809 xhdr_flgs |= _X_MTIME; 5810 break; 5811 default: 5812 (void) fprintf(stderr, 5813 gettext("tar: unrecognized extended" 5814 " header keyword '%s'. Ignored.\n"), keyword); 5815 break; 5816 } 5817 } 5818 5819 getdir(); /* get regular header */ 5820 5821 if (xhdr_flgs & _X_DEVMAJOR) { 5822 Gen.g_devmajor = Xtarhdr.x_devmajor; 5823 } 5824 if (xhdr_flgs & _X_DEVMINOR) { 5825 Gen.g_devminor = Xtarhdr.x_devminor; 5826 } 5827 if (xhdr_flgs & _X_GID) { 5828 Gen.g_gid = Xtarhdr.x_gid; 5829 sp->st_gid = Gen.g_gid; 5830 } 5831 if (xhdr_flgs & _X_UID) { 5832 Gen.g_uid = Xtarhdr.x_uid; 5833 sp->st_uid = Gen.g_uid; 5834 } 5835 if (xhdr_flgs & _X_SIZE) { 5836 Gen.g_filesz = Xtarhdr.x_filesz; 5837 sp->st_size = Gen.g_filesz; 5838 } 5839 if (xhdr_flgs & _X_MTIME) { 5840 Gen.g_mtime = Xtarhdr.x_mtime.tv_sec; 5841 sp->st_mtim.tv_sec = Gen.g_mtime; 5842 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 5843 } 5844 5845 if (errors && errflag) 5846 done(1); 5847 else 5848 if (errors) 5849 Errflg = 1; 5850 return (errors); 5851 } 5852 5853 /* 5854 * gen_num creates a string from a keyword and an usigned long long in the 5855 * format: %d %s=%s\n 5856 * This is part of the extended header data record. 5857 */ 5858 5859 void 5860 gen_num(const char *keyword, const u_longlong_t number) 5861 { 5862 char save_val[ULONGLONG_MAX_DIGITS + 1]; 5863 int len; 5864 char *curr_ptr; 5865 5866 (void) sprintf(save_val, "%llu", number); 5867 /* 5868 * len = length of entire line, including itself. len will be 5869 * two digits. So, add the string lengths plus the length of len, 5870 * plus a blank, an equal sign, and a newline. 5871 */ 5872 len = strlen(save_val) + strlen(keyword) + 5; 5873 if (xrec_offset + len > xrec_size) { 5874 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5875 fatal(gettext( 5876 "cannot allocate extended header buffer")); 5877 xrec_ptr = curr_ptr; 5878 xrec_size *= 2; 5879 } 5880 (void) sprintf(&xrec_ptr[xrec_offset], 5881 "%d %s=%s\n", len, keyword, save_val); 5882 xrec_offset += len; 5883 } 5884 5885 /* 5886 * gen_date creates a string from a keyword and a timestruc_t in the 5887 * format: %d %s=%s\n 5888 * This is part of the extended header data record. 5889 * Currently, granularity is only microseconds, so the low-order three digits 5890 * will be truncated. 5891 */ 5892 5893 void 5894 gen_date(const char *keyword, const timestruc_t time_value) 5895 { 5896 /* Allow for <seconds>.<nanoseconds>\n */ 5897 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 5898 int len; 5899 char *curr_ptr; 5900 5901 (void) sprintf(save_val, "%ld", time_value.tv_sec); 5902 len = strlen(save_val); 5903 save_val[len] = '.'; 5904 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 5905 5906 /* 5907 * len = length of entire line, including itself. len will be 5908 * two digits. So, add the string lengths plus the length of len, 5909 * plus a blank, an equal sign, and a newline. 5910 */ 5911 len = strlen(save_val) + strlen(keyword) + 5; 5912 if (xrec_offset + len > xrec_size) { 5913 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5914 fatal(gettext( 5915 "cannot allocate extended header buffer")); 5916 xrec_ptr = curr_ptr; 5917 xrec_size *= 2; 5918 } 5919 (void) sprintf(&xrec_ptr[xrec_offset], 5920 "%d %s=%s\n", len, keyword, save_val); 5921 xrec_offset += len; 5922 } 5923 5924 /* 5925 * gen_string creates a string from a keyword and a char * in the 5926 * format: %d %s=%s\n 5927 * This is part of the extended header data record. 5928 */ 5929 5930 void 5931 gen_string(const char *keyword, const char *value) 5932 { 5933 int len; 5934 char *curr_ptr; 5935 5936 /* 5937 * len = length of entire line, including itself. The character length 5938 * of len must be 1-4 characters, because the maximum size of the path 5939 * or the name is PATH_MAX, which is 1024. So, assume 1 character 5940 * for len, one for the space, one for the "=", and one for the newline. 5941 * Then adjust as needed. 5942 */ 5943 /* LINTED constant expression */ 5944 assert(PATH_MAX <= 9996); 5945 len = strlen(value) + strlen(keyword) + 4; 5946 if (len > 997) 5947 len += 3; 5948 else if (len > 98) 5949 len += 2; 5950 else if (len > 9) 5951 len += 1; 5952 if (xrec_offset + len > xrec_size) { 5953 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5954 fatal(gettext( 5955 "cannot allocate extended header buffer")); 5956 xrec_ptr = curr_ptr; 5957 xrec_size *= 2; 5958 } 5959 #ifdef XHDR_DEBUG 5960 if (strcmp(keyword+1, "name") != 0) 5961 #endif 5962 (void) sprintf(&xrec_ptr[xrec_offset], 5963 "%d %s=%s\n", len, keyword, value); 5964 #ifdef XHDR_DEBUG 5965 else { 5966 len += 11; 5967 (void) sprintf(&xrec_ptr[xrec_offset], 5968 "%d %s=%snametoolong\n", len, keyword, value); 5969 } 5970 #endif 5971 xrec_offset += len; 5972 } 5973 5974 /* 5975 * Convert time found in the extended header data to seconds and nanoseconds. 5976 */ 5977 5978 void 5979 get_xtime(char *value, timestruc_t *xtime) 5980 { 5981 char nanosec[10]; 5982 char *period; 5983 int i; 5984 5985 (void) memset(nanosec, '0', 9); 5986 nanosec[9] = '\0'; 5987 5988 period = strchr(value, '.'); 5989 if (period != NULL) 5990 period[0] = '\0'; 5991 xtime->tv_sec = strtol(value, NULL, 10); 5992 if (period == NULL) 5993 xtime->tv_nsec = 0; 5994 else { 5995 i = strlen(period +1); 5996 (void) strncpy(nanosec, period + 1, min(i, 9)); 5997 xtime->tv_nsec = strtol(nanosec, NULL, 10); 5998 } 5999 } 6000 6001 /* 6002 * Check linkpath for length. 6003 * Emit an error message and return 1 if too long. 6004 */ 6005 6006 int 6007 chk_path_build( 6008 char *name, 6009 char *longname, 6010 char *linkname, 6011 char *prefix, 6012 char type, 6013 int filetype) 6014 { 6015 6016 if (strlen(linkname) > (size_t)NAMSIZ) { 6017 if (Eflag > 0) { 6018 xhdr_flgs |= _X_LINKPATH; 6019 Xtarhdr.x_linkpath = linkname; 6020 } else { 6021 (void) fprintf(stderr, gettext( 6022 "tar: %s: linked to %s\n"), longname, linkname); 6023 (void) fprintf(stderr, gettext( 6024 "tar: %s: linked name too long\n"), linkname); 6025 if (errflag) 6026 done(1); 6027 else 6028 Errflg = 1; 6029 return (1); 6030 } 6031 } 6032 if (xhdr_flgs & _X_LINKPATH) 6033 return (build_dblock(name, tchar, type, 6034 filetype, &stbuf, stbuf.st_dev, 6035 prefix)); 6036 else 6037 return (build_dblock(name, linkname, type, 6038 filetype, &stbuf, stbuf.st_dev, prefix)); 6039 } 6040 6041 /* 6042 * Convert from UTF-8 to local character set. 6043 */ 6044 6045 static int 6046 utf8_local( 6047 char *option, 6048 char **Xhdr_ptrptr, 6049 char *target, 6050 const char *source, 6051 int max_val) 6052 { 6053 static iconv_t iconv_cd; 6054 char *nl_target; 6055 const char *iconv_src; 6056 char *iconv_trg; 6057 size_t inlen, 6058 outlen; 6059 6060 if (charset_type == -1) { /* iconv_open failed in earlier try */ 6061 (void) fprintf(stderr, gettext( 6062 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6063 xhdr_count, source); 6064 return (1); 6065 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 6066 nl_target = nl_langinfo(CODESET); 6067 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6068 nl_target = "646"; 6069 if (strcmp(nl_target, "646") == 0) 6070 charset_type = 1; 6071 else if (strcmp(nl_target, "UTF-8") == 0) 6072 charset_type = 3; 6073 else { 6074 if (strncmp(nl_target, "ISO", 3) == 0) 6075 nl_target += 3; 6076 charset_type = 2; 6077 errno = 0; 6078 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 6079 (iconv_t)-1) { 6080 if (errno == EINVAL) 6081 (void) fprintf(stderr, gettext( 6082 "tar: conversion routines not " 6083 "available for current locale. ")); 6084 (void) fprintf(stderr, gettext( 6085 "file # %llu: (%s) UTF-8 conversion" 6086 " failed.\n"), xhdr_count, source); 6087 charset_type = -1; 6088 return (1); 6089 } 6090 } 6091 } 6092 6093 /* locale using 7-bit codeset or UTF-8 locale */ 6094 if (charset_type == 1 || charset_type == 3) { 6095 if (strlen(source) > max_val) { 6096 (void) fprintf(stderr, gettext( 6097 "tar: file # %llu: Extended header %s too long.\n"), 6098 xhdr_count, option); 6099 return (1); 6100 } 6101 if (charset_type == 3) 6102 (void) strcpy(target, source); 6103 else if (c_utf8(target, source) != 0) { 6104 (void) fprintf(stderr, gettext( 6105 "tar: file # %llu: (%s) UTF-8 conversion" 6106 " failed.\n"), xhdr_count, source); 6107 return (1); 6108 } 6109 *Xhdr_ptrptr = target; 6110 return (0); 6111 } 6112 6113 iconv_src = source; 6114 iconv_trg = target; 6115 inlen = strlen(source); 6116 outlen = max_val * UTF_8_FACTOR; 6117 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6118 (size_t)-1) { /* Error occurred: didn't convert */ 6119 (void) fprintf(stderr, gettext( 6120 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6121 xhdr_count, source); 6122 /* Get remaining output; reinitialize conversion descriptor */ 6123 iconv_src = (const char *)NULL; 6124 inlen = 0; 6125 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6126 return (1); 6127 } 6128 /* Get remaining output; reinitialize conversion descriptor */ 6129 iconv_src = (const char *)NULL; 6130 inlen = 0; 6131 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6132 (size_t)-1) { /* Error occurred: didn't convert */ 6133 (void) fprintf(stderr, gettext( 6134 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6135 xhdr_count, source); 6136 return (1); 6137 } 6138 6139 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6140 if (strlen(target) > max_val) { 6141 (void) fprintf(stderr, gettext( 6142 "tar: file # %llu: Extended header %s too long.\n"), 6143 xhdr_count, option); 6144 return (1); 6145 } 6146 *Xhdr_ptrptr = target; 6147 return (0); 6148 } 6149 6150 /* 6151 * Check gname, uname, path, and linkpath to see if they need to go in an 6152 * extended header. If they are already slated to be in an extended header, 6153 * or if they are not ascii, then they need to be in the extended header. 6154 * Then, convert all extended names to UTF-8. 6155 */ 6156 6157 int 6158 gen_utf8_names(const char *filename) 6159 { 6160 static iconv_t iconv_cd; 6161 char *nl_target; 6162 char tempbuf[MAXNAM + 1]; 6163 int nbytes, 6164 errors; 6165 6166 if (charset_type == -1) { /* Previous failure to open. */ 6167 (void) fprintf(stderr, gettext( 6168 "tar: file # %llu: UTF-8 conversion failed.\n"), 6169 xhdr_count); 6170 return (1); 6171 } 6172 6173 if (charset_type == 0) { /* Need to get conversion descriptor */ 6174 nl_target = nl_langinfo(CODESET); 6175 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6176 nl_target = "646"; 6177 if (strcmp(nl_target, "646") == 0) 6178 charset_type = 1; 6179 else if (strcmp(nl_target, "UTF-8") == 0) 6180 charset_type = 3; 6181 else { 6182 if (strncmp(nl_target, "ISO", 3) == 0) 6183 nl_target += 3; 6184 charset_type = 2; 6185 errno = 0; 6186 #ifdef ICONV_DEBUG 6187 (void) fprintf(stderr, 6188 "Opening iconv_cd with target %s\n", 6189 nl_target); 6190 #endif 6191 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 6192 (iconv_t)-1) { 6193 if (errno == EINVAL) 6194 (void) fprintf(stderr, gettext( 6195 "tar: conversion routines not " 6196 "available for current locale. ")); 6197 (void) fprintf(stderr, gettext( 6198 "file (%s): UTF-8 conversion failed.\n"), 6199 filename); 6200 charset_type = -1; 6201 return (1); 6202 } 6203 } 6204 } 6205 6206 errors = 0; 6207 6208 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 6209 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 6210 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 6211 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 6212 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 6213 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 6214 tempbuf[NAMSIZ] = '\0'; 6215 } 6216 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 6217 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 6218 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 6219 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 6220 tempbuf[NAMSIZ] = '\0'; 6221 nbytes = strlen(tempbuf); 6222 if (nbytes > 0) { 6223 tempbuf[nbytes++] = '/'; 6224 tempbuf[nbytes] = '\0'; 6225 } 6226 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, NAMSIZ); 6227 tempbuf[nbytes + NAMSIZ] = '\0'; 6228 } 6229 errors += local_utf8(&Xtarhdr.x_path, local_path, 6230 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 6231 6232 if (errors > 0) 6233 (void) fprintf(stderr, gettext( 6234 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 6235 6236 if (errors && errflag) 6237 done(1); 6238 else 6239 if (errors) 6240 Errflg = 1; 6241 return (errors); 6242 } 6243 6244 static int 6245 local_utf8( 6246 char **Xhdr_ptrptr, 6247 char *target, 6248 const char *source, 6249 iconv_t iconv_cd, 6250 int xhdrflg, 6251 int max_val) 6252 { 6253 const char *iconv_src; 6254 const char *starting_src; 6255 char *iconv_trg; 6256 size_t inlen, 6257 outlen; 6258 #ifdef ICONV_DEBUG 6259 unsigned char c_to_hex; 6260 #endif 6261 6262 /* 6263 * If the item is already slated for extended format, get the string 6264 * to convert from the extended header record. Otherwise, get it from 6265 * the regular (dblock) area. 6266 */ 6267 if (xhdr_flgs & xhdrflg) { 6268 if (charset_type == 3) { /* Already UTF-8, just copy */ 6269 (void) strcpy(target, *Xhdr_ptrptr); 6270 *Xhdr_ptrptr = target; 6271 return (0); 6272 } else 6273 iconv_src = (const char *) *Xhdr_ptrptr; 6274 } else { 6275 if (charset_type == 3) /* Already in UTF-8 format */ 6276 return (0); /* Don't create xhdr record */ 6277 iconv_src = source; 6278 } 6279 starting_src = iconv_src; 6280 iconv_trg = target; 6281 if ((inlen = strlen(iconv_src)) == 0) 6282 return (0); 6283 6284 if (charset_type == 1) { /* locale using 7-bit codeset */ 6285 if (c_utf8(target, starting_src) != 0) { 6286 (void) fprintf(stderr, 6287 gettext("tar: invalid character in" 6288 " UTF-8 conversion of '%s'\n"), starting_src); 6289 return (1); 6290 } 6291 return (0); 6292 } 6293 6294 outlen = max_val * UTF_8_FACTOR; 6295 errno = 0; 6296 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6297 (size_t)-1) { 6298 /* An error occurred, or not all characters were converted */ 6299 if (errno == EILSEQ) 6300 (void) fprintf(stderr, 6301 gettext("tar: invalid character in" 6302 " UTF-8 conversion of '%s'\n"), starting_src); 6303 else 6304 (void) fprintf(stderr, gettext( 6305 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6306 starting_src); 6307 /* Get remaining output; reinitialize conversion descriptor */ 6308 iconv_src = (const char *)NULL; 6309 inlen = 0; 6310 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6311 return (1); 6312 } 6313 /* Get remaining output; reinitialize conversion descriptor */ 6314 iconv_src = (const char *)NULL; 6315 inlen = 0; 6316 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6317 (size_t)-1) { /* Error occurred: didn't convert */ 6318 if (errno == EILSEQ) 6319 (void) fprintf(stderr, 6320 gettext("tar: invalid character in" 6321 " UTF-8 conversion of '%s'\n"), starting_src); 6322 else 6323 (void) fprintf(stderr, gettext( 6324 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6325 starting_src); 6326 return (1); 6327 } 6328 6329 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6330 if (strcmp(starting_src, target) != 0) { 6331 *Xhdr_ptrptr = target; 6332 xhdr_flgs |= xhdrflg; 6333 #ifdef ICONV_DEBUG 6334 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 6335 strlen(starting_src), inlen, max_val, outlen); 6336 (void) fprintf(stderr, "Input string:\n "); 6337 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 6338 c_to_hex = (unsigned char)starting_src[inlen]; 6339 (void) fprintf(stderr, " %2.2x", c_to_hex); 6340 if (inlen % 20 == 19) 6341 (void) fprintf(stderr, "\n "); 6342 } 6343 (void) fprintf(stderr, "\nOutput string:\n "); 6344 for (inlen = 0; inlen < strlen(target); inlen++) { 6345 c_to_hex = (unsigned char)target[inlen]; 6346 (void) fprintf(stderr, " %2.2x", c_to_hex); 6347 if (inlen % 20 == 19) 6348 (void) fprintf(stderr, "\n "); 6349 } 6350 (void) fprintf(stderr, "\n"); 6351 #endif 6352 } 6353 6354 return (0); 6355 } 6356 6357 /* 6358 * Function to test each byte of the source string to make sure it is 6359 * in within bounds (value between 0 and 127). 6360 * If valid, copy source to target. 6361 */ 6362 6363 int 6364 c_utf8(char *target, const char *source) 6365 { 6366 size_t len; 6367 const char *thischar; 6368 6369 len = strlen(source); 6370 thischar = source; 6371 while (len-- > 0) { 6372 if (!isascii((int)(*thischar++))) 6373 return (1); 6374 } 6375 6376 (void) strcpy(target, source); 6377 return (0); 6378 } 6379 6380 6381 #if defined(O_XATTR) 6382 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 6383 6384 static void 6385 prepare_xattr( 6386 char **attrbuf, 6387 char *filename, 6388 char *attrname, 6389 char typeflag, 6390 struct linkbuf *linkinfo, 6391 int *rlen) 6392 { 6393 char *bufhead; /* ptr to full buffer */ 6394 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 6395 struct xattr_buf *tptr; /* ptr to pathing pieces */ 6396 int totalen; /* total buffer length */ 6397 int len; /* length returned to user */ 6398 int stringlen; /* length of filename + attr */ 6399 /* 6400 * length of filename + attr 6401 * in link section 6402 */ 6403 int linkstringlen; 6404 int complen; /* length of pathing section */ 6405 int linklen; /* length of link section */ 6406 6407 /* 6408 * Release previous buffer 6409 */ 6410 6411 if (*attrbuf != (char *)NULL) { 6412 free(*attrbuf); 6413 *attrbuf = NULL; 6414 } 6415 6416 /* 6417 * First add in fixed size stuff 6418 */ 6419 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 6420 6421 /* 6422 * Add space for two nulls 6423 */ 6424 stringlen = strlen(attrname) + strlen(filename) + 2; 6425 complen = stringlen + sizeof (struct xattr_buf); 6426 6427 len += stringlen; 6428 6429 /* 6430 * Now add on space for link info if any 6431 */ 6432 6433 if (linkinfo != NULL) { 6434 /* 6435 * Again add space for two nulls 6436 */ 6437 linkstringlen = strlen(linkinfo->pathname) + 6438 strlen(linkinfo->attrname) + 2; 6439 len += linkstringlen; 6440 } 6441 6442 /* 6443 * Now add padding to end to fill out TBLOCK 6444 * 6445 * Function returns size of real data and not size + padding. 6446 */ 6447 6448 totalen = ROUNDTOTBLOCK(len); 6449 6450 if ((bufhead = calloc(1, totalen)) == NULL) { 6451 fatal(gettext("Out of memory.")); 6452 } 6453 6454 6455 /* 6456 * Now we can fill in the necessary pieces 6457 */ 6458 6459 if (linkinfo != (struct linkbuf *)NULL) { 6460 linklen = linkstringlen + (sizeof (struct xattr_buf)); 6461 } else { 6462 linklen = 0; 6463 } 6464 6465 /* 6466 * first fill in the fixed header 6467 */ 6468 hptr = (struct xattr_hdr *)bufhead; 6469 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 6470 (void) sprintf(hptr->h_component_len, "%0*d", 6471 sizeof (hptr->h_component_len) - 1, complen); 6472 (void) sprintf(hptr->h_link_component_len, "%0*d", 6473 sizeof (hptr->h_link_component_len) - 1, linklen); 6474 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 6475 6476 /* 6477 * Now fill in the filename + attrnames section 6478 */ 6479 6480 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 6481 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 6482 stringlen); 6483 (void) strcpy(tptr->h_names, filename); 6484 (void) strcpy(&tptr->h_names[strlen(filename) + 1], attrname); 6485 tptr->h_typeflag = typeflag; 6486 6487 /* 6488 * Now fill in the optional link section if we have one 6489 */ 6490 6491 if (linkinfo != (struct linkbuf *)NULL) { 6492 tptr = (struct xattr_buf *)(bufhead + 6493 sizeof (struct xattr_hdr) + complen); 6494 6495 (void) sprintf(tptr->h_namesz, "%0*d", 6496 sizeof (tptr->h_namesz) - 1, linkstringlen); 6497 (void) strcpy(tptr->h_names, linkinfo->pathname); 6498 (void) strcpy( 6499 &tptr->h_names[strlen(linkinfo->pathname) + 1], 6500 linkinfo->attrname); 6501 tptr->h_typeflag = typeflag; 6502 } 6503 *attrbuf = (char *)bufhead; 6504 *rlen = len; 6505 } 6506 6507 #else 6508 static void 6509 prepare_xattr( 6510 char **attrbuf, 6511 char *filename, 6512 char *attrname, 6513 char typeflag, 6514 struct linkbuf *linkinfo, 6515 int *rlen) 6516 { 6517 *attrbuf = NULL; 6518 *rlen = 0; 6519 } 6520 #endif 6521 6522 int 6523 getstat(int dirfd, char *longname, char *shortname) 6524 { 6525 6526 int i, j; 6527 int printerr; 6528 int slnkerr; 6529 struct stat symlnbuf; 6530 6531 if (!hflag) 6532 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 6533 else 6534 i = fstatat(dirfd, shortname, &stbuf, 0); 6535 6536 6537 if (i < 0) { 6538 /* Initialize flag to print error mesg. */ 6539 printerr = 1; 6540 /* 6541 * If stat is done, then need to do lstat 6542 * to determine whether it's a sym link 6543 */ 6544 if (hflag) { 6545 /* Save returned error */ 6546 slnkerr = errno; 6547 6548 j = fstatat(dirfd, shortname, 6549 &symlnbuf, AT_SYMLINK_NOFOLLOW); 6550 /* 6551 * Suppress error message when file is a symbolic link 6552 * and function modifier 'l' is off. Exception: when 6553 * a symlink points to a symlink points to a 6554 * symlink ... and we get past MAXSYMLINKS. That 6555 * error will cause a file not to be archived, and 6556 * needs to be printed. 6557 */ 6558 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 6559 (S_ISLNK(symlnbuf.st_mode))) 6560 printerr = 0; 6561 6562 /* 6563 * Restore errno in case the lstat 6564 * on symbolic link change 6565 */ 6566 errno = slnkerr; 6567 } 6568 6569 if (printerr) { 6570 (void) fprintf(stderr, gettext( 6571 "tar: %s: %s\n"), longname, strerror(errno)); 6572 Errflg = 1; 6573 } 6574 return (1); 6575 } 6576 return (0); 6577 } 6578 6579 #if defined(O_XATTR) 6580 static void 6581 xattrs_put(char *longname, char *shortname, char *parent) 6582 { 6583 int dirfd; 6584 DIR *dirp; 6585 struct dirent *dp; 6586 6587 if (pathconf(shortname, _PC_XATTR_EXISTS) != 1) { 6588 return; 6589 } 6590 6591 if ((dirfd = attropen(shortname, ".", O_RDONLY)) < 0) { 6592 (void) fprintf(stderr, gettext( 6593 "tar: unable to open attribute directory for file %s\n"), 6594 longname); 6595 return; 6596 } 6597 6598 if ((dirp = fdopendir(dirfd)) == NULL) { 6599 (void) fprintf(stderr, gettext( 6600 "tar: unable to open dir pointer for file %s\n"), longname); 6601 return; 6602 } 6603 6604 while (dp = readdir(dirp)) { 6605 if (dp->d_name[0] == '.' && dp->d_name[1] == '.' && 6606 dp->d_name[2] == '\0') 6607 continue; 6608 6609 if (dp->d_name[0] == '.' && dp->d_name[1] == '\0') 6610 Hiddendir = 1; 6611 else 6612 Hiddendir = 0; 6613 6614 (void) putfile(longname, dp->d_name, parent, 6615 XATTR_FILE, LEV0, SYMLINK_LEV0); 6616 6617 if (exitflag) 6618 break; 6619 } 6620 6621 (void) closedir(dirp); 6622 } 6623 #else 6624 static void 6625 xattrs_put(char *longname, char *shortname, char *parent) 6626 { 6627 } 6628 #endif /* O_XATTR */ 6629 6630 static int 6631 put_link(char *name, char *longname, char *component, 6632 char *prefix, int filetype, char type) 6633 { 6634 6635 if (stbuf.st_nlink > 1) { 6636 struct linkbuf *lp; 6637 int found = 0; 6638 6639 for (lp = ihead; lp != NULL; lp = lp->nextp) 6640 if (lp->inum == stbuf.st_ino && 6641 lp->devnum == stbuf.st_dev) { 6642 found++; 6643 break; 6644 } 6645 if (found) { 6646 #if defined(O_XATTR) 6647 if (filetype == XATTR_FILE) 6648 if (put_xattr_hdr(longname, component, prefix, 6649 type, filetype, lp)) { 6650 goto out; 6651 } 6652 #endif 6653 stbuf.st_size = (off_t)0; 6654 if (filetype != XATTR_FILE) { 6655 tomodes(&stbuf); 6656 if (chk_path_build(name, longname, lp->pathname, 6657 prefix, type, filetype) > 0) { 6658 goto out; 6659 } 6660 } 6661 6662 if (mulvol && tapepos + 1 >= blocklim) 6663 newvol(); 6664 (void) writetbuf((char *)&dblock, 1); 6665 /* 6666 * write_ancillary() is not needed here. 6667 * The first link is handled in the following 6668 * else statement. No need to process ACLs 6669 * for other hard links since they are the 6670 * same file. 6671 */ 6672 6673 if (vflag) { 6674 #ifdef DEBUG 6675 if (NotTape) 6676 DEBUG("seek = %" FMT_blkcnt_t 6677 "K\t", K(tapepos), 0); 6678 #endif 6679 if (filetype == XATTR_FILE) { 6680 (void) fprintf(vfile, gettext( 6681 "a %s attribute %s link to " 6682 "attribute %s\n"), 6683 name, component, lp->attrname); 6684 } else { 6685 (void) fprintf(vfile, gettext( 6686 "a %s link to %s\n"), 6687 longname, lp->pathname); 6688 } 6689 } 6690 lp->count--; 6691 return (0); 6692 } else { 6693 lp = (struct linkbuf *)getmem(sizeof (*lp)); 6694 if (lp != (struct linkbuf *)NULL) { 6695 lp->nextp = ihead; 6696 ihead = lp; 6697 lp->inum = stbuf.st_ino; 6698 lp->devnum = stbuf.st_dev; 6699 lp->count = stbuf.st_nlink - 1; 6700 if (filetype == XATTR_FILE) { 6701 (void) strcpy(lp->pathname, longname); 6702 (void) strcpy(lp->attrname, component); 6703 } else { 6704 (void) strcpy(lp->pathname, longname); 6705 (void) strcpy(lp->attrname, ""); 6706 } 6707 } 6708 } 6709 } 6710 6711 out: 6712 return (1); 6713 } 6714 6715 static int 6716 put_extra_attributes(char *longname, char *shortname, char *prefix, 6717 int filetype, char typeflag) 6718 { 6719 static acl_t *aclp = NULL; 6720 int error; 6721 6722 if (aclp != NULL) { 6723 acl_free(aclp); 6724 aclp = NULL; 6725 } 6726 #if defined(O_XATTR) 6727 if (atflag && filetype == XATTR_FILE) { 6728 if (put_xattr_hdr(longname, shortname, prefix, 6729 typeflag, filetype, NULL)) { 6730 return (1); 6731 } 6732 } 6733 #endif 6734 6735 /* ACL support */ 6736 if (pflag) { 6737 char *secinfo = NULL; 6738 int len = 0; 6739 6740 /* ACL support */ 6741 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 6742 /* 6743 * Get ACL info: dont bother allocating space if 6744 * there is only a trivial ACL. 6745 */ 6746 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 6747 &aclp)) != 0) { 6748 (void) fprintf(stderr, gettext( 6749 "%s: failed to retrieve acl : %s\n"), 6750 longname, acl_strerror(error)); 6751 return (1); 6752 } 6753 } 6754 6755 /* append security attributes if any */ 6756 if (aclp != NULL) { 6757 (void) append_secattr(&secinfo, &len, aclp); 6758 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 6759 } 6760 } 6761 return (0); 6762 } 6763 6764 #if defined(O_XATTR) 6765 static int 6766 put_xattr_hdr(char *longname, char *shortname, char *prefix, 6767 int typeflag, int filetype, struct linkbuf *lp) 6768 { 6769 char *lname = NULL; 6770 char *sname = NULL; 6771 int error = 0; 6772 static char *attrbuf = NULL; 6773 int attrlen; 6774 6775 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 6776 strlen(shortname) + strlen(".hdr") + 1); 6777 6778 if (lname == NULL) { 6779 fatal(gettext("Out of Memory.")); 6780 } 6781 sname = malloc(sizeof (char) * strlen(shortname) + 6782 strlen(".hdr")); 6783 if (sname == NULL) { 6784 fatal(gettext("Out of Memory.")); 6785 } 6786 6787 (void) sprintf(sname, "%s.hdr", shortname); 6788 (void) sprintf(lname, "/dev/null/%s", sname); 6789 6790 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 6791 sizeof (dblock.dbuf.name)) { 6792 fatal(gettext( 6793 "Buffer overflow writing extended attribute file name")); 6794 } 6795 6796 /* 6797 * dump extended attr lookup info 6798 */ 6799 prepare_xattr(&attrbuf, longname, shortname, typeflag, lp, &attrlen); 6800 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 6801 6802 (void) sprintf(lname, "/dev/null/%s", shortname); 6803 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 6804 6805 /* 6806 * Set up filename for attribute 6807 */ 6808 6809 error = build_dblock(lname, tchar, '0', filetype, 6810 &stbuf, stbuf.st_dev, prefix); 6811 free(lname); 6812 free(sname); 6813 6814 return (error); 6815 } 6816 #endif 6817 6818 #if defined(O_XATTR) 6819 static int 6820 read_xattr_hdr() 6821 { 6822 char buf[TBLOCK]; 6823 blkcnt_t blocks; 6824 char *tp; 6825 off_t bytes; 6826 int comp_len, link_len; 6827 int namelen; 6828 6829 6830 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 6831 return (1); 6832 6833 bytes = stbuf.st_size; 6834 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 6835 (void) fprintf(stderr, gettext( 6836 "Insufficient memory for extended attribute\n")); 6837 return (1); 6838 } 6839 6840 tp = (char *)xattrhead; 6841 blocks = TBLOCKS(bytes); 6842 while (blocks-- > 0) { 6843 readtape(buf); 6844 if (bytes <= TBLOCK) { 6845 (void) memcpy(tp, buf, (size_t)bytes); 6846 break; 6847 } else { 6848 (void) memcpy(tp, buf, TBLOCK); 6849 tp += TBLOCK; 6850 } 6851 bytes -= TBLOCK; 6852 } 6853 6854 /* 6855 * Validate that we can handle header format 6856 */ 6857 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 6858 (void) fprintf(stderr, 6859 gettext("Unknown extended attribute format encountered\n")); 6860 (void) fprintf(stderr, 6861 gettext("Disabling extended attribute parsing\n")); 6862 xattrbadhead = 1; 6863 return (0); 6864 } 6865 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 6866 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 6867 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 6868 sizeof (struct xattr_hdr)); 6869 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 6870 if (link_len > 0) 6871 xattr_linkp = (struct xattr_buf *) 6872 ((int)xattrp + (int)comp_len); 6873 else 6874 xattr_linkp = NULL; 6875 6876 xattraname = xattrp->h_names + strlen(xattrp->h_names) + 1; 6877 if (xattr_linkp) { 6878 xattr_linkaname = xattr_linkp->h_names + 6879 strlen(xattr_linkp->h_names) + 1; 6880 } else { 6881 xattr_linkaname = NULL; 6882 } 6883 return (0); 6884 } 6885 #else 6886 static int 6887 read_xattr_hdr() 6888 { 6889 return (0); 6890 } 6891 #endif 6892 6893 /* 6894 * skip over extra slashes in string. 6895 * 6896 * For example: 6897 * /usr/tmp///// 6898 * 6899 * would return pointer at 6900 * /usr/tmp///// 6901 * ^ 6902 */ 6903 static char * 6904 skipslashes(char *string, char *start) 6905 { 6906 while ((string > start) && *(string - 1) == '/') { 6907 string--; 6908 } 6909 6910 return (string); 6911 } 6912 6913 /* 6914 * Return the parent directory of a given path. 6915 * 6916 * Examples: 6917 * /usr/tmp return /usr 6918 * /usr/tmp/file return /usr/tmp 6919 * / returns . 6920 * /usr returns / 6921 * file returns . 6922 * 6923 * dir is assumed to be at least as big as path. 6924 */ 6925 static void 6926 get_parent(char *path, char *dir) 6927 { 6928 char *s; 6929 char tmpdir[PATH_MAX + 1]; 6930 6931 if (strlen(path) > PATH_MAX) { 6932 fatal(gettext("pathname is too long")); 6933 } 6934 (void) strcpy(tmpdir, path); 6935 chop_endslashes(tmpdir); 6936 6937 if ((s = strrchr(tmpdir, '/')) == NULL) { 6938 (void) strcpy(dir, "."); 6939 } else { 6940 s = skipslashes(s, tmpdir); 6941 *s = '\0'; 6942 if (s == tmpdir) 6943 (void) strcpy(dir, "/"); 6944 else 6945 (void) strcpy(dir, tmpdir); 6946 } 6947 } 6948 6949 #if defined(O_XATTR) 6950 static char * 6951 get_component(char *path) 6952 { 6953 char *ptr; 6954 6955 ptr = strrchr(path, '/'); 6956 if (ptr == NULL) { 6957 return (path); 6958 } else { 6959 /* 6960 * Handle trailing slash 6961 */ 6962 if (*(ptr + 1) == '\0') 6963 return (ptr); 6964 else 6965 return (ptr + 1); 6966 } 6967 } 6968 #else 6969 static char * 6970 get_component(char *path) 6971 { 6972 return (path); 6973 } 6974 #endif 6975 6976 static int 6977 retry_attrdir_open(char *name) 6978 { 6979 int dirfd = -1; 6980 struct timeval times[2]; 6981 mode_t newmode; 6982 struct stat parentstat; 6983 6984 /* 6985 * We couldn't get to attrdir. See if its 6986 * just a mode problem on the parent file. 6987 * for example: a mode such as r-xr--r-- 6988 * won't let us create an attribute dir 6989 * if it doesn't already exist. 6990 */ 6991 6992 if (stat(name, &parentstat) == -1) { 6993 (void) fprintf(stderr, gettext("Cannot stat file %s %s\n"), 6994 name, strerror(errno)); 6995 return (1); 6996 } 6997 newmode = S_IWUSR | parentstat.st_mode; 6998 if (chmod(name, newmode) == -1) { 6999 (void) fprintf(stderr, 7000 gettext("Cannot chmod file %s to %o %s\n"), 7001 name, newmode, strerror(errno)); 7002 return (1); 7003 7004 } 7005 7006 dirfd = attropen(name, ".", O_RDONLY); 7007 if (dirfd == -1) { 7008 (void) fprintf(stderr, 7009 gettext("Cannot open attribute directory of" 7010 " file %s %s\n"), name, strerror(errno)); 7011 return (1); 7012 } else { 7013 7014 /* 7015 * Put mode back to original 7016 */ 7017 (void) chmod(name, parentstat.st_mode); 7018 7019 /* 7020 * Put back time stamps 7021 */ 7022 7023 times[0].tv_sec = parentstat.st_atime; 7024 times[0].tv_usec = 0; 7025 times[1].tv_sec = parentstat.st_mtime; 7026 times[1].tv_usec = 0; 7027 (void) utimes(name, times); 7028 } 7029 7030 return (dirfd); 7031 } 7032 7033 #if !defined(O_XATTR) 7034 static int 7035 openat64(int fd, const char *name, int oflag, mode_t cmode) 7036 { 7037 return (open64(name, oflag, cmode)); 7038 } 7039 7040 static int 7041 openat(int fd, const char *name, int oflag, mode_t cmode) 7042 { 7043 return (open(name, oflag, cmode)); 7044 } 7045 7046 static int 7047 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 7048 { 7049 if (flag == AT_SYMLINK_NOFOLLOW) 7050 return (lchown(name, owner, group)); 7051 else 7052 return (chown(name, owner, group)); 7053 } 7054 7055 static int 7056 renameat(int fromfd, char *old, int tofd, char *new) 7057 { 7058 return (rename(old, new)); 7059 } 7060 7061 static int 7062 futimesat(int fd, char *path, struct timeval times[2]) 7063 { 7064 return (utimes(path, times)); 7065 } 7066 7067 static int 7068 unlinkat(int dirfd, char *path, int flag) 7069 { 7070 if (flag == AT_REMOVEDIR) 7071 return (rmdir(path)); 7072 else 7073 return (unlink(path)); 7074 } 7075 7076 static int 7077 fstatat(int fd, char *path, struct stat *buf, int flag) 7078 { 7079 if (flag == AT_SYMLINK_NOFOLLOW) 7080 return (lstat(path, buf)); 7081 else 7082 return (stat(path, buf)); 7083 } 7084 7085 static int 7086 attropen(char *file, char *attr, int omode, mode_t cmode) 7087 { 7088 errno = ENOTSUP; 7089 return (-1); 7090 } 7091 #endif 7092 7093 static void 7094 chop_endslashes(char *path) 7095 { 7096 char *end, *ptr; 7097 7098 /* 7099 * Chop of slashes, but not if all we have is slashes 7100 * for example: //// 7101 * should make no changes, otherwise it will screw up 7102 * checkdir 7103 */ 7104 end = &path[strlen(path) -1]; 7105 if (*end == '/' && end != path) { 7106 ptr = skipslashes(end, path); 7107 if (ptr != NULL && ptr != path) { 7108 *ptr = '\0'; 7109 } 7110 } 7111 } 7112