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