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