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