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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* Copyright (c) 1987, 1988 Microsoft Corporation */ 30 /* All Rights Reserved */ 31 32 /* 33 * Portions of this source code were derived from Berkeley 4.3 BSD 34 * under license from the Regents of the University of California. 35 */ 36 37 #include <unistd.h> 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 #include <sys/mkdev.h> 42 #include <sys/wait.h> 43 #include <dirent.h> 44 #include <errno.h> 45 #include <stdio.h> 46 #include <signal.h> 47 #include <ctype.h> 48 #include <locale.h> 49 #include <nl_types.h> 50 #include <langinfo.h> 51 #include <pwd.h> 52 #include <grp.h> 53 #include <fcntl.h> 54 #include <string.h> 55 #include <malloc.h> 56 #include <time.h> 57 #include <utime.h> 58 #include <stdlib.h> 59 #include <stdarg.h> 60 #include <widec.h> 61 #include <sys/mtio.h> 62 #include <sys/acl.h> 63 #include <strings.h> 64 #include <deflt.h> 65 #include <limits.h> 66 #include <iconv.h> 67 #include <assert.h> 68 #include <libgen.h> 69 #include <libintl.h> 70 #include <aclutils.h> 71 #include <libnvpair.h> 72 #include <archives.h> 73 74 #if defined(__SunOS_5_6) || defined(__SunOS_5_7) 75 extern int defcntl(); 76 #endif 77 #if defined(_PC_SATTR_ENABLED) 78 #include <attr.h> 79 #include <libcmdutils.h> 80 #endif 81 82 /* Trusted Extensions */ 83 #include <zone.h> 84 #include <tsol/label.h> 85 #include <sys/tsol/label_macro.h> 86 87 #include "getresponse.h" 88 /* 89 * Source compatibility 90 */ 91 92 /* 93 * These constants come from archives.h and sys/fcntl.h 94 * and were introduced by the extended attributes project 95 * in Solaris 9. 96 */ 97 #if !defined(O_XATTR) 98 #define AT_SYMLINK_NOFOLLOW 0x1000 99 #define AT_REMOVEDIR 0x1 100 #define AT_FDCWD 0xffd19553 101 #define _XATTR_HDRTYPE 'E' 102 static int attropen(); 103 static int fstatat(); 104 static int renameat(); 105 static int unlinkat(); 106 static int openat(); 107 static int fchownat(); 108 static int futimesat(); 109 #endif 110 111 /* 112 * Compiling with -D_XPG4_2 gets this but produces other problems, so 113 * instead of including sys/time.h and compiling with -D_XPG4_2, I'm 114 * explicitly doing the declaration here. 115 */ 116 int utimes(const char *path, const struct timeval timeval_ptr[]); 117 118 #ifndef MINSIZE 119 #define MINSIZE 250 120 #endif 121 #define DEF_FILE "/etc/default/tar" 122 123 #define min(a, b) ((a) < (b) ? (a) : (b)) 124 #define max(a, b) ((a) > (b) ? (a) : (b)) 125 126 /* -DDEBUG ONLY for debugging */ 127 #ifdef DEBUG 128 #undef DEBUG 129 #define DEBUG(a, b, c)\ 130 (void) fprintf(stderr, "DEBUG - "), (void) fprintf(stderr, a, b, c) 131 #endif 132 133 #define TBLOCK 512 /* tape block size--should be universal */ 134 135 #ifdef BSIZE 136 #define SYS_BLOCK BSIZE /* from sys/param.h: secondary block size */ 137 #else /* BSIZE */ 138 #define SYS_BLOCK 512 /* default if no BSIZE in param.h */ 139 #endif /* BSIZE */ 140 141 #define NBLOCK 20 142 #define NAMSIZ 100 143 #define PRESIZ 155 144 #define MAXNAM 256 145 #define MODEMASK 0777777 /* file creation mode mask */ 146 #define POSIXMODES 07777 /* mask for POSIX mode bits */ 147 #define MAXEXT 9 /* reasonable max # extents for a file */ 148 #define EXTMIN 50 /* min blks left on floppy to split a file */ 149 150 /* max value dblock.dbuf.efsize can store */ 151 #define TAR_EFSIZE_MAX 0777777777 152 153 /* 154 * Symbols which specify the values at which the use of the 'E' function 155 * modifier is required to properly store a file. 156 * 157 * TAR_OFFSET_MAX - the largest file size we can archive 158 * OCTAL7CHAR - the limit for ustar gid, uid, dev 159 */ 160 161 #ifdef XHDR_DEBUG 162 /* tiny values which force the creation of extended header entries */ 163 #define TAR_OFFSET_MAX 9 164 #define OCTAL7CHAR 2 165 #else 166 /* normal values */ 167 #define TAR_OFFSET_MAX 077777777777ULL 168 #define OCTAL7CHAR 07777777 169 #endif 170 171 #define TBLOCKS(bytes) (((bytes) + TBLOCK - 1) / TBLOCK) 172 #define K(tblocks) ((tblocks+1)/2) /* tblocks to Kbytes for printing */ 173 174 #define MAXLEV (PATH_MAX / 2) 175 #define LEV0 1 176 #define SYMLINK_LEV0 0 177 178 #define TRUE 1 179 #define FALSE 0 180 181 #define XATTR_FILE 1 182 #define NORMAL_FILE 0 183 184 #define PUT_AS_LINK 1 185 #define PUT_NOTAS_LINK 0 186 187 #ifndef VIEW_READONLY 188 #define VIEW_READONLY "SUNWattr_ro" 189 #endif 190 191 #ifndef VIEW_READWRITE 192 #define VIEW_READWRITE "SUNWattr_rw" 193 #endif 194 195 #if _FILE_OFFSET_BITS == 64 196 #define FMT_off_t "lld" 197 #define FMT_off_t_o "llo" 198 #define FMT_blkcnt_t "lld" 199 #else 200 #define FMT_off_t "ld" 201 #define FMT_off_t_o "lo" 202 #define FMT_blkcnt_t "ld" 203 #endif 204 205 /* ACL support */ 206 207 static 208 struct sec_attr { 209 char attr_type; 210 char attr_len[7]; 211 char attr_info[1]; 212 } *attr; 213 214 #if defined(O_XATTR) 215 typedef enum { 216 ATTR_OK, 217 ATTR_SKIP, 218 ATTR_CHDIR_ERR, 219 ATTR_OPEN_ERR, 220 ATTR_XATTR_ERR, 221 ATTR_SATTR_ERR 222 } attr_status_t; 223 #endif 224 225 #if defined(O_XATTR) 226 typedef enum { 227 ARC_CREATE, 228 ARC_RESTORE 229 } arc_action_t; 230 #endif 231 232 typedef struct attr_data { 233 char *attr_parent; 234 char *attr_path; 235 int attr_parentfd; 236 int attr_rw_sysattr; 237 } attr_data_t; 238 239 /* 240 * 241 * Tar has been changed to support extended attributes. 242 * 243 * As part of this change tar now uses the new *at() syscalls 244 * such as openat, fchownat(), unlinkat()... 245 * 246 * This was done so that attributes can be handled with as few code changes 247 * as possible. 248 * 249 * What this means is that tar now opens the directory that a file or directory 250 * resides in and then performs *at() functions to manipulate the entry. 251 * 252 * For example a new file is now created like this: 253 * 254 * dfd = open(<some dir path>) 255 * fd = openat(dfd, <name>,....); 256 * 257 * or in the case of an extended attribute 258 * 259 * dfd = attropen(<pathname>, ".", ....) 260 * 261 * Once we have a directory file descriptor all of the *at() functions can 262 * be applied to it. 263 * 264 * unlinkat(dfd, <component name>,...) 265 * fchownat(dfd, <component name>,..) 266 * 267 * This works for both normal namespace files and extended attribute file 268 * 269 */ 270 271 /* 272 * 273 * Extended attribute Format 274 * 275 * Extended attributes are stored in two pieces. 276 * 1. An attribute header which has information about 277 * what file the attribute is for and what the attribute 278 * is named. 279 * 2. The attribute record itself. Stored as a normal file type 280 * of entry. 281 * Both the header and attribute record have special modes/typeflags 282 * associated with them. 283 * 284 * The names of the header in the archive look like: 285 * /dev/null/attr.hdr 286 * 287 * The name of the attribute looks like: 288 * /dev/null/attr 289 * 290 * This is done so that an archiver that doesn't understand these formats 291 * can just dispose of the attribute records. 292 * 293 * The format is composed of a fixed size header followed 294 * by a variable sized xattr_buf. If the attribute is a hard link 295 * to another attribute then another xattr_buf section is included 296 * for the link. 297 * 298 * The xattr_buf is used to define the necessary "pathing" steps 299 * to get to the extended attribute. This is necessary to support 300 * a fully recursive attribute model where an attribute may itself 301 * have an attribute. 302 * 303 * The basic layout looks like this. 304 * 305 * -------------------------------- 306 * | | 307 * | xattr_hdr | 308 * | | 309 * -------------------------------- 310 * -------------------------------- 311 * | | 312 * | xattr_buf | 313 * | | 314 * -------------------------------- 315 * -------------------------------- 316 * | | 317 * | (optional link info) | 318 * | | 319 * -------------------------------- 320 * -------------------------------- 321 * | | 322 * | attribute itself | 323 * | stored as normal tar | 324 * | or cpio data with | 325 * | special mode or | 326 * | typeflag | 327 * | | 328 * -------------------------------- 329 * 330 */ 331 332 /* 333 * xattrhead is a pointer to the xattr_hdr 334 * 335 * xattrp is a pointer to the xattr_buf structure 336 * which contains the "pathing" steps to get to attributes 337 * 338 * xattr_linkp is a pointer to another xattr_buf structure that is 339 * only used when an attribute is actually linked to another attribute 340 * 341 */ 342 343 static struct xattr_hdr *xattrhead; 344 static struct xattr_buf *xattrp; 345 static struct xattr_buf *xattr_linkp; /* pointer to link info, if any */ 346 static char *xattrapath; /* attribute name */ 347 static char *xattr_linkaname; /* attribute attribute is linked to */ 348 static char Hiddendir; /* are we processing hidden xattr dir */ 349 static char xattrbadhead; 350 351 /* Was statically allocated tbuf[NBLOCK] */ 352 static 353 union hblock { 354 char dummy[TBLOCK]; 355 struct header { 356 char name[NAMSIZ]; /* If non-null prefix, path is */ 357 /* <prefix>/<name>; otherwise */ 358 /* <name> */ 359 char mode[8]; 360 char uid[8]; 361 char gid[8]; 362 char size[12]; /* size of this extent if file split */ 363 char mtime[12]; 364 char chksum[8]; 365 char typeflag; 366 char linkname[NAMSIZ]; 367 char magic[6]; 368 char version[2]; 369 char uname[32]; 370 char gname[32]; 371 char devmajor[8]; 372 char devminor[8]; 373 char prefix[PRESIZ]; /* Together with "name", the path of */ 374 /* the file: <prefix>/<name> */ 375 char extno; /* extent #, null if not split */ 376 char extotal; /* total extents */ 377 char efsize[10]; /* size of entire file */ 378 } dbuf; 379 } dblock, *tbuf, xhdr_buf; 380 381 static 382 struct xtar_hdr { 383 uid_t x_uid, /* Uid of file */ 384 x_gid; /* Gid of file */ 385 major_t x_devmajor; /* Device major node */ 386 minor_t x_devminor; /* Device minor node */ 387 off_t x_filesz; /* Length of file */ 388 char *x_uname, /* Pointer to name of user */ 389 *x_gname, /* Pointer to gid of user */ 390 *x_linkpath, /* Path for a hard/symbolic link */ 391 *x_path; /* Path of file */ 392 timestruc_t x_mtime; /* Seconds and nanoseconds */ 393 } Xtarhdr; 394 395 static 396 struct gen_hdr { 397 ulong_t g_mode; /* Mode of file */ 398 uid_t g_uid, /* Uid of file */ 399 g_gid; /* Gid of file */ 400 off_t g_filesz; /* Length of file */ 401 time_t g_mtime; /* Modification time */ 402 uint_t g_cksum; /* Checksum of file */ 403 ulong_t g_devmajor, /* File system of file */ 404 g_devminor; /* Major/minor of special files */ 405 } Gen; 406 407 static 408 struct linkbuf { 409 ino_t inum; 410 dev_t devnum; 411 int count; 412 char pathname[MAXNAM+1]; /* added 1 for last NULL */ 413 char attrname[MAXNAM+1]; 414 struct linkbuf *nextp; 415 } *ihead; 416 417 /* see comments before build_table() */ 418 #define TABLE_SIZE 512 419 typedef struct file_list { 420 char *name; /* Name of file to {in,ex}clude */ 421 struct file_list *next; /* Linked list */ 422 } file_list_t; 423 static file_list_t *exclude_tbl[TABLE_SIZE], 424 *include_tbl[TABLE_SIZE]; 425 426 static int append_secattr(char **, int *, int, char *, char); 427 static void write_ancillary(union hblock *, char *, int, char); 428 429 static void add_file_to_table(file_list_t *table[], char *str); 430 static void assert_string(char *s, char *msg); 431 static int istape(int fd, int type); 432 static void backtape(void); 433 static void build_table(file_list_t *table[], char *file); 434 static int check_prefix(char **namep, char **dirp, char **compp); 435 static void closevol(void); 436 static void copy(void *dst, void *src); 437 static int convtoreg(off_t); 438 static void delete_target(int fd, char *comp, char *namep); 439 static void doDirTimes(char *name, timestruc_t modTime); 440 static void done(int n); 441 static void dorep(char *argv[]); 442 #ifdef _iBCS2 443 static void dotable(char *argv[], int cnt); 444 static void doxtract(char *argv[], int cnt); 445 #else 446 static void dotable(char *argv[]); 447 static void doxtract(char *argv[]); 448 #endif 449 static void fatal(char *format, ...); 450 static void vperror(int exit_status, char *fmt, ...); 451 static void flushtape(void); 452 static void getdir(void); 453 static void *getmem(size_t); 454 static void longt(struct stat *st, char aclchar); 455 static void load_info_from_xtarhdr(u_longlong_t flag, struct xtar_hdr *xhdrp); 456 static int makeDir(char *name); 457 static void mterr(char *operation, int i, int exitcode); 458 static void newvol(void); 459 static void passtape(void); 460 static void putempty(blkcnt_t n); 461 static int putfile(char *longname, char *shortname, char *parent, 462 attr_data_t *attrinfo, int filetype, int lev, int symlink_lev); 463 static void readtape(char *buffer); 464 static void seekdisk(blkcnt_t blocks); 465 static void setPathTimes(int dirfd, char *path, timestruc_t modTime); 466 static void setbytes_to_skip(struct stat *st, int err); 467 static void splitfile(char *longname, int ifd, char *name, 468 char *prefix, int filetype); 469 static void tomodes(struct stat *sp); 470 static void usage(void); 471 static int xblocks(int issysattr, off_t bytes, int ofile); 472 static int xsfile(int issysattr, int ofd); 473 static void resugname(int dirfd, char *name, int symflag); 474 static int bcheck(char *bstr); 475 static int checkdir(char *name); 476 static int checksum(union hblock *dblockp); 477 #ifdef EUC 478 static int checksum_signed(union hblock *dblockp); 479 #endif /* EUC */ 480 static int checkupdate(char *arg); 481 static int checkw(char c, char *name); 482 static int cmp(char *b, char *s, int n); 483 static int defset(char *arch); 484 static int endtape(void); 485 static int is_in_table(file_list_t *table[], char *str); 486 static int notsame(void); 487 static int is_prefix(char *s1, char *s2); 488 static int response(void); 489 static int build_dblock(const char *, const char *, const char, 490 const int filetype, const struct stat *, const dev_t, const char *); 491 static unsigned int hash(char *str); 492 493 #ifdef _iBCS2 494 static void initarg(char *argv[], char *file); 495 static char *nextarg(); 496 #endif 497 static blkcnt_t kcheck(char *kstr); 498 static off_t bsrch(char *s, int n, off_t l, off_t h); 499 static void onintr(int sig); 500 static void onquit(int sig); 501 static void onhup(int sig); 502 static uid_t getuidbyname(char *); 503 static gid_t getgidbyname(char *); 504 static char *getname(gid_t); 505 static char *getgroup(gid_t); 506 static int checkf(char *name, int mode, int howmuch); 507 static int writetbuf(char *buffer, int n); 508 static int wantit(char *argv[], char **namep, char **dirp, char **comp, 509 attr_data_t **attrinfo); 510 static void append_ext_attr(char *shortname, char **secinfo, int *len); 511 static int get_xdata(void); 512 static void gen_num(const char *keyword, const u_longlong_t number); 513 static void gen_date(const char *keyword, const timestruc_t time_value); 514 static void gen_string(const char *keyword, const char *value); 515 static void get_xtime(char *value, timestruc_t *xtime); 516 static int chk_path_build(char *name, char *longname, char *linkname, 517 char *prefix, char type, int filetype); 518 static int gen_utf8_names(const char *filename); 519 static int utf8_local(char *option, char **Xhdr_ptrptr, char *target, 520 const char *src, int max_val); 521 static int local_utf8(char **Xhdr_ptrptr, char *target, const char *src, 522 iconv_t iconv_cd, int xhdrflg, int max_val); 523 static int c_utf8(char *target, const char *source); 524 static int getstat(int dirfd, char *longname, char *shortname, 525 char *attrparent); 526 static void xattrs_put(char *, char *, char *, char *); 527 static void prepare_xattr(char **, char *, char *, 528 char, struct linkbuf *, int *); 529 static int put_link(char *name, char *longname, char *component, 530 char *longattrname, char *prefix, int filetype, char typeflag); 531 static int put_extra_attributes(char *longname, char *shortname, 532 char *longattrname, char *prefix, int filetype, char typeflag); 533 static int put_xattr_hdr(char *longname, char *shortname, char *longattrname, 534 char *prefix, int typeflag, int filetype, struct linkbuf *lp); 535 static int read_xattr_hdr(attr_data_t **attrinfo); 536 537 /* Trusted Extensions */ 538 #define AUTO_ZONE "/zone" 539 540 static void extract_attr(char **file_ptr, struct sec_attr *); 541 static int check_ext_attr(char *filename); 542 static void rebuild_comp_path(char *str, char **namep); 543 static int rebuild_lk_comp_path(char *str, char **namep); 544 545 static void get_parent(char *path, char *dir); 546 static char *get_component(char *path); 547 static int retry_open_attr(int pdirfd, int cwd, char *dirp, char *pattr, 548 char *name, int oflag, mode_t mode); 549 static char *skipslashes(char *string, char *start); 550 static void chop_endslashes(char *path); 551 552 static struct stat stbuf; 553 554 static char *myname; 555 static int checkflag = 0; 556 #ifdef _iBCS2 557 static int Fileflag; 558 char *sysv3_env; 559 #endif 560 static int Xflag, Fflag, iflag, hflag, Bflag, Iflag; 561 static int rflag, xflag, vflag, tflag, mt, cflag, mflag, pflag; 562 static int uflag; 563 static int eflag, errflag, qflag; 564 static int oflag; 565 static int bflag, kflag, Aflag; 566 static int Pflag; /* POSIX conformant archive */ 567 static int Eflag; /* Allow files greater than 8GB */ 568 static int atflag; /* traverse extended attributes */ 569 static int saflag; /* traverse extended sys attributes */ 570 static int Dflag; /* Data change flag */ 571 /* Trusted Extensions */ 572 static int Tflag; /* Trusted Extensions attr flags */ 573 static int dir_flag; /* for attribute extract */ 574 static int mld_flag; /* for attribute extract */ 575 static char *orig_namep; /* original namep - unadorned */ 576 static int rpath_flag; /* MLD real path is rebuilt */ 577 static char real_path[MAXPATHLEN]; /* MLD real path */ 578 static int lk_rpath_flag; /* linked to real path is rebuilt */ 579 static char lk_real_path[MAXPATHLEN]; /* linked real path */ 580 static bslabel_t bs_label; /* for attribute extract */ 581 static bslabel_t admin_low; 582 static bslabel_t admin_high; 583 static int ignored_aprivs = 0; 584 static int ignored_fprivs = 0; 585 static int ignored_fattrs = 0; 586 587 static int term, chksum, wflag, 588 first = TRUE, defaults_used = FALSE, linkerrok; 589 static blkcnt_t recno; 590 static int freemem = 1; 591 static int nblock = NBLOCK; 592 static int Errflg = 0; 593 static int exitflag = 0; 594 595 static dev_t mt_dev; /* device containing output file */ 596 static ino_t mt_ino; /* inode number of output file */ 597 static int mt_devtype; /* dev type of archive, from stat structure */ 598 599 static int update = 1; /* for `open' call */ 600 601 static off_t low; 602 static off_t high; 603 604 static FILE *tfile; 605 static FILE *vfile = stdout; 606 static char tname[] = "/tmp/tarXXXXXX"; 607 static char archive[] = "archive0="; 608 static char *Xfile; 609 static char *usefile; 610 static char *Filefile; 611 612 static int mulvol; /* multi-volume option selected */ 613 static blkcnt_t blocklim; /* number of blocks to accept per volume */ 614 static blkcnt_t tapepos; /* current block number to be written */ 615 static int NotTape; /* true if tape is a disk */ 616 static int dumping; /* true if writing a tape or other archive */ 617 static int extno; /* number of extent: starts at 1 */ 618 static int extotal; /* total extents in this file */ 619 static off_t extsize; /* size of current extent during extraction */ 620 static ushort_t Oumask = 0; /* old umask value */ 621 static int is_posix; /* true if archive we're reading is POSIX-conformant */ 622 static const char *magic_type = "ustar"; 623 static size_t xrec_size = 8 * PATH_MAX; /* extended rec initial size */ 624 static char *xrec_ptr; 625 static off_t xrec_offset = 0; 626 static int Xhdrflag; 627 static int charset_type = 0; 628 629 static u_longlong_t xhdr_flgs; /* Bits set determine which items */ 630 /* need to be in extended header. */ 631 #define _X_DEVMAJOR 0x1 632 #define _X_DEVMINOR 0x2 633 #define _X_GID 0x4 634 #define _X_GNAME 0x8 635 #define _X_LINKPATH 0x10 636 #define _X_PATH 0x20 637 #define _X_SIZE 0x40 638 #define _X_UID 0x80 639 #define _X_UNAME 0x100 640 #define _X_ATIME 0x200 641 #define _X_CTIME 0x400 642 #define _X_MTIME 0x800 643 #define _X_XHDR 0x1000 /* Bit flag that determines whether 'X' */ 644 /* typeflag was followed by 'A' or non 'A' */ 645 /* typeflag. */ 646 #define _X_LAST 0x40000000 647 648 #define PID_MAX_DIGITS (10 * sizeof (pid_t) / 4) 649 #define TIME_MAX_DIGITS (10 * sizeof (time_t) / 4) 650 #define LONG_MAX_DIGITS (10 * sizeof (long) / 4) 651 #define ULONGLONG_MAX_DIGITS (10 * sizeof (u_longlong_t) / 4) 652 /* 653 * UTF_8 encoding requires more space than the current codeset equivalent. 654 * Currently a factor of 2-3 would suffice, but it is possible for a factor 655 * of 6 to be needed in the future, so for saftey, we use that here. 656 */ 657 #define UTF_8_FACTOR 6 658 659 static u_longlong_t xhdr_count = 0; 660 static char xhdr_dirname[PRESIZ + 1]; 661 static char pidchars[PID_MAX_DIGITS + 1]; 662 static char *tchar = ""; /* null linkpath */ 663 664 static char local_path[UTF_8_FACTOR * PATH_MAX + 1]; 665 static char local_linkpath[UTF_8_FACTOR * PATH_MAX + 1]; 666 static char local_gname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 667 static char local_uname[UTF_8_FACTOR * _POSIX_NAME_MAX + 1]; 668 669 /* 670 * The following mechanism is provided to allow us to debug tar in complicated 671 * situations, like when it is part of a pipe. The idea is that you compile 672 * with -DWAITAROUND defined, and then add the 'z' function modifier to the 673 * target tar invocation, eg. "tar czf tarfile file". If stderr is available, 674 * it will tell you to which pid to attach the debugger; otherwise, use ps to 675 * find it. Attach to the process from the debugger, and, *PRESTO*, you are 676 * there! 677 * 678 * Simply assign "waitaround = 0" once you attach to the process, and then 679 * proceed from there as usual. 680 */ 681 682 #ifdef WAITAROUND 683 int waitaround = 0; /* wait for rendezvous with the debugger */ 684 #endif 685 686 687 int 688 main(int argc, char *argv[]) 689 { 690 char *cp; 691 char *tmpdirp; 692 pid_t thispid; 693 694 #ifdef _iBCS2 695 int tbl_cnt = 0; 696 sysv3_env = getenv("SYSV3"); 697 #endif 698 (void) setlocale(LC_ALL, ""); 699 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 700 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 701 #endif 702 (void) textdomain(TEXT_DOMAIN); 703 if (argc < 2) 704 usage(); 705 706 tfile = NULL; 707 if ((myname = strdup(argv[0])) == NULL) { 708 (void) fprintf(stderr, gettext( 709 "tar: cannot allocate program name\n")); 710 exit(1); 711 } 712 713 if (init_yes() < 0) { 714 (void) fprintf(stderr, gettext(ERR_MSG_INIT_YES), 715 strerror(errno)); 716 exit(2); 717 } 718 719 /* 720 * For XPG4 compatibility, we must be able to accept the "--" 721 * argument normally recognized by getopt; it is used to delimit 722 * the end opt the options section, and so can only appear in 723 * the position of the first argument. We simply skip it. 724 */ 725 726 if (strcmp(argv[1], "--") == 0) { 727 argv++; 728 argc--; 729 if (argc < 3) 730 usage(); 731 } 732 733 argv[argc] = NULL; 734 argv++; 735 736 /* 737 * Set up default values. 738 * Search the operand string looking for the first digit or an 'f'. 739 * If you find a digit, use the 'archive#' entry in DEF_FILE. 740 * If 'f' is given, bypass looking in DEF_FILE altogether. 741 * If no digit or 'f' is given, still look in DEF_FILE but use '0'. 742 */ 743 if ((usefile = getenv("TAPE")) == (char *)NULL) { 744 for (cp = *argv; *cp; ++cp) 745 if (isdigit(*cp) || *cp == 'f') 746 break; 747 if (*cp != 'f') { 748 archive[7] = (*cp)? *cp: '0'; 749 if (!(defaults_used = defset(archive))) { 750 usefile = NULL; 751 nblock = 1; 752 blocklim = 0; 753 NotTape = 0; 754 } 755 } 756 } 757 758 for (cp = *argv++; *cp; cp++) 759 switch (*cp) { 760 #ifdef WAITAROUND 761 case 'z': 762 /* rendezvous with the debugger */ 763 waitaround = 1; 764 break; 765 #endif 766 case 'f': 767 assert_string(*argv, gettext( 768 "tar: tarfile must be specified with 'f' " 769 "function modifier\n")); 770 usefile = *argv++; 771 break; 772 case 'F': 773 #ifdef _iBCS2 774 if (sysv3_env) { 775 assert_string(*argv, gettext( 776 "tar: 'F' requires a file name\n")); 777 Filefile = *argv++; 778 Fileflag++; 779 } else 780 #endif /* _iBCS2 */ 781 Fflag++; 782 break; 783 case 'c': 784 cflag++; 785 rflag++; 786 update = 1; 787 break; 788 #if defined(O_XATTR) 789 case '@': 790 atflag++; 791 break; 792 #endif /* O_XATTR */ 793 #if defined(_PC_SATTR_ENABLED) 794 case '/': 795 saflag++; 796 break; 797 #endif /* _PC_SATTR_ENABLED */ 798 case 'u': 799 uflag++; /* moved code after signals caught */ 800 rflag++; 801 update = 2; 802 break; 803 case 'r': 804 rflag++; 805 update = 2; 806 break; 807 case 'v': 808 vflag++; 809 break; 810 case 'w': 811 wflag++; 812 break; 813 case 'x': 814 xflag++; 815 break; 816 case 'X': 817 assert_string(*argv, gettext( 818 "tar: exclude file must be specified with 'X' " 819 "function modifier\n")); 820 Xflag = 1; 821 Xfile = *argv++; 822 build_table(exclude_tbl, Xfile); 823 break; 824 case 't': 825 tflag++; 826 break; 827 case 'm': 828 mflag++; 829 break; 830 case 'p': 831 pflag++; 832 break; 833 case 'D': 834 Dflag++; 835 break; 836 case '-': 837 /* ignore this silently */ 838 break; 839 case '0': /* numeric entries used only for defaults */ 840 case '1': 841 case '2': 842 case '3': 843 case '4': 844 case '5': 845 case '6': 846 case '7': 847 break; 848 case 'b': 849 assert_string(*argv, gettext( 850 "tar: blocking factor must be specified " 851 "with 'b' function modifier\n")); 852 bflag++; 853 nblock = bcheck(*argv++); 854 break; 855 case 'q': 856 qflag++; 857 break; 858 case 'k': 859 assert_string(*argv, gettext( 860 "tar: size value must be specified with 'k' " 861 "function modifier\n")); 862 kflag++; 863 blocklim = kcheck(*argv++); 864 break; 865 case 'n': /* not a magtape (instead of 'k') */ 866 NotTape++; /* assume non-magtape */ 867 break; 868 case 'l': 869 linkerrok++; 870 break; 871 case 'e': 872 #ifdef _iBCS2 873 /* If sysv3 IS set, don't be as verbose */ 874 if (!sysv3_env) 875 #endif /* _iBCS2 */ 876 errflag++; 877 eflag++; 878 break; 879 case 'o': 880 oflag++; 881 break; 882 case 'h': 883 hflag++; 884 break; 885 case 'i': 886 iflag++; 887 break; 888 case 'B': 889 Bflag++; 890 break; 891 case 'P': 892 Pflag++; 893 break; 894 case 'E': 895 Eflag++; 896 Pflag++; /* Only POSIX archive made */ 897 break; 898 case 'T': 899 Tflag++; /* Handle Trusted Extensions attrs */ 900 pflag++; /* also set flag for ACL */ 901 break; 902 default: 903 (void) fprintf(stderr, gettext( 904 "tar: %c: unknown function modifier\n"), *cp); 905 usage(); 906 } 907 908 #ifdef _iBCS2 909 if (Xflag && Fileflag) { 910 (void) fprintf(stderr, gettext( 911 "tar: specify only one of X or F.\n")); 912 usage(); 913 } 914 #endif /* _iBCS2 */ 915 916 if (!rflag && !xflag && !tflag) 917 usage(); 918 if ((rflag && xflag) || (xflag && tflag) || (rflag && tflag)) { 919 (void) fprintf(stderr, gettext( 920 "tar: specify only one of [ctxru].\n")); 921 usage(); 922 } 923 /* Trusted Extensions attribute handling */ 924 if (Tflag && ((getzoneid() != GLOBAL_ZONEID) || 925 !is_system_labeled())) { 926 (void) fprintf(stderr, gettext( 927 "tar: the 'T' option is only available with " 928 "Trusted Extensions\nand must be run from " 929 "the global zone.\n")); 930 usage(); 931 } 932 if (cflag && *argv == NULL && Filefile == NULL) 933 fatal(gettext("Missing filenames")); 934 if (usefile == NULL) 935 fatal(gettext("device argument required")); 936 937 /* alloc a buffer of the right size */ 938 if ((tbuf = (union hblock *) 939 calloc(sizeof (union hblock) * nblock, sizeof (char))) == 940 (union hblock *)NULL) { 941 (void) fprintf(stderr, gettext( 942 "tar: cannot allocate physio buffer\n")); 943 exit(1); 944 } 945 946 if ((xrec_ptr = malloc(xrec_size)) == NULL) { 947 (void) fprintf(stderr, gettext( 948 "tar: cannot allocate extended header buffer\n")); 949 exit(1); 950 } 951 952 #ifdef WAITAROUND 953 if (waitaround) { 954 (void) fprintf(stderr, gettext("Rendezvous with tar on pid" 955 " %d\n"), getpid()); 956 957 while (waitaround) { 958 (void) sleep(10); 959 } 960 } 961 #endif 962 963 thispid = getpid(); 964 (void) sprintf(pidchars, "%ld", thispid); 965 thispid = strlen(pidchars); 966 967 if ((tmpdirp = getenv("TMPDIR")) == (char *)NULL) 968 (void) strcpy(xhdr_dirname, "/tmp"); 969 else { 970 /* 971 * Make sure that dir is no longer than what can 972 * fit in the prefix part of the header. 973 */ 974 if (strlen(tmpdirp) > (size_t)(PRESIZ - thispid - 12)) { 975 (void) strcpy(xhdr_dirname, "/tmp"); 976 if ((vflag > 0) && (Eflag > 0)) 977 (void) fprintf(stderr, gettext( 978 "Ignoring TMPDIR\n")); 979 } else 980 (void) strcpy(xhdr_dirname, tmpdirp); 981 } 982 (void) strcat(xhdr_dirname, "/PaxHeaders."); 983 (void) strcat(xhdr_dirname, pidchars); 984 985 if (rflag) { 986 if (cflag && tfile != NULL) 987 usage(); 988 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 989 (void) signal(SIGINT, onintr); 990 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 991 (void) signal(SIGHUP, onhup); 992 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 993 (void) signal(SIGQUIT, onquit); 994 if (uflag) { 995 int tnum; 996 if ((tnum = mkstemp(tname)) == -1) 997 vperror(1, "%s", tname); 998 if ((tfile = fdopen(tnum, "w")) == NULL) 999 vperror(1, "%s", tname); 1000 } 1001 if (strcmp(usefile, "-") == 0) { 1002 if (cflag == 0) 1003 fatal(gettext( 1004 "can only create standard output archives.")); 1005 vfile = stderr; 1006 mt = dup(1); 1007 ++bflag; 1008 } else { 1009 if (cflag) 1010 mt = open(usefile, 1011 O_RDWR|O_CREAT|O_TRUNC, 0666); 1012 else 1013 mt = open(usefile, O_RDWR); 1014 1015 if (mt < 0) { 1016 if (cflag == 0 || (mt = creat(usefile, 0666)) 1017 < 0) 1018 vperror(1, "%s", usefile); 1019 } 1020 } 1021 /* Get inode and device number of output file */ 1022 (void) fstat(mt, &stbuf); 1023 mt_ino = stbuf.st_ino; 1024 mt_dev = stbuf.st_dev; 1025 mt_devtype = stbuf.st_mode & S_IFMT; 1026 NotTape = !istape(mt, mt_devtype); 1027 1028 if (rflag && !cflag && (mt_devtype == S_IFIFO)) 1029 fatal(gettext("cannot append to pipe or FIFO.")); 1030 1031 if (Aflag && vflag) 1032 (void) printf( 1033 gettext("Suppressing absolute pathnames\n")); 1034 dorep(argv); 1035 } else if (xflag || tflag) { 1036 /* 1037 * for each argument, check to see if there is a "-I file" pair. 1038 * if so, move the 3rd argument into "-I"'s place, build_table() 1039 * using "file"'s name and increment argc one (the second 1040 * increment appears in the for loop) which removes the two 1041 * args "-I" and "file" from the argument vector. 1042 */ 1043 for (argc = 0; argv[argc]; argc++) { 1044 if (strcmp(argv[argc], "-I") == 0) { 1045 if (!argv[argc+1]) { 1046 (void) fprintf(stderr, gettext( 1047 "tar: missing argument for -I flag\n")); 1048 done(2); 1049 } else { 1050 Iflag = 1; 1051 argv[argc] = argv[argc+2]; 1052 build_table(include_tbl, argv[++argc]); 1053 #ifdef _iBCS2 1054 if (Fileflag) { 1055 (void) fprintf(stderr, gettext( 1056 "tar: only one of I or F.\n")); 1057 usage(); 1058 } 1059 #endif /* _iBCS2 */ 1060 1061 } 1062 } 1063 } 1064 if (strcmp(usefile, "-") == 0) { 1065 mt = dup(0); 1066 ++bflag; 1067 /* try to recover from short reads when reading stdin */ 1068 ++Bflag; 1069 } else if ((mt = open(usefile, 0)) < 0) 1070 vperror(1, "%s", usefile); 1071 1072 if (xflag) { 1073 if (Aflag && vflag) 1074 (void) printf(gettext( 1075 "Suppressing absolute pathnames.\n")); 1076 1077 #ifdef _iBCS2 1078 doxtract(argv, tbl_cnt); 1079 #else 1080 doxtract(argv); 1081 #endif 1082 } else if (tflag) 1083 1084 #ifdef _iBCS2 1085 dotable(argv, tbl_cnt); 1086 #else 1087 dotable(argv); 1088 #endif 1089 } 1090 else 1091 usage(); 1092 1093 done(Errflg); 1094 1095 /* Not reached: keep compiler quiet */ 1096 return (1); 1097 } 1098 1099 static void 1100 usage(void) 1101 { 1102 1103 #ifdef _iBCS2 1104 if (sysv3_env) { 1105 (void) fprintf(stderr, gettext( 1106 #if defined(O_XATTR) 1107 #if defined(_PC_SATTR_ENABLED) 1108 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@/[0-7]][bfFk][X...] " 1109 #else 1110 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw@[0-7]][bfFk][X...] " 1111 #endif /* _PC_SATTR_ENABLED */ 1112 #else 1113 "Usage: tar {c|r|t|u|x}[BDeEhilmnopPqTvw[0-7]][bfFk][X...] " 1114 #endif /* O_XATTR */ 1115 "[blocksize] [tarfile] [filename] [size] [exclude-file...] " 1116 "{file | -I include-file | -C directory file}...\n")); 1117 } else 1118 #endif /* _iBCS2 */ 1119 { 1120 (void) fprintf(stderr, gettext( 1121 #if defined(O_XATTR) 1122 #if defined(_PC_SATTR_ENABLED) 1123 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@/[0-7]][bfk][X...] " 1124 #else 1125 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] " 1126 #endif /* _PC_SATTR_ENABLED */ 1127 #else 1128 "Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw[0-7]][bfk][X...] " 1129 #endif /* O_XATTR */ 1130 "[blocksize] [tarfile] [size] [exclude-file...] " 1131 "{file | -I include-file | -C directory file}...\n")); 1132 } 1133 done(1); 1134 } 1135 1136 /* 1137 * dorep - do "replacements" 1138 * 1139 * Dorep is responsible for creating ('c'), appending ('r') 1140 * and updating ('u'); 1141 */ 1142 1143 static void 1144 dorep(char *argv[]) 1145 { 1146 char *cp, *cp2, *p; 1147 char wdir[PATH_MAX+2], tempdir[PATH_MAX+2], *parent; 1148 char file[PATH_MAX*2], origdir[PATH_MAX+1]; 1149 FILE *fp = (FILE *)NULL; 1150 FILE *ff = (FILE *)NULL; 1151 int archtype; 1152 int ret; 1153 1154 1155 if (!cflag) { 1156 xhdr_flgs = 0; 1157 getdir(); /* read header for next file */ 1158 if (Xhdrflag > 0) { 1159 if (!Eflag) 1160 fatal(gettext("Archive contains extended" 1161 " header. -E flag required.\n")); 1162 ret = get_xdata(); /* Get extended header items */ 1163 /* and regular header */ 1164 } else { 1165 if (Eflag) 1166 fatal(gettext("Archive contains no extended" 1167 " header. -E flag not allowed.\n")); 1168 } 1169 while (!endtape()) { /* changed from a do while */ 1170 setbytes_to_skip(&stbuf, ret); 1171 passtape(); /* skip the file data */ 1172 if (term) 1173 done(Errflg); /* received signal to stop */ 1174 xhdr_flgs = 0; 1175 getdir(); 1176 if (Xhdrflag > 0) 1177 ret = get_xdata(); 1178 } 1179 if (ret == 0) { 1180 if ((dblock.dbuf.typeflag != 'A') && 1181 (xhdr_flgs != 0)) { 1182 load_info_from_xtarhdr(xhdr_flgs, 1183 &Xtarhdr); 1184 xhdr_flgs |= _X_XHDR; 1185 } 1186 } 1187 backtape(); /* was called by endtape */ 1188 if (tfile != NULL) { 1189 char buf[200]; 1190 1191 (void) sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 " 1192 "!= prev {print; prev=$1}' %s >%sX;mv %sX %s", 1193 tname, tname, tname, tname, tname, tname); 1194 (void) fflush(tfile); 1195 (void) system(buf); 1196 (void) freopen(tname, "r", tfile); 1197 (void) fstat(fileno(tfile), &stbuf); 1198 high = stbuf.st_size; 1199 } 1200 } 1201 1202 dumping = 1; 1203 if (mulvol) { /* SP-1 */ 1204 if (nblock && (blocklim%nblock) != 0) 1205 fatal(gettext( 1206 "Volume size not a multiple of block size.")); 1207 blocklim -= 2; /* for trailer records */ 1208 if (vflag) 1209 (void) fprintf(vfile, gettext("Volume ends at %" 1210 FMT_blkcnt_t "K, blocking factor = %dK\n"), 1211 K((blocklim - 1)), K(nblock)); 1212 } 1213 1214 #ifdef _iBCS2 1215 if (Fileflag) { 1216 if (Filefile != NULL) { 1217 if ((ff = fopen(Filefile, "r")) == NULL) 1218 vperror(0, "%s", Filefile); 1219 } else { 1220 (void) fprintf(stderr, gettext( 1221 "tar: F requires a file name.\n")); 1222 usage(); 1223 } 1224 } 1225 #endif /* _iBCS2 */ 1226 1227 /* 1228 * Save the original directory before it gets 1229 * changed. 1230 */ 1231 if (getcwd(origdir, (PATH_MAX+1)) == NULL) { 1232 vperror(0, gettext("A parent directory cannot be read")); 1233 exit(1); 1234 } 1235 1236 (void) strcpy(wdir, origdir); 1237 1238 while ((*argv || fp || ff) && !term) { 1239 if (fp || (strcmp(*argv, "-I") == 0)) { 1240 #ifdef _iBCS2 1241 if (Fileflag) { 1242 (void) fprintf(stderr, gettext( 1243 "tar: only one of I or F.\n")); 1244 usage(); 1245 } 1246 #endif /* _iBCS2 */ 1247 if (fp == NULL) { 1248 if (*++argv == NULL) 1249 fatal(gettext( 1250 "missing file name for -I flag.")); 1251 else if ((fp = fopen(*argv++, "r")) == NULL) 1252 vperror(0, "%s", argv[-1]); 1253 continue; 1254 } else if ((fgets(file, PATH_MAX-1, fp)) == NULL) { 1255 (void) fclose(fp); 1256 fp = NULL; 1257 continue; 1258 } else { 1259 cp = cp2 = file; 1260 if ((p = strchr(cp2, '\n'))) 1261 *p = 0; 1262 } 1263 } else if ((strcmp(*argv, "-C") == 0) && argv[1]) { 1264 #ifdef _iBCS2 1265 if (Fileflag) { 1266 (void) fprintf(stderr, gettext( 1267 "tar: only one of F or C\n")); 1268 usage(); 1269 } 1270 #endif /* _iBCS2 */ 1271 1272 if (chdir(*++argv) < 0) 1273 vperror(0, gettext( 1274 "can't change directories to %s"), *argv); 1275 else 1276 (void) getcwd(wdir, (sizeof (wdir))); 1277 argv++; 1278 continue; 1279 #ifdef _iBCS2 1280 } else if (Fileflag && (ff != NULL)) { 1281 if ((fgets(file, PATH_MAX-1, ff)) == NULL) { 1282 (void) fclose(ff); 1283 ff = NULL; 1284 continue; 1285 } else { 1286 cp = cp2 = file; 1287 if (p = strchr(cp2, '\n')) 1288 *p = 0; 1289 } 1290 #endif /* _iBCS2 */ 1291 } else 1292 cp = cp2 = strcpy(file, *argv++); 1293 1294 /* 1295 * point cp2 to the last '/' in file, but not 1296 * to a trailing '/' 1297 */ 1298 for (; *cp; cp++) { 1299 if (*cp == '/') { 1300 while (*(cp+1) == '/') { 1301 ++cp; 1302 } 1303 if (*(cp+1) != '\0') { 1304 /* not trailing slash */ 1305 cp2 = cp; 1306 } 1307 } 1308 } 1309 if (cp2 != file) { 1310 *cp2 = '\0'; 1311 if (chdir(file) < 0) { 1312 vperror(0, gettext( 1313 "can't change directories to %s"), file); 1314 continue; 1315 } 1316 *cp2 = '/'; 1317 cp2++; 1318 } 1319 1320 parent = getcwd(tempdir, (sizeof (tempdir))); 1321 1322 archtype = putfile(file, cp2, parent, NULL, NORMAL_FILE, 1323 LEV0, SYMLINK_LEV0); 1324 1325 #if defined(O_XATTR) 1326 if (!exitflag) { 1327 if ((atflag || saflag) && 1328 (archtype == PUT_NOTAS_LINK)) { 1329 xattrs_put(file, cp2, parent, NULL); 1330 } 1331 } 1332 #endif 1333 1334 if (chdir(origdir) < 0) 1335 vperror(0, gettext("cannot change back?: %s"), origdir); 1336 1337 if (exitflag) { 1338 /* 1339 * If e function modifier has been specified 1340 * write the files (that are listed before the 1341 * file causing the error) to tape. exitflag is 1342 * used because only some of the error conditions 1343 * in putfile() recognize the e function modifier. 1344 */ 1345 break; 1346 } 1347 } 1348 1349 putempty((blkcnt_t)2); 1350 flushtape(); 1351 closevol(); /* SP-1 */ 1352 if (linkerrok == 1) 1353 for (; ihead != NULL; ihead = ihead->nextp) { 1354 if (ihead->count == 0) 1355 continue; 1356 (void) fprintf(stderr, gettext( 1357 "tar: missing links to %s\n"), ihead->pathname); 1358 if (errflag) 1359 done(1); 1360 else 1361 Errflg = 1; 1362 } 1363 } 1364 1365 1366 /* 1367 * endtape - check for tape at end 1368 * 1369 * endtape checks the entry in dblock.dbuf to see if its the 1370 * special EOT entry. Endtape is usually called after getdir(). 1371 * 1372 * endtape used to call backtape; it no longer does, he who 1373 * wants it backed up must call backtape himself 1374 * RETURNS: 0 if not EOT, tape position unaffected 1375 * 1 if EOT, tape position unaffected 1376 */ 1377 1378 static int 1379 endtape(void) 1380 { 1381 if (dblock.dbuf.name[0] == '\0') { /* null header = EOT */ 1382 return (1); 1383 } else 1384 return (0); 1385 } 1386 1387 /* 1388 * getdir - get directory entry from tar tape 1389 * 1390 * getdir reads the next tarblock off the tape and cracks 1391 * it as a directory. The checksum must match properly. 1392 * 1393 * If tfile is non-null getdir writes the file name and mod date 1394 * to tfile. 1395 */ 1396 1397 static void 1398 getdir(void) 1399 { 1400 struct stat *sp; 1401 #ifdef EUC 1402 static int warn_chksum_sign = 0; 1403 #endif /* EUC */ 1404 1405 top: 1406 readtape((char *)&dblock); 1407 if (dblock.dbuf.name[0] == '\0') 1408 return; 1409 sp = &stbuf; 1410 (void) sscanf(dblock.dbuf.mode, "%8lo", &Gen.g_mode); 1411 (void) sscanf(dblock.dbuf.uid, "%8lo", (ulong_t *)&Gen.g_uid); 1412 (void) sscanf(dblock.dbuf.gid, "%8lo", (ulong_t *)&Gen.g_gid); 1413 (void) sscanf(dblock.dbuf.size, "%12" FMT_off_t_o, &Gen.g_filesz); 1414 (void) sscanf(dblock.dbuf.mtime, "%12lo", (ulong_t *)&Gen.g_mtime); 1415 (void) sscanf(dblock.dbuf.chksum, "%8o", &Gen.g_cksum); 1416 (void) sscanf(dblock.dbuf.devmajor, "%8lo", &Gen.g_devmajor); 1417 (void) sscanf(dblock.dbuf.devminor, "%8lo", &Gen.g_devminor); 1418 1419 is_posix = (strcmp(dblock.dbuf.magic, magic_type) == 0); 1420 1421 sp->st_mode = Gen.g_mode; 1422 if (is_posix && (sp->st_mode & S_IFMT) == 0) 1423 switch (dblock.dbuf.typeflag) { 1424 case '0': case 0: case _XATTR_HDRTYPE: 1425 sp->st_mode |= S_IFREG; 1426 break; 1427 case '1': /* hard link */ 1428 break; 1429 case '2': 1430 sp->st_mode |= S_IFLNK; 1431 break; 1432 case '3': 1433 sp->st_mode |= S_IFCHR; 1434 break; 1435 case '4': 1436 sp->st_mode |= S_IFBLK; 1437 break; 1438 case '5': 1439 sp->st_mode |= S_IFDIR; 1440 break; 1441 case '6': 1442 sp->st_mode |= S_IFIFO; 1443 break; 1444 default: 1445 if (convtoreg(Gen.g_filesz)) 1446 sp->st_mode |= S_IFREG; 1447 break; 1448 } 1449 1450 if (dblock.dbuf.typeflag == 'X') 1451 Xhdrflag = 1; /* Currently processing extended header */ 1452 else 1453 Xhdrflag = 0; 1454 1455 sp->st_uid = Gen.g_uid; 1456 sp->st_gid = Gen.g_gid; 1457 sp->st_size = Gen.g_filesz; 1458 sp->st_mtime = Gen.g_mtime; 1459 chksum = Gen.g_cksum; 1460 1461 if (dblock.dbuf.extno != '\0') { /* split file? */ 1462 extno = dblock.dbuf.extno; 1463 extsize = Gen.g_filesz; 1464 extotal = dblock.dbuf.extotal; 1465 } else { 1466 extno = 0; /* tell others file not split */ 1467 extsize = 0; 1468 extotal = 0; 1469 } 1470 1471 #ifdef EUC 1472 if (chksum != checksum(&dblock)) { 1473 if (chksum != checksum_signed(&dblock)) { 1474 (void) fprintf(stderr, gettext( 1475 "tar: directory checksum error\n")); 1476 if (iflag) 1477 goto top; 1478 done(2); 1479 } else { 1480 if (! warn_chksum_sign) { 1481 warn_chksum_sign = 1; 1482 (void) fprintf(stderr, gettext( 1483 "tar: warning: tar file made with signed checksum\n")); 1484 } 1485 } 1486 } 1487 #else 1488 if (chksum != checksum(&dblock)) { 1489 (void) fprintf(stderr, gettext( 1490 "tar: directory checksum error\n")); 1491 if (iflag) 1492 goto top; 1493 done(2); 1494 } 1495 #endif /* EUC */ 1496 if (tfile != NULL && Xhdrflag == 0) { 1497 /* 1498 * If an extended header is present, then time is available 1499 * in nanoseconds in the extended header data, so set it. 1500 * Otherwise, give an invalid value so that checkupdate will 1501 * not test beyond seconds. 1502 */ 1503 if ((xhdr_flgs & _X_MTIME)) 1504 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 1505 else 1506 sp->st_mtim.tv_nsec = -1; 1507 1508 if (xhdr_flgs & _X_PATH) 1509 (void) fprintf(tfile, "%s %10ld.%9.9ld\n", 1510 Xtarhdr.x_path, sp->st_mtim.tv_sec, 1511 sp->st_mtim.tv_nsec); 1512 else 1513 (void) fprintf(tfile, "%.*s %10ld.%9.9ld\n", 1514 NAMSIZ, dblock.dbuf.name, sp->st_mtim.tv_sec, 1515 sp->st_mtim.tv_nsec); 1516 } 1517 1518 #if defined(O_XATTR) 1519 Hiddendir = 0; 1520 if (xattrp && dblock.dbuf.typeflag == _XATTR_HDRTYPE) { 1521 if (xattrbadhead) { 1522 free(xattrhead); 1523 xattrp = NULL; 1524 xattr_linkp = NULL; 1525 xattrhead = NULL; 1526 } else { 1527 char *aname = basename(xattrapath); 1528 size_t xindex = aname - xattrapath; 1529 1530 if (xattrapath[xindex] == '.' && 1531 xattrapath[xindex + 1] == '\0' && 1532 xattrp->h_typeflag == '5') { 1533 Hiddendir = 1; 1534 sp->st_mode = 1535 (S_IFDIR | (sp->st_mode & POSIXMODES)); 1536 } 1537 dblock.dbuf.typeflag = xattrp->h_typeflag; 1538 } 1539 } 1540 #endif 1541 } 1542 1543 1544 /* 1545 * passtape - skip over a file on the tape 1546 * 1547 * passtape skips over the next data file on the tape. 1548 * The tape directory entry must be in dblock.dbuf. This 1549 * routine just eats the number of blocks computed from the 1550 * directory size entry; the tape must be (logically) positioned 1551 * right after thee directory info. 1552 */ 1553 1554 static void 1555 passtape(void) 1556 { 1557 blkcnt_t blocks; 1558 char buf[TBLOCK]; 1559 1560 /* 1561 * Types link(1), sym-link(2), char special(3), blk special(4), 1562 * directory(5), and FIFO(6) do not have data blocks associated 1563 * with them so just skip reading the data block. 1564 */ 1565 if (dblock.dbuf.typeflag == '1' || dblock.dbuf.typeflag == '2' || 1566 dblock.dbuf.typeflag == '3' || dblock.dbuf.typeflag == '4' || 1567 dblock.dbuf.typeflag == '5' || dblock.dbuf.typeflag == '6') 1568 return; 1569 blocks = TBLOCKS(stbuf.st_size); 1570 1571 /* if operating on disk, seek instead of reading */ 1572 if (NotTape) 1573 seekdisk(blocks); 1574 else 1575 while (blocks-- > 0) 1576 readtape(buf); 1577 } 1578 1579 #if defined(O_XATTR) 1580 static int 1581 is_sysattr(char *name) 1582 { 1583 return ((strcmp(name, VIEW_READONLY) == 0) || 1584 (strcmp(name, VIEW_READWRITE) == 0)); 1585 } 1586 #endif 1587 1588 #if defined(O_XATTR) 1589 /* 1590 * Verify the attribute, attrname, is an attribute we want to restore. 1591 * Never restore read-only system attribute files. Only restore read-write 1592 * system attributes files when -/ was specified, and only traverse into 1593 * the 2nd level attribute directory containing only system attributes if 1594 * -@ was specified. This keeps us from archiving 1595 * <attribute name>/<read-write system attribute file> 1596 * when -/ was specified without -@. 1597 * 1598 * attrname - attribute file name 1599 * attrparent - attribute's parent name within the base file's attribute 1600 * directory hierarchy 1601 */ 1602 static attr_status_t 1603 verify_attr(char *attrname, char *attrparent, int arc_rwsysattr, 1604 int *rw_sysattr) 1605 { 1606 #if defined(_PC_SATTR_ENABLED) 1607 int attr_supported; 1608 1609 /* Never restore read-only system attribute files */ 1610 if ((attr_supported = sysattr_type(attrname)) == _RO_SATTR) { 1611 *rw_sysattr = 0; 1612 return (ATTR_SKIP); 1613 } else { 1614 *rw_sysattr = (attr_supported == _RW_SATTR); 1615 } 1616 #else 1617 /* 1618 * Only need to check if this attribute is an extended system 1619 * attribute. 1620 */ 1621 if (*rw_sysattr = is_sysattr(attrname)) { 1622 return (ATTR_SKIP); 1623 } else { 1624 return (ATTR_OK); 1625 } 1626 #endif /* _PC_SATTR_ENABLED */ 1627 1628 /* 1629 * If the extended system attribute file is specified with the 1630 * arc_rwsysattr flag, as being transient (default extended 1631 * attributes), then don't archive it. 1632 */ 1633 if (*rw_sysattr && !arc_rwsysattr) { 1634 return (ATTR_SKIP); 1635 } 1636 1637 /* 1638 * Only restore read-write system attribute files 1639 * when -/ was specified. Only restore extended 1640 * attributes when -@ was specified. 1641 */ 1642 if (atflag) { 1643 if (!saflag) { 1644 /* 1645 * Only archive/restore the hidden directory "." if 1646 * we're processing the top level hidden attribute 1647 * directory. We don't want to process the 1648 * hidden attribute directory of the attribute 1649 * directory that contains only extended system 1650 * attributes. 1651 */ 1652 if (*rw_sysattr || (Hiddendir && 1653 (attrparent != NULL))) { 1654 return (ATTR_SKIP); 1655 } 1656 } 1657 } else if (saflag) { 1658 /* 1659 * Only archive/restore read-write extended system attribute 1660 * files of the base file. 1661 */ 1662 if (!*rw_sysattr || (attrparent != NULL)) { 1663 return (ATTR_SKIP); 1664 } 1665 } else { 1666 return (ATTR_SKIP); 1667 } 1668 1669 return (ATTR_OK); 1670 } 1671 #endif 1672 1673 static void 1674 free_children(file_list_t *children) 1675 { 1676 file_list_t *child = children; 1677 file_list_t *cptr; 1678 1679 while (child != NULL) { 1680 cptr = child->next; 1681 if (child->name != NULL) { 1682 free(child->name); 1683 } 1684 child = cptr; 1685 } 1686 } 1687 1688 static int 1689 putfile(char *longname, char *shortname, char *parent, attr_data_t *attrinfo, 1690 int filetype, int lev, int symlink_lev) 1691 { 1692 int infile = -1; /* deliberately invalid */ 1693 blkcnt_t blocks; 1694 char buf[PATH_MAX + 2]; /* Add trailing slash and null */ 1695 char *bigbuf; 1696 int maxread; 1697 int hint; /* amount to write to get "in sync" */ 1698 char filetmp[PATH_MAX + 1]; 1699 char *cp; 1700 char *name; 1701 char *attrparent = NULL; 1702 char *longattrname = NULL; 1703 file_list_t *child = NULL; 1704 file_list_t *child_end = NULL; 1705 file_list_t *cptr; 1706 struct dirent *dp; 1707 DIR *dirp; 1708 int i; 1709 int split; 1710 int dirfd = -1; 1711 int rc = PUT_NOTAS_LINK; 1712 int archtype = 0; 1713 int rw_sysattr = 0; 1714 char newparent[PATH_MAX + MAXNAMLEN + 1]; 1715 char *prefix = ""; 1716 char *tmpbuf; 1717 char goodbuf[PRESIZ + 2]; 1718 char junkbuf[MAXNAM+1]; 1719 char *lastslash; 1720 int j; 1721 struct stat sbuf; 1722 int readlink_max; 1723 1724 (void) memset(goodbuf, '\0', sizeof (goodbuf)); 1725 (void) memset(junkbuf, '\0', sizeof (junkbuf)); 1726 1727 xhdr_flgs = 0; 1728 1729 if (filetype == XATTR_FILE) { 1730 attrparent = attrinfo->attr_parent; 1731 longattrname = attrinfo->attr_path; 1732 dirfd = attrinfo->attr_parentfd; 1733 rw_sysattr = attrinfo->attr_rw_sysattr; 1734 } else { 1735 dirfd = open(".", O_RDONLY); 1736 } 1737 1738 if (dirfd == -1) { 1739 (void) fprintf(stderr, gettext( 1740 "tar: unable to open%sdirectory %s%s%s%s\n"), 1741 (filetype == XATTR_FILE) ? gettext(" attribute ") : " ", 1742 (attrparent == NULL) ? "" : gettext("of attribute "), 1743 (attrparent == NULL) ? "" : attrparent, 1744 (attrparent == NULL) ? "" : gettext(" of "), 1745 (filetype == XATTR_FILE) ? longname : parent); 1746 goto out; 1747 } 1748 1749 if (lev > MAXLEV) { 1750 (void) fprintf(stderr, 1751 gettext("tar: directory nesting too deep, %s not dumped\n"), 1752 longname); 1753 goto out; 1754 } 1755 1756 if (getstat(dirfd, longname, shortname, attrparent)) 1757 goto out; 1758 1759 if (hflag) { 1760 /* 1761 * Catch nesting where a file is a symlink to its directory. 1762 */ 1763 j = fstatat(dirfd, shortname, &sbuf, AT_SYMLINK_NOFOLLOW); 1764 if (S_ISLNK(sbuf.st_mode)) { 1765 if (symlink_lev++ >= MAXSYMLINKS) { 1766 (void) fprintf(stderr, gettext( 1767 "tar: %s: Number of symbolic links " 1768 "encountered during path name traversal " 1769 "exceeds MAXSYMLINKS\n"), longname); 1770 Errflg = 1; 1771 goto out; 1772 } 1773 } 1774 } 1775 1776 /* 1777 * Check if the input file is the same as the tar file we 1778 * are creating 1779 */ 1780 if ((mt_ino == stbuf.st_ino) && (mt_dev == stbuf.st_dev)) { 1781 (void) fprintf(stderr, gettext( 1782 "tar: %s%s%s%s%s same as archive file\n"), 1783 rw_sysattr ? gettext("system ") : "", 1784 (longattrname == NULL) ? "" : gettext("attribute "), 1785 (longattrname == NULL) ? "" : longattrname, 1786 (longattrname == NULL) ? "" : gettext(" of "), 1787 longname); 1788 Errflg = 1; 1789 goto out; 1790 } 1791 /* 1792 * Check size limit - we can't archive files that 1793 * exceed TAR_OFFSET_MAX bytes because of header 1794 * limitations. Exclude file types that set 1795 * st_size to zero below because they take no 1796 * archive space to represent contents. 1797 */ 1798 if ((stbuf.st_size > (off_t)TAR_OFFSET_MAX) && 1799 !S_ISDIR(stbuf.st_mode) && 1800 !S_ISCHR(stbuf.st_mode) && 1801 !S_ISBLK(stbuf.st_mode) && 1802 (Eflag == 0)) { 1803 (void) fprintf(stderr, gettext( 1804 "tar: %s%s%s%s%s too large to archive. " 1805 "Use E function modifier.\n"), 1806 rw_sysattr ? gettext("system ") : "", 1807 (longattrname == NULL) ? "" : gettext("attribute "), 1808 (longattrname == NULL) ? "" : longattrname, 1809 (longattrname == NULL) ? "" : gettext(" of "), 1810 longname); 1811 if (errflag) 1812 exitflag = 1; 1813 Errflg = 1; 1814 goto out; 1815 } 1816 1817 if (tfile != NULL && checkupdate(longname) == 0) { 1818 goto out; 1819 } 1820 if (checkw('r', longname) == 0) { 1821 goto out; 1822 } 1823 1824 if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) 1825 goto out; 1826 1827 if (Xflag) { 1828 if (is_in_table(exclude_tbl, longname)) { 1829 if (vflag) { 1830 (void) fprintf(vfile, gettext( 1831 "a %s excluded\n"), longname); 1832 } 1833 goto out; 1834 } 1835 } 1836 1837 /* 1838 * If the length of the fullname is greater than MAXNAM, 1839 * print out a message and return (unless extended headers are used, 1840 * in which case fullname is limited to PATH_MAX). 1841 */ 1842 1843 if ((((split = (int)strlen(longname)) > MAXNAM) && (Eflag == 0)) || 1844 (split > PATH_MAX)) { 1845 (void) fprintf(stderr, gettext( 1846 "tar: %s: file name too long\n"), longname); 1847 if (errflag) 1848 exitflag = 1; 1849 Errflg = 1; 1850 goto out; 1851 } 1852 1853 /* 1854 * We split the fullname into prefix and name components if any one 1855 * of three conditions holds: 1856 * -- the length of the fullname exceeds NAMSIZ, 1857 * -- the length of the fullname equals NAMSIZ, and the shortname 1858 * is less than NAMSIZ, (splitting in this case preserves 1859 * compatibility with 5.6 and 5.5.1 tar), or 1860 * -- the length of the fullname equals NAMSIZ, the file is a 1861 * directory and we are not in POSIX-conformant mode (where 1862 * trailing slashes are removed from directories). 1863 */ 1864 if ((split > NAMSIZ) || 1865 (split == NAMSIZ && strlen(shortname) < NAMSIZ) || 1866 (split == NAMSIZ && S_ISDIR(stbuf.st_mode) && !Pflag)) { 1867 /* 1868 * Since path is limited to PRESIZ characters, look for the 1869 * last slash within PRESIZ + 1 characters only. 1870 */ 1871 (void) strncpy(&goodbuf[0], longname, min(split, PRESIZ + 1)); 1872 tmpbuf = goodbuf; 1873 lastslash = strrchr(tmpbuf, '/'); 1874 if (lastslash == NULL) { 1875 i = split; /* Length of name */ 1876 j = 0; /* Length of prefix */ 1877 goodbuf[0] = '\0'; 1878 } else { 1879 *lastslash = '\0'; /* Terminate the prefix */ 1880 j = strlen(tmpbuf); 1881 i = split - j - 1; 1882 } 1883 /* 1884 * If the filename is greater than NAMSIZ we can't 1885 * archive the file unless we are using extended headers. 1886 */ 1887 if ((i > NAMSIZ) || (i == NAMSIZ && S_ISDIR(stbuf.st_mode) && 1888 !Pflag)) { 1889 /* Determine which (filename or path) is too long. */ 1890 lastslash = strrchr(longname, '/'); 1891 if (lastslash != NULL) 1892 i = strlen(lastslash + 1); 1893 if (Eflag > 0) { 1894 xhdr_flgs |= _X_PATH; 1895 Xtarhdr.x_path = longname; 1896 if (i <= NAMSIZ) 1897 (void) strcpy(junkbuf, lastslash + 1); 1898 else 1899 (void) sprintf(junkbuf, "%llu", 1900 xhdr_count + 1); 1901 if (split - i - 1 > PRESIZ) 1902 (void) strcpy(goodbuf, xhdr_dirname); 1903 } else { 1904 if ((i > NAMSIZ) || (i == NAMSIZ && 1905 S_ISDIR(stbuf.st_mode) && !Pflag)) 1906 (void) fprintf(stderr, gettext( 1907 "tar: %s: filename is greater than " 1908 "%d\n"), lastslash == NULL ? 1909 longname : lastslash + 1, NAMSIZ); 1910 else 1911 (void) fprintf(stderr, gettext( 1912 "tar: %s: prefix is greater than %d" 1913 "\n"), longname, PRESIZ); 1914 if (errflag) 1915 exitflag = 1; 1916 Errflg = 1; 1917 goto out; 1918 } 1919 } else 1920 (void) strncpy(&junkbuf[0], longname + j + 1, 1921 strlen(longname + j + 1)); 1922 name = junkbuf; 1923 prefix = goodbuf; 1924 } else { 1925 name = longname; 1926 } 1927 if (Aflag) { 1928 if ((prefix != NULL) && (*prefix != '\0')) 1929 while (*prefix == '/') 1930 ++prefix; 1931 else 1932 while (*name == '/') 1933 ++name; 1934 } 1935 1936 switch (stbuf.st_mode & S_IFMT) { 1937 case S_IFDIR: 1938 stbuf.st_size = (off_t)0; 1939 blocks = TBLOCKS(stbuf.st_size); 1940 1941 if (filetype != XATTR_FILE && Hiddendir == 0) { 1942 i = 0; 1943 cp = buf; 1944 while ((*cp++ = longname[i++])) 1945 ; 1946 *--cp = '/'; 1947 *++cp = 0; 1948 } 1949 if (!oflag) { 1950 tomodes(&stbuf); 1951 if (build_dblock(name, tchar, '5', filetype, 1952 &stbuf, stbuf.st_dev, prefix) != 0) { 1953 goto out; 1954 } 1955 if (!Pflag) { 1956 /* 1957 * Old archives require a slash at the end 1958 * of a directory name. 1959 * 1960 * XXX 1961 * If directory name is too long, will 1962 * slash overfill field? 1963 */ 1964 if (strlen(name) > (unsigned)NAMSIZ-1) { 1965 (void) fprintf(stderr, gettext( 1966 "tar: %s: filename is greater " 1967 "than %d\n"), name, NAMSIZ); 1968 if (errflag) 1969 exitflag = 1; 1970 Errflg = 1; 1971 goto out; 1972 } else { 1973 if (strlen(name) == (NAMSIZ - 1)) { 1974 (void) memcpy(dblock.dbuf.name, 1975 name, NAMSIZ); 1976 dblock.dbuf.name[NAMSIZ-1] 1977 = '/'; 1978 } else 1979 (void) sprintf(dblock.dbuf.name, 1980 "%s/", name); 1981 1982 /* 1983 * need to recalculate checksum 1984 * because the name changed. 1985 */ 1986 (void) sprintf(dblock.dbuf.chksum, 1987 "%07o", checksum(&dblock)); 1988 } 1989 } 1990 1991 if (put_extra_attributes(longname, shortname, 1992 longattrname, prefix, filetype, '5') != 0) 1993 goto out; 1994 1995 #if defined(O_XATTR) 1996 /* 1997 * Reset header typeflag when archiving directory, since 1998 * build_dblock changed it on us. 1999 */ 2000 if (filetype == XATTR_FILE) { 2001 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2002 } else { 2003 dblock.dbuf.typeflag = '5'; 2004 } 2005 #else 2006 dblock.dbuf.typeflag = '5'; 2007 #endif 2008 2009 (void) sprintf(dblock.dbuf.chksum, "%07o", 2010 checksum(&dblock)); 2011 2012 (void) writetbuf((char *)&dblock, 1); 2013 } 2014 if (vflag) { 2015 #ifdef DEBUG 2016 if (NotTape) 2017 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2018 0); 2019 #endif 2020 if (filetype == XATTR_FILE && Hiddendir) { 2021 (void) fprintf(vfile, "a %s attribute %s ", 2022 longname, longattrname); 2023 2024 } else { 2025 (void) fprintf(vfile, "a %s/ ", longname); 2026 } 2027 if (NotTape) 2028 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2029 K(blocks)); 2030 else 2031 (void) fprintf(vfile, gettext("%" FMT_blkcnt_t 2032 " tape blocks\n"), blocks); 2033 } 2034 2035 /* 2036 * If hidden dir then break now since xattrs_put() will do 2037 * the iterating of the directory. 2038 * 2039 * At the moment, there can only be system attributes on 2040 * attributes. There can be no attributes on attributes or 2041 * directories within the attributes hidden directory hierarchy. 2042 */ 2043 if (filetype == XATTR_FILE) 2044 break; 2045 2046 if (*shortname != '/') 2047 (void) sprintf(newparent, "%s/%s", parent, shortname); 2048 else 2049 (void) sprintf(newparent, "%s", shortname); 2050 2051 if (chdir(shortname) < 0) { 2052 vperror(0, "%s", newparent); 2053 goto out; 2054 } 2055 2056 if ((dirp = opendir(".")) == NULL) { 2057 vperror(0, gettext( 2058 "can't open directory %s"), longname); 2059 if (chdir(parent) < 0) 2060 vperror(0, gettext("cannot change back?: %s"), 2061 parent); 2062 goto out; 2063 } 2064 2065 /* 2066 * Create a list of files (children) in this directory to avoid 2067 * having to perform telldir()/seekdir(). 2068 */ 2069 while ((dp = readdir(dirp)) != NULL && !term) { 2070 if ((strcmp(".", dp->d_name) == 0) || 2071 (strcmp("..", dp->d_name) == 0)) 2072 continue; 2073 if (((cptr = (file_list_t *)calloc(sizeof (char), 2074 sizeof (file_list_t))) == NULL) || 2075 ((cptr->name = strdup(dp->d_name)) == NULL)) { 2076 vperror(1, gettext( 2077 "Insufficient memory for directory " 2078 "list entry %s/%s\n"), 2079 newparent, dp->d_name); 2080 } 2081 2082 /* Add the file to the list */ 2083 if (child == NULL) { 2084 child = cptr; 2085 } else { 2086 child_end->next = cptr; 2087 } 2088 child_end = cptr; 2089 } 2090 (void) closedir(dirp); 2091 2092 /* 2093 * Archive each of the files in the current directory. 2094 * If a file is a directory, putfile() is called 2095 * recursively to archive the file hierarchy of the 2096 * directory before archiving the next file in the 2097 * current directory. 2098 */ 2099 while ((child != NULL) && !term) { 2100 (void) strcpy(cp, child->name); 2101 archtype = putfile(buf, cp, newparent, NULL, 2102 NORMAL_FILE, lev + 1, symlink_lev); 2103 2104 if (!exitflag) { 2105 if ((atflag || saflag) && 2106 (archtype == PUT_NOTAS_LINK)) { 2107 xattrs_put(buf, cp, newparent, NULL); 2108 } 2109 } 2110 if (exitflag) 2111 break; 2112 2113 /* Free each child as we are done processing it. */ 2114 cptr = child; 2115 child = child->next; 2116 free(cptr->name); 2117 free(cptr); 2118 } 2119 if ((child != NULL) && !term) { 2120 free_children(child); 2121 } 2122 2123 if (chdir(parent) < 0) { 2124 vperror(0, gettext("cannot change back?: %s"), parent); 2125 } 2126 2127 break; 2128 2129 case S_IFLNK: 2130 readlink_max = NAMSIZ; 2131 if (stbuf.st_size > NAMSIZ) { 2132 if (Eflag > 0) { 2133 xhdr_flgs |= _X_LINKPATH; 2134 readlink_max = PATH_MAX; 2135 } else { 2136 (void) fprintf(stderr, gettext( 2137 "tar: %s: symbolic link too long\n"), 2138 longname); 2139 if (errflag) 2140 exitflag = 1; 2141 Errflg = 1; 2142 goto out; 2143 } 2144 } 2145 /* 2146 * Sym-links need header size of zero since you 2147 * don't store any data for this type. 2148 */ 2149 stbuf.st_size = (off_t)0; 2150 tomodes(&stbuf); 2151 i = readlink(shortname, filetmp, readlink_max); 2152 if (i < 0) { 2153 vperror(0, gettext( 2154 "can't read symbolic link %s"), longname); 2155 goto out; 2156 } else { 2157 filetmp[i] = 0; 2158 } 2159 if (vflag) 2160 (void) fprintf(vfile, gettext( 2161 "a %s symbolic link to %s\n"), 2162 longname, filetmp); 2163 if (xhdr_flgs & _X_LINKPATH) { 2164 Xtarhdr.x_linkpath = filetmp; 2165 if (build_dblock(name, tchar, '2', filetype, &stbuf, 2166 stbuf.st_dev, prefix) != 0) 2167 goto out; 2168 } else 2169 if (build_dblock(name, filetmp, '2', filetype, &stbuf, 2170 stbuf.st_dev, prefix) != 0) 2171 goto out; 2172 (void) writetbuf((char *)&dblock, 1); 2173 /* 2174 * No acls for symlinks: mode is always 777 2175 * dont call write ancillary 2176 */ 2177 rc = PUT_AS_LINK; 2178 break; 2179 case S_IFREG: 2180 if ((infile = openat(dirfd, shortname, 0)) < 0) { 2181 vperror(0, "unable to open %s%s%s%s", longname, 2182 rw_sysattr ? gettext(" system") : "", 2183 (filetype == XATTR_FILE) ? 2184 gettext(" attribute ") : "", 2185 (filetype == XATTR_FILE) ? (longattrname == NULL) ? 2186 shortname : longattrname : ""); 2187 goto out; 2188 } 2189 2190 blocks = TBLOCKS(stbuf.st_size); 2191 2192 if (put_link(name, longname, shortname, longattrname, 2193 prefix, filetype, '1') == 0) { 2194 (void) close(infile); 2195 rc = PUT_AS_LINK; 2196 goto out; 2197 } 2198 2199 tomodes(&stbuf); 2200 2201 /* correctly handle end of volume */ 2202 while (mulvol && tapepos + blocks + 1 > blocklim) { 2203 /* file won't fit */ 2204 if (eflag) { 2205 if (blocks <= blocklim) { 2206 newvol(); 2207 break; 2208 } 2209 (void) fprintf(stderr, gettext( 2210 "tar: Single file cannot fit on volume\n")); 2211 done(3); 2212 } 2213 /* split if floppy has some room and file is large */ 2214 if (((blocklim - tapepos) >= EXTMIN) && 2215 ((blocks + 1) >= blocklim/10)) { 2216 splitfile(longname, infile, 2217 name, prefix, filetype); 2218 (void) close(dirfd); 2219 (void) close(infile); 2220 goto out; 2221 } 2222 newvol(); /* not worth it--just get new volume */ 2223 } 2224 #ifdef DEBUG 2225 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2226 blocks); 2227 #endif 2228 if (build_dblock(name, tchar, '0', filetype, 2229 &stbuf, stbuf.st_dev, prefix) != 0) { 2230 goto out; 2231 } 2232 if (vflag) { 2233 #ifdef DEBUG 2234 if (NotTape) 2235 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2236 0); 2237 #endif 2238 (void) fprintf(vfile, "a %s%s%s%s ", longname, 2239 rw_sysattr ? gettext(" system") : "", 2240 (filetype == XATTR_FILE) ? gettext( 2241 " attribute ") : "", 2242 (filetype == XATTR_FILE) ? 2243 longattrname : ""); 2244 if (NotTape) 2245 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2246 K(blocks)); 2247 else 2248 (void) fprintf(vfile, 2249 gettext("%" FMT_blkcnt_t " tape blocks\n"), 2250 blocks); 2251 } 2252 2253 if (put_extra_attributes(longname, shortname, longattrname, 2254 prefix, filetype, '0') != 0) 2255 goto out; 2256 2257 /* 2258 * No need to reset typeflag for extended attribute here, since 2259 * put_extra_attributes already set it and we haven't called 2260 * build_dblock(). 2261 */ 2262 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2263 hint = writetbuf((char *)&dblock, 1); 2264 maxread = max(min(stbuf.st_blksize, stbuf.st_size), 2265 (nblock * TBLOCK)); 2266 if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2267 maxread = TBLOCK; 2268 bigbuf = buf; 2269 } 2270 2271 while (((i = (int) 2272 read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2273 blocks) { 2274 blkcnt_t nblks; 2275 2276 nblks = ((i-1)/TBLOCK)+1; 2277 if (nblks > blocks) 2278 nblks = blocks; 2279 hint = writetbuf(bigbuf, nblks); 2280 blocks -= nblks; 2281 } 2282 (void) close(infile); 2283 if (bigbuf != buf) 2284 free(bigbuf); 2285 if (i < 0) 2286 vperror(0, gettext("Read error on %s"), longname); 2287 else if (blocks != 0 || i != 0) { 2288 (void) fprintf(stderr, gettext( 2289 "tar: %s: file changed size\n"), longname); 2290 if (errflag) { 2291 exitflag = 1; 2292 Errflg = 1; 2293 } else if (!Dflag) { 2294 Errflg = 1; 2295 } 2296 } 2297 putempty(blocks); 2298 break; 2299 case S_IFIFO: 2300 blocks = TBLOCKS(stbuf.st_size); 2301 stbuf.st_size = (off_t)0; 2302 2303 if (put_link(name, longname, shortname, longattrname, 2304 prefix, filetype, '6') == 0) { 2305 rc = PUT_AS_LINK; 2306 goto out; 2307 } 2308 tomodes(&stbuf); 2309 2310 while (mulvol && tapepos + blocks + 1 > blocklim) { 2311 if (eflag) { 2312 if (blocks <= blocklim) { 2313 newvol(); 2314 break; 2315 } 2316 (void) fprintf(stderr, gettext( 2317 "tar: Single file cannot fit on volume\n")); 2318 done(3); 2319 } 2320 2321 if (((blocklim - tapepos) >= EXTMIN) && 2322 ((blocks + 1) >= blocklim/10)) { 2323 splitfile(longname, infile, name, 2324 prefix, filetype); 2325 (void) close(dirfd); 2326 (void) close(infile); 2327 goto out; 2328 } 2329 newvol(); 2330 } 2331 #ifdef DEBUG 2332 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2333 blocks); 2334 #endif 2335 if (vflag) { 2336 #ifdef DEBUG 2337 if (NotTape) 2338 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2339 0); 2340 #endif 2341 if (NotTape) 2342 (void) fprintf(vfile, gettext("a %s %" 2343 FMT_blkcnt_t "K\n "), longname, K(blocks)); 2344 else 2345 (void) fprintf(vfile, gettext( 2346 "a %s %" FMT_blkcnt_t " tape blocks\n"), 2347 longname, blocks); 2348 } 2349 if (build_dblock(name, tchar, '6', filetype, 2350 &stbuf, stbuf.st_dev, prefix) != 0) 2351 goto out; 2352 2353 if (put_extra_attributes(longname, shortname, longattrname, 2354 prefix, filetype, '6') != 0) 2355 goto out; 2356 2357 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2358 dblock.dbuf.typeflag = '6'; 2359 2360 (void) writetbuf((char *)&dblock, 1); 2361 break; 2362 case S_IFCHR: 2363 stbuf.st_size = (off_t)0; 2364 blocks = TBLOCKS(stbuf.st_size); 2365 if (put_link(name, longname, shortname, longattrname, 2366 prefix, filetype, '3') == 0) { 2367 rc = PUT_AS_LINK; 2368 goto out; 2369 } 2370 tomodes(&stbuf); 2371 2372 while (mulvol && tapepos + blocks + 1 > blocklim) { 2373 if (eflag) { 2374 if (blocks <= blocklim) { 2375 newvol(); 2376 break; 2377 } 2378 (void) fprintf(stderr, gettext( 2379 "tar: Single file cannot fit on volume\n")); 2380 done(3); 2381 } 2382 2383 if (((blocklim - tapepos) >= EXTMIN) && 2384 ((blocks + 1) >= blocklim/10)) { 2385 splitfile(longname, infile, name, 2386 prefix, filetype); 2387 (void) close(dirfd); 2388 goto out; 2389 } 2390 newvol(); 2391 } 2392 #ifdef DEBUG 2393 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2394 blocks); 2395 #endif 2396 if (vflag) { 2397 #ifdef DEBUG 2398 if (NotTape) 2399 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2400 0); 2401 #endif 2402 if (NotTape) 2403 (void) fprintf(vfile, gettext("a %s %" 2404 FMT_blkcnt_t "K\n"), longname, K(blocks)); 2405 else 2406 (void) fprintf(vfile, gettext("a %s %" 2407 FMT_blkcnt_t " tape blocks\n"), longname, 2408 blocks); 2409 } 2410 if (build_dblock(name, tchar, '3', 2411 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2412 goto out; 2413 2414 if (put_extra_attributes(longname, shortname, longattrname, 2415 prefix, filetype, '3') != 0) 2416 goto out; 2417 2418 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2419 dblock.dbuf.typeflag = '3'; 2420 2421 (void) writetbuf((char *)&dblock, 1); 2422 break; 2423 case S_IFBLK: 2424 stbuf.st_size = (off_t)0; 2425 blocks = TBLOCKS(stbuf.st_size); 2426 if (put_link(name, longname, shortname, longattrname, 2427 prefix, filetype, '4') == 0) { 2428 rc = PUT_AS_LINK; 2429 goto out; 2430 } 2431 tomodes(&stbuf); 2432 2433 while (mulvol && tapepos + blocks + 1 > blocklim) { 2434 if (eflag) { 2435 if (blocks <= blocklim) { 2436 newvol(); 2437 break; 2438 } 2439 (void) fprintf(stderr, gettext( 2440 "tar: Single file cannot fit on volume\n")); 2441 done(3); 2442 } 2443 2444 if (((blocklim - tapepos) >= EXTMIN) && 2445 ((blocks + 1) >= blocklim/10)) { 2446 splitfile(longname, infile, 2447 name, prefix, filetype); 2448 (void) close(dirfd); 2449 goto out; 2450 } 2451 newvol(); 2452 } 2453 #ifdef DEBUG 2454 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2455 blocks); 2456 #endif 2457 if (vflag) { 2458 #ifdef DEBUG 2459 if (NotTape) 2460 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2461 0); 2462 #endif 2463 (void) fprintf(vfile, "a %s ", longname); 2464 if (NotTape) 2465 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2466 K(blocks)); 2467 else 2468 (void) fprintf(vfile, gettext("%" 2469 FMT_blkcnt_t " tape blocks\n"), blocks); 2470 } 2471 if (build_dblock(name, tchar, '4', 2472 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2473 goto out; 2474 2475 if (put_extra_attributes(longname, shortname, longattrname, 2476 prefix, filetype, '4') != 0) 2477 goto out; 2478 2479 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2480 dblock.dbuf.typeflag = '4'; 2481 2482 (void) writetbuf((char *)&dblock, 1); 2483 break; 2484 default: 2485 (void) fprintf(stderr, gettext( 2486 "tar: %s is not a file. Not dumped\n"), longname); 2487 if (errflag) 2488 exitflag = 1; 2489 Errflg = 1; 2490 goto out; 2491 } 2492 2493 out: 2494 if ((dirfd != -1) && (filetype != XATTR_FILE)) { 2495 (void) close(dirfd); 2496 } 2497 return (rc); 2498 } 2499 2500 2501 /* 2502 * splitfile dump a large file across volumes 2503 * 2504 * splitfile(longname, fd); 2505 * char *longname; full name of file 2506 * int ifd; input file descriptor 2507 * 2508 * NOTE: only called by putfile() to dump a large file. 2509 */ 2510 2511 static void 2512 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2513 { 2514 blkcnt_t blocks; 2515 off_t bytes, s; 2516 char buf[TBLOCK]; 2517 int i, extents; 2518 2519 blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2520 2521 /* 2522 * # extents = 2523 * size of file after using up rest of this floppy 2524 * blocks - (blocklim - tapepos) + 1 (for header) 2525 * plus roundup value before divide by blocklim-1 2526 * + (blocklim - 1) - 1 2527 * all divided by blocklim-1 (one block for each header). 2528 * this gives 2529 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2530 * which reduces to the expression used. 2531 * one is added to account for this first extent. 2532 * 2533 * When one is dealing with extremely large archives, one may want 2534 * to allow for a large number of extents. This code should be 2535 * revisited to determine if extents should be changed to something 2536 * larger than an int. 2537 */ 2538 extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2539 2540 if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2541 (void) fprintf(stderr, gettext( 2542 "tar: %s needs unusual number of volumes to split\n" 2543 "tar: %s not dumped\n"), longname, longname); 2544 return; 2545 } 2546 if (build_dblock(name, tchar, '0', filetype, 2547 &stbuf, stbuf.st_dev, prefix) != 0) 2548 return; 2549 2550 dblock.dbuf.extotal = extents; 2551 bytes = stbuf.st_size; 2552 2553 /* 2554 * The value contained in dblock.dbuf.efsize was formerly used when the 2555 * v flag was specified in conjunction with the t flag. Although it is 2556 * no longer used, older versions of tar will expect the former 2557 * behaviour, so we must continue to write it to the archive. 2558 * 2559 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2560 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2561 * store 0. 2562 */ 2563 if (bytes <= TAR_EFSIZE_MAX) 2564 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2565 else 2566 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2567 2568 (void) fprintf(stderr, gettext( 2569 "tar: large file %s needs %d extents.\n" 2570 "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2571 longname, extents, K(tapepos)); 2572 2573 s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2574 for (i = 1; i <= extents; i++) { 2575 if (i > 1) { 2576 newvol(); 2577 if (i == extents) 2578 s = bytes; /* last ext. gets true bytes */ 2579 else 2580 s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2581 } 2582 bytes -= s; 2583 blocks = TBLOCKS(s); 2584 2585 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2586 dblock.dbuf.extno = i; 2587 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2588 (void) writetbuf((char *)&dblock, 1); 2589 2590 if (vflag) 2591 (void) fprintf(vfile, 2592 "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n", 2593 longname, K(blocks), i, extents); 2594 while (blocks && read(ifd, buf, TBLOCK) > 0) { 2595 blocks--; 2596 (void) writetbuf(buf, 1); 2597 } 2598 if (blocks != 0) { 2599 (void) fprintf(stderr, gettext( 2600 "tar: %s: file changed size\n"), longname); 2601 (void) fprintf(stderr, gettext( 2602 "tar: aborting split file %s\n"), longname); 2603 (void) close(ifd); 2604 return; 2605 } 2606 } 2607 (void) close(ifd); 2608 if (vflag) 2609 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2610 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2611 extents); 2612 } 2613 2614 /* 2615 * convtoreg - determines whether the file should be converted to a 2616 * regular file when extracted 2617 * 2618 * Returns 1 when file size > 0 and typeflag is not recognized 2619 * Otherwise returns 0 2620 */ 2621 static int 2622 convtoreg(off_t size) 2623 { 2624 if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2625 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2626 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2627 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2628 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2629 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2630 (dblock.dbuf.typeflag != 'X')) { 2631 return (1); 2632 } 2633 return (0); 2634 } 2635 2636 #if defined(O_XATTR) 2637 static int 2638 save_cwd(void) 2639 { 2640 return (open(".", O_RDONLY)); 2641 } 2642 #endif 2643 2644 #if defined(O_XATTR) 2645 static void 2646 rest_cwd(int *cwd) 2647 { 2648 if (*cwd != -1) { 2649 if (fchdir(*cwd) < 0) { 2650 vperror(0, gettext( 2651 "Cannot fchdir to attribute directory")); 2652 exit(1); 2653 } 2654 (void) close(*cwd); 2655 *cwd = -1; 2656 } 2657 } 2658 #endif 2659 2660 /* 2661 * Verify the underlying file system supports the attribute type. 2662 * Only archive extended attribute files when '-@' was specified. 2663 * Only archive system extended attribute files if '-/' was specified. 2664 */ 2665 #if defined(O_XATTR) 2666 static attr_status_t 2667 verify_attr_support(char *filename, int attrflg, arc_action_t actflag, 2668 int *ext_attrflg) 2669 { 2670 /* 2671 * Verify extended attributes are supported/exist. We only 2672 * need to check if we are processing a base file, not an 2673 * extended attribute. 2674 */ 2675 if (attrflg) { 2676 *ext_attrflg = (pathconf(filename, (actflag == ARC_CREATE) ? 2677 _PC_XATTR_EXISTS : _PC_XATTR_ENABLED) == 1); 2678 } 2679 2680 if (atflag) { 2681 if (!*ext_attrflg) { 2682 #if defined(_PC_SATTR_ENABLED) 2683 if (saflag) { 2684 /* Verify system attributes are supported */ 2685 if (sysattr_support(filename, 2686 (actflag == ARC_CREATE) ? _PC_SATTR_EXISTS : 2687 _PC_SATTR_ENABLED) != 1) { 2688 return (ATTR_SATTR_ERR); 2689 } 2690 } else 2691 return (ATTR_XATTR_ERR); 2692 #else 2693 return (ATTR_XATTR_ERR); 2694 #endif /* _PC_SATTR_ENABLED */ 2695 } 2696 2697 #if defined(_PC_SATTR_ENABLED) 2698 } else if (saflag) { 2699 /* Verify system attributes are supported */ 2700 if (sysattr_support(filename, (actflag == ARC_CREATE) ? 2701 _PC_SATTR_EXISTS : _PC_SATTR_ENABLED) != 1) { 2702 return (ATTR_SATTR_ERR); 2703 } 2704 #endif /* _PC_SATTR_ENABLED */ 2705 } else { 2706 return (ATTR_SKIP); 2707 } 2708 2709 return (ATTR_OK); 2710 } 2711 #endif 2712 2713 #if defined(O_XATTR) 2714 /* 2715 * Recursively open attribute directories until the attribute directory 2716 * containing the specified attribute, attrname, is opened. 2717 * 2718 * Currently, only 2 directory levels of attributes are supported, (i.e., 2719 * extended system attributes on extended attributes). The following are 2720 * the possible input combinations: 2721 * 1. Open the attribute directory of the base file (don't change 2722 * into it). 2723 * attrinfo->parent = NULL 2724 * attrname = '.' 2725 * 2. Open the attribute directory of the base file and change into it. 2726 * attrinfo->parent = NULL 2727 * attrname = <attr> | <sys_attr> 2728 * 3. Open the attribute directory of the base file, change into it, 2729 * then recursively call open_attr_dir() to open the attribute's 2730 * parent directory (don't change into it). 2731 * attrinfo->parent = <attr> 2732 * attrname = '.' 2733 * 4. Open the attribute directory of the base file, change into it, 2734 * then recursively call open_attr_dir() to open the attribute's 2735 * parent directory and change into it. 2736 * attrinfo->parent = <attr> 2737 * attrname = <attr> | <sys_attr> 2738 * 2739 * An attribute directory will be opened only if the underlying file system 2740 * supports the attribute type, and if the command line specifications (atflag 2741 * and saflag) enable the processing of the attribute type. 2742 * 2743 * On succesful return, attrinfo->parentfd will be the file descriptor of the 2744 * opened attribute directory. In addition, if the attribute is a read-write 2745 * extended system attribute, attrinfo->rw_sysattr will be set to 1, otherwise 2746 * it will be set to 0. 2747 * 2748 * Possible return values: 2749 * ATTR_OK Successfully opened and, if needed, changed into the 2750 * attribute directory containing attrname. 2751 * ATTR_SKIP The command line specifications don't enable the 2752 * processing of the attribute type. 2753 * ATTR_CHDIR_ERR An error occurred while trying to change into an 2754 * attribute directory. 2755 * ATTR_OPEN_ERR An error occurred while trying to open an 2756 * attribute directory. 2757 * ATTR_XATTR_ERR The underlying file system doesn't support extended 2758 * attributes. 2759 * ATTR_SATTR_ERR The underlying file system doesn't support extended 2760 * system attributes. 2761 */ 2762 static int 2763 open_attr_dir(char *attrname, char *dirp, int cwd, attr_data_t *attrinfo) 2764 { 2765 attr_status_t rc; 2766 int firsttime = (attrinfo->attr_parentfd == -1); 2767 int saveerrno; 2768 int ext_attr; 2769 2770 /* 2771 * open_attr_dir() was recursively called (input combination number 4), 2772 * close the previously opened file descriptor as we've already changed 2773 * into it. 2774 */ 2775 if (!firsttime) { 2776 (void) close(attrinfo->attr_parentfd); 2777 attrinfo->attr_parentfd = -1; 2778 } 2779 2780 /* 2781 * Verify that the underlying file system supports the restoration 2782 * of the attribute. 2783 */ 2784 if ((rc = verify_attr_support(dirp, firsttime, ARC_RESTORE, 2785 &ext_attr)) != ATTR_OK) { 2786 return (rc); 2787 } 2788 2789 /* Open the base file's attribute directory */ 2790 if ((attrinfo->attr_parentfd = attropen(dirp, ".", O_RDONLY)) == -1) { 2791 /* 2792 * Save the errno from the attropen so it can be reported 2793 * if the retry of the attropen fails. 2794 */ 2795 saveerrno = errno; 2796 if ((attrinfo->attr_parentfd = retry_open_attr(-1, cwd, dirp, 2797 NULL, ".", O_RDONLY, 0)) == -1) { 2798 /* 2799 * Reset typeflag back to real value so passtape 2800 * will skip ahead correctly. 2801 */ 2802 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2803 (void) close(attrinfo->attr_parentfd); 2804 attrinfo->attr_parentfd = -1; 2805 errno = saveerrno; 2806 return (ATTR_OPEN_ERR); 2807 } 2808 } 2809 2810 /* 2811 * Change into the parent attribute's directory unless we are 2812 * processing the hidden attribute directory of the base file itself. 2813 */ 2814 if ((Hiddendir == 0) || (firsttime && attrinfo->attr_parent != NULL)) { 2815 if (fchdir(attrinfo->attr_parentfd) != 0) { 2816 saveerrno = errno; 2817 (void) close(attrinfo->attr_parentfd); 2818 attrinfo->attr_parentfd = -1; 2819 errno = saveerrno; 2820 return (ATTR_CHDIR_ERR); 2821 } 2822 } 2823 2824 /* Determine if the attribute should be processed */ 2825 if ((rc = verify_attr(attrname, attrinfo->attr_parent, 1, 2826 &attrinfo->attr_rw_sysattr)) != ATTR_OK) { 2827 saveerrno = errno; 2828 (void) close(attrinfo->attr_parentfd); 2829 attrinfo->attr_parentfd = -1; 2830 errno = saveerrno; 2831 return (rc); 2832 } 2833 2834 /* 2835 * If the attribute is an extended attribute, or extended system 2836 * attribute, of an attribute (i.e., <attr>/<sys_attr>), then 2837 * recursively call open_attr_dir() to open the attribute directory 2838 * of the parent attribute. 2839 */ 2840 if (firsttime && (attrinfo->attr_parent != NULL)) { 2841 return (open_attr_dir(attrname, attrinfo->attr_parent, 2842 attrinfo->attr_parentfd, attrinfo)); 2843 } 2844 2845 return (ATTR_OK); 2846 } 2847 #endif 2848 2849 static void 2850 #ifdef _iBCS2 2851 doxtract(char *argv[], int tbl_cnt) 2852 #else 2853 doxtract(char *argv[]) 2854 #endif 2855 { 2856 struct stat xtractbuf; /* stat on file after extracting */ 2857 blkcnt_t blocks; 2858 off_t bytes; 2859 int ofile; 2860 int newfile; /* Does the file already exist */ 2861 int xcnt = 0; /* count # files extracted */ 2862 int fcnt = 0; /* count # files in argv list */ 2863 int dir; 2864 int dirfd = -1; 2865 int cwd = -1; 2866 int rw_sysattr; 2867 int saveerrno; 2868 uid_t Uid; 2869 char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 2870 char dirname[PATH_MAX+1]; 2871 char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 2872 int once = 1; 2873 int error; 2874 int symflag; 2875 int want; 2876 attr_data_t *attrinfo = NULL; /* attribute info */ 2877 acl_t *aclp = NULL; /* acl info */ 2878 char dot[] = "."; /* dirp for using realpath */ 2879 timestruc_t time_zero; /* used for call to doDirTimes */ 2880 int dircreate; 2881 int convflag; 2882 time_zero.tv_sec = 0; 2883 time_zero.tv_nsec = 0; 2884 2885 /* reset Trusted Extensions variables */ 2886 rpath_flag = 0; 2887 lk_rpath_flag = 0; 2888 dir_flag = 0; 2889 mld_flag = 0; 2890 bslundef(&bs_label); 2891 bsllow(&admin_low); 2892 bslhigh(&admin_high); 2893 orig_namep = 0; 2894 2895 dumping = 0; /* for newvol(), et al: we are not writing */ 2896 2897 /* 2898 * Count the number of files that are to be extracted 2899 */ 2900 Uid = getuid(); 2901 2902 #ifdef _iBCS2 2903 initarg(argv, Filefile); 2904 while (nextarg() != NULL) 2905 ++fcnt; 2906 fcnt += tbl_cnt; 2907 #endif /* _iBCS2 */ 2908 2909 for (;;) { 2910 convflag = 0; 2911 symflag = 0; 2912 dir = 0; 2913 Hiddendir = 0; 2914 rw_sysattr = 0; 2915 ofile = -1; 2916 2917 if (dirfd != -1) { 2918 (void) close(dirfd); 2919 dirfd = -1; 2920 } 2921 if (ofile != -1) { 2922 if (close(ofile) != 0) 2923 vperror(2, gettext("close error")); 2924 } 2925 2926 #if defined(O_XATTR) 2927 if (cwd != -1) { 2928 rest_cwd(&cwd); 2929 } 2930 #endif 2931 2932 /* namep is set by wantit to point to the full name */ 2933 if ((want = wantit(argv, &namep, &dirp, &comp, 2934 &attrinfo)) == 0) { 2935 #if defined(O_XATTR) 2936 if (xattrp != NULL) { 2937 free(xattrhead); 2938 xattrp = NULL; 2939 xattr_linkp = NULL; 2940 xattrhead = NULL; 2941 } 2942 #endif 2943 continue; 2944 } 2945 if (want == -1) 2946 break; 2947 2948 /* Trusted Extensions */ 2949 /* 2950 * During tar extract (x): 2951 * If the pathname of the restored file has been 2952 * reconstructed from the ancillary file, 2953 * use it to process the normal file. 2954 */ 2955 if (mld_flag) { /* Skip over .MLD. directory */ 2956 mld_flag = 0; 2957 passtape(); 2958 continue; 2959 } 2960 orig_namep = namep; /* save original */ 2961 if (rpath_flag) { 2962 namep = real_path; /* use zone path */ 2963 comp = real_path; /* use zone path */ 2964 dirp = dot; /* work from the top */ 2965 rpath_flag = 0; /* reset */ 2966 } 2967 2968 if (dirfd != -1) 2969 (void) close(dirfd); 2970 2971 (void) strcpy(&dirname[0], namep); 2972 dircreate = checkdir(&dirname[0]); 2973 2974 #if defined(O_XATTR) 2975 if (xattrp != NULL) { 2976 int rc; 2977 2978 if (((cwd = save_cwd()) == -1) || 2979 ((rc = open_attr_dir(comp, dirp, cwd, 2980 attrinfo)) != ATTR_OK)) { 2981 if (cwd == -1) { 2982 vperror(0, gettext( 2983 "unable to save current working " 2984 "directory while processing " 2985 "attribute %s of %s"), 2986 dirp, attrinfo->attr_path); 2987 } else if (rc != ATTR_SKIP) { 2988 (void) fprintf(vfile, 2989 gettext("tar: cannot open " 2990 "%sattribute %s of file %s: %s\n"), 2991 attrinfo->attr_rw_sysattr ? gettext( 2992 "system ") : "", 2993 comp, dirp, strerror(errno)); 2994 } 2995 free(xattrhead); 2996 xattrp = NULL; 2997 xattr_linkp = NULL; 2998 xattrhead = NULL; 2999 3000 passtape(); 3001 continue; 3002 } else { 3003 dirfd = attrinfo->attr_parentfd; 3004 rw_sysattr = attrinfo->attr_rw_sysattr; 3005 } 3006 } else { 3007 dirfd = open(dirp, O_RDONLY); 3008 } 3009 #else 3010 dirfd = open(dirp, O_RDONLY); 3011 #endif 3012 if (dirfd == -1) { 3013 (void) fprintf(vfile, gettext( 3014 "tar: cannot open %s: %s\n"), 3015 dirp, strerror(errno)); 3016 passtape(); 3017 continue; 3018 } 3019 3020 if (xhdr_flgs & _X_LINKPATH) 3021 (void) strcpy(templink, Xtarhdr.x_linkpath); 3022 else { 3023 #if defined(O_XATTR) 3024 if (xattrp && dblock.dbuf.typeflag == '1') { 3025 (void) sprintf(templink, "%.*s", NAMSIZ, 3026 xattrp->h_names); 3027 } else { 3028 (void) sprintf(templink, "%.*s", NAMSIZ, 3029 dblock.dbuf.linkname); 3030 } 3031 #else 3032 (void) sprintf(templink, "%.*s", NAMSIZ, 3033 dblock.dbuf.linkname); 3034 #endif 3035 } 3036 3037 if (Fflag) { 3038 char *s; 3039 3040 if ((s = strrchr(namep, '/')) == 0) 3041 s = namep; 3042 3043 else 3044 s++; 3045 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 3046 passtape(); 3047 continue; 3048 } 3049 } 3050 3051 if (checkw('x', namep) == 0) { 3052 passtape(); 3053 continue; 3054 } 3055 if (once) { 3056 if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 3057 if (geteuid() == (uid_t)0) { 3058 checkflag = 1; 3059 pflag = 1; 3060 } else { 3061 /* get file creation mask */ 3062 Oumask = umask(0); 3063 (void) umask(Oumask); 3064 } 3065 once = 0; 3066 } else { 3067 if (geteuid() == (uid_t)0) { 3068 pflag = 1; 3069 checkflag = 2; 3070 } 3071 if (!pflag) { 3072 /* get file creation mask */ 3073 Oumask = umask(0); 3074 (void) umask(Oumask); 3075 } 3076 once = 0; 3077 } 3078 } 3079 3080 #if defined(O_XATTR) 3081 /* 3082 * Handle extraction of hidden attr dir. 3083 * Dir is automatically created, we only 3084 * need to update mode and perm's. 3085 */ 3086 if ((xattrp != NULL) && Hiddendir == 1) { 3087 bytes = stbuf.st_size; 3088 blocks = TBLOCKS(bytes); 3089 if (vflag) { 3090 (void) fprintf(vfile, 3091 "x %s%s%s, %" FMT_off_t " bytes, ", namep, 3092 gettext(" attribute "), 3093 xattrapath, bytes); 3094 if (NotTape) 3095 (void) fprintf(vfile, 3096 "%" FMT_blkcnt_t "K\n", K(blocks)); 3097 else 3098 (void) fprintf(vfile, gettext("%" 3099 FMT_blkcnt_t " tape blocks\n"), 3100 blocks); 3101 } 3102 3103 /* 3104 * Set the permissions and mode of the attribute 3105 * unless the attribute is a system attribute (can't 3106 * successfully do this) or the hidden attribute 3107 * directory (".") of an attribute (when the attribute 3108 * is restored, the hidden attribute directory of an 3109 * attribute is transient). Note: when the permissions 3110 * and mode are set for the hidden attribute directory 3111 * of a file on a system supporting extended system 3112 * attributes, even though it returns successfully, it 3113 * will not have any affect since the attribute 3114 * directory is transient. 3115 */ 3116 if (attrinfo->attr_parent == NULL) { 3117 if (fchownat(dirfd, ".", stbuf.st_uid, 3118 stbuf.st_gid, 0) != 0) { 3119 vperror(0, gettext( 3120 "%s%s%s: failed to set ownership " 3121 "of attribute directory"), namep, 3122 gettext(" attribute "), xattrapath); 3123 } 3124 3125 if (fchmod(dirfd, stbuf.st_mode) != 0) { 3126 vperror(0, gettext( 3127 "%s%s%s: failed to set permissions " 3128 "of attribute directory"), namep, 3129 gettext(" attribute "), xattrapath); 3130 } 3131 } 3132 goto filedone; 3133 } 3134 #endif 3135 3136 if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 3137 dir = 1; 3138 if (vflag) { 3139 (void) fprintf(vfile, "x %s, 0 bytes, ", 3140 &dirname[0]); 3141 if (NotTape) 3142 (void) fprintf(vfile, "0K\n"); 3143 else 3144 (void) fprintf(vfile, gettext("%" 3145 FMT_blkcnt_t " tape blocks\n"), 3146 (blkcnt_t)0); 3147 } 3148 goto filedone; 3149 } 3150 3151 if (dblock.dbuf.typeflag == '6') { /* FIFO */ 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_IFIFO), 3173 (int)Gen.g_devmajor) < 0) { 3174 vperror(0, gettext("%s: mknod failed"), namep); 3175 continue; 3176 } 3177 bytes = stbuf.st_size; 3178 blocks = TBLOCKS(bytes); 3179 if (vflag) { 3180 (void) fprintf(vfile, "x %s, %" FMT_off_t 3181 " bytes, ", namep, bytes); 3182 if (NotTape) 3183 (void) fprintf(vfile, "%" FMT_blkcnt_t 3184 "K\n", K(blocks)); 3185 else 3186 (void) fprintf(vfile, gettext("%" 3187 FMT_blkcnt_t " tape blocks\n"), 3188 blocks); 3189 } 3190 goto filedone; 3191 } 3192 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */ 3193 if (rmdir(namep) < 0) { 3194 if (errno == ENOTDIR) 3195 (void) unlink(namep); 3196 } 3197 linkp = templink; 3198 if (*linkp != NULL) { 3199 if (Aflag && *linkp == '/') 3200 linkp++; 3201 if (link(linkp, namep) < 0) { 3202 (void) fprintf(stderr, gettext( 3203 "tar: %s: cannot link\n"), namep); 3204 continue; 3205 } 3206 if (vflag) 3207 (void) fprintf(vfile, gettext( 3208 "x %s linked to %s\n"), namep, 3209 linkp); 3210 xcnt++; /* increment # files extracted */ 3211 continue; 3212 } 3213 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR), 3214 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3215 vperror(0, gettext( 3216 "%s: mknod failed"), namep); 3217 continue; 3218 } 3219 bytes = stbuf.st_size; 3220 blocks = TBLOCKS(bytes); 3221 if (vflag) { 3222 (void) fprintf(vfile, "x %s, %" FMT_off_t 3223 " bytes, ", namep, bytes); 3224 if (NotTape) 3225 (void) fprintf(vfile, "%" FMT_blkcnt_t 3226 "K\n", K(blocks)); 3227 else 3228 (void) fprintf(vfile, gettext("%" 3229 FMT_blkcnt_t " tape blocks\n"), 3230 blocks); 3231 } 3232 goto filedone; 3233 } else if (dblock.dbuf.typeflag == '3' && Uid) { 3234 (void) fprintf(stderr, gettext( 3235 "Can't create special %s\n"), namep); 3236 continue; 3237 } 3238 3239 /* BLOCK SPECIAL */ 3240 3241 if (dblock.dbuf.typeflag == '4' && !Uid) { 3242 if (rmdir(namep) < 0) { 3243 if (errno == ENOTDIR) 3244 (void) unlink(namep); 3245 } 3246 linkp = templink; 3247 if (*linkp != NULL) { 3248 if (Aflag && *linkp == '/') 3249 linkp++; 3250 if (link(linkp, namep) < 0) { 3251 (void) fprintf(stderr, gettext( 3252 "tar: %s: cannot link\n"), namep); 3253 continue; 3254 } 3255 if (vflag) 3256 (void) fprintf(vfile, gettext( 3257 "x %s linked to %s\n"), namep, 3258 linkp); 3259 xcnt++; /* increment # files extracted */ 3260 continue; 3261 } 3262 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK), 3263 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 3264 vperror(0, gettext("%s: mknod failed"), namep); 3265 continue; 3266 } 3267 bytes = stbuf.st_size; 3268 blocks = TBLOCKS(bytes); 3269 if (vflag) { 3270 (void) fprintf(vfile, gettext("x %s, %" 3271 FMT_off_t " bytes, "), namep, bytes); 3272 if (NotTape) 3273 (void) fprintf(vfile, "%" FMT_blkcnt_t 3274 "K\n", K(blocks)); 3275 else 3276 (void) fprintf(vfile, gettext("%" 3277 FMT_blkcnt_t " tape blocks\n"), 3278 blocks); 3279 } 3280 goto filedone; 3281 } else if (dblock.dbuf.typeflag == '4' && Uid) { 3282 (void) fprintf(stderr, 3283 gettext("Can't create special %s\n"), namep); 3284 continue; 3285 } 3286 if (dblock.dbuf.typeflag == '2') { /* symlink */ 3287 if ((Tflag) && (lk_rpath_flag == 1)) 3288 linkp = lk_real_path; 3289 else 3290 linkp = templink; 3291 if (Aflag && *linkp == '/') 3292 linkp++; 3293 if (rmdir(namep) < 0) { 3294 if (errno == ENOTDIR) 3295 (void) unlink(namep); 3296 } 3297 if (symlink(linkp, namep) < 0) { 3298 vperror(0, gettext("%s: symbolic link failed"), 3299 namep); 3300 continue; 3301 } 3302 if (vflag) 3303 (void) fprintf(vfile, gettext( 3304 "x %s symbolic link to %s\n"), 3305 namep, linkp); 3306 3307 symflag = AT_SYMLINK_NOFOLLOW; 3308 goto filedone; 3309 } 3310 if (dblock.dbuf.typeflag == '1') { 3311 linkp = templink; 3312 if (Aflag && *linkp == '/') 3313 linkp++; 3314 if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) { 3315 if (errno == ENOTDIR) 3316 (void) unlinkat(dirfd, comp, 0); 3317 } 3318 #if defined(O_XATTR) 3319 if (xattrp && xattr_linkp) { 3320 if (fchdir(dirfd) < 0) { 3321 vperror(0, gettext( 3322 "Cannot fchdir to attribute " 3323 "directory %s"), 3324 (attrinfo->attr_parent == NULL) ? 3325 dirp : attrinfo->attr_parent); 3326 exit(1); 3327 } 3328 3329 error = link(xattr_linkaname, xattrapath); 3330 } else { 3331 error = link(linkp, namep); 3332 } 3333 #else 3334 error = link(linkp, namep); 3335 #endif 3336 3337 if (error < 0) { 3338 (void) fprintf(stderr, gettext( 3339 "tar: %s%s%s: cannot link\n"), 3340 namep, (xattr_linkp != NULL) ? 3341 gettext(" attribute ") : "", 3342 (xattr_linkp != NULL) ? 3343 xattrapath : ""); 3344 continue; 3345 } 3346 if (vflag) 3347 (void) fprintf(vfile, gettext( 3348 "x %s%s%s linked to %s%s%s\n"), namep, 3349 (xattr_linkp != NULL) ? 3350 gettext(" attribute ") : "", 3351 (xattr_linkp != NULL) ? 3352 xattr_linkaname : "", 3353 linkp, 3354 (xattr_linkp != NULL) ? 3355 gettext(" attribute ") : "", 3356 (xattr_linkp != NULL) ? xattrapath : ""); 3357 xcnt++; /* increment # files extracted */ 3358 #if defined(O_XATTR) 3359 if (xattrp != NULL) { 3360 free(xattrhead); 3361 xattrp = NULL; 3362 xattr_linkp = NULL; 3363 xattrhead = NULL; 3364 } 3365 #endif 3366 continue; 3367 } 3368 3369 /* REGULAR FILES */ 3370 3371 if (convtoreg(stbuf.st_size)) { 3372 convflag = 1; 3373 if (errflag) { 3374 (void) fprintf(stderr, gettext( 3375 "tar: %s: typeflag '%c' not recognized\n"), 3376 namep, dblock.dbuf.typeflag); 3377 done(1); 3378 } else { 3379 (void) fprintf(stderr, gettext( 3380 "tar: %s: typeflag '%c' not recognized, " 3381 "converting to regular file\n"), namep, 3382 dblock.dbuf.typeflag); 3383 Errflg = 1; 3384 } 3385 } 3386 if (dblock.dbuf.typeflag == '0' || 3387 dblock.dbuf.typeflag == NULL || convflag) { 3388 delete_target(dirfd, comp, namep); 3389 linkp = templink; 3390 if (*linkp != NULL) { 3391 if (Aflag && *linkp == '/') 3392 linkp++; 3393 if (link(linkp, comp) < 0) { 3394 (void) fprintf(stderr, gettext( 3395 "tar: %s: cannot link\n"), namep); 3396 continue; 3397 } 3398 if (vflag) 3399 (void) fprintf(vfile, gettext( 3400 "x %s linked to %s\n"), comp, 3401 linkp); 3402 xcnt++; /* increment # files extracted */ 3403 #if defined(O_XATTR) 3404 if (xattrp != NULL) { 3405 free(xattrhead); 3406 xattrp = NULL; 3407 xattr_linkp = NULL; 3408 xattrhead = NULL; 3409 } 3410 #endif 3411 continue; 3412 } 3413 newfile = ((fstatat(dirfd, comp, 3414 &xtractbuf, 0) == -1) ? TRUE : FALSE); 3415 ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC, 3416 stbuf.st_mode & MODEMASK); 3417 saveerrno = errno; 3418 3419 #if defined(O_XATTR) 3420 if (xattrp != NULL) { 3421 if (ofile < 0) { 3422 ofile = retry_open_attr(dirfd, cwd, 3423 dirp, attrinfo->attr_parent, comp, 3424 O_RDWR|O_CREAT|O_TRUNC, 3425 stbuf.st_mode & MODEMASK); 3426 } 3427 } 3428 #endif 3429 if (ofile < 0) { 3430 errno = saveerrno; 3431 (void) fprintf(stderr, gettext( 3432 "tar: %s%s%s%s - cannot create\n"), 3433 (xattrp == NULL) ? "" : (rw_sysattr ? 3434 gettext("system attribure ") : 3435 gettext("attribute ")), 3436 (xattrp == NULL) ? "" : xattrapath, 3437 (xattrp == NULL) ? "" : gettext(" of "), 3438 (xattrp == NULL) ? comp : namep); 3439 if (errflag) 3440 done(1); 3441 else 3442 Errflg = 1; 3443 #if defined(O_XATTR) 3444 if (xattrp != NULL) { 3445 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 3446 free(xattrhead); 3447 xattrp = NULL; 3448 xattr_linkp = NULL; 3449 xattrhead = NULL; 3450 } 3451 #endif 3452 passtape(); 3453 continue; 3454 } 3455 3456 if (Tflag && (check_ext_attr(namep) == 0)) { 3457 if (errflag) 3458 done(1); 3459 else 3460 Errflg = 1; 3461 passtape(); 3462 continue; 3463 } 3464 3465 if (extno != 0) { /* file is in pieces */ 3466 if (extotal < 1 || extotal > MAXEXT) 3467 (void) fprintf(stderr, gettext( 3468 "tar: ignoring bad extent info for " 3469 "%s%s%s%s\n"), 3470 (xattrp == NULL) ? "" : (rw_sysattr ? 3471 gettext("system attribute ") : 3472 gettext("attribute ")), 3473 (xattrp == NULL) ? "" : xattrapath, 3474 (xattrp == NULL) ? "" : gettext(" of "), 3475 (xattrp == NULL) ? comp : namep); 3476 else { 3477 /* extract it */ 3478 (void) xsfile(rw_sysattr, ofile); 3479 } 3480 } 3481 extno = 0; /* let everyone know file is not split */ 3482 bytes = stbuf.st_size; 3483 blocks = TBLOCKS(bytes); 3484 if (vflag) { 3485 (void) fprintf(vfile, 3486 "x %s%s%s, %" FMT_off_t " bytes, ", 3487 (xattrp == NULL) ? "" : dirp, 3488 (xattrp == NULL) ? "" : (rw_sysattr ? 3489 gettext(" system attribute ") : 3490 gettext(" attribute ")), 3491 (xattrp == NULL) ? namep : xattrapath, bytes); 3492 if (NotTape) 3493 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 3494 K(blocks)); 3495 else 3496 (void) fprintf(vfile, gettext("%" 3497 FMT_blkcnt_t " tape blocks\n"), blocks); 3498 } 3499 3500 if (xblocks(rw_sysattr, bytes, ofile) != 0) { 3501 #if defined(O_XATTR) 3502 if (xattrp != NULL) { 3503 free(xattrhead); 3504 xattrp = NULL; 3505 xattr_linkp = NULL; 3506 xattrhead = NULL; 3507 } 3508 #endif 3509 continue; 3510 } 3511 filedone: 3512 if (mflag == 0 && !symflag) { 3513 if (dir) 3514 doDirTimes(namep, stbuf.st_mtim); 3515 3516 else 3517 #if defined(O_XATTR) 3518 if (xattrp != NULL) { 3519 /* 3520 * Set the time on the attribute unless 3521 * the attribute is a system attribute 3522 * (can't successfully do this) or the 3523 * hidden attribute directory, "." (the 3524 * time on the hidden attribute 3525 * directory will be updated when 3526 * attributes are restored, otherwise 3527 * it's transient). 3528 */ 3529 if (!rw_sysattr && (Hiddendir == 0)) { 3530 setPathTimes(dirfd, comp, 3531 stbuf.st_mtim); 3532 } 3533 } else 3534 setPathTimes(dirfd, comp, 3535 stbuf.st_mtim); 3536 #else 3537 setPathTimes(dirfd, comp, stbuf.st_mtim); 3538 #endif 3539 } 3540 3541 /* moved this code from above */ 3542 if (pflag && !symflag && Hiddendir == 0) { 3543 if (xattrp != NULL) 3544 (void) fchmod(ofile, stbuf.st_mode & MODEMASK); 3545 else 3546 (void) chmod(namep, stbuf.st_mode & MODEMASK); 3547 } 3548 3549 3550 /* 3551 * Because ancillary file preceeds the normal file, 3552 * acl info may have been retrieved (in aclp). 3553 * All file types are directed here (go filedone). 3554 * Always restore ACLs if there are ACLs. 3555 */ 3556 if (aclp != NULL) { 3557 int ret; 3558 3559 #if defined(O_XATTR) 3560 if (xattrp != NULL) { 3561 if (Hiddendir) 3562 ret = facl_set(dirfd, aclp); 3563 else 3564 ret = facl_set(ofile, aclp); 3565 } else { 3566 ret = acl_set(namep, aclp); 3567 } 3568 #else 3569 ret = acl_set(namep, aclp); 3570 #endif 3571 if (ret < 0) { 3572 if (pflag) { 3573 (void) fprintf(stderr, gettext( 3574 "%s%s%s%s: failed to set acl " 3575 "entries\n"), namep, 3576 (xattrp == NULL) ? "" : 3577 (rw_sysattr ? gettext( 3578 " system attribute ") : 3579 gettext(" attribute ")), 3580 (xattrp == NULL) ? "" : 3581 xattrapath); 3582 } 3583 /* else: silent and continue */ 3584 } 3585 acl_free(aclp); 3586 aclp = NULL; 3587 } 3588 3589 if (!oflag) 3590 resugname(dirfd, comp, symflag); /* set file ownership */ 3591 3592 if (pflag && newfile == TRUE && !dir && 3593 (dblock.dbuf.typeflag == '0' || 3594 dblock.dbuf.typeflag == NULL || 3595 convflag || dblock.dbuf.typeflag == '1')) { 3596 if (fstat(ofile, &xtractbuf) == -1) 3597 (void) fprintf(stderr, gettext( 3598 "tar: cannot stat extracted file " 3599 "%s%s%s%s\n"), 3600 (xattrp == NULL) ? "" : (rw_sysattr ? 3601 gettext("system attribute ") : 3602 gettext("attribute ")), 3603 (xattrp == NULL) ? "" : xattrapath, 3604 (xattrp == NULL) ? "" : 3605 gettext(" of "), namep); 3606 3607 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT)) 3608 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) { 3609 (void) fprintf(stderr, gettext( 3610 "tar: warning - file permissions have " 3611 "changed for %s%s%s%s (are 0%o, should be " 3612 "0%o)\n"), 3613 (xattrp == NULL) ? "" : (rw_sysattr ? 3614 gettext("system attribute ") : 3615 gettext("attribute ")), 3616 (xattrp == NULL) ? "" : xattrapath, 3617 (xattrp == NULL) ? "" : 3618 gettext(" of "), namep, 3619 xtractbuf.st_mode, stbuf.st_mode); 3620 3621 } 3622 } 3623 #if defined(O_XATTR) 3624 if (xattrp != NULL) { 3625 free(xattrhead); 3626 xattrp = NULL; 3627 xattr_linkp = NULL; 3628 xattrhead = NULL; 3629 } 3630 #endif 3631 3632 if (ofile != -1) { 3633 (void) close(dirfd); 3634 dirfd = -1; 3635 if (close(ofile) != 0) 3636 vperror(2, gettext("close error")); 3637 ofile = -1; 3638 } 3639 xcnt++; /* increment # files extracted */ 3640 } 3641 3642 /* 3643 * Process ancillary file. 3644 * 3645 */ 3646 3647 if (dblock.dbuf.typeflag == 'A') { /* acl info */ 3648 char buf[TBLOCK]; 3649 char *secp; 3650 char *tp; 3651 int attrsize; 3652 int cnt; 3653 3654 /* reset Trusted Extensions flags */ 3655 dir_flag = 0; 3656 mld_flag = 0; 3657 lk_rpath_flag = 0; 3658 rpath_flag = 0; 3659 3660 if (pflag) { 3661 bytes = stbuf.st_size; 3662 if ((secp = malloc((int)bytes)) == NULL) { 3663 (void) fprintf(stderr, gettext( 3664 "Insufficient memory for acl\n")); 3665 passtape(); 3666 continue; 3667 } 3668 tp = secp; 3669 blocks = TBLOCKS(bytes); 3670 3671 /* 3672 * Display a line for each ancillary file. 3673 */ 3674 if (vflag && Tflag) 3675 (void) fprintf(vfile, "x %s(A), %" 3676 FMT_blkcnt_t " bytes, %" 3677 FMT_blkcnt_t " tape blocks\n", 3678 namep, bytes, blocks); 3679 3680 while (blocks-- > 0) { 3681 readtape(buf); 3682 if (bytes <= TBLOCK) { 3683 (void) memcpy(tp, buf, 3684 (size_t)bytes); 3685 break; 3686 } else { 3687 (void) memcpy(tp, buf, 3688 TBLOCK); 3689 tp += TBLOCK; 3690 } 3691 bytes -= TBLOCK; 3692 } 3693 bytes = stbuf.st_size; 3694 /* got all attributes in secp */ 3695 tp = secp; 3696 do { 3697 attr = (struct sec_attr *)tp; 3698 switch (attr->attr_type) { 3699 case UFSD_ACL: 3700 case ACE_ACL: 3701 (void) sscanf(attr->attr_len, 3702 "%7o", 3703 (uint_t *) 3704 &cnt); 3705 /* header is 8 */ 3706 attrsize = 8 + (int)strlen( 3707 &attr->attr_info[0]) + 1; 3708 error = 3709 acl_fromtext( 3710 &attr->attr_info[0], &aclp); 3711 3712 if (error != 0) { 3713 (void) fprintf(stderr, 3714 gettext( 3715 "aclfromtext " 3716 "failed: %s\n"), 3717 acl_strerror( 3718 error)); 3719 bytes -= attrsize; 3720 break; 3721 } 3722 if (acl_cnt(aclp) != cnt) { 3723 (void) fprintf(stderr, 3724 gettext( 3725 "aclcnt error\n")); 3726 bytes -= attrsize; 3727 break; 3728 } 3729 bytes -= attrsize; 3730 break; 3731 3732 /* Trusted Extensions */ 3733 3734 case DIR_TYPE: 3735 case LBL_TYPE: 3736 case APRIV_TYPE: 3737 case FPRIV_TYPE: 3738 case COMP_TYPE: 3739 case LK_COMP_TYPE: 3740 case ATTR_FLAG_TYPE: 3741 attrsize = 3742 sizeof (struct sec_attr) + 3743 strlen(&attr->attr_info[0]); 3744 bytes -= attrsize; 3745 if (Tflag) 3746 extract_attr(&namep, 3747 attr); 3748 break; 3749 3750 default: 3751 (void) fprintf(stderr, gettext( 3752 "unrecognized attr" 3753 " type\n")); 3754 bytes = (off_t)0; 3755 break; 3756 } 3757 3758 /* next attributes */ 3759 tp += attrsize; 3760 } while (bytes != 0); 3761 free(secp); 3762 } else { 3763 passtape(); 3764 } 3765 } /* acl */ 3766 3767 } /* for */ 3768 3769 /* 3770 * Ensure that all the directories still on the directory stack 3771 * get their modification times set correctly by flushing the 3772 * stack. 3773 */ 3774 3775 doDirTimes(NULL, time_zero); 3776 3777 #if defined(O_XATTR) 3778 if (xattrp != NULL) { 3779 free(xattrhead); 3780 xattrp = NULL; 3781 xattr_linkp = NULL; 3782 xattrhead = NULL; 3783 } 3784 #endif 3785 3786 /* 3787 * Check if the number of files extracted is different from the 3788 * number of files listed on the command line 3789 */ 3790 if (fcnt > xcnt) { 3791 (void) fprintf(stderr, 3792 gettext("tar: %d file(s) not extracted\n"), 3793 fcnt-xcnt); 3794 Errflg = 1; 3795 } 3796 } 3797 3798 /* 3799 * xblocks extract file/extent from tape to output file 3800 * 3801 * xblocks(issysattr, bytes, ofile); 3802 * 3803 * issysattr flag set if the files being extracted 3804 * is an extended system attribute file. 3805 * unsigned long long bytes size of extent or file to be extracted 3806 * ofile output file 3807 * 3808 * called by doxtract() and xsfile() 3809 */ 3810 3811 static int 3812 xblocks(int issysattr, off_t bytes, int ofile) 3813 { 3814 char *buf; 3815 char tempname[NAMSIZ+1]; 3816 size_t maxwrite; 3817 size_t bytesread; 3818 size_t piosize; /* preferred I/O size */ 3819 struct stat tsbuf; 3820 3821 /* Don't need to do anything if this is a zero size file */ 3822 if (bytes <= 0) { 3823 return (0); 3824 } 3825 3826 /* 3827 * To figure out the size of the buffer used to accumulate data 3828 * from readtape() and to write to the file, we need to determine 3829 * the largest chunk of data to be written to the file at one time. 3830 * This is determined based on the smallest of the following two 3831 * things: 3832 * 1) The size of the archived file. 3833 * 2) The preferred I/O size of the file. 3834 */ 3835 if (issysattr || (bytes <= TBLOCK)) { 3836 /* 3837 * Writes to system attribute files must be 3838 * performed in one operation. 3839 */ 3840 maxwrite = bytes; 3841 } else { 3842 /* 3843 * fstat() the file to get the preferred I/O size. 3844 * If it fails, then resort back to just writing 3845 * one block at a time. 3846 */ 3847 if (fstat(ofile, &tsbuf) == 0) { 3848 piosize = tsbuf.st_blksize; 3849 } else { 3850 piosize = TBLOCK; 3851 } 3852 maxwrite = min(bytes, piosize); 3853 } 3854 3855 /* 3856 * The buffer used to accumulate the data for the write operation 3857 * needs to be the maximum number of bytes to be written rounded up 3858 * to the nearest TBLOCK since readtape reads one block at a time. 3859 */ 3860 if ((buf = malloc(TBLOCKS(maxwrite) * TBLOCK)) == NULL) { 3861 fatal(gettext("cannot allocate buffer")); 3862 } 3863 3864 while (bytes > 0) { 3865 3866 /* 3867 * readtape() obtains one block (TBLOCK) of data at a time. 3868 * Accumulate as many blocks of data in buf as we can write 3869 * in one operation. 3870 */ 3871 for (bytesread = 0; bytesread < maxwrite; bytesread += TBLOCK) { 3872 readtape(buf + bytesread); 3873 } 3874 3875 if (write(ofile, buf, maxwrite) < 0) { 3876 int saveerrno = errno; 3877 3878 if (xhdr_flgs & _X_PATH) 3879 (void) strlcpy(tempname, Xtarhdr.x_path, 3880 sizeof (tempname)); 3881 else 3882 (void) sprintf(tempname, "%.*s", NAMSIZ, 3883 dblock.dbuf.name); 3884 /* 3885 * If the extended system attribute being extracted 3886 * contains attributes that the user needs privileges 3887 * for, then just display a warning message, skip 3888 * the extraction of this file, and return. 3889 */ 3890 if ((saveerrno == EPERM) && issysattr) { 3891 (void) fprintf(stderr, gettext( 3892 "tar: unable to extract system attribute " 3893 "%s: insufficient privileges\n"), tempname); 3894 Errflg = 1; 3895 (void) free(buf); 3896 return (1); 3897 } else { 3898 (void) fprintf(stderr, gettext( 3899 "tar: %s: HELP - extract write error\n"), 3900 tempname); 3901 done(2); 3902 } 3903 } 3904 bytes -= maxwrite; 3905 3906 /* 3907 * If we've reached this point and there is still data 3908 * to be written, maxwrite had to have been determined 3909 * by the preferred I/O size. If the number of bytes 3910 * left to write is smaller than the preferred I/O size, 3911 * then we're about to do our final write to the file, so 3912 * just set maxwrite to the number of bytes left to write. 3913 */ 3914 if ((bytes > 0) && (bytes < maxwrite)) { 3915 maxwrite = bytes; 3916 } 3917 } 3918 free(buf); 3919 3920 return (0); 3921 } 3922 3923 /* 3924 * xsfile extract split file 3925 * 3926 * xsfile(ofd); ofd = output file descriptor 3927 * 3928 * file extracted and put in ofd via xblocks() 3929 * 3930 * NOTE: only called by doxtract() to extract one large file 3931 */ 3932 3933 static union hblock savedblock; /* to ensure same file across volumes */ 3934 3935 static int 3936 xsfile(int issysattr, int ofd) 3937 { 3938 int i, c; 3939 int sysattrerr = 0; 3940 char name[PATH_MAX+1]; /* holds name for diagnostics */ 3941 int extents, totalext; 3942 off_t bytes, totalbytes; 3943 3944 if (xhdr_flgs & _X_PATH) 3945 (void) strcpy(name, Xtarhdr.x_path); 3946 else 3947 (void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name); 3948 3949 totalbytes = (off_t)0; /* in case we read in half the file */ 3950 totalext = 0; /* these keep count */ 3951 3952 (void) fprintf(stderr, gettext( 3953 "tar: %s split across %d volumes\n"), name, extotal); 3954 3955 /* make sure we do extractions in order */ 3956 if (extno != 1) { /* starting in middle of file? */ 3957 (void) printf(gettext( 3958 "tar: first extent read is not #1\n" 3959 "OK to read file beginning with extent #%d (%s/%s) ? "), 3960 extno, yesstr, nostr); 3961 if (yes() == 0) { 3962 canit: 3963 passtape(); 3964 if (close(ofd) != 0) 3965 vperror(2, gettext("close error")); 3966 if (sysattrerr) { 3967 return (1); 3968 } else { 3969 return (0); 3970 } 3971 } 3972 } 3973 extents = extotal; 3974 i = extno; 3975 /*CONSTCOND*/ 3976 while (1) { 3977 if (xhdr_flgs & _X_SIZE) { 3978 bytes = extsize; 3979 } else { 3980 bytes = stbuf.st_size; 3981 } 3982 3983 if (vflag) 3984 (void) fprintf(vfile, "+++ x %s [extent #%d], %" 3985 FMT_off_t " bytes, %ldK\n", name, extno, bytes, 3986 (long)K(TBLOCKS(bytes))); 3987 if (xblocks(issysattr, bytes, ofd) != 0) { 3988 sysattrerr = 1; 3989 goto canit; 3990 } 3991 3992 totalbytes += bytes; 3993 totalext++; 3994 if (++i > extents) 3995 break; 3996 3997 /* get next volume and verify it's the right one */ 3998 copy(&savedblock, &dblock); 3999 tryagain: 4000 newvol(); 4001 xhdr_flgs = 0; 4002 getdir(); 4003 if (Xhdrflag > 0) 4004 (void) get_xdata(); /* Get x-header & regular hdr */ 4005 if ((dblock.dbuf.typeflag != 'A') && (xhdr_flgs != 0)) { 4006 load_info_from_xtarhdr(xhdr_flgs, &Xtarhdr); 4007 xhdr_flgs |= _X_XHDR; 4008 } 4009 if (endtape()) { /* seemingly empty volume */ 4010 (void) fprintf(stderr, gettext( 4011 "tar: first record is null\n")); 4012 asknicely: 4013 (void) fprintf(stderr, gettext( 4014 "tar: need volume with extent #%d of %s\n"), 4015 i, name); 4016 goto tryagain; 4017 } 4018 if (notsame()) { 4019 (void) fprintf(stderr, gettext( 4020 "tar: first file on that volume is not " 4021 "the same file\n")); 4022 goto asknicely; 4023 } 4024 if (i != extno) { 4025 (void) fprintf(stderr, gettext( 4026 "tar: extent #%d received out of order\ntar: " 4027 "should be #%d\n"), extno, i); 4028 (void) fprintf(stderr, gettext( 4029 "Ignore error, Abort this file, or " 4030 "load New volume (i/a/n) ? ")); 4031 c = response(); 4032 if (c == 'a') 4033 goto canit; 4034 if (c != 'i') /* default to new volume */ 4035 goto asknicely; 4036 i = extno; /* okay, start from there */ 4037 } 4038 } 4039 if (vflag) 4040 (void) fprintf(vfile, gettext( 4041 "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"), 4042 name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes))); 4043 4044 return (0); 4045 } 4046 4047 4048 /* 4049 * notsame() check if extract file extent is invalid 4050 * 4051 * returns true if anything differs between savedblock and dblock 4052 * except extno (extent number), checksum, or size (extent size). 4053 * Determines if this header belongs to the same file as the one we're 4054 * extracting. 4055 * 4056 * NOTE: though rather bulky, it is only called once per file 4057 * extension, and it can withstand changes in the definition 4058 * of the header structure. 4059 * 4060 * WARNING: this routine is local to xsfile() above 4061 */ 4062 4063 static int 4064 notsame(void) 4065 { 4066 return ( 4067 (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) || 4068 (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) || 4069 (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) || 4070 (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) || 4071 (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) || 4072 (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) || 4073 (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) || 4074 (savedblock.dbuf.extotal != dblock.dbuf.extotal) || 4075 (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize))); 4076 } 4077 4078 static void 4079 #ifdef _iBCS2 4080 dotable(char *argv[], int tbl_cnt) 4081 #else 4082 dotable(char *argv[]) 4083 #endif 4084 4085 { 4086 int tcnt; /* count # files tabled */ 4087 int fcnt; /* count # files in argv list */ 4088 char *namep, *dirp, *comp; 4089 int want; 4090 char aclchar = ' '; /* either blank or '+' */ 4091 char templink[PATH_MAX+1]; 4092 attr_data_t *attrinfo = NULL; 4093 4094 dumping = 0; 4095 4096 /* if not on magtape, maximize seek speed */ 4097 if (NotTape && !bflag) { 4098 #if SYS_BLOCK > TBLOCK 4099 nblock = SYS_BLOCK / TBLOCK; 4100 #else 4101 nblock = 1; 4102 #endif 4103 } 4104 /* 4105 * Count the number of files that are to be tabled 4106 */ 4107 fcnt = tcnt = 0; 4108 4109 #ifdef _iBCS2 4110 initarg(argv, Filefile); 4111 while (nextarg() != NULL) 4112 ++fcnt; 4113 fcnt += tbl_cnt; 4114 #endif /* _iBCS2 */ 4115 4116 for (;;) { 4117 4118 /* namep is set by wantit to point to the full name */ 4119 if ((want = wantit(argv, &namep, &dirp, &comp, &attrinfo)) == 0) 4120 continue; 4121 if (want == -1) 4122 break; 4123 if (dblock.dbuf.typeflag != 'A') 4124 ++tcnt; 4125 4126 /* 4127 * ACL support: 4128 * aclchar is introduced to indicate if there are 4129 * acl entries. longt() now takes one extra argument. 4130 */ 4131 if (vflag) { 4132 if (dblock.dbuf.typeflag == 'A') { 4133 aclchar = '+'; 4134 passtape(); 4135 continue; 4136 } 4137 longt(&stbuf, aclchar); 4138 aclchar = ' '; 4139 } 4140 4141 4142 #if defined(O_XATTR) 4143 if (xattrp != NULL) { 4144 int issysattr; 4145 char *bn = basename(attrinfo->attr_path); 4146 4147 /* 4148 * We could use sysattr_type() to test whether or not 4149 * the attribute we are processing is really an 4150 * extended system attribute, which as of this writing 4151 * just does a strcmp(), however, sysattr_type() may 4152 * be changed to issue a pathconf() call instead, which 4153 * would require being changed into the parent attribute 4154 * directory. So instead, just do simple string 4155 * comparisons to see if we are processing an extended 4156 * system attribute. 4157 */ 4158 issysattr = is_sysattr(bn); 4159 4160 (void) printf(gettext("%s %sattribute %s"), 4161 xattrp->h_names, 4162 issysattr ? gettext("system ") : "", 4163 attrinfo->attr_path); 4164 } else { 4165 (void) printf("%s", namep); 4166 } 4167 #else 4168 (void) printf("%s", namep); 4169 #endif 4170 4171 if (extno != 0) { 4172 if (vflag) { 4173 /* keep the '\n' for backwards compatibility */ 4174 (void) fprintf(vfile, gettext( 4175 "\n [extent #%d of %d]"), extno, extotal); 4176 } else { 4177 (void) fprintf(vfile, gettext( 4178 " [extent #%d of %d]"), extno, extotal); 4179 } 4180 } 4181 if (xhdr_flgs & _X_LINKPATH) { 4182 (void) strcpy(templink, Xtarhdr.x_linkpath); 4183 } else { 4184 #if defined(O_XATTR) 4185 if (xattrp != NULL) { 4186 (void) sprintf(templink, 4187 "file %.*s", NAMSIZ, xattrp->h_names); 4188 } else { 4189 (void) sprintf(templink, "%.*s", NAMSIZ, 4190 dblock.dbuf.linkname); 4191 } 4192 #else 4193 (void) sprintf(templink, "%.*s", NAMSIZ, 4194 dblock.dbuf.linkname); 4195 #endif 4196 templink[NAMSIZ] = '\0'; 4197 } 4198 if (dblock.dbuf.typeflag == '1') { 4199 /* 4200 * TRANSLATION_NOTE 4201 * Subject is omitted here. 4202 * Translate this as if 4203 * <subject> linked to %s 4204 */ 4205 #if defined(O_XATTR) 4206 if (xattrp != NULL) { 4207 (void) printf( 4208 gettext(" linked to attribute %s"), 4209 xattr_linkp->h_names + 4210 strlen(xattr_linkp->h_names) + 1); 4211 } else { 4212 (void) printf( 4213 gettext(" linked to %s"), templink); 4214 } 4215 #else 4216 (void) printf( 4217 gettext(" linked to %s"), templink); 4218 4219