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 3029 error = 3030 acl_fromtext( 3031 &attr->attr_info[0], &aclp); 3032 3033 if (error != 0) { 3034 (void) fprintf(stderr, 3035 gettext( 3036 "aclfromtext " 3037 "failed: %s\n"), 3038 acl_strerror( 3039 error)); 3040 bytes -= attrsize; 3041 break; 3042 } 3043 if (acl_cnt(aclp) != cnt) { 3044 (void) fprintf(stderr, 3045 gettext( 3046 "aclcnt error\n")); 3047 bytes -= attrsize; 3048 break; 3049 } 3050 bytes -= attrsize; 3051 break; 3052 3053 /* SunFed case goes here */ 3054 3055 default: 3056 (void) fprintf(stderr, gettext( 3057 "unrecognized attr" 3058 " type\n")); 3059 bytes = (off_t)0; 3060 break; 3061 } 3062 3063 /* next attributes */ 3064 tp += attrsize; 3065 } while (bytes != 0); 3066 free(secp); 3067 } else 3068 passtape(); 3069 } /* acl */ 3070 3071 } /* for */ 3072 3073 /* 3074 * Ensure that all the directories still on the directory stack 3075 * get their modification times set correctly by flushing the 3076 * stack. 3077 */ 3078 3079 doDirTimes(NULL, time_zero); 3080 3081 /* 3082 * Check if the number of files extracted is different from the 3083 * number of files listed on the command line 3084 */ 3085 if (fcnt > xcnt) { 3086 (void) fprintf(stderr, 3087 gettext("tar: %d file(s) not extracted\n"), 3088 fcnt-xcnt); 3089 Errflg = 1; 3090 } 3091 } 3092 3093 /* 3094 * xblocks extract file/extent from tape to output file 3095 * 3096 * xblocks(bytes, ofile); 3097 * unsigned long long bytes; size of extent or file to be extracted 3098 * 3099 * called by doxtract() and xsfile() 3100 */ 3101 3102 static void 3103 xblocks(off_t bytes, int ofile) 3104 { 3105 blkcnt_t blocks; 3106 char buf[TBLOCK]; 3107 char tempname[NAMSIZ+1]; 3108 int write_count; 3109 3110 blocks = TBLOCKS(bytes); 3111 while (blocks-- > 0) { 3112 readtape(buf); 3113 if (bytes > TBLOCK) 3114 write_count = TBLOCK; 3115 else 3116 write_count = bytes; 3117 if (write(ofile, buf, write_count) < 0) { 3118 if (xhdr_flgs & _X_PATH) 3119 (void) strcpy(tempname, Xtarhdr.x_path); 3120 else 3121 (void) sprintf(tempname, "%.*s", NAMSIZ, 3122 dblock.dbuf.name); 3123 (void) fprintf(stderr, gettext( 3124 "tar: %s: HELP - extract write error\n"), tempname); 3125 done(2); 3126 } 3127 bytes -= TBLOCK; 3128 } 3129 } 3130 3131 3132 /* 3133 * xsfile extract split file 3134 * 3135 * xsfile(ofd); ofd = output file descriptor 3136 * 3137 * file extracted and put in ofd via xblocks() 3138 * 3139 * NOTE: only called by doxtract() to extract one large file 3140 */ 3141 3142 static union hblock savedblock; /* to ensure same file across volumes */ 3143 3144 static void 3145 xsfile(int ofd) 3146 { 3147 int i, c; 3148 char name[PATH_MAX+1]; /* holds name for diagnostics */ 3149 int extents, totalext; 3150 off_t bytes, totalbytes; 3151 3152 if (xhdr_flgs & _X_PATH) 3153 (void) strcpy(name, Xtarhdr.x_path); 3154 else 3155 (void) sprintf(name, "%.*s", NAMSIZ, dblock.dbuf.name); 3156 3157 totalbytes = (off_t)0; /* in case we read in half the file */ 3158 totalext = 0; /* these keep count */ 3159 3160 (void) fprintf(stderr, gettext( 3161 "tar: %s split across %d volumes\n"), name, extotal); 3162 3163 /* make sure we do extractions in order */ 3164 if (extno != 1) { /* starting in middle of file? */ 3165 wchar_t yeschar; 3166 wchar_t nochar; 3167 (void) mbtowc(&yeschar, nl_langinfo(YESSTR), MB_LEN_MAX); 3168 (void) mbtowc(&nochar, nl_langinfo(NOSTR), MB_LEN_MAX); 3169 (void) printf(gettext( 3170 "tar: first extent read is not #1\n" 3171 "OK to read file beginning with extent #%d (%wc/%wc) ? "), 3172 extno, yeschar, nochar); 3173 if (yesnoresponse() != yeschar) { 3174 canit: 3175 passtape(); 3176 if (close(ofd) != 0) 3177 vperror(2, gettext("close error")); 3178 return; 3179 } 3180 } 3181 extents = extotal; 3182 i = extno; 3183 /*CONSTCOND*/ 3184 while (1) { 3185 if (xhdr_flgs & _X_SIZE) { 3186 bytes = extsize; 3187 } else { 3188 bytes = stbuf.st_size; 3189 } 3190 3191 if (vflag) 3192 (void) fprintf(vfile, "+++ x %s [extent #%d], %" 3193 FMT_off_t " bytes, %ldK\n", name, extno, bytes, 3194 (long)K(TBLOCKS(bytes))); 3195 xblocks(bytes, ofd); 3196 3197 totalbytes += bytes; 3198 totalext++; 3199 if (++i > extents) 3200 break; 3201 3202 /* get next volume and verify it's the right one */ 3203 copy(&savedblock, &dblock); 3204 tryagain: 3205 newvol(); 3206 xhdr_flgs = 0; 3207 getdir(); 3208 if (Xhdrflag > 0) 3209 (void) get_xdata(); /* Get x-header & regular hdr */ 3210 if (endtape()) { /* seemingly empty volume */ 3211 (void) fprintf(stderr, gettext( 3212 "tar: first record is null\n")); 3213 asknicely: 3214 (void) fprintf(stderr, gettext( 3215 "tar: need volume with extent #%d of %s\n"), 3216 i, name); 3217 goto tryagain; 3218 } 3219 if (notsame()) { 3220 (void) fprintf(stderr, gettext( 3221 "tar: first file on that volume is not " 3222 "the same file\n")); 3223 goto asknicely; 3224 } 3225 if (i != extno) { 3226 (void) fprintf(stderr, gettext( 3227 "tar: extent #%d received out of order\ntar: " 3228 "should be #%d\n"), extno, i); 3229 (void) fprintf(stderr, gettext( 3230 "Ignore error, Abort this file, or " 3231 "load New volume (i/a/n) ? ")); 3232 c = response(); 3233 if (c == 'a') 3234 goto canit; 3235 if (c != 'i') /* default to new volume */ 3236 goto asknicely; 3237 i = extno; /* okay, start from there */ 3238 } 3239 } 3240 if (vflag) 3241 (void) fprintf(vfile, gettext( 3242 "x %s (in %d extents), %" FMT_off_t " bytes, %ldK\n"), 3243 name, totalext, totalbytes, (long)K(TBLOCKS(totalbytes))); 3244 } 3245 3246 3247 /* 3248 * notsame() check if extract file extent is invalid 3249 * 3250 * returns true if anything differs between savedblock and dblock 3251 * except extno (extent number), checksum, or size (extent size). 3252 * Determines if this header belongs to the same file as the one we're 3253 * extracting. 3254 * 3255 * NOTE: though rather bulky, it is only called once per file 3256 * extension, and it can withstand changes in the definition 3257 * of the header structure. 3258 * 3259 * WARNING: this routine is local to xsfile() above 3260 */ 3261 3262 static int 3263 notsame(void) 3264 { 3265 return ( 3266 (strncmp(savedblock.dbuf.name, dblock.dbuf.name, NAMSIZ)) || 3267 (strcmp(savedblock.dbuf.mode, dblock.dbuf.mode)) || 3268 (strcmp(savedblock.dbuf.uid, dblock.dbuf.uid)) || 3269 (strcmp(savedblock.dbuf.gid, dblock.dbuf.gid)) || 3270 (strcmp(savedblock.dbuf.mtime, dblock.dbuf.mtime)) || 3271 (savedblock.dbuf.typeflag != dblock.dbuf.typeflag) || 3272 (strncmp(savedblock.dbuf.linkname, dblock.dbuf.linkname, NAMSIZ)) || 3273 (savedblock.dbuf.extotal != dblock.dbuf.extotal) || 3274 (strcmp(savedblock.dbuf.efsize, dblock.dbuf.efsize))); 3275 } 3276 3277 3278 static void 3279 #ifdef _iBCS2 3280 dotable(char *argv[], int tbl_cnt) 3281 #else 3282 dotable(char *argv[]) 3283 #endif 3284 3285 { 3286 int tcnt; /* count # files tabled */ 3287 int fcnt; /* count # files in argv list */ 3288 char *namep, *dirp, *comp; 3289 int want; 3290 char aclchar = ' '; /* either blank or '+' */ 3291 char templink[PATH_MAX+1]; 3292 char *np; 3293 3294 dumping = 0; 3295 3296 /* if not on magtape, maximize seek speed */ 3297 if (NotTape && !bflag) { 3298 #if SYS_BLOCK > TBLOCK 3299 nblock = SYS_BLOCK / TBLOCK; 3300 #else 3301 nblock = 1; 3302 #endif 3303 } 3304 /* 3305 * Count the number of files that are to be tabled 3306 */ 3307 fcnt = tcnt = 0; 3308 3309 #ifdef _iBCS2 3310 initarg(argv, Filefile); 3311 while (nextarg() != NULL) 3312 ++fcnt; 3313 fcnt += tbl_cnt; 3314 #endif /* _iBCS2 */ 3315 3316 for (;;) { 3317 3318 /* namep is set by wantit to point to the full name */ 3319 if ((want = wantit(argv, &namep, &dirp, &comp)) == 0) 3320 continue; 3321 if (want == -1) 3322 break; 3323 if (dblock.dbuf.typeflag != 'A') 3324 ++tcnt; 3325 3326 /* 3327 * ACL support: 3328 * aclchar is introduced to indicate if there are 3329 * acl entries. longt() now takes one extra argument. 3330 */ 3331 if (vflag) { 3332 if (dblock.dbuf.typeflag == 'A') { 3333 aclchar = '+'; 3334 passtape(); 3335 continue; 3336 } 3337 longt(&stbuf, aclchar); 3338 aclchar = ' '; 3339 } 3340 3341 3342 #if defined(O_XATTR) 3343 if (xattrp != (struct xattr_buf *)NULL) { 3344 np = xattrp->h_names + strlen(xattrp->h_names) + 1; 3345 (void) printf(gettext("%s attribute %s"), 3346 xattrp->h_names, np); 3347 3348 } else { 3349 (void) printf("%s", namep); 3350 } 3351 #else 3352 (void) printf("%s", namep); 3353 #endif 3354 3355 if (extno != 0) { 3356 if (vflag) { 3357 /* keep the '\n' for backwards compatibility */ 3358 (void) fprintf(vfile, gettext( 3359 "\n [extent #%d of %d]"), extno, extotal); 3360 } else { 3361 (void) fprintf(vfile, gettext( 3362 " [extent #%d of %d]"), extno, extotal); 3363 } 3364 } 3365 if (xhdr_flgs & _X_LINKPATH) { 3366 (void) strcpy(templink, Xtarhdr.x_linkpath); 3367 } else { 3368 #if defined(O_XATTR) 3369 if (xattrp != (struct xattr_buf *)NULL) { 3370 (void) sprintf(templink, 3371 "file %.*s", NAMSIZ, xattrp->h_names); 3372 } else { 3373 (void) sprintf(templink, "%.*s", NAMSIZ, 3374 dblock.dbuf.linkname); 3375 } 3376 #else 3377 (void) sprintf(templink, "%.*s", NAMSIZ, 3378 dblock.dbuf.linkname); 3379 #endif 3380 templink[NAMSIZ] = '\0'; 3381 } 3382 if (dblock.dbuf.typeflag == '1') { 3383 /* 3384 * TRANSLATION_NOTE 3385 * Subject is omitted here. 3386 * Translate this as if 3387 * <subject> linked to %s 3388 */ 3389 #if defined(O_XATTR) 3390 if (xattrp != (struct xattr_buf *)NULL) { 3391 (void) printf( 3392 gettext(" linked to attribute %s"), 3393 xattr_linkp->h_names + 3394 strlen(xattr_linkp->h_names) + 1); 3395 } else { 3396 (void) printf( 3397 gettext(" linked to %s"), templink); 3398 } 3399 #else 3400 (void) printf( 3401 gettext(" linked to %s"), templink); 3402 3403 #endif 3404 } 3405 if (dblock.dbuf.typeflag == '2') 3406 (void) printf(gettext( 3407 /* 3408 * TRANSLATION_NOTE 3409 * Subject is omitted here. 3410 * Translate this as if 3411 * <subject> symbolic link to %s 3412 */ 3413 " symbolic link to %s"), templink); 3414 (void) printf("\n"); 3415 #if defined(O_XATTR) 3416 if (xattrp != (struct xattr_buf *)NULL) { 3417 free(xattrhead); 3418 xattrp = NULL; 3419 xattrhead = NULL; 3420 } 3421 #endif 3422 passtape(); 3423 } 3424 /* 3425 * Check if the number of files tabled is different from the 3426 * number of files listed on the command line 3427 */ 3428 if (fcnt > tcnt) { 3429 (void) fprintf(stderr, gettext( 3430 "tar: %d file(s) not found\n"), fcnt-tcnt); 3431 Errflg = 1; 3432 } 3433 } 3434 3435 static void 3436 putempty(blkcnt_t n) 3437 { 3438 char buf[TBLOCK]; 3439 char *cp; 3440 3441 for (cp = buf; cp < &buf[TBLOCK]; ) 3442 *cp++ = '\0'; 3443 while (n-- > 0) 3444 (void) writetbuf(buf, 1); 3445 } 3446 3447 static ushort_t Ftype = S_IFMT; 3448 3449 static void 3450 verbose(struct stat *st, char aclchar) 3451 { 3452 int i, j, temp; 3453 mode_t mode; 3454 char modestr[12]; 3455 3456 for (i = 0; i < 11; i++) 3457 modestr[i] = '-'; 3458 modestr[i] = '\0'; 3459 3460 /* a '+' sign is printed if there is ACL */ 3461 modestr[i-1] = aclchar; 3462 3463 mode = st->st_mode; 3464 for (i = 0; i < 3; i++) { 3465 temp = (mode >> (6 - (i * 3))); 3466 j = (i * 3) + 1; 3467 if (S_IROTH & temp) 3468 modestr[j] = 'r'; 3469 if (S_IWOTH & temp) 3470 modestr[j + 1] = 'w'; 3471 if (S_IXOTH & temp) 3472 modestr[j + 2] = 'x'; 3473 } 3474 temp = st->st_mode & Ftype; 3475 switch (temp) { 3476 case (S_IFIFO): 3477 modestr[0] = 'p'; 3478 break; 3479 case (S_IFCHR): 3480 modestr[0] = 'c'; 3481 break; 3482 case (S_IFDIR): 3483 modestr[0] = 'd'; 3484 break; 3485 case (S_IFBLK): 3486 modestr[0] = 'b'; 3487 break; 3488 case (S_IFREG): /* was initialized to '-' */ 3489 break; 3490 case (S_IFLNK): 3491 modestr[0] = 'l'; 3492 break; 3493 default: 3494 /* This field may be zero in old archives. */ 3495 if (is_posix && dblock.dbuf.typeflag != '1') { 3496 /* 3497 * For POSIX compliant archives, the mode field 3498 * consists of 12 bits, ie: the file type bits 3499 * are not stored in dblock.dbuf.mode. 3500 * For files other than hard links, getdir() sets 3501 * the file type bits in the st_mode field of the 3502 * stat structure based upon dblock.dbuf.typeflag. 3503 */ 3504 (void) fprintf(stderr, gettext( 3505 "tar: impossible file type")); 3506 } 3507 } 3508 3509 if ((S_ISUID & Gen.g_mode) == S_ISUID) 3510 modestr[3] = 's'; 3511 if ((S_ISVTX & Gen.g_mode) == S_ISVTX) 3512 modestr[9] = 't'; 3513 if ((S_ISGID & Gen.g_mode) == S_ISGID && modestr[6] == 'x') 3514 modestr[6] = 's'; 3515 else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x') 3516 modestr[6] = 'l'; 3517 (void) fprintf(vfile, "%s", modestr); 3518 } 3519 3520 static void 3521 longt(struct stat *st, char aclchar) 3522 { 3523 char fileDate[30]; 3524 struct tm *tm; 3525 3526 verbose(st, aclchar); 3527 (void) fprintf(vfile, "%3ld/%-3ld", st->st_uid, st->st_gid); 3528 3529 if (dblock.dbuf.typeflag == '2') { 3530 if (xhdr_flgs & _X_LINKPATH) 3531 st->st_size = (off_t)strlen(Xtarhdr.x_linkpath); 3532 else 3533 st->st_size = (off_t)(memchr(dblock.dbuf.linkname, 3534 '\0', NAMSIZ) ? 3535 (strlen(dblock.dbuf.linkname)) : (NAMSIZ)); 3536 } 3537 (void) fprintf(vfile, " %6" FMT_off_t, st->st_size); 3538 3539 tm = localtime(&(st->st_mtime)); 3540 (void) strftime(fileDate, sizeof (fileDate), 3541 dcgettext((const char *)0, "%b %e %R %Y", LC_TIME), tm); 3542 (void) fprintf(vfile, " %s ", fileDate); 3543 } 3544 3545 3546 /* 3547 * checkdir - Attempt to ensure that the path represented in name 3548 * exists, and return 1 if this is true and name itself is a 3549 * directory. 3550 * Return 0 if this path cannot be created or if name is not 3551 * a directory. 3552 */ 3553 3554 static int 3555 checkdir(char *name) 3556 { 3557 char lastChar; /* the last character in name */ 3558 char *cp; /* scratch pointer into name */ 3559 char *firstSlash = NULL; /* first slash in name */ 3560 char *lastSlash = NULL; /* last slash in name */ 3561 int nameLen; /* length of name */ 3562 int trailingSlash; /* true if name ends in slash */ 3563 int leadingSlash; /* true if name begins with slash */ 3564 int markedDir; /* true if name denotes a directory */ 3565 int success; /* status of makeDir call */ 3566 3567 3568 /* 3569 * Scan through the name, and locate first and last slashes. 3570 */ 3571 3572 for (cp = name; *cp; cp++) { 3573 if (*cp == '/') { 3574 if (! firstSlash) { 3575 firstSlash = cp; 3576 } 3577 lastSlash = cp; 3578 } 3579 } 3580 3581 /* 3582 * Determine what you can from the proceeds of the scan. 3583 */ 3584 3585 lastChar = *(cp - 1); 3586 nameLen = (int)(cp - name); 3587 trailingSlash = (lastChar == '/'); 3588 leadingSlash = (*name == '/'); 3589 markedDir = (dblock.dbuf.typeflag == '5' || trailingSlash); 3590 3591 if (! lastSlash && ! markedDir) { 3592 /* 3593 * The named file does not have any subdrectory 3594 * structure; just bail out. 3595 */ 3596 3597 return (0); 3598 } 3599 3600 /* 3601 * Make sure that name doesn`t end with slash for the loop. 3602 * This ensures that the makeDir attempt after the loop is 3603 * meaningful. 3604 */ 3605 3606 if (trailingSlash) { 3607 name[nameLen-1] = '\0'; 3608 } 3609 3610 /* 3611 * Make the path one component at a time. 3612 */ 3613 3614 for (cp = strchr(leadingSlash ? name+1 : name, '/'); 3615 cp; 3616 cp = strchr(cp+1, '/')) { 3617 *cp = '\0'; 3618 success = makeDir(name); 3619 *cp = '/'; 3620 3621 if (!success) { 3622 name[nameLen-1] = lastChar; 3623 return (0); 3624 } 3625 } 3626 3627 /* 3628 * This makes the last component of the name, if it is a 3629 * directory. 3630 */ 3631 3632 if (markedDir) { 3633 if (! makeDir(name)) { 3634 name[nameLen-1] = lastChar; 3635 return (0); 3636 } 3637 } 3638 3639 name[nameLen-1] = (lastChar == '/') ? '\0' : lastChar; 3640 return (markedDir); 3641 } 3642 3643 /* 3644 * resugname - Restore the user name and group name. Search the NIS 3645 * before using the uid and gid. 3646 * (It is presumed that an archive entry cannot be 3647 * simultaneously a symlink and some other type.) 3648 */ 3649 3650 static void 3651 resugname(int dirfd, /* dir fd file resides in */ 3652 char *name, /* name of the file to be modified */ 3653 int symflag) /* true if file is a symbolic link */ 3654 { 3655 uid_t duid; 3656 gid_t dgid; 3657 struct stat *sp = &stbuf; 3658 char *u_g_name; 3659 3660 if (checkflag == 1) { /* Extended tar format and euid == 0 */ 3661 3662 /* 3663 * Try and extract the intended uid and gid from the name 3664 * service before believing the uid and gid in the header. 3665 * 3666 * In the case where we archived a setuid or setgid file 3667 * owned by someone with a large uid, then it will 3668 * have made it into the archive with a uid of nobody. If 3669 * the corresponding username doesn't appear to exist, then we 3670 * want to make sure it *doesn't* end up as setuid nobody! 3671 * 3672 * Our caller will print an error message about the fact 3673 * that the restore didn't work out quite right .. 3674 */ 3675 if (xhdr_flgs & _X_UNAME) 3676 u_g_name = Xtarhdr.x_uname; 3677 else 3678 u_g_name = dblock.dbuf.uname; 3679 if ((duid = getuidbyname(u_g_name)) == -1) { 3680 if (S_ISREG(sp->st_mode) && sp->st_uid == UID_NOBODY && 3681 (sp->st_mode & S_ISUID) == S_ISUID) 3682 (void) chmod(name, 3683 MODEMASK & sp->st_mode & ~S_ISUID); 3684 duid = sp->st_uid; 3685 } 3686 3687 /* (Ditto for gids) */ 3688 3689 if (xhdr_flgs & _X_GNAME) 3690 u_g_name = Xtarhdr.x_gname; 3691 else 3692 u_g_name = dblock.dbuf.gname; 3693 if ((dgid = getgidbyname(u_g_name)) == -1) { 3694 if (S_ISREG(sp->st_mode) && sp->st_gid == GID_NOBODY && 3695 (sp->st_mode & S_ISGID) == S_ISGID) 3696 (void) chmod(name, 3697 MODEMASK & sp->st_mode & ~S_ISGID); 3698 dgid = sp->st_gid; 3699 } 3700 } else if (checkflag == 2) { /* tar format and euid == 0 */ 3701 duid = sp->st_uid; 3702 dgid = sp->st_gid; 3703 } 3704 if ((checkflag == 1) || (checkflag == 2)) 3705 (void) fchownat(dirfd, name, duid, dgid, symflag); 3706 } 3707 3708 /*ARGSUSED*/ 3709 static void 3710 onintr(int sig) 3711 { 3712 (void) signal(SIGINT, SIG_IGN); 3713 term++; 3714 } 3715 3716 /*ARGSUSED*/ 3717 static void 3718 onquit(int sig) 3719 { 3720 (void) signal(SIGQUIT, SIG_IGN); 3721 term++; 3722 } 3723 3724 /*ARGSUSED*/ 3725 static void 3726 onhup(int sig) 3727 { 3728 (void) signal(SIGHUP, SIG_IGN); 3729 term++; 3730 } 3731 3732 static void 3733 tomodes(struct stat *sp) 3734 { 3735 uid_t uid; 3736 gid_t gid; 3737 3738 bzero(dblock.dummy, TBLOCK); 3739 3740 /* 3741 * If the uid or gid is too large, we can't put it into 3742 * the archive. We could fail to put anything in the 3743 * archive at all .. but most of the time the name service 3744 * will save the day when we do a lookup at restore time. 3745 * 3746 * Instead we choose a "safe" uid and gid, and fix up whether 3747 * or not the setuid and setgid bits are left set to extraction 3748 * time. 3749 */ 3750 if (Eflag) { 3751 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) { 3752 xhdr_flgs |= _X_UID; 3753 Xtarhdr.x_uid = uid; 3754 } 3755 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) { 3756 xhdr_flgs |= _X_GID; 3757 Xtarhdr.x_gid = gid; 3758 } 3759 if (sp->st_size > TAR_OFFSET_MAX) { 3760 xhdr_flgs |= _X_SIZE; 3761 Xtarhdr.x_filesz = sp->st_size; 3762 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3763 (off_t)0); 3764 } else 3765 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3766 sp->st_size); 3767 } else { 3768 (void) sprintf(dblock.dbuf.size, "%011" FMT_off_t_o, 3769 sp->st_size); 3770 } 3771 if ((ulong_t)(uid = sp->st_uid) > (ulong_t)OCTAL7CHAR) 3772 uid = UID_NOBODY; 3773 if ((ulong_t)(gid = sp->st_gid) > (ulong_t)OCTAL7CHAR) 3774 gid = GID_NOBODY; 3775 (void) sprintf(dblock.dbuf.gid, "%07lo", gid); 3776 (void) sprintf(dblock.dbuf.uid, "%07lo", uid); 3777 (void) sprintf(dblock.dbuf.mode, "%07lo", sp->st_mode & POSIXMODES); 3778 (void) sprintf(dblock.dbuf.mtime, "%011lo", sp->st_mtime); 3779 } 3780 3781 static int 3782 #ifdef EUC 3783 /* 3784 * Warning: the result of this function depends whether 'char' is a 3785 * signed or unsigned data type. This a source of potential 3786 * non-portability among heterogeneous systems. It is retained here 3787 * for backward compatibility. 3788 */ 3789 checksum_signed(union hblock *dblockp) 3790 #else 3791 checksum(union hblock *dblockp) 3792 #endif /* EUC */ 3793 { 3794 int i; 3795 char *cp; 3796 3797 for (cp = dblockp->dbuf.chksum; 3798 cp < &dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]; cp++) 3799 *cp = ' '; 3800 i = 0; 3801 for (cp = dblockp->dummy; cp < &(dblockp->dummy[TBLOCK]); cp++) 3802 i += *cp; 3803 return (i); 3804 } 3805 3806 #ifdef EUC 3807 /* 3808 * Generate unsigned checksum, regardless of what C compiler is 3809 * used. Survives in the face of arbitrary 8-bit clean filenames, 3810 * e.g., internationalized filenames. 3811 */ 3812 static int 3813 checksum(union hblock *dblockp) 3814 { 3815 unsigned i; 3816 unsigned char *cp; 3817 3818 for (cp = (unsigned char *) dblockp->dbuf.chksum; 3819 cp < (unsigned char *) 3820 &(dblockp->dbuf.chksum[sizeof (dblockp->dbuf.chksum)]); cp++) 3821 *cp = ' '; 3822 i = 0; 3823 for (cp = (unsigned char *) dblockp->dummy; 3824 cp < (unsigned char *) &(dblockp->dummy[TBLOCK]); cp++) 3825 i += *cp; 3826 3827 return (i); 3828 } 3829 #endif /* EUC */ 3830 3831 /* 3832 * If the w flag is set, output the action to be taken and the name of the 3833 * file. Perform the action if the user response is affirmative. 3834 */ 3835 3836 static int 3837 checkw(char c, char *name) 3838 { 3839 if (wflag) { 3840 (void) fprintf(vfile, "%c ", c); 3841 if (vflag) 3842 longt(&stbuf, ' '); /* do we have acl info here */ 3843 (void) fprintf(vfile, "%s: ", name); 3844 if (response() == 'y') { 3845 return (1); 3846 } 3847 return (0); 3848 } 3849 return (1); 3850 } 3851 3852 /* 3853 * When the F flag is set, exclude RCS and SCCS directories. If F is set 3854 * twice, also exclude .o files, and files names errs, core, and a.out. 3855 */ 3856 3857 static int 3858 checkf(char *name, int mode, int howmuch) 3859 { 3860 int l; 3861 3862 if ((mode & S_IFMT) == S_IFDIR) { 3863 if ((strcmp(name, "SCCS") == 0) || (strcmp(name, "RCS") == 0)) 3864 return (0); 3865 return (1); 3866 } 3867 if ((l = (int)strlen(name)) < 3) 3868 return (1); 3869 if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') 3870 return (0); 3871 if (howmuch > 1) { 3872 if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 || 3873 strcmp(name, "a.out") == 0) 3874 return (0); 3875 } 3876 3877 /* SHOULD CHECK IF IT IS EXECUTABLE */ 3878 return (1); 3879 } 3880 3881 static int 3882 response(void) 3883 { 3884 int c; 3885 3886 c = getchar(); 3887 if (c != '\n') 3888 while (getchar() != '\n') 3889 ; 3890 else c = 'n'; 3891 return ((c >= 'A' && c <= 'Z') ? c + ('a'-'A') : c); 3892 } 3893 3894 /* Has file been modified since being put into archive? If so, return > 0. */ 3895 3896 static int 3897 checkupdate(char *arg) 3898 { 3899 char name[PATH_MAX+1]; 3900 time_t mtime; 3901 long nsecs; 3902 off_t seekp; 3903 static off_t lookup(char *); 3904 3905 rewind(tfile); 3906 if ((seekp = lookup(arg)) < 0) 3907 return (1); 3908 (void) fseek(tfile, seekp, 0); 3909 (void) fscanf(tfile, "%s %ld.%ld", name, &mtime, &nsecs); 3910 3911 /* 3912 * Unless nanoseconds were stored in the file, only use seconds for 3913 * comparison of time. Nanoseconds are stored when -E is specified. 3914 */ 3915 if (Eflag == 0) 3916 return (stbuf.st_mtime > mtime); 3917 3918 if ((stbuf.st_mtime < mtime) || 3919 ((stbuf.st_mtime == mtime) && (stbuf.st_mtim.tv_nsec <= nsecs))) 3920 return (0); 3921 return (1); 3922 } 3923 3924 3925 /* 3926 * newvol get new floppy (or tape) volume 3927 * 3928 * newvol(); resets tapepos and first to TRUE, prompts for 3929 * for new volume, and waits. 3930 * if dumping, end-of-file is written onto the tape. 3931 */ 3932 3933 static void 3934 newvol(void) 3935 { 3936 int c; 3937 3938 if (dumping) { 3939 #ifdef DEBUG 3940 DEBUG("newvol called with 'dumping' set\n", 0, 0); 3941 #endif 3942 putempty((blkcnt_t)2); /* 2 EOT marks */ 3943 closevol(); 3944 flushtape(); 3945 sync(); 3946 tapepos = 0; 3947 } else 3948 first = TRUE; 3949 if (close(mt) != 0) 3950 vperror(2, gettext("close error")); 3951 mt = 0; 3952 (void) fprintf(stderr, gettext( 3953 "tar: \007please insert new volume, then press RETURN.")); 3954 (void) fseek(stdin, (off_t)0, 2); /* scan over read-ahead */ 3955 while ((c = getchar()) != '\n' && ! term) 3956 if (c == EOF) 3957 done(Errflg); 3958 if (term) 3959 done(Errflg); 3960 3961 errno = 0; 3962 3963 if (strcmp(usefile, "-") == 0) { 3964 mt = dup(1); 3965 } else { 3966 mt = open(usefile, dumping ? update : 0); 3967 } 3968 3969 if (mt < 0) { 3970 (void) fprintf(stderr, gettext( 3971 "tar: cannot reopen %s (%s)\n"), 3972 dumping ? gettext("output") : gettext("input"), usefile); 3973 3974 (void) fprintf(stderr, "update=%d, usefile=%s, mt=%d, [%s]\n", 3975 update, usefile, mt, strerror(errno)); 3976 3977 done(2); 3978 } 3979 } 3980 3981 /* 3982 * Write a trailer portion to close out the current output volume. 3983 */ 3984 3985 static void 3986 closevol(void) 3987 { 3988 if (mulvol) { 3989 /* 3990 * blocklim does not count the 2 EOT marks; 3991 * tapepos does count the 2 EOT marks; 3992 * therefore we need the +2 below. 3993 */ 3994 putempty(blocklim + (blkcnt_t)2 - tapepos); 3995 } 3996 } 3997 3998 static void 3999 done(int n) 4000 { 4001 (void) unlink(tname); 4002 if (mt > 0) { 4003 if ((close(mt) != 0) || (fclose(stdout) != 0)) { 4004 perror(gettext("tar: close error")); 4005 exit(2); 4006 } 4007 } 4008 exit(n); 4009 } 4010 4011 /* 4012 * Determine if s1 is a prefix portion of s2 (or the same as s2). 4013 */ 4014 4015 static int 4016 is_prefix(char *s1, char *s2) 4017 { 4018 while (*s1) 4019 if (*s1++ != *s2++) 4020 return (0); 4021 if (*s2) 4022 return (*s2 == '/'); 4023 return (1); 4024 } 4025 4026 /* 4027 * lookup and bsrch look through tfile entries to find a match for a name. 4028 * The name can be up to PATH_MAX bytes. bsrch compares what it sees between 4029 * a pair of newline chars, so the buffer it uses must be long enough for 4030 * two lines: name and modification time as well as period, newline and space. 4031 * 4032 * A kludge was added to bsrch to take care of matching on the first entry 4033 * in the file--there is no leading newline. So, if we are reading from the 4034 * start of the file, read into byte two and set the first byte to a newline. 4035 * Otherwise, the first entry cannot be matched. 4036 * 4037 */ 4038 4039 #define N (2 * (PATH_MAX + TIME_MAX_DIGITS + LONG_MAX_DIGITS + 3)) 4040 static off_t 4041 lookup(char *s) 4042 { 4043 int i; 4044 off_t a; 4045 4046 for (i = 0; s[i]; i++) 4047 if (s[i] == ' ') 4048 break; 4049 a = bsrch(s, i, low, high); 4050 return (a); 4051 } 4052 4053 static off_t 4054 bsrch(char *s, int n, off_t l, off_t h) 4055 { 4056 int i, j; 4057 char b[N]; 4058 off_t m, m1; 4059 4060 4061 loop: 4062 if (l >= h) 4063 return ((off_t)-1); 4064 m = l + (h-l)/2 - N/2; 4065 if (m < l) 4066 m = l; 4067 (void) fseek(tfile, m, 0); 4068 if (m == 0) { 4069 (void) fread(b+1, 1, N-1, tfile); 4070 b[0] = '\n'; 4071 m--; 4072 } else 4073 (void) fread(b, 1, N, tfile); 4074 for (i = 0; i < N; i++) { 4075 if (b[i] == '\n') 4076 break; 4077 m++; 4078 } 4079 if (m >= h) 4080 return ((off_t)-1); 4081 m1 = m; 4082 j = i; 4083 for (i++; i < N; i++) { 4084 m1++; 4085 if (b[i] == '\n') 4086 break; 4087 } 4088 i = cmp(b+j, s, n); 4089 if (i < 0) { 4090 h = m; 4091 goto loop; 4092 } 4093 if (i > 0) { 4094 l = m1; 4095 goto loop; 4096 } 4097 if (m < 0) 4098 m = 0; 4099 return (m); 4100 } 4101 4102 static int 4103 cmp(char *b, char *s, int n) 4104 { 4105 int i; 4106 4107 assert(b[0] == '\n'); 4108 4109 for (i = 0; i < n; i++) { 4110 if (b[i+1] > s[i]) 4111 return (-1); 4112 if (b[i+1] < s[i]) 4113 return (1); 4114 } 4115 return (b[i+1] == ' '? 0 : -1); 4116 } 4117 4118 4119 /* 4120 * seekdisk seek to next file on archive 4121 * 4122 * called by passtape() only 4123 * 4124 * WARNING: expects "nblock" to be set, that is, readtape() to have 4125 * already been called. Since passtape() is only called 4126 * after a file header block has been read (why else would 4127 * we skip to next file?), this is currently safe. 4128 * 4129 * changed to guarantee SYS_BLOCK boundary 4130 */ 4131 4132 static void 4133 seekdisk(blkcnt_t blocks) 4134 { 4135 off_t seekval; 4136 #if SYS_BLOCK > TBLOCK 4137 /* handle non-multiple of SYS_BLOCK */ 4138 blkcnt_t nxb; /* # extra blocks */ 4139 #endif 4140 4141 tapepos += blocks; 4142 #ifdef DEBUG 4143 DEBUG("seekdisk(%" FMT_blkcnt_t ") called\n", blocks, 0); 4144 #endif 4145 if (recno + blocks <= nblock) { 4146 recno += blocks; 4147 return; 4148 } 4149 if (recno > nblock) 4150 recno = nblock; 4151 seekval = (off_t)blocks - (nblock - recno); 4152 recno = nblock; /* so readtape() reads next time through */ 4153 #if SYS_BLOCK > TBLOCK 4154 nxb = (blkcnt_t)(seekval % (off_t)(SYS_BLOCK / TBLOCK)); 4155 #ifdef DEBUG 4156 DEBUG("xtrablks=%" FMT_blkcnt_t " seekval=%" FMT_blkcnt_t " blks\n", 4157 nxb, seekval); 4158 #endif 4159 if (nxb && nxb > seekval) /* don't seek--we'll read */ 4160 goto noseek; 4161 seekval -= nxb; /* don't seek quite so far */ 4162 #endif 4163 if (lseek(mt, (off_t)(TBLOCK * seekval), 1) == (off_t)-1) { 4164 (void) fprintf(stderr, gettext( 4165 "tar: device seek error\n")); 4166 done(3); 4167 } 4168 #if SYS_BLOCK > TBLOCK 4169 /* read those extra blocks */ 4170 noseek: 4171 if (nxb) { 4172 #ifdef DEBUG 4173 DEBUG("reading extra blocks\n", 0, 0); 4174 #endif 4175 if (read(mt, tbuf, TBLOCK*nblock) < 0) { 4176 (void) fprintf(stderr, gettext( 4177 "tar: read error while skipping file\n")); 4178 done(8); 4179 } 4180 recno = nxb; /* so we don't read in next readtape() */ 4181 } 4182 #endif 4183 } 4184 4185 static void 4186 readtape(char *buffer) 4187 { 4188 int i, j; 4189 4190 ++tapepos; 4191 if (recno >= nblock || first) { 4192 if (first) { 4193 /* 4194 * set the number of blocks to read initially, based on 4195 * the defined defaults for the device, or on the 4196 * explicit block factor given. 4197 */ 4198 if (bflag || defaults_used) 4199 j = nblock; 4200 else 4201 j = NBLOCK; 4202 } else 4203 j = nblock; 4204 4205 if ((i = read(mt, tbuf, TBLOCK*j)) < 0) { 4206 (void) fprintf(stderr, gettext( 4207 "tar: tape read error\n")); 4208 done(3); 4209 /* 4210 * i == 0 means EOF reached and !rflag means that when 4211 * tar command uses 'r' as a function letter, we are trying 4212 * to update or replace an empty tar file which will fail. 4213 * So this fix is not for 'r' function letter. 4214 */ 4215 } else if (i == 0 && !rflag) { 4216 if (first) { 4217 (void) fprintf(stderr, gettext( 4218 "tar: blocksize = %d\n"), i); 4219 done(Errflg); 4220 } 4221 else 4222 mterr("read", 0, 2); 4223 } else if ((!first || Bflag) && i != TBLOCK*j) { 4224 /* 4225 * Short read - try to get the remaining bytes. 4226 */ 4227 4228 int remaining = (TBLOCK * j) - i; 4229 char *b = (char *)tbuf + i; 4230 int r; 4231 4232 do { 4233 if ((r = read(mt, b, remaining)) < 0) { 4234 (void) fprintf(stderr, 4235 gettext("tar: tape read error\n")); 4236 done(3); 4237 } 4238 b += r; 4239 remaining -= r; 4240 i += r; 4241 } while (remaining > 0 && r != 0); 4242 } 4243 if (first) { 4244 if ((i % TBLOCK) != 0) { 4245 (void) fprintf(stderr, gettext( 4246 "tar: tape blocksize error\n")); 4247 done(3); 4248 } 4249 i /= TBLOCK; 4250 if (vflag && i != nblock && i != 1) { 4251 if (!NotTape) 4252 (void) fprintf(stderr, gettext( 4253 "tar: blocksize = %d\n"), i); 4254 } 4255 4256 /* 4257 * If we are reading a tape, then a short read is 4258 * understood to signify that the amount read is 4259 * the tape's actual blocking factor. We adapt 4260 * nblock accordingly. There is no reason to do 4261 * this when the device is not blocked. 4262 */ 4263 4264 if (!NotTape) 4265 nblock = i; 4266 } 4267 recno = 0; 4268 } 4269 4270 first = FALSE; 4271 copy(buffer, &tbuf[recno++]); 4272 } 4273 4274 4275 /* 4276 * replacement for writetape. 4277 */ 4278 4279 static int 4280 writetbuf(char *buffer, int n) 4281 { 4282 int i; 4283 4284 tapepos += n; /* output block count */ 4285 4286 if (recno >= nblock) { 4287 i = write(mt, (char *)tbuf, TBLOCK*nblock); 4288 if (i != TBLOCK*nblock) 4289 mterr("write", i, 2); 4290 recno = 0; 4291 } 4292 4293 /* 4294 * Special case: We have an empty tape buffer, and the 4295 * users data size is >= the tape block size: Avoid 4296 * the bcopy and dma direct to tape. BIG WIN. Add the 4297 * residual to the tape buffer. 4298 */ 4299 while (recno == 0 && n >= nblock) { 4300 i = (int)write(mt, buffer, TBLOCK*nblock); 4301 if (i != TBLOCK*nblock) 4302 mterr("write", i, 2); 4303 n -= nblock; 4304 buffer += (nblock * TBLOCK); 4305 } 4306 4307 while (n-- > 0) { 4308 (void) memcpy((char *)&tbuf[recno++], buffer, TBLOCK); 4309 buffer += TBLOCK; 4310 if (recno >= nblock) { 4311 i = (int)write(mt, (char *)tbuf, TBLOCK*nblock); 4312 if (i != TBLOCK*nblock) 4313 mterr("write", i, 2); 4314 recno = 0; 4315 } 4316 } 4317 4318 /* Tell the user how much to write to get in sync */ 4319 return (nblock - recno); 4320 } 4321 4322 /* 4323 * backtape - reposition tape after reading soft "EOF" record 4324 * 4325 * Backtape tries to reposition the tape back over the EOF 4326 * record. This is for the 'u' and 'r' function letters so that the 4327 * tape can be extended. This code is not well designed, but 4328 * I'm confident that the only callers who care about the 4329 * backspace-over-EOF feature are those involved in 'u' and 'r'. 4330 * 4331 * The proper way to backup the tape is through the use of mtio. 4332 * Earlier spins used lseek combined with reads in a confusing 4333 * maneuver that only worked on 4.x, but shouldn't have, even 4334 * there. Lseeks are explicitly not supported for tape devices. 4335 */ 4336 4337 static void 4338 backtape(void) 4339 { 4340 struct mtop mtcmd; 4341 #ifdef DEBUG 4342 DEBUG("backtape() called, recno=%" FMT_blkcnt_t " nblock=%d\n", recno, 4343 nblock); 4344 #endif 4345 /* 4346 * Backup to the position in the archive where the record 4347 * currently sitting in the tbuf buffer is situated. 4348 */ 4349 4350 if (NotTape) { 4351 /* 4352 * For non-tape devices, this means lseeking to the 4353 * correct position. The absolute location tapepos-recno 4354 * should be the beginning of the current record. 4355 */ 4356 4357 if (lseek(mt, (off_t)(TBLOCK*(tapepos-recno)), SEEK_SET) == 4358 (off_t)-1) { 4359 (void) fprintf(stderr, 4360 gettext("tar: lseek to end of archive failed\n")); 4361 done(4); 4362 } 4363 } else { 4364 /* 4365 * For tape devices, we backup over the most recently 4366 * read record. 4367 */ 4368 4369 mtcmd.mt_op = MTBSR; 4370 mtcmd.mt_count = 1; 4371 4372 if (ioctl(mt, MTIOCTOP, &mtcmd) < 0) { 4373 (void) fprintf(stderr, 4374 gettext("tar: backspace over record failed\n")); 4375 done(4); 4376 } 4377 } 4378 4379 /* 4380 * Decrement the tape and tbuf buffer indices to prepare for the 4381 * coming write to overwrite the soft EOF record. 4382 */ 4383 4384 recno--; 4385 tapepos--; 4386 } 4387 4388 4389 /* 4390 * flushtape write buffered block(s) onto tape 4391 * 4392 * recno points to next free block in tbuf. If nonzero, a write is done. 4393 * Care is taken to write in multiples of SYS_BLOCK when device is 4394 * non-magtape in case raw i/o is used. 4395 * 4396 * NOTE: this is called by writetape() to do the actual writing 4397 */ 4398 4399 static void 4400 flushtape(void) 4401 { 4402 #ifdef DEBUG 4403 DEBUG("flushtape() called, recno=%" FMT_blkcnt_t "\n", recno, 0); 4404 #endif 4405 if (recno > 0) { /* anything buffered? */ 4406 if (NotTape) { 4407 #if SYS_BLOCK > TBLOCK 4408 int i; 4409 4410 /* 4411 * an odd-block write can only happen when 4412 * we are at the end of a volume that is not a tape. 4413 * Here we round recno up to an even SYS_BLOCK 4414 * boundary. 4415 */ 4416 if ((i = recno % (SYS_BLOCK / TBLOCK)) != 0) { 4417 #ifdef DEBUG 4418 DEBUG("flushtape() %d rounding blocks\n", i, 0); 4419 #endif 4420 recno += i; /* round up to even SYS_BLOCK */ 4421 } 4422 #endif 4423 if (recno > nblock) 4424 recno = nblock; 4425 } 4426 #ifdef DEBUG 4427 DEBUG("writing out %" FMT_blkcnt_t " blocks of %" FMT_blkcnt_t 4428 " bytes\n", (blkcnt_t)(NotTape ? recno : nblock), 4429 (blkcnt_t)(NotTape ? recno : nblock) * TBLOCK); 4430 #endif 4431 if (write(mt, tbuf, 4432 (size_t)(NotTape ? recno : nblock) * TBLOCK) < 0) { 4433 (void) fprintf(stderr, gettext( 4434 "tar: tape write error\n")); 4435 done(2); 4436 } 4437 recno = 0; 4438 } 4439 } 4440 4441 static void 4442 copy(void *dst, void *src) 4443 { 4444 (void) memcpy(dst, src, TBLOCK); 4445 } 4446 4447 #ifdef _iBCS2 4448 /* 4449 * initarg -- initialize things for nextarg. 4450 * 4451 * argv filename list, a la argv. 4452 * filefile name of file containing filenames. Unless doing 4453 * a create, seeks must be allowable (e.g. no named pipes). 4454 * 4455 * - if filefile is non-NULL, it will be used first, and argv will 4456 * be used when the data in filefile are exhausted. 4457 * - otherwise argv will be used. 4458 */ 4459 static char **Cmdargv = NULL; 4460 static FILE *FILEFile = NULL; 4461 static long seekFile = -1; 4462 static char *ptrtoFile, *begofFile, *endofFile; 4463 4464 static void 4465 initarg(char *argv[], char *filefile) 4466 { 4467 struct stat statbuf; 4468 char *p; 4469 int nbytes; 4470 4471 Cmdargv = argv; 4472 if (filefile == NULL) 4473 return; /* no -F file */ 4474 if (FILEFile != NULL) { 4475 /* 4476 * need to REinitialize 4477 */ 4478 if (seekFile != -1) 4479 (void) fseek(FILEFile, seekFile, 0); 4480 ptrtoFile = begofFile; 4481 return; 4482 } 4483 /* 4484 * first time initialization 4485 */ 4486 if ((FILEFile = fopen(filefile, "r")) == NULL) 4487 fatal(gettext("cannot open (%s)"), filefile); 4488 (void) fstat(fileno(FILEFile), &statbuf); 4489 if ((statbuf.st_mode & S_IFMT) != S_IFREG) { 4490 (void) fprintf(stderr, gettext( 4491 "tar: %s is not a regular file\n"), filefile); 4492 (void) fclose(FILEFile); 4493 done(1); 4494 } 4495 ptrtoFile = begofFile = endofFile; 4496 seekFile = 0; 4497 if (!xflag) 4498 return; /* the file will be read only once anyway */ 4499 nbytes = statbuf.st_size; 4500 while ((begofFile = calloc(nbytes, sizeof (char))) == NULL) 4501 nbytes -= 20; 4502 if (nbytes < 50) { 4503 free(begofFile); 4504 begofFile = endofFile; 4505 return; /* no room so just do plain reads */ 4506 } 4507 if (fread(begofFile, 1, nbytes, FILEFile) != nbytes) 4508 fatal(gettext("could not read %s"), filefile); 4509 ptrtoFile = begofFile; 4510 endofFile = begofFile + nbytes; 4511 for (p = begofFile; p < endofFile; ++p) 4512 if (*p == '\n') 4513 *p = '\0'; 4514 if (nbytes != statbuf.st_size) 4515 seekFile = nbytes + 1; 4516 else 4517 (void) fclose(FILEFile); 4518 } 4519 4520 /* 4521 * nextarg -- get next argument of arglist. 4522 * 4523 * The argument is taken from wherever is appropriate. 4524 * 4525 * If the 'F file' function modifier has been specified, the argument 4526 * will be taken from the file, unless EOF has been reached. 4527 * Otherwise the argument will be taken from argv. 4528 * 4529 * WARNING: 4530 * Return value may point to static data, whose contents are over- 4531 * written on each call. 4532 */ 4533 static char * 4534 nextarg(void) 4535 { 4536 static char nameFile[PATH_MAX + 1]; 4537 int n; 4538 char *p; 4539 4540 if (FILEFile) { 4541 if (ptrtoFile < endofFile) { 4542 p = ptrtoFile; 4543 while (*ptrtoFile) 4544 ++ptrtoFile; 4545 ++ptrtoFile; 4546 return (p); 4547 } 4548 if (fgets(nameFile, PATH_MAX + 1, FILEFile) != NULL) { 4549 n = strlen(nameFile); 4550 if (n > 0 && nameFile[n-1] == '\n') 4551 nameFile[n-1] = '\0'; 4552 return (nameFile); 4553 } 4554 } 4555 return (*Cmdargv++); 4556 } 4557 #endif /* _iBCS2 */ 4558 4559 /* 4560 * kcheck() 4561 * - checks the validity of size values for non-tape devices 4562 * - if size is zero, mulvol tar is disabled and size is 4563 * assumed to be infinite. 4564 * - returns volume size in TBLOCKS 4565 */ 4566 4567 static blkcnt_t 4568 kcheck(char *kstr) 4569 { 4570 blkcnt_t kval; 4571 4572 kval = strtoll(kstr, NULL, 0); 4573 if (kval == (blkcnt_t)0) { /* no multi-volume; size is infinity. */ 4574 mulvol = 0; /* definitely not mulvol, but we must */ 4575 return (0); /* took out setting of NotTape */ 4576 } 4577 if (kval < (blkcnt_t)MINSIZE) { 4578 (void) fprintf(stderr, gettext( 4579 "tar: sizes below %luK not supported (%" FMT_blkcnt_t 4580 ").\n"), (ulong_t)MINSIZE, kval); 4581 if (!kflag) 4582 (void) fprintf(stderr, gettext( 4583 "bad size entry for %s in %s.\n"), 4584 archive, DEF_FILE); 4585 done(1); 4586 } 4587 mulvol++; 4588 NotTape++; /* implies non-tape */ 4589 return (kval * 1024 / TBLOCK); /* convert to TBLOCKS */ 4590 } 4591 4592 4593 /* 4594 * bcheck() 4595 * - checks the validity of blocking factors 4596 * - returns blocking factor 4597 */ 4598 4599 static int 4600 bcheck(char *bstr) 4601 { 4602 blkcnt_t bval; 4603 4604 bval = strtoll(bstr, NULL, 0); 4605 if ((bval <= 0) || (bval > INT_MAX / TBLOCK)) { 4606 (void) fprintf(stderr, gettext( 4607 "tar: invalid blocksize \"%s\".\n"), bstr); 4608 if (!bflag) 4609 (void) fprintf(stderr, gettext( 4610 "bad blocksize entry for '%s' in %s.\n"), 4611 archive, DEF_FILE); 4612 done(1); 4613 } 4614 4615 return ((int)bval); 4616 } 4617 4618 4619 /* 4620 * defset() 4621 * - reads DEF_FILE for the set of default values specified. 4622 * - initializes 'usefile', 'nblock', and 'blocklim', and 'NotTape'. 4623 * - 'usefile' points to static data, so will be overwritten 4624 * if this routine is called a second time. 4625 * - the pattern specified by 'arch' must be followed by four 4626 * blank-separated fields (1) device (2) blocking, 4627 * (3) size(K), and (4) tape 4628 * for example: archive0=/dev/fd 1 400 n 4629 */ 4630 4631 static int 4632 defset(char *arch) 4633 { 4634 char *bp; 4635 4636 if (defopen(DEF_FILE) != 0) 4637 return (FALSE); 4638 if (defcntl(DC_SETFLAGS, (DC_STD & ~(DC_CASE))) == -1) { 4639 (void) fprintf(stderr, gettext( 4640 "tar: error setting parameters for %s.\n"), DEF_FILE); 4641 return (FALSE); /* & following ones too */ 4642 } 4643 if ((bp = defread(arch)) == NULL) { 4644 (void) fprintf(stderr, gettext( 4645 "tar: missing or invalid '%s' entry in %s.\n"), 4646 arch, DEF_FILE); 4647 return (FALSE); 4648 } 4649 if ((usefile = strtok(bp, " \t")) == NULL) { 4650 (void) fprintf(stderr, gettext( 4651 "tar: '%s' entry in %s is empty!\n"), arch, DEF_FILE); 4652 return (FALSE); 4653 } 4654 if ((bp = strtok(NULL, " \t")) == NULL) { 4655 (void) fprintf(stderr, gettext( 4656 "tar: block component missing in '%s' entry in %s.\n"), 4657 arch, DEF_FILE); 4658 return (FALSE); 4659 } 4660 nblock = bcheck(bp); 4661 if ((bp = strtok(NULL, " \t")) == NULL) { 4662 (void) fprintf(stderr, gettext( 4663 "tar: size component missing in '%s' entry in %s.\n"), 4664 arch, DEF_FILE); 4665 return (FALSE); 4666 } 4667 blocklim = kcheck(bp); 4668 if ((bp = strtok(NULL, " \t")) != NULL) 4669 NotTape = (*bp == 'n' || *bp == 'N'); 4670 else 4671 NotTape = (blocklim != 0); 4672 (void) defopen(NULL); 4673 #ifdef DEBUG 4674 DEBUG("defset: archive='%s'; usefile='%s'\n", arch, usefile); 4675 DEBUG("defset: nblock='%d'; blocklim='%" FMT_blkcnt_t "'\n", 4676 nblock, blocklim); 4677 DEBUG("defset: not tape = %d\n", NotTape, 0); 4678 #endif 4679 return (TRUE); 4680 } 4681 4682 4683 /* 4684 * Following code handles excluded and included files. 4685 * A hash table of file names to be {in,ex}cluded is built. 4686 * For excluded files, before writing or extracting a file 4687 * check to see if it is in the exclude_tbl. 4688 * For included files, the wantit() procedure will check to 4689 * see if the named file is in the include_tbl. 4690 */ 4691 4692 static void 4693 build_table(struct file_list *table[], char *file) 4694 { 4695 FILE *fp; 4696 char buf[PATH_MAX + 1]; 4697 4698 if ((fp = fopen(file, "r")) == (FILE *)NULL) 4699 vperror(1, gettext("could not open %s"), file); 4700 while (fgets(buf, sizeof (buf), fp) != NULL) { 4701 if (buf[strlen(buf) - 1] == '\n') 4702 buf[strlen(buf) - 1] = '\0'; 4703 /* Only add to table if line has something in it */ 4704 if (strspn(buf, " \t") != strlen(buf)) 4705 add_file_to_table(table, buf); 4706 } 4707 (void) fclose(fp); 4708 } 4709 4710 4711 /* 4712 * Add a file name to the the specified table, if the file name has any 4713 * trailing '/'s then delete them before inserting into the table 4714 */ 4715 4716 static void 4717 add_file_to_table(struct file_list *table[], char *str) 4718 { 4719 char name[PATH_MAX + 1]; 4720 unsigned int h; 4721 struct file_list *exp; 4722 4723 (void) strcpy(name, str); 4724 while (name[strlen(name) - 1] == '/') { 4725 name[strlen(name) - 1] = NULL; 4726 } 4727 4728 h = hash(name); 4729 if ((exp = (struct file_list *)calloc(sizeof (struct file_list), 4730 sizeof (char))) == NULL) { 4731 (void) fprintf(stderr, gettext( 4732 "tar: out of memory, exclude/include table(entry)\n")); 4733 exit(1); 4734 } 4735 4736 if ((exp->name = strdup(name)) == NULL) { 4737 (void) fprintf(stderr, gettext( 4738 "tar: out of memory, exclude/include table(file name)\n")); 4739 exit(1); 4740 } 4741 4742 exp->next = table[h]; 4743 table[h] = exp; 4744 } 4745 4746 4747 /* 4748 * See if a file name or any of the file's parent directories is in the 4749 * specified table, if the file name has any trailing '/'s then delete 4750 * them before searching the table 4751 */ 4752 4753 static int 4754 is_in_table(struct file_list *table[], char *str) 4755 { 4756 char name[PATH_MAX + 1]; 4757 unsigned int h; 4758 struct file_list *exp; 4759 char *ptr; 4760 4761 (void) strcpy(name, str); 4762 while (name[strlen(name) - 1] == '/') { 4763 name[strlen(name) - 1] = NULL; 4764 } 4765 4766 /* 4767 * check for the file name in the passed list 4768 */ 4769 h = hash(name); 4770 exp = table[h]; 4771 while (exp != NULL) { 4772 if (strcmp(name, exp->name) == 0) { 4773 return (1); 4774 } 4775 exp = exp->next; 4776 } 4777 4778 /* 4779 * check for any parent directories in the file list 4780 */ 4781 while ((ptr = strrchr(name, '/'))) { 4782 *ptr = NULL; 4783 h = hash(name); 4784 exp = table[h]; 4785 while (exp != NULL) { 4786 if (strcmp(name, exp->name) == 0) { 4787 return (1); 4788 } 4789 exp = exp->next; 4790 } 4791 } 4792 4793 return (0); 4794 } 4795 4796 4797 /* 4798 * Compute a hash from a string. 4799 */ 4800 4801 static unsigned int 4802 hash(char *str) 4803 { 4804 char *cp; 4805 unsigned int h; 4806 4807 h = 0; 4808 for (cp = str; *cp; cp++) { 4809 h += *cp; 4810 } 4811 return (h % TABLE_SIZE); 4812 } 4813 4814 static void * 4815 getmem(size_t size) 4816 { 4817 void *p = calloc((unsigned)size, sizeof (char)); 4818 4819 if (p == NULL && freemem) { 4820 (void) fprintf(stderr, gettext( 4821 "tar: out of memory, link and directory modtime " 4822 "info lost\n")); 4823 freemem = 0; 4824 if (errflag) 4825 done(1); 4826 else 4827 Errflg = 1; 4828 } 4829 return (p); 4830 } 4831 4832 /* 4833 * vperror() --variable argument perror. 4834 * Takes 3 args: exit_status, formats, args. If exit_status is 0, then 4835 * the errflag (exit on error) is checked -- if it is non-zero, tar exits 4836 * with the value of whatever "errno" is set to. If exit_status is not 4837 * zero, then tar exits with that error status. If errflag and exit_status 4838 * are both zero, the routine returns to where it was called and sets Errflg 4839 * to errno. 4840 */ 4841 4842 static void 4843 vperror(int exit_status, char *fmt, ...) 4844 { 4845 va_list ap; 4846 4847 va_start(ap, fmt); 4848 (void) fputs("tar: ", stderr); 4849 (void) vfprintf(stderr, fmt, ap); 4850 (void) fprintf(stderr, ": %s\n", strerror(errno)); 4851 va_end(ap); 4852 if (exit_status) 4853 done(exit_status); 4854 else 4855 if (errflag) 4856 done(errno); 4857 else 4858 Errflg = errno; 4859 } 4860 4861 4862 static void 4863 fatal(char *format, ...) 4864 { 4865 va_list ap; 4866 4867 va_start(ap, format); 4868 (void) fprintf(stderr, "tar: "); 4869 (void) vfprintf(stderr, format, ap); 4870 (void) fprintf(stderr, "\n"); 4871 va_end(ap); 4872 done(1); 4873 } 4874 4875 4876 /* 4877 * Check to make sure that argument is a char * ptr. 4878 * Actually, we just check to see that it is non-null. 4879 * If it is null, print out the message and call usage(), bailing out. 4880 */ 4881 4882 static void 4883 assert_string(char *s, char *msg) 4884 { 4885 if (s == NULL) { 4886 (void) fprintf(stderr, msg); 4887 usage(); 4888 } 4889 } 4890 4891 4892 static void 4893 mterr(char *operation, int i, int exitcode) 4894 { 4895 (void) fprintf(stderr, gettext( 4896 "tar: %s error: "), operation); 4897 if (i < 0) 4898 perror(""); 4899 else 4900 (void) fprintf(stderr, gettext("unexpected EOF\n")); 4901 done(exitcode); 4902 } 4903 4904 static int 4905 wantit(char *argv[], char **namep, char **dirp, char **component) 4906 { 4907 char **cp; 4908 int gotit; /* true if we've found a match */ 4909 4910 top: 4911 xhdr_flgs = 0; 4912 getdir(); 4913 if (Xhdrflag > 0) { 4914 if (get_xdata() != 0) { /* Xhdr items and regular header */ 4915 passtape(); 4916 return (0); /* Error--don't want to extract */ 4917 } 4918 } 4919 4920 #if defined(O_XATTR) 4921 if (dblock.dbuf.typeflag == _XATTR_HDRTYPE && xattrbadhead == 0) { 4922 if (atflag || tflag) { 4923 (void) read_xattr_hdr(); 4924 } else { 4925 passtape(); 4926 } 4927 goto top; 4928 } 4929 #endif 4930 4931 /* sets *namep to point at the proper name */ 4932 check_prefix(namep, dirp, component); 4933 4934 if (endtape()) { 4935 if (Bflag) { 4936 /* 4937 * Logically at EOT - consume any extra blocks 4938 * so that write to our stdin won't fail and 4939 * emit an error message; otherwise something 4940 * like "dd if=foo.tar | (cd bar; tar xvf -)" 4941 * will produce a bogus error message from "dd". 4942 */ 4943 4944 while (read(mt, tbuf, TBLOCK*nblock) > 0) { 4945 /* empty body */ 4946 } 4947 } 4948 return (-1); 4949 } 4950 4951 gotit = 0; 4952 4953 if ((Iflag && is_in_table(include_tbl, *namep)) || 4954 (! Iflag && *argv == NULL)) { 4955 gotit = 1; 4956 } else { 4957 for (cp = argv; *cp; cp++) { 4958 if (is_prefix(*cp, *namep)) { 4959 gotit = 1; 4960 break; 4961 } 4962 } 4963 } 4964 4965 if (! gotit) { 4966 passtape(); 4967 return (0); 4968 } 4969 4970 if (Xflag && is_in_table(exclude_tbl, *namep)) { 4971 if (vflag) { 4972 (void) fprintf(stderr, gettext("%s excluded\n"), 4973 *namep); 4974 } 4975 passtape(); 4976 return (0); 4977 } 4978 4979 return (1); 4980 } 4981 4982 4983 /* 4984 * Return through *namep a pointer to the proper fullname (i.e "<name> | 4985 * <prefix>/<name>"), as represented in the header entry dblock.dbuf. 4986 */ 4987 4988 static void 4989 check_prefix(char **namep, char **dirp, char **compp) 4990 { 4991 static char fullname[PATH_MAX + 1]; 4992 static char dir[PATH_MAX + 1]; 4993 static char component[PATH_MAX + 1]; 4994 static char savename[PATH_MAX + 1]; 4995 char *s; 4996 4997 (void) memset(dir, 0, sizeof (dir)); 4998 (void) memset(component, 0, sizeof (component)); 4999 5000 if (xhdr_flgs & _X_PATH) { 5001 (void) strcpy(fullname, Xtarhdr.x_path); 5002 } else { 5003 if (dblock.dbuf.prefix[0] != '\0') 5004 (void) sprintf(fullname, "%.*s/%.*s", PRESIZ, 5005 dblock.dbuf.prefix, NAMSIZ, dblock.dbuf.name); 5006 else 5007 (void) sprintf(fullname, "%.*s", NAMSIZ, 5008 dblock.dbuf.name); 5009 } 5010 5011 /* 5012 * Set dir and component names 5013 */ 5014 5015 get_parent(fullname, dir); 5016 5017 #if defined(O_XATTR) 5018 if (xattrp == (struct xattr_buf *)NULL) { 5019 #endif 5020 /* 5021 * Save of real name since were going to chop off the 5022 * trailing slashes. 5023 */ 5024 (void) strcpy(savename, fullname); 5025 /* 5026 * first strip of trailing slashes. 5027 */ 5028 chop_endslashes(savename); 5029 s = get_component(savename); 5030 (void) strcpy(component, s); 5031 5032 #if defined(O_XATTR) 5033 } else { 5034 (void) strcpy(fullname, xattrp->h_names); 5035 (void) strcpy(dir, fullname); 5036 (void) strcpy(component, xattrp->h_names + 5037 strlen(xattrp->h_names) + 1); 5038 } 5039 #endif 5040 *namep = fullname; 5041 *dirp = dir; 5042 *compp = component; 5043 } 5044 5045 5046 static wchar_t 5047 yesnoresponse(void) 5048 { 5049 wchar_t c; 5050 5051 c = getwchar(); 5052 if (c != '\n') 5053 while (getwchar() != '\n') 5054 ; 5055 else c = 0; 5056 return (c); 5057 } 5058 5059 5060 /* 5061 * Return true if the object indicated by the file descriptor and type 5062 * is a tape device, false otherwise 5063 */ 5064 5065 static int 5066 istape(int fd, int type) 5067 { 5068 int result = 0; 5069 5070 if (S_ISCHR(type)) { 5071 struct mtget mtg; 5072 5073 if (ioctl(fd, MTIOCGET, &mtg) != -1) { 5074 result = 1; 5075 } 5076 } 5077 5078 return (result); 5079 } 5080 5081 #include <utmpx.h> 5082 5083 struct utmpx utmpx; 5084 5085 #define NMAX (sizeof (utmpx.ut_name)) 5086 5087 typedef struct cachenode { /* this struct must be zeroed before using */ 5088 struct cachenode *next; /* next in hash chain */ 5089 int val; /* the uid or gid of this entry */ 5090 int namehash; /* name's hash signature */ 5091 char name[NMAX+1]; /* the string that val maps to */ 5092 } cachenode_t; 5093 5094 #define HASHSIZE 256 5095 5096 static cachenode_t *names[HASHSIZE]; 5097 static cachenode_t *groups[HASHSIZE]; 5098 static cachenode_t *uids[HASHSIZE]; 5099 static cachenode_t *gids[HASHSIZE]; 5100 5101 static int 5102 hash_byname(char *name) 5103 { 5104 int i, c, h = 0; 5105 5106 for (i = 0; i < NMAX; i++) { 5107 c = name[i]; 5108 if (c == '\0') 5109 break; 5110 h = (h << 4) + h + c; 5111 } 5112 return (h); 5113 } 5114 5115 static cachenode_t * 5116 hash_lookup_byval(cachenode_t *table[], int val) 5117 { 5118 int h = val; 5119 cachenode_t *c; 5120 5121 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5122 if (c->val == val) 5123 return (c); 5124 } 5125 return (NULL); 5126 } 5127 5128 static cachenode_t * 5129 hash_lookup_byname(cachenode_t *table[], char *name) 5130 { 5131 int h = hash_byname(name); 5132 cachenode_t *c; 5133 5134 for (c = table[h & (HASHSIZE - 1)]; c != NULL; c = c->next) { 5135 if (c->namehash == h && strcmp(c->name, name) == 0) 5136 return (c); 5137 } 5138 return (NULL); 5139 } 5140 5141 static cachenode_t * 5142 hash_insert(cachenode_t *table[], char *name, int value) 5143 { 5144 cachenode_t *c; 5145 int signature; 5146 5147 c = calloc(1, sizeof (cachenode_t)); 5148 if (c == NULL) { 5149 perror("malloc"); 5150 exit(1); 5151 } 5152 if (name != NULL) { 5153 (void) strncpy(c->name, name, NMAX); 5154 c->namehash = hash_byname(name); 5155 } 5156 c->val = value; 5157 if (table == uids || table == gids) 5158 signature = c->val; 5159 else 5160 signature = c->namehash; 5161 c->next = table[signature & (HASHSIZE - 1)]; 5162 table[signature & (HASHSIZE - 1)] = c; 5163 return (c); 5164 } 5165 5166 static char * 5167 getname(uid_t uid) 5168 { 5169 cachenode_t *c; 5170 5171 if ((c = hash_lookup_byval(uids, uid)) == NULL) { 5172 struct passwd *pwent = getpwuid(uid); 5173 c = hash_insert(uids, pwent ? pwent->pw_name : NULL, uid); 5174 } 5175 return (c->name); 5176 } 5177 5178 static char * 5179 getgroup(gid_t gid) 5180 { 5181 cachenode_t *c; 5182 5183 if ((c = hash_lookup_byval(gids, gid)) == NULL) { 5184 struct group *grent = getgrgid(gid); 5185 c = hash_insert(gids, grent ? grent->gr_name : NULL, gid); 5186 } 5187 return (c->name); 5188 } 5189 5190 static uid_t 5191 getuidbyname(char *name) 5192 { 5193 cachenode_t *c; 5194 5195 if ((c = hash_lookup_byname(names, name)) == NULL) { 5196 struct passwd *pwent = getpwnam(name); 5197 c = hash_insert(names, name, pwent ? (int)pwent->pw_uid : -1); 5198 } 5199 return ((uid_t)c->val); 5200 } 5201 5202 static gid_t 5203 getgidbyname(char *group) 5204 { 5205 cachenode_t *c; 5206 5207 if ((c = hash_lookup_byname(groups, group)) == NULL) { 5208 struct group *grent = getgrnam(group); 5209 c = hash_insert(groups, group, grent ? (int)grent->gr_gid : -1); 5210 } 5211 return ((gid_t)c->val); 5212 } 5213 5214 /* 5215 * Build the header. 5216 * Determine whether or not an extended header is also needed. If needed, 5217 * create and write the extended header and its data. 5218 * Writing of the extended header assumes that "tomodes" has been called and 5219 * the relevant information has been placed in the header block. 5220 */ 5221 5222 static int 5223 build_dblock( 5224 const char *name, 5225 const char *linkname, 5226 const char typeflag, 5227 const int filetype, 5228 const struct stat *sp, 5229 const dev_t device, 5230 const char *prefix) 5231 { 5232 int nblks; 5233 major_t dev; 5234 const char *filename; 5235 const char *lastslash; 5236 5237 if (filetype == XATTR_FILE) 5238 dblock.dbuf.typeflag = _XATTR_HDRTYPE; 5239 else 5240 dblock.dbuf.typeflag = typeflag; 5241 (void) memset(dblock.dbuf.name, '\0', NAMSIZ); 5242 (void) memset(dblock.dbuf.linkname, '\0', NAMSIZ); 5243 (void) memset(dblock.dbuf.prefix, '\0', PRESIZ); 5244 5245 if (xhdr_flgs & _X_PATH) 5246 filename = Xtarhdr.x_path; 5247 else 5248 filename = name; 5249 5250 if ((dev = major(device)) > OCTAL7CHAR) { 5251 if (Eflag) { 5252 xhdr_flgs |= _X_DEVMAJOR; 5253 Xtarhdr.x_devmajor = dev; 5254 } else { 5255 (void) fprintf(stderr, gettext( 5256 "Device major too large for %s. Use -E flag."), 5257 filename); 5258 if (errflag) 5259 done(1); 5260 else 5261 Errflg = 1; 5262 } 5263 dev = 0; 5264 } 5265 (void) sprintf(dblock.dbuf.devmajor, "%07lo", dev); 5266 if ((dev = minor(device)) > OCTAL7CHAR) { 5267 if (Eflag) { 5268 xhdr_flgs |= _X_DEVMINOR; 5269 Xtarhdr.x_devminor = dev; 5270 } else { 5271 (void) fprintf(stderr, gettext( 5272 "Device minor too large for %s. Use -E flag."), 5273 filename); 5274 if (errflag) 5275 done(1); 5276 else 5277 Errflg = 1; 5278 } 5279 dev = 0; 5280 } 5281 (void) sprintf(dblock.dbuf.devminor, "%07lo", dev); 5282 5283 (void) strncpy(dblock.dbuf.name, name, NAMSIZ); 5284 (void) strncpy(dblock.dbuf.linkname, linkname, NAMSIZ); 5285 (void) sprintf(dblock.dbuf.magic, "%.5s", magic_type); 5286 (void) sprintf(dblock.dbuf.version, "00"); 5287 (void) sprintf(dblock.dbuf.uname, "%.31s", getname(sp->st_uid)); 5288 (void) sprintf(dblock.dbuf.gname, "%.31s", getgroup(sp->st_gid)); 5289 (void) strncpy(dblock.dbuf.prefix, prefix, PRESIZ); 5290 (void) sprintf(dblock.dbuf.chksum, "%07o", checksum(&dblock)); 5291 5292 if (Eflag) { 5293 (void) bcopy(dblock.dummy, xhdr_buf.dummy, TBLOCK); 5294 (void) memset(xhdr_buf.dbuf.name, '\0', NAMSIZ); 5295 lastslash = strrchr(name, '/'); 5296 if (lastslash == NULL) 5297 lastslash = name; 5298 else 5299 lastslash++; 5300 (void) strcpy(xhdr_buf.dbuf.name, lastslash); 5301 (void) memset(xhdr_buf.dbuf.linkname, '\0', NAMSIZ); 5302 (void) memset(xhdr_buf.dbuf.prefix, '\0', PRESIZ); 5303 (void) strcpy(xhdr_buf.dbuf.prefix, xhdr_dirname); 5304 xhdr_count++; 5305 xrec_offset = 0; 5306 gen_date("mtime", sp->st_mtim); 5307 xhdr_buf.dbuf.typeflag = 'X'; 5308 if (gen_utf8_names(filename) != 0) 5309 return (1); 5310 5311 #ifdef XHDR_DEBUG 5312 Xtarhdr.x_uname = dblock.dbuf.uname; 5313 Xtarhdr.x_gname = dblock.dbuf.gname; 5314 xhdr_flgs |= (_X_UNAME | _X_GNAME); 5315 #endif 5316 if (xhdr_flgs) { 5317 if (xhdr_flgs & _X_DEVMAJOR) 5318 gen_num("SUN.devmajor", Xtarhdr.x_devmajor); 5319 if (xhdr_flgs & _X_DEVMINOR) 5320 gen_num("SUN.devminor", Xtarhdr.x_devminor); 5321 if (xhdr_flgs & _X_GID) 5322 gen_num("gid", Xtarhdr.x_gid); 5323 if (xhdr_flgs & _X_UID) 5324 gen_num("uid", Xtarhdr.x_uid); 5325 if (xhdr_flgs & _X_SIZE) 5326 gen_num("size", Xtarhdr.x_filesz); 5327 if (xhdr_flgs & _X_PATH) 5328 gen_string("path", Xtarhdr.x_path); 5329 if (xhdr_flgs & _X_LINKPATH) 5330 gen_string("linkpath", Xtarhdr.x_linkpath); 5331 if (xhdr_flgs & _X_GNAME) 5332 gen_string("gname", Xtarhdr.x_gname); 5333 if (xhdr_flgs & _X_UNAME) 5334 gen_string("uname", Xtarhdr.x_uname); 5335 } 5336 (void) sprintf(xhdr_buf.dbuf.size, 5337 "%011" FMT_off_t_o, xrec_offset); 5338 (void) sprintf(xhdr_buf.dbuf.chksum, "%07o", 5339 checksum(&xhdr_buf)); 5340 (void) writetbuf((char *)&xhdr_buf, 1); 5341 nblks = TBLOCKS(xrec_offset); 5342 (void) writetbuf(xrec_ptr, nblks); 5343 } 5344 return (0); 5345 } 5346 5347 5348 /* 5349 * makeDir - ensure that a directory with the pathname denoted by name 5350 * exists, and return 1 on success, and 0 on failure (e.g., 5351 * read-only file system, exists but not-a-directory). 5352 */ 5353 5354 static int 5355 makeDir(char *name) 5356 { 5357 struct stat buf; 5358 5359 if (access(name, 0) < 0) { /* name doesn't exist */ 5360 if (mkdir(name, 0777) < 0) { 5361 vperror(0, "%s", name); 5362 return (0); 5363 } 5364 } else { /* name exists */ 5365 if (stat(name, &buf) < 0) { 5366 vperror(0, "%s", name); 5367 return (0); 5368 } 5369 5370 return ((buf.st_mode & S_IFMT) == S_IFDIR); 5371 } 5372 5373 return (1); 5374 } 5375 5376 5377 /* 5378 * Save this directory and its mtime on the stack, popping and setting 5379 * the mtimes of any stacked dirs which aren't parents of this one. 5380 * A null name causes the entire stack to be unwound and set. 5381 * 5382 * Since all the elements of the directory "stack" share a common 5383 * prefix, we can make do with one string. We keep only the current 5384 * directory path, with an associated array of mtime's. A negative 5385 * mtime means no mtime. 5386 * 5387 * This stack algorithm is not guaranteed to work for tapes created 5388 * with the 'r' function letter, but the vast majority of tapes with 5389 * directories are not. This avoids saving every directory record on 5390 * the tape and setting all the times at the end. 5391 * 5392 * (This was borrowed from the 4.1.3 source, and adapted to the 5.x 5393 * environment) 5394 */ 5395 5396 static void 5397 doDirTimes(char *name, timestruc_t modTime) 5398 { 5399 static char dirstack[PATH_MAX+2]; 5400 /* Add spaces for the last slash and last NULL */ 5401 static timestruc_t modtimes[PATH_MAX+1]; /* hash table */ 5402 char *p = dirstack; 5403 char *q = name; 5404 char *savp; 5405 5406 if (q) { 5407 /* 5408 * Find common prefix 5409 */ 5410 5411 while (*p == *q && *p) { 5412 p++; q++; 5413 } 5414 } 5415 5416 savp = p; 5417 while (*p) { 5418 /* 5419 * Not a child: unwind the stack, setting the times. 5420 * The order we do this doesn't matter, so we go "forward." 5421 */ 5422 5423 if (*p == '/') 5424 if (modtimes[p - dirstack].tv_sec >= 0) { 5425 *p = '\0'; /* zap the slash */ 5426 setPathTimes(AT_FDCWD, dirstack, 5427 modtimes[p - dirstack]); 5428 *p = '/'; 5429 } 5430 ++p; 5431 } 5432 5433 p = savp; 5434 5435 /* 5436 * Push this one on the "stack" 5437 */ 5438 5439 if (q) { 5440 5441 /* 5442 * Since the name parameter points the dir pathname 5443 * which is limited only to contain PATH_MAX chars 5444 * at maximum, we can ignore the overflow case of p. 5445 */ 5446 5447 while ((*p = *q++)) { /* append the rest of the new dir */ 5448 modtimes[p - dirstack].tv_sec = -1; 5449 p++; 5450 } 5451 5452 /* 5453 * If the tar file had used 'P' or 'E' function modifier, 5454 * append the last slash. 5455 */ 5456 if (*(p - 1) != '/') { 5457 *p++ = '/'; 5458 *p = '\0'; 5459 } 5460 /* overwrite the last one */ 5461 modtimes[p - dirstack - 1] = modTime; 5462 } 5463 } 5464 5465 5466 /* 5467 * setPathTimes - set the modification time for given path. Return 1 if 5468 * successful and 0 if not successful. 5469 */ 5470 5471 static void 5472 setPathTimes(int dirfd, char *path, timestruc_t modTime) 5473 5474 { 5475 struct timeval timebuf[2]; 5476 5477 /* 5478 * futimesat takes an array of two timeval structs. 5479 * The first entry contains access time. 5480 * The second entry contains modification time. 5481 * Unlike a timestruc_t, which uses nanoseconds, timeval uses 5482 * microseconds. 5483 */ 5484 timebuf[0].tv_sec = time((time_t *)0); 5485 timebuf[0].tv_usec = 0; 5486 timebuf[1].tv_sec = modTime.tv_sec; 5487 5488 /* Extended header: use microseconds */ 5489 timebuf[1].tv_usec = (xhdr_flgs & _X_MTIME) ? modTime.tv_nsec/1000 : 0; 5490 5491 if (futimesat(dirfd, path, timebuf) < 0) 5492 vperror(0, "can't set time on %s", path); 5493 } 5494 5495 5496 /* 5497 * If hflag is set then delete the symbolic link's target. 5498 * If !hflag then delete the target. 5499 */ 5500 5501 static void 5502 delete_target(int fd, char *namep) 5503 { 5504 struct stat xtractbuf; 5505 char buf[PATH_MAX + 1]; 5506 int n; 5507 5508 5509 if (unlinkat(fd, namep, AT_REMOVEDIR) < 0) { 5510 if (errno == ENOTDIR && !hflag) { 5511 (void) unlinkat(fd, namep, 0); 5512 } else if (errno == ENOTDIR && hflag) { 5513 if (!lstat(namep, &xtractbuf)) { 5514 if ((xtractbuf.st_mode & S_IFMT) != S_IFLNK) { 5515 (void) unlinkat(fd, namep, 0); 5516 } else if ((n = readlink(namep, buf, 5517 PATH_MAX)) != -1) { 5518 buf[n] = (char)NULL; 5519 (void) unlinkat(fd, buf, 5520 AT_REMOVEDIR); 5521 if (errno == ENOTDIR) 5522 (void) unlinkat(fd, buf, 0); 5523 } else { 5524 (void) unlinkat(fd, namep, 0); 5525 } 5526 } else { 5527 (void) unlinkat(fd, namep, 0); 5528 } 5529 } 5530 } 5531 } 5532 5533 5534 /* 5535 * ACL changes: 5536 * putfile(): 5537 * Get acl info after stat. Write out ancillary file 5538 * before the normal file, i.e. directory, regular, FIFO, 5539 * link, special. If acl count is less than 4, no need to 5540 * create ancillary file. (i.e. standard permission is in 5541 * use. 5542 * doxtract(): 5543 * Process ancillary file. Read it in and set acl info. 5544 * watch out for 'o' function modifier. 5545 * 't' function letter to display table 5546 */ 5547 5548 /* 5549 * New functions for ACLs and other security attributes 5550 */ 5551 5552 /* 5553 * The function appends the new security attribute info to the end of 5554 * existing secinfo. 5555 */ 5556 int 5557 append_secattr( 5558 char **secinfo, /* existing security info */ 5559 int *secinfo_len, /* length of existing security info */ 5560 acl_t *aclp) 5561 { 5562 char *new_secinfo; 5563 char *attrtext; 5564 int newattrsize; 5565 int oldsize; 5566 5567 /* no need to add */ 5568 if (aclp == (void *)NULL) 5569 return (0); 5570 5571 switch (acl_type(aclp)) { 5572 case ACLENT_T: 5573 case ACE_T: 5574 attrtext = acl_totext(aclp); 5575 if (attrtext == NULL) { 5576 (void) fprintf(stderr, "acltotext failed\n"); 5577 return (-1); 5578 } 5579 /* header: type + size = 8 */ 5580 newattrsize = 8 + (int)strlen(attrtext) + 1; 5581 attr = (struct sec_attr *)malloc(newattrsize); 5582 if (attr == NULL) { 5583 (void) fprintf(stderr, "can't allocate memory\n"); 5584 return (-1); 5585 } 5586 attr->attr_type = (acl_type(aclp) == ACLENT_T) ? 5587 UFSD_ACL : ACE_ACL; 5588 (void) sprintf(attr->attr_len, 5589 "%06o", acl_cnt(aclp)); /* acl entry count */ 5590 (void) strcpy((char *)&attr->attr_info[0], attrtext); 5591 free(attrtext); 5592 break; 5593 5594 /* SunFed's case goes here */ 5595 5596 default: 5597 (void) fprintf(stderr, "unrecognized attribute type\n"); 5598 return (-1); 5599 } 5600 5601 /* old security info + new attr header(8) + new attr */ 5602 oldsize = *secinfo_len; 5603 *secinfo_len += newattrsize; 5604 new_secinfo = (char *)malloc(*secinfo_len); 5605 if (new_secinfo == NULL) { 5606 (void) fprintf(stderr, "can't allocate memory\n"); 5607 *secinfo_len -= newattrsize; 5608 return (-1); 5609 } 5610 5611 (void) memcpy(new_secinfo, *secinfo, oldsize); 5612 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 5613 5614 free(*secinfo); 5615 *secinfo = new_secinfo; 5616 return (0); 5617 } 5618 5619 /* 5620 * write_ancillary(): write out an ancillary file. 5621 * The file has the same header as normal file except the type and size 5622 * fields. The type is 'A' and size is the sum of all attributes 5623 * in bytes. 5624 * The body contains a list of attribute type, size and info. Currently, 5625 * there is only ACL info. This file is put before the normal file. 5626 */ 5627 void 5628 write_ancillary(union hblock *dblockp, char *secinfo, int len, char hdrtype) 5629 { 5630 long blocks; 5631 int savflag; 5632 int savsize; 5633 5634 /* Just tranditional permissions or no security attribute info */ 5635 if (len == 0 || secinfo == NULL) 5636 return; 5637 5638 /* save flag and size */ 5639 savflag = (dblockp->dbuf).typeflag; 5640 (void) sscanf(dblockp->dbuf.size, "%12o", (uint_t *)&savsize); 5641 5642 /* special flag for ancillary file */ 5643 if (hdrtype == _XATTR_HDRTYPE) 5644 dblockp->dbuf.typeflag = _XATTR_HDRTYPE; 5645 else 5646 dblockp->dbuf.typeflag = 'A'; 5647 5648 /* for pre-2.5 versions of tar, need to make sure */ 5649 /* the ACL file is readable */ 5650 (void) sprintf(dblock.dbuf.mode, "%07lo", 5651 (stbuf.st_mode & POSIXMODES) | 0000200); 5652 (void) sprintf(dblockp->dbuf.size, "%011o", len); 5653 (void) sprintf(dblockp->dbuf.chksum, "%07o", checksum(dblockp)); 5654 5655 /* write out the header */ 5656 (void) writetbuf((char *)dblockp, 1); 5657 5658 /* write out security info */ 5659 blocks = TBLOCKS(len); 5660 (void) writetbuf((char *)secinfo, (int)blocks); 5661 5662 /* restore mode, flag and size */ 5663 (void) sprintf(dblock.dbuf.mode, "%07lo", stbuf.st_mode & POSIXMODES); 5664 dblockp->dbuf.typeflag = savflag; 5665 (void) sprintf(dblockp->dbuf.size, "%011o", savsize); 5666 } 5667 5668 /* 5669 * Read the data record for extended headers and then the regular header. 5670 * The data are read into the buffer and then null-terminated. Entries 5671 * are of the format: 5672 * "%d %s=%s\n" 5673 * 5674 * When an extended header record is found, the extended header must 5675 * be processed and its values used to override the values in the 5676 * normal header. The way this is done is to process the extended 5677 * header data record and set the data values, then call getdir 5678 * to process the regular header, then then to reconcile the two 5679 * sets of data. 5680 */ 5681 5682 static int 5683 get_xdata(void) 5684 { 5685 struct keylist_pair { 5686 int keynum; 5687 char *keylist; 5688 } keylist_pair[] = { _X_DEVMAJOR, "SUN.devmajor", 5689 _X_DEVMINOR, "SUN.devminor", 5690 _X_GID, "gid", 5691 _X_GNAME, "gname", 5692 _X_LINKPATH, "linkpath", 5693 _X_PATH, "path", 5694 _X_SIZE, "size", 5695 _X_UID, "uid", 5696 _X_UNAME, "uname", 5697 _X_MTIME, "mtime", 5698 _X_LAST, "NULL" }; 5699 char *lineloc; 5700 int length, i; 5701 char *keyword, *value; 5702 blkcnt_t nblocks; 5703 int bufneeded; 5704 struct stat *sp = &stbuf; 5705 int errors; 5706 5707 Xtarhdr.x_uid = 0; 5708 Xtarhdr.x_gid = 0; 5709 Xtarhdr.x_devmajor = 0; 5710 Xtarhdr.x_devminor = 0; 5711 Xtarhdr.x_filesz = 0; 5712 Xtarhdr.x_uname = NULL; 5713 Xtarhdr.x_gname = NULL; 5714 Xtarhdr.x_linkpath = NULL; 5715 Xtarhdr.x_path = NULL; 5716 Xtarhdr.x_mtime.tv_sec = 0; 5717 Xtarhdr.x_mtime.tv_nsec = 0; 5718 xhdr_count++; 5719 errors = 0; 5720 5721 nblocks = TBLOCKS(stbuf.st_size); 5722 bufneeded = nblocks * TBLOCK; 5723 if (bufneeded >= xrec_size) { 5724 free(xrec_ptr); 5725 xrec_size = bufneeded + 1; 5726 if ((xrec_ptr = malloc(xrec_size)) == NULL) 5727 fatal(gettext("cannot allocate buffer")); 5728 } 5729 5730 lineloc = xrec_ptr; 5731 5732 while (nblocks-- > 0) { 5733 readtape(lineloc); 5734 lineloc += TBLOCK; 5735 } 5736 lineloc = xrec_ptr; 5737 xrec_ptr[stbuf.st_size] = '\0'; 5738 while (lineloc < xrec_ptr + stbuf.st_size) { 5739 length = atoi(lineloc); 5740 *(lineloc + length - 1) = '\0'; 5741 keyword = strchr(lineloc, ' ') + 1; 5742 value = strchr(keyword, '=') + 1; 5743 *(value - 1) = '\0'; 5744 i = 0; 5745 lineloc += length; 5746 while (keylist_pair[i].keynum != (int)_X_LAST) { 5747 if (strcmp(keyword, keylist_pair[i].keylist) == 0) 5748 break; 5749 i++; 5750 } 5751 errno = 0; 5752 switch (keylist_pair[i].keynum) { 5753 case _X_DEVMAJOR: 5754 Xtarhdr.x_devmajor = (major_t)strtoul(value, NULL, 0); 5755 if (errno) { 5756 (void) fprintf(stderr, gettext( 5757 "tar: Extended header major value error " 5758 "for file # %llu.\n"), xhdr_count); 5759 errors++; 5760 } else 5761 xhdr_flgs |= _X_DEVMAJOR; 5762 break; 5763 case _X_DEVMINOR: 5764 Xtarhdr.x_devminor = (minor_t)strtoul(value, NULL, 0); 5765 if (errno) { 5766 (void) fprintf(stderr, gettext( 5767 "tar: Extended header minor value error " 5768 "for file # %llu.\n"), xhdr_count); 5769 errors++; 5770 } else 5771 xhdr_flgs |= _X_DEVMINOR; 5772 break; 5773 case _X_GID: 5774 xhdr_flgs |= _X_GID; 5775 Xtarhdr.x_gid = strtol(value, NULL, 0); 5776 if ((errno) || (Xtarhdr.x_gid > UID_MAX)) { 5777 (void) fprintf(stderr, gettext( 5778 "tar: Extended header gid value error " 5779 "for file # %llu.\n"), xhdr_count); 5780 Xtarhdr.x_gid = GID_NOBODY; 5781 } 5782 break; 5783 case _X_GNAME: 5784 if (utf8_local("gname", &Xtarhdr.x_gname, 5785 local_gname, value, _POSIX_NAME_MAX) == 0) 5786 xhdr_flgs |= _X_GNAME; 5787 break; 5788 case _X_LINKPATH: 5789 if (utf8_local("linkpath", &Xtarhdr.x_linkpath, 5790 local_linkpath, value, PATH_MAX) == 0) 5791 xhdr_flgs |= _X_LINKPATH; 5792 else 5793 errors++; 5794 break; 5795 case _X_PATH: 5796 if (utf8_local("path", &Xtarhdr.x_path, 5797 local_path, value, PATH_MAX) == 0) 5798 xhdr_flgs |= _X_PATH; 5799 else 5800 errors++; 5801 break; 5802 case _X_SIZE: 5803 Xtarhdr.x_filesz = strtoull(value, NULL, 0); 5804 if (errno) { 5805 (void) fprintf(stderr, gettext( 5806 "tar: Extended header invalid filesize " 5807 "for file # %llu.\n"), xhdr_count); 5808 errors++; 5809 } else 5810 xhdr_flgs |= _X_SIZE; 5811 break; 5812 case _X_UID: 5813 xhdr_flgs |= _X_UID; 5814 Xtarhdr.x_uid = strtol(value, NULL, 0); 5815 if ((errno) || (Xtarhdr.x_uid > UID_MAX)) { 5816 (void) fprintf(stderr, gettext( 5817 "tar: Extended header uid value error " 5818 "for file # %llu.\n"), xhdr_count); 5819 Xtarhdr.x_uid = UID_NOBODY; 5820 } 5821 break; 5822 case _X_UNAME: 5823 if (utf8_local("uname", &Xtarhdr.x_uname, 5824 local_uname, value, _POSIX_NAME_MAX) == 0) 5825 xhdr_flgs |= _X_UNAME; 5826 break; 5827 case _X_MTIME: 5828 get_xtime(value, &(Xtarhdr.x_mtime)); 5829 if (errno) 5830 (void) fprintf(stderr, gettext( 5831 "tar: Extended header modification time " 5832 "value error for file # %llu.\n"), 5833 xhdr_count); 5834 else 5835 xhdr_flgs |= _X_MTIME; 5836 break; 5837 default: 5838 (void) fprintf(stderr, 5839 gettext("tar: unrecognized extended" 5840 " header keyword '%s'. Ignored.\n"), keyword); 5841 break; 5842 } 5843 } 5844 5845 getdir(); /* get regular header */ 5846 5847 if (xhdr_flgs & _X_DEVMAJOR) { 5848 Gen.g_devmajor = Xtarhdr.x_devmajor; 5849 } 5850 if (xhdr_flgs & _X_DEVMINOR) { 5851 Gen.g_devminor = Xtarhdr.x_devminor; 5852 } 5853 if (xhdr_flgs & _X_GID) { 5854 Gen.g_gid = Xtarhdr.x_gid; 5855 sp->st_gid = Gen.g_gid; 5856 } 5857 if (xhdr_flgs & _X_UID) { 5858 Gen.g_uid = Xtarhdr.x_uid; 5859 sp->st_uid = Gen.g_uid; 5860 } 5861 if (xhdr_flgs & _X_SIZE) { 5862 Gen.g_filesz = Xtarhdr.x_filesz; 5863 sp->st_size = Gen.g_filesz; 5864 } 5865 if (xhdr_flgs & _X_MTIME) { 5866 Gen.g_mtime = Xtarhdr.x_mtime.tv_sec; 5867 sp->st_mtim.tv_sec = Gen.g_mtime; 5868 sp->st_mtim.tv_nsec = Xtarhdr.x_mtime.tv_nsec; 5869 } 5870 5871 if (errors && errflag) 5872 done(1); 5873 else 5874 if (errors) 5875 Errflg = 1; 5876 return (errors); 5877 } 5878 5879 /* 5880 * gen_num creates a string from a keyword and an usigned long long in the 5881 * format: %d %s=%s\n 5882 * This is part of the extended header data record. 5883 */ 5884 5885 void 5886 gen_num(const char *keyword, const u_longlong_t number) 5887 { 5888 char save_val[ULONGLONG_MAX_DIGITS + 1]; 5889 int len; 5890 char *curr_ptr; 5891 5892 (void) sprintf(save_val, "%llu", number); 5893 /* 5894 * len = length of entire line, including itself. len will be 5895 * two digits. So, add the string lengths plus the length of len, 5896 * plus a blank, an equal sign, and a newline. 5897 */ 5898 len = strlen(save_val) + strlen(keyword) + 5; 5899 if (xrec_offset + len > xrec_size) { 5900 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5901 fatal(gettext( 5902 "cannot allocate extended header buffer")); 5903 xrec_ptr = curr_ptr; 5904 xrec_size *= 2; 5905 } 5906 (void) sprintf(&xrec_ptr[xrec_offset], 5907 "%d %s=%s\n", len, keyword, save_val); 5908 xrec_offset += len; 5909 } 5910 5911 /* 5912 * gen_date creates a string from a keyword and a timestruc_t in the 5913 * format: %d %s=%s\n 5914 * This is part of the extended header data record. 5915 * Currently, granularity is only microseconds, so the low-order three digits 5916 * will be truncated. 5917 */ 5918 5919 void 5920 gen_date(const char *keyword, const timestruc_t time_value) 5921 { 5922 /* Allow for <seconds>.<nanoseconds>\n */ 5923 char save_val[TIME_MAX_DIGITS + LONG_MAX_DIGITS + 2]; 5924 int len; 5925 char *curr_ptr; 5926 5927 (void) sprintf(save_val, "%ld", time_value.tv_sec); 5928 len = strlen(save_val); 5929 save_val[len] = '.'; 5930 (void) sprintf(&save_val[len + 1], "%9.9ld", time_value.tv_nsec); 5931 5932 /* 5933 * len = length of entire line, including itself. len will be 5934 * two digits. So, add the string lengths plus the length of len, 5935 * plus a blank, an equal sign, and a newline. 5936 */ 5937 len = strlen(save_val) + strlen(keyword) + 5; 5938 if (xrec_offset + len > xrec_size) { 5939 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5940 fatal(gettext( 5941 "cannot allocate extended header buffer")); 5942 xrec_ptr = curr_ptr; 5943 xrec_size *= 2; 5944 } 5945 (void) sprintf(&xrec_ptr[xrec_offset], 5946 "%d %s=%s\n", len, keyword, save_val); 5947 xrec_offset += len; 5948 } 5949 5950 /* 5951 * gen_string creates a string from a keyword and a char * in the 5952 * format: %d %s=%s\n 5953 * This is part of the extended header data record. 5954 */ 5955 5956 void 5957 gen_string(const char *keyword, const char *value) 5958 { 5959 int len; 5960 char *curr_ptr; 5961 5962 /* 5963 * len = length of entire line, including itself. The character length 5964 * of len must be 1-4 characters, because the maximum size of the path 5965 * or the name is PATH_MAX, which is 1024. So, assume 1 character 5966 * for len, one for the space, one for the "=", and one for the newline. 5967 * Then adjust as needed. 5968 */ 5969 /* LINTED constant expression */ 5970 assert(PATH_MAX <= 9996); 5971 len = strlen(value) + strlen(keyword) + 4; 5972 if (len > 997) 5973 len += 3; 5974 else if (len > 98) 5975 len += 2; 5976 else if (len > 9) 5977 len += 1; 5978 if (xrec_offset + len > xrec_size) { 5979 if (((curr_ptr = realloc(xrec_ptr, 2 * xrec_size)) == NULL)) 5980 fatal(gettext( 5981 "cannot allocate extended header buffer")); 5982 xrec_ptr = curr_ptr; 5983 xrec_size *= 2; 5984 } 5985 #ifdef XHDR_DEBUG 5986 if (strcmp(keyword+1, "name") != 0) 5987 #endif 5988 (void) sprintf(&xrec_ptr[xrec_offset], 5989 "%d %s=%s\n", len, keyword, value); 5990 #ifdef XHDR_DEBUG 5991 else { 5992 len += 11; 5993 (void) sprintf(&xrec_ptr[xrec_offset], 5994 "%d %s=%snametoolong\n", len, keyword, value); 5995 } 5996 #endif 5997 xrec_offset += len; 5998 } 5999 6000 /* 6001 * Convert time found in the extended header data to seconds and nanoseconds. 6002 */ 6003 6004 void 6005 get_xtime(char *value, timestruc_t *xtime) 6006 { 6007 char nanosec[10]; 6008 char *period; 6009 int i; 6010 6011 (void) memset(nanosec, '0', 9); 6012 nanosec[9] = '\0'; 6013 6014 period = strchr(value, '.'); 6015 if (period != NULL) 6016 period[0] = '\0'; 6017 xtime->tv_sec = strtol(value, NULL, 10); 6018 if (period == NULL) 6019 xtime->tv_nsec = 0; 6020 else { 6021 i = strlen(period +1); 6022 (void) strncpy(nanosec, period + 1, min(i, 9)); 6023 xtime->tv_nsec = strtol(nanosec, NULL, 10); 6024 } 6025 } 6026 6027 /* 6028 * Check linkpath for length. 6029 * Emit an error message and return 1 if too long. 6030 */ 6031 6032 int 6033 chk_path_build( 6034 char *name, 6035 char *longname, 6036 char *linkname, 6037 char *prefix, 6038 char type, 6039 int filetype) 6040 { 6041 6042 if (strlen(linkname) > (size_t)NAMSIZ) { 6043 if (Eflag > 0) { 6044 xhdr_flgs |= _X_LINKPATH; 6045 Xtarhdr.x_linkpath = linkname; 6046 } else { 6047 (void) fprintf(stderr, gettext( 6048 "tar: %s: linked to %s\n"), longname, linkname); 6049 (void) fprintf(stderr, gettext( 6050 "tar: %s: linked name too long\n"), linkname); 6051 if (errflag) 6052 done(1); 6053 else 6054 Errflg = 1; 6055 return (1); 6056 } 6057 } 6058 if (xhdr_flgs & _X_LINKPATH) 6059 return (build_dblock(name, tchar, type, 6060 filetype, &stbuf, stbuf.st_dev, 6061 prefix)); 6062 else 6063 return (build_dblock(name, linkname, type, 6064 filetype, &stbuf, stbuf.st_dev, prefix)); 6065 } 6066 6067 /* 6068 * Convert from UTF-8 to local character set. 6069 */ 6070 6071 static int 6072 utf8_local( 6073 char *option, 6074 char **Xhdr_ptrptr, 6075 char *target, 6076 const char *source, 6077 int max_val) 6078 { 6079 static iconv_t iconv_cd; 6080 char *nl_target; 6081 const char *iconv_src; 6082 char *iconv_trg; 6083 size_t inlen; 6084 size_t outlen; 6085 6086 if (charset_type == -1) { /* iconv_open failed in earlier try */ 6087 (void) fprintf(stderr, gettext( 6088 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6089 xhdr_count, source); 6090 return (1); 6091 } else if (charset_type == 0) { /* iconv_open has not yet been done */ 6092 nl_target = nl_langinfo(CODESET); 6093 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6094 nl_target = "646"; 6095 if (strcmp(nl_target, "646") == 0) 6096 charset_type = 1; 6097 else if (strcmp(nl_target, "UTF-8") == 0) 6098 charset_type = 3; 6099 else { 6100 if (strncmp(nl_target, "ISO", 3) == 0) 6101 nl_target += 3; 6102 charset_type = 2; 6103 errno = 0; 6104 if ((iconv_cd = iconv_open(nl_target, "UTF-8")) == 6105 (iconv_t)-1) { 6106 if (errno == EINVAL) 6107 (void) fprintf(stderr, gettext( 6108 "tar: conversion routines not " 6109 "available for current locale. ")); 6110 (void) fprintf(stderr, gettext( 6111 "file # %llu: (%s) UTF-8 conversion" 6112 " failed.\n"), xhdr_count, source); 6113 charset_type = -1; 6114 return (1); 6115 } 6116 } 6117 } 6118 6119 /* locale using 7-bit codeset or UTF-8 locale */ 6120 if (charset_type == 1 || charset_type == 3) { 6121 if (strlen(source) > max_val) { 6122 (void) fprintf(stderr, gettext( 6123 "tar: file # %llu: Extended header %s too long.\n"), 6124 xhdr_count, option); 6125 return (1); 6126 } 6127 if (charset_type == 3) 6128 (void) strcpy(target, source); 6129 else if (c_utf8(target, source) != 0) { 6130 (void) fprintf(stderr, gettext( 6131 "tar: file # %llu: (%s) UTF-8 conversion" 6132 " failed.\n"), xhdr_count, source); 6133 return (1); 6134 } 6135 *Xhdr_ptrptr = target; 6136 return (0); 6137 } 6138 6139 iconv_src = source; 6140 iconv_trg = target; 6141 inlen = strlen(source); 6142 outlen = max_val * UTF_8_FACTOR; 6143 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6144 (size_t)-1) { /* Error occurred: didn't convert */ 6145 (void) fprintf(stderr, gettext( 6146 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6147 xhdr_count, source); 6148 /* Get remaining output; reinitialize conversion descriptor */ 6149 iconv_src = (const char *)NULL; 6150 inlen = 0; 6151 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6152 return (1); 6153 } 6154 /* Get remaining output; reinitialize conversion descriptor */ 6155 iconv_src = (const char *)NULL; 6156 inlen = 0; 6157 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6158 (size_t)-1) { /* Error occurred: didn't convert */ 6159 (void) fprintf(stderr, gettext( 6160 "tar: file # %llu: (%s) UTF-8 conversion failed.\n"), 6161 xhdr_count, source); 6162 return (1); 6163 } 6164 6165 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6166 if (strlen(target) > max_val) { 6167 (void) fprintf(stderr, gettext( 6168 "tar: file # %llu: Extended header %s too long.\n"), 6169 xhdr_count, option); 6170 return (1); 6171 } 6172 *Xhdr_ptrptr = target; 6173 return (0); 6174 } 6175 6176 /* 6177 * Check gname, uname, path, and linkpath to see if they need to go in an 6178 * extended header. If they are already slated to be in an extended header, 6179 * or if they are not ascii, then they need to be in the extended header. 6180 * Then, convert all extended names to UTF-8. 6181 */ 6182 6183 int 6184 gen_utf8_names(const char *filename) 6185 { 6186 static iconv_t iconv_cd; 6187 char *nl_target; 6188 char tempbuf[MAXNAM + 1]; 6189 int nbytes; 6190 int errors; 6191 6192 if (charset_type == -1) { /* Previous failure to open. */ 6193 (void) fprintf(stderr, gettext( 6194 "tar: file # %llu: UTF-8 conversion failed.\n"), 6195 xhdr_count); 6196 return (1); 6197 } 6198 6199 if (charset_type == 0) { /* Need to get conversion descriptor */ 6200 nl_target = nl_langinfo(CODESET); 6201 if (strlen(nl_target) == 0) /* locale using 7-bit codeset */ 6202 nl_target = "646"; 6203 if (strcmp(nl_target, "646") == 0) 6204 charset_type = 1; 6205 else if (strcmp(nl_target, "UTF-8") == 0) 6206 charset_type = 3; 6207 else { 6208 if (strncmp(nl_target, "ISO", 3) == 0) 6209 nl_target += 3; 6210 charset_type = 2; 6211 errno = 0; 6212 #ifdef ICONV_DEBUG 6213 (void) fprintf(stderr, 6214 "Opening iconv_cd with target %s\n", 6215 nl_target); 6216 #endif 6217 if ((iconv_cd = iconv_open("UTF-8", nl_target)) == 6218 (iconv_t)-1) { 6219 if (errno == EINVAL) 6220 (void) fprintf(stderr, gettext( 6221 "tar: conversion routines not " 6222 "available for current locale. ")); 6223 (void) fprintf(stderr, gettext( 6224 "file (%s): UTF-8 conversion failed.\n"), 6225 filename); 6226 charset_type = -1; 6227 return (1); 6228 } 6229 } 6230 } 6231 6232 errors = 0; 6233 6234 errors += local_utf8(&Xtarhdr.x_gname, local_gname, 6235 dblock.dbuf.gname, iconv_cd, _X_GNAME, _POSIX_NAME_MAX); 6236 errors += local_utf8(&Xtarhdr.x_uname, local_uname, 6237 dblock.dbuf.uname, iconv_cd, _X_UNAME, _POSIX_NAME_MAX); 6238 if ((xhdr_flgs & _X_LINKPATH) == 0) { /* Need null-terminated str. */ 6239 (void) strncpy(tempbuf, dblock.dbuf.linkname, NAMSIZ); 6240 tempbuf[NAMSIZ] = '\0'; 6241 } 6242 errors += local_utf8(&Xtarhdr.x_linkpath, local_linkpath, 6243 tempbuf, iconv_cd, _X_LINKPATH, PATH_MAX); 6244 if ((xhdr_flgs & _X_PATH) == 0) { /* Concatenate prefix & name */ 6245 (void) strncpy(tempbuf, dblock.dbuf.prefix, PRESIZ); 6246 tempbuf[PRESIZ] = '\0'; 6247 nbytes = strlen(tempbuf); 6248 if (nbytes > 0) { 6249 tempbuf[nbytes++] = '/'; 6250 tempbuf[nbytes] = '\0'; 6251 } 6252 (void) strncat(tempbuf + nbytes, dblock.dbuf.name, 6253 (MAXNAM - nbytes)); 6254 tempbuf[MAXNAM] = '\0'; 6255 } 6256 errors += local_utf8(&Xtarhdr.x_path, local_path, 6257 tempbuf, iconv_cd, _X_PATH, PATH_MAX); 6258 6259 if (errors > 0) 6260 (void) fprintf(stderr, gettext( 6261 "tar: file (%s): UTF-8 conversion failed.\n"), filename); 6262 6263 if (errors && errflag) 6264 done(1); 6265 else 6266 if (errors) 6267 Errflg = 1; 6268 return (errors); 6269 } 6270 6271 static int 6272 local_utf8( 6273 char **Xhdr_ptrptr, 6274 char *target, 6275 const char *source, 6276 iconv_t iconv_cd, 6277 int xhdrflg, 6278 int max_val) 6279 { 6280 const char *iconv_src; 6281 const char *starting_src; 6282 char *iconv_trg; 6283 size_t inlen; 6284 size_t outlen; 6285 #ifdef ICONV_DEBUG 6286 unsigned char c_to_hex; 6287 #endif 6288 6289 /* 6290 * If the item is already slated for extended format, get the string 6291 * to convert from the extended header record. Otherwise, get it from 6292 * the regular (dblock) area. 6293 */ 6294 if (xhdr_flgs & xhdrflg) { 6295 if (charset_type == 3) { /* Already UTF-8, just copy */ 6296 (void) strcpy(target, *Xhdr_ptrptr); 6297 *Xhdr_ptrptr = target; 6298 return (0); 6299 } else 6300 iconv_src = (const char *) *Xhdr_ptrptr; 6301 } else { 6302 if (charset_type == 3) /* Already in UTF-8 format */ 6303 return (0); /* Don't create xhdr record */ 6304 iconv_src = source; 6305 } 6306 starting_src = iconv_src; 6307 iconv_trg = target; 6308 if ((inlen = strlen(iconv_src)) == 0) 6309 return (0); 6310 6311 if (charset_type == 1) { /* locale using 7-bit codeset */ 6312 if (c_utf8(target, starting_src) != 0) { 6313 (void) fprintf(stderr, 6314 gettext("tar: invalid character in" 6315 " UTF-8 conversion of '%s'\n"), starting_src); 6316 return (1); 6317 } 6318 return (0); 6319 } 6320 6321 outlen = max_val * UTF_8_FACTOR; 6322 errno = 0; 6323 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6324 (size_t)-1) { 6325 /* An error occurred, or not all characters were converted */ 6326 if (errno == EILSEQ) 6327 (void) fprintf(stderr, 6328 gettext("tar: invalid character in" 6329 " UTF-8 conversion of '%s'\n"), starting_src); 6330 else 6331 (void) fprintf(stderr, gettext( 6332 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6333 starting_src); 6334 /* Get remaining output; reinitialize conversion descriptor */ 6335 iconv_src = (const char *)NULL; 6336 inlen = 0; 6337 (void) iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen); 6338 return (1); 6339 } 6340 /* Get remaining output; reinitialize conversion descriptor */ 6341 iconv_src = (const char *)NULL; 6342 inlen = 0; 6343 if (iconv(iconv_cd, &iconv_src, &inlen, &iconv_trg, &outlen) == 6344 (size_t)-1) { /* Error occurred: didn't convert */ 6345 if (errno == EILSEQ) 6346 (void) fprintf(stderr, 6347 gettext("tar: invalid character in" 6348 " UTF-8 conversion of '%s'\n"), starting_src); 6349 else 6350 (void) fprintf(stderr, gettext( 6351 "tar: conversion to UTF-8 aborted for '%s'.\n"), 6352 starting_src); 6353 return (1); 6354 } 6355 6356 *iconv_trg = '\0'; /* Null-terminate iconv output string */ 6357 if (strcmp(starting_src, target) != 0) { 6358 *Xhdr_ptrptr = target; 6359 xhdr_flgs |= xhdrflg; 6360 #ifdef ICONV_DEBUG 6361 (void) fprintf(stderr, "*** inlen: %d %d; outlen: %d %d\n", 6362 strlen(starting_src), inlen, max_val, outlen); 6363 (void) fprintf(stderr, "Input string:\n "); 6364 for (inlen = 0; inlen < strlen(starting_src); inlen++) { 6365 c_to_hex = (unsigned char)starting_src[inlen]; 6366 (void) fprintf(stderr, " %2.2x", c_to_hex); 6367 if (inlen % 20 == 19) 6368 (void) fprintf(stderr, "\n "); 6369 } 6370 (void) fprintf(stderr, "\nOutput string:\n "); 6371 for (inlen = 0; inlen < strlen(target); inlen++) { 6372 c_to_hex = (unsigned char)target[inlen]; 6373 (void) fprintf(stderr, " %2.2x", c_to_hex); 6374 if (inlen % 20 == 19) 6375 (void) fprintf(stderr, "\n "); 6376 } 6377 (void) fprintf(stderr, "\n"); 6378 #endif 6379 } 6380 6381 return (0); 6382 } 6383 6384 /* 6385 * Function to test each byte of the source string to make sure it is 6386 * in within bounds (value between 0 and 127). 6387 * If valid, copy source to target. 6388 */ 6389 6390 int 6391 c_utf8(char *target, const char *source) 6392 { 6393 size_t len; 6394 const char *thischar; 6395 6396 len = strlen(source); 6397 thischar = source; 6398 while (len-- > 0) { 6399 if (!isascii((int)(*thischar++))) 6400 return (1); 6401 } 6402 6403 (void) strcpy(target, source); 6404 return (0); 6405 } 6406 6407 6408 #if defined(O_XATTR) 6409 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 6410 6411 static void 6412 prepare_xattr( 6413 char **attrbuf, 6414 char *filename, 6415 char *attrname, 6416 char typeflag, 6417 struct linkbuf *linkinfo, 6418 int *rlen) 6419 { 6420 char *bufhead; /* ptr to full buffer */ 6421 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 6422 struct xattr_buf *tptr; /* ptr to pathing pieces */ 6423 int totalen; /* total buffer length */ 6424 int len; /* length returned to user */ 6425 int stringlen; /* length of filename + attr */ 6426 /* 6427 * length of filename + attr 6428 * in link section 6429 */ 6430 int linkstringlen; 6431 int complen; /* length of pathing section */ 6432 int linklen; /* length of link section */ 6433 6434 /* 6435 * Release previous buffer 6436 */ 6437 6438 if (*attrbuf != (char *)NULL) { 6439 free(*attrbuf); 6440 *attrbuf = NULL; 6441 } 6442 6443 /* 6444 * First add in fixed size stuff 6445 */ 6446 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 6447 6448 /* 6449 * Add space for two nulls 6450 */ 6451 stringlen = strlen(attrname) + strlen(filename) + 2; 6452 complen = stringlen + sizeof (struct xattr_buf); 6453 6454 len += stringlen; 6455 6456 /* 6457 * Now add on space for link info if any 6458 */ 6459 6460 if (linkinfo != NULL) { 6461 /* 6462 * Again add space for two nulls 6463 */ 6464 linkstringlen = strlen(linkinfo->pathname) + 6465 strlen(linkinfo->attrname) + 2; 6466 len += linkstringlen; 6467 } 6468 6469 /* 6470 * Now add padding to end to fill out TBLOCK 6471 * 6472 * Function returns size of real data and not size + padding. 6473 */ 6474 6475 totalen = ROUNDTOTBLOCK(len); 6476 6477 if ((bufhead = calloc(1, totalen)) == NULL) { 6478 fatal(gettext("Out of memory.")); 6479 } 6480 6481 6482 /* 6483 * Now we can fill in the necessary pieces 6484 */ 6485 6486 if (linkinfo != (struct linkbuf *)NULL) { 6487 linklen = linkstringlen + (sizeof (struct xattr_buf)); 6488 } else { 6489 linklen = 0; 6490 } 6491 6492 /* 6493 * first fill in the fixed header 6494 */ 6495 hptr = (struct xattr_hdr *)bufhead; 6496 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 6497 (void) sprintf(hptr->h_component_len, "%0*d", 6498 sizeof (hptr->h_component_len) - 1, complen); 6499 (void) sprintf(hptr->h_link_component_len, "%0*d", 6500 sizeof (hptr->h_link_component_len) - 1, linklen); 6501 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 6502 6503 /* 6504 * Now fill in the filename + attrnames section 6505 */ 6506 6507 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 6508 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 6509 stringlen); 6510 (void) strcpy(tptr->h_names, filename); 6511 (void) strcpy(&tptr->h_names[strlen(filename) + 1], attrname); 6512 tptr->h_typeflag = typeflag; 6513 6514 /* 6515 * Now fill in the optional link section if we have one 6516 */ 6517 6518 if (linkinfo != (struct linkbuf *)NULL) { 6519 tptr = (struct xattr_buf *)(bufhead + 6520 sizeof (struct xattr_hdr) + complen); 6521 6522 (void) sprintf(tptr->h_namesz, "%0*d", 6523 sizeof (tptr->h_namesz) - 1, linkstringlen); 6524 (void) strcpy(tptr->h_names, linkinfo->pathname); 6525 (void) strcpy( 6526 &tptr->h_names[strlen(linkinfo->pathname) + 1], 6527 linkinfo->attrname); 6528 tptr->h_typeflag = typeflag; 6529 } 6530 *attrbuf = (char *)bufhead; 6531 *rlen = len; 6532 } 6533 6534 #else 6535 static void 6536 prepare_xattr( 6537 char **attrbuf, 6538 char *filename, 6539 char *attrname, 6540 char typeflag, 6541 struct linkbuf *linkinfo, 6542 int *rlen) 6543 { 6544 *attrbuf = NULL; 6545 *rlen = 0; 6546 } 6547 #endif 6548 6549 int 6550 getstat(int dirfd, char *longname, char *shortname) 6551 { 6552 6553 int i, j; 6554 int printerr; 6555 int slnkerr; 6556 struct stat symlnbuf; 6557 6558 if (!hflag) 6559 i = fstatat(dirfd, shortname, &stbuf, AT_SYMLINK_NOFOLLOW); 6560 else 6561 i = fstatat(dirfd, shortname, &stbuf, 0); 6562 6563 if (i < 0) { 6564 /* Initialize flag to print error mesg. */ 6565 printerr = 1; 6566 /* 6567 * If stat is done, then need to do lstat 6568 * to determine whether it's a sym link 6569 */ 6570 if (hflag) { 6571 /* Save returned error */ 6572 slnkerr = errno; 6573 6574 j = fstatat(dirfd, shortname, 6575 &symlnbuf, AT_SYMLINK_NOFOLLOW); 6576 /* 6577 * Suppress error message when file is a symbolic link 6578 * and function modifier 'l' is off. Exception: when 6579 * a symlink points to a symlink points to a 6580 * symlink ... and we get past MAXSYMLINKS. That 6581 * error will cause a file not to be archived, and 6582 * needs to be printed. 6583 */ 6584 if ((j == 0) && (!linkerrok) && (slnkerr != ELOOP) && 6585 (S_ISLNK(symlnbuf.st_mode))) 6586 printerr = 0; 6587 6588 /* 6589 * Restore errno in case the lstat 6590 * on symbolic link change 6591 */ 6592 errno = slnkerr; 6593 } 6594 6595 if (printerr) { 6596 (void) fprintf(stderr, gettext( 6597 "tar: %s: %s\n"), longname, strerror(errno)); 6598 Errflg = 1; 6599 } 6600 return (1); 6601 } 6602 return (0); 6603 } 6604 6605 #if defined(O_XATTR) 6606 static void 6607 xattrs_put(char *longname, char *shortname, char *parent) 6608 { 6609 int dirfd; 6610 DIR *dirp; 6611 struct dirent *dp; 6612 6613 if (pathconf(shortname, _PC_XATTR_EXISTS) != 1) { 6614 return; 6615 } 6616 6617 if ((dirfd = attropen(shortname, ".", O_RDONLY)) < 0) { 6618 (void) fprintf(stderr, gettext( 6619 "tar: unable to open attribute directory for file %s\n"), 6620 longname); 6621 return; 6622 } 6623 6624 if ((dirp = fdopendir(dirfd)) == NULL) { 6625 (void) fprintf(stderr, gettext( 6626 "tar: unable to open dir pointer for file %s\n"), longname); 6627 return; 6628 } 6629 6630 while (dp = readdir(dirp)) { 6631 if (dp->d_name[0] == '.' && dp->d_name[1] == '.' && 6632 dp->d_name[2] == '\0') 6633 continue; 6634 6635 if (dp->d_name[0] == '.' && dp->d_name[1] == '\0') 6636 Hiddendir = 1; 6637 else 6638 Hiddendir = 0; 6639 6640 (void) putfile(longname, dp->d_name, parent, 6641 XATTR_FILE, LEV0, SYMLINK_LEV0); 6642 6643 if (exitflag) 6644 break; 6645 } 6646 6647 (void) closedir(dirp); 6648 } 6649 #else 6650 static void 6651 xattrs_put(char *longname, char *shortname, char *parent) 6652 { 6653 } 6654 #endif /* O_XATTR */ 6655 6656 static int 6657 put_link(char *name, char *longname, char *component, 6658 char *prefix, int filetype, char type) 6659 { 6660 6661 if (stbuf.st_nlink > 1) { 6662 struct linkbuf *lp; 6663 int found = 0; 6664 6665 for (lp = ihead; lp != NULL; lp = lp->nextp) 6666 if (lp->inum == stbuf.st_ino && 6667 lp->devnum == stbuf.st_dev) { 6668 found++; 6669 break; 6670 } 6671 if (found) { 6672 #if defined(O_XATTR) 6673 if (filetype == XATTR_FILE) 6674 if (put_xattr_hdr(longname, component, prefix, 6675 type, filetype, lp)) { 6676 goto out; 6677 } 6678 #endif 6679 stbuf.st_size = (off_t)0; 6680 if (filetype != XATTR_FILE) { 6681 tomodes(&stbuf); 6682 if (chk_path_build(name, longname, lp->pathname, 6683 prefix, type, filetype) > 0) { 6684 goto out; 6685 } 6686 } 6687 6688 if (mulvol && tapepos + 1 >= blocklim) 6689 newvol(); 6690 (void) writetbuf((char *)&dblock, 1); 6691 /* 6692 * write_ancillary() is not needed here. 6693 * The first link is handled in the following 6694 * else statement. No need to process ACLs 6695 * for other hard links since they are the 6696 * same file. 6697 */ 6698 6699 if (vflag) { 6700 #ifdef DEBUG 6701 if (NotTape) 6702 DEBUG("seek = %" FMT_blkcnt_t 6703 "K\t", K(tapepos), 0); 6704 #endif 6705 if (filetype == XATTR_FILE) { 6706 (void) fprintf(vfile, gettext( 6707 "a %s attribute %s link to " 6708 "attribute %s\n"), 6709 name, component, lp->attrname); 6710 } else { 6711 (void) fprintf(vfile, gettext( 6712 "a %s link to %s\n"), 6713 longname, lp->pathname); 6714 } 6715 } 6716 lp->count--; 6717 return (0); 6718 } else { 6719 lp = (struct linkbuf *)getmem(sizeof (*lp)); 6720 if (lp != (struct linkbuf *)NULL) { 6721 lp->nextp = ihead; 6722 ihead = lp; 6723 lp->inum = stbuf.st_ino; 6724 lp->devnum = stbuf.st_dev; 6725 lp->count = stbuf.st_nlink - 1; 6726 if (filetype == XATTR_FILE) { 6727 (void) strcpy(lp->pathname, longname); 6728 (void) strcpy(lp->attrname, component); 6729 } else { 6730 (void) strcpy(lp->pathname, longname); 6731 (void) strcpy(lp->attrname, ""); 6732 } 6733 } 6734 } 6735 } 6736 6737 out: 6738 return (1); 6739 } 6740 6741 static int 6742 put_extra_attributes(char *longname, char *shortname, char *prefix, 6743 int filetype, char typeflag) 6744 { 6745 static acl_t *aclp = NULL; 6746 int error; 6747 6748 if (aclp != NULL) { 6749 acl_free(aclp); 6750 aclp = NULL; 6751 } 6752 #if defined(O_XATTR) 6753 if (atflag && filetype == XATTR_FILE) { 6754 if (put_xattr_hdr(longname, shortname, prefix, 6755 typeflag, filetype, NULL)) { 6756 return (1); 6757 } 6758 } 6759 #endif 6760 6761 /* ACL support */ 6762 if (pflag) { 6763 char *secinfo = NULL; 6764 int len = 0; 6765 6766 /* ACL support */ 6767 if (((stbuf.st_mode & S_IFMT) != S_IFLNK)) { 6768 /* 6769 * Get ACL info: dont bother allocating space if 6770 * there is only a trivial ACL. 6771 */ 6772 if ((error = acl_get(shortname, ACL_NO_TRIVIAL, 6773 &aclp)) != 0) { 6774 (void) fprintf(stderr, gettext( 6775 "%s: failed to retrieve acl : %s\n"), 6776 longname, acl_strerror(error)); 6777 return (1); 6778 } 6779 } 6780 6781 /* append security attributes if any */ 6782 if (aclp != NULL) { 6783 (void) append_secattr(&secinfo, &len, aclp); 6784 (void) write_ancillary(&dblock, secinfo, len, ACL_HDR); 6785 } 6786 } 6787 return (0); 6788 } 6789 6790 #if defined(O_XATTR) 6791 static int 6792 put_xattr_hdr(char *longname, char *shortname, char *prefix, 6793 int typeflag, int filetype, struct linkbuf *lp) 6794 { 6795 char *lname = NULL; 6796 char *sname = NULL; 6797 int error = 0; 6798 static char *attrbuf = NULL; 6799 int attrlen; 6800 6801 lname = malloc(sizeof (char) * strlen("/dev/null") + 1 + 6802 strlen(shortname) + strlen(".hdr") + 1); 6803 6804 if (lname == NULL) { 6805 fatal(gettext("Out of Memory.")); 6806 } 6807 sname = malloc(sizeof (char) * strlen(shortname) + 6808 strlen(".hdr")); 6809 if (sname == NULL) { 6810 fatal(gettext("Out of Memory.")); 6811 } 6812 6813 (void) sprintf(sname, "%s.hdr", shortname); 6814 (void) sprintf(lname, "/dev/null/%s", sname); 6815 6816 if (strlcpy(dblock.dbuf.name, lname, sizeof (dblock.dbuf.name)) >= 6817 sizeof (dblock.dbuf.name)) { 6818 fatal(gettext( 6819 "Buffer overflow writing extended attribute file name")); 6820 } 6821 6822 /* 6823 * dump extended attr lookup info 6824 */ 6825 prepare_xattr(&attrbuf, longname, shortname, typeflag, lp, &attrlen); 6826 write_ancillary(&dblock, attrbuf, attrlen, _XATTR_HDRTYPE); 6827 6828 (void) sprintf(lname, "/dev/null/%s", shortname); 6829 (void) strncpy(dblock.dbuf.name, sname, NAMSIZ); 6830 6831 /* 6832 * Set up filename for attribute 6833 */ 6834 6835 error = build_dblock(lname, tchar, '0', filetype, 6836 &stbuf, stbuf.st_dev, prefix); 6837 free(lname); 6838 free(sname); 6839 6840 return (error); 6841 } 6842 #endif 6843 6844 #if defined(O_XATTR) 6845 static int 6846 read_xattr_hdr() 6847 { 6848 char buf[TBLOCK]; 6849 blkcnt_t blocks; 6850 char *tp; 6851 off_t bytes; 6852 int comp_len, link_len; 6853 int namelen; 6854 6855 6856 if (dblock.dbuf.typeflag != _XATTR_HDRTYPE) 6857 return (1); 6858 6859 bytes = stbuf.st_size; 6860 if ((xattrhead = calloc(1, (int)bytes)) == NULL) { 6861 (void) fprintf(stderr, gettext( 6862 "Insufficient memory for extended attribute\n")); 6863 return (1); 6864 } 6865 6866 tp = (char *)xattrhead; 6867 blocks = TBLOCKS(bytes); 6868 while (blocks-- > 0) { 6869 readtape(buf); 6870 if (bytes <= TBLOCK) { 6871 (void) memcpy(tp, buf, (size_t)bytes); 6872 break; 6873 } else { 6874 (void) memcpy(tp, buf, TBLOCK); 6875 tp += TBLOCK; 6876 } 6877 bytes -= TBLOCK; 6878 } 6879 6880 /* 6881 * Validate that we can handle header format 6882 */ 6883 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 6884 (void) fprintf(stderr, 6885 gettext("Unknown extended attribute format encountered\n")); 6886 (void) fprintf(stderr, 6887 gettext("Disabling extended attribute parsing\n")); 6888 xattrbadhead = 1; 6889 return (0); 6890 } 6891 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 6892 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 6893 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 6894 sizeof (struct xattr_hdr)); 6895 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 6896 if (link_len > 0) 6897 xattr_linkp = (struct xattr_buf *) 6898 ((int)xattrp + (int)comp_len); 6899 else 6900 xattr_linkp = NULL; 6901 6902 xattraname = xattrp->h_names + strlen(xattrp->h_names) + 1; 6903 if (xattr_linkp) { 6904 xattr_linkaname = xattr_linkp->h_names + 6905 strlen(xattr_linkp->h_names) + 1; 6906 } else { 6907 xattr_linkaname = NULL; 6908 } 6909 6910 return (0); 6911 } 6912 #else 6913 static int 6914 read_xattr_hdr() 6915 { 6916 return (0); 6917 } 6918 #endif 6919 6920 /* 6921 * skip over extra slashes in string. 6922 * 6923 * For example: 6924 * /usr/tmp///// 6925 * 6926 * would return pointer at 6927 * /usr/tmp///// 6928 * ^ 6929 */ 6930 static char * 6931 skipslashes(char *string, char *start) 6932 { 6933 while ((string > start) && *(string - 1) == '/') { 6934 string--; 6935 } 6936 6937 return (string); 6938 } 6939 6940 /* 6941 * Return the parent directory of a given path. 6942 * 6943 * Examples: 6944 * /usr/tmp return /usr 6945 * /usr/tmp/file return /usr/tmp 6946 * / returns . 6947 * /usr returns / 6948 * file returns . 6949 * 6950 * dir is assumed to be at least as big as path. 6951 */ 6952 static void 6953 get_parent(char *path, char *dir) 6954 { 6955 char *s; 6956 char tmpdir[PATH_MAX + 1]; 6957 6958 if (strlen(path) > PATH_MAX) { 6959 fatal(gettext("pathname is too long")); 6960 } 6961 (void) strcpy(tmpdir, path); 6962 chop_endslashes(tmpdir); 6963 6964 if ((s = strrchr(tmpdir, '/')) == NULL) { 6965 (void) strcpy(dir, "."); 6966 } else { 6967 s = skipslashes(s, tmpdir); 6968 *s = '\0'; 6969 if (s == tmpdir) 6970 (void) strcpy(dir, "/"); 6971 else 6972 (void) strcpy(dir, tmpdir); 6973 } 6974 } 6975 6976 #if defined(O_XATTR) 6977 static char * 6978 get_component(char *path) 6979 { 6980 char *ptr; 6981 6982 ptr = strrchr(path, '/'); 6983 if (ptr == NULL) { 6984 return (path); 6985 } else { 6986 /* 6987 * Handle trailing slash 6988 */ 6989 if (*(ptr + 1) == '\0') 6990 return (ptr); 6991 else 6992 return (ptr + 1); 6993 } 6994 } 6995 #else 6996 static char * 6997 get_component(char *path) 6998 { 6999 return (path); 7000 } 7001 #endif 7002 7003 static int 7004 retry_attrdir_open(char *name) 7005 { 7006 int dirfd = -1; 7007 struct timeval times[2]; 7008 mode_t newmode; 7009 struct stat parentstat; 7010 acl_t *aclp = NULL; 7011 int error; 7012 7013 /* 7014 * We couldn't get to attrdir. See if its 7015 * just a mode problem on the parent file. 7016 * for example: a mode such as r-xr--r-- 7017 * won't let us create an attribute dir 7018 * if it doesn't already exist. 7019 * 7020 * If file has a non-trivial ACL, then save it 7021 * off so that we can place it back on after doing 7022 * chmod's. 7023 */ 7024 7025 if (stat(name, &parentstat) == -1) { 7026 (void) fprintf(stderr, gettext("tar: cannot stat file %s %s\n"), 7027 name, strerror(errno)); 7028 return (-1); 7029 } 7030 if ((error = acl_get(name, ACL_NO_TRIVIAL, &aclp)) != 0) { 7031 (void) fprintf(stderr, gettext("tar: failed to retrieve ACL on" 7032 " %s %s\n"), name, strerror(errno)); 7033 return (-1); 7034 } 7035 7036 newmode = S_IWUSR | parentstat.st_mode; 7037 if (chmod(name, newmode) == -1) { 7038 (void) fprintf(stderr, 7039 gettext("tar: cannot chmod file %s to %o %s\n"), 7040 name, newmode, strerror(errno)); 7041 if (aclp) 7042 acl_free(aclp); 7043 return (-1); 7044 } 7045 7046 dirfd = attropen(name, ".", O_RDONLY); 7047 7048 /* 7049 * Don't print error message if attropen() failed, 7050 * caller will print message. 7051 */ 7052 7053 /* 7054 * Put mode back to original 7055 */ 7056 if (chmod(name, parentstat.st_mode) == -1) { 7057 (void) fprintf(stderr, 7058 gettext("tar: cannot chmod file %s to %o %s\n"), 7059 name, newmode, strerror(errno)); 7060 } 7061 7062 if (aclp) { 7063 error = acl_set(name, aclp); 7064 if (error) { 7065 (void) fprintf(stderr, 7066 gettext("tar: %s: failed to set acl entries\n"), 7067 name); 7068 } 7069 acl_free(aclp); 7070 } 7071 7072 /* 7073 * Put back time stamps 7074 */ 7075 7076 times[0].tv_sec = parentstat.st_atime; 7077 times[0].tv_usec = 0; 7078 times[1].tv_sec = parentstat.st_mtime; 7079 times[1].tv_usec = 0; 7080 (void) utimes(name, times); 7081 7082 return (dirfd); 7083 } 7084 7085 #if !defined(O_XATTR) 7086 static int 7087 openat64(int fd, const char *name, int oflag, mode_t cmode) 7088 { 7089 return (open64(name, oflag, cmode)); 7090 } 7091 7092 static int 7093 openat(int fd, const char *name, int oflag, mode_t cmode) 7094 { 7095 return (open(name, oflag, cmode)); 7096 } 7097 7098 static int 7099 fchownat(int fd, const char *name, uid_t owner, gid_t group, int flag) 7100 { 7101 if (flag == AT_SYMLINK_NOFOLLOW) 7102 return (lchown(name, owner, group)); 7103 else 7104 return (chown(name, owner, group)); 7105 } 7106 7107 static int 7108 renameat(int fromfd, char *old, int tofd, char *new) 7109 { 7110 return (rename(old, new)); 7111 } 7112 7113 static int 7114 futimesat(int fd, char *path, struct timeval times[2]) 7115 { 7116 return (utimes(path, times)); 7117 } 7118 7119 static int 7120 unlinkat(int dirfd, char *path, int flag) 7121 { 7122 if (flag == AT_REMOVEDIR) 7123 return (rmdir(path)); 7124 else 7125 return (unlink(path)); 7126 } 7127 7128 static int 7129 fstatat(int fd, char *path, struct stat *buf, int flag) 7130 { 7131 if (flag == AT_SYMLINK_NOFOLLOW) 7132 return (lstat(path, buf)); 7133 else 7134 return (stat(path, buf)); 7135 } 7136 7137 static int 7138 attropen(char *file, char *attr, int omode, mode_t cmode) 7139 { 7140 errno = ENOTSUP; 7141 return (-1); 7142 } 7143 #endif 7144 7145 static void 7146 chop_endslashes(char *path) 7147 { 7148 char *end, *ptr; 7149 7150 /* 7151 * Chop of slashes, but not if all we have is slashes 7152 * for example: //// 7153 * should make no changes, otherwise it will screw up 7154 * checkdir 7155 */ 7156 end = &path[strlen(path) -1]; 7157 if (*end == '/' && end != path) { 7158 ptr = skipslashes(end, path); 7159 if (ptr != NULL && ptr != path) { 7160 *ptr = '\0'; 7161 } 7162 } 7163 } 7164