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