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(min(stbuf.st_blksize, stbuf.st_size), 2000 (nblock * TBLOCK)); 2001 if ((bigbuf = calloc((unsigned)maxread, sizeof (char))) == 0) { 2002 maxread = TBLOCK; 2003 bigbuf = buf; 2004 } 2005 2006 while (((i = (int) 2007 read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0) && 2008 blocks) { 2009 blkcnt_t nblks; 2010 2011 nblks = ((i-1)/TBLOCK)+1; 2012 if (nblks > blocks) 2013 nblks = blocks; 2014 hint = writetbuf(bigbuf, nblks); 2015 blocks -= nblks; 2016 } 2017 (void) close(infile); 2018 if (bigbuf != buf) 2019 free(bigbuf); 2020 if (i < 0) 2021 vperror(0, gettext("Read error on %s"), longname); 2022 else if (blocks != 0 || i != 0) { 2023 (void) fprintf(stderr, gettext( 2024 "tar: %s: file changed size\n"), longname); 2025 if (errflag) { 2026 exitflag = 1; 2027 Errflg = 1; 2028 } else if (!Dflag) { 2029 Errflg = 1; 2030 } 2031 } 2032 putempty(blocks); 2033 break; 2034 case S_IFIFO: 2035 blocks = TBLOCKS(stbuf.st_size); 2036 stbuf.st_size = (off_t)0; 2037 2038 if (put_link(name, longname, shortname, 2039 prefix, filetype, '6') == 0) { 2040 rc = PUT_AS_LINK; 2041 goto out; 2042 } 2043 tomodes(&stbuf); 2044 2045 while (mulvol && tapepos + blocks + 1 > blocklim) { 2046 if (eflag) { 2047 if (blocks <= blocklim) { 2048 newvol(); 2049 break; 2050 } 2051 (void) fprintf(stderr, gettext( 2052 "tar: Single file cannot fit on volume\n")); 2053 done(3); 2054 } 2055 2056 if (((blocklim - tapepos) >= EXTMIN) && 2057 ((blocks + 1) >= blocklim/10)) { 2058 splitfile(longname, infile, name, 2059 prefix, filetype); 2060 (void) close(dirfd); 2061 (void) close(infile); 2062 goto out; 2063 } 2064 newvol(); 2065 } 2066 #ifdef DEBUG 2067 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2068 blocks); 2069 #endif 2070 if (vflag) { 2071 #ifdef DEBUG 2072 if (NotTape) 2073 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2074 0); 2075 #endif 2076 if (NotTape) 2077 (void) fprintf(vfile, gettext("a %s %" 2078 FMT_blkcnt_t "K\n "), longname, K(blocks)); 2079 else 2080 (void) fprintf(vfile, gettext( 2081 "a %s %" FMT_blkcnt_t " tape blocks\n"), 2082 longname, blocks); 2083 } 2084 if (build_dblock(name, tchar, '6', filetype, 2085 &stbuf, stbuf.st_dev, prefix) != 0) 2086 goto out; 2087 2088 if (put_extra_attributes(longname, shortname, prefix, 2089 filetype, '6') != 0) 2090 goto out; 2091 2092 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2093 dblock.dbuf.typeflag = '6'; 2094 2095 (void) writetbuf((char *)&dblock, 1); 2096 break; 2097 case S_IFCHR: 2098 stbuf.st_size = (off_t)0; 2099 blocks = TBLOCKS(stbuf.st_size); 2100 if (put_link(name, longname, 2101 shortname, prefix, filetype, '3') == 0) { 2102 rc = PUT_AS_LINK; 2103 goto out; 2104 } 2105 tomodes(&stbuf); 2106 2107 while (mulvol && tapepos + blocks + 1 > blocklim) { 2108 if (eflag) { 2109 if (blocks <= blocklim) { 2110 newvol(); 2111 break; 2112 } 2113 (void) fprintf(stderr, gettext( 2114 "tar: Single file cannot fit on volume\n")); 2115 done(3); 2116 } 2117 2118 if (((blocklim - tapepos) >= EXTMIN) && 2119 ((blocks + 1) >= blocklim/10)) { 2120 splitfile(longname, infile, name, 2121 prefix, filetype); 2122 (void) close(dirfd); 2123 goto out; 2124 } 2125 newvol(); 2126 } 2127 #ifdef DEBUG 2128 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2129 blocks); 2130 #endif 2131 if (vflag) { 2132 #ifdef DEBUG 2133 if (NotTape) 2134 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2135 0); 2136 #endif 2137 if (NotTape) 2138 (void) fprintf(vfile, gettext("a %s %" 2139 FMT_blkcnt_t "K\n"), longname, K(blocks)); 2140 else 2141 (void) fprintf(vfile, gettext("a %s %" 2142 FMT_blkcnt_t " tape blocks\n"), longname, 2143 blocks); 2144 } 2145 if (build_dblock(name, tchar, '3', 2146 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2147 goto out; 2148 2149 if (put_extra_attributes(longname, shortname, 2150 prefix, filetype, '3') != 0) 2151 goto out; 2152 2153 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2154 dblock.dbuf.typeflag = '3'; 2155 2156 (void) writetbuf((char *)&dblock, 1); 2157 break; 2158 case S_IFBLK: 2159 stbuf.st_size = (off_t)0; 2160 blocks = TBLOCKS(stbuf.st_size); 2161 if (put_link(name, longname, 2162 shortname, prefix, filetype, '4') == 0) { 2163 rc = PUT_AS_LINK; 2164 goto out; 2165 } 2166 tomodes(&stbuf); 2167 2168 while (mulvol && tapepos + blocks + 1 > blocklim) { 2169 if (eflag) { 2170 if (blocks <= blocklim) { 2171 newvol(); 2172 break; 2173 } 2174 (void) fprintf(stderr, gettext( 2175 "tar: Single file cannot fit on volume\n")); 2176 done(3); 2177 } 2178 2179 if (((blocklim - tapepos) >= EXTMIN) && 2180 ((blocks + 1) >= blocklim/10)) { 2181 splitfile(longname, infile, 2182 name, prefix, filetype); 2183 (void) close(dirfd); 2184 goto out; 2185 } 2186 newvol(); 2187 } 2188 #ifdef DEBUG 2189 DEBUG("putfile: %s wants %" FMT_blkcnt_t " blocks\n", longname, 2190 blocks); 2191 #endif 2192 if (vflag) { 2193 #ifdef DEBUG 2194 if (NotTape) 2195 DEBUG("seek = %" FMT_blkcnt_t "K\t", K(tapepos), 2196 0); 2197 #endif 2198 (void) fprintf(vfile, "a %s ", longname); 2199 if (NotTape) 2200 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2201 K(blocks)); 2202 else 2203 (void) fprintf(vfile, gettext("%" 2204 FMT_blkcnt_t " tape blocks\n"), blocks); 2205 } 2206 if (build_dblock(name, tchar, '4', 2207 filetype, &stbuf, stbuf.st_rdev, prefix) != 0) 2208 goto out; 2209 2210 if (put_extra_attributes(longname, shortname, 2211 prefix, filetype, '4') != 0) 2212 goto out; 2213 2214 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2215 dblock.dbuf.typeflag = '4'; 2216 2217 (void) writetbuf((char *)&dblock, 1); 2218 break; 2219 default: 2220 (void) fprintf(stderr, gettext( 2221 "tar: %s is not a file. Not dumped\n"), longname); 2222 if (errflag) 2223 exitflag = 1; 2224 Errflg = 1; 2225 goto out; 2226 } 2227 2228 out: 2229 if (dirfd != -1) { 2230 if (filetype == XATTR_FILE) 2231 (void) chdir(parent); 2232 (void) close(dirfd); 2233 } 2234 return (rc); 2235 } 2236 2237 2238 /* 2239 * splitfile dump a large file across volumes 2240 * 2241 * splitfile(longname, fd); 2242 * char *longname; full name of file 2243 * int ifd; input file descriptor 2244 * 2245 * NOTE: only called by putfile() to dump a large file. 2246 */ 2247 2248 static void 2249 splitfile(char *longname, int ifd, char *name, char *prefix, int filetype) 2250 { 2251 blkcnt_t blocks; 2252 off_t bytes, s; 2253 char buf[TBLOCK]; 2254 int i, extents; 2255 2256 blocks = TBLOCKS(stbuf.st_size); /* blocks file needs */ 2257 2258 /* 2259 * # extents = 2260 * size of file after using up rest of this floppy 2261 * blocks - (blocklim - tapepos) + 1 (for header) 2262 * plus roundup value before divide by blocklim-1 2263 * + (blocklim - 1) - 1 2264 * all divided by blocklim-1 (one block for each header). 2265 * this gives 2266 * (blocks - blocklim + tapepos + 1 + blocklim - 2)/(blocklim-1) 2267 * which reduces to the expression used. 2268 * one is added to account for this first extent. 2269 * 2270 * When one is dealing with extremely large archives, one may want 2271 * to allow for a large number of extents. This code should be 2272 * revisited to determine if extents should be changed to something 2273 * larger than an int. 2274 */ 2275 extents = (int)((blocks + tapepos - 1ULL)/(blocklim - 1ULL) + 1); 2276 2277 if (extents < 2 || extents > MAXEXT) { /* let's be reasonable */ 2278 (void) fprintf(stderr, gettext( 2279 "tar: %s needs unusual number of volumes to split\n" 2280 "tar: %s not dumped\n"), longname, longname); 2281 return; 2282 } 2283 if (build_dblock(name, tchar, '0', filetype, 2284 &stbuf, stbuf.st_dev, prefix) != 0) 2285 return; 2286 2287 dblock.dbuf.extotal = extents; 2288 bytes = stbuf.st_size; 2289 2290 /* 2291 * The value contained in dblock.dbuf.efsize was formerly used when the 2292 * v flag was specified in conjunction with the t flag. Although it is 2293 * no longer used, older versions of tar will expect the former 2294 * behaviour, so we must continue to write it to the archive. 2295 * 2296 * Since dblock.dbuf.efsize is 10 chars in size, the maximum value it 2297 * can store is TAR_EFSIZE_MAX. If bytes exceeds that value, simply 2298 * store 0. 2299 */ 2300 if (bytes <= TAR_EFSIZE_MAX) 2301 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, bytes); 2302 else 2303 (void) sprintf(dblock.dbuf.efsize, "%9" FMT_off_t_o, (off_t)0); 2304 2305 (void) fprintf(stderr, gettext( 2306 "tar: large file %s needs %d extents.\n" 2307 "tar: current device seek position = %" FMT_blkcnt_t "K\n"), 2308 longname, extents, K(tapepos)); 2309 2310 s = (off_t)(blocklim - tapepos - 1) * TBLOCK; 2311 for (i = 1; i <= extents; i++) { 2312 if (i > 1) { 2313 newvol(); 2314 if (i == extents) 2315 s = bytes; /* last ext. gets true bytes */ 2316 else 2317 s = (off_t)(blocklim - 1)*TBLOCK; /* all */ 2318 } 2319 bytes -= s; 2320 blocks = TBLOCKS(s); 2321 2322 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, s); 2323 dblock.dbuf.extno = i; 2324 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 2325 (void) writetbuf((char *)&dblock, 1); 2326 2327 if (vflag) 2328 (void) fprintf(vfile, 2329 "+++ a %s %" FMT_blkcnt_t "K [extent #%d of %d]\n", 2330 longname, K(blocks), i, extents); 2331 while (blocks && read(ifd, buf, TBLOCK) > 0) { 2332 blocks--; 2333 (void) writetbuf(buf, 1); 2334 } 2335 if (blocks != 0) { 2336 (void) fprintf(stderr, gettext( 2337 "tar: %s: file changed size\n"), longname); 2338 (void) fprintf(stderr, gettext( 2339 "tar: aborting split file %s\n"), longname); 2340 (void) close(ifd); 2341 return; 2342 } 2343 } 2344 (void) close(ifd); 2345 if (vflag) 2346 (void) fprintf(vfile, gettext("a %s %" FMT_off_t "K (in %d " 2347 "extents)\n"), longname, K(TBLOCKS(stbuf.st_size)), 2348 extents); 2349 } 2350 2351 /* 2352 * convtoreg - determines whether the file should be converted to a 2353 * regular file when extracted 2354 * 2355 * Returns 1 when file size > 0 and typeflag is not recognized 2356 * Otherwise returns 0 2357 */ 2358 static int 2359 convtoreg(off_t size) 2360 { 2361 if ((size > 0) && (dblock.dbuf.typeflag != '0') && 2362 (dblock.dbuf.typeflag != NULL) && (dblock.dbuf.typeflag != '1') && 2363 (dblock.dbuf.typeflag != '2') && (dblock.dbuf.typeflag != '3') && 2364 (dblock.dbuf.typeflag != '4') && (dblock.dbuf.typeflag != '5') && 2365 (dblock.dbuf.typeflag != '6') && (dblock.dbuf.typeflag != 'A') && 2366 (dblock.dbuf.typeflag != _XATTR_HDRTYPE) && 2367 (dblock.dbuf.typeflag != 'X')) { 2368 return (1); 2369 } 2370 return (0); 2371 } 2372 2373 static void 2374 #ifdef _iBCS2 2375 doxtract(char *argv[], int tbl_cnt) 2376 #else 2377 doxtract(char *argv[]) 2378 #endif 2379 { 2380 struct stat xtractbuf; /* stat on file after extracting */ 2381 blkcnt_t blocks; 2382 off_t bytes; 2383 int ofile; 2384 int newfile; /* Does the file already exist */ 2385 int xcnt = 0; /* count # files extracted */ 2386 int fcnt = 0; /* count # files in argv list */ 2387 int dir; 2388 int dirfd = -1; 2389 uid_t Uid; 2390 char *namep, *dirp, *comp, *linkp; /* for removing absolute paths */ 2391 char dirname[PATH_MAX+1]; 2392 char templink[PATH_MAX+1]; /* temp link with terminating NULL */ 2393 char origdir[PATH_MAX+1]; 2394 int once = 1; 2395 int error; 2396 int symflag; 2397 int want; 2398 acl_t *aclp = NULL; /* acl info */ 2399 timestruc_t time_zero; /* used for call to doDirTimes */ 2400 int dircreate; 2401 int convflag; 2402 int cnt; 2403 2404 time_zero.tv_sec = 0; 2405 time_zero.tv_nsec = 0; 2406 2407 dumping = 0; /* for newvol(), et al: we are not writing */ 2408 2409 /* 2410 * Count the number of files that are to be extracted 2411 */ 2412 Uid = getuid(); 2413 2414 #ifdef _iBCS2 2415 initarg(argv, Filefile); 2416 while (nextarg() != NULL) 2417 ++fcnt; 2418 fcnt += tbl_cnt; 2419 #endif /* _iBCS2 */ 2420 2421 for (;;) { 2422 convflag = 0; 2423 symflag = 0; 2424 dir = 0; 2425 ofile = -1; 2426 2427 /* namep is set by wantit to point to the full name */ 2428 if ((want = wantit(argv, &namep, &dirp, &comp)) == 0) { 2429 #if defined(O_XATTR) 2430 if (xattrp != (struct xattr_buf *)NULL) { 2431 free(xattrhead); 2432 xattrp = NULL; 2433 xattr_linkp = NULL; 2434 xattrhead = NULL; 2435 } 2436 #endif 2437 continue; 2438 } 2439 if (want == -1) 2440 break; 2441 2442 if (dirfd != -1) 2443 (void) close(dirfd); 2444 2445 (void) strcpy(&dirname[0], namep); 2446 dircreate = checkdir(&dirname[0]); 2447 2448 #if defined(O_XATTR) 2449 if (xattrp != (struct xattr_buf *)NULL) { 2450 dirfd = attropen(dirp, ".", O_RDONLY); 2451 } else { 2452 dirfd = open(dirp, O_RDONLY); 2453 } 2454 #else 2455 dirfd = open(dirp, O_RDONLY); 2456 #endif 2457 2458 if (dirfd == -1) { 2459 #if defined(O_XATTR) 2460 if (xattrp) { 2461 dirfd = retry_attrdir_open(dirp); 2462 } 2463 #endif 2464 if (dirfd == -1) { 2465 #if defined(O_XATTR) 2466 if (xattrp) { 2467 (void) fprintf(vfile, 2468 gettext("tar: cannot open " 2469 "attribute %s of file %s: %s\n"), 2470 xattraname, dirp, strerror(errno)); 2471 /* 2472 * Reset typeflag back to real 2473 * value so passtape will skip 2474 * ahead correctly. 2475 */ 2476 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 2477 free(xattrhead); 2478 xattrp = NULL; 2479 xattr_linkp = NULL; 2480 xattrhead = NULL; 2481 } else { 2482 fprintf(vfile, 2483 gettext("tar: cannot open %s %s\n"), 2484 dirp, strerror(errno)); 2485 } 2486 #else 2487 fprintf(vfile, 2488 gettext("tar: cannot open %s %s\n"), 2489 dirp, strerror(errno)); 2490 #endif 2491 passtape(); 2492 continue; 2493 } 2494 } 2495 2496 if (xhdr_flgs & _X_LINKPATH) 2497 (void) strcpy(templink, Xtarhdr.x_linkpath); 2498 else { 2499 #if defined(O_XATTR) 2500 if (xattrp && dblock.dbuf.typeflag == '1') { 2501 (void) sprintf(templink, "%.*s", NAMSIZ, 2502 xattrp->h_names); 2503 } else { 2504 (void) sprintf(templink, "%.*s", NAMSIZ, 2505 dblock.dbuf.linkname); 2506 } 2507 #else 2508 (void) sprintf(templink, "%.*s", NAMSIZ, 2509 dblock.dbuf.linkname); 2510 #endif 2511 } 2512 2513 if (Fflag) { 2514 char *s; 2515 2516 if ((s = strrchr(namep, '/')) == 0) 2517 s = namep; 2518 2519 else 2520 s++; 2521 if (checkf(s, stbuf.st_mode, Fflag) == 0) { 2522 passtape(); 2523 continue; 2524 } 2525 } 2526 2527 if (checkw('x', namep) == 0) { 2528 passtape(); 2529 continue; 2530 } 2531 if (once) { 2532 if (strcmp(dblock.dbuf.magic, magic_type) == 0) { 2533 if (geteuid() == (uid_t)0) { 2534 checkflag = 1; 2535 pflag = 1; 2536 } else { 2537 /* get file creation mask */ 2538 Oumask = umask(0); 2539 (void) umask(Oumask); 2540 } 2541 once = 0; 2542 } else { 2543 if (geteuid() == (uid_t)0) { 2544 pflag = 1; 2545 checkflag = 2; 2546 } 2547 if (!pflag) { 2548 /* get file creation mask */ 2549 Oumask = umask(0); 2550 (void) umask(Oumask); 2551 } 2552 once = 0; 2553 } 2554 } 2555 2556 #if defined(O_XATTR) 2557 /* 2558 * Handle extraction of hidden attr dir. 2559 * Dir is automatically created, we only 2560 * need to update mode and perm's. 2561 */ 2562 if ((xattrp != (struct xattr_buf *)NULL) && Hiddendir == 1) { 2563 if (fchownat(dirfd, ".", stbuf.st_uid, 2564 stbuf.st_gid, 0) != 0) { 2565 vperror(0, gettext( 2566 "%s: failed to set ownership of attribute" 2567 " directory"), namep); 2568 } 2569 2570 if (fchmod(dirfd, stbuf.st_mode) != 0) { 2571 vperror(0, gettext( 2572 "%s: failed to set permissions of" 2573 " attribute directory"), namep); 2574 } 2575 goto filedone; 2576 } 2577 #endif 2578 2579 if (dircreate && (!is_posix || dblock.dbuf.typeflag == '5')) { 2580 dir = 1; 2581 if (vflag) { 2582 (void) fprintf(vfile, "x %s, 0 bytes, ", 2583 &dirname[0]); 2584 if (NotTape) 2585 (void) fprintf(vfile, "0K\n"); 2586 else 2587 (void) fprintf(vfile, gettext("%" 2588 FMT_blkcnt_t " tape blocks\n"), 2589 (blkcnt_t)0); 2590 } 2591 goto filedone; 2592 } 2593 2594 if (dblock.dbuf.typeflag == '6') { /* FIFO */ 2595 if (rmdir(namep) < 0) { 2596 if (errno == ENOTDIR) 2597 (void) unlink(namep); 2598 } 2599 linkp = templink; 2600 if (*linkp != NULL) { 2601 if (Aflag && *linkp == '/') 2602 linkp++; 2603 if (link(linkp, namep) < 0) { 2604 (void) fprintf(stderr, gettext( 2605 "tar: %s: cannot link\n"), namep); 2606 continue; 2607 } 2608 if (vflag) 2609 (void) fprintf(vfile, gettext( 2610 "%s linked to %s\n"), namep, linkp); 2611 xcnt++; /* increment # files extracted */ 2612 continue; 2613 } 2614 if (mknod(namep, (int)(Gen.g_mode|S_IFIFO), 2615 (int)Gen.g_devmajor) < 0) { 2616 vperror(0, gettext("%s: mknod failed"), namep); 2617 continue; 2618 } 2619 bytes = stbuf.st_size; 2620 blocks = TBLOCKS(bytes); 2621 if (vflag) { 2622 (void) fprintf(vfile, "x %s, %" FMT_off_t 2623 " bytes, ", namep, bytes); 2624 if (NotTape) 2625 (void) fprintf(vfile, "%" FMT_blkcnt_t 2626 "K\n", K(blocks)); 2627 else 2628 (void) fprintf(vfile, gettext("%" 2629 FMT_blkcnt_t " tape blocks\n"), 2630 blocks); 2631 } 2632 goto filedone; 2633 } 2634 if (dblock.dbuf.typeflag == '3' && !Uid) { /* CHAR SPECIAL */ 2635 if (rmdir(namep) < 0) { 2636 if (errno == ENOTDIR) 2637 (void) unlink(namep); 2638 } 2639 linkp = templink; 2640 if (*linkp != NULL) { 2641 if (Aflag && *linkp == '/') 2642 linkp++; 2643 if (link(linkp, namep) < 0) { 2644 (void) fprintf(stderr, gettext( 2645 "tar: %s: cannot link\n"), namep); 2646 continue; 2647 } 2648 if (vflag) 2649 (void) fprintf(vfile, gettext( 2650 "%s linked to %s\n"), namep, linkp); 2651 xcnt++; /* increment # files extracted */ 2652 continue; 2653 } 2654 if (mknod(namep, (int)(Gen.g_mode|S_IFCHR), 2655 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 2656 vperror(0, gettext( 2657 "%s: mknod failed"), namep); 2658 continue; 2659 } 2660 bytes = stbuf.st_size; 2661 blocks = TBLOCKS(bytes); 2662 if (vflag) { 2663 (void) fprintf(vfile, "x %s, %" FMT_off_t 2664 " bytes, ", namep, bytes); 2665 if (NotTape) 2666 (void) fprintf(vfile, "%" FMT_blkcnt_t 2667 "K\n", K(blocks)); 2668 else 2669 (void) fprintf(vfile, gettext("%" 2670 FMT_blkcnt_t " tape blocks\n"), 2671 blocks); 2672 } 2673 goto filedone; 2674 } else if (dblock.dbuf.typeflag == '3' && Uid) { 2675 (void) fprintf(stderr, gettext( 2676 "Can't create special %s\n"), namep); 2677 continue; 2678 } 2679 2680 /* BLOCK SPECIAL */ 2681 2682 if (dblock.dbuf.typeflag == '4' && !Uid) { 2683 if (rmdir(namep) < 0) { 2684 if (errno == ENOTDIR) 2685 (void) unlink(namep); 2686 } 2687 linkp = templink; 2688 if (*linkp != NULL) { 2689 if (Aflag && *linkp == '/') 2690 linkp++; 2691 if (link(linkp, namep) < 0) { 2692 (void) fprintf(stderr, gettext( 2693 "tar: %s: cannot link\n"), namep); 2694 continue; 2695 } 2696 if (vflag) 2697 (void) fprintf(vfile, gettext( 2698 "%s linked to %s\n"), namep, linkp); 2699 xcnt++; /* increment # files extracted */ 2700 continue; 2701 } 2702 if (mknod(namep, (int)(Gen.g_mode|S_IFBLK), 2703 (int)makedev(Gen.g_devmajor, Gen.g_devminor)) < 0) { 2704 vperror(0, gettext("%s: mknod failed"), namep); 2705 continue; 2706 } 2707 bytes = stbuf.st_size; 2708 blocks = TBLOCKS(bytes); 2709 if (vflag) { 2710 (void) fprintf(vfile, gettext("x %s, %" 2711 FMT_off_t " bytes, "), namep, bytes); 2712 if (NotTape) 2713 (void) fprintf(vfile, "%" FMT_blkcnt_t 2714 "K\n", K(blocks)); 2715 else 2716 (void) fprintf(vfile, gettext("%" 2717 FMT_blkcnt_t " tape blocks\n"), 2718 blocks); 2719 } 2720 goto filedone; 2721 } else if (dblock.dbuf.typeflag == '4' && Uid) { 2722 (void) fprintf(stderr, 2723 gettext("Can't create special %s\n"), namep); 2724 continue; 2725 } 2726 if (dblock.dbuf.typeflag == '2') { /* symlink */ 2727 linkp = templink; 2728 if (Aflag && *linkp == '/') 2729 linkp++; 2730 if (rmdir(namep) < 0) { 2731 if (errno == ENOTDIR) 2732 (void) unlink(namep); 2733 } 2734 if (symlink(linkp, namep) < 0) { 2735 vperror(0, gettext("%s: symbolic link failed"), 2736 namep); 2737 continue; 2738 } 2739 if (vflag) 2740 (void) fprintf(vfile, gettext( 2741 "x %s symbolic link to %s\n"), 2742 namep, linkp); 2743 2744 symflag = AT_SYMLINK_NOFOLLOW; 2745 goto filedone; 2746 } 2747 if (dblock.dbuf.typeflag == '1') { 2748 linkp = templink; 2749 if (Aflag && *linkp == '/') 2750 linkp++; 2751 if (unlinkat(dirfd, comp, AT_REMOVEDIR) < 0) { 2752 if (errno == ENOTDIR) 2753 (void) unlinkat(dirfd, comp, 0); 2754 } 2755 #if defined(O_XATTR) 2756 if (xattrp && xattr_linkp) { 2757 if (getcwd(origdir, (PATH_MAX+1)) == 2758 (char *)NULL) { 2759 vperror(0, gettext( 2760 "A parent directory cannot" 2761 " be read")); 2762 exit(1); 2763 } 2764 2765 if (fchdir(dirfd) < 0) { 2766 vperror(0, gettext( 2767 "Cannot fchdir to attribute " 2768 "directory")); 2769 exit(1); 2770 } 2771 2772 error = link(xattr_linkaname, xattraname); 2773 if (chdir(origdir) < 0) { 2774 vperror(0, gettext( 2775 "Cannot chdir out of attribute " 2776 "directory")); 2777 exit(1); 2778 } 2779 } else { 2780 error = link(linkp, namep); 2781 } 2782 #else 2783 error = link(linkp, namep); 2784 #endif 2785 2786 if (error < 0) { 2787 (void) fprintf(stderr, gettext( 2788 "tar: %s%s%s: cannot link\n"), 2789 namep, (xattr_linkp != NULL) ? 2790 gettext(" attribute ") : "", 2791 (xattr_linkp != NULL) ? 2792 xattraname : ""); 2793 continue; 2794 } 2795 if (vflag) 2796 (void) fprintf(vfile, gettext( 2797 "%s%s%s linked to %s%s%s\n"), namep, 2798 (xattr_linkp != NULL) ? 2799 gettext(" attribute ") : "", 2800 (xattr_linkp != NULL) ? 2801 xattr_linkaname : "", 2802 linkp, (xattr_linkp != NULL) ? 2803 gettext(" attribute ") : "", 2804 (xattr_linkp != NULL) ? 2805 xattraname : ""); 2806 xcnt++; /* increment # files extracted */ 2807 #if defined(O_XATTR) 2808 if (xattrp != (struct xattr_buf *)NULL) { 2809 free(xattrhead); 2810 xattrp = NULL; 2811 xattr_linkp = NULL; 2812 xattrhead = NULL; 2813 } 2814 #endif 2815 continue; 2816 } 2817 2818 /* REGULAR FILES */ 2819 2820 if (convtoreg(stbuf.st_size)) { 2821 convflag = 1; 2822 if (errflag) { 2823 (void) fprintf(stderr, gettext( 2824 "tar: %s: typeflag '%c' not recognized\n"), 2825 namep, dblock.dbuf.typeflag); 2826 done(1); 2827 } else { 2828 (void) fprintf(stderr, gettext( 2829 "tar: %s: typeflag '%c' not recognized, " 2830 "converting to regular file\n"), namep, 2831 dblock.dbuf.typeflag); 2832 Errflg = 1; 2833 } 2834 } 2835 if (dblock.dbuf.typeflag == '0' || 2836 dblock.dbuf.typeflag == NULL || convflag) { 2837 delete_target(dirfd, comp); 2838 linkp = templink; 2839 if (*linkp != NULL) { 2840 if (Aflag && *linkp == '/') 2841 linkp++; 2842 if (link(linkp, comp) < 0) { 2843 (void) fprintf(stderr, gettext( 2844 "tar: %s: cannot link\n"), namep); 2845 continue; 2846 } 2847 if (vflag) 2848 (void) fprintf(vfile, gettext( 2849 "%s linked to %s\n"), comp, linkp); 2850 xcnt++; /* increment # files extracted */ 2851 continue; 2852 } 2853 newfile = ((fstatat(dirfd, comp, 2854 &xtractbuf, 0) == -1) ? TRUE : FALSE); 2855 if ((ofile = openat(dirfd, comp, O_RDWR|O_CREAT|O_TRUNC, 2856 stbuf.st_mode & MODEMASK)) < 0) { 2857 (void) fprintf(stderr, gettext( 2858 "tar: %s - cannot create\n"), comp); 2859 if (errflag) 2860 done(1); 2861 else 2862 Errflg = 1; 2863 passtape(); 2864 continue; 2865 } 2866 2867 if (extno != 0) { /* file is in pieces */ 2868 if (extotal < 1 || extotal > MAXEXT) 2869 (void) fprintf(stderr, gettext( 2870 "tar: ignoring bad extent info for %s\n"), 2871 comp); 2872 else { 2873 xsfile(ofile); /* extract it */ 2874 goto filedone; 2875 } 2876 } 2877 extno = 0; /* let everyone know file is not split */ 2878 bytes = stbuf.st_size; 2879 blocks = TBLOCKS(bytes); 2880 if (vflag) { 2881 (void) fprintf(vfile, 2882 "x %s%s%s, %" FMT_off_t " bytes, ", 2883 (xattrp == NULL) ? "" : dirp, 2884 (xattrp == NULL) ? "" : gettext(" attribute "), 2885 (xattrp == NULL) ? namep : comp, bytes); 2886 if (NotTape) 2887 (void) fprintf(vfile, "%" FMT_blkcnt_t "K\n", 2888 K(blocks)); 2889 else 2890 (void) fprintf(vfile, gettext("%" 2891 FMT_blkcnt_t " tape blocks\n"), blocks); 2892 } 2893 2894 xblocks(bytes, ofile); 2895 filedone: 2896 if (mflag == 0 && !symflag) { 2897 if (dir) 2898 doDirTimes(namep, stbuf.st_mtim); 2899 else 2900 setPathTimes(dirfd, comp, stbuf.st_mtim); 2901 } 2902 2903 /* moved this code from above */ 2904 if (pflag && !symflag && Hiddendir == 0) { 2905 if (xattrp != (struct xattr_buf *)NULL) 2906 (void) fchmod(ofile, stbuf.st_mode & MODEMASK); 2907 else 2908 (void) chmod(namep, stbuf.st_mode & MODEMASK); 2909 } 2910 2911 2912 /* 2913 * Because ancillary file preceeds the normal file, 2914 * acl info may have been retrieved (in aclp). 2915 * All file types are directed here (go filedone). 2916 * Always restore ACLs if there are ACLs. 2917 */ 2918 if (aclp != NULL) { 2919 int ret; 2920 2921 #if defined(O_XATTR) 2922 if (xattrp != (struct xattr_buf *)NULL) { 2923 if (Hiddendir) 2924 ret = facl_set(dirfd, aclp); 2925 else 2926 ret = facl_set(ofile, aclp); 2927 } else { 2928 ret = acl_set(namep, aclp); 2929 } 2930 #else 2931 ret = acl_set(namep, &aclp); 2932 #endif 2933 if (ret < 0) { 2934 if (pflag) { 2935 (void) fprintf(stderr, gettext( 2936 "%s: failed to set acl entries\n"), 2937 namep); 2938 } 2939 /* else: silent and continue */ 2940 } 2941 acl_free(aclp); 2942 aclp = NULL; 2943 } 2944 2945 #if defined(O_XATTR) 2946 if (xattrp != (struct xattr_buf *)NULL) { 2947 free(xattrhead); 2948 xattrp = NULL; 2949 xattr_linkp = NULL; 2950 xattrhead = NULL; 2951 } 2952 #endif 2953 2954 if (!oflag) 2955 resugname(dirfd, comp, symflag); /* set file ownership */ 2956 2957 if (pflag && newfile == TRUE && !dir && 2958 (dblock.dbuf.typeflag == '0' || 2959 dblock.dbuf.typeflag == NULL || 2960 convflag || dblock.dbuf.typeflag == '1')) { 2961 if (fstat(ofile, &xtractbuf) == -1) 2962 (void) fprintf(stderr, gettext( 2963 "tar: cannot stat extracted file %s\n"), 2964 namep); 2965 else if ((xtractbuf.st_mode & (MODEMASK & ~S_IFMT)) 2966 != (stbuf.st_mode & (MODEMASK & ~S_IFMT))) { 2967 (void) fprintf(stderr, gettext( 2968 "tar: warning - file permissions have " 2969 "changed for %s (are 0%o, should be " 2970 "0%o)\n"), 2971 namep, xtractbuf.st_mode, stbuf.st_mode); 2972 } 2973 } 2974 if (ofile != -1) { 2975 (void) close(dirfd); 2976 dirfd = -1; 2977 if (close(ofile) != 0) 2978 vperror(2, gettext("close error")); 2979 } 2980 xcnt++; /* increment # files extracted */ 2981 } 2982 if (dblock.dbuf.typeflag == 'A') { /* acl info */ 2983 char buf[TBLOCK]; 2984 char *secp; 2985 char *tp; 2986 int attrsize; 2987 int cnt; 2988 2989 2990 if (pflag) { 2991 bytes = stbuf.st_size; 2992 if ((secp = malloc((int)bytes)) == NULL) { 2993 (void) fprintf(stderr, gettext( 2994 "Insufficient memory for acl\n")); 2995 passtape(); 2996 continue; 2997 } 2998 tp = secp; 2999 blocks = TBLOCKS(bytes); 3000 while (blocks-- > 0) { 3001 readtape(buf); 3002 if (bytes <= TBLOCK) { 3003 (void) memcpy(tp, buf, 3004 (size_t)bytes); 3005 break; 3006 } else { 3007 (void) memcpy(tp, buf, 3008 TBLOCK); 3009 tp += TBLOCK; 3010 } 3011 bytes -= TBLOCK; 3012 } 3013 bytes = stbuf.st_size; 3014 /* got all attributes in secp */ 3015 tp = secp; 3016 do { 3017 attr = (struct sec_attr *)tp; 3018 switch (attr->attr_type) { 3019 case UFSD_ACL: 3020 case ACE_ACL: 3021 (void) sscanf(attr->attr_len, 3022 "%7o", 3023 (uint_t *) 3024 &cnt); 3025 /* header is 8 */ 3026 attrsize = 8 + (int)strlen( 3027 &attr->attr_info[0]) + 1; 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: " 3227 "should be #%d\n"), 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 ; 3889 else c = 'n'; 3890 return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c); 3891 } 3892 3893 /* Has file been modified since being put into archive? If so, return > 0. */ 3894 3895 static int 3896 checkupdate(char *arg) 3897 { 3898 char name[PATH_MAX+1]; 3899 time_t mtime; 3900 long nsecs; 3901 off_t seekp; 3902 static off_t lookup(char *); 3903 3904 rewind(tfile); 3905 if ((seekp = lookup(arg)) < 0) 3906 return (1); 3907 (void) fseek(tfile, seekp, 0); 3908 (void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs); 3909 3910 /* 3911 * Unless nanoseconds were stored in the file, only use seconds for 3912 * comparison of time. Nanoseconds are stored when -E is specified. 3913 */ 3914 if (Eflag == 0) 3915 return (stbuf.st_mtime > mtime); 3916 3917 if ((stbuf.st_mtime < mtime) || 3918 ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs))) 3919 return (0); 3920 return (1); 3921 } 3922 3923 3924 /* 3925 * newvol get new floppy (or tape) volume 3926 * 3927 * newvol(); resets tapepos and first to TRUE, prompts for 3928 * for new volume, and waits. 3929 * if dumping, end-of-file is written onto the tape. 3930 */ 3931 3932 static void 3933 newvol(void) 3934 { 3935 int c; 3936 3937 if (dumping) { 3938 #ifdef DEBUG 3939 DEBUG("newvol called with 'dumping' set\n", 0, 0); 3940 #endif 3941 putempty((blkcnt_t)2); /* 2 EOT marks */ 3942 closevol(); 3943 flushtape(); 3944 sync(); 3945 tapepos = 0; 3946 } else 3947 first = TRUE; 3948 if (close(mt) != 0) 3949 vperror(2, gettext("close error")); 3950 mt = 0; 3951 (void) fprintf(stderr, gettext( 3952 "tar: \007please insert new volume, then press RETURN.")); 3953 (void) fseek(stdin, (off_t)0, 2); /* scan over read-ahead */ 3954 while ((c = getchar()) != '\n' && ! term) 3955 if (c == EOF) 3956 done(Errflg); 3957 if (term) 3958 done(Errflg); 3959 3960 errno = 0; 3961 3962 if (strcmp(usefile, "-") == 0) { 3963 mt = dup(1); 3964 } else { 3965 mt = open(usefile, dumping ? update : 0); 3966 } 3967 3968 if (mt < 0) { 3969 (void) fprintf(stderr, gettext( 3970 "tar: cannot reopen %s (%s)\n"), 3971 dumping ? gettext("output") : gettext("input"), usefile); 3972 3973 (void) fprintf(stderr, "update=%d, usefile=%s, mt=%d, [%s]\n", 3974 update, usefile, mt, strerror(errno)); 3975 3976 done(2); 3977 } 3978 } 3979 3980 /* 3981 * Write a trailer portion to close out the current output volume. 3982 */ 3983 3984 static void 3985 closevol(void) 3986 { 3987 if (mulvol) { 3988 /* 3989 * blocklim does not count the 2 EOT marks; 3990 * tapepos does count the 2 EOT marks; 3991 * therefore we need the +2 below. 3992 */ 3993 putempty(blocklim + (blkcnt_t)2 - tapepos); 3994 } 3995 } 3996 3997 static void 3998 done(int n) 3999 { 4000 (void) unlink(tname); 4001 if (mt > 0) { 4002 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 4003 perror(gettext("tar: close error")); 4004 exit(2); 4005 } 4006 } 4007 exit(n); 4008 } 4009 4010 /* 4011 * Determine if s1 is a prefix portion of s2 (or the same as s2). 4012 */ 4013 4014 static int 4015 is_prefix(char *s1, char *s2) 4016 { 4017 while (*s1) 4018 if (*s1++ != *s2++) 4019 return (0); 4020 if (*s2) 4021 return (*s2 == '/'); 4022 return (1); 4023 } 4024 4025 /* 4026 * lookup and bsrch look through tfile entries to find a match for a name. 4027 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 4028 * a pair of newline chars, so the buffer it uses must be long enough for 4029 * two lines: name and modification time as well as period, newline and space. 4030 * 4031 * A kludge was added to bsrch to take care of matching on the first entry 4032 * in the file--there is no leading newline. So, if we are reading from the 4033 * start of the file, read into byte two and set the first byte to a newline. 4034 * Otherwise, the first entry cannot be matched. 4035 * 4036 */ 4037 4038 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 4039 static off_t 4040 lookup(char *s) 4041 { 4042 int i; 4043 off_t a; 4044 4045 for (i = 0; s[i]; i++) 4046 if (s[i] == ' ') 4047 break; 4048 a = bsrch(s, i, low, high); 4049 return (a); 4050 } 4051 4052 static off_t 4053 bsrch(char *s, int n, off_t l, off_t h) 4054 { 4055 int i, j; 4056 char b[N]; 4057 off_t m, m1; 4058 4059 4060 loop: 4061 if (l >= h) 4062 return ((off_t)-1); 4063 m = l + (h-l)/2 - N/2; 4064 if (m < l) 4065 m = l; 4066 (void) fseek(tfile, m, 0); 4067 if (m == 0) { 4068 (void) fread(b+1, 1, N-1, tfile); 4069 b[0] = '\n'; 4070 m--; 4071 } else 4072 (void) fread(b, 1, N, tfile); 4073 for (i = 0; i < N; i++) { 4074 if (b[i] == '\n') 4075 break; 4076 m++; 4077 } 4078 if (m >= h) 4079 return ((off_t)-1); 4080 m1 = m; 4081 j = i; 4082 for (i++; i < N; i++) { 4083 m1++; 4084 if (b[i] == '\n') 4085 break; 4086 } 4087 i = cmp(b+j, s, n); 4088 if (i < 0) { 4089 h = m; 4090 goto loop; 4091 } 4092 if (i > 0) { 4093 l = m1; 4094 goto loop; 4095 } 4096 if (m < 0) 4097 m = 0; 4098 return (m); 4099 } 4100 4101 static int 4102 cmp(char *b, char *s, int n) 4103 { 4104 int i; 4105 4106 assert(b[0] == '\n'); 4107 4108 for (i = 0; i < n; i++) { 4109 if (b[i+1] > s[i]) 4110 return (-1); 4111 if (b[i+1] < s[i]) 4112 return (1); 4113 } 4114 return (b[i+1] == ' '? 0 : -1); 4115 } 4116 4117 4118 /* 4119 * seekdisk seek to next file on archive 4120 * 4121 * called by passtape() only 4122 * 4123 * WARNING: expects "nblock" to be set, that is, readtape() to have 4124 * already been called. Since passtape() is only called 4125 * after a file header block has been read (why else would 4126 * we skip to next file?), this is currently safe. 4127 * 4128 * changed to guarantee SYS_BLOCK boundary 4129 */ 4130 4131 static void 4132 seekdisk(blkcnt_t blocks) 4133 { 4134 off_t seekval; 4135 #if SYS_BLOCK > TBLOCK 4136 /* handle non-multiple of SYS_BLOCK */ 4137 blkcnt_t nxb; /* # extra blocks */ 4138 #endif 4139 4140 tapepos += blocks; 4141 #ifdef DEBUG 4142 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 4143 #endif 4144 if (recno + blocks <= nblock) { 4145 recno += blocks; 4146 return; 4147 } 4148 if (recno > nblock) 4149 recno = nblock; 4150 seekval = (off_t)blocks - (nblock - recno); 4151 recno = nblock; /* so readtape() reads next time through */ 4152 #if SYS_BLOCK > TBLOCK 4153 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 4154 #ifdef DEBUG 4155 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 4156 nxb, seekval); 4157 #endif 4158 if (nxb && nxb > seekval) /* don't seek--we'll read */ 4159 goto noseek; 4160 seekval -= nxb; /* don't seek quite so far */ 4161 #endif 4162 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 4163 (void) fprintf(stderr, gettext( 4164 "tar: device seek error\n")); 4165 done(3); 4166 } 4167 #if SYS_BLOCK > TBLOCK 4168 /* read those extra blocks */ 4169 noseek: 4170 if (nxb) { 4171 #ifdef DEBUG 4172 DEBUG("reading extra blocks\n", 0, 0); 4173 #endif 4174 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 4175 (void) fprintf(stderr, gettext( 4176 "tar: read error while skipping file\n")); 4177 done(8); 4178 } 4179 recno = nxb; /* so we don't read in next readtape() */ 4180 } 4181 #endif 4182 } 4183 4184 static void 4185 readtape(char *buffer) 4186 { 4187 int i, j; 4188 4189 ++tapepos; 4190 if (recno >= nblock || first) { 4191 if (first) { 4192 /* 4193 * set the number of blocks to read initially, based on 4194 * the defined defaults for the device, or on the 4195 * explicit block factor given. 4196 */ 4197 if (bflag || defaults_used) 4198 j = nblock; 4199 else 4200 j = NBLOCK; 4201 } else 4202 j = nblock; 4203 4204 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 4205 (void) fprintf(stderr, gettext( 4206 "tar: tape read error\n")); 4207 done(3); 4208 /* 4209 * i == 0 means EOF reached and !rflag means that when 4210 * tar command uses 'r' as a function letter, we are trying 4211 * to update or replace an empty tar file which will fail. 4212 * So this fix is not for 'r' function letter. 4213 */ 4214 } else if (i == 0 && !rflag) { 4215 if (first) { 4216 (void) fprintf(stderr, gettext( 4217 "tar: blocksize = %d\n"), i); 4218 done(Errflg); 4219 } 4220 else 4221 mterr("read", 0, 2); 4222 } else if ((!first || Bflag) && i != TBLOCK*j) { 4223 /* 4224 * Short read - try to get the remaining bytes. 4225 */ 4226 4227 int remaining = (TBLOCK * j) - i; 4228 char *b = (char *)tbuf + i; 4229 int r; 4230 4231 do { 4232 if ((r = read(mt, b, remaining)) < 0) { 4233 (void) fprintf(stderr, 4234 gettext("tar: tape read error\n")); 4235 done(3); 4236 } 4237 b += r; 4238 remaining -= r; 4239 i += r; 4240 } while (remaining > 0 && r != 0); 4241 } 4242 if (first) { 4243 if ((i % TBLOCK) != 0) { 4244 (void) fprintf(stderr, gettext( 4245 "tar: tape blocksize error\n")); 4246 done(3); 4247 } 4248 i /= TBLOCK; 4249 if (vflag && i != nblock && i != 1) { 4250 if (!NotTape) 4251 (void) fprintf(stderr, gettext( 4252 "tar: blocksize = %d\n"), i); 4253 } 4254 4255 /* 4256 * If we are reading a tape, then a short read is 4257 * understood to signify that the amount read is 4258 * the tape's actual blocking factor. We adapt 4259 * nblock accordingly. There is no reason to do 4260 * this when the device is not blocked. 4261 */ 4262 4263 if (!NotTape) 4264 nblock = i; 4265 } 4266 recno = 0; 4267 } 4268 4269 first = FALSE; 4270 copy(buffer, &tbuf[recno++]); 4271 } 4272 4273 4274 /* 4275 * replacement for writetape. 4276 */ 4277 4278 static int 4279 writetbuf(char *buffer, int n) 4280 { 4281 int i; 4282 4283 tapepos += n; /* output block count */ 4284 4285 if (recno >= nblock) { 4286 i = write(mt, (char *)tbuf, TBLOCK*nblock); 4287 if (i != TBLOCK*nblock) 4288 mterr("write", i, 2); 4289 recno = 0; 4290 } 4291 4292 /* 4293 * Special case: We have an empty tape buffer, and the 4294 * users data size is >= the tape block size: Avoid 4295 * the bcopy and dma direct to tape. BIG WIN. Add the 4296 * residual to the tape buffer. 4297 */ 4298 while (recno == 0 && n >= nblock) { 4299 i = (int)write(mt, buffer, TBLOCK*nblock); 4300 if (i != TBLOCK*nblock) 4301 mterr("write", i, 2); 4302 n -= nblock; 4303 buffer += (nblock * TBLOCK); 4304 } 4305 4306 while (n-- > 0) { 4307 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 4308 buffer += TBLOCK; 4309 if (recno >= nblock) { 4310 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 4311 if (i != TBLOCK*nblock) 4312 mterr("write", i, 2); 4313 recno = 0; 4314 } 4315 } 4316 4317 /* Tell the user how much to write to get in sync */ 4318 return (nblock - recno); 4319 } 4320 4321 /* 4322 * backtape - reposition tape after reading soft "EOF" record 4323 * 4324 * Backtape tries to reposition the tape back over the EOF 4325 * record. This is for the 'u' and 'r' function letters so that the 4326 * tape can be extended. This code is not well designed, but 4327 * I'm confident that the only callers who care about the 4328 * backspace-over-EOF feature are those involved in 'u' and 'r'. 4329 * 4330 * The proper way to backup the tape is through the use of mtio. 4331 * Earlier spins used lseek combined with reads in a confusing 4332 * maneuver that only worked on 4.x, but shouldn't have, even 4333 * there. Lseeks are explicitly not supported for tape devices. 4334 */ 4335 4336 static void 4337 backtape(void) 4338 { 4339 struct mtop mtcmd; 4340 #ifdef DEBUG 4341 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 4342 nblock); 4343 #endif 4344 /* 4345 * Backup to the position in the archive where the record 4346 * currently sitting in the tbuf buffer is situated. 4347 */ 4348 4349 if (NotTape) { 4350 /* 4351 * For non-tape devices, this means lseeking to the 4352 * correct position. The absolute location tapepos-recno 4353 * should be the beginning of the current record. 4354 */ 4355 4356 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 4357 (off_t)-1) { 4358 (void) fprintf(stderr, 4359 gettext("tar: lseek to end of archive failed\n")); 4360 done(4); 4361 } 4362 } else { 4363 /* 4364 * For tape devices, we backup over the most recently 4365 * read record. 4366 */ 4367 4368 mtcmd.mt_op = MTBSR; 4369 mtcmd.mt_count = 1; 4370 4371 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 4372 (void) fprintf(stderr, 4373 gettext("tar: backspace over record failed\n")); 4374 done(4); 4375 } 4376 } 4377 4378 /* 4379 * Decrement the tape and tbuf buffer indices to prepare for the 4380 * coming write to overwrite the soft EOF record. 4381 */ 4382 4383 recno--; 4384 tapepos--; 4385 } 4386 4387 4388 /* 4389 * flushtape write buffered block(s) onto tape 4390 * 4391 * recno points to next free block in tbuf. If nonzero, a write is done. 4392 * Care is taken to write in multiples of SYS_BLOCK when device is 4393 * non-magtape in case raw i/o is used. 4394 * 4395 * NOTE: this is called by writetape() to do the actual writing 4396 */ 4397 4398 static void 4399 flushtape(void) 4400 { 4401 #ifdef DEBUG 4402 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 4403 #endif 4404 if (recno > 0) { /* anything buffered? */ 4405 if (NotTape) { 4406 #if SYS_BLOCK > TBLOCK 4407 int i; 4408 4409 /* 4410 * an odd-block write can only happen when 4411 * we are at the end of a volume that is not a tape. 4412 * Here we round recno up to an even SYS_BLOCK 4413 * boundary. 4414 */ 4415 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 4416 #ifdef DEBUG 4417 DEBUG("flushtape() %d rounding blocks\n", i, 0); 4418 #endif 4419 recno += i; /* round up to even SYS_BLOCK */ 4420 } 4421 #endif 4422 if (recno > nblock) 4423 recno = nblock; 4424 } 4425 #ifdef DEBUG 4426 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 4427 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 4428 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 4429 #endif 4430 if (write(mt, tbuf, 4431 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 4432 (void) fprintf(stderr, gettext( 4433 "tar: tape write error\n")); 4434 done(2); 4435 } 4436 recno = 0; 4437 } 4438 } 4439 4440 static void 4441 copy(void *dst, void *src) 4442 { 4443 (void) memcpy(dst, src, TBLOCK); 4444 } 4445 4446 #ifdef _iBCS2 4447 /* 4448 * initarg -- initialize things for nextarg. 4449 * 4450 * argv filename list, a la argv. 4451 * filefile name of file containing filenames. Unless doing 4452 * a create, seeks must be allowable (e.g. no named pipes). 4453 * 4454 * - if filefile is non-NULL, it will be used first, and argv will 4455 * be used when the data in filefile are exhausted. 4456 * - otherwise argv will be used. 4457 */ 4458 static char **Cmdargv = NULL; 4459 static FILE *FILEFile = NULL; 4460 static long seekFile = -1; 4461 static char *ptrtoFile, *begofFile, *endofFile; 4462 4463 static void 4464 initarg(char *argv[], char *filefile) 4465 { 4466 struct stat statbuf; 4467 char *p; 4468 int nbytes; 4469 4470 Cmdargv = argv; 4471 if (filefile == NULL) 4472 return; /* no -F file */ 4473 if (FILEFile != NULL) { 4474 /* 4475 * need to REinitialize 4476 */ 4477 if (seekFile != -1) 4478 (void) fseek(FILEFile, seekFile, 0); 4479 ptrtoFile = begofFile; 4480 return; 4481 } 4482 /* 4483 * first time initialization 4484 */ 4485 if ((FILEFile = fopen(filefile, "r")) == NULL) 4486 fatal(gettext("cannot open (%s)"), filefile); 4487 (void) fstat(fileno(FILEFile), &statbuf); 4488 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 4489 (void) fprintf(stderr, gettext( 4490 "tar: %s is not a regular file\n"), filefile); 4491 (void) fclose(FILEFile); 4492 done(1); 4493 } 4494 ptrtoFile = begofFile = endofFile; 4495 seekFile = 0; 4496 if (!xflag) 4497 return; /* the file will be read only once anyway */ 4498 nbytes = statbuf.st_size; 4499 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 4500 nbytes -= 20; 4501 if (nbytes < 50) { 4502 free(begofFile); 4503 begofFile = endofFile; 4504 return; /* no room so just do plain reads */ 4505 } 4506 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 4507 fatal(gettext("could not read %s"), filefile); 4508 ptrtoFile = begofFile; 4509 endofFile = begofFile + nbytes; 4510 for (p = begofFile; p < endofFile; ++p) 4511 if (*p == '\n') 4512 *p = '\0'; 4513 if (nbytes != statbuf.st_size) 4514 seekFile = nbytes + 1; 4515 else 4516 (void) fclose(FILEFile); 4517 } 4518 4519 /* 4520 * nextarg -- get next argument of arglist. 4521 * 4522 * The argument is taken from wherever is appropriate. 4523 * 4524 * If the 'F file' function modifier has been specified, the argument 4525 * will be taken from the file, unless EOF has been reached. 4526 * Otherwise the argument will be taken from argv. 4527 * 4528 * WARNING: 4529 * Return value may point to static data, whose contents are over- 4530 * written on each call. 4531 */ 4532 static char * 4533 nextarg(void) 4534 { 4535 static char nameFile[PATH_MAX + 1]; 4536 int n; 4537 char *p; 4538 4539 if (FILEFile) { 4540 if (ptrtoFile < endofFile) { 4541 p = ptrtoFile; 4542 while (*ptrtoFile) 4543 ++ptrtoFile; 4544 ++ptrtoFile; 4545 return (p); 4546 } 4547 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 4548 n = strlen(nameFile); 4549 if (n > 0 && nameFile[n-1] == '\n') 4550 nameFile[n-1] = '\0'; 4551 return (nameFile); 4552 } 4553 } 4554 return (*Cmdargv++); 4555 } 4556 #endif /* _iBCS2 */ 4557 4558 /* 4559 * kcheck() 4560 * - checks the validity of size values for non-tape devices 4561 * - if size is zero, mulvol tar is disabled and size is 4562 * assumed to be infinite. 4563 * - returns volume size in TBLOCKS 4564 */ 4565 4566 static blkcnt_t 4567 kcheck(char *kstr) 4568 { 4569 blkcnt_t kval; 4570 4571 kval = strtoll(kstr, NULL, 0); 4572 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 4573 mulvol = 0; /* definitely not mulvol, but we must */ 4574 return (0); /* took out setting of NotTape */ 4575 } 4576 if (kval < (blkcnt_t)MINSIZE) { 4577 (void) fprintf(stderr, gettext( 4578 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 4579 ").\n"), (ulong_t)MINSIZE, kval); 4580 if (!kflag) 4581 (void) fprintf(stderr, gettext( 4582 "bad size entry for %s in %s.\n"), 4583 archive, DEF_FILE); 4584 done(1); 4585 } 4586 mulvol++; 4587 NotTape++; /* implies non-tape */ 4588 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 4589 } 4590 4591 4592 /* 4593 * bcheck() 4594 * - checks the validity of blocking factors 4595 * - returns blocking factor 4596 */ 4597 4598 static int 4599 bcheck(char *bstr) 4600 { 4601 blkcnt_t bval; 4602 4603 bval = strtoll(bstr, NULL, 0); 4604 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 4605 (void) fprintf(stderr, gettext( 4606 "tar: invalid blocksize \"%s\".\n"), bstr); 4607 if (!bflag) 4608 (void) fprintf(stderr, gettext( 4609 "bad blocksize entry for '%s' in %s.\n"), 4610 archive, DEF_FILE); 4611 done(1); 4612 } 4613 4614 return ((int)bval); 4615 } 4616 4617 4618 /* 4619 * defset() 4620 * - reads DEF_FILE for the set of default values specified. 4621 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 4622 * - 'usefile' points to static data, so will be overwritten 4623 * if this routine is called a second time. 4624 * - the pattern specified by 'arch' must be followed by four 4625 * blank-separated fields (1) device (2) blocking, 4626 * (3) size(K), and (4) tape 4627 * for example: archive0=/dev/fd 1 400 n 4628 */ 4629 4630 static int 4631 defset(char *arch) 4632 { 4633 char *bp; 4634 4635 if (defopen(DEF_FILE) != 0) 4636 return (FALSE); 4637 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 4638 (void) fprintf(stderr, gettext( 4639 "tar: error setting parameters for %s.\n"), DEF_FILE); 4640 return (FALSE); /* & following ones too */ 4641 } 4642 if ((bp = defread(arch)) == NULL) { 4643 (void) fprintf(stderr, gettext( 4644 "tar: missing or invalid '%s' entry in %s.\n"), 4645 arch, DEF_FILE); 4646 return (FALSE); 4647 } 4648 if ((usefile = strtok(bp, " \t")) == NULL) { 4649 (void) fprintf(stderr, gettext( 4650 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 4651 return (FALSE); 4652 } 4653 if ((bp = strtok(NULL, " \t")) == NULL) { 4654 (void) fprintf(stderr, gettext( 4655 "tar: block component missing in '%s' entry in %s.\n"), 4656 arch, DEF_FILE); 4657 return (FALSE); 4658 } 4659 nblock = bcheck(bp); 4660 if ((bp = strtok(NULL, " \t")) == NULL) { 4661 (void) fprintf(stderr, gettext( 4662 "tar: size component missing in '%s' entry in %s.\n"), 4663 arch, DEF_FILE); 4664 return (FALSE); 4665 } 4666 blocklim = kcheck(bp); 4667 if ((bp = strtok(NULL, " \t")) != NULL) 4668 NotTape = (*bp == 'n' || *bp == 'N'); 4669 else 4670 NotTape = (blocklim != 0); 4671 (void) defopen(NULL); 4672 #ifdef DEBUG 4673 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 4674 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 4675 nblock, blocklim); 4676 DEBUG("defset: not tape = %d\n", NotTape, 0); 4677 #endif 4678 return (TRUE); 4679 } 4680 4681 4682 /* 4683 * Following code handles excluded and included files. 4684 * A hash table of file names to be {in,ex}cluded is built. 4685 * For excluded files, before writing or extracting a file 4686 * check to see if it is in the exclude_tbl. 4687 * For included files, the wantit() procedure will check to 4688 * see if the named file is in the include_tbl. 4689 */ 4690 4691 static void 4692 build_table(struct file_list *table[], char *file) 4693 { 4694 FILE *fp; 4695 char buf[PATH_MAX + 1]; 4696 4697 if ((fp = fopen(file, "r")) == (FILE *)NULL) 4698 vperror(1, gettext("could not open %s"), file); 4699 while (fgets(buf, sizeof (buf), fp) != NULL) { 4700 if (buf[strlen(buf) - 1] == '\n') 4701 buf[strlen(buf) - 1] = '\0'; 4702 /* Only add to table if line has something in it */ 4703 if (strspn(buf, " \t") != strlen(buf)) 4704 add_file_to_table(table, buf); 4705 } 4706 (void) fclose(fp); 4707 } 4708 4709 4710 /* 4711 * Add a file name to the the specified table, if the file name has any 4712 * trailing '/'s then delete them before inserting into the table 4713 */ 4714 4715 static void 4716 add_file_to_table(struct file_list *table[], char *str) 4717 { 4718 char name[PATH_MAX + 1]; 4719 unsigned int h; 4720 struct file_list *exp; 4721 4722 (void) strcpy(name, str); 4723 while (name[strlen(name) - 1] == '/') { 4724 name[strlen(name) - 1] = NULL; 4725 } 4726 4727 h = hash(name); 4728 if ((exp = (struct file_list *)calloc(sizeof (struct file_list), 4729 sizeof (char))) == NULL) { 4730 (void) fprintf(stderr, gettext( 4731 "tar: out of memory, exclude/include table(entry)\n")); 4732 exit(1); 4733 } 4734 4735 if ((exp->name = strdup(name)) == NULL) { 4736 (void) fprintf(stderr, gettext( 4737 "tar: out of memory, exclude/include table(file name)\n")); 4738 exit(1); 4739 } 4740 4741 exp->next = table[h]; 4742 table[h] = exp; 4743 } 4744 4745 4746 /* 4747 * See if a file name or any of the file's parent directories is in the 4748 * specified table, if the file name has any trailing '/'s then delete 4749 * them before searching the table 4750 */ 4751 4752 static int 4753 is_in_table(struct file_list *table[], char *str) 4754 { 4755 char name[PATH_MAX + 1]; 4756 unsigned int h; 4757 struct file_list *exp; 4758 char *ptr; 4759 4760 (void) strcpy(name, str); 4761 while (name[strlen(name) - 1] == '/') { 4762 name[strlen(name) - 1] = NULL; 4763 } 4764 4765 /* 4766 * check for the file name in the passed list 4767 */ 4768 h = hash(name); 4769 exp = table[h]; 4770 while (exp != NULL) { 4771 if (strcmp(name, exp->name) == 0) { 4772 return (1); 4773 } 4774 exp = exp->next; 4775 } 4776 4777 /* 4778 * check for any parent directories in the file list 4779 */ 4780 while ((ptr = strrchr(name, '/'))) { 4781 *ptr = NULL; 4782 h = hash(name); 4783 exp = table[h]; 4784 while (exp != NULL) { 4785 if (strcmp(name, exp->name) == 0) { 4786 return (1); 4787 } 4788 exp = exp->next; 4789 } 4790 } 4791 4792 return (0); 4793 } 4794 4795 4796 /* 4797 * Compute a hash from a string. 4798 */ 4799 4800 static unsigned int 4801 hash(char *str) 4802 { 4803 char *cp; 4804 unsigned int h; 4805 4806 h = 0; 4807 for (cp = str; *cp; cp++) { 4808 h += *cp; 4809 } 4810 return (h % TABLE_SIZE); 4811 } 4812 4813 static void * 4814 getmem(size_t size) 4815 { 4816 void *p = calloc((unsigned)size, sizeof (char)); 4817 4818 if (p == NULL && freemem) { 4819 (void) fprintf(stderr, gettext( 4820 "tar: out of memory, link and directory modtime " 4821 "info lost\n")); 4822 freemem = 0; 4823 if (errflag) 4824 done(1); 4825 else 4826 Errflg = 1; 4827 } 4828 return (p); 4829 } 4830 4831 /* 4832 * vperror() --variable argument perror. 4833 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 4834 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 4835 * with the value of whatever "errno" is set to. If exit_status is not 4836 * zero, then tar exits with that error status. If errflag and exit_status 4837 * are both zero, the routine returns to where it was called and sets Errflg 4838 * to errno. 4839 */ 4840 4841 static void 4842 vperror(int exit_status, char *fmt, ...) 4843 { 4844 va_list ap; 4845 4846 va_start(ap, fmt); 4847 (void) fputs("tar: ", stderr); 4848 (void) vfprintf(stderr, fmt, ap); 4849 (void) fprintf(stderr, ": %s\n", strerror(errno)); 4850 va_end(ap); 4851 if (exit_status) 4852 done(exit_status); 4853 else 4854 if (errflag) 4855 done(errno); 4856 else 4857 Errflg = errno; 4858 } 4859 4860 4861 static void 4862 fatal(char *format, ...) 4863 { 4864 va_list ap; 4865 4866 va_start(ap, format); 4867 (void) fprintf(stderr, "tar: "); 4868 (void) vfprintf(stderr, format, ap); 4869 (void) fprintf(stderr, "\n"); 4870 va_end(ap); 4871 done(1); 4872 } 4873 4874 4875 /* 4876 * Check to make sure that argument is a char * ptr. 4877 * Actually, we just check to see that it is non-null. 4878 * If it is null, print out the message and call usage(), bailing out. 4879 */ 4880 4881 static void 4882 assert_string(char *s, char *msg) 4883 { 4884 if (s == NULL) { 4885 (void) fprintf(stderr, msg); 4886 usage(); 4887 } 4888 } 4889 4890 4891 static void 4892 mterr(char *operation, int i, int exitcode) 4893 { 4894 (void) fprintf(stderr, gettext( 4895 "tar: %s error: "), operation); 4896 if (i < 0) 4897 perror(""); 4898 else 4899 (void) fprintf(stderr, gettext("unexpected EOF\n")); 4900 done(exitcode); 4901 } 4902 4903 static int 4904 wantit(char *argv[], char **namep, char **dirp, char **component) 4905 { 4906 char **cp; 4907 int gotit; /* true if we've found a match */ 4908 4909 top: 4910 xhdr_flgs = 0; 4911 getdir(); 4912 if (Xhdrflag > 0) { 4913 if (get_xdata() != 0) { /* Xhdr items and regular header */ 4914 passtape(); 4915 return (0); /* Error--don't want to extract */ 4916 } 4917 } 4918 4919 #if defined(O_XATTR) 4920 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 4921 if (atflag || tflag) { 4922 (void) read_xattr_hdr(); 4923 } else { 4924 passtape(); 4925 } 4926 goto top; 4927 } 4928 #endif 4929 4930 /* sets *namep to point at the proper name */ 4931 check_prefix(namep, dirp, component); 4932 4933 if (endtape()) { 4934 if (Bflag) { 4935 /* 4936 * Logically at EOT - consume any extra blocks 4937 * so that write to our stdin won't fail and 4938 * emit an error message; otherwise something 4939 * like "dd if=foo.tar | (cd bar; tar xvf -)" 4940 * will produce a bogus error message from "dd". 4941 */ 4942 4943 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 4944 /* empty body */ 4945 } 4946 } 4947 return (-1); 4948 } 4949 4950 gotit = 0; 4951 4952 if ((Iflag && is_in_table(include_tbl, *namep)) || 4953 (! Iflag && *argv == NULL)) { 4954 gotit = 1; 4955 } else { 4956 for (cp = argv; *cp; cp++) { 4957 if (is_prefix(*cp, *namep)) { 4958 gotit = 1; 4959 break; 4960 } 4961 } 4962 } 4963 4964 if (! gotit) { 4965 passtape(); 4966 return (0); 4967 } 4968 4969 if (Xflag && is_in_table(exclude_tbl, *namep)) { 4970 if (vflag) { 4971 (void) fprintf(stderr, gettext("%s excluded\n"), 4972 *namep); 4973 } 4974 passtape(); 4975 return (0); 4976 } 4977 4978 return (1); 4979 } 4980 4981 4982 /* 4983 * Return through *namep a pointer to the proper fullname (i.e "<name> | 4984 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 4985 */ 4986 4987 static void 4988 check_prefix(char **namep, char **dirp, char **compp) 4989 { 4990 static char fullname[PATH_MAX + 1]; 4991 static char dir[PATH_MAX + 1]; 4992 static char component[PATH_MAX + 1]; 4993 static char savename[PATH_MAX + 1]; 4994 char *s; 4995 4996 (void) memset(dir, 0, sizeof (dir)); 4997 (void) memset(component, 0, sizeof (component)); 4998 4999 if (xhdr_flgs & _X_PATH) { 5000 (void) strcpy(fullname, Xtarhdr.x_path); 5001 } else { 5002 if (dblock.dbuf.prefix[0] != '\0') 5003 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 5004 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 5005 else 5006 (void) sprintf(fullname, "%.*s", NAMSIZ, 5007 dblock.dbuf.name); 5008 } 5009 5010 /* 5011 * Set dir and component names 5012 */ 5013 5014 get_parent(fullname, dir); 5015 5016 #if defined(O_XATTR) 5017 if (xattrp == (struct xattr_buf *)NULL) { 5018 #endif 5019 /* 5020 * Save of real name since were going to chop off the 5021 * trailing slashes. 5022 */ 5023 (void) strcpy(savename, fullname); 5024 /* 5025 * first strip of trailing slashes. 5026 */ 5027 chop_endslashes(savename); 5028 s = get_component(savename); 5029 (void) strcpy(component, s); 5030 5031 #if defined(O_XATTR) 5032 } else { 5033 (void) strcpy(fullname, xattrp->h_names); 5034 (void) strcpy(dir, fullname); 5035 (void) strcpy(component, xattrp->h_names + 5036 strlen(xattrp->h_names) + 1); 5037 } 5038 #endif 5039 *namep = fullname; 5040 *dirp = dir; 5041 *compp = component; 5042 } 5043 5044 5045 static wchar_t 5046 yesnoresponse(void) 5047 { 5048 wchar_t c; 5049 5050 c = getwchar(); 5051 if (c != '\n') 5052 while (getwchar() != '\n') 5053 ; 5054 else c = 0; 5055 return (c); 5056 } 5057 5058 5059 /* 5060 * Return true if the object indicated by the file descriptor and type 5061 * is a tape device, false otherwise 5062 */ 5063 5064 static int 5065 istape(int fd, int type) 5066 { 5067 int result = 0; 5068 5069 if (S_ISCHR(type)) { 5070 struct mtget mtg; 5071 5072 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 5073 result = 1; 5074 } 5075 } 5076 5077 return (result); 5078 } 5079 5080 #include <utmpx.h> 5081 5082 struct utmpx utmpx; 5083 5084 #define NMAX (sizeof (utmpx.ut_name)) 5085 5086 typedef struct cachenode { /* this struct must be zeroed before using */ 5087 struct cachenode *next; /* next in hash chain */ 5088 int val; /* the uid or gid of this entry */ 5089 int namehash; /* name's hash signature */ 5090 char name[NMAX+1]; /* the string that val maps to */ 5091 } cachenode_t; 5092 5093 #define HASHSIZE 256 5094 5095 static cachenode_t *names[HASHSIZE]; 5096 static cachenode_t *groups[HASHSIZE]; 5097 static cachenode_t *uids[HASHSIZE]; 5098 static cachenode_t *gids[HASHSIZE]; 5099 5100 static int 5101 hash_byname(char *name) 5102 { 5103 int i, c, h = 0; 5104 5105 for (i = 0; i < NMAX; i++) { 5106 c = name[i]; 5107 if (c == '\0') 5108 break; 5109 h = (h << 4) + h + c; 5110 } 5111 return (h); 5112 } 5113 5114 static cachenode_t * 5115 hash_lookup_byval(cachenode_t *table[], int val) 5116 { 5117 int h = val; 5118 cachenode_t *c; 5119 5120 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5121 if (c->val == val) 5122 return (c); 5123 } 5124 return (NULL); 5125 } 5126 5127 static cachenode_t * 5128 hash_lookup_byname(cachenode_t *table[], char *name) 5129 { 5130 int h = hash_byname(name); 5131 cachenode_t *c; 5132 5133 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5134 if (c->namehash == h && strcmp(c->name, name) == 0) 5135 return (c); 5136 } 5137 return (NULL); 5138 } 5139 5140 static cachenode_t * 5141 hash_insert(cachenode_t *table[], char *name, int value) 5142 { 5143 cachenode_t *c; 5144 int signature; 5145 5146 c = calloc(1, sizeof (cachenode_t)); 5147 if (c == NULL) { 5148 perror("malloc"); 5149 exit(1); 5150 } 5151 if (name != NULL) { 5152 (void) strncpy(c->name, name, NMAX); 5153 c->namehash = hash_byname(name); 5154 } 5155 c->val = value; 5156 if (table == uids || table == gids) 5157 signature = c->val; 5158 else 5159 signature = c->namehash; 5160 c->next = table[signature & (HASHSIZE - 1)]; 5161 table[signature & (HASHSIZE - 1)] = c; 5162 return (c); 5163 } 5164 5165 static char * 5166 getname(uid_t uid) 5167 { 5168 cachenode_t *c; 5169 5170 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 5171 struct passwd *pwent = getpwuid(uid); 5172 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 5173 } 5174 return (c->name); 5175 } 5176 5177 static char * 5178 getgroup(gid_t gid) 5179 { 5180 cachenode_t *c; 5181 5182 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 5183 struct group *grent = getgrgid(gid); 5184 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 5185 } 5186 return (c->name); 5187 } 5188 5189 static uid_t 5190 getuidbyname(char *name) 5191 { 5192 cachenode_t *c; 5193 5194 if ((c = hash_lookup_byname(names, name)) == NULL) { 5195 struct passwd *pwent = getpwnam(name); 5196 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 5197 } 5198 return ((uid_t)c->val); 5199 } 5200 5201 static gid_t 5202 getgidbyname(char *group) 5203 { 5204 cachenode_t *c; 5205 5206 if ((c = hash_lookup_byname(groups, group)) == NULL) { 5207 struct group *grent = getgrnam(group); 5208 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 5209 } 5210 return ((gid_t)c->val); 5211 } 5212 5213 /* 5214 * Build the header. 5215 * Determine whether or not an extended header is also needed. If needed, 5216 * create and write the extended header and its data. 5217 * Writing of the extended header assumes that "tomodes" has been called and 5218 * the relevant information has been placed in the header block. 5219 */ 5220 5221 static int 5222 build_dblock( 5223 const char *name, 5224 const char *linkname, 5225 const char typeflag, 5226 const int filetype, 5227 const struct stat *sp, 5228 const dev_t device, 5229 const char *prefix) 5230 { 5231 int nblks; 5232 major_t dev; 5233 const char *filename; 5234 const char *lastslash; 5235 5236 if (filetype == XATTR_FILE) 5237 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 5238 else 5239 dblock.dbuf.typeflag = typeflag; 5240 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 5241 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 5242 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 5243 5244 if (xhdr_flgs & _X_PATH) 5245 filename = Xtarhdr.x_path; 5246 else 5247 filename = name; 5248 5249 if ((dev = major(device)) > OCTAL7CHAR) { 5250 if (Eflag) { 5251 xhdr_flgs |= _X_DEVMAJOR; 5252 Xtarhdr.x_devmajor = dev; 5253 } else { 5254 (void) fprintf(stderr, gettext( 5255 "Device major too large for %s. Use -E flag."), 5256 filename); 5257 if (errflag) 5258 done(1); 5259 else 5260 Errflg = 1; 5261 } 5262 dev = 0; 5263 } 5264 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 5265 if ((dev = minor(device)) > OCTAL7CHAR) { 5266 if (Eflag) { 5267 xhdr_flgs |= _X_DEVMINOR; 5268 Xtarhdr.x_devminor = dev; 5269 } else { 5270 (void) fprintf(stderr, gettext( 5271 "Device minor too large for %s. Use -E flag."), 5272 filename); 5273 if (errflag) 5274 done(1); 5275 else 5276 Errflg = 1; 5277 } 5278 dev = 0; 5279 } 5280 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 5281 5282 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 5283 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 5284 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 5285 (void) sprintf(dblock.dbuf.version, "00"); 5286 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 5287 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 5288 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 5289 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 5290 5291 if (Eflag) { 5292 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 5293 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 5294 lastslash = strrchr(name, '/'); 5295 if (lastslash == NULL) 5296 lastslash = name; 5297 else 5298 lastslash++; 5299 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 5300 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 5301 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 5302 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 5303 xhdr_count++; 5304 xrec_offset = 0; 5305 gen_date("mtime", sp->st_mtim); 5306 xhdr_buf.dbuf.typeflag = 'X'; 5307 if (gen_utf8_names(filename) != 0) 5308 return (1); 5309 5310 #ifdef XHDR_DEBUG 5311 Xtarhdr.x_uname = dblock.dbuf.uname; 5312 Xtarhdr.x_gname = dblock.dbuf.gname; 5313 xhdr_flgs |= (_X_UNAME | _X_GNAME); 5314 #endif 5315 if (xhdr_flgs) { 5316 if (xhdr_flgs & _X_DEVMAJOR) 5317 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 5318 if (xhdr_flgs & _X_DEVMINOR) 5319 gen_num("SUN.devminor", Xtarhdr.x_devminor); 5320 if (xhdr_flgs & _X_GID) 5321 gen_num("gid", Xtarhdr.x_gid); 5322 if (xhdr_flgs & _X_UID) 5323 gen_num("uid", Xtarhdr.x_uid); 5324 if (xhdr_flgs & _X_SIZE) 5325 gen_num("size", Xtarhdr.x_filesz); 5326 if (xhdr_flgs & _X_PATH) 5327 gen_string("path", Xtarhdr.x_path); 5328 if (xhdr_flgs & _X_LINKPATH) 5329 gen_string("linkpath", Xtarhdr.x_linkpath); 5330 if (xhdr_flgs & _X_GNAME) 5331 gen_string("gname", Xtarhdr.x_gname); 5332 if (xhdr_flgs & _X_UNAME) 5333 gen_string("uname", Xtarhdr.x_uname); 5334 } 5335 (void) sprintf(xhdr_buf.dbuf.size, 5336 "%011" FMT_off_t_o, xrec_offset); 5337 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 5338 checksum(&xhdr_buf)); 5339 (void) writetbuf((char *)&xhdr_buf, 1); 5340 nblks = TBLOCKS(xrec_offset); 5341 (void) writetbuf(xrec_ptr, nblks); 5342 } 5343 return (0); 5344 } 5345 5346 5347 /* 5348 * makeDir - ensure that a directory with the pathname denoted by name 5349 * exists, and return 1 on success, and 0 on failure (e.g., 5350 * read-only file system, exists but not-a-directory). 5351 */ 5352 5353 static int 5354 makeDir(char *name) 5355 { 5356 struct stat buf; 5357 5358 if (access(name, 0) < 0) { /* name doesn't exist */ 5359 if (mkdir(name, 0777) < 0) { 5360 vperror(0, "%s", name); 5361 return (0); 5362 } 5363 } else { /* name exists */ 5364 if (stat(name, &buf) < 0) { 5365 vperror(0, "%s", name); 5366 return (0); 5367 } 5368 5369 return ((buf.st_mode & S_IFMT) == S_IFDIR); 5370 } 5371 5372 return (1); 5373 } 5374 5375 5376 /* 5377 * Save this directory and its mtime on the stack, popping and setting 5378 * the mtimes of any stacked dirs which aren't parents of this one. 5379 * A null name causes the entire stack to be unwound and set. 5380 * 5381 * Since all the elements of the directory "stack" share a common 5382 * prefix, we can make do with one string. We keep only the current 5383 * directory path, with an associated array of mtime's. A negative 5384 * mtime means no mtime. 5385 * 5386 * This stack algorithm is not guaranteed to work for tapes created 5387 * with the 'r' function letter, but the vast majority of tapes with 5388 * directories are not. This avoids saving every directory record on 5389 * the tape and setting all the times at the end. 5390 * 5391 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 5392 * environment) 5393 */ 5394 5395 static void 5396 doDirTimes(char *name, timestruc_t modTime) 5397 { 5398 static char dirstack[PATH_MAX+2]; 5399 /* Add spaces for the last slash and last NULL */ 5400 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 5401 char *p = dirstack; 5402 char *q = name; 5403 char *savp; 5404 5405 if (q) { 5406 /* 5407 * Find common prefix 5408 */ 5409 5410 while (*p == *q && *p) { 5411 p++; q++; 5412 } 5413 } 5414 5415 savp = p; 5416 while (*p) { 5417 /* 5418 * Not a child: unwind the stack, setting the times. 5419 * The order we do this doesn't matter, so we go "forward." 5420 */ 5421 5422 if (*p == '/') 5423 if (modtimes[p - dirstack].tv_sec >= 0) { 5424 *p = '\0'; /* zap the slash */ 5425 setPathTimes(AT_FDCWD, dirstack, 5426 modtimes[p - dirstack]); 5427 *p = '/'; 5428 } 5429 ++p; 5430 } 5431 5432 p = savp; 5433 5434 /* 5435 * Push this one on the "stack" 5436 */ 5437 5438 if (q) { 5439 5440 /* 5441 * Since the name parameter points the dir pathname 5442 * which is limited only to contain PATH_MAX chars 5443 * at maximum, we can ignore the overflow case of p. 5444 */ 5445 5446 while ((*p = *q++)) { /* append the rest of the new dir */ 5447 modtimes[p - dirstack].tv_sec = -1; 5448 p++; 5449 } 5450 5451 /* 5452 * If the tar file had used 'P' or 'E' function modifier, 5453 * append the last slash. 5454 */ 5455 if (*(p - 1) != '/') { 5456 *p++ = '/'; 5457 *p = '\0'; 5458 } 5459 /* overwrite the last one */ 5460 modtimes[p - dirstack - 1] = modTime; 5461 } 5462 } 5463 5464 5465 /* 5466 * setPathTimes - set the modification time for given path. Return 1 if 5467 * successful and 0 if not successful. 5468 */ 5469 5470 static void 5471 setPathTimes(int dirfd, char *path, timestruc_t modTime) 5472 5473 { 5474 struct timeval timebuf[2]; 5475 5476 /* 5477 * futimesat takes an array of two timeval structs. 5478 * The first entry contains access time. 5479 * The second entry contains modification time. 5480 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 5481 * microseconds. 5482 */ 5483 timebuf[0].tv_sec = time((time_t *)0); 5484 timebuf[0].tv_usec = 0; 5485 timebuf[1].tv_sec = modTime.tv_sec; 5486 5487 /* Extended header: use microseconds */ 5488 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 5489 5490 if (futimesat(dirfd, path, timebuf) < 0) 5491 vperror(0, "can't set time on %s", path); 5492 } 5493 5494 5495 /* 5496 * If hflag is set then delete the symbolic link's target. 5497 * If !hflag then delete the target. 5498 */ 5499 5500 static void 5501 delete_target(int fd, char *namep) 5502 { 5503 struct stat xtractbuf; 5504 char buf[PATH_MAX + 1]; 5505 int n; 5506 5507 5508 if (unlinkat(fd, namep, AT_REMOVEDIR) < 0) { 5509 if (errno == ENOTDIR && !hflag) { 5510 (void) unlinkat(fd, namep, 0); 5511 } else if (errno == ENOTDIR && hflag) { 5512 if (!lstat(namep, &xtractbuf)) { 5513 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 5514 (void) unlinkat(fd, namep, 0); 5515 } else if ((n = readlink(namep, buf, 5516 PATH_MAX)) != -1) { 5517 buf[n] = (char)NULL; 5518 (void) unlinkat(fd, buf, 5519 AT_REMOVEDIR); 5520 if (errno == ENOTDIR) 5521 (void) unlinkat(fd, buf, 0); 5522 } else { 5523 (void) unlinkat(fd, namep, 0); 5524 } 5525 } else { 5526 (void) unlinkat(fd, namep, 0); 5527 } 5528 } 5529 } 5530 } 5531 5532 5533 /* 5534 * ACL changes: 5535 * putfile(): 5536 * Get acl info after stat. Write out ancillary file 5537 * before the normal file, i.e. directory, regular, FIFO, 5538 * link, special. If acl count is less than 4, no need to 5539 * create ancillary file. (i.e. standard permission is in 5540 * use. 5541 * doxtract(): 5542 * Process ancillary file. Read it in and set acl info. 5543 * watch out for 'o' function modifier. 5544 * 't' function letter to display table 5545 */ 5546 5547 /* 5548 * New functions for ACLs and other security attributes 5549 */ 5550 5551 /* 5552 * The function appends the new security attribute info to the end of 5553 * existing secinfo. 5554 */ 5555 int 5556 append_secattr( 5557 char **secinfo, /* existing security info */ 5558 int *secinfo_len, /* length of existing security info */ 5559 acl_t *aclp) 5560 { 5561 char *new_secinfo; 5562 char *attrtext; 5563 int newattrsize; 5564 int oldsize; 5565 5566 /* no need to add */ 5567 if (aclp == (void *)NULL) 5568 return (0); 5569 5570 switch (acl_type(aclp)) { 5571 case ACLENT_T: 5572 case ACE_T: 5573 attrtext = acl_totext(aclp, ACL_APPEND_ID | ACL_COMPACT_FMT); 5574 if (attrtext == NULL) { 5575 (void) fprintf(stderr, "acltotext failed\n"); 5576 return (-1); 5577 } 5578 /* header: type + size = 8 */ 5579 newattrsize = 8 + (int)strlen(attrtext) + 1; 5580 attr = (struct sec_attr *)malloc(newattrsize); 5581 if (attr == NULL) { 5582 (void) fprintf(stderr, "can't allocate memory\n"); 5583 return (-1); 5584 } 5585 attr->attr_type = (acl_type(aclp) == ACLENT_T) ? 5586 UFSD_ACL : ACE_ACL; 5587 (void) sprintf(attr->attr_len, 5588 "%06o", acl_cnt(aclp)); /* acl entry count */ 5589 (void) strcpy((char *)&attr->attr_info[0], attrtext); 5590 free(attrtext); 5591 break; 5592 5593 /* SunFed's case goes here */ 5594 5595 default: 5596 (void) fprintf(stderr, "unrecognized attribute type\n"); 5597 return (-1); 5598 } 5599 5600 /* old security info + new attr header(8) + new attr */ 5601 oldsize = *secinfo_len; 5602 *secinfo_len += newattrsize; 5603 new_secinfo = (char *)malloc(*secinfo_len); 5604 if (new_secinfo == NULL) { 5605 (void) fprintf(stderr, "can't allocate memory\n"); 5606 *secinfo_len -= newattrsize; 5607 return (-1); 5608 } 5609 5610 (void) memcpy(new_secinfo, *secinfo, oldsize); 5611 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 5612 5613 free(*secinfo); 5614 *secinfo = new_secinfo; 5615 return (0); 5616 } 5617 5618 /* 5619 * write_ancillary(): write out an ancillary file. 5620 * The file has the same header as normal file except the type and size 5621 * fields. The type is 'A' and size is the sum of all attributes 5622 * in bytes. 5623 * The body contains a list of attribute type, size and info. Currently, 5624 * there is only ACL info. This file is put before the normal file. 5625 */ 5626 void 5627 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 5628 { 5629 long blocks; 5630 int savflag; 5631 int savsize; 5632 5633 /* Just tranditional permissions or no security attribute info */ 5634 if (len == 0 || secinfo == NULL) 5635 return; 5636 5637 /* save flag and size */ 5638 savflag = (dblockp->dbuf).typeflag; 5639 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 5640 5641 /* special flag for ancillary file */ 5642 if (hdrtype == _XATTR_HDRTYPE) 5643 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 5644 else 5645 dblockp->dbuf.typeflag = 'A'; 5646 5647 /* for pre-2.5 versions of tar, need to make sure */ 5648 /* the ACL file is readable */ 5649 (void) sprintf(dblock.dbuf.mode, "%07lo", 5650 (stbuf.st_mode & POSIXMODES) | 0000200); 5651 (void) sprintf(dblockp->dbuf.size, "%011o", len); 5652 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 5653 5654 /* write out the header */ 5655 (void) writetbuf((char *)dblockp, 1); 5656 5657 /* write out security info */ 5658 blocks = TBLOCKS(len); 5659 (void) writetbuf((char *)secinfo, (int)blocks); 5660 5661 /* restore mode, flag and size */ 5662 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 5663 dblockp->dbuf.typeflag = savflag; 5664 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 5665 } 5666 5667 /* 5668 * Read the data record for extended headers and then the regular header. 5669 * The data are read into the buffer and then null-terminated. Entries 5670 * are of the format: 5671 * "%d %s=%s\n" 5672 * 5673 * When an extended header record is found, the extended header must 5674 * be processed and its values used to override the values in the 5675 * normal header. The way this is done is to process the extended 5676 * header data record and set the data values, then call getdir 5677 * to process the regular header, then then to reconcile the two 5678 * sets of data. 5679 */ 5680 5681 static int 5682 get_xdata(void) 5683 { 5684 struct keylist_pair { 5685 int keynum; 5686 char *keylist; 5687 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 5688 _X_DEVMINOR, "SUN.devminor", 5689 _X_GID, "gid", 5690 _X_GNAME, "gname", 5691 _X_LINKPATH, "linkpath", 5692 _X_PATH, "path", 5693 _X_SIZE, "size", 5694 _X_UID, "uid", 5695 _X_UNAME, "uname", 5696 _X_MTIME, "mtime", 5697 _X_LAST, "NULL" }; 5698 char *lineloc; 5699 int length, i; 5700 char *keyword, *value; 5701 blkcnt_t nblocks; 5702 int bufneeded; 5703 struct stat *sp = &stbuf; 5704 int errors; 5705 5706 Xtarhdr.x_uid = 0; 5707 Xtarhdr.x_gid = 0; 5708 Xtarhdr.x_devmajor = 0; 5709 Xtarhdr.x_devminor = 0; 5710 Xtarhdr.x_filesz = 0; 5711 Xtarhdr.x_uname = NULL; 5712 Xtarhdr.x_gname = NULL; 5713 Xtarhdr.x_linkpath = NULL; 5714 Xtarhdr.x_path = NULL; 5715 Xtarhdr.x_mtime.tv_sec = 0; 5716 Xtarhdr.x_mtime.tv_nsec = 0; 5717 xhdr_count++; 5718 errors = 0; 5719 5720 nblocks = TBLOCKS(stbuf.st_size); 5721 bufneeded = nblocks * TBLOCK; 5722 if (bufneeded >= xrec_size) { 5723 free(xrec_ptr); 5724 xrec_size = bufneeded + 1; 5725 if ((xrec_ptr = malloc(xrec_size)) == NULL) 5726 fatal(gettext("cannot allocate buffer")); 5727 } 5728 5729 lineloc = xrec_ptr; 5730 5731 while (nblocks-- > 0) { 5732 readtape(lineloc); 5733 lineloc += TBLOCK; 5734 } 5735 lineloc = xrec_ptr; 5736 xrec_ptr[stbuf.st_size] = '\0'; 5737 while (lineloc < xrec_ptr + stbuf.st_size) { 5738 length = atoi(lineloc); 5739 *(lineloc + length - 1) = '\0'; 5740 keyword = strchr(lineloc, ' ') + 1; 5741 value = strchr(keyword, '=') + 1; 5742 *(value - 1) = '\0'; 5743 i = 0; 5744 lineloc += length; 5745 while (keylist_pair[i].keynum != (int)_X_LAST) { 5746 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 5747 break; 5748 i++; 5749 } 5750 errno = 0; 5751 switch (keylist_pair[i].keynum) { 5752 case _X_DEVMAJOR: 5753 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 5754 if (errno) { 5755 (void) fprintf(stderr, gettext( 5756 "tar: Extended header major value error " 5757 "for file # %llu.\n"), xhdr_count); 5758 errors++; 5759 } else 5760 xhdr_flgs |= _X_DEVMAJOR; 5761 break; 5762 case _X_DEVMINOR: 5763 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 5764 if (errno) { 5765 (void) fprintf(stderr, gettext( 5766 "tar: Extended header minor value error " 5767 "for file # %llu.\n"), xhdr_count); 5768 errors++; 5769 } else 5770 xhdr_flgs |= _X_DEVMINOR; 5771 break; 5772 case _X_GID: 5773 xhdr_flgs |= _X_GID; 5774 Xtarhdr.x_gid = strtol(value, NULL, 0); 5775 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 5776 (void) fprintf(stderr, gettext( 5777 "tar: Extended header gid value error " 5778 "for file # %llu.\n"), xhdr_count); 5779 Xtarhdr.x_gid = GID_NOBODY; 5780 } 5781 break; 5782 case _X_GNAME: 5783 if (utf8_local("gname", &Xtarhdr.x_gname, 5784 local_gname, value, _POSIX_NAME_MAX) == 0) 5785 xhdr_flgs |= _X_GNAME; 5786 break; 5787 case _X_LINKPATH: 5788 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 5789 local_linkpath, value, PATH_MAX) == 0) 5790 xhdr_flgs |= _X_LINKPATH; 5791 else 5792 errors++; 5793 break; 5794 case _X_PATH: 5795 if (utf8_local("path", &Xtarhdr.x_path, 5796 local_path, value, PATH_MAX) == 0) 5797 xhdr_flgs |= _X_PATH; 5798 else 5799 errors++; 5800 break; 5801 case _X_SIZE: 5802 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 5803 if (errno) { 5804 (void) fprintf(stderr, gettext( 5805 "tar: Extended header invalid filesize " 5806 "for file # %llu.\n"), xhdr_count); 5807 errors++; 5808 } else 5809 xhdr_flgs |= _X_SIZE; 5810 break; 5811 case _X_UID: 5812 xhdr_flgs |= _X_UID; 5813 Xtarhdr.x_uid = strtol(value, NULL, 0); 5814 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 5815 (void) fprintf(stderr, gettext( 5816 "tar: Extended header uid value error " 5817 "for file # %llu.\n"), xhdr_count); 5818 Xtarhdr.x_uid = UID_NOBODY; 5819 } 5820 break; 5821 case _X_UNAME: 5822 if (utf8_local("uname", &Xtarhdr.x_uname, 5823 local_uname, value, _POSIX_NAME_MAX) == 0) 5824 xhdr_flgs |= _X_UNAME; 5825 break; 5826 case _X_MTIME: 5827 get_xtime(value, &(Xtarhdr.x_mtime)); 5828 if (errno) 5829 (void) fprintf(stderr, gettext( 5830 "tar: Extended header modification time " 5831 "value error for file # %llu.\n"), 5832 xhdr_count); 5833 else 5834 xhdr_flgs |= _X_MTIME; 5835 break; 5836 default: 5837 (void) fprintf(stderr, 5838 gettext("tar: unrecognized extended" 5839 " header keyword '%s'. Ignored.\n"), keyword); 5840 break; 5841 } 5842 } 5843 5844 getdir(); /* get regular header */ 5845 5846 if (xhdr_flgs & _X_DEVMAJOR) { 5847 Gen.g_devmajor = Xtarhdr.x_devmajor; 5848 } 5849 if (xhdr_flgs & _X_DEVMINOR) { 5850 Gen.g_devminor = Xtarhdr.x_devminor; 5851 } 5852 if (xhdr_flgs & _X_GID) { 5853 Gen.g_gid = Xtarhdr.x_gid; 5854 sp->st_gid = Gen.g_gid; 5855 } 5856 if (xhdr_flgs & _X_UID) { 5857 Gen.g_uid = Xtarhdr.x_uid; 5858 sp->st_uid = Gen.g_uid; 5859 } 5860 if (xhdr_flgs & _X_SIZE) { 5861 Gen.g_filesz = Xtarhdr.x_filesz; 5862 sp->st_size = Gen.g_filesz; 5863 } 5864 if (xhdr_flgs & _X_MTIME) { 5865 Gen.g_mtime = Xtarhdr.x_mtime.tv_sec; 5866 sp->st_mtim.tv_sec = Gen.g_mtime; 5867 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 5868 } 5869 5870 if (errors && errflag) 5871 done(1); 5872 else 5873 if (errors) 5874 Errflg = 1; 5875 return (errors); 5876 } 5877 5878 /* 5879 * gen_num creates a string from a keyword and an usigned long long in the 5880 * format: %d %s=%s\n 5881 * This is part of the extended header data record. 5882 */ 5883 5884 void 5885 gen_num(const char *keyword, const u_longlong_t number) 5886 { 5887 char save_val[ULONGLONG_MAX_DIGITS + 1]; 5888 int len; 5889 char *curr_ptr; 5890 5891 (void) sprintf(save_val, "%llu", number); 5892 /* 5893 * len = length of entire line, including itself. len will be 5894 * two digits. So, add the string lengths plus the length of len, 5895 * plus a blank, an equal sign, and a newline. 5896 */ 5897 len = strlen(save_val) + strlen(keyword) + 5; 5898 if (xrec_offset + len > xrec_size) { 5899 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5900 fatal(gettext( 5901 "cannot allocate extended header buffer")); 5902 xrec_ptr = curr_ptr; 5903 xrec_size *= 2; 5904 } 5905 (void) sprintf(&xrec_ptr[xrec_offset], 5906 "%d %s=%s\n", len, keyword, save_val); 5907 xrec_offset += len; 5908 } 5909 5910 /* 5911 * gen_date creates a string from a keyword and a timestruc_t in the 5912 * format: %d %s=%s\n 5913 * This is part of the extended header data record. 5914 * Currently, granularity is only microseconds, so the low-order three digits 5915 * will be truncated. 5916 */ 5917 5918 void 5919 gen_date(const char *keyword, const timestruc_t time_value) 5920 { 5921 /* Allow for <seconds>.<nanoseconds>\n */ 5922 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 5923 int len; 5924 char *curr_ptr; 5925 5926 (void) sprintf(save_val, "%ld", time_value.tv_sec); 5927 len = strlen(save_val); 5928 save_val[len] = '.'; 5929 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 5930 5931 /* 5932 * len = length of entire line, including itself. len will be 5933 * two digits. So, add the string lengths plus the length of len, 5934 * plus a blank, an equal sign, and a newline. 5935 */ 5936 len = strlen(save_val) + strlen(keyword) + 5; 5937 if (xrec_offset + len > xrec_size) { 5938 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5939 fatal(gettext( 5940 "cannot allocate extended header buffer")); 5941 xrec_ptr = curr_ptr; 5942 xrec_size *= 2; 5943 } 5944 (void) sprintf(&xrec_ptr[xrec_offset], 5945 "%d %s=%s\n", len, keyword, save_val); 5946 xrec_offset += len; 5947 } 5948 5949 /* 5950 * gen_string creates a string from a keyword and a char * in the 5951 * format: %d %s=%s\n 5952 * This is part of the extended header data record. 5953 */ 5954 5955 void 5956 gen_string(const char *keyword, const char *value) 5957 { 5958 int len; 5959 char *curr_ptr; 5960 5961 /* 5962 * len = length of entire line, including itself. The character length 5963 * of len must be 1-4 characters, because the maximum size of the path 5964 * or the name is PATH_MAX, which is 1024. So, assume 1 character 5965 * for len, one for the space, one for the "=", and one for the newline. 5966 * Then adjust as needed. 5967 */ 5968 /* LINTED constant expression */ 5969 assert(PATH_MAX <= 9996); 5970 len = strlen(value) + strlen(keyword) + 4; 5971 if (len > 997) 5972 len += 3; 5973 else if (len > 98) 5974 len += 2; 5975 else if (len > 9) 5976 len += 1; 5977 if (xrec_offset + len > xrec_size) { 5978 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5979 fatal(gettext( 5980 "cannot allocate extended header buffer")); 5981 xrec_ptr = curr_ptr; 5982 xrec_size *= 2; 5983 } 5984 #ifdef XHDR_DEBUG 5985 if (strcmp(keyword+1, "name") != 0) 5986 #endif 5987 (void) sprintf(&xrec_ptr[xrec_offset], 5988 "%d %s=%s\n", len, keyword, value); 5989 #ifdef XHDR_DEBUG 5990 else { 5991 len += 11; 5992 (void) sprintf(&xrec_ptr[xrec_offset], 5993 "%d %s=%snametoolong\n", len, keyword, value); 5994 } 5995 #endif 5996 xrec_offset += len; 5997 } 5998 5999 /* 6000 * Convert time found in the extended header data to seconds and nanoseconds. 6001 */ 6002 6003 void 6004 get_xtime(char *value, timestruc_t *xtime) 6005 { 6006 char nanosec[10]; 6007 char *period; 6008 int i; 6009 6010 (void) memset(nanosec, '0', 9); 6011 nanosec[9] = '\0'; 6012 6013 period = strchr(value, '.'); 6014 if (period != NULL) 6015 period[0] = '\0'; 6016 xtime->tv_sec = strtol(value, NULL, 10); 6017 if (period == NULL) 6018 xtime->tv_nsec = 0; 6019 else { 6020 i = strlen(period +1); 6021 (void) strncpy(nanosec, period + 1, min(i, 9)); 6022 xtime->tv_nsec = strtol(nanosec, NULL, 10); 6023 } 6024 } 6025 6026 /* 6027 * Check linkpath for length. 6028 * Emit an error message and return 1 if too long. 6029 */ 6030 6031 int 6032 chk_path_build( 6033 char *name, 6034 char *longname, 6035 char *linkname, 6036 char *prefix, 6037 char type, 6038 int filetype) 6039 { 6040 6041 if (strlen(linkname) > (size_t)NAMSIZ) { 6042 if (Eflag > 0) { 6043 xhdr_flgs |= _X_LINKPATH; 6044 Xtarhdr.x_linkpath = linkname; 6045 } else { 6046 (void) fprintf(stderr, gettext( 6047 "tar: %s: linked to %s\n"), longname, linkname); 6048 (void) fprintf(stderr, gettext( 6049 "tar: %s: linked name too long\n"), linkname); 6050 if (errflag) 6051 done(1); 6052 else 6053 Errflg = 1; 6054 return (1); 6055 } 6056 } 6057 if (xhdr_flgs & _X_LINKPATH) 6058 return (build_dblock(name, tchar, type, 6059 filetype, &stbuf, stbuf.st_dev, 6060 prefix)); 6061 else 6062 return (build_dblock(name, linkname, type, 6063 filetype, &stbuf, stbuf.st_dev, prefix)); 6064 } 6065 6066 /* 6067 * Convert from UTF-8 to local character set. 6068 */ 6069 6070 static int 6071 utf8_local( 6072 char *option, 6073 char **Xhdr_ptrptr, 6074 char *target, 6075 const char *source, 6076 int max_val) 6077 { 6078 static iconv_t iconv_cd; 6079 char *nl_target; 6080 const char *iconv_src; 6081 char *iconv_trg; 6082 size_t inlen; 6083 size_t outlen; 6084 6085 if (charset_type == -1) { /* iconv_open failed in earlier try */ 6086 (void) fprintf(stderr, gettext( 6087 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6088 xhdr_count, source); 6089 return (1); 6090 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 6091 nl_target = nl_langinfo(CODESET); 6092 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6093 nl_target = "646"; 6094 if (strcmp(nl_target, "646") == 0) 6095 charset_type = 1; 6096 else if (strcmp(nl_target, "UTF-8") == 0) 6097 charset_type = 3; 6098 else { 6099 if (strncmp(nl_target, "ISO", 3) == 0) 6100 nl_target += 3; 6101 charset_type = 2; 6102 errno = 0; 6103 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 6104 (iconv_t)-1) { 6105 if (errno == EINVAL) 6106 (void) fprintf(stderr, gettext( 6107 "tar: conversion routines not " 6108 "available for current locale. ")); 6109 (void) fprintf(stderr, gettext( 6110 "file # %llu: (%s) UTF-8 conversion" 6111 " failed.\n"), xhdr_count, source); 6112 charset_type = -1; 6113 return (1); 6114 } 6115 } 6116 } 6117 6118 /* locale using 7-bit codeset or UTF-8 locale */ 6119 if (charset_type == 1 || charset_type == 3) { 6120 if (strlen(source) > max_val) { 6121 (void) fprintf(stderr, gettext( 6122 "tar: file # %llu: Extended header %s too long.\n"), 6123 xhdr_count, option); 6124 return (1); 6125 } 6126 if (charset_type == 3) 6127 (void) strcpy(target, source); 6128 else if (c_utf8(target, source) != 0) { 6129 (void) fprintf(stderr, gettext( 6130 "tar: file # %llu: (%s) UTF-8 conversion" 6131 " failed.\n"), xhdr_count, source); 6132 return (1); 6133 } 6134 *Xhdr_ptrptr = target; 6135 return (0); 6136 } 6137 6138 iconv_src = source; 6139 iconv_trg = target; 6140 inlen = strlen(source); 6141 outlen = max_val * UTF_8_FACTOR; 6142 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6143 (size_t)-1) { /* Error occurred: didn't convert */ 6144 (void) fprintf(stderr, gettext( 6145 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6146 xhdr_count, source); 6147 /* Get remaining output; reinitialize conversion descriptor */ 6148 iconv_src = (const char *)NULL; 6149 inlen = 0; 6150 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6151 return (1); 6152 } 6153 /* Get remaining output; reinitialize conversion descriptor */ 6154 iconv_src = (const char *)NULL; 6155 inlen = 0; 6156 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6157 (size_t)-1) { /* Error occurred: didn't convert */ 6158 (void) fprintf(stderr, gettext( 6159 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6160 xhdr_count, source); 6161 return (1); 6162 } 6163 6164 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6165 if (strlen(target) > max_val) { 6166 (void) fprintf(stderr, gettext( 6167 "tar: file # %llu: Extended header %s too long.\n"), 6168 xhdr_count, option); 6169 return (1); 6170 } 6171 *Xhdr_ptrptr = target; 6172 return (0); 6173 } 6174 6175 /* 6176 * Check gname, uname, path, and linkpath to see if they need to go in an 6177 * extended header. If they are already slated to be in an extended header, 6178 * or if they are not ascii, then they need to be in the extended header. 6179 * Then, convert all extended names to UTF-8. 6180 */ 6181 6182 int 6183 gen_utf8_names(const char *filename) 6184 { 6185 static iconv_t iconv_cd; 6186 char *nl_target; 6187 char tempbuf[MAXNAM + 1]; 6188 int nbytes; 6189 int errors; 6190 6191 if (charset_type == -1) { /* Previous failure to open. */ 6192 (void) fprintf(stderr, gettext( 6193 "tar: file # %llu: UTF-8 conversion failed.\n"), 6194 xhdr_count); 6195 return (1); 6196 } 6197 6198 if (charset_type == 0) { /* Need to get conversion descriptor */ 6199 nl_target = nl_langinfo(CODESET); 6200 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6201 nl_target = "646"; 6202 if (strcmp(nl_target, "646") == 0) 6203 charset_type = 1; 6204 else if (strcmp(nl_target, "UTF-8") == 0) 6205 charset_type = 3; 6206 else { 6207 if (strncmp(nl_target, "ISO", 3) == 0) 6208 nl_target += 3; 6209 charset_type = 2; 6210 errno = 0; 6211 #ifdef ICONV_DEBUG 6212 (void) fprintf(stderr, 6213 "Opening iconv_cd with target %s\n", 6214 nl_target); 6215 #endif 6216 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 6217 (iconv_t)-1) { 6218 if (errno == EINVAL) 6219 (void) fprintf(stderr, gettext( 6220 "tar: conversion routines not " 6221 "available for current locale. ")); 6222 (void) fprintf(stderr, gettext( 6223 "file (%s): UTF-8 conversion failed.\n"), 6224 filename); 6225 charset_type = -1; 6226 return (1); 6227 } 6228 } 6229 } 6230 6231 errors = 0; 6232 6233 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 6234 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 6235 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 6236 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 6237 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 6238 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 6239 tempbuf[NAMSIZ] = '\0'; 6240 } 6241 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 6242 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 6243 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 6244 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 6245 tempbuf[PRESIZ] = '\0'; 6246 nbytes = strlen(tempbuf); 6247 if (nbytes > 0) { 6248 tempbuf[nbytes++] = '/'; 6249 tempbuf[nbytes] = '\0'; 6250 } 6251 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, 6252 (MAXNAM - nbytes)); 6253 tempbuf[MAXNAM] = '\0'; 6254 } 6255 errors += local_utf8(&Xtarhdr.x_path, local_path, 6256 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 6257 6258 if (errors > 0) 6259 (void) fprintf(stderr, gettext( 6260 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 6261 6262 if (errors && errflag) 6263 done(1); 6264 else 6265 if (errors) 6266 Errflg = 1; 6267 return (errors); 6268 } 6269 6270 static int 6271 local_utf8( 6272 char **Xhdr_ptrptr, 6273 char *target, 6274 const char *source, 6275 iconv_t iconv_cd, 6276 int xhdrflg, 6277 int max_val) 6278 { 6279 const char *iconv_src; 6280 const char *starting_src; 6281 char *iconv_trg; 6282 size_t inlen; 6283 size_t outlen; 6284 #ifdef ICONV_DEBUG 6285 unsigned char c_to_hex; 6286 #endif 6287 6288 /* 6289 * If the item is already slated for extended format, get the string 6290 * to convert from the extended header record. Otherwise, get it from 6291 * the regular (dblock) area. 6292 */ 6293 if (xhdr_flgs & xhdrflg) { 6294 if (charset_type == 3) { /* Already UTF-8, just copy */ 6295 (void) strcpy(target, *Xhdr_ptrptr); 6296 *Xhdr_ptrptr = target; 6297 return (0); 6298 } else 6299 iconv_src = (const char *) *Xhdr_ptrptr; 6300 } else { 6301 if (charset_type == 3) /* Already in UTF-8 format */ 6302 return (0); /* Don't create xhdr record */ 6303 iconv_src = source; 6304 } 6305 starting_src = iconv_src; 6306 iconv_trg = target; 6307 if ((inlen = strlen(iconv_src)) == 0) 6308 return (0); 6309 6310 if (charset_type == 1) { /* locale using 7-bit codeset */ 6311 if (c_utf8(target, starting_src) != 0) { 6312 (void) fprintf(stderr, 6313 gettext("tar: invalid character in" 6314 " UTF-8 conversion of '%s'\n"), starting_src); 6315 return (1); 6316 } 6317 return (0); 6318 } 6319 6320 outlen = max_val * UTF_8_FACTOR; 6321 errno = 0; 6322 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6323 (size_t)-1) { 6324 /* An error occurred, or not all characters were converted */ 6325 if (errno == EILSEQ) 6326 (void) fprintf(stderr, 6327 gettext("tar: invalid character in" 6328 " UTF-8 conversion of '%s'\n"), starting_src); 6329 else 6330 (void) fprintf(stderr, gettext( 6331 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6332 starting_src); 6333 /* Get remaining output; reinitialize conversion descriptor */ 6334 iconv_src = (const char *)NULL; 6335 inlen = 0; 6336 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6337 return (1); 6338 } 6339 /* Get remaining output; reinitialize conversion descriptor */ 6340 iconv_src = (const char *)NULL; 6341 inlen = 0; 6342 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6343 (size_t)-1) { /* Error occurred: didn't convert */ 6344 if (errno == EILSEQ) 6345 (void) fprintf(stderr, 6346 gettext("tar: invalid character in" 6347 " UTF-8 conversion of '%s'\n"), starting_src); 6348 else 6349 (void) fprintf(stderr, gettext( 6350 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6351 starting_src); 6352 return (1); 6353 } 6354 6355 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6356 if (strcmp(starting_src, target) != 0) { 6357 *Xhdr_ptrptr = target; 6358 xhdr_flgs |= xhdrflg; 6359 #ifdef ICONV_DEBUG 6360 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 6361 strlen(starting_src), inlen, max_val, outlen); 6362 (void) fprintf(stderr, "Input string:\n "); 6363 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 6364 c_to_hex = (unsigned char)starting_src[inlen]; 6365 (void) fprintf(stderr, " %2.2x", c_to_hex); 6366 if (inlen % 20 == 19) 6367 (void) fprintf(stderr, "\n "); 6368 } 6369 (void) fprintf(stderr, "\nOutput string:\n "); 6370 for (inlen = 0; inlen < strlen(target); inlen++) { 6371 c_to_hex = (unsigned char)target[inlen]; 6372 (void) fprintf(stderr, " %2.2x", c_to_hex); 6373 if (inlen % 20 == 19) 6374 (void) fprintf(stderr, "\n "); 6375 } 6376 (void) fprintf(stderr, "\n"); 6377 #endif 6378 } 6379 6380 return (0); 6381 } 6382 6383 /* 6384 * Function to test each byte of the source string to make sure it is 6385 * in within bounds (value between 0 and 127). 6386 * If valid, copy source to target. 6387 */ 6388 6389 int 6390 c_utf8(char *target, const char *source) 6391 { 6392 size_t len; 6393 const char *thischar; 6394 6395 len = strlen(source); 6396 thischar = source; 6397 while (len-- > 0) { 6398 if (!isascii((int)(*thischar++))) 6399 return (1); 6400 } 6401 6402 (void) strcpy(target, source); 6403 return (0); 6404 } 6405 6406 6407 #if defined(O_XATTR) 6408 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 6409 6410 static void 6411 prepare_xattr( 6412 char **attrbuf, 6413 char *filename, 6414 char *attrname, 6415 char typeflag, 6416 struct linkbuf *linkinfo, 6417 int *rlen) 6418 { 6419 char *bufhead; /* ptr to full buffer */ 6420 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 6421 struct xattr_buf *tptr; /* ptr to pathing pieces */ 6422 int totalen; /* total buffer length */ 6423 int len; /* length returned to user */ 6424 int stringlen; /* length of filename + attr */ 6425 /* 6426 * length of filename + attr 6427 * in link section 6428 */ 6429 int linkstringlen; 6430 int complen; /* length of pathing section */ 6431 int linklen; /* length of link section */ 6432 6433 /* 6434 * Release previous buffer 6435 */ 6436 6437 if (*attrbuf != (char *)NULL) { 6438 free(*attrbuf); 6439 *attrbuf = NULL; 6440 } 6441 6442 /* 6443 * First add in fixed size stuff 6444 */ 6445 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 6446 6447 /* 6448 * Add space for two nulls 6449 */ 6450 stringlen = strlen(attrname) + strlen(filename) + 2; 6451 complen = stringlen + sizeof (struct xattr_buf); 6452 6453 len += stringlen; 6454 6455 /* 6456 * Now add on space for link info if any 6457 */ 6458 6459 if (linkinfo != NULL) { 6460 /* 6461 * Again add space for two nulls 6462 */ 6463 linkstringlen = strlen(linkinfo->pathname) + 6464 strlen(linkinfo->attrname) + 2; 6465 len += linkstringlen; 6466 } 6467 6468 /* 6469 * Now add padding to end to fill out TBLOCK 6470 * 6471 * Function returns size of real data and not size + padding. 6472 */ 6473 6474 totalen = ROUNDTOTBLOCK(len); 6475 6476 if ((bufhead = calloc(1, totalen)) == NULL) { 6477 fatal(gettext("Out of memory.")); 6478 } 6479 6480 6481 /* 6482 * Now we can fill in the necessary pieces 6483 */ 6484 6485 if (linkinfo != (struct linkbuf *)NULL) { 6486 linklen = linkstringlen + (sizeof (struct xattr_buf)); 6487 } else { 6488 linklen = 0; 6489 } 6490 6491 /* 6492 * first fill in the fixed header 6493 */ 6494 hptr = (struct xattr_hdr *)bufhead; 6495 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 6496 (void) sprintf(hptr->h_component_len, "%0*d", 6497 sizeof (hptr->h_component_len) - 1, complen); 6498 (void) sprintf(hptr->h_link_component_len, "%0*d", 6499 sizeof (hptr->h_link_component_len) - 1, linklen); 6500 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 6501 6502 /* 6503 * Now fill in the filename + attrnames section 6504 */ 6505 6506 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 6507 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 6508 stringlen); 6509 (void) strcpy(tptr->h_names, filename); 6510 (void) strcpy(&tptr->h_names[strlen(filename) + 1], attrname); 6511 tptr->h_typeflag = typeflag; 6512 6513 /* 6514 * Now fill in the optional link section if we have one 6515 */ 6516 6517 if (linkinfo != (struct linkbuf *)NULL) { 6518 tptr = (struct xattr_buf *)(bufhead + 6519 sizeof (struct xattr_hdr) + complen); 6520 6521 (void) sprintf(tptr->h_namesz, "%0*d", 6522 sizeof (tptr->h_namesz) - 1, linkstringlen); 6523 (void) strcpy(tptr->h_names, linkinfo->pathname); 6524 (void) strcpy( 6525 &tptr->h_names[strlen(linkinfo->pathname) + 1], 6526 linkinfo->attrname); 6527 tptr->h_typeflag = typeflag; 6528 } 6529 *attrbuf = (char *)bufhead; 6530 *rlen = len; 6531 } 6532 6533 #else 6534 static void 6535 prepare_xattr( 6536 char **attrbuf, 6537 char *filename, 6538 char *attrname, 6539 char typeflag, 6540 struct linkbuf *linkinfo, 6541 int *rlen) 6542 { 6543 *attrbuf = NULL; 6544 *rlen = 0; 6545 } 6546 #endif 6547 6548 int 6549 getstat(int dirfd, char *longname, char *shortname) 6550 { 6551 6552 int i, j; 6553 int printerr; 6554 int slnkerr; 6555 struct stat symlnbuf; 6556 6557 if (!hflag) 6558 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 6559 else 6560 i = fstatat(dirfd, shortname, &stbuf, 0); 6561 6562 if (i < 0) { 6563 /* Initialize flag to print error mesg. */ 6564 printerr = 1; 6565 /* 6566 * If stat is done, then need to do lstat 6567 * to determine whether it's a sym link 6568 */ 6569 if (hflag) { 6570 /* Save returned error */ 6571 slnkerr = errno; 6572 6573 j = fstatat(dirfd, shortname, 6574 &symlnbuf, AT_SYMLINK_NOFOLLOW); 6575 /* 6576 * Suppress error message when file is a symbolic link 6577 * and function modifier 'l' is off. Exception: when 6578 * a symlink points to a symlink points to a 6579 * symlink ... and we get past MAXSYMLINKS. That 6580 * error will cause a file not to be archived, and 6581 * needs to be printed. 6582 */ 6583 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 6584 (S_ISLNK(symlnbuf.st_mode))) 6585 printerr = 0; 6586 6587 /* 6588 * Restore errno in case the lstat 6589 * on symbolic link change 6590 */ 6591 errno = slnkerr; 6592 } 6593 6594 if (printerr) { 6595 (void) fprintf(stderr, gettext( 6596 "tar: %s: %s\n"), longname, strerror(errno)); 6597 Errflg = 1; 6598 } 6599 return (1); 6600 } 6601 return (0); 6602 } 6603 6604 #if defined(O_XATTR) 6605 static void 6606 xattrs_put(char *longname, char *shortname, char *parent) 6607 { 6608 int dirfd; 6609 DIR *dirp; 6610 struct dirent *dp; 6611 6612 if (pathconf(shortname, _PC_XATTR_EXISTS) != 1) { 6613 return; 6614 } 6615 6616 if ((dirfd = attropen(shortname, ".", O_RDONLY)) < 0) { 6617 (void) fprintf(stderr, gettext( 6618 "tar: unable to open attribute directory for file %s\n"), 6619 longname); 6620 return; 6621 } 6622 6623 if ((dirp = fdopendir(dirfd)) == NULL) { 6624 (void) fprintf(stderr, gettext( 6625 "tar: unable to open dir pointer for file %s\n"), longname); 6626 return; 6627 } 6628 6629 while (dp = readdir(dirp)) { 6630 if (dp->d_name[0] == '.' && dp->d_name[1] == '.' && 6631 dp->d_name[2] == '\0') 6632 continue; 6633 6634 if (dp->d_name[0] == '.' && dp->d_name[1] == '\0') 6635 Hiddendir = 1; 6636 else 6637 Hiddendir = 0; 6638 6639 (void) putfile(longname, dp->d_name, parent, 6640 XATTR_FILE, LEV0, SYMLINK_LEV0); 6641 6642 if (exitflag) 6643 break; 6644 } 6645 6646 (void) closedir(dirp); 6647 } 6648 #else 6649 static void 6650 xattrs_put(char *longname, char *shortname, char *parent) 6651 { 6652 } 6653 #endif /* O_XATTR */ 6654 6655 static int 6656 put_link(char *name, char *longname, char *component, 6657 char *prefix, int filetype, char type) 6658 { 6659 6660 if (stbuf.st_nlink > 1) { 6661 struct linkbuf *lp; 6662 int found = 0; 6663 6664 for (lp = ihead; lp != NULL; lp = lp->nextp) 6665 if (lp->inum == stbuf.st_ino && 6666 lp->devnum == stbuf.st_dev) { 6667 found++; 6668 break; 6669 } 6670 if (found) { 6671 #if defined(O_XATTR) 6672 if (filetype == XATTR_FILE) 6673 if (put_xattr_hdr(longname, component, prefix, 6674 type, filetype, lp)) { 6675 goto out; 6676 } 6677 #endif 6678 stbuf.st_size = (off_t)0; 6679 if (filetype != XATTR_FILE) { 6680 tomodes(&stbuf); 6681 if (chk_path_build(name, longname, lp->pathname, 6682 prefix, type, filetype) > 0) { 6683 goto out; 6684 } 6685 } 6686 6687 if (mulvol && tapepos + 1 >= blocklim) 6688 newvol(); 6689 (void) writetbuf((char *)&dblock, 1); 6690 /* 6691 * write_ancillary() is not needed here. 6692 * The first link is handled in the following 6693 * else statement. No need to process ACLs 6694 * for other hard links since they are the 6695 * same file. 6696 */ 6697 6698 if (vflag) { 6699 #ifdef DEBUG 6700 if (NotTape) 6701 DEBUG("seek = %" FMT_blkcnt_t 6702 "K\t", K(tapepos), 0); 6703 #endif 6704 if (filetype == XATTR_FILE) { 6705 (void) fprintf(vfile, gettext( 6706 "a %s attribute %s link to " 6707 "attribute %s\n"), 6708 name, component, lp->attrname); 6709 } else { 6710 (void) fprintf(vfile, gettext( 6711 "a %s link to %s\n"), 6712 longname, lp->pathname); 6713 } 6714 } 6715 lp->count--; 6716 return (0); 6717 } else { 6718 lp = (struct linkbuf *)getmem(sizeof (*lp)); 6719 if (lp != (struct linkbuf *)NULL) { 6720 lp->nextp = ihead; 6721 ihead = lp; 6722 lp->inum = stbuf.st_ino; 6723 lp->devnum = stbuf.st_dev; 6724 lp->count = stbuf.st_nlink - 1; 6725 if (filetype == XATTR_FILE) { 6726 (void) strcpy(lp->pathname, longname); 6727 (void) strcpy(lp->attrname, component); 6728 } else { 6729 (void) strcpy(lp->pathname, longname); 6730 (void) strcpy(lp->attrname, ""); 6731 } 6732 } 6733 } 6734 } 6735 6736 out: 6737 return (1); 6738 } 6739 6740 static int 6741 put_extra_attributes(char *longname, char *shortname, char *prefix, 6742 int filetype, char typeflag) 6743 { 6744 static acl_t *aclp = NULL; 6745 int error; 6746 6747 if (aclp != NULL) { 6748 acl_free(aclp); 6749 aclp = NULL; 6750 } 6751 #if defined(O_XATTR) 6752 if (atflag && filetype == XATTR_FILE) { 6753 if (put_xattr_hdr(longname, shortname, prefix, 6754 typeflag, filetype, NULL)) { 6755 return (1); 6756 } 6757 } 6758 #endif 6759 6760 /* ACL support */ 6761 if (pflag) { 6762 char *secinfo = NULL; 6763 int len = 0; 6764 6765 /* ACL support */ 6766 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 6767 /* 6768 * Get ACL info: dont bother allocating space if 6769 * there is only a trivial ACL. 6770 */ 6771 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 6772 &aclp)) != 0) { 6773 (void) fprintf(stderr, gettext( 6774 "%s: failed to retrieve acl : %s\n"), 6775 longname, acl_strerror(error)); 6776 return (1); 6777 } 6778 } 6779 6780 /* append security attributes if any */ 6781 if (aclp != NULL) { 6782 (void) append_secattr(&secinfo, &len, aclp); 6783 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 6784 } 6785 } 6786 return (0); 6787 } 6788 6789 #if defined(O_XATTR) 6790 static int 6791 put_xattr_hdr(char *longname, char *shortname, char *prefix, 6792 int typeflag, int filetype, struct linkbuf *lp) 6793 { 6794 char *lname = NULL; 6795 char *sname = NULL; 6796 int error = 0; 6797 static char *attrbuf = NULL; 6798 int attrlen; 6799 6800 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 6801 strlen(shortname) + strlen(".hdr") + 1); 6802 6803 if (lname == NULL) { 6804 fatal(gettext("Out of Memory.")); 6805 } 6806 sname = malloc(sizeof (char) * strlen(shortname) + 6807 strlen(".hdr")); 6808 if (sname == NULL) { 6809 fatal(gettext("Out of Memory.")); 6810 } 6811 6812 (void) sprintf(sname, "%s.hdr", shortname); 6813 (void) sprintf(lname, "/dev/null/%s", sname); 6814 6815 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 6816 sizeof (dblock.dbuf.name)) { 6817 fatal(gettext( 6818 "Buffer overflow writing extended attribute file name")); 6819 } 6820 6821 /* 6822 * dump extended attr lookup info 6823 */ 6824 prepare_xattr(&attrbuf, longname, shortname, typeflag, lp, &attrlen); 6825 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 6826 6827 (void) sprintf(lname, "/dev/null/%s", shortname); 6828 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 6829 6830 /* 6831 * Set up filename for attribute 6832 */ 6833 6834 error = build_dblock(lname, tchar, '0', filetype, 6835 &stbuf, stbuf.st_dev, prefix); 6836 free(lname); 6837 free(sname); 6838 6839 return (error); 6840 } 6841 #endif 6842 6843 #if defined(O_XATTR) 6844 static int 6845 read_xattr_hdr() 6846 { 6847 char buf[TBLOCK]; 6848 blkcnt_t blocks; 6849 char *tp; 6850 off_t bytes; 6851 int comp_len, link_len; 6852 int namelen; 6853 6854 6855 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 6856 return (1); 6857 6858 bytes = stbuf.st_size; 6859 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 6860 (void) fprintf(stderr, gettext( 6861 "Insufficient memory for extended attribute\n")); 6862 return (1); 6863 } 6864 6865 tp = (char *)xattrhead; 6866 blocks = TBLOCKS(bytes); 6867 while (blocks-- > 0) { 6868 readtape(buf); 6869 if (bytes <= TBLOCK) { 6870 (void) memcpy(tp, buf, (size_t)bytes); 6871 break; 6872 } else { 6873 (void) memcpy(tp, buf, TBLOCK); 6874 tp += TBLOCK; 6875 } 6876 bytes -= TBLOCK; 6877 } 6878 6879 /* 6880 * Validate that we can handle header format 6881 */ 6882 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 6883 (void) fprintf(stderr, 6884 gettext("Unknown extended attribute format encountered\n")); 6885 (void) fprintf(stderr, 6886 gettext("Disabling extended attribute parsing\n")); 6887 xattrbadhead = 1; 6888 return (0); 6889 } 6890 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 6891 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 6892 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 6893 sizeof (struct xattr_hdr)); 6894 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 6895 if (link_len > 0) 6896 xattr_linkp = (struct xattr_buf *) 6897 ((int)xattrp + (int)comp_len); 6898 else 6899 xattr_linkp = NULL; 6900 6901 xattraname = xattrp->h_names + strlen(xattrp->h_names) + 1; 6902 if (xattr_linkp) { 6903 xattr_linkaname = xattr_linkp->h_names + 6904 strlen(xattr_linkp->h_names) + 1; 6905 } else { 6906 xattr_linkaname = NULL; 6907 } 6908 6909 return (0); 6910 } 6911 #else 6912 static int 6913 read_xattr_hdr() 6914 { 6915 return (0); 6916 } 6917 #endif 6918 6919 /* 6920 * skip over extra slashes in string. 6921 * 6922 * For example: 6923 * /usr/tmp///// 6924 * 6925 * would return pointer at 6926 * /usr/tmp///// 6927 * ^ 6928 */ 6929 static char * 6930 skipslashes(char *string, char *start) 6931 { 6932 while ((string > start) && *(string - 1) == '/') { 6933 string--; 6934 } 6935 6936 return (string); 6937 } 6938 6939 /* 6940 * Return the parent directory of a given path. 6941 * 6942 * Examples: 6943 * /usr/tmp return /usr 6944 * /usr/tmp/file return /usr/tmp 6945 * / returns . 6946 * /usr returns / 6947 * file returns . 6948 * 6949 * dir is assumed to be at least as big as path. 6950 */ 6951 static void 6952 get_parent(char *path, char *dir) 6953 { 6954 char *s; 6955 char tmpdir[PATH_MAX + 1]; 6956 6957 if (strlen(path) > PATH_MAX) { 6958 fatal(gettext("pathname is too long")); 6959 } 6960 (void) strcpy(tmpdir, path); 6961 chop_endslashes(tmpdir); 6962 6963 if ((s = strrchr(tmpdir, '/')) == NULL) { 6964 (void) strcpy(dir, "."); 6965 } else { 6966 s = skipslashes(s, tmpdir); 6967 *s = '\0'; 6968 if (s == tmpdir) 6969 (void) strcpy(dir, "/"); 6970 else 6971 (void) strcpy(dir, tmpdir); 6972 } 6973 } 6974 6975 #if defined(O_XATTR) 6976 static char * 6977 get_component(char *path) 6978 { 6979 char *ptr; 6980 6981 ptr = strrchr(path, '/'); 6982 if (ptr == NULL) { 6983 return (path); 6984 } else { 6985 /* 6986 * Handle trailing slash 6987 */ 6988 if (*(ptr + 1) == '\0') 6989 return (ptr); 6990 else 6991 return (ptr + 1); 6992 } 6993 } 6994 #else 6995 static char * 6996 get_component(char *path) 6997 { 6998 return (path); 6999 } 7000 #endif 7001 7002 static int 7003 retry_attrdir_open(char *name) 7004 { 7005 int dirfd = -1; 7006 struct timeval times[2]; 7007 mode_t newmode; 7008 struct stat parentstat; 7009 acl_t *aclp = NULL; 7010 int error; 7011 7012 /* 7013 * We couldn't get to attrdir. See if its 7014 * just a mode problem on the parent file. 7015 * for example: a mode such as r-xr--r-- 7016 * won't let us create an attribute dir 7017 * if it doesn't already exist. 7018 * 7019 * If file has a non-trivial ACL, then save it 7020 * off so that we can place it back on after doing 7021 * chmod's. 7022 */ 7023 7024 if (stat(name, &parentstat) == -1) { 7025 (void) fprintf(stderr, gettext("tar: cannot stat file %s %s\n"), 7026 name, strerror(errno)); 7027 return (-1); 7028 } 7029 if ((error = acl_get(name, ACL_NO_TRIVIAL, &aclp)) != 0) { 7030 (void) fprintf(stderr, gettext("tar: failed to retrieve ACL on" 7031 " %s %s\n"), name, strerror(errno)); 7032 return (-1); 7033 } 7034 7035 newmode = S_IWUSR | parentstat.st_mode; 7036 if (chmod(name, newmode) == -1) { 7037 (void) fprintf(stderr, 7038 gettext("tar: cannot chmod file %s to %o %s\n"), 7039 name, newmode, strerror(errno)); 7040 if (aclp) 7041 acl_free(aclp); 7042 return (-1); 7043 } 7044 7045 dirfd = attropen(name, ".", O_RDONLY); 7046 7047 /* 7048 * Don't print error message if attropen() failed, 7049 * caller will print message. 7050 */ 7051 7052 /* 7053 * Put mode back to original 7054 */ 7055 if (chmod(name, parentstat.st_mode) == -1) { 7056 (void) fprintf(stderr, 7057 gettext("tar: cannot chmod file %s to %o %s\n"), 7058 name, newmode, strerror(errno)); 7059 } 7060 7061 if (aclp) { 7062 error = acl_set(name, aclp); 7063 if (error) { 7064 (void) fprintf(stderr, 7065 gettext("tar: %s: failed to set acl entries\n"), 7066 name); 7067 } 7068 acl_free(aclp); 7069 } 7070 7071 /* 7072 * Put back time stamps 7073 */ 7074 7075 times[0].tv_sec = parentstat.st_atime; 7076 times[0].tv_usec = 0; 7077 times[1].tv_sec = parentstat.st_mtime; 7078 times[1].tv_usec = 0; 7079 (void) utimes(name, times); 7080 7081 return (dirfd); 7082 } 7083 7084 #if !defined(O_XATTR) 7085 static int 7086 openat64(int fd, const char *name, int oflag, mode_t cmode) 7087 { 7088 return (open64(name, oflag, cmode)); 7089 } 7090 7091 static int 7092 openat(int fd, const char *name, int oflag, mode_t cmode) 7093 { 7094 return (open(name, oflag, cmode)); 7095 } 7096 7097 static int 7098 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 7099 { 7100 if (flag == AT_SYMLINK_NOFOLLOW) 7101 return (lchown(name, owner, group)); 7102 else 7103 return (chown(name, owner, group)); 7104 } 7105 7106 static int 7107 renameat(int fromfd, char *old, int tofd, char *new) 7108 { 7109 return (rename(old, new)); 7110 } 7111 7112 static int 7113 futimesat(int fd, char *path, struct timeval times[2]) 7114 { 7115 return (utimes(path, times)); 7116 } 7117 7118 static int 7119 unlinkat(int dirfd, char *path, int flag) 7120 { 7121 if (flag == AT_REMOVEDIR) 7122 return (rmdir(path)); 7123 else 7124 return (unlink(path)); 7125 } 7126 7127 static int 7128 fstatat(int fd, char *path, struct stat *buf, int flag) 7129 { 7130 if (flag == AT_SYMLINK_NOFOLLOW) 7131 return (lstat(path, buf)); 7132 else 7133 return (stat(path, buf)); 7134 } 7135 7136 static int 7137 attropen(char *file, char *attr, int omode, mode_t cmode) 7138 { 7139 errno = ENOTSUP; 7140 return (-1); 7141 } 7142 #endif 7143 7144 static void 7145 chop_endslashes(char *path) 7146 { 7147 char *end, *ptr; 7148 7149 /* 7150 * Chop of slashes, but not if all we have is slashes 7151 * for example: //// 7152 * should make no changes, otherwise it will screw up 7153 * checkdir 7154 */ 7155 end = &path[strlen(path) -1]; 7156 if (*end == '/' && end != path) { 7157 ptr = skipslashes(end, path); 7158 if (ptr != NULL && ptr != path) { 7159 *ptr = '\0'; 7160 } 7161 } 7162 } 7163