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