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