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