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