1 /* Copyright (c) 1988 AT&T */ 2 /* All Rights Reserved */ 3 4 /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ 5 /* The copyright notice above does not evidence any */ 6 /* actual or intended publication of such source code. */ 7 8 #ident "@(#)cpio:cpio.c 1.30.1.11" 9 /* /sccs/src/cmd/s.cpio.c 10 cpio.c 1.30.1.11 1/11/86 13:46:48 11 Reworked cpio which uses getopt(3) to interpret flag arguments and 12 changes reels to the save file name. 13 Performance and size improvements. 14 */ 15 16 /* cpio COMPILE: cc -O cpio.c -s -i -o cpio -lgen -lerr 17 cpio -- copy file collections 18 19 */ 20 #include <errno.h> 21 #include <stdio.h> 22 #include <fcntl.h> 23 #include <memory.h> 24 #include <pwd.h> 25 #include <string.h> 26 #include <signal.h> 27 #include <varargs.h> 28 #include <sys/param.h> 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <paths.h> 32 33 struct utimbuf { 34 time_t actime; 35 time_t modtime; 36 }; 37 #ifndef S_IFIFO 38 #define S_IFIFO 010000 39 #endif 40 41 #define EQ(x,y) (strcmp(x,y)==0) 42 43 /* MKSHORT: for VAX, Interdata, ... */ 44 /* Take a 4-byte long, lv, and turn it */ 45 /* into an array of two 2-byte shorts, v*/ 46 #define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];} 47 48 #define MAGIC 070707 /* cpio magic number */ 49 #define BSMAGIC 0143561 /* byte-swapped cpio magic number */ 50 #define IN 'i' /* copy in */ 51 #define OUT 'o' /* copy out */ 52 #define PASS 'p' /* direct copy */ 53 #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */ 54 #define LINKS 500 /* no. of links allocated per bunch */ 55 #define CHARS 76 /* ASCII header size minus filename field */ 56 #define BUFSIZE 512 /* In u370, can't use BUFSIZ or BSIZE */ 57 #define CPIOBSZ 4096 /* file read/write */ 58 #define MK_USHORT(a) (a & 00000177777) /* Make unsigned shorts for portable */ 59 /* header. Hardware may only know */ 60 /* integer operations and sign extend */ 61 /* the large unsigned short resulting */ 62 /* in 8 rather than 6 octal char in */ 63 /* the header. */ 64 65 static struct stat Statb, Xstatb; 66 67 /* Cpio header format */ 68 static struct header { 69 short h_magic; 70 short h_dev; 71 ushort h_ino; 72 ushort h_mode, 73 h_uid, 74 h_gid; 75 short h_nlink; 76 short h_rdev; 77 short h_mtime[2], 78 h_namesize, 79 h_filesize[2]; 80 char h_name[256]; 81 } Hdr; 82 83 char Symlbuf[MAXPATHLEN + 1]; /* target of symbolic link */ 84 static unsigned Bufsize = BUFSIZE; /* default record size */ 85 static char Buf[CPIOBSZ], *Cbuf; 86 static char *Cp; 87 88 89 static 90 short Option, 91 Dir, 92 Uncond, 93 PassLink, 94 Rename, 95 Toc, 96 Verbose, 97 Mod_time, 98 Acc_time, 99 Cflag, 100 fflag, 101 Swap, 102 byteswap, 103 halfswap; 104 105 static 106 int Ifile, 107 Ofile, 108 Input = 0, 109 Output = 1; 110 /* sBlocks: short Blocks. Cumulative character */ 111 /* count for short reads in bread(). Encountered */ 112 /* with communication lines and pipes as in: */ 113 /* split -100 cpio_archive; cat xa* | cpio -icd */ 114 static 115 long sBlocks, 116 Blocks, 117 Longfile, 118 Longtime; 119 120 static 121 char Fullname[256], 122 Name[256]; 123 static 124 int Pathend; 125 static 126 char *swfile; 127 static 128 char *eommsg = "Change to part %d and press RETURN key. [q] "; 129 130 static 131 FILE *Rtty, 132 *Wtty; 133 static 134 char ttyname[] = _PATH_TTY; 135 136 static 137 char **Pattern = 0; 138 static 139 char Chdr[500]; 140 static 141 short Dev; 142 ushort Uid, 143 A_directory, 144 A_special, 145 A_symlink, 146 Filetype = S_IFMT; 147 148 extern errno; 149 extern void exit(); 150 char *malloc(); 151 FILE *popen(); 152 153 static char *smemcpy(); 154 155 static 156 union { 157 long l; 158 short s[2]; 159 char c[4]; 160 } U; 161 162 /* for VAX, Interdata, ... */ 163 static 164 long mklong(v) 165 short v[]; 166 { 167 U.l = 1; 168 if(U.c[0]) 169 U.s[0] = v[1], U.s[1] = v[0]; 170 else 171 U.s[0] = v[0], U.s[1] = v[1]; 172 return U.l; 173 } 174 175 static usage(), chkswfile(), getname(), bintochar(), chkhdr(), gethdr(); 176 static ckname(), openout(), breread(), bread(), bwrite(), eomchgreel(); 177 static postml(), pentry(), nmatch(), gmatch(), umatch(), set_time(); 178 static chgreel(), missdir(), pwd(), fperr(), fperrno(); 179 180 main(argc, argv) 181 int argc; 182 char **argv; 183 { 184 register ct; 185 long filesz; 186 int symlsz; 187 register char *fullp; 188 register i; 189 int ans; 190 register char *symlinkp; 191 short select; /* set when files are selected */ 192 extern char *optarg; 193 extern int optind; 194 195 signal(SIGSYS, SIG_IGN); 196 if(argc <= 1 || *argv[1] != '-') 197 usage(); 198 Uid = getuid(); 199 200 while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvM:6eI:O:")) != EOF ) { 201 202 switch( ans ) { 203 case 'a': /* reset access time */ 204 Acc_time++; 205 break; 206 case 'B': /* change record size to 5120 bytes */ 207 Bufsize = 5120; 208 break; 209 case 'C': /* reset buffer size to arbitrary valu 210 */ 211 Bufsize = atoi( optarg ); 212 if( Bufsize == 0 ) { 213 fperr("Illegal argument to -%c, '%s'", 214 ans, optarg ); 215 exit(2); 216 } 217 break; 218 case 'i': 219 Option = IN; 220 break; 221 case 'f': /* copy files not matched by patterns */ 222 fflag++; 223 break; 224 case 'o': 225 Option = OUT; 226 break; 227 case 'p': 228 Option = PASS; 229 break; 230 case 'c': /* ASCII header */ 231 Cflag++; 232 break; 233 case 'd': /* create directories when needed */ 234 Dir++; 235 break; 236 case 'l': /* link files, when necessary */ 237 PassLink++; 238 break; 239 case 'm': /* retain mod time */ 240 Mod_time++; 241 break; 242 case 'r': /* rename files interactively */ 243 Rename++; 244 Rtty = fopen(ttyname, "r"); 245 Wtty = fopen(ttyname, "w"); 246 if(Rtty==NULL || Wtty==NULL) { 247 fperrno("Cannot rename (%s missing)", 248 ttyname ); 249 exit(2); 250 } 251 break; 252 case 'S': /* swap halfwords */ 253 halfswap++; 254 Swap++; 255 break; 256 case 's': /* swap bytes */ 257 byteswap++; 258 Swap++; 259 break; 260 case 'b': /* swap both bytes and halfwords */ 261 halfswap++; 262 byteswap++; 263 Swap++; 264 break; 265 case 't': /* table of contents */ 266 Toc++; 267 break; 268 case 'u': /* copy unconditionally */ 269 Uncond++; 270 break; 271 case 'v': /* verbose - print out file names */ 272 Verbose++; 273 break; 274 case 'M': /* alternate message for end-of-media */ 275 eommsg = optarg; 276 break; 277 case '6': /* for old, sixth-edition files */ 278 Filetype = 060000; 279 break; 280 case 'I': 281 chkswfile( swfile, ans, Option ); 282 if( (i = open( optarg, O_RDONLY ) ) < 0) { 283 fperrno("Cannot open <%s> for input", optarg); 284 exit(2); 285 } 286 if( dup2(i, Input ) < 0 ) { 287 fperrno("Cannot dup to standard input"); 288 exit(2); 289 } 290 swfile = optarg; 291 break; 292 case 'O': 293 chkswfile( swfile, ans, Option ); 294 if( (i = open( optarg, O_WRONLY | O_CREAT | O_TRUNC, 295 0666 ) ) < 0) { 296 fperrno("Cannot open <%s> for output", optarg); 297 exit(2); 298 } 299 if( dup2(i, Output ) < 0 ) { 300 fperrno("Cannot dup to standard output"); 301 exit(2); 302 } 303 swfile = optarg; 304 break; 305 default: 306 usage(); 307 } 308 } 309 if(!Option) { 310 (void) fprintf(stderr, 311 "Options must include one of -o, -i, or -p\n"); 312 exit(2); 313 } 314 315 if(Option == PASS) { 316 if(Rename) { 317 (void) fprintf(stderr, 318 "Pass and Rename cannot be used together\n"); 319 exit(2); 320 } 321 if( Bufsize != BUFSIZE ) { 322 fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n"); 323 Bufsize = BUFSIZE; 324 } 325 326 }else { 327 Cp = Cbuf = (char *)malloc(Bufsize); 328 if(Cp == NULL) { 329 perror("cpio"); 330 exit(2); 331 } 332 } 333 argc -= optind; 334 argv += optind; 335 336 switch(Option) { 337 case OUT: 338 if(argc != 0) 339 usage(); 340 /* get filename, copy header and file out */ 341 while(getname()) { 342 if( mklong(Hdr.h_filesize) == 0L) { 343 if( Cflag ) 344 bwrite(Chdr,CHARS+Hdr.h_namesize); 345 else 346 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 347 if(Verbose) 348 (void) fprintf(stderr, "%s\n", 349 Hdr.h_name); 350 continue; 351 } else if( A_symlink ) { 352 symlsz = (int) mklong(Hdr.h_filesize); 353 if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 354 fperrno("Cannot read symbolic link <%s>", 355 Hdr.h_name); 356 continue; 357 } 358 Symlbuf[symlsz] = '\0'; 359 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 360 bwrite(Symlbuf, symlsz); 361 if(Verbose) 362 (void) fprintf(stderr, "%s\n", 363 Hdr.h_name); 364 continue; 365 } 366 if((Ifile = open(Hdr.h_name, 0)) < 0) { 367 fperrno("Cannot open <%s>", Hdr.h_name); 368 continue; 369 } 370 if ( Cflag ) 371 bwrite(Chdr,CHARS+Hdr.h_namesize); 372 else 373 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 374 for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 375 ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 376 if(read(Ifile, Buf, ct) < 0) { 377 fperrno("Cannot read %s", Hdr.h_name); 378 continue; 379 } 380 bwrite(Buf,ct); 381 } 382 close(Ifile); 383 if(Acc_time) { 384 struct utimbuf utb; 385 386 utb.actime = Statb.st_atime; 387 utb.modtime = Statb.st_mtime; 388 (void)utime(Hdr.h_name, &utb); 389 } 390 if(Verbose) 391 (void) fprintf(stderr, "%s\n", Hdr.h_name); 392 } 393 394 /* copy trailer, after all files have been copied */ 395 strcpy(Hdr.h_name, "TRAILER!!!"); 396 Hdr.h_magic = MAGIC; 397 MKSHORT(Hdr.h_filesize, 0L); 398 Hdr.h_namesize = strlen("TRAILER!!!") + 1; 399 if ( Cflag ) { 400 bintochar(0L); 401 bwrite(Chdr, CHARS+Hdr.h_namesize); 402 } 403 else 404 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 405 bwrite(Cbuf, Bufsize); 406 break; 407 408 case IN: 409 if(argc > 0 ) { /* save patterns, if any */ 410 Pattern = argv; 411 } 412 pwd(); 413 chkhdr(); 414 while(gethdr()) { 415 if (A_symlink) { 416 symlsz = (int) mklong(Hdr.h_filesize); 417 bread(Symlbuf, symlsz); 418 Symlbuf[symlsz] = '\0'; 419 if( ckname(Hdr.h_name) && !Toc) 420 (void)openout(Hdr.h_name, Symlbuf); 421 } else { 422 if( (select = ckname(Hdr.h_name)) && !Toc ) 423 Ofile = openout(Hdr.h_name, (char *)0); 424 else 425 Ofile = 0; 426 for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 427 ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 428 bread(Buf, ct); 429 if(Ofile) { 430 if(Swap) 431 swap(Buf,ct,byteswap,halfswap); 432 if(write(Ofile, Buf, ct) < 0) { 433 fperrno("Cannot write %s", Hdr.h_name); 434 continue; 435 } 436 } 437 } 438 if( Ofile ) { 439 (void) close(Ofile); 440 if(chmod(Hdr.h_name, Hdr.h_mode) < 0) 441 fperrno("Cannot change mode of <%s>", 442 Hdr.h_name); 443 set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 444 } 445 } 446 if(select) { 447 if(Verbose) 448 if(Toc) 449 pentry(Hdr.h_name); 450 else 451 puts(Hdr.h_name); 452 else if(Toc) 453 puts(Hdr.h_name); 454 } 455 } 456 break; 457 458 case PASS: /* move files around */ 459 if(argc != 1) 460 usage(); 461 if(access(argv[0], 2) == -1) { 462 (void) fperrno("Cannot write in <%s>", argv[0]); 463 exit(2); 464 } 465 strcpy(Fullname, argv[0]); /* destination directory */ 466 if(stat(Fullname, &Xstatb) < 0) { 467 fperrno("Cannot stat <%s>", Fullname); 468 exit(2); 469 } 470 if((Xstatb.st_mode&S_IFMT) != S_IFDIR) { 471 (void) fprintf(stderr, "<%s> is not a directory", 472 Fullname); 473 exit(2); 474 } 475 Dev = Xstatb.st_dev; 476 if( Fullname[ strlen(Fullname) - 1 ] != '/' ) 477 strcat(Fullname, "/"); 478 fullp = Fullname + strlen(Fullname); 479 480 while(getname()) { 481 if (A_directory && !Dir) 482 fperr("Use `-d' option to copy <%s>", 483 Hdr.h_name); 484 if(!ckname(Hdr.h_name)) 485 continue; 486 i = 0; 487 while(Hdr.h_name[i] == '/') 488 i++; 489 strcpy(fullp, &(Hdr.h_name[i])); 490 491 if( PassLink && !A_directory && Dev == Statb.st_dev ) { 492 if(link(Hdr.h_name, Fullname) < 0) { 493 switch(errno) { 494 case ENOENT: 495 if(missdir(Fullname) != 0) { 496 fperrno("Cannot create directory for <%s>", 497 Fullname); 498 continue; 499 } 500 break; 501 case EEXIST: 502 if(unlink(Fullname) < 0) { 503 fperrno("Cannot unlink <%s>", 504 Fullname); 505 continue; 506 } 507 break; 508 default: 509 fperrno("Cannot link <%s> to <%s>", 510 Hdr.h_name, Fullname); 511 continue; 512 } 513 if(link(Hdr.h_name, Fullname) < 0) { 514 fperrno("Cannot link <%s> to <%s>", 515 Hdr.h_name, Fullname); 516 continue; 517 } 518 } 519 520 goto ckverbose; 521 } 522 if( A_symlink ) { 523 symlsz = (int) mklong(Hdr.h_filesize); 524 if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 525 fperrno("Cannot read symbolic link <%s>", 526 Hdr.h_name); 527 continue; 528 } 529 Symlbuf[symlsz] = '\0'; 530 if(!openout(Fullname, Symlbuf)) 531 continue; 532 Blocks += ((symlsz + (BUFSIZE - 1)) / BUFSIZE); 533 if(Verbose) 534 puts(Fullname); 535 continue; 536 } 537 if(!(Ofile = openout(Fullname, (char *)0))) 538 continue; 539 if((Ifile = open(Hdr.h_name, 0)) < 0) { 540 fperrno("Cannot open <%s>", Hdr.h_name); 541 close(Ofile); 542 continue; 543 } 544 filesz = Statb.st_size; 545 for(; filesz > 0; filesz -= CPIOBSZ) { 546 ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 547 if(read(Ifile, Buf, ct) < 0) { 548 fperrno("Cannot read %s", Hdr.h_name); 549 break; 550 } 551 if(write(Ofile, Buf, ct) < 0) { 552 fperrno("Cannot write %s", Hdr.h_name); 553 break; 554 } 555 /* Removed u370 ifdef which caused cpio */ 556 /* to report blocks in terms of 4096 bytes. */ 557 558 Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE); 559 } 560 close(Ifile); 561 if(Acc_time) { 562 struct utimbuf utb; 563 564 utb.actime = Statb.st_atime; 565 utb.modtime = Statb.st_mtime; 566 (void)utime(Hdr.h_name, &utb); 567 } 568 if(Ofile) { 569 close(Ofile); 570 if(chmod(Fullname, Hdr.h_mode) < 0) 571 fperrno("Cannot change mode of <%s>", 572 Fullname); 573 set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime)); 574 ckverbose: 575 if(Verbose) 576 puts(Fullname); 577 } 578 } 579 } 580 /* print number of blocks actually copied */ 581 Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE); 582 (void) fprintf(stderr, "%ld blocks\n", Blocks * (Bufsize>>9)); 583 exit(0); 584 } 585 586 static 587 usage() 588 { 589 (void) fprintf(stderr, 590 "Usage: %s\n %s\n %s\n %s\n %s\n", 591 "cpio -o[acvB] <name-list >collection", 592 "cpio -o[acvB] -Ocollection <name-list", 593 "cpio -i[cdmrstuvfB6] [ pattern ... ] <collection", 594 "cpio -i[cdmrstuvfB6] -Icollection [ pattern ... ]", 595 "cpio -p[adlmruv] directory <name-list"); 596 } 597 598 static 599 chkswfile( sp, c, option ) 600 char *sp; 601 char c; 602 short option; 603 { 604 if( !option ) { 605 fperr( "-%c must be specified before -%c option", 606 c == 'I' ? 'i' : 'o', c ); 607 exit(2); 608 } 609 if( (c == 'I' && option != IN) || (c == 'O' && option != OUT) ) { 610 fperr( "-%c option not permitted with -%c option", c, 611 option ); 612 exit(2); 613 } 614 if( !sp ) 615 return; 616 fperr("No more than one -I or -O flag permitted"); 617 exit(2); 618 } 619 620 static 621 getname() /* get file name, get info for header */ 622 { 623 register char *namep = Name; 624 register ushort ftype; 625 struct stat Lstatb; 626 long tlong; 627 628 for(;;) { 629 if(gets(namep) == NULL) 630 return 0; 631 while(*namep == '.' && namep[1] == '/') { 632 namep++; 633 while(*namep == '/') namep++; 634 } 635 strcpy(Hdr.h_name, namep); 636 if(lstat(namep, &Statb) < 0) { 637 fperrno("Cannot stat <%s>", Hdr.h_name); 638 continue; 639 } 640 ftype = Statb.st_mode & Filetype; 641 A_directory = (ftype == S_IFDIR); 642 A_special = (ftype == S_IFBLK) 643 || (ftype == S_IFCHR) 644 || (ftype == S_IFIFO); 645 A_symlink = (ftype == S_IFLNK); 646 Hdr.h_magic = MAGIC; 647 Hdr.h_namesize = strlen(Hdr.h_name) + 1; 648 Hdr.h_uid = Statb.st_uid; 649 Hdr.h_gid = Statb.st_gid; 650 Hdr.h_dev = Statb.st_dev; 651 Hdr.h_ino = Statb.st_ino; 652 Hdr.h_mode = Statb.st_mode; 653 MKSHORT(Hdr.h_mtime, Statb.st_mtime); 654 Hdr.h_nlink = Statb.st_nlink; 655 tlong = ((Hdr.h_mode&S_IFMT) == S_IFREG || 656 (Hdr.h_mode&S_IFMT) == S_IFLNK)? Statb.st_size: 0L; 657 MKSHORT(Hdr.h_filesize, tlong); 658 Hdr.h_rdev = Statb.st_rdev; 659 if( Cflag ) 660 bintochar(tlong); 661 return 1; 662 } 663 } 664 665 static 666 bintochar(t) /* ASCII header write */ 667 long t; 668 { 669 sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s", 670 MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid, 671 Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev), 672 Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name); 673 } 674 675 static 676 chartobin() /* ASCII header read */ 677 { 678 sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo", 679 &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid, 680 &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime, 681 &Hdr.h_namesize, &Longfile); 682 MKSHORT(Hdr.h_filesize, Longfile); 683 MKSHORT(Hdr.h_mtime, Longtime); 684 } 685 686 687 /* Check the header for the magic number. Switch modes automatically to 688 match the type of header found. 689 */ 690 static 691 chkhdr() 692 { 693 bread(Chdr, CHARS); 694 chartobin(); 695 if( Hdr.h_magic == MAGIC ) 696 Cflag = 1; 697 else { 698 breread(&Hdr.h_magic, sizeof Hdr.h_magic); 699 if( Hdr.h_magic == MAGIC || Hdr.h_magic == (short)BSMAGIC ) 700 Cflag = 0; 701 else { 702 fperr("This is not a cpio file. Bad magic number."); 703 exit(2); 704 } 705 } 706 breread(Chdr, 0); 707 } 708 709 710 static 711 gethdr() /* get file headers */ 712 { 713 register ushort ftype; 714 715 if (Cflag) { 716 bread(Chdr, CHARS); 717 chartobin(); 718 } 719 else 720 bread(&Hdr, HDRSIZE); 721 722 if(Hdr.h_magic == (short)BSMAGIC) 723 swap((char *)&Hdr, HDRSIZE, 1, 0); 724 else if( Hdr.h_magic != MAGIC ) { 725 fperr("Out of phase--get help"); 726 exit(2); 727 } 728 bread(Hdr.h_name, Hdr.h_namesize); 729 if(EQ(Hdr.h_name, "TRAILER!!!")) 730 return 0; 731 ftype = Hdr.h_mode & Filetype; 732 A_directory = (ftype == S_IFDIR); 733 A_special = (ftype == S_IFBLK) 734 || (ftype == S_IFCHR) 735 || (ftype == S_IFIFO); 736 A_symlink = (ftype == S_IFLNK); 737 return 1; 738 } 739 740 static 741 ckname(namep) /* check filenames with patterns given on cmd line */ 742 register char *namep; 743 { 744 char buf[sizeof Hdr.h_name]; 745 746 if(fflag ^ !nmatch(namep, Pattern)) { 747 return 0; 748 } 749 if(Rename && !A_directory) { /* rename interactively */ 750 fprintf(Wtty, "Rename <%s>\n", namep); 751 fflush(Wtty); 752 fgets(buf, sizeof buf, Rtty); 753 if(feof(Rtty)) 754 exit(2); 755 buf[strlen(buf) - 1] = '\0'; 756 if(EQ(buf, "")) { 757 strcpy(namep,buf); 758 printf("Skipped\n"); 759 return 0; 760 } 761 else if(EQ(buf, ".")) 762 printf("Same name\n"); 763 else 764 strcpy(namep,buf); 765 } 766 return 1; 767 } 768 769 static 770 openout(namep, symlname) /* open files for writing, set all necessary info */ 771 register char *namep; 772 char *symlname; 773 { 774 register f; 775 register char *np; 776 int ans; 777 778 if(!strncmp(namep, "./", 2)) 779 namep += 2; 780 np = namep; 781 if(A_directory) { 782 if( !Dir || Rename || EQ(namep, ".") || EQ(namep, "..") ) 783 /* do not consider . or .. files */ 784 return 0; 785 if(stat(namep, &Xstatb) == -1) { 786 787 /* try creating (only twice) */ 788 ans = 0; 789 do { 790 if(mkdir(namep, Hdr.h_mode) != 0) { 791 ans += 1; 792 }else { 793 ans = 0; 794 break; 795 } 796 }while(ans < 2 && missdir(namep) == 0); 797 if(ans == 1) { 798 fperrno("Cannot create directory for <%s>", 799 namep); 800 return(0); 801 }else if(ans == 2) { 802 fperrno("Cannot create directory <%s>", namep); 803 return(0); 804 } 805 } 806 807 ret: 808 if(chmod(namep, Hdr.h_mode) < 0) 809 fperrno("Cannot change mode of <%s>", namep); 810 if(Uid == 0) 811 if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 812 fperrno("Cannot change ownership of <%s>", 813 namep); 814 set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 815 return 0; 816 } 817 if(Hdr.h_nlink > 1) 818 if(!postml(namep, np)) 819 return 0; 820 if(lstat(namep, &Xstatb) == 0) { 821 if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) { 822 if(unlink(namep) < 0) { 823 fperrno("cannot unlink current <%s>", namep); 824 } 825 } 826 if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) { 827 /* There's a newer or same aged version of file on destination */ 828 fperr("current <%s> newer or same age", np); 829 return 0; 830 } 831 } 832 if( Option == PASS 833 && Hdr.h_ino == Xstatb.st_ino 834 && Hdr.h_dev == Xstatb.st_dev) { 835 fperr("Attempt to pass file to self!"); 836 exit(2); 837 } 838 if(A_symlink) { 839 /* try symlinking (only twice) */ 840 ans = 0; 841 do { 842 if(symlink( 843 symlname, namep) < 0) { 844 ans += 1; 845 }else { 846 ans = 0; 847 break; 848 } 849 }while(ans < 2 && missdir(np) == 0); 850 if(ans == 1) { 851 fperrno("Cannot create directory for <%s>", namep); 852 return(0); 853 }else if(ans == 2) { 854 fperrno("Cannot symlink <%s> and <%s>", namep, symlname); 855 return(0); 856 } 857 858 return 0; 859 } 860 if(A_special) { 861 if((Hdr.h_mode & Filetype) == S_IFIFO) 862 Hdr.h_rdev = 0; 863 864 /* try creating (only twice) */ 865 ans = 0; 866 do { 867 if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) { 868 ans += 1; 869 }else { 870 ans = 0; 871 break; 872 } 873 }while(ans < 2 && missdir(np) == 0); 874 if(ans == 1) { 875 fperrno("Cannot create directory for <%s>", namep); 876 return(0); 877 }else if(ans == 2) { 878 fperrno("Cannot mknod <%s>", namep); 879 return(0); 880 } 881 882 goto ret; 883 } 884 885 /* try creating (only twice) */ 886 ans = 0; 887 do { 888 if((f = creat(namep, Hdr.h_mode)) < 0) { 889 ans += 1; 890 }else { 891 ans = 0; 892 break; 893 } 894 }while(ans < 2 && missdir(np) == 0); 895 if(ans == 1) { 896 fperrno("Cannot create directory for <%s>", namep); 897 return(0); 898 }else if(ans == 2) { 899 fperrno("Cannot create <%s>", namep); 900 return(0); 901 } 902 903 if(Uid == 0) 904 if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 905 fperrno("Cannot change ownership of <%s>", namep); 906 return f; 907 } 908 909 910 /* Shared by bread() and breread() 911 */ 912 static int nleft = 0; /* unread chars left in Cbuf */ 913 static char *ip; /* pointer to next char to be read from Cbuf */ 914 915 /* Reread the current buffer Cbuf. 916 A character count, c, of 0 simply resets the pointer so next bread gets 917 the same data again. 918 */ 919 static 920 breread(b, c) 921 char *b; 922 int c; 923 { 924 ip = Cbuf; 925 if( nleft ) 926 nleft = Bufsize; 927 if( !c ) 928 return; 929 bread(b, c); 930 } 931 932 static 933 bread(b, c) 934 register char *b; 935 register int c; 936 { 937 register int rv; 938 register char *p = ip; 939 940 if( !Cflag ) { 941 /* round c up to an even number */ 942 c = (c+1)/2; 943 c *= 2; 944 } 945 while( c ) { 946 if( nleft == 0 ) { 947 while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) { 948 Input = chgreel(0, Input, rv); 949 } 950 if( rv == Bufsize ) { 951 nleft = Bufsize; 952 p = Cbuf; 953 ++Blocks; 954 } 955 else if( rv == -1 ) { 956 fperrno("Read error on archive"); 957 exit(2); 958 } 959 else if( rv < Bufsize ) { /* short read */ 960 smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv ); 961 nleft = rv; 962 p = &Cbuf[ Bufsize - rv ]; 963 sBlocks += rv; 964 } 965 } 966 if( nleft <= c ) { 967 memcpy( b, p, nleft ); 968 c -= nleft; 969 b += nleft; 970 p += nleft; 971 nleft = 0; 972 } 973 else { 974 memcpy( b, p, c ); 975 nleft -= c; 976 b += c; 977 p += c; 978 c = 0; 979 } 980 } 981 ip = p; 982 } 983 984 985 static 986 bwrite(rp, c) 987 register char *rp; 988 register c; 989 { 990 register char *cp = Cp; 991 static unsigned Ccnt = 0; 992 register unsigned Cleft; 993 register int rv; 994 995 if( !Cflag ) { 996 /* round c up to an even number */ 997 c = (c+1)/2; 998 c *= 2; 999 } 1000 while( c ) { 1001 if( (Cleft = Bufsize - Ccnt) <= c ) { 1002 memcpy( cp, rp, Cleft ); 1003 rv = write(Output, Cbuf, Bufsize); 1004 if( rv == 0 || ( rv == -1 && errno == ENXIO ) ) { 1005 rv = eomchgreel(); 1006 } 1007 if( rv == Bufsize ) { 1008 Ccnt = 0; 1009 cp = Cbuf; 1010 } 1011 else if( rv == -1 ) { 1012 fperrno("Write error on archive"); 1013 exit(2); 1014 } 1015 else if( rv < Bufsize ) { 1016 Output = chgreel(1, Output, 0); 1017 smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv ); 1018 Ccnt = Bufsize - rv; 1019 cp = &Cbuf[ rv ]; 1020 } 1021 ++Blocks; 1022 rp += Cleft; 1023 c -= Cleft; 1024 } 1025 else { 1026 memcpy( cp, rp, c ); 1027 Ccnt += c; 1028 cp += c; 1029 rp += c; 1030 c = 0; 1031 } 1032 } 1033 Cp = cp; 1034 } 1035 1036 1037 static int reelcount = 1; /* used below and in chgreel() */ 1038 1039 /* Change reel due to reaching end-of-media. 1040 Keep trying to get a successful write before considering the 1041 change-of-reel as successful. 1042 */ 1043 static 1044 int 1045 eomchgreel() 1046 { 1047 int rv; 1048 1049 while( 1 ) { 1050 Output = chgreel(1, Output, 0); 1051 rv = write(Output, Cbuf, Bufsize); 1052 if( rv == Bufsize ) 1053 return rv; 1054 if( rv == -1 ) 1055 fperrno( "Unable to write this medium" ); 1056 else 1057 fperr( "Unable to write this medium: Premature EOF" ); 1058 (void) fprintf(stderr, "Try again.\n"); 1059 reelcount--; 1060 } 1061 /*NOTREACHED*/ 1062 } 1063 1064 1065 static 1066 postml(namep, np) /* linking funtion: Postml() is called after */ 1067 register char *namep, *np; /* namep is created. Postml() checks to see */ 1068 { /* if namep should be linked to np. If so, */ 1069 /* postml() removes the independent instance */ 1070 register i; /* of namep and links namep to np. */ 1071 static struct ml { 1072 short m_dev; 1073 ushort m_ino; 1074 char m_name[2]; 1075 } **ml = 0; 1076 register struct ml *mlp; 1077 static unsigned mlsize = 0; 1078 static unsigned mlinks = 0; 1079 char *lnamep; 1080 int ans; 1081 1082 if( !ml ) { 1083 mlsize = LINKS; 1084 ml = (struct ml **) malloc(mlsize * sizeof(struct ml)); 1085 } 1086 else if( mlinks == mlsize ) { 1087 mlsize += LINKS; 1088 ml = (struct ml **) realloc((char *) ml, 1089 mlsize * sizeof(struct ml)); 1090 } 1091 if (ml == NULL) { 1092 fperr("Out of memory for links"); 1093 exit(2); 1094 } 1095 for(i = 0; i < mlinks; ++i) { 1096 mlp = ml[i]; 1097 if(mlp->m_ino==Hdr.h_ino && mlp->m_dev==Hdr.h_dev) { 1098 if(Verbose) 1099 printf("%s linked to %s\n", ml[i]->m_name, 1100 np); 1101 unlink(namep); 1102 if(Option == IN && *(mlp->m_name) != '/') { 1103 Fullname[Pathend] = '\0'; 1104 strcat(Fullname, mlp->m_name); 1105 lnamep = Fullname; 1106 } 1107 lnamep = mlp->m_name; 1108 1109 /* try linking (only twice) */ 1110 ans = 0; 1111 do { 1112 if(link(lnamep, namep) < 0) { 1113 ans += 1; 1114 }else { 1115 ans = 0; 1116 break; 1117 } 1118 }while(ans < 2 && missdir(np) == 0); 1119 if(ans == 1) { 1120 fperrno("Cannot create directory for <%s>", np); 1121 return(0); 1122 }else if(ans == 2) { 1123 fperrno("Cannot link <%s> & <%s>", lnamep, np); 1124 return(0); 1125 } 1126 1127 set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 1128 return 0; 1129 } 1130 } 1131 if( !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) { 1132 static int first=1; 1133 1134 if(first) 1135 fperr("Out of memory for links"); 1136 first = 0; 1137 return 1; 1138 } 1139 ml[mlinks]->m_dev = Hdr.h_dev; 1140 ml[mlinks]->m_ino = Hdr.h_ino; 1141 strcpy(ml[mlinks]->m_name, np); 1142 ++mlinks; 1143 return 1; 1144 } 1145 1146 static 1147 pentry(namep) /* print verbose table of contents */ 1148 register char *namep; 1149 { 1150 static short lastid = -1; 1151 static struct passwd *pw; 1152 static char tbuf[32]; 1153 char *ctime(); 1154 1155 printf("%-7o", MK_USHORT(Hdr.h_mode)); 1156 if(lastid == Hdr.h_uid) 1157 printf("%-6s", pw->pw_name); 1158 else { 1159 setpwent(); 1160 if(pw = getpwuid((int)Hdr.h_uid)) { 1161 printf("%-6s", pw->pw_name); 1162 lastid = Hdr.h_uid; 1163 } else { 1164 printf("%-6d", Hdr.h_uid); 1165 lastid = -1; 1166 } 1167 } 1168 printf("%7ld ", mklong(Hdr.h_filesize)); 1169 U.l = mklong(Hdr.h_mtime); 1170 strcpy(tbuf, ctime((long *)&U.l)); 1171 tbuf[24] = '\0'; 1172 printf(" %s %s", &tbuf[4], namep); 1173 if (A_symlink) 1174 printf(" -> %s", Symlbuf); 1175 putchar('\n'); 1176 } 1177 1178 /* pattern matching functions */ 1179 static 1180 nmatch(s, pat) 1181 char *s, **pat; 1182 { 1183 if( !pat ) 1184 return 1; 1185 while(*pat) { 1186 if((**pat == '!' && !gmatch(s, *pat+1)) 1187 || gmatch(s, *pat)) 1188 return 1; 1189 ++pat; 1190 } 1191 return 0; 1192 } 1193 1194 1195 static 1196 gmatch(s, p) 1197 register char *s, *p; 1198 { 1199 register int c; 1200 register cc, ok, lc, scc; 1201 1202 scc = *s; 1203 lc = 077777; 1204 switch (c = *p) { 1205 1206 case '[': 1207 ok = 0; 1208 while (cc = *++p) { 1209 switch (cc) { 1210 1211 case ']': 1212 if (ok) 1213 return(gmatch(++s, ++p)); 1214 else 1215 return(0); 1216 1217 case '-': 1218 ok |= ((lc <= scc) && (scc <= (cc=p[1]))); 1219 } 1220 if (scc==(lc=cc)) ok++; 1221 } 1222 return(0); 1223 1224 case '?': 1225 caseq: 1226 if(scc) return(gmatch(++s, ++p)); 1227 return(0); 1228 case '*': 1229 return(umatch(s, ++p)); 1230 case 0: 1231 return(!scc); 1232 } 1233 if (c==scc) goto caseq; 1234 return(0); 1235 } 1236 1237 1238 1239 static 1240 umatch(s, p) 1241 register char *s, *p; 1242 { 1243 if(*p==0) return(1); 1244 while(*s) 1245 if (gmatch(s++,p)) return(1); 1246 return(0); 1247 } 1248 1249 swap(buf, bytecount, bytes, halfwords) /* swap halfwords, bytes or both */ 1250 char *buf; 1251 int bytecount; 1252 int bytes, halfwords; 1253 { 1254 register int count; 1255 int n, i; 1256 1257 if(bytes) { 1258 register union swpbytes { 1259 short shortw; 1260 char charv[2]; 1261 } *pbuf; 1262 register char c; 1263 1264 count = bytecount; 1265 pbuf = (union swpbytes *)buf; 1266 if (count % sizeof(union swpbytes)) 1267 pbuf->charv[count] = 0; 1268 count = (count + (sizeof(union swpbytes) - 1)) / sizeof(union swpbytes); 1269 while (count--) { 1270 c = pbuf->charv[0]; 1271 pbuf->charv[0] = pbuf->charv[1]; 1272 pbuf->charv[1] = c; 1273 ++pbuf; 1274 } 1275 } 1276 if (halfwords) { 1277 register union swphalf { 1278 long longw; 1279 short shortv[2]; 1280 char charv[4]; 1281 } *pbuf; 1282 register short cc; 1283 1284 count = bytecount; 1285 pbuf = (union swphalf *)buf; 1286 if (n = count % sizeof(union swphalf)) 1287 if(bytes && n % 2) 1288 for(i = count + 1; i <= count + (sizeof(union swphalf) - n); i++) 1289 pbuf->charv[i] = 0; 1290 else 1291 for (i = count; i < count + (sizeof(union swphalf) - n); i++) 1292 pbuf->charv[i] = 0; 1293 count = (count + (sizeof(union swphalf) - 1)) / sizeof(union swphalf); 1294 while (count--) { 1295 cc = pbuf->shortv[0]; 1296 pbuf->shortv[0] = pbuf->shortv[1]; 1297 pbuf->shortv[1] = cc; 1298 ++pbuf; 1299 } 1300 } 1301 } 1302 1303 1304 static 1305 set_time(namep, atime, mtime) /* set access and modification times */ 1306 register char *namep; 1307 time_t atime, mtime; 1308 { 1309 static struct utimbuf timevec; 1310 1311 if(!Mod_time) 1312 return; 1313 timevec.actime = atime; 1314 timevec.modtime = mtime; 1315 (void)utime(namep, &timevec); 1316 } 1317 1318 1319 1320 static 1321 chgreel(x, fl, rv) 1322 int x, fl, rv; 1323 { 1324 register f; 1325 char str[BUFSIZ]; 1326 struct stat statb; 1327 1328 fstat(fl, &statb); 1329 if((statb.st_mode&S_IFMT) != S_IFCHR) { 1330 fperrno("Can't %s: ", x? "write output": "read input"); 1331 exit(2); 1332 } 1333 if( rv == 0 || 1334 ( rv == -1 && ( errno == ENOSPC || errno == ENXIO ) ) ) 1335 fperr( "\007Reached end of medium on %s", 1336 x? "output":"input" ); 1337 else { 1338 fperrno( "\007Encountered an error on %s", 1339 x? "output":"input" ); 1340 exit(2); 1341 } 1342 if( Rtty == NULL ) { 1343 Rtty = fopen(ttyname, "r"); 1344 if( Rtty == NULL ) { 1345 fperrno("Cannot prompt (can't open %s)", ttyname); 1346 exit(2); 1347 } 1348 } 1349 close(fl); 1350 reelcount++; 1351 again: 1352 if( swfile ) { 1353 askagain: 1354 fperr( eommsg, reelcount ); 1355 fgets(str, sizeof str, Rtty); 1356 switch( *str ) { 1357 case '\n': 1358 strcpy( str, swfile ); 1359 break; 1360 case 'q': 1361 exit(2); 1362 default: 1363 goto askagain; 1364 } 1365 } 1366 else { 1367 fperr("If you want to go on, type device/file name when ready."); 1368 fgets(str, sizeof str, Rtty); 1369 str[strlen(str) - 1] = '\0'; 1370 if(!*str) 1371 exit(2); 1372 } 1373 if((f = open(str, x? 1: 0)) < 0) { 1374 fperrno("Can't open <%s>", str); 1375 goto again; 1376 } 1377 return f; 1378 } 1379 1380 1381 1382 static 1383 missdir(namep) 1384 register char *namep; 1385 { 1386 register char *np; 1387 register ct = 2; 1388 1389 for(np = namep; *np; ++np) 1390 if(*np == '/') { 1391 if(np == namep) continue; /* skip over 'root slash' */ 1392 *np = '\0'; 1393 if(stat(namep, &Xstatb) == -1) { 1394 if(Dir) { 1395 if((ct = mkdir(namep, 0777)) != 0) { 1396 *np = '/'; 1397 return(ct); 1398 } 1399 }else { 1400 fperr("missing 'd' option"); 1401 return(-1); 1402 } 1403 } 1404 *np = '/'; 1405 } 1406 if (ct == 2) ct = 0; /* the file already exists */ 1407 return ct; 1408 } 1409 1410 1411 1412 static 1413 pwd() /* get working directory */ 1414 { 1415 if (getwd(Fullname) == 0) { 1416 (void)fprintf(stderr, "cpio: %s\n", 1417 Fullname); 1418 exit(2); 1419 } 1420 Pathend = strlen(Fullname); 1421 Fullname[Pathend++] = '/'; 1422 Fullname[Pathend] = '\0'; 1423 } 1424 1425 1426 /* 1427 print message on the stderr 1428 */ 1429 static 1430 fperr( va_alist ) 1431 va_dcl 1432 { 1433 va_list args; 1434 char *fmt; 1435 1436 va_start( args ); 1437 fprintf( stderr, "cpio: "); 1438 fmt = va_arg( args, char * ); 1439 vfprintf( stderr, fmt, args ); 1440 putc( '\n', stderr); 1441 fflush( stderr ); 1442 } 1443 1444 /* 1445 print message on the stderr followed by error number and meaning. 1446 */ 1447 static 1448 fperrno( va_alist ) 1449 va_dcl 1450 { 1451 va_list args; 1452 char *fmt; 1453 1454 va_start( args ); 1455 fprintf( stderr, "cpio: "); 1456 fmt = va_arg( args, char * ); 1457 vfprintf( stderr, fmt, args ); 1458 fprintf( stderr, ": " ); 1459 fflush( stderr ); 1460 perror(""); 1461 } 1462 1463 1464 /* Safe memory copy. 1465 Fast if the to and from strings do not overlap, 1466 slower but safe if they do. 1467 */ 1468 1469 static char * 1470 smemcpy( to, from, count ) 1471 register char *to, *from; 1472 register unsigned count; 1473 { 1474 char *savedto; 1475 1476 if( &to[ count ] <= from || &from[ count ] <= to ) 1477 return memcpy( to, from, count ); 1478 1479 if( to == from ) 1480 return to; 1481 1482 savedto = to; 1483 if( to < from ) 1484 while( count-- ) 1485 *(to++) = *(from++); 1486 else { 1487 to += count; 1488 from += count; 1489 while( count-- ) 1490 *(--to) = *(--from); 1491 } 1492 1493 return savedto; 1494 } 1495