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