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