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