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