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