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 if (tfile != NULL) 4919 (void) unlink(tname); 4920 if (compress_opt != NULL) 4921 (void) free(compress_opt); 4922 if (mt > 0) { 4923 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 4924 perror(gettext("tar: close error")); 4925 exit(2); 4926 } 4927 } 4928 exit(n); 4929 } 4930 4931 /* 4932 * Determine if s1 is a prefix portion of s2 (or the same as s2). 4933 */ 4934 4935 static int 4936 is_prefix(char *s1, char *s2) 4937 { 4938 while (*s1) 4939 if (*s1++ != *s2++) 4940 return (0); 4941 if (*s2) 4942 return (*s2 == '/'); 4943 return (1); 4944 } 4945 4946 /* 4947 * lookup and bsrch look through tfile entries to find a match for a name. 4948 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 4949 * a pair of newline chars, so the buffer it uses must be long enough for 4950 * two lines: name and modification time as well as period, newline and space. 4951 * 4952 * A kludge was added to bsrch to take care of matching on the first entry 4953 * in the file--there is no leading newline. So, if we are reading from the 4954 * start of the file, read into byte two and set the first byte to a newline. 4955 * Otherwise, the first entry cannot be matched. 4956 * 4957 */ 4958 4959 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 4960 static off_t 4961 lookup(char *s) 4962 { 4963 int i; 4964 off_t a; 4965 4966 for (i = 0; s[i]; i++) 4967 if (s[i] == ' ') 4968 break; 4969 a = bsrch(s, i, low, high); 4970 return (a); 4971 } 4972 4973 static off_t 4974 bsrch(char *s, int n, off_t l, off_t h) 4975 { 4976 int i, j; 4977 char b[N]; 4978 off_t m, m1; 4979 4980 4981 loop: 4982 if (l >= h) 4983 return ((off_t)-1); 4984 m = l + (h-l)/2 - N/2; 4985 if (m < l) 4986 m = l; 4987 (void) fseek(tfile, m, 0); 4988 if (m == 0) { 4989 (void) fread(b+1, 1, N-1, tfile); 4990 b[0] = '\n'; 4991 m--; 4992 } else 4993 (void) fread(b, 1, N, tfile); 4994 for (i = 0; i < N; i++) { 4995 if (b[i] == '\n') 4996 break; 4997 m++; 4998 } 4999 if (m >= h) 5000 return ((off_t)-1); 5001 m1 = m; 5002 j = i; 5003 for (i++; i < N; i++) { 5004 m1++; 5005 if (b[i] == '\n') 5006 break; 5007 } 5008 i = cmp(b+j, s, n); 5009 if (i < 0) { 5010 h = m; 5011 goto loop; 5012 } 5013 if (i > 0) { 5014 l = m1; 5015 goto loop; 5016 } 5017 if (m < 0) 5018 m = 0; 5019 return (m); 5020 } 5021 5022 static int 5023 cmp(char *b, char *s, int n) 5024 { 5025 int i; 5026 5027 assert(b[0] == '\n'); 5028 5029 for (i = 0; i < n; i++) { 5030 if (b[i+1] > s[i]) 5031 return (-1); 5032 if (b[i+1] < s[i]) 5033 return (1); 5034 } 5035 return (b[i+1] == ' '? 0 : -1); 5036 } 5037 5038 5039 /* 5040 * seekdisk seek to next file on archive 5041 * 5042 * called by passtape() only 5043 * 5044 * WARNING: expects "nblock" to be set, that is, readtape() to have 5045 * already been called. Since passtape() is only called 5046 * after a file header block has been read (why else would 5047 * we skip to next file?), this is currently safe. 5048 * 5049 * changed to guarantee SYS_BLOCK boundary 5050 */ 5051 5052 static void 5053 seekdisk(blkcnt_t blocks) 5054 { 5055 off_t seekval; 5056 #if SYS_BLOCK > TBLOCK 5057 /* handle non-multiple of SYS_BLOCK */ 5058 blkcnt_t nxb; /* # extra blocks */ 5059 #endif 5060 5061 tapepos += blocks; 5062 #ifdef DEBUG 5063 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 5064 #endif 5065 if (recno + blocks <= nblock) { 5066 recno += blocks; 5067 return; 5068 } 5069 if (recno > nblock) 5070 recno = nblock; 5071 seekval = (off_t)blocks - (nblock - recno); 5072 recno = nblock; /* so readtape() reads next time through */ 5073 #if SYS_BLOCK > TBLOCK 5074 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 5075 #ifdef DEBUG 5076 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 5077 nxb, seekval); 5078 #endif 5079 if (nxb && nxb > seekval) /* don't seek--we'll read */ 5080 goto noseek; 5081 seekval -= nxb; /* don't seek quite so far */ 5082 #endif 5083 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 5084 (void) fprintf(stderr, gettext( 5085 "tar: device seek error\n")); 5086 done(3); 5087 } 5088 #if SYS_BLOCK > TBLOCK 5089 /* read those extra blocks */ 5090 noseek: 5091 if (nxb) { 5092 #ifdef DEBUG 5093 DEBUG("reading extra blocks\n", 0, 0); 5094 #endif 5095 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 5096 (void) fprintf(stderr, gettext( 5097 "tar: read error while skipping file\n")); 5098 done(8); 5099 } 5100 recno = nxb; /* so we don't read in next readtape() */ 5101 } 5102 #endif 5103 } 5104 5105 static void 5106 readtape(char *buffer) 5107 { 5108 int i, j; 5109 5110 ++tapepos; 5111 if (recno >= nblock || first) { 5112 if (first) { 5113 /* 5114 * set the number of blocks to read initially, based on 5115 * the defined defaults for the device, or on the 5116 * explicit block factor given. 5117 */ 5118 if (bflag || defaults_used) 5119 j = nblock; 5120 else 5121 j = NBLOCK; 5122 } else 5123 j = nblock; 5124 5125 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 5126 (void) fprintf(stderr, gettext( 5127 "tar: tape read error\n")); 5128 done(3); 5129 /* 5130 * i == 0 and !rflag means that EOF is reached and we are 5131 * trying to update or replace an empty tar file, so exit 5132 * with an error. 5133 * 5134 * If i == 0 and !first and NotTape, it means the pointer 5135 * has gone past the EOF. It could happen if two processes 5136 * try to update the same tar file simultaneously. So exit 5137 * with an error. 5138 */ 5139 5140 } else if (i == 0) { 5141 if (first && !rflag) { 5142 (void) fprintf(stderr, gettext( 5143 "tar: blocksize = %d\n"), i); 5144 done(Errflg); 5145 } else if (!first && (!rflag || NotTape)) { 5146 mterr("read", 0, 2); 5147 } 5148 } else if ((!first || Bflag) && i != TBLOCK*j) { 5149 /* 5150 * Short read - try to get the remaining bytes. 5151 */ 5152 5153 int remaining = (TBLOCK * j) - i; 5154 char *b = (char *)tbuf + i; 5155 int r; 5156 5157 do { 5158 if ((r = read(mt, b, remaining)) < 0) { 5159 (void) fprintf(stderr, 5160 gettext("tar: tape read error\n")); 5161 done(3); 5162 } 5163 b += r; 5164 remaining -= r; 5165 i += r; 5166 } while (remaining > 0 && r != 0); 5167 } 5168 if (first) { 5169 if ((i % TBLOCK) != 0) { 5170 (void) fprintf(stderr, gettext( 5171 "tar: tape blocksize error\n")); 5172 done(3); 5173 } 5174 i /= TBLOCK; 5175 if (vflag && i != nblock && i != 1) { 5176 if (!NotTape) 5177 (void) fprintf(stderr, gettext( 5178 "tar: blocksize = %d\n"), i); 5179 } 5180 5181 /* 5182 * If we are reading a tape, then a short read is 5183 * understood to signify that the amount read is 5184 * the tape's actual blocking factor. We adapt 5185 * nblock accordingly. There is no reason to do 5186 * this when the device is not blocked. 5187 */ 5188 5189 if (!NotTape) 5190 nblock = i; 5191 } 5192 recno = 0; 5193 } 5194 5195 first = FALSE; 5196 copy(buffer, &tbuf[recno++]); 5197 } 5198 5199 5200 /* 5201 * replacement for writetape. 5202 */ 5203 5204 static int 5205 writetbuf(char *buffer, int n) 5206 { 5207 int i; 5208 5209 tapepos += n; /* output block count */ 5210 5211 if (recno >= nblock) { 5212 i = write(mt, (char *)tbuf, TBLOCK*nblock); 5213 if (i != TBLOCK*nblock) 5214 mterr("write", i, 2); 5215 recno = 0; 5216 } 5217 5218 /* 5219 * Special case: We have an empty tape buffer, and the 5220 * users data size is >= the tape block size: Avoid 5221 * the bcopy and dma direct to tape. BIG WIN. Add the 5222 * residual to the tape buffer. 5223 */ 5224 while (recno == 0 && n >= nblock) { 5225 i = (int)write(mt, buffer, TBLOCK*nblock); 5226 if (i != TBLOCK*nblock) 5227 mterr("write", i, 2); 5228 n -= nblock; 5229 buffer += (nblock * TBLOCK); 5230 } 5231 5232 while (n-- > 0) { 5233 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 5234 buffer += TBLOCK; 5235 if (recno >= nblock) { 5236 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 5237 if (i != TBLOCK*nblock) 5238 mterr("write", i, 2); 5239 recno = 0; 5240 } 5241 } 5242 5243 /* Tell the user how much to write to get in sync */ 5244 return (nblock - recno); 5245 } 5246 5247 /* 5248 * backtape - reposition tape after reading soft "EOF" record 5249 * 5250 * Backtape tries to reposition the tape back over the EOF 5251 * record. This is for the 'u' and 'r' function letters so that the 5252 * tape can be extended. This code is not well designed, but 5253 * I'm confident that the only callers who care about the 5254 * backspace-over-EOF feature are those involved in 'u' and 'r'. 5255 * 5256 * The proper way to backup the tape is through the use of mtio. 5257 * Earlier spins used lseek combined with reads in a confusing 5258 * maneuver that only worked on 4.x, but shouldn't have, even 5259 * there. Lseeks are explicitly not supported for tape devices. 5260 */ 5261 5262 static void 5263 backtape(void) 5264 { 5265 struct mtop mtcmd; 5266 #ifdef DEBUG 5267 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 5268 nblock); 5269 #endif 5270 /* 5271 * Backup to the position in the archive where the record 5272 * currently sitting in the tbuf buffer is situated. 5273 */ 5274 5275 if (NotTape) { 5276 /* 5277 * For non-tape devices, this means lseeking to the 5278 * correct position. The absolute location tapepos-recno 5279 * should be the beginning of the current record. 5280 */ 5281 5282 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 5283 (off_t)-1) { 5284 (void) fprintf(stderr, 5285 gettext("tar: lseek to end of archive failed\n")); 5286 done(4); 5287 } 5288 } else { 5289 /* 5290 * For tape devices, we backup over the most recently 5291 * read record. 5292 */ 5293 5294 mtcmd.mt_op = MTBSR; 5295 mtcmd.mt_count = 1; 5296 5297 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 5298 (void) fprintf(stderr, 5299 gettext("tar: backspace over record failed\n")); 5300 done(4); 5301 } 5302 } 5303 5304 /* 5305 * Decrement the tape and tbuf buffer indices to prepare for the 5306 * coming write to overwrite the soft EOF record. 5307 */ 5308 5309 recno--; 5310 tapepos--; 5311 } 5312 5313 5314 /* 5315 * flushtape write buffered block(s) onto tape 5316 * 5317 * recno points to next free block in tbuf. If nonzero, a write is done. 5318 * Care is taken to write in multiples of SYS_BLOCK when device is 5319 * non-magtape in case raw i/o is used. 5320 * 5321 * NOTE: this is called by writetape() to do the actual writing 5322 */ 5323 5324 static void 5325 flushtape(void) 5326 { 5327 #ifdef DEBUG 5328 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 5329 #endif 5330 if (recno > 0) { /* anything buffered? */ 5331 if (NotTape) { 5332 #if SYS_BLOCK > TBLOCK 5333 int i; 5334 5335 /* 5336 * an odd-block write can only happen when 5337 * we are at the end of a volume that is not a tape. 5338 * Here we round recno up to an even SYS_BLOCK 5339 * boundary. 5340 */ 5341 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 5342 #ifdef DEBUG 5343 DEBUG("flushtape() %d rounding blocks\n", i, 0); 5344 #endif 5345 recno += i; /* round up to even SYS_BLOCK */ 5346 } 5347 #endif 5348 if (recno > nblock) 5349 recno = nblock; 5350 } 5351 #ifdef DEBUG 5352 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 5353 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 5354 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 5355 #endif 5356 if (write(mt, tbuf, 5357 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 5358 (void) fprintf(stderr, gettext( 5359 "tar: tape write error\n")); 5360 done(2); 5361 } 5362 recno = 0; 5363 } 5364 } 5365 5366 static void 5367 copy(void *dst, void *src) 5368 { 5369 (void) memcpy(dst, src, TBLOCK); 5370 } 5371 5372 #ifdef _iBCS2 5373 /* 5374 * initarg -- initialize things for nextarg. 5375 * 5376 * argv filename list, a la argv. 5377 * filefile name of file containing filenames. Unless doing 5378 * a create, seeks must be allowable (e.g. no named pipes). 5379 * 5380 * - if filefile is non-NULL, it will be used first, and argv will 5381 * be used when the data in filefile are exhausted. 5382 * - otherwise argv will be used. 5383 */ 5384 static char **Cmdargv = NULL; 5385 static FILE *FILEFile = NULL; 5386 static long seekFile = -1; 5387 static char *ptrtoFile, *begofFile, *endofFile; 5388 5389 static void 5390 initarg(char *argv[], char *filefile) 5391 { 5392 struct stat statbuf; 5393 char *p; 5394 int nbytes; 5395 5396 Cmdargv = argv; 5397 if (filefile == NULL) 5398 return; /* no -F file */ 5399 if (FILEFile != NULL) { 5400 /* 5401 * need to REinitialize 5402 */ 5403 if (seekFile != -1) 5404 (void) fseek(FILEFile, seekFile, 0); 5405 ptrtoFile = begofFile; 5406 return; 5407 } 5408 /* 5409 * first time initialization 5410 */ 5411 if ((FILEFile = fopen(filefile, "r")) == NULL) 5412 fatal(gettext("cannot open (%s)"), filefile); 5413 (void) fstat(fileno(FILEFile), &statbuf); 5414 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 5415 (void) fprintf(stderr, gettext( 5416 "tar: %s is not a regular file\n"), filefile); 5417 (void) fclose(FILEFile); 5418 done(1); 5419 } 5420 ptrtoFile = begofFile = endofFile; 5421 seekFile = 0; 5422 if (!xflag) 5423 return; /* the file will be read only once anyway */ 5424 nbytes = statbuf.st_size; 5425 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 5426 nbytes -= 20; 5427 if (nbytes < 50) { 5428 free(begofFile); 5429 begofFile = endofFile; 5430 return; /* no room so just do plain reads */ 5431 } 5432 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 5433 fatal(gettext("could not read %s"), filefile); 5434 ptrtoFile = begofFile; 5435 endofFile = begofFile + nbytes; 5436 for (p = begofFile; p < endofFile; ++p) 5437 if (*p == '\n') 5438 *p = '\0'; 5439 if (nbytes != statbuf.st_size) 5440 seekFile = nbytes + 1; 5441 else 5442 (void) fclose(FILEFile); 5443 } 5444 5445 /* 5446 * nextarg -- get next argument of arglist. 5447 * 5448 * The argument is taken from wherever is appropriate. 5449 * 5450 * If the 'F file' function modifier has been specified, the argument 5451 * will be taken from the file, unless EOF has been reached. 5452 * Otherwise the argument will be taken from argv. 5453 * 5454 * WARNING: 5455 * Return value may point to static data, whose contents are over- 5456 * written on each call. 5457 */ 5458 static char * 5459 nextarg(void) 5460 { 5461 static char nameFile[PATH_MAX + 1]; 5462 int n; 5463 char *p; 5464 5465 if (FILEFile) { 5466 if (ptrtoFile < endofFile) { 5467 p = ptrtoFile; 5468 while (*ptrtoFile) 5469 ++ptrtoFile; 5470 ++ptrtoFile; 5471 return (p); 5472 } 5473 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 5474 n = strlen(nameFile); 5475 if (n > 0 && nameFile[n-1] == '\n') 5476 nameFile[n-1] = '\0'; 5477 return (nameFile); 5478 } 5479 } 5480 return (*Cmdargv++); 5481 } 5482 #endif /* _iBCS2 */ 5483 5484 /* 5485 * kcheck() 5486 * - checks the validity of size values for non-tape devices 5487 * - if size is zero, mulvol tar is disabled and size is 5488 * assumed to be infinite. 5489 * - returns volume size in TBLOCKS 5490 */ 5491 5492 static blkcnt_t 5493 kcheck(char *kstr) 5494 { 5495 blkcnt_t kval; 5496 5497 kval = strtoll(kstr, NULL, 0); 5498 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 5499 mulvol = 0; /* definitely not mulvol, but we must */ 5500 return (0); /* took out setting of NotTape */ 5501 } 5502 if (kval < (blkcnt_t)MINSIZE) { 5503 (void) fprintf(stderr, gettext( 5504 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 5505 ").\n"), (ulong_t)MINSIZE, kval); 5506 if (!kflag) 5507 (void) fprintf(stderr, gettext( 5508 "bad size entry for %s in %s.\n"), 5509 archive, DEF_FILE); 5510 done(1); 5511 } 5512 mulvol++; 5513 NotTape++; /* implies non-tape */ 5514 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 5515 } 5516 5517 5518 /* 5519 * bcheck() 5520 * - checks the validity of blocking factors 5521 * - returns blocking factor 5522 */ 5523 5524 static int 5525 bcheck(char *bstr) 5526 { 5527 blkcnt_t bval; 5528 5529 bval = strtoll(bstr, NULL, 0); 5530 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 5531 (void) fprintf(stderr, gettext( 5532 "tar: invalid blocksize \"%s\".\n"), bstr); 5533 if (!bflag) 5534 (void) fprintf(stderr, gettext( 5535 "bad blocksize entry for '%s' in %s.\n"), 5536 archive, DEF_FILE); 5537 done(1); 5538 } 5539 5540 return ((int)bval); 5541 } 5542 5543 5544 /* 5545 * defset() 5546 * - reads DEF_FILE for the set of default values specified. 5547 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 5548 * - 'usefile' points to static data, so will be overwritten 5549 * if this routine is called a second time. 5550 * - the pattern specified by 'arch' must be followed by four 5551 * blank-separated fields (1) device (2) blocking, 5552 * (3) size(K), and (4) tape 5553 * for example: archive0=/dev/fd 1 400 n 5554 */ 5555 5556 static int 5557 defset(char *arch) 5558 { 5559 char *bp; 5560 5561 if (defopen(DEF_FILE) != 0) 5562 return (FALSE); 5563 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 5564 (void) fprintf(stderr, gettext( 5565 "tar: error setting parameters for %s.\n"), DEF_FILE); 5566 return (FALSE); /* & following ones too */ 5567 } 5568 if ((bp = defread(arch)) == NULL) { 5569 (void) fprintf(stderr, gettext( 5570 "tar: missing or invalid '%s' entry in %s.\n"), 5571 arch, DEF_FILE); 5572 return (FALSE); 5573 } 5574 if ((usefile = strtok(bp, " \t")) == NULL) { 5575 (void) fprintf(stderr, gettext( 5576 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 5577 return (FALSE); 5578 } 5579 if ((bp = strtok(NULL, " \t")) == NULL) { 5580 (void) fprintf(stderr, gettext( 5581 "tar: block component missing in '%s' entry in %s.\n"), 5582 arch, DEF_FILE); 5583 return (FALSE); 5584 } 5585 nblock = bcheck(bp); 5586 if ((bp = strtok(NULL, " \t")) == NULL) { 5587 (void) fprintf(stderr, gettext( 5588 "tar: size component missing in '%s' entry in %s.\n"), 5589 arch, DEF_FILE); 5590 return (FALSE); 5591 } 5592 blocklim = kcheck(bp); 5593 if ((bp = strtok(NULL, " \t")) != NULL) 5594 NotTape = (*bp == 'n' || *bp == 'N'); 5595 else 5596 NotTape = (blocklim != 0); 5597 (void) defopen(NULL); 5598 #ifdef DEBUG 5599 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 5600 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 5601 nblock, blocklim); 5602 DEBUG("defset: not tape = %d\n", NotTape, 0); 5603 #endif 5604 return (TRUE); 5605 } 5606 5607 5608 /* 5609 * Following code handles excluded and included files. 5610 * A hash table of file names to be {in,ex}cluded is built. 5611 * For excluded files, before writing or extracting a file 5612 * check to see if it is in the exclude_tbl. 5613 * For included files, the wantit() procedure will check to 5614 * see if the named file is in the include_tbl. 5615 */ 5616 5617 static void 5618 build_table(file_list_t *table[], char *file) 5619 { 5620 FILE *fp; 5621 char buf[PATH_MAX + 1]; 5622 5623 if ((fp = fopen(file, "r")) == (FILE *)NULL) 5624 vperror(1, gettext("could not open %s"), file); 5625 while (fgets(buf, sizeof (buf), fp) != NULL) { 5626 if (buf[strlen(buf) - 1] == '\n') 5627 buf[strlen(buf) - 1] = '\0'; 5628 /* Only add to table if line has something in it */ 5629 if (strspn(buf, " \t") != strlen(buf)) 5630 add_file_to_table(table, buf); 5631 } 5632 (void) fclose(fp); 5633 } 5634 5635 5636 /* 5637 * Add a file name to the the specified table, if the file name has any 5638 * trailing '/'s then delete them before inserting into the table 5639 */ 5640 5641 static void 5642 add_file_to_table(file_list_t *table[], char *str) 5643 { 5644 char name[PATH_MAX + 1]; 5645 unsigned int h; 5646 file_list_t *exp; 5647 5648 (void) strcpy(name, str); 5649 while (name[strlen(name) - 1] == '/') { 5650 name[strlen(name) - 1] = NULL; 5651 } 5652 5653 h = hash(name); 5654 if ((exp = (file_list_t *)calloc(sizeof (file_list_t), 5655 sizeof (char))) == NULL) { 5656 (void) fprintf(stderr, gettext( 5657 "tar: out of memory, exclude/include table(entry)\n")); 5658 exit(1); 5659 } 5660 5661 if ((exp->name = strdup(name)) == NULL) { 5662 (void) fprintf(stderr, gettext( 5663 "tar: out of memory, exclude/include table(file name)\n")); 5664 exit(1); 5665 } 5666 5667 exp->next = table[h]; 5668 table[h] = exp; 5669 } 5670 5671 5672 /* 5673 * See if a file name or any of the file's parent directories is in the 5674 * specified table, if the file name has any trailing '/'s then delete 5675 * them before searching the table 5676 */ 5677 5678 static int 5679 is_in_table(file_list_t *table[], char *str) 5680 { 5681 char name[PATH_MAX + 1]; 5682 unsigned int h; 5683 file_list_t *exp; 5684 char *ptr; 5685 5686 (void) strcpy(name, str); 5687 while (name[strlen(name) - 1] == '/') { 5688 name[strlen(name) - 1] = NULL; 5689 } 5690 5691 /* 5692 * check for the file name in the passed list 5693 */ 5694 h = hash(name); 5695 exp = table[h]; 5696 while (exp != NULL) { 5697 if (strcmp(name, exp->name) == 0) { 5698 return (1); 5699 } 5700 exp = exp->next; 5701 } 5702 5703 /* 5704 * check for any parent directories in the file list 5705 */ 5706 while ((ptr = strrchr(name, '/'))) { 5707 *ptr = NULL; 5708 h = hash(name); 5709 exp = table[h]; 5710 while (exp != NULL) { 5711 if (strcmp(name, exp->name) == 0) { 5712 return (1); 5713 } 5714 exp = exp->next; 5715 } 5716 } 5717 5718 return (0); 5719 } 5720 5721 5722 /* 5723 * Compute a hash from a string. 5724 */ 5725 5726 static unsigned int 5727 hash(char *str) 5728 { 5729 char *cp; 5730 unsigned int h; 5731 5732 h = 0; 5733 for (cp = str; *cp; cp++) { 5734 h += *cp; 5735 } 5736 return (h % TABLE_SIZE); 5737 } 5738 5739 static void * 5740 getmem(size_t size) 5741 { 5742 void *p = calloc((unsigned)size, sizeof (char)); 5743 5744 if (p == NULL && freemem) { 5745 (void) fprintf(stderr, gettext( 5746 "tar: out of memory, link and directory modtime " 5747 "info lost\n")); 5748 freemem = 0; 5749 if (errflag) 5750 done(1); 5751 else 5752 Errflg = 1; 5753 } 5754 return (p); 5755 } 5756 5757 /* 5758 * vperror() --variable argument perror. 5759 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 5760 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 5761 * with the value of whatever "errno" is set to. If exit_status is not 5762 * zero, then tar exits with that error status. If errflag and exit_status 5763 * are both zero, the routine returns to where it was called and sets Errflg 5764 * to errno. 5765 */ 5766 5767 static void 5768 vperror(int exit_status, char *fmt, ...) 5769 { 5770 va_list ap; 5771 5772 va_start(ap, fmt); 5773 (void) fputs("tar: ", stderr); 5774 (void) vfprintf(stderr, fmt, ap); 5775 (void) fprintf(stderr, ": %s\n", strerror(errno)); 5776 va_end(ap); 5777 if (exit_status) 5778 done(exit_status); 5779 else 5780 if (errflag) 5781 done(errno); 5782 else 5783 Errflg = errno; 5784 } 5785 5786 5787 static void 5788 fatal(char *format, ...) 5789 { 5790 va_list ap; 5791 5792 va_start(ap, format); 5793 (void) fprintf(stderr, "tar: "); 5794 (void) vfprintf(stderr, format, ap); 5795 (void) fprintf(stderr, "\n"); 5796 va_end(ap); 5797 done(1); 5798 } 5799 5800 5801 /* 5802 * Check to make sure that argument is a char * ptr. 5803 * Actually, we just check to see that it is non-null. 5804 * If it is null, print out the message and call usage(), bailing out. 5805 */ 5806 5807 static void 5808 assert_string(char *s, char *msg) 5809 { 5810 if (s == NULL) { 5811 (void) fprintf(stderr, msg); 5812 usage(); 5813 } 5814 } 5815 5816 5817 static void 5818 mterr(char *operation, int i, int exitcode) 5819 { 5820 (void) fprintf(stderr, gettext( 5821 "tar: %s error: "), operation); 5822 if (i < 0) 5823 perror(""); 5824 else 5825 (void) fprintf(stderr, gettext("unexpected EOF\n")); 5826 done(exitcode); 5827 } 5828 5829 static int 5830 wantit(char *argv[], char **namep, char **dirp, char **component, 5831 attr_data_t **attrinfo) 5832 { 5833 char **cp; 5834 int gotit; /* true if we've found a match */ 5835 int ret; 5836 5837 top: 5838 if (xhdr_flgs & _X_XHDR) { 5839 xhdr_flgs = 0; 5840 } 5841 getdir(); 5842 if (Xhdrflag > 0) { 5843 ret = get_xdata(); 5844 if (ret != 0) { /* Xhdr items and regular header */ 5845 setbytes_to_skip(&stbuf, ret); 5846 passtape(); 5847 return (0); /* Error--don't want to extract */ 5848 } 5849 } 5850 5851 /* 5852 * If typeflag is not 'A' and xhdr_flgs is set, then processing 5853 * of ancillary file is either over or ancillary file 5854 * processing is not required, load info from Xtarhdr and set 5855 * _X_XHDR bit in xhdr_flgs. 5856 */ 5857 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 5858 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 5859 xhdr_flgs |= _X_XHDR; 5860 } 5861 5862 #if defined(O_XATTR) 5863 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 5864 /* 5865 * Always needs to read the extended header. If atflag, saflag, 5866 * or tflag isn't set, then we'll have the correct info for 5867 * passtape() later. 5868 */ 5869 (void) read_xattr_hdr(attrinfo); 5870 goto top; 5871 } 5872 /* 5873 * Now that we've read the extended header, call passtape() 5874 * if we don't want to restore attributes or system attributes. 5875 * Don't restore the attribute if we are extracting 5876 * a file from an archive (as opposed to doing a table of 5877 * contents) and any of the following are true: 5878 * 1. neither -@ or -/ was specified. 5879 * 2. -@ was specified, -/ wasn't specified, and we're 5880 * processing a hidden attribute directory of an attribute 5881 * or we're processing a read-write system attribute file. 5882 * 3. -@ wasn't specified, -/ was specified, and the file 5883 * we're processing is not a read-write system attribute file, 5884 * or we're processing the hidden attribute directory of an 5885 * attribute. 5886 * 5887 * We always process the attributes if we're just generating 5888 * generating a table of contents, or if both -@ and -/ were 5889 * specified. 5890 */ 5891 if (xattrp != NULL) { 5892 attr_data_t *ainfo = *attrinfo; 5893 5894 if (!tflag && 5895 ((!atflag && !saflag) || 5896 (atflag && !saflag && ((ainfo->attr_parent != NULL) || 5897 ainfo->attr_rw_sysattr)) || 5898 (!atflag && saflag && ((ainfo->attr_parent != NULL) || 5899 !ainfo->attr_rw_sysattr)))) { 5900 passtape(); 5901 return (0); 5902 } 5903 } 5904 #endif 5905 5906 /* sets *namep to point at the proper name */ 5907 if (check_prefix(namep, dirp, component) != 0) { 5908 passtape(); 5909 return (0); 5910 } 5911 5912 if (endtape()) { 5913 if (Bflag) { 5914 /* 5915 * Logically at EOT - consume any extra blocks 5916 * so that write to our stdin won't fail and 5917 * emit an error message; otherwise something 5918 * like "dd if=foo.tar | (cd bar; tar xvf -)" 5919 * will produce a bogus error message from "dd". 5920 */ 5921 5922 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 5923 /* empty body */ 5924 } 5925 } 5926 return (-1); 5927 } 5928 5929 gotit = 0; 5930 5931 if ((Iflag && is_in_table(include_tbl, *namep)) || 5932 (! Iflag && *argv == NULL)) { 5933 gotit = 1; 5934 } else { 5935 for (cp = argv; *cp; cp++) { 5936 if (is_prefix(*cp, *namep)) { 5937 gotit = 1; 5938 break; 5939 } 5940 } 5941 } 5942 5943 if (! gotit) { 5944 passtape(); 5945 return (0); 5946 } 5947 5948 if (Xflag && is_in_table(exclude_tbl, *namep)) { 5949 if (vflag) { 5950 (void) fprintf(stderr, gettext("%s excluded\n"), 5951 *namep); 5952 } 5953 passtape(); 5954 return (0); 5955 } 5956 5957 return (1); 5958 } 5959 5960 5961 static void 5962 setbytes_to_skip(struct stat *st, int err) 5963 { 5964 /* 5965 * In a scenario where a typeflag 'X' was followed by 5966 * a typeflag 'A' and typeflag 'O', then the number of 5967 * bytes to skip should be the size of ancillary file, 5968 * plus the dblock for regular file, and the size 5969 * from Xtarhdr. However, if the typeflag was just 'X' 5970 * followed by typeflag 'O', then the number of bytes 5971 * to skip should be the size from Xtarhdr. 5972 */ 5973 if ((err != 0) && (dblock.dbuf.typeflag == 'A') && 5974 (xhdr_flgs & _X_SIZE)) { 5975 st->st_size += TBLOCK + Xtarhdr.x_filesz; 5976 xhdr_flgs |= _X_XHDR; 5977 } else if ((dblock.dbuf.typeflag != 'A') && 5978 (xhdr_flgs & _X_SIZE)) { 5979 st->st_size += Xtarhdr.x_filesz; 5980 xhdr_flgs |= _X_XHDR; 5981 } 5982 } 5983 5984 static int 5985 fill_in_attr_info(char *attr, char *longname, char *attrparent, int atparentfd, 5986 int rw_sysattr, attr_data_t **attrinfo) 5987 { 5988 size_t pathlen; 5989 char *tpath; 5990 char *tparent; 5991 5992 /* parent info */ 5993 if (attrparent != NULL) { 5994 if ((tparent = strdup(attrparent)) == NULL) { 5995 vperror(0, gettext( 5996 "unable to allocate memory for attribute parent " 5997 "name for %sattribute %s/%s of %s"), 5998 rw_sysattr ? gettext("system ") : "", 5999 attrparent, attr, longname); 6000 return (1); 6001 } 6002 } else { 6003 tparent = NULL; 6004 } 6005 6006 /* path info */ 6007 pathlen = strlen(attr) + 1; 6008 if (attrparent != NULL) { 6009 pathlen += strlen(attrparent) + 1; /* add 1 for '/' */ 6010 } 6011 if ((tpath = calloc(1, pathlen)) == NULL) { 6012 vperror(0, gettext( 6013 "unable to allocate memory for full " 6014 "attribute path name for %sattribute %s%s%s of %s"), 6015 rw_sysattr ? gettext("system ") : "", 6016 (attrparent == NULL) ? "" : attrparent, 6017 (attrparent == NULL) ? "" : "/", 6018 attr, longname); 6019 if (tparent != NULL) { 6020 free(tparent); 6021 } 6022 return (1); 6023 } 6024 (void) snprintf(tpath, pathlen, "%s%s%s", 6025 (attrparent == NULL) ? "" : attrparent, 6026 (attrparent == NULL) ? "" : "/", 6027 attr); 6028 6029 /* fill in the attribute info */ 6030 if (*attrinfo == NULL) { 6031 if ((*attrinfo = malloc(sizeof (attr_data_t))) == NULL) { 6032 vperror(0, gettext( 6033 "unable to allocate memory for attribute " 6034 "information for %sattribute %s%s%s of %s"), 6035 rw_sysattr ? gettext("system ") : "", 6036 (attrparent == NULL) ? "" : attrparent, 6037 (attrparent == NULL) ? "" : gettext("/"), 6038 attr, longname); 6039 if (tparent != NULL) { 6040 free(tparent); 6041 } 6042 free(tpath); 6043 return (1); 6044 } 6045 } else { 6046 if ((*attrinfo)->attr_parent != NULL) { 6047 free((*attrinfo)->attr_parent); 6048 } 6049 if ((*attrinfo)->attr_path != NULL) { 6050 free((*attrinfo)->attr_path); 6051 } 6052 /* 6053 * The parent file descriptor is passed in, so don't 6054 * close it here as it should be closed by the function 6055 * that opened it. 6056 */ 6057 } 6058 (*attrinfo)->attr_parent = tparent; 6059 (*attrinfo)->attr_path = tpath; 6060 (*attrinfo)->attr_rw_sysattr = rw_sysattr; 6061 (*attrinfo)->attr_parentfd = atparentfd; 6062 6063 return (0); 6064 } 6065 6066 /* 6067 * Test if name has a '..' sequence in it. 6068 * 6069 * Return 1 if found, 0 otherwise. 6070 */ 6071 6072 static int 6073 has_dot_dot(char *name) 6074 { 6075 char *s; 6076 size_t name_len = strlen(name); 6077 6078 for (s = name; s < (name + name_len - 2); s++) { 6079 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6080 return (1); 6081 6082 while (! (*s == '/')) { 6083 if (! *s++) 6084 return (0); 6085 } 6086 } 6087 6088 return (0); 6089 } 6090 6091 /* 6092 * Test if name is an absolute path name. 6093 * 6094 * Return 1 if true, 0 otherwise. 6095 */ 6096 6097 static int 6098 is_absolute(char *name) 6099 { 6100 return (name[0] == '/'); 6101 } 6102 6103 /* 6104 * Adjust the pathname to make it a relative one. Strip off any leading 6105 * '/' characters and if the pathname contains any '..' sequences, strip 6106 * upto and including the last occurance of '../' (or '..' if found at 6107 * the very end of the pathname). 6108 * 6109 * Return the relative pathname. stripped_prefix will also return the 6110 * portion of name that was stripped off and should be freed by the 6111 * calling routine when no longer needed. 6112 */ 6113 6114 static char * 6115 make_relative_name(char *name, char **stripped_prefix) 6116 { 6117 char *s; 6118 size_t prefix_len = 0; 6119 size_t name_len = strlen(name); 6120 6121 for (s = name + prefix_len; s < (name + name_len - 2); ) { 6122 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6123 prefix_len = s + 2 - name; 6124 6125 do { 6126 char c = *s++; 6127 6128 if (c == '/') 6129 break; 6130 } while (*s); 6131 } 6132 6133 for (s = name + prefix_len; *s == '/'; s++) 6134 continue; 6135 prefix_len = s - name; 6136 6137 /* Create the portion of the name that was stripped off. */ 6138 s = malloc(prefix_len + 1); 6139 memcpy(s, name, prefix_len); 6140 s[prefix_len] = 0; 6141 *stripped_prefix = s; 6142 s = &name[prefix_len]; 6143 6144 return (s); 6145 } 6146 6147 /* 6148 * Return through *namep a pointer to the proper fullname (i.e "<name> | 6149 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 6150 * 6151 * Returns 0 if successful, otherwise returns 1. 6152 */ 6153 6154 static int 6155 check_prefix(char **namep, char **dirp, char **compp) 6156 { 6157 static char fullname[PATH_MAX + 1]; 6158 static char dir[PATH_MAX + 1]; 6159 static char component[PATH_MAX + 1]; 6160 static char savename[PATH_MAX + 1]; 6161 char *s; 6162 6163 (void) memset(dir, 0, sizeof (dir)); 6164 (void) memset(component, 0, sizeof (component)); 6165 6166 if (xhdr_flgs & _X_PATH) { 6167 (void) strcpy(fullname, Xtarhdr.x_path); 6168 } else { 6169 if (dblock.dbuf.prefix[0] != '\0') 6170 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 6171 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 6172 else 6173 (void) sprintf(fullname, "%.*s", NAMSIZ, 6174 dblock.dbuf.name); 6175 } 6176 6177 /* 6178 * If we are printing a table of contents or extracting an archive, 6179 * make absolute pathnames relative and prohibit the unpacking of 6180 * files contain ".." in their name (unless the user has supplied 6181 * the -P option). 6182 */ 6183 if ((tflag || xflag) && !Pflag) { 6184 if (is_absolute(fullname) || has_dot_dot(fullname)) { 6185 char *stripped_prefix; 6186 size_t prefix_len = 0; 6187 6188 (void) strcpy(savename, fullname); 6189 strcpy(fullname, 6190 make_relative_name(savename, &stripped_prefix)); 6191 (void) fprintf(stderr, 6192 gettext("tar: Removing leading '%s' from '%s'\n"), 6193 stripped_prefix, savename); 6194 free(stripped_prefix); 6195 } 6196 } 6197 6198 /* 6199 * Set dir and component names 6200 */ 6201 6202 get_parent(fullname, dir); 6203 6204 #if defined(O_XATTR) 6205 if (xattrp == NULL) { 6206 #endif 6207 /* 6208 * Save of real name since were going to chop off the 6209 * trailing slashes. 6210 */ 6211 (void) strcpy(savename, fullname); 6212 /* 6213 * first strip of trailing slashes. 6214 */ 6215 chop_endslashes(savename); 6216 s = get_component(savename); 6217 (void) strcpy(component, s); 6218 6219 #if defined(O_XATTR) 6220 } else { 6221 (void) strcpy(fullname, xattrp->h_names); 6222 (void) strcpy(dir, fullname); 6223 (void) strcpy(component, basename(xattrp->h_names + 6224 strlen(xattrp->h_names) + 1)); 6225 } 6226 #endif 6227 *namep = fullname; 6228 *dirp = dir; 6229 *compp = component; 6230 6231 return (0); 6232 } 6233 6234 /* 6235 * Return true if the object indicated by the file descriptor and type 6236 * is a tape device, false otherwise 6237 */ 6238 6239 static int 6240 istape(int fd, int type) 6241 { 6242 int result = 0; 6243 6244 if (S_ISCHR(type)) { 6245 struct mtget mtg; 6246 6247 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 6248 result = 1; 6249 } 6250 } 6251 6252 return (result); 6253 } 6254 6255 #include <utmpx.h> 6256 6257 struct utmpx utmpx; 6258 6259 #define NMAX (sizeof (utmpx.ut_name)) 6260 6261 typedef struct cachenode { /* this struct must be zeroed before using */ 6262 struct cachenode *next; /* next in hash chain */ 6263 int val; /* the uid or gid of this entry */ 6264 int namehash; /* name's hash signature */ 6265 char name[NMAX+1]; /* the string that val maps to */ 6266 } cachenode_t; 6267 6268 #define HASHSIZE 256 6269 6270 static cachenode_t *names[HASHSIZE]; 6271 static cachenode_t *groups[HASHSIZE]; 6272 static cachenode_t *uids[HASHSIZE]; 6273 static cachenode_t *gids[HASHSIZE]; 6274 6275 static int 6276 hash_byname(char *name) 6277 { 6278 int i, c, h = 0; 6279 6280 for (i = 0; i < NMAX; i++) { 6281 c = name[i]; 6282 if (c == '\0') 6283 break; 6284 h = (h << 4) + h + c; 6285 } 6286 return (h); 6287 } 6288 6289 static cachenode_t * 6290 hash_lookup_byval(cachenode_t *table[], int val) 6291 { 6292 int h = val; 6293 cachenode_t *c; 6294 6295 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6296 if (c->val == val) 6297 return (c); 6298 } 6299 return (NULL); 6300 } 6301 6302 static cachenode_t * 6303 hash_lookup_byname(cachenode_t *table[], char *name) 6304 { 6305 int h = hash_byname(name); 6306 cachenode_t *c; 6307 6308 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6309 if (c->namehash == h && strcmp(c->name, name) == 0) 6310 return (c); 6311 } 6312 return (NULL); 6313 } 6314 6315 static cachenode_t * 6316 hash_insert(cachenode_t *table[], char *name, int value) 6317 { 6318 cachenode_t *c; 6319 int signature; 6320 6321 c = calloc(1, sizeof (cachenode_t)); 6322 if (c == NULL) { 6323 perror("malloc"); 6324 exit(1); 6325 } 6326 if (name != NULL) { 6327 (void) strncpy(c->name, name, NMAX); 6328 c->namehash = hash_byname(name); 6329 } 6330 c->val = value; 6331 if (table == uids || table == gids) 6332 signature = c->val; 6333 else 6334 signature = c->namehash; 6335 c->next = table[signature & (HASHSIZE - 1)]; 6336 table[signature & (HASHSIZE - 1)] = c; 6337 return (c); 6338 } 6339 6340 static char * 6341 getname(uid_t uid) 6342 { 6343 cachenode_t *c; 6344 6345 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 6346 struct passwd *pwent = getpwuid(uid); 6347 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 6348 } 6349 return (c->name); 6350 } 6351 6352 static char * 6353 getgroup(gid_t gid) 6354 { 6355 cachenode_t *c; 6356 6357 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 6358 struct group *grent = getgrgid(gid); 6359 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 6360 } 6361 return (c->name); 6362 } 6363 6364 static uid_t 6365 getuidbyname(char *name) 6366 { 6367 cachenode_t *c; 6368 6369 if ((c = hash_lookup_byname(names, name)) == NULL) { 6370 struct passwd *pwent = getpwnam(name); 6371 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 6372 } 6373 return ((uid_t)c->val); 6374 } 6375 6376 static gid_t 6377 getgidbyname(char *group) 6378 { 6379 cachenode_t *c; 6380 6381 if ((c = hash_lookup_byname(groups, group)) == NULL) { 6382 struct group *grent = getgrnam(group); 6383 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 6384 } 6385 return ((gid_t)c->val); 6386 } 6387 6388 /* 6389 * Build the header. 6390 * Determine whether or not an extended header is also needed. If needed, 6391 * create and write the extended header and its data. 6392 * Writing of the extended header assumes that "tomodes" has been called and 6393 * the relevant information has been placed in the header block. 6394 */ 6395 6396 static int 6397 build_dblock( 6398 const char *name, 6399 const char *linkname, 6400 const char typeflag, 6401 const int filetype, 6402 const struct stat *sp, 6403 const dev_t device, 6404 const char *prefix) 6405 { 6406 int nblks; 6407 major_t dev; 6408 const char *filename; 6409 const char *lastslash; 6410 6411 if (filetype == XATTR_FILE) 6412 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 6413 else 6414 dblock.dbuf.typeflag = typeflag; 6415 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 6416 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 6417 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 6418 6419 if (xhdr_flgs & _X_PATH) 6420 filename = Xtarhdr.x_path; 6421 else 6422 filename = name; 6423 6424 if ((dev = major(device)) > OCTAL7CHAR) { 6425 if (Eflag) { 6426 xhdr_flgs |= _X_DEVMAJOR; 6427 Xtarhdr.x_devmajor = dev; 6428 } else { 6429 (void) fprintf(stderr, gettext( 6430 "Device major too large for %s. Use -E flag."), 6431 filename); 6432 if (errflag) 6433 done(1); 6434 else 6435 Errflg = 1; 6436 } 6437 dev = 0; 6438 } 6439 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 6440 if ((dev = minor(device)) > OCTAL7CHAR) { 6441 if (Eflag) { 6442 xhdr_flgs |= _X_DEVMINOR; 6443 Xtarhdr.x_devminor = dev; 6444 } else { 6445 (void) fprintf(stderr, gettext( 6446 "Device minor too large for %s. Use -E flag."), 6447 filename); 6448 if (errflag) 6449 done(1); 6450 else 6451 Errflg = 1; 6452 } 6453 dev = 0; 6454 } 6455 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 6456 6457 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 6458 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 6459 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 6460 (void) sprintf(dblock.dbuf.version, "00"); 6461 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 6462 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 6463 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 6464 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 6465 6466 if (Eflag) { 6467 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 6468 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 6469 lastslash = strrchr(name, '/'); 6470 if (lastslash == NULL) 6471 lastslash = name; 6472 else 6473 lastslash++; 6474 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 6475 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 6476 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 6477 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 6478 xhdr_count++; 6479 xrec_offset = 0; 6480 gen_date("mtime", sp->st_mtim); 6481 xhdr_buf.dbuf.typeflag = 'X'; 6482 if (gen_utf8_names(filename) != 0) 6483 return (1); 6484 6485 #ifdef XHDR_DEBUG 6486 Xtarhdr.x_uname = dblock.dbuf.uname; 6487 Xtarhdr.x_gname = dblock.dbuf.gname; 6488 xhdr_flgs |= (_X_UNAME | _X_GNAME); 6489 #endif 6490 if (xhdr_flgs) { 6491 if (xhdr_flgs & _X_DEVMAJOR) 6492 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 6493 if (xhdr_flgs & _X_DEVMINOR) 6494 gen_num("SUN.devminor", Xtarhdr.x_devminor); 6495 if (xhdr_flgs & _X_GID) 6496 gen_num("gid", Xtarhdr.x_gid); 6497 if (xhdr_flgs & _X_UID) 6498 gen_num("uid", Xtarhdr.x_uid); 6499 if (xhdr_flgs & _X_SIZE) 6500 gen_num("size", Xtarhdr.x_filesz); 6501 if (xhdr_flgs & _X_PATH) 6502 gen_string("path", Xtarhdr.x_path); 6503 if (xhdr_flgs & _X_LINKPATH) 6504 gen_string("linkpath", Xtarhdr.x_linkpath); 6505 if (xhdr_flgs & _X_GNAME) 6506 gen_string("gname", Xtarhdr.x_gname); 6507 if (xhdr_flgs & _X_UNAME) 6508 gen_string("uname", Xtarhdr.x_uname); 6509 } 6510 (void) sprintf(xhdr_buf.dbuf.size, 6511 "%011" FMT_off_t_o, xrec_offset); 6512 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 6513 checksum(&xhdr_buf)); 6514 (void) writetbuf((char *)&xhdr_buf, 1); 6515 nblks = TBLOCKS(xrec_offset); 6516 (void) writetbuf(xrec_ptr, nblks); 6517 } 6518 return (0); 6519 } 6520 6521 6522 /* 6523 * makeDir - ensure that a directory with the pathname denoted by name 6524 * exists, and return 1 on success, and 0 on failure (e.g., 6525 * read-only file system, exists but not-a-directory). 6526 */ 6527 6528 static int 6529 makeDir(char *name) 6530 { 6531 struct stat buf; 6532 6533 if (access(name, 0) < 0) { /* name doesn't exist */ 6534 if (mkdir(name, 0777) < 0) { 6535 vperror(0, "%s", name); 6536 return (0); 6537 } 6538 } else { /* name exists */ 6539 if (stat(name, &buf) < 0) { 6540 vperror(0, "%s", name); 6541 return (0); 6542 } 6543 6544 return ((buf.st_mode & S_IFMT) == S_IFDIR); 6545 } 6546 6547 return (1); 6548 } 6549 6550 6551 /* 6552 * Save this directory and its mtime on the stack, popping and setting 6553 * the mtimes of any stacked dirs which aren't parents of this one. 6554 * A null name causes the entire stack to be unwound and set. 6555 * 6556 * Since all the elements of the directory "stack" share a common 6557 * prefix, we can make do with one string. We keep only the current 6558 * directory path, with an associated array of mtime's. A negative 6559 * mtime means no mtime. 6560 * 6561 * This stack algorithm is not guaranteed to work for tapes created 6562 * with the 'r' function letter, but the vast majority of tapes with 6563 * directories are not. This avoids saving every directory record on 6564 * the tape and setting all the times at the end. 6565 * 6566 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 6567 * environment) 6568 */ 6569 6570 static void 6571 doDirTimes(char *name, timestruc_t modTime) 6572 { 6573 static char dirstack[PATH_MAX+2]; 6574 /* Add spaces for the last slash and last NULL */ 6575 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 6576 char *p = dirstack; 6577 char *q = name; 6578 char *savp; 6579 6580 if (q) { 6581 /* 6582 * Find common prefix 6583 */ 6584 6585 while (*p == *q && *p) { 6586 p++; q++; 6587 } 6588 } 6589 6590 savp = p; 6591 while (*p) { 6592 /* 6593 * Not a child: unwind the stack, setting the times. 6594 * The order we do this doesn't matter, so we go "forward." 6595 */ 6596 6597 if (*p == '/') 6598 if (modtimes[p - dirstack].tv_sec >= 0) { 6599 *p = '\0'; /* zap the slash */ 6600 setPathTimes(AT_FDCWD, dirstack, 6601 modtimes[p - dirstack]); 6602 *p = '/'; 6603 } 6604 ++p; 6605 } 6606 6607 p = savp; 6608 6609 /* 6610 * Push this one on the "stack" 6611 */ 6612 6613 if (q) { 6614 6615 /* 6616 * Since the name parameter points the dir pathname 6617 * which is limited only to contain PATH_MAX chars 6618 * at maximum, we can ignore the overflow case of p. 6619 */ 6620 6621 while ((*p = *q++)) { /* append the rest of the new dir */ 6622 modtimes[p - dirstack].tv_sec = -1; 6623 p++; 6624 } 6625 6626 /* 6627 * If the tar file had used 'P' or 'E' function modifier, 6628 * append the last slash. 6629 */ 6630 if (*(p - 1) != '/') { 6631 *p++ = '/'; 6632 *p = '\0'; 6633 } 6634 /* overwrite the last one */ 6635 modtimes[p - dirstack - 1] = modTime; 6636 } 6637 } 6638 6639 6640 /* 6641 * setPathTimes - set the modification time for given path. Return 1 if 6642 * successful and 0 if not successful. 6643 */ 6644 6645 static void 6646 setPathTimes(int dirfd, char *path, timestruc_t modTime) 6647 6648 { 6649 struct timeval timebuf[2]; 6650 6651 /* 6652 * futimesat takes an array of two timeval structs. 6653 * The first entry contains access time. 6654 * The second entry contains modification time. 6655 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 6656 * microseconds. 6657 */ 6658 timebuf[0].tv_sec = time((time_t *)0); 6659 timebuf[0].tv_usec = 0; 6660 timebuf[1].tv_sec = modTime.tv_sec; 6661 6662 /* Extended header: use microseconds */ 6663 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 6664 6665 if (futimesat(dirfd, path, timebuf) < 0) 6666 vperror(0, "can't set time on %s", path); 6667 } 6668 6669 6670 /* 6671 * If hflag is set then delete the symbolic link's target. 6672 * If !hflag then delete the target. 6673 */ 6674 6675 static void 6676 delete_target(int fd, char *comp, char *namep) 6677 { 6678 struct stat xtractbuf; 6679 char buf[PATH_MAX + 1]; 6680 int n; 6681 6682 6683 if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) { 6684 if (errno == ENOTDIR && !hflag) { 6685 (void) unlinkat(fd, comp, 0); 6686 } else if (errno == ENOTDIR && hflag) { 6687 if (!lstat(namep, &xtractbuf)) { 6688 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 6689 (void) unlinkat(fd, comp, 0); 6690 } else if ((n = readlink(namep, buf, 6691 PATH_MAX)) != -1) { 6692 buf[n] = (char)NULL; 6693 (void) unlinkat(fd, buf, 6694 AT_REMOVEDIR); 6695 if (errno == ENOTDIR) 6696 (void) unlinkat(fd, buf, 0); 6697 } else { 6698 (void) unlinkat(fd, comp, 0); 6699 } 6700 } else { 6701 (void) unlinkat(fd, comp, 0); 6702 } 6703 } 6704 } 6705 } 6706 6707 6708 /* 6709 * ACL changes: 6710 * putfile(): 6711 * Get acl info after stat. Write out ancillary file 6712 * before the normal file, i.e. directory, regular, FIFO, 6713 * link, special. If acl count is less than 4, no need to 6714 * create ancillary file. (i.e. standard permission is in 6715 * use. 6716 * doxtract(): 6717 * Process ancillary file. Read it in and set acl info. 6718 * watch out for 'o' function modifier. 6719 * 't' function letter to display table 6720 */ 6721 6722 /* 6723 * New functions for ACLs and other security attributes 6724 */ 6725 6726 /* 6727 * The function appends the new security attribute info to the end of 6728 * existing secinfo. 6729 */ 6730 int 6731 append_secattr( 6732 char **secinfo, /* existing security info */ 6733 int *secinfo_len, /* length of existing security info */ 6734 int size, /* new attribute size: unit depends on type */ 6735 char *attrtext, /* new attribute text */ 6736 char attr_type) /* new attribute type */ 6737 { 6738 char *new_secinfo; 6739 int newattrsize; 6740 int oldsize; 6741 struct sec_attr *attr; 6742 6743 /* no need to add */ 6744 if (attr_type != DIR_TYPE) { 6745 if (attrtext == NULL) 6746 return (0); 6747 } 6748 6749 switch (attr_type) { 6750 case UFSD_ACL: 6751 case ACE_ACL: 6752 if (attrtext == NULL) { 6753 (void) fprintf(stderr, "acltotext failed\n"); 6754 return (-1); 6755 } 6756 /* header: type + size = 8 */ 6757 newattrsize = 8 + (int)strlen(attrtext) + 1; 6758 attr = (struct sec_attr *)malloc(newattrsize); 6759 if (attr == NULL) { 6760 (void) fprintf(stderr, "can't allocate memory\n"); 6761 return (-1); 6762 } 6763 attr->attr_type = attr_type; 6764 (void) sprintf(attr->attr_len, 6765 "%06o", size); /* acl entry count */ 6766 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6767 free(attrtext); 6768 break; 6769 6770 /* Trusted Extensions */ 6771 case DIR_TYPE: 6772 case LBL_TYPE: 6773 newattrsize = sizeof (struct sec_attr) + strlen(attrtext); 6774 attr = (struct sec_attr *)malloc(newattrsize); 6775 if (attr == NULL) { 6776 (void) fprintf(stderr, 6777 gettext("can't allocate memory\n")); 6778 return (-1); 6779 } 6780 attr->attr_type = attr_type; 6781 (void) sprintf(attr->attr_len, 6782 "%06d", size); /* len of attr data */ 6783 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6784 break; 6785 6786 default: 6787 (void) fprintf(stderr, "unrecognized attribute type\n"); 6788 return (-1); 6789 } 6790 6791 /* old security info + new attr header(8) + new attr */ 6792 oldsize = *secinfo_len; 6793 *secinfo_len += newattrsize; 6794 new_secinfo = (char *)malloc(*secinfo_len); 6795 if (new_secinfo == NULL) { 6796 (void) fprintf(stderr, "can't allocate memory\n"); 6797 *secinfo_len -= newattrsize; 6798 free(attr); 6799 return (-1); 6800 } 6801 6802 (void) memcpy(new_secinfo, *secinfo, oldsize); 6803 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 6804 6805 free(*secinfo); 6806 free(attr); 6807 *secinfo = new_secinfo; 6808 return (0); 6809 } 6810 6811 /* 6812 * write_ancillary(): write out an ancillary file. 6813 * The file has the same header as normal file except the type and size 6814 * fields. The type is 'A' and size is the sum of all attributes 6815 * in bytes. 6816 * The body contains a list of attribute type, size and info. Currently, 6817 * there is only ACL info. This file is put before the normal file. 6818 */ 6819 void 6820 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 6821 { 6822 long blocks; 6823 int savflag; 6824 int savsize; 6825 6826 /* Just tranditional permissions or no security attribute info */ 6827 if (len == 0 || secinfo == NULL) 6828 return; 6829 6830 /* save flag and size */ 6831 savflag = (dblockp->dbuf).typeflag; 6832 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 6833 6834 /* special flag for ancillary file */ 6835 if (hdrtype == _XATTR_HDRTYPE) 6836 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 6837 else 6838 dblockp->dbuf.typeflag = 'A'; 6839 6840 /* for pre-2.5 versions of tar, need to make sure */ 6841 /* the ACL file is readable */ 6842 (void) sprintf(dblock.dbuf.mode, "%07lo", 6843 (stbuf.st_mode & POSIXMODES) | 0000200); 6844 (void) sprintf(dblockp->dbuf.size, "%011o", len); 6845 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 6846 6847 /* write out the header */ 6848 (void) writetbuf((char *)dblockp, 1); 6849 6850 /* write out security info */ 6851 blocks = TBLOCKS(len); 6852 (void) writetbuf((char *)secinfo, (int)blocks); 6853 6854 /* restore mode, flag and size */ 6855 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 6856 dblockp->dbuf.typeflag = savflag; 6857 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 6858 } 6859 6860 /* 6861 * Read the data record for extended headers and then the regular header. 6862 * The data are read into the buffer and then null-terminated. Entries 6863 * for typeflag 'X' extended headers are of the format: 6864 * "%d %s=%s\n" 6865 * 6866 * When an extended header record is found, the extended header must 6867 * be processed and its values used to override the values in the 6868 * normal header. The way this is done is to process the extended 6869 * header data record and set the data values, then call getdir 6870 * to process the regular header, then then to reconcile the two 6871 * sets of data. 6872 */ 6873 6874 static int 6875 get_xdata(void) 6876 { 6877 struct keylist_pair { 6878 int keynum; 6879 char *keylist; 6880 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 6881 _X_DEVMINOR, "SUN.devminor", 6882 _X_GID, "gid", 6883 _X_GNAME, "gname", 6884 _X_LINKPATH, "linkpath", 6885 _X_PATH, "path", 6886 _X_SIZE, "size", 6887 _X_UID, "uid", 6888 _X_UNAME, "uname", 6889 _X_MTIME, "mtime", 6890 _X_LAST, "NULL" }; 6891 char *lineloc; 6892 int length, i; 6893 char *keyword, *value; 6894 blkcnt_t nblocks; 6895 int bufneeded; 6896 int errors; 6897 6898 (void) memset(&Xtarhdr, 0, sizeof (Xtarhdr)); 6899 xhdr_count++; 6900 errors = 0; 6901 6902 nblocks = TBLOCKS(stbuf.st_size); 6903 bufneeded = nblocks * TBLOCK; 6904 if (bufneeded >= xrec_size) { 6905 free(xrec_ptr); 6906 xrec_size = bufneeded + 1; 6907 if ((xrec_ptr = malloc(xrec_size)) == NULL) 6908 fatal(gettext("cannot allocate buffer")); 6909 } 6910 6911 lineloc = xrec_ptr; 6912 6913 while (nblocks-- > 0) { 6914 readtape(lineloc); 6915 lineloc += TBLOCK; 6916 } 6917 lineloc = xrec_ptr; 6918 xrec_ptr[stbuf.st_size] = '\0'; 6919 while (lineloc < xrec_ptr + stbuf.st_size) { 6920 if (dblock.dbuf.typeflag == 'L') { 6921 length = xrec_size; 6922 keyword = "path"; 6923 value = lineloc; 6924 } else { 6925 length = atoi(lineloc); 6926 *(lineloc + length - 1) = '\0'; 6927 keyword = strchr(lineloc, ' ') + 1; 6928 value = strchr(keyword, '=') + 1; 6929 *(value - 1) = '\0'; 6930 } 6931 i = 0; 6932 lineloc += length; 6933 while (keylist_pair[i].keynum != (int)_X_LAST) { 6934 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 6935 break; 6936 i++; 6937 } 6938 errno = 0; 6939 switch (keylist_pair[i].keynum) { 6940 case _X_DEVMAJOR: 6941 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 6942 if (errno) { 6943 (void) fprintf(stderr, gettext( 6944 "tar: Extended header major value error " 6945 "for file # %llu.\n"), xhdr_count); 6946 errors++; 6947 } else 6948 xhdr_flgs |= _X_DEVMAJOR; 6949 break; 6950 case _X_DEVMINOR: 6951 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 6952 if (errno) { 6953 (void) fprintf(stderr, gettext( 6954 "tar: Extended header minor value error " 6955 "for file # %llu.\n"), xhdr_count); 6956 errors++; 6957 } else 6958 xhdr_flgs |= _X_DEVMINOR; 6959 break; 6960 case _X_GID: 6961 xhdr_flgs |= _X_GID; 6962 Xtarhdr.x_gid = strtol(value, NULL, 0); 6963 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 6964 (void) fprintf(stderr, gettext( 6965 "tar: Extended header gid value error " 6966 "for file # %llu.\n"), xhdr_count); 6967 Xtarhdr.x_gid = GID_NOBODY; 6968 } 6969 break; 6970 case _X_GNAME: 6971 if (utf8_local("gname", &Xtarhdr.x_gname, 6972 local_gname, value, _POSIX_NAME_MAX) == 0) 6973 xhdr_flgs |= _X_GNAME; 6974 break; 6975 case _X_LINKPATH: 6976 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 6977 local_linkpath, value, PATH_MAX) == 0) 6978 xhdr_flgs |= _X_LINKPATH; 6979 else 6980 errors++; 6981 break; 6982 case _X_PATH: 6983 if (utf8_local("path", &Xtarhdr.x_path, 6984 local_path, value, PATH_MAX) == 0) 6985 xhdr_flgs |= _X_PATH; 6986 else 6987 errors++; 6988 break; 6989 case _X_SIZE: 6990 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 6991 if (errno) { 6992 (void) fprintf(stderr, gettext( 6993 "tar: Extended header invalid filesize " 6994 "for file # %llu.\n"), xhdr_count); 6995 errors++; 6996 } else 6997 xhdr_flgs |= _X_SIZE; 6998 break; 6999 case _X_UID: 7000 xhdr_flgs |= _X_UID; 7001 Xtarhdr.x_uid = strtol(value, NULL, 0); 7002 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 7003 (void) fprintf(stderr, gettext( 7004 "tar: Extended header uid value error " 7005 "for file # %llu.\n"), xhdr_count); 7006 Xtarhdr.x_uid = UID_NOBODY; 7007 } 7008 break; 7009 case _X_UNAME: 7010 if (utf8_local("uname", &Xtarhdr.x_uname, 7011 local_uname, value, _POSIX_NAME_MAX) == 0) 7012 xhdr_flgs |= _X_UNAME; 7013 break; 7014 case _X_MTIME: 7015 get_xtime(value, &(Xtarhdr.x_mtime)); 7016 if (errno) 7017 (void) fprintf(stderr, gettext( 7018 "tar: Extended header modification time " 7019 "value error for file # %llu.\n"), 7020 xhdr_count); 7021 else 7022 xhdr_flgs |= _X_MTIME; 7023 break; 7024 default: 7025 (void) fprintf(stderr, 7026 gettext("tar: unrecognized extended" 7027 " header keyword '%s'. Ignored.\n"), keyword); 7028 break; 7029 } 7030 } 7031 7032 getdir(); /* get regular header */ 7033 if (errors && errflag) 7034 done(1); 7035 else 7036 if (errors) 7037 Errflg = 1; 7038 return (errors); 7039 } 7040 7041 /* 7042 * load_info_from_xtarhdr - sets Gen and stbuf variables from 7043 * extended header 7044 * load_info_from_xtarhdr(flag, xhdrp); 7045 * u_longlong_t flag; xhdr_flgs 7046 * struct xtar_hdr *xhdrp; pointer to extended header 7047 * NOTE: called when typeflag is not 'A' and xhdr_flgs 7048 * is set. 7049 */ 7050 static void 7051 load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp) 7052 { 7053 if (flag & _X_DEVMAJOR) { 7054 Gen.g_devmajor = xhdrp->x_devmajor; 7055 } 7056 if (flag & _X_DEVMINOR) { 7057 Gen.g_devminor = xhdrp->x_devminor; 7058 } 7059 if (flag & _X_GID) { 7060 Gen.g_gid = xhdrp->x_gid; 7061 stbuf.st_gid = xhdrp->x_gid; 7062 } 7063 if (flag & _X_UID) { 7064 Gen.g_uid = xhdrp->x_uid; 7065 stbuf.st_uid = xhdrp->x_uid; 7066 } 7067 if (flag & _X_SIZE) { 7068 Gen.g_filesz = xhdrp->x_filesz; 7069 stbuf.st_size = xhdrp->x_filesz; 7070 } 7071 if (flag & _X_MTIME) { 7072 Gen.g_mtime = xhdrp->x_mtime.tv_sec; 7073 stbuf.st_mtim.tv_sec = xhdrp->x_mtime.tv_sec; 7074 stbuf.st_mtim.tv_nsec = xhdrp->x_mtime.tv_nsec; 7075 } 7076 } 7077 7078 /* 7079 * gen_num creates a string from a keyword and an usigned long long in the 7080 * format: %d %s=%s\n 7081 * This is part of the extended header data record. 7082 */ 7083 7084 void 7085 gen_num(const char *keyword, const u_longlong_t number) 7086 { 7087 char save_val[ULONGLONG_MAX_DIGITS + 1]; 7088 int len; 7089 char *curr_ptr; 7090 7091 (void) sprintf(save_val, "%llu", number); 7092 /* 7093 * len = length of entire line, including itself. len will be 7094 * two digits. So, add the string lengths plus the length of len, 7095 * plus a blank, an equal sign, and a newline. 7096 */ 7097 len = strlen(save_val) + strlen(keyword) + 5; 7098 if (xrec_offset + len > xrec_size) { 7099 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7100 fatal(gettext( 7101 "cannot allocate extended header buffer")); 7102 xrec_ptr = curr_ptr; 7103 xrec_size *= 2; 7104 } 7105 (void) sprintf(&xrec_ptr[xrec_offset], 7106 "%d %s=%s\n", len, keyword, save_val); 7107 xrec_offset += len; 7108 } 7109 7110 /* 7111 * gen_date creates a string from a keyword and a timestruc_t in the 7112 * format: %d %s=%s\n 7113 * This is part of the extended header data record. 7114 * Currently, granularity is only microseconds, so the low-order three digits 7115 * will be truncated. 7116 */ 7117 7118 void 7119 gen_date(const char *keyword, const timestruc_t time_value) 7120 { 7121 /* Allow for <seconds>.<nanoseconds>\n */ 7122 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 7123 int len; 7124 char *curr_ptr; 7125 7126 (void) sprintf(save_val, "%ld", time_value.tv_sec); 7127 len = strlen(save_val); 7128 save_val[len] = '.'; 7129 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 7130 7131 /* 7132 * len = length of entire line, including itself. len will be 7133 * two digits. So, add the string lengths plus the length of len, 7134 * plus a blank, an equal sign, and a newline. 7135 */ 7136 len = strlen(save_val) + strlen(keyword) + 5; 7137 if (xrec_offset + len > xrec_size) { 7138 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7139 fatal(gettext( 7140 "cannot allocate extended header buffer")); 7141 xrec_ptr = curr_ptr; 7142 xrec_size *= 2; 7143 } 7144 (void) sprintf(&xrec_ptr[xrec_offset], 7145 "%d %s=%s\n", len, keyword, save_val); 7146 xrec_offset += len; 7147 } 7148 7149 /* 7150 * gen_string creates a string from a keyword and a char * in the 7151 * format: %d %s=%s\n 7152 * This is part of the extended header data record. 7153 */ 7154 7155 void 7156 gen_string(const char *keyword, const char *value) 7157 { 7158 int len; 7159 char *curr_ptr; 7160 7161 /* 7162 * len = length of entire line, including itself. The character length 7163 * of len must be 1-4 characters, because the maximum size of the path 7164 * or the name is PATH_MAX, which is 1024. So, assume 1 character 7165 * for len, one for the space, one for the "=", and one for the newline. 7166 * Then adjust as needed. 7167 */ 7168 /* LINTED constant expression */ 7169 assert(PATH_MAX <= 9996); 7170 len = strlen(value) + strlen(keyword) + 4; 7171 if (len > 997) 7172 len += 3; 7173 else if (len > 98) 7174 len += 2; 7175 else if (len > 9) 7176 len += 1; 7177 if (xrec_offset + len > xrec_size) { 7178 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7179 fatal(gettext( 7180 "cannot allocate extended header buffer")); 7181 xrec_ptr = curr_ptr; 7182 xrec_size *= 2; 7183 } 7184 #ifdef XHDR_DEBUG 7185 if (strcmp(keyword+1, "name") != 0) 7186 #endif 7187 (void) sprintf(&xrec_ptr[xrec_offset], 7188 "%d %s=%s\n", len, keyword, value); 7189 #ifdef XHDR_DEBUG 7190 else { 7191 len += 11; 7192 (void) sprintf(&xrec_ptr[xrec_offset], 7193 "%d %s=%snametoolong\n", len, keyword, value); 7194 } 7195 #endif 7196 xrec_offset += len; 7197 } 7198 7199 /* 7200 * Convert time found in the extended header data to seconds and nanoseconds. 7201 */ 7202 7203 void 7204 get_xtime(char *value, timestruc_t *xtime) 7205 { 7206 char nanosec[10]; 7207 char *period; 7208 int i; 7209 7210 (void) memset(nanosec, '0', 9); 7211 nanosec[9] = '\0'; 7212 7213 period = strchr(value, '.'); 7214 if (period != NULL) 7215 period[0] = '\0'; 7216 xtime->tv_sec = strtol(value, NULL, 10); 7217 if (period == NULL) 7218 xtime->tv_nsec = 0; 7219 else { 7220 i = strlen(period +1); 7221 (void) strncpy(nanosec, period + 1, min(i, 9)); 7222 xtime->tv_nsec = strtol(nanosec, NULL, 10); 7223 } 7224 } 7225 7226 /* 7227 * Check linkpath for length. 7228 * Emit an error message and return 1 if too long. 7229 */ 7230 7231 int 7232 chk_path_build( 7233 char *name, 7234 char *longname, 7235 char *linkname, 7236 char *prefix, 7237 char type, 7238 int filetype) 7239 { 7240 7241 if (strlen(linkname) > (size_t)NAMSIZ) { 7242 if (Eflag > 0) { 7243 xhdr_flgs |= _X_LINKPATH; 7244 Xtarhdr.x_linkpath = linkname; 7245 } else { 7246 (void) fprintf(stderr, gettext( 7247 "tar: %s: linked to %s\n"), longname, linkname); 7248 (void) fprintf(stderr, gettext( 7249 "tar: %s: linked name too long\n"), linkname); 7250 if (errflag) 7251 done(1); 7252 else 7253 Errflg = 1; 7254 return (1); 7255 } 7256 } 7257 if (xhdr_flgs & _X_LINKPATH) 7258 return (build_dblock(name, tchar, type, 7259 filetype, &stbuf, stbuf.st_dev, 7260 prefix)); 7261 else 7262 return (build_dblock(name, linkname, type, 7263 filetype, &stbuf, stbuf.st_dev, prefix)); 7264 } 7265 7266 /* 7267 * Convert from UTF-8 to local character set. 7268 */ 7269 7270 static int 7271 utf8_local( 7272 char *option, 7273 char **Xhdr_ptrptr, 7274 char *target, 7275 const char *source, 7276 int max_val) 7277 { 7278 static iconv_t iconv_cd; 7279 char *nl_target; 7280 const char *iconv_src; 7281 char *iconv_trg; 7282 size_t inlen; 7283 size_t outlen; 7284 7285 if (charset_type == -1) { /* iconv_open failed in earlier try */ 7286 (void) fprintf(stderr, gettext( 7287 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7288 xhdr_count, source); 7289 return (1); 7290 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 7291 nl_target = nl_langinfo(CODESET); 7292 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7293 nl_target = "646"; 7294 if (strcmp(nl_target, "646") == 0) 7295 charset_type = 1; 7296 else if (strcmp(nl_target, "UTF-8") == 0) 7297 charset_type = 3; 7298 else { 7299 if (strncmp(nl_target, "ISO", 3) == 0) 7300 nl_target += 3; 7301 charset_type = 2; 7302 errno = 0; 7303 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 7304 (iconv_t)-1) { 7305 if (errno == EINVAL) 7306 (void) fprintf(stderr, gettext( 7307 "tar: conversion routines not " 7308 "available for current locale. ")); 7309 (void) fprintf(stderr, gettext( 7310 "file # %llu: (%s) UTF-8 conversion" 7311 " failed.\n"), xhdr_count, source); 7312 charset_type = -1; 7313 return (1); 7314 } 7315 } 7316 } 7317 7318 /* locale using 7-bit codeset or UTF-8 locale */ 7319 if (charset_type == 1 || charset_type == 3) { 7320 if (strlen(source) > max_val) { 7321 (void) fprintf(stderr, gettext( 7322 "tar: file # %llu: Extended header %s too long.\n"), 7323 xhdr_count, option); 7324 return (1); 7325 } 7326 if (charset_type == 3) 7327 (void) strcpy(target, source); 7328 else if (c_utf8(target, source) != 0) { 7329 (void) fprintf(stderr, gettext( 7330 "tar: file # %llu: (%s) UTF-8 conversion" 7331 " failed.\n"), xhdr_count, source); 7332 return (1); 7333 } 7334 *Xhdr_ptrptr = target; 7335 return (0); 7336 } 7337 7338 iconv_src = source; 7339 iconv_trg = target; 7340 inlen = strlen(source); 7341 outlen = max_val * UTF_8_FACTOR; 7342 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7343 (size_t)-1) { /* Error occurred: didn't convert */ 7344 (void) fprintf(stderr, gettext( 7345 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7346 xhdr_count, source); 7347 /* Get remaining output; reinitialize conversion descriptor */ 7348 iconv_src = (const char *)NULL; 7349 inlen = 0; 7350 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7351 return (1); 7352 } 7353 /* Get remaining output; reinitialize conversion descriptor */ 7354 iconv_src = (const char *)NULL; 7355 inlen = 0; 7356 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7357 (size_t)-1) { /* Error occurred: didn't convert */ 7358 (void) fprintf(stderr, gettext( 7359 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7360 xhdr_count, source); 7361 return (1); 7362 } 7363 7364 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7365 if (strlen(target) > max_val) { 7366 (void) fprintf(stderr, gettext( 7367 "tar: file # %llu: Extended header %s too long.\n"), 7368 xhdr_count, option); 7369 return (1); 7370 } 7371 *Xhdr_ptrptr = target; 7372 return (0); 7373 } 7374 7375 /* 7376 * Check gname, uname, path, and linkpath to see if they need to go in an 7377 * extended header. If they are already slated to be in an extended header, 7378 * or if they are not ascii, then they need to be in the extended header. 7379 * Then, convert all extended names to UTF-8. 7380 */ 7381 7382 int 7383 gen_utf8_names(const char *filename) 7384 { 7385 static iconv_t iconv_cd; 7386 char *nl_target; 7387 char tempbuf[MAXNAM + 1]; 7388 int nbytes; 7389 int errors; 7390 7391 if (charset_type == -1) { /* Previous failure to open. */ 7392 (void) fprintf(stderr, gettext( 7393 "tar: file # %llu: UTF-8 conversion failed.\n"), 7394 xhdr_count); 7395 return (1); 7396 } 7397 7398 if (charset_type == 0) { /* Need to get conversion descriptor */ 7399 nl_target = nl_langinfo(CODESET); 7400 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7401 nl_target = "646"; 7402 if (strcmp(nl_target, "646") == 0) 7403 charset_type = 1; 7404 else if (strcmp(nl_target, "UTF-8") == 0) 7405 charset_type = 3; 7406 else { 7407 if (strncmp(nl_target, "ISO", 3) == 0) 7408 nl_target += 3; 7409 charset_type = 2; 7410 errno = 0; 7411 #ifdef ICONV_DEBUG 7412 (void) fprintf(stderr, 7413 "Opening iconv_cd with target %s\n", 7414 nl_target); 7415 #endif 7416 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 7417 (iconv_t)-1) { 7418 if (errno == EINVAL) 7419 (void) fprintf(stderr, gettext( 7420 "tar: conversion routines not " 7421 "available for current locale. ")); 7422 (void) fprintf(stderr, gettext( 7423 "file (%s): UTF-8 conversion failed.\n"), 7424 filename); 7425 charset_type = -1; 7426 return (1); 7427 } 7428 } 7429 } 7430 7431 errors = 0; 7432 7433 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 7434 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 7435 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 7436 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 7437 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 7438 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 7439 tempbuf[NAMSIZ] = '\0'; 7440 } 7441 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 7442 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 7443 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 7444 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 7445 tempbuf[PRESIZ] = '\0'; 7446 nbytes = strlen(tempbuf); 7447 if (nbytes > 0) { 7448 tempbuf[nbytes++] = '/'; 7449 tempbuf[nbytes] = '\0'; 7450 } 7451 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, 7452 (MAXNAM - nbytes)); 7453 tempbuf[MAXNAM] = '\0'; 7454 } 7455 errors += local_utf8(&Xtarhdr.x_path, local_path, 7456 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 7457 7458 if (errors > 0) 7459 (void) fprintf(stderr, gettext( 7460 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 7461 7462 if (errors && errflag) 7463 done(1); 7464 else 7465 if (errors) 7466 Errflg = 1; 7467 return (errors); 7468 } 7469 7470 static int 7471 local_utf8( 7472 char **Xhdr_ptrptr, 7473 char *target, 7474 const char *source, 7475 iconv_t iconv_cd, 7476 int xhdrflg, 7477 int max_val) 7478 { 7479 const char *iconv_src; 7480 const char *starting_src; 7481 char *iconv_trg; 7482 size_t inlen; 7483 size_t outlen; 7484 #ifdef ICONV_DEBUG 7485 unsigned char c_to_hex; 7486 #endif 7487 7488 /* 7489 * If the item is already slated for extended format, get the string 7490 * to convert from the extended header record. Otherwise, get it from 7491 * the regular (dblock) area. 7492 */ 7493 if (xhdr_flgs & xhdrflg) { 7494 if (charset_type == 3) { /* Already UTF-8, just copy */ 7495 (void) strcpy(target, *Xhdr_ptrptr); 7496 *Xhdr_ptrptr = target; 7497 return (0); 7498 } else 7499 iconv_src = (const char *) *Xhdr_ptrptr; 7500 } else { 7501 if (charset_type == 3) /* Already in UTF-8 format */ 7502 return (0); /* Don't create xhdr record */ 7503 iconv_src = source; 7504 } 7505 starting_src = iconv_src; 7506 iconv_trg = target; 7507 if ((inlen = strlen(iconv_src)) == 0) 7508 return (0); 7509 7510 if (charset_type == 1) { /* locale using 7-bit codeset */ 7511 if (c_utf8(target, starting_src) != 0) { 7512 (void) fprintf(stderr, 7513 gettext("tar: invalid character in" 7514 " UTF-8 conversion of '%s'\n"), starting_src); 7515 return (1); 7516 } 7517 return (0); 7518 } 7519 7520 outlen = max_val * UTF_8_FACTOR; 7521 errno = 0; 7522 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7523 (size_t)-1) { 7524 /* An error occurred, or not all characters were converted */ 7525 if (errno == EILSEQ) 7526 (void) fprintf(stderr, 7527 gettext("tar: invalid character in" 7528 " UTF-8 conversion of '%s'\n"), starting_src); 7529 else 7530 (void) fprintf(stderr, gettext( 7531 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7532 starting_src); 7533 /* Get remaining output; reinitialize conversion descriptor */ 7534 iconv_src = (const char *)NULL; 7535 inlen = 0; 7536 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7537 return (1); 7538 } 7539 /* Get remaining output; reinitialize conversion descriptor */ 7540 iconv_src = (const char *)NULL; 7541 inlen = 0; 7542 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7543 (size_t)-1) { /* Error occurred: didn't convert */ 7544 if (errno == EILSEQ) 7545 (void) fprintf(stderr, 7546 gettext("tar: invalid character in" 7547 " UTF-8 conversion of '%s'\n"), starting_src); 7548 else 7549 (void) fprintf(stderr, gettext( 7550 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7551 starting_src); 7552 return (1); 7553 } 7554 7555 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7556 if (strcmp(starting_src, target) != 0) { 7557 *Xhdr_ptrptr = target; 7558 xhdr_flgs |= xhdrflg; 7559 #ifdef ICONV_DEBUG 7560 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 7561 strlen(starting_src), inlen, max_val, outlen); 7562 (void) fprintf(stderr, "Input string:\n "); 7563 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 7564 c_to_hex = (unsigned char)starting_src[inlen]; 7565 (void) fprintf(stderr, " %2.2x", c_to_hex); 7566 if (inlen % 20 == 19) 7567 (void) fprintf(stderr, "\n "); 7568 } 7569 (void) fprintf(stderr, "\nOutput string:\n "); 7570 for (inlen = 0; inlen < strlen(target); inlen++) { 7571 c_to_hex = (unsigned char)target[inlen]; 7572 (void) fprintf(stderr, " %2.2x", c_to_hex); 7573 if (inlen % 20 == 19) 7574 (void) fprintf(stderr, "\n "); 7575 } 7576 (void) fprintf(stderr, "\n"); 7577 #endif 7578 } 7579 7580 return (0); 7581 } 7582 7583 /* 7584 * Function to test each byte of the source string to make sure it is 7585 * in within bounds (value between 0 and 127). 7586 * If valid, copy source to target. 7587 */ 7588 7589 int 7590 c_utf8(char *target, const char *source) 7591 { 7592 size_t len; 7593 const char *thischar; 7594 7595 len = strlen(source); 7596 thischar = source; 7597 while (len-- > 0) { 7598 if (!isascii((int)(*thischar++))) 7599 return (1); 7600 } 7601 7602 (void) strcpy(target, source); 7603 return (0); 7604 } 7605 7606 7607 #if defined(O_XATTR) 7608 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 7609 7610 static void 7611 prepare_xattr( 7612 char **attrbuf, 7613 char *filename, 7614 char *attrpath, 7615 char typeflag, 7616 struct linkbuf *linkinfo, 7617 int *rlen) 7618 { 7619 char *bufhead; /* ptr to full buffer */ 7620 char *aptr; 7621 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 7622 struct xattr_buf *tptr; /* ptr to pathing pieces */ 7623 int totalen; /* total buffer length */ 7624 int len; /* length returned to user */ 7625 int stringlen; /* length of filename + attr */ 7626 /* 7627 * length of filename + attr 7628 * in link section 7629 */ 7630 int linkstringlen; 7631 int complen; /* length of pathing section */ 7632 int linklen; /* length of link section */ 7633 int attrnames_index; /* attrnames starting index */ 7634 7635 /* 7636 * Release previous buffer 7637 */ 7638 7639 if (*attrbuf != (char *)NULL) { 7640 free(*attrbuf); 7641 *attrbuf = NULL; 7642 } 7643 7644 /* 7645 * First add in fixed size stuff 7646 */ 7647 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 7648 7649 /* 7650 * Add space for two nulls 7651 */ 7652 stringlen = strlen(attrpath) + strlen(filename) + 2; 7653 complen = stringlen + sizeof (struct xattr_buf); 7654 7655 len += stringlen; 7656 7657 /* 7658 * Now add on space for link info if any 7659 */ 7660 7661 if (linkinfo != NULL) { 7662 /* 7663 * Again add space for two nulls 7664 */ 7665 linkstringlen = strlen(linkinfo->pathname) + 7666 strlen(linkinfo->attrname) + 2; 7667 linklen = linkstringlen + sizeof (struct xattr_buf); 7668 len += linklen; 7669 } else { 7670 linklen = 0; 7671 } 7672 7673 /* 7674 * Now add padding to end to fill out TBLOCK 7675 * 7676 * Function returns size of real data and not size + padding. 7677 */ 7678 7679 totalen = ROUNDTOTBLOCK(len); 7680 7681 if ((bufhead = calloc(1, totalen)) == NULL) { 7682 fatal(gettext("Out of memory.")); 7683 } 7684 7685 7686 /* 7687 * Now we can fill in the necessary pieces 7688 */ 7689 7690 /* 7691 * first fill in the fixed header 7692 */ 7693 hptr = (struct xattr_hdr *)bufhead; 7694 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 7695 (void) sprintf(hptr->h_component_len, "%0*d", 7696 sizeof (hptr->h_component_len) - 1, complen); 7697 (void) sprintf(hptr->h_link_component_len, "%0*d", 7698 sizeof (hptr->h_link_component_len) - 1, linklen); 7699 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 7700 7701 /* 7702 * Now fill in the filename + attrnames section 7703 * The filename and attrnames section can be composed of two or more 7704 * path segments separated by a null character. The first segment 7705 * is the path to the parent file that roots the entire sequence in 7706 * the normal name space. The remaining segments describes a path 7707 * rooted at the hidden extended attribute directory of the leaf file of 7708 * the previous segment, making it possible to name attributes on 7709 * attributes. Thus, if we are just archiving an extended attribute, 7710 * the second segment will contain the attribute name. If we are 7711 * archiving a system attribute of an extended attribute, then the 7712 * second segment will contain the attribute name, and a third segment 7713 * will contain the system attribute name. The attribute pathing 7714 * information is obtained from 'attrpath'. 7715 */ 7716 7717 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 7718 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 7719 stringlen); 7720 (void) strcpy(tptr->h_names, filename); 7721 attrnames_index = strlen(filename) + 1; 7722 (void) strcpy(&tptr->h_names[attrnames_index], attrpath); 7723 tptr->h_typeflag = typeflag; 7724 7725 /* 7726 * Split the attrnames section into two segments if 'attrpath' 7727 * contains pathing information for a system attribute of an 7728 * extended attribute. We split them by replacing the '/' with 7729 * a '\0'. 7730 */ 7731 if ((aptr = strpbrk(&tptr->h_names[attrnames_index], "/")) != NULL) { 7732 *aptr = '\0'; 7733 } 7734 7735 /* 7736 * Now fill in the optional link section if we have one 7737 */ 7738 7739 if (linkinfo != (struct linkbuf *)NULL) { 7740 tptr = (struct xattr_buf *)(bufhead + 7741 sizeof (struct xattr_hdr) + complen); 7742 7743 (void) sprintf(tptr->h_namesz, "%0*d", 7744 sizeof (tptr->h_namesz) - 1, linkstringlen); 7745 (void) strcpy(tptr->h_names, linkinfo->pathname); 7746 (void) strcpy( 7747 &tptr->h_names[strlen(linkinfo->pathname) + 1], 7748 linkinfo->attrname); 7749 tptr->h_typeflag = typeflag; 7750 } 7751 *attrbuf = (char *)bufhead; 7752 *rlen = len; 7753 } 7754 7755 #else 7756 static void 7757 prepare_xattr( 7758 char **attrbuf, 7759 char *filename, 7760 char *attrname, 7761 char typeflag, 7762 struct linkbuf *linkinfo, 7763 int *rlen) 7764 { 7765 *attrbuf = NULL; 7766 *rlen = 0; 7767 } 7768 #endif 7769 7770 int 7771 getstat(int dirfd, char *longname, char *shortname, char *attrparent) 7772 { 7773 7774 int i, j; 7775 int printerr; 7776 int slnkerr; 7777 struct stat symlnbuf; 7778 7779 if (!hflag) 7780 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 7781 else 7782 i = fstatat(dirfd, shortname, &stbuf, 0); 7783 7784 if (i < 0) { 7785 /* Initialize flag to print error mesg. */ 7786 printerr = 1; 7787 /* 7788 * If stat is done, then need to do lstat 7789 * to determine whether it's a sym link 7790 */ 7791 if (hflag) { 7792 /* Save returned error */ 7793 slnkerr = errno; 7794 7795 j = fstatat(dirfd, shortname, 7796 &symlnbuf, AT_SYMLINK_NOFOLLOW); 7797 /* 7798 * Suppress error message when file is a symbolic link 7799 * and function modifier 'l' is off. Exception: when 7800 * a symlink points to a symlink points to a 7801 * symlink ... and we get past MAXSYMLINKS. That 7802 * error will cause a file not to be archived, and 7803 * needs to be printed. 7804 */ 7805 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 7806 (S_ISLNK(symlnbuf.st_mode))) 7807 printerr = 0; 7808 7809 /* 7810 * Restore errno in case the lstat 7811 * on symbolic link change 7812 */ 7813 errno = slnkerr; 7814 } 7815 7816 if (printerr) { 7817 (void) fprintf(stderr, gettext( 7818 "tar: %s%s%s%s: %s\n"), 7819 (attrparent == NULL) ? "" : gettext("attribute "), 7820 (attrparent == NULL) ? "" : attrparent, 7821 (attrparent == NULL) ? "" : gettext(" of "), 7822 longname, strerror(errno)); 7823 Errflg = 1; 7824 } 7825 return (1); 7826 } 7827 return (0); 7828 } 7829 7830 /* 7831 * Recursively archive the extended attributes and/or extended system attributes 7832 * of the base file, longname. Note: extended system attribute files will be 7833 * archived only if the extended system attributes are not transient (i.e. the 7834 * extended system attributes are other than the default values). 7835 * 7836 * If -@ was specified and the underlying file system supports it, archive the 7837 * extended attributes, and if there is a system attribute associated with the 7838 * extended attribute, then recursively call xattrs_put() to archive the 7839 * hidden attribute directory and the extended system attribute. If -/ was 7840 * specified and the underlying file system supports it, archive the extended 7841 * system attributes. Read-only extended system attributes are never archived. 7842 * 7843 * Currently, there cannot be attributes on attributes; only system 7844 * attributes on attributes. In addition, there cannot be attributes on 7845 * system attributes. A file and it's attribute directory hierarchy looks as 7846 * follows: 7847 * longname ----> . ("." is the hidden attribute directory) 7848 * | 7849 * ---------------------------- 7850 * | | 7851 * <sys_attr_name> <attr_name> ----> . 7852 * | 7853 * <sys_attr_name> 7854 * 7855 */ 7856 #if defined(O_XATTR) 7857 static void 7858 xattrs_put(char *longname, char *shortname, char *parent, char *attrparent) 7859 { 7860 char *filename = (attrparent == NULL) ? shortname : attrparent; 7861 int arc_rwsysattr = 0; 7862 int dirfd; 7863 int fd = -1; 7864 int rw_sysattr = 0; 7865 int ext_attr = 0; 7866 int rc; 7867 DIR *dirp; 7868 struct dirent *dp; 7869 attr_data_t *attrinfo = NULL; 7870 7871 /* 7872 * If the underlying file system supports it, then archive the extended 7873 * attributes if -@ was specified, and the extended system attributes 7874 * if -/ was specified. 7875 */ 7876 if (verify_attr_support(filename, (attrparent == NULL), ARC_CREATE, 7877 &ext_attr) != ATTR_OK) { 7878 return; 7879 } 7880 7881 /* 7882 * Only want to archive a read-write extended system attribute file 7883 * if it contains extended system attribute settings that are not the 7884 * default values. 7885 */ 7886 #if defined(_PC_SATTR_ENABLED) 7887 if (saflag) { 7888 int filefd; 7889 nvlist_t *slist = NULL; 7890 7891 /* Determine if there are non-transient system attributes */ 7892 errno = 0; 7893 if ((filefd = open(filename, O_RDONLY)) == -1) { 7894 if (attrparent == NULL) { 7895 vperror(0, gettext( 7896 "unable to open file %s"), longname); 7897 } 7898 return; 7899 } 7900 if (((slist = sysattr_list(basename(myname), filefd, 7901 filename)) != NULL) || (errno != 0)) { 7902 arc_rwsysattr = 1; 7903 } 7904 if (slist != NULL) { 7905 (void) nvlist_free(slist); 7906 slist = NULL; 7907 } 7908 (void) close(filefd); 7909 } 7910 7911 /* 7912 * If we aren't archiving extended system attributes, and we are 7913 * processing an attribute, or if we are archiving extended system 7914 * attributes, and there are are no extended attributes, then there's 7915 * no need to open up the attribute directory of the file unless the 7916 * extended system attributes are not transient (i.e, the system 7917 * attributes are not the default values). 7918 */ 7919 if ((arc_rwsysattr == 0) && ((attrparent != NULL) || 7920 (saflag && !ext_attr))) { 7921 return; 7922 } 7923 #endif /* _PC_SATTR_ENABLED */ 7924 7925 /* open the parent attribute directory */ 7926 fd = attropen(filename, ".", O_RDONLY); 7927 if (fd < 0) { 7928 vperror(0, gettext( 7929 "unable to open attribute directory for %s%s%sfile %s"), 7930 (attrparent == NULL) ? "" : gettext("attribute "), 7931 (attrparent == NULL) ? "" : attrparent, 7932 (attrparent == NULL) ? "" : gettext(" of "), 7933 longname); 7934 return; 7935 } 7936 7937 /* 7938 * We need to change into the parent's attribute directory to determine 7939 * if each of the attributes should be archived. 7940 */ 7941 if (fchdir(fd) < 0) { 7942 vperror(0, gettext( 7943 "cannot change to attribute directory of %s%s%sfile %s"), 7944 (attrparent == NULL) ? "" : gettext("attribute "), 7945 (attrparent == NULL) ? "" : attrparent, 7946 (attrparent == NULL) ? "" : gettext(" of "), 7947 longname); 7948 (void) close(fd); 7949 return; 7950 } 7951 7952 if (((dirfd = dup(fd)) == -1) || 7953 ((dirp = fdopendir(dirfd)) == NULL)) { 7954 (void) fprintf(stderr, gettext( 7955 "tar: unable to open dir pointer for %s%s%sfile %s\n"), 7956 (attrparent == NULL) ? "" : gettext("attribute "), 7957 (attrparent == NULL) ? "" : attrparent, 7958 (attrparent == NULL) ? "" : gettext(" of "), 7959 longname); 7960 if (fd > 0) { 7961 (void) close(fd); 7962 } 7963 return; 7964 } 7965 7966 while (dp = readdir(dirp)) { 7967 if (strcmp(dp->d_name, "..") == 0) { 7968 continue; 7969 } else if (strcmp(dp->d_name, ".") == 0) { 7970 Hiddendir = 1; 7971 } else { 7972 Hiddendir = 0; 7973 } 7974 7975 /* Determine if this attribute should be archived */ 7976 if (verify_attr(dp->d_name, attrparent, arc_rwsysattr, 7977 &rw_sysattr) != ATTR_OK) { 7978 continue; 7979 } 7980 7981 /* gather the attribute's information to pass to putfile() */ 7982 if ((fill_in_attr_info(dp->d_name, longname, attrparent, 7983 fd, rw_sysattr, &attrinfo)) == 1) { 7984 continue; 7985 } 7986 7987 /* add the attribute to the archive */ 7988 rc = putfile(longname, dp->d_name, parent, attrinfo, 7989 XATTR_FILE, LEV0, SYMLINK_LEV0); 7990 7991 if (exitflag) { 7992 break; 7993 } 7994 7995 #if defined(_PC_SATTR_ENABLED) 7996 /* 7997 * If both -/ and -@ were specified, then archive the 7998 * attribute's extended system attributes and hidden directory 7999 * by making a recursive call to xattrs_put(). 8000 */ 8001 if (!rw_sysattr && saflag && atflag && (rc != PUT_AS_LINK) && 8002 (Hiddendir == 0)) { 8003 8004 xattrs_put(longname, shortname, parent, dp->d_name); 8005 8006 /* 8007 * Change back to the parent's attribute directory 8008 * to process any further attributes. 8009 */ 8010 if (fchdir(fd) < 0) { 8011 vperror(0, gettext( 8012 "cannot change back to attribute directory " 8013 "of file %s"), longname); 8014 break; 8015 } 8016 } 8017 #endif /* _PC_SATTR_ENABLED */ 8018 } 8019 8020 if (attrinfo != NULL) { 8021 if (attrinfo->attr_parent != NULL) { 8022 free(attrinfo->attr_parent); 8023 } 8024 free(attrinfo->attr_path); 8025 free(attrinfo); 8026 } 8027 (void) closedir(dirp); 8028 if (fd != -1) { 8029 (void) close(fd); 8030 } 8031 8032 /* Change back to the parent directory of the base file */ 8033 if (attrparent == NULL) { 8034 (void) chdir(parent); 8035 } 8036 Hiddendir = 0; 8037 } 8038 #else 8039 static void 8040 xattrs_put(char *longname, char *shortname, char *parent, char *attrppath) 8041 { 8042 } 8043 #endif /* O_XATTR */ 8044 8045 static int 8046 put_link(char *name, char *longname, char *component, char *longattrname, 8047 char *prefix, int filetype, char type) 8048 { 8049 8050 if (stbuf.st_nlink > 1) { 8051 struct linkbuf *lp; 8052 int found = 0; 8053 8054 for (lp = ihead; lp != NULL; lp = lp->nextp) 8055 if (lp->inum == stbuf.st_ino && 8056 lp->devnum == stbuf.st_dev) { 8057 found++; 8058 break; 8059 } 8060 if (found) { 8061 #if defined(O_XATTR) 8062 if (filetype == XATTR_FILE) 8063 if (put_xattr_hdr(longname, component, 8064 longattrname, prefix, type, filetype, lp)) { 8065 goto out; 8066 } 8067 #endif 8068 stbuf.st_size = (off_t)0; 8069 if (filetype != XATTR_FILE) { 8070 tomodes(&stbuf); 8071 if (chk_path_build(name, longname, lp->pathname, 8072 prefix, type, filetype) > 0) { 8073 goto out; 8074 } 8075 } 8076 8077 if (mulvol && tapepos + 1 >= blocklim) 8078 newvol(); 8079 (void) writetbuf((char *)&dblock, 1); 8080 /* 8081 * write_ancillary() is not needed here. 8082 * The first link is handled in the following 8083 * else statement. No need to process ACLs 8084 * for other hard links since they are the 8085 * same file. 8086 */ 8087 8088 if (vflag) { 8089 #ifdef DEBUG 8090 if (NotTape) 8091 DEBUG("seek = %" FMT_blkcnt_t 8092 "K\t", K(tapepos), 0); 8093 #endif 8094 if (filetype == XATTR_FILE) { 8095 (void) fprintf(vfile, gettext( 8096 "a %s attribute %s link to " 8097 "%s attribute %s\n"), 8098 name, component, name, 8099 lp->attrname); 8100 } else { 8101 (void) fprintf(vfile, gettext( 8102 "a %s link to %s\n"), 8103 longname, lp->pathname); 8104 } 8105 } 8106 lp->count--; 8107 return (0); 8108 } else { 8109 lp = (struct linkbuf *)getmem(sizeof (*lp)); 8110 if (lp != (struct linkbuf *)NULL) { 8111 lp->nextp = ihead; 8112 ihead = lp; 8113 lp->inum = stbuf.st_ino; 8114 lp->devnum = stbuf.st_dev; 8115 lp->count = stbuf.st_nlink - 1; 8116 if (filetype == XATTR_FILE) { 8117 (void) strcpy(lp->pathname, longname); 8118 (void) strcpy(lp->attrname, 8119 component); 8120 } else { 8121 (void) strcpy(lp->pathname, longname); 8122 (void) strcpy(lp->attrname, ""); 8123 } 8124 } 8125 } 8126 } 8127 8128 out: 8129 return (1); 8130 } 8131 8132 static int 8133 put_extra_attributes(char *longname, char *shortname, char *longattrname, 8134 char *prefix, int filetype, char typeflag) 8135 { 8136 static acl_t *aclp = NULL; 8137 int error; 8138 8139 if (aclp != NULL) { 8140 acl_free(aclp); 8141 aclp = NULL; 8142 } 8143 #if defined(O_XATTR) 8144 if ((atflag || saflag) && (filetype == XATTR_FILE)) { 8145 if (put_xattr_hdr(longname, shortname, longattrname, prefix, 8146 typeflag, filetype, NULL)) { 8147 return (1); 8148 } 8149 } 8150 #endif 8151 8152 /* ACL support */ 8153 if (pflag) { 8154 char *secinfo = NULL; 8155 int len = 0; 8156 8157 /* ACL support */ 8158 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 8159 /* 8160 * Get ACL info: dont bother allocating space if 8161 * there is only a trivial ACL. 8162 */ 8163 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 8164 &aclp)) != 0) { 8165 (void) fprintf(stderr, gettext( 8166 "%s: failed to retrieve acl : %s\n"), 8167 longname, acl_strerror(error)); 8168 return (1); 8169 } 8170 } 8171 8172 /* append security attributes if any */ 8173 if (aclp != NULL) { 8174 (void) append_secattr(&secinfo, &len, acl_cnt(aclp), 8175 acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT | 8176 ACL_SID_FMT), (acl_type(aclp) == ACLENT_T) ? 8177 UFSD_ACL : ACE_ACL); 8178 } 8179 8180 if (Tflag) { 8181 /* append Trusted Extensions extended attributes */ 8182 append_ext_attr(shortname, &secinfo, &len); 8183 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8184 8185 } else if (aclp != NULL) { 8186 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8187 } 8188 } 8189 return (0); 8190 } 8191 8192 #if defined(O_XATTR) 8193 static int 8194 put_xattr_hdr(char *longname, char *shortname, char *longattrname, char *prefix, 8195 int typeflag, int filetype, struct linkbuf *lp) 8196 { 8197 char *lname = NULL; 8198 char *sname = NULL; 8199 int error = 0; 8200 static char *attrbuf = NULL; 8201 int attrlen; 8202 8203 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 8204 strlen(shortname) + strlen(".hdr") + 1); 8205 8206 if (lname == NULL) { 8207 fatal(gettext("Out of Memory.")); 8208 } 8209 sname = malloc(sizeof (char) * strlen(shortname) + 8210 strlen(".hdr") + 1); 8211 if (sname == NULL) { 8212 fatal(gettext("Out of Memory.")); 8213 } 8214 8215 (void) sprintf(sname, "%s.hdr", shortname); 8216 (void) sprintf(lname, "/dev/null/%s", sname); 8217 8218 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 8219 sizeof (dblock.dbuf.name)) { 8220 fatal(gettext( 8221 "Buffer overflow writing extended attribute file name")); 8222 } 8223 8224 /* 8225 * dump extended attr lookup info 8226 */ 8227 prepare_xattr(&attrbuf, longname, longattrname, typeflag, lp, &attrlen); 8228 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 8229 8230 (void) sprintf(lname, "/dev/null/%s", shortname); 8231 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 8232 8233 /* 8234 * Set up filename for attribute 8235 */ 8236 8237 error = build_dblock(lname, tchar, '0', filetype, 8238 &stbuf, stbuf.st_dev, prefix); 8239 free(lname); 8240 free(sname); 8241 8242 return (error); 8243 } 8244 #endif 8245 8246 #if defined(O_XATTR) 8247 static int 8248 read_xattr_hdr(attr_data_t **attrinfo) 8249 { 8250 char buf[TBLOCK]; 8251 char *attrparent = NULL; 8252 blkcnt_t blocks; 8253 char *tp; 8254 off_t bytes; 8255 int comp_len, link_len; 8256 int namelen; 8257 int attrparentlen; 8258 int parentfilelen; 8259 8260 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 8261 return (1); 8262 8263 bytes = stbuf.st_size; 8264 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 8265 (void) fprintf(stderr, gettext( 8266 "Insufficient memory for extended attribute\n")); 8267 return (1); 8268 } 8269 8270 tp = (char *)xattrhead; 8271 blocks = TBLOCKS(bytes); 8272 while (blocks-- > 0) { 8273 readtape(buf); 8274 if (bytes <= TBLOCK) { 8275 (void) memcpy(tp, buf, (size_t)bytes); 8276 break; 8277 } else { 8278 (void) memcpy(tp, buf, TBLOCK); 8279 tp += TBLOCK; 8280 } 8281 bytes -= TBLOCK; 8282 } 8283 8284 /* 8285 * Validate that we can handle header format 8286 */ 8287 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 8288 (void) fprintf(stderr, 8289 gettext("Unknown extended attribute format encountered\n")); 8290 (void) fprintf(stderr, 8291 gettext("Disabling extended attribute parsing\n")); 8292 xattrbadhead = 1; 8293 return (0); 8294 } 8295 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 8296 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 8297 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 8298 sizeof (struct xattr_hdr)); 8299 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 8300 if (link_len > 0) 8301 xattr_linkp = (struct xattr_buf *) 8302 ((int)xattrp + (int)comp_len); 8303 else 8304 xattr_linkp = NULL; 8305 8306 /* 8307 * Gather the attribute path from the filename and attrnames section. 8308 * The filename and attrnames section can be composed of two or more 8309 * path segments separated by a null character. The first segment 8310 * is the path to the parent file that roots the entire sequence in 8311 * the normal name space. The remaining segments describes a path 8312 * rooted at the hidden extended attribute directory of the leaf file of 8313 * the previous segment, making it possible to name attributes on 8314 * attributes. 8315 */ 8316 parentfilelen = strlen(xattrp->h_names); 8317 xattrapath = xattrp->h_names + parentfilelen + 1; 8318 if ((strlen(xattrapath) + parentfilelen + 2) < namelen) { 8319 /* 8320 * The attrnames section contains a system attribute on an 8321 * attribute. Save the name of the attribute for use later, 8322 * and replace the null separating the attribute name from 8323 * the system attribute name with a '/' so that xattrapath can 8324 * be used to display messages with the full attribute path name 8325 * rooted at the hidden attribute directory of the base file 8326 * in normal name space. 8327 */ 8328 attrparent = strdup(xattrapath); 8329 attrparentlen = strlen(attrparent); 8330 xattrapath[attrparentlen] = '/'; 8331 } 8332 if ((fill_in_attr_info((attrparent == NULL) ? xattrapath : 8333 xattrapath + attrparentlen + 1, xattrapath, attrparent, 8334 -1, 0, attrinfo)) == 1) { 8335 free(attrparent); 8336 return (1); 8337 } 8338 8339 /* Gather link info */ 8340 if (xattr_linkp) { 8341 xattr_linkaname = xattr_linkp->h_names + 8342 strlen(xattr_linkp->h_names) + 1; 8343 } else { 8344 xattr_linkaname = NULL; 8345 } 8346 8347 return (0); 8348 } 8349 #else 8350 static int 8351 read_xattr_hdr(attr_data_t **attrinfo) 8352 { 8353 return (0); 8354 } 8355 #endif 8356 8357 /* 8358 * skip over extra slashes in string. 8359 * 8360 * For example: 8361 * /usr/tmp///// 8362 * 8363 * would return pointer at 8364 * /usr/tmp///// 8365 * ^ 8366 */ 8367 static char * 8368 skipslashes(char *string, char *start) 8369 { 8370 while ((string > start) && *(string - 1) == '/') { 8371 string--; 8372 } 8373 8374 return (string); 8375 } 8376 8377 /* 8378 * Return the parent directory of a given path. 8379 * 8380 * Examples: 8381 * /usr/tmp return /usr 8382 * /usr/tmp/file return /usr/tmp 8383 * / returns . 8384 * /usr returns / 8385 * file returns . 8386 * 8387 * dir is assumed to be at least as big as path. 8388 */ 8389 static void 8390 get_parent(char *path, char *dir) 8391 { 8392 char *s; 8393 char tmpdir[PATH_MAX + 1]; 8394 8395 if (strlen(path) > PATH_MAX) { 8396 fatal(gettext("pathname is too long")); 8397 } 8398 (void) strcpy(tmpdir, path); 8399 chop_endslashes(tmpdir); 8400 8401 if ((s = strrchr(tmpdir, '/')) == NULL) { 8402 (void) strcpy(dir, "."); 8403 } else { 8404 s = skipslashes(s, tmpdir); 8405 *s = '\0'; 8406 if (s == tmpdir) 8407 (void) strcpy(dir, "/"); 8408 else 8409 (void) strcpy(dir, tmpdir); 8410 } 8411 } 8412 8413 #if defined(O_XATTR) 8414 static char * 8415 get_component(char *path) 8416 { 8417 char *ptr; 8418 8419 ptr = strrchr(path, '/'); 8420 if (ptr == NULL) { 8421 return (path); 8422 } else { 8423 /* 8424 * Handle trailing slash 8425 */ 8426 if (*(ptr + 1) == '\0') 8427 return (ptr); 8428 else 8429 return (ptr + 1); 8430 } 8431 } 8432 #else 8433 static char * 8434 get_component(char *path) 8435 { 8436 return (path); 8437 } 8438 #endif 8439 8440 #if defined(O_XATTR) 8441 static int 8442 retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, char *name, 8443 int oflag, mode_t mode) 8444 { 8445 int dirfd; 8446 int ofilefd = -1; 8447 struct timeval times[2]; 8448 mode_t newmode; 8449 struct stat parentstat; 8450 acl_t *aclp = NULL; 8451 int error; 8452 8453 /* 8454 * We couldn't get to attrdir. See if its 8455 * just a mode problem on the parent file. 8456 * for example: a mode such as r-xr--r-- 8457 * on a ufs file system without extended 8458 * system attribute support won't let us 8459 * create an attribute dir if it doesn't 8460 * already exist, and on a ufs file system 8461 * with extended system attribute support 8462 * won't let us open the attribute for 8463 * write. 8464 * 8465 * If file has a non-trivial ACL, then save it 8466 * off so that we can place it back on after doing 8467 * chmod's. 8468 */ 8469 if ((dirfd = openat(cwd, (pattr == NULL) ? dirp : pattr, 8470 O_RDONLY)) == -1) { 8471 return (-1); 8472 } 8473 if (fstat(dirfd, &parentstat) == -1) { 8474 (void) fprintf(stderr, gettext( 8475 "tar: cannot stat %sfile %s: %s\n"), 8476 (pdirfd == -1) ? "" : gettext("parent of "), 8477 (pdirfd == -1) ? dirp : name, strerror(errno)); 8478 return (-1); 8479 } 8480 if ((error = facl_get(dirfd, ACL_NO_TRIVIAL, &aclp)) != 0) { 8481 (void) fprintf(stderr, gettext( 8482 "tar: failed to retrieve ACL on %sfile %s: %s\n"), 8483 (pdirfd == -1) ? "" : gettext("parent of "), 8484 (pdirfd == -1) ? dirp : name, strerror(errno)); 8485 return (-1); 8486 } 8487 8488 newmode = S_IWUSR | parentstat.st_mode; 8489 if (fchmod(dirfd, newmode) == -1) { 8490 (void) fprintf(stderr, 8491 gettext( 8492 "tar: cannot fchmod %sfile %s to %o: %s\n"), 8493 (pdirfd == -1) ? "" : gettext("parent of "), 8494 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8495 if (aclp) 8496 acl_free(aclp); 8497 return (-1); 8498 } 8499 8500 8501 if (pdirfd == -1) { 8502 /* 8503 * We weren't able to create the attribute directory before. 8504 * Now try again. 8505 */ 8506 ofilefd = attropen(dirp, ".", oflag); 8507 } else { 8508 /* 8509 * We weren't able to create open the attribute before. 8510 * Now try again. 8511 */ 8512 ofilefd = openat(pdirfd, name, oflag, mode); 8513 } 8514 8515 /* 8516 * Put mode back to original 8517 */ 8518 if (fchmod(dirfd, parentstat.st_mode) == -1) { 8519 (void) fprintf(stderr, 8520 gettext("tar: cannot chmod %sfile %s to %o: %s\n"), 8521 (pdirfd == -1) ? "" : gettext("parent of "), 8522 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8523 } 8524 8525 if (aclp) { 8526 error = facl_set(dirfd, aclp); 8527 if (error) { 8528 (void) fprintf(stderr, 8529 gettext("tar: failed to set acl entries on " 8530 "%sfile %s\n"), 8531 (pdirfd == -1) ? "" : gettext("parent of "), 8532 (pdirfd == -1) ? dirp : name); 8533 } 8534 acl_free(aclp); 8535 } 8536 8537 /* 8538 * Put back time stamps 8539 */ 8540 8541 times[0].tv_sec = parentstat.st_atime; 8542 times[0].tv_usec = 0; 8543 times[1].tv_sec = parentstat.st_mtime; 8544 times[1].tv_usec = 0; 8545 8546 (void) futimesat(cwd, (pattr == NULL) ? dirp : pattr, times); 8547 8548 (void) close(dirfd); 8549 8550 return (ofilefd); 8551 } 8552 #endif 8553 8554 #if !defined(O_XATTR) 8555 static int 8556 openat64(int fd, const char *name, int oflag, mode_t cmode) 8557 { 8558 return (open64(name, oflag, cmode)); 8559 } 8560 8561 static int 8562 openat(int fd, const char *name, int oflag, mode_t cmode) 8563 { 8564 return (open(name, oflag, cmode)); 8565 } 8566 8567 static int 8568 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 8569 { 8570 if (flag == AT_SYMLINK_NOFOLLOW) 8571 return (lchown(name, owner, group)); 8572 else 8573 return (chown(name, owner, group)); 8574 } 8575 8576 static int 8577 renameat(int fromfd, char *old, int tofd, char *new) 8578 { 8579 return (rename(old, new)); 8580 } 8581 8582 static int 8583 futimesat(int fd, char *path, struct timeval times[2]) 8584 { 8585 return (utimes(path, times)); 8586 } 8587 8588 static int 8589 unlinkat(int dirfd, char *path, int flag) 8590 { 8591 if (flag == AT_REMOVEDIR) 8592 return (rmdir(path)); 8593 else 8594 return (unlink(path)); 8595 } 8596 8597 static int 8598 fstatat(int fd, char *path, struct stat *buf, int flag) 8599 { 8600 if (flag == AT_SYMLINK_NOFOLLOW) 8601 return (lstat(path, buf)); 8602 else 8603 return (stat(path, buf)); 8604 } 8605 8606 static int 8607 attropen(char *file, char *attr, int omode, mode_t cmode) 8608 { 8609 errno = ENOTSUP; 8610 return (-1); 8611 } 8612 #endif 8613 8614 static void 8615 chop_endslashes(char *path) 8616 { 8617 char *end, *ptr; 8618 8619 /* 8620 * Chop of slashes, but not if all we have is slashes 8621 * for example: //// 8622 * should make no changes, otherwise it will screw up 8623 * checkdir 8624 */ 8625 end = &path[strlen(path) -1]; 8626 if (*end == '/' && end != path) { 8627 ptr = skipslashes(end, path); 8628 if (ptr != NULL && ptr != path) { 8629 *ptr = '\0'; 8630 } 8631 } 8632 } 8633 /* Trusted Extensions */ 8634 8635 /* 8636 * append_ext_attr(): 8637 * 8638 * Append extended attributes and other information into the buffer 8639 * that gets written to the ancillary file. 8640 * 8641 * With option 'T', we create a tarfile which 8642 * has an ancillary file each corresponding archived file. 8643 * Each ancillary file contains 1 or more of the 8644 * following attributes: 8645 * 8646 * attribute type attribute process procedure 8647 * ---------------- ---------------- -------------------------- 8648 * DIR_TYPE = 'D' directory flag append if a directory 8649 * LBL_TYPE = 'L' SL[IL] or SL append ascii label 8650 * 8651 * 8652 */ 8653 static void 8654 append_ext_attr(char *shortname, char **secinfo, int *len) 8655 { 8656 bslabel_t b_slabel; /* binary sensitvity label */ 8657 char *ascii = NULL; /* ascii label */ 8658 8659 /* 8660 * For each attribute type, append it if it is 8661 * relevant to the file type. 8662 */ 8663 8664 /* 8665 * For attribute type DIR_TYPE, 8666 * append it to the following file type: 8667 * 8668 * S_IFDIR: directories 8669 */ 8670 8671 /* 8672 * For attribute type LBL_TYPE, 8673 * append it to the following file type: 8674 * 8675 * S_IFDIR: directories (including mld, sld) 8676 * S_IFLNK: symbolic link 8677 * S_IFREG: regular file but not hard link 8678 * S_IFIFO: FIFO file but not hard link 8679 * S_IFCHR: char special file but not hard link 8680 * S_IFBLK: block special file but not hard link 8681 */ 8682 switch (stbuf.st_mode & S_IFMT) { 8683 8684 case S_IFDIR: 8685 8686 /* 8687 * append DIR_TYPE 8688 */ 8689 (void) append_secattr(secinfo, len, 1, 8690 "\0", DIR_TYPE); 8691 8692 /* 8693 * Get and append attribute types LBL_TYPE. 8694 * For directories, LBL_TYPE contains SL. 8695 */ 8696 /* get binary sensitivity label */ 8697 if (getlabel(shortname, &b_slabel) != 0) { 8698 (void) fprintf(stderr, 8699 gettext("tar: can't get sensitvity label for " 8700 " %s, getlabel() error: %s\n"), 8701 shortname, strerror(errno)); 8702 } else { 8703 /* get ascii SL */ 8704 if (bsltos(&b_slabel, &ascii, 8705 0, 0) <= 0) { 8706 (void) fprintf(stderr, 8707 gettext("tar: can't get ascii SL for" 8708 " %s\n"), shortname); 8709 } else { 8710 /* append LBL_TYPE */ 8711 (void) append_secattr(secinfo, len, 8712 strlen(ascii) + 1, ascii, 8713 LBL_TYPE); 8714 8715 /* free storage */ 8716 if (ascii != NULL) { 8717 free(ascii); 8718 ascii = (char *)0; 8719 } 8720 } 8721 8722 } 8723 break; 8724 8725 case S_IFLNK: 8726 case S_IFREG: 8727 case S_IFIFO: 8728 case S_IFCHR: 8729 case S_IFBLK: 8730 8731 /* get binary sensitivity label */ 8732 if (getlabel(shortname, &b_slabel) != 0) { 8733 (void) fprintf(stderr, 8734 gettext("tar: can't get sensitivty label for %s, " 8735 "getlabel() error: %s\n"), 8736 shortname, strerror(errno)); 8737 } else { 8738 /* get ascii IL[SL] */ 8739 if (bsltos(&b_slabel, &ascii, 0, 0) <= 0) { 8740 (void) fprintf(stderr, 8741 gettext("tar: can't translate sensitivity " 8742 " label for %s\n"), shortname); 8743 } else { 8744 char *cmw_label; 8745 size_t cmw_length; 8746 8747 cmw_length = strlen("ADMIN_LOW [] ") + 8748 strlen(ascii); 8749 if ((cmw_label = malloc(cmw_length)) == NULL) { 8750 (void) fprintf(stderr, gettext( 8751 "Insufficient memory for label\n")); 8752 exit(1); 8753 } 8754 /* append LBL_TYPE */ 8755 (void) snprintf(cmw_label, cmw_length, 8756 "ADMIN_LOW [%s]", ascii); 8757 (void) append_secattr(secinfo, len, 8758 strlen(cmw_label) + 1, cmw_label, 8759 LBL_TYPE); 8760 8761 /* free storage */ 8762 if (ascii != NULL) { 8763 free(cmw_label); 8764 free(ascii); 8765 ascii = (char *)0; 8766 } 8767 } 8768 } 8769 break; 8770 8771 default: 8772 break; 8773 } /* end switch for LBL_TYPE */ 8774 8775 8776 /* DONE !! */ 8777 return; 8778 8779 } /* end of append_ext_attr */ 8780 8781 8782 /* 8783 * Name: extract_attr() 8784 * 8785 * Description: 8786 * Process attributes from the ancillary file due to 8787 * the T option. 8788 * 8789 * Call by doxtract() as part of the switch case structure. 8790 * Making this a separate routine because the nesting are too 8791 * deep in doxtract, thus, leaving very little space 8792 * on each line for instructions. 8793 * 8794 * With option 'T', we extract from a TS 8 or TS 2.5 ancillary file 8795 * 8796 * For option 'T', following are possible attributes in 8797 * a TS 8 ancillary file: (NOTE: No IL support) 8798 * 8799 * attribute type attribute process procedure 8800 * ---------------- ---------------- ------------------------- 8801 * # LBL_TYPE = 'L' SL construct binary label 8802 * # APRIV_TYPE = 'P' allowed priv construct privileges 8803 * # FPRIV_TYPE = 'p' forced priv construct privileges 8804 * # COMP_TYPE = 'C' path component construct real path 8805 * # DIR_TYPE = 'D' directory flag note it is a directory 8806 * $ UFSD_ACL = '1' ACL data construct ACL entries 8807 * ATTR_FLAG_TYPE = 'F' file attr flags construct binary flags 8808 * LK_COMP_TYPE = 'K' linked path comp construct linked real path 8809 * 8810 * note: # = attribute names common between TS 8 & TS 2.5 ancillary 8811 * files. 8812 * $ = ACL attribute is processed for the option 'p', it doesn't 8813 * need option 'T'. 8814 * 8815 * Trusted Extensions ignores APRIV_TYPE, FPRIV_TYPE, and ATTR_FLAG_TYPE 8816 * 8817 */ 8818 static void 8819 extract_attr(char **file_ptr, struct sec_attr *attr) 8820 { 8821 int reterr, err; 8822 char *dummy_buf; /* for attribute extract */ 8823 8824 dummy_buf = attr->attr_info; 8825 8826 switch (attr->attr_type) { 8827 8828 case DIR_TYPE: 8829 8830 dir_flag++; 8831 break; 8832 8833 case LBL_TYPE: 8834 8835 /* 8836 * LBL_TYPE is used to indicate SL for directory, and 8837 * CMW label for other file types. 8838 */ 8839 8840 if (!dir_flag) { /* not directory */ 8841 /* Skip over IL portion */ 8842 char *sl_ptr = strchr(dummy_buf, '['); 8843 8844 if (sl_ptr == NULL) 8845 err = 0; 8846 else 8847 err = stobsl(sl_ptr, &bs_label, 8848 NEW_LABEL, &reterr); 8849 } else { /* directory */ 8850 err = stobsl(dummy_buf, &bs_label, 8851 NEW_LABEL, &reterr); 8852 } 8853 if (err == 0) { 8854 (void) fprintf(stderr, gettext("tar: " 8855 "can't convert %s to binary label\n"), 8856 dummy_buf); 8857 bslundef(&bs_label); 8858 } else if (!blequal(&bs_label, &admin_low) && 8859 !blequal(&bs_label, &admin_high)) { 8860 bslabel_t *from_label; 8861 char *buf; 8862 char tempbuf[MAXPATHLEN]; 8863 8864 if (*orig_namep != '/') { 8865 /* got relative linked to path */ 8866 (void) getcwd(tempbuf, (sizeof (tempbuf))); 8867 (void) strncat(tempbuf, "/", MAXPATHLEN); 8868 } else 8869 *tempbuf = '\0'; 8870 8871 buf = real_path; 8872 (void) strncat(tempbuf, orig_namep, MAXPATHLEN); 8873 from_label = getlabelbypath(tempbuf); 8874 if (from_label != NULL) { 8875 if (blequal(from_label, &admin_low)) { 8876 if ((getpathbylabel(tempbuf, buf, 8877 MAXPATHLEN, &bs_label) == NULL)) { 8878 (void) fprintf(stderr, 8879 gettext("tar: " 8880 "can't get zone root path for " 8881 "%s\n"), tempbuf); 8882 } else 8883 rpath_flag = 1; 8884 } 8885 free(from_label); 8886 } 8887 } 8888 break; 8889 8890 case COMP_TYPE: 8891 8892 rebuild_comp_path(dummy_buf, file_ptr); 8893 break; 8894 8895 case LK_COMP_TYPE: 8896 8897 if (rebuild_lk_comp_path(dummy_buf, file_ptr) 8898 == 0) { 8899 lk_rpath_flag = 1; 8900 } else { 8901 (void) fprintf(stderr, gettext("tar: warning: link's " 8902 "target pathname might be invalid.\n")); 8903 lk_rpath_flag = 0; 8904 } 8905 break; 8906 case APRIV_TYPE: 8907 ignored_aprivs++; 8908 break; 8909 case FPRIV_TYPE: 8910 ignored_fprivs++; 8911 break; 8912 case ATTR_FLAG_TYPE: 8913 ignored_fattrs++; 8914 break; 8915 8916 default: 8917 8918 break; 8919 } 8920 8921 /* done */ 8922 return; 8923 8924 } /* end extract_attr */ 8925 8926 8927 8928 /* 8929 * Name: rebuild_comp_path() 8930 * 8931 * Description: 8932 * Take the string of components passed down by the calling 8933 * routine and parse the values and rebuild the path. 8934 * This routine no longer needs to produce a new real_path 8935 * string because it is produced when the 'L' LABEL_TYPE is 8936 * interpreted. So the only thing done here is to distinguish 8937 * between an SLD and an MLD entry. We only want one, so we 8938 * ignore the MLD entry by setting the mld_flag. 8939 * 8940 * return value: 8941 * none 8942 */ 8943 static void 8944 rebuild_comp_path(char *str, char **namep) 8945 { 8946 char *cp; 8947 8948 while (*str != '\0') { 8949 8950 switch (*str) { 8951 8952 case MLD_TYPE: 8953 8954 str++; 8955 if ((cp = strstr(str, ";;")) != NULL) { 8956 *cp = '\0'; 8957 str = cp + 2; 8958 *cp = ';'; 8959 } 8960 mld_flag = 1; 8961 break; 8962 8963 case SLD_TYPE: 8964 8965 str++; 8966 if ((cp = strstr(str, ";;")) != NULL) { 8967 *cp = '\0'; 8968 str = cp + 2; 8969 *cp = ';'; 8970 } 8971 mld_flag = 0; 8972 break; 8973 8974 case PATH_TYPE: 8975 8976 str++; 8977 if ((cp = strstr(str, ";;")) != NULL) { 8978 *cp = '\0'; 8979 str = cp + 2; 8980 *cp = ';'; 8981 } 8982 break; 8983 } 8984 } 8985 if (rpath_flag) 8986 *namep = real_path; 8987 return; 8988 8989 } /* end rebuild_comp_path() */ 8990 8991 /* 8992 * Name: rebuild_lk_comp_path() 8993 * 8994 * Description: 8995 * Take the string of components passed down by the calling 8996 * routine and parse the values and rebuild the path. 8997 * 8998 * return value: 8999 * 0 = succeeded 9000 * -1 = failed 9001 */ 9002 static int 9003 rebuild_lk_comp_path(char *str, char **namep) 9004 { 9005 char *cp; 9006 int reterr; 9007 bslabel_t bslabel; 9008 char *buf; 9009 char pbuf[MAXPATHLEN]; 9010 char *ptr1, *ptr2; 9011 int plen; 9012 int use_pbuf; 9013 char tempbuf[MAXPATHLEN]; 9014 int mismatch; 9015 bslabel_t *from_label; 9016 char zonename[ZONENAME_MAX]; 9017 zoneid_t zoneid; 9018 9019 /* init stuff */ 9020 use_pbuf = 0; 9021 mismatch = 0; 9022 9023 /* 9024 * For linked to pathname (LK_COMP_TYPE): 9025 * - If the linked to pathname is absolute (start with /), we 9026 * will use it as is. 9027 * - If it is a relative pathname then it is relative to 1 of 2 9028 * directories. For a hardlink, it is relative to the current 9029 * directory. For a symbolic link, it is relative to the 9030 * directory the symbolic link is in. For the symbolic link 9031 * case, set a flag to indicate we need to use the prefix of 9032 * the restored file's pathname with the linked to pathname. 9033 * 9034 * NOTE: At this point, we have no way to determine if we have 9035 * a hardlink or a symbolic link. We will compare the 1st 9036 * component in the prefix portion of the restore file's 9037 * pathname to the 1st component in the attribute data 9038 * (the linked pathname). If they are the same, we will assume 9039 * the link pathname to reconstruct is relative to the current 9040 * directory. Otherwise, we will set a flag indicate we need 9041 * to use a prefix with the reconstructed name. Need to compare 9042 * both the adorned and unadorned version before deciding a 9043 * mismatch. 9044 */ 9045 9046 buf = lk_real_path; 9047 if (*(str + 1) != '/') { /* got relative linked to path */ 9048 ptr1 = orig_namep; 9049 ptr2 = strrchr(ptr1, '/'); 9050 plen = ptr2 - ptr1; 9051 if (plen > 0) { 9052 pbuf[0] = '\0'; 9053 plen++; /* include '/' */ 9054 (void) strncpy(pbuf, ptr1, plen); 9055 *(pbuf + plen) = '\0'; 9056 ptr2 = strchr(pbuf, '/'); 9057 if (strncmp(pbuf, str + 1, ptr2 - pbuf) != 0) 9058 mismatch = 1; 9059 } 9060 9061 if (mismatch == 1) 9062 use_pbuf = 1; 9063 } 9064 9065 buf[0] = '\0'; 9066 9067 while (*str != '\0') { 9068 9069 switch (*str) { 9070 9071 case MLD_TYPE: 9072 9073 str++; 9074 if ((cp = strstr(str, ";;")) != NULL) { 9075 *cp = '\0'; 9076 9077 /* 9078 * Ignore attempts to backup over .MLD. 9079 */ 9080 if (strcmp(str, "../") != 0) 9081 (void) strncat(buf, str, MAXPATHLEN); 9082 str = cp + 2; 9083 *cp = ';'; 9084 } 9085 break; 9086 9087 case SLD_TYPE: 9088 9089 str++; 9090 if ((cp = strstr(str, ";;")) != NULL) { 9091 *cp = '\0'; 9092 9093 /* 9094 * Use the path name in the header if 9095 * error occurs when processing the 9096 * SLD type. 9097 */ 9098 9099 if (!stobsl(str, &bslabel, 9100 NO_CORRECTION, &reterr)) { 9101 (void) fprintf(stderr, gettext( 9102 "tar: can't translate to binary" 9103 "SL for SLD, stobsl() error:" 9104 " %s\n"), strerror(errno)); 9105 return (-1); 9106 } 9107 9108 str = cp + 2; 9109 *cp = ';'; 9110 9111 if (use_pbuf == 1) { 9112 if (*pbuf != '/') { 9113 /* relative linked to path */ 9114 9115 (void) getcwd(tempbuf, 9116 (sizeof (tempbuf))); 9117 (void) strncat(tempbuf, "/", 9118 MAXPATHLEN); 9119 (void) strncat(tempbuf, pbuf, 9120 MAXPATHLEN); 9121 } 9122 else 9123 (void) strcpy(tempbuf, pbuf); 9124 9125 } else if (*buf != '/') { 9126 /* got relative linked to path */ 9127 9128 (void) getcwd(tempbuf, 9129 (sizeof (tempbuf))); 9130 (void) strncat(tempbuf, "/", 9131 MAXPATHLEN); 9132 } else 9133 *tempbuf = '\0'; 9134 9135 (void) strncat(tempbuf, buf, MAXPATHLEN); 9136 *buf = '\0'; 9137 9138 if (blequal(&bslabel, &admin_high)) { 9139 bslabel = admin_low; 9140 } 9141 9142 9143 /* 9144 * Check for cross-zone symbolic links 9145 */ 9146 from_label = getlabelbypath(real_path); 9147 if (rpath_flag && (from_label != NULL) && 9148 !blequal(&bslabel, from_label)) { 9149 if ((zoneid = 9150 getzoneidbylabel(&bslabel)) == -1) { 9151 (void) fprintf(stderr, 9152 gettext("tar: can't get " 9153 "zone ID for %s\n"), 9154 tempbuf); 9155 return (-1); 9156 } 9157 if (zone_getattr(zoneid, ZONE_ATTR_NAME, 9158 &zonename, ZONENAME_MAX) == -1) { 9159 /* Badly configured zone info */ 9160 (void) fprintf(stderr, 9161 gettext("tar: can't get " 9162 "zonename for %s\n"), 9163 tempbuf); 9164 return (-1); 9165 } 9166 (void) strncpy(buf, AUTO_ZONE, 9167 MAXPATHLEN); 9168 (void) strncat(buf, "/", 9169 MAXPATHLEN); 9170 (void) strncat(buf, zonename, 9171 MAXPATHLEN); 9172 } 9173 if (from_label != NULL) 9174 free(from_label); 9175 (void) strncat(buf, tempbuf, MAXPATHLEN); 9176 break; 9177 } 9178 mld_flag = 0; 9179 break; 9180 9181 case PATH_TYPE: 9182 9183 str++; 9184 if ((cp = strstr(str, ";;")) != NULL) { 9185 *cp = '\0'; 9186 (void) strncat(buf, str, MAXPATHLEN); 9187 str = cp + 2; 9188 *cp = ';'; 9189 } 9190 break; 9191 9192 default: 9193 9194 (void) fprintf(stderr, gettext( 9195 "tar: error rebuilding path %s\n"), 9196 *namep); 9197 *buf = '\0'; 9198 str++; 9199 return (-1); 9200 } 9201 } 9202 9203 /* 9204 * Done for LK_COMP_TYPE 9205 */ 9206 9207 return (0); /* component path is rebuilt successfully */ 9208 9209 } /* end rebuild_lk_comp_path() */ 9210 9211 /* 9212 * Name: check_ext_attr() 9213 * 9214 * Description: 9215 * Check the extended attributes for a file being extracted. 9216 * The attributes being checked here are CMW labels. 9217 * ACLs are not set here because they are set by the 9218 * pflag in doxtract(). 9219 * 9220 * If the label doesn't match, return 0 9221 * else return 1 9222 */ 9223 static int 9224 check_ext_attr(char *filename) 9225 { 9226 bslabel_t currentlabel; /* label from zone */ 9227 9228 if (bltype(&bs_label, SUN_SL_UN)) { 9229 /* No label check possible */ 9230 return (0); 9231 } 9232 if (getlabel(filename, ¤tlabel) != 0) { 9233 (void) fprintf(stderr, 9234 gettext("tar: can't get label for " 9235 " %s, getlabel() error: %s\n"), 9236 filename, strerror(errno)); 9237 return (0); 9238 } else if ((blequal(¤tlabel, &bs_label)) == 0) { 9239 char *src_label = NULL; /* ascii label */ 9240 9241 /* get current src SL */ 9242 if (bsltos(&bs_label, &src_label, 0, 0) <= 0) { 9243 (void) fprintf(stderr, 9244 gettext("tar: can't interpret requested label for" 9245 " %s\n"), filename); 9246 } else { 9247 (void) fprintf(stderr, 9248 gettext("tar: can't apply label %s to %s\n"), 9249 src_label, filename); 9250 free(src_label); 9251 } 9252 (void) fprintf(stderr, 9253 gettext("tar: %s not restored\n"), filename); 9254 return (0); 9255 } 9256 return (1); 9257 9258 } /* end check_ext_attr */ 9259 9260 /* Compressing a tar file using compression method provided in 'opt' */ 9261 9262 static void 9263 compress_back() 9264 { 9265 pid_t pid; 9266 int status; 9267 int wret; 9268 struct stat statb; 9269 9270 if (vflag) { 9271 (void) fprintf(vfile, 9272 gettext("Compressing '%s' with '%s'...\n"), 9273 usefile, compress_opt); 9274 } 9275 if ((pid = fork()) == 0) { 9276 (void) execlp(compress_opt, compress_opt, 9277 usefile, NULL); 9278 } else if (pid == -1) { 9279 vperror(1, "%s", gettext("Could not fork")); 9280 } 9281 wait_pid(pid); 9282 if (suffix == 0) { 9283 (void) rename(tfname, usefile); 9284 } 9285 } 9286 9287 /* The magic numbers from /etc/magic */ 9288 9289 #define GZIP_MAGIC "\037\213" 9290 #define BZIP_MAGIC "BZh" 9291 #define COMP_MAGIC "\037\235" 9292 9293 void 9294 check_compression() 9295 { 9296 char magic[2]; 9297 char buf[16]; 9298 FILE *fp; 9299 9300 if ((fp = fopen(usefile, "r")) != NULL) { 9301 (void) fread(buf, sizeof (char), 6, fp); 9302 magic[0] = buf[0]; 9303 magic[1] = buf[1]; 9304 (void) fclose(fp); 9305 } 9306 9307 if (memcmp(magic, GZIP_MAGIC, 2) == 0) { 9308 if (xflag || tflag) { 9309 compress_opt = compress_malloc(strlen(GZCAT) + 1); 9310 (void) strcpy(compress_opt, GZCAT); 9311 } else if (uflag || rflag) { 9312 compress_opt = compress_malloc(strlen(GZIP) + 1); 9313 (void) strcpy(compress_opt, GZIP); 9314 } 9315 } else if (memcmp(magic, BZIP_MAGIC, 2) == 0) { 9316 if (xflag || tflag) { 9317 compress_opt = compress_malloc(strlen(BZCAT) + 1); 9318 (void) strcpy(compress_opt, BZCAT); 9319 } else if (uflag || rflag) { 9320 compress_opt = compress_malloc(strlen(BZIP) + 1); 9321 (void) strcpy(compress_opt, BZIP); 9322 } 9323 } else if (memcmp(magic, COMP_MAGIC, 2) == 0) { 9324 if (xflag || tflag) { 9325 compress_opt = compress_malloc(strlen(ZCAT) + 1); 9326 (void) strcpy(compress_opt, ZCAT); 9327 } else if (uflag || rflag) { 9328 compress_opt = compress_malloc(strlen(COMPRESS) + 1); 9329 (void) strcpy(compress_opt, COMPRESS); 9330 } 9331 } 9332 } 9333 9334 char * 9335 add_suffix() 9336 { 9337 (void) strcpy(tfname, usefile); 9338 if (strcmp(compress_opt, GZIP) == 0) { 9339 if ((suffix = gz_suffix()) == NULL) { 9340 strlcat(tfname, gsuffix[0], sizeof (tfname)); 9341 return (gsuffix[0]); 9342 } 9343 } else if (strcmp(compress_opt, COMPRESS) == 0) { 9344 if ((suffix = gz_suffix()) == NULL) { 9345 strlcat(tfname, gsuffix[6], sizeof (tfname)); 9346 return (gsuffix[6]); 9347 } 9348 } else if (strcmp(compress_opt, BZIP) == 0) { 9349 if ((suffix = bz_suffix()) == NULL) { 9350 strlcat(tfname, bsuffix[0], sizeof (tfname)); 9351 return (bsuffix[0]); 9352 } 9353 } 9354 return (NULL); 9355 } 9356 9357 /* Decompressing a tar file using compression method from the file type */ 9358 void 9359 decompress_file(void) 9360 { 9361 pid_t pid; 9362 int status; 9363 char cmdstr[PATH_MAX]; 9364 char fname[PATH_MAX]; 9365 char *added_suffix; 9366 9367 9368 added_suffix = add_suffix(); 9369 if (added_suffix != NULL) { 9370 (void) rename(usefile, tfname); 9371 } 9372 if ((pid = fork()) == 0) { 9373 if (vflag) { 9374 (void) fprintf(vfile, 9375 gettext("Decompressing '%s' with " 9376 "'%s'...\n"), usefile, compress_opt); 9377 } 9378 (void) execlp(compress_opt, compress_opt, "-df", 9379 tfname, NULL); 9380 (void) fprintf(vfile, gettext("Could not exec %s: %s\n"), 9381 compress_opt, usefile, strerror(errno)); 9382 } else if (pid == -1) { 9383 vperror(1, "Could not fork"); 9384 } 9385 wait_pid(pid); 9386 if (suffix != NULL) { 9387 /* restore the file name - original file was without suffix */ 9388 *(usefile + strlen(usefile) - strlen(suffix)) = '\0'; 9389 } 9390 } 9391 9392 /* Set the archive for writing and then compress the archive */ 9393 pid_t 9394 compress_file(void) 9395 { 9396 int fd[2]; 9397 pid_t pid; 9398 9399 if (vflag) { 9400 (void) fprintf(vfile, gettext("Compressing '%s' with " 9401 "'%s'...\n"), usefile, compress_opt); 9402 } 9403 9404 if (pipe(fd) < 0) { 9405 vperror(1, gettext("Could not create pipe")); 9406 } 9407 if (pid = fork() > 0) { 9408 mt = fd[1]; 9409 (void) close(fd[0]); 9410 return (pid); 9411 } 9412 /* child */ 9413 (void) dup2(fd[0], STDIN_FILENO); 9414 (void) close(fd[1]); 9415 (void) dup2(mt, STDOUT_FILENO); 9416 (void) execlp(compress_opt, compress_opt, NULL); 9417 vperror(1, "%s", gettext("Could not exec %s"), compress_opt); 9418 return (0); /*NOTREACHED*/ 9419 } 9420 9421 pid_t 9422 uncompress_file(void) 9423 { 9424 int fd[2]; 9425 pid_t pid; 9426 9427 if (vflag) { 9428 (void) fprintf(vfile, gettext("Decompressing '%s' with " 9429 "'%s'...\n"), usefile, compress_opt); 9430 } 9431 9432 if (pipe(fd) < 0) { 9433 vperror(1, gettext("Could not create pipe")); 9434 } 9435 if (pid = fork() > 0) { 9436 mt = fd[0]; 9437 (void) close(fd[1]); 9438 return (pid); 9439 } 9440 /* child */ 9441 (void) dup2(fd[1], STDOUT_FILENO); 9442 (void) close(fd[0]); 9443 (void) dup2(mt, STDIN_FILENO); 9444 (void) execlp(compress_opt, compress_opt, NULL); 9445 vperror(1, "%s", gettext("Could not exec %s"), compress_opt); 9446 return (0); /*NOTREACHED*/ 9447 } 9448 9449 /* Checking valid 'bzip2' suffix */ 9450 char * 9451 bz_suffix() 9452 { 9453 int i; 9454 int slen; 9455 int nlen = strlen(usefile); 9456 9457 for (i = 0; i < BS; i++) { 9458 slen = strlen(bsuffix[i]); 9459 if (nlen < slen) 9460 return (NULL); 9461 if (strcmp(usefile + nlen - slen, bsuffix[i]) == 0) 9462 return (bsuffix[i]); 9463 } 9464 return (NULL); 9465 } 9466 9467 /* Checking valid 'gzip' suffix */ 9468 char * 9469 gz_suffix() 9470 { 9471 int i; 9472 int slen; 9473 int nlen = strlen(usefile); 9474 9475 for (i = 0; i < GS; i++) { 9476 slen = strlen(gsuffix[i]); 9477 if (nlen < slen) 9478 return (NULL); 9479 if (strcmp(usefile + nlen - slen, gsuffix[i]) == 0) 9480 return (gsuffix[i]); 9481 } 9482 return (NULL); 9483 } 9484 9485 void * 9486 compress_malloc(size_t size) 9487 { 9488 void *opt; 9489 9490 if ((opt = malloc(size)) == NULL) { 9491 vperror(1, "%s", 9492 gettext("Could not allocate compress buffer\n")); 9493 } 9494 return (opt); 9495 } 9496 9497 void 9498 wait_pid(pid_t pid) 9499 { 9500 int status; 9501 9502 while (waitpid(pid, &status, 0) == -1 && errno == EINTR) 9503 ; 9504 } 9505