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