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