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