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