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