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