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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26 /* All Rights Reserved */ 27 28 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 29 /* All Rights Reserved */ 30 31 /* 32 * Portions of this source code were derived from Berkeley 4.3 BSD 33 * under license from the Regents of the University of California. 34 */ 35 36 #include <unistd.h> 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/stat.h> 40 #include <sys/mkdev.h> 41 #include <sys/wait.h> 42 #include <dirent.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <signal.h> 46 #include <ctype.h> 47 #include <locale.h> 48 #include <nl_types.h> 49 #include <langinfo.h> 50 #include <pwd.h> 51 #include <grp.h> 52 #include <fcntl.h> 53 #include <string.h> 54 #include <malloc.h> 55 #include <time.h> 56 #include <utime.h> 57 #include <stdlib.h> 58 #include <stdarg.h> 59 #include <widec.h> 60 #include <sys/mtio.h> 61 #include <sys/acl.h> 62 #include <strings.h> 63 #include <deflt.h> 64 #include <limits.h> 65 #include <iconv.h> 66 #include <assert.h> 67 #include <libgen.h> 68 #include <libintl.h> 69 #include <aclutils.h> 70 #include <libnvpair.h> 71 #include <archives.h> 72 73 #if defined(__SunOS_5_6) || defined(__SunOS_5_7) 74 extern int defcntl(); 75 #endif 76 #if defined(_PC_SATTR_ENABLED) 77 #include <attr.h> 78 #include <libcmdutils.h> 79 #endif 80 81 /* Trusted Extensions */ 82 #include <zone.h> 83 #include <tsol/label.h> 84 #include <sys/tsol/label_macro.h> 85 86 #include "getresponse.h" 87 /* 88 * Source compatibility 89 */ 90 91 /* 92 * These constants come from archives.h and sys/fcntl.h 93 * and were introduced by the extended attributes project 94 * in Solaris 9. 95 */ 96 #if !defined(O_XATTR) 97 #define AT_SYMLINK_NOFOLLOW 0x1000 98 #define AT_REMOVEDIR 0x1 99 #define AT_FDCWD 0xffd19553 100 #define _XATTR_HDRTYPE 'E' 101 static int attropen(); 102 static int fstatat(); 103 static int renameat(); 104 static int unlinkat(); 105 static int openat(); 106 static int fchownat(); 107 static int futimesat(); 108 #endif 109 110 /* 111 * Compiling with -D_XPG4_2 gets this but produces other problems, so 112 * instead of including sys/time.h and compiling with -D_XPG4_2, I'm 113 * explicitly doing the declaration here. 114 */ 115 int utimes(const char *path, const struct timeval timeval_ptr[]); 116 117 #ifndef MINSIZE 118 #define MINSIZE 250 119 #endif 120 #define DEF_FILE "/etc/default/tar" 121 122 #define min(a, b) ((a) < (b) ? (a) : (b)) 123 #define max(a, b) ((a) > (b) ? (a) : (b)) 124 125 /* -DDEBUG ONLY for debugging */ 126 #ifdef DEBUG 127 #undef DEBUG 128 #define DEBUG(a, b, c)\ 129 (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c) 130 #endif 131 132 #define TBLOCK 512 /* tape block size--should be universal */ 133 134 #ifdef BSIZE 135 #define SYS_BLOCK BSIZE /* from sys/param.h: secondary block size */ 136 #else /* BSIZE */ 137 #define SYS_BLOCK 512 /* default if no BSIZE in param.h */ 138 #endif /* BSIZE */ 139 140 #define NBLOCK 20 141 #define NAMSIZ 100 142 #define PRESIZ 155 143 #define MAXNAM 256 144 #define MODEMASK 0777777 /* file creation mode mask */ 145 #define POSIXMODES 07777 /* mask for POSIX mode bits */ 146 #define MAXEXT 9 /* reasonable max # extents for a file */ 147 #define EXTMIN 50 /* min blks left on floppy to split a file */ 148 149 /* max value dblock.dbuf.efsize can store */ 150 #define TAR_EFSIZE_MAX 0777777777 151 152 /* 153 * Symbols which specify the values at which the use of the 'E' function 154 * modifier is required to properly store a file. 155 * 156 * TAR_OFFSET_MAX - the largest file size we can archive 157 * OCTAL7CHAR - the limit for ustar gid, uid, dev 158 */ 159 160 #ifdef XHDR_DEBUG 161 /* tiny values which force the creation of extended header entries */ 162 #define TAR_OFFSET_MAX 9 163 #define OCTAL7CHAR 2 164 #else 165 /* normal values */ 166 #define TAR_OFFSET_MAX 077777777777ULL 167 #define OCTAL7CHAR 07777777 168 #endif 169 170 #define TBLOCKS(bytes) (((bytes) + TBLOCK - 1) / TBLOCK) 171 #define K(tblocks) ((tblocks+1)/2) /* tblocks to Kbytes for printing */ 172 173 #define MAXLEV (PATH_MAX / 2) 174 #define LEV0 1 175 #define SYMLINK_LEV0 0 176 177 #define TRUE 1 178 #define FALSE 0 179 180 #define XATTR_FILE 1 181 #define NORMAL_FILE 0 182 183 #define PUT_AS_LINK 1 184 #define PUT_NOTAS_LINK 0 185 186 #ifndef VIEW_READONLY 187 #define VIEW_READONLY "SUNWattr_ro" 188 #endif 189 190 #ifndef VIEW_READWRITE 191 #define VIEW_READWRITE "SUNWattr_rw" 192 #endif 193 194 #if _FILE_OFFSET_BITS == 64 195 #define FMT_off_t "lld" 196 #define FMT_off_t_o "llo" 197 #define FMT_blkcnt_t "lld" 198 #else 199 #define FMT_off_t "ld" 200 #define FMT_off_t_o "lo" 201 #define FMT_blkcnt_t "ld" 202 #endif 203 204 /* ACL support */ 205 206 static 207 struct sec_attr { 208 char attr_type; 209 char attr_len[7]; 210 char attr_info[1]; 211 } *attr; 212 213 #if defined(O_XATTR) 214 typedef enum { 215 ATTR_OK, 216 ATTR_SKIP, 217 ATTR_CHDIR_ERR, 218 ATTR_OPEN_ERR, 219 ATTR_XATTR_ERR, 220 ATTR_SATTR_ERR 221 } attr_status_t; 222 #endif 223 224 #if defined(O_XATTR) 225 typedef enum { 226 ARC_CREATE, 227 ARC_RESTORE 228 } arc_action_t; 229 #endif 230 231 typedef struct attr_data { 232 char *attr_parent; 233 char *attr_path; 234 int attr_parentfd; 235 int attr_rw_sysattr; 236 } attr_data_t; 237 238 /* 239 * 240 * Tar has been changed to support extended attributes. 241 * 242 * As part of this change tar now uses the new *at() syscalls 243 * such as openat, fchownat(), unlinkat()... 244 * 245 * This was done so that attributes can be handled with as few code changes 246 * as possible. 247 * 248 * What this means is that tar now opens the directory that a file or directory 249 * resides in and then performs *at() functions to manipulate the entry. 250 * 251 * For example a new file is now created like this: 252 * 253 * dfd = open(<some dir path>) 254 * fd = openat(dfd, <name>,....); 255 * 256 * or in the case of an extended attribute 257 * 258 * dfd = attropen(<pathname>, ".", ....) 259 * 260 * Once we have a directory file descriptor all of the *at() functions can 261 * be applied to it. 262 * 263 * unlinkat(dfd, <component name>,...) 264 * fchownat(dfd, <component name>,..) 265 * 266 * This works for both normal namespace files and extended attribute file 267 * 268 */ 269 270 /* 271 * 272 * Extended attribute Format 273 * 274 * Extended attributes are stored in two pieces. 275 * 1. An attribute header which has information about 276 * what file the attribute is for and what the attribute 277 * is named. 278 * 2. The attribute record itself. Stored as a normal file type 279 * of entry. 280 * Both the header and attribute record have special modes/typeflags 281 * associated with them. 282 * 283 * The names of the header in the archive look like: 284 * /dev/null/attr.hdr 285 * 286 * The name of the attribute looks like: 287 * /dev/null/attr 288 * 289 * This is done so that an archiver that doesn't understand these formats 290 * can just dispose of the attribute records. 291 * 292 * The format is composed of a fixed size header followed 293 * by a variable sized xattr_buf. If the attribute is a hard link 294 * to another attribute then another xattr_buf section is included 295 * for the link. 296 * 297 * The xattr_buf is used to define the necessary "pathing" steps 298 * to get to the extended attribute. This is necessary to support 299 * a fully recursive attribute model where an attribute may itself 300 * have an attribute. 301 * 302 * The basic layout looks like this. 303 * 304 * -------------------------------- 305 * | | 306 * | xattr_hdr | 307 * | | 308 * -------------------------------- 309 * -------------------------------- 310 * | | 311 * | xattr_buf | 312 * | | 313 * -------------------------------- 314 * -------------------------------- 315 * | | 316 * | (optional link info) | 317 * | | 318 * -------------------------------- 319 * -------------------------------- 320 * | | 321 * | attribute itself | 322 * | stored as normal tar | 323 * | or cpio data with | 324 * | special mode or | 325 * | typeflag | 326 * | | 327 * -------------------------------- 328 * 329 */ 330 331 /* 332 * xattrhead is a pointer to the xattr_hdr 333 * 334 * xattrp is a pointer to the xattr_buf structure 335 * which contains the "pathing" steps to get to attributes 336 * 337 * xattr_linkp is a pointer to another xattr_buf structure that is 338 * only used when an attribute is actually linked to another attribute 339 * 340 */ 341 342 static struct xattr_hdr *xattrhead; 343 static struct xattr_buf *xattrp; 344 static struct xattr_buf *xattr_linkp; /* pointer to link info, if any */ 345 static char *xattrapath; /* attribute name */ 346 static char *xattr_linkaname; /* attribute attribute is linked to */ 347 static char Hiddendir; /* are we processing hidden xattr dir */ 348 static char xattrbadhead; 349 350 /* Was statically allocated tbuf[NBLOCK] */ 351 static 352 union hblock { 353 char dummy[TBLOCK]; 354 struct header { 355 char name[NAMSIZ]; /* If non-null prefix, path is */ 356 /* <prefix>/<name>; otherwise */ 357 /* <name> */ 358 char mode[8]; 359 char uid[8]; 360 char gid[8]; 361 char size[12]; /* size of this extent if file split */ 362 char mtime[12]; 363 char chksum[8]; 364 char typeflag; 365 char linkname[NAMSIZ]; 366 char magic[6]; 367 char version[2]; 368 char uname[32]; 369 char gname[32]; 370 char devmajor[8]; 371 char devminor[8]; 372 char prefix[PRESIZ]; /* Together with "name", the path of */ 373 /* the file: <prefix>/<name> */ 374 char extno; /* extent #, null if not split */ 375 char extotal; /* total extents */ 376 char efsize[10]; /* size of entire file */ 377 } dbuf; 378 } dblock, *tbuf, xhdr_buf; 379 380 static 381 struct xtar_hdr { 382 uid_t x_uid, /* Uid of file */ 383 x_gid; /* Gid of file */ 384 major_t x_devmajor; /* Device major node */ 385 minor_t x_devminor; /* Device minor node */ 386 off_t x_filesz; /* Length of file */ 387 char *x_uname, /* Pointer to name of user */ 388 *x_gname, /* Pointer to gid of user */ 389 *x_linkpath, /* Path for a hard/symbolic link */ 390 *x_path; /* Path of file */ 391 timestruc_t x_mtime; /* Seconds and nanoseconds */ 392 } Xtarhdr; 393 394 static 395 struct gen_hdr { 396 ulong_t g_mode; /* Mode of file */ 397 uid_t g_uid, /* Uid of file */ 398 g_gid; /* Gid of file */ 399 off_t g_filesz; /* Length of file */ 400 time_t g_mtime; /* Modification time */ 401 uint_t g_cksum; /* Checksum of file */ 402 ulong_t g_devmajor, /* File system of file */ 403 g_devminor; /* Major/minor of special files */ 404 } Gen; 405 406 static 407 struct linkbuf { 408 ino_t inum; 409 dev_t devnum; 410 int count; 411 char pathname[MAXNAM+1]; /* added 1 for last NULL */ 412 char attrname[MAXNAM+1]; 413 struct linkbuf *nextp; 414 } *ihead; 415 416 /* see comments before build_table() */ 417 #define TABLE_SIZE 512 418 typedef struct file_list { 419 char *name; /* Name of file to {in,ex}clude */ 420 struct file_list *next; /* Linked list */ 421 } file_list_t; 422 static file_list_t *exclude_tbl[TABLE_SIZE], 423 *include_tbl[TABLE_SIZE]; 424 425 static int append_secattr(char **, int *, int, char *, char); 426 static void write_ancillary(union hblock *, char *, int, char); 427 428 static void add_file_to_table(file_list_t *table[], char *str); 429 static void assert_string(char *s, char *msg); 430 static int istape(int fd, int type); 431 static void backtape(void); 432 static void build_table(file_list_t *table[], char *file); 433 static int check_prefix(char **namep, char **dirp, char **compp); 434 static void closevol(void); 435 static void copy(void *dst, void *src); 436 static int convtoreg(off_t); 437 static void delete_target(int fd, char *comp, char *namep); 438 static void doDirTimes(char *name, timestruc_t modTime); 439 static void done(int n); 440 static void dorep(char *argv[]); 441 #ifdef _iBCS2 442 static void dotable(char *argv[], int cnt); 443 static void doxtract(char *argv[], int cnt); 444 #else 445 static void dotable(char *argv[]); 446 static void doxtract(char *argv[]); 447 #endif 448 static int is_directory(char *name); 449 static int has_dot_dot(char *name); 450 static int is_absolute(char *name); 451 static char *make_relative_name(char *name, char **stripped_prefix); 452 static void fatal(char *format, ...); 453 static void vperror(int exit_status, char *fmt, ...); 454 static void flushtape(void); 455 static void getdir(void); 456 static void *getmem(size_t); 457 static void longt(struct stat *st, char aclchar); 458 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp); 459 static int makeDir(char *name); 460 static void mterr(char *operation, int i, int exitcode); 461 static void newvol(void); 462 static void passtape(void); 463 static void putempty(blkcnt_t n); 464 static int putfile(char *longname, char *shortname, char *parent, 465 attr_data_t *attrinfo, int filetype, int lev, int symlink_lev); 466 static void readtape(char *buffer); 467 static void seekdisk(blkcnt_t blocks); 468 static void setPathTimes(int dirfd, char *path, timestruc_t modTime); 469 static void setbytes_to_skip(struct stat *st, int err); 470 static void splitfile(char *longname, int ifd, char *name, 471 char *prefix, int filetype); 472 static void tomodes(struct stat *sp); 473 static void usage(void); 474 static int xblocks(int issysattr, off_t bytes, int ofile); 475 static int xsfile(int issysattr, int ofd); 476 static void resugname(int dirfd, char *name, int symflag); 477 static int bcheck(char *bstr); 478 static int checkdir(char *name); 479 static int checksum(union hblock *dblockp); 480 #ifdef EUC 481 static int checksum_signed(union hblock *dblockp); 482 #endif /* EUC */ 483 static int checkupdate(char *arg); 484 static int checkw(char c, char *name); 485 static int cmp(char *b, char *s, int n); 486 static int defset(char *arch); 487 static int endtape(void); 488 static int is_in_table(file_list_t *table[], char *str); 489 static int notsame(void); 490 static int is_prefix(char *s1, char *s2); 491 static int response(void); 492 static int build_dblock(const char *, const char *, const char, 493 const int filetype, const struct stat *, const dev_t, const char *); 494 static unsigned int hash(char *str); 495 496 #ifdef _iBCS2 497 static void initarg(char *argv[], char *file); 498 static char *nextarg(); 499 #endif 500 static blkcnt_t kcheck(char *kstr); 501 static off_t bsrch(char *s, int n, off_t l, off_t h); 502 static void onintr(int sig); 503 static void onquit(int sig); 504 static void onhup(int sig); 505 static uid_t getuidbyname(char *); 506 static gid_t getgidbyname(char *); 507 static char *getname(gid_t); 508 static char *getgroup(gid_t); 509 static int checkf(char *name, int mode, int howmuch); 510 static int writetbuf(char *buffer, int n); 511 static int wantit(char *argv[], char **namep, char **dirp, char **comp, 512 attr_data_t **attrinfo); 513 static void append_ext_attr(char *shortname, char **secinfo, int *len); 514 static int get_xdata(void); 515 static void gen_num(const char *keyword, const u_longlong_t number); 516 static void gen_date(const char *keyword, const timestruc_t time_value); 517 static void gen_string(const char *keyword, const char *value); 518 static void get_xtime(char *value, timestruc_t *xtime); 519 static int chk_path_build(char *name, char *longname, char *linkname, 520 char *prefix, char type, int filetype); 521 static int gen_utf8_names(const char *filename); 522 static int utf8_local(char *option, char **Xhdr_ptrptr, char *target, 523 const char *src, int max_val); 524 static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src, 525 iconv_t iconv_cd, int xhdrflg, int max_val); 526 static int c_utf8(char *target, const char *source); 527 static int getstat(int dirfd, char *longname, char *shortname, 528 char *attrparent); 529 static void xattrs_put(char *, char *, char *, char *); 530 static void prepare_xattr(char **, char *, char *, 531 char, struct linkbuf *, int *); 532 static int put_link(char *name, char *longname, char *component, 533 char *longattrname, char *prefix, int filetype, char typeflag); 534 static int put_extra_attributes(char *longname, char *shortname, 535 char *longattrname, char *prefix, int filetype, char typeflag); 536 static int put_xattr_hdr(char *longname, char *shortname, char *longattrname, 537 char *prefix, int typeflag, int filetype, struct linkbuf *lp); 538 static int read_xattr_hdr(attr_data_t **attrinfo); 539 540 /* Trusted Extensions */ 541 #define AUTO_ZONE "/zone" 542 543 static void extract_attr(char **file_ptr, struct sec_attr *); 544 static int check_ext_attr(char *filename); 545 static void rebuild_comp_path(char *str, char **namep); 546 static int rebuild_lk_comp_path(char *str, char **namep); 547 548 static void get_parent(char *path, char *dir); 549 static char *get_component(char *path); 550 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, 551 char *name, int oflag, mode_t mode); 552 static char *skipslashes(char *string, char *start); 553 static void chop_endslashes(char *path); 554 static pid_t compress_file(void); 555 static void compress_back(void); 556 static void decompress_file(void); 557 static pid_t uncompress_file(void); 558 static void *compress_malloc(size_t); 559 static void check_compression(); 560 static char *bz_suffix(); 561 static char *gz_suffix(); 562 static char *add_suffix(); 563 static void wait_pid(pid_t); 564 565 static struct stat stbuf; 566 567 static char *myname; 568 static int checkflag = 0; 569 #ifdef _iBCS2 570 static int Fileflag; 571 char *sysv3_env; 572 #endif 573 static int Xflag, Fflag, iflag, hflag, Bflag, Iflag; 574 static int rflag, xflag, vflag, tflag, mt, svmt, cflag, mflag, pflag; 575 static int uflag; 576 static int eflag, errflag, qflag; 577 static int oflag; 578 static int bflag, kflag, Aflag; 579 static int Pflag; /* POSIX conformant archive */ 580 static int Eflag; /* Allow files greater than 8GB */ 581 static int atflag; /* traverse extended attributes */ 582 static int saflag; /* traverse extended sys attributes */ 583 static int Dflag; /* Data change flag */ 584 static int jflag; /* flag to use 'bzip2' */ 585 static int zflag; /* flag to use 'gzip' */ 586 static int Zflag; /* flag to use 'compress' */ 587 588 /* Trusted Extensions */ 589 static int Tflag; /* Trusted Extensions attr flags */ 590 static int dir_flag; /* for attribute extract */ 591 static int mld_flag; /* for attribute extract */ 592 static char *orig_namep; /* original namep - unadorned */ 593 static int rpath_flag; /* MLD real path is rebuilt */ 594 static char real_path[MAXPATHLEN]; /* MLD real path */ 595 static int lk_rpath_flag; /* linked to real path is rebuilt */ 596 static char lk_real_path[MAXPATHLEN]; /* linked real path */ 597 static bslabel_t bs_label; /* for attribute extract */ 598 static bslabel_t admin_low; 599 static bslabel_t admin_high; 600 static int ignored_aprivs = 0; 601 static int ignored_fprivs = 0; 602 static int ignored_fattrs = 0; 603 604 static int term, chksum, wflag, 605 first = TRUE, defaults_used = FALSE, linkerrok; 606 static blkcnt_t recno; 607 static int freemem = 1; 608 static int nblock = NBLOCK; 609 static int Errflg = 0; 610 static int exitflag = 0; 611 612 static dev_t mt_dev; /* device containing output file */ 613 static ino_t mt_ino; /* inode number of output file */ 614 static int mt_devtype; /* dev type of archive, from stat structure */ 615 616 static int update = 1; /* for `open' call */ 617 618 static off_t low; 619 static off_t high; 620 621 static FILE *tfile; 622 static FILE *vfile = stdout; 623 static char *tmpdir; 624 static char *tmp_suffix = "/tarXXXXXX"; 625 static char *tname; 626 static char archive[] = "archive0="; 627 static char *Xfile; 628 static char *usefile; 629 static char tfname[1024]; 630 static char *Filefile; 631 632 static int mulvol; /* multi-volume option selected */ 633 static blkcnt_t blocklim; /* number of blocks to accept per volume */ 634 static blkcnt_t tapepos; /* current block number to be written */ 635 static int NotTape; /* true if tape is a disk */ 636 static int dumping; /* true if writing a tape or other archive */ 637 static int extno; /* number of extent: starts at 1 */ 638 static int extotal; /* total extents in this file */ 639 static off_t extsize; /* size of current extent during extraction */ 640 static ushort_t Oumask = 0; /* old umask value */ 641 static int is_posix; /* true if archive we're reading is POSIX-conformant */ 642 static const char *magic_type = "ustar"; 643 static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */ 644 static char *xrec_ptr; 645 static off_t xrec_offset = 0; 646 static int Xhdrflag; 647 static int charset_type = 0; 648 649 static u_longlong_t xhdr_flgs; /* Bits set determine which items */ 650 /* need to be in extended header. */ 651 #define _X_DEVMAJOR 0x1 652 #define _X_DEVMINOR 0x2 653 #define _X_GID 0x4 654 #define _X_GNAME 0x8 655 #define _X_LINKPATH 0x10 656 #define _X_PATH 0x20 657 #define _X_SIZE 0x40 658 #define _X_UID 0x80 659 #define _X_UNAME 0x100 660 #define _X_ATIME 0x200 661 #define _X_CTIME 0x400 662 #define _X_MTIME 0x800 663 #define _X_XHDR 0x1000 /* Bit flag that determines whether 'X' */ 664 /* typeflag was followed by 'A' or non 'A' */ 665 /* typeflag. */ 666 #define _X_LAST 0x40000000 667 668 #define PID_MAX_DIGITS (10 * sizeof (pid_t) / 4) 669 #define TIME_MAX_DIGITS (10 * sizeof (time_t) / 4) 670 #define LONG_MAX_DIGITS (10 * sizeof (long) / 4) 671 #define ULONGLONG_MAX_DIGITS (10 * sizeof (u_longlong_t) / 4) 672 /* 673 * UTF_8 encoding requires more space than the current codeset equivalent. 674 * Currently a factor of 2-3 would suffice, but it is possible for a factor 675 * of 6 to be needed in the future, so for saftey, we use that here. 676 */ 677 #define UTF_8_FACTOR 6 678 679 static u_longlong_t xhdr_count = 0; 680 static char xhdr_dirname[PRESIZ + 1]; 681 static char pidchars[PID_MAX_DIGITS + 1]; 682 static char *tchar = ""; /* null linkpath */ 683 684 static char local_path[UTF_8_FACTOR * PATH_MAX + 1]; 685 static char local_linkpath[UTF_8_FACTOR * PATH_MAX + 1]; 686 static char local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 687 static char local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 688 689 /* 690 * The following mechanism is provided to allow us to debug tar in complicated 691 * situations, like when it is part of a pipe. The idea is that you compile 692 * with -DWAITAROUND defined, and then add the 'D' function modifier to the 693 * target tar invocation, eg. "tar cDf tarfile file". If stderr is available, 694 * it will tell you to which pid to attach the debugger; otherwise, use ps to 695 * find it. Attach to the process from the debugger, and, *PRESTO*, you are 696 * there! 697 * 698 * Simply assign "waitaround = 0" once you attach to the process, and then 699 * proceed from there as usual. 700 */ 701 702 #ifdef WAITAROUND 703 int waitaround = 0; /* wait for rendezvous with the debugger */ 704 #endif 705 706 #define BZIP "/usr/bin/bzip2" 707 #define GZIP "/usr/bin/gzip" 708 #define COMPRESS "/usr/bin/compress" 709 #define BZCAT "/usr/bin/bzcat" 710 #define GZCAT "/usr/bin/gzcat" 711 #define ZCAT "/usr/bin/zcat" 712 #define GS 8 /* number of valid 'gzip' sufixes */ 713 #define BS 4 /* number of valid 'bzip2' sufixes */ 714 715 static char *compress_opt; /* compression type */ 716 717 static char *gsuffix[] = {".gz", "-gz", ".z", "-z", "_z", ".Z", 718 ".tgz", ".taz"}; 719 static char *bsuffix[] = {".bz2", ".bz", ".tbz2", ".tbz"}; 720 static char *suffix; 721 722 723 int 724 main(int argc, char *argv[]) 725 { 726 char *cp; 727 char *tmpdirp; 728 pid_t thispid; 729 pid_t pid; 730 int wstat; 731 732 #ifdef _iBCS2 733 int tbl_cnt = 0; 734 sysv3_env = getenv("SYSV3"); 735 #endif 736 (void) setlocale(LC_ALL, ""); 737 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 738 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 739 #endif 740 (void) textdomain(TEXT_DOMAIN); 741 if (argc < 2) 742 usage(); 743 744 tfile = NULL; 745 if ((myname = strdup(argv[0])) == NULL) { 746 (void) fprintf(stderr, gettext( 747 "tar: cannot allocate program name\n")); 748 exit(1); 749 } 750 751 if (init_yes() < 0) { 752 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES), 753 strerror(errno)); 754 exit(2); 755 } 756 757 /* 758 * For XPG4 compatibility, we must be able to accept the "--" 759 * argument normally recognized by getopt; it is used to delimit 760 * the end opt the options section, and so can only appear in 761 * the position of the first argument. We simply skip it. 762 */ 763 764 if (strcmp(argv[1], "--") == 0) { 765 argv++; 766 argc--; 767 if (argc < 3) 768 usage(); 769 } 770 771 argv[argc] = NULL; 772 argv++; 773 774 /* 775 * Set up default values. 776 * Search the operand string looking for the first digit or an 'f'. 777 * If you find a digit, use the 'archive#' entry in DEF_FILE. 778 * If 'f' is given, bypass looking in DEF_FILE altogether. 779 * If no digit or 'f' is given, still look in DEF_FILE but use '0'. 780 */ 781 if ((usefile = getenv("TAPE")) == (char *)NULL) { 782 for (cp = *argv; *cp; ++cp) 783 if (isdigit(*cp) || *cp == 'f') 784 break; 785 if (*cp != 'f') { 786 archive[7] = (*cp)? *cp: '0'; 787 if (!(defaults_used = defset(archive))) { 788 usefile = NULL; 789 nblock = 1; 790 blocklim = 0; 791 NotTape = 0; 792 } 793 } 794 } 795 796 for (cp = *argv++; *cp; cp++) 797 switch (*cp) { 798 #ifdef WAITAROUND 799 case 'D': 800 /* rendezvous with the debugger */ 801 waitaround = 1; 802 break; 803 #endif 804 case 'f': 805 assert_string(*argv, gettext( 806 "tar: tarfile must be specified with 'f' " 807 "function modifier\n")); 808 usefile = *argv++; 809 break; 810 case 'F': 811 #ifdef _iBCS2 812 if (sysv3_env) { 813 assert_string(*argv, gettext( 814 "tar: 'F' requires a file name\n")); 815 Filefile = *argv++; 816 Fileflag++; 817 } else 818 #endif /* _iBCS2 */ 819 Fflag++; 820 break; 821 case 'c': 822 cflag++; 823 rflag++; 824 update = 1; 825 break; 826 #if defined(O_XATTR) 827 case '@': 828 atflag++; 829 break; 830 #endif /* O_XATTR */ 831 #if defined(_PC_SATTR_ENABLED) 832 case '/': 833 saflag++; 834 break; 835 #endif /* _PC_SATTR_ENABLED */ 836 case 'u': 837 uflag++; /* moved code after signals caught */ 838 rflag++; 839 update = 2; 840 break; 841 case 'r': 842 rflag++; 843 update = 2; 844 break; 845 case 'v': 846 vflag++; 847 break; 848 case 'w': 849 wflag++; 850 break; 851 case 'x': 852 xflag++; 853 break; 854 case 'X': 855 assert_string(*argv, gettext( 856 "tar: exclude file must be specified with 'X' " 857 "function modifier\n")); 858 Xflag = 1; 859 Xfile = *argv++; 860 build_table(exclude_tbl, Xfile); 861 break; 862 case 't': 863 tflag++; 864 break; 865 case 'm': 866 mflag++; 867 break; 868 case 'p': 869 pflag++; 870 break; 871 case 'D': 872 Dflag++; 873 break; 874 case '-': 875 /* ignore this silently */ 876 break; 877 case '0': /* numeric entries used only for defaults */ 878 case '1': 879 case '2': 880 case '3': 881 case '4': 882 case '5': 883 case '6': 884 case '7': 885 break; 886 case 'b': 887 assert_string(*argv, gettext( 888 "tar: blocking factor must be specified " 889 "with 'b' function modifier\n")); 890 bflag++; 891 nblock = bcheck(*argv++); 892 break; 893 case 'q': 894 qflag++; 895 break; 896 case 'k': 897 assert_string(*argv, gettext( 898 "tar: size value must be specified with 'k' " 899 "function modifier\n")); 900 kflag++; 901 blocklim = kcheck(*argv++); 902 break; 903 case 'n': /* not a magtape (instead of 'k') */ 904 NotTape++; /* assume non-magtape */ 905 break; 906 case 'l': 907 linkerrok++; 908 break; 909 case 'e': 910 #ifdef _iBCS2 911 /* If sysv3 IS set, don't be as verbose */ 912 if (!sysv3_env) 913 #endif /* _iBCS2 */ 914 errflag++; 915 eflag++; 916 break; 917 case 'o': 918 oflag++; 919 break; 920 case 'h': 921 hflag++; 922 break; 923 case 'i': 924 iflag++; 925 break; 926 case 'B': 927 Bflag++; 928 break; 929 case 'P': 930 Pflag++; 931 break; 932 case 'E': 933 Eflag++; 934 Pflag++; /* Only POSIX archive made */ 935 break; 936 case 'T': 937 Tflag++; /* Handle Trusted Extensions attrs */ 938 pflag++; /* also set flag for ACL */ 939 break; 940 case 'j': /* compession "bzip2" */ 941 jflag++; 942 break; 943 case 'z': /* compression "gzip" */ 944 zflag++; 945 break; 946 case 'Z': /* compression "compress" */ 947 Zflag++; 948 break; 949 default: 950 (void) fprintf(stderr, gettext( 951 "tar: %c: unknown function modifier\n"), *cp); 952 usage(); 953 } 954 955 #ifdef _iBCS2 956 if (Xflag && Fileflag) { 957 (void) fprintf(stderr, gettext( 958 "tar: specify only one of X or F.\n")); 959 usage(); 960 } 961 #endif /* _iBCS2 */ 962 963 if (!rflag && !xflag && !tflag) 964 usage(); 965 if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) { 966 (void) fprintf(stderr, gettext( 967 "tar: specify only one of [ctxru].\n")); 968 usage(); 969 } 970 if (cflag) { 971 if ((zflag && jflag) || (zflag && Zflag) || 972 (jflag && Zflag)) { 973 (void) fprintf(stderr, gettext( 974 "tar: specify only one of [jzZ] to " 975 "create a compressed file.\n")); 976 usage(); 977 } 978 } 979 /* Trusted Extensions attribute handling */ 980 if (Tflag && ((getzoneid() != GLOBAL_ZONEID) || 981 !is_system_labeled())) { 982 (void) fprintf(stderr, gettext( 983 "tar: the 'T' option is only available with " 984 "Trusted Extensions\nand must be run from " 985 "the global zone.\n")); 986 usage(); 987 } 988 if (cflag && *argv == NULL && Filefile == NULL) 989 fatal(gettext("Missing filenames")); 990 if (usefile == NULL) 991 fatal(gettext("device argument required")); 992 993 /* alloc a buffer of the right size */ 994 if ((tbuf = (union hblock *) 995 calloc(sizeof (union hblock) * nblock, sizeof (char))) == 996 (union hblock *)NULL) { 997 (void) fprintf(stderr, gettext( 998 "tar: cannot allocate physio buffer\n")); 999 exit(1); 1000 } 1001 1002 if ((xrec_ptr = malloc(xrec_size)) == NULL) { 1003 (void) fprintf(stderr, gettext( 1004 "tar: cannot allocate extended header buffer\n")); 1005 exit(1); 1006 } 1007 1008 #ifdef WAITAROUND 1009 if (waitaround) { 1010 (void) fprintf(stderr, gettext("Rendezvous with tar on pid" 1011 " %d\n"), getpid()); 1012 1013 while (waitaround) { 1014 (void) sleep(10); 1015 } 1016 } 1017 #endif 1018 1019 thispid = getpid(); 1020 (void) sprintf(pidchars, "%ld", thispid); 1021 thispid = strlen(pidchars); 1022 1023 if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL) 1024 (void) strcpy(xhdr_dirname, "/tmp"); 1025 else { 1026 /* 1027 * Make sure that dir is no longer than what can 1028 * fit in the prefix part of the header. 1029 */ 1030 if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) { 1031 (void) strcpy(xhdr_dirname, "/tmp"); 1032 if ((vflag > 0) && (Eflag > 0)) 1033 (void) fprintf(stderr, gettext( 1034 "Ignoring TMPDIR\n")); 1035 } else 1036 (void) strcpy(xhdr_dirname, tmpdirp); 1037 } 1038 (void) strcat(xhdr_dirname, "/PaxHeaders."); 1039 (void) strcat(xhdr_dirname, pidchars); 1040 1041 if (rflag) { 1042 if (cflag && usefile != NULL) { 1043 /* Set the compression type */ 1044 if (jflag) { 1045 compress_opt = compress_malloc(strlen(BZIP) 1046 + 1); 1047 (void) strcpy(compress_opt, BZIP); 1048 } else if (zflag) { 1049 compress_opt = compress_malloc(strlen(GZIP) 1050 + 1); 1051 (void) strcpy(compress_opt, GZIP); 1052 } else if (Zflag) { 1053 compress_opt = 1054 compress_malloc(strlen(COMPRESS) + 1); 1055 (void) strcpy(compress_opt, COMPRESS); 1056 } 1057 } else { 1058 /* 1059 * Decompress if the file is compressed for 1060 * an update or replace. 1061 */ 1062 if (strcmp(usefile, "-") != 0) { 1063 check_compression(); 1064 if (compress_opt != NULL) { 1065 decompress_file(); 1066 } 1067 } 1068 } 1069 1070 if (cflag && tfile != NULL) 1071 usage(); 1072 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 1073 (void) signal(SIGINT, onintr); 1074 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 1075 (void) signal(SIGHUP, onhup); 1076 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 1077 (void) signal(SIGQUIT, onquit); 1078 if (uflag) { 1079 int tnum; 1080 struct stat sbuf; 1081 1082 tmpdir = getenv("TMPDIR"); 1083 /* 1084 * If the name is invalid or this isn't a directory, 1085 * or the directory is not writable, then reset to 1086 * a default temporary directory. 1087 */ 1088 if (tmpdir == NULL || *tmpdir == '\0' || 1089 (strlen(tmpdir) + strlen(tmp_suffix)) > PATH_MAX) { 1090 tmpdir = "/tmp"; 1091 } else if (stat(tmpdir, &sbuf) < 0 || 1092 (sbuf.st_mode & S_IFMT) != S_IFDIR || 1093 (sbuf.st_mode & S_IWRITE) == 0) { 1094 tmpdir = "/tmp"; 1095 } 1096 1097 if ((tname = calloc(1, strlen(tmpdir) + 1098 strlen(tmp_suffix) + 1)) == NULL) { 1099 vperror(1, gettext("tar: out of memory, " 1100 "cannot create temporary file\n")); 1101 } 1102 (void) strcpy(tname, tmpdir); 1103 (void) strcat(tname, tmp_suffix); 1104 1105 if ((tnum = mkstemp(tname)) == -1) 1106 vperror(1, "%s", tname); 1107 if ((tfile = fdopen(tnum, "w")) == NULL) 1108 vperror(1, "%s", tname); 1109 } 1110 if (strcmp(usefile, "-") == 0) { 1111 if (cflag == 0) 1112 fatal(gettext( 1113 "can only create standard output archives.")); 1114 vfile = stderr; 1115 mt = dup(1); 1116 ++bflag; 1117 } else { 1118 if (cflag) 1119 mt = open(usefile, 1120 O_RDWR|O_CREAT|O_TRUNC, 0666); 1121 else 1122 mt = open(usefile, O_RDWR); 1123 1124 if (mt < 0) { 1125 if (cflag == 0 || (mt = creat(usefile, 0666)) 1126 < 0) 1127 vperror(1, "%s", usefile); 1128 } 1129 } 1130 /* Get inode and device number of output file */ 1131 (void) fstat(mt, &stbuf); 1132 mt_ino = stbuf.st_ino; 1133 mt_dev = stbuf.st_dev; 1134 mt_devtype = stbuf.st_mode & S_IFMT; 1135 NotTape = !istape(mt, mt_devtype); 1136 1137 if (rflag && !cflag && (mt_devtype == S_IFIFO)) 1138 fatal(gettext("cannot append to pipe or FIFO.")); 1139 1140 if (Aflag && vflag) 1141 (void) printf( 1142 gettext("Suppressing absolute pathnames\n")); 1143 if (cflag && compress_opt != NULL) { 1144 pid = compress_file(); 1145 wait_pid(pid); 1146 } 1147 dorep(argv); 1148 if (rflag && !cflag && (compress_opt != NULL)) 1149 compress_back(); 1150 } else if (xflag || tflag) { 1151 /* 1152 * for each argument, check to see if there is a "-I file" pair. 1153 * if so, move the 3rd argument into "-I"'s place, build_table() 1154 * using "file"'s name and increment argc one (the second 1155 * increment appears in the for loop) which removes the two 1156 * args "-I" and "file" from the argument vector. 1157 */ 1158 for (argc = 0; argv[argc]; argc++) { 1159 if (strcmp(argv[argc], "-I") == 0) { 1160 if (!argv[argc+1]) { 1161 (void) fprintf(stderr, gettext( 1162 "tar: missing argument for -I flag\n")); 1163 done(2); 1164 } else { 1165 Iflag = 1; 1166 argv[argc] = argv[argc+2]; 1167 build_table(include_tbl, argv[++argc]); 1168 #ifdef _iBCS2 1169 if (Fileflag) { 1170 (void) fprintf(stderr, gettext( 1171 "tar: only one of I or F.\n")); 1172 usage(); 1173 } 1174 #endif /* _iBCS2 */ 1175 1176 } 1177 } 1178 } 1179 if (strcmp(usefile, "-") == 0) { 1180 mt = dup(0); 1181 ++bflag; 1182 /* try to recover from short reads when reading stdin */ 1183 ++Bflag; 1184 } else if ((mt = open(usefile, 0)) < 0) 1185 vperror(1, "%s", usefile); 1186 1187 /* Decompress if the file is compressed */ 1188 1189 if (strcmp(usefile, "-") != 0) { 1190 check_compression(); 1191 if (compress_opt != NULL) { 1192 pid = uncompress_file(); 1193 wait_pid(pid); 1194 } 1195 } 1196 if (xflag) { 1197 if (Aflag && vflag) 1198 (void) printf(gettext( 1199 "Suppressing absolute pathnames.\n")); 1200 1201 #ifdef _iBCS2 1202 doxtract(argv, tbl_cnt); 1203 #else 1204 doxtract(argv); 1205 #endif 1206 } else if (tflag) 1207 1208 #ifdef _iBCS2 1209 dotable(argv, tbl_cnt); 1210 #else 1211 dotable(argv); 1212 #endif 1213 } 1214 else 1215 usage(); 1216 1217 done(Errflg); 1218 1219 /* Not reached: keep compiler quiet */ 1220 return (1); 1221 } 1222 1223 static void 1224 usage(void) 1225 { 1226 1227 #ifdef _iBCS2 1228 if (sysv3_env) { 1229 (void) fprintf(stderr, gettext( 1230 #if defined(O_XATTR) 1231 #if defined(_PC_SATTR_ENABLED) 1232 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] " 1233 #else 1234 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] " 1235 #endif /* _PC_SATTR_ENABLED */ 1236 #else 1237 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] " 1238 #endif /* O_XATTR */ 1239 "[j|z|Z] " 1240 "[blocksize] [tarfile] [filename] [size] [exclude-file...] " 1241 "{file | -I include-file | -C directory file}...\n")); 1242 } else 1243 #endif /* _iBCS2 */ 1244 { 1245 (void) fprintf(stderr, gettext( 1246 #if defined(O_XATTR) 1247 #if defined(_PC_SATTR_ENABLED) 1248 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] " 1249 #else 1250 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] " 1251 #endif /* _PC_SATTR_ENABLED */ 1252 #else 1253 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] " 1254 #endif /* O_XATTR */ 1255 "[j|z|Z] " 1256 "[blocksize] [tarfile] [size] [exclude-file...] " 1257 "{file | -I include-file | -C directory file}...\n")); 1258 } 1259 done(1); 1260 } 1261 1262 /* 1263 * dorep - do "replacements" 1264 * 1265 * Dorep is responsible for creating ('c'), appending ('r') 1266 * and updating ('u'); 1267 */ 1268 1269 static void 1270 dorep(char *argv[]) 1271 { 1272 char *cp, *cp2, *p; 1273 char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent; 1274 char file[PATH_MAX*2], origdir[PATH_MAX+1]; 1275 FILE *fp = (FILE *)NULL; 1276 FILE *ff = (FILE *)NULL; 1277 int archtype; 1278 int ret; 1279 1280 1281 if (!cflag) { 1282 xhdr_flgs = 0; 1283 getdir(); /* read header for next file */ 1284 if (Xhdrflag > 0) { 1285 if (!Eflag) 1286 fatal(gettext("Archive contains extended" 1287 " header. -E flag required.\n")); 1288 ret = get_xdata(); /* Get extended header items */ 1289 /* and regular header */ 1290 } else { 1291 if (Eflag) 1292 fatal(gettext("Archive contains no extended" 1293 " header. -E flag not allowed.\n")); 1294 } 1295 while (!endtape()) { /* changed from a do while */ 1296 setbytes_to_skip(&stbuf, ret); 1297 passtape(); /* skip the file data */ 1298 if (term) 1299 done(Errflg); /* received signal to stop */ 1300 xhdr_flgs = 0; 1301 getdir(); 1302 if (Xhdrflag > 0) 1303 ret = get_xdata(); 1304 } 1305 if (ret == 0) { 1306 if ((dblock.dbuf.typeflag != 'A') && 1307 (xhdr_flgs != 0)) { 1308 load_info_from_xtarhdr(xhdr_flgs, 1309 &Xtarhdr); 1310 xhdr_flgs |= _X_XHDR; 1311 } 1312 } 1313 backtape(); /* was called by endtape */ 1314 if (tfile != NULL) { 1315 /* 1316 * Buffer size is calculated to be the size of the 1317 * tmpdir string, plus 6 times the size of the tname 1318 * string, plus a value that is known to be greater 1319 * than the command pipeline string. 1320 */ 1321 int buflen = strlen(tmpdir) + (6 * strlen(tname)) + 100; 1322 char *buf; 1323 1324 if ((buf = (char *)calloc(1, buflen)) == NULL) { 1325 vperror(1, gettext("tar: out of memory, " 1326 "cannot create sort command file\n")); 1327 } 1328 1329 (void) snprintf(buf, buflen, "env 'TMPDIR=%s' " 1330 "sort +0 -1 +1nr %s -o %s; awk '$1 " 1331 "!= prev {print; prev=$1}' %s >%sX;mv %sX %s", 1332 tmpdir, tname, tname, tname, tname, tname, tname); 1333 (void) fflush(tfile); 1334 (void) system(buf); 1335 free(buf); 1336 (void) freopen(tname, "r", tfile); 1337 (void) fstat(fileno(tfile), &stbuf); 1338 high = stbuf.st_size; 1339 } 1340 } 1341 1342 dumping = 1; 1343 if (mulvol) { /* SP-1 */ 1344 if (nblock && (blocklim%nblock) != 0) 1345 fatal(gettext( 1346 "Volume size not a multiple of block size.")); 1347 blocklim -= 2; /* for trailer records */ 1348 if (vflag) 1349 (void) fprintf(vfile, gettext("Volume ends at %" 1350 FMT_blkcnt_t "K, blocking factor = %dK\n"), 1351 K((blocklim - 1)), K(nblock)); 1352 } 1353 1354 #ifdef _iBCS2 1355 if (Fileflag) { 1356 if (Filefile != NULL) { 1357 if ((ff = fopen(Filefile, "r")) == NULL) 1358 vperror(0, "%s", Filefile); 1359 } else { 1360 (void) fprintf(stderr, gettext( 1361 "tar: F requires a file name.\n")); 1362 usage(); 1363 } 1364 } 1365 #endif /* _iBCS2 */ 1366 1367 /* 1368 * Save the original directory before it gets 1369 * changed. 1370 */ 1371 if (getcwd(origdir, (PATH_MAX+1)) == NULL) { 1372 vperror(0, gettext("A parent directory cannot be read")); 1373 exit(1); 1374 } 1375 1376 (void) strcpy(wdir, origdir); 1377 1378 while ((*argv || fp || ff) && !term) { 1379 if (fp || (strcmp(*argv, "-I") == 0)) { 1380 #ifdef _iBCS2 1381 if (Fileflag) { 1382 (void) fprintf(stderr, gettext( 1383 "tar: only one of I or F.\n")); 1384 usage(); 1385 } 1386 #endif /* _iBCS2 */ 1387 if (fp == NULL) { 1388 if (*++argv == NULL) 1389 fatal(gettext( 1390 "missing file name for -I flag.")); 1391 else if ((fp = fopen(*argv++, "r")) == NULL) 1392 vperror(0, "%s", argv[-1]); 1393 continue; 1394 } else if ((fgets(file, PATH_MAX-1, fp)) == NULL) { 1395 (void) fclose(fp); 1396 fp = NULL; 1397 continue; 1398 } else { 1399 cp = cp2 = file; 1400 if ((p = strchr(cp2, '\n'))) 1401 *p = 0; 1402 } 1403 } else if ((strcmp(*argv, "-C") == 0) && argv[1]) { 1404 #ifdef _iBCS2 1405 if (Fileflag) { 1406 (void) fprintf(stderr, gettext( 1407 "tar: only one of F or C\n")); 1408 usage(); 1409 } 1410 #endif /* _iBCS2 */ 1411 1412 if (chdir(*++argv) < 0) 1413 vperror(0, gettext( 1414 "can't change directories to %s"), *argv); 1415 else 1416 (void) getcwd(wdir, (sizeof (wdir))); 1417 argv++; 1418 continue; 1419 #ifdef _iBCS2 1420 } else if (Fileflag && (ff != NULL)) { 1421 if ((fgets(file, PATH_MAX-1, ff)) == NULL) { 1422 (void) fclose(ff); 1423 ff = NULL; 1424 continue; 1425 } else { 1426 cp = cp2 = file; 1427 if (p = strchr(cp2, '\n')) 1428 *p = 0; 1429 } 1430 #endif /* _iBCS2 */ 1431 } else 1432 cp = cp2 = strcpy(file, *argv++); 1433 1434 /* 1435 * point cp2 to the last '/' in file, but not 1436 * to a trailing '/' 1437 */ 1438 for (; *cp; cp++) { 1439 if (*cp == '/') { 1440 while (*(cp+1) == '/') { 1441 ++cp; 1442 } 1443 if (*(cp+1) != '\0') { 1444 /* not trailing slash */ 1445 cp2 = cp; 1446 } 1447 } 1448 } 1449 if (cp2 != file) { 1450 *cp2 = '\0'; 1451 if (chdir(file) < 0) { 1452 vperror(0, gettext( 1453 "can't change directories to %s"), file); 1454 continue; 1455 } 1456 *cp2 = '/'; 1457 cp2++; 1458 } 1459 1460 parent = getcwd(tempdir, (sizeof (tempdir))); 1461 1462 archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE, 1463 LEV0, SYMLINK_LEV0); 1464 1465 #if defined(O_XATTR) 1466 if (!exitflag) { 1467 if ((atflag || saflag) && 1468 (archtype == PUT_NOTAS_LINK)) { 1469 xattrs_put(file, cp2, parent, NULL); 1470 } 1471 } 1472 #endif 1473 1474 if (chdir(origdir) < 0) 1475 vperror(0, gettext("cannot change back?: %s"), origdir); 1476 1477 if (exitflag) { 1478 /* 1479 * If e function modifier has been specified 1480 * write the files (that are listed before the 1481 * file causing the error) to tape. exitflag is 1482 * used because only some of the error conditions 1483 * in putfile() recognize the e function modifier. 1484 */ 1485 break; 1486 } 1487 } 1488 1489 putempty((blkcnt_t)2); 1490 flushtape(); 1491 closevol(); /* SP-1 */ 1492 if (linkerrok == 1) 1493 for (; ihead != NULL; ihead = ihead->nextp) { 1494 if (ihead->count == 0) 1495 continue; 1496 (void) fprintf(stderr, gettext( 1497 "tar: missing links to %s\n"), ihead->pathname); 1498 if (errflag) 1499 done(1); 1500 else 1501 Errflg = 1; 1502 } 1503 } 1504 1505 1506 /* 1507 * endtape - check for tape at end 1508 * 1509 * endtape checks the entry in dblock.dbuf to see if its the 1510 * special EOT entry. Endtape is usually called after getdir(). 1511 * 1512 * endtape used to call backtape; it no longer does, he who 1513 * wants it backed up must call backtape himself 1514 * RETURNS: 0 if not EOT, tape position unaffected 1515 * 1 if EOT, tape position unaffected 1516 */ 1517 1518 static int 1519 endtape(void) 1520 { 1521 if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */ 1522 return (1); 1523 } else 1524 return (0); 1525 } 1526 1527 /* 1528 * getdir - get directory entry from tar tape 1529 * 1530 * getdir reads the next tarblock off the tape and cracks 1531 * it as a directory. The checksum must match properly. 1532 * 1533 * If tfile is non-null getdir writes the file name and mod date 1534 * to tfile. 1535 */ 1536 1537 static void 1538 getdir(void) 1539 { 1540 struct stat *sp; 1541 #ifdef EUC 1542 static int warn_chksum_sign = 0; 1543 #endif /* EUC */ 1544 1545 top: 1546 readtape((char *)&dblock); 1547 if (dblock.dbuf.name[0] == '\0') 1548 return; 1549 sp = &stbuf; 1550 (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode); 1551 (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid); 1552 (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid); 1553 (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz); 1554 (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime); 1555 (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum); 1556 (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor); 1557 (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor); 1558 1559 is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0); 1560 1561 sp->st_mode = Gen.g_mode; 1562 if (is_posix && (sp->st_mode & S_IFMT) == 0) 1563 switch (dblock.dbuf.typeflag) { 1564 case '0': case 0: case _XATTR_HDRTYPE: 1565 sp->st_mode |= S_IFREG; 1566 break; 1567 case '1': /* hard link */ 1568 break; 1569 case '2': 1570 sp->st_mode |= S_IFLNK; 1571 break; 1572 case '3': 1573 sp->st_mode |= S_IFCHR; 1574 break; 1575 case '4': 1576 sp->st_mode |= S_IFBLK; 1577 break; 1578 case '5': 1579 sp->st_mode |= S_IFDIR; 1580 break; 1581 case '6': 1582 sp->st_mode |= S_IFIFO; 1583 break; 1584 default: 1585 if (convtoreg(Gen.g_filesz)) 1586 sp->st_mode |= S_IFREG; 1587 break; 1588 } 1589 1590 if ((dblock.dbuf.typeflag == 'X') || (dblock.dbuf.typeflag == 'L')) { 1591 Xhdrflag = 1; /* Currently processing extended header */ 1592 } else { 1593 Xhdrflag = 0; 1594 } 1595 1596 sp->st_uid = Gen.g_uid; 1597 sp->st_gid = Gen.g_gid; 1598 sp->st_size = Gen.g_filesz; 1599 sp->st_mtime = Gen.g_mtime; 1600 chksum = Gen.g_cksum; 1601 1602 if (dblock.dbuf.extno != '\0') { /* split file? */ 1603 extno = dblock.dbuf.extno; 1604 extsize = Gen.g_filesz; 1605 extotal = dblock.dbuf.extotal; 1606 } else { 1607 extno = 0; /* tell others file not split */ 1608 extsize = 0; 1609 extotal = 0; 1610 } 1611 1612 #ifdef EUC 1613 if (chksum != checksum(&dblock)) { 1614 if (chksum != checksum_signed(&dblock)) { 1615 (void) fprintf(stderr, gettext( 1616 "tar: directory checksum error\n")); 1617 if (iflag) 1618 goto top; 1619 done(2); 1620 } else { 1621 if (! warn_chksum_sign) { 1622 warn_chksum_sign = 1; 1623 (void) fprintf(stderr, gettext( 1624 "tar: warning: tar file made with signed checksum\n")); 1625 } 1626 } 1627 } 1628 #else 1629 if (chksum != checksum(&dblock)) { 1630 (void) fprintf(stderr, gettext( 1631 "tar: directory checksum error\n")); 1632 if (iflag) 1633 goto top; 1634 done(2); 1635 } 1636 #endif /* EUC */ 1637 if (tfile != NULL && Xhdrflag == 0) { 1638 /* 1639 * If an extended header is present, then time is available 1640 * in nanoseconds in the extended header data, so set it. 1641 * Otherwise, give an invalid value so that checkupdate will 1642 * not test beyond seconds. 1643 */ 1644 if ((xhdr_flgs & _X_MTIME)) 1645 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 1646 else 1647 sp->st_mtim.tv_nsec = -1; 1648 1649 if (xhdr_flgs & _X_PATH) 1650 (void) fprintf(tfile, "%s %10ld.%9.9ld\n", 1651 Xtarhdr.x_path, sp->st_mtim.tv_sec, 1652 sp->st_mtim.tv_nsec); 1653 else 1654 (void) fprintf(tfile, "%.*s %10ld.%9.9ld\n", 1655 NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec, 1656 sp->st_mtim.tv_nsec); 1657 } 1658 1659 #if defined(O_XATTR) 1660 Hiddendir = 0; 1661 if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) { 1662 if (xattrbadhead) { 1663 free(xattrhead); 1664 xattrp = NULL; 1665 xattr_linkp = NULL; 1666 xattrhead = NULL; 1667 } else { 1668 char *aname = basename(xattrapath); 1669 size_t xindex = aname - xattrapath; 1670 1671 if (xattrapath[xindex] == '.' && 1672 xattrapath[xindex + 1] == '\0' && 1673 xattrp->h_typeflag == '5') { 1674 Hiddendir = 1; 1675 sp->st_mode = 1676 (S_IFDIR | (sp->st_mode & POSIXMODES)); 1677 } 1678 dblock.dbuf.typeflag = xattrp->h_typeflag; 1679 } 1680 } 1681 #endif 1682 } 1683 1684 1685 /* 1686 * passtape - skip over a file on the tape 1687 * 1688 * passtape skips over the next data file on the tape. 1689 * The tape directory entry must be in dblock.dbuf. This 1690 * routine just eats the number of blocks computed from the 1691 * directory size entry; the tape must be (logically) positioned 1692 * right after thee directory info. 1693 */ 1694 1695 static void 1696 passtape(void) 1697 { 1698 blkcnt_t blocks; 1699 char buf[TBLOCK]; 1700 1701 /* 1702 * Types link(1), sym-link(2), char special(3), blk special(4), 1703 * directory(5), and FIFO(6) do not have data blocks associated 1704 * with them so just skip reading the data block. 1705 */ 1706 if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' || 1707 dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' || 1708 dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6') 1709 return; 1710 blocks = TBLOCKS(stbuf.st_size); 1711 1712 /* if operating on disk, seek instead of reading */ 1713 if (NotTape) 1714 seekdisk(blocks); 1715 else 1716 while (blocks-- > 0) 1717 readtape(buf); 1718 } 1719 1720 #if defined(O_XATTR) 1721 static int 1722 is_sysattr(char *name) 1723 { 1724 return ((strcmp(name, VIEW_READONLY) == 0) || 1725 (strcmp(name, VIEW_READWRITE) == 0)); 1726 } 1727 #endif 1728 1729 #if defined(O_XATTR) 1730 /* 1731 * Verify the attribute, attrname, is an attribute we want to restore. 1732 * Never restore read-only system attribute files. Only restore read-write 1733 * system attributes files when -/ was specified, and only traverse into 1734 * the 2nd level attribute directory containing only system attributes if 1735 * -@ was specified. This keeps us from archiving 1736 * <attribute name>/<read-write system attribute file> 1737 * when -/ was specified without -@. 1738 * 1739 * attrname - attribute file name 1740 * attrparent - attribute's parent name within the base file's attribute 1741 * directory hierarchy 1742 */ 1743 static attr_status_t 1744 verify_attr(char *attrname, char *attrparent, int arc_rwsysattr, 1745 int *rw_sysattr) 1746 { 1747 #if defined(_PC_SATTR_ENABLED) 1748 int attr_supported; 1749 1750 /* Never restore read-only system attribute files */ 1751 if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) { 1752 *rw_sysattr = 0; 1753 return (ATTR_SKIP); 1754 } else { 1755 *rw_sysattr = (attr_supported == _RW_SATTR); 1756 } 1757 #else 1758 /* 1759 * Only need to check if this attribute is an extended system 1760 * attribute. 1761 */ 1762 if (*rw_sysattr = is_sysattr(attrname)) { 1763 return (ATTR_SKIP); 1764 } else { 1765 return (ATTR_OK); 1766 } 1767 #endif /* _PC_SATTR_ENABLED */ 1768 1769 /* 1770 * If the extended system attribute file is specified with the 1771 * arc_rwsysattr flag, as being transient (default extended 1772 * attributes), then don't archive it. 1773 */ 1774 if (*rw_sysattr && !arc_rwsysattr) { 1775 return (ATTR_SKIP); 1776 } 1777 1778 /* 1779 * Only restore read-write system attribute files 1780 * when -/ was specified. Only restore extended 1781 * attributes when -@ was specified. 1782 */ 1783 if (atflag) { 1784 if (!saflag) { 1785 /* 1786 * Only archive/restore the hidden directory "." if 1787 * we're processing the top level hidden attribute 1788 * directory. We don't want to process the 1789 * hidden attribute directory of the attribute 1790 * directory that contains only extended system 1791 * attributes. 1792 */ 1793 if (*rw_sysattr || (Hiddendir && 1794 (attrparent != NULL))) { 1795 return (ATTR_SKIP); 1796 } 1797 } 1798 } else if (saflag) { 1799 /* 1800 * Only archive/restore read-write extended system attribute 1801 * files of the base file. 1802 */ 1803 if (!*rw_sysattr || (attrparent != NULL)) { 1804 return (ATTR_SKIP); 1805 } 1806 } else { 1807 return (ATTR_SKIP); 1808 } 1809 1810 return (ATTR_OK); 1811 } 1812 #endif 1813 1814 static void 1815 free_children(file_list_t *children) 1816 { 1817 file_list_t *child = children; 1818 file_list_t *cptr; 1819 1820 while (child != NULL) { 1821 cptr = child->next; 1822 if (child->name != NULL) { 1823 free(child->name); 1824 } 1825 child = cptr; 1826 } 1827 } 1828 1829 static int 1830 putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, 1831 int filetype, int lev, int symlink_lev) 1832 { 1833 int infile = -1; /* deliberately invalid */ 1834 blkcnt_t blocks; 1835 char buf[PATH_MAX + 2]; /* Add trailing slash and null */ 1836 char *bigbuf; 1837 int maxread; 1838 int hint; /* amount to write to get "in sync" */ 1839 char filetmp[PATH_MAX + 1]; 1840 char *cp; 1841 char *name; 1842 char *attrparent = NULL; 1843 char *longattrname = NULL; 1844 file_list_t *child = NULL; 1845 file_list_t *child_end = NULL; 1846 file_list_t *cptr; 1847 struct dirent *dp; 1848 DIR *dirp; 1849 int i; 1850 int split; 1851 int dirfd = -1; 1852 int rc = PUT_NOTAS_LINK; 1853 int archtype = 0; 1854 int rw_sysattr = 0; 1855 char newparent[PATH_MAX + MAXNAMLEN + 1]; 1856 char *prefix = ""; 1857 char *tmpbuf; 1858 char goodbuf[PRESIZ + 2]; 1859 char junkbuf[MAXNAM+1]; 1860 char *lastslash; 1861 int j; 1862 struct stat sbuf; 1863 int readlink_max; 1864 1865 (void) memset(goodbuf, '\0', sizeof (goodbuf)); 1866 (void) memset(junkbuf, '\0', sizeof (junkbuf)); 1867 1868 xhdr_flgs = 0; 1869 1870 if (filetype == XATTR_FILE) { 1871 attrparent = attrinfo->attr_parent; 1872 longattrname = attrinfo->attr_path; 1873 dirfd = attrinfo->attr_parentfd; 1874 rw_sysattr = attrinfo->attr_rw_sysattr; 1875 } else { 1876 dirfd = open(".", O_RDONLY); 1877 } 1878 1879 if (dirfd == -1) { 1880 (void) fprintf(stderr, gettext( 1881 "tar: unable to open%sdirectory %s%s%s%s\n"), 1882 (filetype == XATTR_FILE) ? gettext(" attribute ") : " ", 1883 (attrparent == NULL) ? "" : gettext("of attribute "), 1884 (attrparent == NULL) ? "" : attrparent, 1885 (attrparent == NULL) ? "" : gettext(" of "), 1886 (filetype == XATTR_FILE) ? longname : parent); 1887 goto out; 1888 } 1889 1890 if (lev > MAXLEV) { 1891 (void) fprintf(stderr, 1892 gettext("tar: directory nesting too deep, %s not dumped\n"), 1893 longname); 1894 goto out; 1895 } 1896 1897 if (getstat(dirfd, longname, shortname, attrparent)) 1898 goto out; 1899 1900 if (hflag) { 1901 /* 1902 * Catch nesting where a file is a symlink to its directory. 1903 */ 1904 j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW); 1905 if (S_ISLNK(sbuf.st_mode)) { 1906 if (symlink_lev++ >= MAXSYMLINKS) { 1907 (void) fprintf(stderr, gettext( 1908 "tar: %s: Number of symbolic links " 1909 "encountered during path name traversal " 1910 "exceeds MAXSYMLINKS\n"), longname); 1911 Errflg = 1; 1912 goto out; 1913 } 1914 } 1915 } 1916 1917 /* 1918 * Check if the input file is the same as the tar file we 1919 * are creating 1920 */ 1921 if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) { 1922 (void) fprintf(stderr, gettext( 1923 "tar: %s%s%s%s%s same as archive file\n"), 1924 rw_sysattr ? gettext("system ") : "", 1925 (longattrname == NULL) ? "" : gettext("attribute "), 1926 (longattrname == NULL) ? "" : longattrname, 1927 (longattrname == NULL) ? "" : gettext(" of "), 1928 longname); 1929 Errflg = 1; 1930 goto out; 1931 } 1932 /* 1933 * Check size limit - we can't archive files that 1934 * exceed TAR_OFFSET_MAX bytes because of header 1935 * limitations. Exclude file types that set 1936 * st_size to zero below because they take no 1937 * archive space to represent contents. 1938 */ 1939 if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) && 1940 !S_ISDIR(stbuf.st_mode) && 1941 !S_ISCHR(stbuf.st_mode) && 1942 !S_ISBLK(stbuf.st_mode) && 1943 (Eflag == 0)) { 1944 (void) fprintf(stderr, gettext( 1945 "tar: %s%s%s%s%s too large to archive. " 1946 "Use E function modifier.\n"), 1947 rw_sysattr ? gettext("system ") : "", 1948 (longattrname == NULL) ? "" : gettext("attribute "), 1949 (longattrname == NULL) ? "" : longattrname, 1950 (longattrname == NULL) ? "" : gettext(" of "), 1951 longname); 1952 if (errflag) 1953 exitflag = 1; 1954 Errflg = 1; 1955 goto out; 1956 } 1957 1958 if (tfile != NULL && checkupdate(longname) == 0) { 1959 goto out; 1960 } 1961 if (checkw('r', longname) == 0) { 1962 goto out; 1963 } 1964 1965 if (Fflag && 1966 checkf(longname, (stbuf.st_mode & S_IFMT) == S_IFDIR, Fflag) == 0) 1967 goto out; 1968 1969 if (Xflag) { 1970 if (is_in_table(exclude_tbl, longname)) { 1971 if (vflag) { 1972 (void) fprintf(vfile, gettext( 1973 "a %s excluded\n"), longname); 1974 } 1975 goto out; 1976 } 1977 } 1978 1979 /* 1980 * If the length of the fullname is greater than MAXNAM, 1981 * print out a message and return (unless extended headers are used, 1982 * in which case fullname is limited to PATH_MAX). 1983 */ 1984 1985 if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) || 1986 (split > PATH_MAX)) { 1987 (void) fprintf(stderr, gettext( 1988 "tar: %s: file name too long\n"), longname); 1989 if (errflag) 1990 exitflag = 1; 1991 Errflg = 1; 1992 goto out; 1993 } 1994 1995 /* 1996 * We split the fullname into prefix and name components if any one 1997 * of three conditions holds: 1998 * -- the length of the fullname exceeds NAMSIZ, 1999 * -- the length of the fullname equals NAMSIZ, and the shortname 2000 * is less than NAMSIZ, (splitting in this case preserves 2001 * compatibility with 5.6 and 5.5.1 tar), or 2002 * -- the length of the fullname equals NAMSIZ, the file is a 2003 * directory and we are not in POSIX-conformant mode (where 2004 * trailing slashes are removed from directories). 2005 */ 2006 if ((split > NAMSIZ) || 2007 (split == NAMSIZ && strlen(shortname) < NAMSIZ) || 2008 (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) { 2009 /* 2010 * Since path is limited to PRESIZ characters, look for the 2011 * last slash within PRESIZ + 1 characters only. 2012 */ 2013 (void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1)); 2014 tmpbuf = goodbuf; 2015 lastslash = strrchr(tmpbuf, '/'); 2016 if (lastslash == NULL) { 2017 i = split; /* Length of name */ 2018 j = 0; /* Length of prefix */ 2019 goodbuf[0] = '\0'; 2020 } else { 2021 *lastslash = '\0'; /* Terminate the prefix */ 2022 j = strlen(tmpbuf); 2023 i = split - j - 1; 2024 } 2025 /* 2026 * If the filename is greater than NAMSIZ we can't 2027 * archive the file unless we are using extended headers. 2028 */ 2029 if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) && 2030 !Pflag)) { 2031 /* Determine which (filename or path) is too long. */ 2032 lastslash = strrchr(longname, '/'); 2033 if (lastslash != NULL) 2034 i = strlen(lastslash + 1); 2035 if (Eflag > 0) { 2036 xhdr_flgs |= _X_PATH; 2037 Xtarhdr.x_path = longname; 2038 if (i <= NAMSIZ) 2039 (void) strcpy(junkbuf, lastslash + 1); 2040 else 2041 (void) sprintf(junkbuf, "%llu", 2042 xhdr_count + 1); 2043 if (split - i - 1 > PRESIZ) 2044 (void) strcpy(goodbuf, xhdr_dirname); 2045 } else { 2046 if ((i > NAMSIZ) || (i == NAMSIZ && 2047 S_ISDIR(stbuf.st_mode) && !Pflag)) 2048 (void) fprintf(stderr, gettext( 2049 "tar: %s: filename is greater than " 2050 "%d\n"), lastslash == NULL ? 2051 longname : lastslash + 1, NAMSIZ); 2052 else 2053 (void) fprintf(stderr, gettext( 2054 "tar: %s: prefix is greater than %d" 2055 "\n"), longname, PRESIZ); 2056 if (errflag) 2057 exitflag = 1; 2058 Errflg = 1; 2059 goto out; 2060 } 2061 } else 2062 (void) strncpy(&junkbuf[0], longname + j + 1, 2063 strlen(longname + j + 1)); 2064 name = junkbuf; 2065 prefix = goodbuf; 2066 } else { 2067 name = longname; 2068 } 2069 if (Aflag) { 2070 if ((prefix != NULL) && (*prefix != '\0')) 2071 while (*prefix == '/') 2072 ++prefix; 2073 else 2074 while (*name == '/') 2075 ++name; 2076 } 2077 2078 switch (stbuf.st_mode & S_IFMT) { 2079 case S_IFDIR: 2080 stbuf.st_size = (off_t)0; 2081 blocks = TBLOCKS(stbuf.st_size); 2082 2083 if (filetype != XATTR_FILE && Hiddendir == 0) { 2084 i = 0; 2085 cp = buf; 2086 while ((*cp++ = longname[i++])) 2087 ; 2088 *--cp = '/'; 2089 *++cp = 0; 2090 } 2091 if (!oflag) { 2092 tomodes(&stbuf); 2093 if (build_dblock(name, tchar, '5', filetype, 2094 &stbuf, stbuf.st_dev, prefix) != 0) { 2095 goto out; 2096 } 2097 if (!Pflag) { 2098 /* 2099 * Old archives require a slash at the end 2100 * of a directory name. 2101 * 2102 * XXX 2103 * If directory name is too long, will 2104 * slash overfill field? 2105 */ 2106 if (strlen(name) > (unsigned)NAMSIZ-1) { 2107 (void) fprintf(stderr, gettext( 2108 "tar: %s: filename is greater " 2109 "than %d\n"), name, NAMSIZ); 2110 if (errflag) 2111 exitflag = 1; 2112 Errflg = 1; 2113 goto out; 2114 } else { 2115 if (strlen(name) == (NAMSIZ - 1)) { 2116 (void) memcpy(dblock.dbuf.name, 2117 name, NAMSIZ); 2118 dblock.dbuf.name[NAMSIZ-1] 2119 = '/'; 2120 } else 2121 (void) sprintf(dblock.dbuf.name, 2122 "%s/", name); 2123 2124 /* 2125 * need to recalculate checksum 2126 * because the name changed. 2127 */ 2128 (void) sprintf(dblock.dbuf.chksum, 2129 "%07o", checksum(&dblock)); 2130 } 2131 } 2132 2133 if (put_extra_attributes(longname, shortname, 2134 longattrname, prefix, filetype, '5') != 0) 2135 goto out; 2136 2137 #if defined(O_XATTR) 2138 /* 2139 * Reset header typeflag when archiving directory, since 2140 * build_dblock changed it on us. 2141 */ 2142 if (filetype == XATTR_FILE) { 2143 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2144 } else { 2145 dblock.dbuf.typeflag = '5'; 2146 } 2147 #else 2148 dblock.dbuf.typeflag = '5'; 2149 #endif 2150 2151 (void) sprintf(dblock.dbuf.chksum, "%07o", 2152 checksum(&dblock)); 2153 2154 (void) writetbuf((char *)&dblock, 1); 2155 } 2156 if (vflag) { 2157 #ifdef DEBUG 2158 if (NotTape) 2159 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2160 0); 2161 #endif 2162 if (filetype == XATTR_FILE && Hiddendir) { 2163 (void) fprintf(vfile, 2164 gettext("a %s attribute %s "), 2165 longname, longattrname); 2166 2167 } else { 2168 (void) fprintf(vfile, "a %s/ ", longname); 2169 } 2170 if (NotTape) 2171 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2172 K(blocks)); 2173 else 2174 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t 2175 " tape blocks\n"), blocks); 2176 } 2177 2178 /* 2179 * If hidden dir then break now since xattrs_put() will do 2180 * the iterating of the directory. 2181 * 2182 * At the moment, there can only be system attributes on 2183 * attributes. There can be no attributes on attributes or 2184 * directories within the attributes hidden directory hierarchy. 2185 */ 2186 if (filetype == XATTR_FILE) 2187 break; 2188 2189 if (*shortname != '/') 2190 (void) sprintf(newparent, "%s/%s", parent, shortname); 2191 else 2192 (void) sprintf(newparent, "%s", shortname); 2193 2194 if (chdir(shortname) < 0) { 2195 vperror(0, "%s", newparent); 2196 goto out; 2197 } 2198 2199 if ((dirp = opendir(".")) == NULL) { 2200 vperror(0, gettext( 2201 "can't open directory %s"), longname); 2202 if (chdir(parent) < 0) 2203 vperror(0, gettext("cannot change back?: %s"), 2204 parent); 2205 goto out; 2206 } 2207 2208 /* 2209 * Create a list of files (children) in this directory to avoid 2210 * having to perform telldir()/seekdir(). 2211 */ 2212 while ((dp = readdir(dirp)) != NULL && !term) { 2213 if ((strcmp(".", dp->d_name) == 0) || 2214 (strcmp("..", dp->d_name) == 0)) 2215 continue; 2216 if (((cptr = (file_list_t *)calloc(sizeof (char), 2217 sizeof (file_list_t))) == NULL) || 2218 ((cptr->name = strdup(dp->d_name)) == NULL)) { 2219 vperror(1, gettext( 2220 "Insufficient memory for directory " 2221 "list entry %s/%s\n"), 2222 newparent, dp->d_name); 2223 } 2224 2225 /* Add the file to the list */ 2226 if (child == NULL) { 2227 child = cptr; 2228 } else { 2229 child_end->next = cptr; 2230 } 2231 child_end = cptr; 2232 } 2233 (void) closedir(dirp); 2234 2235 /* 2236 * Archive each of the files in the current directory. 2237 * If a file is a directory, putfile() is called 2238 * recursively to archive the file hierarchy of the 2239 * directory before archiving the next file in the 2240 * current directory. 2241 */ 2242 while ((child != NULL) && !term) { 2243 (void) strcpy(cp, child->name); 2244 archtype = putfile(buf, cp, newparent, NULL, 2245 NORMAL_FILE, lev + 1, symlink_lev); 2246 2247 if (!exitflag) { 2248 if ((atflag || saflag) && 2249 (archtype == PUT_NOTAS_LINK)) { 2250 xattrs_put(buf, cp, newparent, NULL); 2251 } 2252 } 2253 if (exitflag) 2254 break; 2255 2256 /* Free each child as we are done processing it. */ 2257 cptr = child; 2258 child = child->next; 2259 free(cptr->name); 2260 free(cptr); 2261 } 2262 if ((child != NULL) && !term) { 2263 free_children(child); 2264 } 2265 2266 if (chdir(parent) < 0) { 2267 vperror(0, gettext("cannot change back?: %s"), parent); 2268 } 2269 2270 break; 2271 2272 case S_IFLNK: 2273 readlink_max = NAMSIZ; 2274 if (stbuf.st_size > NAMSIZ) { 2275 if (Eflag > 0) { 2276 xhdr_flgs |= _X_LINKPATH; 2277 readlink_max = PATH_MAX; 2278 } else { 2279 (void) fprintf(stderr, gettext( 2280 "tar: %s: symbolic link too long\n"), 2281 longname); 2282 if (errflag) 2283 exitflag = 1; 2284 Errflg = 1; 2285 goto out; 2286 } 2287 } 2288 /* 2289 * Sym-links need header size of zero since you 2290 * don't store any data for this type. 2291 */ 2292 stbuf.st_size = (off_t)0; 2293 tomodes(&stbuf); 2294 i = readlink(shortname, filetmp, readlink_max); 2295 if (i < 0) { 2296 vperror(0, gettext( 2297 "can't read symbolic link %s"), longname); 2298 goto out; 2299 } else { 2300 filetmp[i] = 0; 2301 } 2302 if (vflag) 2303 (void) fprintf(vfile, gettext( 2304 "a %s symbolic link to %s\n"), 2305 longname, filetmp); 2306 if (xhdr_flgs & _X_LINKPATH) { 2307 Xtarhdr.x_linkpath = filetmp; 2308 if (build_dblock(name, tchar, '2', filetype, &stbuf, 2309 stbuf.st_dev, prefix) != 0) 2310 goto out; 2311 } else 2312 if (build_dblock(name, filetmp, '2', filetype, &stbuf, 2313 stbuf.st_dev, prefix) != 0) 2314 goto out; 2315 (void) writetbuf((char *)&dblock, 1); 2316 /* 2317 * No acls for symlinks: mode is always 777 2318 * dont call write ancillary 2319 */ 2320 rc = PUT_AS_LINK; 2321 break; 2322 case S_IFREG: 2323 if ((infile = openat(dirfd, shortname, 0)) < 0) { 2324 vperror(0, gettext("unable to open %s%s%s%s"), longname, 2325 rw_sysattr ? gettext(" system") : "", 2326 (filetype == XATTR_FILE) ? 2327 gettext(" attribute ") : "", 2328 (filetype == XATTR_FILE) ? (longattrname == NULL) ? 2329 shortname : longattrname : ""); 2330 goto out; 2331 } 2332 2333 blocks = TBLOCKS(stbuf.st_size); 2334 2335 if (put_link(name, longname, shortname, longattrname, 2336 prefix, filetype, '1') == 0) { 2337 (void) close(infile); 2338 rc = PUT_AS_LINK; 2339 goto out; 2340 } 2341 2342 tomodes(&stbuf); 2343 2344 /* correctly handle end of volume */ 2345 while (mulvol && tapepos + blocks + 1 > blocklim) { 2346 /* file won't fit */ 2347 if (eflag) { 2348 if (blocks <= blocklim) { 2349 newvol(); 2350 break; 2351 } 2352 (void) fprintf(stderr, gettext( 2353 "tar: Single file cannot fit on volume\n")); 2354 done(3); 2355 } 2356 /* split if floppy has some room and file is large */ 2357 if (((blocklim - tapepos) >= EXTMIN) && 2358 ((blocks + 1) >= blocklim/10)) { 2359 splitfile(longname, infile, 2360 name, prefix, filetype); 2361 (void) close(dirfd); 2362 (void) close(infile); 2363 goto out; 2364 } 2365 newvol(); /* not worth it--just get new volume */ 2366 } 2367 #ifdef DEBUG 2368 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2369 blocks); 2370 #endif 2371 if (build_dblock(name, tchar, '0', filetype, 2372 &stbuf, stbuf.st_dev, prefix) != 0) { 2373 goto out; 2374 } 2375 if (vflag) { 2376 #ifdef DEBUG 2377 if (NotTape) 2378 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2379 0); 2380 #endif 2381 (void) fprintf(vfile, "a %s%s%s%s ", longname, 2382 rw_sysattr ? gettext(" system") : "", 2383 (filetype == XATTR_FILE) ? gettext( 2384 " attribute ") : "", 2385 (filetype == XATTR_FILE) ? 2386 longattrname : ""); 2387 if (NotTape) 2388 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2389 K(blocks)); 2390 else 2391 (void) fprintf(vfile, 2392 gettext("%" FMT_blkcnt_t " tape blocks\n"), 2393 blocks); 2394 } 2395 2396 if (put_extra_attributes(longname, shortname, longattrname, 2397 prefix, filetype, '0') != 0) 2398 goto out; 2399 2400 /* 2401 * No need to reset typeflag for extended attribute here, since 2402 * put_extra_attributes already set it and we haven't called 2403 * build_dblock(). 2404 */ 2405 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2406 hint = writetbuf((char *)&dblock, 1); 2407 maxread = max(min(stbuf.st_blksize, stbuf.st_size), 2408 (nblock * TBLOCK)); 2409 if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2410 maxread = TBLOCK; 2411 bigbuf = buf; 2412 } 2413 2414 while (((i = (int) 2415 read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2416 blocks) { 2417 blkcnt_t nblks; 2418 2419 nblks = ((i-1)/TBLOCK)+1; 2420 if (nblks > blocks) 2421 nblks = blocks; 2422 hint = writetbuf(bigbuf, nblks); 2423 blocks -= nblks; 2424 } 2425 (void) close(infile); 2426 if (bigbuf != buf) 2427 free(bigbuf); 2428 if (i < 0) 2429 vperror(0, gettext("Read error on %s"), longname); 2430 else if (blocks != 0 || i != 0) { 2431 (void) fprintf(stderr, gettext( 2432 "tar: %s: file changed size\n"), longname); 2433 if (errflag) { 2434 exitflag = 1; 2435 Errflg = 1; 2436 } else if (!Dflag) { 2437 Errflg = 1; 2438 } 2439 } 2440 putempty(blocks); 2441 break; 2442 case S_IFIFO: 2443 blocks = TBLOCKS(stbuf.st_size); 2444 stbuf.st_size = (off_t)0; 2445 2446 if (put_link(name, longname, shortname, longattrname, 2447 prefix, filetype, '6') == 0) { 2448 rc = PUT_AS_LINK; 2449 goto out; 2450 } 2451 tomodes(&stbuf); 2452 2453 while (mulvol && tapepos + blocks + 1 > blocklim) { 2454 if (eflag) { 2455 if (blocks <= blocklim) { 2456 newvol(); 2457 break; 2458 } 2459 (void) fprintf(stderr, gettext( 2460 "tar: Single file cannot fit on volume\n")); 2461 done(3); 2462 } 2463 2464 if (((blocklim - tapepos) >= EXTMIN) && 2465 ((blocks + 1) >= blocklim/10)) { 2466 splitfile(longname, infile, name, 2467 prefix, filetype); 2468 (void) close(dirfd); 2469 (void) close(infile); 2470 goto out; 2471 } 2472 newvol(); 2473 } 2474 #ifdef DEBUG 2475 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2476 blocks); 2477 #endif 2478 if (vflag) { 2479 #ifdef DEBUG 2480 if (NotTape) 2481 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2482 0); 2483 #endif 2484 if (NotTape) 2485 (void) fprintf(vfile, gettext("a %s %" 2486 FMT_blkcnt_t "K\n "), longname, K(blocks)); 2487 else 2488 (void) fprintf(vfile, gettext( 2489 "a %s %" FMT_blkcnt_t " tape blocks\n"), 2490 longname, blocks); 2491 } 2492 if (build_dblock(name, tchar, '6', filetype, 2493 &stbuf, stbuf.st_dev, prefix) != 0) 2494 goto out; 2495 2496 if (put_extra_attributes(longname, shortname, longattrname, 2497 prefix, filetype, '6') != 0) 2498 goto out; 2499 2500 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2501 dblock.dbuf.typeflag = '6'; 2502 2503 (void) writetbuf((char *)&dblock, 1); 2504 break; 2505 case S_IFCHR: 2506 stbuf.st_size = (off_t)0; 2507 blocks = TBLOCKS(stbuf.st_size); 2508 if (put_link(name, longname, shortname, longattrname, 2509 prefix, filetype, '3') == 0) { 2510 rc = PUT_AS_LINK; 2511 goto out; 2512 } 2513 tomodes(&stbuf); 2514 2515 while (mulvol && tapepos + blocks + 1 > blocklim) { 2516 if (eflag) { 2517 if (blocks <= blocklim) { 2518 newvol(); 2519 break; 2520 } 2521 (void) fprintf(stderr, gettext( 2522 "tar: Single file cannot fit on volume\n")); 2523 done(3); 2524 } 2525 2526 if (((blocklim - tapepos) >= EXTMIN) && 2527 ((blocks + 1) >= blocklim/10)) { 2528 splitfile(longname, infile, name, 2529 prefix, filetype); 2530 (void) close(dirfd); 2531 goto out; 2532 } 2533 newvol(); 2534 } 2535 #ifdef DEBUG 2536 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2537 blocks); 2538 #endif 2539 if (vflag) { 2540 #ifdef DEBUG 2541 if (NotTape) 2542 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2543 0); 2544 #endif 2545 if (NotTape) 2546 (void) fprintf(vfile, gettext("a %s %" 2547 FMT_blkcnt_t "K\n"), longname, K(blocks)); 2548 else 2549 (void) fprintf(vfile, gettext("a %s %" 2550 FMT_blkcnt_t " tape blocks\n"), longname, 2551 blocks); 2552 } 2553 if (build_dblock(name, tchar, '3', 2554 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2555 goto out; 2556 2557 if (put_extra_attributes(longname, shortname, longattrname, 2558 prefix, filetype, '3') != 0) 2559 goto out; 2560 2561 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2562 dblock.dbuf.typeflag = '3'; 2563 2564 (void) writetbuf((char *)&dblock, 1); 2565 break; 2566 case S_IFBLK: 2567 stbuf.st_size = (off_t)0; 2568 blocks = TBLOCKS(stbuf.st_size); 2569 if (put_link(name, longname, shortname, longattrname, 2570 prefix, filetype, '4') == 0) { 2571 rc = PUT_AS_LINK; 2572 goto out; 2573 } 2574 tomodes(&stbuf); 2575 2576 while (mulvol && tapepos + blocks + 1 > blocklim) { 2577 if (eflag) { 2578 if (blocks <= blocklim) { 2579 newvol(); 2580 break; 2581 } 2582 (void) fprintf(stderr, gettext( 2583 "tar: Single file cannot fit on volume\n")); 2584 done(3); 2585 } 2586 2587 if (((blocklim - tapepos) >= EXTMIN) && 2588 ((blocks + 1) >= blocklim/10)) { 2589 splitfile(longname, infile, 2590 name, prefix, filetype); 2591 (void) close(dirfd); 2592 goto out; 2593 } 2594 newvol(); 2595 } 2596 #ifdef DEBUG 2597 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2598 blocks); 2599 #endif 2600 if (vflag) { 2601 #ifdef DEBUG 2602 if (NotTape) 2603 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2604 0); 2605 #endif 2606 (void) fprintf(vfile, "a %s ", longname); 2607 if (NotTape) 2608 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2609 K(blocks)); 2610 else 2611 (void) fprintf(vfile, gettext("%" 2612 FMT_blkcnt_t " tape blocks\n"), blocks); 2613 } 2614 if (build_dblock(name, tchar, '4', 2615 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2616 goto out; 2617 2618 if (put_extra_attributes(longname, shortname, longattrname, 2619 prefix, filetype, '4') != 0) 2620 goto out; 2621 2622 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2623 dblock.dbuf.typeflag = '4'; 2624 2625 (void) writetbuf((char *)&dblock, 1); 2626 break; 2627 default: 2628 (void) fprintf(stderr, gettext( 2629 "tar: %s is not a file. Not dumped\n"), longname); 2630 if (errflag) 2631 exitflag = 1; 2632 Errflg = 1; 2633 goto out; 2634 } 2635 2636 out: 2637 if ((dirfd != -1) && (filetype != XATTR_FILE)) { 2638 (void) close(dirfd); 2639 } 2640 return (rc); 2641 } 2642 2643 2644 /* 2645 * splitfile dump a large file across volumes 2646 * 2647 * splitfile(longname, fd); 2648 * char *longname; full name of file 2649 * int ifd; input file descriptor 2650 * 2651 * NOTE: only called by putfile() to dump a large file. 2652 */ 2653 2654 static void 2655 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2656 { 2657 blkcnt_t blocks; 2658 off_t bytes, s; 2659 char buf[TBLOCK]; 2660 int i, extents; 2661 2662 blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2663 2664 /* 2665 * # extents = 2666 * size of file after using up rest of this floppy 2667 * blocks - (blocklim - tapepos) + 1 (for header) 2668 * plus roundup value before divide by blocklim-1 2669 * + (blocklim - 1) - 1 2670 * all divided by blocklim-1 (one block for each header). 2671 * this gives 2672 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2673 * which reduces to the expression used. 2674 * one is added to account for this first extent. 2675 * 2676 * When one is dealing with extremely large archives, one may want 2677 * to allow for a large number of extents. This code should be 2678 * revisited to determine if extents should be changed to something 2679 * larger than an int. 2680 */ 2681 extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2682 2683 if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2684 (void) fprintf(stderr, gettext( 2685 "tar: %s needs unusual number of volumes to split\n" 2686 "tar: %s not dumped\n"), longname, longname); 2687 return; 2688 } 2689 if (build_dblock(name, tchar, '0', filetype, 2690 &stbuf, stbuf.st_dev, prefix) != 0) 2691 return; 2692 2693 dblock.dbuf.extotal = extents; 2694 bytes = stbuf.st_size; 2695 2696 /* 2697 * The value contained in dblock.dbuf.efsize was formerly used when the 2698 * v flag was specified in conjunction with the t flag. Although it is 2699 * no longer used, older versions of tar will expect the former 2700 * behaviour, so we must continue to write it to the archive. 2701 * 2702 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2703 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2704 * store 0. 2705 */ 2706 if (bytes <= TAR_EFSIZE_MAX) 2707 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2708 else 2709 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2710 2711 (void) fprintf(stderr, gettext( 2712 "tar: large file %s needs %d extents.\n" 2713 "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2714 longname, extents, K(tapepos)); 2715 2716 s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2717 for (i = 1; i <= extents; i++) { 2718 if (i > 1) { 2719 newvol(); 2720 if (i == extents) 2721 s = bytes; /* last ext. gets true bytes */ 2722 else 2723 s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2724 } 2725 bytes -= s; 2726 blocks = TBLOCKS(s); 2727 2728 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2729 dblock.dbuf.extno = i; 2730 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2731 (void) writetbuf((char *)&dblock, 1); 2732 2733 if (vflag) 2734 (void) fprintf(vfile, 2735 gettext("+++ a %s %" FMT_blkcnt_t 2736 "K [extent #%d of %d]\n"), 2737 longname, K(blocks), i, extents); 2738 while (blocks && read(ifd, buf, TBLOCK) > 0) { 2739 blocks--; 2740 (void) writetbuf(buf, 1); 2741 } 2742 if (blocks != 0) { 2743 (void) fprintf(stderr, gettext( 2744 "tar: %s: file changed size\n"), longname); 2745 (void) fprintf(stderr, gettext( 2746 "tar: aborting split file %s\n"), longname); 2747 (void) close(ifd); 2748 return; 2749 } 2750 } 2751 (void) close(ifd); 2752 if (vflag) 2753 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2754 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2755 extents); 2756 } 2757 2758 /* 2759 * convtoreg - determines whether the file should be converted to a 2760 * regular file when extracted 2761 * 2762 * Returns 1 when file size > 0 and typeflag is not recognized 2763 * Otherwise returns 0 2764 */ 2765 static int 2766 convtoreg(off_t size) 2767 { 2768 if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2769 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2770 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2771 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2772 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2773 (dblock.dbuf.typeflag != 'L') && 2774 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2775 (dblock.dbuf.typeflag != 'X')) { 2776 return (1); 2777 } 2778 return (0); 2779 } 2780 2781 #if defined(O_XATTR) 2782 static int 2783 save_cwd(void) 2784 { 2785 return (open(".", O_RDONLY)); 2786 } 2787 #endif 2788 2789 #if defined(O_XATTR) 2790 static void 2791 rest_cwd(int *cwd) 2792 { 2793 if (*cwd != -1) { 2794 if (fchdir(*cwd) < 0) { 2795 vperror(0, gettext( 2796 "Cannot fchdir to attribute directory")); 2797 exit(1); 2798 } 2799 (void) close(*cwd); 2800 *cwd = -1; 2801 } 2802 } 2803 #endif 2804 2805 /* 2806 * Verify the underlying file system supports the attribute type. 2807 * Only archive extended attribute files when '-@' was specified. 2808 * Only archive system extended attribute files if '-/' was specified. 2809 */ 2810 #if defined(O_XATTR) 2811 static attr_status_t 2812 verify_attr_support(char *filename, int attrflg, arc_action_t actflag, 2813 int *ext_attrflg) 2814 { 2815 /* 2816 * Verify extended attributes are supported/exist. We only 2817 * need to check if we are processing a base file, not an 2818 * extended attribute. 2819 */ 2820 if (attrflg) { 2821 *ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ? 2822 _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1); 2823 } 2824 2825 if (atflag) { 2826 if (!*ext_attrflg) { 2827 #if defined(_PC_SATTR_ENABLED) 2828 if (saflag) { 2829 /* Verify system attributes are supported */ 2830 if (sysattr_support(filename, 2831 (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS : 2832 _PC_SATTR_ENABLED) != 1) { 2833 return (ATTR_SATTR_ERR); 2834 } 2835 } else 2836 return (ATTR_XATTR_ERR); 2837 #else 2838 return (ATTR_XATTR_ERR); 2839 #endif /* _PC_SATTR_ENABLED */ 2840 } 2841 2842 #if defined(_PC_SATTR_ENABLED) 2843 } else if (saflag) { 2844 /* Verify system attributes are supported */ 2845 if (sysattr_support(filename, (actflag == ARC_CREATE) ? 2846 _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) { 2847 return (ATTR_SATTR_ERR); 2848 } 2849 #endif /* _PC_SATTR_ENABLED */ 2850 } else { 2851 return (ATTR_SKIP); 2852 } 2853 2854 return (ATTR_OK); 2855 } 2856 #endif 2857 2858 #if defined(O_XATTR) 2859 /* 2860 * Recursively open attribute directories until the attribute directory 2861 * containing the specified attribute, attrname, is opened. 2862 * 2863 * Currently, only 2 directory levels of attributes are supported, (i.e., 2864 * extended system attributes on extended attributes). The following are 2865 * the possible input combinations: 2866 * 1. Open the attribute directory of the base file (don't change 2867 * into it). 2868 * attrinfo->parent = NULL 2869 * attrname = '.' 2870 * 2. Open the attribute directory of the base file and change into it. 2871 * attrinfo->parent = NULL 2872 * attrname = <attr> | <sys_attr> 2873 * 3. Open the attribute directory of the base file, change into it, 2874 * then recursively call open_attr_dir() to open the attribute's 2875 * parent directory (don't change into it). 2876 * attrinfo->parent = <attr> 2877 * attrname = '.' 2878 * 4. Open the attribute directory of the base file, change into it, 2879 * then recursively call open_attr_dir() to open the attribute's 2880 * parent directory and change into it. 2881 * attrinfo->parent = <attr> 2882 * attrname = <attr> | <sys_attr> 2883 * 2884 * An attribute directory will be opened only if the underlying file system 2885 * supports the attribute type, and if the command line specifications (atflag 2886 * and saflag) enable the processing of the attribute type. 2887 * 2888 * On succesful return, attrinfo->parentfd will be the file descriptor of the 2889 * opened attribute directory. In addition, if the attribute is a read-write 2890 * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise 2891 * it will be set to 0. 2892 * 2893 * Possible return values: 2894 * ATTR_OK Successfully opened and, if needed, changed into the 2895 * attribute directory containing attrname. 2896 * ATTR_SKIP The command line specifications don't enable the 2897 * processing of the attribute type. 2898 * ATTR_CHDIR_ERR An error occurred while trying to change into an 2899 * attribute directory. 2900 * ATTR_OPEN_ERR An error occurred while trying to open an 2901 * attribute directory. 2902 * ATTR_XATTR_ERR The underlying file system doesn't support extended 2903 * attributes. 2904 * ATTR_SATTR_ERR The underlying file system doesn't support extended 2905 * system attributes. 2906 */ 2907 static int 2908 open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo) 2909 { 2910 attr_status_t rc; 2911 int firsttime = (attrinfo->attr_parentfd == -1); 2912 int saveerrno; 2913 int ext_attr; 2914 2915 /* 2916 * open_attr_dir() was recursively called (input combination number 4), 2917 * close the previously opened file descriptor as we've already changed 2918 * into it. 2919 */ 2920 if (!firsttime) { 2921 (void) close(attrinfo->attr_parentfd); 2922 attrinfo->attr_parentfd = -1; 2923 } 2924 2925 /* 2926 * Verify that the underlying file system supports the restoration 2927 * of the attribute. 2928 */ 2929 if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE, 2930 &ext_attr)) != ATTR_OK) { 2931 return (rc); 2932 } 2933 2934 /* Open the base file's attribute directory */ 2935 if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) { 2936 /* 2937 * Save the errno from the attropen so it can be reported 2938 * if the retry of the attropen fails. 2939 */ 2940 saveerrno = errno; 2941 if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp, 2942 NULL, ".", O_RDONLY, 0)) == -1) { 2943 /* 2944 * Reset typeflag back to real value so passtape 2945 * will skip ahead correctly. 2946 */ 2947 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2948 (void) close(attrinfo->attr_parentfd); 2949 attrinfo->attr_parentfd = -1; 2950 errno = saveerrno; 2951 return (ATTR_OPEN_ERR); 2952 } 2953 } 2954 2955 /* 2956 * Change into the parent attribute's directory unless we are 2957 * processing the hidden attribute directory of the base file itself. 2958 */ 2959 if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) { 2960 if (fchdir(attrinfo->attr_parentfd) != 0) { 2961 saveerrno = errno; 2962 (void) close(attrinfo->attr_parentfd); 2963 attrinfo->attr_parentfd = -1; 2964 errno = saveerrno; 2965 return (ATTR_CHDIR_ERR); 2966 } 2967 } 2968 2969 /* Determine if the attribute should be processed */ 2970 if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1, 2971 &attrinfo->attr_rw_sysattr)) != ATTR_OK) { 2972 saveerrno = errno; 2973 (void) close(attrinfo->attr_parentfd); 2974 attrinfo->attr_parentfd = -1; 2975 errno = saveerrno; 2976 return (rc); 2977 } 2978 2979 /* 2980 * If the attribute is an extended attribute, or extended system 2981 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then 2982 * recursively call open_attr_dir() to open the attribute directory 2983 * of the parent attribute. 2984 */ 2985 if (firsttime && (attrinfo->attr_parent != NULL)) { 2986 return (open_attr_dir(attrname, attrinfo->attr_parent, 2987 attrinfo->attr_parentfd, attrinfo)); 2988 } 2989 2990 return (ATTR_OK); 2991 } 2992 #endif 2993 2994 static void 2995 #ifdef _iBCS2 2996 doxtract(char *argv[], int tbl_cnt) 2997 #else 2998 doxtract(char *argv[]) 2999 #endif 3000 { 3001 struct stat xtractbuf; /* stat on file after extracting */ 3002 blkcnt_t blocks; 3003 off_t bytes; 3004 int ofile; 3005 int newfile; /* Does the file already exist */ 3006 int xcnt = 0; /* count # files extracted */ 3007 int fcnt = 0; /* count # files in argv list */ 3008 int dir; 3009 int dirfd = -1; 3010 int cwd = -1; 3011 int rw_sysattr; 3012 int saveerrno; 3013 uid_t Uid; 3014 char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 3015 char dirname[PATH_MAX+1]; 3016 char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 3017 int once = 1; 3018 int error; 3019 int symflag; 3020 int want; 3021 attr_data_t *attrinfo = NULL; /* attribute info */ 3022 acl_t *aclp = NULL; /* acl info */ 3023 char dot[] = "."; /* dirp for using realpath */ 3024 timestruc_t time_zero; /* used for call to doDirTimes */ 3025 int dircreate; 3026 int convflag; 3027 time_zero.tv_sec = 0; 3028 time_zero.tv_nsec = 0; 3029 3030 /* reset Trusted Extensions variables */ 3031 rpath_flag = 0; 3032 lk_rpath_flag = 0; 3033 dir_flag = 0; 3034 mld_flag = 0; 3035 bslundef(&bs_label); 3036 bsllow(&admin_low); 3037 bslhigh(&admin_high); 3038 orig_namep = 0; 3039 3040 dumping = 0; /* for newvol(), et al: we are not writing */ 3041 3042 /* 3043 * Count the number of files that are to be extracted 3044 */ 3045 Uid = getuid(); 3046 3047 #ifdef _iBCS2 3048 initarg(argv, Filefile); 3049 while (nextarg() != NULL) 3050 ++fcnt; 3051 fcnt += tbl_cnt; 3052 #endif /* _iBCS2 */ 3053 3054 for (;;) { 3055 convflag = 0; 3056 symflag = 0; 3057 dir = 0; 3058 Hiddendir = 0; 3059 rw_sysattr = 0; 3060 ofile = -1; 3061 3062 if (dirfd != -1) { 3063 (void) close(dirfd); 3064 dirfd = -1; 3065 } 3066 if (ofile != -1) { 3067 if (close(ofile) != 0) 3068 vperror(2, gettext("close error")); 3069 } 3070 3071 #if defined(O_XATTR) 3072 if (cwd != -1) { 3073 rest_cwd(&cwd); 3074 } 3075 #endif 3076 3077 /* namep is set by wantit to point to the full name */ 3078 if ((want = wantit(argv, &namep, &dirp, &comp, 3079 &attrinfo)) == 0) { 3080 #if defined(O_XATTR) 3081 if (xattrp != NULL) { 3082 free(xattrhead); 3083 xattrp = NULL; 3084 xattr_linkp = NULL; 3085 xattrhead = NULL; 3086 } 3087 #endif 3088 continue; 3089 } 3090 if (want == -1) 3091 break; 3092 3093 /* Trusted Extensions */ 3094 /* 3095 * During tar extract (x): 3096 * If the pathname of the restored file has been 3097 * reconstructed from the ancillary file, 3098 * use it to process the normal file. 3099 */ 3100 if (mld_flag) { /* Skip over .MLD. directory */ 3101 mld_flag = 0; 3102 passtape(); 3103 continue; 3104 } 3105 orig_namep = namep; /* save original */ 3106 if (rpath_flag) { 3107 namep = real_path; /* use zone path */ 3108 comp = real_path; /* use zone path */ 3109 dirp = dot; /* work from the top */ 3110 rpath_flag = 0; /* reset */ 3111 } 3112 3113 if (dirfd != -1) 3114 (void) close(dirfd); 3115 3116 (void) strcpy(&dirname[0], namep); 3117 dircreate = checkdir(&dirname[0]); 3118 3119 #if defined(O_XATTR) 3120 if (xattrp != NULL) { 3121 int rc; 3122 3123 if (((cwd = save_cwd()) == -1) || 3124 ((rc = open_attr_dir(comp, dirp, cwd, 3125 attrinfo)) != ATTR_OK)) { 3126 if (cwd == -1) { 3127 vperror(0, gettext( 3128 "unable to save current working " 3129 "directory while processing " 3130 "attribute %s of %s"), 3131 dirp, attrinfo->attr_path); 3132 } else if (rc != ATTR_SKIP) { 3133 (void) fprintf(vfile, 3134 gettext("tar: cannot open " 3135 "%sattribute %s of file %s: %s\n"), 3136 attrinfo->attr_rw_sysattr ? gettext( 3137 "system ") : "", 3138 comp, dirp, strerror(errno)); 3139 } 3140 free(xattrhead); 3141 xattrp = NULL; 3142 xattr_linkp = NULL; 3143 xattrhead = NULL; 3144 3145 passtape(); 3146 continue; 3147 } else { 3148 dirfd = attrinfo->attr_parentfd; 3149 rw_sysattr = attrinfo->attr_rw_sysattr; 3150 } 3151 } else { 3152 dirfd = open(dirp, O_RDONLY); 3153 } 3154 #else 3155 dirfd = open(dirp, O_RDONLY); 3156 #endif 3157 if (dirfd == -1) { 3158 (void) fprintf(vfile, gettext( 3159 "tar: cannot open %s: %s\n"), 3160 dirp, strerror(errno)); 3161 passtape(); 3162 continue; 3163 } 3164 3165 if (xhdr_flgs & _X_LINKPATH) 3166 (void) strcpy(templink, Xtarhdr.x_linkpath); 3167 else { 3168 #if defined(O_XATTR) 3169 if (xattrp && dblock.dbuf.typeflag == '1') { 3170 (void) sprintf(templink, "%.*s", NAMSIZ, 3171 xattrp->h_names); 3172 } else { 3173 (void) sprintf(templink, "%.*s", NAMSIZ, 3174 dblock.dbuf.linkname); 3175 } 3176 #else 3177 (void) sprintf(templink, "%.*s", NAMSIZ, 3178 dblock.dbuf.linkname); 3179 #endif 3180 } 3181 3182 if (Fflag) { 3183 if (checkf(namep, is_directory(namep), Fflag) == 0) { 3184 passtape(); 3185 continue; 3186 } 3187 } 3188 3189 if (checkw('x', namep) == 0) { 3190 passtape(); 3191 continue; 3192 } 3193 if (once) { 3194 if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 3195 if (geteuid() == (uid_t)0) { 3196 checkflag = 1; 3197 pflag = 1; 3198 } else { 3199 /* get file creation mask */ 3200 Oumask = umask(0); 3201 (void) umask(Oumask); 3202 } 3203 once = 0; 3204 } else { 3205 if (geteuid() == (uid_t)0) { 3206 pflag = 1; 3207 checkflag = 2; 3208 } 3209 if (!pflag) { 3210 /* get file creation mask */ 3211 Oumask = umask(0); 3212 (void) umask(Oumask); 3213 } 3214 once = 0; 3215 } 3216 } 3217 3218 #if defined(O_XATTR) 3219 /* 3220 * Handle extraction of hidden attr dir. 3221 * Dir is automatically created, we only 3222 * need to update mode and perm's. 3223 */ 3224 if ((xattrp != NULL) && Hiddendir == 1) { 3225 bytes = stbuf.st_size; 3226 blocks = TBLOCKS(bytes); 3227 if (vflag) { 3228 (void) fprintf(vfile, 3229 "x %s%s%s, %" FMT_off_t " %s, ", namep, 3230 gettext(" attribute "), 3231 xattrapath, bytes, 3232 gettext("bytes")); 3233 if (NotTape) 3234 (void) fprintf(vfile, 3235 "%" FMT_blkcnt_t "K\n", K(blocks)); 3236 else 3237 (void) fprintf(vfile, gettext("%" 3238 FMT_blkcnt_t " tape blocks\n"), 3239 blocks); 3240 } 3241 3242 /* 3243 * Set the permissions and mode of the attribute 3244 * unless the attribute is a system attribute (can't 3245 * successfully do this) or the hidden attribute 3246 * directory (".") of an attribute (when the attribute 3247 * is restored, the hidden attribute directory of an 3248 * attribute is transient). Note: when the permissions 3249 * and mode are set for the hidden attribute directory 3250 * of a file on a system supporting extended system 3251 * attributes, even though it returns successfully, it 3252 * will not have any affect since the attribute 3253 * directory is transient. 3254 */ 3255 if (attrinfo->attr_parent == NULL) { 3256 if (fchownat(dirfd, ".", stbuf.st_uid, 3257 stbuf.st_gid, 0) != 0) { 3258 vperror(0, gettext( 3259 "%s%s%s: failed to set ownership " 3260 "of attribute directory"), namep, 3261 gettext(" attribute "), xattrapath); 3262 } 3263 3264 if (fchmod(dirfd, stbuf.st_mode) != 0) { 3265 vperror(0, gettext( 3266 "%s%s%s: failed to set permissions " 3267 "of attribute directory"), namep, 3268 gettext(" attribute "), xattrapath); 3269 } 3270 } 3271 goto filedone; 3272 } 3273 #endif 3274 3275 if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 3276 dir = 1; 3277 if (vflag) { 3278 (void) fprintf(vfile, "x %s, 0 %s, ", 3279 &dirname[0], gettext("bytes")); 3280 if (NotTape) 3281 (void) fprintf(vfile, "0K\n"); 3282 else 3283 (void) fprintf(vfile, gettext("%" 3284 FMT_blkcnt_t " tape blocks\n"), 3285 (blkcnt_t)0); 3286 } 3287 goto filedone; 3288 } 3289 3290 if (dblock.dbuf.typeflag == '6') { /* FIFO */ 3291 if (rmdir(namep) < 0) { 3292 if (errno == ENOTDIR) 3293 (void) unlink(namep); 3294 } 3295 linkp = templink; 3296 if (*linkp != NULL) { 3297 if (Aflag && *linkp == '/') 3298 linkp++; 3299 if (link(linkp, namep) < 0) { 3300 (void) fprintf(stderr, gettext( 3301 "tar: %s: cannot link\n"), namep); 3302 continue; 3303 } 3304 if (vflag) 3305 (void) fprintf(vfile, gettext( 3306 "x %s linked to %s\n"), namep, 3307 linkp); 3308 xcnt++; /* increment # files extracted */ 3309 continue; 3310 } 3311 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO), 3312 (int)Gen.g_devmajor) < 0) { 3313 vperror(0, gettext("%s: mknod failed"), namep); 3314 continue; 3315 } 3316 bytes = stbuf.st_size; 3317 blocks = TBLOCKS(bytes); 3318 if (vflag) { 3319 (void) fprintf(vfile, "x %s, %" FMT_off_t 3320 " %s, ", namep, bytes, gettext("bytes")); 3321 if (NotTape) 3322 (void) fprintf(vfile, "%" FMT_blkcnt_t 3323 "K\n", K(blocks)); 3324 else 3325 (void) fprintf(vfile, gettext("%" 3326 FMT_blkcnt_t " tape blocks\n"), 3327 blocks); 3328 } 3329 goto filedone; 3330 } 3331 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */ 3332 if (rmdir(namep) < 0) { 3333 if (errno == ENOTDIR) 3334 (void) unlink(namep); 3335 } 3336 linkp = templink; 3337 if (*linkp != NULL) { 3338 if (Aflag && *linkp == '/') 3339 linkp++; 3340 if (link(linkp, namep) < 0) { 3341 (void) fprintf(stderr, gettext( 3342 "tar: %s: cannot link\n"), namep); 3343 continue; 3344 } 3345 if (vflag) 3346 (void) fprintf(vfile, gettext( 3347 "x %s linked to %s\n"), namep, 3348 linkp); 3349 xcnt++; /* increment # files extracted */ 3350 continue; 3351 } 3352 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR), 3353 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3354 vperror(0, gettext( 3355 "%s: mknod failed"), namep); 3356 continue; 3357 } 3358 bytes = stbuf.st_size; 3359 blocks = TBLOCKS(bytes); 3360 if (vflag) { 3361 (void) fprintf(vfile, "x %s, %" FMT_off_t 3362 " %s, ", namep, bytes, gettext("bytes")); 3363 if (NotTape) 3364 (void) fprintf(vfile, "%" FMT_blkcnt_t 3365 "K\n", K(blocks)); 3366 else 3367 (void) fprintf(vfile, gettext("%" 3368 FMT_blkcnt_t " tape blocks\n"), 3369 blocks); 3370 } 3371 goto filedone; 3372 } else if (dblock.dbuf.typeflag == '3' && Uid) { 3373 (void) fprintf(stderr, gettext( 3374 "Can't create special %s\n"), namep); 3375 continue; 3376 } 3377 3378 /* BLOCK SPECIAL */ 3379 3380 if (dblock.dbuf.typeflag == '4' && !Uid) { 3381 if (rmdir(namep) < 0) { 3382 if (errno == ENOTDIR) 3383 (void) unlink(namep); 3384 } 3385 linkp = templink; 3386 if (*linkp != NULL) { 3387 if (Aflag && *linkp == '/') 3388 linkp++; 3389 if (link(linkp, namep) < 0) { 3390 (void) fprintf(stderr, gettext( 3391 "tar: %s: cannot link\n"), namep); 3392 continue; 3393 } 3394 if (vflag) 3395 (void) fprintf(vfile, gettext( 3396 "x %s linked to %s\n"), namep, 3397 linkp); 3398 xcnt++; /* increment # files extracted */ 3399 continue; 3400 } 3401 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK), 3402 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3403 vperror(0, gettext("%s: mknod failed"), namep); 3404 continue; 3405 } 3406 bytes = stbuf.st_size; 3407 blocks = TBLOCKS(bytes); 3408 if (vflag) { 3409 (void) fprintf(vfile, gettext("x %s, %" 3410 FMT_off_t " bytes, "), namep, bytes); 3411 if (NotTape) 3412 (void) fprintf(vfile, "%" FMT_blkcnt_t 3413 "K\n", K(blocks)); 3414 else 3415 (void) fprintf(vfile, gettext("%" 3416 FMT_blkcnt_t " tape blocks\n"), 3417 blocks); 3418 } 3419 goto filedone; 3420 } else if (dblock.dbuf.typeflag == '4' && Uid) { 3421 (void) fprintf(stderr, 3422 gettext("Can't create special %s\n"), namep); 3423 continue; 3424 } 3425 if (dblock.dbuf.typeflag == '2') { /* symlink */ 3426 if ((Tflag) && (lk_rpath_flag == 1)) 3427 linkp = lk_real_path; 3428 else 3429 linkp = templink; 3430 if (Aflag && *linkp == '/') 3431 linkp++; 3432 if (rmdir(namep) < 0) { 3433 if (errno == ENOTDIR) 3434 (void) unlink(namep); 3435 } 3436 if (symlink(linkp, namep) < 0) { 3437 vperror(0, gettext("%s: symbolic link failed"), 3438 namep); 3439 continue; 3440 } 3441 if (vflag) 3442 (void) fprintf(vfile, gettext( 3443 "x %s symbolic link to %s\n"), 3444 namep, linkp); 3445 3446 symflag = AT_SYMLINK_NOFOLLOW; 3447 goto filedone; 3448 } 3449 if (dblock.dbuf.typeflag == '1') { 3450 linkp = templink; 3451 if (Aflag && *linkp == '/') 3452 linkp++; 3453 if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) { 3454 if (errno == ENOTDIR) 3455 (void) unlinkat(dirfd, comp, 0); 3456 } 3457 #if defined(O_XATTR) 3458 if (xattrp && xattr_linkp) { 3459 if (fchdir(dirfd) < 0) { 3460 vperror(0, gettext( 3461 "Cannot fchdir to attribute " 3462 "directory %s"), 3463 (attrinfo->attr_parent == NULL) ? 3464 dirp : attrinfo->attr_parent); 3465 exit(1); 3466 } 3467 3468 error = link(xattr_linkaname, xattrapath); 3469 } else { 3470 error = link(linkp, namep); 3471 } 3472 #else 3473 error = link(linkp, namep); 3474 #endif 3475 3476 if (error < 0) { 3477 (void) fprintf(stderr, gettext( 3478 "tar: %s%s%s: cannot link\n"), 3479 namep, (xattr_linkp != NULL) ? 3480 gettext(" attribute ") : "", 3481 (xattr_linkp != NULL) ? 3482 xattrapath : ""); 3483 continue; 3484 } 3485 if (vflag) 3486 (void) fprintf(vfile, gettext( 3487 "x %s%s%s linked to %s%s%s\n"), namep, 3488 (xattr_linkp != NULL) ? 3489 gettext(" attribute ") : "", 3490 (xattr_linkp != NULL) ? 3491 xattr_linkaname : "", 3492 linkp, 3493 (xattr_linkp != NULL) ? 3494 gettext(" attribute ") : "", 3495 (xattr_linkp != NULL) ? xattrapath : ""); 3496 xcnt++; /* increment # files extracted */ 3497 #if defined(O_XATTR) 3498 if (xattrp != NULL) { 3499 free(xattrhead); 3500 xattrp = NULL; 3501 xattr_linkp = NULL; 3502 xattrhead = NULL; 3503 } 3504 #endif 3505 continue; 3506 } 3507 3508 /* REGULAR FILES */ 3509 3510 if (convtoreg(stbuf.st_size)) { 3511 convflag = 1; 3512 if (errflag) { 3513 (void) fprintf(stderr, gettext( 3514 "tar: %s: typeflag '%c' not recognized\n"), 3515 namep, dblock.dbuf.typeflag); 3516 done(1); 3517 } else { 3518 (void) fprintf(stderr, gettext( 3519 "tar: %s: typeflag '%c' not recognized, " 3520 "converting to regular file\n"), namep, 3521 dblock.dbuf.typeflag); 3522 Errflg = 1; 3523 } 3524 } 3525 if (dblock.dbuf.typeflag == '0' || 3526 dblock.dbuf.typeflag == NULL || convflag) { 3527 delete_target(dirfd, comp, namep); 3528 linkp = templink; 3529 if (*linkp != NULL) { 3530 if (Aflag && *linkp == '/') 3531 linkp++; 3532 if (link(linkp, comp) < 0) { 3533 (void) fprintf(stderr, gettext( 3534 "tar: %s: cannot link\n"), namep); 3535 continue; 3536 } 3537 if (vflag) 3538 (void) fprintf(vfile, gettext( 3539 "x %s linked to %s\n"), comp, 3540 linkp); 3541 xcnt++; /* increment # files extracted */ 3542 #if defined(O_XATTR) 3543 if (xattrp != NULL) { 3544 free(xattrhead); 3545 xattrp = NULL; 3546 xattr_linkp = NULL; 3547 xattrhead = NULL; 3548 } 3549 #endif 3550 continue; 3551 } 3552 newfile = ((fstatat(dirfd, comp, 3553 &xtractbuf, 0) == -1) ? TRUE : FALSE); 3554 ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC, 3555 stbuf.st_mode & MODEMASK); 3556 saveerrno = errno; 3557 3558 #if defined(O_XATTR) 3559 if (xattrp != NULL) { 3560 if (ofile < 0) { 3561 ofile = retry_open_attr(dirfd, cwd, 3562 dirp, attrinfo->attr_parent, comp, 3563 O_RDWR|O_CREAT|O_TRUNC, 3564 stbuf.st_mode & MODEMASK); 3565 } 3566 } 3567 #endif 3568 if (ofile < 0) { 3569 errno = saveerrno; 3570 (void) fprintf(stderr, gettext( 3571 "tar: %s%s%s%s - cannot create\n"), 3572 (xattrp == NULL) ? "" : (rw_sysattr ? 3573 gettext("system attribute ") : 3574 gettext("attribute ")), 3575 (xattrp == NULL) ? "" : xattrapath, 3576 (xattrp == NULL) ? "" : gettext(" of "), 3577 (xattrp == NULL) ? comp : namep); 3578 if (errflag) 3579 done(1); 3580 else 3581 Errflg = 1; 3582 #if defined(O_XATTR) 3583 if (xattrp != NULL) { 3584 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 3585 free(xattrhead); 3586 xattrp = NULL; 3587 xattr_linkp = NULL; 3588 xattrhead = NULL; 3589 } 3590 #endif 3591 passtape(); 3592 continue; 3593 } 3594 3595 if (Tflag && (check_ext_attr(namep) == 0)) { 3596 if (errflag) 3597 done(1); 3598 else 3599 Errflg = 1; 3600 passtape(); 3601 continue; 3602 } 3603 3604 if (extno != 0) { /* file is in pieces */ 3605 if (extotal < 1 || extotal > MAXEXT) 3606 (void) fprintf(stderr, gettext( 3607 "tar: ignoring bad extent info for " 3608 "%s%s%s%s\n"), 3609 (xattrp == NULL) ? "" : (rw_sysattr ? 3610 gettext("system attribute ") : 3611 gettext("attribute ")), 3612 (xattrp == NULL) ? "" : xattrapath, 3613 (xattrp == NULL) ? "" : gettext(" of "), 3614 (xattrp == NULL) ? comp : namep); 3615 else { 3616 /* extract it */ 3617 (void) xsfile(rw_sysattr, ofile); 3618 } 3619 } 3620 extno = 0; /* let everyone know file is not split */ 3621 bytes = stbuf.st_size; 3622 blocks = TBLOCKS(bytes); 3623 if (vflag) { 3624 (void) fprintf(vfile, 3625 "x %s%s%s, %" FMT_off_t " %s, ", 3626 (xattrp == NULL) ? "" : dirp, 3627 (xattrp == NULL) ? "" : (rw_sysattr ? 3628 gettext(" system attribute ") : 3629 gettext(" attribute ")), 3630 (xattrp == NULL) ? namep : xattrapath, bytes, 3631 gettext("bytes")); 3632 if (NotTape) 3633 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 3634 K(blocks)); 3635 else 3636 (void) fprintf(vfile, gettext("%" 3637 FMT_blkcnt_t " tape blocks\n"), blocks); 3638 } 3639 3640 if (xblocks(rw_sysattr, bytes, ofile) != 0) { 3641 #if defined(O_XATTR) 3642 if (xattrp != NULL) { 3643 free(xattrhead); 3644 xattrp = NULL; 3645 xattr_linkp = NULL; 3646 xattrhead = NULL; 3647 } 3648 #endif 3649 continue; 3650 } 3651 filedone: 3652 if (mflag == 0 && !symflag) { 3653 if (dir) 3654 doDirTimes(namep, stbuf.st_mtim); 3655 3656 else 3657 #if defined(O_XATTR) 3658 if (xattrp != NULL) { 3659 /* 3660 * Set the time on the attribute unless 3661 * the attribute is a system attribute 3662 * (can't successfully do this) or the 3663 * hidden attribute directory, "." (the 3664 * time on the hidden attribute 3665 * directory will be updated when 3666 * attributes are restored, otherwise 3667 * it's transient). 3668 */ 3669 if (!rw_sysattr && (Hiddendir == 0)) { 3670 setPathTimes(dirfd, comp, 3671 stbuf.st_mtim); 3672 } 3673 } else 3674 setPathTimes(dirfd, comp, 3675 stbuf.st_mtim); 3676 #else 3677 setPathTimes(dirfd, comp, stbuf.st_mtim); 3678 #endif 3679 } 3680 3681 /* moved this code from above */ 3682 if (pflag && !symflag && Hiddendir == 0) { 3683 if (xattrp != NULL) 3684 (void) fchmod(ofile, stbuf.st_mode & MODEMASK); 3685 else 3686 (void) chmod(namep, stbuf.st_mode & MODEMASK); 3687 } 3688 3689 3690 /* 3691 * Because ancillary file preceeds the normal file, 3692 * acl info may have been retrieved (in aclp). 3693 * All file types are directed here (go filedone). 3694 * Always restore ACLs if there are ACLs. 3695 */ 3696 if (aclp != NULL) { 3697 int ret; 3698 3699 #if defined(O_XATTR) 3700 if (xattrp != NULL) { 3701 if (Hiddendir) 3702 ret = facl_set(dirfd, aclp); 3703 else 3704 ret = facl_set(ofile, aclp); 3705 } else { 3706 ret = acl_set(namep, aclp); 3707 } 3708 #else 3709 ret = acl_set(namep, aclp); 3710 #endif 3711 if (ret < 0) { 3712 if (pflag) { 3713 (void) fprintf(stderr, gettext( 3714 "%s%s%s%s: failed to set acl " 3715 "entries\n"), namep, 3716 (xattrp == NULL) ? "" : 3717 (rw_sysattr ? gettext( 3718 " system attribute ") : 3719 gettext(" attribute ")), 3720 (xattrp == NULL) ? "" : 3721 xattrapath); 3722 } 3723 /* else: silent and continue */ 3724 } 3725 acl_free(aclp); 3726 aclp = NULL; 3727 } 3728 3729 if (!oflag) 3730 resugname(dirfd, comp, symflag); /* set file ownership */ 3731 3732 if (pflag && newfile == TRUE && !dir && 3733 (dblock.dbuf.typeflag == '0' || 3734 dblock.dbuf.typeflag == NULL || 3735 convflag || dblock.dbuf.typeflag == '1')) { 3736 if (fstat(ofile, &xtractbuf) == -1) 3737 (void) fprintf(stderr, gettext( 3738 "tar: cannot stat extracted file " 3739 "%s%s%s%s\n"), 3740 (xattrp == NULL) ? "" : (rw_sysattr ? 3741 gettext("system attribute ") : 3742 gettext("attribute ")), 3743 (xattrp == NULL) ? "" : xattrapath, 3744 (xattrp == NULL) ? "" : 3745 gettext(" of "), namep); 3746 3747 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT)) 3748 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) { 3749 (void) fprintf(stderr, gettext( 3750 "tar: warning - file permissions have " 3751 "changed for %s%s%s%s (are 0%o, should be " 3752 "0%o)\n"), 3753 (xattrp == NULL) ? "" : (rw_sysattr ? 3754 gettext("system attribute ") : 3755 gettext("attribute ")), 3756 (xattrp == NULL) ? "" : xattrapath, 3757 (xattrp == NULL) ? "" : 3758 gettext(" of "), namep, 3759 xtractbuf.st_mode, stbuf.st_mode); 3760 3761 } 3762 } 3763 #if defined(O_XATTR) 3764 if (xattrp != NULL) { 3765 free(xattrhead); 3766 xattrp = NULL; 3767 xattr_linkp = NULL; 3768 xattrhead = NULL; 3769 } 3770 #endif 3771 3772 if (ofile != -1) { 3773 (void) close(dirfd); 3774 dirfd = -1; 3775 if (close(ofile) != 0) 3776 vperror(2, gettext("close error")); 3777 ofile = -1; 3778 } 3779 xcnt++; /* increment # files extracted */ 3780 } 3781 3782 /* 3783 * Process ancillary file. 3784 * 3785 */ 3786 3787 if (dblock.dbuf.typeflag == 'A') { /* acl info */ 3788 char buf[TBLOCK]; 3789 char *secp; 3790 char *tp; 3791 int attrsize; 3792 int cnt; 3793 3794 /* reset Trusted Extensions flags */ 3795 dir_flag = 0; 3796 mld_flag = 0; 3797 lk_rpath_flag = 0; 3798 rpath_flag = 0; 3799 3800 if (pflag) { 3801 bytes = stbuf.st_size; 3802 if ((secp = malloc((int)bytes)) == NULL) { 3803 (void) fprintf(stderr, gettext( 3804 "Insufficient memory for acl\n")); 3805 passtape(); 3806 continue; 3807 } 3808 tp = secp; 3809 blocks = TBLOCKS(bytes); 3810 3811 /* 3812 * Display a line for each ancillary file. 3813 */ 3814 if (vflag && Tflag) 3815 (void) fprintf(vfile, "x %s(A), %" 3816 FMT_blkcnt_t " %s, %" 3817 FMT_blkcnt_t " %s\n", 3818 namep, bytes, gettext("bytes"), 3819 blocks, gettext("tape blocks")); 3820 3821 while (blocks-- > 0) { 3822 readtape(buf); 3823 if (bytes <= TBLOCK) { 3824 (void) memcpy(tp, buf, 3825 (size_t)bytes); 3826 break; 3827 } else { 3828 (void) memcpy(tp, buf, 3829 TBLOCK); 3830 tp += TBLOCK; 3831 } 3832 bytes -= TBLOCK; 3833 } 3834 bytes = stbuf.st_size; 3835 /* got all attributes in secp */ 3836 tp = secp; 3837 do { 3838 attr = (struct sec_attr *)tp; 3839 switch (attr->attr_type) { 3840 case UFSD_ACL: 3841 case ACE_ACL: 3842 (void) sscanf(attr->attr_len, 3843 "%7o", 3844 (uint_t *) 3845 &cnt); 3846 /* header is 8 */ 3847 attrsize = 8 + (int)strlen( 3848 &attr->attr_info[0]) + 1; 3849 error = 3850 acl_fromtext( 3851 &attr->attr_info[0], &aclp); 3852 3853 if (error != 0) { 3854 (void) fprintf(stderr, 3855 gettext( 3856 "aclfromtext " 3857 "failed: %s\n"), 3858 acl_strerror( 3859 error)); 3860 bytes -= attrsize; 3861 break; 3862 } 3863 if (acl_cnt(aclp) != cnt) { 3864 (void) fprintf(stderr, 3865 gettext( 3866 "aclcnt error\n")); 3867 bytes -= attrsize; 3868 break; 3869 } 3870 bytes -= attrsize; 3871 break; 3872 3873 /* Trusted Extensions */ 3874 3875 case DIR_TYPE: 3876 case LBL_TYPE: 3877 case APRIV_TYPE: 3878 case FPRIV_TYPE: 3879 case COMP_TYPE: 3880 case LK_COMP_TYPE: 3881 case ATTR_FLAG_TYPE: 3882 attrsize = 3883 sizeof (struct sec_attr) + 3884 strlen(&attr->attr_info[0]); 3885 bytes -= attrsize; 3886 if (Tflag) 3887 extract_attr(&namep, 3888 attr); 3889 break; 3890 3891 default: 3892 (void) fprintf(stderr, gettext( 3893 "unrecognized attr" 3894 " type\n")); 3895 bytes = (off_t)0; 3896 break; 3897 } 3898 3899 /* next attributes */ 3900 tp += attrsize; 3901 } while (bytes != 0); 3902 free(secp); 3903 } else { 3904 passtape(); 3905 } 3906 } /* acl */ 3907 3908 } /* for */ 3909 3910 /* 3911 * Ensure that all the directories still on the directory stack 3912 * get their modification times set correctly by flushing the 3913 * stack. 3914 */ 3915 3916 doDirTimes(NULL, time_zero); 3917 3918 #if defined(O_XATTR) 3919 if (xattrp != NULL) { 3920 free(xattrhead); 3921 xattrp = NULL; 3922 xattr_linkp = NULL; 3923 xattrhead = NULL; 3924 } 3925 #endif 3926 3927 /* 3928 * Check if the number of files extracted is different from the 3929 * number of files listed on the command line 3930 */ 3931 if (fcnt > xcnt) { 3932 (void) fprintf(stderr, 3933 gettext("tar: %d file(s) not extracted\n"), 3934 fcnt-xcnt); 3935 Errflg = 1; 3936 } 3937 } 3938 3939 /* 3940 * xblocks extract file/extent from tape to output file 3941 * 3942 * xblocks(issysattr, bytes, ofile); 3943 * 3944 * issysattr flag set if the files being extracted 3945 * is an extended system attribute file. 3946 * unsigned long long bytes size of extent or file to be extracted 3947 * ofile output file 3948 * 3949 * called by doxtract() and xsfile() 3950 */ 3951 3952 static int 3953 xblocks(int issysattr, off_t bytes, int ofile) 3954 { 3955 char *buf; 3956 char tempname[NAMSIZ+1]; 3957 size_t maxwrite; 3958 size_t bytesread; 3959 size_t piosize; /* preferred I/O size */ 3960 struct stat tsbuf; 3961 3962 /* Don't need to do anything if this is a zero size file */ 3963 if (bytes <= 0) { 3964 return (0); 3965 } 3966 3967 /* 3968 * To figure out the size of the buffer used to accumulate data 3969 * from readtape() and to write to the file, we need to determine 3970 * the largest chunk of data to be written to the file at one time. 3971 * This is determined based on the smallest of the following two 3972 * things: 3973 * 1) The size of the archived file. 3974 * 2) The preferred I/O size of the file. 3975 */ 3976 if (issysattr || (bytes <= TBLOCK)) { 3977 /* 3978 * Writes to system attribute files must be 3979 * performed in one operation. 3980 */ 3981 maxwrite = bytes; 3982 } else { 3983 /* 3984 * fstat() the file to get the preferred I/O size. 3985 * If it fails, then resort back to just writing 3986 * one block at a time. 3987 */ 3988 if (fstat(ofile, &tsbuf) == 0) { 3989 piosize = tsbuf.st_blksize; 3990 } else { 3991 piosize = TBLOCK; 3992 } 3993 maxwrite = min(bytes, piosize); 3994 } 3995 3996 /* 3997 * The buffer used to accumulate the data for the write operation 3998 * needs to be the maximum number of bytes to be written rounded up 3999 * to the nearest TBLOCK since readtape reads one block at a time. 4000 */ 4001 if ((buf = malloc(TBLOCKS(maxwrite) * TBLOCK)) == NULL) { 4002 fatal(gettext("cannot allocate buffer")); 4003 } 4004 4005 while (bytes > 0) { 4006 4007 /* 4008 * readtape() obtains one block (TBLOCK) of data at a time. 4009 * Accumulate as many blocks of data in buf as we can write 4010 * in one operation. 4011 */ 4012 for (bytesread = 0; bytesread < maxwrite; bytesread += TBLOCK) { 4013 readtape(buf + bytesread); 4014 } 4015 4016 if (write(ofile, buf, maxwrite) < 0) { 4017 int saveerrno = errno; 4018 4019 if (xhdr_flgs & _X_PATH) 4020 (void) strlcpy(tempname, Xtarhdr.x_path, 4021 sizeof (tempname)); 4022 else 4023 (void) sprintf(tempname, "%.*s", NAMSIZ, 4024 dblock.dbuf.name); 4025 /* 4026 * If the extended system attribute being extracted 4027 * contains attributes that the user needs privileges 4028 * for, then just display a warning message, skip 4029 * the extraction of this file, and return. 4030 */ 4031 if ((saveerrno == EPERM) && issysattr) { 4032 (void) fprintf(stderr, gettext( 4033 "tar: unable to extract system attribute " 4034 "%s: insufficient privileges\n"), tempname); 4035 Errflg = 1; 4036 (void) free(buf); 4037 return (1); 4038 } else { 4039 (void) fprintf(stderr, gettext( 4040 "tar: %s: HELP - extract write error\n"), 4041 tempname); 4042 done(2); 4043 } 4044 } 4045 bytes -= maxwrite; 4046 4047 /* 4048 * If we've reached this point and there is still data 4049 * to be written, maxwrite had to have been determined 4050 * by the preferred I/O size. If the number of bytes 4051 * left to write is smaller than the preferred I/O size, 4052 * then we're about to do our final write to the file, so 4053 * just set maxwrite to the number of bytes left to write. 4054 */ 4055 if ((bytes > 0) && (bytes < maxwrite)) { 4056 maxwrite = bytes; 4057 } 4058 } 4059 free(buf); 4060 4061 return (0); 4062 } 4063 4064 /* 4065 * xsfile extract split file 4066 * 4067 * xsfile(ofd); ofd = output file descriptor 4068 * 4069 * file extracted and put in ofd via xblocks() 4070 * 4071 * NOTE: only called by doxtract() to extract one large file 4072 */ 4073 4074 static union hblock savedblock; /* to ensure same file across volumes */ 4075 4076 static int 4077 xsfile(int issysattr, int ofd) 4078 { 4079 int i, c; 4080 int sysattrerr = 0; 4081 char name[PATH_MAX+1]; /* holds name for diagnostics */ 4082 int extents, totalext; 4083 off_t bytes, totalbytes; 4084 4085 if (xhdr_flgs & _X_PATH) 4086 (void) strcpy(name, Xtarhdr.x_path); 4087 else 4088 (void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name); 4089 4090 totalbytes = (off_t)0; /* in case we read in half the file */ 4091 totalext = 0; /* these keep count */ 4092 4093 (void) fprintf(stderr, gettext( 4094 "tar: %s split across %d volumes\n"), name, extotal); 4095 4096 /* make sure we do extractions in order */ 4097 if (extno != 1) { /* starting in middle of file? */ 4098 (void) printf(gettext( 4099 "tar: first extent read is not #1\n" 4100 "OK to read file beginning with extent #%d (%s/%s) ? "), 4101 extno, yesstr, nostr); 4102 if (yes() == 0) { 4103 canit: 4104 passtape(); 4105 if (close(ofd) != 0) 4106 vperror(2, gettext("close error")); 4107 if (sysattrerr) { 4108 return (1); 4109 } else { 4110 return (0); 4111 } 4112 } 4113 } 4114 extents = extotal; 4115 i = extno; 4116 /*CONSTCOND*/ 4117 while (1) { 4118 if (xhdr_flgs & _X_SIZE) { 4119 bytes = extsize; 4120 } else { 4121 bytes = stbuf.st_size; 4122 } 4123 4124 if (vflag) 4125 (void) fprintf(vfile, "+++ x %s [%s #%d], %" 4126 FMT_off_t " %s, %ldK\n", 4127 name, gettext("extent"), extno, 4128 bytes, gettext("bytes"), 4129 (long)K(TBLOCKS(bytes))); 4130 if (xblocks(issysattr, bytes, ofd) != 0) { 4131 sysattrerr = 1; 4132 goto canit; 4133 } 4134 4135 totalbytes += bytes; 4136 totalext++; 4137 if (++i > extents) 4138 break; 4139 4140 /* get next volume and verify it's the right one */ 4141 copy(&savedblock, &dblock); 4142 tryagain: 4143 newvol(); 4144 xhdr_flgs = 0; 4145 getdir(); 4146 if (Xhdrflag > 0) 4147 (void) get_xdata(); /* Get x-header & regular hdr */ 4148 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 4149 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 4150 xhdr_flgs |= _X_XHDR; 4151 } 4152 if (endtape()) { /* seemingly empty volume */ 4153 (void) fprintf(stderr, gettext( 4154 "tar: first record is null\n")); 4155 asknicely: 4156 (void) fprintf(stderr, gettext( 4157 "tar: need volume with extent #%d of %s\n"), 4158 i, name); 4159 goto tryagain; 4160 } 4161 if (notsame()) { 4162 (void) fprintf(stderr, gettext( 4163 "tar: first file on that volume is not " 4164 "the same file\n")); 4165 goto asknicely; 4166 } 4167 if (i != extno) { 4168 (void) fprintf(stderr, gettext( 4169 "tar: extent #%d received out of order\ntar: " 4170 "should be #%d\n"), extno, i); 4171 (void) fprintf(stderr, gettext( 4172 "Ignore error, Abort this file, or " 4173 "load New volume (i/a/n) ? ")); 4174 c = response(); 4175 if (c == 'a') 4176 goto canit; 4177 if (c != 'i') /* default to new volume */ 4178 goto asknicely; 4179 i = extno; /* okay, start from there */ 4180 } 4181 } 4182 if (vflag) 4183 (void) fprintf(vfile, gettext( 4184 "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"), 4185 name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes))); 4186 4187 return (0); 4188 } 4189 4190 4191 /* 4192 * notsame() check if extract file extent is invalid 4193 * 4194 * returns true if anything differs between savedblock and dblock 4195 * except extno (extent number), checksum, or size (extent size). 4196 * Determines if this header belongs to the same file as the one we're 4197 * extracting. 4198 * 4199 * NOTE: though rather bulky, it is only called once per file 4200 * extension, and it can withstand changes in the definition 4201 * of the header structure. 4202 * 4203 * WARNING: this routine is local to xsfile() above 4204 */ 4205 4206 static int 4207 notsame(void) 4208 { 4209 return ( 4210 (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) || 4211 (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) || 4212 (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) || 4213 (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) || 4214 (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) || 4215 (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) || 4216 (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) || 4217 (savedblock.dbuf.extotal != dblock.dbuf.extotal) || 4218 (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize))); 4219 } 4220 4221 static void 4222 #ifdef _iBCS2 4223 dotable(char *argv[], int tbl_cnt) 4224 #else 4225 dotable(char *argv[]) 4226 #endif 4227 4228 { 4229 int tcnt; /* count # files tabled */ 4230 int fcnt; /* count # files in argv list */ 4231 char *namep, *dirp, *comp; 4232 int want; 4233 char aclchar = ' '; /* either blank or '+' */ 4234 char templink[PATH_MAX+1]; 4235 attr_data_t *attrinfo = NULL; 4236 4237 dumping = 0; 4238 4239 /* if not on magtape, maximize seek speed */ 4240 if (NotTape && !bflag) { 4241 #if SYS_BLOCK > TBLOCK 4242 nblock = SYS_BLOCK / TBLOCK; 4243 #else 4244 nblock = 1; 4245 #endif 4246 } 4247 /* 4248 * Count the number of files that are to be tabled 4249 */ 4250 fcnt = tcnt = 0; 4251 4252 #ifdef _iBCS2 4253 initarg(argv, Filefile); 4254 while (nextarg() != NULL) 4255 ++fcnt; 4256 fcnt += tbl_cnt; 4257 #endif /* _iBCS2 */ 4258 4259 for (;;) { 4260 4261 /* namep is set by wantit to point to the full name */ 4262 if ((want = wantit(argv, &namep, &dirp, &comp, &attrinfo)) == 0) 4263 continue; 4264 if (want == -1) 4265 break; 4266 if (dblock.dbuf.typeflag != 'A') 4267 ++tcnt; 4268 4269 if (Fflag) { 4270 if (checkf(namep, is_directory(namep), Fflag) == 0) { 4271 passtape(); 4272 continue; 4273 } 4274 } 4275 /* 4276 * ACL support: 4277 * aclchar is introduced to indicate if there are 4278 * acl entries. longt() now takes one extra argument. 4279 */ 4280 if (vflag) { 4281 if (dblock.dbuf.typeflag == 'A') { 4282 aclchar = '+'; 4283 passtape(); 4284 continue; 4285 } 4286 longt(&stbuf, aclchar); 4287 aclchar = ' '; 4288 } 4289 4290 4291 #if defined(O_XATTR) 4292 if (xattrp != NULL) { 4293 int issysattr; 4294 char *bn = basename(attrinfo->attr_path); 4295 4296 /* 4297 * We could use sysattr_type() to test whether or not 4298 * the attribute we are processing is really an 4299 * extended system attribute, which as of this writing 4300 * just does a strcmp(), however, sysattr_type() may 4301 * be changed to issue a pathconf() call instead, which 4302 * would require being changed into the parent attribute 4303 * directory. So instead, just do simple string 4304 * comparisons to see if we are processing an extended 4305 * system attribute. 4306 */ 4307 issysattr = is_sysattr(bn); 4308 4309 (void) printf(gettext("%s %sattribute %s"), 4310 xattrp->h_names, 4311 issysattr ? gettext("system ") : "", 4312 attrinfo->attr_path); 4313 } else { 4314 (void) printf("%s", namep); 4315 } 4316 #else 4317 (void) printf("%s", namep); 4318 #endif 4319 4320 if (extno != 0) { 4321 if (vflag) { 4322 /* keep the '\n' for backwards compatibility */ 4323 (void) fprintf(vfile, gettext( 4324 "\n [extent #%d of %d]"), extno, extotal); 4325 } else { 4326 (void) fprintf(vfile, gettext( 4327 " [extent #%d of %d]"), extno, extotal); 4328 } 4329 } 4330 if (xhdr_flgs & _X_LINKPATH) { 4331 (void) strcpy(templink, Xtarhdr.x_linkpath); 4332 } else { 4333 #if defined(O_XATTR) 4334 if (xattrp != NULL) { 4335 (void) sprintf(templink, 4336 "file %.*s", NAMSIZ, xattrp->h_names); 4337 } else { 4338 (void) sprintf(templink, "%.*s", NAMSIZ, 4339 dblock.dbuf.linkname); 4340 } 4341 #else 4342 (void) sprintf(templink, "%.*s", NAMSIZ, 4343 dblock.dbuf.linkname); 4344 #endif 4345 templink[NAMSIZ] = '\0'; 4346 } 4347 if (dblock.dbuf.typeflag == '1') { 4348 /* 4349 * TRANSLATION_NOTE 4350 * Subject is omitted here. 4351 * Translate this as if 4352 * <subject> linked to %s 4353 */ 4354 #if defined(O_XATTR) 4355 if (xattrp != NULL) { 4356 (void) printf( 4357 gettext(" linked to attribute %s"), 4358 xattr_linkp->h_names + 4359 strlen(xattr_linkp->h_names) + 1); 4360 } else { 4361 (void) printf( 4362 gettext(" linked to %s"), templink); 4363 } 4364 #else 4365 (void) printf( 4366 gettext(" linked to %s"), templink); 4367 4368 #endif 4369 } 4370 if (dblock.dbuf.typeflag == '2') 4371 (void) printf(gettext( 4372 /* 4373 * TRANSLATION_NOTE 4374 * Subject is omitted here. 4375 * Translate this as if 4376 * <subject> symbolic link to %s 4377 */ 4378 " symbolic link to %s"), templink); 4379 (void) printf("\n"); 4380 #if defined(O_XATTR) 4381 if (xattrp != NULL) { 4382 free(xattrhead); 4383 xattrp = NULL; 4384 xattrhead = NULL; 4385 } 4386 #endif 4387 passtape(); 4388 } 4389 /* 4390 * Check if the number of files tabled is different from the 4391 * number of files listed on the command line 4392 */ 4393 if (fcnt > tcnt) { 4394 (void) fprintf(stderr, gettext( 4395 "tar: %d file(s) not found\n"), fcnt-tcnt); 4396 Errflg = 1; 4397 } 4398 } 4399 4400 static void 4401 putempty(blkcnt_t n) 4402 { 4403 char buf[TBLOCK]; 4404 char *cp; 4405 4406 for (cp = buf; cp < &buf[TBLOCK]; ) 4407 *cp++ = '\0'; 4408 while (n-- > 0) 4409 (void) writetbuf(buf, 1); 4410 } 4411 4412 static ushort_t Ftype = S_IFMT; 4413 4414 static void 4415 verbose(struct stat *st, char aclchar) 4416 { 4417 int i, j, temp; 4418 mode_t mode; 4419 char modestr[12]; 4420 4421 for (i = 0; i < 11; i++) 4422 modestr[i] = '-'; 4423 modestr[i] = '\0'; 4424 4425 /* a '+' sign is printed if there is ACL */ 4426 modestr[i-1] = aclchar; 4427 4428 mode = st->st_mode; 4429 for (i = 0; i < 3; i++) { 4430 temp = (mode >> (6 - (i * 3))); 4431 j = (i * 3) + 1; 4432 if (S_IROTH & temp) 4433 modestr[j] = 'r'; 4434 if (S_IWOTH & temp) 4435 modestr[j + 1] = 'w'; 4436 if (S_IXOTH & temp) 4437 modestr[j + 2] = 'x'; 4438 } 4439 temp = st->st_mode & Ftype; 4440 switch (temp) { 4441 case (S_IFIFO): 4442 modestr[0] = 'p'; 4443 break; 4444 case (S_IFCHR): 4445 modestr[0] = 'c'; 4446 break; 4447 case (S_IFDIR): 4448 modestr[0] = 'd'; 4449 break; 4450 case (S_IFBLK): 4451 modestr[0] = 'b'; 4452 break; 4453 case (S_IFREG): /* was initialized to '-' */ 4454 break; 4455 case (S_IFLNK): 4456 modestr[0] = 'l'; 4457 break; 4458 default: 4459 /* This field may be zero in old archives. */ 4460 if (is_posix && dblock.dbuf.typeflag != '1') { 4461 /* 4462 * For POSIX compliant archives, the mode field 4463 * consists of 12 bits, ie: the file type bits 4464 * are not stored in dblock.dbuf.mode. 4465 * For files other than hard links, getdir() sets 4466 * the file type bits in the st_mode field of the 4467 * stat structure based upon dblock.dbuf.typeflag. 4468 */ 4469 (void) fprintf(stderr, gettext( 4470 "tar: impossible file type")); 4471 } 4472 } 4473 4474 if ((S_ISUID & Gen.g_mode) == S_ISUID) 4475 modestr[3] = 's'; 4476 if ((S_ISVTX & Gen.g_mode) == S_ISVTX) 4477 modestr[9] = 't'; 4478 if ((S_ISGID & Gen.g_mode) == S_ISGID && modestr[6] == 'x') 4479 modestr[6] = 's'; 4480 else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x') 4481 modestr[6] = 'l'; 4482 (void) fprintf(vfile, "%s", modestr); 4483 } 4484 4485 static void 4486 longt(struct stat *st, char aclchar) 4487 { 4488 char fileDate[30]; 4489 struct tm *tm; 4490 4491 verbose(st, aclchar); 4492 (void) fprintf(vfile, "%3ld/%-3ld", st->st_uid, st->st_gid); 4493 4494 if (dblock.dbuf.typeflag == '2') { 4495 if (xhdr_flgs & _X_LINKPATH) 4496 st->st_size = (off_t)strlen(Xtarhdr.x_linkpath); 4497 else 4498 st->st_size = (off_t)(memchr(dblock.dbuf.linkname, 4499 '\0', NAMSIZ) ? 4500 (strlen(dblock.dbuf.linkname)) : (NAMSIZ)); 4501 } 4502 (void) fprintf(vfile, " %6" FMT_off_t, st->st_size); 4503 4504 tm = localtime(&(st->st_mtime)); 4505 (void) strftime(fileDate, sizeof (fileDate), 4506 dcgettext((const char *)0, "%b %e %R %Y", LC_TIME), tm); 4507 (void) fprintf(vfile, " %s ", fileDate); 4508 } 4509 4510 4511 /* 4512 * checkdir - Attempt to ensure that the path represented in name 4513 * exists, and return 1 if this is true and name itself is a 4514 * directory. 4515 * Return 0 if this path cannot be created or if name is not 4516 * a directory. 4517 */ 4518 4519 static int 4520 checkdir(char *name) 4521 { 4522 char lastChar; /* the last character in name */ 4523 char *cp; /* scratch pointer into name */ 4524 char *firstSlash = NULL; /* first slash in name */ 4525 char *lastSlash = NULL; /* last slash in name */ 4526 int nameLen; /* length of name */ 4527 int trailingSlash; /* true if name ends in slash */ 4528 int leadingSlash; /* true if name begins with slash */ 4529 int markedDir; /* true if name denotes a directory */ 4530 int success; /* status of makeDir call */ 4531 4532 4533 /* 4534 * Scan through the name, and locate first and last slashes. 4535 */ 4536 4537 for (cp = name; *cp; cp++) { 4538 if (*cp == '/') { 4539 if (! firstSlash) { 4540 firstSlash = cp; 4541 } 4542 lastSlash = cp; 4543 } 4544 } 4545 4546 /* 4547 * Determine what you can from the proceeds of the scan. 4548 */ 4549 4550 lastChar = *(cp - 1); 4551 nameLen = (int)(cp - name); 4552 trailingSlash = (lastChar == '/'); 4553 leadingSlash = (*name == '/'); 4554 markedDir = (dblock.dbuf.typeflag == '5' || trailingSlash); 4555 4556 if (! lastSlash && ! markedDir) { 4557 /* 4558 * The named file does not have any subdrectory 4559 * structure; just bail out. 4560 */ 4561 4562 return (0); 4563 } 4564 4565 /* 4566 * Make sure that name doesn`t end with slash for the loop. 4567 * This ensures that the makeDir attempt after the loop is 4568 * meaningful. 4569 */ 4570 4571 if (trailingSlash) { 4572 name[nameLen-1] = '\0'; 4573 } 4574 4575 /* 4576 * Make the path one component at a time. 4577 */ 4578 4579 for (cp = strchr(leadingSlash ? name+1 : name, '/'); 4580 cp; 4581 cp = strchr(cp+1, '/')) { 4582 *cp = '\0'; 4583 success = makeDir(name); 4584 *cp = '/'; 4585 4586 if (!success) { 4587 name[nameLen-1] = lastChar; 4588 return (0); 4589 } 4590 } 4591 4592 /* 4593 * This makes the last component of the name, if it is a 4594 * directory. 4595 */ 4596 4597 if (markedDir) { 4598 if (! makeDir(name)) { 4599 name[nameLen-1] = lastChar; 4600 return (0); 4601 } 4602 } 4603 4604 name[nameLen-1] = (lastChar == '/') ? '\0' : lastChar; 4605 return (markedDir); 4606 } 4607 4608 /* 4609 * resugname - Restore the user name and group name. Search the NIS 4610 * before using the uid and gid. 4611 * (It is presumed that an archive entry cannot be 4612 * simultaneously a symlink and some other type.) 4613 */ 4614 4615 static void 4616 resugname(int dirfd, /* dir fd file resides in */ 4617 char *name, /* name of the file to be modified */ 4618 int symflag) /* true if file is a symbolic link */ 4619 { 4620 uid_t duid; 4621 gid_t dgid; 4622 struct stat *sp = &stbuf; 4623 char *u_g_name; 4624 4625 if (checkflag == 1) { /* Extended tar format and euid == 0 */ 4626 4627 /* 4628 * Try and extract the intended uid and gid from the name 4629 * service before believing the uid and gid in the header. 4630 * 4631 * In the case where we archived a setuid or setgid file 4632 * owned by someone with a large uid, then it will 4633 * have made it into the archive with a uid of nobody. If 4634 * the corresponding username doesn't appear to exist, then we 4635 * want to make sure it *doesn't* end up as setuid nobody! 4636 * 4637 * Our caller will print an error message about the fact 4638 * that the restore didn't work out quite right .. 4639 */ 4640 if (xhdr_flgs & _X_UNAME) 4641 u_g_name = Xtarhdr.x_uname; 4642 else 4643 u_g_name = dblock.dbuf.uname; 4644 if ((duid = getuidbyname(u_g_name)) == -1) { 4645 if (S_ISREG(sp->st_mode) && sp->st_uid == UID_NOBODY && 4646 (sp->st_mode & S_ISUID) == S_ISUID) 4647 (void) chmod(name, 4648 MODEMASK & sp->st_mode & ~S_ISUID); 4649 duid = sp->st_uid; 4650 } 4651 4652 /* (Ditto for gids) */ 4653 4654 if (xhdr_flgs & _X_GNAME) 4655 u_g_name = Xtarhdr.x_gname; 4656 else 4657 u_g_name = dblock.dbuf.gname; 4658 if ((dgid = getgidbyname(u_g_name)) == -1) { 4659 if (S_ISREG(sp->st_mode) && sp->st_gid == GID_NOBODY && 4660 (sp->st_mode & S_ISGID) == S_ISGID) 4661 (void) chmod(name, 4662 MODEMASK & sp->st_mode & ~S_ISGID); 4663 dgid = sp->st_gid; 4664 } 4665 } else if (checkflag == 2) { /* tar format and euid == 0 */ 4666 duid = sp->st_uid; 4667 dgid = sp->st_gid; 4668 } 4669 if ((checkflag == 1) || (checkflag == 2)) 4670 (void) fchownat(dirfd, name, duid, dgid, symflag); 4671 } 4672 4673 /*ARGSUSED*/ 4674 static void 4675 onintr(int sig) 4676 { 4677 (void) signal(SIGINT, SIG_IGN); 4678 term++; 4679 } 4680 4681 /*ARGSUSED*/ 4682 static void 4683 onquit(int sig) 4684 { 4685 (void) signal(SIGQUIT, SIG_IGN); 4686 term++; 4687 } 4688 4689 /*ARGSUSED*/ 4690 static void 4691 onhup(int sig) 4692 { 4693 (void) signal(SIGHUP, SIG_IGN); 4694 term++; 4695 } 4696 4697 static void 4698 tomodes(struct stat *sp) 4699 { 4700 uid_t uid; 4701 gid_t gid; 4702 4703 bzero(dblock.dummy, TBLOCK); 4704 4705 /* 4706 * If the uid or gid is too large, we can't put it into 4707 * the archive. We could fail to put anything in the 4708 * archive at all .. but most of the time the name service 4709 * will save the day when we do a lookup at restore time. 4710 * 4711 * Instead we choose a "safe" uid and gid, and fix up whether 4712 * or not the setuid and setgid bits are left set to extraction 4713 * time. 4714 */ 4715 if (Eflag) { 4716 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) { 4717 xhdr_flgs |= _X_UID; 4718 Xtarhdr.x_uid = uid; 4719 } 4720 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) { 4721 xhdr_flgs |= _X_GID; 4722 Xtarhdr.x_gid = gid; 4723 } 4724 if (sp->st_size > TAR_OFFSET_MAX) { 4725 xhdr_flgs |= _X_SIZE; 4726 Xtarhdr.x_filesz = sp->st_size; 4727 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4728 (off_t)0); 4729 } else 4730 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4731 sp->st_size); 4732 } else { 4733 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4734 sp->st_size); 4735 } 4736 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) 4737 uid = UID_NOBODY; 4738 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) 4739 gid = GID_NOBODY; 4740 (void) sprintf(dblock.dbuf.gid, "%07lo", gid); 4741 (void) sprintf(dblock.dbuf.uid, "%07lo", uid); 4742 (void) sprintf(dblock.dbuf.mode, "%07lo", sp->st_mode & POSIXMODES); 4743 (void) sprintf(dblock.dbuf.mtime, "%011lo", sp->st_mtime); 4744 } 4745 4746 static int 4747 #ifdef EUC 4748 /* 4749 * Warning: the result of this function depends whether 'char' is a 4750 * signed or unsigned data type. This a source of potential 4751 * non-portability among heterogeneous systems. It is retained here 4752 * for backward compatibility. 4753 */ 4754 checksum_signed(union hblock *dblockp) 4755 #else 4756 checksum(union hblock *dblockp) 4757 #endif /* EUC */ 4758 { 4759 int i; 4760 char *cp; 4761 4762 for (cp = dblockp->dbuf.chksum; 4763 cp < &dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]; cp++) 4764 *cp = ' '; 4765 i = 0; 4766 for (cp = dblockp->dummy; cp < &(dblockp->dummy[TBLOCK]); cp++) 4767 i += *cp; 4768 return (i); 4769 } 4770 4771 #ifdef EUC 4772 /* 4773 * Generate unsigned checksum, regardless of what C compiler is 4774 * used. Survives in the face of arbitrary 8-bit clean filenames, 4775 * e.g., internationalized filenames. 4776 */ 4777 static int 4778 checksum(union hblock *dblockp) 4779 { 4780 unsigned i; 4781 unsigned char *cp; 4782 4783 for (cp = (unsigned char *) dblockp->dbuf.chksum; 4784 cp < (unsigned char *) 4785 &(dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]); cp++) 4786 *cp = ' '; 4787 i = 0; 4788 for (cp = (unsigned char *) dblockp->dummy; 4789 cp < (unsigned char *) &(dblockp->dummy[TBLOCK]); cp++) 4790 i += *cp; 4791 4792 return (i); 4793 } 4794 #endif /* EUC */ 4795 4796 /* 4797 * If the w flag is set, output the action to be taken and the name of the 4798 * file. Perform the action if the user response is affirmative. 4799 */ 4800 4801 static int 4802 checkw(char c, char *name) 4803 { 4804 if (wflag) { 4805 (void) fprintf(vfile, "%c ", c); 4806 if (vflag) 4807 longt(&stbuf, ' '); /* do we have acl info here */ 4808 (void) fprintf(vfile, "%s: ", name); 4809 if (yes() == 1) { 4810 return (1); 4811 } 4812 return (0); 4813 } 4814 return (1); 4815 } 4816 4817 /* 4818 * When the F flag is set, exclude RCS and SCCS directories (and any files 4819 * or directories under them). If F is set twice, also exclude .o files, 4820 * and files names errs, core, and a.out. 4821 * 4822 * Return 0 if file should be excluded, 1 otherwise. 4823 */ 4824 4825 static int 4826 checkf(char *longname, int is_dir, int howmuch) 4827 { 4828 static char fullname[PATH_MAX + 1]; 4829 char *dir, *name; 4830 4831 #if defined(O_XATTR) 4832 /* 4833 * If there is an xattr_buf structure associated with this file, 4834 * always return 1. 4835 */ 4836 if (xattrp) { 4837 return (1); 4838 } 4839 #endif 4840 4841 /* 4842 * First check to see if the base name is an RCS or SCCS directory. 4843 */ 4844 if (strlcpy(fullname, longname, sizeof (fullname)) >= sizeof (fullname)) 4845 return (1); 4846 4847 name = basename(fullname); 4848 if (is_dir) { 4849 if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0)) 4850 return (0); 4851 } 4852 4853 /* 4854 * If two -F command line options were given then exclude .o files, 4855 * and files named errs, core, and a.out. 4856 */ 4857 if (howmuch > 1 && !is_dir) { 4858 size_t l = strlen(name); 4859 4860 if (l >= 3 && name[l - 2] == '.' && name[l - 1] == 'o') 4861 return (0); 4862 if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 || 4863 strcmp(name, "a.out") == 0) 4864 return (0); 4865 } 4866 4867 /* 4868 * At this point, check to see if this file has a parent directory 4869 * named RCS or SCCS. If so, then this file should be excluded too. 4870 * The strcpy() operation is done again, because basename(3C) may 4871 * modify the path string passed to it. 4872 */ 4873 if (strlcpy(fullname, longname, sizeof (fullname)) >= sizeof (fullname)) 4874 return (1); 4875 4876 dir = dirname(fullname); 4877 while (strcmp(dir, ".") != 0) { 4878 name = basename(dir); 4879 if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0)) 4880 return (0); 4881 dir = dirname(dir); 4882 } 4883 4884 return (1); 4885 } 4886 4887 static int 4888 response(void) 4889 { 4890 int c; 4891 4892 c = getchar(); 4893 if (c != '\n') 4894 while (getchar() != '\n') 4895 ; 4896 else c = 'n'; 4897 return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c); 4898 } 4899 4900 /* Has file been modified since being put into archive? If so, return > 0. */ 4901 4902 static off_t lookup(char *); 4903 4904 static int 4905 checkupdate(char *arg) 4906 { 4907 char name[PATH_MAX+1]; 4908 time_t mtime; 4909 long nsecs; 4910 off_t seekp; 4911 4912 rewind(tfile); 4913 if ((seekp = lookup(arg)) < 0) 4914 return (1); 4915 (void) fseek(tfile, seekp, 0); 4916 (void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs); 4917 4918 /* 4919 * Unless nanoseconds were stored in the file, only use seconds for 4920 * comparison of time. Nanoseconds are stored when -E is specified. 4921 */ 4922 if (Eflag == 0) 4923 return (stbuf.st_mtime > mtime); 4924 4925 if ((stbuf.st_mtime < mtime) || 4926 ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs))) 4927 return (0); 4928 return (1); 4929 } 4930 4931 4932 /* 4933 * newvol get new floppy (or tape) volume 4934 * 4935 * newvol(); resets tapepos and first to TRUE, prompts for 4936 * for new volume, and waits. 4937 * if dumping, end-of-file is written onto the tape. 4938 */ 4939 4940 static void 4941 newvol(void) 4942 { 4943 int c; 4944 4945 if (dumping) { 4946 #ifdef DEBUG 4947 DEBUG("newvol called with 'dumping' set\n", 0, 0); 4948 #endif 4949 putempty((blkcnt_t)2); /* 2 EOT marks */ 4950 closevol(); 4951 flushtape(); 4952 sync(); 4953 tapepos = 0; 4954 } else 4955 first = TRUE; 4956 if (close(mt) != 0) 4957 vperror(2, gettext("close error")); 4958 mt = 0; 4959 (void) fprintf(stderr, gettext( 4960 "tar: \007please insert new volume, then press RETURN.")); 4961 (void) fseek(stdin, (off_t)0, 2); /* scan over read-ahead */ 4962 while ((c = getchar()) != '\n' && ! term) 4963 if (c == EOF) 4964 done(Errflg); 4965 if (term) 4966 done(Errflg); 4967 4968 errno = 0; 4969 4970 if (strcmp(usefile, "-") == 0) { 4971 mt = dup(1); 4972 } else { 4973 mt = open(usefile, dumping ? update : 0); 4974 } 4975 4976 if (mt < 0) { 4977 (void) fprintf(stderr, gettext( 4978 "tar: cannot reopen %s (%s)\n"), 4979 dumping ? gettext("output") : gettext("input"), usefile); 4980 4981 #ifdef DEBUG 4982 DEBUG("update=%d, usefile=%s ", update, usefile); 4983 DEBUG("mt=%d, [%s]\n", mt, strerror(errno)); 4984 #endif 4985 4986 done(2); 4987 } 4988 } 4989 4990 /* 4991 * Write a trailer portion to close out the current output volume. 4992 */ 4993 4994 static void 4995 closevol(void) 4996 { 4997 if (mulvol) { 4998 /* 4999 * blocklim does not count the 2 EOT marks; 5000 * tapepos does count the 2 EOT marks; 5001 * therefore we need the +2 below. 5002 */ 5003 putempty(blocklim + (blkcnt_t)2 - tapepos); 5004 } 5005 } 5006 5007 static void 5008 done(int n) 5009 { 5010 /* 5011 * If we were terminated in some way, and we would otherwise have 5012 * exited with a value of 0, adjust to 1, so that external callers 5013 * can determine this by looking at the exit status. 5014 */ 5015 if (term && n == 0) 5016 n = 1; 5017 5018 if (tfile != NULL) 5019 (void) unlink(tname); 5020 if (compress_opt != NULL) 5021 (void) free(compress_opt); 5022 if (mt > 0) { 5023 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 5024 perror(gettext("tar: close error")); 5025 exit(2); 5026 } 5027 } 5028 exit(n); 5029 } 5030 5031 /* 5032 * Determine if s1 is a prefix portion of s2 (or the same as s2). 5033 */ 5034 5035 static int 5036 is_prefix(char *s1, char *s2) 5037 { 5038 while (*s1) 5039 if (*s1++ != *s2++) 5040 return (0); 5041 if (*s2) 5042 return (*s2 == '/'); 5043 return (1); 5044 } 5045 5046 /* 5047 * lookup and bsrch look through tfile entries to find a match for a name. 5048 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 5049 * a pair of newline chars, so the buffer it uses must be long enough for 5050 * two lines: name and modification time as well as period, newline and space. 5051 * 5052 * A kludge was added to bsrch to take care of matching on the first entry 5053 * in the file--there is no leading newline. So, if we are reading from the 5054 * start of the file, read into byte two and set the first byte to a newline. 5055 * Otherwise, the first entry cannot be matched. 5056 * 5057 */ 5058 5059 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 5060 static off_t 5061 lookup(char *s) 5062 { 5063 int i; 5064 off_t a; 5065 5066 for (i = 0; s[i]; i++) 5067 if (s[i] == ' ') 5068 break; 5069 a = bsrch(s, i, low, high); 5070 return (a); 5071 } 5072 5073 static off_t 5074 bsrch(char *s, int n, off_t l, off_t h) 5075 { 5076 int i, j; 5077 char b[N]; 5078 off_t m, m1; 5079 5080 5081 loop: 5082 if (l >= h) 5083 return ((off_t)-1); 5084 m = l + (h-l)/2 - N/2; 5085 if (m < l) 5086 m = l; 5087 (void) fseek(tfile, m, 0); 5088 if (m == 0) { 5089 (void) fread(b+1, 1, N-1, tfile); 5090 b[0] = '\n'; 5091 m--; 5092 } else 5093 (void) fread(b, 1, N, tfile); 5094 for (i = 0; i < N; i++) { 5095 if (b[i] == '\n') 5096 break; 5097 m++; 5098 } 5099 if (m >= h) 5100 return ((off_t)-1); 5101 m1 = m; 5102 j = i; 5103 for (i++; i < N; i++) { 5104 m1++; 5105 if (b[i] == '\n') 5106 break; 5107 } 5108 i = cmp(b+j, s, n); 5109 if (i < 0) { 5110 h = m; 5111 goto loop; 5112 } 5113 if (i > 0) { 5114 l = m1; 5115 goto loop; 5116 } 5117 if (m < 0) 5118 m = 0; 5119 return (m); 5120 } 5121 5122 static int 5123 cmp(char *b, char *s, int n) 5124 { 5125 int i; 5126 5127 assert(b[0] == '\n'); 5128 5129 for (i = 0; i < n; i++) { 5130 if (b[i+1] > s[i]) 5131 return (-1); 5132 if (b[i+1] < s[i]) 5133 return (1); 5134 } 5135 return (b[i+1] == ' '? 0 : -1); 5136 } 5137 5138 5139 /* 5140 * seekdisk seek to next file on archive 5141 * 5142 * called by passtape() only 5143 * 5144 * WARNING: expects "nblock" to be set, that is, readtape() to have 5145 * already been called. Since passtape() is only called 5146 * after a file header block has been read (why else would 5147 * we skip to next file?), this is currently safe. 5148 * 5149 * changed to guarantee SYS_BLOCK boundary 5150 */ 5151 5152 static void 5153 seekdisk(blkcnt_t blocks) 5154 { 5155 off_t seekval; 5156 #if SYS_BLOCK > TBLOCK 5157 /* handle non-multiple of SYS_BLOCK */ 5158 blkcnt_t nxb; /* # extra blocks */ 5159 #endif 5160 5161 tapepos += blocks; 5162 #ifdef DEBUG 5163 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 5164 #endif 5165 if (recno + blocks <= nblock) { 5166 recno += blocks; 5167 return; 5168 } 5169 if (recno > nblock) 5170 recno = nblock; 5171 seekval = (off_t)blocks - (nblock - recno); 5172 recno = nblock; /* so readtape() reads next time through */ 5173 #if SYS_BLOCK > TBLOCK 5174 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 5175 #ifdef DEBUG 5176 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 5177 nxb, seekval); 5178 #endif 5179 if (nxb && nxb > seekval) /* don't seek--we'll read */ 5180 goto noseek; 5181 seekval -= nxb; /* don't seek quite so far */ 5182 #endif 5183 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 5184 (void) fprintf(stderr, gettext( 5185 "tar: device seek error\n")); 5186 done(3); 5187 } 5188 #if SYS_BLOCK > TBLOCK 5189 /* read those extra blocks */ 5190 noseek: 5191 if (nxb) { 5192 #ifdef DEBUG 5193 DEBUG("reading extra blocks\n", 0, 0); 5194 #endif 5195 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 5196 (void) fprintf(stderr, gettext( 5197 "tar: read error while skipping file\n")); 5198 done(8); 5199 } 5200 recno = nxb; /* so we don't read in next readtape() */ 5201 } 5202 #endif 5203 } 5204 5205 static void 5206 readtape(char *buffer) 5207 { 5208 int i, j; 5209 5210 ++tapepos; 5211 if (recno >= nblock || first) { 5212 if (first) { 5213 /* 5214 * set the number of blocks to read initially, based on 5215 * the defined defaults for the device, or on the 5216 * explicit block factor given. 5217 */ 5218 if (bflag || defaults_used || NotTape) 5219 j = nblock; 5220 else 5221 j = NBLOCK; 5222 } else 5223 j = nblock; 5224 5225 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 5226 (void) fprintf(stderr, gettext( 5227 "tar: tape read error\n")); 5228 done(3); 5229 /* 5230 * i == 0 and !rflag means that EOF is reached and we are 5231 * trying to update or replace an empty tar file, so exit 5232 * with an error. 5233 * 5234 * If i == 0 and !first and NotTape, it means the pointer 5235 * has gone past the EOF. It could happen if two processes 5236 * try to update the same tar file simultaneously. So exit 5237 * with an error. 5238 */ 5239 5240 } else if (i == 0) { 5241 if (first && !rflag) { 5242 (void) fprintf(stderr, gettext( 5243 "tar: blocksize = %d\n"), i); 5244 done(Errflg); 5245 } else if (!first && (!rflag || NotTape)) { 5246 mterr("read", 0, 2); 5247 } 5248 } else if ((!first || Bflag) && i != TBLOCK*j) { 5249 /* 5250 * Short read - try to get the remaining bytes. 5251 */ 5252 5253 int remaining = (TBLOCK * j) - i; 5254 char *b = (char *)tbuf + i; 5255 int r; 5256 5257 do { 5258 if ((r = read(mt, b, remaining)) < 0) { 5259 (void) fprintf(stderr, 5260 gettext("tar: tape read error\n")); 5261 done(3); 5262 } 5263 b += r; 5264 remaining -= r; 5265 i += r; 5266 } while (remaining > 0 && r != 0); 5267 } 5268 if (first) { 5269 if ((i % TBLOCK) != 0) { 5270 (void) fprintf(stderr, gettext( 5271 "tar: tape blocksize error\n")); 5272 done(3); 5273 } 5274 i /= TBLOCK; 5275 if (vflag && i != nblock && i != 1) { 5276 if (!NotTape) 5277 (void) fprintf(stderr, gettext( 5278 "tar: blocksize = %d\n"), i); 5279 } 5280 5281 /* 5282 * If we are reading a tape, then a short read is 5283 * understood to signify that the amount read is 5284 * the tape's actual blocking factor. We adapt 5285 * nblock accordingly. There is no reason to do 5286 * this when the device is not blocked. 5287 */ 5288 5289 if (!NotTape) 5290 nblock = i; 5291 } 5292 recno = 0; 5293 } 5294 5295 first = FALSE; 5296 copy(buffer, &tbuf[recno++]); 5297 } 5298 5299 5300 /* 5301 * replacement for writetape. 5302 */ 5303 5304 static int 5305 writetbuf(char *buffer, int n) 5306 { 5307 int i; 5308 5309 tapepos += n; /* output block count */ 5310 5311 if (recno >= nblock) { 5312 i = write(mt, (char *)tbuf, TBLOCK*nblock); 5313 if (i != TBLOCK*nblock) 5314 mterr("write", i, 2); 5315 recno = 0; 5316 } 5317 5318 /* 5319 * Special case: We have an empty tape buffer, and the 5320 * users data size is >= the tape block size: Avoid 5321 * the bcopy and dma direct to tape. BIG WIN. Add the 5322 * residual to the tape buffer. 5323 */ 5324 while (recno == 0 && n >= nblock) { 5325 i = (int)write(mt, buffer, TBLOCK*nblock); 5326 if (i != TBLOCK*nblock) 5327 mterr("write", i, 2); 5328 n -= nblock; 5329 buffer += (nblock * TBLOCK); 5330 } 5331 5332 while (n-- > 0) { 5333 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 5334 buffer += TBLOCK; 5335 if (recno >= nblock) { 5336 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 5337 if (i != TBLOCK*nblock) 5338 mterr("write", i, 2); 5339 recno = 0; 5340 } 5341 } 5342 5343 /* Tell the user how much to write to get in sync */ 5344 return (nblock - recno); 5345 } 5346 5347 /* 5348 * backtape - reposition tape after reading soft "EOF" record 5349 * 5350 * Backtape tries to reposition the tape back over the EOF 5351 * record. This is for the 'u' and 'r' function letters so that the 5352 * tape can be extended. This code is not well designed, but 5353 * I'm confident that the only callers who care about the 5354 * backspace-over-EOF feature are those involved in 'u' and 'r'. 5355 * 5356 * The proper way to backup the tape is through the use of mtio. 5357 * Earlier spins used lseek combined with reads in a confusing 5358 * maneuver that only worked on 4.x, but shouldn't have, even 5359 * there. Lseeks are explicitly not supported for tape devices. 5360 */ 5361 5362 static void 5363 backtape(void) 5364 { 5365 struct mtop mtcmd; 5366 #ifdef DEBUG 5367 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 5368 nblock); 5369 #endif 5370 /* 5371 * Backup to the position in the archive where the record 5372 * currently sitting in the tbuf buffer is situated. 5373 */ 5374 5375 if (NotTape) { 5376 /* 5377 * For non-tape devices, this means lseeking to the 5378 * correct position. The absolute location tapepos-recno 5379 * should be the beginning of the current record. 5380 */ 5381 5382 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 5383 (off_t)-1) { 5384 (void) fprintf(stderr, 5385 gettext("tar: lseek to end of archive failed\n")); 5386 done(4); 5387 } 5388 } else { 5389 /* 5390 * For tape devices, we backup over the most recently 5391 * read record. 5392 */ 5393 5394 mtcmd.mt_op = MTBSR; 5395 mtcmd.mt_count = 1; 5396 5397 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 5398 (void) fprintf(stderr, 5399 gettext("tar: backspace over record failed\n")); 5400 done(4); 5401 } 5402 } 5403 5404 /* 5405 * Decrement the tape and tbuf buffer indices to prepare for the 5406 * coming write to overwrite the soft EOF record. 5407 */ 5408 5409 recno--; 5410 tapepos--; 5411 } 5412 5413 5414 /* 5415 * flushtape write buffered block(s) onto tape 5416 * 5417 * recno points to next free block in tbuf. If nonzero, a write is done. 5418 * Care is taken to write in multiples of SYS_BLOCK when device is 5419 * non-magtape in case raw i/o is used. 5420 * 5421 * NOTE: this is called by writetape() to do the actual writing 5422 */ 5423 5424 static void 5425 flushtape(void) 5426 { 5427 #ifdef DEBUG 5428 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 5429 #endif 5430 if (recno > 0) { /* anything buffered? */ 5431 if (NotTape) { 5432 #if SYS_BLOCK > TBLOCK 5433 int i; 5434 5435 /* 5436 * an odd-block write can only happen when 5437 * we are at the end of a volume that is not a tape. 5438 * Here we round recno up to an even SYS_BLOCK 5439 * boundary. 5440 */ 5441 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 5442 #ifdef DEBUG 5443 DEBUG("flushtape() %d rounding blocks\n", i, 0); 5444 #endif 5445 recno += i; /* round up to even SYS_BLOCK */ 5446 } 5447 #endif 5448 if (recno > nblock) 5449 recno = nblock; 5450 } 5451 #ifdef DEBUG 5452 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 5453 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 5454 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 5455 #endif 5456 if (write(mt, tbuf, 5457 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 5458 (void) fprintf(stderr, gettext( 5459 "tar: tape write error\n")); 5460 done(2); 5461 } 5462 recno = 0; 5463 } 5464 } 5465 5466 static void 5467 copy(void *dst, void *src) 5468 { 5469 (void) memcpy(dst, src, TBLOCK); 5470 } 5471 5472 #ifdef _iBCS2 5473 /* 5474 * initarg -- initialize things for nextarg. 5475 * 5476 * argv filename list, a la argv. 5477 * filefile name of file containing filenames. Unless doing 5478 * a create, seeks must be allowable (e.g. no named pipes). 5479 * 5480 * - if filefile is non-NULL, it will be used first, and argv will 5481 * be used when the data in filefile are exhausted. 5482 * - otherwise argv will be used. 5483 */ 5484 static char **Cmdargv = NULL; 5485 static FILE *FILEFile = NULL; 5486 static long seekFile = -1; 5487 static char *ptrtoFile, *begofFile, *endofFile; 5488 5489 static void 5490 initarg(char *argv[], char *filefile) 5491 { 5492 struct stat statbuf; 5493 char *p; 5494 int nbytes; 5495 5496 Cmdargv = argv; 5497 if (filefile == NULL) 5498 return; /* no -F file */ 5499 if (FILEFile != NULL) { 5500 /* 5501 * need to REinitialize 5502 */ 5503 if (seekFile != -1) 5504 (void) fseek(FILEFile, seekFile, 0); 5505 ptrtoFile = begofFile; 5506 return; 5507 } 5508 /* 5509 * first time initialization 5510 */ 5511 if ((FILEFile = fopen(filefile, "r")) == NULL) 5512 fatal(gettext("cannot open (%s)"), filefile); 5513 (void) fstat(fileno(FILEFile), &statbuf); 5514 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 5515 (void) fprintf(stderr, gettext( 5516 "tar: %s is not a regular file\n"), filefile); 5517 (void) fclose(FILEFile); 5518 done(1); 5519 } 5520 ptrtoFile = begofFile = endofFile; 5521 seekFile = 0; 5522 if (!xflag) 5523 return; /* the file will be read only once anyway */ 5524 nbytes = statbuf.st_size; 5525 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 5526 nbytes -= 20; 5527 if (nbytes < 50) { 5528 free(begofFile); 5529 begofFile = endofFile; 5530 return; /* no room so just do plain reads */ 5531 } 5532 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 5533 fatal(gettext("could not read %s"), filefile); 5534 ptrtoFile = begofFile; 5535 endofFile = begofFile + nbytes; 5536 for (p = begofFile; p < endofFile; ++p) 5537 if (*p == '\n') 5538 *p = '\0'; 5539 if (nbytes != statbuf.st_size) 5540 seekFile = nbytes + 1; 5541 else 5542 (void) fclose(FILEFile); 5543 } 5544 5545 /* 5546 * nextarg -- get next argument of arglist. 5547 * 5548 * The argument is taken from wherever is appropriate. 5549 * 5550 * If the 'F file' function modifier has been specified, the argument 5551 * will be taken from the file, unless EOF has been reached. 5552 * Otherwise the argument will be taken from argv. 5553 * 5554 * WARNING: 5555 * Return value may point to static data, whose contents are over- 5556 * written on each call. 5557 */ 5558 static char * 5559 nextarg(void) 5560 { 5561 static char nameFile[PATH_MAX + 1]; 5562 int n; 5563 char *p; 5564 5565 if (FILEFile) { 5566 if (ptrtoFile < endofFile) { 5567 p = ptrtoFile; 5568 while (*ptrtoFile) 5569 ++ptrtoFile; 5570 ++ptrtoFile; 5571 return (p); 5572 } 5573 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 5574 n = strlen(nameFile); 5575 if (n > 0 && nameFile[n-1] == '\n') 5576 nameFile[n-1] = '\0'; 5577 return (nameFile); 5578 } 5579 } 5580 return (*Cmdargv++); 5581 } 5582 #endif /* _iBCS2 */ 5583 5584 /* 5585 * kcheck() 5586 * - checks the validity of size values for non-tape devices 5587 * - if size is zero, mulvol tar is disabled and size is 5588 * assumed to be infinite. 5589 * - returns volume size in TBLOCKS 5590 */ 5591 5592 static blkcnt_t 5593 kcheck(char *kstr) 5594 { 5595 blkcnt_t kval; 5596 5597 kval = strtoll(kstr, NULL, 0); 5598 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 5599 mulvol = 0; /* definitely not mulvol, but we must */ 5600 return (0); /* took out setting of NotTape */ 5601 } 5602 if (kval < (blkcnt_t)MINSIZE) { 5603 (void) fprintf(stderr, gettext( 5604 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 5605 ").\n"), (ulong_t)MINSIZE, kval); 5606 if (!kflag) 5607 (void) fprintf(stderr, gettext( 5608 "bad size entry for %s in %s.\n"), 5609 archive, DEF_FILE); 5610 done(1); 5611 } 5612 mulvol++; 5613 NotTape++; /* implies non-tape */ 5614 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 5615 } 5616 5617 5618 /* 5619 * bcheck() 5620 * - checks the validity of blocking factors 5621 * - returns blocking factor 5622 */ 5623 5624 static int 5625 bcheck(char *bstr) 5626 { 5627 blkcnt_t bval; 5628 5629 bval = strtoll(bstr, NULL, 0); 5630 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 5631 (void) fprintf(stderr, gettext( 5632 "tar: invalid blocksize \"%s\".\n"), bstr); 5633 if (!bflag) 5634 (void) fprintf(stderr, gettext( 5635 "bad blocksize entry for '%s' in %s.\n"), 5636 archive, DEF_FILE); 5637 done(1); 5638 } 5639 5640 return ((int)bval); 5641 } 5642 5643 5644 /* 5645 * defset() 5646 * - reads DEF_FILE for the set of default values specified. 5647 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 5648 * - 'usefile' points to static data, so will be overwritten 5649 * if this routine is called a second time. 5650 * - the pattern specified by 'arch' must be followed by four 5651 * blank-separated fields (1) device (2) blocking, 5652 * (3) size(K), and (4) tape 5653 * for example: archive0=/dev/fd 1 400 n 5654 */ 5655 5656 static int 5657 defset(char *arch) 5658 { 5659 char *bp; 5660 5661 if (defopen(DEF_FILE) != 0) 5662 return (FALSE); 5663 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 5664 (void) fprintf(stderr, gettext( 5665 "tar: error setting parameters for %s.\n"), DEF_FILE); 5666 return (FALSE); /* & following ones too */ 5667 } 5668 if ((bp = defread(arch)) == NULL) { 5669 (void) fprintf(stderr, gettext( 5670 "tar: missing or invalid '%s' entry in %s.\n"), 5671 arch, DEF_FILE); 5672 return (FALSE); 5673 } 5674 if ((usefile = strtok(bp, " \t")) == NULL) { 5675 (void) fprintf(stderr, gettext( 5676 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 5677 return (FALSE); 5678 } 5679 if ((bp = strtok(NULL, " \t")) == NULL) { 5680 (void) fprintf(stderr, gettext( 5681 "tar: block component missing in '%s' entry in %s.\n"), 5682 arch, DEF_FILE); 5683 return (FALSE); 5684 } 5685 nblock = bcheck(bp); 5686 if ((bp = strtok(NULL, " \t")) == NULL) { 5687 (void) fprintf(stderr, gettext( 5688 "tar: size component missing in '%s' entry in %s.\n"), 5689 arch, DEF_FILE); 5690 return (FALSE); 5691 } 5692 blocklim = kcheck(bp); 5693 if ((bp = strtok(NULL, " \t")) != NULL) 5694 NotTape = (*bp == 'n' || *bp == 'N'); 5695 else 5696 NotTape = (blocklim != 0); 5697 (void) defopen(NULL); 5698 #ifdef DEBUG 5699 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 5700 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 5701 nblock, blocklim); 5702 DEBUG("defset: not tape = %d\n", NotTape, 0); 5703 #endif 5704 return (TRUE); 5705 } 5706 5707 5708 /* 5709 * Following code handles excluded and included files. 5710 * A hash table of file names to be {in,ex}cluded is built. 5711 * For excluded files, before writing or extracting a file 5712 * check to see if it is in the exclude_tbl. 5713 * For included files, the wantit() procedure will check to 5714 * see if the named file is in the include_tbl. 5715 */ 5716 5717 static void 5718 build_table(file_list_t *table[], char *file) 5719 { 5720 FILE *fp; 5721 char buf[PATH_MAX + 1]; 5722 5723 if ((fp = fopen(file, "r")) == (FILE *)NULL) 5724 vperror(1, gettext("could not open %s"), file); 5725 while (fgets(buf, sizeof (buf), fp) != NULL) { 5726 if (buf[strlen(buf) - 1] == '\n') 5727 buf[strlen(buf) - 1] = '\0'; 5728 /* Only add to table if line has something in it */ 5729 if (strspn(buf, " \t") != strlen(buf)) 5730 add_file_to_table(table, buf); 5731 } 5732 (void) fclose(fp); 5733 } 5734 5735 5736 /* 5737 * Add a file name to the the specified table, if the file name has any 5738 * trailing '/'s then delete them before inserting into the table 5739 */ 5740 5741 static void 5742 add_file_to_table(file_list_t *table[], char *str) 5743 { 5744 char name[PATH_MAX + 1]; 5745 unsigned int h; 5746 file_list_t *exp; 5747 5748 (void) strcpy(name, str); 5749 while (name[strlen(name) - 1] == '/') { 5750 name[strlen(name) - 1] = NULL; 5751 } 5752 5753 h = hash(name); 5754 if ((exp = (file_list_t *)calloc(sizeof (file_list_t), 5755 sizeof (char))) == NULL) { 5756 (void) fprintf(stderr, gettext( 5757 "tar: out of memory, exclude/include table(entry)\n")); 5758 exit(1); 5759 } 5760 5761 if ((exp->name = strdup(name)) == NULL) { 5762 (void) fprintf(stderr, gettext( 5763 "tar: out of memory, exclude/include table(file name)\n")); 5764 exit(1); 5765 } 5766 5767 exp->next = table[h]; 5768 table[h] = exp; 5769 } 5770 5771 5772 /* 5773 * See if a file name or any of the file's parent directories is in the 5774 * specified table, if the file name has any trailing '/'s then delete 5775 * them before searching the table 5776 */ 5777 5778 static int 5779 is_in_table(file_list_t *table[], char *str) 5780 { 5781 char name[PATH_MAX + 1]; 5782 unsigned int h; 5783 file_list_t *exp; 5784 char *ptr; 5785 5786 (void) strcpy(name, str); 5787 while (name[strlen(name) - 1] == '/') { 5788 name[strlen(name) - 1] = NULL; 5789 } 5790 5791 /* 5792 * check for the file name in the passed list 5793 */ 5794 h = hash(name); 5795 exp = table[h]; 5796 while (exp != NULL) { 5797 if (strcmp(name, exp->name) == 0) { 5798 return (1); 5799 } 5800 exp = exp->next; 5801 } 5802 5803 /* 5804 * check for any parent directories in the file list 5805 */ 5806 while ((ptr = strrchr(name, '/'))) { 5807 *ptr = NULL; 5808 h = hash(name); 5809 exp = table[h]; 5810 while (exp != NULL) { 5811 if (strcmp(name, exp->name) == 0) { 5812 return (1); 5813 } 5814 exp = exp->next; 5815 } 5816 } 5817 5818 return (0); 5819 } 5820 5821 5822 /* 5823 * Compute a hash from a string. 5824 */ 5825 5826 static unsigned int 5827 hash(char *str) 5828 { 5829 char *cp; 5830 unsigned int h; 5831 5832 h = 0; 5833 for (cp = str; *cp; cp++) { 5834 h += *cp; 5835 } 5836 return (h % TABLE_SIZE); 5837 } 5838 5839 static void * 5840 getmem(size_t size) 5841 { 5842 void *p = calloc((unsigned)size, sizeof (char)); 5843 5844 if (p == NULL && freemem) { 5845 (void) fprintf(stderr, gettext( 5846 "tar: out of memory, link and directory modtime " 5847 "info lost\n")); 5848 freemem = 0; 5849 if (errflag) 5850 done(1); 5851 else 5852 Errflg = 1; 5853 } 5854 return (p); 5855 } 5856 5857 /* 5858 * vperror() --variable argument perror. 5859 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 5860 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 5861 * with the value of whatever "errno" is set to. If exit_status is not 5862 * zero, then tar exits with that error status. If errflag and exit_status 5863 * are both zero, the routine returns to where it was called and sets Errflg 5864 * to errno. 5865 */ 5866 5867 static void 5868 vperror(int exit_status, char *fmt, ...) 5869 { 5870 va_list ap; 5871 5872 va_start(ap, fmt); 5873 (void) fputs("tar: ", stderr); 5874 (void) vfprintf(stderr, fmt, ap); 5875 (void) fprintf(stderr, ": %s\n", strerror(errno)); 5876 va_end(ap); 5877 if (exit_status) 5878 done(exit_status); 5879 else 5880 if (errflag) 5881 done(errno); 5882 else 5883 Errflg = errno; 5884 } 5885 5886 5887 static void 5888 fatal(char *format, ...) 5889 { 5890 va_list ap; 5891 5892 va_start(ap, format); 5893 (void) fprintf(stderr, "tar: "); 5894 (void) vfprintf(stderr, format, ap); 5895 (void) fprintf(stderr, "\n"); 5896 va_end(ap); 5897 done(1); 5898 } 5899 5900 5901 /* 5902 * Check to make sure that argument is a char * ptr. 5903 * Actually, we just check to see that it is non-null. 5904 * If it is null, print out the message and call usage(), bailing out. 5905 */ 5906 5907 static void 5908 assert_string(char *s, char *msg) 5909 { 5910 if (s == NULL) { 5911 (void) fprintf(stderr, msg); 5912 usage(); 5913 } 5914 } 5915 5916 5917 static void 5918 mterr(char *operation, int i, int exitcode) 5919 { 5920 (void) fprintf(stderr, gettext( 5921 "tar: %s error: "), operation); 5922 if (i < 0) 5923 perror(""); 5924 else 5925 (void) fprintf(stderr, gettext("unexpected EOF\n")); 5926 done(exitcode); 5927 } 5928 5929 static int 5930 wantit(char *argv[], char **namep, char **dirp, char **component, 5931 attr_data_t **attrinfo) 5932 { 5933 char **cp; 5934 int gotit; /* true if we've found a match */ 5935 int ret; 5936 5937 top: 5938 if (xhdr_flgs & _X_XHDR) { 5939 xhdr_flgs = 0; 5940 } 5941 getdir(); 5942 if (Xhdrflag > 0) { 5943 ret = get_xdata(); 5944 if (ret != 0) { /* Xhdr items and regular header */ 5945 setbytes_to_skip(&stbuf, ret); 5946 passtape(); 5947 return (0); /* Error--don't want to extract */ 5948 } 5949 } 5950 5951 /* 5952 * If typeflag is not 'A' and xhdr_flgs is set, then processing 5953 * of ancillary file is either over or ancillary file 5954 * processing is not required, load info from Xtarhdr and set 5955 * _X_XHDR bit in xhdr_flgs. 5956 */ 5957 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 5958 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 5959 xhdr_flgs |= _X_XHDR; 5960 } 5961 5962 #if defined(O_XATTR) 5963 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 5964 /* 5965 * Always needs to read the extended header. If atflag, saflag, 5966 * or tflag isn't set, then we'll have the correct info for 5967 * passtape() later. 5968 */ 5969 (void) read_xattr_hdr(attrinfo); 5970 goto top; 5971 } 5972 /* 5973 * Now that we've read the extended header, call passtape() 5974 * if we don't want to restore attributes or system attributes. 5975 * Don't restore the attribute if we are extracting 5976 * a file from an archive (as opposed to doing a table of 5977 * contents) and any of the following are true: 5978 * 1. neither -@ or -/ was specified. 5979 * 2. -@ was specified, -/ wasn't specified, and we're 5980 * processing a hidden attribute directory of an attribute 5981 * or we're processing a read-write system attribute file. 5982 * 3. -@ wasn't specified, -/ was specified, and the file 5983 * we're processing is not a read-write system attribute file, 5984 * or we're processing the hidden attribute directory of an 5985 * attribute. 5986 * 5987 * We always process the attributes if we're just generating 5988 * generating a table of contents, or if both -@ and -/ were 5989 * specified. 5990 */ 5991 if (xattrp != NULL) { 5992 attr_data_t *ainfo = *attrinfo; 5993 5994 if (!tflag && 5995 ((!atflag && !saflag) || 5996 (atflag && !saflag && ((ainfo->attr_parent != NULL) || 5997 ainfo->attr_rw_sysattr)) || 5998 (!atflag && saflag && ((ainfo->attr_parent != NULL) || 5999 !ainfo->attr_rw_sysattr)))) { 6000 passtape(); 6001 return (0); 6002 } 6003 } 6004 #endif 6005 6006 /* sets *namep to point at the proper name */ 6007 if (check_prefix(namep, dirp, component) != 0) { 6008 passtape(); 6009 return (0); 6010 } 6011 6012 if (endtape()) { 6013 if (Bflag) { 6014 /* 6015 * Logically at EOT - consume any extra blocks 6016 * so that write to our stdin won't fail and 6017 * emit an error message; otherwise something 6018 * like "dd if=foo.tar | (cd bar; tar xvf -)" 6019 * will produce a bogus error message from "dd". 6020 */ 6021 6022 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 6023 /* empty body */ 6024 } 6025 } 6026 return (-1); 6027 } 6028 6029 gotit = 0; 6030 6031 if ((Iflag && is_in_table(include_tbl, *namep)) || 6032 (! Iflag && *argv == NULL)) { 6033 gotit = 1; 6034 } else { 6035 for (cp = argv; *cp; cp++) { 6036 if (is_prefix(*cp, *namep)) { 6037 gotit = 1; 6038 break; 6039 } 6040 } 6041 } 6042 6043 if (! gotit) { 6044 passtape(); 6045 return (0); 6046 } 6047 6048 if (Xflag && is_in_table(exclude_tbl, *namep)) { 6049 if (vflag) { 6050 (void) fprintf(stderr, gettext("%s excluded\n"), 6051 *namep); 6052 } 6053 passtape(); 6054 return (0); 6055 } 6056 6057 return (1); 6058 } 6059 6060 6061 static void 6062 setbytes_to_skip(struct stat *st, int err) 6063 { 6064 /* 6065 * In a scenario where a typeflag 'X' was followed by 6066 * a typeflag 'A' and typeflag 'O', then the number of 6067 * bytes to skip should be the size of ancillary file, 6068 * plus the dblock for regular file, and the size 6069 * from Xtarhdr. However, if the typeflag was just 'X' 6070 * followed by typeflag 'O', then the number of bytes 6071 * to skip should be the size from Xtarhdr. 6072 */ 6073 if ((err != 0) && (dblock.dbuf.typeflag == 'A') && 6074 (xhdr_flgs & _X_SIZE)) { 6075 st->st_size += TBLOCK + Xtarhdr.x_filesz; 6076 xhdr_flgs |= _X_XHDR; 6077 } else if ((dblock.dbuf.typeflag != 'A') && 6078 (xhdr_flgs & _X_SIZE)) { 6079 st->st_size += Xtarhdr.x_filesz; 6080 xhdr_flgs |= _X_XHDR; 6081 } 6082 } 6083 6084 static int 6085 fill_in_attr_info(char *attr, char *longname, char *attrparent, int atparentfd, 6086 int rw_sysattr, attr_data_t **attrinfo) 6087 { 6088 size_t pathlen; 6089 char *tpath; 6090 char *tparent; 6091 6092 /* parent info */ 6093 if (attrparent != NULL) { 6094 if ((tparent = strdup(attrparent)) == NULL) { 6095 vperror(0, gettext( 6096 "unable to allocate memory for attribute parent " 6097 "name for %sattribute %s/%s of %s"), 6098 rw_sysattr ? gettext("system ") : "", 6099 attrparent, attr, longname); 6100 return (1); 6101 } 6102 } else { 6103 tparent = NULL; 6104 } 6105 6106 /* path info */ 6107 pathlen = strlen(attr) + 1; 6108 if (attrparent != NULL) { 6109 pathlen += strlen(attrparent) + 1; /* add 1 for '/' */ 6110 } 6111 if ((tpath = calloc(1, pathlen)) == NULL) { 6112 vperror(0, gettext( 6113 "unable to allocate memory for full " 6114 "attribute path name for %sattribute %s%s%s of %s"), 6115 rw_sysattr ? gettext("system ") : "", 6116 (attrparent == NULL) ? "" : attrparent, 6117 (attrparent == NULL) ? "" : "/", 6118 attr, longname); 6119 if (tparent != NULL) { 6120 free(tparent); 6121 } 6122 return (1); 6123 } 6124 (void) snprintf(tpath, pathlen, "%s%s%s", 6125 (attrparent == NULL) ? "" : attrparent, 6126 (attrparent == NULL) ? "" : "/", 6127 attr); 6128 6129 /* fill in the attribute info */ 6130 if (*attrinfo == NULL) { 6131 if ((*attrinfo = malloc(sizeof (attr_data_t))) == NULL) { 6132 vperror(0, gettext( 6133 "unable to allocate memory for attribute " 6134 "information for %sattribute %s%s%s of %s"), 6135 rw_sysattr ? gettext("system ") : "", 6136 (attrparent == NULL) ? "" : attrparent, 6137 (attrparent == NULL) ? "" : gettext("/"), 6138 attr, longname); 6139 if (tparent != NULL) { 6140 free(tparent); 6141 } 6142 free(tpath); 6143 return (1); 6144 } 6145 } else { 6146 if ((*attrinfo)->attr_parent != NULL) { 6147 free((*attrinfo)->attr_parent); 6148 } 6149 if ((*attrinfo)->attr_path != NULL) { 6150 free((*attrinfo)->attr_path); 6151 } 6152 /* 6153 * The parent file descriptor is passed in, so don't 6154 * close it here as it should be closed by the function 6155 * that opened it. 6156 */ 6157 } 6158 (*attrinfo)->attr_parent = tparent; 6159 (*attrinfo)->attr_path = tpath; 6160 (*attrinfo)->attr_rw_sysattr = rw_sysattr; 6161 (*attrinfo)->attr_parentfd = atparentfd; 6162 6163 return (0); 6164 } 6165 6166 /* 6167 * Test to see if name is a directory. 6168 * 6169 * Return 1 if true, 0 otherwise. 6170 */ 6171 6172 static int 6173 is_directory(char *name) 6174 { 6175 #if defined(O_XATTR) 6176 /* 6177 * If there is an xattr_buf structure associated with this file, 6178 * then the directory test is based on whether the name has a 6179 * trailing slash. 6180 */ 6181 if (xattrp) 6182 return (name[strlen(name) - 1] == '/'); 6183 #endif 6184 if (is_posix) 6185 return (dblock.dbuf.typeflag == '5'); 6186 else 6187 return (name[strlen(name) - 1] == '/'); 6188 } 6189 6190 /* 6191 * Test if name has a '..' sequence in it. 6192 * 6193 * Return 1 if found, 0 otherwise. 6194 */ 6195 6196 static int 6197 has_dot_dot(char *name) 6198 { 6199 char *s; 6200 size_t name_len = strlen(name); 6201 6202 for (s = name; s < (name + name_len - 2); s++) { 6203 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6204 return (1); 6205 6206 while (! (*s == '/')) { 6207 if (! *s++) 6208 return (0); 6209 } 6210 } 6211 6212 return (0); 6213 } 6214 6215 /* 6216 * Test if name is an absolute path name. 6217 * 6218 * Return 1 if true, 0 otherwise. 6219 */ 6220 6221 static int 6222 is_absolute(char *name) 6223 { 6224 #if defined(O_XATTR) 6225 /* 6226 * If this is an extended attribute (whose name will begin with 6227 * "/dev/null/", always return 0 as they should be extracted with 6228 * the name intact, to allow other tar archiving programs that 6229 * don't understand extended attributes, to correctly throw them away. 6230 */ 6231 if (xattrp) 6232 return (0); 6233 #endif 6234 6235 return (name[0] == '/'); 6236 } 6237 6238 /* 6239 * Adjust the pathname to make it a relative one. Strip off any leading 6240 * '/' characters and if the pathname contains any '..' sequences, strip 6241 * upto and including the last occurance of '../' (or '..' if found at 6242 * the very end of the pathname). 6243 * 6244 * Return the relative pathname. stripped_prefix will also return the 6245 * portion of name that was stripped off and should be freed by the 6246 * calling routine when no longer needed. 6247 */ 6248 6249 static char * 6250 make_relative_name(char *name, char **stripped_prefix) 6251 { 6252 char *s; 6253 size_t prefix_len = 0; 6254 size_t name_len = strlen(name); 6255 6256 for (s = name + prefix_len; s < (name + name_len - 2); ) { 6257 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6258 prefix_len = s + 2 - name; 6259 6260 do { 6261 char c = *s++; 6262 6263 if (c == '/') 6264 break; 6265 } while (*s); 6266 } 6267 6268 for (s = name + prefix_len; *s == '/'; s++) 6269 continue; 6270 prefix_len = s - name; 6271 6272 /* Create the portion of the name that was stripped off. */ 6273 s = malloc(prefix_len + 1); 6274 memcpy(s, name, prefix_len); 6275 s[prefix_len] = 0; 6276 *stripped_prefix = s; 6277 s = &name[prefix_len]; 6278 6279 return (s); 6280 } 6281 6282 /* 6283 * Return through *namep a pointer to the proper fullname (i.e "<name> | 6284 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 6285 * 6286 * Returns 0 if successful, otherwise returns 1. 6287 */ 6288 6289 static int 6290 check_prefix(char **namep, char **dirp, char **compp) 6291 { 6292 static char fullname[PATH_MAX + 1]; 6293 static char dir[PATH_MAX + 1]; 6294 static char component[PATH_MAX + 1]; 6295 static char savename[PATH_MAX + 1]; 6296 char *s; 6297 6298 (void) memset(dir, 0, sizeof (dir)); 6299 (void) memset(component, 0, sizeof (component)); 6300 6301 if (xhdr_flgs & _X_PATH) { 6302 (void) strcpy(fullname, Xtarhdr.x_path); 6303 } else { 6304 if (dblock.dbuf.prefix[0] != '\0') 6305 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 6306 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 6307 else 6308 (void) sprintf(fullname, "%.*s", NAMSIZ, 6309 dblock.dbuf.name); 6310 } 6311 6312 /* 6313 * If we are printing a table of contents or extracting an archive, 6314 * make absolute pathnames relative and prohibit the unpacking of 6315 * files contain ".." in their name (unless the user has supplied 6316 * the -P option). 6317 */ 6318 if ((tflag || xflag) && !Pflag) { 6319 if (is_absolute(fullname) || has_dot_dot(fullname)) { 6320 char *stripped_prefix; 6321 size_t prefix_len = 0; 6322 6323 (void) strcpy(savename, fullname); 6324 strcpy(fullname, 6325 make_relative_name(savename, &stripped_prefix)); 6326 (void) fprintf(stderr, 6327 gettext("tar: Removing leading '%s' from '%s'\n"), 6328 stripped_prefix, savename); 6329 free(stripped_prefix); 6330 } 6331 } 6332 6333 /* 6334 * Set dir and component names 6335 */ 6336 6337 get_parent(fullname, dir); 6338 6339 #if defined(O_XATTR) 6340 if (xattrp == NULL) { 6341 #endif 6342 /* 6343 * Save of real name since were going to chop off the 6344 * trailing slashes. 6345 */ 6346 (void) strcpy(savename, fullname); 6347 /* 6348 * first strip of trailing slashes. 6349 */ 6350 chop_endslashes(savename); 6351 s = get_component(savename); 6352 (void) strcpy(component, s); 6353 6354 #if defined(O_XATTR) 6355 } else { 6356 (void) strcpy(fullname, xattrp->h_names); 6357 (void) strcpy(dir, fullname); 6358 (void) strcpy(component, basename(xattrp->h_names + 6359 strlen(xattrp->h_names) + 1)); 6360 } 6361 #endif 6362 *namep = fullname; 6363 *dirp = dir; 6364 *compp = component; 6365 6366 return (0); 6367 } 6368 6369 /* 6370 * Return true if the object indicated by the file descriptor and type 6371 * is a tape device, false otherwise 6372 */ 6373 6374 static int 6375 istape(int fd, int type) 6376 { 6377 int result = 0; 6378 6379 if (S_ISCHR(type)) { 6380 struct mtget mtg; 6381 6382 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 6383 result = 1; 6384 } 6385 } 6386 6387 return (result); 6388 } 6389 6390 #include <utmpx.h> 6391 6392 struct utmpx utmpx; 6393 6394 #define NMAX (sizeof (utmpx.ut_name)) 6395 6396 typedef struct cachenode { /* this struct must be zeroed before using */ 6397 struct cachenode *next; /* next in hash chain */ 6398 int val; /* the uid or gid of this entry */ 6399 int namehash; /* name's hash signature */ 6400 char name[NMAX+1]; /* the string that val maps to */ 6401 } cachenode_t; 6402 6403 #define HASHSIZE 256 6404 6405 static cachenode_t *names[HASHSIZE]; 6406 static cachenode_t *groups[HASHSIZE]; 6407 static cachenode_t *uids[HASHSIZE]; 6408 static cachenode_t *gids[HASHSIZE]; 6409 6410 static int 6411 hash_byname(char *name) 6412 { 6413 int i, c, h = 0; 6414 6415 for (i = 0; i < NMAX; i++) { 6416 c = name[i]; 6417 if (c == '\0') 6418 break; 6419 h = (h << 4) + h + c; 6420 } 6421 return (h); 6422 } 6423 6424 static cachenode_t * 6425 hash_lookup_byval(cachenode_t *table[], int val) 6426 { 6427 int h = val; 6428 cachenode_t *c; 6429 6430 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6431 if (c->val == val) 6432 return (c); 6433 } 6434 return (NULL); 6435 } 6436 6437 static cachenode_t * 6438 hash_lookup_byname(cachenode_t *table[], char *name) 6439 { 6440 int h = hash_byname(name); 6441 cachenode_t *c; 6442 6443 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6444 if (c->namehash == h && strcmp(c->name, name) == 0) 6445 return (c); 6446 } 6447 return (NULL); 6448 } 6449 6450 static cachenode_t * 6451 hash_insert(cachenode_t *table[], char *name, int value) 6452 { 6453 cachenode_t *c; 6454 int signature; 6455 6456 c = calloc(1, sizeof (cachenode_t)); 6457 if (c == NULL) { 6458 perror("malloc"); 6459 exit(1); 6460 } 6461 if (name != NULL) { 6462 (void) strncpy(c->name, name, NMAX); 6463 c->namehash = hash_byname(name); 6464 } 6465 c->val = value; 6466 if (table == uids || table == gids) 6467 signature = c->val; 6468 else 6469 signature = c->namehash; 6470 c->next = table[signature & (HASHSIZE - 1)]; 6471 table[signature & (HASHSIZE - 1)] = c; 6472 return (c); 6473 } 6474 6475 static char * 6476 getname(uid_t uid) 6477 { 6478 cachenode_t *c; 6479 6480 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 6481 struct passwd *pwent = getpwuid(uid); 6482 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 6483 } 6484 return (c->name); 6485 } 6486 6487 static char * 6488 getgroup(gid_t gid) 6489 { 6490 cachenode_t *c; 6491 6492 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 6493 struct group *grent = getgrgid(gid); 6494 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 6495 } 6496 return (c->name); 6497 } 6498 6499 static uid_t 6500 getuidbyname(char *name) 6501 { 6502 cachenode_t *c; 6503 6504 if ((c = hash_lookup_byname(names, name)) == NULL) { 6505 struct passwd *pwent = getpwnam(name); 6506 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 6507 } 6508 return ((uid_t)c->val); 6509 } 6510 6511 static gid_t 6512 getgidbyname(char *group) 6513 { 6514 cachenode_t *c; 6515 6516 if ((c = hash_lookup_byname(groups, group)) == NULL) { 6517 struct group *grent = getgrnam(group); 6518 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 6519 } 6520 return ((gid_t)c->val); 6521 } 6522 6523 /* 6524 * Build the header. 6525 * Determine whether or not an extended header is also needed. If needed, 6526 * create and write the extended header and its data. 6527 * Writing of the extended header assumes that "tomodes" has been called and 6528 * the relevant information has been placed in the header block. 6529 */ 6530 6531 static int 6532 build_dblock( 6533 const char *name, 6534 const char *linkname, 6535 const char typeflag, 6536 const int filetype, 6537 const struct stat *sp, 6538 const dev_t device, 6539 const char *prefix) 6540 { 6541 int nblks; 6542 major_t dev; 6543 const char *filename; 6544 const char *lastslash; 6545 6546 if (filetype == XATTR_FILE) 6547 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 6548 else 6549 dblock.dbuf.typeflag = typeflag; 6550 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 6551 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 6552 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 6553 6554 if (xhdr_flgs & _X_PATH) 6555 filename = Xtarhdr.x_path; 6556 else 6557 filename = name; 6558 6559 if ((dev = major(device)) > OCTAL7CHAR) { 6560 if (Eflag) { 6561 xhdr_flgs |= _X_DEVMAJOR; 6562 Xtarhdr.x_devmajor = dev; 6563 } else { 6564 (void) fprintf(stderr, gettext( 6565 "Device major too large for %s. Use -E flag."), 6566 filename); 6567 if (errflag) 6568 done(1); 6569 else 6570 Errflg = 1; 6571 } 6572 dev = 0; 6573 } 6574 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 6575 if ((dev = minor(device)) > OCTAL7CHAR) { 6576 if (Eflag) { 6577 xhdr_flgs |= _X_DEVMINOR; 6578 Xtarhdr.x_devminor = dev; 6579 } else { 6580 (void) fprintf(stderr, gettext( 6581 "Device minor too large for %s. Use -E flag."), 6582 filename); 6583 if (errflag) 6584 done(1); 6585 else 6586 Errflg = 1; 6587 } 6588 dev = 0; 6589 } 6590 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 6591 6592 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 6593 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 6594 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 6595 (void) sprintf(dblock.dbuf.version, "00"); 6596 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 6597 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 6598 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 6599 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 6600 6601 if (Eflag) { 6602 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 6603 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 6604 lastslash = strrchr(name, '/'); 6605 if (lastslash == NULL) 6606 lastslash = name; 6607 else 6608 lastslash++; 6609 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 6610 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 6611 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 6612 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 6613 xhdr_count++; 6614 xrec_offset = 0; 6615 gen_date("mtime", sp->st_mtim); 6616 xhdr_buf.dbuf.typeflag = 'X'; 6617 if (gen_utf8_names(filename) != 0) 6618 return (1); 6619 6620 #ifdef XHDR_DEBUG 6621 Xtarhdr.x_uname = dblock.dbuf.uname; 6622 Xtarhdr.x_gname = dblock.dbuf.gname; 6623 xhdr_flgs |= (_X_UNAME | _X_GNAME); 6624 #endif 6625 if (xhdr_flgs) { 6626 if (xhdr_flgs & _X_DEVMAJOR) 6627 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 6628 if (xhdr_flgs & _X_DEVMINOR) 6629 gen_num("SUN.devminor", Xtarhdr.x_devminor); 6630 if (xhdr_flgs & _X_GID) 6631 gen_num("gid", Xtarhdr.x_gid); 6632 if (xhdr_flgs & _X_UID) 6633 gen_num("uid", Xtarhdr.x_uid); 6634 if (xhdr_flgs & _X_SIZE) 6635 gen_num("size", Xtarhdr.x_filesz); 6636 if (xhdr_flgs & _X_PATH) 6637 gen_string("path", Xtarhdr.x_path); 6638 if (xhdr_flgs & _X_LINKPATH) 6639 gen_string("linkpath", Xtarhdr.x_linkpath); 6640 if (xhdr_flgs & _X_GNAME) 6641 gen_string("gname", Xtarhdr.x_gname); 6642 if (xhdr_flgs & _X_UNAME) 6643 gen_string("uname", Xtarhdr.x_uname); 6644 } 6645 (void) sprintf(xhdr_buf.dbuf.size, 6646 "%011" FMT_off_t_o, xrec_offset); 6647 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 6648 checksum(&xhdr_buf)); 6649 (void) writetbuf((char *)&xhdr_buf, 1); 6650 nblks = TBLOCKS(xrec_offset); 6651 (void) writetbuf(xrec_ptr, nblks); 6652 } 6653 return (0); 6654 } 6655 6656 6657 /* 6658 * makeDir - ensure that a directory with the pathname denoted by name 6659 * exists, and return 1 on success, and 0 on failure (e.g., 6660 * read-only file system, exists but not-a-directory). 6661 */ 6662 6663 static int 6664 makeDir(char *name) 6665 { 6666 struct stat buf; 6667 6668 if (access(name, 0) < 0) { /* name doesn't exist */ 6669 if (mkdir(name, 0777) < 0) { 6670 vperror(0, "%s", name); 6671 return (0); 6672 } 6673 } else { /* name exists */ 6674 if (stat(name, &buf) < 0) { 6675 vperror(0, "%s", name); 6676 return (0); 6677 } 6678 6679 return ((buf.st_mode & S_IFMT) == S_IFDIR); 6680 } 6681 6682 return (1); 6683 } 6684 6685 6686 /* 6687 * Save this directory and its mtime on the stack, popping and setting 6688 * the mtimes of any stacked dirs which aren't parents of this one. 6689 * A null name causes the entire stack to be unwound and set. 6690 * 6691 * Since all the elements of the directory "stack" share a common 6692 * prefix, we can make do with one string. We keep only the current 6693 * directory path, with an associated array of mtime's. A negative 6694 * mtime means no mtime. 6695 * 6696 * This stack algorithm is not guaranteed to work for tapes created 6697 * with the 'r' function letter, but the vast majority of tapes with 6698 * directories are not. This avoids saving every directory record on 6699 * the tape and setting all the times at the end. 6700 * 6701 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 6702 * environment) 6703 */ 6704 6705 static void 6706 doDirTimes(char *name, timestruc_t modTime) 6707 { 6708 static char dirstack[PATH_MAX+2]; 6709 /* Add spaces for the last slash and last NULL */ 6710 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 6711 char *p = dirstack; 6712 char *q = name; 6713 char *savp; 6714 6715 if (q) { 6716 /* 6717 * Find common prefix 6718 */ 6719 6720 while (*p == *q && *p) { 6721 p++; q++; 6722 } 6723 } 6724 6725 savp = p; 6726 while (*p) { 6727 /* 6728 * Not a child: unwind the stack, setting the times. 6729 * The order we do this doesn't matter, so we go "forward." 6730 */ 6731 6732 if (*p == '/') 6733 if (modtimes[p - dirstack].tv_sec >= 0) { 6734 *p = '\0'; /* zap the slash */ 6735 setPathTimes(AT_FDCWD, dirstack, 6736 modtimes[p - dirstack]); 6737 *p = '/'; 6738 } 6739 ++p; 6740 } 6741 6742 p = savp; 6743 6744 /* 6745 * Push this one on the "stack" 6746 */ 6747 6748 if (q) { 6749 6750 /* 6751 * Since the name parameter points the dir pathname 6752 * which is limited only to contain PATH_MAX chars 6753 * at maximum, we can ignore the overflow case of p. 6754 */ 6755 6756 while ((*p = *q++)) { /* append the rest of the new dir */ 6757 modtimes[p - dirstack].tv_sec = -1; 6758 p++; 6759 } 6760 6761 /* 6762 * If the tar file had used 'P' or 'E' function modifier, 6763 * append the last slash. 6764 */ 6765 if (*(p - 1) != '/') { 6766 *p++ = '/'; 6767 *p = '\0'; 6768 } 6769 /* overwrite the last one */ 6770 modtimes[p - dirstack - 1] = modTime; 6771 } 6772 } 6773 6774 6775 /* 6776 * setPathTimes - set the modification time for given path. Return 1 if 6777 * successful and 0 if not successful. 6778 */ 6779 6780 static void 6781 setPathTimes(int dirfd, char *path, timestruc_t modTime) 6782 6783 { 6784 struct timeval timebuf[2]; 6785 6786 /* 6787 * futimesat takes an array of two timeval structs. 6788 * The first entry contains access time. 6789 * The second entry contains modification time. 6790 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 6791 * microseconds. 6792 */ 6793 timebuf[0].tv_sec = time((time_t *)0); 6794 timebuf[0].tv_usec = 0; 6795 timebuf[1].tv_sec = modTime.tv_sec; 6796 6797 /* Extended header: use microseconds */ 6798 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 6799 6800 if (futimesat(dirfd, path, timebuf) < 0) 6801 vperror(0, gettext("can't set time on %s"), path); 6802 } 6803 6804 6805 /* 6806 * If hflag is set then delete the symbolic link's target. 6807 * If !hflag then delete the target. 6808 */ 6809 6810 static void 6811 delete_target(int fd, char *comp, char *namep) 6812 { 6813 struct stat xtractbuf; 6814 char buf[PATH_MAX + 1]; 6815 int n; 6816 6817 6818 if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) { 6819 if (errno == ENOTDIR && !hflag) { 6820 (void) unlinkat(fd, comp, 0); 6821 } else if (errno == ENOTDIR && hflag) { 6822 if (!lstat(namep, &xtractbuf)) { 6823 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 6824 (void) unlinkat(fd, comp, 0); 6825 } else if ((n = readlink(namep, buf, 6826 PATH_MAX)) != -1) { 6827 buf[n] = (char)NULL; 6828 (void) unlinkat(fd, buf, 6829 AT_REMOVEDIR); 6830 if (errno == ENOTDIR) 6831 (void) unlinkat(fd, buf, 0); 6832 } else { 6833 (void) unlinkat(fd, comp, 0); 6834 } 6835 } else { 6836 (void) unlinkat(fd, comp, 0); 6837 } 6838 } 6839 } 6840 } 6841 6842 6843 /* 6844 * ACL changes: 6845 * putfile(): 6846 * Get acl info after stat. Write out ancillary file 6847 * before the normal file, i.e. directory, regular, FIFO, 6848 * link, special. If acl count is less than 4, no need to 6849 * create ancillary file. (i.e. standard permission is in 6850 * use. 6851 * doxtract(): 6852 * Process ancillary file. Read it in and set acl info. 6853 * watch out for 'o' function modifier. 6854 * 't' function letter to display table 6855 */ 6856 6857 /* 6858 * New functions for ACLs and other security attributes 6859 */ 6860 6861 /* 6862 * The function appends the new security attribute info to the end of 6863 * existing secinfo. 6864 */ 6865 int 6866 append_secattr( 6867 char **secinfo, /* existing security info */ 6868 int *secinfo_len, /* length of existing security info */ 6869 int size, /* new attribute size: unit depends on type */ 6870 char *attrtext, /* new attribute text */ 6871 char attr_type) /* new attribute type */ 6872 { 6873 char *new_secinfo; 6874 int newattrsize; 6875 int oldsize; 6876 struct sec_attr *attr; 6877 6878 /* no need to add */ 6879 if (attr_type != DIR_TYPE) { 6880 if (attrtext == NULL) 6881 return (0); 6882 } 6883 6884 switch (attr_type) { 6885 case UFSD_ACL: 6886 case ACE_ACL: 6887 if (attrtext == NULL) { 6888 (void) fprintf(stderr, gettext("acltotext failed\n")); 6889 return (-1); 6890 } 6891 /* header: type + size = 8 */ 6892 newattrsize = 8 + (int)strlen(attrtext) + 1; 6893 attr = (struct sec_attr *)malloc(newattrsize); 6894 if (attr == NULL) { 6895 (void) fprintf(stderr, 6896 gettext("can't allocate memory\n")); 6897 return (-1); 6898 } 6899 attr->attr_type = attr_type; 6900 (void) sprintf(attr->attr_len, 6901 "%06o", size); /* acl entry count */ 6902 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6903 free(attrtext); 6904 break; 6905 6906 /* Trusted Extensions */ 6907 case DIR_TYPE: 6908 case LBL_TYPE: 6909 newattrsize = sizeof (struct sec_attr) + strlen(attrtext); 6910 attr = (struct sec_attr *)malloc(newattrsize); 6911 if (attr == NULL) { 6912 (void) fprintf(stderr, 6913 gettext("can't allocate memory\n")); 6914 return (-1); 6915 } 6916 attr->attr_type = attr_type; 6917 (void) sprintf(attr->attr_len, 6918 "%06d", size); /* len of attr data */ 6919 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6920 break; 6921 6922 default: 6923 (void) fprintf(stderr, 6924 gettext("unrecognized attribute type\n")); 6925 return (-1); 6926 } 6927 6928 /* old security info + new attr header(8) + new attr */ 6929 oldsize = *secinfo_len; 6930 *secinfo_len += newattrsize; 6931 new_secinfo = (char *)malloc(*secinfo_len); 6932 if (new_secinfo == NULL) { 6933 (void) fprintf(stderr, gettext("can't allocate memory\n")); 6934 *secinfo_len -= newattrsize; 6935 free(attr); 6936 return (-1); 6937 } 6938 6939 (void) memcpy(new_secinfo, *secinfo, oldsize); 6940 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 6941 6942 free(*secinfo); 6943 free(attr); 6944 *secinfo = new_secinfo; 6945 return (0); 6946 } 6947 6948 /* 6949 * write_ancillary(): write out an ancillary file. 6950 * The file has the same header as normal file except the type and size 6951 * fields. The type is 'A' and size is the sum of all attributes 6952 * in bytes. 6953 * The body contains a list of attribute type, size and info. Currently, 6954 * there is only ACL info. This file is put before the normal file. 6955 */ 6956 void 6957 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 6958 { 6959 long blocks; 6960 int savflag; 6961 int savsize; 6962 6963 /* Just tranditional permissions or no security attribute info */ 6964 if (len == 0 || secinfo == NULL) 6965 return; 6966 6967 /* save flag and size */ 6968 savflag = (dblockp->dbuf).typeflag; 6969 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 6970 6971 /* special flag for ancillary file */ 6972 if (hdrtype == _XATTR_HDRTYPE) 6973 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 6974 else 6975 dblockp->dbuf.typeflag = 'A'; 6976 6977 /* for pre-2.5 versions of tar, need to make sure */ 6978 /* the ACL file is readable */ 6979 (void) sprintf(dblock.dbuf.mode, "%07lo", 6980 (stbuf.st_mode & POSIXMODES) | 0000200); 6981 (void) sprintf(dblockp->dbuf.size, "%011o", len); 6982 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 6983 6984 /* write out the header */ 6985 (void) writetbuf((char *)dblockp, 1); 6986 6987 /* write out security info */ 6988 blocks = TBLOCKS(len); 6989 (void) writetbuf((char *)secinfo, (int)blocks); 6990 6991 /* restore mode, flag and size */ 6992 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 6993 dblockp->dbuf.typeflag = savflag; 6994 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 6995 } 6996 6997 /* 6998 * Read the data record for extended headers and then the regular header. 6999 * The data are read into the buffer and then null-terminated. Entries 7000 * for typeflag 'X' extended headers are of the format: 7001 * "%d %s=%s\n" 7002 * 7003 * When an extended header record is found, the extended header must 7004 * be processed and its values used to override the values in the 7005 * normal header. The way this is done is to process the extended 7006 * header data record and set the data values, then call getdir 7007 * to process the regular header, then then to reconcile the two 7008 * sets of data. 7009 */ 7010 7011 static int 7012 get_xdata(void) 7013 { 7014 struct keylist_pair { 7015 int keynum; 7016 char *keylist; 7017 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 7018 _X_DEVMINOR, "SUN.devminor", 7019 _X_GID, "gid", 7020 _X_GNAME, "gname", 7021 _X_LINKPATH, "linkpath", 7022 _X_PATH, "path", 7023 _X_SIZE, "size", 7024 _X_UID, "uid", 7025 _X_UNAME, "uname", 7026 _X_MTIME, "mtime", 7027 _X_LAST, "NULL" }; 7028 char *lineloc; 7029 int length, i; 7030 char *keyword, *value; 7031 blkcnt_t nblocks; 7032 int bufneeded; 7033 int errors; 7034 7035 (void) memset(&Xtarhdr, 0, sizeof (Xtarhdr)); 7036 xhdr_count++; 7037 errors = 0; 7038 7039 nblocks = TBLOCKS(stbuf.st_size); 7040 bufneeded = nblocks * TBLOCK; 7041 if (bufneeded >= xrec_size) { 7042 free(xrec_ptr); 7043 xrec_size = bufneeded + 1; 7044 if ((xrec_ptr = malloc(xrec_size)) == NULL) 7045 fatal(gettext("cannot allocate buffer")); 7046 } 7047 7048 lineloc = xrec_ptr; 7049 7050 while (nblocks-- > 0) { 7051 readtape(lineloc); 7052 lineloc += TBLOCK; 7053 } 7054 lineloc = xrec_ptr; 7055 xrec_ptr[stbuf.st_size] = '\0'; 7056 while (lineloc < xrec_ptr + stbuf.st_size) { 7057 if (dblock.dbuf.typeflag == 'L') { 7058 length = xrec_size; 7059 keyword = "path"; 7060 value = lineloc; 7061 } else { 7062 length = atoi(lineloc); 7063 *(lineloc + length - 1) = '\0'; 7064 keyword = strchr(lineloc, ' ') + 1; 7065 value = strchr(keyword, '=') + 1; 7066 *(value - 1) = '\0'; 7067 } 7068 i = 0; 7069 lineloc += length; 7070 while (keylist_pair[i].keynum != (int)_X_LAST) { 7071 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 7072 break; 7073 i++; 7074 } 7075 errno = 0; 7076 switch (keylist_pair[i].keynum) { 7077 case _X_DEVMAJOR: 7078 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 7079 if (errno) { 7080 (void) fprintf(stderr, gettext( 7081 "tar: Extended header major value error " 7082 "for file # %llu.\n"), xhdr_count); 7083 errors++; 7084 } else 7085 xhdr_flgs |= _X_DEVMAJOR; 7086 break; 7087 case _X_DEVMINOR: 7088 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 7089 if (errno) { 7090 (void) fprintf(stderr, gettext( 7091 "tar: Extended header minor value error " 7092 "for file # %llu.\n"), xhdr_count); 7093 errors++; 7094 } else 7095 xhdr_flgs |= _X_DEVMINOR; 7096 break; 7097 case _X_GID: 7098 xhdr_flgs |= _X_GID; 7099 Xtarhdr.x_gid = strtol(value, NULL, 0); 7100 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 7101 (void) fprintf(stderr, gettext( 7102 "tar: Extended header gid value error " 7103 "for file # %llu.\n"), xhdr_count); 7104 Xtarhdr.x_gid = GID_NOBODY; 7105 } 7106 break; 7107 case _X_GNAME: 7108 if (utf8_local("gname", &Xtarhdr.x_gname, 7109 local_gname, value, _POSIX_NAME_MAX) == 0) 7110 xhdr_flgs |= _X_GNAME; 7111 break; 7112 case _X_LINKPATH: 7113 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 7114 local_linkpath, value, PATH_MAX) == 0) 7115 xhdr_flgs |= _X_LINKPATH; 7116 else 7117 errors++; 7118 break; 7119 case _X_PATH: 7120 if (utf8_local("path", &Xtarhdr.x_path, 7121 local_path, value, PATH_MAX) == 0) 7122 xhdr_flgs |= _X_PATH; 7123 else 7124 errors++; 7125 break; 7126 case _X_SIZE: 7127 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 7128 if (errno) { 7129 (void) fprintf(stderr, gettext( 7130 "tar: Extended header invalid filesize " 7131 "for file # %llu.\n"), xhdr_count); 7132 errors++; 7133 } else 7134 xhdr_flgs |= _X_SIZE; 7135 break; 7136 case _X_UID: 7137 xhdr_flgs |= _X_UID; 7138 Xtarhdr.x_uid = strtol(value, NULL, 0); 7139 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 7140 (void) fprintf(stderr, gettext( 7141 "tar: Extended header uid value error " 7142 "for file # %llu.\n"), xhdr_count); 7143 Xtarhdr.x_uid = UID_NOBODY; 7144 } 7145 break; 7146 case _X_UNAME: 7147 if (utf8_local("uname", &Xtarhdr.x_uname, 7148 local_uname, value, _POSIX_NAME_MAX) == 0) 7149 xhdr_flgs |= _X_UNAME; 7150 break; 7151 case _X_MTIME: 7152 get_xtime(value, &(Xtarhdr.x_mtime)); 7153 if (errno) 7154 (void) fprintf(stderr, gettext( 7155 "tar: Extended header modification time " 7156 "value error for file # %llu.\n"), 7157 xhdr_count); 7158 else 7159 xhdr_flgs |= _X_MTIME; 7160 break; 7161 default: 7162 (void) fprintf(stderr, 7163 gettext("tar: unrecognized extended" 7164 " header keyword '%s'. Ignored.\n"), keyword); 7165 break; 7166 } 7167 } 7168 7169 getdir(); /* get regular header */ 7170 if (errors && errflag) 7171 done(1); 7172 else 7173 if (errors) 7174 Errflg = 1; 7175 return (errors); 7176 } 7177 7178 /* 7179 * load_info_from_xtarhdr - sets Gen and stbuf variables from 7180 * extended header 7181 * load_info_from_xtarhdr(flag, xhdrp); 7182 * u_longlong_t flag; xhdr_flgs 7183 * struct xtar_hdr *xhdrp; pointer to extended header 7184 * NOTE: called when typeflag is not 'A' and xhdr_flgs 7185 * is set. 7186 */ 7187 static void 7188 load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp) 7189 { 7190 if (flag & _X_DEVMAJOR) { 7191 Gen.g_devmajor = xhdrp->x_devmajor; 7192 } 7193 if (flag & _X_DEVMINOR) { 7194 Gen.g_devminor = xhdrp->x_devminor; 7195 } 7196 if (flag & _X_GID) { 7197 Gen.g_gid = xhdrp->x_gid; 7198 stbuf.st_gid = xhdrp->x_gid; 7199 } 7200 if (flag & _X_UID) { 7201 Gen.g_uid = xhdrp->x_uid; 7202 stbuf.st_uid = xhdrp->x_uid; 7203 } 7204 if (flag & _X_SIZE) { 7205 Gen.g_filesz = xhdrp->x_filesz; 7206 stbuf.st_size = xhdrp->x_filesz; 7207 } 7208 if (flag & _X_MTIME) { 7209 Gen.g_mtime = xhdrp->x_mtime.tv_sec; 7210 stbuf.st_mtim.tv_sec = xhdrp->x_mtime.tv_sec; 7211 stbuf.st_mtim.tv_nsec = xhdrp->x_mtime.tv_nsec; 7212 } 7213 } 7214 7215 /* 7216 * gen_num creates a string from a keyword and an usigned long long in the 7217 * format: %d %s=%s\n 7218 * This is part of the extended header data record. 7219 */ 7220 7221 void 7222 gen_num(const char *keyword, const u_longlong_t number) 7223 { 7224 char save_val[ULONGLONG_MAX_DIGITS + 1]; 7225 int len; 7226 char *curr_ptr; 7227 7228 (void) sprintf(save_val, "%llu", number); 7229 /* 7230 * len = length of entire line, including itself. len will be 7231 * two digits. So, add the string lengths plus the length of len, 7232 * plus a blank, an equal sign, and a newline. 7233 */ 7234 len = strlen(save_val) + strlen(keyword) + 5; 7235 if (xrec_offset + len > xrec_size) { 7236 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7237 fatal(gettext( 7238 "cannot allocate extended header buffer")); 7239 xrec_ptr = curr_ptr; 7240 xrec_size *= 2; 7241 } 7242 (void) sprintf(&xrec_ptr[xrec_offset], 7243 "%d %s=%s\n", len, keyword, save_val); 7244 xrec_offset += len; 7245 } 7246 7247 /* 7248 * gen_date creates a string from a keyword and a timestruc_t in the 7249 * format: %d %s=%s\n 7250 * This is part of the extended header data record. 7251 * Currently, granularity is only microseconds, so the low-order three digits 7252 * will be truncated. 7253 */ 7254 7255 void 7256 gen_date(const char *keyword, const timestruc_t time_value) 7257 { 7258 /* Allow for <seconds>.<nanoseconds>\n */ 7259 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 7260 int len; 7261 char *curr_ptr; 7262 7263 (void) sprintf(save_val, "%ld", time_value.tv_sec); 7264 len = strlen(save_val); 7265 save_val[len] = '.'; 7266 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 7267 7268 /* 7269 * len = length of entire line, including itself. len will be 7270 * two digits. So, add the string lengths plus the length of len, 7271 * plus a blank, an equal sign, and a newline. 7272 */ 7273 len = strlen(save_val) + strlen(keyword) + 5; 7274 if (xrec_offset + len > xrec_size) { 7275 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7276 fatal(gettext( 7277 "cannot allocate extended header buffer")); 7278 xrec_ptr = curr_ptr; 7279 xrec_size *= 2; 7280 } 7281 (void) sprintf(&xrec_ptr[xrec_offset], 7282 "%d %s=%s\n", len, keyword, save_val); 7283 xrec_offset += len; 7284 } 7285 7286 /* 7287 * gen_string creates a string from a keyword and a char * in the 7288 * format: %d %s=%s\n 7289 * This is part of the extended header data record. 7290 */ 7291 7292 void 7293 gen_string(const char *keyword, const char *value) 7294 { 7295 int len; 7296 char *curr_ptr; 7297 7298 /* 7299 * len = length of entire line, including itself. The character length 7300 * of len must be 1-4 characters, because the maximum size of the path 7301 * or the name is PATH_MAX, which is 1024. So, assume 1 character 7302 * for len, one for the space, one for the "=", and one for the newline. 7303 * Then adjust as needed. 7304 */ 7305 /* LINTED constant expression */ 7306 assert(PATH_MAX <= 9996); 7307 len = strlen(value) + strlen(keyword) + 4; 7308 if (len > 997) 7309 len += 3; 7310 else if (len > 98) 7311 len += 2; 7312 else if (len > 9) 7313 len += 1; 7314 if (xrec_offset + len > xrec_size) { 7315 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7316 fatal(gettext( 7317 "cannot allocate extended header buffer")); 7318 xrec_ptr = curr_ptr; 7319 xrec_size *= 2; 7320 } 7321 #ifdef XHDR_DEBUG 7322 if (strcmp(keyword+1, "name") != 0) 7323 #endif 7324 (void) sprintf(&xrec_ptr[xrec_offset], 7325 "%d %s=%s\n", len, keyword, value); 7326 #ifdef XHDR_DEBUG 7327 else { 7328 len += 11; 7329 (void) sprintf(&xrec_ptr[xrec_offset], 7330 "%d %s=%snametoolong\n", len, keyword, value); 7331 } 7332 #endif 7333 xrec_offset += len; 7334 } 7335 7336 /* 7337 * Convert time found in the extended header data to seconds and nanoseconds. 7338 */ 7339 7340 void 7341 get_xtime(char *value, timestruc_t *xtime) 7342 { 7343 char nanosec[10]; 7344 char *period; 7345 int i; 7346 7347 (void) memset(nanosec, '0', 9); 7348 nanosec[9] = '\0'; 7349 7350 period = strchr(value, '.'); 7351 if (period != NULL) 7352 period[0] = '\0'; 7353 xtime->tv_sec = strtol(value, NULL, 10); 7354 if (period == NULL) 7355 xtime->tv_nsec = 0; 7356 else { 7357 i = strlen(period +1); 7358 (void) strncpy(nanosec, period + 1, min(i, 9)); 7359 xtime->tv_nsec = strtol(nanosec, NULL, 10); 7360 } 7361 } 7362 7363 /* 7364 * Check linkpath for length. 7365 * Emit an error message and return 1 if too long. 7366 */ 7367 7368 int 7369 chk_path_build( 7370 char *name, 7371 char *longname, 7372 char *linkname, 7373 char *prefix, 7374 char type, 7375 int filetype) 7376 { 7377 7378 if (strlen(linkname) > (size_t)NAMSIZ) { 7379 if (Eflag > 0) { 7380 xhdr_flgs |= _X_LINKPATH; 7381 Xtarhdr.x_linkpath = linkname; 7382 } else { 7383 (void) fprintf(stderr, gettext( 7384 "tar: %s: linked to %s\n"), longname, linkname); 7385 (void) fprintf(stderr, gettext( 7386 "tar: %s: linked name too long\n"), linkname); 7387 if (errflag) 7388 done(1); 7389 else 7390 Errflg = 1; 7391 return (1); 7392 } 7393 } 7394 if (xhdr_flgs & _X_LINKPATH) 7395 return (build_dblock(name, tchar, type, 7396 filetype, &stbuf, stbuf.st_dev, 7397 prefix)); 7398 else 7399 return (build_dblock(name, linkname, type, 7400 filetype, &stbuf, stbuf.st_dev, prefix)); 7401 } 7402 7403 /* 7404 * Convert from UTF-8 to local character set. 7405 */ 7406 7407 static int 7408 utf8_local( 7409 char *option, 7410 char **Xhdr_ptrptr, 7411 char *target, 7412 const char *source, 7413 int max_val) 7414 { 7415 static iconv_t iconv_cd; 7416 char *nl_target; 7417 const char *iconv_src; 7418 char *iconv_trg; 7419 size_t inlen; 7420 size_t outlen; 7421 7422 if (charset_type == -1) { /* iconv_open failed in earlier try */ 7423 (void) fprintf(stderr, gettext( 7424 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7425 xhdr_count, source); 7426 return (1); 7427 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 7428 nl_target = nl_langinfo(CODESET); 7429 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7430 nl_target = "646"; 7431 if (strcmp(nl_target, "646") == 0) 7432 charset_type = 1; 7433 else if (strcmp(nl_target, "UTF-8") == 0) 7434 charset_type = 3; 7435 else { 7436 if (strncmp(nl_target, "ISO", 3) == 0) 7437 nl_target += 3; 7438 charset_type = 2; 7439 errno = 0; 7440 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 7441 (iconv_t)-1) { 7442 if (errno == EINVAL) 7443 (void) fprintf(stderr, gettext( 7444 "tar: conversion routines not " 7445 "available for current locale. ")); 7446 (void) fprintf(stderr, gettext( 7447 "file # %llu: (%s) UTF-8 conversion" 7448 " failed.\n"), xhdr_count, source); 7449 charset_type = -1; 7450 return (1); 7451 } 7452 } 7453 } 7454 7455 /* locale using 7-bit codeset or UTF-8 locale */ 7456 if (charset_type == 1 || charset_type == 3) { 7457 if (strlen(source) > max_val) { 7458 (void) fprintf(stderr, gettext( 7459 "tar: file # %llu: Extended header %s too long.\n"), 7460 xhdr_count, option); 7461 return (1); 7462 } 7463 if (charset_type == 3) 7464 (void) strcpy(target, source); 7465 else if (c_utf8(target, source) != 0) { 7466 (void) fprintf(stderr, gettext( 7467 "tar: file # %llu: (%s) UTF-8 conversion" 7468 " failed.\n"), xhdr_count, source); 7469 return (1); 7470 } 7471 *Xhdr_ptrptr = target; 7472 return (0); 7473 } 7474 7475 iconv_src = source; 7476 iconv_trg = target; 7477 inlen = strlen(source); 7478 outlen = max_val * UTF_8_FACTOR; 7479 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7480 (size_t)-1) { /* Error occurred: didn't convert */ 7481 (void) fprintf(stderr, gettext( 7482 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7483 xhdr_count, source); 7484 /* Get remaining output; reinitialize conversion descriptor */ 7485 iconv_src = (const char *)NULL; 7486 inlen = 0; 7487 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7488 return (1); 7489 } 7490 /* Get remaining output; reinitialize conversion descriptor */ 7491 iconv_src = (const char *)NULL; 7492 inlen = 0; 7493 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7494 (size_t)-1) { /* Error occurred: didn't convert */ 7495 (void) fprintf(stderr, gettext( 7496 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7497 xhdr_count, source); 7498 return (1); 7499 } 7500 7501 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7502 if (strlen(target) > max_val) { 7503 (void) fprintf(stderr, gettext( 7504 "tar: file # %llu: Extended header %s too long.\n"), 7505 xhdr_count, option); 7506 return (1); 7507 } 7508 *Xhdr_ptrptr = target; 7509 return (0); 7510 } 7511 7512 /* 7513 * Check gname, uname, path, and linkpath to see if they need to go in an 7514 * extended header. If they are already slated to be in an extended header, 7515 * or if they are not ascii, then they need to be in the extended header. 7516 * Then, convert all extended names to UTF-8. 7517 */ 7518 7519 int 7520 gen_utf8_names(const char *filename) 7521 { 7522 static iconv_t iconv_cd; 7523 char *nl_target; 7524 char tempbuf[MAXNAM + 1]; 7525 int nbytes; 7526 int errors; 7527 7528 if (charset_type == -1) { /* Previous failure to open. */ 7529 (void) fprintf(stderr, gettext( 7530 "tar: file # %llu: UTF-8 conversion failed.\n"), 7531 xhdr_count); 7532 return (1); 7533 } 7534 7535 if (charset_type == 0) { /* Need to get conversion descriptor */ 7536 nl_target = nl_langinfo(CODESET); 7537 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7538 nl_target = "646"; 7539 if (strcmp(nl_target, "646") == 0) 7540 charset_type = 1; 7541 else if (strcmp(nl_target, "UTF-8") == 0) 7542 charset_type = 3; 7543 else { 7544 if (strncmp(nl_target, "ISO", 3) == 0) 7545 nl_target += 3; 7546 charset_type = 2; 7547 errno = 0; 7548 #ifdef ICONV_DEBUG 7549 (void) fprintf(stderr, 7550 gettext("Opening iconv_cd with target %s\n"), 7551 nl_target); 7552 #endif 7553 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 7554 (iconv_t)-1) { 7555 if (errno == EINVAL) 7556 (void) fprintf(stderr, gettext( 7557 "tar: conversion routines not " 7558 "available for current locale. ")); 7559 (void) fprintf(stderr, gettext( 7560 "file (%s): UTF-8 conversion failed.\n"), 7561 filename); 7562 charset_type = -1; 7563 return (1); 7564 } 7565 } 7566 } 7567 7568 errors = 0; 7569 7570 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 7571 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 7572 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 7573 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 7574 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 7575 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 7576 tempbuf[NAMSIZ] = '\0'; 7577 } 7578 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 7579 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 7580 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 7581 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 7582 tempbuf[PRESIZ] = '\0'; 7583 nbytes = strlen(tempbuf); 7584 if (nbytes > 0) { 7585 tempbuf[nbytes++] = '/'; 7586 tempbuf[nbytes] = '\0'; 7587 } 7588 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, 7589 (MAXNAM - nbytes)); 7590 tempbuf[MAXNAM] = '\0'; 7591 } 7592 errors += local_utf8(&Xtarhdr.x_path, local_path, 7593 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 7594 7595 if (errors > 0) 7596 (void) fprintf(stderr, gettext( 7597 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 7598 7599 if (errors && errflag) 7600 done(1); 7601 else 7602 if (errors) 7603 Errflg = 1; 7604 return (errors); 7605 } 7606 7607 static int 7608 local_utf8( 7609 char **Xhdr_ptrptr, 7610 char *target, 7611 const char *source, 7612 iconv_t iconv_cd, 7613 int xhdrflg, 7614 int max_val) 7615 { 7616 const char *iconv_src; 7617 const char *starting_src; 7618 char *iconv_trg; 7619 size_t inlen; 7620 size_t outlen; 7621 #ifdef ICONV_DEBUG 7622 unsigned char c_to_hex; 7623 #endif 7624 7625 /* 7626 * If the item is already slated for extended format, get the string 7627 * to convert from the extended header record. Otherwise, get it from 7628 * the regular (dblock) area. 7629 */ 7630 if (xhdr_flgs & xhdrflg) { 7631 if (charset_type == 3) { /* Already UTF-8, just copy */ 7632 (void) strcpy(target, *Xhdr_ptrptr); 7633 *Xhdr_ptrptr = target; 7634 return (0); 7635 } else 7636 iconv_src = (const char *) *Xhdr_ptrptr; 7637 } else { 7638 if (charset_type == 3) /* Already in UTF-8 format */ 7639 return (0); /* Don't create xhdr record */ 7640 iconv_src = source; 7641 } 7642 starting_src = iconv_src; 7643 iconv_trg = target; 7644 if ((inlen = strlen(iconv_src)) == 0) 7645 return (0); 7646 7647 if (charset_type == 1) { /* locale using 7-bit codeset */ 7648 if (c_utf8(target, starting_src) != 0) { 7649 (void) fprintf(stderr, 7650 gettext("tar: invalid character in" 7651 " UTF-8 conversion of '%s'\n"), starting_src); 7652 return (1); 7653 } 7654 return (0); 7655 } 7656 7657 outlen = max_val * UTF_8_FACTOR; 7658 errno = 0; 7659 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7660 (size_t)-1) { 7661 /* An error occurred, or not all characters were converted */ 7662 if (errno == EILSEQ) 7663 (void) fprintf(stderr, 7664 gettext("tar: invalid character in" 7665 " UTF-8 conversion of '%s'\n"), starting_src); 7666 else 7667 (void) fprintf(stderr, gettext( 7668 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7669 starting_src); 7670 /* Get remaining output; reinitialize conversion descriptor */ 7671 iconv_src = (const char *)NULL; 7672 inlen = 0; 7673 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7674 return (1); 7675 } 7676 /* Get remaining output; reinitialize conversion descriptor */ 7677 iconv_src = (const char *)NULL; 7678 inlen = 0; 7679 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7680 (size_t)-1) { /* Error occurred: didn't convert */ 7681 if (errno == EILSEQ) 7682 (void) fprintf(stderr, 7683 gettext("tar: invalid character in" 7684 " UTF-8 conversion of '%s'\n"), starting_src); 7685 else 7686 (void) fprintf(stderr, gettext( 7687 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7688 starting_src); 7689 return (1); 7690 } 7691 7692 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7693 if (strcmp(starting_src, target) != 0) { 7694 *Xhdr_ptrptr = target; 7695 xhdr_flgs |= xhdrflg; 7696 #ifdef ICONV_DEBUG 7697 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 7698 strlen(starting_src), inlen, max_val, outlen); 7699 (void) fprintf(stderr, "Input string:\n "); 7700 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 7701 c_to_hex = (unsigned char)starting_src[inlen]; 7702 (void) fprintf(stderr, " %2.2x", c_to_hex); 7703 if (inlen % 20 == 19) 7704 (void) fprintf(stderr, "\n "); 7705 } 7706 (void) fprintf(stderr, "\nOutput string:\n "); 7707 for (inlen = 0; inlen < strlen(target); inlen++) { 7708 c_to_hex = (unsigned char)target[inlen]; 7709 (void) fprintf(stderr, " %2.2x", c_to_hex); 7710 if (inlen % 20 == 19) 7711 (void) fprintf(stderr, "\n "); 7712 } 7713 (void) fprintf(stderr, "\n"); 7714 #endif 7715 } 7716 7717 return (0); 7718 } 7719 7720 /* 7721 * Function to test each byte of the source string to make sure it is 7722 * in within bounds (value between 0 and 127). 7723 * If valid, copy source to target. 7724 */ 7725 7726 int 7727 c_utf8(char *target, const char *source) 7728 { 7729 size_t len; 7730 const char *thischar; 7731 7732 len = strlen(source); 7733 thischar = source; 7734 while (len-- > 0) { 7735 if (!isascii((int)(*thischar++))) 7736 return (1); 7737 } 7738 7739 (void) strcpy(target, source); 7740 return (0); 7741 } 7742 7743 7744 #if defined(O_XATTR) 7745 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 7746 7747 static void 7748 prepare_xattr( 7749 char **attrbuf, 7750 char *filename, 7751 char *attrpath, 7752 char typeflag, 7753 struct linkbuf *linkinfo, 7754 int *rlen) 7755 { 7756 char *bufhead; /* ptr to full buffer */ 7757 char *aptr; 7758 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 7759 struct xattr_buf *tptr; /* ptr to pathing pieces */ 7760 int totalen; /* total buffer length */ 7761 int len; /* length returned to user */ 7762 int stringlen; /* length of filename + attr */ 7763 /* 7764 * length of filename + attr 7765 * in link section 7766 */ 7767 int linkstringlen; 7768 int complen; /* length of pathing section */ 7769 int linklen; /* length of link section */ 7770 int attrnames_index; /* attrnames starting index */ 7771 7772 /* 7773 * Release previous buffer 7774 */ 7775 7776 if (*attrbuf != (char *)NULL) { 7777 free(*attrbuf); 7778 *attrbuf = NULL; 7779 } 7780 7781 /* 7782 * First add in fixed size stuff 7783 */ 7784 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 7785 7786 /* 7787 * Add space for two nulls 7788 */ 7789 stringlen = strlen(attrpath) + strlen(filename) + 2; 7790 complen = stringlen + sizeof (struct xattr_buf); 7791 7792 len += stringlen; 7793 7794 /* 7795 * Now add on space for link info if any 7796 */ 7797 7798 if (linkinfo != NULL) { 7799 /* 7800 * Again add space for two nulls 7801 */ 7802 linkstringlen = strlen(linkinfo->pathname) + 7803 strlen(linkinfo->attrname) + 2; 7804 linklen = linkstringlen + sizeof (struct xattr_buf); 7805 len += linklen; 7806 } else { 7807 linklen = 0; 7808 } 7809 7810 /* 7811 * Now add padding to end to fill out TBLOCK 7812 * 7813 * Function returns size of real data and not size + padding. 7814 */ 7815 7816 totalen = ROUNDTOTBLOCK(len); 7817 7818 if ((bufhead = calloc(1, totalen)) == NULL) { 7819 fatal(gettext("Out of memory.")); 7820 } 7821 7822 7823 /* 7824 * Now we can fill in the necessary pieces 7825 */ 7826 7827 /* 7828 * first fill in the fixed header 7829 */ 7830 hptr = (struct xattr_hdr *)bufhead; 7831 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 7832 (void) sprintf(hptr->h_component_len, "%0*d", 7833 sizeof (hptr->h_component_len) - 1, complen); 7834 (void) sprintf(hptr->h_link_component_len, "%0*d", 7835 sizeof (hptr->h_link_component_len) - 1, linklen); 7836 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 7837 7838 /* 7839 * Now fill in the filename + attrnames section 7840 * The filename and attrnames section can be composed of two or more 7841 * path segments separated by a null character. The first segment 7842 * is the path to the parent file that roots the entire sequence in 7843 * the normal name space. The remaining segments describes a path 7844 * rooted at the hidden extended attribute directory of the leaf file of 7845 * the previous segment, making it possible to name attributes on 7846 * attributes. Thus, if we are just archiving an extended attribute, 7847 * the second segment will contain the attribute name. If we are 7848 * archiving a system attribute of an extended attribute, then the 7849 * second segment will contain the attribute name, and a third segment 7850 * will contain the system attribute name. The attribute pathing 7851 * information is obtained from 'attrpath'. 7852 */ 7853 7854 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 7855 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 7856 stringlen); 7857 (void) strcpy(tptr->h_names, filename); 7858 attrnames_index = strlen(filename) + 1; 7859 (void) strcpy(&tptr->h_names[attrnames_index], attrpath); 7860 tptr->h_typeflag = typeflag; 7861 7862 /* 7863 * Split the attrnames section into two segments if 'attrpath' 7864 * contains pathing information for a system attribute of an 7865 * extended attribute. We split them by replacing the '/' with 7866 * a '\0'. 7867 */ 7868 if ((aptr = strpbrk(&tptr->h_names[attrnames_index], "/")) != NULL) { 7869 *aptr = '\0'; 7870 } 7871 7872 /* 7873 * Now fill in the optional link section if we have one 7874 */ 7875 7876 if (linkinfo != (struct linkbuf *)NULL) { 7877 tptr = (struct xattr_buf *)(bufhead + 7878 sizeof (struct xattr_hdr) + complen); 7879 7880 (void) sprintf(tptr->h_namesz, "%0*d", 7881 sizeof (tptr->h_namesz) - 1, linkstringlen); 7882 (void) strcpy(tptr->h_names, linkinfo->pathname); 7883 (void) strcpy( 7884 &tptr->h_names[strlen(linkinfo->pathname) + 1], 7885 linkinfo->attrname); 7886 tptr->h_typeflag = typeflag; 7887 } 7888 *attrbuf = (char *)bufhead; 7889 *rlen = len; 7890 } 7891 7892 #else 7893 static void 7894 prepare_xattr( 7895 char **attrbuf, 7896 char *filename, 7897 char *attrname, 7898 char typeflag, 7899 struct linkbuf *linkinfo, 7900 int *rlen) 7901 { 7902 *attrbuf = NULL; 7903 *rlen = 0; 7904 } 7905 #endif 7906 7907 int 7908 getstat(int dirfd, char *longname, char *shortname, char *attrparent) 7909 { 7910 7911 int i, j; 7912 int printerr; 7913 int slnkerr; 7914 struct stat symlnbuf; 7915 7916 if (!hflag) 7917 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 7918 else 7919 i = fstatat(dirfd, shortname, &stbuf, 0); 7920 7921 if (i < 0) { 7922 /* Initialize flag to print error mesg. */ 7923 printerr = 1; 7924 /* 7925 * If stat is done, then need to do lstat 7926 * to determine whether it's a sym link 7927 */ 7928 if (hflag) { 7929 /* Save returned error */ 7930 slnkerr = errno; 7931 7932 j = fstatat(dirfd, shortname, 7933 &symlnbuf, AT_SYMLINK_NOFOLLOW); 7934 /* 7935 * Suppress error message when file is a symbolic link 7936 * and function modifier 'l' is off. Exception: when 7937 * a symlink points to a symlink points to a 7938 * symlink ... and we get past MAXSYMLINKS. That 7939 * error will cause a file not to be archived, and 7940 * needs to be printed. 7941 */ 7942 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 7943 (S_ISLNK(symlnbuf.st_mode))) 7944 printerr = 0; 7945 7946 /* 7947 * Restore errno in case the lstat 7948 * on symbolic link change 7949 */ 7950 errno = slnkerr; 7951 } 7952 7953 if (printerr) { 7954 (void) fprintf(stderr, gettext( 7955 "tar: %s%s%s%s: %s\n"), 7956 (attrparent == NULL) ? "" : gettext("attribute "), 7957 (attrparent == NULL) ? "" : attrparent, 7958 (attrparent == NULL) ? "" : gettext(" of "), 7959 longname, strerror(errno)); 7960 Errflg = 1; 7961 } 7962 return (1); 7963 } 7964 return (0); 7965 } 7966 7967 /* 7968 * Recursively archive the extended attributes and/or extended system attributes 7969 * of the base file, longname. Note: extended system attribute files will be 7970 * archived only if the extended system attributes are not transient (i.e. the 7971 * extended system attributes are other than the default values). 7972 * 7973 * If -@ was specified and the underlying file system supports it, archive the 7974 * extended attributes, and if there is a system attribute associated with the 7975 * extended attribute, then recursively call xattrs_put() to archive the 7976 * hidden attribute directory and the extended system attribute. If -/ was 7977 * specified and the underlying file system supports it, archive the extended 7978 * system attributes. Read-only extended system attributes are never archived. 7979 * 7980 * Currently, there cannot be attributes on attributes; only system 7981 * attributes on attributes. In addition, there cannot be attributes on 7982 * system attributes. A file and it's attribute directory hierarchy looks as 7983 * follows: 7984 * longname ----> . ("." is the hidden attribute directory) 7985 * | 7986 * ---------------------------- 7987 * | | 7988 * <sys_attr_name> <attr_name> ----> . 7989 * | 7990 * <sys_attr_name> 7991 * 7992 */ 7993 #if defined(O_XATTR) 7994 static void 7995 xattrs_put(char *longname, char *shortname, char *parent, char *attrparent) 7996 { 7997 char *filename = (attrparent == NULL) ? shortname : attrparent; 7998 int arc_rwsysattr = 0; 7999 int dirfd; 8000 int fd = -1; 8001 int rw_sysattr = 0; 8002 int ext_attr = 0; 8003 int rc; 8004 DIR *dirp; 8005 struct dirent *dp; 8006 attr_data_t *attrinfo = NULL; 8007 8008 /* 8009 * If the underlying file system supports it, then archive the extended 8010 * attributes if -@ was specified, and the extended system attributes 8011 * if -/ was specified. 8012 */ 8013 if (verify_attr_support(filename, (attrparent == NULL), ARC_CREATE, 8014 &ext_attr) != ATTR_OK) { 8015 return; 8016 } 8017 8018 /* 8019 * Only want to archive a read-write extended system attribute file 8020 * if it contains extended system attribute settings that are not the 8021 * default values. 8022 */ 8023 #if defined(_PC_SATTR_ENABLED) 8024 if (saflag) { 8025 int filefd; 8026 nvlist_t *slist = NULL; 8027 8028 /* Determine if there are non-transient system attributes */ 8029 errno = 0; 8030 if ((filefd = open(filename, O_RDONLY)) == -1) { 8031 if (attrparent == NULL) { 8032 vperror(0, gettext( 8033 "unable to open file %s"), longname); 8034 } 8035 return; 8036 } 8037 if (((slist = sysattr_list(basename(myname), filefd, 8038 filename)) != NULL) || (errno != 0)) { 8039 arc_rwsysattr = 1; 8040 } 8041 if (slist != NULL) { 8042 (void) nvlist_free(slist); 8043 slist = NULL; 8044 } 8045 (void) close(filefd); 8046 } 8047 8048 /* 8049 * If we aren't archiving extended system attributes, and we are 8050 * processing an attribute, or if we are archiving extended system 8051 * attributes, and there are are no extended attributes, then there's 8052 * no need to open up the attribute directory of the file unless the 8053 * extended system attributes are not transient (i.e, the system 8054 * attributes are not the default values). 8055 */ 8056 if ((arc_rwsysattr == 0) && ((attrparent != NULL) || 8057 (saflag && !ext_attr))) { 8058 return; 8059 } 8060 #endif /* _PC_SATTR_ENABLED */ 8061 8062 /* open the parent attribute directory */ 8063 fd = attropen(filename, ".", O_RDONLY); 8064 if (fd < 0) { 8065 vperror(0, gettext( 8066 "unable to open attribute directory for %s%s%sfile %s"), 8067 (attrparent == NULL) ? "" : gettext("attribute "), 8068 (attrparent == NULL) ? "" : attrparent, 8069 (attrparent == NULL) ? "" : gettext(" of "), 8070 longname); 8071 return; 8072 } 8073 8074 /* 8075 * We need to change into the parent's attribute directory to determine 8076 * if each of the attributes should be archived. 8077 */ 8078 if (fchdir(fd) < 0) { 8079 vperror(0, gettext( 8080 "cannot change to attribute directory of %s%s%sfile %s"), 8081 (attrparent == NULL) ? "" : gettext("attribute "), 8082 (attrparent == NULL) ? "" : attrparent, 8083 (attrparent == NULL) ? "" : gettext(" of "), 8084 longname); 8085 (void) close(fd); 8086 return; 8087 } 8088 8089 if (((dirfd = dup(fd)) == -1) || 8090 ((dirp = fdopendir(dirfd)) == NULL)) { 8091 (void) fprintf(stderr, gettext( 8092 "tar: unable to open dir pointer for %s%s%sfile %s\n"), 8093 (attrparent == NULL) ? "" : gettext("attribute "), 8094 (attrparent == NULL) ? "" : attrparent, 8095 (attrparent == NULL) ? "" : gettext(" of "), 8096 longname); 8097 if (fd > 0) { 8098 (void) close(fd); 8099 } 8100 return; 8101 } 8102 8103 while (dp = readdir(dirp)) { 8104 if (strcmp(dp->d_name, "..") == 0) { 8105 continue; 8106 } else if (strcmp(dp->d_name, ".") == 0) { 8107 Hiddendir = 1; 8108 } else { 8109 Hiddendir = 0; 8110 } 8111 8112 /* Determine if this attribute should be archived */ 8113 if (verify_attr(dp->d_name, attrparent, arc_rwsysattr, 8114 &rw_sysattr) != ATTR_OK) { 8115 continue; 8116 } 8117 8118 /* gather the attribute's information to pass to putfile() */ 8119 if ((fill_in_attr_info(dp->d_name, longname, attrparent, 8120 fd, rw_sysattr, &attrinfo)) == 1) { 8121 continue; 8122 } 8123 8124 /* add the attribute to the archive */ 8125 rc = putfile(longname, dp->d_name, parent, attrinfo, 8126 XATTR_FILE, LEV0, SYMLINK_LEV0); 8127 8128 if (exitflag) { 8129 break; 8130 } 8131 8132 #if defined(_PC_SATTR_ENABLED) 8133 /* 8134 * If both -/ and -@ were specified, then archive the 8135 * attribute's extended system attributes and hidden directory 8136 * by making a recursive call to xattrs_put(). 8137 */ 8138 if (!rw_sysattr && saflag && atflag && (rc != PUT_AS_LINK) && 8139 (Hiddendir == 0)) { 8140 8141 xattrs_put(longname, shortname, parent, dp->d_name); 8142 8143 /* 8144 * Change back to the parent's attribute directory 8145 * to process any further attributes. 8146 */ 8147 if (fchdir(fd) < 0) { 8148 vperror(0, gettext( 8149 "cannot change back to attribute directory " 8150 "of file %s"), longname); 8151 break; 8152 } 8153 } 8154 #endif /* _PC_SATTR_ENABLED */ 8155 } 8156 8157 if (attrinfo != NULL) { 8158 if (attrinfo->attr_parent != NULL) { 8159 free(attrinfo->attr_parent); 8160 } 8161 free(attrinfo->attr_path); 8162 free(attrinfo); 8163 } 8164 (void) closedir(dirp); 8165 if (fd != -1) { 8166 (void) close(fd); 8167 } 8168 8169 /* Change back to the parent directory of the base file */ 8170 if (attrparent == NULL) { 8171 (void) chdir(parent); 8172 } 8173 Hiddendir = 0; 8174 } 8175 #else 8176 static void 8177 xattrs_put(char *longname, char *shortname, char *parent, char *attrppath) 8178 { 8179 } 8180 #endif /* O_XATTR */ 8181 8182 static int 8183 put_link(char *name, char *longname, char *component, char *longattrname, 8184 char *prefix, int filetype, char type) 8185 { 8186 8187 if (stbuf.st_nlink > 1) { 8188 struct linkbuf *lp; 8189 int found = 0; 8190 8191 for (lp = ihead; lp != NULL; lp = lp->nextp) 8192 if (lp->inum == stbuf.st_ino && 8193 lp->devnum == stbuf.st_dev) { 8194 found++; 8195 break; 8196 } 8197 if (found) { 8198 #if defined(O_XATTR) 8199 if (filetype == XATTR_FILE) 8200 if (put_xattr_hdr(longname, component, 8201 longattrname, prefix, type, filetype, lp)) { 8202 goto out; 8203 } 8204 #endif 8205 stbuf.st_size = (off_t)0; 8206 if (filetype != XATTR_FILE) { 8207 tomodes(&stbuf); 8208 if (chk_path_build(name, longname, lp->pathname, 8209 prefix, type, filetype) > 0) { 8210 goto out; 8211 } 8212 } 8213 8214 if (mulvol && tapepos + 1 >= blocklim) 8215 newvol(); 8216 (void) writetbuf((char *)&dblock, 1); 8217 /* 8218 * write_ancillary() is not needed here. 8219 * The first link is handled in the following 8220 * else statement. No need to process ACLs 8221 * for other hard links since they are the 8222 * same file. 8223 */ 8224 8225 if (vflag) { 8226 #ifdef DEBUG 8227 if (NotTape) 8228 DEBUG("seek = %" FMT_blkcnt_t 8229 "K\t", K(tapepos), 0); 8230 #endif 8231 if (filetype == XATTR_FILE) { 8232 (void) fprintf(vfile, gettext( 8233 "a %s attribute %s link to " 8234 "%s attribute %s\n"), 8235 name, component, name, 8236 lp->attrname); 8237 } else { 8238 (void) fprintf(vfile, gettext( 8239 "a %s link to %s\n"), 8240 longname, lp->pathname); 8241 } 8242 } 8243 lp->count--; 8244 return (0); 8245 } else { 8246 lp = (struct linkbuf *)getmem(sizeof (*lp)); 8247 if (lp != (struct linkbuf *)NULL) { 8248 lp->nextp = ihead; 8249 ihead = lp; 8250 lp->inum = stbuf.st_ino; 8251 lp->devnum = stbuf.st_dev; 8252 lp->count = stbuf.st_nlink - 1; 8253 if (filetype == XATTR_FILE) { 8254 (void) strcpy(lp->pathname, longname); 8255 (void) strcpy(lp->attrname, 8256 component); 8257 } else { 8258 (void) strcpy(lp->pathname, longname); 8259 (void) strcpy(lp->attrname, ""); 8260 } 8261 } 8262 } 8263 } 8264 8265 out: 8266 return (1); 8267 } 8268 8269 static int 8270 put_extra_attributes(char *longname, char *shortname, char *longattrname, 8271 char *prefix, int filetype, char typeflag) 8272 { 8273 static acl_t *aclp = NULL; 8274 int error; 8275 8276 if (aclp != NULL) { 8277 acl_free(aclp); 8278 aclp = NULL; 8279 } 8280 #if defined(O_XATTR) 8281 if ((atflag || saflag) && (filetype == XATTR_FILE)) { 8282 if (put_xattr_hdr(longname, shortname, longattrname, prefix, 8283 typeflag, filetype, NULL)) { 8284 return (1); 8285 } 8286 } 8287 #endif 8288 8289 /* ACL support */ 8290 if (pflag) { 8291 char *secinfo = NULL; 8292 int len = 0; 8293 8294 /* ACL support */ 8295 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 8296 /* 8297 * Get ACL info: dont bother allocating space if 8298 * there is only a trivial ACL. 8299 */ 8300 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 8301 &aclp)) != 0) { 8302 (void) fprintf(stderr, gettext( 8303 "%s: failed to retrieve acl : %s\n"), 8304 longname, acl_strerror(error)); 8305 return (1); 8306 } 8307 } 8308 8309 /* append security attributes if any */ 8310 if (aclp != NULL) { 8311 (void) append_secattr(&secinfo, &len, acl_cnt(aclp), 8312 acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT | 8313 ACL_SID_FMT), (acl_type(aclp) == ACLENT_T) ? 8314 UFSD_ACL : ACE_ACL); 8315 } 8316 8317 if (Tflag) { 8318 /* append Trusted Extensions extended attributes */ 8319 append_ext_attr(shortname, &secinfo, &len); 8320 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8321 8322 } else if (aclp != NULL) { 8323 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8324 } 8325 } 8326 return (0); 8327 } 8328 8329 #if defined(O_XATTR) 8330 static int 8331 put_xattr_hdr(char *longname, char *shortname, char *longattrname, char *prefix, 8332 int typeflag, int filetype, struct linkbuf *lp) 8333 { 8334 char *lname = NULL; 8335 char *sname = NULL; 8336 int error = 0; 8337 static char *attrbuf = NULL; 8338 int attrlen; 8339 8340 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 8341 strlen(shortname) + strlen(".hdr") + 1); 8342 8343 if (lname == NULL) { 8344 fatal(gettext("Out of Memory.")); 8345 } 8346 sname = malloc(sizeof (char) * strlen(shortname) + 8347 strlen(".hdr") + 1); 8348 if (sname == NULL) { 8349 fatal(gettext("Out of Memory.")); 8350 } 8351 8352 (void) sprintf(sname, "%s.hdr", shortname); 8353 (void) sprintf(lname, "/dev/null/%s", sname); 8354 8355 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 8356 sizeof (dblock.dbuf.name)) { 8357 fatal(gettext( 8358 "Buffer overflow writing extended attribute file name")); 8359 } 8360 8361 /* 8362 * dump extended attr lookup info 8363 */ 8364 prepare_xattr(&attrbuf, longname, longattrname, typeflag, lp, &attrlen); 8365 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 8366 8367 (void) sprintf(lname, "/dev/null/%s", shortname); 8368 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 8369 8370 /* 8371 * Set up filename for attribute 8372 */ 8373 8374 error = build_dblock(lname, tchar, '0', filetype, 8375 &stbuf, stbuf.st_dev, prefix); 8376 free(lname); 8377 free(sname); 8378 8379 return (error); 8380 } 8381 #endif 8382 8383 #if defined(O_XATTR) 8384 static int 8385 read_xattr_hdr(attr_data_t **attrinfo) 8386 { 8387 char buf[TBLOCK]; 8388 char *attrparent = NULL; 8389 blkcnt_t blocks; 8390 char *tp; 8391 off_t bytes; 8392 int comp_len, link_len; 8393 int namelen; 8394 int attrparentlen; 8395 int parentfilelen; 8396 8397 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 8398 return (1); 8399 8400 bytes = stbuf.st_size; 8401 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 8402 (void) fprintf(stderr, gettext( 8403 "Insufficient memory for extended attribute\n")); 8404 return (1); 8405 } 8406 8407 tp = (char *)xattrhead; 8408 blocks = TBLOCKS(bytes); 8409 while (blocks-- > 0) { 8410 readtape(buf); 8411 if (bytes <= TBLOCK) { 8412 (void) memcpy(tp, buf, (size_t)bytes); 8413 break; 8414 } else { 8415 (void) memcpy(tp, buf, TBLOCK); 8416 tp += TBLOCK; 8417 } 8418 bytes -= TBLOCK; 8419 } 8420 8421 /* 8422 * Validate that we can handle header format 8423 */ 8424 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 8425 (void) fprintf(stderr, 8426 gettext("Unknown extended attribute format encountered\n")); 8427 (void) fprintf(stderr, 8428 gettext("Disabling extended attribute parsing\n")); 8429 xattrbadhead = 1; 8430 return (0); 8431 } 8432 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 8433 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 8434 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 8435 sizeof (struct xattr_hdr)); 8436 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 8437 if (link_len > 0) 8438 xattr_linkp = (struct xattr_buf *) 8439 ((int)xattrp + (int)comp_len); 8440 else 8441 xattr_linkp = NULL; 8442 8443 /* 8444 * Gather the attribute path from the filename and attrnames section. 8445 * The filename and attrnames section can be composed of two or more 8446 * path segments separated by a null character. The first segment 8447 * is the path to the parent file that roots the entire sequence in 8448 * the normal name space. The remaining segments describes a path 8449 * rooted at the hidden extended attribute directory of the leaf file of 8450 * the previous segment, making it possible to name attributes on 8451 * attributes. 8452 */ 8453 parentfilelen = strlen(xattrp->h_names); 8454 xattrapath = xattrp->h_names + parentfilelen + 1; 8455 if ((strlen(xattrapath) + parentfilelen + 2) < namelen) { 8456 /* 8457 * The attrnames section contains a system attribute on an 8458 * attribute. Save the name of the attribute for use later, 8459 * and replace the null separating the attribute name from 8460 * the system attribute name with a '/' so that xattrapath can 8461 * be used to display messages with the full attribute path name 8462 * rooted at the hidden attribute directory of the base file 8463 * in normal name space. 8464 */ 8465 attrparent = strdup(xattrapath); 8466 attrparentlen = strlen(attrparent); 8467 xattrapath[attrparentlen] = '/'; 8468 } 8469 if ((fill_in_attr_info((attrparent == NULL) ? xattrapath : 8470 xattrapath + attrparentlen + 1, xattrapath, attrparent, 8471 -1, 0, attrinfo)) == 1) { 8472 free(attrparent); 8473 return (1); 8474 } 8475 8476 /* Gather link info */ 8477 if (xattr_linkp) { 8478 xattr_linkaname = xattr_linkp->h_names + 8479 strlen(xattr_linkp->h_names) + 1; 8480 } else { 8481 xattr_linkaname = NULL; 8482 } 8483 8484 return (0); 8485 } 8486 #else 8487 static int 8488 read_xattr_hdr(attr_data_t **attrinfo) 8489 { 8490 return (0); 8491 } 8492 #endif 8493 8494 /* 8495 * skip over extra slashes in string. 8496 * 8497 * For example: 8498 * /usr/tmp///// 8499 * 8500 * would return pointer at 8501 * /usr/tmp///// 8502 * ^ 8503 */ 8504 static char * 8505 skipslashes(char *string, char *start) 8506 { 8507 while ((string > start) && *(string - 1) == '/') { 8508 string--; 8509 } 8510 8511 return (string); 8512 } 8513 8514 /* 8515 * Return the parent directory of a given path. 8516 * 8517 * Examples: 8518 * /usr/tmp return /usr 8519 * /usr/tmp/file return /usr/tmp 8520 * / returns . 8521 * /usr returns / 8522 * file returns . 8523 * 8524 * dir is assumed to be at least as big as path. 8525 */ 8526 static void 8527 get_parent(char *path, char *dir) 8528 { 8529 char *s; 8530 char tmpdir[PATH_MAX + 1]; 8531 8532 if (strlen(path) > PATH_MAX) { 8533 fatal(gettext("pathname is too long")); 8534 } 8535 (void) strcpy(tmpdir, path); 8536 chop_endslashes(tmpdir); 8537 8538 if ((s = strrchr(tmpdir, '/')) == NULL) { 8539 (void) strcpy(dir, "."); 8540 } else { 8541 s = skipslashes(s, tmpdir); 8542 *s = '\0'; 8543 if (s == tmpdir) 8544 (void) strcpy(dir, "/"); 8545 else 8546 (void) strcpy(dir, tmpdir); 8547 } 8548 } 8549 8550 #if defined(O_XATTR) 8551 static char * 8552 get_component(char *path) 8553 { 8554 char *ptr; 8555 8556 ptr = strrchr(path, '/'); 8557 if (ptr == NULL) { 8558 return (path); 8559 } else { 8560 /* 8561 * Handle trailing slash 8562 */ 8563 if (*(ptr + 1) == '\0') 8564 return (ptr); 8565 else 8566 return (ptr + 1); 8567 } 8568 } 8569 #else 8570 static char * 8571 get_component(char *path) 8572 { 8573 return (path); 8574 } 8575 #endif 8576 8577 #if defined(O_XATTR) 8578 static int 8579 retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, char *name, 8580 int oflag, mode_t mode) 8581 { 8582 int dirfd; 8583 int ofilefd = -1; 8584 struct timeval times[2]; 8585 mode_t newmode; 8586 struct stat parentstat; 8587 acl_t *aclp = NULL; 8588 int error; 8589 8590 /* 8591 * We couldn't get to attrdir. See if its 8592 * just a mode problem on the parent file. 8593 * for example: a mode such as r-xr--r-- 8594 * on a ufs file system without extended 8595 * system attribute support won't let us 8596 * create an attribute dir if it doesn't 8597 * already exist, and on a ufs file system 8598 * with extended system attribute support 8599 * won't let us open the attribute for 8600 * write. 8601 * 8602 * If file has a non-trivial ACL, then save it 8603 * off so that we can place it back on after doing 8604 * chmod's. 8605 */ 8606 if ((dirfd = openat(cwd, (pattr == NULL) ? dirp : pattr, 8607 O_RDONLY)) == -1) { 8608 return (-1); 8609 } 8610 if (fstat(dirfd, &parentstat) == -1) { 8611 (void) fprintf(stderr, gettext( 8612 "tar: cannot stat %sfile %s: %s\n"), 8613 (pdirfd == -1) ? "" : gettext("parent of "), 8614 (pdirfd == -1) ? dirp : name, strerror(errno)); 8615 return (-1); 8616 } 8617 if ((error = facl_get(dirfd, ACL_NO_TRIVIAL, &aclp)) != 0) { 8618 (void) fprintf(stderr, gettext( 8619 "tar: failed to retrieve ACL on %sfile %s: %s\n"), 8620 (pdirfd == -1) ? "" : gettext("parent of "), 8621 (pdirfd == -1) ? dirp : name, strerror(errno)); 8622 return (-1); 8623 } 8624 8625 newmode = S_IWUSR | parentstat.st_mode; 8626 if (fchmod(dirfd, newmode) == -1) { 8627 (void) fprintf(stderr, 8628 gettext( 8629 "tar: cannot fchmod %sfile %s to %o: %s\n"), 8630 (pdirfd == -1) ? "" : gettext("parent of "), 8631 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8632 if (aclp) 8633 acl_free(aclp); 8634 return (-1); 8635 } 8636 8637 8638 if (pdirfd == -1) { 8639 /* 8640 * We weren't able to create the attribute directory before. 8641 * Now try again. 8642 */ 8643 ofilefd = attropen(dirp, ".", oflag); 8644 } else { 8645 /* 8646 * We weren't able to create open the attribute before. 8647 * Now try again. 8648 */ 8649 ofilefd = openat(pdirfd, name, oflag, mode); 8650 } 8651 8652 /* 8653 * Put mode back to original 8654 */ 8655 if (fchmod(dirfd, parentstat.st_mode) == -1) { 8656 (void) fprintf(stderr, 8657 gettext("tar: cannot chmod %sfile %s to %o: %s\n"), 8658 (pdirfd == -1) ? "" : gettext("parent of "), 8659 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8660 } 8661 8662 if (aclp) { 8663 error = facl_set(dirfd, aclp); 8664 if (error) { 8665 (void) fprintf(stderr, 8666 gettext("tar: failed to set acl entries on " 8667 "%sfile %s\n"), 8668 (pdirfd == -1) ? "" : gettext("parent of "), 8669 (pdirfd == -1) ? dirp : name); 8670 } 8671 acl_free(aclp); 8672 } 8673 8674 /* 8675 * Put back time stamps 8676 */ 8677 8678 times[0].tv_sec = parentstat.st_atime; 8679 times[0].tv_usec = 0; 8680 times[1].tv_sec = parentstat.st_mtime; 8681 times[1].tv_usec = 0; 8682 8683 (void) futimesat(cwd, (pattr == NULL) ? dirp : pattr, times); 8684 8685 (void) close(dirfd); 8686 8687 return (ofilefd); 8688 } 8689 #endif 8690 8691 #if !defined(O_XATTR) 8692 static int 8693 openat64(int fd, const char *name, int oflag, mode_t cmode) 8694 { 8695 return (open64(name, oflag, cmode)); 8696 } 8697 8698 static int 8699 openat(int fd, const char *name, int oflag, mode_t cmode) 8700 { 8701 return (open(name, oflag, cmode)); 8702 } 8703 8704 static int 8705 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 8706 { 8707 if (flag == AT_SYMLINK_NOFOLLOW) 8708 return (lchown(name, owner, group)); 8709 else 8710 return (chown(name, owner, group)); 8711 } 8712 8713 static int 8714 renameat(int fromfd, char *old, int tofd, char *new) 8715 { 8716 return (rename(old, new)); 8717 } 8718 8719 static int 8720 futimesat(int fd, char *path, struct timeval times[2]) 8721 { 8722 return (utimes(path, times)); 8723 } 8724 8725 static int 8726 unlinkat(int dirfd, char *path, int flag) 8727 { 8728 if (flag == AT_REMOVEDIR) 8729 return (rmdir(path)); 8730 else 8731 return (unlink(path)); 8732 } 8733 8734 static int 8735 fstatat(int fd, char *path, struct stat *buf, int flag) 8736 { 8737 if (flag == AT_SYMLINK_NOFOLLOW) 8738 return (lstat(path, buf)); 8739 else 8740 return (stat(path, buf)); 8741 } 8742 8743 static int 8744 attropen(char *file, char *attr, int omode, mode_t cmode) 8745 { 8746 errno = ENOTSUP; 8747 return (-1); 8748 } 8749 #endif 8750 8751 static void 8752 chop_endslashes(char *path) 8753 { 8754 char *end, *ptr; 8755 8756 /* 8757 * Chop of slashes, but not if all we have is slashes 8758 * for example: //// 8759 * should make no changes, otherwise it will screw up 8760 * checkdir 8761 */ 8762 end = &path[strlen(path) -1]; 8763 if (*end == '/' && end != path) { 8764 ptr = skipslashes(end, path); 8765 if (ptr != NULL && ptr != path) { 8766 *ptr = '\0'; 8767 } 8768 } 8769 } 8770 /* Trusted Extensions */ 8771 8772 /* 8773 * append_ext_attr(): 8774 * 8775 * Append extended attributes and other information into the buffer 8776 * that gets written to the ancillary file. 8777 * 8778 * With option 'T', we create a tarfile which 8779 * has an ancillary file each corresponding archived file. 8780 * Each ancillary file contains 1 or more of the 8781 * following attributes: 8782 * 8783 * attribute type attribute process procedure 8784 * ---------------- ---------------- -------------------------- 8785 * DIR_TYPE = 'D' directory flag append if a directory 8786 * LBL_TYPE = 'L' SL[IL] or SL append ascii label 8787 * 8788 * 8789 */ 8790 static void 8791 append_ext_attr(char *shortname, char **secinfo, int *len) 8792 { 8793 bslabel_t b_slabel; /* binary sensitvity label */ 8794 char *ascii = NULL; /* ascii label */ 8795 8796 /* 8797 * For each attribute type, append it if it is 8798 * relevant to the file type. 8799 */ 8800 8801 /* 8802 * For attribute type DIR_TYPE, 8803 * append it to the following file type: 8804 * 8805 * S_IFDIR: directories 8806 */ 8807 8808 /* 8809 * For attribute type LBL_TYPE, 8810 * append it to the following file type: 8811 * 8812 * S_IFDIR: directories (including mld, sld) 8813 * S_IFLNK: symbolic link 8814 * S_IFREG: regular file but not hard link 8815 * S_IFIFO: FIFO file but not hard link 8816 * S_IFCHR: char special file but not hard link 8817 * S_IFBLK: block special file but not hard link 8818 */ 8819 switch (stbuf.st_mode & S_IFMT) { 8820 8821 case S_IFDIR: 8822 8823 /* 8824 * append DIR_TYPE 8825 */ 8826 (void) append_secattr(secinfo, len, 1, 8827 "\0", DIR_TYPE); 8828 8829 /* 8830 * Get and append attribute types LBL_TYPE. 8831 * For directories, LBL_TYPE contains SL. 8832 */ 8833 /* get binary sensitivity label */ 8834 if (getlabel(shortname, &b_slabel) != 0) { 8835 (void) fprintf(stderr, 8836 gettext("tar: can't get sensitvity label for " 8837 " %s, getlabel() error: %s\n"), 8838 shortname, strerror(errno)); 8839 } else { 8840 /* get ascii SL */ 8841 if (bsltos(&b_slabel, &ascii, 8842 0, 0) <= 0) { 8843 (void) fprintf(stderr, 8844 gettext("tar: can't get ascii SL for" 8845 " %s\n"), shortname); 8846 } else { 8847 /* append LBL_TYPE */ 8848 (void) append_secattr(secinfo, len, 8849 strlen(ascii) + 1, ascii, 8850 LBL_TYPE); 8851 8852 /* free storage */ 8853 if (ascii != NULL) { 8854 free(ascii); 8855 ascii = (char *)0; 8856 } 8857 } 8858 8859 } 8860 break; 8861 8862 case S_IFLNK: 8863 case S_IFREG: 8864 case S_IFIFO: 8865 case S_IFCHR: 8866 case S_IFBLK: 8867 8868 /* get binary sensitivity label */ 8869 if (getlabel(shortname, &b_slabel) != 0) { 8870 (void) fprintf(stderr, 8871 gettext("tar: can't get sensitivty label for %s, " 8872 "getlabel() error: %s\n"), 8873 shortname, strerror(errno)); 8874 } else { 8875 /* get ascii IL[SL] */ 8876 if (bsltos(&b_slabel, &ascii, 0, 0) <= 0) { 8877 (void) fprintf(stderr, 8878 gettext("tar: can't translate sensitivity " 8879 " label for %s\n"), shortname); 8880 } else { 8881 char *cmw_label; 8882 size_t cmw_length; 8883 8884 cmw_length = strlen("ADMIN_LOW [] ") + 8885 strlen(ascii); 8886 if ((cmw_label = malloc(cmw_length)) == NULL) { 8887 (void) fprintf(stderr, gettext( 8888 "Insufficient memory for label\n")); 8889 exit(1); 8890 } 8891 /* append LBL_TYPE */ 8892 (void) snprintf(cmw_label, cmw_length, 8893 "ADMIN_LOW [%s]", ascii); 8894 (void) append_secattr(secinfo, len, 8895 strlen(cmw_label) + 1, cmw_label, 8896 LBL_TYPE); 8897 8898 /* free storage */ 8899 if (ascii != NULL) { 8900 free(cmw_label); 8901 free(ascii); 8902 ascii = (char *)0; 8903 } 8904 } 8905 } 8906 break; 8907 8908 default: 8909 break; 8910 } /* end switch for LBL_TYPE */ 8911 8912 8913 /* DONE !! */ 8914 return; 8915 8916 } /* end of append_ext_attr */ 8917 8918 8919 /* 8920 * Name: extract_attr() 8921 * 8922 * Description: 8923 * Process attributes from the ancillary file due to 8924 * the T option. 8925 * 8926 * Call by doxtract() as part of the switch case structure. 8927 * Making this a separate routine because the nesting are too 8928 * deep in doxtract, thus, leaving very little space 8929 * on each line for instructions. 8930 * 8931 * With option 'T', we extract from a TS 8 or TS 2.5 ancillary file 8932 * 8933 * For option 'T', following are possible attributes in 8934 * a TS 8 ancillary file: (NOTE: No IL support) 8935 * 8936 * attribute type attribute process procedure 8937 * ---------------- ---------------- ------------------------- 8938 * # LBL_TYPE = 'L' SL construct binary label 8939 * # APRIV_TYPE = 'P' allowed priv construct privileges 8940 * # FPRIV_TYPE = 'p' forced priv construct privileges 8941 * # COMP_TYPE = 'C' path component construct real path 8942 * # DIR_TYPE = 'D' directory flag note it is a directory 8943 * $ UFSD_ACL = '1' ACL data construct ACL entries 8944 * ATTR_FLAG_TYPE = 'F' file attr flags construct binary flags 8945 * LK_COMP_TYPE = 'K' linked path comp construct linked real path 8946 * 8947 * note: # = attribute names common between TS 8 & TS 2.5 ancillary 8948 * files. 8949 * $ = ACL attribute is processed for the option 'p', it doesn't 8950 * need option 'T'. 8951 * 8952 * Trusted Extensions ignores APRIV_TYPE, FPRIV_TYPE, and ATTR_FLAG_TYPE 8953 * 8954 */ 8955 static void 8956 extract_attr(char **file_ptr, struct sec_attr *attr) 8957 { 8958 int reterr, err; 8959 char *dummy_buf; /* for attribute extract */ 8960 8961 dummy_buf = attr->attr_info; 8962 8963 switch (attr->attr_type) { 8964 8965 case DIR_TYPE: 8966 8967 dir_flag++; 8968 break; 8969 8970 case LBL_TYPE: 8971 8972 /* 8973 * LBL_TYPE is used to indicate SL for directory, and 8974 * CMW label for other file types. 8975 */ 8976 8977 if (!dir_flag) { /* not directory */ 8978 /* Skip over IL portion */ 8979 char *sl_ptr = strchr(dummy_buf, '['); 8980 8981 if (sl_ptr == NULL) 8982 err = 0; 8983 else 8984 err = stobsl(sl_ptr, &bs_label, 8985 NEW_LABEL, &reterr); 8986 } else { /* directory */ 8987 err = stobsl(dummy_buf, &bs_label, 8988 NEW_LABEL, &reterr); 8989 } 8990 if (err == 0) { 8991 (void) fprintf(stderr, gettext("tar: " 8992 "can't convert %s to binary label\n"), 8993 dummy_buf); 8994 bslundef(&bs_label); 8995 } else if (!blequal(&bs_label, &admin_low) && 8996 !blequal(&bs_label, &admin_high)) { 8997 bslabel_t *from_label; 8998 char *buf; 8999 char tempbuf[MAXPATHLEN]; 9000 9001 if (*orig_namep != '/') { 9002 /* got relative linked to path */ 9003 (void) getcwd(tempbuf, (sizeof (tempbuf))); 9004 (void) strncat(tempbuf, "/", MAXPATHLEN); 9005 } else 9006 *tempbuf = '\0'; 9007 9008 buf = real_path; 9009 (void) strncat(tempbuf, orig_namep, MAXPATHLEN); 9010 from_label = getlabelbypath(tempbuf); 9011 if (from_label != NULL) { 9012 if (blequal(from_label, &admin_low)) { 9013 if ((getpathbylabel(tempbuf, buf, 9014 MAXPATHLEN, &bs_label) == NULL)) { 9015 (void) fprintf(stderr, 9016 gettext("tar: " 9017 "can't get zone root path for " 9018 "%s\n"), tempbuf); 9019 } else 9020 rpath_flag = 1; 9021 } 9022 free(from_label); 9023 } 9024 } 9025 break; 9026 9027 case COMP_TYPE: 9028 9029 rebuild_comp_path(dummy_buf, file_ptr); 9030 break; 9031 9032 case LK_COMP_TYPE: 9033 9034 if (rebuild_lk_comp_path(dummy_buf, file_ptr) 9035 == 0) { 9036 lk_rpath_flag = 1; 9037 } else { 9038 (void) fprintf(stderr, gettext("tar: warning: link's " 9039 "target pathname might be invalid.\n")); 9040 lk_rpath_flag = 0; 9041 } 9042 break; 9043 case APRIV_TYPE: 9044 ignored_aprivs++; 9045 break; 9046 case FPRIV_TYPE: 9047 ignored_fprivs++; 9048 break; 9049 case ATTR_FLAG_TYPE: 9050 ignored_fattrs++; 9051 break; 9052 9053 default: 9054 9055 break; 9056 } 9057 9058 /* done */ 9059 return; 9060 9061 } /* end extract_attr */ 9062 9063 9064 9065 /* 9066 * Name: rebuild_comp_path() 9067 * 9068 * Description: 9069 * Take the string of components passed down by the calling 9070 * routine and parse the values and rebuild the path. 9071 * This routine no longer needs to produce a new real_path 9072 * string because it is produced when the 'L' LABEL_TYPE is 9073 * interpreted. So the only thing done here is to distinguish 9074 * between an SLD and an MLD entry. We only want one, so we 9075 * ignore the MLD entry by setting the mld_flag. 9076 * 9077 * return value: 9078 * none 9079 */ 9080 static void 9081 rebuild_comp_path(char *str, char **namep) 9082 { 9083 char *cp; 9084 9085 while (*str != '\0') { 9086 9087 switch (*str) { 9088 9089 case MLD_TYPE: 9090 9091 str++; 9092 if ((cp = strstr(str, ";;")) != NULL) { 9093 *cp = '\0'; 9094 str = cp + 2; 9095 *cp = ';'; 9096 } 9097 mld_flag = 1; 9098 break; 9099 9100 case SLD_TYPE: 9101 9102 str++; 9103 if ((cp = strstr(str, ";;")) != NULL) { 9104 *cp = '\0'; 9105 str = cp + 2; 9106 *cp = ';'; 9107 } 9108 mld_flag = 0; 9109 break; 9110 9111 case PATH_TYPE: 9112 9113 str++; 9114 if ((cp = strstr(str, ";;")) != NULL) { 9115 *cp = '\0'; 9116 str = cp + 2; 9117 *cp = ';'; 9118 } 9119 break; 9120 } 9121 } 9122 if (rpath_flag) 9123 *namep = real_path; 9124 return; 9125 9126 } /* end rebuild_comp_path() */ 9127 9128 /* 9129 * Name: rebuild_lk_comp_path() 9130 * 9131 * Description: 9132 * Take the string of components passed down by the calling 9133 * routine and parse the values and rebuild the path. 9134 * 9135 * return value: 9136 * 0 = succeeded 9137 * -1 = failed 9138 */ 9139 static int 9140 rebuild_lk_comp_path(char *str, char **namep) 9141 { 9142 char *cp; 9143 int reterr; 9144 bslabel_t bslabel; 9145 char *buf; 9146 char pbuf[MAXPATHLEN]; 9147 char *ptr1, *ptr2; 9148 int plen; 9149 int use_pbuf; 9150 char tempbuf[MAXPATHLEN]; 9151 int mismatch; 9152 bslabel_t *from_label; 9153 char zonename[ZONENAME_MAX]; 9154 zoneid_t zoneid; 9155 9156 /* init stuff */ 9157 use_pbuf = 0; 9158 mismatch = 0; 9159 9160 /* 9161 * For linked to pathname (LK_COMP_TYPE): 9162 * - If the linked to pathname is absolute (start with /), we 9163 * will use it as is. 9164 * - If it is a relative pathname then it is relative to 1 of 2 9165 * directories. For a hardlink, it is relative to the current 9166 * directory. For a symbolic link, it is relative to the 9167 * directory the symbolic link is in. For the symbolic link 9168 * case, set a flag to indicate we need to use the prefix of 9169 * the restored file's pathname with the linked to pathname. 9170 * 9171 * NOTE: At this point, we have no way to determine if we have 9172 * a hardlink or a symbolic link. We will compare the 1st 9173 * component in the prefix portion of the restore file's 9174 * pathname to the 1st component in the attribute data 9175 * (the linked pathname). If they are the same, we will assume 9176 * the link pathname to reconstruct is relative to the current 9177 * directory. Otherwise, we will set a flag indicate we need 9178 * to use a prefix with the reconstructed name. Need to compare 9179 * both the adorned and unadorned version before deciding a 9180 * mismatch. 9181 */ 9182 9183 buf = lk_real_path; 9184 if (*(str + 1) != '/') { /* got relative linked to path */ 9185 ptr1 = orig_namep; 9186 ptr2 = strrchr(ptr1, '/'); 9187 plen = ptr2 - ptr1; 9188 if (plen > 0) { 9189 pbuf[0] = '\0'; 9190 plen++; /* include '/' */ 9191 (void) strncpy(pbuf, ptr1, plen); 9192 *(pbuf + plen) = '\0'; 9193 ptr2 = strchr(pbuf, '/'); 9194 if (strncmp(pbuf, str + 1, ptr2 - pbuf) != 0) 9195 mismatch = 1; 9196 } 9197 9198 if (mismatch == 1) 9199 use_pbuf = 1; 9200 } 9201 9202 buf[0] = '\0'; 9203 9204 while (*str != '\0') { 9205 9206 switch (*str) { 9207 9208 case MLD_TYPE: 9209 9210 str++; 9211 if ((cp = strstr(str, ";;")) != NULL) { 9212 *cp = '\0'; 9213 9214 /* 9215 * Ignore attempts to backup over .MLD. 9216 */ 9217 if (strcmp(str, "../") != 0) 9218 (void) strncat(buf, str, MAXPATHLEN); 9219 str = cp + 2; 9220 *cp = ';'; 9221 } 9222 break; 9223 9224 case SLD_TYPE: 9225 9226 str++; 9227 if ((cp = strstr(str, ";;")) != NULL) { 9228 *cp = '\0'; 9229 9230 /* 9231 * Use the path name in the header if 9232 * error occurs when processing the 9233 * SLD type. 9234 */ 9235 9236 if (!stobsl(str, &bslabel, 9237 NO_CORRECTION, &reterr)) { 9238 (void) fprintf(stderr, gettext( 9239 "tar: can't translate to binary" 9240 "SL for SLD, stobsl() error:" 9241 " %s\n"), strerror(errno)); 9242 return (-1); 9243 } 9244 9245 str = cp + 2; 9246 *cp = ';'; 9247 9248 if (use_pbuf == 1) { 9249 if (*pbuf != '/') { 9250 /* relative linked to path */ 9251 9252 (void) getcwd(tempbuf, 9253 (sizeof (tempbuf))); 9254 (void) strncat(tempbuf, "/", 9255 MAXPATHLEN); 9256 (void) strncat(tempbuf, pbuf, 9257 MAXPATHLEN); 9258 } 9259 else 9260 (void) strcpy(tempbuf, pbuf); 9261 9262 } else if (*buf != '/') { 9263 /* got relative linked to path */ 9264 9265 (void) getcwd(tempbuf, 9266 (sizeof (tempbuf))); 9267 (void) strncat(tempbuf, "/", 9268 MAXPATHLEN); 9269 } else 9270 *tempbuf = '\0'; 9271 9272 (void) strncat(tempbuf, buf, MAXPATHLEN); 9273 *buf = '\0'; 9274 9275 if (blequal(&bslabel, &admin_high)) { 9276 bslabel = admin_low; 9277 } 9278 9279 9280 /* 9281 * Check for cross-zone symbolic links 9282 */ 9283 from_label = getlabelbypath(real_path); 9284 if (rpath_flag && (from_label != NULL) && 9285 !blequal(&bslabel, from_label)) { 9286 if ((zoneid = 9287 getzoneidbylabel(&bslabel)) == -1) { 9288 (void) fprintf(stderr, 9289 gettext("tar: can't get " 9290 "zone ID for %s\n"), 9291 tempbuf); 9292 return (-1); 9293 } 9294 if (zone_getattr(zoneid, ZONE_ATTR_NAME, 9295 &zonename, ZONENAME_MAX) == -1) { 9296 /* Badly configured zone info */ 9297 (void) fprintf(stderr, 9298 gettext("tar: can't get " 9299 "zonename for %s\n"), 9300 tempbuf); 9301 return (-1); 9302 } 9303 (void) strncpy(buf, AUTO_ZONE, 9304 MAXPATHLEN); 9305 (void) strncat(buf, "/", 9306 MAXPATHLEN); 9307 (void) strncat(buf, zonename, 9308 MAXPATHLEN); 9309 } 9310 if (from_label != NULL) 9311 free(from_label); 9312 (void) strncat(buf, tempbuf, MAXPATHLEN); 9313 break; 9314 } 9315 mld_flag = 0; 9316 break; 9317 9318 case PATH_TYPE: 9319 9320 str++; 9321 if ((cp = strstr(str, ";;")) != NULL) { 9322 *cp = '\0'; 9323 (void) strncat(buf, str, MAXPATHLEN); 9324 str = cp + 2; 9325 *cp = ';'; 9326 } 9327 break; 9328 9329 default: 9330 9331 (void) fprintf(stderr, gettext( 9332 "tar: error rebuilding path %s\n"), 9333 *namep); 9334 *buf = '\0'; 9335 str++; 9336 return (-1); 9337 } 9338 } 9339 9340 /* 9341 * Done for LK_COMP_TYPE 9342 */ 9343 9344 return (0); /* component path is rebuilt successfully */ 9345 9346 } /* end rebuild_lk_comp_path() */ 9347 9348 /* 9349 * Name: check_ext_attr() 9350 * 9351 * Description: 9352 * Check the extended attributes for a file being extracted. 9353 * The attributes being checked here are CMW labels. 9354 * ACLs are not set here because they are set by the 9355 * pflag in doxtract(). 9356 * 9357 * If the label doesn't match, return 0 9358 * else return 1 9359 */ 9360 static int 9361 check_ext_attr(char *filename) 9362 { 9363 bslabel_t currentlabel; /* label from zone */ 9364 9365 if (bltype(&bs_label, SUN_SL_UN)) { 9366 /* No label check possible */ 9367 return (0); 9368 } 9369 if (getlabel(filename, ¤tlabel) != 0) { 9370 (void) fprintf(stderr, 9371 gettext("tar: can't get label for " 9372 " %s, getlabel() error: %s\n"), 9373 filename, strerror(errno)); 9374 return (0); 9375 } else if ((blequal(¤tlabel, &bs_label)) == 0) { 9376 char *src_label = NULL; /* ascii label */ 9377 9378 /* get current src SL */ 9379 if (bsltos(&bs_label, &src_label, 0, 0) <= 0) { 9380 (void) fprintf(stderr, 9381 gettext("tar: can't interpret requested label for" 9382 " %s\n"), filename); 9383 } else { 9384 (void) fprintf(stderr, 9385 gettext("tar: can't apply label %s to %s\n"), 9386 src_label, filename); 9387 free(src_label); 9388 } 9389 (void) fprintf(stderr, 9390 gettext("tar: %s not restored\n"), filename); 9391 return (0); 9392 } 9393 return (1); 9394 9395 } /* end check_ext_attr */ 9396 9397 /* Compressing a tar file using compression method provided in 'opt' */ 9398 9399 static void 9400 compress_back() 9401 { 9402 pid_t pid; 9403 int status; 9404 int wret; 9405 struct stat statb; 9406 9407 if (vflag) { 9408 (void) fprintf(vfile, 9409 gettext("Compressing '%s' with '%s'...\n"), 9410 usefile, compress_opt); 9411 } 9412 if ((pid = fork()) == 0) { 9413 (void) execlp(compress_opt, compress_opt, 9414 usefile, NULL); 9415 } else if (pid == -1) { 9416 vperror(1, "%s", gettext("Could not fork")); 9417 } 9418 wait_pid(pid); 9419 if (suffix == 0) { 9420 (void) rename(tfname, usefile); 9421 } 9422 } 9423 9424 /* The magic numbers from /etc/magic */ 9425 9426 #define GZIP_MAGIC "\037\213" 9427 #define BZIP_MAGIC "BZh" 9428 #define COMP_MAGIC "\037\235" 9429 9430 void 9431 check_compression() 9432 { 9433 char magic[2]; 9434 char buf[16]; 9435 FILE *fp; 9436 9437 if ((fp = fopen(usefile, "r")) != NULL) { 9438 (void) fread(buf, sizeof (char), 6, fp); 9439 magic[0] = buf[0]; 9440 magic[1] = buf[1]; 9441 (void) fclose(fp); 9442 } 9443 9444 if (memcmp(magic, GZIP_MAGIC, 2) == 0) { 9445 if (xflag || tflag) { 9446 compress_opt = compress_malloc(strlen(GZCAT) + 1); 9447 (void) strcpy(compress_opt, GZCAT); 9448 } else if (uflag || rflag) { 9449 compress_opt = compress_malloc(strlen(GZIP) + 1); 9450 (void) strcpy(compress_opt, GZIP); 9451 } 9452 } else if (memcmp(magic, BZIP_MAGIC, 2) == 0) { 9453 if (xflag || tflag) { 9454 compress_opt = compress_malloc(strlen(BZCAT) + 1); 9455 (void) strcpy(compress_opt, BZCAT); 9456 } else if (uflag || rflag) { 9457 compress_opt = compress_malloc(strlen(BZIP) + 1); 9458 (void) strcpy(compress_opt, BZIP); 9459 } 9460 } else if (memcmp(magic, COMP_MAGIC, 2) == 0) { 9461 if (xflag || tflag) { 9462 compress_opt = compress_malloc(strlen(ZCAT) + 1); 9463 (void) strcpy(compress_opt, ZCAT); 9464 } else if (uflag || rflag) { 9465 compress_opt = compress_malloc(strlen(COMPRESS) + 1); 9466 (void) strcpy(compress_opt, COMPRESS); 9467 } 9468 } 9469 } 9470 9471 char * 9472 add_suffix() 9473 { 9474 (void) strcpy(tfname, usefile); 9475 if (strcmp(compress_opt, GZIP) == 0) { 9476 if ((suffix = gz_suffix()) == NULL) { 9477 strlcat(tfname, gsuffix[0], sizeof (tfname)); 9478 return (gsuffix[0]); 9479 } 9480 } else if (strcmp(compress_opt, COMPRESS) == 0) { 9481 if ((suffix = gz_suffix()) == NULL) { 9482 strlcat(tfname, gsuffix[6], sizeof (tfname)); 9483 return (gsuffix[6]); 9484 } 9485 } else if (strcmp(compress_opt, BZIP) == 0) { 9486 if ((suffix = bz_suffix()) == NULL) { 9487 strlcat(tfname, bsuffix[0], sizeof (tfname)); 9488 return (bsuffix[0]); 9489 } 9490 } 9491 return (NULL); 9492 } 9493 9494 /* Decompressing a tar file using compression method from the file type */ 9495 void 9496 decompress_file(void) 9497 { 9498 pid_t pid; 9499 int status; 9500 char cmdstr[PATH_MAX]; 9501 char fname[PATH_MAX]; 9502 char *added_suffix; 9503 9504 9505 added_suffix = add_suffix(); 9506 if (added_suffix != NULL) { 9507 (void) rename(usefile, tfname); 9508 } 9509 if ((pid = fork()) == 0) { 9510 if (vflag) { 9511 (void) fprintf(vfile, 9512 gettext("Decompressing '%s' with " 9513 "'%s'...\n"), usefile, compress_opt); 9514 } 9515 (void) execlp(compress_opt, compress_opt, "-df", 9516 tfname, NULL); 9517 vperror(1, gettext("Could not exec %s"), compress_opt); 9518 } else if (pid == -1) { 9519 vperror(1, gettext("Could not fork")); 9520 } 9521 wait_pid(pid); 9522 if (suffix != NULL) { 9523 /* restore the file name - original file was without suffix */ 9524 *(usefile + strlen(usefile) - strlen(suffix)) = '\0'; 9525 } 9526 } 9527 9528 /* Set the archive for writing and then compress the archive */ 9529 pid_t 9530 compress_file(void) 9531 { 9532 int fd[2]; 9533 pid_t pid; 9534 9535 if (vflag) { 9536 (void) fprintf(vfile, gettext("Compressing '%s' with " 9537 "'%s'...\n"), usefile, compress_opt); 9538 } 9539 9540 if (pipe(fd) < 0) { 9541 vperror(1, gettext("Could not create pipe")); 9542 } 9543 if (pid = fork() > 0) { 9544 mt = fd[1]; 9545 (void) close(fd[0]); 9546 return (pid); 9547 } 9548 /* child */ 9549 (void) dup2(fd[0], STDIN_FILENO); 9550 (void) close(fd[1]); 9551 (void) dup2(mt, STDOUT_FILENO); 9552 (void) execlp(compress_opt, compress_opt, NULL); 9553 vperror(1, gettext("Could not exec %s"), compress_opt); 9554 return (0); /*NOTREACHED*/ 9555 } 9556 9557 pid_t 9558 uncompress_file(void) 9559 { 9560 int fd[2]; 9561 pid_t pid; 9562 9563 if (vflag) { 9564 (void) fprintf(vfile, gettext("Decompressing '%s' with " 9565 "'%s'...\n"), usefile, compress_opt); 9566 } 9567 9568 if (pipe(fd) < 0) { 9569 vperror(1, gettext("Could not create pipe")); 9570 } 9571 if (pid = fork() > 0) { 9572 mt = fd[0]; 9573 (void) close(fd[1]); 9574 return (pid); 9575 } 9576 /* child */ 9577 (void) dup2(fd[1], STDOUT_FILENO); 9578 (void) close(fd[0]); 9579 (void) dup2(mt, STDIN_FILENO); 9580 (void) execlp(compress_opt, compress_opt, NULL); 9581 vperror(1, gettext("Could not exec %s"), compress_opt); 9582 return (0); /*NOTREACHED*/ 9583 } 9584 9585 /* Checking valid 'bzip2' suffix */ 9586 char * 9587 bz_suffix() 9588 { 9589 int i; 9590 int slen; 9591 int nlen = strlen(usefile); 9592 9593 for (i = 0; i < BS; i++) { 9594 slen = strlen(bsuffix[i]); 9595 if (nlen < slen) 9596 return (NULL); 9597 if (strcmp(usefile + nlen - slen, bsuffix[i]) == 0) 9598 return (bsuffix[i]); 9599 } 9600 return (NULL); 9601 } 9602 9603 /* Checking valid 'gzip' suffix */ 9604 char * 9605 gz_suffix() 9606 { 9607 int i; 9608 int slen; 9609 int nlen = strlen(usefile); 9610 9611 for (i = 0; i < GS; i++) { 9612 slen = strlen(gsuffix[i]); 9613 if (nlen < slen) 9614 return (NULL); 9615 if (strcmp(usefile + nlen - slen, gsuffix[i]) == 0) 9616 return (gsuffix[i]); 9617 } 9618 return (NULL); 9619 } 9620 9621 void * 9622 compress_malloc(size_t size) 9623 { 9624 void *opt; 9625 9626 if ((opt = malloc(size)) == NULL) { 9627 vperror(1, "%s", 9628 gettext("Could not allocate compress buffer\n")); 9629 } 9630 return (opt); 9631 } 9632 9633 void 9634 wait_pid(pid_t pid) 9635 { 9636 int status; 9637 9638 while (waitpid(pid, &status, 0) == -1 && errno == EINTR) 9639 ; 9640 } 9641