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