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