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