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