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, 2121 gettext("a %s attribute %s "), 2122 longname, longattrname); 2123 2124 } else { 2125 (void) fprintf(vfile, "a %s/ ", longname); 2126 } 2127 if (NotTape) 2128 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2129 K(blocks)); 2130 else 2131 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t 2132 " tape blocks\n"), blocks); 2133 } 2134 2135 /* 2136 * If hidden dir then break now since xattrs_put() will do 2137 * the iterating of the directory. 2138 * 2139 * At the moment, there can only be system attributes on 2140 * attributes. There can be no attributes on attributes or 2141 * directories within the attributes hidden directory hierarchy. 2142 */ 2143 if (filetype == XATTR_FILE) 2144 break; 2145 2146 if (*shortname != '/') 2147 (void) sprintf(newparent, "%s/%s", parent, shortname); 2148 else 2149 (void) sprintf(newparent, "%s", shortname); 2150 2151 if (chdir(shortname) < 0) { 2152 vperror(0, "%s", newparent); 2153 goto out; 2154 } 2155 2156 if ((dirp = opendir(".")) == NULL) { 2157 vperror(0, gettext( 2158 "can't open directory %s"), longname); 2159 if (chdir(parent) < 0) 2160 vperror(0, gettext("cannot change back?: %s"), 2161 parent); 2162 goto out; 2163 } 2164 2165 /* 2166 * Create a list of files (children) in this directory to avoid 2167 * having to perform telldir()/seekdir(). 2168 */ 2169 while ((dp = readdir(dirp)) != NULL && !term) { 2170 if ((strcmp(".", dp->d_name) == 0) || 2171 (strcmp("..", dp->d_name) == 0)) 2172 continue; 2173 if (((cptr = (file_list_t *)calloc(sizeof (char), 2174 sizeof (file_list_t))) == NULL) || 2175 ((cptr->name = strdup(dp->d_name)) == NULL)) { 2176 vperror(1, gettext( 2177 "Insufficient memory for directory " 2178 "list entry %s/%s\n"), 2179 newparent, dp->d_name); 2180 } 2181 2182 /* Add the file to the list */ 2183 if (child == NULL) { 2184 child = cptr; 2185 } else { 2186 child_end->next = cptr; 2187 } 2188 child_end = cptr; 2189 } 2190 (void) closedir(dirp); 2191 2192 /* 2193 * Archive each of the files in the current directory. 2194 * If a file is a directory, putfile() is called 2195 * recursively to archive the file hierarchy of the 2196 * directory before archiving the next file in the 2197 * current directory. 2198 */ 2199 while ((child != NULL) && !term) { 2200 (void) strcpy(cp, child->name); 2201 archtype = putfile(buf, cp, newparent, NULL, 2202 NORMAL_FILE, lev + 1, symlink_lev); 2203 2204 if (!exitflag) { 2205 if ((atflag || saflag) && 2206 (archtype == PUT_NOTAS_LINK)) { 2207 xattrs_put(buf, cp, newparent, NULL); 2208 } 2209 } 2210 if (exitflag) 2211 break; 2212 2213 /* Free each child as we are done processing it. */ 2214 cptr = child; 2215 child = child->next; 2216 free(cptr->name); 2217 free(cptr); 2218 } 2219 if ((child != NULL) && !term) { 2220 free_children(child); 2221 } 2222 2223 if (chdir(parent) < 0) { 2224 vperror(0, gettext("cannot change back?: %s"), parent); 2225 } 2226 2227 break; 2228 2229 case S_IFLNK: 2230 readlink_max = NAMSIZ; 2231 if (stbuf.st_size > NAMSIZ) { 2232 if (Eflag > 0) { 2233 xhdr_flgs |= _X_LINKPATH; 2234 readlink_max = PATH_MAX; 2235 } else { 2236 (void) fprintf(stderr, gettext( 2237 "tar: %s: symbolic link too long\n"), 2238 longname); 2239 if (errflag) 2240 exitflag = 1; 2241 Errflg = 1; 2242 goto out; 2243 } 2244 } 2245 /* 2246 * Sym-links need header size of zero since you 2247 * don't store any data for this type. 2248 */ 2249 stbuf.st_size = (off_t)0; 2250 tomodes(&stbuf); 2251 i = readlink(shortname, filetmp, readlink_max); 2252 if (i < 0) { 2253 vperror(0, gettext( 2254 "can't read symbolic link %s"), longname); 2255 goto out; 2256 } else { 2257 filetmp[i] = 0; 2258 } 2259 if (vflag) 2260 (void) fprintf(vfile, gettext( 2261 "a %s symbolic link to %s\n"), 2262 longname, filetmp); 2263 if (xhdr_flgs & _X_LINKPATH) { 2264 Xtarhdr.x_linkpath = filetmp; 2265 if (build_dblock(name, tchar, '2', filetype, &stbuf, 2266 stbuf.st_dev, prefix) != 0) 2267 goto out; 2268 } else 2269 if (build_dblock(name, filetmp, '2', filetype, &stbuf, 2270 stbuf.st_dev, prefix) != 0) 2271 goto out; 2272 (void) writetbuf((char *)&dblock, 1); 2273 /* 2274 * No acls for symlinks: mode is always 777 2275 * dont call write ancillary 2276 */ 2277 rc = PUT_AS_LINK; 2278 break; 2279 case S_IFREG: 2280 if ((infile = openat(dirfd, shortname, 0)) < 0) { 2281 vperror(0, gettext("unable to open %s%s%s%s"), longname, 2282 rw_sysattr ? gettext(" system") : "", 2283 (filetype == XATTR_FILE) ? 2284 gettext(" attribute ") : "", 2285 (filetype == XATTR_FILE) ? (longattrname == NULL) ? 2286 shortname : longattrname : ""); 2287 goto out; 2288 } 2289 2290 blocks = TBLOCKS(stbuf.st_size); 2291 2292 if (put_link(name, longname, shortname, longattrname, 2293 prefix, filetype, '1') == 0) { 2294 (void) close(infile); 2295 rc = PUT_AS_LINK; 2296 goto out; 2297 } 2298 2299 tomodes(&stbuf); 2300 2301 /* correctly handle end of volume */ 2302 while (mulvol && tapepos + blocks + 1 > blocklim) { 2303 /* file won't fit */ 2304 if (eflag) { 2305 if (blocks <= blocklim) { 2306 newvol(); 2307 break; 2308 } 2309 (void) fprintf(stderr, gettext( 2310 "tar: Single file cannot fit on volume\n")); 2311 done(3); 2312 } 2313 /* split if floppy has some room and file is large */ 2314 if (((blocklim - tapepos) >= EXTMIN) && 2315 ((blocks + 1) >= blocklim/10)) { 2316 splitfile(longname, infile, 2317 name, prefix, filetype); 2318 (void) close(dirfd); 2319 (void) close(infile); 2320 goto out; 2321 } 2322 newvol(); /* not worth it--just get new volume */ 2323 } 2324 #ifdef DEBUG 2325 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2326 blocks); 2327 #endif 2328 if (build_dblock(name, tchar, '0', filetype, 2329 &stbuf, stbuf.st_dev, prefix) != 0) { 2330 goto out; 2331 } 2332 if (vflag) { 2333 #ifdef DEBUG 2334 if (NotTape) 2335 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2336 0); 2337 #endif 2338 (void) fprintf(vfile, "a %s%s%s%s ", longname, 2339 rw_sysattr ? gettext(" system") : "", 2340 (filetype == XATTR_FILE) ? gettext( 2341 " attribute ") : "", 2342 (filetype == XATTR_FILE) ? 2343 longattrname : ""); 2344 if (NotTape) 2345 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2346 K(blocks)); 2347 else 2348 (void) fprintf(vfile, 2349 gettext("%" FMT_blkcnt_t " tape blocks\n"), 2350 blocks); 2351 } 2352 2353 if (put_extra_attributes(longname, shortname, longattrname, 2354 prefix, filetype, '0') != 0) 2355 goto out; 2356 2357 /* 2358 * No need to reset typeflag for extended attribute here, since 2359 * put_extra_attributes already set it and we haven't called 2360 * build_dblock(). 2361 */ 2362 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2363 hint = writetbuf((char *)&dblock, 1); 2364 maxread = max(min(stbuf.st_blksize, stbuf.st_size), 2365 (nblock * TBLOCK)); 2366 if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2367 maxread = TBLOCK; 2368 bigbuf = buf; 2369 } 2370 2371 while (((i = (int) 2372 read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2373 blocks) { 2374 blkcnt_t nblks; 2375 2376 nblks = ((i-1)/TBLOCK)+1; 2377 if (nblks > blocks) 2378 nblks = blocks; 2379 hint = writetbuf(bigbuf, nblks); 2380 blocks -= nblks; 2381 } 2382 (void) close(infile); 2383 if (bigbuf != buf) 2384 free(bigbuf); 2385 if (i < 0) 2386 vperror(0, gettext("Read error on %s"), longname); 2387 else if (blocks != 0 || i != 0) { 2388 (void) fprintf(stderr, gettext( 2389 "tar: %s: file changed size\n"), longname); 2390 if (errflag) { 2391 exitflag = 1; 2392 Errflg = 1; 2393 } else if (!Dflag) { 2394 Errflg = 1; 2395 } 2396 } 2397 putempty(blocks); 2398 break; 2399 case S_IFIFO: 2400 blocks = TBLOCKS(stbuf.st_size); 2401 stbuf.st_size = (off_t)0; 2402 2403 if (put_link(name, longname, shortname, longattrname, 2404 prefix, filetype, '6') == 0) { 2405 rc = PUT_AS_LINK; 2406 goto out; 2407 } 2408 tomodes(&stbuf); 2409 2410 while (mulvol && tapepos + blocks + 1 > blocklim) { 2411 if (eflag) { 2412 if (blocks <= blocklim) { 2413 newvol(); 2414 break; 2415 } 2416 (void) fprintf(stderr, gettext( 2417 "tar: Single file cannot fit on volume\n")); 2418 done(3); 2419 } 2420 2421 if (((blocklim - tapepos) >= EXTMIN) && 2422 ((blocks + 1) >= blocklim/10)) { 2423 splitfile(longname, infile, name, 2424 prefix, filetype); 2425 (void) close(dirfd); 2426 (void) close(infile); 2427 goto out; 2428 } 2429 newvol(); 2430 } 2431 #ifdef DEBUG 2432 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2433 blocks); 2434 #endif 2435 if (vflag) { 2436 #ifdef DEBUG 2437 if (NotTape) 2438 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2439 0); 2440 #endif 2441 if (NotTape) 2442 (void) fprintf(vfile, gettext("a %s %" 2443 FMT_blkcnt_t "K\n "), longname, K(blocks)); 2444 else 2445 (void) fprintf(vfile, gettext( 2446 "a %s %" FMT_blkcnt_t " tape blocks\n"), 2447 longname, blocks); 2448 } 2449 if (build_dblock(name, tchar, '6', filetype, 2450 &stbuf, stbuf.st_dev, prefix) != 0) 2451 goto out; 2452 2453 if (put_extra_attributes(longname, shortname, longattrname, 2454 prefix, filetype, '6') != 0) 2455 goto out; 2456 2457 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2458 dblock.dbuf.typeflag = '6'; 2459 2460 (void) writetbuf((char *)&dblock, 1); 2461 break; 2462 case S_IFCHR: 2463 stbuf.st_size = (off_t)0; 2464 blocks = TBLOCKS(stbuf.st_size); 2465 if (put_link(name, longname, shortname, longattrname, 2466 prefix, filetype, '3') == 0) { 2467 rc = PUT_AS_LINK; 2468 goto out; 2469 } 2470 tomodes(&stbuf); 2471 2472 while (mulvol && tapepos + blocks + 1 > blocklim) { 2473 if (eflag) { 2474 if (blocks <= blocklim) { 2475 newvol(); 2476 break; 2477 } 2478 (void) fprintf(stderr, gettext( 2479 "tar: Single file cannot fit on volume\n")); 2480 done(3); 2481 } 2482 2483 if (((blocklim - tapepos) >= EXTMIN) && 2484 ((blocks + 1) >= blocklim/10)) { 2485 splitfile(longname, infile, name, 2486 prefix, filetype); 2487 (void) close(dirfd); 2488 goto out; 2489 } 2490 newvol(); 2491 } 2492 #ifdef DEBUG 2493 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2494 blocks); 2495 #endif 2496 if (vflag) { 2497 #ifdef DEBUG 2498 if (NotTape) 2499 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2500 0); 2501 #endif 2502 if (NotTape) 2503 (void) fprintf(vfile, gettext("a %s %" 2504 FMT_blkcnt_t "K\n"), longname, K(blocks)); 2505 else 2506 (void) fprintf(vfile, gettext("a %s %" 2507 FMT_blkcnt_t " tape blocks\n"), longname, 2508 blocks); 2509 } 2510 if (build_dblock(name, tchar, '3', 2511 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2512 goto out; 2513 2514 if (put_extra_attributes(longname, shortname, longattrname, 2515 prefix, filetype, '3') != 0) 2516 goto out; 2517 2518 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2519 dblock.dbuf.typeflag = '3'; 2520 2521 (void) writetbuf((char *)&dblock, 1); 2522 break; 2523 case S_IFBLK: 2524 stbuf.st_size = (off_t)0; 2525 blocks = TBLOCKS(stbuf.st_size); 2526 if (put_link(name, longname, shortname, longattrname, 2527 prefix, filetype, '4') == 0) { 2528 rc = PUT_AS_LINK; 2529 goto out; 2530 } 2531 tomodes(&stbuf); 2532 2533 while (mulvol && tapepos + blocks + 1 > blocklim) { 2534 if (eflag) { 2535 if (blocks <= blocklim) { 2536 newvol(); 2537 break; 2538 } 2539 (void) fprintf(stderr, gettext( 2540 "tar: Single file cannot fit on volume\n")); 2541 done(3); 2542 } 2543 2544 if (((blocklim - tapepos) >= EXTMIN) && 2545 ((blocks + 1) >= blocklim/10)) { 2546 splitfile(longname, infile, 2547 name, prefix, filetype); 2548 (void) close(dirfd); 2549 goto out; 2550 } 2551 newvol(); 2552 } 2553 #ifdef DEBUG 2554 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2555 blocks); 2556 #endif 2557 if (vflag) { 2558 #ifdef DEBUG 2559 if (NotTape) 2560 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2561 0); 2562 #endif 2563 (void) fprintf(vfile, "a %s ", longname); 2564 if (NotTape) 2565 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2566 K(blocks)); 2567 else 2568 (void) fprintf(vfile, gettext("%" 2569 FMT_blkcnt_t " tape blocks\n"), blocks); 2570 } 2571 if (build_dblock(name, tchar, '4', 2572 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2573 goto out; 2574 2575 if (put_extra_attributes(longname, shortname, longattrname, 2576 prefix, filetype, '4') != 0) 2577 goto out; 2578 2579 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2580 dblock.dbuf.typeflag = '4'; 2581 2582 (void) writetbuf((char *)&dblock, 1); 2583 break; 2584 default: 2585 (void) fprintf(stderr, gettext( 2586 "tar: %s is not a file. Not dumped\n"), longname); 2587 if (errflag) 2588 exitflag = 1; 2589 Errflg = 1; 2590 goto out; 2591 } 2592 2593 out: 2594 if ((dirfd != -1) && (filetype != XATTR_FILE)) { 2595 (void) close(dirfd); 2596 } 2597 return (rc); 2598 } 2599 2600 2601 /* 2602 * splitfile dump a large file across volumes 2603 * 2604 * splitfile(longname, fd); 2605 * char *longname; full name of file 2606 * int ifd; input file descriptor 2607 * 2608 * NOTE: only called by putfile() to dump a large file. 2609 */ 2610 2611 static void 2612 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2613 { 2614 blkcnt_t blocks; 2615 off_t bytes, s; 2616 char buf[TBLOCK]; 2617 int i, extents; 2618 2619 blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2620 2621 /* 2622 * # extents = 2623 * size of file after using up rest of this floppy 2624 * blocks - (blocklim - tapepos) + 1 (for header) 2625 * plus roundup value before divide by blocklim-1 2626 * + (blocklim - 1) - 1 2627 * all divided by blocklim-1 (one block for each header). 2628 * this gives 2629 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2630 * which reduces to the expression used. 2631 * one is added to account for this first extent. 2632 * 2633 * When one is dealing with extremely large archives, one may want 2634 * to allow for a large number of extents. This code should be 2635 * revisited to determine if extents should be changed to something 2636 * larger than an int. 2637 */ 2638 extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2639 2640 if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2641 (void) fprintf(stderr, gettext( 2642 "tar: %s needs unusual number of volumes to split\n" 2643 "tar: %s not dumped\n"), longname, longname); 2644 return; 2645 } 2646 if (build_dblock(name, tchar, '0', filetype, 2647 &stbuf, stbuf.st_dev, prefix) != 0) 2648 return; 2649 2650 dblock.dbuf.extotal = extents; 2651 bytes = stbuf.st_size; 2652 2653 /* 2654 * The value contained in dblock.dbuf.efsize was formerly used when the 2655 * v flag was specified in conjunction with the t flag. Although it is 2656 * no longer used, older versions of tar will expect the former 2657 * behaviour, so we must continue to write it to the archive. 2658 * 2659 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2660 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2661 * store 0. 2662 */ 2663 if (bytes <= TAR_EFSIZE_MAX) 2664 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2665 else 2666 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2667 2668 (void) fprintf(stderr, gettext( 2669 "tar: large file %s needs %d extents.\n" 2670 "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2671 longname, extents, K(tapepos)); 2672 2673 s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2674 for (i = 1; i <= extents; i++) { 2675 if (i > 1) { 2676 newvol(); 2677 if (i == extents) 2678 s = bytes; /* last ext. gets true bytes */ 2679 else 2680 s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2681 } 2682 bytes -= s; 2683 blocks = TBLOCKS(s); 2684 2685 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2686 dblock.dbuf.extno = i; 2687 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2688 (void) writetbuf((char *)&dblock, 1); 2689 2690 if (vflag) 2691 (void) fprintf(vfile, 2692 gettext("+++ a %s %" FMT_blkcnt_t 2693 "K [extent #%d of %d]\n"), 2694 longname, K(blocks), i, extents); 2695 while (blocks && read(ifd, buf, TBLOCK) > 0) { 2696 blocks--; 2697 (void) writetbuf(buf, 1); 2698 } 2699 if (blocks != 0) { 2700 (void) fprintf(stderr, gettext( 2701 "tar: %s: file changed size\n"), longname); 2702 (void) fprintf(stderr, gettext( 2703 "tar: aborting split file %s\n"), longname); 2704 (void) close(ifd); 2705 return; 2706 } 2707 } 2708 (void) close(ifd); 2709 if (vflag) 2710 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2711 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2712 extents); 2713 } 2714 2715 /* 2716 * convtoreg - determines whether the file should be converted to a 2717 * regular file when extracted 2718 * 2719 * Returns 1 when file size > 0 and typeflag is not recognized 2720 * Otherwise returns 0 2721 */ 2722 static int 2723 convtoreg(off_t size) 2724 { 2725 if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2726 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2727 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2728 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2729 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2730 (dblock.dbuf.typeflag != 'L') && 2731 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2732 (dblock.dbuf.typeflag != 'X')) { 2733 return (1); 2734 } 2735 return (0); 2736 } 2737 2738 #if defined(O_XATTR) 2739 static int 2740 save_cwd(void) 2741 { 2742 return (open(".", O_RDONLY)); 2743 } 2744 #endif 2745 2746 #if defined(O_XATTR) 2747 static void 2748 rest_cwd(int *cwd) 2749 { 2750 if (*cwd != -1) { 2751 if (fchdir(*cwd) < 0) { 2752 vperror(0, gettext( 2753 "Cannot fchdir to attribute directory")); 2754 exit(1); 2755 } 2756 (void) close(*cwd); 2757 *cwd = -1; 2758 } 2759 } 2760 #endif 2761 2762 /* 2763 * Verify the underlying file system supports the attribute type. 2764 * Only archive extended attribute files when '-@' was specified. 2765 * Only archive system extended attribute files if '-/' was specified. 2766 */ 2767 #if defined(O_XATTR) 2768 static attr_status_t 2769 verify_attr_support(char *filename, int attrflg, arc_action_t actflag, 2770 int *ext_attrflg) 2771 { 2772 /* 2773 * Verify extended attributes are supported/exist. We only 2774 * need to check if we are processing a base file, not an 2775 * extended attribute. 2776 */ 2777 if (attrflg) { 2778 *ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ? 2779 _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1); 2780 } 2781 2782 if (atflag) { 2783 if (!*ext_attrflg) { 2784 #if defined(_PC_SATTR_ENABLED) 2785 if (saflag) { 2786 /* Verify system attributes are supported */ 2787 if (sysattr_support(filename, 2788 (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS : 2789 _PC_SATTR_ENABLED) != 1) { 2790 return (ATTR_SATTR_ERR); 2791 } 2792 } else 2793 return (ATTR_XATTR_ERR); 2794 #else 2795 return (ATTR_XATTR_ERR); 2796 #endif /* _PC_SATTR_ENABLED */ 2797 } 2798 2799 #if defined(_PC_SATTR_ENABLED) 2800 } else if (saflag) { 2801 /* Verify system attributes are supported */ 2802 if (sysattr_support(filename, (actflag == ARC_CREATE) ? 2803 _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) { 2804 return (ATTR_SATTR_ERR); 2805 } 2806 #endif /* _PC_SATTR_ENABLED */ 2807 } else { 2808 return (ATTR_SKIP); 2809 } 2810 2811 return (ATTR_OK); 2812 } 2813 #endif 2814 2815 #if defined(O_XATTR) 2816 /* 2817 * Recursively open attribute directories until the attribute directory 2818 * containing the specified attribute, attrname, is opened. 2819 * 2820 * Currently, only 2 directory levels of attributes are supported, (i.e., 2821 * extended system attributes on extended attributes). The following are 2822 * the possible input combinations: 2823 * 1. Open the attribute directory of the base file (don't change 2824 * into it). 2825 * attrinfo->parent = NULL 2826 * attrname = '.' 2827 * 2. Open the attribute directory of the base file and change into it. 2828 * attrinfo->parent = NULL 2829 * attrname = <attr> | <sys_attr> 2830 * 3. Open the attribute directory of the base file, change into it, 2831 * then recursively call open_attr_dir() to open the attribute's 2832 * parent directory (don't change into it). 2833 * attrinfo->parent = <attr> 2834 * attrname = '.' 2835 * 4. Open the attribute directory of the base file, change into it, 2836 * then recursively call open_attr_dir() to open the attribute's 2837 * parent directory and change into it. 2838 * attrinfo->parent = <attr> 2839 * attrname = <attr> | <sys_attr> 2840 * 2841 * An attribute directory will be opened only if the underlying file system 2842 * supports the attribute type, and if the command line specifications (atflag 2843 * and saflag) enable the processing of the attribute type. 2844 * 2845 * On succesful return, attrinfo->parentfd will be the file descriptor of the 2846 * opened attribute directory. In addition, if the attribute is a read-write 2847 * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise 2848 * it will be set to 0. 2849 * 2850 * Possible return values: 2851 * ATTR_OK Successfully opened and, if needed, changed into the 2852 * attribute directory containing attrname. 2853 * ATTR_SKIP The command line specifications don't enable the 2854 * processing of the attribute type. 2855 * ATTR_CHDIR_ERR An error occurred while trying to change into an 2856 * attribute directory. 2857 * ATTR_OPEN_ERR An error occurred while trying to open an 2858 * attribute directory. 2859 * ATTR_XATTR_ERR The underlying file system doesn't support extended 2860 * attributes. 2861 * ATTR_SATTR_ERR The underlying file system doesn't support extended 2862 * system attributes. 2863 */ 2864 static int 2865 open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo) 2866 { 2867 attr_status_t rc; 2868 int firsttime = (attrinfo->attr_parentfd == -1); 2869 int saveerrno; 2870 int ext_attr; 2871 2872 /* 2873 * open_attr_dir() was recursively called (input combination number 4), 2874 * close the previously opened file descriptor as we've already changed 2875 * into it. 2876 */ 2877 if (!firsttime) { 2878 (void) close(attrinfo->attr_parentfd); 2879 attrinfo->attr_parentfd = -1; 2880 } 2881 2882 /* 2883 * Verify that the underlying file system supports the restoration 2884 * of the attribute. 2885 */ 2886 if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE, 2887 &ext_attr)) != ATTR_OK) { 2888 return (rc); 2889 } 2890 2891 /* Open the base file's attribute directory */ 2892 if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) { 2893 /* 2894 * Save the errno from the attropen so it can be reported 2895 * if the retry of the attropen fails. 2896 */ 2897 saveerrno = errno; 2898 if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp, 2899 NULL, ".", O_RDONLY, 0)) == -1) { 2900 /* 2901 * Reset typeflag back to real value so passtape 2902 * will skip ahead correctly. 2903 */ 2904 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2905 (void) close(attrinfo->attr_parentfd); 2906 attrinfo->attr_parentfd = -1; 2907 errno = saveerrno; 2908 return (ATTR_OPEN_ERR); 2909 } 2910 } 2911 2912 /* 2913 * Change into the parent attribute's directory unless we are 2914 * processing the hidden attribute directory of the base file itself. 2915 */ 2916 if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) { 2917 if (fchdir(attrinfo->attr_parentfd) != 0) { 2918 saveerrno = errno; 2919 (void) close(attrinfo->attr_parentfd); 2920 attrinfo->attr_parentfd = -1; 2921 errno = saveerrno; 2922 return (ATTR_CHDIR_ERR); 2923 } 2924 } 2925 2926 /* Determine if the attribute should be processed */ 2927 if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1, 2928 &attrinfo->attr_rw_sysattr)) != ATTR_OK) { 2929 saveerrno = errno; 2930 (void) close(attrinfo->attr_parentfd); 2931 attrinfo->attr_parentfd = -1; 2932 errno = saveerrno; 2933 return (rc); 2934 } 2935 2936 /* 2937 * If the attribute is an extended attribute, or extended system 2938 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then 2939 * recursively call open_attr_dir() to open the attribute directory 2940 * of the parent attribute. 2941 */ 2942 if (firsttime && (attrinfo->attr_parent != NULL)) { 2943 return (open_attr_dir(attrname, attrinfo->attr_parent, 2944 attrinfo->attr_parentfd, attrinfo)); 2945 } 2946 2947 return (ATTR_OK); 2948 } 2949 #endif 2950 2951 static void 2952 #ifdef _iBCS2 2953 doxtract(char *argv[], int tbl_cnt) 2954 #else 2955 doxtract(char *argv[]) 2956 #endif 2957 { 2958 struct stat xtractbuf; /* stat on file after extracting */ 2959 blkcnt_t blocks; 2960 off_t bytes; 2961 int ofile; 2962 int newfile; /* Does the file already exist */ 2963 int xcnt = 0; /* count # files extracted */ 2964 int fcnt = 0; /* count # files in argv list */ 2965 int dir; 2966 int dirfd = -1; 2967 int cwd = -1; 2968 int rw_sysattr; 2969 int saveerrno; 2970 uid_t Uid; 2971 char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 2972 char dirname[PATH_MAX+1]; 2973 char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 2974 int once = 1; 2975 int error; 2976 int symflag; 2977 int want; 2978 attr_data_t *attrinfo = NULL; /* attribute info */ 2979 acl_t *aclp = NULL; /* acl info */ 2980 char dot[] = "."; /* dirp for using realpath */ 2981 timestruc_t time_zero; /* used for call to doDirTimes */ 2982 int dircreate; 2983 int convflag; 2984 time_zero.tv_sec = 0; 2985 time_zero.tv_nsec = 0; 2986 2987 /* reset Trusted Extensions variables */ 2988 rpath_flag = 0; 2989 lk_rpath_flag = 0; 2990 dir_flag = 0; 2991 mld_flag = 0; 2992 bslundef(&bs_label); 2993 bsllow(&admin_low); 2994 bslhigh(&admin_high); 2995 orig_namep = 0; 2996 2997 dumping = 0; /* for newvol(), et al: we are not writing */ 2998 2999 /* 3000 * Count the number of files that are to be extracted 3001 */ 3002 Uid = getuid(); 3003 3004 #ifdef _iBCS2 3005 initarg(argv, Filefile); 3006 while (nextarg() != NULL) 3007 ++fcnt; 3008 fcnt += tbl_cnt; 3009 #endif /* _iBCS2 */ 3010 3011 for (;;) { 3012 convflag = 0; 3013 symflag = 0; 3014 dir = 0; 3015 Hiddendir = 0; 3016 rw_sysattr = 0; 3017 ofile = -1; 3018 3019 if (dirfd != -1) { 3020 (void) close(dirfd); 3021 dirfd = -1; 3022 } 3023 if (ofile != -1) { 3024 if (close(ofile) != 0) 3025 vperror(2, gettext("close error")); 3026 } 3027 3028 #if defined(O_XATTR) 3029 if (cwd != -1) { 3030 rest_cwd(&cwd); 3031 } 3032 #endif 3033 3034 /* namep is set by wantit to point to the full name */ 3035 if ((want = wantit(argv, &namep, &dirp, &comp, 3036 &attrinfo)) == 0) { 3037 #if defined(O_XATTR) 3038 if (xattrp != NULL) { 3039 free(xattrhead); 3040 xattrp = NULL; 3041 xattr_linkp = NULL; 3042 xattrhead = NULL; 3043 } 3044 #endif 3045 continue; 3046 } 3047 if (want == -1) 3048 break; 3049 3050 /* Trusted Extensions */ 3051 /* 3052 * During tar extract (x): 3053 * If the pathname of the restored file has been 3054 * reconstructed from the ancillary file, 3055 * use it to process the normal file. 3056 */ 3057 if (mld_flag) { /* Skip over .MLD. directory */ 3058 mld_flag = 0; 3059 passtape(); 3060 continue; 3061 } 3062 orig_namep = namep; /* save original */ 3063 if (rpath_flag) { 3064 namep = real_path; /* use zone path */ 3065 comp = real_path; /* use zone path */ 3066 dirp = dot; /* work from the top */ 3067 rpath_flag = 0; /* reset */ 3068 } 3069 3070 if (dirfd != -1) 3071 (void) close(dirfd); 3072 3073 (void) strcpy(&dirname[0], namep); 3074 dircreate = checkdir(&dirname[0]); 3075 3076 #if defined(O_XATTR) 3077 if (xattrp != NULL) { 3078 int rc; 3079 3080 if (((cwd = save_cwd()) == -1) || 3081 ((rc = open_attr_dir(comp, dirp, cwd, 3082 attrinfo)) != ATTR_OK)) { 3083 if (cwd == -1) { 3084 vperror(0, gettext( 3085 "unable to save current working " 3086 "directory while processing " 3087 "attribute %s of %s"), 3088 dirp, attrinfo->attr_path); 3089 } else if (rc != ATTR_SKIP) { 3090 (void) fprintf(vfile, 3091 gettext("tar: cannot open " 3092 "%sattribute %s of file %s: %s\n"), 3093 attrinfo->attr_rw_sysattr ? gettext( 3094 "system ") : "", 3095 comp, dirp, strerror(errno)); 3096 } 3097 free(xattrhead); 3098 xattrp = NULL; 3099 xattr_linkp = NULL; 3100 xattrhead = NULL; 3101 3102 passtape(); 3103 continue; 3104 } else { 3105 dirfd = attrinfo->attr_parentfd; 3106 rw_sysattr = attrinfo->attr_rw_sysattr; 3107 } 3108 } else { 3109 dirfd = open(dirp, O_RDONLY); 3110 } 3111 #else 3112 dirfd = open(dirp, O_RDONLY); 3113 #endif 3114 if (dirfd == -1) { 3115 (void) fprintf(vfile, gettext( 3116 "tar: cannot open %s: %s\n"), 3117 dirp, strerror(errno)); 3118 passtape(); 3119 continue; 3120 } 3121 3122 if (xhdr_flgs & _X_LINKPATH) 3123 (void) strcpy(templink, Xtarhdr.x_linkpath); 3124 else { 3125 #if defined(O_XATTR) 3126 if (xattrp && dblock.dbuf.typeflag == '1') { 3127 (void) sprintf(templink, "%.*s", NAMSIZ, 3128 xattrp->h_names); 3129 } else { 3130 (void) sprintf(templink, "%.*s", NAMSIZ, 3131 dblock.dbuf.linkname); 3132 } 3133 #else 3134 (void) sprintf(templink, "%.*s", NAMSIZ, 3135 dblock.dbuf.linkname); 3136 #endif 3137 } 3138 3139 if (Fflag) { 3140 char *s; 3141 3142 if ((s = strrchr(namep, '/')) == 0) 3143 s = namep; 3144 3145 else 3146 s++; 3147 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 3148 passtape(); 3149 continue; 3150 } 3151 } 3152 3153 if (checkw('x', namep) == 0) { 3154 passtape(); 3155 continue; 3156 } 3157 if (once) { 3158 if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 3159 if (geteuid() == (uid_t)0) { 3160 checkflag = 1; 3161 pflag = 1; 3162 } else { 3163 /* get file creation mask */ 3164 Oumask = umask(0); 3165 (void) umask(Oumask); 3166 } 3167 once = 0; 3168 } else { 3169 if (geteuid() == (uid_t)0) { 3170 pflag = 1; 3171 checkflag = 2; 3172 } 3173 if (!pflag) { 3174 /* get file creation mask */ 3175 Oumask = umask(0); 3176 (void) umask(Oumask); 3177 } 3178 once = 0; 3179 } 3180 } 3181 3182 #if defined(O_XATTR) 3183 /* 3184 * Handle extraction of hidden attr dir. 3185 * Dir is automatically created, we only 3186 * need to update mode and perm's. 3187 */ 3188 if ((xattrp != NULL) && Hiddendir == 1) { 3189 bytes = stbuf.st_size; 3190 blocks = TBLOCKS(bytes); 3191 if (vflag) { 3192 (void) fprintf(vfile, 3193 "x %s%s%s, %" FMT_off_t " %s, ", namep, 3194 gettext(" attribute "), 3195 xattrapath, bytes, 3196 gettext("bytes")); 3197 if (NotTape) 3198 (void) fprintf(vfile, 3199 "%" FMT_blkcnt_t "K\n", K(blocks)); 3200 else 3201 (void) fprintf(vfile, gettext("%" 3202 FMT_blkcnt_t " tape blocks\n"), 3203 blocks); 3204 } 3205 3206 /* 3207 * Set the permissions and mode of the attribute 3208 * unless the attribute is a system attribute (can't 3209 * successfully do this) or the hidden attribute 3210 * directory (".") of an attribute (when the attribute 3211 * is restored, the hidden attribute directory of an 3212 * attribute is transient). Note: when the permissions 3213 * and mode are set for the hidden attribute directory 3214 * of a file on a system supporting extended system 3215 * attributes, even though it returns successfully, it 3216 * will not have any affect since the attribute 3217 * directory is transient. 3218 */ 3219 if (attrinfo->attr_parent == NULL) { 3220 if (fchownat(dirfd, ".", stbuf.st_uid, 3221 stbuf.st_gid, 0) != 0) { 3222 vperror(0, gettext( 3223 "%s%s%s: failed to set ownership " 3224 "of attribute directory"), namep, 3225 gettext(" attribute "), xattrapath); 3226 } 3227 3228 if (fchmod(dirfd, stbuf.st_mode) != 0) { 3229 vperror(0, gettext( 3230 "%s%s%s: failed to set permissions " 3231 "of attribute directory"), namep, 3232 gettext(" attribute "), xattrapath); 3233 } 3234 } 3235 goto filedone; 3236 } 3237 #endif 3238 3239 if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 3240 dir = 1; 3241 if (vflag) { 3242 (void) fprintf(vfile, "x %s, 0 %s, ", 3243 &dirname[0], gettext("bytes")); 3244 if (NotTape) 3245 (void) fprintf(vfile, "0K\n"); 3246 else 3247 (void) fprintf(vfile, gettext("%" 3248 FMT_blkcnt_t " tape blocks\n"), 3249 (blkcnt_t)0); 3250 } 3251 goto filedone; 3252 } 3253 3254 if (dblock.dbuf.typeflag == '6') { /* FIFO */ 3255 if (rmdir(namep) < 0) { 3256 if (errno == ENOTDIR) 3257 (void) unlink(namep); 3258 } 3259 linkp = templink; 3260 if (*linkp != NULL) { 3261 if (Aflag && *linkp == '/') 3262 linkp++; 3263 if (link(linkp, namep) < 0) { 3264 (void) fprintf(stderr, gettext( 3265 "tar: %s: cannot link\n"), namep); 3266 continue; 3267 } 3268 if (vflag) 3269 (void) fprintf(vfile, gettext( 3270 "x %s linked to %s\n"), namep, 3271 linkp); 3272 xcnt++; /* increment # files extracted */ 3273 continue; 3274 } 3275 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO), 3276 (int)Gen.g_devmajor) < 0) { 3277 vperror(0, gettext("%s: mknod failed"), namep); 3278 continue; 3279 } 3280 bytes = stbuf.st_size; 3281 blocks = TBLOCKS(bytes); 3282 if (vflag) { 3283 (void) fprintf(vfile, "x %s, %" FMT_off_t 3284 " %s, ", namep, bytes, gettext("bytes")); 3285 if (NotTape) 3286 (void) fprintf(vfile, "%" FMT_blkcnt_t 3287 "K\n", K(blocks)); 3288 else 3289 (void) fprintf(vfile, gettext("%" 3290 FMT_blkcnt_t " tape blocks\n"), 3291 blocks); 3292 } 3293 goto filedone; 3294 } 3295 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */ 3296 if (rmdir(namep) < 0) { 3297 if (errno == ENOTDIR) 3298 (void) unlink(namep); 3299 } 3300 linkp = templink; 3301 if (*linkp != NULL) { 3302 if (Aflag && *linkp == '/') 3303 linkp++; 3304 if (link(linkp, namep) < 0) { 3305 (void) fprintf(stderr, gettext( 3306 "tar: %s: cannot link\n"), namep); 3307 continue; 3308 } 3309 if (vflag) 3310 (void) fprintf(vfile, gettext( 3311 "x %s linked to %s\n"), namep, 3312 linkp); 3313 xcnt++; /* increment # files extracted */ 3314 continue; 3315 } 3316 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR), 3317 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3318 vperror(0, gettext( 3319 "%s: mknod failed"), namep); 3320 continue; 3321 } 3322 bytes = stbuf.st_size; 3323 blocks = TBLOCKS(bytes); 3324 if (vflag) { 3325 (void) fprintf(vfile, "x %s, %" FMT_off_t 3326 " %s, ", namep, bytes, gettext("bytes")); 3327 if (NotTape) 3328 (void) fprintf(vfile, "%" FMT_blkcnt_t 3329 "K\n", K(blocks)); 3330 else 3331 (void) fprintf(vfile, gettext("%" 3332 FMT_blkcnt_t " tape blocks\n"), 3333 blocks); 3334 } 3335 goto filedone; 3336 } else if (dblock.dbuf.typeflag == '3' && Uid) { 3337 (void) fprintf(stderr, gettext( 3338 "Can't create special %s\n"), namep); 3339 continue; 3340 } 3341 3342 /* BLOCK SPECIAL */ 3343 3344 if (dblock.dbuf.typeflag == '4' && !Uid) { 3345 if (rmdir(namep) < 0) { 3346 if (errno == ENOTDIR) 3347 (void) unlink(namep); 3348 } 3349 linkp = templink; 3350 if (*linkp != NULL) { 3351 if (Aflag && *linkp == '/') 3352 linkp++; 3353 if (link(linkp, namep) < 0) { 3354 (void) fprintf(stderr, gettext( 3355 "tar: %s: cannot link\n"), namep); 3356 continue; 3357 } 3358 if (vflag) 3359 (void) fprintf(vfile, gettext( 3360 "x %s linked to %s\n"), namep, 3361 linkp); 3362 xcnt++; /* increment # files extracted */ 3363 continue; 3364 } 3365 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK), 3366 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3367 vperror(0, gettext("%s: mknod failed"), namep); 3368 continue; 3369 } 3370 bytes = stbuf.st_size; 3371 blocks = TBLOCKS(bytes); 3372 if (vflag) { 3373 (void) fprintf(vfile, gettext("x %s, %" 3374 FMT_off_t " bytes, "), namep, bytes); 3375 if (NotTape) 3376 (void) fprintf(vfile, "%" FMT_blkcnt_t 3377 "K\n", K(blocks)); 3378 else 3379 (void) fprintf(vfile, gettext("%" 3380 FMT_blkcnt_t " tape blocks\n"), 3381 blocks); 3382 } 3383 goto filedone; 3384 } else if (dblock.dbuf.typeflag == '4' && Uid) { 3385 (void) fprintf(stderr, 3386 gettext("Can't create special %s\n"), namep); 3387 continue; 3388 } 3389 if (dblock.dbuf.typeflag == '2') { /* symlink */ 3390 if ((Tflag) && (lk_rpath_flag == 1)) 3391 linkp = lk_real_path; 3392 else 3393 linkp = templink; 3394 if (Aflag && *linkp == '/') 3395 linkp++; 3396 if (rmdir(namep) < 0) { 3397 if (errno == ENOTDIR) 3398 (void) unlink(namep); 3399 } 3400 if (symlink(linkp, namep) < 0) { 3401 vperror(0, gettext("%s: symbolic link failed"), 3402 namep); 3403 continue; 3404 } 3405 if (vflag) 3406 (void) fprintf(vfile, gettext( 3407 "x %s symbolic link to %s\n"), 3408 namep, linkp); 3409 3410 symflag = AT_SYMLINK_NOFOLLOW; 3411 goto filedone; 3412 } 3413 if (dblock.dbuf.typeflag == '1') { 3414 linkp = templink; 3415 if (Aflag && *linkp == '/') 3416 linkp++; 3417 if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) { 3418 if (errno == ENOTDIR) 3419 (void) unlinkat(dirfd, comp, 0); 3420 } 3421 #if defined(O_XATTR) 3422 if (xattrp && xattr_linkp) { 3423 if (fchdir(dirfd) < 0) { 3424 vperror(0, gettext( 3425 "Cannot fchdir to attribute " 3426 "directory %s"), 3427 (attrinfo->attr_parent == NULL) ? 3428 dirp : attrinfo->attr_parent); 3429 exit(1); 3430 } 3431 3432 error = link(xattr_linkaname, xattrapath); 3433 } else { 3434 error = link(linkp, namep); 3435 } 3436 #else 3437 error = link(linkp, namep); 3438 #endif 3439 3440 if (error < 0) { 3441 (void) fprintf(stderr, gettext( 3442 "tar: %s%s%s: cannot link\n"), 3443 namep, (xattr_linkp != NULL) ? 3444 gettext(" attribute ") : "", 3445 (xattr_linkp != NULL) ? 3446 xattrapath : ""); 3447 continue; 3448 } 3449 if (vflag) 3450 (void) fprintf(vfile, gettext( 3451 "x %s%s%s linked to %s%s%s\n"), namep, 3452 (xattr_linkp != NULL) ? 3453 gettext(" attribute ") : "", 3454 (xattr_linkp != NULL) ? 3455 xattr_linkaname : "", 3456 linkp, 3457 (xattr_linkp != NULL) ? 3458 gettext(" attribute ") : "", 3459 (xattr_linkp != NULL) ? xattrapath : ""); 3460 xcnt++; /* increment # files extracted */ 3461 #if defined(O_XATTR) 3462 if (xattrp != NULL) { 3463 free(xattrhead); 3464 xattrp = NULL; 3465 xattr_linkp = NULL; 3466 xattrhead = NULL; 3467 } 3468 #endif 3469 continue; 3470 } 3471 3472 /* REGULAR FILES */ 3473 3474 if (convtoreg(stbuf.st_size)) { 3475 convflag = 1; 3476 if (errflag) { 3477 (void) fprintf(stderr, gettext( 3478 "tar: %s: typeflag '%c' not recognized\n"), 3479 namep, dblock.dbuf.typeflag); 3480 done(1); 3481 } else { 3482 (void) fprintf(stderr, gettext( 3483 "tar: %s: typeflag '%c' not recognized, " 3484 "converting to regular file\n"), namep, 3485 dblock.dbuf.typeflag); 3486 Errflg = 1; 3487 } 3488 } 3489 if (dblock.dbuf.typeflag == '0' || 3490 dblock.dbuf.typeflag == NULL || convflag) { 3491 delete_target(dirfd, comp, namep); 3492 linkp = templink; 3493 if (*linkp != NULL) { 3494 if (Aflag && *linkp == '/') 3495 linkp++; 3496 if (link(linkp, comp) < 0) { 3497 (void) fprintf(stderr, gettext( 3498 "tar: %s: cannot link\n"), namep); 3499 continue; 3500 } 3501 if (vflag) 3502 (void) fprintf(vfile, gettext( 3503 "x %s linked to %s\n"), comp, 3504 linkp); 3505 xcnt++; /* increment # files extracted */ 3506 #if defined(O_XATTR) 3507 if (xattrp != NULL) { 3508 free(xattrhead); 3509 xattrp = NULL; 3510 xattr_linkp = NULL; 3511 xattrhead = NULL; 3512 } 3513 #endif 3514 continue; 3515 } 3516 newfile = ((fstatat(dirfd, comp, 3517 &xtractbuf, 0) == -1) ? TRUE : FALSE); 3518 ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC, 3519 stbuf.st_mode & MODEMASK); 3520 saveerrno = errno; 3521 3522 #if defined(O_XATTR) 3523 if (xattrp != NULL) { 3524 if (ofile < 0) { 3525 ofile = retry_open_attr(dirfd, cwd, 3526 dirp, attrinfo->attr_parent, comp, 3527 O_RDWR|O_CREAT|O_TRUNC, 3528 stbuf.st_mode & MODEMASK); 3529 } 3530 } 3531 #endif 3532 if (ofile < 0) { 3533 errno = saveerrno; 3534 (void) fprintf(stderr, gettext( 3535 "tar: %s%s%s%s - cannot create\n"), 3536 (xattrp == NULL) ? "" : (rw_sysattr ? 3537 gettext("system attribute ") : 3538 gettext("attribute ")), 3539 (xattrp == NULL) ? "" : xattrapath, 3540 (xattrp == NULL) ? "" : gettext(" of "), 3541 (xattrp == NULL) ? comp : namep); 3542 if (errflag) 3543 done(1); 3544 else 3545 Errflg = 1; 3546 #if defined(O_XATTR) 3547 if (xattrp != NULL) { 3548 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 3549 free(xattrhead); 3550 xattrp = NULL; 3551 xattr_linkp = NULL; 3552 xattrhead = NULL; 3553 } 3554 #endif 3555 passtape(); 3556 continue; 3557 } 3558 3559 if (Tflag && (check_ext_attr(namep) == 0)) { 3560 if (errflag) 3561 done(1); 3562 else 3563 Errflg = 1; 3564 passtape(); 3565 continue; 3566 } 3567 3568 if (extno != 0) { /* file is in pieces */ 3569 if (extotal < 1 || extotal > MAXEXT) 3570 (void) fprintf(stderr, gettext( 3571 "tar: ignoring bad extent info for " 3572 "%s%s%s%s\n"), 3573 (xattrp == NULL) ? "" : (rw_sysattr ? 3574 gettext("system attribute ") : 3575 gettext("attribute ")), 3576 (xattrp == NULL) ? "" : xattrapath, 3577 (xattrp == NULL) ? "" : gettext(" of "), 3578 (xattrp == NULL) ? comp : namep); 3579 else { 3580 /* extract it */ 3581 (void) xsfile(rw_sysattr, ofile); 3582 } 3583 } 3584 extno = 0; /* let everyone know file is not split */ 3585 bytes = stbuf.st_size; 3586 blocks = TBLOCKS(bytes); 3587 if (vflag) { 3588 (void) fprintf(vfile, 3589 "x %s%s%s, %" FMT_off_t " %s, ", 3590 (xattrp == NULL) ? "" : dirp, 3591 (xattrp == NULL) ? "" : (rw_sysattr ? 3592 gettext(" system attribute ") : 3593 gettext(" attribute ")), 3594 (xattrp == NULL) ? namep : xattrapath, bytes, 3595 gettext("bytes")); 3596 if (NotTape) 3597 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 3598 K(blocks)); 3599 else 3600 (void) fprintf(vfile, gettext("%" 3601 FMT_blkcnt_t " tape blocks\n"), blocks); 3602 } 3603 3604 if (xblocks(rw_sysattr, bytes, ofile) != 0) { 3605 #if defined(O_XATTR) 3606 if (xattrp != NULL) { 3607 free(xattrhead); 3608 xattrp = NULL; 3609 xattr_linkp = NULL; 3610 xattrhead = NULL; 3611 } 3612 #endif 3613 continue; 3614 } 3615 filedone: 3616 if (mflag == 0 && !symflag) { 3617 if (dir) 3618 doDirTimes(namep, stbuf.st_mtim); 3619 3620 else 3621 #if defined(O_XATTR) 3622 if (xattrp != NULL) { 3623 /* 3624 * Set the time on the attribute unless 3625 * the attribute is a system attribute 3626 * (can't successfully do this) or the 3627 * hidden attribute directory, "." (the 3628 * time on the hidden attribute 3629 * directory will be updated when 3630 * attributes are restored, otherwise 3631 * it's transient). 3632 */ 3633 if (!rw_sysattr && (Hiddendir == 0)) { 3634 setPathTimes(dirfd, comp, 3635 stbuf.st_mtim); 3636 } 3637 } else 3638 setPathTimes(dirfd, comp, 3639 stbuf.st_mtim); 3640 #else 3641 setPathTimes(dirfd, comp, stbuf.st_mtim); 3642 #endif 3643 } 3644 3645 /* moved this code from above */ 3646 if (pflag && !symflag && Hiddendir == 0) { 3647 if (xattrp != NULL) 3648 (void) fchmod(ofile, stbuf.st_mode & MODEMASK); 3649 else 3650 (void) chmod(namep, stbuf.st_mode & MODEMASK); 3651 } 3652 3653 3654 /* 3655 * Because ancillary file preceeds the normal file, 3656 * acl info may have been retrieved (in aclp). 3657 * All file types are directed here (go filedone). 3658 * Always restore ACLs if there are ACLs. 3659 */ 3660 if (aclp != NULL) { 3661 int ret; 3662 3663 #if defined(O_XATTR) 3664 if (xattrp != NULL) { 3665 if (Hiddendir) 3666 ret = facl_set(dirfd, aclp); 3667 else 3668 ret = facl_set(ofile, aclp); 3669 } else { 3670 ret = acl_set(namep, aclp); 3671 } 3672 #else 3673 ret = acl_set(namep, aclp); 3674 #endif 3675 if (ret < 0) { 3676 if (pflag) { 3677 (void) fprintf(stderr, gettext( 3678 "%s%s%s%s: failed to set acl " 3679 "entries\n"), namep, 3680 (xattrp == NULL) ? "" : 3681 (rw_sysattr ? gettext( 3682 " system attribute ") : 3683 gettext(" attribute ")), 3684 (xattrp == NULL) ? "" : 3685 xattrapath); 3686 } 3687 /* else: silent and continue */ 3688 } 3689 acl_free(aclp); 3690 aclp = NULL; 3691 } 3692 3693 if (!oflag) 3694 resugname(dirfd, comp, symflag); /* set file ownership */ 3695 3696 if (pflag && newfile == TRUE && !dir && 3697 (dblock.dbuf.typeflag == '0' || 3698 dblock.dbuf.typeflag == NULL || 3699 convflag || dblock.dbuf.typeflag == '1')) { 3700 if (fstat(ofile, &xtractbuf) == -1) 3701 (void) fprintf(stderr, gettext( 3702 "tar: cannot stat extracted file " 3703 "%s%s%s%s\n"), 3704 (xattrp == NULL) ? "" : (rw_sysattr ? 3705 gettext("system attribute ") : 3706 gettext("attribute ")), 3707 (xattrp == NULL) ? "" : xattrapath, 3708 (xattrp == NULL) ? "" : 3709 gettext(" of "), namep); 3710 3711 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT)) 3712 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) { 3713 (void) fprintf(stderr, gettext( 3714 "tar: warning - file permissions have " 3715 "changed for %s%s%s%s (are 0%o, should be " 3716 "0%o)\n"), 3717 (xattrp == NULL) ? "" : (rw_sysattr ? 3718 gettext("system attribute ") : 3719 gettext("attribute ")), 3720 (xattrp == NULL) ? "" : xattrapath, 3721 (xattrp == NULL) ? "" : 3722 gettext(" of "), namep, 3723 xtractbuf.st_mode, stbuf.st_mode); 3724 3725 } 3726 } 3727 #if defined(O_XATTR) 3728 if (xattrp != NULL) { 3729 free(xattrhead); 3730 xattrp = NULL; 3731 xattr_linkp = NULL; 3732 xattrhead = NULL; 3733 } 3734 #endif 3735 3736 if (ofile != -1) { 3737 (void) close(dirfd); 3738 dirfd = -1; 3739 if (close(ofile) != 0) 3740 vperror(2, gettext("close error")); 3741 ofile = -1; 3742 } 3743 xcnt++; /* increment # files extracted */ 3744 } 3745 3746 /* 3747 * Process ancillary file. 3748 * 3749 */ 3750 3751 if (dblock.dbuf.typeflag == 'A') { /* acl info */ 3752 char buf[TBLOCK]; 3753 char *secp; 3754 char *tp; 3755 int attrsize; 3756 int cnt; 3757 3758 /* reset Trusted Extensions flags */ 3759 dir_flag = 0; 3760 mld_flag = 0; 3761 lk_rpath_flag = 0; 3762 rpath_flag = 0; 3763 3764 if (pflag) { 3765 bytes = stbuf.st_size; 3766 if ((secp = malloc((int)bytes)) == NULL) { 3767 (void) fprintf(stderr, gettext( 3768 "Insufficient memory for acl\n")); 3769 passtape(); 3770 continue; 3771 } 3772 tp = secp; 3773 blocks = TBLOCKS(bytes); 3774 3775 /* 3776 * Display a line for each ancillary file. 3777 */ 3778 if (vflag && Tflag) 3779 (void) fprintf(vfile, "x %s(A), %" 3780 FMT_blkcnt_t " %s, %" 3781 FMT_blkcnt_t " %s\n", 3782 namep, bytes, gettext("bytes"), 3783 blocks, gettext("tape blocks")); 3784 3785 while (blocks-- > 0) { 3786 readtape(buf); 3787 if (bytes <= TBLOCK) { 3788 (void) memcpy(tp, buf, 3789 (size_t)bytes); 3790 break; 3791 } else { 3792 (void) memcpy(tp, buf, 3793 TBLOCK); 3794 tp += TBLOCK; 3795 } 3796 bytes -= TBLOCK; 3797 } 3798 bytes = stbuf.st_size; 3799 /* got all attributes in secp */ 3800 tp = secp; 3801 do { 3802 attr = (struct sec_attr *)tp; 3803 switch (attr->attr_type) { 3804 case UFSD_ACL: 3805 case ACE_ACL: 3806 (void) sscanf(attr->attr_len, 3807 "%7o", 3808 (uint_t *) 3809 &cnt); 3810 /* header is 8 */ 3811 attrsize = 8 + (int)strlen( 3812 &attr->attr_info[0]) + 1; 3813 error = 3814 acl_fromtext( 3815 &attr->attr_info[0], &aclp); 3816 3817 if (error != 0) { 3818 (void) fprintf(stderr, 3819 gettext( 3820 "aclfromtext " 3821 "failed: %s\n"), 3822 acl_strerror( 3823 error)); 3824 bytes -= attrsize; 3825 break; 3826 } 3827 if (acl_cnt(aclp) != cnt) { 3828 (void) fprintf(stderr, 3829 gettext( 3830 "aclcnt error\n")); 3831 bytes -= attrsize; 3832 break; 3833 } 3834 bytes -= attrsize; 3835 break; 3836 3837 /* Trusted Extensions */ 3838 3839 case DIR_TYPE: 3840 case LBL_TYPE: 3841 case APRIV_TYPE: 3842 case FPRIV_TYPE: 3843 case COMP_TYPE: 3844 case LK_COMP_TYPE: 3845 case ATTR_FLAG_TYPE: 3846 attrsize = 3847 sizeof (struct sec_attr) + 3848 strlen(&attr->attr_info[0]); 3849 bytes -= attrsize; 3850 if (Tflag) 3851 extract_attr(&namep, 3852 attr); 3853 break; 3854 3855 default: 3856 (void) fprintf(stderr, gettext( 3857 "unrecognized attr" 3858 " type\n")); 3859 bytes = (off_t)0; 3860 break; 3861 } 3862 3863 /* next attributes */ 3864 tp += attrsize; 3865 } while (bytes != 0); 3866 free(secp); 3867 } else { 3868 passtape(); 3869 } 3870 } /* acl */ 3871 3872 } /* for */ 3873 3874 /* 3875 * Ensure that all the directories still on the directory stack 3876 * get their modification times set correctly by flushing the 3877 * stack. 3878 */ 3879 3880 doDirTimes(NULL, time_zero); 3881 3882 #if defined(O_XATTR) 3883 if (xattrp != NULL) { 3884 free(xattrhead); 3885 xattrp = NULL; 3886 xattr_linkp = NULL; 3887 xattrhead = NULL; 3888 } 3889 #endif 3890 3891 /* 3892 * Check if the number of files extracted is different from the 3893 * number of files listed on the command line 3894 */ 3895 if (fcnt > xcnt) { 3896 (void) fprintf(stderr, 3897 gettext("tar: %d file(s) not extracted\n"), 3898 fcnt-xcnt); 3899 Errflg = 1; 3900 } 3901 } 3902 3903 /* 3904 * xblocks extract file/extent from tape to output file 3905 * 3906 * xblocks(issysattr, bytes, ofile); 3907 * 3908 * issysattr flag set if the files being extracted 3909 * is an extended system attribute file. 3910 * unsigned long long bytes size of extent or file to be extracted 3911 * ofile output file 3912 * 3913 * called by doxtract() and xsfile() 3914 */ 3915 3916 static int 3917 xblocks(int issysattr, off_t bytes, int ofile) 3918 { 3919 char *buf; 3920 char tempname[NAMSIZ+1]; 3921 size_t maxwrite; 3922 size_t bytesread; 3923 size_t piosize; /* preferred I/O size */ 3924 struct stat tsbuf; 3925 3926 /* Don't need to do anything if this is a zero size file */ 3927 if (bytes <= 0) { 3928 return (0); 3929 } 3930 3931 /* 3932 * To figure out the size of the buffer used to accumulate data 3933 * from readtape() and to write to the file, we need to determine 3934 * the largest chunk of data to be written to the file at one time. 3935 * This is determined based on the smallest of the following two 3936 * things: 3937 * 1) The size of the archived file. 3938 * 2) The preferred I/O size of the file. 3939 */ 3940 if (issysattr || (bytes <= TBLOCK)) { 3941 /* 3942 * Writes to system attribute files must be 3943 * performed in one operation. 3944 */ 3945 maxwrite = bytes; 3946 } else { 3947 /* 3948 * fstat() the file to get the preferred I/O size. 3949 * If it fails, then resort back to just writing 3950 * one block at a time. 3951 */ 3952 if (fstat(ofile, &tsbuf) == 0) { 3953 piosize = tsbuf.st_blksize; 3954 } else { 3955 piosize = TBLOCK; 3956 } 3957 maxwrite = min(bytes, piosize); 3958 } 3959 3960 /* 3961 * The buffer used to accumulate the data for the write operation 3962 * needs to be the maximum number of bytes to be written rounded up 3963 * to the nearest TBLOCK since readtape reads one block at a time. 3964 */ 3965 if ((buf = malloc(TBLOCKS(maxwrite) * TBLOCK)) == NULL) { 3966 fatal(gettext("cannot allocate buffer")); 3967 } 3968 3969 while (bytes > 0) { 3970 3971 /* 3972 * readtape() obtains one block (TBLOCK) of data at a time. 3973 * Accumulate as many blocks of data in buf as we can write 3974 * in one operation. 3975 */ 3976 for (bytesread = 0; bytesread < maxwrite; bytesread += TBLOCK) { 3977 readtape(buf + bytesread); 3978 } 3979 3980 if (write(ofile, buf, maxwrite) < 0) { 3981 int saveerrno = errno; 3982 3983 if (xhdr_flgs & _X_PATH) 3984 (void) strlcpy(tempname, Xtarhdr.x_path, 3985 sizeof (tempname)); 3986 else 3987 (void) sprintf(tempname, "%.*s", NAMSIZ, 3988 dblock.dbuf.name); 3989 /* 3990 * If the extended system attribute being extracted 3991 * contains attributes that the user needs privileges 3992 * for, then just display a warning message, skip 3993 * the extraction of this file, and return. 3994 */ 3995 if ((saveerrno == EPERM) && issysattr) { 3996 (void) fprintf(stderr, gettext( 3997 "tar: unable to extract system attribute " 3998 "%s: insufficient privileges\n"), tempname); 3999 Errflg = 1; 4000 (void) free(buf); 4001 return (1); 4002 } else { 4003 (void) fprintf(stderr, gettext( 4004 "tar: %s: HELP - extract write error\n"), 4005 tempname); 4006 done(2); 4007 } 4008 } 4009 bytes -= maxwrite; 4010 4011 /* 4012 * If we've reached this point and there is still data 4013 * to be written, maxwrite had to have been determined 4014 * by the preferred I/O size. If the number of bytes 4015 * left to write is smaller than the preferred I/O size, 4016 * then we're about to do our final write to the file, so 4017 * just set maxwrite to the number of bytes left to write. 4018 */ 4019 if ((bytes > 0) && (bytes < maxwrite)) { 4020 maxwrite = bytes; 4021 } 4022 } 4023 free(buf); 4024 4025 return (0); 4026 } 4027 4028 /* 4029 * xsfile extract split file 4030 * 4031 * xsfile(ofd); ofd = output file descriptor 4032 * 4033 * file extracted and put in ofd via xblocks() 4034 * 4035 * NOTE: only called by doxtract() to extract one large file 4036 */ 4037 4038 static union hblock savedblock; /* to ensure same file across volumes */ 4039 4040 static int 4041 xsfile(int issysattr, int ofd) 4042 { 4043 int i, c; 4044 int sysattrerr = 0; 4045 char name[PATH_MAX+1]; /* holds name for diagnostics */ 4046 int extents, totalext; 4047 off_t bytes, totalbytes; 4048 4049 if (xhdr_flgs & _X_PATH) 4050 (void) strcpy(name, Xtarhdr.x_path); 4051 else 4052 (void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name); 4053 4054 totalbytes = (off_t)0; /* in case we read in half the file */ 4055 totalext = 0; /* these keep count */ 4056 4057 (void) fprintf(stderr, gettext( 4058 "tar: %s split across %d volumes\n"), name, extotal); 4059 4060 /* make sure we do extractions in order */ 4061 if (extno != 1) { /* starting in middle of file? */ 4062 (void) printf(gettext( 4063 "tar: first extent read is not #1\n" 4064 "OK to read file beginning with extent #%d (%s/%s) ? "), 4065 extno, yesstr, nostr); 4066 if (yes() == 0) { 4067 canit: 4068 passtape(); 4069 if (close(ofd) != 0) 4070 vperror(2, gettext("close error")); 4071 if (sysattrerr) { 4072 return (1); 4073 } else { 4074 return (0); 4075 } 4076 } 4077 } 4078 extents = extotal; 4079 i = extno; 4080 /*CONSTCOND*/ 4081 while (1) { 4082 if (xhdr_flgs & _X_SIZE) { 4083 bytes = extsize; 4084 } else { 4085 bytes = stbuf.st_size; 4086 } 4087 4088 if (vflag) 4089 (void) fprintf(vfile, "+++ x %s [%s #%d], %" 4090 FMT_off_t " %s, %ldK\n", 4091 name, gettext("extent"), extno, 4092 bytes, gettext("bytes"), 4093 (long)K(TBLOCKS(bytes))); 4094 if (xblocks(issysattr, bytes, ofd) != 0) { 4095 sysattrerr = 1; 4096 goto canit; 4097 } 4098 4099 totalbytes += bytes; 4100 totalext++; 4101 if (++i > extents) 4102 break; 4103 4104 /* get next volume and verify it's the right one */ 4105 copy(&savedblock, &dblock); 4106 tryagain: 4107 newvol(); 4108 xhdr_flgs = 0; 4109 getdir(); 4110 if (Xhdrflag > 0) 4111 (void) get_xdata(); /* Get x-header & regular hdr */ 4112 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 4113 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 4114 xhdr_flgs |= _X_XHDR; 4115 } 4116 if (endtape()) { /* seemingly empty volume */ 4117 (void) fprintf(stderr, gettext( 4118 "tar: first record is null\n")); 4119 asknicely: 4120 (void) fprintf(stderr, gettext( 4121 "tar: need volume with extent #%d of %s\n"), 4122 i, name); 4123 goto tryagain; 4124 } 4125 if (notsame()) { 4126 (void) fprintf(stderr, gettext( 4127 "tar: first file on that volume is not " 4128 "the same file\n")); 4129 goto asknicely; 4130 } 4131 if (i != extno) { 4132 (void) fprintf(stderr, gettext( 4133 "tar: extent #%d received out of order\ntar: " 4134 "should be #%d\n"), extno, i); 4135 (void) fprintf(stderr, gettext( 4136 "Ignore error, Abort this file, or " 4137 "load New volume (i/a/n) ? ")); 4138 c = response(); 4139 if (c == 'a') 4140 goto canit; 4141 if (c != 'i') /* default to new volume */ 4142 goto asknicely; 4143 i = extno; /* okay, start from there */ 4144 } 4145 } 4146 if (vflag) 4147 (void) fprintf(vfile, gettext( 4148 "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"), 4149 name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes))); 4150 4151 return (0); 4152 } 4153 4154 4155 /* 4156 * notsame() check if extract file extent is invalid 4157 * 4158 * returns true if anything differs between savedblock and dblock 4159 * except extno (extent number), checksum, or size (extent size). 4160 * Determines if this header belongs to the same file as the one we're 4161 * extracting. 4162 * 4163 * NOTE: though rather bulky, it is only called once per file 4164 * extension, and it can withstand changes in the definition 4165 * of the header structure. 4166 * 4167 * WARNING: this routine is local to xsfile() above 4168 */ 4169 4170 static int 4171 notsame(void) 4172 { 4173 return ( 4174 (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) || 4175 (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) || 4176 (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) || 4177 (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) || 4178 (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) || 4179 (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) || 4180 (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) || 4181 (savedblock.dbuf.extotal != dblock.dbuf.extotal) || 4182 (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize))); 4183 } 4184 4185 static void 4186 #ifdef _iBCS2 4187 dotable(char *argv[], int tbl_cnt) 4188 #else 4189 dotable(char *argv[]) 4190 #endif 4191 4192 { 4193 int tcnt; /* count # files tabled */ 4194 int fcnt; /* count # files in argv list */ 4195 char *namep, *dirp, *comp; 4196 int want; 4197 char aclchar = ' '; /* either blank or '+' */ 4198 char templink[PATH_MAX+1]; 4199 attr_data_t *attrinfo = NULL; 4200 4201 dumping = 0; 4202 4203 /* if not on magtape, maximize seek speed */ 4204 if (NotTape && !bflag) { 4205 #if SYS_BLOCK > TBLOCK 4206 nblock = SYS_BLOCK / TBLOCK; 4207 #else 4208 nblock = 1; 4209 #endif 4210 } 4211 /* 4212 * Count the number of files that are to be tabled 4213 */ 4214 fcnt = tcnt = 0; 4215 4216 #ifdef _iBCS2 4217 initarg(argv, Filefile); 4218 while (nextarg() != NULL) 4219 ++fcnt; 4220 fcnt += tbl_cnt; 4221 #endif /* _iBCS2 */ 4222 4223 for (;;) { 4224 4225 /* namep is set by wantit to point to the full name */ 4226 if ((want = wantit(argv, &namep, &dirp, &comp, &attrinfo)) == 0) 4227 continue; 4228 if (want == -1) 4229 break; 4230 if (dblock.dbuf.typeflag != 'A') 4231 ++tcnt; 4232 4233 /* 4234 * ACL support: 4235 * aclchar is introduced to indicate if there are 4236 * acl entries. longt() now takes one extra argument. 4237 */ 4238 if (vflag) { 4239 if (dblock.dbuf.typeflag == 'A') { 4240 aclchar = '+'; 4241 passtape(); 4242 continue; 4243 } 4244 longt(&stbuf, aclchar); 4245 aclchar = ' '; 4246 } 4247 4248 4249 #if defined(O_XATTR) 4250 if (xattrp != NULL) { 4251 int issysattr; 4252 char *bn = basename(attrinfo->attr_path); 4253 4254 /* 4255 * We could use sysattr_type() to test whether or not 4256 * the attribute we are processing is really an 4257 * extended system attribute, which as of this writing 4258 * just does a strcmp(), however, sysattr_type() may 4259 * be changed to issue a pathconf() call instead, which 4260 * would require being changed into the parent attribute 4261 * directory. So instead, just do simple string 4262 * comparisons to see if we are processing an extended 4263 * system attribute. 4264 */ 4265 issysattr = is_sysattr(bn); 4266 4267 (void) printf(gettext("%s %sattribute %s"), 4268 xattrp->h_names, 4269 issysattr ? gettext("system ") : "", 4270 attrinfo->attr_path); 4271 } else { 4272 (void) printf("%s", namep); 4273 } 4274 #else 4275 (void) printf("%s", namep); 4276 #endif 4277 4278 if (extno != 0) { 4279 if (vflag) { 4280 /* keep the '\n' for backwards compatibility */ 4281 (void) fprintf(vfile, gettext( 4282 "\n [extent #%d of %d]"), extno, extotal); 4283 } else { 4284 (void) fprintf(vfile, gettext( 4285 " [extent #%d of %d]"), extno, extotal); 4286 } 4287 } 4288 if (xhdr_flgs & _X_LINKPATH) { 4289 (void) strcpy(templink, Xtarhdr.x_linkpath); 4290 } else { 4291 #if defined(O_XATTR) 4292 if (xattrp != NULL) { 4293 (void) sprintf(templink, 4294 "file %.*s", NAMSIZ, xattrp->h_names); 4295 } else { 4296 (void) sprintf(templink, "%.*s", NAMSIZ, 4297 dblock.dbuf.linkname); 4298 } 4299 #else 4300 (void) sprintf(templink, "%.*s", NAMSIZ, 4301 dblock.dbuf.linkname); 4302 #endif 4303 templink[NAMSIZ] = '\0'; 4304 } 4305 if (dblock.dbuf.typeflag == '1') { 4306 /* 4307 * TRANSLATION_NOTE 4308 * Subject is omitted here. 4309 * Translate this as if 4310 * <subject> linked to %s 4311 */ 4312 #if defined(O_XATTR) 4313 if (xattrp != NULL) { 4314 (void) printf( 4315 gettext(" linked to attribute %s"), 4316 xattr_linkp->h_names + 4317 strlen(xattr_linkp->h_names) + 1); 4318 } else { 4319 (void) printf( 4320 gettext(" linked to %s"), templink); 4321 } 4322 #else 4323 (void) printf( 4324 gettext(" linked to %s"), templink); 4325 4326 #endif 4327 } 4328 if (dblock.dbuf.typeflag == '2') 4329 (void) printf(gettext( 4330 /* 4331 * TRANSLATION_NOTE 4332 * Subject is omitted here. 4333 * Translate this as if 4334 * <subject> symbolic link to %s 4335 */ 4336 " symbolic link to %s"), templink); 4337 (void) printf("\n"); 4338 #if defined(O_XATTR) 4339 if (xattrp != NULL) { 4340 free(xattrhead); 4341 xattrp = NULL; 4342 xattrhead = NULL; 4343 } 4344 #endif 4345 passtape(); 4346 } 4347 /* 4348 * Check if the number of files tabled is different from the 4349 * number of files listed on the command line 4350 */ 4351 if (fcnt > tcnt) { 4352 (void) fprintf(stderr, gettext( 4353 "tar: %d file(s) not found\n"), fcnt-tcnt); 4354 Errflg = 1; 4355 } 4356 } 4357 4358 static void 4359 putempty(blkcnt_t n) 4360 { 4361 char buf[TBLOCK]; 4362 char *cp; 4363 4364 for (cp = buf; cp < &buf[TBLOCK]; ) 4365 *cp++ = '\0'; 4366 while (n-- > 0) 4367 (void) writetbuf(buf, 1); 4368 } 4369 4370 static ushort_t Ftype = S_IFMT; 4371 4372 static void 4373 verbose(struct stat *st, char aclchar) 4374 { 4375 int i, j, temp; 4376 mode_t mode; 4377 char modestr[12]; 4378 4379 for (i = 0; i < 11; i++) 4380 modestr[i] = '-'; 4381 modestr[i] = '\0'; 4382 4383 /* a '+' sign is printed if there is ACL */ 4384 modestr[i-1] = aclchar; 4385 4386 mode = st->st_mode; 4387 for (i = 0; i < 3; i++) { 4388 temp = (mode >> (6 - (i * 3))); 4389 j = (i * 3) + 1; 4390 if (S_IROTH & temp) 4391 modestr[j] = 'r'; 4392 if (S_IWOTH & temp) 4393 modestr[j + 1] = 'w'; 4394 if (S_IXOTH & temp) 4395 modestr[j + 2] = 'x'; 4396 } 4397 temp = st->st_mode & Ftype; 4398 switch (temp) { 4399 case (S_IFIFO): 4400 modestr[0] = 'p'; 4401 break; 4402 case (S_IFCHR): 4403 modestr[0] = 'c'; 4404 break; 4405 case (S_IFDIR): 4406 modestr[0] = 'd'; 4407 break; 4408 case (S_IFBLK): 4409 modestr[0] = 'b'; 4410 break; 4411 case (S_IFREG): /* was initialized to '-' */ 4412 break; 4413 case (S_IFLNK): 4414 modestr[0] = 'l'; 4415 break; 4416 default: 4417 /* This field may be zero in old archives. */ 4418 if (is_posix && dblock.dbuf.typeflag != '1') { 4419 /* 4420 * For POSIX compliant archives, the mode field 4421 * consists of 12 bits, ie: the file type bits 4422 * are not stored in dblock.dbuf.mode. 4423 * For files other than hard links, getdir() sets 4424 * the file type bits in the st_mode field of the 4425 * stat structure based upon dblock.dbuf.typeflag. 4426 */ 4427 (void) fprintf(stderr, gettext( 4428 "tar: impossible file type")); 4429 } 4430 } 4431 4432 if ((S_ISUID & Gen.g_mode) == S_ISUID) 4433 modestr[3] = 's'; 4434 if ((S_ISVTX & Gen.g_mode) == S_ISVTX) 4435 modestr[9] = 't'; 4436 if ((S_ISGID & Gen.g_mode) == S_ISGID && modestr[6] == 'x') 4437 modestr[6] = 's'; 4438 else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x') 4439 modestr[6] = 'l'; 4440 (void) fprintf(vfile, "%s", modestr); 4441 } 4442 4443 static void 4444 longt(struct stat *st, char aclchar) 4445 { 4446 char fileDate[30]; 4447 struct tm *tm; 4448 4449 verbose(st, aclchar); 4450 (void) fprintf(vfile, "%3ld/%-3ld", st->st_uid, st->st_gid); 4451 4452 if (dblock.dbuf.typeflag == '2') { 4453 if (xhdr_flgs & _X_LINKPATH) 4454 st->st_size = (off_t)strlen(Xtarhdr.x_linkpath); 4455 else 4456 st->st_size = (off_t)(memchr(dblock.dbuf.linkname, 4457 '\0', NAMSIZ) ? 4458 (strlen(dblock.dbuf.linkname)) : (NAMSIZ)); 4459 } 4460 (void) fprintf(vfile, " %6" FMT_off_t, st->st_size); 4461 4462 tm = localtime(&(st->st_mtime)); 4463 (void) strftime(fileDate, sizeof (fileDate), 4464 dcgettext((const char *)0, "%b %e %R %Y", LC_TIME), tm); 4465 (void) fprintf(vfile, " %s ", fileDate); 4466 } 4467 4468 4469 /* 4470 * checkdir - Attempt to ensure that the path represented in name 4471 * exists, and return 1 if this is true and name itself is a 4472 * directory. 4473 * Return 0 if this path cannot be created or if name is not 4474 * a directory. 4475 */ 4476 4477 static int 4478 checkdir(char *name) 4479 { 4480 char lastChar; /* the last character in name */ 4481 char *cp; /* scratch pointer into name */ 4482 char *firstSlash = NULL; /* first slash in name */ 4483 char *lastSlash = NULL; /* last slash in name */ 4484 int nameLen; /* length of name */ 4485 int trailingSlash; /* true if name ends in slash */ 4486 int leadingSlash; /* true if name begins with slash */ 4487 int markedDir; /* true if name denotes a directory */ 4488 int success; /* status of makeDir call */ 4489 4490 4491 /* 4492 * Scan through the name, and locate first and last slashes. 4493 */ 4494 4495 for (cp = name; *cp; cp++) { 4496 if (*cp == '/') { 4497 if (! firstSlash) { 4498 firstSlash = cp; 4499 } 4500 lastSlash = cp; 4501 } 4502 } 4503 4504 /* 4505 * Determine what you can from the proceeds of the scan. 4506 */ 4507 4508 lastChar = *(cp - 1); 4509 nameLen = (int)(cp - name); 4510 trailingSlash = (lastChar == '/'); 4511 leadingSlash = (*name == '/'); 4512 markedDir = (dblock.dbuf.typeflag == '5' || trailingSlash); 4513 4514 if (! lastSlash && ! markedDir) { 4515 /* 4516 * The named file does not have any subdrectory 4517 * structure; just bail out. 4518 */ 4519 4520 return (0); 4521 } 4522 4523 /* 4524 * Make sure that name doesn`t end with slash for the loop. 4525 * This ensures that the makeDir attempt after the loop is 4526 * meaningful. 4527 */ 4528 4529 if (trailingSlash) { 4530 name[nameLen-1] = '\0'; 4531 } 4532 4533 /* 4534 * Make the path one component at a time. 4535 */ 4536 4537 for (cp = strchr(leadingSlash ? name+1 : name, '/'); 4538 cp; 4539 cp = strchr(cp+1, '/')) { 4540 *cp = '\0'; 4541 success = makeDir(name); 4542 *cp = '/'; 4543 4544 if (!success) { 4545 name[nameLen-1] = lastChar; 4546 return (0); 4547 } 4548 } 4549 4550 /* 4551 * This makes the last component of the name, if it is a 4552 * directory. 4553 */ 4554 4555 if (markedDir) { 4556 if (! makeDir(name)) { 4557 name[nameLen-1] = lastChar; 4558 return (0); 4559 } 4560 } 4561 4562 name[nameLen-1] = (lastChar == '/') ? '\0' : lastChar; 4563 return (markedDir); 4564 } 4565 4566 /* 4567 * resugname - Restore the user name and group name. Search the NIS 4568 * before using the uid and gid. 4569 * (It is presumed that an archive entry cannot be 4570 * simultaneously a symlink and some other type.) 4571 */ 4572 4573 static void 4574 resugname(int dirfd, /* dir fd file resides in */ 4575 char *name, /* name of the file to be modified */ 4576 int symflag) /* true if file is a symbolic link */ 4577 { 4578 uid_t duid; 4579 gid_t dgid; 4580 struct stat *sp = &stbuf; 4581 char *u_g_name; 4582 4583 if (checkflag == 1) { /* Extended tar format and euid == 0 */ 4584 4585 /* 4586 * Try and extract the intended uid and gid from the name 4587 * service before believing the uid and gid in the header. 4588 * 4589 * In the case where we archived a setuid or setgid file 4590 * owned by someone with a large uid, then it will 4591 * have made it into the archive with a uid of nobody. If 4592 * the corresponding username doesn't appear to exist, then we 4593 * want to make sure it *doesn't* end up as setuid nobody! 4594 * 4595 * Our caller will print an error message about the fact 4596 * that the restore didn't work out quite right .. 4597 */ 4598 if (xhdr_flgs & _X_UNAME) 4599 u_g_name = Xtarhdr.x_uname; 4600 else 4601 u_g_name = dblock.dbuf.uname; 4602 if ((duid = getuidbyname(u_g_name)) == -1) { 4603 if (S_ISREG(sp->st_mode) && sp->st_uid == UID_NOBODY && 4604 (sp->st_mode & S_ISUID) == S_ISUID) 4605 (void) chmod(name, 4606 MODEMASK & sp->st_mode & ~S_ISUID); 4607 duid = sp->st_uid; 4608 } 4609 4610 /* (Ditto for gids) */ 4611 4612 if (xhdr_flgs & _X_GNAME) 4613 u_g_name = Xtarhdr.x_gname; 4614 else 4615 u_g_name = dblock.dbuf.gname; 4616 if ((dgid = getgidbyname(u_g_name)) == -1) { 4617 if (S_ISREG(sp->st_mode) && sp->st_gid == GID_NOBODY && 4618 (sp->st_mode & S_ISGID) == S_ISGID) 4619 (void) chmod(name, 4620 MODEMASK & sp->st_mode & ~S_ISGID); 4621 dgid = sp->st_gid; 4622 } 4623 } else if (checkflag == 2) { /* tar format and euid == 0 */ 4624 duid = sp->st_uid; 4625 dgid = sp->st_gid; 4626 } 4627 if ((checkflag == 1) || (checkflag == 2)) 4628 (void) fchownat(dirfd, name, duid, dgid, symflag); 4629 } 4630 4631 /*ARGSUSED*/ 4632 static void 4633 onintr(int sig) 4634 { 4635 (void) signal(SIGINT, SIG_IGN); 4636 term++; 4637 } 4638 4639 /*ARGSUSED*/ 4640 static void 4641 onquit(int sig) 4642 { 4643 (void) signal(SIGQUIT, SIG_IGN); 4644 term++; 4645 } 4646 4647 /*ARGSUSED*/ 4648 static void 4649 onhup(int sig) 4650 { 4651 (void) signal(SIGHUP, SIG_IGN); 4652 term++; 4653 } 4654 4655 static void 4656 tomodes(struct stat *sp) 4657 { 4658 uid_t uid; 4659 gid_t gid; 4660 4661 bzero(dblock.dummy, TBLOCK); 4662 4663 /* 4664 * If the uid or gid is too large, we can't put it into 4665 * the archive. We could fail to put anything in the 4666 * archive at all .. but most of the time the name service 4667 * will save the day when we do a lookup at restore time. 4668 * 4669 * Instead we choose a "safe" uid and gid, and fix up whether 4670 * or not the setuid and setgid bits are left set to extraction 4671 * time. 4672 */ 4673 if (Eflag) { 4674 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) { 4675 xhdr_flgs |= _X_UID; 4676 Xtarhdr.x_uid = uid; 4677 } 4678 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) { 4679 xhdr_flgs |= _X_GID; 4680 Xtarhdr.x_gid = gid; 4681 } 4682 if (sp->st_size > TAR_OFFSET_MAX) { 4683 xhdr_flgs |= _X_SIZE; 4684 Xtarhdr.x_filesz = sp->st_size; 4685 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4686 (off_t)0); 4687 } else 4688 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4689 sp->st_size); 4690 } else { 4691 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 4692 sp->st_size); 4693 } 4694 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) 4695 uid = UID_NOBODY; 4696 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) 4697 gid = GID_NOBODY; 4698 (void) sprintf(dblock.dbuf.gid, "%07lo", gid); 4699 (void) sprintf(dblock.dbuf.uid, "%07lo", uid); 4700 (void) sprintf(dblock.dbuf.mode, "%07lo", sp->st_mode & POSIXMODES); 4701 (void) sprintf(dblock.dbuf.mtime, "%011lo", sp->st_mtime); 4702 } 4703 4704 static int 4705 #ifdef EUC 4706 /* 4707 * Warning: the result of this function depends whether 'char' is a 4708 * signed or unsigned data type. This a source of potential 4709 * non-portability among heterogeneous systems. It is retained here 4710 * for backward compatibility. 4711 */ 4712 checksum_signed(union hblock *dblockp) 4713 #else 4714 checksum(union hblock *dblockp) 4715 #endif /* EUC */ 4716 { 4717 int i; 4718 char *cp; 4719 4720 for (cp = dblockp->dbuf.chksum; 4721 cp < &dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]; cp++) 4722 *cp = ' '; 4723 i = 0; 4724 for (cp = dblockp->dummy; cp < &(dblockp->dummy[TBLOCK]); cp++) 4725 i += *cp; 4726 return (i); 4727 } 4728 4729 #ifdef EUC 4730 /* 4731 * Generate unsigned checksum, regardless of what C compiler is 4732 * used. Survives in the face of arbitrary 8-bit clean filenames, 4733 * e.g., internationalized filenames. 4734 */ 4735 static int 4736 checksum(union hblock *dblockp) 4737 { 4738 unsigned i; 4739 unsigned char *cp; 4740 4741 for (cp = (unsigned char *) dblockp->dbuf.chksum; 4742 cp < (unsigned char *) 4743 &(dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]); cp++) 4744 *cp = ' '; 4745 i = 0; 4746 for (cp = (unsigned char *) dblockp->dummy; 4747 cp < (unsigned char *) &(dblockp->dummy[TBLOCK]); cp++) 4748 i += *cp; 4749 4750 return (i); 4751 } 4752 #endif /* EUC */ 4753 4754 /* 4755 * If the w flag is set, output the action to be taken and the name of the 4756 * file. Perform the action if the user response is affirmative. 4757 */ 4758 4759 static int 4760 checkw(char c, char *name) 4761 { 4762 if (wflag) { 4763 (void) fprintf(vfile, "%c ", c); 4764 if (vflag) 4765 longt(&stbuf, ' '); /* do we have acl info here */ 4766 (void) fprintf(vfile, "%s: ", name); 4767 if (yes() == 1) { 4768 return (1); 4769 } 4770 return (0); 4771 } 4772 return (1); 4773 } 4774 4775 /* 4776 * When the F flag is set, exclude RCS and SCCS directories. If F is set 4777 * twice, also exclude .o files, and files names errs, core, and a.out. 4778 */ 4779 4780 static int 4781 checkf(char *name, int mode, int howmuch) 4782 { 4783 int l; 4784 4785 if ((mode & S_IFMT) == S_IFDIR) { 4786 if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0)) 4787 return (0); 4788 return (1); 4789 } 4790 if ((l = (int)strlen(name)) < 3) 4791 return (1); 4792 if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 4793 return (0); 4794 if (howmuch > 1) { 4795 if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 || 4796 strcmp(name, "a.out") == 0) 4797 return (0); 4798 } 4799 4800 /* SHOULD CHECK IF IT IS EXECUTABLE */ 4801 return (1); 4802 } 4803 4804 static int 4805 response(void) 4806 { 4807 int c; 4808 4809 c = getchar(); 4810 if (c != '\n') 4811 while (getchar() != '\n') 4812 ; 4813 else c = 'n'; 4814 return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c); 4815 } 4816 4817 /* Has file been modified since being put into archive? If so, return > 0. */ 4818 4819 static off_t lookup(char *); 4820 4821 static int 4822 checkupdate(char *arg) 4823 { 4824 char name[PATH_MAX+1]; 4825 time_t mtime; 4826 long nsecs; 4827 off_t seekp; 4828 4829 rewind(tfile); 4830 if ((seekp = lookup(arg)) < 0) 4831 return (1); 4832 (void) fseek(tfile, seekp, 0); 4833 (void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs); 4834 4835 /* 4836 * Unless nanoseconds were stored in the file, only use seconds for 4837 * comparison of time. Nanoseconds are stored when -E is specified. 4838 */ 4839 if (Eflag == 0) 4840 return (stbuf.st_mtime > mtime); 4841 4842 if ((stbuf.st_mtime < mtime) || 4843 ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs))) 4844 return (0); 4845 return (1); 4846 } 4847 4848 4849 /* 4850 * newvol get new floppy (or tape) volume 4851 * 4852 * newvol(); resets tapepos and first to TRUE, prompts for 4853 * for new volume, and waits. 4854 * if dumping, end-of-file is written onto the tape. 4855 */ 4856 4857 static void 4858 newvol(void) 4859 { 4860 int c; 4861 4862 if (dumping) { 4863 #ifdef DEBUG 4864 DEBUG("newvol called with 'dumping' set\n", 0, 0); 4865 #endif 4866 putempty((blkcnt_t)2); /* 2 EOT marks */ 4867 closevol(); 4868 flushtape(); 4869 sync(); 4870 tapepos = 0; 4871 } else 4872 first = TRUE; 4873 if (close(mt) != 0) 4874 vperror(2, gettext("close error")); 4875 mt = 0; 4876 (void) fprintf(stderr, gettext( 4877 "tar: \007please insert new volume, then press RETURN.")); 4878 (void) fseek(stdin, (off_t)0, 2); /* scan over read-ahead */ 4879 while ((c = getchar()) != '\n' && ! term) 4880 if (c == EOF) 4881 done(Errflg); 4882 if (term) 4883 done(Errflg); 4884 4885 errno = 0; 4886 4887 if (strcmp(usefile, "-") == 0) { 4888 mt = dup(1); 4889 } else { 4890 mt = open(usefile, dumping ? update : 0); 4891 } 4892 4893 if (mt < 0) { 4894 (void) fprintf(stderr, gettext( 4895 "tar: cannot reopen %s (%s)\n"), 4896 dumping ? gettext("output") : gettext("input"), usefile); 4897 4898 #ifdef DEBUG 4899 DEBUG("update=%d, usefile=%s ", update, usefile); 4900 DEBUG("mt=%d, [%s]\n", mt, strerror(errno)); 4901 #endif 4902 4903 done(2); 4904 } 4905 } 4906 4907 /* 4908 * Write a trailer portion to close out the current output volume. 4909 */ 4910 4911 static void 4912 closevol(void) 4913 { 4914 if (mulvol) { 4915 /* 4916 * blocklim does not count the 2 EOT marks; 4917 * tapepos does count the 2 EOT marks; 4918 * therefore we need the +2 below. 4919 */ 4920 putempty(blocklim + (blkcnt_t)2 - tapepos); 4921 } 4922 } 4923 4924 static void 4925 done(int n) 4926 { 4927 if (tfile != NULL) 4928 (void) unlink(tname); 4929 if (compress_opt != NULL) 4930 (void) free(compress_opt); 4931 if (mt > 0) { 4932 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 4933 perror(gettext("tar: close error")); 4934 exit(2); 4935 } 4936 } 4937 exit(n); 4938 } 4939 4940 /* 4941 * Determine if s1 is a prefix portion of s2 (or the same as s2). 4942 */ 4943 4944 static int 4945 is_prefix(char *s1, char *s2) 4946 { 4947 while (*s1) 4948 if (*s1++ != *s2++) 4949 return (0); 4950 if (*s2) 4951 return (*s2 == '/'); 4952 return (1); 4953 } 4954 4955 /* 4956 * lookup and bsrch look through tfile entries to find a match for a name. 4957 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 4958 * a pair of newline chars, so the buffer it uses must be long enough for 4959 * two lines: name and modification time as well as period, newline and space. 4960 * 4961 * A kludge was added to bsrch to take care of matching on the first entry 4962 * in the file--there is no leading newline. So, if we are reading from the 4963 * start of the file, read into byte two and set the first byte to a newline. 4964 * Otherwise, the first entry cannot be matched. 4965 * 4966 */ 4967 4968 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 4969 static off_t 4970 lookup(char *s) 4971 { 4972 int i; 4973 off_t a; 4974 4975 for (i = 0; s[i]; i++) 4976 if (s[i] == ' ') 4977 break; 4978 a = bsrch(s, i, low, high); 4979 return (a); 4980 } 4981 4982 static off_t 4983 bsrch(char *s, int n, off_t l, off_t h) 4984 { 4985 int i, j; 4986 char b[N]; 4987 off_t m, m1; 4988 4989 4990 loop: 4991 if (l >= h) 4992 return ((off_t)-1); 4993 m = l + (h-l)/2 - N/2; 4994 if (m < l) 4995 m = l; 4996 (void) fseek(tfile, m, 0); 4997 if (m == 0) { 4998 (void) fread(b+1, 1, N-1, tfile); 4999 b[0] = '\n'; 5000 m--; 5001 } else 5002 (void) fread(b, 1, N, tfile); 5003 for (i = 0; i < N; i++) { 5004 if (b[i] == '\n') 5005 break; 5006 m++; 5007 } 5008 if (m >= h) 5009 return ((off_t)-1); 5010 m1 = m; 5011 j = i; 5012 for (i++; i < N; i++) { 5013 m1++; 5014 if (b[i] == '\n') 5015 break; 5016 } 5017 i = cmp(b+j, s, n); 5018 if (i < 0) { 5019 h = m; 5020 goto loop; 5021 } 5022 if (i > 0) { 5023 l = m1; 5024 goto loop; 5025 } 5026 if (m < 0) 5027 m = 0; 5028 return (m); 5029 } 5030 5031 static int 5032 cmp(char *b, char *s, int n) 5033 { 5034 int i; 5035 5036 assert(b[0] == '\n'); 5037 5038 for (i = 0; i < n; i++) { 5039 if (b[i+1] > s[i]) 5040 return (-1); 5041 if (b[i+1] < s[i]) 5042 return (1); 5043 } 5044 return (b[i+1] == ' '? 0 : -1); 5045 } 5046 5047 5048 /* 5049 * seekdisk seek to next file on archive 5050 * 5051 * called by passtape() only 5052 * 5053 * WARNING: expects "nblock" to be set, that is, readtape() to have 5054 * already been called. Since passtape() is only called 5055 * after a file header block has been read (why else would 5056 * we skip to next file?), this is currently safe. 5057 * 5058 * changed to guarantee SYS_BLOCK boundary 5059 */ 5060 5061 static void 5062 seekdisk(blkcnt_t blocks) 5063 { 5064 off_t seekval; 5065 #if SYS_BLOCK > TBLOCK 5066 /* handle non-multiple of SYS_BLOCK */ 5067 blkcnt_t nxb; /* # extra blocks */ 5068 #endif 5069 5070 tapepos += blocks; 5071 #ifdef DEBUG 5072 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 5073 #endif 5074 if (recno + blocks <= nblock) { 5075 recno += blocks; 5076 return; 5077 } 5078 if (recno > nblock) 5079 recno = nblock; 5080 seekval = (off_t)blocks - (nblock - recno); 5081 recno = nblock; /* so readtape() reads next time through */ 5082 #if SYS_BLOCK > TBLOCK 5083 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 5084 #ifdef DEBUG 5085 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 5086 nxb, seekval); 5087 #endif 5088 if (nxb && nxb > seekval) /* don't seek--we'll read */ 5089 goto noseek; 5090 seekval -= nxb; /* don't seek quite so far */ 5091 #endif 5092 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 5093 (void) fprintf(stderr, gettext( 5094 "tar: device seek error\n")); 5095 done(3); 5096 } 5097 #if SYS_BLOCK > TBLOCK 5098 /* read those extra blocks */ 5099 noseek: 5100 if (nxb) { 5101 #ifdef DEBUG 5102 DEBUG("reading extra blocks\n", 0, 0); 5103 #endif 5104 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 5105 (void) fprintf(stderr, gettext( 5106 "tar: read error while skipping file\n")); 5107 done(8); 5108 } 5109 recno = nxb; /* so we don't read in next readtape() */ 5110 } 5111 #endif 5112 } 5113 5114 static void 5115 readtape(char *buffer) 5116 { 5117 int i, j; 5118 5119 ++tapepos; 5120 if (recno >= nblock || first) { 5121 if (first) { 5122 /* 5123 * set the number of blocks to read initially, based on 5124 * the defined defaults for the device, or on the 5125 * explicit block factor given. 5126 */ 5127 if (bflag || defaults_used || NotTape) 5128 j = nblock; 5129 else 5130 j = NBLOCK; 5131 } else 5132 j = nblock; 5133 5134 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 5135 (void) fprintf(stderr, gettext( 5136 "tar: tape read error\n")); 5137 done(3); 5138 /* 5139 * i == 0 and !rflag means that EOF is reached and we are 5140 * trying to update or replace an empty tar file, so exit 5141 * with an error. 5142 * 5143 * If i == 0 and !first and NotTape, it means the pointer 5144 * has gone past the EOF. It could happen if two processes 5145 * try to update the same tar file simultaneously. So exit 5146 * with an error. 5147 */ 5148 5149 } else if (i == 0) { 5150 if (first && !rflag) { 5151 (void) fprintf(stderr, gettext( 5152 "tar: blocksize = %d\n"), i); 5153 done(Errflg); 5154 } else if (!first && (!rflag || NotTape)) { 5155 mterr("read", 0, 2); 5156 } 5157 } else if ((!first || Bflag) && i != TBLOCK*j) { 5158 /* 5159 * Short read - try to get the remaining bytes. 5160 */ 5161 5162 int remaining = (TBLOCK * j) - i; 5163 char *b = (char *)tbuf + i; 5164 int r; 5165 5166 do { 5167 if ((r = read(mt, b, remaining)) < 0) { 5168 (void) fprintf(stderr, 5169 gettext("tar: tape read error\n")); 5170 done(3); 5171 } 5172 b += r; 5173 remaining -= r; 5174 i += r; 5175 } while (remaining > 0 && r != 0); 5176 } 5177 if (first) { 5178 if ((i % TBLOCK) != 0) { 5179 (void) fprintf(stderr, gettext( 5180 "tar: tape blocksize error\n")); 5181 done(3); 5182 } 5183 i /= TBLOCK; 5184 if (vflag && i != nblock && i != 1) { 5185 if (!NotTape) 5186 (void) fprintf(stderr, gettext( 5187 "tar: blocksize = %d\n"), i); 5188 } 5189 5190 /* 5191 * If we are reading a tape, then a short read is 5192 * understood to signify that the amount read is 5193 * the tape's actual blocking factor. We adapt 5194 * nblock accordingly. There is no reason to do 5195 * this when the device is not blocked. 5196 */ 5197 5198 if (!NotTape) 5199 nblock = i; 5200 } 5201 recno = 0; 5202 } 5203 5204 first = FALSE; 5205 copy(buffer, &tbuf[recno++]); 5206 } 5207 5208 5209 /* 5210 * replacement for writetape. 5211 */ 5212 5213 static int 5214 writetbuf(char *buffer, int n) 5215 { 5216 int i; 5217 5218 tapepos += n; /* output block count */ 5219 5220 if (recno >= nblock) { 5221 i = write(mt, (char *)tbuf, TBLOCK*nblock); 5222 if (i != TBLOCK*nblock) 5223 mterr("write", i, 2); 5224 recno = 0; 5225 } 5226 5227 /* 5228 * Special case: We have an empty tape buffer, and the 5229 * users data size is >= the tape block size: Avoid 5230 * the bcopy and dma direct to tape. BIG WIN. Add the 5231 * residual to the tape buffer. 5232 */ 5233 while (recno == 0 && n >= nblock) { 5234 i = (int)write(mt, buffer, TBLOCK*nblock); 5235 if (i != TBLOCK*nblock) 5236 mterr("write", i, 2); 5237 n -= nblock; 5238 buffer += (nblock * TBLOCK); 5239 } 5240 5241 while (n-- > 0) { 5242 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 5243 buffer += TBLOCK; 5244 if (recno >= nblock) { 5245 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 5246 if (i != TBLOCK*nblock) 5247 mterr("write", i, 2); 5248 recno = 0; 5249 } 5250 } 5251 5252 /* Tell the user how much to write to get in sync */ 5253 return (nblock - recno); 5254 } 5255 5256 /* 5257 * backtape - reposition tape after reading soft "EOF" record 5258 * 5259 * Backtape tries to reposition the tape back over the EOF 5260 * record. This is for the 'u' and 'r' function letters so that the 5261 * tape can be extended. This code is not well designed, but 5262 * I'm confident that the only callers who care about the 5263 * backspace-over-EOF feature are those involved in 'u' and 'r'. 5264 * 5265 * The proper way to backup the tape is through the use of mtio. 5266 * Earlier spins used lseek combined with reads in a confusing 5267 * maneuver that only worked on 4.x, but shouldn't have, even 5268 * there. Lseeks are explicitly not supported for tape devices. 5269 */ 5270 5271 static void 5272 backtape(void) 5273 { 5274 struct mtop mtcmd; 5275 #ifdef DEBUG 5276 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 5277 nblock); 5278 #endif 5279 /* 5280 * Backup to the position in the archive where the record 5281 * currently sitting in the tbuf buffer is situated. 5282 */ 5283 5284 if (NotTape) { 5285 /* 5286 * For non-tape devices, this means lseeking to the 5287 * correct position. The absolute location tapepos-recno 5288 * should be the beginning of the current record. 5289 */ 5290 5291 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 5292 (off_t)-1) { 5293 (void) fprintf(stderr, 5294 gettext("tar: lseek to end of archive failed\n")); 5295 done(4); 5296 } 5297 } else { 5298 /* 5299 * For tape devices, we backup over the most recently 5300 * read record. 5301 */ 5302 5303 mtcmd.mt_op = MTBSR; 5304 mtcmd.mt_count = 1; 5305 5306 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 5307 (void) fprintf(stderr, 5308 gettext("tar: backspace over record failed\n")); 5309 done(4); 5310 } 5311 } 5312 5313 /* 5314 * Decrement the tape and tbuf buffer indices to prepare for the 5315 * coming write to overwrite the soft EOF record. 5316 */ 5317 5318 recno--; 5319 tapepos--; 5320 } 5321 5322 5323 /* 5324 * flushtape write buffered block(s) onto tape 5325 * 5326 * recno points to next free block in tbuf. If nonzero, a write is done. 5327 * Care is taken to write in multiples of SYS_BLOCK when device is 5328 * non-magtape in case raw i/o is used. 5329 * 5330 * NOTE: this is called by writetape() to do the actual writing 5331 */ 5332 5333 static void 5334 flushtape(void) 5335 { 5336 #ifdef DEBUG 5337 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 5338 #endif 5339 if (recno > 0) { /* anything buffered? */ 5340 if (NotTape) { 5341 #if SYS_BLOCK > TBLOCK 5342 int i; 5343 5344 /* 5345 * an odd-block write can only happen when 5346 * we are at the end of a volume that is not a tape. 5347 * Here we round recno up to an even SYS_BLOCK 5348 * boundary. 5349 */ 5350 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 5351 #ifdef DEBUG 5352 DEBUG("flushtape() %d rounding blocks\n", i, 0); 5353 #endif 5354 recno += i; /* round up to even SYS_BLOCK */ 5355 } 5356 #endif 5357 if (recno > nblock) 5358 recno = nblock; 5359 } 5360 #ifdef DEBUG 5361 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 5362 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 5363 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 5364 #endif 5365 if (write(mt, tbuf, 5366 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 5367 (void) fprintf(stderr, gettext( 5368 "tar: tape write error\n")); 5369 done(2); 5370 } 5371 recno = 0; 5372 } 5373 } 5374 5375 static void 5376 copy(void *dst, void *src) 5377 { 5378 (void) memcpy(dst, src, TBLOCK); 5379 } 5380 5381 #ifdef _iBCS2 5382 /* 5383 * initarg -- initialize things for nextarg. 5384 * 5385 * argv filename list, a la argv. 5386 * filefile name of file containing filenames. Unless doing 5387 * a create, seeks must be allowable (e.g. no named pipes). 5388 * 5389 * - if filefile is non-NULL, it will be used first, and argv will 5390 * be used when the data in filefile are exhausted. 5391 * - otherwise argv will be used. 5392 */ 5393 static char **Cmdargv = NULL; 5394 static FILE *FILEFile = NULL; 5395 static long seekFile = -1; 5396 static char *ptrtoFile, *begofFile, *endofFile; 5397 5398 static void 5399 initarg(char *argv[], char *filefile) 5400 { 5401 struct stat statbuf; 5402 char *p; 5403 int nbytes; 5404 5405 Cmdargv = argv; 5406 if (filefile == NULL) 5407 return; /* no -F file */ 5408 if (FILEFile != NULL) { 5409 /* 5410 * need to REinitialize 5411 */ 5412 if (seekFile != -1) 5413 (void) fseek(FILEFile, seekFile, 0); 5414 ptrtoFile = begofFile; 5415 return; 5416 } 5417 /* 5418 * first time initialization 5419 */ 5420 if ((FILEFile = fopen(filefile, "r")) == NULL) 5421 fatal(gettext("cannot open (%s)"), filefile); 5422 (void) fstat(fileno(FILEFile), &statbuf); 5423 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 5424 (void) fprintf(stderr, gettext( 5425 "tar: %s is not a regular file\n"), filefile); 5426 (void) fclose(FILEFile); 5427 done(1); 5428 } 5429 ptrtoFile = begofFile = endofFile; 5430 seekFile = 0; 5431 if (!xflag) 5432 return; /* the file will be read only once anyway */ 5433 nbytes = statbuf.st_size; 5434 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 5435 nbytes -= 20; 5436 if (nbytes < 50) { 5437 free(begofFile); 5438 begofFile = endofFile; 5439 return; /* no room so just do plain reads */ 5440 } 5441 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 5442 fatal(gettext("could not read %s"), filefile); 5443 ptrtoFile = begofFile; 5444 endofFile = begofFile + nbytes; 5445 for (p = begofFile; p < endofFile; ++p) 5446 if (*p == '\n') 5447 *p = '\0'; 5448 if (nbytes != statbuf.st_size) 5449 seekFile = nbytes + 1; 5450 else 5451 (void) fclose(FILEFile); 5452 } 5453 5454 /* 5455 * nextarg -- get next argument of arglist. 5456 * 5457 * The argument is taken from wherever is appropriate. 5458 * 5459 * If the 'F file' function modifier has been specified, the argument 5460 * will be taken from the file, unless EOF has been reached. 5461 * Otherwise the argument will be taken from argv. 5462 * 5463 * WARNING: 5464 * Return value may point to static data, whose contents are over- 5465 * written on each call. 5466 */ 5467 static char * 5468 nextarg(void) 5469 { 5470 static char nameFile[PATH_MAX + 1]; 5471 int n; 5472 char *p; 5473 5474 if (FILEFile) { 5475 if (ptrtoFile < endofFile) { 5476 p = ptrtoFile; 5477 while (*ptrtoFile) 5478 ++ptrtoFile; 5479 ++ptrtoFile; 5480 return (p); 5481 } 5482 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 5483 n = strlen(nameFile); 5484 if (n > 0 && nameFile[n-1] == '\n') 5485 nameFile[n-1] = '\0'; 5486 return (nameFile); 5487 } 5488 } 5489 return (*Cmdargv++); 5490 } 5491 #endif /* _iBCS2 */ 5492 5493 /* 5494 * kcheck() 5495 * - checks the validity of size values for non-tape devices 5496 * - if size is zero, mulvol tar is disabled and size is 5497 * assumed to be infinite. 5498 * - returns volume size in TBLOCKS 5499 */ 5500 5501 static blkcnt_t 5502 kcheck(char *kstr) 5503 { 5504 blkcnt_t kval; 5505 5506 kval = strtoll(kstr, NULL, 0); 5507 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 5508 mulvol = 0; /* definitely not mulvol, but we must */ 5509 return (0); /* took out setting of NotTape */ 5510 } 5511 if (kval < (blkcnt_t)MINSIZE) { 5512 (void) fprintf(stderr, gettext( 5513 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 5514 ").\n"), (ulong_t)MINSIZE, kval); 5515 if (!kflag) 5516 (void) fprintf(stderr, gettext( 5517 "bad size entry for %s in %s.\n"), 5518 archive, DEF_FILE); 5519 done(1); 5520 } 5521 mulvol++; 5522 NotTape++; /* implies non-tape */ 5523 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 5524 } 5525 5526 5527 /* 5528 * bcheck() 5529 * - checks the validity of blocking factors 5530 * - returns blocking factor 5531 */ 5532 5533 static int 5534 bcheck(char *bstr) 5535 { 5536 blkcnt_t bval; 5537 5538 bval = strtoll(bstr, NULL, 0); 5539 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 5540 (void) fprintf(stderr, gettext( 5541 "tar: invalid blocksize \"%s\".\n"), bstr); 5542 if (!bflag) 5543 (void) fprintf(stderr, gettext( 5544 "bad blocksize entry for '%s' in %s.\n"), 5545 archive, DEF_FILE); 5546 done(1); 5547 } 5548 5549 return ((int)bval); 5550 } 5551 5552 5553 /* 5554 * defset() 5555 * - reads DEF_FILE for the set of default values specified. 5556 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 5557 * - 'usefile' points to static data, so will be overwritten 5558 * if this routine is called a second time. 5559 * - the pattern specified by 'arch' must be followed by four 5560 * blank-separated fields (1) device (2) blocking, 5561 * (3) size(K), and (4) tape 5562 * for example: archive0=/dev/fd 1 400 n 5563 */ 5564 5565 static int 5566 defset(char *arch) 5567 { 5568 char *bp; 5569 5570 if (defopen(DEF_FILE) != 0) 5571 return (FALSE); 5572 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 5573 (void) fprintf(stderr, gettext( 5574 "tar: error setting parameters for %s.\n"), DEF_FILE); 5575 return (FALSE); /* & following ones too */ 5576 } 5577 if ((bp = defread(arch)) == NULL) { 5578 (void) fprintf(stderr, gettext( 5579 "tar: missing or invalid '%s' entry in %s.\n"), 5580 arch, DEF_FILE); 5581 return (FALSE); 5582 } 5583 if ((usefile = strtok(bp, " \t")) == NULL) { 5584 (void) fprintf(stderr, gettext( 5585 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 5586 return (FALSE); 5587 } 5588 if ((bp = strtok(NULL, " \t")) == NULL) { 5589 (void) fprintf(stderr, gettext( 5590 "tar: block component missing in '%s' entry in %s.\n"), 5591 arch, DEF_FILE); 5592 return (FALSE); 5593 } 5594 nblock = bcheck(bp); 5595 if ((bp = strtok(NULL, " \t")) == NULL) { 5596 (void) fprintf(stderr, gettext( 5597 "tar: size component missing in '%s' entry in %s.\n"), 5598 arch, DEF_FILE); 5599 return (FALSE); 5600 } 5601 blocklim = kcheck(bp); 5602 if ((bp = strtok(NULL, " \t")) != NULL) 5603 NotTape = (*bp == 'n' || *bp == 'N'); 5604 else 5605 NotTape = (blocklim != 0); 5606 (void) defopen(NULL); 5607 #ifdef DEBUG 5608 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 5609 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 5610 nblock, blocklim); 5611 DEBUG("defset: not tape = %d\n", NotTape, 0); 5612 #endif 5613 return (TRUE); 5614 } 5615 5616 5617 /* 5618 * Following code handles excluded and included files. 5619 * A hash table of file names to be {in,ex}cluded is built. 5620 * For excluded files, before writing or extracting a file 5621 * check to see if it is in the exclude_tbl. 5622 * For included files, the wantit() procedure will check to 5623 * see if the named file is in the include_tbl. 5624 */ 5625 5626 static void 5627 build_table(file_list_t *table[], char *file) 5628 { 5629 FILE *fp; 5630 char buf[PATH_MAX + 1]; 5631 5632 if ((fp = fopen(file, "r")) == (FILE *)NULL) 5633 vperror(1, gettext("could not open %s"), file); 5634 while (fgets(buf, sizeof (buf), fp) != NULL) { 5635 if (buf[strlen(buf) - 1] == '\n') 5636 buf[strlen(buf) - 1] = '\0'; 5637 /* Only add to table if line has something in it */ 5638 if (strspn(buf, " \t") != strlen(buf)) 5639 add_file_to_table(table, buf); 5640 } 5641 (void) fclose(fp); 5642 } 5643 5644 5645 /* 5646 * Add a file name to the the specified table, if the file name has any 5647 * trailing '/'s then delete them before inserting into the table 5648 */ 5649 5650 static void 5651 add_file_to_table(file_list_t *table[], char *str) 5652 { 5653 char name[PATH_MAX + 1]; 5654 unsigned int h; 5655 file_list_t *exp; 5656 5657 (void) strcpy(name, str); 5658 while (name[strlen(name) - 1] == '/') { 5659 name[strlen(name) - 1] = NULL; 5660 } 5661 5662 h = hash(name); 5663 if ((exp = (file_list_t *)calloc(sizeof (file_list_t), 5664 sizeof (char))) == NULL) { 5665 (void) fprintf(stderr, gettext( 5666 "tar: out of memory, exclude/include table(entry)\n")); 5667 exit(1); 5668 } 5669 5670 if ((exp->name = strdup(name)) == NULL) { 5671 (void) fprintf(stderr, gettext( 5672 "tar: out of memory, exclude/include table(file name)\n")); 5673 exit(1); 5674 } 5675 5676 exp->next = table[h]; 5677 table[h] = exp; 5678 } 5679 5680 5681 /* 5682 * See if a file name or any of the file's parent directories is in the 5683 * specified table, if the file name has any trailing '/'s then delete 5684 * them before searching the table 5685 */ 5686 5687 static int 5688 is_in_table(file_list_t *table[], char *str) 5689 { 5690 char name[PATH_MAX + 1]; 5691 unsigned int h; 5692 file_list_t *exp; 5693 char *ptr; 5694 5695 (void) strcpy(name, str); 5696 while (name[strlen(name) - 1] == '/') { 5697 name[strlen(name) - 1] = NULL; 5698 } 5699 5700 /* 5701 * check for the file name in the passed list 5702 */ 5703 h = hash(name); 5704 exp = table[h]; 5705 while (exp != NULL) { 5706 if (strcmp(name, exp->name) == 0) { 5707 return (1); 5708 } 5709 exp = exp->next; 5710 } 5711 5712 /* 5713 * check for any parent directories in the file list 5714 */ 5715 while ((ptr = strrchr(name, '/'))) { 5716 *ptr = NULL; 5717 h = hash(name); 5718 exp = table[h]; 5719 while (exp != NULL) { 5720 if (strcmp(name, exp->name) == 0) { 5721 return (1); 5722 } 5723 exp = exp->next; 5724 } 5725 } 5726 5727 return (0); 5728 } 5729 5730 5731 /* 5732 * Compute a hash from a string. 5733 */ 5734 5735 static unsigned int 5736 hash(char *str) 5737 { 5738 char *cp; 5739 unsigned int h; 5740 5741 h = 0; 5742 for (cp = str; *cp; cp++) { 5743 h += *cp; 5744 } 5745 return (h % TABLE_SIZE); 5746 } 5747 5748 static void * 5749 getmem(size_t size) 5750 { 5751 void *p = calloc((unsigned)size, sizeof (char)); 5752 5753 if (p == NULL && freemem) { 5754 (void) fprintf(stderr, gettext( 5755 "tar: out of memory, link and directory modtime " 5756 "info lost\n")); 5757 freemem = 0; 5758 if (errflag) 5759 done(1); 5760 else 5761 Errflg = 1; 5762 } 5763 return (p); 5764 } 5765 5766 /* 5767 * vperror() --variable argument perror. 5768 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 5769 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 5770 * with the value of whatever "errno" is set to. If exit_status is not 5771 * zero, then tar exits with that error status. If errflag and exit_status 5772 * are both zero, the routine returns to where it was called and sets Errflg 5773 * to errno. 5774 */ 5775 5776 static void 5777 vperror(int exit_status, char *fmt, ...) 5778 { 5779 va_list ap; 5780 5781 va_start(ap, fmt); 5782 (void) fputs("tar: ", stderr); 5783 (void) vfprintf(stderr, fmt, ap); 5784 (void) fprintf(stderr, ": %s\n", strerror(errno)); 5785 va_end(ap); 5786 if (exit_status) 5787 done(exit_status); 5788 else 5789 if (errflag) 5790 done(errno); 5791 else 5792 Errflg = errno; 5793 } 5794 5795 5796 static void 5797 fatal(char *format, ...) 5798 { 5799 va_list ap; 5800 5801 va_start(ap, format); 5802 (void) fprintf(stderr, "tar: "); 5803 (void) vfprintf(stderr, format, ap); 5804 (void) fprintf(stderr, "\n"); 5805 va_end(ap); 5806 done(1); 5807 } 5808 5809 5810 /* 5811 * Check to make sure that argument is a char * ptr. 5812 * Actually, we just check to see that it is non-null. 5813 * If it is null, print out the message and call usage(), bailing out. 5814 */ 5815 5816 static void 5817 assert_string(char *s, char *msg) 5818 { 5819 if (s == NULL) { 5820 (void) fprintf(stderr, msg); 5821 usage(); 5822 } 5823 } 5824 5825 5826 static void 5827 mterr(char *operation, int i, int exitcode) 5828 { 5829 (void) fprintf(stderr, gettext( 5830 "tar: %s error: "), operation); 5831 if (i < 0) 5832 perror(""); 5833 else 5834 (void) fprintf(stderr, gettext("unexpected EOF\n")); 5835 done(exitcode); 5836 } 5837 5838 static int 5839 wantit(char *argv[], char **namep, char **dirp, char **component, 5840 attr_data_t **attrinfo) 5841 { 5842 char **cp; 5843 int gotit; /* true if we've found a match */ 5844 int ret; 5845 5846 top: 5847 if (xhdr_flgs & _X_XHDR) { 5848 xhdr_flgs = 0; 5849 } 5850 getdir(); 5851 if (Xhdrflag > 0) { 5852 ret = get_xdata(); 5853 if (ret != 0) { /* Xhdr items and regular header */ 5854 setbytes_to_skip(&stbuf, ret); 5855 passtape(); 5856 return (0); /* Error--don't want to extract */ 5857 } 5858 } 5859 5860 /* 5861 * If typeflag is not 'A' and xhdr_flgs is set, then processing 5862 * of ancillary file is either over or ancillary file 5863 * processing is not required, load info from Xtarhdr and set 5864 * _X_XHDR bit in xhdr_flgs. 5865 */ 5866 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 5867 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 5868 xhdr_flgs |= _X_XHDR; 5869 } 5870 5871 #if defined(O_XATTR) 5872 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 5873 /* 5874 * Always needs to read the extended header. If atflag, saflag, 5875 * or tflag isn't set, then we'll have the correct info for 5876 * passtape() later. 5877 */ 5878 (void) read_xattr_hdr(attrinfo); 5879 goto top; 5880 } 5881 /* 5882 * Now that we've read the extended header, call passtape() 5883 * if we don't want to restore attributes or system attributes. 5884 * Don't restore the attribute if we are extracting 5885 * a file from an archive (as opposed to doing a table of 5886 * contents) and any of the following are true: 5887 * 1. neither -@ or -/ was specified. 5888 * 2. -@ was specified, -/ wasn't specified, and we're 5889 * processing a hidden attribute directory of an attribute 5890 * or we're processing a read-write system attribute file. 5891 * 3. -@ wasn't specified, -/ was specified, and the file 5892 * we're processing is not a read-write system attribute file, 5893 * or we're processing the hidden attribute directory of an 5894 * attribute. 5895 * 5896 * We always process the attributes if we're just generating 5897 * generating a table of contents, or if both -@ and -/ were 5898 * specified. 5899 */ 5900 if (xattrp != NULL) { 5901 attr_data_t *ainfo = *attrinfo; 5902 5903 if (!tflag && 5904 ((!atflag && !saflag) || 5905 (atflag && !saflag && ((ainfo->attr_parent != NULL) || 5906 ainfo->attr_rw_sysattr)) || 5907 (!atflag && saflag && ((ainfo->attr_parent != NULL) || 5908 !ainfo->attr_rw_sysattr)))) { 5909 passtape(); 5910 return (0); 5911 } 5912 } 5913 #endif 5914 5915 /* sets *namep to point at the proper name */ 5916 if (check_prefix(namep, dirp, component) != 0) { 5917 passtape(); 5918 return (0); 5919 } 5920 5921 if (endtape()) { 5922 if (Bflag) { 5923 /* 5924 * Logically at EOT - consume any extra blocks 5925 * so that write to our stdin won't fail and 5926 * emit an error message; otherwise something 5927 * like "dd if=foo.tar | (cd bar; tar xvf -)" 5928 * will produce a bogus error message from "dd". 5929 */ 5930 5931 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 5932 /* empty body */ 5933 } 5934 } 5935 return (-1); 5936 } 5937 5938 gotit = 0; 5939 5940 if ((Iflag && is_in_table(include_tbl, *namep)) || 5941 (! Iflag && *argv == NULL)) { 5942 gotit = 1; 5943 } else { 5944 for (cp = argv; *cp; cp++) { 5945 if (is_prefix(*cp, *namep)) { 5946 gotit = 1; 5947 break; 5948 } 5949 } 5950 } 5951 5952 if (! gotit) { 5953 passtape(); 5954 return (0); 5955 } 5956 5957 if (Xflag && is_in_table(exclude_tbl, *namep)) { 5958 if (vflag) { 5959 (void) fprintf(stderr, gettext("%s excluded\n"), 5960 *namep); 5961 } 5962 passtape(); 5963 return (0); 5964 } 5965 5966 return (1); 5967 } 5968 5969 5970 static void 5971 setbytes_to_skip(struct stat *st, int err) 5972 { 5973 /* 5974 * In a scenario where a typeflag 'X' was followed by 5975 * a typeflag 'A' and typeflag 'O', then the number of 5976 * bytes to skip should be the size of ancillary file, 5977 * plus the dblock for regular file, and the size 5978 * from Xtarhdr. However, if the typeflag was just 'X' 5979 * followed by typeflag 'O', then the number of bytes 5980 * to skip should be the size from Xtarhdr. 5981 */ 5982 if ((err != 0) && (dblock.dbuf.typeflag == 'A') && 5983 (xhdr_flgs & _X_SIZE)) { 5984 st->st_size += TBLOCK + Xtarhdr.x_filesz; 5985 xhdr_flgs |= _X_XHDR; 5986 } else if ((dblock.dbuf.typeflag != 'A') && 5987 (xhdr_flgs & _X_SIZE)) { 5988 st->st_size += Xtarhdr.x_filesz; 5989 xhdr_flgs |= _X_XHDR; 5990 } 5991 } 5992 5993 static int 5994 fill_in_attr_info(char *attr, char *longname, char *attrparent, int atparentfd, 5995 int rw_sysattr, attr_data_t **attrinfo) 5996 { 5997 size_t pathlen; 5998 char *tpath; 5999 char *tparent; 6000 6001 /* parent info */ 6002 if (attrparent != NULL) { 6003 if ((tparent = strdup(attrparent)) == NULL) { 6004 vperror(0, gettext( 6005 "unable to allocate memory for attribute parent " 6006 "name for %sattribute %s/%s of %s"), 6007 rw_sysattr ? gettext("system ") : "", 6008 attrparent, attr, longname); 6009 return (1); 6010 } 6011 } else { 6012 tparent = NULL; 6013 } 6014 6015 /* path info */ 6016 pathlen = strlen(attr) + 1; 6017 if (attrparent != NULL) { 6018 pathlen += strlen(attrparent) + 1; /* add 1 for '/' */ 6019 } 6020 if ((tpath = calloc(1, pathlen)) == NULL) { 6021 vperror(0, gettext( 6022 "unable to allocate memory for full " 6023 "attribute path name for %sattribute %s%s%s of %s"), 6024 rw_sysattr ? gettext("system ") : "", 6025 (attrparent == NULL) ? "" : attrparent, 6026 (attrparent == NULL) ? "" : "/", 6027 attr, longname); 6028 if (tparent != NULL) { 6029 free(tparent); 6030 } 6031 return (1); 6032 } 6033 (void) snprintf(tpath, pathlen, "%s%s%s", 6034 (attrparent == NULL) ? "" : attrparent, 6035 (attrparent == NULL) ? "" : "/", 6036 attr); 6037 6038 /* fill in the attribute info */ 6039 if (*attrinfo == NULL) { 6040 if ((*attrinfo = malloc(sizeof (attr_data_t))) == NULL) { 6041 vperror(0, gettext( 6042 "unable to allocate memory for attribute " 6043 "information for %sattribute %s%s%s of %s"), 6044 rw_sysattr ? gettext("system ") : "", 6045 (attrparent == NULL) ? "" : attrparent, 6046 (attrparent == NULL) ? "" : gettext("/"), 6047 attr, longname); 6048 if (tparent != NULL) { 6049 free(tparent); 6050 } 6051 free(tpath); 6052 return (1); 6053 } 6054 } else { 6055 if ((*attrinfo)->attr_parent != NULL) { 6056 free((*attrinfo)->attr_parent); 6057 } 6058 if ((*attrinfo)->attr_path != NULL) { 6059 free((*attrinfo)->attr_path); 6060 } 6061 /* 6062 * The parent file descriptor is passed in, so don't 6063 * close it here as it should be closed by the function 6064 * that opened it. 6065 */ 6066 } 6067 (*attrinfo)->attr_parent = tparent; 6068 (*attrinfo)->attr_path = tpath; 6069 (*attrinfo)->attr_rw_sysattr = rw_sysattr; 6070 (*attrinfo)->attr_parentfd = atparentfd; 6071 6072 return (0); 6073 } 6074 6075 /* 6076 * Test if name has a '..' sequence in it. 6077 * 6078 * Return 1 if found, 0 otherwise. 6079 */ 6080 6081 static int 6082 has_dot_dot(char *name) 6083 { 6084 char *s; 6085 size_t name_len = strlen(name); 6086 6087 for (s = name; s < (name + name_len - 2); s++) { 6088 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6089 return (1); 6090 6091 while (! (*s == '/')) { 6092 if (! *s++) 6093 return (0); 6094 } 6095 } 6096 6097 return (0); 6098 } 6099 6100 /* 6101 * Test if name is an absolute path name. 6102 * 6103 * Return 1 if true, 0 otherwise. 6104 */ 6105 6106 static int 6107 is_absolute(char *name) 6108 { 6109 return (name[0] == '/'); 6110 } 6111 6112 /* 6113 * Adjust the pathname to make it a relative one. Strip off any leading 6114 * '/' characters and if the pathname contains any '..' sequences, strip 6115 * upto and including the last occurance of '../' (or '..' if found at 6116 * the very end of the pathname). 6117 * 6118 * Return the relative pathname. stripped_prefix will also return the 6119 * portion of name that was stripped off and should be freed by the 6120 * calling routine when no longer needed. 6121 */ 6122 6123 static char * 6124 make_relative_name(char *name, char **stripped_prefix) 6125 { 6126 char *s; 6127 size_t prefix_len = 0; 6128 size_t name_len = strlen(name); 6129 6130 for (s = name + prefix_len; s < (name + name_len - 2); ) { 6131 if (s[0] == '.' && s[1] == '.' && ((s[2] == '/') || !s[2])) 6132 prefix_len = s + 2 - name; 6133 6134 do { 6135 char c = *s++; 6136 6137 if (c == '/') 6138 break; 6139 } while (*s); 6140 } 6141 6142 for (s = name + prefix_len; *s == '/'; s++) 6143 continue; 6144 prefix_len = s - name; 6145 6146 /* Create the portion of the name that was stripped off. */ 6147 s = malloc(prefix_len + 1); 6148 memcpy(s, name, prefix_len); 6149 s[prefix_len] = 0; 6150 *stripped_prefix = s; 6151 s = &name[prefix_len]; 6152 6153 return (s); 6154 } 6155 6156 /* 6157 * Return through *namep a pointer to the proper fullname (i.e "<name> | 6158 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 6159 * 6160 * Returns 0 if successful, otherwise returns 1. 6161 */ 6162 6163 static int 6164 check_prefix(char **namep, char **dirp, char **compp) 6165 { 6166 static char fullname[PATH_MAX + 1]; 6167 static char dir[PATH_MAX + 1]; 6168 static char component[PATH_MAX + 1]; 6169 static char savename[PATH_MAX + 1]; 6170 char *s; 6171 6172 (void) memset(dir, 0, sizeof (dir)); 6173 (void) memset(component, 0, sizeof (component)); 6174 6175 if (xhdr_flgs & _X_PATH) { 6176 (void) strcpy(fullname, Xtarhdr.x_path); 6177 } else { 6178 if (dblock.dbuf.prefix[0] != '\0') 6179 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 6180 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 6181 else 6182 (void) sprintf(fullname, "%.*s", NAMSIZ, 6183 dblock.dbuf.name); 6184 } 6185 6186 /* 6187 * If we are printing a table of contents or extracting an archive, 6188 * make absolute pathnames relative and prohibit the unpacking of 6189 * files contain ".." in their name (unless the user has supplied 6190 * the -P option). 6191 */ 6192 if ((tflag || xflag) && !Pflag) { 6193 if (is_absolute(fullname) || has_dot_dot(fullname)) { 6194 char *stripped_prefix; 6195 size_t prefix_len = 0; 6196 6197 (void) strcpy(savename, fullname); 6198 strcpy(fullname, 6199 make_relative_name(savename, &stripped_prefix)); 6200 (void) fprintf(stderr, 6201 gettext("tar: Removing leading '%s' from '%s'\n"), 6202 stripped_prefix, savename); 6203 free(stripped_prefix); 6204 } 6205 } 6206 6207 /* 6208 * Set dir and component names 6209 */ 6210 6211 get_parent(fullname, dir); 6212 6213 #if defined(O_XATTR) 6214 if (xattrp == NULL) { 6215 #endif 6216 /* 6217 * Save of real name since were going to chop off the 6218 * trailing slashes. 6219 */ 6220 (void) strcpy(savename, fullname); 6221 /* 6222 * first strip of trailing slashes. 6223 */ 6224 chop_endslashes(savename); 6225 s = get_component(savename); 6226 (void) strcpy(component, s); 6227 6228 #if defined(O_XATTR) 6229 } else { 6230 (void) strcpy(fullname, xattrp->h_names); 6231 (void) strcpy(dir, fullname); 6232 (void) strcpy(component, basename(xattrp->h_names + 6233 strlen(xattrp->h_names) + 1)); 6234 } 6235 #endif 6236 *namep = fullname; 6237 *dirp = dir; 6238 *compp = component; 6239 6240 return (0); 6241 } 6242 6243 /* 6244 * Return true if the object indicated by the file descriptor and type 6245 * is a tape device, false otherwise 6246 */ 6247 6248 static int 6249 istape(int fd, int type) 6250 { 6251 int result = 0; 6252 6253 if (S_ISCHR(type)) { 6254 struct mtget mtg; 6255 6256 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 6257 result = 1; 6258 } 6259 } 6260 6261 return (result); 6262 } 6263 6264 #include <utmpx.h> 6265 6266 struct utmpx utmpx; 6267 6268 #define NMAX (sizeof (utmpx.ut_name)) 6269 6270 typedef struct cachenode { /* this struct must be zeroed before using */ 6271 struct cachenode *next; /* next in hash chain */ 6272 int val; /* the uid or gid of this entry */ 6273 int namehash; /* name's hash signature */ 6274 char name[NMAX+1]; /* the string that val maps to */ 6275 } cachenode_t; 6276 6277 #define HASHSIZE 256 6278 6279 static cachenode_t *names[HASHSIZE]; 6280 static cachenode_t *groups[HASHSIZE]; 6281 static cachenode_t *uids[HASHSIZE]; 6282 static cachenode_t *gids[HASHSIZE]; 6283 6284 static int 6285 hash_byname(char *name) 6286 { 6287 int i, c, h = 0; 6288 6289 for (i = 0; i < NMAX; i++) { 6290 c = name[i]; 6291 if (c == '\0') 6292 break; 6293 h = (h << 4) + h + c; 6294 } 6295 return (h); 6296 } 6297 6298 static cachenode_t * 6299 hash_lookup_byval(cachenode_t *table[], int val) 6300 { 6301 int h = val; 6302 cachenode_t *c; 6303 6304 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6305 if (c->val == val) 6306 return (c); 6307 } 6308 return (NULL); 6309 } 6310 6311 static cachenode_t * 6312 hash_lookup_byname(cachenode_t *table[], char *name) 6313 { 6314 int h = hash_byname(name); 6315 cachenode_t *c; 6316 6317 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 6318 if (c->namehash == h && strcmp(c->name, name) == 0) 6319 return (c); 6320 } 6321 return (NULL); 6322 } 6323 6324 static cachenode_t * 6325 hash_insert(cachenode_t *table[], char *name, int value) 6326 { 6327 cachenode_t *c; 6328 int signature; 6329 6330 c = calloc(1, sizeof (cachenode_t)); 6331 if (c == NULL) { 6332 perror("malloc"); 6333 exit(1); 6334 } 6335 if (name != NULL) { 6336 (void) strncpy(c->name, name, NMAX); 6337 c->namehash = hash_byname(name); 6338 } 6339 c->val = value; 6340 if (table == uids || table == gids) 6341 signature = c->val; 6342 else 6343 signature = c->namehash; 6344 c->next = table[signature & (HASHSIZE - 1)]; 6345 table[signature & (HASHSIZE - 1)] = c; 6346 return (c); 6347 } 6348 6349 static char * 6350 getname(uid_t uid) 6351 { 6352 cachenode_t *c; 6353 6354 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 6355 struct passwd *pwent = getpwuid(uid); 6356 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 6357 } 6358 return (c->name); 6359 } 6360 6361 static char * 6362 getgroup(gid_t gid) 6363 { 6364 cachenode_t *c; 6365 6366 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 6367 struct group *grent = getgrgid(gid); 6368 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 6369 } 6370 return (c->name); 6371 } 6372 6373 static uid_t 6374 getuidbyname(char *name) 6375 { 6376 cachenode_t *c; 6377 6378 if ((c = hash_lookup_byname(names, name)) == NULL) { 6379 struct passwd *pwent = getpwnam(name); 6380 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 6381 } 6382 return ((uid_t)c->val); 6383 } 6384 6385 static gid_t 6386 getgidbyname(char *group) 6387 { 6388 cachenode_t *c; 6389 6390 if ((c = hash_lookup_byname(groups, group)) == NULL) { 6391 struct group *grent = getgrnam(group); 6392 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 6393 } 6394 return ((gid_t)c->val); 6395 } 6396 6397 /* 6398 * Build the header. 6399 * Determine whether or not an extended header is also needed. If needed, 6400 * create and write the extended header and its data. 6401 * Writing of the extended header assumes that "tomodes" has been called and 6402 * the relevant information has been placed in the header block. 6403 */ 6404 6405 static int 6406 build_dblock( 6407 const char *name, 6408 const char *linkname, 6409 const char typeflag, 6410 const int filetype, 6411 const struct stat *sp, 6412 const dev_t device, 6413 const char *prefix) 6414 { 6415 int nblks; 6416 major_t dev; 6417 const char *filename; 6418 const char *lastslash; 6419 6420 if (filetype == XATTR_FILE) 6421 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 6422 else 6423 dblock.dbuf.typeflag = typeflag; 6424 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 6425 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 6426 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 6427 6428 if (xhdr_flgs & _X_PATH) 6429 filename = Xtarhdr.x_path; 6430 else 6431 filename = name; 6432 6433 if ((dev = major(device)) > OCTAL7CHAR) { 6434 if (Eflag) { 6435 xhdr_flgs |= _X_DEVMAJOR; 6436 Xtarhdr.x_devmajor = dev; 6437 } else { 6438 (void) fprintf(stderr, gettext( 6439 "Device major too large for %s. Use -E flag."), 6440 filename); 6441 if (errflag) 6442 done(1); 6443 else 6444 Errflg = 1; 6445 } 6446 dev = 0; 6447 } 6448 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 6449 if ((dev = minor(device)) > OCTAL7CHAR) { 6450 if (Eflag) { 6451 xhdr_flgs |= _X_DEVMINOR; 6452 Xtarhdr.x_devminor = dev; 6453 } else { 6454 (void) fprintf(stderr, gettext( 6455 "Device minor too large for %s. Use -E flag."), 6456 filename); 6457 if (errflag) 6458 done(1); 6459 else 6460 Errflg = 1; 6461 } 6462 dev = 0; 6463 } 6464 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 6465 6466 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 6467 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 6468 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 6469 (void) sprintf(dblock.dbuf.version, "00"); 6470 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 6471 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 6472 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 6473 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 6474 6475 if (Eflag) { 6476 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 6477 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 6478 lastslash = strrchr(name, '/'); 6479 if (lastslash == NULL) 6480 lastslash = name; 6481 else 6482 lastslash++; 6483 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 6484 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 6485 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 6486 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 6487 xhdr_count++; 6488 xrec_offset = 0; 6489 gen_date("mtime", sp->st_mtim); 6490 xhdr_buf.dbuf.typeflag = 'X'; 6491 if (gen_utf8_names(filename) != 0) 6492 return (1); 6493 6494 #ifdef XHDR_DEBUG 6495 Xtarhdr.x_uname = dblock.dbuf.uname; 6496 Xtarhdr.x_gname = dblock.dbuf.gname; 6497 xhdr_flgs |= (_X_UNAME | _X_GNAME); 6498 #endif 6499 if (xhdr_flgs) { 6500 if (xhdr_flgs & _X_DEVMAJOR) 6501 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 6502 if (xhdr_flgs & _X_DEVMINOR) 6503 gen_num("SUN.devminor", Xtarhdr.x_devminor); 6504 if (xhdr_flgs & _X_GID) 6505 gen_num("gid", Xtarhdr.x_gid); 6506 if (xhdr_flgs & _X_UID) 6507 gen_num("uid", Xtarhdr.x_uid); 6508 if (xhdr_flgs & _X_SIZE) 6509 gen_num("size", Xtarhdr.x_filesz); 6510 if (xhdr_flgs & _X_PATH) 6511 gen_string("path", Xtarhdr.x_path); 6512 if (xhdr_flgs & _X_LINKPATH) 6513 gen_string("linkpath", Xtarhdr.x_linkpath); 6514 if (xhdr_flgs & _X_GNAME) 6515 gen_string("gname", Xtarhdr.x_gname); 6516 if (xhdr_flgs & _X_UNAME) 6517 gen_string("uname", Xtarhdr.x_uname); 6518 } 6519 (void) sprintf(xhdr_buf.dbuf.size, 6520 "%011" FMT_off_t_o, xrec_offset); 6521 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 6522 checksum(&xhdr_buf)); 6523 (void) writetbuf((char *)&xhdr_buf, 1); 6524 nblks = TBLOCKS(xrec_offset); 6525 (void) writetbuf(xrec_ptr, nblks); 6526 } 6527 return (0); 6528 } 6529 6530 6531 /* 6532 * makeDir - ensure that a directory with the pathname denoted by name 6533 * exists, and return 1 on success, and 0 on failure (e.g., 6534 * read-only file system, exists but not-a-directory). 6535 */ 6536 6537 static int 6538 makeDir(char *name) 6539 { 6540 struct stat buf; 6541 6542 if (access(name, 0) < 0) { /* name doesn't exist */ 6543 if (mkdir(name, 0777) < 0) { 6544 vperror(0, "%s", name); 6545 return (0); 6546 } 6547 } else { /* name exists */ 6548 if (stat(name, &buf) < 0) { 6549 vperror(0, "%s", name); 6550 return (0); 6551 } 6552 6553 return ((buf.st_mode & S_IFMT) == S_IFDIR); 6554 } 6555 6556 return (1); 6557 } 6558 6559 6560 /* 6561 * Save this directory and its mtime on the stack, popping and setting 6562 * the mtimes of any stacked dirs which aren't parents of this one. 6563 * A null name causes the entire stack to be unwound and set. 6564 * 6565 * Since all the elements of the directory "stack" share a common 6566 * prefix, we can make do with one string. We keep only the current 6567 * directory path, with an associated array of mtime's. A negative 6568 * mtime means no mtime. 6569 * 6570 * This stack algorithm is not guaranteed to work for tapes created 6571 * with the 'r' function letter, but the vast majority of tapes with 6572 * directories are not. This avoids saving every directory record on 6573 * the tape and setting all the times at the end. 6574 * 6575 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 6576 * environment) 6577 */ 6578 6579 static void 6580 doDirTimes(char *name, timestruc_t modTime) 6581 { 6582 static char dirstack[PATH_MAX+2]; 6583 /* Add spaces for the last slash and last NULL */ 6584 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 6585 char *p = dirstack; 6586 char *q = name; 6587 char *savp; 6588 6589 if (q) { 6590 /* 6591 * Find common prefix 6592 */ 6593 6594 while (*p == *q && *p) { 6595 p++; q++; 6596 } 6597 } 6598 6599 savp = p; 6600 while (*p) { 6601 /* 6602 * Not a child: unwind the stack, setting the times. 6603 * The order we do this doesn't matter, so we go "forward." 6604 */ 6605 6606 if (*p == '/') 6607 if (modtimes[p - dirstack].tv_sec >= 0) { 6608 *p = '\0'; /* zap the slash */ 6609 setPathTimes(AT_FDCWD, dirstack, 6610 modtimes[p - dirstack]); 6611 *p = '/'; 6612 } 6613 ++p; 6614 } 6615 6616 p = savp; 6617 6618 /* 6619 * Push this one on the "stack" 6620 */ 6621 6622 if (q) { 6623 6624 /* 6625 * Since the name parameter points the dir pathname 6626 * which is limited only to contain PATH_MAX chars 6627 * at maximum, we can ignore the overflow case of p. 6628 */ 6629 6630 while ((*p = *q++)) { /* append the rest of the new dir */ 6631 modtimes[p - dirstack].tv_sec = -1; 6632 p++; 6633 } 6634 6635 /* 6636 * If the tar file had used 'P' or 'E' function modifier, 6637 * append the last slash. 6638 */ 6639 if (*(p - 1) != '/') { 6640 *p++ = '/'; 6641 *p = '\0'; 6642 } 6643 /* overwrite the last one */ 6644 modtimes[p - dirstack - 1] = modTime; 6645 } 6646 } 6647 6648 6649 /* 6650 * setPathTimes - set the modification time for given path. Return 1 if 6651 * successful and 0 if not successful. 6652 */ 6653 6654 static void 6655 setPathTimes(int dirfd, char *path, timestruc_t modTime) 6656 6657 { 6658 struct timeval timebuf[2]; 6659 6660 /* 6661 * futimesat takes an array of two timeval structs. 6662 * The first entry contains access time. 6663 * The second entry contains modification time. 6664 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 6665 * microseconds. 6666 */ 6667 timebuf[0].tv_sec = time((time_t *)0); 6668 timebuf[0].tv_usec = 0; 6669 timebuf[1].tv_sec = modTime.tv_sec; 6670 6671 /* Extended header: use microseconds */ 6672 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 6673 6674 if (futimesat(dirfd, path, timebuf) < 0) 6675 vperror(0, gettext("can't set time on %s"), path); 6676 } 6677 6678 6679 /* 6680 * If hflag is set then delete the symbolic link's target. 6681 * If !hflag then delete the target. 6682 */ 6683 6684 static void 6685 delete_target(int fd, char *comp, char *namep) 6686 { 6687 struct stat xtractbuf; 6688 char buf[PATH_MAX + 1]; 6689 int n; 6690 6691 6692 if (unlinkat(fd, comp, AT_REMOVEDIR) < 0) { 6693 if (errno == ENOTDIR && !hflag) { 6694 (void) unlinkat(fd, comp, 0); 6695 } else if (errno == ENOTDIR && hflag) { 6696 if (!lstat(namep, &xtractbuf)) { 6697 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 6698 (void) unlinkat(fd, comp, 0); 6699 } else if ((n = readlink(namep, buf, 6700 PATH_MAX)) != -1) { 6701 buf[n] = (char)NULL; 6702 (void) unlinkat(fd, buf, 6703 AT_REMOVEDIR); 6704 if (errno == ENOTDIR) 6705 (void) unlinkat(fd, buf, 0); 6706 } else { 6707 (void) unlinkat(fd, comp, 0); 6708 } 6709 } else { 6710 (void) unlinkat(fd, comp, 0); 6711 } 6712 } 6713 } 6714 } 6715 6716 6717 /* 6718 * ACL changes: 6719 * putfile(): 6720 * Get acl info after stat. Write out ancillary file 6721 * before the normal file, i.e. directory, regular, FIFO, 6722 * link, special. If acl count is less than 4, no need to 6723 * create ancillary file. (i.e. standard permission is in 6724 * use. 6725 * doxtract(): 6726 * Process ancillary file. Read it in and set acl info. 6727 * watch out for 'o' function modifier. 6728 * 't' function letter to display table 6729 */ 6730 6731 /* 6732 * New functions for ACLs and other security attributes 6733 */ 6734 6735 /* 6736 * The function appends the new security attribute info to the end of 6737 * existing secinfo. 6738 */ 6739 int 6740 append_secattr( 6741 char **secinfo, /* existing security info */ 6742 int *secinfo_len, /* length of existing security info */ 6743 int size, /* new attribute size: unit depends on type */ 6744 char *attrtext, /* new attribute text */ 6745 char attr_type) /* new attribute type */ 6746 { 6747 char *new_secinfo; 6748 int newattrsize; 6749 int oldsize; 6750 struct sec_attr *attr; 6751 6752 /* no need to add */ 6753 if (attr_type != DIR_TYPE) { 6754 if (attrtext == NULL) 6755 return (0); 6756 } 6757 6758 switch (attr_type) { 6759 case UFSD_ACL: 6760 case ACE_ACL: 6761 if (attrtext == NULL) { 6762 (void) fprintf(stderr, gettext("acltotext failed\n")); 6763 return (-1); 6764 } 6765 /* header: type + size = 8 */ 6766 newattrsize = 8 + (int)strlen(attrtext) + 1; 6767 attr = (struct sec_attr *)malloc(newattrsize); 6768 if (attr == NULL) { 6769 (void) fprintf(stderr, 6770 gettext("can't allocate memory\n")); 6771 return (-1); 6772 } 6773 attr->attr_type = attr_type; 6774 (void) sprintf(attr->attr_len, 6775 "%06o", size); /* acl entry count */ 6776 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6777 free(attrtext); 6778 break; 6779 6780 /* Trusted Extensions */ 6781 case DIR_TYPE: 6782 case LBL_TYPE: 6783 newattrsize = sizeof (struct sec_attr) + strlen(attrtext); 6784 attr = (struct sec_attr *)malloc(newattrsize); 6785 if (attr == NULL) { 6786 (void) fprintf(stderr, 6787 gettext("can't allocate memory\n")); 6788 return (-1); 6789 } 6790 attr->attr_type = attr_type; 6791 (void) sprintf(attr->attr_len, 6792 "%06d", size); /* len of attr data */ 6793 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6794 break; 6795 6796 default: 6797 (void) fprintf(stderr, 6798 gettext("unrecognized attribute type\n")); 6799 return (-1); 6800 } 6801 6802 /* old security info + new attr header(8) + new attr */ 6803 oldsize = *secinfo_len; 6804 *secinfo_len += newattrsize; 6805 new_secinfo = (char *)malloc(*secinfo_len); 6806 if (new_secinfo == NULL) { 6807 (void) fprintf(stderr, gettext("can't allocate memory\n")); 6808 *secinfo_len -= newattrsize; 6809 free(attr); 6810 return (-1); 6811 } 6812 6813 (void) memcpy(new_secinfo, *secinfo, oldsize); 6814 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 6815 6816 free(*secinfo); 6817 free(attr); 6818 *secinfo = new_secinfo; 6819 return (0); 6820 } 6821 6822 /* 6823 * write_ancillary(): write out an ancillary file. 6824 * The file has the same header as normal file except the type and size 6825 * fields. The type is 'A' and size is the sum of all attributes 6826 * in bytes. 6827 * The body contains a list of attribute type, size and info. Currently, 6828 * there is only ACL info. This file is put before the normal file. 6829 */ 6830 void 6831 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 6832 { 6833 long blocks; 6834 int savflag; 6835 int savsize; 6836 6837 /* Just tranditional permissions or no security attribute info */ 6838 if (len == 0 || secinfo == NULL) 6839 return; 6840 6841 /* save flag and size */ 6842 savflag = (dblockp->dbuf).typeflag; 6843 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 6844 6845 /* special flag for ancillary file */ 6846 if (hdrtype == _XATTR_HDRTYPE) 6847 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 6848 else 6849 dblockp->dbuf.typeflag = 'A'; 6850 6851 /* for pre-2.5 versions of tar, need to make sure */ 6852 /* the ACL file is readable */ 6853 (void) sprintf(dblock.dbuf.mode, "%07lo", 6854 (stbuf.st_mode & POSIXMODES) | 0000200); 6855 (void) sprintf(dblockp->dbuf.size, "%011o", len); 6856 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 6857 6858 /* write out the header */ 6859 (void) writetbuf((char *)dblockp, 1); 6860 6861 /* write out security info */ 6862 blocks = TBLOCKS(len); 6863 (void) writetbuf((char *)secinfo, (int)blocks); 6864 6865 /* restore mode, flag and size */ 6866 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 6867 dblockp->dbuf.typeflag = savflag; 6868 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 6869 } 6870 6871 /* 6872 * Read the data record for extended headers and then the regular header. 6873 * The data are read into the buffer and then null-terminated. Entries 6874 * for typeflag 'X' extended headers are of the format: 6875 * "%d %s=%s\n" 6876 * 6877 * When an extended header record is found, the extended header must 6878 * be processed and its values used to override the values in the 6879 * normal header. The way this is done is to process the extended 6880 * header data record and set the data values, then call getdir 6881 * to process the regular header, then then to reconcile the two 6882 * sets of data. 6883 */ 6884 6885 static int 6886 get_xdata(void) 6887 { 6888 struct keylist_pair { 6889 int keynum; 6890 char *keylist; 6891 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 6892 _X_DEVMINOR, "SUN.devminor", 6893 _X_GID, "gid", 6894 _X_GNAME, "gname", 6895 _X_LINKPATH, "linkpath", 6896 _X_PATH, "path", 6897 _X_SIZE, "size", 6898 _X_UID, "uid", 6899 _X_UNAME, "uname", 6900 _X_MTIME, "mtime", 6901 _X_LAST, "NULL" }; 6902 char *lineloc; 6903 int length, i; 6904 char *keyword, *value; 6905 blkcnt_t nblocks; 6906 int bufneeded; 6907 int errors; 6908 6909 (void) memset(&Xtarhdr, 0, sizeof (Xtarhdr)); 6910 xhdr_count++; 6911 errors = 0; 6912 6913 nblocks = TBLOCKS(stbuf.st_size); 6914 bufneeded = nblocks * TBLOCK; 6915 if (bufneeded >= xrec_size) { 6916 free(xrec_ptr); 6917 xrec_size = bufneeded + 1; 6918 if ((xrec_ptr = malloc(xrec_size)) == NULL) 6919 fatal(gettext("cannot allocate buffer")); 6920 } 6921 6922 lineloc = xrec_ptr; 6923 6924 while (nblocks-- > 0) { 6925 readtape(lineloc); 6926 lineloc += TBLOCK; 6927 } 6928 lineloc = xrec_ptr; 6929 xrec_ptr[stbuf.st_size] = '\0'; 6930 while (lineloc < xrec_ptr + stbuf.st_size) { 6931 if (dblock.dbuf.typeflag == 'L') { 6932 length = xrec_size; 6933 keyword = "path"; 6934 value = lineloc; 6935 } else { 6936 length = atoi(lineloc); 6937 *(lineloc + length - 1) = '\0'; 6938 keyword = strchr(lineloc, ' ') + 1; 6939 value = strchr(keyword, '=') + 1; 6940 *(value - 1) = '\0'; 6941 } 6942 i = 0; 6943 lineloc += length; 6944 while (keylist_pair[i].keynum != (int)_X_LAST) { 6945 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 6946 break; 6947 i++; 6948 } 6949 errno = 0; 6950 switch (keylist_pair[i].keynum) { 6951 case _X_DEVMAJOR: 6952 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 6953 if (errno) { 6954 (void) fprintf(stderr, gettext( 6955 "tar: Extended header major value error " 6956 "for file # %llu.\n"), xhdr_count); 6957 errors++; 6958 } else 6959 xhdr_flgs |= _X_DEVMAJOR; 6960 break; 6961 case _X_DEVMINOR: 6962 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 6963 if (errno) { 6964 (void) fprintf(stderr, gettext( 6965 "tar: Extended header minor value error " 6966 "for file # %llu.\n"), xhdr_count); 6967 errors++; 6968 } else 6969 xhdr_flgs |= _X_DEVMINOR; 6970 break; 6971 case _X_GID: 6972 xhdr_flgs |= _X_GID; 6973 Xtarhdr.x_gid = strtol(value, NULL, 0); 6974 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 6975 (void) fprintf(stderr, gettext( 6976 "tar: Extended header gid value error " 6977 "for file # %llu.\n"), xhdr_count); 6978 Xtarhdr.x_gid = GID_NOBODY; 6979 } 6980 break; 6981 case _X_GNAME: 6982 if (utf8_local("gname", &Xtarhdr.x_gname, 6983 local_gname, value, _POSIX_NAME_MAX) == 0) 6984 xhdr_flgs |= _X_GNAME; 6985 break; 6986 case _X_LINKPATH: 6987 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 6988 local_linkpath, value, PATH_MAX) == 0) 6989 xhdr_flgs |= _X_LINKPATH; 6990 else 6991 errors++; 6992 break; 6993 case _X_PATH: 6994 if (utf8_local("path", &Xtarhdr.x_path, 6995 local_path, value, PATH_MAX) == 0) 6996 xhdr_flgs |= _X_PATH; 6997 else 6998 errors++; 6999 break; 7000 case _X_SIZE: 7001 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 7002 if (errno) { 7003 (void) fprintf(stderr, gettext( 7004 "tar: Extended header invalid filesize " 7005 "for file # %llu.\n"), xhdr_count); 7006 errors++; 7007 } else 7008 xhdr_flgs |= _X_SIZE; 7009 break; 7010 case _X_UID: 7011 xhdr_flgs |= _X_UID; 7012 Xtarhdr.x_uid = strtol(value, NULL, 0); 7013 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 7014 (void) fprintf(stderr, gettext( 7015 "tar: Extended header uid value error " 7016 "for file # %llu.\n"), xhdr_count); 7017 Xtarhdr.x_uid = UID_NOBODY; 7018 } 7019 break; 7020 case _X_UNAME: 7021 if (utf8_local("uname", &Xtarhdr.x_uname, 7022 local_uname, value, _POSIX_NAME_MAX) == 0) 7023 xhdr_flgs |= _X_UNAME; 7024 break; 7025 case _X_MTIME: 7026 get_xtime(value, &(Xtarhdr.x_mtime)); 7027 if (errno) 7028 (void) fprintf(stderr, gettext( 7029 "tar: Extended header modification time " 7030 "value error for file # %llu.\n"), 7031 xhdr_count); 7032 else 7033 xhdr_flgs |= _X_MTIME; 7034 break; 7035 default: 7036 (void) fprintf(stderr, 7037 gettext("tar: unrecognized extended" 7038 " header keyword '%s'. Ignored.\n"), keyword); 7039 break; 7040 } 7041 } 7042 7043 getdir(); /* get regular header */ 7044 if (errors && errflag) 7045 done(1); 7046 else 7047 if (errors) 7048 Errflg = 1; 7049 return (errors); 7050 } 7051 7052 /* 7053 * load_info_from_xtarhdr - sets Gen and stbuf variables from 7054 * extended header 7055 * load_info_from_xtarhdr(flag, xhdrp); 7056 * u_longlong_t flag; xhdr_flgs 7057 * struct xtar_hdr *xhdrp; pointer to extended header 7058 * NOTE: called when typeflag is not 'A' and xhdr_flgs 7059 * is set. 7060 */ 7061 static void 7062 load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp) 7063 { 7064 if (flag & _X_DEVMAJOR) { 7065 Gen.g_devmajor = xhdrp->x_devmajor; 7066 } 7067 if (flag & _X_DEVMINOR) { 7068 Gen.g_devminor = xhdrp->x_devminor; 7069 } 7070 if (flag & _X_GID) { 7071 Gen.g_gid = xhdrp->x_gid; 7072 stbuf.st_gid = xhdrp->x_gid; 7073 } 7074 if (flag & _X_UID) { 7075 Gen.g_uid = xhdrp->x_uid; 7076 stbuf.st_uid = xhdrp->x_uid; 7077 } 7078 if (flag & _X_SIZE) { 7079 Gen.g_filesz = xhdrp->x_filesz; 7080 stbuf.st_size = xhdrp->x_filesz; 7081 } 7082 if (flag & _X_MTIME) { 7083 Gen.g_mtime = xhdrp->x_mtime.tv_sec; 7084 stbuf.st_mtim.tv_sec = xhdrp->x_mtime.tv_sec; 7085 stbuf.st_mtim.tv_nsec = xhdrp->x_mtime.tv_nsec; 7086 } 7087 } 7088 7089 /* 7090 * gen_num creates a string from a keyword and an usigned long long in the 7091 * format: %d %s=%s\n 7092 * This is part of the extended header data record. 7093 */ 7094 7095 void 7096 gen_num(const char *keyword, const u_longlong_t number) 7097 { 7098 char save_val[ULONGLONG_MAX_DIGITS + 1]; 7099 int len; 7100 char *curr_ptr; 7101 7102 (void) sprintf(save_val, "%llu", number); 7103 /* 7104 * len = length of entire line, including itself. len will be 7105 * two digits. So, add the string lengths plus the length of len, 7106 * plus a blank, an equal sign, and a newline. 7107 */ 7108 len = strlen(save_val) + strlen(keyword) + 5; 7109 if (xrec_offset + len > xrec_size) { 7110 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7111 fatal(gettext( 7112 "cannot allocate extended header buffer")); 7113 xrec_ptr = curr_ptr; 7114 xrec_size *= 2; 7115 } 7116 (void) sprintf(&xrec_ptr[xrec_offset], 7117 "%d %s=%s\n", len, keyword, save_val); 7118 xrec_offset += len; 7119 } 7120 7121 /* 7122 * gen_date creates a string from a keyword and a timestruc_t in the 7123 * format: %d %s=%s\n 7124 * This is part of the extended header data record. 7125 * Currently, granularity is only microseconds, so the low-order three digits 7126 * will be truncated. 7127 */ 7128 7129 void 7130 gen_date(const char *keyword, const timestruc_t time_value) 7131 { 7132 /* Allow for <seconds>.<nanoseconds>\n */ 7133 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 7134 int len; 7135 char *curr_ptr; 7136 7137 (void) sprintf(save_val, "%ld", time_value.tv_sec); 7138 len = strlen(save_val); 7139 save_val[len] = '.'; 7140 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 7141 7142 /* 7143 * len = length of entire line, including itself. len will be 7144 * two digits. So, add the string lengths plus the length of len, 7145 * plus a blank, an equal sign, and a newline. 7146 */ 7147 len = strlen(save_val) + strlen(keyword) + 5; 7148 if (xrec_offset + len > xrec_size) { 7149 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7150 fatal(gettext( 7151 "cannot allocate extended header buffer")); 7152 xrec_ptr = curr_ptr; 7153 xrec_size *= 2; 7154 } 7155 (void) sprintf(&xrec_ptr[xrec_offset], 7156 "%d %s=%s\n", len, keyword, save_val); 7157 xrec_offset += len; 7158 } 7159 7160 /* 7161 * gen_string creates a string from a keyword and a char * in the 7162 * format: %d %s=%s\n 7163 * This is part of the extended header data record. 7164 */ 7165 7166 void 7167 gen_string(const char *keyword, const char *value) 7168 { 7169 int len; 7170 char *curr_ptr; 7171 7172 /* 7173 * len = length of entire line, including itself. The character length 7174 * of len must be 1-4 characters, because the maximum size of the path 7175 * or the name is PATH_MAX, which is 1024. So, assume 1 character 7176 * for len, one for the space, one for the "=", and one for the newline. 7177 * Then adjust as needed. 7178 */ 7179 /* LINTED constant expression */ 7180 assert(PATH_MAX <= 9996); 7181 len = strlen(value) + strlen(keyword) + 4; 7182 if (len > 997) 7183 len += 3; 7184 else if (len > 98) 7185 len += 2; 7186 else if (len > 9) 7187 len += 1; 7188 if (xrec_offset + len > xrec_size) { 7189 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 7190 fatal(gettext( 7191 "cannot allocate extended header buffer")); 7192 xrec_ptr = curr_ptr; 7193 xrec_size *= 2; 7194 } 7195 #ifdef XHDR_DEBUG 7196 if (strcmp(keyword+1, "name") != 0) 7197 #endif 7198 (void) sprintf(&xrec_ptr[xrec_offset], 7199 "%d %s=%s\n", len, keyword, value); 7200 #ifdef XHDR_DEBUG 7201 else { 7202 len += 11; 7203 (void) sprintf(&xrec_ptr[xrec_offset], 7204 "%d %s=%snametoolong\n", len, keyword, value); 7205 } 7206 #endif 7207 xrec_offset += len; 7208 } 7209 7210 /* 7211 * Convert time found in the extended header data to seconds and nanoseconds. 7212 */ 7213 7214 void 7215 get_xtime(char *value, timestruc_t *xtime) 7216 { 7217 char nanosec[10]; 7218 char *period; 7219 int i; 7220 7221 (void) memset(nanosec, '0', 9); 7222 nanosec[9] = '\0'; 7223 7224 period = strchr(value, '.'); 7225 if (period != NULL) 7226 period[0] = '\0'; 7227 xtime->tv_sec = strtol(value, NULL, 10); 7228 if (period == NULL) 7229 xtime->tv_nsec = 0; 7230 else { 7231 i = strlen(period +1); 7232 (void) strncpy(nanosec, period + 1, min(i, 9)); 7233 xtime->tv_nsec = strtol(nanosec, NULL, 10); 7234 } 7235 } 7236 7237 /* 7238 * Check linkpath for length. 7239 * Emit an error message and return 1 if too long. 7240 */ 7241 7242 int 7243 chk_path_build( 7244 char *name, 7245 char *longname, 7246 char *linkname, 7247 char *prefix, 7248 char type, 7249 int filetype) 7250 { 7251 7252 if (strlen(linkname) > (size_t)NAMSIZ) { 7253 if (Eflag > 0) { 7254 xhdr_flgs |= _X_LINKPATH; 7255 Xtarhdr.x_linkpath = linkname; 7256 } else { 7257 (void) fprintf(stderr, gettext( 7258 "tar: %s: linked to %s\n"), longname, linkname); 7259 (void) fprintf(stderr, gettext( 7260 "tar: %s: linked name too long\n"), linkname); 7261 if (errflag) 7262 done(1); 7263 else 7264 Errflg = 1; 7265 return (1); 7266 } 7267 } 7268 if (xhdr_flgs & _X_LINKPATH) 7269 return (build_dblock(name, tchar, type, 7270 filetype, &stbuf, stbuf.st_dev, 7271 prefix)); 7272 else 7273 return (build_dblock(name, linkname, type, 7274 filetype, &stbuf, stbuf.st_dev, prefix)); 7275 } 7276 7277 /* 7278 * Convert from UTF-8 to local character set. 7279 */ 7280 7281 static int 7282 utf8_local( 7283 char *option, 7284 char **Xhdr_ptrptr, 7285 char *target, 7286 const char *source, 7287 int max_val) 7288 { 7289 static iconv_t iconv_cd; 7290 char *nl_target; 7291 const char *iconv_src; 7292 char *iconv_trg; 7293 size_t inlen; 7294 size_t outlen; 7295 7296 if (charset_type == -1) { /* iconv_open failed in earlier try */ 7297 (void) fprintf(stderr, gettext( 7298 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7299 xhdr_count, source); 7300 return (1); 7301 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 7302 nl_target = nl_langinfo(CODESET); 7303 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7304 nl_target = "646"; 7305 if (strcmp(nl_target, "646") == 0) 7306 charset_type = 1; 7307 else if (strcmp(nl_target, "UTF-8") == 0) 7308 charset_type = 3; 7309 else { 7310 if (strncmp(nl_target, "ISO", 3) == 0) 7311 nl_target += 3; 7312 charset_type = 2; 7313 errno = 0; 7314 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 7315 (iconv_t)-1) { 7316 if (errno == EINVAL) 7317 (void) fprintf(stderr, gettext( 7318 "tar: conversion routines not " 7319 "available for current locale. ")); 7320 (void) fprintf(stderr, gettext( 7321 "file # %llu: (%s) UTF-8 conversion" 7322 " failed.\n"), xhdr_count, source); 7323 charset_type = -1; 7324 return (1); 7325 } 7326 } 7327 } 7328 7329 /* locale using 7-bit codeset or UTF-8 locale */ 7330 if (charset_type == 1 || charset_type == 3) { 7331 if (strlen(source) > max_val) { 7332 (void) fprintf(stderr, gettext( 7333 "tar: file # %llu: Extended header %s too long.\n"), 7334 xhdr_count, option); 7335 return (1); 7336 } 7337 if (charset_type == 3) 7338 (void) strcpy(target, source); 7339 else if (c_utf8(target, source) != 0) { 7340 (void) fprintf(stderr, gettext( 7341 "tar: file # %llu: (%s) UTF-8 conversion" 7342 " failed.\n"), xhdr_count, source); 7343 return (1); 7344 } 7345 *Xhdr_ptrptr = target; 7346 return (0); 7347 } 7348 7349 iconv_src = source; 7350 iconv_trg = target; 7351 inlen = strlen(source); 7352 outlen = max_val * UTF_8_FACTOR; 7353 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7354 (size_t)-1) { /* Error occurred: didn't convert */ 7355 (void) fprintf(stderr, gettext( 7356 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7357 xhdr_count, source); 7358 /* Get remaining output; reinitialize conversion descriptor */ 7359 iconv_src = (const char *)NULL; 7360 inlen = 0; 7361 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7362 return (1); 7363 } 7364 /* Get remaining output; reinitialize conversion descriptor */ 7365 iconv_src = (const char *)NULL; 7366 inlen = 0; 7367 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7368 (size_t)-1) { /* Error occurred: didn't convert */ 7369 (void) fprintf(stderr, gettext( 7370 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 7371 xhdr_count, source); 7372 return (1); 7373 } 7374 7375 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7376 if (strlen(target) > max_val) { 7377 (void) fprintf(stderr, gettext( 7378 "tar: file # %llu: Extended header %s too long.\n"), 7379 xhdr_count, option); 7380 return (1); 7381 } 7382 *Xhdr_ptrptr = target; 7383 return (0); 7384 } 7385 7386 /* 7387 * Check gname, uname, path, and linkpath to see if they need to go in an 7388 * extended header. If they are already slated to be in an extended header, 7389 * or if they are not ascii, then they need to be in the extended header. 7390 * Then, convert all extended names to UTF-8. 7391 */ 7392 7393 int 7394 gen_utf8_names(const char *filename) 7395 { 7396 static iconv_t iconv_cd; 7397 char *nl_target; 7398 char tempbuf[MAXNAM + 1]; 7399 int nbytes; 7400 int errors; 7401 7402 if (charset_type == -1) { /* Previous failure to open. */ 7403 (void) fprintf(stderr, gettext( 7404 "tar: file # %llu: UTF-8 conversion failed.\n"), 7405 xhdr_count); 7406 return (1); 7407 } 7408 7409 if (charset_type == 0) { /* Need to get conversion descriptor */ 7410 nl_target = nl_langinfo(CODESET); 7411 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 7412 nl_target = "646"; 7413 if (strcmp(nl_target, "646") == 0) 7414 charset_type = 1; 7415 else if (strcmp(nl_target, "UTF-8") == 0) 7416 charset_type = 3; 7417 else { 7418 if (strncmp(nl_target, "ISO", 3) == 0) 7419 nl_target += 3; 7420 charset_type = 2; 7421 errno = 0; 7422 #ifdef ICONV_DEBUG 7423 (void) fprintf(stderr, 7424 gettext("Opening iconv_cd with target %s\n"), 7425 nl_target); 7426 #endif 7427 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 7428 (iconv_t)-1) { 7429 if (errno == EINVAL) 7430 (void) fprintf(stderr, gettext( 7431 "tar: conversion routines not " 7432 "available for current locale. ")); 7433 (void) fprintf(stderr, gettext( 7434 "file (%s): UTF-8 conversion failed.\n"), 7435 filename); 7436 charset_type = -1; 7437 return (1); 7438 } 7439 } 7440 } 7441 7442 errors = 0; 7443 7444 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 7445 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 7446 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 7447 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 7448 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 7449 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 7450 tempbuf[NAMSIZ] = '\0'; 7451 } 7452 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 7453 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 7454 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 7455 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 7456 tempbuf[PRESIZ] = '\0'; 7457 nbytes = strlen(tempbuf); 7458 if (nbytes > 0) { 7459 tempbuf[nbytes++] = '/'; 7460 tempbuf[nbytes] = '\0'; 7461 } 7462 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, 7463 (MAXNAM - nbytes)); 7464 tempbuf[MAXNAM] = '\0'; 7465 } 7466 errors += local_utf8(&Xtarhdr.x_path, local_path, 7467 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 7468 7469 if (errors > 0) 7470 (void) fprintf(stderr, gettext( 7471 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 7472 7473 if (errors && errflag) 7474 done(1); 7475 else 7476 if (errors) 7477 Errflg = 1; 7478 return (errors); 7479 } 7480 7481 static int 7482 local_utf8( 7483 char **Xhdr_ptrptr, 7484 char *target, 7485 const char *source, 7486 iconv_t iconv_cd, 7487 int xhdrflg, 7488 int max_val) 7489 { 7490 const char *iconv_src; 7491 const char *starting_src; 7492 char *iconv_trg; 7493 size_t inlen; 7494 size_t outlen; 7495 #ifdef ICONV_DEBUG 7496 unsigned char c_to_hex; 7497 #endif 7498 7499 /* 7500 * If the item is already slated for extended format, get the string 7501 * to convert from the extended header record. Otherwise, get it from 7502 * the regular (dblock) area. 7503 */ 7504 if (xhdr_flgs & xhdrflg) { 7505 if (charset_type == 3) { /* Already UTF-8, just copy */ 7506 (void) strcpy(target, *Xhdr_ptrptr); 7507 *Xhdr_ptrptr = target; 7508 return (0); 7509 } else 7510 iconv_src = (const char *) *Xhdr_ptrptr; 7511 } else { 7512 if (charset_type == 3) /* Already in UTF-8 format */ 7513 return (0); /* Don't create xhdr record */ 7514 iconv_src = source; 7515 } 7516 starting_src = iconv_src; 7517 iconv_trg = target; 7518 if ((inlen = strlen(iconv_src)) == 0) 7519 return (0); 7520 7521 if (charset_type == 1) { /* locale using 7-bit codeset */ 7522 if (c_utf8(target, starting_src) != 0) { 7523 (void) fprintf(stderr, 7524 gettext("tar: invalid character in" 7525 " UTF-8 conversion of '%s'\n"), starting_src); 7526 return (1); 7527 } 7528 return (0); 7529 } 7530 7531 outlen = max_val * UTF_8_FACTOR; 7532 errno = 0; 7533 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7534 (size_t)-1) { 7535 /* An error occurred, or not all characters were converted */ 7536 if (errno == EILSEQ) 7537 (void) fprintf(stderr, 7538 gettext("tar: invalid character in" 7539 " UTF-8 conversion of '%s'\n"), starting_src); 7540 else 7541 (void) fprintf(stderr, gettext( 7542 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7543 starting_src); 7544 /* Get remaining output; reinitialize conversion descriptor */ 7545 iconv_src = (const char *)NULL; 7546 inlen = 0; 7547 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 7548 return (1); 7549 } 7550 /* Get remaining output; reinitialize conversion descriptor */ 7551 iconv_src = (const char *)NULL; 7552 inlen = 0; 7553 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 7554 (size_t)-1) { /* Error occurred: didn't convert */ 7555 if (errno == EILSEQ) 7556 (void) fprintf(stderr, 7557 gettext("tar: invalid character in" 7558 " UTF-8 conversion of '%s'\n"), starting_src); 7559 else 7560 (void) fprintf(stderr, gettext( 7561 "tar: conversion to UTF-8 aborted for '%s'.\n"), 7562 starting_src); 7563 return (1); 7564 } 7565 7566 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 7567 if (strcmp(starting_src, target) != 0) { 7568 *Xhdr_ptrptr = target; 7569 xhdr_flgs |= xhdrflg; 7570 #ifdef ICONV_DEBUG 7571 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 7572 strlen(starting_src), inlen, max_val, outlen); 7573 (void) fprintf(stderr, "Input string:\n "); 7574 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 7575 c_to_hex = (unsigned char)starting_src[inlen]; 7576 (void) fprintf(stderr, " %2.2x", c_to_hex); 7577 if (inlen % 20 == 19) 7578 (void) fprintf(stderr, "\n "); 7579 } 7580 (void) fprintf(stderr, "\nOutput string:\n "); 7581 for (inlen = 0; inlen < strlen(target); inlen++) { 7582 c_to_hex = (unsigned char)target[inlen]; 7583 (void) fprintf(stderr, " %2.2x", c_to_hex); 7584 if (inlen % 20 == 19) 7585 (void) fprintf(stderr, "\n "); 7586 } 7587 (void) fprintf(stderr, "\n"); 7588 #endif 7589 } 7590 7591 return (0); 7592 } 7593 7594 /* 7595 * Function to test each byte of the source string to make sure it is 7596 * in within bounds (value between 0 and 127). 7597 * If valid, copy source to target. 7598 */ 7599 7600 int 7601 c_utf8(char *target, const char *source) 7602 { 7603 size_t len; 7604 const char *thischar; 7605 7606 len = strlen(source); 7607 thischar = source; 7608 while (len-- > 0) { 7609 if (!isascii((int)(*thischar++))) 7610 return (1); 7611 } 7612 7613 (void) strcpy(target, source); 7614 return (0); 7615 } 7616 7617 7618 #if defined(O_XATTR) 7619 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 7620 7621 static void 7622 prepare_xattr( 7623 char **attrbuf, 7624 char *filename, 7625 char *attrpath, 7626 char typeflag, 7627 struct linkbuf *linkinfo, 7628 int *rlen) 7629 { 7630 char *bufhead; /* ptr to full buffer */ 7631 char *aptr; 7632 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 7633 struct xattr_buf *tptr; /* ptr to pathing pieces */ 7634 int totalen; /* total buffer length */ 7635 int len; /* length returned to user */ 7636 int stringlen; /* length of filename + attr */ 7637 /* 7638 * length of filename + attr 7639 * in link section 7640 */ 7641 int linkstringlen; 7642 int complen; /* length of pathing section */ 7643 int linklen; /* length of link section */ 7644 int attrnames_index; /* attrnames starting index */ 7645 7646 /* 7647 * Release previous buffer 7648 */ 7649 7650 if (*attrbuf != (char *)NULL) { 7651 free(*attrbuf); 7652 *attrbuf = NULL; 7653 } 7654 7655 /* 7656 * First add in fixed size stuff 7657 */ 7658 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 7659 7660 /* 7661 * Add space for two nulls 7662 */ 7663 stringlen = strlen(attrpath) + strlen(filename) + 2; 7664 complen = stringlen + sizeof (struct xattr_buf); 7665 7666 len += stringlen; 7667 7668 /* 7669 * Now add on space for link info if any 7670 */ 7671 7672 if (linkinfo != NULL) { 7673 /* 7674 * Again add space for two nulls 7675 */ 7676 linkstringlen = strlen(linkinfo->pathname) + 7677 strlen(linkinfo->attrname) + 2; 7678 linklen = linkstringlen + sizeof (struct xattr_buf); 7679 len += linklen; 7680 } else { 7681 linklen = 0; 7682 } 7683 7684 /* 7685 * Now add padding to end to fill out TBLOCK 7686 * 7687 * Function returns size of real data and not size + padding. 7688 */ 7689 7690 totalen = ROUNDTOTBLOCK(len); 7691 7692 if ((bufhead = calloc(1, totalen)) == NULL) { 7693 fatal(gettext("Out of memory.")); 7694 } 7695 7696 7697 /* 7698 * Now we can fill in the necessary pieces 7699 */ 7700 7701 /* 7702 * first fill in the fixed header 7703 */ 7704 hptr = (struct xattr_hdr *)bufhead; 7705 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 7706 (void) sprintf(hptr->h_component_len, "%0*d", 7707 sizeof (hptr->h_component_len) - 1, complen); 7708 (void) sprintf(hptr->h_link_component_len, "%0*d", 7709 sizeof (hptr->h_link_component_len) - 1, linklen); 7710 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 7711 7712 /* 7713 * Now fill in the filename + attrnames section 7714 * The filename and attrnames section can be composed of two or more 7715 * path segments separated by a null character. The first segment 7716 * is the path to the parent file that roots the entire sequence in 7717 * the normal name space. The remaining segments describes a path 7718 * rooted at the hidden extended attribute directory of the leaf file of 7719 * the previous segment, making it possible to name attributes on 7720 * attributes. Thus, if we are just archiving an extended attribute, 7721 * the second segment will contain the attribute name. If we are 7722 * archiving a system attribute of an extended attribute, then the 7723 * second segment will contain the attribute name, and a third segment 7724 * will contain the system attribute name. The attribute pathing 7725 * information is obtained from 'attrpath'. 7726 */ 7727 7728 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 7729 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 7730 stringlen); 7731 (void) strcpy(tptr->h_names, filename); 7732 attrnames_index = strlen(filename) + 1; 7733 (void) strcpy(&tptr->h_names[attrnames_index], attrpath); 7734 tptr->h_typeflag = typeflag; 7735 7736 /* 7737 * Split the attrnames section into two segments if 'attrpath' 7738 * contains pathing information for a system attribute of an 7739 * extended attribute. We split them by replacing the '/' with 7740 * a '\0'. 7741 */ 7742 if ((aptr = strpbrk(&tptr->h_names[attrnames_index], "/")) != NULL) { 7743 *aptr = '\0'; 7744 } 7745 7746 /* 7747 * Now fill in the optional link section if we have one 7748 */ 7749 7750 if (linkinfo != (struct linkbuf *)NULL) { 7751 tptr = (struct xattr_buf *)(bufhead + 7752 sizeof (struct xattr_hdr) + complen); 7753 7754 (void) sprintf(tptr->h_namesz, "%0*d", 7755 sizeof (tptr->h_namesz) - 1, linkstringlen); 7756 (void) strcpy(tptr->h_names, linkinfo->pathname); 7757 (void) strcpy( 7758 &tptr->h_names[strlen(linkinfo->pathname) + 1], 7759 linkinfo->attrname); 7760 tptr->h_typeflag = typeflag; 7761 } 7762 *attrbuf = (char *)bufhead; 7763 *rlen = len; 7764 } 7765 7766 #else 7767 static void 7768 prepare_xattr( 7769 char **attrbuf, 7770 char *filename, 7771 char *attrname, 7772 char typeflag, 7773 struct linkbuf *linkinfo, 7774 int *rlen) 7775 { 7776 *attrbuf = NULL; 7777 *rlen = 0; 7778 } 7779 #endif 7780 7781 int 7782 getstat(int dirfd, char *longname, char *shortname, char *attrparent) 7783 { 7784 7785 int i, j; 7786 int printerr; 7787 int slnkerr; 7788 struct stat symlnbuf; 7789 7790 if (!hflag) 7791 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 7792 else 7793 i = fstatat(dirfd, shortname, &stbuf, 0); 7794 7795 if (i < 0) { 7796 /* Initialize flag to print error mesg. */ 7797 printerr = 1; 7798 /* 7799 * If stat is done, then need to do lstat 7800 * to determine whether it's a sym link 7801 */ 7802 if (hflag) { 7803 /* Save returned error */ 7804 slnkerr = errno; 7805 7806 j = fstatat(dirfd, shortname, 7807 &symlnbuf, AT_SYMLINK_NOFOLLOW); 7808 /* 7809 * Suppress error message when file is a symbolic link 7810 * and function modifier 'l' is off. Exception: when 7811 * a symlink points to a symlink points to a 7812 * symlink ... and we get past MAXSYMLINKS. That 7813 * error will cause a file not to be archived, and 7814 * needs to be printed. 7815 */ 7816 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 7817 (S_ISLNK(symlnbuf.st_mode))) 7818 printerr = 0; 7819 7820 /* 7821 * Restore errno in case the lstat 7822 * on symbolic link change 7823 */ 7824 errno = slnkerr; 7825 } 7826 7827 if (printerr) { 7828 (void) fprintf(stderr, gettext( 7829 "tar: %s%s%s%s: %s\n"), 7830 (attrparent == NULL) ? "" : gettext("attribute "), 7831 (attrparent == NULL) ? "" : attrparent, 7832 (attrparent == NULL) ? "" : gettext(" of "), 7833 longname, strerror(errno)); 7834 Errflg = 1; 7835 } 7836 return (1); 7837 } 7838 return (0); 7839 } 7840 7841 /* 7842 * Recursively archive the extended attributes and/or extended system attributes 7843 * of the base file, longname. Note: extended system attribute files will be 7844 * archived only if the extended system attributes are not transient (i.e. the 7845 * extended system attributes are other than the default values). 7846 * 7847 * If -@ was specified and the underlying file system supports it, archive the 7848 * extended attributes, and if there is a system attribute associated with the 7849 * extended attribute, then recursively call xattrs_put() to archive the 7850 * hidden attribute directory and the extended system attribute. If -/ was 7851 * specified and the underlying file system supports it, archive the extended 7852 * system attributes. Read-only extended system attributes are never archived. 7853 * 7854 * Currently, there cannot be attributes on attributes; only system 7855 * attributes on attributes. In addition, there cannot be attributes on 7856 * system attributes. A file and it's attribute directory hierarchy looks as 7857 * follows: 7858 * longname ----> . ("." is the hidden attribute directory) 7859 * | 7860 * ---------------------------- 7861 * | | 7862 * <sys_attr_name> <attr_name> ----> . 7863 * | 7864 * <sys_attr_name> 7865 * 7866 */ 7867 #if defined(O_XATTR) 7868 static void 7869 xattrs_put(char *longname, char *shortname, char *parent, char *attrparent) 7870 { 7871 char *filename = (attrparent == NULL) ? shortname : attrparent; 7872 int arc_rwsysattr = 0; 7873 int dirfd; 7874 int fd = -1; 7875 int rw_sysattr = 0; 7876 int ext_attr = 0; 7877 int rc; 7878 DIR *dirp; 7879 struct dirent *dp; 7880 attr_data_t *attrinfo = NULL; 7881 7882 /* 7883 * If the underlying file system supports it, then archive the extended 7884 * attributes if -@ was specified, and the extended system attributes 7885 * if -/ was specified. 7886 */ 7887 if (verify_attr_support(filename, (attrparent == NULL), ARC_CREATE, 7888 &ext_attr) != ATTR_OK) { 7889 return; 7890 } 7891 7892 /* 7893 * Only want to archive a read-write extended system attribute file 7894 * if it contains extended system attribute settings that are not the 7895 * default values. 7896 */ 7897 #if defined(_PC_SATTR_ENABLED) 7898 if (saflag) { 7899 int filefd; 7900 nvlist_t *slist = NULL; 7901 7902 /* Determine if there are non-transient system attributes */ 7903 errno = 0; 7904 if ((filefd = open(filename, O_RDONLY)) == -1) { 7905 if (attrparent == NULL) { 7906 vperror(0, gettext( 7907 "unable to open file %s"), longname); 7908 } 7909 return; 7910 } 7911 if (((slist = sysattr_list(basename(myname), filefd, 7912 filename)) != NULL) || (errno != 0)) { 7913 arc_rwsysattr = 1; 7914 } 7915 if (slist != NULL) { 7916 (void) nvlist_free(slist); 7917 slist = NULL; 7918 } 7919 (void) close(filefd); 7920 } 7921 7922 /* 7923 * If we aren't archiving extended system attributes, and we are 7924 * processing an attribute, or if we are archiving extended system 7925 * attributes, and there are are no extended attributes, then there's 7926 * no need to open up the attribute directory of the file unless the 7927 * extended system attributes are not transient (i.e, the system 7928 * attributes are not the default values). 7929 */ 7930 if ((arc_rwsysattr == 0) && ((attrparent != NULL) || 7931 (saflag && !ext_attr))) { 7932 return; 7933 } 7934 #endif /* _PC_SATTR_ENABLED */ 7935 7936 /* open the parent attribute directory */ 7937 fd = attropen(filename, ".", O_RDONLY); 7938 if (fd < 0) { 7939 vperror(0, gettext( 7940 "unable to open attribute directory for %s%s%sfile %s"), 7941 (attrparent == NULL) ? "" : gettext("attribute "), 7942 (attrparent == NULL) ? "" : attrparent, 7943 (attrparent == NULL) ? "" : gettext(" of "), 7944 longname); 7945 return; 7946 } 7947 7948 /* 7949 * We need to change into the parent's attribute directory to determine 7950 * if each of the attributes should be archived. 7951 */ 7952 if (fchdir(fd) < 0) { 7953 vperror(0, gettext( 7954 "cannot change to attribute directory of %s%s%sfile %s"), 7955 (attrparent == NULL) ? "" : gettext("attribute "), 7956 (attrparent == NULL) ? "" : attrparent, 7957 (attrparent == NULL) ? "" : gettext(" of "), 7958 longname); 7959 (void) close(fd); 7960 return; 7961 } 7962 7963 if (((dirfd = dup(fd)) == -1) || 7964 ((dirp = fdopendir(dirfd)) == NULL)) { 7965 (void) fprintf(stderr, gettext( 7966 "tar: unable to open dir pointer for %s%s%sfile %s\n"), 7967 (attrparent == NULL) ? "" : gettext("attribute "), 7968 (attrparent == NULL) ? "" : attrparent, 7969 (attrparent == NULL) ? "" : gettext(" of "), 7970 longname); 7971 if (fd > 0) { 7972 (void) close(fd); 7973 } 7974 return; 7975 } 7976 7977 while (dp = readdir(dirp)) { 7978 if (strcmp(dp->d_name, "..") == 0) { 7979 continue; 7980 } else if (strcmp(dp->d_name, ".") == 0) { 7981 Hiddendir = 1; 7982 } else { 7983 Hiddendir = 0; 7984 } 7985 7986 /* Determine if this attribute should be archived */ 7987 if (verify_attr(dp->d_name, attrparent, arc_rwsysattr, 7988 &rw_sysattr) != ATTR_OK) { 7989 continue; 7990 } 7991 7992 /* gather the attribute's information to pass to putfile() */ 7993 if ((fill_in_attr_info(dp->d_name, longname, attrparent, 7994 fd, rw_sysattr, &attrinfo)) == 1) { 7995 continue; 7996 } 7997 7998 /* add the attribute to the archive */ 7999 rc = putfile(longname, dp->d_name, parent, attrinfo, 8000 XATTR_FILE, LEV0, SYMLINK_LEV0); 8001 8002 if (exitflag) { 8003 break; 8004 } 8005 8006 #if defined(_PC_SATTR_ENABLED) 8007 /* 8008 * If both -/ and -@ were specified, then archive the 8009 * attribute's extended system attributes and hidden directory 8010 * by making a recursive call to xattrs_put(). 8011 */ 8012 if (!rw_sysattr && saflag && atflag && (rc != PUT_AS_LINK) && 8013 (Hiddendir == 0)) { 8014 8015 xattrs_put(longname, shortname, parent, dp->d_name); 8016 8017 /* 8018 * Change back to the parent's attribute directory 8019 * to process any further attributes. 8020 */ 8021 if (fchdir(fd) < 0) { 8022 vperror(0, gettext( 8023 "cannot change back to attribute directory " 8024 "of file %s"), longname); 8025 break; 8026 } 8027 } 8028 #endif /* _PC_SATTR_ENABLED */ 8029 } 8030 8031 if (attrinfo != NULL) { 8032 if (attrinfo->attr_parent != NULL) { 8033 free(attrinfo->attr_parent); 8034 } 8035 free(attrinfo->attr_path); 8036 free(attrinfo); 8037 } 8038 (void) closedir(dirp); 8039 if (fd != -1) { 8040 (void) close(fd); 8041 } 8042 8043 /* Change back to the parent directory of the base file */ 8044 if (attrparent == NULL) { 8045 (void) chdir(parent); 8046 } 8047 Hiddendir = 0; 8048 } 8049 #else 8050 static void 8051 xattrs_put(char *longname, char *shortname, char *parent, char *attrppath) 8052 { 8053 } 8054 #endif /* O_XATTR */ 8055 8056 static int 8057 put_link(char *name, char *longname, char *component, char *longattrname, 8058 char *prefix, int filetype, char type) 8059 { 8060 8061 if (stbuf.st_nlink > 1) { 8062 struct linkbuf *lp; 8063 int found = 0; 8064 8065 for (lp = ihead; lp != NULL; lp = lp->nextp) 8066 if (lp->inum == stbuf.st_ino && 8067 lp->devnum == stbuf.st_dev) { 8068 found++; 8069 break; 8070 } 8071 if (found) { 8072 #if defined(O_XATTR) 8073 if (filetype == XATTR_FILE) 8074 if (put_xattr_hdr(longname, component, 8075 longattrname, prefix, type, filetype, lp)) { 8076 goto out; 8077 } 8078 #endif 8079 stbuf.st_size = (off_t)0; 8080 if (filetype != XATTR_FILE) { 8081 tomodes(&stbuf); 8082 if (chk_path_build(name, longname, lp->pathname, 8083 prefix, type, filetype) > 0) { 8084 goto out; 8085 } 8086 } 8087 8088 if (mulvol && tapepos + 1 >= blocklim) 8089 newvol(); 8090 (void) writetbuf((char *)&dblock, 1); 8091 /* 8092 * write_ancillary() is not needed here. 8093 * The first link is handled in the following 8094 * else statement. No need to process ACLs 8095 * for other hard links since they are the 8096 * same file. 8097 */ 8098 8099 if (vflag) { 8100 #ifdef DEBUG 8101 if (NotTape) 8102 DEBUG("seek = %" FMT_blkcnt_t 8103 "K\t", K(tapepos), 0); 8104 #endif 8105 if (filetype == XATTR_FILE) { 8106 (void) fprintf(vfile, gettext( 8107 "a %s attribute %s link to " 8108 "%s attribute %s\n"), 8109 name, component, name, 8110 lp->attrname); 8111 } else { 8112 (void) fprintf(vfile, gettext( 8113 "a %s link to %s\n"), 8114 longname, lp->pathname); 8115 } 8116 } 8117 lp->count--; 8118 return (0); 8119 } else { 8120 lp = (struct linkbuf *)getmem(sizeof (*lp)); 8121 if (lp != (struct linkbuf *)NULL) { 8122 lp->nextp = ihead; 8123 ihead = lp; 8124 lp->inum = stbuf.st_ino; 8125 lp->devnum = stbuf.st_dev; 8126 lp->count = stbuf.st_nlink - 1; 8127 if (filetype == XATTR_FILE) { 8128 (void) strcpy(lp->pathname, longname); 8129 (void) strcpy(lp->attrname, 8130 component); 8131 } else { 8132 (void) strcpy(lp->pathname, longname); 8133 (void) strcpy(lp->attrname, ""); 8134 } 8135 } 8136 } 8137 } 8138 8139 out: 8140 return (1); 8141 } 8142 8143 static int 8144 put_extra_attributes(char *longname, char *shortname, char *longattrname, 8145 char *prefix, int filetype, char typeflag) 8146 { 8147 static acl_t *aclp = NULL; 8148 int error; 8149 8150 if (aclp != NULL) { 8151 acl_free(aclp); 8152 aclp = NULL; 8153 } 8154 #if defined(O_XATTR) 8155 if ((atflag || saflag) && (filetype == XATTR_FILE)) { 8156 if (put_xattr_hdr(longname, shortname, longattrname, prefix, 8157 typeflag, filetype, NULL)) { 8158 return (1); 8159 } 8160 } 8161 #endif 8162 8163 /* ACL support */ 8164 if (pflag) { 8165 char *secinfo = NULL; 8166 int len = 0; 8167 8168 /* ACL support */ 8169 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 8170 /* 8171 * Get ACL info: dont bother allocating space if 8172 * there is only a trivial ACL. 8173 */ 8174 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 8175 &aclp)) != 0) { 8176 (void) fprintf(stderr, gettext( 8177 "%s: failed to retrieve acl : %s\n"), 8178 longname, acl_strerror(error)); 8179 return (1); 8180 } 8181 } 8182 8183 /* append security attributes if any */ 8184 if (aclp != NULL) { 8185 (void) append_secattr(&secinfo, &len, acl_cnt(aclp), 8186 acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT | 8187 ACL_SID_FMT), (acl_type(aclp) == ACLENT_T) ? 8188 UFSD_ACL : ACE_ACL); 8189 } 8190 8191 if (Tflag) { 8192 /* append Trusted Extensions extended attributes */ 8193 append_ext_attr(shortname, &secinfo, &len); 8194 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8195 8196 } else if (aclp != NULL) { 8197 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 8198 } 8199 } 8200 return (0); 8201 } 8202 8203 #if defined(O_XATTR) 8204 static int 8205 put_xattr_hdr(char *longname, char *shortname, char *longattrname, char *prefix, 8206 int typeflag, int filetype, struct linkbuf *lp) 8207 { 8208 char *lname = NULL; 8209 char *sname = NULL; 8210 int error = 0; 8211 static char *attrbuf = NULL; 8212 int attrlen; 8213 8214 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 8215 strlen(shortname) + strlen(".hdr") + 1); 8216 8217 if (lname == NULL) { 8218 fatal(gettext("Out of Memory.")); 8219 } 8220 sname = malloc(sizeof (char) * strlen(shortname) + 8221 strlen(".hdr") + 1); 8222 if (sname == NULL) { 8223 fatal(gettext("Out of Memory.")); 8224 } 8225 8226 (void) sprintf(sname, "%s.hdr", shortname); 8227 (void) sprintf(lname, "/dev/null/%s", sname); 8228 8229 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 8230 sizeof (dblock.dbuf.name)) { 8231 fatal(gettext( 8232 "Buffer overflow writing extended attribute file name")); 8233 } 8234 8235 /* 8236 * dump extended attr lookup info 8237 */ 8238 prepare_xattr(&attrbuf, longname, longattrname, typeflag, lp, &attrlen); 8239 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 8240 8241 (void) sprintf(lname, "/dev/null/%s", shortname); 8242 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 8243 8244 /* 8245 * Set up filename for attribute 8246 */ 8247 8248 error = build_dblock(lname, tchar, '0', filetype, 8249 &stbuf, stbuf.st_dev, prefix); 8250 free(lname); 8251 free(sname); 8252 8253 return (error); 8254 } 8255 #endif 8256 8257 #if defined(O_XATTR) 8258 static int 8259 read_xattr_hdr(attr_data_t **attrinfo) 8260 { 8261 char buf[TBLOCK]; 8262 char *attrparent = NULL; 8263 blkcnt_t blocks; 8264 char *tp; 8265 off_t bytes; 8266 int comp_len, link_len; 8267 int namelen; 8268 int attrparentlen; 8269 int parentfilelen; 8270 8271 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 8272 return (1); 8273 8274 bytes = stbuf.st_size; 8275 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 8276 (void) fprintf(stderr, gettext( 8277 "Insufficient memory for extended attribute\n")); 8278 return (1); 8279 } 8280 8281 tp = (char *)xattrhead; 8282 blocks = TBLOCKS(bytes); 8283 while (blocks-- > 0) { 8284 readtape(buf); 8285 if (bytes <= TBLOCK) { 8286 (void) memcpy(tp, buf, (size_t)bytes); 8287 break; 8288 } else { 8289 (void) memcpy(tp, buf, TBLOCK); 8290 tp += TBLOCK; 8291 } 8292 bytes -= TBLOCK; 8293 } 8294 8295 /* 8296 * Validate that we can handle header format 8297 */ 8298 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 8299 (void) fprintf(stderr, 8300 gettext("Unknown extended attribute format encountered\n")); 8301 (void) fprintf(stderr, 8302 gettext("Disabling extended attribute parsing\n")); 8303 xattrbadhead = 1; 8304 return (0); 8305 } 8306 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 8307 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 8308 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 8309 sizeof (struct xattr_hdr)); 8310 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 8311 if (link_len > 0) 8312 xattr_linkp = (struct xattr_buf *) 8313 ((int)xattrp + (int)comp_len); 8314 else 8315 xattr_linkp = NULL; 8316 8317 /* 8318 * Gather the attribute path from the filename and attrnames section. 8319 * The filename and attrnames section can be composed of two or more 8320 * path segments separated by a null character. The first segment 8321 * is the path to the parent file that roots the entire sequence in 8322 * the normal name space. The remaining segments describes a path 8323 * rooted at the hidden extended attribute directory of the leaf file of 8324 * the previous segment, making it possible to name attributes on 8325 * attributes. 8326 */ 8327 parentfilelen = strlen(xattrp->h_names); 8328 xattrapath = xattrp->h_names + parentfilelen + 1; 8329 if ((strlen(xattrapath) + parentfilelen + 2) < namelen) { 8330 /* 8331 * The attrnames section contains a system attribute on an 8332 * attribute. Save the name of the attribute for use later, 8333 * and replace the null separating the attribute name from 8334 * the system attribute name with a '/' so that xattrapath can 8335 * be used to display messages with the full attribute path name 8336 * rooted at the hidden attribute directory of the base file 8337 * in normal name space. 8338 */ 8339 attrparent = strdup(xattrapath); 8340 attrparentlen = strlen(attrparent); 8341 xattrapath[attrparentlen] = '/'; 8342 } 8343 if ((fill_in_attr_info((attrparent == NULL) ? xattrapath : 8344 xattrapath + attrparentlen + 1, xattrapath, attrparent, 8345 -1, 0, attrinfo)) == 1) { 8346 free(attrparent); 8347 return (1); 8348 } 8349 8350 /* Gather link info */ 8351 if (xattr_linkp) { 8352 xattr_linkaname = xattr_linkp->h_names + 8353 strlen(xattr_linkp->h_names) + 1; 8354 } else { 8355 xattr_linkaname = NULL; 8356 } 8357 8358 return (0); 8359 } 8360 #else 8361 static int 8362 read_xattr_hdr(attr_data_t **attrinfo) 8363 { 8364 return (0); 8365 } 8366 #endif 8367 8368 /* 8369 * skip over extra slashes in string. 8370 * 8371 * For example: 8372 * /usr/tmp///// 8373 * 8374 * would return pointer at 8375 * /usr/tmp///// 8376 * ^ 8377 */ 8378 static char * 8379 skipslashes(char *string, char *start) 8380 { 8381 while ((string > start) && *(string - 1) == '/') { 8382 string--; 8383 } 8384 8385 return (string); 8386 } 8387 8388 /* 8389 * Return the parent directory of a given path. 8390 * 8391 * Examples: 8392 * /usr/tmp return /usr 8393 * /usr/tmp/file return /usr/tmp 8394 * / returns . 8395 * /usr returns / 8396 * file returns . 8397 * 8398 * dir is assumed to be at least as big as path. 8399 */ 8400 static void 8401 get_parent(char *path, char *dir) 8402 { 8403 char *s; 8404 char tmpdir[PATH_MAX + 1]; 8405 8406 if (strlen(path) > PATH_MAX) { 8407 fatal(gettext("pathname is too long")); 8408 } 8409 (void) strcpy(tmpdir, path); 8410 chop_endslashes(tmpdir); 8411 8412 if ((s = strrchr(tmpdir, '/')) == NULL) { 8413 (void) strcpy(dir, "."); 8414 } else { 8415 s = skipslashes(s, tmpdir); 8416 *s = '\0'; 8417 if (s == tmpdir) 8418 (void) strcpy(dir, "/"); 8419 else 8420 (void) strcpy(dir, tmpdir); 8421 } 8422 } 8423 8424 #if defined(O_XATTR) 8425 static char * 8426 get_component(char *path) 8427 { 8428 char *ptr; 8429 8430 ptr = strrchr(path, '/'); 8431 if (ptr == NULL) { 8432 return (path); 8433 } else { 8434 /* 8435 * Handle trailing slash 8436 */ 8437 if (*(ptr + 1) == '\0') 8438 return (ptr); 8439 else 8440 return (ptr + 1); 8441 } 8442 } 8443 #else 8444 static char * 8445 get_component(char *path) 8446 { 8447 return (path); 8448 } 8449 #endif 8450 8451 #if defined(O_XATTR) 8452 static int 8453 retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, char *name, 8454 int oflag, mode_t mode) 8455 { 8456 int dirfd; 8457 int ofilefd = -1; 8458 struct timeval times[2]; 8459 mode_t newmode; 8460 struct stat parentstat; 8461 acl_t *aclp = NULL; 8462 int error; 8463 8464 /* 8465 * We couldn't get to attrdir. See if its 8466 * just a mode problem on the parent file. 8467 * for example: a mode such as r-xr--r-- 8468 * on a ufs file system without extended 8469 * system attribute support won't let us 8470 * create an attribute dir if it doesn't 8471 * already exist, and on a ufs file system 8472 * with extended system attribute support 8473 * won't let us open the attribute for 8474 * write. 8475 * 8476 * If file has a non-trivial ACL, then save it 8477 * off so that we can place it back on after doing 8478 * chmod's. 8479 */ 8480 if ((dirfd = openat(cwd, (pattr == NULL) ? dirp : pattr, 8481 O_RDONLY)) == -1) { 8482 return (-1); 8483 } 8484 if (fstat(dirfd, &parentstat) == -1) { 8485 (void) fprintf(stderr, gettext( 8486 "tar: cannot stat %sfile %s: %s\n"), 8487 (pdirfd == -1) ? "" : gettext("parent of "), 8488 (pdirfd == -1) ? dirp : name, strerror(errno)); 8489 return (-1); 8490 } 8491 if ((error = facl_get(dirfd, ACL_NO_TRIVIAL, &aclp)) != 0) { 8492 (void) fprintf(stderr, gettext( 8493 "tar: failed to retrieve ACL on %sfile %s: %s\n"), 8494 (pdirfd == -1) ? "" : gettext("parent of "), 8495 (pdirfd == -1) ? dirp : name, strerror(errno)); 8496 return (-1); 8497 } 8498 8499 newmode = S_IWUSR | parentstat.st_mode; 8500 if (fchmod(dirfd, newmode) == -1) { 8501 (void) fprintf(stderr, 8502 gettext( 8503 "tar: cannot fchmod %sfile %s to %o: %s\n"), 8504 (pdirfd == -1) ? "" : gettext("parent of "), 8505 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8506 if (aclp) 8507 acl_free(aclp); 8508 return (-1); 8509 } 8510 8511 8512 if (pdirfd == -1) { 8513 /* 8514 * We weren't able to create the attribute directory before. 8515 * Now try again. 8516 */ 8517 ofilefd = attropen(dirp, ".", oflag); 8518 } else { 8519 /* 8520 * We weren't able to create open the attribute before. 8521 * Now try again. 8522 */ 8523 ofilefd = openat(pdirfd, name, oflag, mode); 8524 } 8525 8526 /* 8527 * Put mode back to original 8528 */ 8529 if (fchmod(dirfd, parentstat.st_mode) == -1) { 8530 (void) fprintf(stderr, 8531 gettext("tar: cannot chmod %sfile %s to %o: %s\n"), 8532 (pdirfd == -1) ? "" : gettext("parent of "), 8533 (pdirfd == -1) ? dirp : name, newmode, strerror(errno)); 8534 } 8535 8536 if (aclp) { 8537 error = facl_set(dirfd, aclp); 8538 if (error) { 8539 (void) fprintf(stderr, 8540 gettext("tar: failed to set acl entries on " 8541 "%sfile %s\n"), 8542 (pdirfd == -1) ? "" : gettext("parent of "), 8543 (pdirfd == -1) ? dirp : name); 8544 } 8545 acl_free(aclp); 8546 } 8547 8548 /* 8549 * Put back time stamps 8550 */ 8551 8552 times[0].tv_sec = parentstat.st_atime; 8553 times[0].tv_usec = 0; 8554 times[1].tv_sec = parentstat.st_mtime; 8555 times[1].tv_usec = 0; 8556 8557 (void) futimesat(cwd, (pattr == NULL) ? dirp : pattr, times); 8558 8559 (void) close(dirfd); 8560 8561 return (ofilefd); 8562 } 8563 #endif 8564 8565 #if !defined(O_XATTR) 8566 static int 8567 openat64(int fd, const char *name, int oflag, mode_t cmode) 8568 { 8569 return (open64(name, oflag, cmode)); 8570 } 8571 8572 static int 8573 openat(int fd, const char *name, int oflag, mode_t cmode) 8574 { 8575 return (open(name, oflag, cmode)); 8576 } 8577 8578 static int 8579 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 8580 { 8581 if (flag == AT_SYMLINK_NOFOLLOW) 8582 return (lchown(name, owner, group)); 8583 else 8584 return (chown(name, owner, group)); 8585 } 8586 8587 static int 8588 renameat(int fromfd, char *old, int tofd, char *new) 8589 { 8590 return (rename(old, new)); 8591 } 8592 8593 static int 8594 futimesat(int fd, char *path, struct timeval times[2]) 8595 { 8596 return (utimes(path, times)); 8597 } 8598 8599 static int 8600 unlinkat(int dirfd, char *path, int flag) 8601 { 8602 if (flag == AT_REMOVEDIR) 8603 return (rmdir(path)); 8604 else 8605 return (unlink(path)); 8606 } 8607 8608 static int 8609 fstatat(int fd, char *path, struct stat *buf, int flag) 8610 { 8611 if (flag == AT_SYMLINK_NOFOLLOW) 8612 return (lstat(path, buf)); 8613 else 8614 return (stat(path, buf)); 8615 } 8616 8617 static int 8618 attropen(char *file, char *attr, int omode, mode_t cmode) 8619 { 8620 errno = ENOTSUP; 8621 return (-1); 8622 } 8623 #endif 8624 8625 static void 8626 chop_endslashes(char *path) 8627 { 8628 char *end, *ptr; 8629 8630 /* 8631 * Chop of slashes, but not if all we have is slashes 8632 * for example: //// 8633 * should make no changes, otherwise it will screw up 8634 * checkdir 8635 */ 8636 end = &path[strlen(path) -1]; 8637 if (*end == '/' && end != path) { 8638 ptr = skipslashes(end, path); 8639 if (ptr != NULL && ptr != path) { 8640 *ptr = '\0'; 8641 } 8642 } 8643 } 8644 /* Trusted Extensions */ 8645 8646 /* 8647 * append_ext_attr(): 8648 * 8649 * Append extended attributes and other information into the buffer 8650 * that gets written to the ancillary file. 8651 * 8652 * With option 'T', we create a tarfile which 8653 * has an ancillary file each corresponding archived file. 8654 * Each ancillary file contains 1 or more of the 8655 * following attributes: 8656 * 8657 * attribute type attribute process procedure 8658 * ---------------- ---------------- -------------------------- 8659 * DIR_TYPE = 'D' directory flag append if a directory 8660 * LBL_TYPE = 'L' SL[IL] or SL append ascii label 8661 * 8662 * 8663 */ 8664 static void 8665 append_ext_attr(char *shortname, char **secinfo, int *len) 8666 { 8667 bslabel_t b_slabel; /* binary sensitvity label */ 8668 char *ascii = NULL; /* ascii label */ 8669 8670 /* 8671 * For each attribute type, append it if it is 8672 * relevant to the file type. 8673 */ 8674 8675 /* 8676 * For attribute type DIR_TYPE, 8677 * append it to the following file type: 8678 * 8679 * S_IFDIR: directories 8680 */ 8681 8682 /* 8683 * For attribute type LBL_TYPE, 8684 * append it to the following file type: 8685 * 8686 * S_IFDIR: directories (including mld, sld) 8687 * S_IFLNK: symbolic link 8688 * S_IFREG: regular file but not hard link 8689 * S_IFIFO: FIFO file but not hard link 8690 * S_IFCHR: char special file but not hard link 8691 * S_IFBLK: block special file but not hard link 8692 */ 8693 switch (stbuf.st_mode & S_IFMT) { 8694 8695 case S_IFDIR: 8696 8697 /* 8698 * append DIR_TYPE 8699 */ 8700 (void) append_secattr(secinfo, len, 1, 8701 "\0", DIR_TYPE); 8702 8703 /* 8704 * Get and append attribute types LBL_TYPE. 8705 * For directories, LBL_TYPE contains SL. 8706 */ 8707 /* get binary sensitivity label */ 8708 if (getlabel(shortname, &b_slabel) != 0) { 8709 (void) fprintf(stderr, 8710 gettext("tar: can't get sensitvity label for " 8711 " %s, getlabel() error: %s\n"), 8712 shortname, strerror(errno)); 8713 } else { 8714 /* get ascii SL */ 8715 if (bsltos(&b_slabel, &ascii, 8716 0, 0) <= 0) { 8717 (void) fprintf(stderr, 8718 gettext("tar: can't get ascii SL for" 8719 " %s\n"), shortname); 8720 } else { 8721 /* append LBL_TYPE */ 8722 (void) append_secattr(secinfo, len, 8723 strlen(ascii) + 1, ascii, 8724 LBL_TYPE); 8725 8726 /* free storage */ 8727 if (ascii != NULL) { 8728 free(ascii); 8729 ascii = (char *)0; 8730 } 8731 } 8732 8733 } 8734 break; 8735 8736 case S_IFLNK: 8737 case S_IFREG: 8738 case S_IFIFO: 8739 case S_IFCHR: 8740 case S_IFBLK: 8741 8742 /* get binary sensitivity label */ 8743 if (getlabel(shortname, &b_slabel) != 0) { 8744 (void) fprintf(stderr, 8745 gettext("tar: can't get sensitivty label for %s, " 8746 "getlabel() error: %s\n"), 8747 shortname, strerror(errno)); 8748 } else { 8749 /* get ascii IL[SL] */ 8750 if (bsltos(&b_slabel, &ascii, 0, 0) <= 0) { 8751 (void) fprintf(stderr, 8752 gettext("tar: can't translate sensitivity " 8753 " label for %s\n"), shortname); 8754 } else { 8755 char *cmw_label; 8756 size_t cmw_length; 8757 8758 cmw_length = strlen("ADMIN_LOW [] ") + 8759 strlen(ascii); 8760 if ((cmw_label = malloc(cmw_length)) == NULL) { 8761 (void) fprintf(stderr, gettext( 8762 "Insufficient memory for label\n")); 8763 exit(1); 8764 } 8765 /* append LBL_TYPE */ 8766 (void) snprintf(cmw_label, cmw_length, 8767 "ADMIN_LOW [%s]", ascii); 8768 (void) append_secattr(secinfo, len, 8769 strlen(cmw_label) + 1, cmw_label, 8770 LBL_TYPE); 8771 8772 /* free storage */ 8773 if (ascii != NULL) { 8774 free(cmw_label); 8775 free(ascii); 8776 ascii = (char *)0; 8777 } 8778 } 8779 } 8780 break; 8781 8782 default: 8783 break; 8784 } /* end switch for LBL_TYPE */ 8785 8786 8787 /* DONE !! */ 8788 return; 8789 8790 } /* end of append_ext_attr */ 8791 8792 8793 /* 8794 * Name: extract_attr() 8795 * 8796 * Description: 8797 * Process attributes from the ancillary file due to 8798 * the T option. 8799 * 8800 * Call by doxtract() as part of the switch case structure. 8801 * Making this a separate routine because the nesting are too 8802 * deep in doxtract, thus, leaving very little space 8803 * on each line for instructions. 8804 * 8805 * With option 'T', we extract from a TS 8 or TS 2.5 ancillary file 8806 * 8807 * For option 'T', following are possible attributes in 8808 * a TS 8 ancillary file: (NOTE: No IL support) 8809 * 8810 * attribute type attribute process procedure 8811 * ---------------- ---------------- ------------------------- 8812 * # LBL_TYPE = 'L' SL construct binary label 8813 * # APRIV_TYPE = 'P' allowed priv construct privileges 8814 * # FPRIV_TYPE = 'p' forced priv construct privileges 8815 * # COMP_TYPE = 'C' path component construct real path 8816 * # DIR_TYPE = 'D' directory flag note it is a directory 8817 * $ UFSD_ACL = '1' ACL data construct ACL entries 8818 * ATTR_FLAG_TYPE = 'F' file attr flags construct binary flags 8819 * LK_COMP_TYPE = 'K' linked path comp construct linked real path 8820 * 8821 * note: # = attribute names common between TS 8 & TS 2.5 ancillary 8822 * files. 8823 * $ = ACL attribute is processed for the option 'p', it doesn't 8824 * need option 'T'. 8825 * 8826 * Trusted Extensions ignores APRIV_TYPE, FPRIV_TYPE, and ATTR_FLAG_TYPE 8827 * 8828 */ 8829 static void 8830 extract_attr(char **file_ptr, struct sec_attr *attr) 8831 { 8832 int reterr, err; 8833 char *dummy_buf; /* for attribute extract */ 8834 8835 dummy_buf = attr->attr_info; 8836 8837 switch (attr->attr_type) { 8838 8839 case DIR_TYPE: 8840 8841 dir_flag++; 8842 break; 8843 8844 case LBL_TYPE: 8845 8846 /* 8847 * LBL_TYPE is used to indicate SL for directory, and 8848 * CMW label for other file types. 8849 */ 8850 8851 if (!dir_flag) { /* not directory */ 8852 /* Skip over IL portion */ 8853 char *sl_ptr = strchr(dummy_buf, '['); 8854 8855 if (sl_ptr == NULL) 8856 err = 0; 8857 else 8858 err = stobsl(sl_ptr, &bs_label, 8859 NEW_LABEL, &reterr); 8860 } else { /* directory */ 8861 err = stobsl(dummy_buf, &bs_label, 8862 NEW_LABEL, &reterr); 8863 } 8864 if (err == 0) { 8865 (void) fprintf(stderr, gettext("tar: " 8866 "can't convert %s to binary label\n"), 8867 dummy_buf); 8868 bslundef(&bs_label); 8869 } else if (!blequal(&bs_label, &admin_low) && 8870 !blequal(&bs_label, &admin_high)) { 8871 bslabel_t *from_label; 8872 char *buf; 8873 char tempbuf[MAXPATHLEN]; 8874 8875 if (*orig_namep != '/') { 8876 /* got relative linked to path */ 8877 (void) getcwd(tempbuf, (sizeof (tempbuf))); 8878 (void) strncat(tempbuf, "/", MAXPATHLEN); 8879 } else 8880 *tempbuf = '\0'; 8881 8882 buf = real_path; 8883 (void) strncat(tempbuf, orig_namep, MAXPATHLEN); 8884 from_label = getlabelbypath(tempbuf); 8885 if (from_label != NULL) { 8886 if (blequal(from_label, &admin_low)) { 8887 if ((getpathbylabel(tempbuf, buf, 8888 MAXPATHLEN, &bs_label) == NULL)) { 8889 (void) fprintf(stderr, 8890 gettext("tar: " 8891 "can't get zone root path for " 8892 "%s\n"), tempbuf); 8893 } else 8894 rpath_flag = 1; 8895 } 8896 free(from_label); 8897 } 8898 } 8899 break; 8900 8901 case COMP_TYPE: 8902 8903 rebuild_comp_path(dummy_buf, file_ptr); 8904 break; 8905 8906 case LK_COMP_TYPE: 8907 8908 if (rebuild_lk_comp_path(dummy_buf, file_ptr) 8909 == 0) { 8910 lk_rpath_flag = 1; 8911 } else { 8912 (void) fprintf(stderr, gettext("tar: warning: link's " 8913 "target pathname might be invalid.\n")); 8914 lk_rpath_flag = 0; 8915 } 8916 break; 8917 case APRIV_TYPE: 8918 ignored_aprivs++; 8919 break; 8920 case FPRIV_TYPE: 8921 ignored_fprivs++; 8922 break; 8923 case ATTR_FLAG_TYPE: 8924 ignored_fattrs++; 8925 break; 8926 8927 default: 8928 8929 break; 8930 } 8931 8932 /* done */ 8933 return; 8934 8935 } /* end extract_attr */ 8936 8937 8938 8939 /* 8940 * Name: rebuild_comp_path() 8941 * 8942 * Description: 8943 * Take the string of components passed down by the calling 8944 * routine and parse the values and rebuild the path. 8945 * This routine no longer needs to produce a new real_path 8946 * string because it is produced when the 'L' LABEL_TYPE is 8947 * interpreted. So the only thing done here is to distinguish 8948 * between an SLD and an MLD entry. We only want one, so we 8949 * ignore the MLD entry by setting the mld_flag. 8950 * 8951 * return value: 8952 * none 8953 */ 8954 static void 8955 rebuild_comp_path(char *str, char **namep) 8956 { 8957 char *cp; 8958 8959 while (*str != '\0') { 8960 8961 switch (*str) { 8962 8963 case MLD_TYPE: 8964 8965 str++; 8966 if ((cp = strstr(str, ";;")) != NULL) { 8967 *cp = '\0'; 8968 str = cp + 2; 8969 *cp = ';'; 8970 } 8971 mld_flag = 1; 8972 break; 8973 8974 case SLD_TYPE: 8975 8976 str++; 8977 if ((cp = strstr(str, ";;")) != NULL) { 8978 *cp = '\0'; 8979 str = cp + 2; 8980 *cp = ';'; 8981 } 8982 mld_flag = 0; 8983 break; 8984 8985 case PATH_TYPE: 8986 8987 str++; 8988 if ((cp = strstr(str, ";;")) != NULL) { 8989 *cp = '\0'; 8990 str = cp + 2; 8991 *cp = ';'; 8992 } 8993 break; 8994 } 8995 } 8996 if (rpath_flag) 8997 *namep = real_path; 8998 return; 8999 9000 } /* end rebuild_comp_path() */ 9001 9002 /* 9003 * Name: rebuild_lk_comp_path() 9004 * 9005 * Description: 9006 * Take the string of components passed down by the calling 9007 * routine and parse the values and rebuild the path. 9008 * 9009 * return value: 9010 * 0 = succeeded 9011 * -1 = failed 9012 */ 9013 static int 9014 rebuild_lk_comp_path(char *str, char **namep) 9015 { 9016 char *cp; 9017 int reterr; 9018 bslabel_t bslabel; 9019 char *buf; 9020 char pbuf[MAXPATHLEN]; 9021 char *ptr1, *ptr2; 9022 int plen; 9023 int use_pbuf; 9024 char tempbuf[MAXPATHLEN]; 9025 int mismatch; 9026 bslabel_t *from_label; 9027 char zonename[ZONENAME_MAX]; 9028 zoneid_t zoneid; 9029 9030 /* init stuff */ 9031 use_pbuf = 0; 9032 mismatch = 0; 9033 9034 /* 9035 * For linked to pathname (LK_COMP_TYPE): 9036 * - If the linked to pathname is absolute (start with /), we 9037 * will use it as is. 9038 * - If it is a relative pathname then it is relative to 1 of 2 9039 * directories. For a hardlink, it is relative to the current 9040 * directory. For a symbolic link, it is relative to the 9041 * directory the symbolic link is in. For the symbolic link 9042 * case, set a flag to indicate we need to use the prefix of 9043 * the restored file's pathname with the linked to pathname. 9044 * 9045 * NOTE: At this point, we have no way to determine if we have 9046 * a hardlink or a symbolic link. We will compare the 1st 9047 * component in the prefix portion of the restore file's 9048 * pathname to the 1st component in the attribute data 9049 * (the linked pathname). If they are the same, we will assume 9050 * the link pathname to reconstruct is relative to the current 9051 * directory. Otherwise, we will set a flag indicate we need 9052 * to use a prefix with the reconstructed name. Need to compare 9053 * both the adorned and unadorned version before deciding a 9054 * mismatch. 9055 */ 9056 9057 buf = lk_real_path; 9058 if (*(str + 1) != '/') { /* got relative linked to path */ 9059 ptr1 = orig_namep; 9060 ptr2 = strrchr(ptr1, '/'); 9061 plen = ptr2 - ptr1; 9062 if (plen > 0) { 9063 pbuf[0] = '\0'; 9064 plen++; /* include '/' */ 9065 (void) strncpy(pbuf, ptr1, plen); 9066 *(pbuf + plen) = '\0'; 9067 ptr2 = strchr(pbuf, '/'); 9068 if (strncmp(pbuf, str + 1, ptr2 - pbuf) != 0) 9069 mismatch = 1; 9070 } 9071 9072 if (mismatch == 1) 9073 use_pbuf = 1; 9074 } 9075 9076 buf[0] = '\0'; 9077 9078 while (*str != '\0') { 9079 9080 switch (*str) { 9081 9082 case MLD_TYPE: 9083 9084 str++; 9085 if ((cp = strstr(str, ";;")) != NULL) { 9086 *cp = '\0'; 9087 9088 /* 9089 * Ignore attempts to backup over .MLD. 9090 */ 9091 if (strcmp(str, "../") != 0) 9092 (void) strncat(buf, str, MAXPATHLEN); 9093 str = cp + 2; 9094 *cp = ';'; 9095 } 9096 break; 9097 9098 case SLD_TYPE: 9099 9100 str++; 9101 if ((cp = strstr(str, ";;")) != NULL) { 9102 *cp = '\0'; 9103 9104 /* 9105 * Use the path name in the header if 9106 * error occurs when processing the 9107 * SLD type. 9108 */ 9109 9110 if (!stobsl(str, &bslabel, 9111 NO_CORRECTION, &reterr)) { 9112 (void) fprintf(stderr, gettext( 9113 "tar: can't translate to binary" 9114 "SL for SLD, stobsl() error:" 9115 " %s\n"), strerror(errno)); 9116 return (-1); 9117 } 9118 9119 str = cp + 2; 9120 *cp = ';'; 9121 9122 if (use_pbuf == 1) { 9123 if (*pbuf != '/') { 9124 /* relative linked to path */ 9125 9126 (void) getcwd(tempbuf, 9127 (sizeof (tempbuf))); 9128 (void) strncat(tempbuf, "/", 9129 MAXPATHLEN); 9130 (void) strncat(tempbuf, pbuf, 9131 MAXPATHLEN); 9132 } 9133 else 9134 (void) strcpy(tempbuf, pbuf); 9135 9136 } else if (*buf != '/') { 9137 /* got relative linked to path */ 9138 9139 (void) getcwd(tempbuf, 9140 (sizeof (tempbuf))); 9141 (void) strncat(tempbuf, "/", 9142 MAXPATHLEN); 9143 } else 9144 *tempbuf = '\0'; 9145 9146 (void) strncat(tempbuf, buf, MAXPATHLEN); 9147 *buf = '\0'; 9148 9149 if (blequal(&bslabel, &admin_high)) { 9150 bslabel = admin_low; 9151 } 9152 9153 9154 /* 9155 * Check for cross-zone symbolic links 9156 */ 9157 from_label = getlabelbypath(real_path); 9158 if (rpath_flag && (from_label != NULL) && 9159 !blequal(&bslabel, from_label)) { 9160 if ((zoneid = 9161 getzoneidbylabel(&bslabel)) == -1) { 9162 (void) fprintf(stderr, 9163 gettext("tar: can't get " 9164 "zone ID for %s\n"), 9165 tempbuf); 9166 return (-1); 9167 } 9168 if (zone_getattr(zoneid, ZONE_ATTR_NAME, 9169 &zonename, ZONENAME_MAX) == -1) { 9170 /* Badly configured zone info */ 9171 (void) fprintf(stderr, 9172 gettext("tar: can't get " 9173 "zonename for %s\n"), 9174 tempbuf); 9175 return (-1); 9176 } 9177 (void) strncpy(buf, AUTO_ZONE, 9178 MAXPATHLEN); 9179 (void) strncat(buf, "/", 9180 MAXPATHLEN); 9181 (void) strncat(buf, zonename, 9182 MAXPATHLEN); 9183 } 9184 if (from_label != NULL) 9185 free(from_label); 9186 (void) strncat(buf, tempbuf, MAXPATHLEN); 9187 break; 9188 } 9189 mld_flag = 0; 9190 break; 9191 9192 case PATH_TYPE: 9193 9194 str++; 9195 if ((cp = strstr(str, ";;")) != NULL) { 9196 *cp = '\0'; 9197 (void) strncat(buf, str, MAXPATHLEN); 9198 str = cp + 2; 9199 *cp = ';'; 9200 } 9201 break; 9202 9203 default: 9204 9205 (void) fprintf(stderr, gettext( 9206 "tar: error rebuilding path %s\n"), 9207 *namep); 9208 *buf = '\0'; 9209 str++; 9210 return (-1); 9211 } 9212 } 9213 9214 /* 9215 * Done for LK_COMP_TYPE 9216 */ 9217 9218 return (0); /* component path is rebuilt successfully */ 9219 9220 } /* end rebuild_lk_comp_path() */ 9221 9222 /* 9223 * Name: check_ext_attr() 9224 * 9225 * Description: 9226 * Check the extended attributes for a file being extracted. 9227 * The attributes being checked here are CMW labels. 9228 * ACLs are not set here because they are set by the 9229 * pflag in doxtract(). 9230 * 9231 * If the label doesn't match, return 0 9232 * else return 1 9233 */ 9234 static int 9235 check_ext_attr(char *filename) 9236 { 9237 bslabel_t currentlabel; /* label from zone */ 9238 9239 if (bltype(&bs_label, SUN_SL_UN)) { 9240 /* No label check possible */ 9241 return (0); 9242 } 9243 if (getlabel(filename, ¤tlabel) != 0) { 9244 (void) fprintf(stderr, 9245 gettext("tar: can't get label for " 9246 " %s, getlabel() error: %s\n"), 9247 filename, strerror(errno)); 9248 return (0); 9249 } else if ((blequal(¤tlabel, &bs_label)) == 0) { 9250 char *src_label = NULL; /* ascii label */ 9251 9252 /* get current src SL */ 9253 if (bsltos(&bs_label, &src_label, 0, 0) <= 0) { 9254 (void) fprintf(stderr, 9255 gettext("tar: can't interpret requested label for" 9256 " %s\n"), filename); 9257 } else { 9258 (void) fprintf(stderr, 9259 gettext("tar: can't apply label %s to %s\n"), 9260 src_label, filename); 9261 free(src_label); 9262 } 9263 (void) fprintf(stderr, 9264 gettext("tar: %s not restored\n"), filename); 9265 return (0); 9266 } 9267 return (1); 9268 9269 } /* end check_ext_attr */ 9270 9271 /* Compressing a tar file using compression method provided in 'opt' */ 9272 9273 static void 9274 compress_back() 9275 { 9276 pid_t pid; 9277 int status; 9278 int wret; 9279 struct stat statb; 9280 9281 if (vflag) { 9282 (void) fprintf(vfile, 9283 gettext("Compressing '%s' with '%s'...\n"), 9284 usefile, compress_opt); 9285 } 9286 if ((pid = fork()) == 0) { 9287 (void) execlp(compress_opt, compress_opt, 9288 usefile, NULL); 9289 } else if (pid == -1) { 9290 vperror(1, "%s", gettext("Could not fork")); 9291 } 9292 wait_pid(pid); 9293 if (suffix == 0) { 9294 (void) rename(tfname, usefile); 9295 } 9296 } 9297 9298 /* The magic numbers from /etc/magic */ 9299 9300 #define GZIP_MAGIC "\037\213" 9301 #define BZIP_MAGIC "BZh" 9302 #define COMP_MAGIC "\037\235" 9303 9304 void 9305 check_compression() 9306 { 9307 char magic[2]; 9308 char buf[16]; 9309 FILE *fp; 9310 9311 if ((fp = fopen(usefile, "r")) != NULL) { 9312 (void) fread(buf, sizeof (char), 6, fp); 9313 magic[0] = buf[0]; 9314 magic[1] = buf[1]; 9315 (void) fclose(fp); 9316 } 9317 9318 if (memcmp(magic, GZIP_MAGIC, 2) == 0) { 9319 if (xflag || tflag) { 9320 compress_opt = compress_malloc(strlen(GZCAT) + 1); 9321 (void) strcpy(compress_opt, GZCAT); 9322 } else if (uflag || rflag) { 9323 compress_opt = compress_malloc(strlen(GZIP) + 1); 9324 (void) strcpy(compress_opt, GZIP); 9325 } 9326 } else if (memcmp(magic, BZIP_MAGIC, 2) == 0) { 9327 if (xflag || tflag) { 9328 compress_opt = compress_malloc(strlen(BZCAT) + 1); 9329 (void) strcpy(compress_opt, BZCAT); 9330 } else if (uflag || rflag) { 9331 compress_opt = compress_malloc(strlen(BZIP) + 1); 9332 (void) strcpy(compress_opt, BZIP); 9333 } 9334 } else if (memcmp(magic, COMP_MAGIC, 2) == 0) { 9335 if (xflag || tflag) { 9336 compress_opt = compress_malloc(strlen(ZCAT) + 1); 9337 (void) strcpy(compress_opt, ZCAT); 9338 } else if (uflag || rflag) { 9339 compress_opt = compress_malloc(strlen(COMPRESS) + 1); 9340 (void) strcpy(compress_opt, COMPRESS); 9341 } 9342 } 9343 } 9344 9345 char * 9346 add_suffix() 9347 { 9348 (void) strcpy(tfname, usefile); 9349 if (strcmp(compress_opt, GZIP) == 0) { 9350 if ((suffix = gz_suffix()) == NULL) { 9351 strlcat(tfname, gsuffix[0], sizeof (tfname)); 9352 return (gsuffix[0]); 9353 } 9354 } else if (strcmp(compress_opt, COMPRESS) == 0) { 9355 if ((suffix = gz_suffix()) == NULL) { 9356 strlcat(tfname, gsuffix[6], sizeof (tfname)); 9357 return (gsuffix[6]); 9358 } 9359 } else if (strcmp(compress_opt, BZIP) == 0) { 9360 if ((suffix = bz_suffix()) == NULL) { 9361 strlcat(tfname, bsuffix[0], sizeof (tfname)); 9362 return (bsuffix[0]); 9363 } 9364 } 9365 return (NULL); 9366 } 9367 9368 /* Decompressing a tar file using compression method from the file type */ 9369 void 9370 decompress_file(void) 9371 { 9372 pid_t pid; 9373 int status; 9374 char cmdstr[PATH_MAX]; 9375 char fname[PATH_MAX]; 9376 char *added_suffix; 9377 9378 9379 added_suffix = add_suffix(); 9380 if (added_suffix != NULL) { 9381 (void) rename(usefile, tfname); 9382 } 9383 if ((pid = fork()) == 0) { 9384 if (vflag) { 9385 (void) fprintf(vfile, 9386 gettext("Decompressing '%s' with " 9387 "'%s'...\n"), usefile, compress_opt); 9388 } 9389 (void) execlp(compress_opt, compress_opt, "-df", 9390 tfname, NULL); 9391 vperror(1, gettext("Could not exec %s"), compress_opt); 9392 } else if (pid == -1) { 9393 vperror(1, gettext("Could not fork")); 9394 } 9395 wait_pid(pid); 9396 if (suffix != NULL) { 9397 /* restore the file name - original file was without suffix */ 9398 *(usefile + strlen(usefile) - strlen(suffix)) = '\0'; 9399 } 9400 } 9401 9402 /* Set the archive for writing and then compress the archive */ 9403 pid_t 9404 compress_file(void) 9405 { 9406 int fd[2]; 9407 pid_t pid; 9408 9409 if (vflag) { 9410 (void) fprintf(vfile, gettext("Compressing '%s' with " 9411 "'%s'...\n"), usefile, compress_opt); 9412 } 9413 9414 if (pipe(fd) < 0) { 9415 vperror(1, gettext("Could not create pipe")); 9416 } 9417 if (pid = fork() > 0) { 9418 mt = fd[1]; 9419 (void) close(fd[0]); 9420 return (pid); 9421 } 9422 /* child */ 9423 (void) dup2(fd[0], STDIN_FILENO); 9424 (void) close(fd[1]); 9425 (void) dup2(mt, STDOUT_FILENO); 9426 (void) execlp(compress_opt, compress_opt, NULL); 9427 vperror(1, gettext("Could not exec %s"), compress_opt); 9428 return (0); /*NOTREACHED*/ 9429 } 9430 9431 pid_t 9432 uncompress_file(void) 9433 { 9434 int fd[2]; 9435 pid_t pid; 9436 9437 if (vflag) { 9438 (void) fprintf(vfile, gettext("Decompressing '%s' with " 9439 "'%s'...\n"), usefile, compress_opt); 9440 } 9441 9442 if (pipe(fd) < 0) { 9443 vperror(1, gettext("Could not create pipe")); 9444 } 9445 if (pid = fork() > 0) { 9446 mt = fd[0]; 9447 (void) close(fd[1]); 9448 return (pid); 9449 } 9450 /* child */ 9451 (void) dup2(fd[1], STDOUT_FILENO); 9452 (void) close(fd[0]); 9453 (void) dup2(mt, STDIN_FILENO); 9454 (void) execlp(compress_opt, compress_opt, NULL); 9455 vperror(1, gettext("Could not exec %s"), compress_opt); 9456 return (0); /*NOTREACHED*/ 9457 } 9458 9459 /* Checking valid 'bzip2' suffix */ 9460 char * 9461 bz_suffix() 9462 { 9463 int i; 9464 int slen; 9465 int nlen = strlen(usefile); 9466 9467 for (i = 0; i < BS; i++) { 9468 slen = strlen(bsuffix[i]); 9469 if (nlen < slen) 9470 return (NULL); 9471 if (strcmp(usefile + nlen - slen, bsuffix[i]) == 0) 9472 return (bsuffix[i]); 9473 } 9474 return (NULL); 9475 } 9476 9477 /* Checking valid 'gzip' suffix */ 9478 char * 9479 gz_suffix() 9480 { 9481 int i; 9482 int slen; 9483 int nlen = strlen(usefile); 9484 9485 for (i = 0; i < GS; i++) { 9486 slen = strlen(gsuffix[i]); 9487 if (nlen < slen) 9488 return (NULL); 9489 if (strcmp(usefile + nlen - slen, gsuffix[i]) == 0) 9490 return (gsuffix[i]); 9491 } 9492 return (NULL); 9493 } 9494 9495 void * 9496 compress_malloc(size_t size) 9497 { 9498 void *opt; 9499 9500 if ((opt = malloc(size)) == NULL) { 9501 vperror(1, "%s", 9502 gettext("Could not allocate compress buffer\n")); 9503 } 9504 return (opt); 9505 } 9506 9507 void 9508 wait_pid(pid_t pid) 9509 { 9510 int status; 9511 9512 while (waitpid(pid, &status, 0) == -1 && errno == EINTR) 9513 ; 9514 } 9515