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