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