|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.