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