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