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