1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 #include <stdio.h> 38 #include <sys/types.h> 39 #include <errno.h> 40 #include <unistd.h> 41 #include <stdlib.h> 42 #include <fcntl.h> 43 #include <memory.h> 44 #include <string.h> 45 #include <stdarg.h> 46 #include <sys/stat.h> 47 #include <sys/statvfs.h> 48 #include <sys/mkdev.h> 49 #include <sys/param.h> 50 #include <utime.h> 51 #include <pwd.h> 52 #include <grp.h> 53 #include <signal.h> 54 #include <ctype.h> 55 #include <archives.h> 56 #include <locale.h> 57 #include <sys/ioctl.h> 58 #include <sys/mtio.h> 59 #include <sys/fdio.h> 60 #include "cpio.h" 61 #include <sys/acl.h> 62 #include <sys/time.h> 63 #include <sys/resource.h> 64 #include <fnmatch.h> 65 #include <libgen.h> 66 #include <libintl.h> 67 #include <dirent.h> 68 #include <limits.h> 69 70 /* 71 * Special kludge for off_t being a signed quantity. 72 */ 73 #if _FILE_OFFSET_BITS == 64 74 typedef u_longlong_t u_off_t; 75 #else 76 typedef ulong_t u_off_t; 77 #endif 78 79 #define SECMODE 0xe080 80 81 #define DEVNULL "/dev/null" 82 #define XATTRHDR ".hdr" 83 84 #define NAMELEN 32 85 #define TYPELEN 16 86 #define PERMLEN 4 87 88 #define FILE_COPIED 1 89 #define FILE_LINKED 2 90 #define FILE_PASS_ERR -1 91 92 #define ARCHIVE_NORMAL 0 93 #define ARCHIVE_ACL 1 94 #define ARCHIVE_XATTR 2 95 96 #define LSTAT(dir, path, statbuf) fstatat(dir, \ 97 get_component((Gen.g_attrnam_p == (char *)NULL) ? \ 98 path : Gen.g_attrnam_p), statbuf, AT_SYMLINK_NOFOLLOW) 99 #define STAT(dir, path, statbuf) fstatat(dir, \ 100 get_component((Gen.g_attrnam_p == (char *)NULL) ? \ 101 path : Gen.g_attrnam_p), statbuf, 0) 102 103 /* 104 * These limits reflect the maximum size regular file that 105 * can be archived, depending on the archive type. For archives 106 * with character-format headers (odc, tar, ustar) we use 107 * CHAR_OFFSET_MAX. Otherwise, we are limited to the size 108 * that will fit in a signed long value. 109 */ 110 #define CHAR_OFFSET_MAX 077777777777 /* 11 octal digits */ 111 #define BIN_OFFSET_MAX LONG_MAX /* signed long max value */ 112 113 static char aclchar = ' '; 114 115 static struct Lnk *add_lnk(struct Lnk **); 116 static int bfill(void); 117 static void bflush(void); 118 static int chgreel(int dir); 119 static int ckname(int); 120 static void ckopts(long mask); 121 static long cksum(char hdr, int byt_cnt, int *err); 122 static int creat_hdr(void); 123 static int creat_lnk(int dirfd, char *name1_p, char *name2_p); 124 static int creat_spec(int dirfd); 125 static int creat_tmp(char *nam_p); 126 static void data_in(int proc_mode); 127 static void data_out(void); 128 static void data_pass(void); 129 static void file_in(void); 130 static int file_out(void); 131 static int file_pass(void); 132 static void flush_lnks(void); 133 static int gethdr(void); 134 static int getname(void); 135 static void getpats(int largc, char **largv); 136 static void ioerror(int dir); 137 static int matched(void); 138 static int missdir(char *nam_p); 139 static long mklong(short v[]); 140 static void mkshort(short sval[], long v); 141 static void msg(int severity, const char *fmt, ...); 142 static int openout(int dirfd); 143 static int read_hdr(int hdr); 144 static void reclaim(struct Lnk *l_p); 145 static void rstbuf(void); 146 static void setpasswd(char *nam); 147 static void rstfiles(int over, int dirfd); 148 static void scan4trail(void); 149 static void setup(int largc, char **largv); 150 static void set_tym(int dirfd, char *nam_p, time_t atime, time_t mtime); 151 static void sigint(int sig); 152 static void swap(char *buf_p, int cnt); 153 static void usage(void); 154 static void verbose(char *nam_p); 155 static void write_hdr(int secflag, off_t len); 156 static void write_trail(void); 157 static int ustar_dir(void); 158 static int ustar_spec(void); 159 static struct stat *convert_to_old_stat(struct stat *, char *, char *); 160 static void read_bar_vol_hdr(void); 161 static void read_bar_file_hdr(void); 162 static void setup_uncompress(FILE **); 163 static void skip_bar_volhdr(void); 164 static void bar_file_in(void); 165 static int g_init(int *devtype, int *fdes); 166 static int g_read(int, int, char *, unsigned); 167 static int g_write(int, int, char *, unsigned); 168 static int is_floppy(int); 169 static int is_tape(int); 170 static int append_secattr(char **, int *, int, char *, char); 171 static void write_ancillary(char *secinfo, int len); 172 static int remove_dir(char *); 173 static int save_cwd(void); 174 static void rest_cwd(int cwd); 175 176 static void xattrs_out(int (*func)()); 177 static void get_parent(char *path, char *dir); 178 static void prepare_xattr_hdr(char **attrbuf, char *filename, 179 char *attrname, char typeflag, struct Lnk *linkinfo, int *rlen); 180 static char tartype(int type); 181 static int openfile(int omode); 182 static mode_t attrmode(char type); 183 static char *get_component(char *path); 184 static int open_dir(char *name); 185 static int open_dirfd(); 186 static void close_dirfd(); 187 static void write_xattr_hdr(); 188 static int retry_attrdir_open(char *name); 189 static char *skipslashes(char *string, char *start); 190 static int read_xattr_hdr(); 191 static void chop_endslashes(char *path); 192 193 194 /* helpful types */ 195 196 static 197 struct passwd *Curpw_p, /* Current password entry for -t option */ 198 *Rpw_p, /* Password entry for -R option */ 199 *dpasswd; 200 201 static 202 struct group *Curgr_p, /* Current group entry for -t option */ 203 *dgroup; 204 205 /* Data structure for buffered I/O. */ 206 207 static 208 struct buf_info { 209 char *b_base_p, /* Pointer to base of buffer */ 210 *b_out_p, /* Position to take bytes from buffer at */ 211 *b_in_p, /* Position to put bytes into buffer at */ 212 *b_end_p; /* Pointer to end of buffer */ 213 long b_cnt, /* Count of unprocessed bytes */ 214 b_size; /* Size of buffer in bytes */ 215 } Buffr; 216 217 /* Generic header format */ 218 219 static 220 struct gen_hdr { 221 ulong_t g_magic, /* Magic number field */ 222 g_ino, /* Inode number of file */ 223 g_mode, /* Mode of file */ 224 g_uid, /* Uid of file */ 225 g_gid, /* Gid of file */ 226 g_nlink, /* Number of links */ 227 g_mtime; /* Modification time */ 228 off_t g_filesz; /* Length of file */ 229 ulong_t g_dev, /* File system of file */ 230 g_rdev, /* Major/minor numbers of special files */ 231 g_namesz, /* Length of filename */ 232 g_cksum; /* Checksum of file */ 233 char g_gname[32], 234 g_uname[32], 235 g_version[2], 236 g_tmagic[6], 237 g_typeflag; 238 char *g_tname, 239 *g_prefix, 240 *g_nam_p, /* Filename */ 241 *g_attrnam_p, /* attribute */ 242 *g_attrfnam_p, /* Real file name attr belongs to */ 243 *g_linktoattrfnam_p, /* file linked attribute belongs to */ 244 *g_linktoattrnam_p, /* attribute g_attrnam_p is linked to */ 245 *g_dirpath; /* dirname currently opened */ 246 int g_dirfd; /* directory file descriptor */ 247 int g_passdirfd; /* directory fd to pass to */ 248 249 } Gen, *G_p; 250 251 /* Data structure for handling multiply-linked files */ 252 static 253 char prebuf[PRESIZ+1], 254 nambuf[NAMSIZ+1], 255 fullnam[MAXNAM+1]; 256 257 258 static 259 struct Lnk { 260 short L_cnt, /* Number of links encountered */ 261 L_data; /* Data has been encountered if 1 */ 262 struct gen_hdr L_gen; /* gen_hdr information for this file */ 263 struct Lnk *L_nxt_p, /* Next file in list */ 264 *L_bck_p, /* Previous file in list */ 265 *L_lnk_p; /* Next link for this file */ 266 } Lnk_hd; 267 268 static 269 struct hdr_cpio Hdr; 270 271 /* 272 * ------------------------------------------------------------------------- 273 * Stuff needed to pre-view the name stream 274 * 275 * issymlink is used to remember that the current file is a symlink between 276 * getname() and file_pass(); the former trashes this information immediately 277 * when -L is specified. 278 */ 279 280 static 281 int issymlink = 0; 282 283 static 284 FILE *In_p = stdin; /* Where the input comes from */ 285 286 typedef struct sl_info 287 { 288 struct sl_info *llink; /* Left subtree ptr (tree depth in *sl_head) */ 289 struct sl_info *rlink; /* Right subtree ptr */ 290 int bal; /* Subtree balance factor */ 291 ulong_t sl_count; /* Number of symlinks */ 292 ino_t sl_ino; /* Inode of file */ 293 ino_t sl_ino2; /* alternate inode for -Hodc */ 294 } sl_info_t; 295 296 /* 297 * The following structure maintains a hash entry for the 298 * balancing trees which are allocated for each device nodes. 299 */ 300 typedef struct sl_info_link 301 { 302 dev_t dev; 303 sl_info_t *head; 304 struct sl_info_link *next; 305 } sl_info_link_t; 306 307 #define SL_INFO_ALLOC_CHUNK 1024 308 #define NDEVHENTRY 0x40 309 #define DEV_HASHKEY(x) ((x) & (NDEVHENTRY -1)) 310 311 /* 312 * For remapping dev,inode for -Hodc archives. 313 */ 314 315 typedef struct sl_remap 316 { 317 dev_t dev; /* device */ 318 int inode_count; /* # inodes seen on dev */ 319 struct sl_remap *next; /* next in the chain */ 320 } sl_remap_t; 321 322 /* forward declarations */ 323 324 static sl_info_t *sl_info_alloc(void); 325 static sl_info_t *sl_insert(dev_t, ino_t); 326 static ulong_t sl_numlinks(dev_t, ino_t); 327 static void sl_preview_synonyms(void); 328 static void sl_remember_tgt(const struct stat *, int); 329 static sl_info_t *sl_search(dev_t, ino_t); 330 static sl_info_t *sl_devhash_lookup(dev_t); 331 static void sl_devhash_insert(dev_t, sl_info_t *); 332 333 extern int sl_compare(ino_t, ino_t); 334 #define sl_compare(lino, rino) (lino < rino ? -1 : (lino > rino ? 1 : 0)) 335 336 /* global storage */ 337 338 static sl_remap_t *sl_remap_head = NULL; /* head of the inode-remap list */ 339 static sl_info_link_t *sl_devhash[NDEVHENTRY]; /* hash table */ 340 341 /* 342 * ------------------------------------------------------------------------- 343 */ 344 345 static 346 struct stat ArchSt, /* stat(2) information of the archive */ 347 SrcSt, /* stat(2) information of source file */ 348 DesSt, /* stat(2) of destination file */ 349 *OldSt = NULL; /* stat info converted to svr32 format */ 350 351 /* 352 * bin_mag: Used to validate a binary magic number, 353 * by combining to bytes into an unsigned short. 354 */ 355 356 static 357 union bin_mag { 358 unsigned char b_byte[2]; 359 ushort_t b_half; 360 } Binmag; 361 362 static 363 union tblock *Thdr_p; /* TAR header pointer */ 364 365 static union b_block *bar_Vhdr; 366 static struct gen_hdr Gen_bar_vol; 367 368 /* 369 * swpbuf: Used in swap() to swap bytes within a halfword, 370 * halfwords within a word, or to reverse the order of the 371 * bytes within a word. Also used in mklong() and mkshort(). 372 */ 373 374 static 375 union swpbuf { 376 unsigned char s_byte[4]; 377 ushort_t s_half[2]; 378 ulong_t s_word; 379 } *Swp_p; 380 381 static 382 char Adir, /* Flags object as a directory */ 383 Hiddendir, /* Processing hidden attribute directory */ 384 Aspec, /* Flags object as a special file */ 385 Do_rename, /* Indicates rename() is to be used */ 386 Time[50], /* Array to hold date and time */ 387 Ttyname[] = "/dev/tty", /* Controlling console */ 388 T_lname[MAXPATHLEN], /* Array to hold links name for tar */ 389 *Buf_p, /* Buffer for file system I/O */ 390 *Empty, /* Empty block for TARTYP headers */ 391 *Full_p, /* Pointer to full pathname */ 392 *Efil_p, /* -E pattern file string */ 393 *Eom_p = "Change to part %d and press RETURN key. [q] ", 394 *Fullnam_p, /* Full pathname */ 395 *Attrfile_p, /* attribute file */ 396 *Hdr_p, /* -H header type string */ 397 *IOfil_p, /* -I/-O input/output archive string */ 398 *Lnkend_p, /* Pointer to end of Lnknam_p */ 399 *Lnknam_p, /* Buffer for linking files with -p option */ 400 *Nam_p, /* Array to hold filename */ 401 *Savenam_p, /* copy of filename xattr belongs to */ 402 *Own_p, /* New owner login id string */ 403 *Renam_p, /* Buffer for renaming files */ 404 *Renametmp_p, /* Tmp Buffer for renaming files */ 405 *Symlnk_p, /* Buffer for holding symbolic link name */ 406 *Over_p, /* Holds temporary filename when overwriting */ 407 **Pat_pp = 0, /* Pattern strings */ 408 bar_linkflag, /* flag to indicate if the file is a link */ 409 bar_linkname[MAXPATHLEN]; /* store the name of the link */ 410 411 static 412 int Append = 0, /* Flag set while searching to end of archive */ 413 Archive, /* File descriptor of the archive */ 414 Buf_error = 0, /* I/O error occured during buffer fill */ 415 Def_mode = 0777, /* Default file/directory protection modes */ 416 Device, /* Device type being accessed (used with libgenIO) */ 417 Error_cnt = 0, /* Cumulative count of I/O errors */ 418 Finished = 1, /* Indicates that a file transfer has completed */ 419 Hdrsz = ASCSZ, /* Fixed length portion of the header */ 420 Hdr_type, /* Flag to indicate type of header selected */ 421 Ifile, /* File des. of file being archived */ 422 Ofile, /* File des. of file being extracted from archive */ 423 Use_old_stat = 0, /* Create an old style -Hodc hdr (small dev's) */ 424 Onecopy = 0, /* Flags old vs. new link handling */ 425 Pad_val = 0, /* Indicates the number of bytes to pad (if any) */ 426 PageSize = 0, /* The native page size, used for figuring block size */ 427 Volcnt = 1, /* Number of archive volumes processed */ 428 Verbcnt = 0, /* Count of number of dots '.' output */ 429 Eomflag = 0, 430 Dflag = 0, 431 Atflag = 0, /* Archive/restore extended attributes */ 432 Compressed, /* Flag to indicate if the bar archive is compressed */ 433 Bar_vol_num = 0; /* Volume number count for bar archive */ 434 435 436 static 437 gid_t Lastgid = -1; /* Used with -t & -v to record current gid */ 438 439 static 440 uid_t Lastuid = -1; /* Used with -t & -v to record current uid */ 441 442 static 443 long Args, /* Mask of selected options */ 444 Max_namesz = CPATH; /* Maximum size of pathnames/filenames */ 445 446 static 447 int Bufsize = BUFSZ; /* Default block size */ 448 449 450 static u_longlong_t Blocks; /* full blocks transferred */ 451 static u_longlong_t SBlocks; /* cumulative char count from short reads */ 452 453 454 static off_t Max_offset = BIN_OFFSET_MAX; /* largest file size */ 455 static off_t Max_filesz; /* from getrlimit */ 456 457 static 458 FILE *Ef_p, /* File pointer of pattern input file */ 459 *Err_p = stderr, /* File pointer for error reporting */ 460 *Out_p = stdout, /* File pointer for non-archive output */ 461 *Rtty_p, /* Input file pointer for interactive rename */ 462 *Wtty_p; /* Output file ptr for interactive rename */ 463 464 static 465 ushort_t Ftype = S_IFMT; /* File type mask */ 466 static 467 uid_t Euid; /* Effective uid of invoker */ 468 469 /* ACL support */ 470 static struct sec_attr { 471 char attr_type; 472 char attr_len[7]; 473 char attr_info[1]; 474 } *attr; 475 476 static int Pflag = 0; /* flag indicates that acl is preserved */ 477 static int aclcnt = 0; /* acl entry count */ 478 static aclent_t *aclp = NULL; /* pointer to ACL */ 479 static int acl_set = 0; /* True if an acl was set on the file */ 480 481 /* 482 * 483 * cpio has been changed to support extended attributes. 484 * 485 * As part of this change cpio has been changed to use the new *at() syscalls 486 * such as openat, fchownat(), unlinkat()... 487 * 488 * This was done so that attributes can be handled with as few code changes 489 * as possible. 490 * 491 * What this means is that cpio now opens the directory that a file or directory 492 * resides in and then performs *at() functions to manipulate the entry. 493 * 494 * For example a new file is now created like this: 495 * 496 * dfd = open(<some dir path>) 497 * fd = openat(dfd, <name>,....); 498 * 499 * or in the case of an extended attribute 500 * 501 * dfd = attropen(<pathname>, ".", ....) 502 * 503 * Once we have a directory file descriptor all of the *at() functions can 504 * be applied to it. 505 * 506 * unlinkat(dfd, <component name>,...) 507 * fchownat(dfd, <component name>,..) 508 * 509 * This works for both normal namespace files and extended attribute file 510 * 511 */ 512 513 /* 514 * Extended attribute layout 515 * 516 * Extended attributes are stored in two pieces. 517 * 1. An attribute header which has information about 518 * what file the attribute is for and what the attribute 519 * is named. 520 * 2. The attribute record itself. Stored as a normal file type 521 * of entry. 522 * Both the header and attribute record have special modes/typeflags 523 * associated with them. 524 * 525 * The names of the header in the archive look like: 526 * /dev/null/attr.hdr 527 * 528 * The name of the attribute looks like: 529 * /dev/null/attr. 530 * 531 * This is done so that an archiver that doesn't understand these formats 532 * can just dispose of the attribute records unless the user chooses to 533 * rename them via cpio -r or pax -i 534 * 535 * The format is composed of a fixed size header followed 536 * by a variable sized xattr_buf. If the attribute is a hard link 537 * to another attribute, then another xattr_buf section is included 538 * for the link. 539 * 540 * The xattr_buf is used to define the necessary "pathing" steps 541 * to get to the extended attribute. This is necessary to support 542 * a fully recursive attribute model where an attribute may itself 543 * have an attribute. 544 * 545 * The basic layout looks like this. 546 * 547 * -------------------------------- 548 * | | 549 * | xattr_hdr | 550 * | | 551 * -------------------------------- 552 * -------------------------------- 553 * | | 554 * | xattr_buf | 555 * | | 556 * -------------------------------- 557 * -------------------------------- 558 * | | 559 * | (optional link info) | 560 * | | 561 * -------------------------------- 562 * -------------------------------- 563 * | | 564 * | attribute itself | 565 * | stored as normal tar | 566 * | or cpio data with | 567 * | special mode or | 568 * | typeflag | 569 * | | 570 * -------------------------------- 571 * 572 */ 573 574 /* 575 * Extended attributes structures 576 * 577 * xattrhead is the complete extended attribute header, as read of off 578 * disk/tape. It includes the variable xattr_buf portion. 579 * 580 * xattrp is basically an offset into xattrhead that points to the 581 * "pathing" section which defines how to get to the attribute. 582 * 583 * xattr_linkp is identical to xattrp except that it is used for linked 584 * attributes. It provides the pathing steps to get to the linked 585 * attribute. 586 * 587 * These structures are updated when an extended attribute header is read off 588 * of disk/tape. 589 */ 590 static struct xattr_hdr *xattrhead; 591 static struct xattr_buf *xattrp; 592 static struct xattr_buf *xattr_linkp; 593 static int xattrbadhead; /* is extended attribute header bad? */ 594 595 static int append_secattr(char **, int *, int, char *, char); 596 static void write_ancillary(char *, int); 597 598 /* 599 * Note regarding cpio and changes to ensure cpio doesn't try to second 600 * guess whether it runs with sufficient privileges or not: 601 * 602 * cpio has been changed so that it doesn't carry a second implementation of 603 * the kernel's policy with respect to privileges. Instead of attempting 604 * to restore uid and gid from an archive only if cpio is run as uid 0, 605 * cpio now *always* tries to restore the uid and gid from the archive. 606 * If the restoration of the uid and gid are unsuccessful, then an error 607 * message will only be received if cpio is being run with root privileges, 608 * i.e., effective uid (euid) is 0, or if -R was specified. 609 * 610 * Note regarding debugging mechanism for cpio: 611 * 612 * The following mechanism is provided to allow us to debug cpio in complicated 613 * situations, like when it is part of a pipe. The idea is that you compile 614 * with -DWAITAROUND defined, and then add the "-z" command line option to the 615 * target cpio invocation. If stderr is available, it will tell you to which 616 * pid to attach the debugger; otherwise, use ps to find it. Attach to the 617 * process from the debugger, and, *PRESTO*, you are there! 618 * 619 * Simply assign "waitaround = 0" once you attach to the process, and then 620 * proceed from there as usual. 621 */ 622 623 #ifdef WAITAROUND 624 int waitaround = 0; /* wait for rendezvous with the debugger */ 625 #endif 626 627 /* 628 * Allocation wrappers and their flags 629 */ 630 #define E_NORMAL 0x0 /* Return NULL if allocation fails */ 631 #define E_EXIT 0x1 /* Exit if allocation fails */ 632 633 static void *e_realloc(int flag, void *old, size_t newsize); 634 static char *e_strdup(int flag, const char *arg); 635 static void *e_valloc(int flag, size_t size); 636 static void *e_zalloc(int flag, size_t size); 637 638 #define EXIT_CODE (Error_cnt > 255 ? 255 : Error_cnt) 639 640 /* 641 * main: Call setup() to process options and perform initializations, 642 * and then select either copy in (-i), copy out (-o), or pass (-p) action. 643 */ 644 645 main(int argc, char **argv) 646 { 647 int i; 648 int passret; 649 650 (void) setlocale(LC_ALL, ""); 651 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 652 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 653 #endif 654 (void) textdomain(TEXT_DOMAIN); 655 656 (void) memset(&Gen, 0, sizeof (Gen)); 657 setup(argc, argv); 658 659 if (signal(SIGINT, sigint) == SIG_IGN) 660 (void) signal(SIGINT, SIG_IGN); 661 switch (Args & (OCi | OCo | OCp)) { 662 case OCi: /* COPY IN */ 663 Hdr_type = NONE; 664 while ((i = gethdr()) != 0) { 665 Gen.g_dirfd = -1; 666 if (i == 1) { 667 file_in(); 668 /* 669 * Any ACL info for this file would or should 670 * have been used after file_in(); clear out 671 * aclp so it is is not erroneously used on 672 * the next file. 673 */ 674 if (aclp != NULL) { 675 free(aclp); 676 aclcnt = 0; 677 aclp = NULL; 678 } 679 acl_set = 0; 680 } 681 (void) memset(&Gen, 0, sizeof (Gen)); 682 } 683 /* Do not count "extra" "read-ahead" buffered data */ 684 if (Buffr.b_cnt > Bufsize) 685 Blocks -= (u_longlong_t)(Buffr.b_cnt / Bufsize); 686 break; 687 case OCo: /* COPY OUT */ 688 if (Args & OCA) { 689 scan4trail(); 690 } 691 692 Gen.g_dirfd = -1; 693 Gen.g_dirpath = NULL; 694 sl_preview_synonyms(); 695 696 while ((i = getname()) != 0) { 697 if (i == 1) { 698 (void) file_out(); 699 if (Atflag) { 700 if (Gen.g_dirfd != -1) { 701 (void) close(Gen.g_dirfd); 702 } 703 Gen.g_dirfd = -1; 704 xattrs_out(file_out); 705 } 706 Hiddendir = 0; 707 } 708 if (aclp != NULL) { 709 free(aclp); 710 aclcnt = 0; 711 aclp = NULL; 712 acl_set = 0; 713 } 714 } 715 write_trail(); 716 break; 717 case OCp: /* PASS */ 718 sl_preview_synonyms(); 719 720 Gen.g_dirfd = -1; 721 Gen.g_passdirfd = -1; 722 Gen.g_dirpath = NULL; 723 while (getname()) { 724 /* 725 * If file is a fully qualified path then 726 * file_pass will strip off the leading '/' 727 * and we need to save off the unstripped 728 * name for attribute traversal. 729 */ 730 if (Atflag) { 731 (void) strcpy(Savenam_p, Gen.g_nam_p); 732 } 733 passret = file_pass(); 734 if (aclp != NULL) { 735 free(aclp); 736 aclcnt = 0; 737 aclp = NULL; 738 acl_set = 0; 739 } 740 if (Gen.g_passdirfd != -1) 741 (void) close(Gen.g_passdirfd); 742 Gen.g_passdirfd = -1; 743 if (Atflag) { 744 if (Gen.g_dirfd != -1) { 745 (void) close(Gen.g_dirfd); 746 } 747 Gen.g_dirfd = -1; 748 if (passret != FILE_LINKED) { 749 Gen.g_nam_p = Savenam_p; 750 xattrs_out(file_pass); 751 } 752 } 753 } 754 break; 755 default: 756 msg(EXT, "Impossible action."); 757 } 758 if (Ofile > 0) { 759 if (close(Ofile) != 0) 760 msg(EXTN, "close error"); 761 } 762 if (Archive > 0) { 763 if (close(Archive) != 0) 764 msg(EXTN, "close error"); 765 } 766 Blocks = (u_longlong_t)(Blocks * Bufsize + SBlocks + 0x1FF) >> 9; 767 msg(EPOST, "%lld blocks", Blocks); 768 if (Error_cnt) 769 msg(EPOST, "%d error(s)", Error_cnt); 770 return (EXIT_CODE); 771 } 772 773 /* 774 * add_lnk: Add a linked file's header to the linked file data structure, by 775 * either adding it to the end of an existing sub-list or starting 776 * a new sub-list. Each sub-list saves the links to a given file. 777 * 778 * Directly returns a pointer to the new entry; returns a pointer to the head 779 * of the sub-list in which that entry is located through the argument. 780 */ 781 782 static struct Lnk * 783 add_lnk(struct Lnk **sublist_return) 784 { 785 struct Lnk *new_entry, *sublist; 786 787 for (sublist = Lnk_hd.L_nxt_p; 788 sublist != &Lnk_hd; 789 sublist = sublist->L_nxt_p) { 790 if (sublist->L_gen.g_ino == G_p->g_ino && 791 sublist->L_gen.g_dev == G_p->g_dev) { 792 /* found */ 793 break; 794 } 795 } 796 797 new_entry = e_zalloc(E_EXIT, sizeof (struct Lnk)); 798 799 new_entry->L_lnk_p = NULL; 800 new_entry->L_gen = *G_p; /* structure copy */ 801 802 new_entry->L_gen.g_nam_p = e_zalloc(E_EXIT, (size_t)G_p->g_namesz); 803 804 (void) strcpy(new_entry->L_gen.g_nam_p, G_p->g_nam_p); 805 806 if (sublist == &Lnk_hd) { 807 /* start new sub-list */ 808 new_entry->L_nxt_p = &Lnk_hd; 809 new_entry->L_bck_p = Lnk_hd.L_bck_p; 810 Lnk_hd.L_bck_p = new_entry->L_bck_p->L_nxt_p = new_entry; 811 new_entry->L_lnk_p = NULL; 812 new_entry->L_cnt = 1; 813 new_entry->L_data = Onecopy ? 0 : 1; 814 sublist = new_entry; 815 } else { 816 /* add to existing sub-list */ 817 struct Lnk *ptr; 818 819 sublist->L_cnt++; 820 821 for (ptr = sublist; 822 ptr->L_lnk_p != NULL; 823 ptr = ptr->L_lnk_p) { 824 ptr->L_gen.g_filesz = G_p->g_filesz; 825 } 826 827 ptr->L_gen.g_filesz = G_p->g_filesz; 828 ptr->L_lnk_p = new_entry; 829 } 830 831 *sublist_return = sublist; 832 return (new_entry); 833 } 834 835 /* 836 * bfill: Read req_cnt bytes (out of filelen bytes) from the I/O buffer, 837 * moving them to rd_buf_p. When there are no bytes left in the I/O buffer, 838 * Fillbuf is set and the I/O buffer is filled. The variable dist is the 839 * distance to lseek if an I/O error is encountered with the -k option set 840 * (converted to a multiple of Bufsize). 841 */ 842 843 static int 844 bfill(void) 845 { 846 int i = 0, rv; 847 static int eof = 0; 848 849 if (!Dflag) { 850 while ((Buffr.b_end_p - Buffr.b_in_p) >= Bufsize) { 851 errno = 0; 852 if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0) { 853 if (((Buffr.b_end_p - Buffr.b_in_p) >= Bufsize) && 854 (Eomflag == 0)) { 855 Eomflag = 1; 856 return (1); 857 } 858 if (errno == ENOSPC) { 859 (void) chgreel(INPUT); 860 if (Hdr_type == BAR) { 861 skip_bar_volhdr(); 862 } 863 continue; 864 } else if (Args & OCk) { 865 if (i++ > MX_SEEKS) 866 msg(EXT, "Cannot recover."); 867 if (lseek(Archive, Bufsize, SEEK_REL) < 0) 868 msg(EXTN, "Cannot lseek()"); 869 Error_cnt++; 870 Buf_error++; 871 rv = 0; 872 continue; 873 } else 874 ioerror(INPUT); 875 } /* (rv = g_read(Device, Archive ... */ 876 if (Hdr_type != BAR || rv == Bufsize) { 877 Buffr.b_in_p += rv; 878 Buffr.b_cnt += (long)rv; 879 } 880 if (rv == Bufsize) { 881 eof = 0; 882 Blocks++; 883 } else if (rv == 0) { 884 if (!eof) { 885 eof = 1; 886 break; 887 } 888 (void) chgreel(INPUT); 889 eof = 0; /* reset the eof after chgreel */ 890 891 /* 892 * if spans multiple volume, skip the volume header of 893 * the next volume so that the file currently being 894 * extracted can continue to be extracted. 895 */ 896 if (Hdr_type == BAR) { 897 skip_bar_volhdr(); 898 } 899 900 continue; 901 } else { 902 eof = 0; 903 SBlocks += (u_longlong_t)rv; 904 } 905 } /* (Buffr.b_end_p - Buffr.b_in_p) <= Bufsize */ 906 907 } else { /* Dflag */ 908 errno = 0; 909 if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0) { 910 return (-1); 911 } /* (rv = g_read(Device, Archive ... */ 912 Buffr.b_in_p += rv; 913 Buffr.b_cnt += (long)rv; 914 if (rv == Bufsize) { 915 eof = 0; 916 Blocks++; 917 } else if (!rv) { 918 if (!eof) { 919 eof = 1; 920 return (rv); 921 } 922 return (-1); 923 } else { 924 eof = 0; 925 SBlocks += (u_longlong_t)rv; 926 } 927 } 928 return (rv); 929 } 930 931 /* 932 * bflush: Move wr_cnt bytes from data_p into the I/O buffer. When the 933 * I/O buffer is full, Flushbuf is set and the buffer is written out. 934 */ 935 936 static void 937 bflush(void) 938 { 939 int rv; 940 941 while (Buffr.b_cnt >= Bufsize) { 942 errno = 0; 943 if ((rv = g_write(Device, Archive, Buffr.b_out_p, 944 Bufsize)) < 0) { 945 if (errno == ENOSPC && !Dflag) 946 rv = chgreel(OUTPUT); 947 else 948 ioerror(OUTPUT); 949 } 950 Buffr.b_out_p += rv; 951 Buffr.b_cnt -= (long)rv; 952 if (rv == Bufsize) 953 Blocks++; 954 else if (rv > 0) 955 SBlocks += (u_longlong_t)rv; 956 } 957 rstbuf(); 958 } 959 960 /* 961 * chgreel: Determine if end-of-medium has been reached. If it has, 962 * close the current medium and prompt the user for the next medium. 963 */ 964 965 static int 966 chgreel(int dir) 967 { 968 int lastchar, tryagain, askagain, rv; 969 int tmpdev; 970 char str[APATH]; 971 struct stat statb; 972 973 rv = 0; 974 if (fstat(Archive, &statb) < 0) 975 msg(EXTN, "Error during stat() of archive"); 976 if ((statb.st_mode & S_IFMT) != S_IFCHR) { 977 if (dir == INPUT) { 978 msg(EXT, "%s%s\n", 979 "Can't read input: end of file encountered ", 980 "prior to expected end of archive."); 981 } 982 } 983 msg(EPOST, "\007End of medium on \"%s\".", dir ? "output" : "input"); 984 if (is_floppy(Archive)) 985 (void) ioctl(Archive, FDEJECT, NULL); 986 if ((close(Archive) != 0) && (dir == OUTPUT)) 987 msg(EXTN, "close error"); 988 Archive = 0; 989 Volcnt++; 990 for (;;) { 991 if (Rtty_p == (FILE *)NULL) 992 Rtty_p = fopen(Ttyname, "r"); 993 do { /* tryagain */ 994 if (IOfil_p) { 995 do { 996 msg(EPOST, gettext(Eom_p), Volcnt); 997 if (!Rtty_p || fgets(str, sizeof (str), 998 Rtty_p) == (char *)NULL) 999 msg(EXT, "Cannot read tty."); 1000 askagain = 0; 1001 switch (*str) { 1002 case '\n': 1003 (void) strcpy(str, IOfil_p); 1004 break; 1005 case 'q': 1006 exit(EXIT_CODE); 1007 default: 1008 askagain = 1; 1009 } 1010 } while (askagain); 1011 } else { 1012 1013 if (Hdr_type == BAR) 1014 Bar_vol_num++; 1015 1016 msg(EPOST, 1017 "To continue, type device/file name when " 1018 "ready."); 1019 if (!Rtty_p || fgets(str, sizeof (str), 1020 Rtty_p) == (char *)NULL) 1021 msg(EXT, "Cannot read tty."); 1022 lastchar = strlen(str) - 1; 1023 if (*(str + lastchar) == '\n') /* remove '\n' */ 1024 *(str + lastchar) = '\0'; 1025 if (!*str) 1026 exit(EXIT_CODE); 1027 } 1028 tryagain = 0; 1029 if ((Archive = open(str, dir)) < 0) { 1030 msg(ERRN, "Cannot open \"%s\"", str); 1031 tryagain = 1; 1032 } 1033 } while (tryagain); 1034 (void) g_init(&tmpdev, &Archive); 1035 if (tmpdev != Device) 1036 msg(EXT, "Cannot change media types in mid-stream."); 1037 if (dir == INPUT) 1038 break; 1039 else { /* dir == OUTPUT */ 1040 errno = 0; 1041 if ((rv = g_write(Device, Archive, Buffr.b_out_p, 1042 Bufsize)) == Bufsize) 1043 break; 1044 else 1045 msg(ERR, 1046 "Unable to write this medium, try " 1047 "another."); 1048 } 1049 } /* ;; */ 1050 Eomflag = 0; 1051 return (rv); 1052 } 1053 1054 /* 1055 * ckname: Check filenames against user specified patterns, 1056 * and/or ask the user for new name when -r is used. 1057 */ 1058 1059 static int 1060 ckname(int flag) 1061 { 1062 int lastchar, len; 1063 1064 if (Hdr_type != TAR && Hdr_type != USTAR && Hdr_type != BAR) { 1065 /* Re-visit tar size issues later */ 1066 if (G_p->g_namesz - 1 > Max_namesz) { 1067 msg(ERR, "Name exceeds maximum length - skipped."); 1068 return (F_SKIP); 1069 } 1070 } 1071 1072 if (Pat_pp && !matched()) 1073 return (F_SKIP); 1074 if ((Args & OCr) && !Adir) { /* rename interactively */ 1075 (void) fprintf(Wtty_p, gettext("Rename \"%s%s%s\"? "), 1076 (G_p->g_attrnam_p == (char *)NULL) ? 1077 G_p->g_nam_p : Renam_p, 1078 (G_p->g_attrnam_p == (char *)NULL) ? 1079 "" : gettext(" Attribute "), 1080 (G_p->g_attrnam_p == (char *)NULL) ? 1081 "" : G_p->g_attrnam_p); 1082 (void) fflush(Wtty_p); 1083 if (fgets(Renametmp_p, Max_namesz + 1, Rtty_p) == (char *)NULL) 1084 msg(EXT, "Cannot read tty."); 1085 if (feof(Rtty_p)) 1086 exit(EXIT_CODE); 1087 lastchar = strlen(Renametmp_p) - 1; 1088 1089 /* remove trailing '\n' */ 1090 if (*(Renametmp_p + lastchar) == '\n') 1091 *(Renametmp_p + lastchar) = '\0'; 1092 if (*Renametmp_p == '\0') { 1093 msg(POST, "%s%s%s Skipped.", 1094 (G_p->g_attrnam_p == (char *)NULL) ? 1095 G_p->g_nam_p : G_p->g_attrfnam_p, 1096 (G_p->g_attrnam_p == (char *)NULL) ? 1097 "" : gettext(" Attribute "), 1098 (G_p->g_attrnam_p == (char *)NULL) ? 1099 "" : G_p->g_attrnam_p); 1100 *G_p->g_nam_p = '\0'; 1101 return (F_SKIP); 1102 } else if (strcmp(Renametmp_p, ".") != 0) { 1103 len = strlen(Renametmp_p); 1104 if (len > (int)strlen(G_p->g_nam_p)) { 1105 if ((G_p->g_nam_p != &nambuf[0]) && 1106 (G_p->g_nam_p != &fullnam[0])) 1107 free(G_p->g_nam_p); 1108 G_p->g_nam_p = e_zalloc(E_EXIT, len + 1); 1109 } 1110 if (G_p->g_attrnam_p != (char *)NULL) { 1111 free(G_p->g_attrnam_p); 1112 G_p->g_attrnam_p = e_strdup(E_EXIT, 1113 Renametmp_p); 1114 (void) strcpy(G_p->g_nam_p, Renam_p); 1115 } else { 1116 (void) strcpy(Renam_p, Renametmp_p); 1117 (void) strcpy(G_p->g_nam_p, Renametmp_p); 1118 } 1119 1120 } 1121 } 1122 if (flag != 0 || Onecopy == 0) { 1123 VERBOSE((Args & OCt), G_p->g_nam_p); 1124 } 1125 if (Args & OCt) 1126 return (F_SKIP); 1127 return (F_EXTR); 1128 } 1129 1130 /* 1131 * ckopts: Check the validity of all command line options. 1132 */ 1133 1134 static void 1135 ckopts(long mask) 1136 { 1137 int oflag; 1138 char *t_p; 1139 long errmsk; 1140 1141 if (mask & OCi) { 1142 errmsk = mask & INV_MSK4i; 1143 } else if (mask & OCo) { 1144 errmsk = mask & INV_MSK4o; 1145 } else if (mask & OCp) { 1146 errmsk = mask & INV_MSK4p; 1147 } else { 1148 msg(ERR, "One of -i, -o or -p must be specified."); 1149 errmsk = 0; 1150 } 1151 1152 if (errmsk) { 1153 /* if non-zero, invalid options were specified */ 1154 Error_cnt++; 1155 } 1156 1157 if ((mask & OCa) && (mask & OCm) && ((mask & OCi) || 1158 (mask & OCo))) { 1159 msg(ERR, "-a and -m are mutually exclusive."); 1160 } 1161 1162 if ((mask & OCc) && (mask & OCH) && (strcmp("odc", Hdr_p))) { 1163 msg(ERR, "-c and -H are mutually exclusive."); 1164 } 1165 1166 if ((mask & OCv) && (mask & OCV)) { 1167 msg(ERR, "-v and -V are mutually exclusive."); 1168 } 1169 1170 if ((mask & OCt) && (mask & OCV)) { 1171 msg(ERR, "-t and -V are mutually exclusive."); 1172 } 1173 1174 if ((mask & OCB) && (mask & OCC)) { 1175 msg(ERR, "-B and -C are mutually exclusive."); 1176 } 1177 1178 if ((mask & OCH) && (mask & OC6)) { 1179 msg(ERR, "-H and -6 are mutually exclusive."); 1180 } 1181 1182 if ((mask & OCM) && !((mask & OCI) || (mask & OCO))) { 1183 msg(ERR, "-M not meaningful without -O or -I."); 1184 } 1185 1186 if ((mask & OCA) && !(mask & OCO)) { 1187 msg(ERR, "-A requires the -O option."); 1188 } 1189 1190 if (Bufsize <= 0) { 1191 msg(ERR, "Illegal size given for -C option."); 1192 } 1193 1194 if (mask & OCH) { 1195 t_p = Hdr_p; 1196 1197 while (*t_p != NULL) { 1198 if (isupper(*t_p)) { 1199 *t_p = 'a' + (*t_p - 'A'); 1200 } 1201 1202 t_p++; 1203 } 1204 1205 if (!(strcmp("odc", Hdr_p))) { 1206 Hdr_type = CHR; 1207 Max_namesz = CPATH; 1208 Onecopy = 0; 1209 Use_old_stat = 1; 1210 } else if (!(strcmp("crc", Hdr_p))) { 1211 Hdr_type = CRC; 1212 Max_namesz = APATH; 1213 Onecopy = 1; 1214 } else if (!(strcmp("tar", Hdr_p))) { 1215 if (Args & OCo) { 1216 Hdr_type = USTAR; 1217 Max_namesz = HNAMLEN - 1; 1218 } else { 1219 Hdr_type = TAR; 1220 Max_namesz = TNAMLEN - 1; 1221 } 1222 Onecopy = 0; 1223 } else if (!(strcmp("ustar", Hdr_p))) { 1224 Hdr_type = USTAR; 1225 Max_namesz = HNAMLEN - 1; 1226 Onecopy = 0; 1227 } else if (!(strcmp("bar", Hdr_p))) { 1228 if ((Args & OCo) || (Args & OCp)) { 1229 msg(ERR, 1230 "Header type bar can only be used with -i"); 1231 } 1232 1233 if (Args & OCP) { 1234 msg(ERR, 1235 "Can't preserve using bar header"); 1236 } 1237 1238 Hdr_type = BAR; 1239 Max_namesz = TNAMLEN - 1; 1240 Onecopy = 0; 1241 } else { 1242 msg(ERR, "Invalid header \"%s\" specified", Hdr_p); 1243 } 1244 } 1245 1246 if (mask & OCr) { 1247 Rtty_p = fopen(Ttyname, "r"); 1248 Wtty_p = fopen(Ttyname, "w"); 1249 1250 if (Rtty_p == (FILE *)NULL || Wtty_p == (FILE *)NULL) { 1251 msg(ERR, "Cannot rename, \"%s\" missing", Ttyname); 1252 } 1253 } 1254 1255 if ((mask & OCE) && (Ef_p = fopen(Efil_p, "r")) == (FILE *)NULL) { 1256 msg(ERR, "Cannot open \"%s\" to read patterns", Efil_p); 1257 } 1258 1259 if ((mask & OCI) && (Archive = open(IOfil_p, O_RDONLY)) < 0) { 1260 msg(ERR, "Cannot open \"%s\" for input", IOfil_p); 1261 } 1262 1263 if (mask & OCO) { 1264 if (mask & OCA) { 1265 if ((Archive = open(IOfil_p, O_RDWR)) < 0) { 1266 msg(ERR, 1267 "Cannot open \"%s\" for append", 1268 IOfil_p); 1269 } 1270 } else { 1271 oflag = (O_WRONLY | O_CREAT | O_TRUNC); 1272 1273 if ((Archive = open(IOfil_p, oflag, 0777)) < 0) { 1274 msg(ERR, 1275 "Cannot open \"%s\" for output", 1276 IOfil_p); 1277 } 1278 } 1279 } 1280 1281 if (mask & OCR) { 1282 if ((Rpw_p = getpwnam(Own_p)) == (struct passwd *)NULL) { 1283 msg(ERR, "\"%s\" is not a valid user id", Own_p); 1284 } 1285 } 1286 1287 if ((mask & OCo) && !(mask & OCO)) { 1288 Out_p = stderr; 1289 } 1290 1291 if ((mask & OCp) && ((mask & (OCB|OCC)) == 0)) { 1292 /* 1293 * We are in pass mode with no block size specified. Use the 1294 * larger of the native page size and 8192. 1295 */ 1296 1297 Bufsize = (PageSize > 8192) ? PageSize : 8192; 1298 } 1299 } 1300 1301 /* 1302 * cksum: Calculate the simple checksum of a file (CRC) or header 1303 * (TARTYP (TAR and USTAR)). For -o and the CRC header, the file is opened and 1304 * the checksum is calculated. For -i and the CRC header, the checksum 1305 * is calculated as each block is transferred from the archive I/O buffer 1306 * to the file system I/O buffer. The TARTYP (TAR and USTAR) headers calculate 1307 * the simple checksum of the header (with the checksum field of the 1308 * header initialized to all spaces (\040). 1309 */ 1310 1311 static long 1312 cksum(char hdr, int byt_cnt, int *err) 1313 { 1314 char *crc_p, *end_p; 1315 int cnt; 1316 long checksum = 0L, have; 1317 off_t lcnt; 1318 1319 if (err != NULL) 1320 *err = 0; 1321 switch (hdr) { 1322 case CRC: 1323 if (Args & OCi) { /* do running checksum */ 1324 end_p = Buffr.b_out_p + byt_cnt; 1325 for (crc_p = Buffr.b_out_p; crc_p < end_p; crc_p++) 1326 checksum += (long)*crc_p; 1327 break; 1328 } 1329 /* OCo - do checksum of file */ 1330 lcnt = G_p->g_filesz; 1331 1332 while (lcnt > 0) { 1333 have = (lcnt < Bufsize) ? lcnt : Bufsize; 1334 errno = 0; 1335 if (read(Ifile, Buf_p, have) != have) { 1336 msg(ERR, "Error computing checksum."); 1337 if (err != NULL) 1338 *err = 1; 1339 break; 1340 } 1341 end_p = Buf_p + have; 1342 for (crc_p = Buf_p; crc_p < end_p; crc_p++) 1343 checksum += (long)*crc_p; 1344 lcnt -= have; 1345 } 1346 if (lseek(Ifile, (off_t)0, SEEK_ABS) < 0) 1347 msg(ERRN, "Cannot reset file after checksum"); 1348 break; 1349 case TARTYP: /* TAR and USTAR */ 1350 crc_p = Thdr_p->tbuf.t_cksum; 1351 for (cnt = 0; cnt < TCRCLEN; cnt++) { 1352 *crc_p = '\040'; 1353 crc_p++; 1354 } 1355 crc_p = (char *)Thdr_p; 1356 for (cnt = 0; cnt < TARSZ; cnt++) { 1357 /* 1358 * tar uses unsigned checksum, so we must use unsigned 1359 * here in order to be able to read tar archives. 1360 */ 1361 checksum += (long)((unsigned char)(*crc_p)); 1362 crc_p++; 1363 } 1364 break; 1365 default: 1366 msg(EXT, "Impossible header type."); 1367 } /* hdr */ 1368 return (checksum); 1369 } 1370 1371 /* 1372 * creat_hdr: Fill in the generic header structure with the specific 1373 * header information based on the value of Hdr_type. 1374 * 1375 * return (1) if this process was successful, and (0) otherwise. 1376 */ 1377 1378 static int 1379 creat_hdr(void) 1380 { 1381 ushort_t ftype; 1382 int fullnamesize; 1383 dev_t dev; 1384 ino_t ino; 1385 1386 ftype = SrcSt.st_mode & Ftype; 1387 Adir = (ftype == S_IFDIR); 1388 Aspec = (ftype == S_IFBLK || ftype == S_IFCHR || ftype == S_IFIFO); 1389 switch (Hdr_type) { 1390 case BIN: 1391 Gen.g_magic = CMN_BIN; 1392 break; 1393 case CHR: 1394 Gen.g_magic = CMN_BIN; 1395 break; 1396 case ASC: 1397 Gen.g_magic = CMN_ASC; 1398 break; 1399 case CRC: 1400 Gen.g_magic = CMN_CRC; 1401 break; 1402 case USTAR: 1403 /* 1404 * If the length of the full name is greater than 256, 1405 * print out a message and return. 1406 */ 1407 if ((fullnamesize = strlen(Gen.g_nam_p)) > MAXNAM) { 1408 msg(ERR, 1409 "%s: file name too long", Gen.g_nam_p); 1410 return (0); 1411 } else if (fullnamesize > NAMSIZ) { 1412 /* 1413 * The length of the full name is greater than 1414 * 100, so we must split the filename from the 1415 * path 1416 */ 1417 char namebuff[NAMSIZ+1]; 1418 char prebuff[PRESIZ+1]; 1419 char *lastslash; 1420 int presize, namesize; 1421 1422 (void) memset(namebuff, '\0', 1423 sizeof (namebuff)); 1424 (void) memset(prebuff, '\0', sizeof (prebuff)); 1425 1426 lastslash = strrchr(Gen.g_nam_p, '/'); 1427 1428 if (lastslash != NULL) { 1429 namesize = strlen(++lastslash); 1430 presize = fullnamesize - namesize - 1; 1431 } else { 1432 namesize = fullnamesize; 1433 lastslash = Gen.g_nam_p; 1434 presize = 0; 1435 } 1436 1437 /* 1438 * If the filename is greater than 100 we can't 1439 * archive the file 1440 */ 1441 if (namesize > NAMSIZ) { 1442 msg(ERR, 1443 "%s: filename is greater than %d", 1444 lastslash, NAMSIZ); 1445 return (0); 1446 } 1447 (void) strncpy(&namebuff[0], lastslash, 1448 namesize); 1449 /* 1450 * If the prefix is greater than 155 we can't 1451 * archive the file. 1452 */ 1453 if (presize > PRESIZ) { 1454 msg(ERR, 1455 "%s: prefix is greater than %d", 1456 Gen.g_nam_p, PRESIZ); 1457 return (0); 1458 } 1459 (void) strncpy(&prebuff[0], Gen.g_nam_p, 1460 presize); 1461 1462 Gen.g_tname = e_zalloc(E_EXIT, namesize + 1); 1463 (void) strcpy(Gen.g_tname, namebuff); 1464 1465 Gen.g_prefix = e_zalloc(E_EXIT, presize + 1); 1466 (void) strcpy(Gen.g_prefix, prebuff); 1467 } else { 1468 Gen.g_tname = Gen.g_nam_p; 1469 } 1470 (void) strcpy(Gen.g_tmagic, "ustar"); 1471 (void) strcpy(Gen.g_version, "00"); 1472 1473 dpasswd = getpwuid(SrcSt.st_uid); 1474 if (dpasswd == (struct passwd *)NULL) { 1475 msg(EPOST, 1476 "cpio: could not get passwd information " 1477 "for %s%s%s", 1478 (Gen.g_attrnam_p == (char *)NULL) ? 1479 Gen.g_nam_p : Gen.g_attrfnam_p, 1480 (Gen.g_attrnam_p == (char *)NULL) ? 1481 "" : gettext(" Attribute "), 1482 (Gen.g_attrnam_p == (char *)NULL) ? 1483 "" : Gen.g_attrnam_p); 1484 /* make name null string */ 1485 Gen.g_uname[0] = '\0'; 1486 } else { 1487 (void) strncpy(&Gen.g_uname[0], 1488 dpasswd->pw_name, 32); 1489 } 1490 dgroup = getgrgid(SrcSt.st_gid); 1491 if (dgroup == (struct group *)NULL) { 1492 msg(EPOST, 1493 "cpio: could not get group information " 1494 "for %s%s%S", 1495 (Gen.g_attrnam_p == (char *)NULL) ? 1496 Gen.g_nam_p : Gen.g_attrfnam_p, 1497 (Gen.g_attrnam_p == (char *)NULL) ? 1498 "" : gettext(" Attribute "), 1499 (Gen.g_attrnam_p == (char *)NULL) ? 1500 "" : Gen.g_attrnam_p); 1501 /* make name null string */ 1502 Gen.g_gname[0] = '\0'; 1503 } else { 1504 (void) strncpy(&Gen.g_gname[0], 1505 dgroup->gr_name, 32); 1506 } 1507 Gen.g_typeflag = tartype(ftype); 1508 /* FALLTHROUGH */ 1509 case TAR: 1510 (void) memset(T_lname, '\0', sizeof (T_lname)); 1511 break; 1512 default: 1513 msg(EXT, "Impossible header type."); 1514 } 1515 1516 dev = SrcSt.st_dev; 1517 ino = SrcSt.st_ino; 1518 1519 if (Use_old_stat) { 1520 SrcSt = *OldSt; 1521 } 1522 1523 Gen.g_namesz = strlen(Gen.g_nam_p) + 1; 1524 Gen.g_uid = SrcSt.st_uid; 1525 Gen.g_gid = SrcSt.st_gid; 1526 Gen.g_dev = SrcSt.st_dev; 1527 1528 if (Use_old_stat) { 1529 /* -Hodc */ 1530 1531 sl_info_t *p = sl_search(dev, ino); 1532 Gen.g_ino = p ? p->sl_ino2 : -1; 1533 1534 if (Gen.g_ino == (ulong_t)-1) { 1535 msg(ERR, "%s%s%s: cannot be archived - inode too big " 1536 "for -Hodc format", 1537 (Gen.g_attrnam_p == (char *)NULL) ? 1538 Gen.g_nam_p : Gen.g_attrfnam_p, 1539 (Gen.g_attrnam_p == (char *)NULL) ? 1540 "" : gettext(" Attribute "), 1541 (Gen.g_attrnam_p == (char *)NULL) ? 1542 "" : Gen.g_attrnam_p); 1543 return (0); 1544 } 1545 } else { 1546 Gen.g_ino = SrcSt.st_ino; 1547 } 1548 1549 Gen.g_mode = SrcSt.st_mode; 1550 Gen.g_mtime = SrcSt.st_mtime; 1551 Gen.g_nlink = (Adir) ? SrcSt.st_nlink 1552 : sl_numlinks(dev, ino); 1553 1554 if (ftype == S_IFREG || ftype == S_IFLNK) 1555 Gen.g_filesz = (off_t)SrcSt.st_size; 1556 else 1557 Gen.g_filesz = (off_t)0; 1558 Gen.g_rdev = SrcSt.st_rdev; 1559 return (1); 1560 } 1561 1562 /* 1563 * creat_lnk: Create a link from the existing name1_p to name2_p. 1564 */ 1565 1566 static 1567 int 1568 creat_lnk(int dirfd, char *name1_p, char *name2_p) 1569 { 1570 int cnt = 0; 1571 1572 do { 1573 errno = 0; 1574 if (!link(name1_p, name2_p)) { 1575 if (aclp != NULL) { 1576 free(aclp); 1577 aclp = NULL; 1578 acl_set = 0; 1579 } 1580 cnt = 0; 1581 break; 1582 } else if (errno == EEXIST) { 1583 if (cnt == 0) { 1584 struct stat lsb1; 1585 struct stat lsb2; 1586 1587 /* 1588 * Check to see if we are trying to link this 1589 * file to itself. If so, count the effort as 1590 * successful. If the two files are different, 1591 * or if either lstat is unsuccessful, proceed 1592 * as we would have otherwise; the appropriate 1593 * error will be reported subsequently. 1594 */ 1595 1596 if (lstat(name1_p, &lsb1) != 0) { 1597 msg(ERR, "Cannot lstat source file %s", 1598 name1_p); 1599 } else { 1600 if (lstat(name2_p, &lsb2) != 0) { 1601 msg(ERR, "Cannot lstat " 1602 "destination file %s", 1603 name2_p); 1604 } else { 1605 if (lsb1.st_dev == 1606 lsb2.st_dev && 1607 lsb1.st_ino == 1608 lsb2.st_ino) { 1609 VERBOSE((Args & 1610 (OCv | OCV)), 1611 name2_p); 1612 return (0); 1613 } 1614 } 1615 } 1616 } 1617 1618 if (!(Args & OCu) && G_p->g_mtime <= DesSt.st_mtime) 1619 msg(ERR, 1620 "Existing \"%s\" same age or newer", 1621 name2_p); 1622 else if (unlinkat(dirfd, get_component(name2_p), 0) < 0) 1623 msg(ERRN, "Error cannot unlink \"%s\"", 1624 name2_p); 1625 } 1626 cnt++; 1627 } while ((cnt < 2) && missdir(name2_p) == 0); 1628 if (!cnt) { 1629 char *newname; 1630 char *fromname; 1631 char *attrname; 1632 1633 newname = name2_p; 1634 fromname = name1_p; 1635 attrname = Gen.g_attrnam_p; 1636 if (attrname) { 1637 if (Args & OCp) { 1638 newname = fromname = Fullnam_p; 1639 } else { 1640 newname = Gen.g_attrfnam_p; 1641 } 1642 } 1643 if (Args & OCv) { 1644 (void) fprintf(Err_p, 1645 gettext("%s%s%s linked to %s%s%s\n"), newname, 1646 (attrname == (char *)NULL) ? 1647 "" : gettext(" attribute "), 1648 (attrname == (char *)NULL) ? 1649 "" : attrname, fromname, 1650 (attrname == (char *)NULL) ? 1651 "" : gettext(" attribute "), 1652 (attrname == (char *)NULL) ? 1653 "" : name1_p); 1654 } 1655 VERBOSE((Args & (OCv | OCV)), newname); 1656 } else if (cnt == 1) 1657 msg(ERRN, 1658 "Unable to create directory for \"%s\"", name2_p); 1659 else if (cnt == 2) 1660 msg(ERRN, 1661 "Cannot link \"%s\" and \"%s\"", name1_p, name2_p); 1662 return (cnt); 1663 } 1664 1665 /* 1666 * creat_spec: 1667 * Create one of the following: 1668 * directory 1669 * character special file 1670 * block special file 1671 * fifo 1672 */ 1673 1674 static int 1675 creat_spec(int dirfd) 1676 { 1677 char *nam_p; 1678 int cnt, result, rv = 0; 1679 char *curdir; 1680 char *lastslash; 1681 1682 Do_rename = 0; /* creat_tmp() may reset this */ 1683 1684 if (Args & OCp) { 1685 nam_p = Fullnam_p; 1686 } else { 1687 nam_p = G_p->g_nam_p; 1688 } 1689 1690 /* 1691 * Is this the extraction of the hidden attribute directory? 1692 * If so then just set the mode/times correctly, and return. 1693 */ 1694 1695 if (Hiddendir) { 1696 if (fchownat(dirfd, ".", G_p->g_uid, G_p->g_gid, 0) != 0) { 1697 msg(ERRN, 1698 "Cannot chown() \"attribute directory of " 1699 "file %s\"", G_p->g_attrfnam_p); 1700 } 1701 1702 if (fchmod(dirfd, G_p->g_mode) != 0) { 1703 msg(ERRN, 1704 "Cannot chmod() \"attribute directory of " 1705 "file %s\"", G_p->g_attrfnam_p); 1706 } 1707 1708 acl_set = 0; 1709 if (Pflag && aclp != NULL) { 1710 if (facl(dirfd, SETACL, aclcnt, aclp) < 0) { 1711 msg(ERRN, 1712 "failed to set acl on attribute" 1713 " directory of %s ", G_p->g_attrfnam_p); 1714 } else { 1715 acl_set = 1; 1716 } 1717 free(aclp); 1718 aclp = NULL; 1719 } 1720 1721 return (1); 1722 } 1723 1724 result = stat(nam_p, &DesSt); 1725 1726 if (ustar_dir() || Adir) { 1727 /* 1728 * The archive file is a directory. 1729 * Skip "." and ".." 1730 */ 1731 1732 curdir = strrchr(nam_p, '.'); 1733 1734 if (curdir != NULL && curdir[1] == NULL) { 1735 lastslash = strrchr(nam_p, '/'); 1736 1737 if (lastslash != NULL) { 1738 lastslash++; 1739 } else { 1740 lastslash = nam_p; 1741 } 1742 1743 if (!(strcmp(lastslash, ".")) || 1744 !(strcmp(lastslash, ".."))) { 1745 return (1); 1746 } 1747 } 1748 1749 if (result == 0) { 1750 /* A file by the same name exists. */ 1751 1752 /* Take care of ACLs */ 1753 acl_set = 0; 1754 1755 if (Pflag && aclp != NULL) { 1756 if (acl(nam_p, SETACL, aclcnt, aclp) < 0) { 1757 msg(ERRN, 1758 "\"%s\": failed to set acl", 1759 nam_p); 1760 } else { 1761 acl_set = 1; 1762 } 1763 1764 free(aclp); 1765 aclp = NULL; 1766 } 1767 if (Args & OCd) { 1768 /* 1769 * We are creating directories. Keep the 1770 * existing file. 1771 */ 1772 1773 rstfiles(U_KEEP, dirfd); 1774 } 1775 1776 /* Report success. */ 1777 1778 return (1); 1779 } 1780 } else { 1781 /* The archive file is not a directory. */ 1782 1783 if (result == 0) { 1784 /* 1785 * A file by the same name exists. Move it to a 1786 * temporary file. 1787 */ 1788 1789 if (creat_tmp(nam_p) < 0) { 1790 /* 1791 * We weren't able to create the temp file. 1792 * Report failure. 1793 */ 1794 1795 return (0); 1796 } 1797 } 1798 } 1799 1800 /* 1801 * This pile tries to create the file directly, and, if there is a 1802 * problem, creates missing directories, and then tries to create the 1803 * file again. Two strikes and you're out. 1804 */ 1805 1806 cnt = 0; 1807 1808 do { 1809 if (ustar_dir() || Adir) { 1810 /* The archive file is a directory. */ 1811 1812 result = mkdir(nam_p, G_p->g_mode); 1813 } else if (ustar_spec() || Aspec) { 1814 /* 1815 * The archive file is block special, 1816 * char special or a fifo. 1817 */ 1818 1819 result = mknod(nam_p, (int)G_p->g_mode, 1820 (int)G_p->g_rdev); 1821 } 1822 1823 if (result >= 0) { 1824 /* 1825 * The file creation succeeded. Take care of the ACLs. 1826 */ 1827 1828 acl_set = 0; 1829 1830 if (Pflag && aclp != NULL) { 1831 if (acl(nam_p, SETACL, aclcnt, aclp) < 0) { 1832 msg(ERRN, 1833 "\"%s\": failed to set acl", nam_p); 1834 } else { 1835 acl_set = 1; 1836 } 1837 1838 free(aclp); 1839 aclp = NULL; 1840 } 1841 1842 cnt = 0; 1843 break; 1844 } 1845 1846 cnt++; 1847 } while (cnt < 2 && missdir(nam_p) == 0); 1848 1849 switch (cnt) { 1850 case 0: 1851 rv = 1; 1852 rstfiles(U_OVER, dirfd); 1853 break; 1854 1855 case 1: 1856 msg(ERRN, 1857 "Cannot create directory for \"%s\"", nam_p); 1858 1859 if (*Over_p == '\0') { 1860 rstfiles(U_KEEP, dirfd); 1861 } 1862 1863 break; 1864 1865 case 2: 1866 if (ustar_dir() || Adir) { 1867 msg(ERRN, "Cannot create directory \"%s\"", nam_p); 1868 } else if (ustar_spec() || Aspec) { 1869 msg(ERRN, "Cannot mknod() \"%s\"", nam_p); 1870 } 1871 1872 if (*Over_p == '\0') { 1873 rstfiles(U_KEEP, dirfd); 1874 } 1875 1876 break; 1877 1878 default: 1879 msg(EXT, "Impossible case."); 1880 } 1881 1882 return (rv); 1883 } 1884 1885 /* 1886 * creat_tmp: 1887 */ 1888 1889 static int 1890 creat_tmp(char *nam_p) 1891 { 1892 char *t_p; 1893 int cwd; 1894 1895 if ((Args & OCp) && G_p->g_ino == DesSt.st_ino && 1896 G_p->g_dev == DesSt.st_dev) { 1897 msg(ERR, "Attempt to pass a file to itself."); 1898 return (-1); 1899 } 1900 1901 if (G_p->g_mtime <= DesSt.st_mtime && !(Args & OCu)) { 1902 msg(ERR, "Existing \"%s\" same age or newer", nam_p); 1903 return (-1); 1904 } 1905 1906 if (Euid && Aspec) { 1907 msg(ERR, "Cannot overwrite \"%s\"", nam_p); 1908 return (-1); 1909 } 1910 1911 /* Make the temporary file name. */ 1912 1913 (void) strcpy(Over_p, nam_p); 1914 t_p = Over_p + strlen(Over_p); 1915 1916 while (t_p != Over_p) { 1917 if (*(t_p - 1) == '/') 1918 break; 1919 t_p--; 1920 } 1921 1922 (void) strcpy(t_p, "XXXXXX"); 1923 1924 if (G_p->g_attrnam_p != (char *)NULL) { 1925 /* 1926 * Save our current directory, so we can go into 1927 * the attribute directory to make the temp file 1928 * and then return. 1929 */ 1930 1931 cwd = save_cwd(); 1932 (void) fchdir(G_p->g_dirfd); 1933 } 1934 1935 (void) mktemp(Over_p); 1936 1937 if (G_p->g_attrnam_p != (char *)NULL) { 1938 /* Return to the current directory. */ 1939 1940 rest_cwd(cwd); 1941 } 1942 1943 if (*Over_p == '\0') { 1944 /* mktemp reports a failure. */ 1945 1946 msg(ERR, "Cannot get temporary file name."); 1947 return (-1); 1948 } 1949 1950 /* 1951 * If it's a regular file, write to the temporary file, and then rename 1952 * in order to accomodate potential executables. 1953 * 1954 * Note: g_typeflag is only defined (set) for USTAR archive types. It 1955 * defaults to 0 in the cpio-format-regular file case, so this test 1956 * succeeds. 1957 */ 1958 1959 if (G_p->g_typeflag == 0 && 1960 (DesSt.st_mode & (ulong_t)Ftype) == S_IFREG && 1961 (G_p->g_mode & (ulong_t)Ftype) == S_IFREG) { 1962 /* 1963 * The archive file and the filesystem file are both regular 1964 * files. We write to the temporary file in this case. 1965 */ 1966 1967 if (Args & OCp) { 1968 if (G_p->g_attrnam_p == (char *)NULL) { 1969 Fullnam_p = Over_p; 1970 } else { 1971 Attrfile_p = Over_p; 1972 } 1973 } else { 1974 G_p->g_nam_p = Over_p; 1975 if (G_p->g_attrnam_p != (char *)NULL) { 1976 Attrfile_p = Over_p; 1977 } 1978 } 1979 1980 if (G_p->g_attrnam_p == (char *)NULL) { 1981 Over_p = nam_p; 1982 } else { 1983 Over_p = G_p->g_attrnam_p; 1984 } 1985 1986 Do_rename = 1; 1987 } else { 1988 /* 1989 * Either the archive file or the filesystem file is not a 1990 * regular file. 1991 */ 1992 1993 Do_rename = 0; 1994 1995 if (S_ISDIR(DesSt.st_mode)) { 1996 /* 1997 * The filesystem file is a directory. 1998 * 1999 * Save the current working directory because we will 2000 * want to restore it back just in case remove_dir() 2001 * fails or get confused about where we should be. 2002 */ 2003 2004 *Over_p = '\0'; 2005 cwd = save_cwd(); 2006 2007 if (remove_dir(nam_p) < 0) { 2008 msg(ERRN, 2009 "Cannot remove the directory \"%s\"", 2010 nam_p); 2011 /* 2012 * Restore working directory back to the one 2013 * saved earlier. 2014 */ 2015 2016 rest_cwd(cwd); 2017 return (-1); 2018 } 2019 2020 /* 2021 * Restore working directory back to the one 2022 * saved earlier 2023 */ 2024 2025 rest_cwd(cwd); 2026 } else { 2027 /* 2028 * The file is not a directory. Will use the original 2029 * link/unlink construct, however, if the file is 2030 * namefs, link would fail with EXDEV. Therefore, we 2031 * use rename() first to back up the file. 2032 */ 2033 if (rename(nam_p, Over_p) < 0) { 2034 /* 2035 * If rename failed, try old construction 2036 * method. 2037 */ 2038 if (link(nam_p, Over_p) < 0) { 2039 msg(ERRN, 2040 "Cannot create temporary file"); 2041 *Over_p = '\0'; 2042 return (-1); 2043 } 2044 2045 if (unlink(nam_p) < 0) { 2046 msg(ERRN, 2047 "Cannot unlink() current \"%s\"", 2048 nam_p); 2049 (void) unlink(Over_p); 2050 *Over_p = '\0'; 2051 return (-1); 2052 } 2053 } 2054 } 2055 } 2056 2057 return (1); 2058 } 2059 2060 /* 2061 * data_in: If proc_mode == P_PROC, bread() the file's data from the archive 2062 * and write(2) it to the open fdes gotten from openout(). If proc_mode == 2063 * P_SKIP, or becomes P_SKIP (due to errors etc), bread(2) the file's data 2064 * and ignore it. If the user specified any of the "swap" options (b, s or S), 2065 * and the length of the file is not appropriate for that action, do not 2066 * perform the "swap", otherwise perform the action on a buffer by buffer basis. 2067 * If the CRC header was selected, calculate a running checksum as each buffer 2068 * is processed. 2069 */ 2070 2071 static void 2072 data_in(int proc_mode) 2073 { 2074 char *nam_p; 2075 int cnt, pad; 2076 long cksumval = 0L; 2077 off_t filesz; 2078 int rv, swapfile = 0; 2079 int compress_flag = 0; /* if the file is compressed */ 2080 int cstatus = 0; 2081 FILE *pipef; /* pipe for bar to do de-compression */ 2082 2083 2084 if (G_p->g_attrnam_p != (char *)NULL) { 2085 nam_p = G_p->g_attrnam_p; 2086 } else { 2087 nam_p = G_p->g_nam_p; 2088 } 2089 2090 2091 if (((G_p->g_mode & Ftype) == S_IFLNK && proc_mode != P_SKIP) || 2092 (Hdr_type == BAR && bar_linkflag == '2' && proc_mode != P_SKIP)) { 2093 proc_mode = P_SKIP; 2094 VERBOSE((Args & (OCv | OCV)), nam_p); 2095 } 2096 if (Args & (OCb | OCs | OCS)) { /* verfify that swapping is possible */ 2097 swapfile = 1; 2098 if (Args & (OCs | OCb) && G_p->g_filesz % 2) { 2099 msg(ERR, 2100 "Cannot swap bytes of \"%s\", odd number of bytes", 2101 nam_p); 2102 swapfile = 0; 2103 } 2104 if (Args & (OCS | OCb) && G_p->g_filesz % 4) { 2105 msg(ERR, 2106 "Cannot swap halfwords of \"%s\", odd number " 2107 "of halfwords", nam_p); 2108 swapfile = 0; 2109 } 2110 } 2111 filesz = G_p->g_filesz; 2112 2113 /* This writes out the file from the archive */ 2114 2115 while (filesz > 0) { 2116 cnt = (int)(filesz > CPIOBSZ) ? CPIOBSZ : filesz; 2117 FILL(cnt); 2118 if (proc_mode != P_SKIP) { 2119 if (Hdr_type == CRC) 2120 cksumval += cksum(CRC, cnt, NULL); 2121 if (swapfile) 2122 swap(Buffr.b_out_p, cnt); 2123 errno = 0; 2124 2125 /* 2126 * if the bar archive is compressed, set up a pipe and 2127 * do the de-compression while reading in the file 2128 */ 2129 if (Hdr_type == BAR) { 2130 if (compress_flag == 0 && Compressed) { 2131 setup_uncompress(&pipef); 2132 compress_flag++; 2133 } 2134 2135 } 2136 2137 rv = write(Ofile, Buffr.b_out_p, cnt); 2138 if (rv < cnt) { 2139 if (rv < 0) 2140 msg(ERRN, "Cannot write \"%s\"", nam_p); 2141 else 2142 msg(EXTN, "Cannot write \"%s\"", nam_p); 2143 proc_mode = P_SKIP; 2144 rstfiles(U_KEEP, G_p->g_dirfd); 2145 cstatus = close(Ofile); 2146 Ofile = 0; 2147 if (cstatus != 0) { 2148 msg(EXTN, "close error"); 2149 } 2150 } 2151 } 2152 Buffr.b_out_p += cnt; 2153 Buffr.b_cnt -= (long)cnt; 2154 filesz -= (off_t)cnt; 2155 } /* filesz */ 2156 2157 pad = (Pad_val + 1 - (G_p->g_filesz & Pad_val)) & Pad_val; 2158 if (pad != 0) { 2159 FILL(pad); 2160 Buffr.b_out_p += pad; 2161 Buffr.b_cnt -= pad; 2162 } 2163 if (proc_mode != P_SKIP) { 2164 if (Hdr_type == CRC && Gen.g_cksum != cksumval) { 2165 msg(ERR, "\"%s\" - checksum error", nam_p); 2166 rstfiles(U_KEEP, G_p->g_dirfd); 2167 } else 2168 rstfiles(U_OVER, G_p->g_dirfd); 2169 if (Hdr_type == BAR && compress_flag) { 2170 (void) pclose(pipef); 2171 } else { 2172 cstatus = close(Ofile); 2173 } 2174 Ofile = 0; 2175 if (cstatus != 0) { 2176 msg(EXTN, "close error"); 2177 } 2178 } 2179 VERBOSE((proc_mode != P_SKIP && (Args & (OCv | OCV))), G_p->g_nam_p); 2180 Finished = 1; 2181 } 2182 2183 /* 2184 * data_out: open(2) the file to be archived, compute the checksum 2185 * of it's data if the CRC header was specified and write the header. 2186 * read(2) each block of data and bwrite() it to the archive. For TARTYP (TAR 2187 * and USTAR) archives, pad the data with NULLs to the next 512 byte boundary. 2188 */ 2189 2190 static void 2191 data_out(void) 2192 { 2193 char *nam_p; 2194 int cnt, amount_read, pad; 2195 off_t amt_to_read, real_filesz; 2196 int errret = 0; 2197 2198 nam_p = G_p->g_nam_p; 2199 if (Aspec) { 2200 if (Pflag && aclp != NULL) { 2201 char *secinfo = NULL; 2202 int len = 0; 2203 2204 /* append security attributes */ 2205 if (append_secattr(&secinfo, &len, aclcnt, 2206 (char *)aclp, UFSD_ACL) == -1) { 2207 msg(ERR, 2208 "can create security information"); 2209 } 2210 /* call append_secattr() if more than one */ 2211 2212 if (len > 0) { 2213 /* write ancillary only if there is sec info */ 2214 (void) write_hdr(ARCHIVE_ACL, (off_t)len); 2215 (void) write_ancillary(secinfo, len); 2216 } 2217 } 2218 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2219 rstfiles(U_KEEP, G_p->g_dirfd); 2220 VERBOSE((Args & (OCv | OCV)), nam_p); 2221 return; 2222 } 2223 if ((G_p->g_mode & Ftype) == S_IFLNK && (Hdr_type != 2224 USTAR && Hdr_type != TAR)) { /* symbolic link */ 2225 int size; 2226 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2227 2228 FLUSH(G_p->g_filesz); 2229 errno = 0; 2230 2231 /* Note that "size" and G_p->g_filesz are the same number */ 2232 2233 if ((size = readlink(nam_p, Buffr.b_in_p, G_p->g_filesz)) < 2234 0) { 2235 msg(ERRN, "Cannot read symbolic link \"%s\"", nam_p); 2236 return; 2237 } 2238 2239 /* 2240 * Note that it is OK not to add the NUL after the name read by 2241 * readlink, because it is not being used subsequently. 2242 */ 2243 2244 Buffr.b_in_p += size; 2245 Buffr.b_cnt += size; 2246 pad = (Pad_val + 1 - (size & Pad_val)) & Pad_val; 2247 if (pad != 0) { 2248 FLUSH(pad); 2249 (void) memcpy(Buffr.b_in_p, Empty, pad); 2250 Buffr.b_in_p += pad; 2251 Buffr.b_cnt += pad; 2252 } 2253 VERBOSE((Args & (OCv | OCV)), nam_p); 2254 return; 2255 } else if ((G_p->g_mode & Ftype) == S_IFLNK && 2256 (Hdr_type == USTAR || Hdr_type == TAR)) { 2257 int size; 2258 2259 /* 2260 * G_p->g_filesz is the length of the right-hand side of 2261 * the symlink "x -> y". 2262 * The tar link field is only NAMSIZ long. 2263 */ 2264 2265 if (G_p->g_filesz > NAMSIZ) { 2266 msg(ERRN, 2267 "Symbolic link too long \"%s\"", nam_p); 2268 return; 2269 } 2270 if ((size = readlink(nam_p, T_lname, G_p->g_filesz)) < 0) { 2271 msg(ERRN, 2272 "Cannot read symbolic link \"%s\"", nam_p); 2273 return; 2274 } 2275 T_lname[size] = '\0'; 2276 G_p->g_filesz = (off_t)0; 2277 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2278 VERBOSE((Args & (OCv | OCV)), nam_p); 2279 return; 2280 } 2281 if ((Ifile = openfile(O_RDONLY)) < 0) { 2282 msg(ERR, "\"%s%s%s\" ?", 2283 (Gen.g_attrnam_p == (char *)NULL) ? 2284 nam_p : Gen.g_attrfnam_p, 2285 (Gen.g_attrnam_p == (char *)NULL) ? 2286 "" : gettext(" Attribute "), 2287 (Gen.g_attrnam_p == (char *)NULL) ? 2288 "" : Gen.g_attrnam_p); 2289 return; 2290 } 2291 2292 /* 2293 * Dump extended attribute header. 2294 */ 2295 2296 if (Gen.g_attrnam_p != (char *)NULL) { 2297 write_xattr_hdr(); 2298 } 2299 2300 if (Hdr_type == CRC) { 2301 long csum = cksum(CRC, 0, &errret); 2302 if (errret != 0) { 2303 G_p->g_cksum = (ulong_t)-1; 2304 msg(POST, "\"%s%s%s\" skipped", 2305 (Gen.g_attrnam_p == (char *)NULL) ? 2306 nam_p : Gen.g_attrfnam_p, 2307 (Gen.g_attrnam_p == (char *)NULL) ? 2308 "" : gettext(" Attribute "), 2309 (Gen.g_attrnam_p == (char *)NULL) ? 2310 "" : nam_p); 2311 (void) close(Ifile); 2312 return; 2313 } 2314 G_p->g_cksum = csum; 2315 } else { 2316 G_p->g_cksum = 0; 2317 } 2318 2319 /* 2320 * ACL has been retrieved in getname(). 2321 */ 2322 if (Pflag) { 2323 char *secinfo = NULL; 2324 int len = 0; 2325 2326 /* append security attributes */ 2327 if ((append_secattr(&secinfo, &len, aclcnt, (char *)aclp, 2328 UFSD_ACL)) == -1) 2329 msg(ERR, "can create security information"); 2330 2331 /* call append_secattr() if more than one */ 2332 2333 if (len > 0) { 2334 /* write ancillary only if there is sec info */ 2335 (void) write_hdr(ARCHIVE_ACL, (off_t)len); 2336 (void) write_ancillary(secinfo, len); 2337 } 2338 } 2339 2340 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2341 2342 real_filesz = 0; 2343 2344 for (amt_to_read = G_p->g_filesz; 2345 amt_to_read > 0; 2346 amt_to_read -= (off_t)amount_read) { 2347 FLUSH(CPIOBSZ); 2348 errno = 0; 2349 2350 if ((amount_read = read(Ifile, Buffr.b_in_p, CPIOBSZ)) < 0) { 2351 msg(EXTN, "Cannot read \"%s%s%s\"", 2352 (Gen.g_attrnam_p == (char *)NULL) ? 2353 nam_p : Gen.g_attrfnam_p, 2354 (Gen.g_attrnam_p == (char *)NULL) ? 2355 "" : gettext(" Attribute "), 2356 (Gen.g_attrnam_p == (char *)NULL) ? 2357 "" : nam_p); 2358 break; 2359 } 2360 2361 if (amount_read == 0) { 2362 /* the file has shrunk */ 2363 real_filesz = G_p->g_filesz - amt_to_read; 2364 break; 2365 } else if (amount_read > amt_to_read) { 2366 /* the file has grown */ 2367 real_filesz = G_p->g_filesz + 2368 (amount_read - amt_to_read); 2369 amount_read = amt_to_read; 2370 } else if (amount_read == amt_to_read) { 2371 /* the file is the same size */ 2372 real_filesz = G_p->g_filesz; 2373 } 2374 2375 Buffr.b_in_p += amount_read; 2376 Buffr.b_cnt += (long)amount_read; 2377 } 2378 2379 while (amt_to_read > 0) { 2380 cnt = (amt_to_read > CPIOBSZ) ? CPIOBSZ : (int)amt_to_read; 2381 FLUSH(cnt); 2382 (void) memset(Buffr.b_in_p, NULL, cnt); 2383 Buffr.b_in_p += cnt; 2384 Buffr.b_cnt += cnt; 2385 amt_to_read -= cnt; 2386 } 2387 2388 pad = (Pad_val + 1 - (G_p->g_filesz & Pad_val)) & Pad_val; 2389 if (pad != 0) { 2390 FLUSH(pad); 2391 (void) memcpy(Buffr.b_in_p, Empty, pad); 2392 Buffr.b_in_p += pad; 2393 Buffr.b_cnt += pad; 2394 } 2395 2396 if (real_filesz > G_p->g_filesz) { 2397 msg(ERR, "File size of \"%s%s%s\" has increased by %lld", 2398 (Gen.g_attrnam_p == (char *)NULL) ? 2399 G_p->g_nam_p : Gen.g_attrfnam_p, 2400 (Gen.g_attrnam_p == (char *)NULL) ? 2401 "" : gettext(" Attribute "), 2402 (Gen.g_attrnam_p == (char *)NULL) ? 2403 "" : G_p->g_nam_p, 2404 (real_filesz - G_p->g_filesz)); 2405 } 2406 if (real_filesz < G_p->g_filesz) { 2407 msg(ERR, "File size of \"%s%s%s\" has decreased by %lld", 2408 (Gen.g_attrnam_p == (char *)NULL) ? 2409 G_p->g_nam_p : Gen.g_attrfnam_p, 2410 (Gen.g_attrnam_p == (char *)NULL) ? 2411 "" : gettext(" Attribute "), 2412 (Gen.g_attrnam_p == (char *)NULL) ? 2413 "" : G_p->g_nam_p, 2414 (G_p->g_filesz - real_filesz)); 2415 } 2416 2417 (void) close(Ifile); 2418 rstfiles(U_KEEP, G_p->g_dirfd); 2419 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2420 } 2421 2422 /* 2423 * data_pass: If not a special file (Aspec), open(2) the file to be 2424 * transferred, read(2) each block of data and write(2) it to the output file 2425 * Ofile, which was opened in file_pass(). 2426 */ 2427 2428 static void 2429 data_pass(void) 2430 { 2431 int cnt, done = 1; 2432 int cstatus; 2433 off_t filesz; 2434 char *namep = Nam_p; 2435 2436 if (G_p->g_attrnam_p != (char *)NULL) { 2437 namep = G_p->g_attrnam_p; 2438 } 2439 if (Aspec) { 2440 rstfiles(U_KEEP, G_p->g_passdirfd); 2441 cstatus = close(Ofile); 2442 Ofile = 0; 2443 VERBOSE((Args & (OCv | OCV)), Nam_p); 2444 if (cstatus != 0) { 2445 msg(EXTN, "close error"); 2446 } 2447 return; 2448 } 2449 if ((Ifile = openat(G_p->g_dirfd, get_component(namep), 0)) < 0) { 2450 msg(ERRN, "Cannot open \"%s%s%s\", skipped", 2451 (G_p->g_attrnam_p == (char *)NULL) ? 2452 Nam_p : G_p->g_attrfnam_p, 2453 (G_p->g_attrnam_p == (char *)NULL) ? 2454 "" : gettext(" Attribute "), 2455 (G_p->g_attrnam_p == (char *)NULL) ? 2456 "" : G_p->g_attrnam_p); 2457 rstfiles(U_KEEP, G_p->g_passdirfd); 2458 cstatus = close(Ofile); 2459 Ofile = 0; 2460 if (cstatus != 0) { 2461 msg(EXTN, "close error"); 2462 } 2463 return; 2464 } 2465 filesz = G_p->g_filesz; 2466 2467 while (filesz > 0) { 2468 cnt = (unsigned)(filesz > Bufsize) ? Bufsize : filesz; 2469 errno = 0; 2470 if (read(Ifile, Buf_p, (unsigned)cnt) < 0) { 2471 msg(ERRN, "Cannot read \"%s%s%s\"", 2472 (G_p->g_attrnam_p == (char *)NULL) ? 2473 Nam_p : G_p->g_attrfnam_p, 2474 (G_p->g_attrnam_p == (char *)NULL) ? 2475 "" : gettext(" Attribute "), 2476 (G_p->g_attrnam_p == (char *)NULL) ? 2477 "" : G_p->g_attrnam_p); 2478 done = 0; 2479 break; 2480 } 2481 errno = 0; 2482 if (write(Ofile, Buf_p, (unsigned)cnt) < 0) { 2483 if (Do_rename) { 2484 msg(ERRN, "Cannot write \"%s%s%s\"", Over_p, 2485 (G_p->g_attrnam_p == (char *)NULL) ? 2486 "" : gettext(" Attribute "), 2487 (G_p->g_attrnam_p == (char *)NULL) ? 2488 "" : Over_p); 2489 } else { 2490 msg(ERRN, "Cannot write \"%s%s%s\"", 2491 Fullnam_p, 2492 (G_p->g_attrnam_p == (char *)NULL) ? 2493 "" : gettext(" Attribute "), 2494 (G_p->g_attrnam_p == (char *)NULL) ? 2495 "" : G_p->g_attrnam_p); 2496 } 2497 2498 done = 0; 2499 break; 2500 } 2501 Blocks += (u_longlong_t)((cnt + (Bufsize - 1)) / Bufsize); 2502 filesz -= (off_t)cnt; 2503 } 2504 if (done) { 2505 rstfiles(U_OVER, G_p->g_passdirfd); 2506 } else { 2507 rstfiles(U_KEEP, G_p->g_passdirfd); 2508 } 2509 (void) close(Ifile); 2510 cstatus = close(Ofile); 2511 Ofile = 0; 2512 if (cstatus != 0) { 2513 msg(EXTN, "close error"); 2514 } 2515 VERBOSE((Args & (OCv | OCV)), Fullnam_p); 2516 Finished = 1; 2517 } 2518 2519 /* 2520 * Allocation wrappers. Used to centralize error handling for 2521 * failed allocations. 2522 */ 2523 static void * 2524 e_alloc_fail(int flag) 2525 { 2526 if (flag == E_EXIT) { 2527 msg(EXTN, "Out of memory"); 2528 } 2529 2530 return (NULL); 2531 } 2532 2533 /* 2534 * Note: unlike the other e_*lloc functions, e_realloc does not zero out the 2535 * additional memory it returns. Ensure that you do not trust its contents 2536 * when you call it. 2537 */ 2538 2539 static void * 2540 e_realloc(int flag, void *old, size_t newsize) 2541 { 2542 void *ret = realloc(old, newsize); 2543 2544 if (ret == NULL) { 2545 return (e_alloc_fail(flag)); 2546 } 2547 2548 return (ret); 2549 } 2550 2551 static char * 2552 e_strdup(int flag, const char *arg) 2553 { 2554 char *ret = strdup(arg); 2555 2556 if (ret == NULL) { 2557 return (e_alloc_fail(flag)); 2558 } 2559 2560 return (ret); 2561 } 2562 2563 static void * 2564 e_valloc(int flag, size_t size) 2565 { 2566 void *ret = valloc(size); 2567 2568 if (ret == NULL) { 2569 return (e_alloc_fail(flag)); 2570 } 2571 2572 return (ret); 2573 } 2574 2575 static void * 2576 e_zalloc(int flag, size_t size) 2577 { 2578 void *ret = malloc(size); 2579 2580 if (ret == NULL) { 2581 return (e_alloc_fail(flag)); 2582 } 2583 2584 (void) memset(ret, 0, size); 2585 return (ret); 2586 } 2587 2588 /* 2589 * file_in: Process an object from the archive. If a TARTYP (TAR or USTAR) 2590 * archive and g_nlink == 1, link this file to the file name in t_linkname 2591 * and return. Handle linked files in one of two ways. If Onecopy == 0, this 2592 * is an old style (binary or -c) archive, create and extract the data for the 2593 * first link found, link all subsequent links to this file and skip their data. 2594 * If Oncecopy == 1, save links until all have been processed, and then 2595 * process the links first to last checking their names against the patterns 2596 * and/or asking the user to rename them. The first link that is accepted 2597 * for xtraction is created and the data is read from the archive. 2598 * All subsequent links that are accepted are linked to this file. 2599 */ 2600 2601 static void 2602 file_in(void) 2603 { 2604 struct Lnk *l_p, *tl_p; 2605 int lnkem = 0, cleanup = 0; 2606 int proc_file; 2607 struct Lnk *ttl_p; 2608 int typeflag; 2609 char savacl; 2610 int cwd; 2611 2612 G_p = &Gen; 2613 2614 /* 2615 * Open target directory if this isn't a skipped file 2616 * and g_nlink == 1 2617 * 2618 * Links are handled further down in this function. 2619 */ 2620 2621 proc_file = ckname(0); 2622 2623 if (proc_file == F_SKIP && G_p->g_nlink == 1) { 2624 /* 2625 * Normally ckname() prints out the file as a side 2626 * effect except for table of contents listing 2627 * when its parameter is zero and Onecopy isn't 2628 * Zero. Due to this we need to force the name 2629 * to be printed here. 2630 */ 2631 if (Onecopy == 1) { 2632 VERBOSE((Args & OCt), G_p->g_nam_p); 2633 } 2634 data_in(P_SKIP); 2635 return; 2636 } 2637 2638 if (proc_file != F_SKIP && open_dirfd() != 0) { 2639 data_in(P_SKIP); 2640 return; 2641 } 2642 2643 if (Hdr_type == BAR) { 2644 bar_file_in(); 2645 close_dirfd(); 2646 return; 2647 } 2648 2649 /* 2650 * For archives in USTAR format, the files are extracted according 2651 * to the typeflag. 2652 */ 2653 if (Hdr_type == USTAR || Hdr_type == TAR) { 2654 typeflag = Thdr_p->tbuf.t_typeflag; 2655 if (G_p->g_nlink == 1) { /* hard link */ 2656 if (proc_file != F_SKIP) { 2657 int i; 2658 char lname[NAMSIZ+1]; 2659 (void) memset(lname, '\0', sizeof (lname)); 2660 2661 (void) strncpy(lname, Thdr_p->tbuf.t_linkname, 2662 NAMSIZ); 2663 for (i = 0; i <= NAMSIZ && lname[i] != 0; i++) 2664 ; 2665 2666 lname[i] = 0; 2667 (void) creat_lnk(G_p->g_dirfd, 2668 &lname[0], G_p->g_nam_p); 2669 } 2670 close_dirfd(); 2671 return; 2672 } 2673 if (typeflag == '3' || typeflag == '4' || typeflag == '5' || 2674 typeflag == '6') { 2675 if (proc_file != F_SKIP && 2676 creat_spec(G_p->g_dirfd) > 0) { 2677 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2678 } 2679 close_dirfd(); 2680 return; 2681 } else if (Adir || Aspec) { 2682 if ((proc_file == F_SKIP) || 2683 (Ofile = openout(G_p->g_dirfd)) < 0) { 2684 data_in(P_SKIP); 2685 } else { 2686 data_in(P_PROC); 2687 } 2688 close_dirfd(); 2689 return; 2690 } 2691 } 2692 2693 if (Adir) { 2694 if (proc_file != F_SKIP && creat_spec(G_p->g_dirfd) > 0) { 2695 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2696 } 2697 close_dirfd(); 2698 if (Onecopy == 1) { 2699 VERBOSE((Args & OCt), G_p->g_nam_p); 2700 } 2701 return; 2702 } 2703 if (G_p->g_nlink == 1 || (Hdr_type == TAR || 2704 Hdr_type == USTAR)) { 2705 if (Aspec) { 2706 if (proc_file != F_SKIP && creat_spec(G_p->g_dirfd) > 0) 2707 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2708 } else { 2709 if ((proc_file == F_SKIP) || 2710 (Ofile = openout(G_p->g_dirfd)) < 0) { 2711 data_in(P_SKIP); 2712 } else { 2713 data_in(P_PROC); 2714 } 2715 } 2716 close_dirfd(); 2717 return; 2718 } 2719 close_dirfd(); 2720 2721 tl_p = add_lnk(&ttl_p); 2722 l_p = ttl_p; 2723 if (l_p->L_cnt == l_p->L_gen.g_nlink) 2724 cleanup = 1; 2725 if (!Onecopy || G_p->g_attrnam_p != (char *)NULL) { 2726 lnkem = (tl_p != l_p) ? 1 : 0; 2727 G_p = &tl_p->L_gen; 2728 if (proc_file == F_SKIP) { 2729 data_in(P_SKIP); 2730 } else { 2731 if (open_dirfd() != 0) 2732 return; 2733 if (!lnkem) { 2734 if (Aspec) { 2735 if (creat_spec(G_p->g_dirfd) > 0) 2736 VERBOSE((Args & (OCv | OCV)), 2737 G_p->g_nam_p); 2738 } else if ((Ofile = 2739 openout(G_p->g_dirfd)) < 0) { 2740 data_in(P_SKIP); 2741 close_dirfd(); 2742 reclaim(l_p); 2743 } else { 2744 data_in(P_PROC); 2745 close_dirfd(); 2746 } 2747 } else { 2748 /* 2749 * Are we linking an attribute? 2750 */ 2751 cwd = -1; 2752 if (l_p->L_gen.g_attrnam_p != (char *)NULL) { 2753 (void) strcpy(Lnkend_p, 2754 l_p->L_gen.g_attrnam_p); 2755 (void) strcpy(Full_p, 2756 tl_p->L_gen.g_attrnam_p); 2757 cwd = save_cwd(); 2758 (void) fchdir(G_p->g_dirfd); 2759 } else { 2760 (void) strcpy(Lnkend_p, 2761 l_p->L_gen.g_nam_p); 2762 (void) strcpy(Full_p, 2763 tl_p->L_gen.g_nam_p); 2764 } 2765 (void) creat_lnk(G_p->g_dirfd, 2766 Lnkend_p, Full_p); 2767 data_in(P_SKIP); 2768 close_dirfd(); 2769 l_p->L_lnk_p = (struct Lnk *)NULL; 2770 free(tl_p->L_gen.g_nam_p); 2771 free(tl_p); 2772 if (cwd != -1) 2773 rest_cwd(cwd); 2774 } 2775 } 2776 } else { /* Onecopy */ 2777 if (tl_p->L_gen.g_filesz) 2778 cleanup = 1; 2779 if (!cleanup) { 2780 close_dirfd(); 2781 return; /* don't do anything yet */ 2782 } 2783 tl_p = l_p; 2784 /* 2785 * ckname will clear aclchar. We need to keep aclchar for 2786 * all links. 2787 */ 2788 savacl = aclchar; 2789 while (tl_p != (struct Lnk *)NULL) { 2790 G_p = &tl_p->L_gen; 2791 aclchar = savacl; 2792 if ((proc_file = ckname(1)) != F_SKIP) { 2793 if (open_dirfd() != 0) { 2794 return; 2795 } 2796 if (l_p->L_data) { 2797 (void) creat_lnk(G_p->g_dirfd, 2798 l_p->L_gen.g_nam_p, 2799 G_p->g_nam_p); 2800 } else if (Aspec) { 2801 (void) creat_spec(G_p->g_dirfd); 2802 l_p->L_data = 1; 2803 VERBOSE((Args & (OCv | OCV)), 2804 G_p->g_nam_p); 2805 } else if ((Ofile = 2806 openout(G_p->g_dirfd)) < 0) { 2807 proc_file = F_SKIP; 2808 } else { 2809 data_in(P_PROC); 2810 l_p->L_data = 1; 2811 } 2812 } /* (proc_file = ckname(1)) != F_SKIP */ 2813 2814 tl_p = tl_p->L_lnk_p; 2815 2816 close_dirfd(); 2817 2818 if (proc_file == F_SKIP && !cleanup) { 2819 tl_p->L_nxt_p = l_p->L_nxt_p; 2820 tl_p->L_bck_p = l_p->L_bck_p; 2821 l_p->L_bck_p->L_nxt_p = tl_p; 2822 l_p->L_nxt_p->L_bck_p = tl_p; 2823 free(l_p->L_gen.g_nam_p); 2824 free(l_p); 2825 } 2826 } /* tl_p->L_lnk_p != (struct Lnk *)NULL */ 2827 if (l_p->L_data == 0) { 2828 data_in(P_SKIP); 2829 } 2830 } 2831 if (cleanup) { 2832 reclaim(l_p); 2833 } 2834 } 2835 2836 /* 2837 * file_out: If the current file is not a special file (!Aspec) and it 2838 * is identical to the archive, skip it (do not archive the archive if it 2839 * is a regular file). If creating a TARTYP (TAR or USTAR) archive, the first 2840 * time a link to a file is encountered, write the header and file out normally. 2841 * Subsequent links to this file put this file name in their t_linkname field. 2842 * Otherwise, links are handled in one of two ways, for the old headers 2843 * (i.e. binary and -c), linked files are written out as they are encountered. 2844 * For the new headers (ASC and CRC), links are saved up until all the links 2845 * to each file are found. For a file with n links, write n - 1 headers with 2846 * g_filesz set to 0, write the final (nth) header with the correct g_filesz 2847 * value and write the data for the file to the archive. 2848 */ 2849 2850 static 2851 int 2852 file_out(void) 2853 { 2854 struct Lnk *l_p, *tl_p; 2855 int cleanup = 0; 2856 struct Lnk *ttl_p; 2857 2858 G_p = &Gen; 2859 if (!Aspec && IDENT(SrcSt, ArchSt)) 2860 return (1); /* do not archive the archive if it's a reg file */ 2861 if (G_p->g_filesz > Max_offset) { 2862 msg(ERR, "cpio: %s%s%s: too large to archive in current mode", 2863 G_p->g_nam_p, 2864 (G_p->g_attrnam_p == (char *)NULL) ? 2865 "" : gettext(" Attribute "), 2866 (G_p->g_attrnam_p == (char *)NULL) ? 2867 "" : G_p->g_attrnam_p); 2868 return (1); /* do not archive if it's too big */ 2869 } 2870 if (Hdr_type == TAR || Hdr_type == USTAR) { /* TAR and USTAR */ 2871 if (Adir) { 2872 if (Gen.g_attrnam_p != (char *)NULL) { 2873 write_xattr_hdr(); 2874 } 2875 write_hdr(ARCHIVE_NORMAL, 0); 2876 return (0); 2877 } 2878 if (G_p->g_nlink == 1) { 2879 data_out(); 2880 return (0); 2881 } 2882 tl_p = add_lnk(&ttl_p); 2883 l_p = ttl_p; 2884 if (tl_p == l_p) { /* first link to this file encountered */ 2885 data_out(); 2886 return (0); 2887 } 2888 (void) strncpy(T_lname, l_p->L_gen.g_nam_p, 2889 l_p->L_gen.g_namesz); 2890 2891 /* 2892 * check if linkname is greater than 100 characters 2893 */ 2894 if (strlen(T_lname) > NAMSIZ) { 2895 msg(EPOST, "cpio: %s: linkname %s is greater than %d", 2896 G_p->g_nam_p, T_lname, NAMSIZ); 2897 return (1); 2898 } 2899 2900 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2901 VERBOSE((Args & (OCv | OCV)), tl_p->L_gen.g_nam_p); 2902 2903 /* find the lnk entry in sublist, unlink it, and free it */ 2904 for (; ttl_p->L_lnk_p != NULL; 2905 ttl_p = ttl_p->L_lnk_p) { 2906 if (ttl_p->L_lnk_p == tl_p) { 2907 ttl_p->L_lnk_p = tl_p->L_lnk_p; 2908 free(tl_p->L_gen.g_nam_p); 2909 free(tl_p); 2910 break; 2911 } 2912 } 2913 2914 return (0); 2915 } 2916 if (Adir) { 2917 /* 2918 * ACL has been retrieved in getname(). 2919 */ 2920 if (Pflag) { 2921 char *secinfo = NULL; 2922 int len = 0; 2923 2924 /* append security attributes */ 2925 if ((append_secattr(&secinfo, &len, aclcnt, 2926 (char *)aclp, UFSD_ACL)) == -1) 2927 msg(ERR, "can create security information"); 2928 2929 /* call append_secattr() if more than one */ 2930 2931 if (len > 0) { 2932 /* write ancillary */ 2933 (void) write_hdr(ARCHIVE_ACL, (off_t)len); 2934 (void) write_ancillary(secinfo, len); 2935 } 2936 } 2937 2938 if (Gen.g_attrnam_p != (char *)NULL) { 2939 write_xattr_hdr(); 2940 } 2941 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2942 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2943 return (0); 2944 } 2945 if (G_p->g_nlink == 1) { 2946 data_out(); 2947 return (0); 2948 } else { 2949 tl_p = add_lnk(&ttl_p); 2950 l_p = ttl_p; 2951 2952 if (l_p->L_cnt == l_p->L_gen.g_nlink) 2953 cleanup = 1; 2954 else if (Onecopy && G_p->g_attrnam_p == (char *)NULL) { 2955 return (0); /* don't process data yet */ 2956 } 2957 } 2958 if (Onecopy && G_p->g_attrnam_p == (char *)NULL) { 2959 tl_p = l_p; 2960 while (tl_p->L_lnk_p != (struct Lnk *)NULL) { 2961 G_p = &tl_p->L_gen; 2962 G_p->g_filesz = (off_t)0; 2963 /* one link with the acl is sufficient */ 2964 write_hdr(ARCHIVE_NORMAL, (off_t)0); 2965 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 2966 tl_p = tl_p->L_lnk_p; 2967 } 2968 G_p = &tl_p->L_gen; 2969 if (open_dirfd() != 0) 2970 return (1); 2971 } 2972 /* old style: has acl and data for every link */ 2973 data_out(); 2974 if (cleanup) 2975 reclaim(l_p); 2976 return (0); 2977 } 2978 2979 /* 2980 * file_pass: If the -l option is set (link files when possible), and the 2981 * source and destination file systems are the same, link the source file 2982 * (G_p->g_nam_p) to the destination file (Fullnam) and return. If not a 2983 * linked file, transfer the data. Otherwise, the first link to a file 2984 * encountered is transferred normally and subsequent links are linked to it. 2985 */ 2986 2987 static int 2988 file_pass(void) 2989 { 2990 struct Lnk *l_p, *tl_p; 2991 struct Lnk *ttl_p; 2992 char *save_name; 2993 int size; 2994 int cwd; 2995 char *lfrom, *lto; 2996 2997 G_p = &Gen; 2998 2999 if (Adir && !(Args & OCd)) { 3000 msg(ERR, "Use -d option to copy \"%s\"", G_p->g_nam_p); 3001 return (FILE_PASS_ERR); 3002 } 3003 3004 save_name = G_p->g_nam_p; 3005 3006 while (*(G_p->g_nam_p) == '/') { 3007 G_p->g_nam_p++; 3008 } 3009 3010 (void) strcpy(Full_p, 3011 (G_p->g_attrfnam_p == (char *)NULL) ? 3012 G_p->g_nam_p : G_p->g_attrfnam_p); 3013 3014 if (G_p->g_attrnam_p == (char *)NULL) { 3015 G_p->g_passdirfd = open_dir(Fullnam_p); 3016 3017 if (G_p->g_passdirfd == -1) { 3018 msg(ERRN, 3019 "Cannot open/create \"%s\"", Fullnam_p); 3020 return (FILE_PASS_ERR); 3021 } 3022 } else { 3023 G_p->g_passdirfd = attropen(Fullnam_p, ".", O_RDONLY); 3024 3025 if (G_p->g_passdirfd == -1) { 3026 G_p->g_passdirfd = retry_attrdir_open(Fullnam_p); 3027 3028 if (G_p->g_passdirfd == -1) { 3029 msg(ERRN, 3030 "Cannot open attribute directory of" 3031 " file \"%s\"", Fullnam_p); 3032 return (FILE_PASS_ERR); 3033 } 3034 } 3035 } 3036 3037 if (Args & OCl) { 3038 /* We are linking back to the source directory. */ 3039 3040 if (!Adir) { 3041 char *existingfile = save_name; 3042 3043 if ((Args & OCL) && issymlink) { 3044 /* We are chasing symlinks. */ 3045 3046 if ((size = readlink(save_name, Symlnk_p, 3047 MAXPATHLEN)) < 0) { 3048 msg(ERRN, 3049 "Cannot read symbolic link \"%s\"", 3050 save_name); 3051 return (FILE_PASS_ERR); 3052 } 3053 3054 Symlnk_p[size] = '\0'; 3055 existingfile = Symlnk_p; 3056 } 3057 3058 if (G_p->g_attrnam_p == (char *)NULL) { 3059 if (creat_lnk(G_p->g_passdirfd, 3060 existingfile, Fullnam_p) == 0) { 3061 return (FILE_LINKED); 3062 } 3063 } 3064 } 3065 } 3066 3067 if ((G_p->g_mode & Ftype) == S_IFLNK && !(Args & OCL)) { 3068 /* The archive file is a symlink. */ 3069 3070 errno = 0; 3071 3072 if ((size = readlink(save_name, Symlnk_p, MAXPATHLEN)) < 0) { 3073 msg(ERRN, 3074 "Cannot read symbolic link \"%s\"", save_name); 3075 return (FILE_PASS_ERR); 3076 } 3077 3078 errno = 0; 3079 (void) missdir(Fullnam_p); 3080 *(Symlnk_p + size) = '\0'; 3081 3082 if (symlink(Symlnk_p, Fullnam_p) < 0) { 3083 if (errno == EEXIST) { 3084 if (openout(G_p->g_passdirfd) < 0) { 3085 return (FILE_PASS_ERR); 3086 } 3087 } else { 3088 msg(ERRN, "Cannot create \"%s\"", Fullnam_p); 3089 return (FILE_PASS_ERR); 3090 } 3091 } 3092 3093 if (lchown(Fullnam_p, (int)G_p->g_uid, (int)G_p->g_gid) < 0) { 3094 if ((Euid == 0) || (Args & OCR)) { 3095 msg(ERRN, 3096 "Error during chown() of \"%s\"", 3097 Fullnam_p); 3098 } 3099 } 3100 3101 VERBOSE((Args & (OCv | OCV)), Fullnam_p); 3102 return (FILE_PASS_ERR); 3103 } 3104 3105 if (!Adir && G_p->g_nlink > 1) { 3106 /* The archive file has hard links. */ 3107 3108 tl_p = add_lnk(&ttl_p); 3109 l_p = ttl_p; 3110 3111 if (tl_p == l_p) { 3112 /* The archive file was not found. */ 3113 3114 G_p = &tl_p->L_gen; 3115 } else { 3116 /* The archive file was found. */ 3117 3118 cwd = -1; 3119 3120 if (l_p->L_gen.g_attrnam_p != (char *)NULL) { 3121 /* We are linking an attribute */ 3122 3123 (void) strcpy(Lnkend_p, l_p->L_gen.g_attrnam_p); 3124 cwd = save_cwd(); 3125 (void) fchdir(G_p->g_passdirfd); 3126 lfrom = get_component(Lnknam_p); 3127 lto = tl_p->L_gen.g_attrnam_p; 3128 } else { 3129 /* We are not linking an attribute */ 3130 3131 (void) strcpy(Lnkend_p, l_p->L_gen.g_nam_p); 3132 (void) strcpy(Full_p, tl_p->L_gen.g_nam_p); 3133 lfrom = Lnknam_p; 3134 lto = Fullnam_p; 3135 } 3136 3137 (void) creat_lnk(G_p->g_passdirfd, lfrom, lto); 3138 3139 if (cwd) { 3140 rest_cwd(cwd); 3141 } 3142 3143 l_p->L_lnk_p = (struct Lnk *)NULL; 3144 free(tl_p->L_gen.g_nam_p); 3145 free(tl_p); 3146 3147 if (l_p->L_cnt == G_p->g_nlink) { 3148 reclaim(l_p); 3149 } 3150 3151 return (FILE_LINKED); 3152 } 3153 } 3154 3155 if (Adir || Aspec) { 3156 /* 3157 * The archive file is a directory, block special, char 3158 * special or a fifo. 3159 */ 3160 3161 if (creat_spec(G_p->g_passdirfd) > 0) { 3162 VERBOSE((Args & (OCv | OCV)), Fullnam_p); 3163 } 3164 } else if ((Ofile = openout(G_p->g_passdirfd)) > 0) { 3165 data_pass(); 3166 } 3167 3168 return (FILE_COPIED); 3169 } 3170 3171 /* 3172 * flush_lnks: With new linked file handling, linked files are not archived 3173 * until all links have been collected. When the end of the list of filenames 3174 * to archive has been reached, all files that did not encounter all their links 3175 * are written out with actual (encountered) link counts. A file with n links 3176 * (that are archived) will be represented by n headers (one for each link (the 3177 * first n - 1 have g_filesz set to 0)) followed by the data for the file. 3178 */ 3179 3180 static void 3181 flush_lnks(void) 3182 { 3183 struct Lnk *l_p, *tl_p; 3184 off_t tfsize; 3185 3186 l_p = Lnk_hd.L_nxt_p; 3187 while (l_p != &Lnk_hd) { 3188 (void) strcpy(Gen.g_nam_p, l_p->L_gen.g_nam_p); 3189 if (stat(Gen.g_nam_p, &SrcSt) == 0) { /* check if file exists */ 3190 tl_p = l_p; 3191 (void) creat_hdr(); 3192 Gen.g_nlink = l_p->L_cnt; /* "actual" link count */ 3193 tfsize = Gen.g_filesz; 3194 Gen.g_filesz = (off_t)0; 3195 G_p = &Gen; 3196 while (tl_p != (struct Lnk *)NULL) { 3197 Gen.g_nam_p = tl_p->L_gen.g_nam_p; 3198 Gen.g_namesz = tl_p->L_gen.g_namesz; 3199 if (tl_p->L_lnk_p == (struct Lnk *)NULL) { 3200 Gen.g_filesz = tfsize; 3201 if (open_dirfd() != 0) { 3202 break; 3203 } 3204 data_out(); 3205 break; 3206 } 3207 write_hdr(ARCHIVE_NORMAL, 3208 (off_t)0); /* header only */ 3209 VERBOSE((Args & (OCv | OCV)), Gen.g_nam_p); 3210 tl_p = tl_p->L_lnk_p; 3211 } 3212 Gen.g_nam_p = Nam_p; 3213 } else /* stat(Gen.g_nam_p, &SrcSt) == 0 */ 3214 msg(ERR, "\"%s%s%s\" has disappeared", 3215 (Gen.g_attrnam_p == (char *)NULL) ? 3216 Gen.g_nam_p : Gen.g_attrfnam_p, 3217 (Gen.g_attrnam_p == (char *)NULL) ? 3218 "" : gettext(" Attribute "), 3219 (Gen.g_attrnam_p == (char *)NULL) ? 3220 "" : Gen.g_attrnam_p); 3221 tl_p = l_p; 3222 l_p = l_p->L_nxt_p; 3223 reclaim(tl_p); 3224 } /* l_p != &Lnk_hd */ 3225 } 3226 3227 /* 3228 * gethdr: Get a header from the archive, validate it and check for the trailer. 3229 * Any user specified Hdr_type is ignored (set to NONE in main). Hdr_type is 3230 * set appropriately after a valid header is found. Unless the -k option is 3231 * set a corrupted header causes an exit with an error. I/O errors during 3232 * examination of any part of the header cause gethdr to throw away any current 3233 * data and start over. Other errors during examination of any part of the 3234 * header cause gethdr to advance one byte and continue the examination. 3235 */ 3236 3237 static int 3238 gethdr(void) 3239 { 3240 ushort_t ftype; 3241 int hit = NONE, cnt = 0; 3242 int goodhdr, hsize, offset; 3243 int bswap = 0; 3244 char *preptr; 3245 int k = 0; 3246 int j; 3247 3248 Gen.g_nam_p = Nam_p; 3249 do { /* hit == NONE && (Args & OCk) && Buffr.b_cnt > 0 */ 3250 FILL(Hdrsz); 3251 switch (Hdr_type) { 3252 case NONE: 3253 case BIN: 3254 Binmag.b_byte[0] = Buffr.b_out_p[0]; 3255 Binmag.b_byte[1] = Buffr.b_out_p[1]; 3256 if ((Binmag.b_half == CMN_BIN) || 3257 (Binmag.b_half == CMN_BBS)) { 3258 hit = read_hdr(BIN); 3259 if (Hdr_type == NONE) 3260 bswap = 1; 3261 hsize = HDRSZ + Gen.g_namesz; 3262 break; 3263 } 3264 if (Hdr_type != NONE) 3265 break; 3266 /*FALLTHROUGH*/ 3267 case CHR: 3268 if (!(strncmp(Buffr.b_out_p, CMS_CHR, CMS_LEN))) { 3269 hit = read_hdr(CHR); 3270 hsize = CHRSZ + Gen.g_namesz; 3271 break; 3272 } 3273 if (Hdr_type != NONE) 3274 break; 3275 /*FALLTHROUGH*/ 3276 case ASC: 3277 if (!(strncmp(Buffr.b_out_p, CMS_ASC, CMS_LEN))) { 3278 hit = read_hdr(ASC); 3279 hsize = ASCSZ + Gen.g_namesz; 3280 Max_namesz = APATH; 3281 break; 3282 } 3283 if (Hdr_type != NONE) 3284 break; 3285 /*FALLTHROUGH*/ 3286 case CRC: 3287 if (!(strncmp(Buffr.b_out_p, CMS_CRC, CMS_LEN))) { 3288 hit = read_hdr(CRC); 3289 hsize = ASCSZ + Gen.g_namesz; 3290 Max_namesz = APATH; 3291 break; 3292 } 3293 if (Hdr_type != NONE) 3294 break; 3295 /*FALLTHROUGH*/ 3296 3297 case BAR: 3298 if (Hdr_p != NULL && strcmp(Hdr_p, "bar") == 0) { 3299 Hdrsz = BARSZ; 3300 FILL(Hdrsz); 3301 if ((hit = read_hdr(BAR)) == NONE) { 3302 Hdrsz = ASCSZ; 3303 break; 3304 } 3305 hit = BAR; 3306 hsize = BARSZ; 3307 break; 3308 } 3309 /*FALLTHROUGH*/ 3310 3311 case USTAR: 3312 if (Hdr_p != NULL && strcmp(Hdr_p, "ustar") == 0) { 3313 Hdrsz = TARSZ; 3314 FILL(Hdrsz); 3315 if ((hit = read_hdr(USTAR)) == NONE) { 3316 Hdrsz = ASCSZ; 3317 break; 3318 } 3319 hit = USTAR; 3320 hsize = TARSZ; 3321 break; 3322 } 3323 /*FALLTHROUGH*/ 3324 case TAR: 3325 if (Hdr_p != NULL && strcmp(Hdr_p, "tar") == 0) { 3326 Hdrsz = TARSZ; 3327 FILL(Hdrsz); 3328 if ((hit = read_hdr(TAR)) == NONE) { 3329 Hdrsz = ASCSZ; 3330 break; 3331 } 3332 hit = TAR; 3333 hsize = TARSZ; 3334 break; 3335 } 3336 /*FALLTHROUGH*/ 3337 default: 3338 msg(EXT, "Impossible header type."); 3339 } /* Hdr_type */ 3340 3341 if (hit == TAR || hit == USTAR) { 3342 Gen.g_nam_p = &nambuf[0]; 3343 } 3344 3345 if (hit != NONE) { 3346 FILL(hsize); 3347 goodhdr = 1; 3348 if (Gen.g_filesz < (off_t)0 || Gen.g_namesz < 1) 3349 goodhdr = 0; 3350 if ((hit != USTAR) && (hit != TAR)) 3351 if (Gen.g_namesz - 1 > Max_namesz) 3352 goodhdr = 0; 3353 /* TAR and USTAR */ 3354 if ((hit == USTAR) || (hit == TAR)) { 3355 if (*Gen.g_nam_p == '\0') { /* tar trailer */ 3356 goodhdr = 1; 3357 } else { 3358 3359 G_p = &Gen; 3360 if (G_p->g_cksum != 3361 cksum(TARTYP, 0, NULL)) { 3362 goodhdr = 0; 3363 msg(ERR, 3364 "Bad header - checksum " 3365 "error."); 3366 } 3367 } 3368 } else if (hit != BAR) { /* binary, -c, ASC and CRC */ 3369 if (Gen.g_nlink <= (ulong_t)0) 3370 goodhdr = 0; 3371 if (*(Buffr.b_out_p + hsize - 1) != '\0') 3372 goodhdr = 0; 3373 } 3374 if (!goodhdr) { 3375 hit = NONE; 3376 if (!(Args & OCk)) 3377 break; 3378 msg(ERR, 3379 "Corrupt header, file(s) may be lost."); 3380 } else { 3381 FILL(hsize); 3382 } 3383 } /* hit != NONE */ 3384 if (hit == NONE) { 3385 Buffr.b_out_p++; 3386 Buffr.b_cnt--; 3387 if (!(Args & OCk)) 3388 break; 3389 if (!cnt++) 3390 msg(ERR, "Searching for magic number/header."); 3391 } 3392 } while (hit == NONE); 3393 if (hit == NONE) { 3394 if (Hdr_type == NONE) 3395 msg(EXT, "Not a cpio file, bad header."); 3396 else 3397 msg(EXT, "Bad magic number/header."); 3398 } else if (cnt > 0) { 3399 msg(EPOST, "Re-synchronized on magic number/header."); 3400 } 3401 if (Hdr_type == NONE) { 3402 Hdr_type = hit; 3403 switch (Hdr_type) { 3404 case BIN: 3405 if (bswap) 3406 Args |= BSM; 3407 Hdrsz = HDRSZ; 3408 Max_namesz = CPATH; 3409 Pad_val = HALFWD; 3410 Onecopy = 0; 3411 break; 3412 case CHR: 3413 Hdrsz = CHRSZ; 3414 Max_namesz = CPATH; 3415 Pad_val = 0; 3416 Onecopy = 0; 3417 break; 3418 case ASC: 3419 case CRC: 3420 Hdrsz = ASCSZ; 3421 Max_namesz = APATH; 3422 Pad_val = FULLWD; 3423 Onecopy = 1; 3424 break; 3425 case USTAR: 3426 Hdrsz = TARSZ; 3427 Max_namesz = HNAMLEN - 1; 3428 Pad_val = FULLBK; 3429 Onecopy = 0; 3430 break; 3431 case BAR: 3432 case TAR: 3433 Hdrsz = TARSZ; 3434 Max_namesz = TNAMLEN - 1; 3435 Pad_val = FULLBK; 3436 Onecopy = 0; 3437 break; 3438 default: 3439 msg(EXT, "Impossible header type."); 3440 } /* Hdr_type */ 3441 } /* Hdr_type == NONE */ 3442 if ((Hdr_type == USTAR) || (Hdr_type == TAR) || 3443 (Hdr_type == BAR)) { /* TAR, USTAR, BAR */ 3444 Gen.g_namesz = 0; 3445 if (Gen.g_nam_p[0] == '\0') 3446 return (0); 3447 else { 3448 preptr = &prebuf[0]; 3449 if (*preptr != (char)NULL) { 3450 k = strlen(&prebuf[0]); 3451 if (k < PRESIZ) { 3452 (void) strcpy(&fullnam[0], &prebuf[0]); 3453 j = 0; 3454 fullnam[k++] = '/'; 3455 while ((j < NAMSIZ) && (&nambuf[j] != 3456 (char)NULL)) { 3457 fullnam[k] = nambuf[j]; 3458 k++; j++; 3459 } 3460 fullnam[k] = '\0'; 3461 } else if (k >= PRESIZ) { 3462 k = 0; 3463 while ((k < PRESIZ) && (prebuf[k] != 3464 '\0')) { 3465 fullnam[k] = prebuf[k]; 3466 k++; 3467 } 3468 fullnam[k++] = '/'; 3469 j = 0; 3470 while ((j < NAMSIZ) && (nambuf[j] != 3471 '\0')) { 3472 fullnam[k] = nambuf[j]; 3473 k++; j++; 3474 } 3475 fullnam[k] = '\0'; 3476 } 3477 Gen.g_nam_p = &fullnam[0]; 3478 } else 3479 Gen.g_nam_p = &nambuf[0]; 3480 3481 /* 3482 * initialize the buffer so that the prefix will not 3483 * applied to the next entry in the archive 3484 */ 3485 (void) memset(prebuf, 0, sizeof (prebuf)); 3486 } 3487 } else if (Hdr_type != BAR) { 3488 (void) memcpy(Gen.g_nam_p, Buffr.b_out_p + Hdrsz, Gen.g_namesz); 3489 if (!(strcmp(Gen.g_nam_p, "TRAILER!!!"))) 3490 return (0); 3491 } 3492 offset = ((hsize + Pad_val) & ~Pad_val); 3493 FILL(offset + Hdrsz); 3494 Thdr_p = (union tblock *)Buffr.b_out_p; 3495 Buffr.b_out_p += offset; 3496 Buffr.b_cnt -= (off_t)offset; 3497 ftype = Gen.g_mode & Ftype; 3498 3499 #if defined(O_XATTR) 3500 /* extended attribute support */ 3501 if (((Gen.g_mode & S_IFMT) == _XATTR_CPIO_MODE) || 3502 ((Hdr_type == USTAR || Hdr_type == TAR) && 3503 Thdr_p->tbuf.t_typeflag == _XATTR_HDRTYPE)) { 3504 if (xattrp != (struct xattr_buf *)NULL) { 3505 if (xattrbadhead) { 3506 free(xattrhead); 3507 xattrp = NULL; 3508 xattr_linkp = NULL; 3509 xattrhead = NULL; 3510 return (1); 3511 } 3512 if (Atflag == 0 && ((Args & OCt) == 0)) { 3513 data_in(P_SKIP); 3514 free(xattrhead); 3515 xattrhead = NULL; 3516 xattrp = NULL; 3517 Gen.g_attrfnam_p = (char *)NULL; 3518 Gen.g_attrnam_p = (char *)NULL; 3519 return (2); 3520 } 3521 3522 if (Gen.g_attrfnam_p != (char *)NULL) { 3523 free(Gen.g_attrfnam_p); 3524 Gen.g_attrfnam_p = (char *)NULL; 3525 } 3526 if (Gen.g_attrnam_p != (char *)NULL) { 3527 free(Gen.g_attrnam_p); 3528 Gen.g_attrnam_p = (char *)NULL; 3529 } 3530 if (Renam_p && Renam_p[0] != '\0') { 3531 Gen.g_attrfnam_p = e_strdup(E_EXIT, Renam_p); 3532 } else { 3533 Gen.g_attrfnam_p = e_strdup(E_EXIT, 3534 xattrp->h_names); 3535 } 3536 3537 Gen.g_attrnam_p = e_strdup(E_EXIT, 3538 xattrp->h_names + strlen(xattrp->h_names) + 1); 3539 3540 if (Hdr_type != USTAR && Hdr_type != TAR) { 3541 Gen.g_mode = Gen.g_mode & (~_XATTR_CPIO_MODE); 3542 Gen.g_mode |= attrmode(xattrp->h_typeflag); 3543 3544 } else if (Hdr_type == USTAR || Hdr_type == TAR) { 3545 Thdr_p->tbuf.t_typeflag = xattrp->h_typeflag; 3546 } 3547 if (xattr_linkp != (struct xattr_buf *)NULL) { 3548 if (Gen.g_linktoattrfnam_p != (char *)NULL) { 3549 free(Gen.g_linktoattrfnam_p); 3550 Gen.g_linktoattrfnam_p = NULL; 3551 } 3552 if (Gen.g_linktoattrnam_p != (char *)NULL) { 3553 free(Gen.g_linktoattrnam_p); 3554 Gen.g_linktoattrnam_p = NULL; 3555 } 3556 Gen.g_linktoattrfnam_p = e_strdup(E_EXIT, 3557 xattr_linkp->h_names); 3558 Gen.g_linktoattrnam_p = e_strdup(E_EXIT, 3559 xattr_linkp->h_names + 3560 strlen(xattr_linkp->h_names) + 1); 3561 xattr_linkp = NULL; 3562 } 3563 ftype = Gen.g_mode & Ftype; 3564 Adir = ftype == S_IFDIR; 3565 Aspec = (ftype == S_IFBLK || 3566 ftype == S_IFCHR || ftype == S_IFIFO); 3567 3568 if (Gen.g_attrnam_p[0] == '.' && 3569 Gen.g_attrnam_p[1] == '\0' && 3570 xattrp->h_typeflag == DIRTYPE) { 3571 Hiddendir = 1; 3572 } else { 3573 Hiddendir = 0; 3574 } 3575 3576 free(xattrhead); 3577 xattrhead = NULL; 3578 xattrp = NULL; 3579 } else { 3580 if (xattrbadhead == 0) { 3581 (void) read_xattr_hdr(); 3582 return (2); 3583 } 3584 } 3585 } 3586 #endif /* O_XATTR */ 3587 3588 /* acl support: grab acl info */ 3589 if ((Gen.g_mode == SECMODE) || ((Hdr_type == USTAR || 3590 Hdr_type == TAR) && Thdr_p->tbuf.t_typeflag == 'A')) { 3591 /* this is an ancillary file */ 3592 off_t bytes; 3593 char *secp; 3594 int pad; 3595 int cnt; 3596 char *tp; 3597 int attrsize; 3598 3599 if (Pflag) { 3600 bytes = Gen.g_filesz; 3601 secp = e_zalloc(E_EXIT, (uint_t)bytes); 3602 tp = secp; 3603 3604 while (bytes > 0) { 3605 cnt = (int)(bytes > CPIOBSZ) ? CPIOBSZ : bytes; 3606 FILL(cnt); 3607 (void) memcpy(tp, Buffr.b_out_p, cnt); 3608 tp += cnt; 3609 Buffr.b_out_p += cnt; 3610 Buffr.b_cnt -= (off_t)cnt; 3611 bytes -= (off_t)cnt; 3612 } 3613 3614 pad = (Pad_val + 1 - (Gen.g_filesz & Pad_val)) & 3615 Pad_val; 3616 if (pad != 0) { 3617 FILL(pad); 3618 Buffr.b_out_p += pad; 3619 Buffr.b_cnt -= (off_t)pad; 3620 } 3621 3622 /* got all attributes in secp */ 3623 tp = secp; 3624 do { 3625 attr = (struct sec_attr *)tp; 3626 switch (attr->attr_type) { 3627 case UFSD_ACL: 3628 (void) sscanf(attr->attr_len, "%7lo", 3629 (ulong_t *)&aclcnt); 3630 /* header is 8 */ 3631 attrsize = 8 + 3632 strlen(&attr->attr_info[0]) 3633 + 1; 3634 aclp = aclfromtext(&attr->attr_info[0], 3635 &cnt); 3636 if (aclp == NULL) { 3637 msg(ERR, "aclfromtext failed"); 3638 break; 3639 } 3640 if (aclcnt != cnt) { 3641 msg(ERR, "acl count error"); 3642 break; 3643 } 3644 bytes -= attrsize; 3645 break; 3646 3647 /* SunFed case goes here */ 3648 3649 default: 3650 msg(EXT, "unrecognized attr type"); 3651 break; 3652 } 3653 /* next attributes */ 3654 tp += attrsize; 3655 } while (bytes > 0); 3656 free(secp); 3657 } else { 3658 /* skip security info */ 3659 G_p = &Gen; 3660 data_in(P_SKIP); 3661 } 3662 /* 3663 * We already got the file content, dont call file_in() 3664 * when return. The new return code(2) is used to 3665 * indicate that. 3666 */ 3667 VERBOSE((Args & OCt), Gen.g_nam_p); 3668 return (2); 3669 } /* acl */ 3670 3671 Adir = (ftype == S_IFDIR); 3672 Aspec = (ftype == S_IFBLK || ftype == S_IFCHR || ftype == S_IFIFO); 3673 3674 /* 3675 * Skip any trailing slashes 3676 */ 3677 chop_endslashes(Gen.g_nam_p); 3678 return (1); 3679 } 3680 3681 /* 3682 * getname: Get file names for inclusion in the archive. When end of file 3683 * on the input stream of file names is reached, flush the link buffer out. 3684 * For each filename, remove leading "./"s and multiple "/"s, and remove 3685 * any trailing newline "\n". Finally, verify the existance of the file, 3686 * and call creat_hdr() to fill in the gen_hdr structure. 3687 */ 3688 3689 static int 3690 getname(void) 3691 { 3692 int goodfile = 0, lastchar, err; 3693 char *s; 3694 char *dir; 3695 3696 Gen.g_nam_p = Nam_p; 3697 3698 while (!goodfile) { 3699 err = 0; 3700 3701 while ((s = fgets(Gen.g_nam_p, APATH+1, In_p)) 3702 != NULL) { 3703 lastchar = strlen(s) - 1; 3704 issymlink = 0; 3705 3706 if (s[lastchar] != '\n') { 3707 if (lastchar == APATH - 1) { 3708 if (!err) { 3709 msg(ERR, 3710 "%s name too long.", 3711 Nam_p); 3712 } 3713 goodfile = 0; 3714 err = 1; 3715 } else { 3716 break; 3717 } 3718 } else { 3719 s[lastchar] = '\0'; 3720 break; 3721 } 3722 } 3723 3724 if (s == (char *)NULL) { 3725 if (Gen.g_dirfd != -1) { 3726 (void) close(Gen.g_dirfd); 3727 Gen.g_dirfd = -1; 3728 } 3729 if (Onecopy && (Args & OCo)) { 3730 flush_lnks(); 3731 } 3732 return (0); 3733 } 3734 3735 while (*Gen.g_nam_p == '.' && Gen.g_nam_p[1] == '/') { 3736 Gen.g_nam_p += 2; 3737 while (*Gen.g_nam_p == '/') 3738 Gen.g_nam_p++; 3739 } 3740 3741 /* 3742 * Skip any trailing slashes 3743 */ 3744 chop_endslashes(Gen.g_nam_p); 3745 3746 /* 3747 * Figure out parent directory 3748 */ 3749 3750 if (Gen.g_attrnam_p != (char *)NULL) { 3751 if (Gen.g_dirfd != -1) { 3752 (void) close(Gen.g_dirfd); 3753 } 3754 Gen.g_dirfd = attropen(Gen.g_attrfnam_p, ".", O_RDONLY); 3755 if (Gen.g_dirfd == -1) { 3756 msg(ERRN, 3757 "Cannot open attribute directory" 3758 " of file %s", Gen.g_attrfnam_p); 3759 continue; 3760 } 3761 } else { 3762 #ifdef O_XATTR 3763 char dirpath[PATH_MAX]; 3764 3765 get_parent(Gen.g_nam_p, dirpath); 3766 if (Atflag) { 3767 dir = dirpath; 3768 if (Gen.g_dirfd != -1) { 3769 (void) close(Gen.g_dirfd); 3770 } 3771 Gen.g_dirfd = open(dir, O_RDONLY); 3772 if (Gen.g_dirfd == -1) { 3773 msg(ERRN, 3774 "Cannot open directory %s", dir); 3775 continue; 3776 } 3777 } else { 3778 /* 3779 * g_dirpath is the pathname cache maintaining 3780 * the dirname which is currently opened. 3781 * We first check the g_dirpath to see if the 3782 * given dirname matches. If so, we don't need 3783 * to open the dir, but we can use the g_dirfd 3784 * as is if it is still available. 3785 */ 3786 dir = NULL; 3787 if (Gen.g_dirpath == NULL || 3788 Gen.g_dirfd == -1) { 3789 /* 3790 * It's the first time or it has 3791 * all gone. 3792 */ 3793 dir = e_strdup(E_EXIT, dirpath); 3794 } else { 3795 if (strcmp(Gen.g_dirpath, 3796 dirpath) != 0) { 3797 /* different directory */ 3798 dir = e_strdup(E_EXIT, dirpath); 3799 } 3800 } 3801 if (dir != NULL) { 3802 /* 3803 * We need to open the new directory. 3804 * discard the pathname and dirfd 3805 * for the previous directory. 3806 */ 3807 if (Gen.g_dirpath != NULL) { 3808 free(Gen.g_dirpath); 3809 Gen.g_dirpath = NULL; 3810 } 3811 if (Gen.g_dirfd != -1) { 3812 (void) close(Gen.g_dirfd); 3813 } 3814 /* open the new dir */ 3815 Gen.g_dirfd = open(dir, O_RDONLY); 3816 if (Gen.g_dirfd == -1) { 3817 msg(ERRN, "Cannot open " 3818 "directory %s", dir); 3819 continue; 3820 } 3821 Gen.g_dirpath = dir; 3822 } 3823 } 3824 #else 3825 Gen.g_dirfd = -1; 3826 #endif 3827 } 3828 3829 /* creat_hdr checks for USTAR filename length */ 3830 3831 if (Hdr_type != USTAR && strlen(Gen.g_nam_p) > 3832 Max_namesz) { 3833 if (!err) { 3834 msg(ERR, "%s%s%s name too long.", 3835 (Gen.g_attrnam_p == (char *)NULL) ? 3836 Nam_p : Gen.g_attrfnam_p, 3837 (Gen.g_attrnam_p == (char *)NULL) ? 3838 "" : gettext(" Attribute "), 3839 (Gen.g_attrnam_p == (char *)NULL) ? 3840 "" : Gen.g_attrnam_p); 3841 } 3842 goodfile = 0; 3843 err = 1; 3844 } 3845 3846 if (err) { 3847 continue; 3848 } else { 3849 G_p = &Gen; 3850 if (!LSTAT(Gen.g_dirfd, Gen.g_nam_p, &SrcSt)) { 3851 goodfile = 1; 3852 3853 if ((SrcSt.st_mode & Ftype) == S_IFLNK) { 3854 issymlink = 1; 3855 3856 if ((Args & OCL)) { 3857 errno = 0; 3858 if (STAT(Gen.g_dirfd, 3859 G_p->g_nam_p, 3860 &SrcSt) < 0) { 3861 msg(ERRN, 3862 "Cannot follow" 3863 " \"%s%s%s\"", 3864 (Gen.g_attrnam_p == 3865 (char *)NULL) ? 3866 Gen.g_nam_p : 3867 Gen.g_attrfnam_p, 3868 (Gen.g_attrnam_p == 3869 (char *)NULL) ? 3870 "" : 3871 gettext( 3872 " Attribute "), 3873 (Gen.g_attrnam_p == 3874 (char *)NULL) ? 3875 "" : 3876 Gen.g_attrnam_p); 3877 goodfile = 0; 3878 } 3879 } 3880 } 3881 3882 if (Use_old_stat) { 3883 OldSt = convert_to_old_stat(&SrcSt, 3884 Gen.g_nam_p, Gen.g_attrnam_p); 3885 3886 if (OldSt == NULL) { 3887 goodfile = 0; 3888 } 3889 } 3890 } else { 3891 msg(ERRN, 3892 "Error with fstatat() of \"%s%s%s\"", 3893 (Gen.g_attrnam_p == (char *)NULL) ? 3894 Gen.g_nam_p : Gen.g_attrfnam_p, 3895 (Gen.g_attrnam_p == (char *)NULL) ? 3896 "" : gettext(" Attribute "), 3897 (Gen.g_attrnam_p == (char *)NULL) ? 3898 "" : Gen.g_attrnam_p); 3899 } 3900 } 3901 } 3902 3903 /* 3904 * Get ACL info: dont bother allocating space if there are only 3905 * standard permissions, i.e. ACL count < 4 3906 */ 3907 if ((SrcSt.st_mode & Ftype) != S_IFLNK && Pflag) { 3908 if ((aclcnt = acl(Gen.g_nam_p, GETACLCNT, 0, NULL)) < 0) 3909 msg(ERRN, "Error with acl() of \"%s\"", Gen.g_nam_p); 3910 if (aclcnt > MIN_ACL_ENTRIES) { 3911 aclp = e_zalloc(E_EXIT, sizeof (aclent_t) * aclcnt); 3912 3913 if (acl(Gen.g_nam_p, GETACL, aclcnt, aclp) < 0) { 3914 msg(ERRN, 3915 "Error with getacl() of \"%s\"", 3916 Gen.g_nam_p); 3917 free(aclp); 3918 aclp = NULL; 3919 } 3920 } 3921 /* else: only traditional permissions, so proceed as usual */ 3922 } 3923 if (creat_hdr()) 3924 return (1); 3925 else return (2); 3926 } 3927 3928 /* 3929 * getpats: Save any filenames/patterns specified as arguments. 3930 * Read additional filenames/patterns from the file specified by the 3931 * user. The filenames/patterns must occur one per line. 3932 */ 3933 3934 static void 3935 getpats(int largc, char **largv) 3936 { 3937 char **t_pp; 3938 size_t len; 3939 unsigned numpat = largc, maxpat = largc + 2; 3940 3941 Pat_pp = e_zalloc(E_EXIT, maxpat * sizeof (char *)); 3942 t_pp = Pat_pp; 3943 while (*largv) { 3944 *t_pp = e_zalloc(E_EXIT, strlen(*largv) + 1); 3945 (void) strcpy(*t_pp, *largv); 3946 t_pp++; 3947 largv++; 3948 } 3949 while (fgets(Nam_p, Max_namesz + 1, Ef_p) != (char *)NULL) { 3950 if (numpat == maxpat - 1) { 3951 maxpat += 10; 3952 Pat_pp = e_realloc(E_EXIT, Pat_pp, 3953 maxpat * sizeof (char *)); 3954 t_pp = Pat_pp + numpat; 3955 } 3956 len = strlen(Nam_p); /* includes the \n */ 3957 *(Nam_p + len - 1) = '\0'; /* remove the \n */ 3958 *t_pp = e_zalloc(E_EXIT, len); 3959 (void) strcpy(*t_pp, Nam_p); 3960 t_pp++; 3961 numpat++; 3962 } 3963 *t_pp = (char *)NULL; 3964 } 3965 3966 static void 3967 ioerror(int dir) 3968 { 3969 int t_errno; 3970 3971 t_errno = errno; 3972 errno = 0; 3973 if (fstat(Archive, &ArchSt) < 0) 3974 msg(EXTN, "Error during stat() of archive"); 3975 errno = t_errno; 3976 if ((ArchSt.st_mode & Ftype) != S_IFCHR) { 3977 if (dir) { 3978 if (errno == EFBIG) 3979 msg(EXT, "ulimit reached for output file."); 3980 else if (errno == ENOSPC) 3981 msg(EXT, "No space left for output file."); 3982 else 3983 msg(EXTN, "I/O error - cannot continue"); 3984 } else 3985 msg(EXT, "Unexpected end-of-file encountered."); 3986 } else 3987 msg(EXTN, "\007I/O error on \"%s\"", dir ? "output" : "input"); 3988 } 3989 3990 /* 3991 * matched: Determine if a filename matches the specified pattern(s). If the 3992 * pattern is matched (the second return), return 0 if -f was specified, else 3993 * return != 0. If the pattern is not matched (the first and third 3994 * returns), return 0 if -f was not specified, else return != 0. 3995 */ 3996 3997 static int 3998 matched(void) 3999 { 4000 char *str_p = G_p->g_nam_p; 4001 char **pat_pp = Pat_pp; 4002 int negatep, result; 4003 4004 /* 4005 * Check for attribute 4006 */ 4007 if (G_p->g_attrfnam_p != (char *)NULL) 4008 str_p = G_p->g_attrfnam_p; 4009 4010 for (pat_pp = Pat_pp; *pat_pp; pat_pp++) { 4011 negatep = (**pat_pp == '!'); 4012 4013 result = fnmatch(negatep ? (*pat_pp+1) : *pat_pp, str_p, 0); 4014 4015 if (result != 0 && result != FNM_NOMATCH) { 4016 msg(POST, "error matching file %s with pattern" 4017 " %s\n", str_p, *pat_pp); 4018 return (Args & OCf); 4019 } 4020 4021 if ((result == 0 && ! negatep) || 4022 (result == FNM_NOMATCH && negatep)) { 4023 /* match occured */ 4024 return (!(Args & OCf)); 4025 } 4026 } 4027 return (Args & OCf); /* not matched */ 4028 } 4029 4030 /* 4031 * missdir: Create missing directories for files. 4032 * (Possible future performance enhancement, if missdir is called, we know 4033 * that at least the very last directory of the path does not exist, therefore, 4034 * scan the path from the end 4035 */ 4036 4037 static int 4038 missdir(char *nam_p) 4039 { 4040 char *c_p; 4041 int cnt = 2; 4042 char *lastp; 4043 4044 if (*(c_p = nam_p) == '/') /* skip over 'root slash' */ 4045 c_p++; 4046 4047 lastp = c_p + strlen(nam_p) - 1; 4048 if (*lastp == '/') 4049 *lastp = '\0'; 4050 4051 for (; *c_p; ++c_p) { 4052 if (*c_p == '/') { 4053 *c_p = '\0'; 4054 if (stat(nam_p, &DesSt) < 0) { 4055 if (Args & OCd) { 4056 cnt = mkdir(nam_p, Def_mode); 4057 if (cnt != 0) { 4058 *c_p = '/'; 4059 return (cnt); 4060 } 4061 } else { 4062 msg(ERR, "Missing -d option."); 4063 *c_p = '/'; 4064 return (-1); 4065 } 4066 } 4067 *c_p = '/'; 4068 } 4069 } 4070 if (cnt == 2) /* the file already exists */ 4071 cnt = 0; 4072 return (cnt); 4073 } 4074 4075 /* 4076 * mklong: Convert two shorts into one long. For VAX, Interdata ... 4077 */ 4078 4079 static long 4080 mklong(short v[]) 4081 { 4082 4083 union swpbuf swp_b; 4084 4085 swp_b.s_word = 1; 4086 if (swp_b.s_byte[0]) { 4087 swp_b.s_half[0] = v[1]; 4088 swp_b.s_half[1] = v[0]; 4089 } else { 4090 swp_b.s_half[0] = v[0]; 4091 swp_b.s_half[1] = v[1]; 4092 } 4093 return (swp_b.s_word); 4094 } 4095 4096 /* 4097 * mkshort: Convert a long into 2 shorts, for VAX, Interdata ... 4098 */ 4099 4100 static void 4101 mkshort(short sval[], long v) 4102 { 4103 union swpbuf *swp_p, swp_b; 4104 4105 /* LINTED alignment */ 4106 swp_p = (union swpbuf *)sval; 4107 swp_b.s_word = 1; 4108 if (swp_b.s_byte[0]) { 4109 swp_b.s_word = v; 4110 swp_p->s_half[0] = swp_b.s_half[1]; 4111 swp_p->s_half[1] = swp_b.s_half[0]; 4112 } else { 4113 swp_b.s_word = v; 4114 swp_p->s_half[0] = swp_b.s_half[0]; 4115 swp_p->s_half[1] = swp_b.s_half[1]; 4116 } 4117 } 4118 4119 /* 4120 * msg: Print either a message (no error) (POST), an error message with or 4121 * without the errno (ERRN or ERR), or print an error message with or without 4122 * the errno and exit (EXTN or EXT). 4123 */ 4124 4125 static void 4126 msg(int severity, const char *fmt, ...) 4127 { 4128 FILE *file_p; 4129 va_list ap; 4130 4131 if ((Args & OCV) && Verbcnt) { /* clear current line of dots */ 4132 (void) fputc('\n', Out_p); 4133 Verbcnt = 0; 4134 } 4135 va_start(ap, fmt); 4136 if (severity == POST) 4137 file_p = Out_p; 4138 else 4139 if (severity == EPOST) 4140 file_p = Err_p; 4141 else { 4142 file_p = Err_p; 4143 Error_cnt++; 4144 } 4145 (void) fflush(Out_p); 4146 (void) fflush(Err_p); 4147 if ((severity != POST) && (severity != EPOST)) 4148 (void) fprintf(file_p, "cpio: "); 4149 4150 /* gettext replaces version of string */ 4151 4152 (void) vfprintf(file_p, gettext(fmt), ap); 4153 if (severity == ERRN || severity == EXTN) { 4154 (void) fprintf(file_p, ", errno %d, ", errno); 4155 perror(""); 4156 } else 4157 (void) fprintf(file_p, "\n"); 4158 (void) fflush(file_p); 4159 va_end(ap); 4160 if (severity == EXT || severity == EXTN) { 4161 (void) fprintf(file_p, gettext("%d errors\n"), Error_cnt); 4162 exit(EXIT_CODE); 4163 } 4164 } 4165 4166 /* 4167 * openout: Open files for output and set all necessary information. 4168 * If the u option is set (unconditionally overwrite existing files), 4169 * and the current file exists, get a temporary file name from mktemp(3C), 4170 * link the temporary file to the existing file, and remove the existing file. 4171 * Finally either creat(2), mkdir(2) or mknod(2) as appropriate. 4172 * 4173 */ 4174 4175 static int 4176 openout(int dirfd) 4177 { 4178 char *nam_p; 4179 int cnt, result; 4180 4181 Do_rename = 0; /* creat_tmp() may reset this */ 4182 4183 if (G_p->g_attrnam_p != (char *)NULL) { 4184 nam_p = G_p->g_attrnam_p; 4185 } else { 4186 if (Args & OCp) { 4187 nam_p = Fullnam_p; 4188 } else { 4189 nam_p = G_p->g_nam_p; 4190 } 4191 } 4192 4193 4194 if ((Max_filesz != RLIM_INFINITY) && 4195 (Max_filesz < (G_p->g_filesz >> 9))) { 4196 /* ... divided by 512 ... */ 4197 msg(ERR, "Skipping \"%s%s%s\": exceeds ulimit by %lld bytes", 4198 (G_p->g_attrnam_p == (char *)NULL) ? 4199 nam_p : G_p->g_attrfnam_p, 4200 (G_p->g_attrnam_p == (char *)NULL) ? 4201 "" : gettext(" Attribute "), 4202 (G_p->g_attrnam_p == (char *)NULL) ? 4203 "" : nam_p, 4204 (off_t)(G_p->g_filesz - (Max_filesz << 9))); 4205 return (-1); 4206 } 4207 4208 if (LSTAT(dirfd, nam_p, &DesSt) == 0) { 4209 /* 4210 * A file by the same name exists. Move it to a temporary 4211 * file. 4212 */ 4213 4214 if (creat_tmp(nam_p) < 0) { 4215 /* 4216 * We weren't able to create the temp file. Report 4217 * failure. 4218 */ 4219 4220 return (-1); 4221 } 4222 } 4223 4224 if (Do_rename) { 4225 /* nam_p was changed by creat_tmp() above. */ 4226 4227 if (Args & OCp) { 4228 if (G_p->g_attrnam_p != (char *)NULL) { 4229 nam_p = Attrfile_p; 4230 } else { 4231 nam_p = Fullnam_p; 4232 } 4233 } else { 4234 nam_p = G_p->g_nam_p; 4235 } 4236 } 4237 4238 /* 4239 * This pile tries to create the file directly, and, if there is a 4240 * problem, creates missing directories, and then tries to create the 4241 * file again. Two strikes and you're out. 4242 * 4243 * On XATTR system, the directory has already been created by 4244 * open_dirfd(), so error shouldn't happen in the loop. However, 4245 * on non-XATTR system, symlink/open may fail with ENOENT. In such 4246 * case, we go to create missing directories. 4247 */ 4248 4249 cnt = 0; 4250 4251 do { 4252 errno = 0; 4253 4254 if (Hdr_type == TAR && Thdr_p->tbuf.t_typeflag == SYMTYPE) { 4255 /* The archive file is a TAR symlink. */ 4256 if ((result = 4257 symlink(Thdr_p->tbuf.t_linkname, nam_p)) >= 0) { 4258 cnt = 0; 4259 if (Over_p != NULL) { 4260 (void) unlinkat(dirfd, 4261 get_component(Over_p), 0); 4262 *Over_p = '\0'; 4263 } 4264 break; 4265 } else if (errno != ENOENT) { 4266 /* The attempt to symlink failed. */ 4267 msg(ERRN, 4268 "Cannot create symbolic link \"%s\" -> " 4269 "\"%s\"", 4270 Thdr_p->tbuf.t_linkname, nam_p); 4271 4272 if (*Over_p != '\0') { 4273 rstfiles(U_KEEP, dirfd); 4274 } 4275 return (-1); 4276 } 4277 } else if (Hdr_type == BAR && bar_linkflag == SYMTYPE) { 4278 if ((result = symlink(bar_linkname, nam_p)) >= 0) { 4279 cnt = 0; 4280 if (Over_p != NULL) { 4281 (void) unlinkat(dirfd, 4282 get_component(Over_p), 0); 4283 *Over_p = '\0'; 4284 } 4285 break; 4286 } else if (errno != ENOENT) { 4287 /* The attempt to symlink failed. */ 4288 msg(ERRN, 4289 "Cannot create symbolic link \"%s\" -> " 4290 "\"%s\"", 4291 bar_linkname, nam_p); 4292 if (*Over_p != '\0') { 4293 rstfiles(U_KEEP, dirfd); 4294 } 4295 return (-1); 4296 } 4297 } else if ((G_p->g_mode & Ftype) == S_IFLNK) { 4298 if ((!(Args & OCp)) && !(Hdr_type == USTAR)) { 4299 (void) strncpy(Symlnk_p, 4300 Buffr.b_out_p, G_p->g_filesz); 4301 *(Symlnk_p + G_p->g_filesz) = '\0'; 4302 } else if ((!(Args & OCp)) && (Hdr_type == USTAR)) { 4303 Symlnk_p[NAMSIZ] = '\0'; 4304 (void) strncpy(Symlnk_p, 4305 &Thdr_p->tbuf.t_linkname[0], NAMSIZ); 4306 } 4307 if ((result = symlink(Symlnk_p, nam_p)) >= 0) { 4308 cnt = 0; 4309 if (Over_p != NULL) { 4310 (void) unlinkat(dirfd, 4311 get_component(Over_p), 0); 4312 *Over_p = '\0'; 4313 } 4314 break; 4315 } else if (errno != ENOENT) { 4316 /* The attempt to symlink failed. */ 4317 msg(ERRN, 4318 "Cannot create symbolic link \"%s\" -> " 4319 "\"%s\"", 4320 Symlnk_p, nam_p); 4321 4322 if (*Over_p != '\0') { 4323 rstfiles(U_KEEP, dirfd); 4324 } 4325 return (-1); 4326 } 4327 } else { 4328 if ((result = openat(dirfd, get_component(nam_p), 4329 O_CREAT|O_RDWR|O_TRUNC, (int)G_p->g_mode)) >= 0) { 4330 /* acl support */ 4331 acl_set = 0; 4332 if (Pflag && aclp != NULL) { 4333 if (facl(result, SETACL, aclcnt, aclp) 4334 < 0) { 4335 msg(ERRN, 4336 "\"%s\": failed to set acl", 4337 nam_p); 4338 } else { 4339 acl_set = 1; 4340 } 4341 free(aclp); 4342 aclp = NULL; 4343 } 4344 cnt = 0; 4345 break; 4346 } else if (errno != ENOENT) { 4347 /* The attempt to open failed. */ 4348 msg(ERRN, "Cannot open file \"%s\"", nam_p); 4349 if (*Over_p != '\0') { 4350 rstfiles(U_KEEP, dirfd); 4351 } 4352 return (-1); 4353 } 4354 } 4355 cnt++; 4356 } while (cnt < 2 && missdir(nam_p) == 0); 4357 4358 switch (cnt) { 4359 case 0: 4360 if ((Args & OCi) && (Hdr_type == USTAR)) { 4361 setpasswd(nam_p); 4362 } 4363 4364 if ((G_p->g_mode & Ftype) == S_IFLNK || 4365 (Hdr_type == BAR && bar_linkflag == SYMTYPE)) { 4366 if (fchownat(dirfd, get_component(nam_p), 4367 (int)G_p->g_uid, (int)G_p->g_gid, 4368 AT_SYMLINK_NOFOLLOW) < 0) { 4369 if ((Euid == 0) || (Args & OCR)) { 4370 msg(ERRN, 4371 "Error during chown() of " 4372 "\"%s%s%s\"", 4373 (G_p->g_attrnam_p == (char *)NULL) ? 4374 nam_p : G_p->g_attrfnam_p, 4375 (G_p->g_attrnam_p == (char *)NULL) ? 4376 "" : gettext(" Attribute "), 4377 (G_p->g_attrnam_p == (char *)NULL) ? 4378 "" : nam_p); 4379 } 4380 } 4381 4382 break; 4383 } 4384 4385 if (fchownat(dirfd, get_component(nam_p), 4386 (int)G_p->g_uid, (int)G_p->g_gid, 0) < 0) { 4387 if ((Euid == 0) || (Args & OCR)) { 4388 msg(ERRN, 4389 "Error during chown() of \"%s%s%s\"", 4390 (G_p->g_attrnam_p == (char *)NULL) ? 4391 nam_p : G_p->g_attrfnam_p, 4392 (G_p->g_attrnam_p == (char *)NULL) ? 4393 "" : gettext(" Attribute "), 4394 (G_p->g_attrnam_p == (char *)NULL) ? 4395 "" : nam_p); 4396 } 4397 } 4398 4399 break; 4400 4401 case 1: 4402 if (Do_rename) { 4403 msg(ERRN, "Cannot create directory for \"%s%s%s\"", 4404 (G_p->g_attrnam_p == (char *)NULL) ? Over_p : 4405 G_p->g_attrfnam_p, 4406 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4407 gettext(" Attribute "), 4408 (G_p->g_attrnam_p == (char *)NULL) ? "" : Over_p); 4409 } else { 4410 msg(ERRN, "Cannot create directory for \"%s%s%s\"", 4411 (G_p->g_attrnam_p == (char *)NULL) ? nam_p : 4412 G_p->g_attrfnam_p, 4413 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4414 gettext(" Attribute "), 4415 (G_p->g_attrnam_p == (char *)NULL) ? "" : nam_p); 4416 } 4417 break; 4418 4419 case 2: 4420 if (Do_rename) { 4421 msg(ERRN, "Cannot create \"%s%s%s\"", 4422 (G_p->g_attrnam_p == (char *)NULL) ? Over_p : 4423 G_p->g_attrfnam_p, 4424 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4425 gettext(" Attribute "), 4426 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4427 Over_p); 4428 } else { 4429 msg(ERRN, "Cannot create \"%s%s%s\"", 4430 (G_p->g_attrnam_p == (char *)NULL) ? nam_p : 4431 G_p->g_attrfnam_p, 4432 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4433 gettext(" Attribute "), 4434 (G_p->g_attrnam_p == (char *)NULL) ? "" : 4435 nam_p); 4436 } 4437 break; 4438 4439 default: 4440 msg(EXT, "Impossible case."); 4441 } 4442 4443 Finished = 0; 4444 return (result); 4445 } 4446 4447 /* 4448 * read_hdr: Transfer headers from the selected format 4449 * in the archive I/O buffer to the generic structure. 4450 */ 4451 4452 static 4453 int 4454 read_hdr(int hdr) 4455 { 4456 int rv = NONE; 4457 major_t maj, rmaj; 4458 minor_t min, rmin; 4459 char tmpnull; 4460 static int bar_read_cnt = 0; 4461 4462 if (hdr != BAR) { 4463 if (Buffr.b_end_p != (Buffr.b_out_p + Hdrsz)) { 4464 tmpnull = *(Buffr.b_out_p + Hdrsz); 4465 *(Buffr.b_out_p + Hdrsz) = '\0'; 4466 } 4467 } 4468 4469 switch (hdr) { 4470 case BIN: 4471 (void) memcpy(&Hdr, Buffr.b_out_p, HDRSZ); 4472 if (Hdr.h_magic == (short)CMN_BBS) { 4473 swap((char *)&Hdr, HDRSZ); 4474 } 4475 Gen.g_magic = Hdr.h_magic; 4476 Gen.g_mode = Hdr.h_mode; 4477 Gen.g_uid = Hdr.h_uid; 4478 Gen.g_gid = Hdr.h_gid; 4479 Gen.g_nlink = Hdr.h_nlink; 4480 Gen.g_mtime = mklong(Hdr.h_mtime); 4481 Gen.g_ino = Hdr.h_ino; 4482 Gen.g_dev = Hdr.h_dev; 4483 Gen.g_rdev = Hdr.h_rdev; 4484 Gen.g_cksum = 0L; 4485 Gen.g_filesz = (off_t)mklong(Hdr.h_filesize); 4486 Gen.g_namesz = Hdr.h_namesize; 4487 rv = BIN; 4488 break; 4489 case CHR: 4490 if (sscanf(Buffr.b_out_p, 4491 "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6o%11llo", 4492 &Gen.g_magic, &Gen.g_dev, &Gen.g_ino, &Gen.g_mode, 4493 &Gen.g_uid, &Gen.g_gid, &Gen.g_nlink, &Gen.g_rdev, 4494 (ulong_t *)&Gen.g_mtime, (uint_t *)&Gen.g_namesz, 4495 (u_off_t *)&Gen.g_filesz) == CHR_CNT) { 4496 rv = CHR; 4497 #define cpioMAJOR(x) (int)(((unsigned)x >> 8) & 0x7F) 4498 #define cpioMINOR(x) (int)(x & 0xFF) 4499 maj = cpioMAJOR(Gen.g_dev); 4500 rmaj = cpioMAJOR(Gen.g_rdev); 4501 min = cpioMINOR(Gen.g_dev); 4502 rmin = cpioMINOR(Gen.g_rdev); 4503 if (Use_old_stat) { 4504 /* needs error checking */ 4505 Gen.g_dev = (maj << 8) | min; 4506 Gen.g_rdev = (rmaj << 8) | rmin; 4507 } else { 4508 Gen.g_dev = makedev(maj, min); 4509 Gen.g_rdev = makedev(rmaj, rmin); 4510 } 4511 } 4512 break; 4513 case ASC: 4514 case CRC: 4515 if (sscanf(Buffr.b_out_p, 4516 "%6lx%8lx%8lx%8lx%8lx%8lx%8lx%8llx%8x%8x%8x%8x%8x%8lx", 4517 &Gen.g_magic, &Gen.g_ino, &Gen.g_mode, &Gen.g_uid, 4518 &Gen.g_gid, &Gen.g_nlink, &Gen.g_mtime, 4519 (u_off_t *)&Gen.g_filesz, (uint_t *)&maj, (uint_t *)&min, 4520 (uint_t *)&rmaj, (uint_t *)&rmin, (uint_t *)&Gen.g_namesz, 4521 &Gen.g_cksum) == ASC_CNT) { 4522 Gen.g_dev = makedev(maj, min); 4523 Gen.g_rdev = makedev(rmaj, rmin); 4524 rv = hdr; 4525 } 4526 break; 4527 case USTAR: /* TAR and USTAR */ 4528 if (*Buffr.b_out_p == '\0') { 4529 *Gen.g_nam_p = '\0'; 4530 nambuf[0] = '\0'; 4531 } else { 4532 Thdr_p = (union tblock *)Buffr.b_out_p; 4533 Gen.g_nam_p[0] = '\0'; 4534 (void) strncpy((char *)&nambuf, 4535 Thdr_p->tbuf.t_name, NAMSIZ); 4536 (void) sscanf(Thdr_p->tbuf.t_mode, "%8lo", 4537 &Gen.g_mode); 4538 (void) sscanf(Thdr_p->tbuf.t_uid, "%8lo", &Gen.g_uid); 4539 (void) sscanf(Thdr_p->tbuf.t_gid, "%8lo", &Gen.g_gid); 4540 (void) sscanf(Thdr_p->tbuf.t_size, "%11llo", 4541 (u_off_t *)&Gen.g_filesz); 4542 (void) sscanf(Thdr_p->tbuf.t_mtime, "%12lo", 4543 (ulong_t *)&Gen.g_mtime); 4544 (void) sscanf(Thdr_p->tbuf.t_cksum, "%8lo", 4545 (ulong_t *)&Gen.g_cksum); 4546 if (Thdr_p->tbuf.t_linkname[0] != (char)NULL) 4547 Gen.g_nlink = 1; 4548 else 4549 Gen.g_nlink = 0; 4550 4551 switch (Thdr_p->tbuf.t_typeflag) { 4552 case SYMTYPE: 4553 /* Symbolic Link */ 4554 Gen.g_nlink = 2; 4555 break; 4556 case CHRTYPE: 4557 Gen.g_mode |= (S_IFMT & S_IFCHR); 4558 break; 4559 case BLKTYPE: 4560 Gen.g_mode |= (S_IFMT & S_IFBLK); 4561 break; 4562 case DIRTYPE: 4563 Gen.g_mode |= (S_IFMT & S_IFDIR); 4564 break; 4565 case FIFOTYPE: 4566 Gen.g_mode |= (S_IFMT & S_IFIFO); 4567 break; 4568 } 4569 4570 (void) sscanf(Thdr_p->tbuf.t_magic, "%8lo", 4571 /* LINTED alignment */ 4572 (ulong_t *)&Gen.g_tmagic); 4573 (void) sscanf(Thdr_p->tbuf.t_version, "%8lo", 4574 /* LINTED alignment */ 4575 (ulong_t *)&Gen.g_version); 4576 (void) sscanf(Thdr_p->tbuf.t_uname, "%32s", 4577 (char *)&Gen.g_uname); 4578 (void) sscanf(Thdr_p->tbuf.t_gname, "%32s", 4579 (char *)&Gen.g_gname); 4580 (void) sscanf(Thdr_p->tbuf.t_devmajor, "%8lo", 4581 &Gen.g_dev); 4582 (void) sscanf(Thdr_p->tbuf.t_devminor, "%8lo", 4583 &Gen.g_rdev); 4584 (void) strncpy((char *)&prebuf, 4585 Thdr_p->tbuf.t_prefix, PRESIZ); 4586 Gen.g_namesz = strlen(Gen.g_nam_p) + 1; 4587 Gen.g_dev = makedev(maj, min); 4588 } 4589 rv = USTAR; 4590 break; 4591 case TAR: 4592 if (*Buffr.b_out_p == '\0') { 4593 *Gen.g_nam_p = '\0'; 4594 nambuf[0] = '\0'; 4595 } else { 4596 Thdr_p = (union tblock *)Buffr.b_out_p; 4597 Gen.g_nam_p[0] = '\0'; 4598 (void) sscanf(Thdr_p->tbuf.t_mode, "%lo", &Gen.g_mode); 4599 (void) sscanf(Thdr_p->tbuf.t_uid, "%lo", &Gen.g_uid); 4600 (void) sscanf(Thdr_p->tbuf.t_gid, "%lo", &Gen.g_gid); 4601 (void) sscanf(Thdr_p->tbuf.t_size, "%llo", 4602 (u_off_t *)&Gen.g_filesz); 4603 (void) sscanf(Thdr_p->tbuf.t_mtime, "%lo", 4604 &Gen.g_mtime); 4605 (void) sscanf(Thdr_p->tbuf.t_cksum, "%lo", 4606 &Gen.g_cksum); 4607 if (Thdr_p->tbuf.t_typeflag == '1') /* hardlink */ 4608 Gen.g_nlink = 1; 4609 else 4610 Gen.g_nlink = 0; 4611 (void) strncpy(Gen.g_nam_p, 4612 Thdr_p->tbuf.t_name, NAMSIZ); 4613 Gen.g_namesz = strlen(Gen.g_nam_p) + 1; 4614 (void) strcpy(nambuf, Gen.g_nam_p); 4615 } 4616 rv = TAR; 4617 break; 4618 case BAR: 4619 if (Bar_vol_num == 0 && bar_read_cnt == 0) { 4620 read_bar_vol_hdr(); 4621 bar_read_cnt++; 4622 } 4623 else 4624 read_bar_file_hdr(); 4625 rv = BAR; 4626 break; 4627 default: 4628 msg(EXT, "Impossible header type."); 4629 } 4630 4631 if (hdr != BAR) { 4632 if (Buffr.b_end_p != (Buffr.b_out_p + Hdrsz)) 4633 *(Buffr.b_out_p + Hdrsz) = tmpnull; 4634 } 4635 4636 return (rv); 4637 } 4638 4639 /* 4640 * reclaim: Reclaim linked file structure storage. 4641 */ 4642 4643 static void 4644 reclaim(struct Lnk *p) 4645 { 4646 p->L_bck_p->L_nxt_p = p->L_nxt_p; 4647 p->L_nxt_p->L_bck_p = p->L_bck_p; 4648 4649 while (p != NULL) { 4650 struct Lnk *new_p = p->L_lnk_p; 4651 4652 free(p->L_gen.g_nam_p); 4653 free(p); 4654 p = new_p; 4655 } 4656 } 4657 4658 /* 4659 * rstbuf: Reset the I/O buffer, move incomplete potential headers to 4660 * the front of the buffer and force bread() to refill the buffer. The 4661 * return value from bread() is returned (to identify I/O errors). On the 4662 * 3B2, reads must begin on a word boundary, therefore, with the -i option, 4663 * any remaining bytes in the buffer must be moved to the base of the buffer 4664 * in such a way that the destination locations of subsequent reads are 4665 * word aligned. 4666 */ 4667 4668 static void 4669 rstbuf(void) 4670 { 4671 int pad; 4672 4673 if ((Args & OCi) || Append) { 4674 if (Buffr.b_out_p != Buffr.b_base_p) { 4675 pad = ((Buffr.b_cnt + FULLWD) & ~FULLWD); 4676 Buffr.b_in_p = Buffr.b_base_p + pad; 4677 pad -= Buffr.b_cnt; 4678 (void) memcpy(Buffr.b_base_p + pad, Buffr.b_out_p, 4679 (int)Buffr.b_cnt); 4680 Buffr.b_out_p = Buffr.b_base_p + pad; 4681 } 4682 if (bfill() < 0) 4683 msg(EXT, "Unexpected end-of-archive encountered."); 4684 } else { /* OCo */ 4685 (void) memcpy(Buffr.b_base_p, Buffr.b_out_p, (int)Buffr.b_cnt); 4686 Buffr.b_out_p = Buffr.b_base_p; 4687 Buffr.b_in_p = Buffr.b_base_p + Buffr.b_cnt; 4688 } 4689 } 4690 4691 static void 4692 setpasswd(char *nam) 4693 { 4694 if ((dpasswd = getpwnam(&Gen.g_uname[0])) == (struct passwd *)NULL) { 4695 msg(EPOST, "cpio: problem reading passwd entry"); 4696 msg(EPOST, "cpio: %s: owner not changed", nam); 4697 if (Gen.g_uid == UID_NOBODY && S_ISREG(Gen.g_mode)) 4698 Gen.g_mode &= ~S_ISUID; 4699 } else 4700 Gen.g_uid = dpasswd->pw_uid; 4701 4702 if ((dgroup = getgrnam(&Gen.g_gname[0])) == (struct group *)NULL) { 4703 msg(EPOST, "cpio: problem reading group entry"); 4704 msg(EPOST, "cpio: %s: group not changed", nam); 4705 if (Gen.g_gid == GID_NOBODY && S_ISREG(Gen.g_mode)) 4706 Gen.g_mode &= ~S_ISGID; 4707 } else 4708 Gen.g_gid = dgroup->gr_gid; 4709 G_p = &Gen; 4710 } 4711 4712 /* 4713 * rstfiles: Perform final changes to the file. If the -u option is set, 4714 * and overwrite == U_OVER, remove the temporary file, else if overwrite 4715 * == U_KEEP, unlink the current file, and restore the existing version 4716 * of the file. In addition, where appropriate, set the access or modification 4717 * times, change the owner and change the modes of the file. 4718 * 4719 * Note that if Do_rename is set, then the roles of original and temporary 4720 * file are reversed. If all went well, we will rename() the temporary file 4721 * over the original in order to accomodate potentially executing files. 4722 */ 4723 static void 4724 rstfiles(int over, int dirfd) 4725 { 4726 char *inam_p, *onam_p, *nam_p; 4727 int error; 4728 4729 if (Args & OCp) { 4730 if (G_p->g_attrnam_p == (char *)NULL) { 4731 nam_p = Fullnam_p; 4732 } else { 4733 nam_p = G_p->g_attrnam_p; 4734 } 4735 } else { 4736 if (Gen.g_nlink > (ulong_t)0) { 4737 nam_p = G_p->g_nam_p; 4738 } else { 4739 nam_p = Gen.g_nam_p; 4740 } 4741 } 4742 if (Gen.g_attrnam_p != (char *)NULL) { 4743 nam_p = Gen.g_attrnam_p; 4744 } 4745 4746 if ((Args & OCi) && (Hdr_type == USTAR)) { 4747 setpasswd(nam_p); 4748 } 4749 if (over == U_KEEP && *Over_p != '\0') { 4750 if (Do_rename) { 4751 msg(POST, "Restoring existing \"%s%s%s\"", 4752 (G_p->g_attrnam_p == (char *)NULL) ? 4753 Over_p : Fullnam_p, 4754 (G_p->g_attrnam_p == (char *)NULL) ? 4755 "" : gettext(" Attribute "), 4756 (G_p->g_attrnam_p == (char *)NULL) ? 4757 "" : Over_p); 4758 } else { 4759 msg(POST, "Restoring existing \"%s%s%s\"", 4760 (G_p->g_attrnam_p == (char *)NULL) ? 4761 nam_p : Fullnam_p, 4762 (G_p->g_attrnam_p == (char *)NULL) ? 4763 "" : gettext(" Attribute "), 4764 (G_p->g_attrnam_p == (char *)NULL) ? 4765 "" : nam_p); 4766 } 4767 4768 /* delete what we just built */ 4769 (void) unlinkat(dirfd, get_component(nam_p), 0); 4770 4771 /* If the old file needs restoring, do the necessary links */ 4772 if (Do_rename) { 4773 char *tmp_ptr; 4774 4775 if (Args & OCp) { 4776 tmp_ptr = Fullnam_p; 4777 Fullnam_p = Over_p; 4778 } else { 4779 tmp_ptr = G_p->g_nam_p; 4780 G_p->g_nam_p = Over_p; 4781 } 4782 Over_p = tmp_ptr; 4783 4784 Do_rename = 0; /* names now have original values */ 4785 } else { 4786 if (rename(Over_p, nam_p) < 0) { 4787 if (link(Over_p, nam_p) < 0) { 4788 msg(EXTN, 4789 "Cannot recover original version" 4790 " of \"%s%s%s\"", 4791 (G_p->g_attrnam_p == (char *)NULL) ? 4792 nam_p : Fullnam_p, 4793 (G_p->g_attrnam_p == (char *)NULL) ? 4794 "" : gettext(" Attribute "), 4795 (G_p->g_attrnam_p == (char *)NULL) ? 4796 "" : nam_p); 4797 } 4798 if (unlinkat(dirfd, get_component(Over_p), 0)) { 4799 msg(ERRN, 4800 "Cannot remove temp file " 4801 "\"%s%s%s\"", 4802 (G_p->g_attrnam_p == (char *)NULL) ? 4803 Over_p : Fullnam_p, 4804 (G_p->g_attrnam_p == (char *)NULL) ? 4805 "" : gettext(" Attribute "), 4806 (G_p->g_attrnam_p == (char *)NULL) ? 4807 "" : Over_p); 4808 } 4809 } 4810 } 4811 *Over_p = '\0'; 4812 return; 4813 } else if (over == U_OVER && *Over_p != '\0') { 4814 if (Do_rename) { 4815 char *tmp_ptr; 4816 4817 (void) renameat(dirfd, get_component(nam_p), 4818 dirfd, get_component(Over_p)); 4819 if (Args & OCp) { 4820 if (G_p->g_attrnam_p == (char *)NULL) { 4821 tmp_ptr = Fullnam_p; 4822 Fullnam_p = Over_p; 4823 Over_p = tmp_ptr; 4824 } else { 4825 /* 4826 * Over_p is pointing at g_attrnam_p 4827 * which must be preserved. 4828 * 4829 * We don't want the tmp_ptr and so 4830 * on to throw away our only copy of 4831 * the name. 4832 */ 4833 Over_p = Attrfile_p; 4834 } 4835 } else { 4836 tmp_ptr = G_p->g_nam_p; 4837 G_p->g_nam_p = Over_p; 4838 Over_p = tmp_ptr; 4839 } 4840 Do_rename = 0; /* names now have original values */ 4841 } else { 4842 if (unlinkat(dirfd, get_component(Over_p), 0) < 0) { 4843 msg(ERRN, 4844 "Cannot unlink() temp file \"%s%s%s\"", 4845 (G_p->g_attrnam_p == (char *)NULL) ? 4846 Over_p : Fullnam_p, 4847 (G_p->g_attrnam_p == (char *)NULL) ? 4848 "" : gettext(" Attribute "), 4849 (G_p->g_attrnam_p == (char *)NULL) ? 4850 "" : Over_p); 4851 } 4852 } 4853 *Over_p = '\0'; 4854 } 4855 if (Args & OCp) { 4856 if (G_p->g_attrnam_p != (char *)NULL) { 4857 inam_p = G_p->g_attrfnam_p; 4858 onam_p = G_p->g_attrnam_p; 4859 } else { 4860 inam_p = Nam_p; 4861 onam_p = Fullnam_p; 4862 } 4863 } else /* OCi only uses onam_p, OCo only uses inam_p */ 4864 if (G_p->g_attrnam_p != (char *)NULL) { 4865 inam_p = onam_p = G_p->g_attrnam_p; 4866 } else { 4867 inam_p = onam_p = G_p->g_nam_p; 4868 } 4869 4870 /* 4871 * change the modes back to the ones originally created in the 4872 * archive 4873 */ 4874 if (Args & OCi) { 4875 mode_t orig_mask, new_mask; 4876 struct stat sbuf; 4877 4878 if (!(Pflag && acl_set)) { 4879 /* Acl was not set, so we must chmod */ 4880 if (LSTAT(dirfd, G_p->g_nam_p, &sbuf) == 0) { 4881 if ((sbuf.st_mode & Ftype) != S_IFLNK) { 4882 orig_mask = umask(0); 4883 new_mask = G_p->g_mode & ~orig_mask; 4884 4885 /* 4886 * use fchmod for attributes, since 4887 * we known they are always regular 4888 * files, whereas when it isn't an 4889 * attribute it could be for a fifo 4890 * or something other that we don't 4891 * open and don't have a valid Ofile 4892 * for. 4893 */ 4894 if (G_p->g_attrnam_p != (char *)NULL) { 4895 error = fchmod(Ofile, new_mask); 4896 } else { 4897 error = chmod(G_p->g_nam_p, 4898 new_mask); 4899 } 4900 if (error < 0) { 4901 msg(ERRN, 4902 "Cannot chmod() \"%s%s%s\"", 4903 (G_p->g_attrnam_p == 4904 (char *)NULL) ? 4905 G_p->g_nam_p : 4906 G_p->g_attrfnam_p, 4907 (G_p->g_attrnam_p == 4908 (char *)NULL) ? 4909 "" : gettext( 4910 " Attribute "), 4911 (G_p->g_attrnam_p == 4912 (char *)NULL) ? 4913 "" : G_p->g_attrnam_p); 4914 } 4915 (void) umask(orig_mask); 4916 } 4917 } 4918 } 4919 } 4920 4921 if (!(Args & OCo)) { 4922 if (Args & OCm) { 4923 set_tym(dirfd, get_component(onam_p), 4924 G_p->g_mtime, G_p->g_mtime); 4925 } 4926 if (!acl_set) { 4927 if (G_p->g_attrnam_p != (char *)NULL) { 4928 error = fchmod(Ofile, (int)G_p->g_mode); 4929 } else { 4930 error = chmod(onam_p, (int)G_p->g_mode); 4931 } 4932 if ((error < 0) && ((Euid == 0) || (Args & OCR))) { 4933 msg(ERRN, "Cannot chmod() \"%s%s%s\"", onam_p, 4934 (G_p->g_attrnam_p == (char *)NULL) ? 4935 "" : gettext(" Attribute "), 4936 (G_p->g_attrnam_p == (char *)NULL) ? 4937 "" : onam_p); 4938 } 4939 } 4940 if ((Args & OCR) && 4941 (fchownat(dirfd, get_component(onam_p), Rpw_p->pw_uid, 4942 Rpw_p->pw_gid, 0) < 0)) { 4943 msg(ERRN, "Cannot chown() \"%s%s%s\"", 4944 onam_p, 4945 (G_p->g_attrnam_p == (char *)NULL) ? 4946 "" : gettext(" Attribute "), 4947 (G_p->g_attrnam_p == (char *)NULL) ? 4948 "" : onam_p); 4949 } 4950 } 4951 4952 if (!(Args & OCi) && (Args & OCa)) { 4953 /* 4954 * Use dirfd since we are updating original file 4955 * and not just created file 4956 */ 4957 set_tym(G_p->g_dirfd, get_component(inam_p), 4958 (ulong_t)SrcSt.st_atime, (ulong_t)SrcSt.st_mtime); 4959 } 4960 4961 if ((Args & OCp) && !(Args & OCR)) { 4962 if (fchownat(dirfd, get_component(onam_p), 4963 G_p->g_uid, G_p->g_gid, 0) < 0) { 4964 if (Euid == 0) { 4965 msg(ERRN, "Cannot chown() \"%s%s%s\"", 4966 onam_p, 4967 (G_p->g_attrnam_p == (char *)NULL) ? 4968 "" : gettext(" Attribute "), 4969 (G_p->g_attrnam_p == (char *)NULL) ? 4970 "" : onam_p); 4971 } 4972 } 4973 } else { 4974 /* OCi only uses onam_p, OCo only uses inam_p */ 4975 if (!(Args & OCR)) { 4976 if ((Args & OCi) && (fchownat(dirfd, 4977 get_component(inam_p), G_p->g_uid, 4978 G_p->g_gid, 0) < 0)) { 4979 if (Euid == 0) { 4980 msg(ERRN, "Cannot chown() \"%s%s%s\"", 4981 onam_p, 4982 (G_p->g_attrnam_p == (char *)NULL) ? 4983 "" : gettext(" Attribute "), 4984 (G_p->g_attrnam_p == (char *)NULL) ? 4985 "" : onam_p); 4986 } 4987 } 4988 } 4989 } 4990 } 4991 4992 /* 4993 * scan4trail: Scan the archive looking for the trailer. 4994 * When found, back the archive up over the trailer and overwrite 4995 * the trailer with the files to be added to the archive. 4996 */ 4997 4998 static void 4999 scan4trail(void) 5000 { 5001 int rv; 5002 off_t off1, off2; 5003 5004 Append = 1; 5005 Hdr_type = NONE; 5006 G_p = (struct gen_hdr *)NULL; 5007 while (gethdr()) { 5008 G_p = &Gen; 5009 data_in(P_SKIP); 5010 } 5011 off1 = Buffr.b_cnt; 5012 off2 = Bufsize - (Buffr.b_cnt % Bufsize); 5013 Buffr.b_out_p = Buffr.b_in_p = Buffr.b_base_p; 5014 Buffr.b_cnt = (off_t)0; 5015 if (lseek(Archive, -(off1 + off2), SEEK_REL) < 0) 5016 msg(EXTN, "Unable to append to this archive"); 5017 if ((rv = g_read(Device, Archive, Buffr.b_in_p, Bufsize)) < 0) 5018 msg(EXTN, "Cannot append to this archive"); 5019 if (lseek(Archive, (off_t)-rv, SEEK_REL) < 0) 5020 msg(EXTN, "Unable to append to this archive"); 5021 Buffr.b_cnt = off2; 5022 Buffr.b_in_p = Buffr.b_base_p + Buffr.b_cnt; 5023 Append = 0; 5024 } 5025 5026 /* 5027 * setup: Perform setup and initialization functions. Parse the options 5028 * using getopt(3C), call ckopts to check the options and initialize various 5029 * structures and pointers. Specifically, for the -i option, save any 5030 * patterns, for the -o option, check (via stat(2)) the archive, and for 5031 * the -p option, validate the destination directory. 5032 */ 5033 5034 static void 5035 setup(int largc, char **largv) 5036 { 5037 extern int optind; 5038 extern char *optarg; 5039 5040 #if defined(O_XATTR) 5041 #ifdef WAITAROUND 5042 char *opts_p = "zabcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@"; 5043 #else 5044 char *opts_p = "abcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6@"; 5045 #endif 5046 #else 5047 #ifdef WAITAROUND 5048 char *opts_p = "zabcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6"; 5049 #else 5050 char *opts_p = "abcdfiklmoprstuvABC:DE:H:I:LM:O:PR:SV6"; 5051 #endif 5052 #endif 5053 5054 char *dupl_p = "Only one occurrence of -%c allowed"; 5055 int option; 5056 int blk_cnt, blk_cnt_max; 5057 struct rlimit rlim; 5058 5059 /* Remember the native page size. */ 5060 5061 PageSize = sysconf(_SC_PAGESIZE); 5062 5063 if (PageSize == -1) { 5064 /* 5065 * This sysconf call will almost certainly never fail. The 5066 * symbol PAGESIZE itself resolves to the above sysconf call, 5067 * so we should go ahead and define our own constant. 5068 */ 5069 PageSize = 8192; 5070 } 5071 5072 Euid = geteuid(); 5073 Hdr_type = BIN; 5074 Max_offset = (off_t)(BIN_OFFSET_MAX); 5075 Efil_p = Hdr_p = Own_p = IOfil_p = NULL; 5076 while ((option = getopt(largc, largv, opts_p)) != EOF) { 5077 switch (option) { 5078 #ifdef WAITAROUND 5079 case 'z': 5080 /* rendezvous with the debugger */ 5081 waitaround = 1; 5082 break; 5083 #endif 5084 case 'a': /* reset access time */ 5085 Args |= OCa; 5086 break; 5087 case 'b': /* swap bytes and halfwords */ 5088 Args |= OCb; 5089 break; 5090 case 'c': /* select character header */ 5091 Args |= OCc; 5092 Hdr_type = ASC; 5093 Max_namesz = APATH; 5094 Onecopy = 1; 5095 break; 5096 case 'd': /* create directories as needed */ 5097 Args |= OCd; 5098 break; 5099 case 'f': /* select files not in patterns */ 5100 Args |= OCf; 5101 break; 5102 case 'i': /* "copy in" */ 5103 Args |= OCi; 5104 Archive = 0; 5105 break; 5106 case 'k': /* retry after I/O errors */ 5107 Args |= OCk; 5108 break; 5109 case 'l': /* link files when possible */ 5110 Args |= OCl; 5111 break; 5112 case 'm': /* retain modification time */ 5113 Args |= OCm; 5114 break; 5115 case 'o': /* "copy out" */ 5116 Args |= OCo; 5117 Archive = 1; 5118 break; 5119 case 'p': /* "pass" */ 5120 Max_namesz = APATH; 5121 Args |= OCp; 5122 break; 5123 case 'r': /* rename files interactively */ 5124 Args |= OCr; 5125 break; 5126 case 's': /* swap bytes */ 5127 Args |= OCs; 5128 break; 5129 case 't': /* table of contents */ 5130 Args |= OCt; 5131 break; 5132 case 'u': /* copy unconditionally */ 5133 Args |= OCu; 5134 break; 5135 case 'v': /* verbose - print file names */ 5136 Args |= OCv; 5137 break; 5138 case 'A': /* append to existing archive */ 5139 Args |= OCA; 5140 break; 5141 case 'B': /* set block size to 5120 bytes */ 5142 Args |= OCB; 5143 Bufsize = 5120; 5144 break; 5145 case 'C': /* set arbitrary block size */ 5146 if (Args & OCC) 5147 msg(ERR, dupl_p, 'C'); 5148 else { 5149 Args |= OCC; 5150 Bufsize = atoi(optarg); 5151 } 5152 break; 5153 case 'D': 5154 Dflag = 1; 5155 break; 5156 case 'E': /* alternate file for pattern input */ 5157 if (Args & OCE) 5158 msg(ERR, dupl_p, 'E'); 5159 else { 5160 Args |= OCE; 5161 Efil_p = optarg; 5162 } 5163 break; 5164 case 'H': /* select header type */ 5165 if (Args & OCH) 5166 msg(ERR, dupl_p, 'H'); 5167 else { 5168 Args |= OCH; 5169 Hdr_p = optarg; 5170 } 5171 break; 5172 case 'I': /* alternate file for archive input */ 5173 if (Args & OCI) 5174 msg(ERR, dupl_p, 'I'); 5175 else { 5176 Args |= OCI; 5177 IOfil_p = optarg; 5178 } 5179 break; 5180 case 'L': /* follow symbolic links */ 5181 Args |= OCL; 5182 break; 5183 case 'M': /* specify new end-of-media message */ 5184 if (Args & OCM) 5185 msg(ERR, dupl_p, 'M'); 5186 else { 5187 Args |= OCM; 5188 Eom_p = optarg; 5189 } 5190 break; 5191 case 'O': /* alternate file for archive output */ 5192 if (Args & OCO) 5193 msg(ERR, dupl_p, 'O'); 5194 else { 5195 Args |= OCO; 5196 IOfil_p = optarg; 5197 } 5198 break; 5199 case 'P': /* preserve acls */ 5200 Args |= OCP; 5201 Pflag++; 5202 break; 5203 case 'R': /* change owner/group of files */ 5204 if (Args & OCR) 5205 msg(ERR, dupl_p, 'R'); 5206 else { 5207 Args |= OCR; 5208 Own_p = optarg; 5209 } 5210 break; 5211 case 'S': /* swap halfwords */ 5212 Args |= OCS; 5213 break; 5214 case 'V': /* print a dot '.' for each file */ 5215 Args |= OCV; 5216 break; 5217 case '6': /* for old, sixth-edition files */ 5218 Args |= OC6; 5219 Ftype = SIXTH; 5220 break; 5221 #if defined(O_XATTR) 5222 case '@': 5223 Atflag++; 5224 break; 5225 #endif 5226 default: 5227 Error_cnt++; 5228 } /* option */ 5229 } /* (option = getopt(largc, largv, opts_p)) != EOF */ 5230 5231 #ifdef WAITAROUND 5232 if (waitaround) { 5233 (void) fprintf(stderr, gettext("Rendezvous with cpio on pid" 5234 " %d\n"), getpid()); 5235 5236 while (waitaround) { 5237 (void) sleep(10); 5238 } 5239 } 5240 #endif 5241 5242 largc -= optind; 5243 largv += optind; 5244 ckopts(Args); 5245 if (!Error_cnt) { 5246 Empty = e_valloc(E_EXIT, TARSZ); 5247 if (Args & OCr) { 5248 Renam_p = e_zalloc(E_EXIT, APATH + 1); 5249 Renametmp_p = e_zalloc(E_EXIT, APATH + 1); 5250 } 5251 Symlnk_p = e_zalloc(E_EXIT, APATH); 5252 Over_p = e_zalloc(E_EXIT, APATH); 5253 Nam_p = e_zalloc(E_EXIT, APATH + 1); 5254 if (Args & OCp) { 5255 Savenam_p = e_zalloc(E_EXIT, APATH + 1); 5256 } 5257 Fullnam_p = e_zalloc(E_EXIT, APATH); 5258 Lnknam_p = e_zalloc(E_EXIT, APATH); 5259 Gen.g_nam_p = Nam_p; 5260 if ((Fullnam_p = getcwd((char *)NULL, APATH)) == (char *)NULL) 5261 msg(EXT, "Unable to determine current directory."); 5262 if (Args & OCi) { 5263 if (largc > 0) /* save patterns for -i option, if any */ 5264 Pat_pp = largv; 5265 if (Args & OCE) 5266 getpats(largc, largv); 5267 } else if (Args & OCo) { 5268 if (largc != 0) /* error if arguments left with -o */ 5269 Error_cnt++; 5270 else if (fstat(Archive, &ArchSt) < 0) 5271 msg(ERRN, "Error during stat() of archive"); 5272 switch (Hdr_type) { 5273 case BIN: 5274 Hdrsz = HDRSZ; 5275 Pad_val = HALFWD; 5276 break; 5277 case CHR: 5278 Hdrsz = CHRSZ; 5279 Pad_val = 0; 5280 Max_offset = (off_t)(CHAR_OFFSET_MAX); 5281 break; 5282 case ASC: 5283 case CRC: 5284 Hdrsz = ASCSZ; 5285 Pad_val = FULLWD; 5286 break; 5287 case TAR: 5288 /* FALLTHROUGH */ 5289 case USTAR: /* TAR and USTAR */ 5290 Hdrsz = TARSZ; 5291 Pad_val = FULLBK; 5292 Max_offset = (off_t)(CHAR_OFFSET_MAX); 5293 break; 5294 default: 5295 msg(EXT, "Impossible header type."); 5296 } 5297 } else { /* directory must be specified */ 5298 if (largc != 1) 5299 Error_cnt++; 5300 else if (access(*largv, 2) < 0) 5301 msg(ERRN, 5302 "Error during access() of \"%s\"", *largv); 5303 } 5304 } 5305 if (Error_cnt) 5306 usage(); /* exits! */ 5307 if (Args & (OCi | OCo)) { 5308 if (!Dflag) { 5309 if (Args & (OCB | OCC)) { 5310 if (g_init(&Device, &Archive) < 0) 5311 msg(EXTN, 5312 "Error during initialization"); 5313 } else { 5314 if ((Bufsize = g_init(&Device, &Archive)) < 0) 5315 msg(EXTN, 5316 "Error during initialization"); 5317 } 5318 } 5319 5320 blk_cnt_max = _20K / Bufsize; 5321 if (blk_cnt_max < MX_BUFS) { 5322 blk_cnt_max = MX_BUFS; 5323 } 5324 5325 Buffr.b_base_p = NULL; 5326 5327 for (blk_cnt = blk_cnt_max; blk_cnt > 1; blk_cnt--) { 5328 Buffr.b_size = (size_t)(Bufsize * blk_cnt); 5329 Buffr.b_base_p = e_valloc(E_NORMAL, Buffr.b_size); 5330 if (Buffr.b_base_p != NULL) { 5331 break; 5332 } 5333 } 5334 if (Buffr.b_base_p == NULL || Buffr.b_size < (2 * CPIOBSZ)) { 5335 msg(EXT, "Out of memory"); 5336 } 5337 5338 Buffr.b_out_p = Buffr.b_in_p = Buffr.b_base_p; 5339 Buffr.b_cnt = 0L; 5340 Buffr.b_end_p = Buffr.b_base_p + Buffr.b_size; 5341 } 5342 5343 /* 5344 * Now that Bufsize has stabilized, we can allocate our i/o buffer 5345 */ 5346 Buf_p = e_valloc(E_EXIT, Bufsize); 5347 5348 if (Args & OCp) { /* get destination directory */ 5349 (void) strcpy(Fullnam_p, *largv); 5350 if (stat(Fullnam_p, &DesSt) < 0) 5351 msg(EXTN, "Error during stat() of \"%s\"", Fullnam_p); 5352 if ((DesSt.st_mode & Ftype) != S_IFDIR) 5353 msg(EXT, "\"%s\" is not a directory", Fullnam_p); 5354 } 5355 Full_p = Fullnam_p + strlen(Fullnam_p) - 1; 5356 if (*Full_p != '/') { 5357 Full_p++; 5358 *Full_p = '/'; 5359 } 5360 Full_p++; 5361 *Full_p = '\0'; 5362 (void) strcpy(Lnknam_p, Fullnam_p); 5363 Lnkend_p = Lnknam_p + strlen(Lnknam_p); 5364 (void) getrlimit(RLIMIT_FSIZE, &rlim); 5365 Max_filesz = (off_t)rlim.rlim_cur; 5366 Lnk_hd.L_nxt_p = Lnk_hd.L_bck_p = &Lnk_hd; 5367 Lnk_hd.L_lnk_p = (struct Lnk *)NULL; 5368 } 5369 5370 /* 5371 * set_tym: Set the access and/or modification times for a file. 5372 */ 5373 5374 static void 5375 set_tym(int dirfd, char *nam_p, time_t atime, time_t mtime) 5376 { 5377 struct timeval times[2]; 5378 5379 times[0].tv_sec = atime; 5380 times[0].tv_usec = 0; 5381 times[1].tv_sec = mtime; 5382 times[1].tv_usec = 0; 5383 5384 if (futimesat(dirfd, nam_p, times) < 0) { 5385 if (Args & OCa) { 5386 msg(ERRN, 5387 "Unable to reset access time for \"%s%s%s\"", 5388 (G_p->g_attrnam_p == (char *)NULL) ? 5389 nam_p : Fullnam_p, 5390 (G_p->g_attrnam_p == (char *)NULL) ? 5391 "" : gettext(" Attribute "), 5392 (G_p->g_attrnam_p == (char *)NULL) ? 5393 "" : nam_p); 5394 } else { 5395 msg(ERRN, 5396 "Unable to reset modification time for \"%s%s%s\"", 5397 (G_p->g_attrnam_p == (char *)NULL) ? 5398 nam_p : Fullnam_p, 5399 (G_p->g_attrnam_p == (char *)NULL) ? 5400 "" : gettext(" Attribute "), 5401 (G_p->g_attrnam_p == (char *)NULL) ? 5402 "" : nam_p); 5403 } 5404 } 5405 } 5406 5407 /* 5408 * sigint: Catch interrupts. If an interrupt occurs during the extraction 5409 * of a file from the archive with the -u option set, and the filename did 5410 * exist, remove the current file and restore the original file. Then exit. 5411 */ 5412 5413 /*ARGSUSED*/ 5414 static void 5415 sigint(int sig) 5416 { 5417 char *nam_p; 5418 5419 (void) signal(SIGINT, SIG_IGN); /* block further signals */ 5420 if (!Finished) { 5421 if (Args & OCi) 5422 nam_p = G_p->g_nam_p; 5423 else /* OCp */ 5424 nam_p = Fullnam_p; 5425 if (*Over_p != '\0') { /* There is a temp file */ 5426 if (unlink(nam_p) < 0) { 5427 msg(ERRN, 5428 "Cannot remove incomplete \"%s\"", nam_p); 5429 } 5430 if (rename(Over_p, nam_p) < 0) { 5431 if (link(Over_p, nam_p) < 0) { 5432 msg(ERRN, 5433 "Cannot recover original \"%s\"", 5434 nam_p); 5435 } 5436 if (unlink(Over_p)) { 5437 msg(ERRN, 5438 "Cannot remove temp file \"%s\"", 5439 Over_p); 5440 } 5441 } 5442 } else if (unlink(nam_p)) 5443 msg(ERRN, 5444 "Cannot remove incomplete \"%s\"", nam_p); 5445 *Over_p = '\0'; 5446 } 5447 exit(EXIT_CODE); 5448 } 5449 5450 /* 5451 * swap: Swap bytes (-s), halfwords (-S) or or both halfwords and bytes (-b). 5452 */ 5453 5454 static void 5455 swap(char *buf_p, int cnt) 5456 { 5457 unsigned char tbyte; 5458 int tcnt; 5459 int rcnt; 5460 ushort_t thalf; 5461 5462 rcnt = cnt % 4; 5463 cnt /= 4; 5464 if (Args & (OCb | OCs | BSM)) { 5465 tcnt = cnt; 5466 /* LINTED alignment */ 5467 Swp_p = (union swpbuf *)buf_p; 5468 while (tcnt-- > 0) { 5469 tbyte = Swp_p->s_byte[0]; 5470 Swp_p->s_byte[0] = Swp_p->s_byte[1]; 5471 Swp_p->s_byte[1] = tbyte; 5472 tbyte = Swp_p->s_byte[2]; 5473 Swp_p->s_byte[2] = Swp_p->s_byte[3]; 5474 Swp_p->s_byte[3] = tbyte; 5475 Swp_p++; 5476 } 5477 if (rcnt >= 2) { 5478 tbyte = Swp_p->s_byte[0]; 5479 Swp_p->s_byte[0] = Swp_p->s_byte[1]; 5480 Swp_p->s_byte[1] = tbyte; 5481 tbyte = Swp_p->s_byte[2]; 5482 } 5483 } 5484 if (Args & (OCb | OCS)) { 5485 tcnt = cnt; 5486 /* LINTED alignment */ 5487 Swp_p = (union swpbuf *)buf_p; 5488 while (tcnt-- > 0) { 5489 thalf = Swp_p->s_half[0]; 5490 Swp_p->s_half[0] = Swp_p->s_half[1]; 5491 Swp_p->s_half[1] = thalf; 5492 Swp_p++; 5493 } 5494 } 5495 } 5496 5497 /* 5498 * usage: Print the usage message on stderr and exit. 5499 */ 5500 5501 static void 5502 usage(void) 5503 { 5504 5505 (void) fflush(stdout); 5506 #if defined(O_XATTR) 5507 (void) fprintf(stderr, gettext("USAGE:\n" 5508 "\tcpio -i[bcdfkmrstuv@BSV6] [-C size] " 5509 "[-E file] [-H hdr] [-I file [-M msg]] " 5510 "[-R id] [patterns]\n" 5511 "\tcpio -o[acv@ABLV] [-C size] " 5512 "[-H hdr] [-O file [-M msg]]\n" 5513 "\tcpio -p[adlmuv@LV] [-R id] directory\n")); 5514 #else 5515 (void) fprintf(stderr, gettext("USAGE:\n" 5516 "\tcpio -i[bcdfkmrstuvBSV6] [-C size] " 5517 "[-E file] [-H hdr] [-I file [-M msg]] " 5518 "[-R id] [patterns]\n" 5519 "\tcpio -o[acvABLV] [-C size] " 5520 "[-H hdr] [-O file [-M msg]]\n" 5521 "\tcpio -p[adlmuvLV] [-R id] directory\n")); 5522 #endif 5523 (void) fflush(stderr); 5524 exit(EXIT_CODE); 5525 } 5526 5527 /* 5528 * verbose: For each file, print either the filename (-v) or a dot (-V). 5529 * If the -t option (table of contents) is set, print either the filename, 5530 * or if the -v option is also set, print an "ls -l"-like listing. 5531 */ 5532 5533 static void 5534 verbose(char *nam_p) 5535 { 5536 int i, j, temp; 5537 mode_t mode; 5538 char modestr[12]; 5539 5540 /* 5541 * The printf format and associated arguments to print the current 5542 * filename. Normally, just nam_p. If we're processing an extended 5543 * attribute, these are overridden. 5544 */ 5545 char *name_fmt = "%s"; 5546 const char *name = nam_p; 5547 const char *attribute = NULL; 5548 5549 if (Gen.g_attrnam_p != (char *)NULL) { 5550 /* 5551 * Translation note: 5552 * 'attribute' is a noun. 5553 */ 5554 name_fmt = gettext("%s attribute %s"); 5555 5556 name = (Args & OCp) ? nam_p : Gen.g_attrfnam_p; 5557 attribute = Gen.g_attrnam_p; 5558 } 5559 5560 if ((Gen.g_mode == SECMODE) || ((Hdr_type == USTAR || 5561 Hdr_type == TAR) && Thdr_p->tbuf.t_typeflag == 'A')) { 5562 /* dont print ancillary file */ 5563 aclchar = '+'; 5564 return; 5565 } 5566 for (i = 0; i < 11; i++) 5567 modestr[i] = '-'; 5568 modestr[i] = '\0'; 5569 modestr[i-1] = aclchar; 5570 aclchar = ' '; 5571 5572 if ((Args & OCt) && (Args & OCv)) { 5573 mode = Gen.g_mode; 5574 for (i = 0; i < 3; i++) { 5575 temp = (mode >> (6 - (i * 3))); 5576 j = (i * 3) + 1; 5577 if (S_IROTH & temp) 5578 modestr[j] = 'r'; 5579 if (S_IWOTH & temp) 5580 modestr[j + 1] = 'w'; 5581 if (S_IXOTH & temp) 5582 modestr[j + 2] = 'x'; 5583 } 5584 5585 if (Hdr_type != BAR) { 5586 temp = Gen.g_mode & Ftype; 5587 switch (temp) { 5588 case (S_IFIFO): 5589 modestr[0] = 'p'; 5590 break; 5591 case (S_IFCHR): 5592 modestr[0] = 'c'; 5593 break; 5594 case (S_IFDIR): 5595 modestr[0] = 'd'; 5596 break; 5597 case (S_IFBLK): 5598 modestr[0] = 'b'; 5599 break; 5600 case (S_IFREG): /* was initialized to '-' */ 5601 break; 5602 case (S_IFLNK): 5603 modestr[0] = 'l'; 5604 break; 5605 default: 5606 msg(ERR, "Impossible file type"); 5607 } 5608 } else { /* bar */ 5609 temp = Gen.g_mode & Ftype; 5610 switch (temp) { 5611 case (S_IFIFO): 5612 modestr[0] = 'p'; 5613 break; 5614 case (S_IFCHR): 5615 modestr[0] = 'c'; 5616 break; 5617 case (S_IFDIR): 5618 modestr[0] = 'd'; 5619 break; 5620 case (S_IFBLK): 5621 modestr[0] = 'b'; 5622 break; 5623 } 5624 if (bar_linkflag == SYMTYPE) 5625 modestr[0] = 'l'; 5626 } 5627 if ((S_ISUID & Gen.g_mode) == S_ISUID) 5628 modestr[3] = 's'; 5629 if ((S_ISVTX & Gen.g_mode) == S_ISVTX) 5630 modestr[9] = 't'; 5631 if ((S_ISGID & G_p->g_mode) == S_ISGID && modestr[6] == 'x') 5632 modestr[6] = 's'; 5633 else if ((S_ENFMT & Gen.g_mode) == S_ENFMT && modestr[6] != 'x') 5634 modestr[6] = 'l'; 5635 if ((Hdr_type == TAR || Hdr_type == USTAR) && Gen.g_nlink == 0) 5636 (void) printf("%s%4d ", modestr, (int)Gen.g_nlink+1); 5637 else 5638 (void) printf("%s%4d ", modestr, (int)Gen.g_nlink); 5639 if (Lastuid == (int)Gen.g_uid) { 5640 if (Lastuid == -1) 5641 (void) printf("-1 "); 5642 else 5643 (void) printf("%-9s", Curpw_p->pw_name); 5644 } else { 5645 if (Curpw_p = getpwuid((int)Gen.g_uid)) { 5646 (void) printf("%-9s", Curpw_p->pw_name); 5647 Lastuid = (int)Gen.g_uid; 5648 } else { 5649 (void) printf("%-9d", (int)Gen.g_uid); 5650 Lastuid = -1; 5651 } 5652 } 5653 if (Lastgid == (int)Gen.g_gid) { 5654 if (Lastgid == -1) 5655 (void) printf("-1 "); 5656 else 5657 (void) printf("%-9s", Curgr_p->gr_name); 5658 } else { 5659 if (Curgr_p = getgrgid((int)Gen.g_gid)) { 5660 (void) printf("%-9s", Curgr_p->gr_name); 5661 Lastgid = (int)Gen.g_gid; 5662 } else { 5663 (void) printf("%-9d", (int)Gen.g_gid); 5664 Lastgid = -1; 5665 } 5666 } 5667 5668 /* print file size */ 5669 if (!Aspec || ((Gen.g_mode & Ftype) == S_IFIFO) || 5670 (Hdr_type == BAR && bar_linkflag == SYMTYPE)) { 5671 if (Gen.g_filesz < (1LL << 31)) 5672 (void) printf("%7lld ", 5673 (offset_t)Gen.g_filesz); 5674 else 5675 (void) printf("%11lld ", 5676 (offset_t)Gen.g_filesz); 5677 } else 5678 (void) printf("%3d,%3d ", (int)major(Gen.g_rdev), 5679 (int)minor(Gen.g_rdev)); 5680 (void) cftime(Time, dcgettext(NULL, FORMAT, LC_TIME), 5681 (time_t *)&Gen.g_mtime); 5682 (void) printf("%s, ", Time); 5683 (void) printf(name_fmt, name, attribute); 5684 if ((Gen.g_mode & Ftype) == S_IFLNK) { 5685 if (Hdr_type == USTAR || Hdr_type == TAR) 5686 (void) strcpy(Symlnk_p, 5687 Thdr_p->tbuf.t_linkname); 5688 else { 5689 (void) strncpy(Symlnk_p, Buffr.b_out_p, 5690 Gen.g_filesz); 5691 *(Symlnk_p + Gen.g_filesz) = '\0'; 5692 } 5693 (void) printf(" -> %s", Symlnk_p); 5694 } 5695 if (Hdr_type == BAR) { 5696 if (bar_linkflag == SYMTYPE) 5697 (void) printf(gettext(" symbolic link to %s"), 5698 bar_linkname); 5699 else if (bar_linkflag == '1') 5700 (void) printf(gettext(" linked to %s"), 5701 bar_linkname); 5702 } 5703 if ((Hdr_type == USTAR || Hdr_type == TAR) && 5704 Thdr_p->tbuf.t_typeflag == '1') { 5705 (void) printf(gettext(" linked to %s%s%s"), 5706 (Gen.g_attrnam_p == (char *)NULL) ? 5707 Thdr_p->tbuf.t_linkname : Gen.g_attrfnam_p, 5708 (Gen.g_attrnam_p == (char *)NULL) ? 5709 "" : gettext(" attribute "), 5710 (Gen.g_attrnam_p == (char *)NULL) ? 5711 "" : Gen.g_linktoattrnam_p); 5712 } 5713 (void) printf("\n"); 5714 } else if ((Args & OCt) || (Args & OCv)) { 5715 (void) fprintf(Out_p, name_fmt, name, attribute); 5716 (void) fputc('\n', Out_p); 5717 } else { /* OCV */ 5718 (void) fputc('.', Out_p); 5719 if (Verbcnt++ >= 49) { /* start a new line of dots */ 5720 Verbcnt = 0; 5721 (void) fputc('\n', Out_p); 5722 } 5723 } 5724 (void) fflush(Out_p); 5725 } 5726 5727 #define MK_USHORT(a) (a & 00000177777) 5728 5729 /* 5730 * write_hdr: Transfer header information for the generic structure 5731 * into the format for the selected header and bwrite() the header. 5732 * ACL support: add two new argumnets. secflag indicates that it's an 5733 * ancillary file. len is the size of the file (incl. all security 5734 * attributes). We only have acls now. 5735 */ 5736 5737 static void 5738 write_hdr(int secflag, off_t len) 5739 { 5740 int cnt, pad; 5741 mode_t mode; 5742 uid_t uid; 5743 gid_t gid; 5744 const char warnfmt[] = "%s%s%s : %s"; 5745 5746 if (secflag == ARCHIVE_ACL) { 5747 mode = SECMODE; 5748 } else { 5749 /* 5750 * If attribute is being archived in cpio format then 5751 * zap off the file type bits since those are truly a 5752 * mask and reset them with _XATTR_CPIO_MODE 5753 */ 5754 5755 /* 5756 * len is the value of g_filesz for normal files 5757 * and the length of the special header buffer in 5758 * the case of acl and xattr headers. 5759 */ 5760 if (G_p->g_attrnam_p != (char *)NULL && Hdr_type != USTAR && 5761 Hdr_type != TAR) { 5762 mode = (G_p->g_mode & S_IAMB) | _XATTR_CPIO_MODE; 5763 } else { 5764 mode = G_p->g_mode; 5765 } 5766 if (secflag != ARCHIVE_XATTR) { 5767 len = G_p->g_filesz; 5768 } 5769 } 5770 5771 uid = G_p->g_uid; 5772 gid = G_p->g_gid; 5773 /* 5774 * Handle EFT uids and gids. If they get too big 5775 * to be represented in a particular format, force 'em to 'nobody'. 5776 */ 5777 switch (Hdr_type) { 5778 case BIN: /* 16-bits of u_short */ 5779 if ((ulong_t)uid > (ulong_t)USHRT_MAX) 5780 uid = UID_NOBODY; 5781 if ((ulong_t)gid > (ulong_t)USHRT_MAX) 5782 gid = GID_NOBODY; 5783 break; 5784 case CHR: /* %.6lo => 262143 base 10 */ 5785 if ((ulong_t)uid > (ulong_t)0777777) 5786 uid = UID_NOBODY; 5787 if ((ulong_t)gid > (ulong_t)0777777) 5788 gid = GID_NOBODY; 5789 break; 5790 case ASC: /* %.8lx => full 32 bits */ 5791 case CRC: 5792 break; 5793 case USTAR: 5794 case TAR: /* %.7lo => 2097151 base 10 */ 5795 if ((ulong_t)uid > (ulong_t)07777777) 5796 uid = UID_NOBODY; 5797 if ((ulong_t)gid > (ulong_t)07777777) 5798 gid = GID_NOBODY; 5799 break; 5800 default: 5801 msg(EXT, "Impossible header type."); 5802 } 5803 5804 /* 5805 * Since cpio formats -don't- encode the symbolic names, print 5806 * a warning message when we map the uid or gid this way. 5807 * Also, if the ownership just changed, clear set[ug]id bits 5808 * 5809 * (Except for USTAR format of course, where we have a string 5810 * representation of the username embedded in the header) 5811 */ 5812 if (uid != G_p->g_uid && Hdr_type != USTAR) { 5813 msg(ERR, warnfmt, 5814 (G_p->g_attrnam_p == (char *)NULL) ? 5815 G_p->g_nam_p : G_p->g_attrfnam_p, 5816 (G_p->g_attrnam_p == (char *)NULL) ? 5817 "" : gettext(" Attribute "), 5818 (G_p->g_attrnam_p == (char *)NULL) ? 5819 "" : G_p->g_attrnam_p, 5820 gettext("uid too large for archive format")); 5821 if (S_ISREG(mode)) 5822 mode &= ~S_ISUID; 5823 } 5824 if (gid != G_p->g_gid && Hdr_type != USTAR) { 5825 msg(ERR, warnfmt, 5826 (G_p->g_attrnam_p == (char *)NULL) ? 5827 G_p->g_nam_p : G_p->g_attrfnam_p, 5828 (G_p->g_attrnam_p == (char *)NULL) ? 5829 "" : gettext(" Attribute "), 5830 (G_p->g_attrnam_p == (char *)NULL) ? 5831 "" : G_p->g_attrnam_p, 5832 gettext("gid too large for archive format")); 5833 if (S_ISREG(mode)) 5834 mode &= ~S_ISGID; 5835 } 5836 5837 switch (Hdr_type) { 5838 case BIN: 5839 case CHR: 5840 case ASC: 5841 case CRC: 5842 cnt = Hdrsz + G_p->g_namesz; 5843 break; 5844 case TAR: 5845 /*FALLTHROUGH*/ 5846 case USTAR: /* TAR and USTAR */ 5847 cnt = TARSZ; 5848 break; 5849 default: 5850 msg(EXT, "Impossible header type."); 5851 } 5852 FLUSH(cnt); 5853 5854 switch (Hdr_type) { 5855 case BIN: 5856 Hdr.h_magic = (short)G_p->g_magic; 5857 Hdr.h_dev = G_p->g_dev; 5858 Hdr.h_ino = G_p->g_ino; 5859 Hdr.h_uid = uid; 5860 Hdr.h_gid = gid; 5861 Hdr.h_mode = mode; 5862 Hdr.h_nlink = G_p->g_nlink; 5863 Hdr.h_rdev = G_p->g_rdev; 5864 mkshort(Hdr.h_mtime, (long)G_p->g_mtime); 5865 Hdr.h_namesize = (short)G_p->g_namesz; 5866 mkshort(Hdr.h_filesize, (long)len); 5867 (void) strcpy(Hdr.h_name, G_p->g_nam_p); 5868 (void) memcpy(Buffr.b_in_p, &Hdr, cnt); 5869 break; 5870 case CHR: 5871 (void) sprintf(Buffr.b_in_p, 5872 "%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.6lo%.11lo%.6lo%." 5873 "11llo%s", G_p->g_magic, G_p->g_dev, G_p->g_ino, mode, 5874 uid, gid, G_p->g_nlink, MK_USHORT(G_p->g_rdev), 5875 G_p->g_mtime, (long)G_p->g_namesz, (offset_t)len, 5876 G_p->g_nam_p); 5877 break; 5878 case ASC: 5879 case CRC: 5880 (void) sprintf(Buffr.b_in_p, 5881 "%.6lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%.8lx%." 5882 "8lx%.8lx%.8lx%.8lx%s", 5883 G_p->g_magic, G_p->g_ino, mode, G_p->g_uid, 5884 G_p->g_gid, G_p->g_nlink, G_p->g_mtime, (long)len, 5885 major(G_p->g_dev), minor(G_p->g_dev), 5886 major(G_p->g_rdev), minor(G_p->g_rdev), 5887 G_p->g_namesz, G_p->g_cksum, G_p->g_nam_p); 5888 break; 5889 case USTAR: 5890 Thdr_p = (union tblock *)Buffr.b_in_p; 5891 (void) memcpy(Thdr_p, Empty, TARSZ); 5892 (void) strncpy(Thdr_p->tbuf.t_name, G_p->g_tname, 5893 (int)strlen(G_p->g_tname)); 5894 (void) sprintf(Thdr_p->tbuf.t_mode, "%07o", (int)mode); 5895 (void) sprintf(Thdr_p->tbuf.t_uid, "%07o", (int)uid); 5896 (void) sprintf(Thdr_p->tbuf.t_gid, "%07o", (int)gid); 5897 (void) sprintf(Thdr_p->tbuf.t_size, "%011llo", 5898 (offset_t)len); 5899 (void) sprintf(Thdr_p->tbuf.t_mtime, "%011lo", G_p->g_mtime); 5900 if (secflag == ARCHIVE_ACL) { 5901 Thdr_p->tbuf.t_typeflag = 'A'; /* ACL file type */ 5902 } else if (secflag == ARCHIVE_XATTR || 5903 (G_p->g_attrnam_p != (char *)NULL)) { 5904 Thdr_p->tbuf.t_typeflag = _XATTR_HDRTYPE; 5905 } else { 5906 Thdr_p->tbuf.t_typeflag = G_p->g_typeflag; 5907 } 5908 if (T_lname[0] != '\0') { 5909 /* 5910 * if not a symbolic link 5911 */ 5912 if (((G_p->g_mode & Ftype) != S_IFLNK) && 5913 (G_p->g_attrnam_p == (char *)NULL)) { 5914 Thdr_p->tbuf.t_typeflag = LNKTYPE; 5915 (void) sprintf(Thdr_p->tbuf.t_size, 5916 "%011lo", 0L); 5917 } 5918 (void) strncpy(Thdr_p->tbuf.t_linkname, T_lname, 5919 strlen(T_lname)); 5920 } 5921 (void) sprintf(Thdr_p->tbuf.t_magic, "%s", TMAGIC); 5922 (void) sprintf(Thdr_p->tbuf.t_version, "%2s", TVERSION); 5923 (void) sprintf(Thdr_p->tbuf.t_uname, "%s", G_p->g_uname); 5924 (void) sprintf(Thdr_p->tbuf.t_gname, "%s", G_p->g_gname); 5925 (void) sprintf(Thdr_p->tbuf.t_devmajor, "%07o", 5926 (int)major(G_p->g_rdev)); 5927 (void) sprintf(Thdr_p->tbuf.t_devminor, "%07o", 5928 (int)minor(G_p->g_rdev)); 5929 if (Gen.g_prefix) { 5930 (void) sprintf(Thdr_p->tbuf.t_prefix, "%s", 5931 Gen.g_prefix); 5932 free(Gen.g_prefix); 5933 Gen.g_prefix = NULL; 5934 } else { 5935 (void) sprintf(Thdr_p->tbuf.t_prefix, "%s", ""); 5936 } 5937 (void) sprintf(Thdr_p->tbuf.t_cksum, "%07o", 5938 (int)cksum(TARTYP, 0, NULL)); 5939 break; 5940 case TAR: 5941 Thdr_p = (union tblock *)Buffr.b_in_p; 5942 (void) memcpy(Thdr_p, Empty, TARSZ); 5943 (void) strncpy(Thdr_p->tbuf.t_name, G_p->g_nam_p, 5944 G_p->g_namesz); 5945 (void) sprintf(Thdr_p->tbuf.t_mode, "%07o ", (int)mode); 5946 (void) sprintf(Thdr_p->tbuf.t_uid, "%07o ", (int)uid); 5947 (void) sprintf(Thdr_p->tbuf.t_gid, "%07o ", (int)gid); 5948 (void) sprintf(Thdr_p->tbuf.t_size, "%011llo ", 5949 (offset_t)len); 5950 (void) sprintf(Thdr_p->tbuf.t_mtime, "%011o ", 5951 (int)G_p->g_mtime); 5952 if (T_lname[0] != '\0') { 5953 Thdr_p->tbuf.t_typeflag = '1'; 5954 } else { 5955 Thdr_p->tbuf.t_typeflag = '\0'; 5956 } 5957 (void) strncpy(Thdr_p->tbuf.t_linkname, T_lname, 5958 strlen(T_lname)); 5959 break; 5960 default: 5961 msg(EXT, "Impossible header type."); 5962 } /* Hdr_type */ 5963 5964 Buffr.b_in_p += cnt; 5965 Buffr.b_cnt += cnt; 5966 pad = ((cnt + Pad_val) & ~Pad_val) - cnt; 5967 if (pad != 0) { 5968 FLUSH(pad); 5969 (void) memcpy(Buffr.b_in_p, Empty, pad); 5970 Buffr.b_in_p += pad; 5971 Buffr.b_cnt += pad; 5972 } 5973 } 5974 5975 /* 5976 * write_trail: Create the appropriate trailer for the selected header type 5977 * and bwrite the trailer. Pad the buffer with nulls out to the next Bufsize 5978 * boundary, and force a write. If the write completes, or if the trailer is 5979 * completely written (but not all of the padding nulls (as can happen on end 5980 * of medium)) return. Otherwise, the trailer was not completely written out, 5981 * so re-pad the buffer with nulls and try again. 5982 */ 5983 5984 static void 5985 write_trail(void) 5986 { 5987 int cnt, need; 5988 5989 switch (Hdr_type) { 5990 case BIN: 5991 Gen.g_magic = CMN_BIN; 5992 break; 5993 case CHR: 5994 Gen.g_magic = CMN_BIN; 5995 break; 5996 case ASC: 5997 Gen.g_magic = CMN_ASC; 5998 break; 5999 case CRC: 6000 Gen.g_magic = CMN_CRC; 6001 break; 6002 } 6003 6004 switch (Hdr_type) { 6005 case BIN: 6006 case CHR: 6007 case ASC: 6008 case CRC: 6009 Gen.g_mode = Gen.g_uid = Gen.g_gid = 0; 6010 Gen.g_nlink = 1; 6011 Gen.g_mtime = Gen.g_ino = Gen.g_dev = 0; 6012 Gen.g_rdev = Gen.g_cksum = 0; 6013 Gen.g_filesz = (off_t)0; 6014 Gen.g_namesz = strlen("TRAILER!!!") + 1; 6015 (void) strcpy(Gen.g_nam_p, "TRAILER!!!"); 6016 G_p = &Gen; 6017 write_hdr(ARCHIVE_NORMAL, (off_t)0); 6018 break; 6019 case TAR: 6020 /*FALLTHROUGH*/ 6021 case USTAR: /* TAR and USTAR */ 6022 for (cnt = 0; cnt < 3; cnt++) { 6023 FLUSH(TARSZ); 6024 (void) memcpy(Buffr.b_in_p, Empty, TARSZ); 6025 Buffr.b_in_p += TARSZ; 6026 Buffr.b_cnt += TARSZ; 6027 } 6028 break; 6029 default: 6030 msg(EXT, "Impossible header type."); 6031 } 6032 need = Bufsize - (Buffr.b_cnt % Bufsize); 6033 if (need == Bufsize) 6034 need = 0; 6035 6036 while (Buffr.b_cnt > 0) { 6037 while (need > 0) { 6038 cnt = (need < TARSZ) ? need : TARSZ; 6039 need -= cnt; 6040 FLUSH(cnt); 6041 (void) memcpy(Buffr.b_in_p, Empty, cnt); 6042 Buffr.b_in_p += cnt; 6043 Buffr.b_cnt += cnt; 6044 } 6045 bflush(); 6046 } 6047 } 6048 6049 /* 6050 * if archives in USTAR format, check if typeflag == '5' for directories 6051 */ 6052 static int 6053 ustar_dir(void) 6054 { 6055 if (Hdr_type == USTAR || Hdr_type == TAR) { 6056 if (Thdr_p->tbuf.t_typeflag == '5') 6057 return (1); 6058 } 6059 return (0); 6060 } 6061 6062 /* 6063 * if archives in USTAR format, check if typeflag == '3' || '4' || '6' 6064 * for character, block, fifo special files 6065 */ 6066 static int 6067 ustar_spec(void) 6068 { 6069 int typeflag; 6070 6071 if (Hdr_type == USTAR || Hdr_type == TAR) { 6072 typeflag = Thdr_p->tbuf.t_typeflag; 6073 if (typeflag == '3' || typeflag == '4' || typeflag == '6') 6074 return (1); 6075 } 6076 return (0); 6077 } 6078 6079 /* 6080 * The return value is a pointer to a converted copy of the information in 6081 * FromStat if the file is representable in -Hodc format, and NULL otherwise. 6082 */ 6083 6084 static struct stat * 6085 convert_to_old_stat(struct stat *FromStat, char *namep, char *attrp) 6086 { 6087 static struct stat ToSt; 6088 cpioinfo_t TmpSt; 6089 6090 (void) memset(&TmpSt, 0, sizeof (cpioinfo_t)); 6091 stat_to_svr32_stat(&TmpSt, FromStat); 6092 (void) memset(&ToSt, 0, sizeof (ToSt)); 6093 6094 if (TmpSt.st_rdev == (o_dev_t)NODEV && 6095 (((TmpSt.st_mode & Ftype) == S_IFCHR) || 6096 ((TmpSt.st_mode & Ftype) == S_IFBLK))) { 6097 /* 6098 * Encountered a problem representing the rdev information. 6099 * Don't archive it. 6100 */ 6101 6102 msg(ERR, "Error -Hodc format can't support expanded" 6103 "types on %s%s%s", 6104 namep, 6105 (attrp == NULL) ? "" : gettext(" Attribute"), 6106 (attrp == NULL) ? "" : attrp); 6107 return (NULL); 6108 } 6109 6110 if (TmpSt.st_dev == (o_dev_t)NODEV) { 6111 /* 6112 * Having trouble representing the device/inode pair. We can't 6113 * track links in this case; break them all into separate 6114 * files. 6115 */ 6116 6117 TmpSt.st_ino = 0; 6118 6119 if (((TmpSt.st_mode & Ftype) != S_IFDIR) && 6120 TmpSt.st_nlink > 1) 6121 msg(POST, 6122 "Warning: file %s%s%s has large " 6123 "device number - linked " 6124 "files will be restored as " 6125 "separate files", 6126 namep, 6127 (attrp == NULL) ? "" : gettext(" Attribute"), 6128 (attrp == NULL) ? "" : attrp); 6129 6130 /* ensure no links */ 6131 6132 TmpSt.st_nlink = 1; 6133 } 6134 6135 /* Start converting values */ 6136 6137 if (TmpSt.st_dev < 0) { 6138 ToSt.st_dev = 0; 6139 } else { 6140 ToSt.st_dev = (dev_t)TmpSt.st_dev; 6141 } 6142 6143 /* -actual- not truncated uid */ 6144 6145 ToSt.st_uid = TmpSt.st_uid; 6146 6147 /* -actual- not truncated gid */ 6148 6149 ToSt.st_gid = TmpSt.st_gid; 6150 ToSt.st_ino = (ino_t)TmpSt.st_ino; 6151 ToSt.st_mode = (mode_t)TmpSt.st_mode; 6152 ToSt.st_mtime = (ulong_t)TmpSt.st_modtime; 6153 ToSt.st_nlink = (nlink_t)TmpSt.st_nlink; 6154 ToSt.st_size = (off_t)TmpSt.st_size; 6155 ToSt.st_rdev = (dev_t)TmpSt.st_rdev; 6156 6157 return (&ToSt); 6158 } 6159 6160 /* 6161 * In the beginning of each bar archive, there is a header which describes the 6162 * current volume being created, followed by a header which describes the 6163 * current file being created, followed by the file itself. If there is 6164 * more than one file to be created, a separate header will be created for 6165 * each additional file. This structure may be repeated if the bar archive 6166 * contains multiple volumes. If a file spans across volumes, its header 6167 * will not be repeated in the next volume. 6168 * +------------------+ 6169 * | vol header | 6170 * |------------------| 6171 * | file header i | i = 0 6172 * |------------------| 6173 * | <file i> | 6174 * |------------------| 6175 * | file header i+1 | 6176 * |------------------| 6177 * | <file i+1> | 6178 * |------------------| 6179 * | . | 6180 * | . | 6181 * | . | 6182 * +------------------+ 6183 */ 6184 6185 /* 6186 * read in the header that describes the current volume of the bar archive 6187 * to be extracted. 6188 */ 6189 static void 6190 read_bar_vol_hdr(void) 6191 { 6192 union b_block *tmp_hdr; 6193 6194 tmp_hdr = (union b_block *)Buffr.b_out_p; 6195 if (tmp_hdr->dbuf.bar_magic[0] == BAR_VOLUME_MAGIC) { 6196 6197 if (bar_Vhdr == NULL) { 6198 bar_Vhdr = e_zalloc(E_EXIT, TBLOCK); 6199 } 6200 (void) memcpy(&(bar_Vhdr->dbuf), &(tmp_hdr->dbuf), TBLOCK); 6201 } else { 6202 (void) fprintf(stderr, gettext( 6203 "bar error: cannot read volume header\n")); 6204 exit(1); 6205 } 6206 6207 (void) sscanf(bar_Vhdr->dbuf.mode, "%8lo", &Gen_bar_vol.g_mode); 6208 (void) sscanf(bar_Vhdr->dbuf.uid, "%8d", (int *)&Gen_bar_vol.g_uid); 6209 (void) sscanf(bar_Vhdr->dbuf.gid, "%8d", (int *)&Gen_bar_vol.g_gid); 6210 (void) sscanf(bar_Vhdr->dbuf.size, "%12llo", 6211 (u_off_t *)&Gen_bar_vol.g_filesz); 6212 (void) sscanf(bar_Vhdr->dbuf.mtime, "%12lo", &Gen_bar_vol.g_mtime); 6213 (void) sscanf(bar_Vhdr->dbuf.chksum, "%8lo", &Gen_bar_vol.g_cksum); 6214 6215 /* set the compress flag */ 6216 if (bar_Vhdr->dbuf.compressed == '1') 6217 Compressed = 1; 6218 else 6219 Compressed = 0; 6220 6221 Buffr.b_out_p += 512; 6222 Buffr.b_cnt -= 512; 6223 6224 /* 6225 * not the first volume; exit 6226 */ 6227 if (strcmp(bar_Vhdr->dbuf.volume_num, "1") != 0) { 6228 (void) fprintf(stderr, 6229 gettext("error: This is not volume 1. ")); 6230 (void) fprintf(stderr, gettext("This is volume %s. "), 6231 bar_Vhdr->dbuf.volume_num); 6232 (void) fprintf(stderr, gettext("Please insert volume 1.\n")); 6233 exit(1); 6234 } 6235 6236 read_bar_file_hdr(); 6237 } 6238 6239 /* 6240 * read in the header that describes the current file to be extracted 6241 */ 6242 static void 6243 read_bar_file_hdr(void) 6244 { 6245 union b_block *tmp_hdr; 6246 char *start_of_name, *name_p; 6247 char *tmp; 6248 6249 if (*Buffr.b_out_p == '\0') { 6250 *Gen.g_nam_p = '\0'; 6251 exit(0); 6252 } 6253 6254 tmp_hdr = (union b_block *)Buffr.b_out_p; 6255 6256 tmp = &tmp_hdr->dbuf.mode[1]; 6257 (void) sscanf(tmp, "%8lo", &Gen.g_mode); 6258 (void) sscanf(tmp_hdr->dbuf.uid, "%8lo", &Gen.g_uid); 6259 (void) sscanf(tmp_hdr->dbuf.gid, "%8lo", &Gen.g_gid); 6260 (void) sscanf(tmp_hdr->dbuf.size, "%12llo", 6261 (u_off_t *)&Gen.g_filesz); 6262 (void) sscanf(tmp_hdr->dbuf.mtime, "%12lo", &Gen.g_mtime); 6263 (void) sscanf(tmp_hdr->dbuf.chksum, "%8lo", &Gen.g_cksum); 6264 (void) sscanf(tmp_hdr->dbuf.rdev, "%8lo", &Gen.g_rdev); 6265 6266 #define to_new_major(x) (int)((unsigned)((x) & OMAXMAJ) << NBITSMINOR) 6267 #define to_new_minor(x) (int)((x) & OMAXMIN) 6268 Gen.g_rdev = to_new_major(Gen.g_rdev) | to_new_minor(Gen.g_rdev); 6269 bar_linkflag = tmp_hdr->dbuf.linkflag; 6270 start_of_name = &tmp_hdr->dbuf.start_of_name; 6271 6272 6273 name_p = Gen.g_nam_p; 6274 while (*name_p++ = *start_of_name++) 6275 ; 6276 *name_p = '\0'; 6277 if (bar_linkflag == LNKTYPE || bar_linkflag == SYMTYPE) 6278 (void) strcpy(bar_linkname, start_of_name); 6279 6280 Gen.g_namesz = strlen(Gen.g_nam_p) + 1; 6281 (void) strcpy(nambuf, Gen.g_nam_p); 6282 } 6283 6284 /* 6285 * if the bar archive is compressed, set up a pipe and do the de-compression 6286 * as the compressed file is read in. 6287 */ 6288 static void 6289 setup_uncompress(FILE **pipef) 6290 { 6291 char *cmd_buf; 6292 size_t cmdlen; 6293 6294 cmd_buf = e_zalloc(E_EXIT, MAXPATHLEN * 2); 6295 6296 if (access(Gen.g_nam_p, W_OK) != 0) { 6297 cmdlen = snprintf(cmd_buf, MAXPATHLEN * 2, 6298 "chmod +w '%s'; uncompress -c > '%s'; " 6299 "chmod 0%o '%s'", 6300 Gen.g_nam_p, Gen.g_nam_p, (int)G_p->g_mode, Gen.g_nam_p); 6301 } else { 6302 cmdlen = snprintf(cmd_buf, MAXPATHLEN * 2, 6303 "uncompress -c > '%s'", Gen.g_nam_p); 6304 } 6305 6306 if (cmdlen >= MAXPATHLEN * 2 || 6307 (*pipef = popen(cmd_buf, "w")) == NULL) { 6308 (void) fprintf(stderr, gettext("error\n")); 6309 exit(1); 6310 } 6311 6312 if (close(Ofile) != 0) 6313 msg(EXTN, "close error"); 6314 Ofile = fileno(*pipef); 6315 6316 free(cmd_buf); 6317 } 6318 6319 /* 6320 * if the bar archive spans multiple volumes, read in the header that 6321 * describes the next volume. 6322 */ 6323 static void 6324 skip_bar_volhdr(void) 6325 { 6326 char *buff; 6327 union b_block *tmp_hdr; 6328 6329 buff = e_zalloc(E_EXIT, (uint_t)Bufsize); 6330 6331 if (g_read(Device, Archive, buff, Bufsize) < 0) { 6332 (void) fprintf(stderr, gettext( 6333 "error in skip_bar_volhdr\n")); 6334 } else { 6335 6336 tmp_hdr = (union b_block *)buff; 6337 if (tmp_hdr->dbuf.bar_magic[0] == BAR_VOLUME_MAGIC) { 6338 6339 if (bar_Vhdr == NULL) { 6340 bar_Vhdr = e_zalloc(E_EXIT, TBLOCK); 6341 } 6342 (void) memcpy(&(bar_Vhdr->dbuf), 6343 &(tmp_hdr->dbuf), TBLOCK); 6344 } else { 6345 (void) fprintf(stderr, 6346 gettext("cpio error: cannot read bar volume " 6347 "header\n")); 6348 exit(1); 6349 } 6350 6351 (void) sscanf(bar_Vhdr->dbuf.mode, "%8lo", 6352 &Gen_bar_vol.g_mode); 6353 (void) sscanf(bar_Vhdr->dbuf.uid, "%8lo", 6354 &Gen_bar_vol.g_uid); 6355 (void) sscanf(bar_Vhdr->dbuf.gid, "%8lo", 6356 &Gen_bar_vol.g_gid); 6357 (void) sscanf(bar_Vhdr->dbuf.size, "%12llo", 6358 (u_off_t *)&Gen_bar_vol.g_filesz); 6359 (void) sscanf(bar_Vhdr->dbuf.mtime, "%12lo", 6360 &Gen_bar_vol.g_mtime); 6361 (void) sscanf(bar_Vhdr->dbuf.chksum, "%8lo", 6362 &Gen_bar_vol.g_cksum); 6363 if (bar_Vhdr->dbuf.compressed == '1') 6364 Compressed = 1; 6365 else 6366 Compressed = 0; 6367 } 6368 6369 /* 6370 * Now put the rest of the bytes read in into the data buffer. 6371 */ 6372 (void) memcpy(Buffr.b_in_p, &buff[512], (Bufsize - 512)); 6373 Buffr.b_in_p += (Bufsize - 512); 6374 Buffr.b_cnt += (long)(Bufsize - 512); 6375 6376 free(buff); 6377 } 6378 6379 /* 6380 * check the linkflag which indicates the type of the file to be extracted, 6381 * invoke the corresponding routine to extract the file. 6382 */ 6383 static void 6384 bar_file_in(void) 6385 { 6386 /* 6387 * the file is a directory 6388 */ 6389 if (Adir) { 6390 if (ckname(1) != F_SKIP && creat_spec(G_p->g_dirfd) > 0) { 6391 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 6392 } 6393 return; 6394 } 6395 6396 switch (bar_linkflag) { 6397 case REGTYPE: 6398 /* regular file */ 6399 if ((ckname(1) == F_SKIP) || 6400 (Ofile = openout(G_p->g_dirfd)) < 0) { 6401 data_in(P_SKIP); 6402 } else { 6403 data_in(P_PROC); 6404 } 6405 break; 6406 case LNKTYPE: 6407 /* hard link */ 6408 if (ckname(1) == F_SKIP) { 6409 break; 6410 } 6411 (void) creat_lnk(G_p->g_dirfd, bar_linkname, G_p->g_nam_p); 6412 break; 6413 case SYMTYPE: 6414 /* symbolic link */ 6415 if ((ckname(1) == F_SKIP) || 6416 (Ofile = openout(G_p->g_dirfd)) < 0) { 6417 data_in(P_SKIP); 6418 } else { 6419 data_in(P_PROC); 6420 } 6421 break; 6422 case CHRTYPE: 6423 /* character device or FIFO */ 6424 if (ckname(1) != F_SKIP && creat_spec(G_p->g_dirfd) > 0) { 6425 VERBOSE((Args & (OCv | OCV)), G_p->g_nam_p); 6426 } 6427 break; 6428 default: 6429 (void) fprintf(stderr, gettext("error: unknown file type\n")); 6430 break; 6431 } 6432 } 6433 6434 6435 /* 6436 * This originally came from libgenIO/g_init.c 6437 * XXX And it is very broken. 6438 */ 6439 6440 /* #include <sys/statvfs.h> */ 6441 #include <ftw.h> 6442 /* #include <libgenIO.h> */ 6443 #define G_TM_TAPE 1 /* Tapemaster controller */ 6444 #define G_XY_DISK 3 /* xy disks */ 6445 #define G_SD_DISK 7 /* scsi sd disk */ 6446 #define G_XT_TAPE 8 /* xt tapes */ 6447 #define G_SF_FLOPPY 9 /* sf floppy */ 6448 #define G_XD_DISK 10 /* xd disks */ 6449 #define G_ST_TAPE 11 /* scsi tape */ 6450 #define G_NS 12 /* noswap pseudo-dev */ 6451 #define G_RAM 13 /* ram pseudo-dev */ 6452 #define G_FT 14 /* tftp */ 6453 #define G_HD 15 /* 386 network disk */ 6454 #define G_FD 16 /* 386 AT disk */ 6455 #define G_FILE 28 /* file, not a device */ 6456 #define G_NO_DEV 29 /* device does not require special treatment */ 6457 #define G_DEV_MAX 30 /* last valid device type */ 6458 6459 /* 6460 * g_init: Determine the device being accessed, set the buffer size, 6461 * and perform any device specific initialization. Since at this point 6462 * Sun has no system call to read the configuration, the major numbers 6463 * are assumed to be static and types are figured out as such. However, 6464 * as a rough estimate, the buffer size for all types is set to 512 6465 * as a default. 6466 */ 6467 6468 static int 6469 g_init(int *devtype, int *fdes) 6470 { 6471 int bufsize; 6472 struct stat st_buf; 6473 struct statvfs stfs_buf; 6474 6475 *devtype = G_NO_DEV; 6476 bufsize = -1; 6477 if (fstat(*fdes, &st_buf) == -1) 6478 return (-1); 6479 if (!(st_buf.st_mode & S_IFCHR) || !(st_buf.st_mode & S_IFBLK)) { 6480 if (st_buf.st_mode & S_IFIFO) { 6481 bufsize = 512; 6482 } else { 6483 /* find block size for this file system */ 6484 *devtype = G_FILE; 6485 if (fstatvfs(*fdes, &stfs_buf) < 0) { 6486 bufsize = -1; 6487 errno = ENODEV; 6488 } else 6489 bufsize = stfs_buf.f_bsize; 6490 } 6491 6492 return (bufsize); 6493 6494 /* 6495 * We'll have to add a remote attribute to stat but this 6496 * should work for now. 6497 */ 6498 } else if (st_buf.st_dev & 0x8000) /* if remote rdev */ 6499 return (512); 6500 6501 bufsize = 512; 6502 6503 if (Hdr_type == BAR) { 6504 if (is_tape(*fdes)) { 6505 bufsize = BAR_TAPE_SIZE; 6506 (void) fprintf(stderr, "Archiving to tape"); 6507 (void) fprintf(stderr, " blocking factor 126\n"); 6508 } else if (is_floppy(*fdes)) { 6509 bufsize = BAR_FLOPPY_SIZE; 6510 (void) fprintf(stderr, "Archiving to floppy"); 6511 (void) fprintf(stderr, " blocking factor 18\n"); 6512 } 6513 } 6514 6515 return (bufsize); 6516 } 6517 6518 /* 6519 * This originally came from libgenIO/g_read.c 6520 */ 6521 6522 /* 6523 * g_read: Read nbytes of data from fdes (of type devtype) and place 6524 * data in location pointed to by buf. In case of end of medium, 6525 * translate (where necessary) device specific EOM indications into 6526 * the generic EOM indication of rv = -1, errno = ENOSPC. 6527 */ 6528 6529 static int 6530 g_read(int devtype, int fdes, char *buf, unsigned nbytes) 6531 { 6532 int rv; 6533 6534 if (devtype < 0 || devtype >= G_DEV_MAX) { 6535 errno = ENODEV; 6536 return (-1); 6537 } 6538 6539 rv = read(fdes, buf, nbytes); 6540 6541 /* st devices return 0 when no space left */ 6542 if ((rv == 0 && errno == 0 && Hdr_type != BAR) || 6543 (rv == -1 && errno == EIO)) { 6544 errno = 0; 6545 rv = 0; 6546 } 6547 6548 return (rv); 6549 } 6550 6551 /* 6552 * This originally came from libgenIO/g_write.c 6553 */ 6554 6555 /* 6556 * g_write: Write nbytes of data to fdes (of type devtype) from 6557 * the location pointed to by buf. In case of end of medium, 6558 * translate (where necessary) device specific EOM indications into 6559 * the generic EOM indication of rv = -1, errno = ENOSPC. 6560 */ 6561 6562 static int 6563 g_write(int devtype, int fdes, char *buf, unsigned nbytes) 6564 { 6565 int rv; 6566 6567 if (devtype < 0 || devtype >= G_DEV_MAX) { 6568 errno = ENODEV; 6569 return (-1); 6570 } 6571 6572 rv = write(fdes, buf, nbytes); 6573 6574 /* st devices return 0 when no more space left */ 6575 if ((rv == 0 && errno == 0) || (rv == -1 && errno == EIO)) { 6576 errno = ENOSPC; 6577 rv = -1; 6578 } 6579 6580 return (rv); 6581 } 6582 6583 /* 6584 * Test for tape 6585 */ 6586 6587 static int 6588 is_tape(int fd) 6589 { 6590 struct mtget stuff; 6591 6592 /* 6593 * try to do a generic tape ioctl, just to see if 6594 * the thing is in fact a tape drive(er). 6595 */ 6596 if (ioctl(fd, MTIOCGET, &stuff) != -1) { 6597 /* the ioctl succeeded, must have been a tape */ 6598 return (1); 6599 } 6600 return (0); 6601 } 6602 6603 /* 6604 * Test for floppy 6605 */ 6606 6607 static int 6608 is_floppy(int fd) 6609 { 6610 struct fd_char stuff; 6611 6612 /* 6613 * try to get the floppy drive characteristics, just to see if 6614 * the thing is in fact a floppy drive(er). 6615 */ 6616 if (ioctl(fd, FDIOGCHAR, &stuff) != -1) { 6617 /* the ioctl succeeded, must have been a floppy */ 6618 return (1); 6619 } 6620 6621 return (0); 6622 } 6623 6624 /* 6625 * New functions for ACLs and other security attributes 6626 */ 6627 6628 /* 6629 * The function appends the new security attribute info to the end of 6630 * existing secinfo. 6631 */ 6632 static int 6633 append_secattr( 6634 char **secinfo, /* existing security info */ 6635 int *secinfo_len, /* length of existing security info */ 6636 int size, /* new attribute size: unit depends on type */ 6637 char *attrp, /* new attribute data pointer */ 6638 char attr_type) /* new attribute type */ 6639 { 6640 char *new_secinfo; 6641 char *attrtext; 6642 size_t newattrsize; 6643 int oldsize; 6644 6645 /* no need to add */ 6646 if (attrp == (char *)NULL) { 6647 return (0); 6648 } 6649 6650 switch (attr_type) { 6651 case UFSD_ACL: 6652 /* LINTED alignment */ 6653 attrtext = acltotext((aclent_t *)attrp, size); 6654 if (attrtext == NULL) { 6655 (void) fprintf(stderr, "acltotext failed\n"); 6656 return (-1); 6657 } 6658 /* header: type + size = 8 */ 6659 newattrsize = 8 + strlen(attrtext) + 1; 6660 attr = e_zalloc(E_NORMAL, newattrsize); 6661 if (attr == NULL) { 6662 (void) fprintf(stderr, "can't allocate memory\n"); 6663 return (-1); 6664 } 6665 attr->attr_type = '1'; /* UFSD_ACL */ 6666 /* acl entry count */ 6667 (void) sprintf(attr->attr_len, "%06o", size); 6668 (void) strcpy((char *)&attr->attr_info[0], attrtext); 6669 free(attrtext); 6670 break; 6671 6672 /* SunFed's case goes here */ 6673 6674 default: 6675 (void) fprintf(stderr, "unrecognized attribute type\n"); 6676 return (-1); 6677 } 6678 6679 /* old security info + new attr header(8) + new attr */ 6680 oldsize = *secinfo_len; 6681 *secinfo_len += newattrsize; 6682 new_secinfo = e_zalloc(E_NORMAL, (uint_t)*secinfo_len); 6683 if (new_secinfo == NULL) { 6684 (void) fprintf(stderr, "can't allocate memory\n"); 6685 *secinfo_len -= newattrsize; 6686 return (-1); 6687 } 6688 6689 (void) memcpy(new_secinfo, *secinfo, oldsize); 6690 (void) memcpy(new_secinfo + oldsize, attr, newattrsize); 6691 6692 free(*secinfo); 6693 *secinfo = new_secinfo; 6694 return (0); 6695 } 6696 6697 static void 6698 write_ancillary(char *secinfo, int len) 6699 { 6700 long pad; 6701 long cnt; 6702 6703 /* Just tranditional permissions or no security attribute info */ 6704 if (len == 0) { 6705 return; 6706 } 6707 6708 /* write out security info */ 6709 while (len > 0) { 6710 cnt = (unsigned)(len > CPIOBSZ) ? CPIOBSZ : len; 6711 FLUSH(cnt); 6712 errno = 0; 6713 (void) memcpy(Buffr.b_in_p, secinfo, (unsigned)cnt); 6714 Buffr.b_in_p += cnt; 6715 Buffr.b_cnt += (long)cnt; 6716 len -= (long)cnt; 6717 } 6718 pad = (Pad_val + 1 - (cnt & Pad_val)) & Pad_val; 6719 if (pad != 0) { 6720 FLUSH(pad); 6721 (void) memcpy(Buffr.b_in_p, Empty, pad); 6722 Buffr.b_in_p += pad; 6723 Buffr.b_cnt += pad; 6724 } 6725 } 6726 6727 static int 6728 remove_dir(char *path) 6729 { 6730 DIR *name; 6731 struct dirent *direct; 6732 struct stat sbuf; 6733 char *path_copy; 6734 6735 #define MSG1 "remove_dir() failed to stat(\"%s\") " 6736 #define MSG2 "remove_dir() failed to remove_dir(\"%s\") " 6737 #define MSG3 "remove_dir() failed to unlink(\"%s\") " 6738 6739 /* 6740 * Open the directory for reading. 6741 */ 6742 if ((name = opendir(path)) == NULL) { 6743 msg(ERRN, "remove_dir() failed to opendir(\"%s\") ", path); 6744 return (-1); 6745 } 6746 6747 if (chdir(path) == -1) { 6748 msg(ERRN, "remove_dir() failed to chdir(\"%s\") ", path); 6749 return (-1); 6750 } 6751 6752 /* 6753 * Read every directory entry. 6754 */ 6755 while ((direct = readdir(name)) != NULL) { 6756 /* 6757 * Ignore "." and ".." entries. 6758 */ 6759 if (strcmp(direct->d_name, ".") == 0 || 6760 strcmp(direct->d_name, "..") == 0) 6761 continue; 6762 6763 if (lstat(direct->d_name, &sbuf) == -1) { 6764 msg(ERRN, MSG1, direct->d_name); 6765 (void) closedir(name); 6766 return (-1); 6767 } 6768 6769 if (S_ISDIR(sbuf.st_mode)) { 6770 if (remove_dir(direct->d_name) == -1) { 6771 msg(ERRN, MSG2, direct->d_name); 6772 (void) closedir(name); 6773 return (-1); 6774 } 6775 } else { 6776 if (unlink(direct->d_name) == -1) { 6777 msg(ERRN, MSG3, direct->d_name); 6778 (void) closedir(name); 6779 return (-1); 6780 } 6781 } 6782 6783 } 6784 6785 /* 6786 * Close the directory we just finished reading. 6787 */ 6788 (void) closedir(name); 6789 6790 /* 6791 * Change directory to the parent directory... 6792 */ 6793 if (chdir("..") == -1) { 6794 msg(ERRN, "remove_dir() failed to chdir(\"..\") "); 6795 return (-1); 6796 } 6797 6798 /* 6799 * ...and finally remove the directory; note we have to 6800 * make a copy since basename is free to modify its input. 6801 */ 6802 path_copy = e_strdup(E_NORMAL, path); 6803 if (path_copy == NULL) { 6804 msg(ERRN, "cannot strdup() the directory pathname "); 6805 return (-1); 6806 } 6807 6808 if (rmdir(basename(path_copy)) == -1) { 6809 free(path_copy); 6810 msg(ERRN, "remove_dir() failed to rmdir(\"%s\") ", path); 6811 return (-1); 6812 } 6813 6814 free(path_copy); 6815 return (0); 6816 6817 } 6818 6819 static int 6820 save_cwd(void) 6821 { 6822 return (open(".", O_RDONLY)); 6823 } 6824 6825 static void 6826 rest_cwd(int cwd) 6827 { 6828 (void) fchdir(cwd); 6829 (void) close(cwd); 6830 } 6831 6832 #if defined(O_XATTR) 6833 static void 6834 xattrs_out(int (*func)()) 6835 { 6836 int dirpfd; 6837 int filefd; 6838 DIR *dirp; 6839 struct dirent *dp; 6840 int slen; 6841 char *namep, *savenamep; 6842 6843 if (pathconf(G_p->g_nam_p, _PC_XATTR_EXISTS) != 1) { 6844 return; 6845 } 6846 6847 /* 6848 * If aclp still exists then free it since it is was set when base 6849 * file was extracted. 6850 */ 6851 if (aclp != (aclent_t *)NULL) { 6852 free(aclp); 6853 aclcnt = 0; 6854 aclp = NULL; 6855 acl_set = 0; 6856 } 6857 6858 Gen.g_dirfd = attropen(G_p->g_nam_p, ".", O_RDONLY); 6859 if (Gen.g_dirfd == -1) { 6860 msg(ERRN, "Cannot open attribute directory of file \"%s\"", 6861 G_p->g_nam_p); 6862 return; 6863 6864 } 6865 savenamep = G_p->g_nam_p; 6866 6867 if ((dirpfd = dup(Gen.g_dirfd)) == -1) { 6868 msg(ERRN, "Cannot dup(2) attribute directory descriptor"); 6869 return; 6870 } 6871 6872 if ((dirp = fdopendir(dirpfd)) == (DIR *)NULL) { 6873 msg(ERRN, "Cannot fdopendir(2) directory file descriptor"); 6874 return; 6875 } 6876 6877 while ((dp = readdir(dirp)) != (struct dirent *)NULL) { 6878 if (strcmp(dp->d_name, "..") == 0) { 6879 continue; 6880 } 6881 6882 if (strcmp(dp->d_name, ".") == 0) { 6883 Hiddendir = 1; 6884 } else { 6885 Hiddendir = 0; 6886 } 6887 6888 Gen.g_attrnam_p = dp->d_name; 6889 6890 if (STAT(Gen.g_dirfd, Gen.g_nam_p, &SrcSt) == -1) { 6891 msg(ERRN, 6892 "Could not fstatat(2) attribute \"%s\" of" 6893 " file \"%s\"", dp->d_name, savenamep); 6894 continue; 6895 } 6896 6897 if (Use_old_stat) { 6898 OldSt = convert_to_old_stat(&SrcSt, 6899 Gen.g_nam_p, Gen.g_attrnam_p); 6900 6901 if (OldSt == NULL) { 6902 msg(ERRN, 6903 "Could not convert to old stat format"); 6904 continue; 6905 } 6906 } 6907 6908 Gen.g_attrfnam_p = savenamep; 6909 6910 /* 6911 * Set up dummy header name 6912 * 6913 * One piece is written with .hdr, which 6914 * contains the actual xattr hdr or pathing information 6915 * then the name is updated to drop the .hdr off 6916 * and the actual file itself is archived. 6917 */ 6918 slen = strlen(Gen.g_attrnam_p) + strlen(DEVNULL) + 6919 strlen(XATTRHDR) + 1; 6920 if ((namep = e_zalloc(E_NORMAL, slen)) == (char *)NULL) { 6921 msg(ERRN, "Could not calloc memory for attribute name"); 6922 continue; 6923 } 6924 (void) sprintf(namep, "%s/%s%s", 6925 DEVNULL, Gen.g_attrnam_p, XATTRHDR); 6926 Gen.g_nam_p = namep; 6927 6928 /* 6929 * Get attribute's ACL info: don't bother allocating space 6930 * if there are only standard permissions, i.e. ACL count < 4 6931 */ 6932 if (Pflag) { 6933 filefd = openat(Gen.g_dirfd, dp->d_name, O_RDONLY); 6934 if (filefd == -1) { 6935 msg(ERRN, 6936 "Could not open attribute \"%s\" of" 6937 " file \"%s\"", dp->d_name, savenamep); 6938 free(namep); 6939 continue; 6940 } 6941 if ((aclcnt = facl(filefd, GETACLCNT, 6942 0, NULL)) < 0) { 6943 msg(ERRN, 6944 "Error with acl() on %s", 6945 Gen.g_nam_p); 6946 } 6947 if (aclcnt > MIN_ACL_ENTRIES) { 6948 aclp = e_zalloc(E_EXIT, 6949 sizeof (aclent_t) * aclcnt); 6950 6951 if (facl(filefd, GETACL, aclcnt, aclp) < 0) { 6952 msg(ERRN, 6953 "Error with getacl() on %s", 6954 Gen.g_nam_p); 6955 free(aclp); 6956 aclp = NULL; 6957 } 6958 } 6959 (void) close(filefd); 6960 } 6961 (void) creat_hdr(); 6962 (void) (*func)(); 6963 if (Gen.g_passdirfd != -1) { 6964 (void) close(Gen.g_passdirfd); 6965 Gen.g_passdirfd = -1; 6966 } 6967 Gen.g_attrnam_p = (char *)NULL; 6968 Gen.g_attrfnam_p = (char *)NULL; 6969 Gen.g_linktoattrfnam_p = (char *)NULL; 6970 Gen.g_linktoattrnam_p = (char *)NULL; 6971 if (aclp != (aclent_t *)NULL) { 6972 free(aclp); 6973 aclcnt = 0; 6974 aclp = NULL; 6975 acl_set = 0; 6976 } 6977 free(namep); 6978 } 6979 6980 (void) closedir(dirp); 6981 (void) close(Gen.g_dirfd); 6982 Gen.g_dirfd = -1; 6983 } 6984 #else 6985 static void 6986 xattrs_out(int (*func)()) 6987 { 6988 } 6989 #endif 6990 6991 /* 6992 * Return the parent directory of a given path. 6993 * 6994 * Examples: 6995 * /usr/tmp return /usr 6996 * /usr/tmp/file return /usr/tmp 6997 * / returns . 6998 * /usr returns / 6999 * file returns . 7000 * 7001 * dir is assumed to be at least as big as path. 7002 */ 7003 static void 7004 get_parent(char *path, char *dir) 7005 { 7006 char *s; 7007 char tmpdir[PATH_MAX + 1]; 7008 7009 if (strlen(path) > PATH_MAX) { 7010 msg(EXT, "pathname is too long"); 7011 } 7012 (void) strcpy(tmpdir, path); 7013 chop_endslashes(tmpdir); 7014 7015 if ((s = strrchr(tmpdir, '/')) == NULL) { 7016 (void) strcpy(dir, "."); 7017 } else { 7018 s = skipslashes(s, tmpdir); 7019 *s = '\0'; 7020 if (s == tmpdir) 7021 (void) strcpy(dir, "/"); 7022 else 7023 (void) strcpy(dir, tmpdir); 7024 } 7025 } 7026 7027 #if defined(O_XATTR) 7028 #define ROUNDTOTBLOCK(a) ((a + (TBLOCK -1)) & ~(TBLOCK -1)) 7029 7030 static void 7031 prepare_xattr_hdr( 7032 char **attrbuf, 7033 char *filename, 7034 char *attrname, 7035 char typeflag, 7036 struct Lnk *linkinfo, 7037 int *rlen) 7038 { 7039 char *bufhead; /* ptr to full buffer */ 7040 struct xattr_hdr *hptr; /* ptr to header in bufhead */ 7041 struct xattr_buf *tptr; /* ptr to pathing pieces */ 7042 int totalen; /* total buffer length */ 7043 int len; /* length returned to user */ 7044 int stringlen; /* length of filename + attr */ 7045 int linkstringlen; /* ditto in link section */ 7046 int complen; /* length of pathing section */ 7047 int linklen; /* length of link section */ 7048 7049 7050 /* 7051 * Release previous buffer if any. 7052 */ 7053 7054 if (*attrbuf != (char *)NULL) { 7055 free(*attrbuf); 7056 *attrbuf = NULL; 7057 } 7058 7059 /* 7060 * First add in fixed size stuff 7061 */ 7062 len = sizeof (struct xattr_hdr) + sizeof (struct xattr_buf); 7063 7064 /* 7065 * Add space for two nulls 7066 */ 7067 stringlen = strlen(attrname) + strlen(filename) + 2; 7068 complen = stringlen + sizeof (struct xattr_buf); 7069 7070 len += stringlen; 7071 7072 /* 7073 * Now add on space for link info if any 7074 */ 7075 7076 if (linkinfo != NULL) { 7077 /* 7078 * Again add space for two nulls 7079 */ 7080 linkstringlen = strlen(linkinfo->L_gen.g_attrfnam_p) + 7081 strlen(linkinfo->L_gen.g_attrnam_p) + 2; 7082 len += linkstringlen; 7083 } 7084 7085 /* 7086 * Now add padding to end to fill out TBLOCK 7087 * 7088 * Function returns size of real data and not size + padding. 7089 */ 7090 7091 totalen = ROUNDTOTBLOCK(len); 7092 bufhead = e_zalloc(E_EXIT, totalen); 7093 7094 /* 7095 * Now we can fill in the necessary pieces 7096 */ 7097 7098 if (linkinfo != (struct Lnk *)NULL) { 7099 linklen = linkstringlen + (sizeof (struct xattr_buf)); 7100 } else { 7101 linklen = 0; 7102 } 7103 7104 /* 7105 * first fill in the fixed header 7106 */ 7107 hptr = (struct xattr_hdr *)bufhead; 7108 (void) sprintf(hptr->h_version, "%s", XATTR_ARCH_VERS); 7109 (void) sprintf(hptr->h_component_len, "%0*d", 7110 sizeof (hptr->h_component_len) - 1, complen); 7111 (void) sprintf(hptr->h_link_component_len, "%0*d", 7112 sizeof (hptr->h_link_component_len) - 1, linklen); 7113 (void) sprintf(hptr->h_size, "%0*d", sizeof (hptr->h_size) - 1, len); 7114 7115 /* 7116 * Now fill in the filename + attrnames section 7117 */ 7118 7119 tptr = (struct xattr_buf *)(bufhead + sizeof (struct xattr_hdr)); 7120 (void) sprintf(tptr->h_namesz, "%0*d", sizeof (tptr->h_namesz) - 1, 7121 stringlen); 7122 (void) strcpy(tptr->h_names, filename); 7123 (void) strcpy(&tptr->h_names[strlen(filename) + 1], attrname); 7124 tptr->h_typeflag = typeflag; 7125 7126 /* 7127 * Now fill in the optional link section if we have one 7128 */ 7129 7130 if (linkinfo != (struct Lnk *)NULL) { 7131 tptr = (struct xattr_buf *)(bufhead + 7132 sizeof (struct xattr_hdr) + complen); 7133 7134 (void) sprintf(tptr->h_namesz, "%0*d", 7135 sizeof (tptr->h_namesz) - 1, linkstringlen); 7136 (void) strcpy(tptr->h_names, linkinfo->L_gen.g_attrfnam_p); 7137 (void) strcpy( 7138 &tptr->h_names[strlen(linkinfo->L_gen.g_attrfnam_p) + 1], 7139 linkinfo->L_gen.g_attrnam_p); 7140 tptr->h_typeflag = typeflag; 7141 } 7142 *attrbuf = (char *)bufhead; 7143 *rlen = len; 7144 } 7145 #endif /* O_XATTR */ 7146 7147 static char 7148 tartype(int type) 7149 { 7150 switch (type) { 7151 7152 case S_IFDIR: 7153 return (DIRTYPE); 7154 7155 case S_IFLNK: 7156 return (SYMTYPE); 7157 7158 case S_IFIFO: 7159 return (FIFOTYPE); 7160 7161 case S_IFCHR: 7162 return (CHRTYPE); 7163 7164 case S_IFBLK: 7165 return (BLKTYPE); 7166 7167 case S_IFREG: 7168 return (REGTYPE); 7169 7170 default: 7171 return ('\0'); 7172 } 7173 } 7174 7175 #if defined(O_XATTR) 7176 static int 7177 openfile(int omode) 7178 { 7179 7180 if (G_p->g_attrnam_p != (char *)NULL) { 7181 return (attropen(G_p->g_attrfnam_p, G_p->g_attrnam_p, omode)); 7182 } else { 7183 return (openat(G_p->g_dirfd, 7184 get_component(G_p->g_nam_p), omode)); 7185 } 7186 } 7187 #else 7188 static int 7189 openfile(int omode) 7190 { 7191 return (openat(G_p->g_dirfd, get_component(G_p->g_nam_p), omode)); 7192 } 7193 #endif 7194 7195 #if defined(O_XATTR) 7196 static int 7197 read_xattr_hdr() 7198 { 7199 off_t bytes; 7200 int comp_len, link_len; 7201 int namelen; 7202 int cnt; 7203 char *tp; 7204 int pad; 7205 7206 /* 7207 * Include any padding in the read. We need to be positioned 7208 * at beginning of next header. 7209 */ 7210 7211 bytes = Gen.g_filesz; 7212 7213 if ((xattrhead = e_zalloc(E_NORMAL, (size_t)bytes)) == NULL) { 7214 (void) fprintf(stderr, gettext( 7215 "Insufficient memory for extended attribute\n")); 7216 return (1); 7217 } 7218 7219 tp = (char *)xattrhead; 7220 while (bytes > 0) { 7221 cnt = (int)(bytes > CPIOBSZ) ? CPIOBSZ : bytes; 7222 FILL(cnt); 7223 (void) memcpy(tp, Buffr.b_out_p, cnt); 7224 tp += cnt; 7225 Buffr.b_out_p += cnt; 7226 Buffr.b_cnt -= (off_t)cnt; 7227 bytes -= (off_t)cnt; 7228 } 7229 7230 pad = (Pad_val + 1 - (Gen.g_filesz & Pad_val)) & 7231 Pad_val; 7232 if (pad != 0) { 7233 FILL(pad); 7234 Buffr.b_out_p += pad; 7235 Buffr.b_cnt -= (off_t)pad; 7236 } 7237 7238 /* 7239 * Validate that we can handle header format 7240 */ 7241 7242 if (strcmp(xattrhead->h_version, XATTR_ARCH_VERS) != 0) { 7243 (void) fprintf(stderr, 7244 gettext("Unknown extended attribute format encountered\n")); 7245 (void) fprintf(stderr, 7246 gettext("Disabling extended attribute header parsing\n")); 7247 xattrbadhead = 1; 7248 return (1); 7249 } 7250 (void) sscanf(xattrhead->h_component_len, "%10d", &comp_len); 7251 (void) sscanf(xattrhead->h_link_component_len, "%10d", &link_len); 7252 xattrp = (struct xattr_buf *)(((char *)xattrhead) + 7253 sizeof (struct xattr_hdr)); 7254 (void) sscanf(xattrp->h_namesz, "%7d", &namelen); 7255 if (link_len > 0) { 7256 xattr_linkp = (struct xattr_buf *)((int)xattrp + (int)comp_len); 7257 } else { 7258 xattr_linkp = NULL; 7259 } 7260 7261 return (0); 7262 } 7263 #endif 7264 7265 static mode_t 7266 attrmode(char type) 7267 { 7268 mode_t mode; 7269 7270 switch (type) { 7271 case '\0': 7272 case REGTYPE: 7273 case LNKTYPE: 7274 mode = S_IFREG; 7275 break; 7276 7277 case SYMTYPE: 7278 mode = S_IFLNK; 7279 break; 7280 7281 case CHRTYPE: 7282 mode = S_IFCHR; 7283 break; 7284 case BLKTYPE: 7285 mode = S_IFBLK; 7286 break; 7287 case DIRTYPE: 7288 mode = S_IFDIR; 7289 break; 7290 case FIFOTYPE: 7291 mode = S_IFIFO; 7292 break; 7293 case CONTTYPE: 7294 default: 7295 mode = 0; 7296 } 7297 7298 return (mode); 7299 } 7300 7301 #if defined(O_XATTR) 7302 static char * 7303 get_component(char *path) 7304 { 7305 char *ptr; 7306 7307 ptr = strrchr(path, '/'); 7308 if (ptr == NULL) { 7309 return (path); 7310 } else { 7311 /* 7312 * Handle trailing slash 7313 */ 7314 if (*(ptr + 1) == '\0') 7315 return (ptr); 7316 else 7317 return (ptr + 1); 7318 } 7319 } 7320 #else 7321 static char * 7322 get_component(char *path) 7323 { 7324 return (path); 7325 } 7326 #endif 7327 7328 static int 7329 open_dir(char *name) 7330 { 7331 int fd = -1; 7332 int cnt = 0; 7333 char *dir; 7334 7335 dir = e_zalloc(E_EXIT, strlen(name) + 1); 7336 7337 /* 7338 * open directory; creating missing directories along the way. 7339 */ 7340 get_parent(name, dir); 7341 do { 7342 fd = open(dir, O_RDONLY); 7343 if (fd != -1) { 7344 free(dir); 7345 return (fd); 7346 } 7347 cnt++; 7348 } while (cnt <= 1 && missdir(name) == 0); 7349 7350 free(dir); 7351 return (-1); 7352 } 7353 7354 static int 7355 open_dirfd() 7356 { 7357 #ifdef O_XATTR 7358 if ((Args & OCt) == 0) { 7359 close_dirfd(); 7360 if (G_p->g_attrnam_p != (char *)NULL) { 7361 G_p->g_dirfd = attropen(G_p->g_attrfnam_p, 7362 ".", O_RDONLY); 7363 if (G_p->g_dirfd == -1 && (Args & (OCi | OCp))) { 7364 G_p->g_dirfd = 7365 retry_attrdir_open(G_p->g_attrfnam_p); 7366 if (G_p->g_dirfd == -1) { 7367 msg(ERRN, 7368 "Cannot open attribute" 7369 " directory of file %s", 7370 G_p->g_attrfnam_p); 7371 return (1); 7372 } 7373 } 7374 } else { 7375 G_p->g_dirfd = open_dir(G_p->g_nam_p); 7376 if (G_p->g_dirfd == -1) { 7377 msg(ERRN, 7378 "Cannot open/create %s", G_p->g_nam_p); 7379 return (1); 7380 } 7381 } 7382 } else { 7383 G_p->g_dirfd = -1; 7384 } 7385 #else 7386 G_p->g_dirfd = -1; 7387 #endif 7388 return (0); 7389 } 7390 7391 static void 7392 close_dirfd() 7393 { 7394 if (G_p->g_dirfd != -1) { 7395 (void) close(G_p->g_dirfd); 7396 G_p->g_dirfd = -1; 7397 } 7398 } 7399 7400 static void 7401 write_xattr_hdr() 7402 { 7403 char *attrbuf = NULL; 7404 int attrlen = 0; 7405 char *namep; 7406 struct Lnk *tl_p, *linkinfo; 7407 7408 7409 /* 7410 * namep was allocated in xattrs_out. It is big enough to hold 7411 * either the name + .hdr on the end or just the attr name 7412 */ 7413 7414 #if defined(O_XATTR) 7415 namep = Gen.g_nam_p; 7416 (void) creat_hdr(); 7417 7418 7419 if (Args & OCo) { 7420 linkinfo = NULL; 7421 tl_p = Lnk_hd.L_nxt_p; 7422 while (tl_p != &Lnk_hd) { 7423 if (tl_p->L_gen.g_ino == G_p->g_ino && 7424 tl_p->L_gen.g_dev == G_p->g_dev) { 7425 linkinfo = tl_p; 7426 break; /* found */ 7427 } 7428 tl_p = tl_p->L_nxt_p; 7429 } 7430 prepare_xattr_hdr(&attrbuf, Gen.g_attrfnam_p, 7431 Gen.g_attrnam_p, 7432 (linkinfo == (struct Lnk *)NULL) ? 7433 tartype(Gen.g_mode & Ftype) : LNKTYPE, 7434 linkinfo, &attrlen); 7435 Gen.g_filesz = attrlen; 7436 write_hdr(ARCHIVE_XATTR, (off_t)attrlen); 7437 (void) sprintf(namep, "%s/%s", DEVNULL, Gen.g_attrnam_p); 7438 (void) write_ancillary(attrbuf, attrlen); 7439 } 7440 7441 (void) creat_hdr(); 7442 #endif 7443 } 7444 7445 static int 7446 retry_attrdir_open(char *name) 7447 { 7448 int dirfd = -1; 7449 struct timeval times[2]; 7450 mode_t newmode; 7451 struct stat parentstat; 7452 7453 /* 7454 * We couldn't get to attrdir. See if its 7455 * just a mode problem on the parent file. 7456 * for example: a mode such as r-xr--r-- 7457 * won't let us create an attribute dir 7458 * if it doesn't already exist. 7459 */ 7460 7461 if (stat(name, &parentstat) == -1) { 7462 msg(ERRN, "Cannot stat file %s", name); 7463 return (-1); 7464 } 7465 newmode = S_IWUSR | parentstat.st_mode; 7466 if (chmod(name, newmode) == -1) { 7467 msg(ERRN, "Cannot change mode of file %s to %o", name, newmode); 7468 return (-1); 7469 } 7470 7471 dirfd = attropen(name, ".", O_RDONLY); 7472 if (dirfd == -1) { 7473 msg(ERRN, "Cannot open attribute directory of file %s", name); 7474 return (-1); 7475 } else { 7476 7477 /* 7478 * Put mode back to original 7479 */ 7480 if (chmod(name, parentstat.st_mode) != 0) { 7481 msg(ERRN, "Cannot restore permissions of file %s to %o", 7482 name, parentstat.st_mode); 7483 } 7484 7485 /* 7486 * Put back time stamps 7487 */ 7488 7489 times[0].tv_sec = parentstat.st_atime; 7490 times[0].tv_usec = 0; 7491 times[1].tv_sec = parentstat.st_mtime; 7492 times[1].tv_usec = 0; 7493 if (utimes(name, times) != 0) { 7494 msg(ERRN, "Cannot reset timestamps on file %s"); 7495 } 7496 } 7497 7498 return (dirfd); 7499 } 7500 7501 /* 7502 * skip over extra slashes in string. 7503 * 7504 * For example: 7505 * /usr/tmp///// 7506 * 7507 * would return pointer at 7508 * /usr/tmp///// 7509 * ^ 7510 */ 7511 static char * 7512 skipslashes(char *string, char *start) 7513 { 7514 while ((string > start) && *(string - 1) == '/') { 7515 string--; 7516 } 7517 7518 return (string); 7519 } 7520 7521 static sl_info_t * 7522 sl_info_alloc(void) 7523 { 7524 static int num_left; 7525 static sl_info_t *slipool; 7526 7527 if (num_left > 0) { 7528 return (&slipool[--num_left]); 7529 } 7530 num_left = SL_INFO_ALLOC_CHUNK; 7531 slipool = e_zalloc(E_EXIT, sizeof (sl_info_t) * num_left); 7532 return (&slipool[--num_left]); 7533 } 7534 7535 /* 7536 * If a match for the key values was found in the tree, return a pointer to it. 7537 * If a match was not found, insert it and return a pointer to it. This is 7538 * based on Knuth's Algorithm A in Vol 3, section 6.2.3. 7539 */ 7540 7541 sl_info_t * 7542 sl_insert(dev_t device, ino_t inode) 7543 { 7544 sl_info_t *p; /* moves down the tree */ 7545 sl_info_t *q; /* scratch */ 7546 sl_info_t *r; /* scratch */ 7547 sl_info_t *s; /* pt where rebalancing may be needed */ 7548 sl_info_t *t; /* father of s */ 7549 sl_info_t *head; 7550 7551 int a; /* used to hold balance factors */ 7552 int done; /* loop control */ 7553 int cmpflg; /* used to hold the result of a comparison */ 7554 7555 /* initialize */ 7556 7557 head = sl_devhash_lookup(device); 7558 7559 if (head == NULL) { 7560 head = sl_info_alloc(); 7561 head->llink = NULL; 7562 head->bal = 0; 7563 7564 p = head->rlink = sl_info_alloc(); 7565 p->sl_ino = inode; 7566 p->sl_count = 0; 7567 p->bal = 0; 7568 p->llink = NULL; 7569 p->rlink = NULL; 7570 sl_devhash_insert(device, head); 7571 return (p); 7572 } 7573 7574 t = head; 7575 s = p = head->rlink; 7576 7577 /* compare */ 7578 7579 for (done = 0; ! done; ) { 7580 switch (sl_compare(inode, p->sl_ino)) { 7581 case -1: 7582 /* move left */ 7583 7584 q = p->llink; 7585 7586 if (q == NULL) { 7587 q = sl_info_alloc(); 7588 p->llink = q; 7589 done = 1; 7590 continue; 7591 } 7592 7593 break; 7594 7595 case 0: 7596 /* found it */ 7597 return (p); 7598 break; 7599 7600 case 1: 7601 /* move right */ 7602 7603 q = p->rlink; 7604 7605 if (q == NULL) { 7606 q = sl_info_alloc(); 7607 p->rlink = q; 7608 done = 1; 7609 continue; 7610 } 7611 7612 break; 7613 } 7614 7615 if (q->bal != 0) { 7616 t = p; 7617 s = q; 7618 } 7619 7620 p = q; 7621 } 7622 7623 /* insert */ 7624 7625 q->sl_ino = inode; 7626 q->sl_count = 0; 7627 q->llink = q->rlink = NULL; 7628 q->bal = 0; 7629 7630 /* adjust balance factors */ 7631 7632 if ((cmpflg = sl_compare(inode, s->sl_ino)) < 0) { 7633 r = p = s->llink; 7634 } else { 7635 r = p = s->rlink; 7636 } 7637 7638 while (p != q) { 7639 switch (sl_compare(inode, p->sl_ino)) { 7640 case -1: 7641 p->bal = -1; 7642 p = p->llink; 7643 break; 7644 7645 case 0: 7646 break; 7647 7648 case 1: 7649 p->bal = 1; 7650 p = p->rlink; 7651 break; 7652 } 7653 } 7654 7655 /* balancing act */ 7656 7657 if (cmpflg < 0) { 7658 a = -1; 7659 } else { 7660 a = 1; 7661 } 7662 7663 if (s->bal == 0) { 7664 s->bal = a; 7665 head->llink = (sl_info_t *)((int)head->llink + 1); 7666 return (q); 7667 } else if (s->bal == -a) { 7668 s->bal = 0; 7669 return (q); 7670 } 7671 7672 /* 7673 * (s->bal == a) 7674 */ 7675 7676 if (r->bal == a) { 7677 /* single rotation */ 7678 7679 p = r; 7680 7681 if (a == -1) { 7682 s->llink = r->rlink; 7683 r->rlink = s; 7684 } else if (a == 1) { 7685 s->rlink = r->llink; 7686 r->llink = s; 7687 } 7688 7689 s->bal = r->bal = 0; 7690 7691 } else if (r->bal == -a) { 7692 /* double rotation */ 7693 7694 if (a == -1) { 7695 p = r->rlink; 7696 r->rlink = p->llink; 7697 p->llink = r; 7698 s->llink = p->rlink; 7699 p->rlink = s; 7700 } else if (a == 1) { 7701 p = r->llink; 7702 r->llink = p->rlink; 7703 p->rlink = r; 7704 s->rlink = p->llink; 7705 p->llink = s; 7706 } 7707 7708 if (p->bal == 0) { 7709 s->bal = 0; 7710 r->bal = 0; 7711 } else if (p->bal == -a) { 7712 s->bal = 0; 7713 r->bal = a; 7714 } else if (p->bal == a) { 7715 s->bal = -a; 7716 r->bal = 0; 7717 } 7718 7719 p->bal = 0; 7720 } 7721 7722 /* finishing touch */ 7723 7724 if (s == t->rlink) { 7725 t->rlink = p; 7726 } else { 7727 t->llink = p; 7728 } 7729 7730 return (q); 7731 } 7732 7733 /* 7734 * sl_numlinks: return the number of links that we saw during our preview. 7735 */ 7736 7737 static ulong_t 7738 sl_numlinks(dev_t device, ino_t inode) 7739 { 7740 sl_info_t *p = sl_search(device, inode); 7741 7742 if (p) { 7743 return (p->sl_count); 7744 } else { 7745 return (1); 7746 } 7747 } 7748 7749 /* 7750 * sl_preview_synonyms: Read the file list from the input stream, remembering 7751 * each reference to each file. 7752 */ 7753 7754 static void 7755 sl_preview_synonyms(void) 7756 { 7757 char buf [APATH+1]; 7758 char *s; 7759 7760 char *suffix = "/cpioXXXXXX"; 7761 char *tmpdir = getenv("TMPDIR"); 7762 int tmpfd, islnk; 7763 FILE *tmpfile; 7764 char *tmpfname; 7765 7766 if (tmpdir == NULL || *tmpdir == '\0' || 7767 (strlen(tmpdir) + strlen(suffix)) > APATH) { 7768 struct statvfs tdsb; 7769 7770 tmpdir = "/var/tmp"; 7771 7772 /* /var/tmp is read-only in the mini-root environment */ 7773 7774 if (statvfs(tmpdir, &tdsb) == -1 || tdsb.f_flag & ST_RDONLY) { 7775 tmpdir = "/tmp"; 7776 } 7777 } 7778 7779 tmpfname = e_zalloc(E_EXIT, strlen(tmpdir) + strlen(suffix) + 1); 7780 7781 (void) strcpy(tmpfname, tmpdir); 7782 (void) strcat(tmpfname, suffix); 7783 7784 if ((tmpfd = mkstemp(tmpfname)) == -1) { 7785 msg(EXTN, "cannot open tmpfile %s", tmpfname); 7786 } 7787 7788 if (unlink(tmpfname) == -1) { 7789 msg(EXTN, "cannot unlink tmpfile %s", tmpfname); 7790 } 7791 7792 if ((tmpfile = fdopen(tmpfd, "w+")) == NULL) { 7793 msg(EXTN, "cannot fdopen tmpfile %s", tmpfname); 7794 } 7795 7796 while ((s = fgets(buf, APATH+1, In_p)) != NULL) { 7797 size_t lastchar; 7798 struct stat sb; 7799 7800 if (fputs(buf, tmpfile) == EOF) { 7801 msg(EXTN, "problem writing to tmpfile %s", tmpfname); 7802 } 7803 7804 /* pre-process the name */ 7805 7806 lastchar = strlen(s) - 1; 7807 7808 if (s[lastchar] != '\n' && lastchar == APATH - 1) { 7809 continue; 7810 } else { 7811 s[lastchar] = '\0'; 7812 } 7813 7814 while (s[0] == '.' && s[1] == '/') { 7815 s += 2; 7816 while (s[0] == '/') { 7817 s++; 7818 } 7819 } 7820 7821 if (lstat(s, &sb) < 0) { 7822 continue; 7823 } 7824 islnk = 0; 7825 if (S_ISLNK(sb.st_mode)) { 7826 islnk = 1; 7827 if (Args & OCL) { 7828 if (stat(s, &sb) < 0) { 7829 continue; 7830 } 7831 } 7832 } 7833 sl_remember_tgt(&sb, islnk); 7834 7835 #if defined(O_XATTR) 7836 if (Atflag) { 7837 int dirfd; 7838 DIR *dirp; 7839 struct dirent *dp; 7840 7841 if (pathconf(s, _PC_XATTR_EXISTS) != 1) 7842 continue; 7843 7844 dirfd = attropen(s, ".", O_RDONLY); 7845 if (dirfd == -1) 7846 continue; 7847 7848 tmpfd = dup(dirfd); 7849 if (tmpfd == -1) { 7850 (void) close(dirfd); 7851 continue; 7852 } 7853 dirp = fdopendir(tmpfd); 7854 if (dirp == NULL) { 7855 (void) close(dirfd); 7856 (void) close(tmpfd); 7857 continue; 7858 } 7859 7860 while (dp = readdir(dirp)) { 7861 if ((dp->d_name[0] == '.' && 7862 dp->d_name[1] == '\0') || 7863 (dp->d_name[0] == '.' && 7864 dp->d_name[1] == '.' && 7865 dp->d_name[2] == '\0')) 7866 continue; 7867 7868 if (fstatat(dirfd, dp->d_name, &sb, 7869 AT_SYMLINK_NOFOLLOW) < 0) { 7870 continue; 7871 } 7872 islnk = 0; 7873 if (S_ISLNK(sb.st_mode)) { 7874 islnk = 1; 7875 if (Args & OCL) { 7876 if (fstatat(dirfd, dp->d_name, 7877 &sb, 0) < 0) { 7878 continue; 7879 } 7880 } 7881 } 7882 sl_remember_tgt(&sb, islnk); 7883 } 7884 (void) closedir(dirp); 7885 (void) close(dirfd); 7886 } 7887 #endif 7888 } 7889 7890 if (ferror(In_p)) { 7891 msg(EXTN, "error reading stdin"); 7892 } 7893 7894 if (fseek(tmpfile, 0L, SEEK_SET) == -1) { 7895 msg(EXTN, "cannot fseek on tmpfile %s", tmpfname); 7896 } 7897 7898 In_p = tmpfile; 7899 free(tmpfname); 7900 } 7901 7902 /* 7903 * sl_remember_tgt: Add the device/inode for lstat or stat info to the list of 7904 * those we've seen before. 7905 * 7906 * This tree (rooted under head) is keyed by the device/inode of the file 7907 * being pointed to. A count is kept of the number of references encountered 7908 * so far. 7909 */ 7910 7911 static void 7912 sl_remember_tgt(const struct stat *sbp, int isSymlink) 7913 { 7914 sl_info_t *p; 7915 dev_t device; 7916 ino_t inode; 7917 7918 device = sbp->st_dev; 7919 inode = sbp->st_ino; 7920 7921 /* Determine whether we've seen this one before */ 7922 7923 p = sl_insert(device, inode); 7924 7925 if (p->sl_count > 0) { 7926 /* 7927 * We have seen this file before. 7928 * Note that if we are not chasing symlinks, and this one is a 7929 * symlink, it is identically the one we saw before (you cannot 7930 * have hard links to symlinks); in this case, we leave the 7931 * count alone, so that we don't wind up archiving a symlink to 7932 * itself. 7933 */ 7934 7935 if ((Args & OCL) || (! isSymlink)) { 7936 p->sl_count++; 7937 } 7938 } else { 7939 /* We have not seen this file before */ 7940 7941 p->sl_count = 1; 7942 7943 if (Use_old_stat) { 7944 /* -Hodc: remap inode (-1 on overflow) */ 7945 7946 sl_remap_t *q; 7947 7948 for (q = sl_remap_head; q && (q->dev != device); 7949 q = q->next) { 7950 /* do nothing */ 7951 } 7952 7953 if (q == NULL) { 7954 q = e_zalloc(E_EXIT, sizeof (sl_remap_t)); 7955 q->dev = device; 7956 p->sl_ino2 = q->inode_count = 1; 7957 7958 q->next = (sl_remap_head) ? 7959 sl_remap_head->next : NULL; 7960 sl_remap_head = q; 7961 } else { 7962 if ((size_t)q->inode_count <= 7963 ((1 << (sizeof (o_ino_t) * 8)) - 1)) { 7964 /* fits in o_ino_t */ 7965 p->sl_ino2 = ++(q->inode_count); 7966 } else { 7967 p->sl_ino2 = (ino_t)-1; 7968 } 7969 } 7970 } 7971 } 7972 } 7973 7974 /* 7975 * A faster search, which does not insert the key values into the tree. 7976 * If the a match was found in the tree, return a pointer to it. If it was not 7977 * found, return NULL. 7978 */ 7979 7980 sl_info_t * 7981 sl_search(dev_t device, ino_t inode) 7982 { 7983 sl_info_t *p; /* moves down the tree */ 7984 int c; /* comparison value */ 7985 sl_info_t *retval = NULL; /* return value */ 7986 sl_info_t *head; 7987 7988 head = sl_devhash_lookup(device); 7989 if (head != NULL) { 7990 for (p = head->rlink; p; ) { 7991 if ((c = sl_compare(inode, p->sl_ino)) == 0) { 7992 retval = p; 7993 break; 7994 } else if (c < 0) { 7995 p = p->llink; 7996 } else { 7997 p = p->rlink; 7998 } 7999 } 8000 } 8001 8002 return (retval); 8003 } 8004 8005 static sl_info_t * 8006 sl_devhash_lookup(dev_t device) 8007 { 8008 int key; 8009 sl_info_link_t *lp; 8010 static sl_info_link_t *devcache; 8011 8012 if (devcache != NULL && devcache->dev == device) { 8013 return (devcache->head); 8014 } 8015 8016 key = DEV_HASHKEY(device); 8017 for (lp = sl_devhash[key]; lp; lp = lp->next) { 8018 if (lp->dev == device) { 8019 devcache = lp; 8020 return (lp->head); 8021 } 8022 } 8023 return (NULL); 8024 } 8025 8026 static void 8027 sl_devhash_insert(dev_t device, sl_info_t *head) 8028 { 8029 int key = DEV_HASHKEY(device); 8030 sl_info_link_t *lp; 8031 8032 lp = e_zalloc(E_EXIT, sizeof (sl_info_link_t)); 8033 lp->dev = device; 8034 lp->head = head; 8035 lp->next = sl_devhash[key]; 8036 sl_devhash[key] = lp; 8037 } 8038 8039 static void 8040 chop_endslashes(char *path) 8041 { 8042 char *end, *ptr; 8043 8044 end = &path[strlen(path) -1]; 8045 if (*end == '/' && end != path) { 8046 ptr = skipslashes(end, path); 8047 if (ptr != NULL && ptr != path) { 8048 *ptr = '\0'; 8049 } 8050 } 8051 } 8052 8053 #if !defined(O_XATTR) 8054 int 8055 openat64(int fd, char *name, int oflag, mode_t cmode) 8056 { 8057 return (open64(name, oflag, cmode)); 8058 } 8059 8060 int 8061 openat(int fd, char *name, int oflag, mode_t cmode) 8062 { 8063 return (open(name, oflag, cmode)); 8064 } 8065 8066 int 8067 fchownat(int fd, char *name, uid_t owner, gid_t group, int flag) 8068 { 8069 if (flag == AT_SYMLINK_NOFOLLOW) 8070 return (lchown(name, owner, group)); 8071 else 8072 return (chown(name, owner, group)); 8073 } 8074 8075 int 8076 renameat(int fromfd, char *old, int tofd, char *new) 8077 { 8078 return (rename(old, new)); 8079 } 8080 8081 int 8082 futimesat(int fd, char *path, struct timeval times[2]) 8083 { 8084 return (utimes(path, times)); 8085 } 8086 8087 int 8088 unlinkat(int dirfd, char *path, int flag) 8089 { 8090 if (flag == AT_REMOVEDIR) { 8091 return (rmdir(path)); 8092 } else { 8093 return (unlink(path)); 8094 } 8095 } 8096 8097 int 8098 fstatat(int fd, char *path, struct stat *buf, int flag) 8099 { 8100 if (flag == AT_SYMLINK_NOFOLLOW) 8101 return (lstat(path, buf)); 8102 else 8103 return (stat(path, buf)); 8104 } 8105 8106 int 8107 attropen(char *file, char *attr, int omode, mode_t cmode) 8108 { 8109 errno = ENOTSUP; 8110 return (-1); 8111 } 8112 #endif 8113