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