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