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