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