133828Sbostic /* Copyright (c) 1988 AT&T */ 233828Sbostic /* All Rights Reserved */ 333828Sbostic 433828Sbostic /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */ 533828Sbostic /* The copyright notice above does not evidence any */ 633828Sbostic /* actual or intended publication of such source code. */ 733828Sbostic 833828Sbostic #ident "@(#)cpio:cpio.c 1.30.1.11" 933828Sbostic /* /sccs/src/cmd/s.cpio.c 1033828Sbostic cpio.c 1.30.1.11 1/11/86 13:46:48 1133828Sbostic Reworked cpio which uses getopt(3) to interpret flag arguments and 1233828Sbostic changes reels to the save file name. 1333828Sbostic Performance and size improvements. 1433828Sbostic */ 1533828Sbostic 1633828Sbostic /* cpio COMPILE: cc -O cpio.c -s -i -o cpio -lgen -lerr 1733828Sbostic cpio -- copy file collections 1833828Sbostic 1933828Sbostic */ 2033828Sbostic #include <errno.h> 2133828Sbostic #include <fcntl.h> 2233828Sbostic #include <memory.h> 2333828Sbostic #include <stdio.h> 2433828Sbostic #include <string.h> 2533828Sbostic #include <signal.h> 2633828Sbostic #include <varargs.h> 27*33829Sbostic #include <sys/param.h> 28*33829Sbostic #include <sys/types.h> 2933828Sbostic #include <sys/stat.h> 3033828Sbostic 31*33829Sbostic struct utimbuf { 32*33829Sbostic time_t actime; 33*33829Sbostic time_t modtime; 34*33829Sbostic }; 35*33829Sbostic #ifndef S_IFIFO 36*33829Sbostic #define S_IFIFO 010000 37*33829Sbostic #endif 38*33829Sbostic 3933828Sbostic #define EQ(x,y) (strcmp(x,y)==0) 4033828Sbostic 4133828Sbostic /* MKSHORT: for VAX, Interdata, ... */ 4233828Sbostic /* Take a 4-byte long, lv, and turn it */ 4333828Sbostic /* into an array of two 2-byte shorts, v*/ 4433828Sbostic #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];} 4533828Sbostic 4633828Sbostic #define MAGIC 070707 /* cpio magic number */ 47*33829Sbostic #define BSMAGIC 0143561 /* byte-swapped cpio magic number */ 4833828Sbostic #define IN 'i' /* copy in */ 4933828Sbostic #define OUT 'o' /* copy out */ 5033828Sbostic #define PASS 'p' /* direct copy */ 5133828Sbostic #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */ 5233828Sbostic #define LINKS 500 /* no. of links allocated per bunch */ 5333828Sbostic #define CHARS 76 /* ASCII header size minus filename field */ 5433828Sbostic #define BUFSIZE 512 /* In u370, can't use BUFSIZ or BSIZE */ 5533828Sbostic #define CPIOBSZ 4096 /* file read/write */ 5633828Sbostic #define MK_USHORT(a) (a & 00000177777) /* Make unsigned shorts for portable */ 5733828Sbostic /* header. Hardware may only know */ 5833828Sbostic /* integer operations and sign extend */ 5933828Sbostic /* the large unsigned short resulting */ 6033828Sbostic /* in 8 rather than 6 octal char in */ 6133828Sbostic /* the header. */ 6233828Sbostic 6333828Sbostic static struct stat Statb, Xstatb; 6433828Sbostic 6533828Sbostic /* Cpio header format */ 6633828Sbostic static struct header { 6733828Sbostic short h_magic; 6833828Sbostic short h_dev; 6933828Sbostic ushort h_ino; 7033828Sbostic ushort h_mode, 7133828Sbostic h_uid, 7233828Sbostic h_gid; 7333828Sbostic short h_nlink; 7433828Sbostic short h_rdev; 7533828Sbostic short h_mtime[2], 7633828Sbostic h_namesize, 7733828Sbostic h_filesize[2]; 7833828Sbostic char h_name[256]; 7933828Sbostic } Hdr; 8033828Sbostic 81*33829Sbostic char Symlbuf[MAXPATHLEN + 1]; /* target of symbolic link */ 8233828Sbostic static unsigned Bufsize = BUFSIZE; /* default record size */ 8333828Sbostic static char Buf[CPIOBSZ], *Cbuf; 8433828Sbostic static char *Cp; 8533828Sbostic 8633828Sbostic 8733828Sbostic static 8833828Sbostic short Option, 8933828Sbostic Dir, 9033828Sbostic Uncond, 9133828Sbostic PassLink, 9233828Sbostic Rename, 9333828Sbostic Toc, 9433828Sbostic Verbose, 9533828Sbostic Mod_time, 9633828Sbostic Acc_time, 9733828Sbostic Cflag, 9833828Sbostic fflag, 9933828Sbostic Swap, 10033828Sbostic byteswap, 10133828Sbostic halfswap; 10233828Sbostic 10333828Sbostic static 10433828Sbostic int Ifile, 10533828Sbostic Ofile, 10633828Sbostic Input = 0, 10733828Sbostic Output = 1; 10833828Sbostic /* sBlocks: short Blocks. Cumulative character */ 10933828Sbostic /* count for short reads in bread(). Encountered */ 11033828Sbostic /* with communication lines and pipes as in: */ 11133828Sbostic /* split -100 cpio_archive; cat xa* | cpio -icd */ 11233828Sbostic static 11333828Sbostic long sBlocks, 11433828Sbostic Blocks, 11533828Sbostic Longfile, 11633828Sbostic Longtime; 11733828Sbostic 11833828Sbostic static 11933828Sbostic char Fullname[256], 12033828Sbostic Name[256]; 12133828Sbostic static 12233828Sbostic int Pathend; 12333828Sbostic static 12433828Sbostic char *swfile; 12533828Sbostic static 12633828Sbostic char *eommsg = "Change to part %d and press RETURN key. [q] "; 12733828Sbostic 12833828Sbostic static 12933828Sbostic FILE *Rtty, 13033828Sbostic *Wtty; 13133828Sbostic static 13233828Sbostic char ttyname[] = "/dev/tty"; 13333828Sbostic 13433828Sbostic static 13533828Sbostic char **Pattern = 0; 13633828Sbostic static 13733828Sbostic char Chdr[500]; 13833828Sbostic static 13933828Sbostic short Dev; 14033828Sbostic ushort Uid, 14133828Sbostic A_directory, 14233828Sbostic A_special, 143*33829Sbostic A_symlink, 14433828Sbostic Filetype = S_IFMT; 14533828Sbostic 14633828Sbostic extern errno; 14733828Sbostic extern void exit(); 14833828Sbostic char *malloc(); 14933828Sbostic FILE *popen(); 15033828Sbostic 151*33829Sbostic static char *smemcpy(); 152*33829Sbostic 15333828Sbostic static 15433828Sbostic union { 15533828Sbostic long l; 15633828Sbostic short s[2]; 15733828Sbostic char c[4]; 15833828Sbostic } U; 15933828Sbostic 16033828Sbostic /* for VAX, Interdata, ... */ 16133828Sbostic static 16233828Sbostic long mklong(v) 16333828Sbostic short v[]; 16433828Sbostic { 16533828Sbostic U.l = 1; 16633828Sbostic if(U.c[0]) 16733828Sbostic U.s[0] = v[1], U.s[1] = v[0]; 16833828Sbostic else 16933828Sbostic U.s[0] = v[0], U.s[1] = v[1]; 17033828Sbostic return U.l; 17133828Sbostic } 17233828Sbostic 17333828Sbostic main(argc, argv) 17433828Sbostic char **argv; 17533828Sbostic { 17633828Sbostic register ct; 17733828Sbostic long filesz; 178*33829Sbostic int symlsz; 17933828Sbostic register char *fullp; 18033828Sbostic register i; 18133828Sbostic int ans; 182*33829Sbostic register char *symlinkp; 18333828Sbostic short select; /* set when files are selected */ 18433828Sbostic extern char *optarg; 18533828Sbostic extern int optind; 18633828Sbostic 187*33829Sbostic signal(SIGSYS, SIG_IGN); 188*33829Sbostic if(argc <= 1 || *argv[1] != '-') 18933828Sbostic usage(); 19033828Sbostic Uid = getuid(); 19133828Sbostic 192*33829Sbostic while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvM:6eI:O:")) != EOF ) { 19333828Sbostic 19433828Sbostic switch( ans ) { 19533828Sbostic case 'a': /* reset access time */ 19633828Sbostic Acc_time++; 19733828Sbostic break; 19833828Sbostic case 'B': /* change record size to 5120 bytes */ 19933828Sbostic Bufsize = 5120; 20033828Sbostic break; 20133828Sbostic case 'C': /* reset buffer size to arbitrary valu 20233828Sbostic */ 20333828Sbostic Bufsize = atoi( optarg ); 204*33829Sbostic if( Bufsize == 0 ) { 205*33829Sbostic fperr("Illegal argument to -%c, '%s'", 20633828Sbostic ans, optarg ); 207*33829Sbostic exit(2); 208*33829Sbostic } 20933828Sbostic break; 21033828Sbostic case 'i': 21133828Sbostic Option = IN; 21233828Sbostic break; 21333828Sbostic case 'f': /* copy files not matched by patterns */ 21433828Sbostic fflag++; 21533828Sbostic break; 21633828Sbostic case 'o': 21733828Sbostic Option = OUT; 21833828Sbostic break; 21933828Sbostic case 'p': 22033828Sbostic Option = PASS; 22133828Sbostic break; 22233828Sbostic case 'c': /* ASCII header */ 22333828Sbostic Cflag++; 22433828Sbostic break; 22533828Sbostic case 'd': /* create directories when needed */ 22633828Sbostic Dir++; 22733828Sbostic break; 22833828Sbostic case 'l': /* link files, when necessary */ 22933828Sbostic PassLink++; 23033828Sbostic break; 23133828Sbostic case 'm': /* retain mod time */ 23233828Sbostic Mod_time++; 23333828Sbostic break; 23433828Sbostic case 'r': /* rename files interactively */ 23533828Sbostic Rename++; 23633828Sbostic Rtty = fopen(ttyname, "r"); 23733828Sbostic Wtty = fopen(ttyname, "w"); 23833828Sbostic if(Rtty==NULL || Wtty==NULL) { 239*33829Sbostic fperrno("Cannot rename (%s missing)", 24033828Sbostic ttyname ); 241*33829Sbostic exit(2); 24233828Sbostic } 24333828Sbostic break; 24433828Sbostic case 'S': /* swap halfwords */ 24533828Sbostic halfswap++; 24633828Sbostic Swap++; 24733828Sbostic break; 24833828Sbostic case 's': /* swap bytes */ 24933828Sbostic byteswap++; 25033828Sbostic Swap++; 25133828Sbostic break; 25233828Sbostic case 'b': /* swap both bytes and halfwords */ 253*33829Sbostic halfswap++; 254*33829Sbostic byteswap++; 25533828Sbostic Swap++; 25633828Sbostic break; 25733828Sbostic case 't': /* table of contents */ 25833828Sbostic Toc++; 25933828Sbostic break; 26033828Sbostic case 'u': /* copy unconditionally */ 26133828Sbostic Uncond++; 26233828Sbostic break; 26333828Sbostic case 'v': /* verbose - print out file names */ 264*33829Sbostic Verbose++; 26533828Sbostic break; 26633828Sbostic case 'M': /* alternate message for end-of-media */ 26733828Sbostic eommsg = optarg; 26833828Sbostic break; 26933828Sbostic case '6': /* for old, sixth-edition files */ 27033828Sbostic Filetype = 060000; 27133828Sbostic break; 27233828Sbostic case 'I': 27333828Sbostic chkswfile( swfile, ans, Option ); 274*33829Sbostic if( (i = open( optarg, O_RDONLY ) ) < 0) { 275*33829Sbostic fperrno("Cannot open <%s> for input", optarg); 276*33829Sbostic exit(2); 277*33829Sbostic } 278*33829Sbostic if( dup2(i, Input ) < 0 ) { 279*33829Sbostic fperrno("Cannot dup to standard input"); 280*33829Sbostic exit(2); 281*33829Sbostic } 28233828Sbostic swfile = optarg; 28333828Sbostic break; 28433828Sbostic case 'O': 28533828Sbostic chkswfile( swfile, ans, Option ); 286*33829Sbostic if( (i = open( optarg, O_WRONLY | O_CREAT | O_TRUNC, 287*33829Sbostic 0666 ) ) < 0) { 288*33829Sbostic fperrno("Cannot open <%s> for output", optarg); 289*33829Sbostic exit(2); 290*33829Sbostic } 291*33829Sbostic if( dup2(i, Output ) < 0 ) { 292*33829Sbostic fperrno("Cannot dup to standard output"); 293*33829Sbostic exit(2); 294*33829Sbostic } 29533828Sbostic swfile = optarg; 29633828Sbostic break; 29733828Sbostic default: 29833828Sbostic usage(); 29933828Sbostic } 30033828Sbostic } 30133828Sbostic if(!Option) { 302*33829Sbostic (void) fprintf(stderr, 303*33829Sbostic "Options must include one of -o, -i, or -p\n"); 304*33829Sbostic exit(2); 30533828Sbostic } 30633828Sbostic 30733828Sbostic if(Option == PASS) { 30833828Sbostic if(Rename) { 309*33829Sbostic (void) fprintf(stderr, 310*33829Sbostic "Pass and Rename cannot be used together\n"); 311*33829Sbostic exit(2); 31233828Sbostic } 31333828Sbostic if( Bufsize != BUFSIZE ) { 31433828Sbostic fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n"); 31533828Sbostic Bufsize = BUFSIZE; 31633828Sbostic } 31733828Sbostic 31833828Sbostic }else { 319*33829Sbostic Cp = Cbuf = (char *)malloc(Bufsize); 320*33829Sbostic if(Cp == NULL) { 321*33829Sbostic perror("cpio"); 322*33829Sbostic exit(2); 323*33829Sbostic } 32433828Sbostic } 32533828Sbostic argc -= optind; 32633828Sbostic argv += optind; 32733828Sbostic 32833828Sbostic switch(Option) { 32933828Sbostic case OUT: 33033828Sbostic if(argc != 0) 33133828Sbostic usage(); 33233828Sbostic /* get filename, copy header and file out */ 33333828Sbostic while(getname()) { 33433828Sbostic if( mklong(Hdr.h_filesize) == 0L) { 33533828Sbostic if( Cflag ) 33633828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 33733828Sbostic else 33833828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 33933828Sbostic if(Verbose) 340*33829Sbostic (void) fprintf(stderr, "%s\n", 341*33829Sbostic Hdr.h_name); 34233828Sbostic continue; 343*33829Sbostic } else if( A_symlink ) { 344*33829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 345*33829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 346*33829Sbostic fperrno("Cannot read symbolic link <%s>", 347*33829Sbostic Hdr.h_name); 348*33829Sbostic continue; 349*33829Sbostic } 350*33829Sbostic Symlbuf[symlsz] = '\0'; 351*33829Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 352*33829Sbostic bwrite(Symlbuf, symlsz); 353*33829Sbostic if(Verbose) 354*33829Sbostic (void) fprintf(stderr, "%s\n", 355*33829Sbostic Hdr.h_name); 356*33829Sbostic continue; 35733828Sbostic } 35833828Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) { 359*33829Sbostic fperrno("Cannot open <%s>", Hdr.h_name); 36033828Sbostic continue; 36133828Sbostic } 36233828Sbostic if ( Cflag ) 36333828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 36433828Sbostic else 36533828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 36633828Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 36733828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 36833828Sbostic if(read(Ifile, Buf, ct) < 0) { 369*33829Sbostic fperrno("Cannot read %s", Hdr.h_name); 37033828Sbostic continue; 37133828Sbostic } 37233828Sbostic bwrite(Buf,ct); 37333828Sbostic } 37433828Sbostic close(Ifile); 375*33829Sbostic if(Acc_time) { 376*33829Sbostic struct utimbuf utb; 377*33829Sbostic 378*33829Sbostic utb.actime = Statb.st_atime; 379*33829Sbostic utb.modtime = Statb.st_mtime; 380*33829Sbostic (void)utime(Hdr.h_name, &utb); 381*33829Sbostic } 38233828Sbostic if(Verbose) 383*33829Sbostic (void) fprintf(stderr, "%s\n", Hdr.h_name); 38433828Sbostic } 38533828Sbostic 38633828Sbostic /* copy trailer, after all files have been copied */ 38733828Sbostic strcpy(Hdr.h_name, "TRAILER!!!"); 38833828Sbostic Hdr.h_magic = MAGIC; 38933828Sbostic MKSHORT(Hdr.h_filesize, 0L); 39033828Sbostic Hdr.h_namesize = strlen("TRAILER!!!") + 1; 39133828Sbostic if ( Cflag ) { 39233828Sbostic bintochar(0L); 39333828Sbostic bwrite(Chdr, CHARS+Hdr.h_namesize); 39433828Sbostic } 39533828Sbostic else 39633828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 39733828Sbostic bwrite(Cbuf, Bufsize); 39833828Sbostic break; 39933828Sbostic 40033828Sbostic case IN: 40133828Sbostic if(argc > 0 ) { /* save patterns, if any */ 40233828Sbostic Pattern = argv; 40333828Sbostic } 40433828Sbostic pwd(); 40533828Sbostic chkhdr(); 40633828Sbostic while(gethdr()) { 407*33829Sbostic if (A_symlink) { 408*33829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 409*33829Sbostic bread(Symlbuf, symlsz); 410*33829Sbostic Symlbuf[symlsz] = '\0'; 411*33829Sbostic if((void) ckname(Hdr.h_name) && !Toc) 412*33829Sbostic (void)openout(Hdr.h_name, Symlbuf); 413*33829Sbostic } else { 414*33829Sbostic if( (select = ckname(Hdr.h_name)) && !Toc ) 415*33829Sbostic Ofile = openout(Hdr.h_name, (char *)0); 416*33829Sbostic else 417*33829Sbostic Ofile = 0; 418*33829Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 419*33829Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 420*33829Sbostic bread(Buf, ct); 421*33829Sbostic if(Ofile) { 422*33829Sbostic if(Swap) 423*33829Sbostic swap(Buf,ct,byteswap,halfswap); 424*33829Sbostic if(write(Ofile, Buf, ct) < 0) { 425*33829Sbostic fperrno("Cannot write %s", Hdr.h_name); 426*33829Sbostic continue; 427*33829Sbostic } 42833828Sbostic } 42933828Sbostic } 430*33829Sbostic if( Ofile ) { 431*33829Sbostic (void) close(Ofile); 432*33829Sbostic if(chmod(Hdr.h_name, Hdr.h_mode) < 0) 433*33829Sbostic fperrno("Cannot change mode of <%s>", 434*33829Sbostic Hdr.h_name); 435*33829Sbostic set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 436*33829Sbostic } 43733828Sbostic } 43833828Sbostic if(select) { 43933828Sbostic if(Verbose) 44033828Sbostic if(Toc) 44133828Sbostic pentry(Hdr.h_name); 44233828Sbostic else 443*33829Sbostic puts(Hdr.h_name); 44433828Sbostic else if(Toc) 44533828Sbostic puts(Hdr.h_name); 44633828Sbostic } 44733828Sbostic } 44833828Sbostic break; 44933828Sbostic 45033828Sbostic case PASS: /* move files around */ 45133828Sbostic if(argc != 1) 45233828Sbostic usage(); 45333828Sbostic if(access(argv[0], 2) == -1) { 454*33829Sbostic (void) fperrno("Cannot write in <%s>", argv[0]); 455*33829Sbostic exit(2); 45633828Sbostic } 45733828Sbostic strcpy(Fullname, argv[0]); /* destination directory */ 458*33829Sbostic if(stat(Fullname, &Xstatb) < 0) { 459*33829Sbostic fperrno("Cannot stat <%s>", Fullname); 460*33829Sbostic exit(2); 461*33829Sbostic } 462*33829Sbostic if((Xstatb.st_mode&S_IFMT) != S_IFDIR) { 463*33829Sbostic (void) fprintf(stderr, "<%s> is not a directory", 464*33829Sbostic Fullname); 465*33829Sbostic exit(2); 466*33829Sbostic } 46733828Sbostic Dev = Xstatb.st_dev; 46833828Sbostic if( Fullname[ strlen(Fullname) - 1 ] != '/' ) 46933828Sbostic strcat(Fullname, "/"); 47033828Sbostic fullp = Fullname + strlen(Fullname); 47133828Sbostic 47233828Sbostic while(getname()) { 47333828Sbostic if (A_directory && !Dir) 474*33829Sbostic fperr("Use `-d' option to copy <%s>", 47533828Sbostic Hdr.h_name); 47633828Sbostic if(!ckname(Hdr.h_name)) 47733828Sbostic continue; 47833828Sbostic i = 0; 47933828Sbostic while(Hdr.h_name[i] == '/') 48033828Sbostic i++; 48133828Sbostic strcpy(fullp, &(Hdr.h_name[i])); 48233828Sbostic 48333828Sbostic if( PassLink && !A_directory && Dev == Statb.st_dev ) { 48433828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 48533828Sbostic switch(errno) { 48633828Sbostic case ENOENT: 48733828Sbostic if(missdir(Fullname) != 0) { 488*33829Sbostic fperrno("Cannot create directory for <%s>", 489*33829Sbostic Fullname); 49033828Sbostic continue; 49133828Sbostic } 49233828Sbostic break; 49333828Sbostic case EEXIST: 49433828Sbostic if(unlink(Fullname) < 0) { 495*33829Sbostic fperrno("Cannot unlink <%s>", 496*33829Sbostic Fullname); 49733828Sbostic continue; 49833828Sbostic } 49933828Sbostic break; 50033828Sbostic default: 501*33829Sbostic fperrno("Cannot link <%s> to <%s>", 502*33829Sbostic Hdr.h_name, Fullname); 50333828Sbostic continue; 50433828Sbostic } 50533828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 506*33829Sbostic fperrno("Cannot link <%s> to <%s>", 507*33829Sbostic Hdr.h_name, Fullname); 50833828Sbostic continue; 50933828Sbostic } 51033828Sbostic } 51133828Sbostic 51233828Sbostic goto ckverbose; 51333828Sbostic } 514*33829Sbostic if( A_symlink ) { 515*33829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 516*33829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 517*33829Sbostic fperrno("Cannot read symbolic link <%s>", 518*33829Sbostic Hdr.h_name); 51933828Sbostic continue; 520*33829Sbostic } 521*33829Sbostic Symlbuf[symlsz] = '\0'; 522*33829Sbostic if(!openout(Fullname, Symlbuf)) 523*33829Sbostic continue; 524*33829Sbostic Blocks += ((symlsz + (BUFSIZE - 1)) / BUFSIZE); 525*33829Sbostic if(Verbose) 526*33829Sbostic puts(Fullname); 527*33829Sbostic continue; 528*33829Sbostic } 529*33829Sbostic if(!(Ofile = openout(Fullname, (char *)0))) 530*33829Sbostic continue; 531*33829Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) { 532*33829Sbostic fperrno("Cannot open <%s>", Hdr.h_name); 53333828Sbostic close(Ofile); 53433828Sbostic continue; 53533828Sbostic } 53633828Sbostic filesz = Statb.st_size; 53733828Sbostic for(; filesz > 0; filesz -= CPIOBSZ) { 53833828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 53933828Sbostic if(read(Ifile, Buf, ct) < 0) { 540*33829Sbostic fperrno("Cannot read %s", Hdr.h_name); 54133828Sbostic break; 54233828Sbostic } 543*33829Sbostic if(write(Ofile, Buf, ct) < 0) { 544*33829Sbostic fperrno("Cannot write %s", Hdr.h_name); 545*33829Sbostic break; 546*33829Sbostic } 547*33829Sbostic /* Removed u370 ifdef which caused cpio */ 548*33829Sbostic /* to report blocks in terms of 4096 bytes. */ 54933828Sbostic 55033828Sbostic Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE); 55133828Sbostic } 55233828Sbostic close(Ifile); 553*33829Sbostic if(Acc_time) { 554*33829Sbostic struct utimbuf utb; 555*33829Sbostic 556*33829Sbostic utb.actime = Statb.st_atime; 557*33829Sbostic utb.modtime = Statb.st_mtime; 558*33829Sbostic (void)utime(Hdr.h_name, &utb); 559*33829Sbostic } 56033828Sbostic if(Ofile) { 56133828Sbostic close(Ofile); 562*33829Sbostic if(chmod(Fullname, Hdr.h_mode) < 0) 563*33829Sbostic fperrno("Cannot change mode of <%s>", 564*33829Sbostic Fullname); 56533828Sbostic set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime)); 56633828Sbostic ckverbose: 56733828Sbostic if(Verbose) 568*33829Sbostic puts(Fullname); 56933828Sbostic } 57033828Sbostic } 57133828Sbostic } 57233828Sbostic /* print number of blocks actually copied */ 57333828Sbostic Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE); 574*33829Sbostic (void) fprintf(stderr, "%ld blocks\n", Blocks * (Bufsize>>9)); 57533828Sbostic exit(0); 57633828Sbostic } 57733828Sbostic 57833828Sbostic static 57933828Sbostic usage() 58033828Sbostic { 581*33829Sbostic (void) fprintf("Usage: %s\n %s\n %s\n %s\n %s\n", 582*33829Sbostic "cpio -o[acvB] <name-list >collection", 583*33829Sbostic "cpio -o[acvB] -Ocollection <name-list", 584*33829Sbostic "cpio -i[cdmrstuvfB6] [ pattern ... ] <collection", 585*33829Sbostic "cpio -i[cdmrstuvfB6] -Icollection [ pattern ... ]", 586*33829Sbostic "cpio -p[adlmruv] directory <name-list"); 58733828Sbostic } 58833828Sbostic 58933828Sbostic static 59033828Sbostic chkswfile( sp, c, option ) 59133828Sbostic char *sp; 59233828Sbostic char c; 59333828Sbostic short option; 59433828Sbostic { 595*33829Sbostic if( !option ) { 596*33829Sbostic fperr( "-%c must be specified before -%c option", 59733828Sbostic c == 'I' ? 'i' : 'o', c ); 598*33829Sbostic exit(2); 599*33829Sbostic } 600*33829Sbostic if( (c == 'I' && option != IN) || (c == 'O' && option != OUT) ) { 601*33829Sbostic fperr( "-%c option not permitted with -%c option", c, 60233828Sbostic option ); 603*33829Sbostic exit(2); 604*33829Sbostic } 60533828Sbostic if( !sp ) 60633828Sbostic return; 607*33829Sbostic fperr("No more than one -I or -O flag permitted"); 608*33829Sbostic exit(2); 60933828Sbostic } 61033828Sbostic 61133828Sbostic static 61233828Sbostic getname() /* get file name, get info for header */ 61333828Sbostic { 61433828Sbostic register char *namep = Name; 61533828Sbostic register ushort ftype; 616*33829Sbostic struct stat Lstatb; 61733828Sbostic long tlong; 61833828Sbostic 61933828Sbostic for(;;) { 62033828Sbostic if(gets(namep) == NULL) 62133828Sbostic return 0; 62233828Sbostic while(*namep == '.' && namep[1] == '/') { 62333828Sbostic namep++; 62433828Sbostic while(*namep == '/') namep++; 62533828Sbostic } 62633828Sbostic strcpy(Hdr.h_name, namep); 627*33829Sbostic if(lstat(namep, &Statb) < 0) { 628*33829Sbostic fperrno("Cannot stat <%s>", Hdr.h_name); 62933828Sbostic continue; 63033828Sbostic } 63133828Sbostic ftype = Statb.st_mode & Filetype; 63233828Sbostic A_directory = (ftype == S_IFDIR); 63333828Sbostic A_special = (ftype == S_IFBLK) 63433828Sbostic || (ftype == S_IFCHR) 63533828Sbostic || (ftype == S_IFIFO); 636*33829Sbostic A_symlink = (ftype == S_IFLNK); 63733828Sbostic Hdr.h_magic = MAGIC; 63833828Sbostic Hdr.h_namesize = strlen(Hdr.h_name) + 1; 63933828Sbostic Hdr.h_uid = Statb.st_uid; 64033828Sbostic Hdr.h_gid = Statb.st_gid; 64133828Sbostic Hdr.h_dev = Statb.st_dev; 64233828Sbostic Hdr.h_ino = Statb.st_ino; 64333828Sbostic Hdr.h_mode = Statb.st_mode; 64433828Sbostic MKSHORT(Hdr.h_mtime, Statb.st_mtime); 64533828Sbostic Hdr.h_nlink = Statb.st_nlink; 646*33829Sbostic tlong = ((Hdr.h_mode&S_IFMT) == S_IFREG || 647*33829Sbostic (Hdr.h_mode&S_IFMT) == S_IFLNK)? Statb.st_size: 0L; 64833828Sbostic MKSHORT(Hdr.h_filesize, tlong); 64933828Sbostic Hdr.h_rdev = Statb.st_rdev; 65033828Sbostic if( Cflag ) 65133828Sbostic bintochar(tlong); 65233828Sbostic return 1; 65333828Sbostic } 65433828Sbostic } 65533828Sbostic 65633828Sbostic static 65733828Sbostic bintochar(t) /* ASCII header write */ 65833828Sbostic long t; 65933828Sbostic { 66033828Sbostic sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s", 66133828Sbostic MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid, 66233828Sbostic Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev), 66333828Sbostic Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name); 66433828Sbostic } 66533828Sbostic 66633828Sbostic static 66733828Sbostic chartobin() /* ASCII header read */ 66833828Sbostic { 66933828Sbostic sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo", 67033828Sbostic &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid, 67133828Sbostic &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime, 67233828Sbostic &Hdr.h_namesize, &Longfile); 67333828Sbostic MKSHORT(Hdr.h_filesize, Longfile); 67433828Sbostic MKSHORT(Hdr.h_mtime, Longtime); 67533828Sbostic } 67633828Sbostic 67733828Sbostic 67833828Sbostic /* Check the header for the magic number. Switch modes automatically to 67933828Sbostic match the type of header found. 68033828Sbostic */ 68133828Sbostic static 68233828Sbostic chkhdr() 68333828Sbostic { 68433828Sbostic bread(Chdr, CHARS); 68533828Sbostic chartobin(); 68633828Sbostic if( Hdr.h_magic == MAGIC ) 68733828Sbostic Cflag = 1; 68833828Sbostic else { 68933828Sbostic breread(&Hdr.h_magic, sizeof Hdr.h_magic); 690*33829Sbostic if( Hdr.h_magic == MAGIC || Hdr.h_magic == (short)BSMAGIC ) 69133828Sbostic Cflag = 0; 692*33829Sbostic else { 693*33829Sbostic fperr("This is not a cpio file. Bad magic number."); 694*33829Sbostic exit(2); 695*33829Sbostic } 69633828Sbostic } 69733828Sbostic breread(Chdr, 0); 69833828Sbostic } 69933828Sbostic 70033828Sbostic 70133828Sbostic static 70233828Sbostic gethdr() /* get file headers */ 70333828Sbostic { 70433828Sbostic register ushort ftype; 70533828Sbostic 70633828Sbostic if (Cflag) { 70733828Sbostic bread(Chdr, CHARS); 70833828Sbostic chartobin(); 70933828Sbostic } 71033828Sbostic else 71133828Sbostic bread(&Hdr, HDRSIZE); 71233828Sbostic 713*33829Sbostic if(Hdr.h_magic == (short)BSMAGIC) 714*33829Sbostic swap((char *)&Hdr, HDRSIZE, 1, 0); 715*33829Sbostic else if( Hdr.h_magic != MAGIC ) { 716*33829Sbostic fperr("Out of phase--get help"); 717*33829Sbostic exit(2); 71833828Sbostic } 71933828Sbostic bread(Hdr.h_name, Hdr.h_namesize); 72033828Sbostic if(EQ(Hdr.h_name, "TRAILER!!!")) 72133828Sbostic return 0; 72233828Sbostic ftype = Hdr.h_mode & Filetype; 72333828Sbostic A_directory = (ftype == S_IFDIR); 72433828Sbostic A_special = (ftype == S_IFBLK) 72533828Sbostic || (ftype == S_IFCHR) 72633828Sbostic || (ftype == S_IFIFO); 727*33829Sbostic A_symlink = (ftype == S_IFLNK); 72833828Sbostic return 1; 72933828Sbostic } 73033828Sbostic 73133828Sbostic static 73233828Sbostic ckname(namep) /* check filenames with patterns given on cmd line */ 73333828Sbostic register char *namep; 73433828Sbostic { 73533828Sbostic char buf[sizeof Hdr.h_name]; 73633828Sbostic 73733828Sbostic if(fflag ^ !nmatch(namep, Pattern)) { 73833828Sbostic return 0; 73933828Sbostic } 74033828Sbostic if(Rename && !A_directory) { /* rename interactively */ 74133828Sbostic fprintf(Wtty, "Rename <%s>\n", namep); 74233828Sbostic fflush(Wtty); 74333828Sbostic fgets(buf, sizeof buf, Rtty); 74433828Sbostic if(feof(Rtty)) 74533828Sbostic exit(2); 74633828Sbostic buf[strlen(buf) - 1] = '\0'; 74733828Sbostic if(EQ(buf, "")) { 74833828Sbostic strcpy(namep,buf); 74933828Sbostic printf("Skipped\n"); 75033828Sbostic return 0; 75133828Sbostic } 75233828Sbostic else if(EQ(buf, ".")) 75333828Sbostic printf("Same name\n"); 75433828Sbostic else 75533828Sbostic strcpy(namep,buf); 75633828Sbostic } 75733828Sbostic return 1; 75833828Sbostic } 75933828Sbostic 76033828Sbostic static 761*33829Sbostic openout(namep, symlname) /* open files for writing, set all necessary info */ 76233828Sbostic register char *namep; 763*33829Sbostic char *symlname; 76433828Sbostic { 76533828Sbostic register f; 76633828Sbostic register char *np; 76733828Sbostic int ans; 76833828Sbostic 76933828Sbostic if(!strncmp(namep, "./", 2)) 77033828Sbostic namep += 2; 77133828Sbostic np = namep; 77233828Sbostic if(A_directory) { 77333828Sbostic if( !Dir || Rename || EQ(namep, ".") || EQ(namep, "..") ) 77433828Sbostic /* do not consider . or .. files */ 77533828Sbostic return 0; 77633828Sbostic if(stat(namep, &Xstatb) == -1) { 77733828Sbostic 77833828Sbostic /* try creating (only twice) */ 77933828Sbostic ans = 0; 78033828Sbostic do { 781*33829Sbostic if(mkdir(namep, Hdr.h_mode) != 0) { 78233828Sbostic ans += 1; 78333828Sbostic }else { 78433828Sbostic ans = 0; 78533828Sbostic break; 78633828Sbostic } 78733828Sbostic }while(ans < 2 && missdir(namep) == 0); 78833828Sbostic if(ans == 1) { 78933828Sbostic fperrno("Cannot create directory for <%s>", 79033828Sbostic namep); 79133828Sbostic return(0); 79233828Sbostic }else if(ans == 2) { 79333828Sbostic fperrno("Cannot create directory <%s>", namep); 79433828Sbostic return(0); 79533828Sbostic } 79633828Sbostic } 79733828Sbostic 79833828Sbostic ret: 799*33829Sbostic if(chmod(namep, Hdr.h_mode) < 0) 800*33829Sbostic fperrno("Cannot change mode of <%s>", namep); 80133828Sbostic if(Uid == 0) 802*33829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 803*33829Sbostic fperrno("Cannot change ownership of <%s>", 804*33829Sbostic namep); 80533828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 80633828Sbostic return 0; 80733828Sbostic } 80833828Sbostic if(Hdr.h_nlink > 1) 80933828Sbostic if(!postml(namep, np)) 81033828Sbostic return 0; 811*33829Sbostic if(lstat(namep, &Xstatb) == 0) { 81233828Sbostic if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) { 81333828Sbostic if(unlink(namep) < 0) { 81433828Sbostic fperrno("cannot unlink current <%s>", namep); 81533828Sbostic } 81633828Sbostic } 81733828Sbostic if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) { 81833828Sbostic /* There's a newer or same aged version of file on destination */ 819*33829Sbostic fperr("current <%s> newer or same age", np); 82033828Sbostic return 0; 82133828Sbostic } 82233828Sbostic } 82333828Sbostic if( Option == PASS 82433828Sbostic && Hdr.h_ino == Xstatb.st_ino 82533828Sbostic && Hdr.h_dev == Xstatb.st_dev) { 826*33829Sbostic fperr("Attempt to pass file to self!"); 827*33829Sbostic exit(2); 82833828Sbostic } 829*33829Sbostic if(A_symlink) { 830*33829Sbostic /* try symlinking (only twice) */ 831*33829Sbostic ans = 0; 832*33829Sbostic do { 833*33829Sbostic if(symlink( 834*33829Sbostic symlname, namep) < 0) { 835*33829Sbostic ans += 1; 836*33829Sbostic }else { 837*33829Sbostic ans = 0; 838*33829Sbostic break; 839*33829Sbostic } 840*33829Sbostic }while(ans < 2 && missdir(np) == 0); 841*33829Sbostic if(ans == 1) { 842*33829Sbostic fperrno("Cannot create directory for <%s>", namep); 843*33829Sbostic return(0); 844*33829Sbostic }else if(ans == 2) { 845*33829Sbostic fperrno("Cannot symlink <%s> and <%s>", namep, symlname); 846*33829Sbostic return(0); 847*33829Sbostic } 848*33829Sbostic 849*33829Sbostic return 0; 850*33829Sbostic } 85133828Sbostic if(A_special) { 85233828Sbostic if((Hdr.h_mode & Filetype) == S_IFIFO) 85333828Sbostic Hdr.h_rdev = 0; 85433828Sbostic 85533828Sbostic /* try creating (only twice) */ 85633828Sbostic ans = 0; 85733828Sbostic do { 85833828Sbostic if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) { 85933828Sbostic ans += 1; 86033828Sbostic }else { 86133828Sbostic ans = 0; 86233828Sbostic break; 86333828Sbostic } 86433828Sbostic }while(ans < 2 && missdir(np) == 0); 86533828Sbostic if(ans == 1) { 86633828Sbostic fperrno("Cannot create directory for <%s>", namep); 86733828Sbostic return(0); 86833828Sbostic }else if(ans == 2) { 86933828Sbostic fperrno("Cannot mknod <%s>", namep); 87033828Sbostic return(0); 87133828Sbostic } 87233828Sbostic 87333828Sbostic goto ret; 87433828Sbostic } 87533828Sbostic 87633828Sbostic /* try creating (only twice) */ 87733828Sbostic ans = 0; 87833828Sbostic do { 87933828Sbostic if((f = creat(namep, Hdr.h_mode)) < 0) { 88033828Sbostic ans += 1; 88133828Sbostic }else { 88233828Sbostic ans = 0; 88333828Sbostic break; 88433828Sbostic } 88533828Sbostic }while(ans < 2 && missdir(np) == 0); 88633828Sbostic if(ans == 1) { 88733828Sbostic fperrno("Cannot create directory for <%s>", namep); 88833828Sbostic return(0); 88933828Sbostic }else if(ans == 2) { 89033828Sbostic fperrno("Cannot create <%s>", namep); 89133828Sbostic return(0); 89233828Sbostic } 89333828Sbostic 89433828Sbostic if(Uid == 0) 895*33829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 896*33829Sbostic fperrno("Cannot change ownership of <%s>", namep); 89733828Sbostic return f; 89833828Sbostic } 89933828Sbostic 90033828Sbostic 90133828Sbostic /* Shared by bread() and breread() 90233828Sbostic */ 90333828Sbostic static int nleft = 0; /* unread chars left in Cbuf */ 90433828Sbostic static char *ip; /* pointer to next char to be read from Cbuf */ 90533828Sbostic 90633828Sbostic /* Reread the current buffer Cbuf. 90733828Sbostic A character count, c, of 0 simply resets the pointer so next bread gets 90833828Sbostic the same data again. 90933828Sbostic */ 91033828Sbostic static 91133828Sbostic breread(b, c) 91233828Sbostic char *b; 91333828Sbostic int c; 91433828Sbostic { 91533828Sbostic ip = Cbuf; 91633828Sbostic if( nleft ) 91733828Sbostic nleft = Bufsize; 91833828Sbostic if( !c ) 91933828Sbostic return; 92033828Sbostic bread(b, c); 92133828Sbostic } 92233828Sbostic 92333828Sbostic static 92433828Sbostic bread(b, c) 92533828Sbostic register char *b; 92633828Sbostic register int c; 92733828Sbostic { 92833828Sbostic register int rv; 92933828Sbostic register char *p = ip; 93033828Sbostic 93133828Sbostic if( !Cflag ) { 93233828Sbostic /* round c up to an even number */ 93333828Sbostic c = (c+1)/2; 93433828Sbostic c *= 2; 93533828Sbostic } 93633828Sbostic while( c ) { 93733828Sbostic if( nleft == 0 ) { 93833828Sbostic while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) { 93933828Sbostic Input = chgreel(0, Input, rv); 94033828Sbostic } 94133828Sbostic if( rv == Bufsize ) { 94233828Sbostic nleft = Bufsize; 94333828Sbostic p = Cbuf; 94433828Sbostic ++Blocks; 94533828Sbostic } 946*33829Sbostic else if( rv == -1 ) { 947*33829Sbostic fperrno("Read error on archive"); 948*33829Sbostic exit(2); 949*33829Sbostic } 95033828Sbostic else if( rv < Bufsize ) { /* short read */ 95133828Sbostic smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv ); 95233828Sbostic nleft = rv; 95333828Sbostic p = &Cbuf[ Bufsize - rv ]; 95433828Sbostic sBlocks += rv; 95533828Sbostic } 95633828Sbostic } 95733828Sbostic if( nleft <= c ) { 95833828Sbostic memcpy( b, p, nleft ); 95933828Sbostic c -= nleft; 96033828Sbostic b += nleft; 96133828Sbostic p += nleft; 96233828Sbostic nleft = 0; 96333828Sbostic } 96433828Sbostic else { 96533828Sbostic memcpy( b, p, c ); 96633828Sbostic nleft -= c; 96733828Sbostic b += c; 96833828Sbostic p += c; 96933828Sbostic c = 0; 97033828Sbostic } 97133828Sbostic } 97233828Sbostic ip = p; 97333828Sbostic } 97433828Sbostic 97533828Sbostic 97633828Sbostic static 97733828Sbostic bwrite(rp, c) 97833828Sbostic register char *rp; 97933828Sbostic register c; 98033828Sbostic { 98133828Sbostic register char *cp = Cp; 98233828Sbostic static unsigned Ccnt = 0; 98333828Sbostic register unsigned Cleft; 98433828Sbostic register int rv; 98533828Sbostic 98633828Sbostic if( !Cflag ) { 98733828Sbostic /* round c up to an even number */ 98833828Sbostic c = (c+1)/2; 98933828Sbostic c *= 2; 99033828Sbostic } 99133828Sbostic while( c ) { 99233828Sbostic if( (Cleft = Bufsize - Ccnt) <= c ) { 99333828Sbostic memcpy( cp, rp, Cleft ); 99433828Sbostic rv = write(Output, Cbuf, Bufsize); 99533828Sbostic if( rv == 0 || ( rv == -1 && errno == ENXIO ) ) { 99633828Sbostic rv = eomchgreel(); 99733828Sbostic } 99833828Sbostic if( rv == Bufsize ) { 99933828Sbostic Ccnt = 0; 100033828Sbostic cp = Cbuf; 100133828Sbostic } 1002*33829Sbostic else if( rv == -1 ) { 1003*33829Sbostic fperrno("Write error on archive"); 1004*33829Sbostic exit(2); 1005*33829Sbostic } 100633828Sbostic else if( rv < Bufsize ) { 100733828Sbostic Output = chgreel(1, Output, 0); 100833828Sbostic smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv ); 100933828Sbostic Ccnt = Bufsize - rv; 101033828Sbostic cp = &Cbuf[ rv ]; 101133828Sbostic } 101233828Sbostic ++Blocks; 101333828Sbostic rp += Cleft; 101433828Sbostic c -= Cleft; 101533828Sbostic } 101633828Sbostic else { 101733828Sbostic memcpy( cp, rp, c ); 101833828Sbostic Ccnt += c; 101933828Sbostic cp += c; 102033828Sbostic rp += c; 102133828Sbostic c = 0; 102233828Sbostic } 102333828Sbostic } 102433828Sbostic Cp = cp; 102533828Sbostic } 102633828Sbostic 102733828Sbostic 102833828Sbostic static int reelcount = 1; /* used below and in chgreel() */ 102933828Sbostic 103033828Sbostic /* Change reel due to reaching end-of-media. 103133828Sbostic Keep trying to get a successful write before considering the 103233828Sbostic change-of-reel as successful. 103333828Sbostic */ 103433828Sbostic static 103533828Sbostic int 103633828Sbostic eomchgreel() 103733828Sbostic { 103833828Sbostic int rv; 103933828Sbostic 104033828Sbostic while( 1 ) { 104133828Sbostic Output = chgreel(1, Output, 0); 104233828Sbostic rv = write(Output, Cbuf, Bufsize); 104333828Sbostic if( rv == Bufsize ) 104433828Sbostic return rv; 1045*33829Sbostic if( rv == -1 ) 1046*33829Sbostic fperrno( "Unable to write this medium" ); 1047*33829Sbostic else 1048*33829Sbostic fperr( "Unable to write this medium: Premature EOF" ); 1049*33829Sbostic (void) fprintf(stderr, "Try again.\n"); 105033828Sbostic reelcount--; 105133828Sbostic } 105233828Sbostic /*NOTREACHED*/ 105333828Sbostic } 105433828Sbostic 105533828Sbostic 105633828Sbostic static 105733828Sbostic postml(namep, np) /* linking funtion: Postml() is called after */ 105833828Sbostic register char *namep, *np; /* namep is created. Postml() checks to see */ 105933828Sbostic { /* if namep should be linked to np. If so, */ 106033828Sbostic /* postml() removes the independent instance */ 106133828Sbostic register i; /* of namep and links namep to np. */ 106233828Sbostic static struct ml { 106333828Sbostic short m_dev; 106433828Sbostic ushort m_ino; 106533828Sbostic char m_name[2]; 106633828Sbostic } **ml = 0; 106733828Sbostic register struct ml *mlp; 106833828Sbostic static unsigned mlsize = 0; 106933828Sbostic static unsigned mlinks = 0; 107033828Sbostic char *lnamep; 107133828Sbostic int ans; 107233828Sbostic 107333828Sbostic if( !ml ) { 107433828Sbostic mlsize = LINKS; 1075*33829Sbostic ml = (struct ml **) malloc(mlsize * sizeof(struct ml)); 107633828Sbostic } 107733828Sbostic else if( mlinks == mlsize ) { 107833828Sbostic mlsize += LINKS; 1079*33829Sbostic ml = (struct ml **) realloc((char *) ml, 1080*33829Sbostic mlsize * sizeof(struct ml)); 108133828Sbostic } 1082*33829Sbostic if (ml == NULL) { 1083*33829Sbostic fperr("Out of memory for links"); 1084*33829Sbostic exit(2); 1085*33829Sbostic } 108633828Sbostic for(i = 0; i < mlinks; ++i) { 108733828Sbostic mlp = ml[i]; 108833828Sbostic if(mlp->m_ino==Hdr.h_ino && mlp->m_dev==Hdr.h_dev) { 108933828Sbostic if(Verbose) 1090*33829Sbostic printf("%s linked to %s\n", ml[i]->m_name, 1091*33829Sbostic np); 109233828Sbostic unlink(namep); 109333828Sbostic if(Option == IN && *(mlp->m_name) != '/') { 109433828Sbostic Fullname[Pathend] = '\0'; 109533828Sbostic strcat(Fullname, mlp->m_name); 109633828Sbostic lnamep = Fullname; 109733828Sbostic } 109833828Sbostic lnamep = mlp->m_name; 109933828Sbostic 110033828Sbostic /* try linking (only twice) */ 110133828Sbostic ans = 0; 110233828Sbostic do { 110333828Sbostic if(link(lnamep, namep) < 0) { 110433828Sbostic ans += 1; 110533828Sbostic }else { 110633828Sbostic ans = 0; 110733828Sbostic break; 110833828Sbostic } 110933828Sbostic }while(ans < 2 && missdir(np) == 0); 111033828Sbostic if(ans == 1) { 111133828Sbostic fperrno("Cannot create directory for <%s>", np); 111233828Sbostic return(0); 111333828Sbostic }else if(ans == 2) { 111433828Sbostic fperrno("Cannot link <%s> & <%s>", lnamep, np); 111533828Sbostic return(0); 111633828Sbostic } 111733828Sbostic 111833828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 111933828Sbostic return 0; 112033828Sbostic } 112133828Sbostic } 1122*33829Sbostic if( !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) { 112333828Sbostic static int first=1; 112433828Sbostic 112533828Sbostic if(first) 1126*33829Sbostic fperr("Out of memory for links"); 112733828Sbostic first = 0; 112833828Sbostic return 1; 112933828Sbostic } 113033828Sbostic ml[mlinks]->m_dev = Hdr.h_dev; 113133828Sbostic ml[mlinks]->m_ino = Hdr.h_ino; 113233828Sbostic strcpy(ml[mlinks]->m_name, np); 113333828Sbostic ++mlinks; 113433828Sbostic return 1; 113533828Sbostic } 113633828Sbostic 113733828Sbostic static 113833828Sbostic pentry(namep) /* print verbose table of contents */ 113933828Sbostic register char *namep; 114033828Sbostic { 114133828Sbostic 114233828Sbostic static short lastid = -1; 114333828Sbostic #include <pwd.h> 114433828Sbostic static struct passwd *pw; 114533828Sbostic struct passwd *getpwuid(); 114633828Sbostic static char tbuf[32]; 114733828Sbostic char *ctime(); 114833828Sbostic 114933828Sbostic printf("%-7o", MK_USHORT(Hdr.h_mode)); 115033828Sbostic if(lastid == Hdr.h_uid) 115133828Sbostic printf("%-6s", pw->pw_name); 115233828Sbostic else { 115333828Sbostic setpwent(); 115433828Sbostic if(pw = getpwuid((int)Hdr.h_uid)) { 115533828Sbostic printf("%-6s", pw->pw_name); 115633828Sbostic lastid = Hdr.h_uid; 115733828Sbostic } else { 115833828Sbostic printf("%-6d", Hdr.h_uid); 115933828Sbostic lastid = -1; 116033828Sbostic } 116133828Sbostic } 116233828Sbostic printf("%7ld ", mklong(Hdr.h_filesize)); 116333828Sbostic U.l = mklong(Hdr.h_mtime); 116433828Sbostic strcpy(tbuf, ctime((long *)&U.l)); 116533828Sbostic tbuf[24] = '\0'; 1166*33829Sbostic printf(" %s %s", &tbuf[4], namep); 1167*33829Sbostic if (A_symlink) 1168*33829Sbostic printf(" -> %s", Symlbuf); 1169*33829Sbostic putchar('\n'); 117033828Sbostic } 117133828Sbostic 117233828Sbostic /* pattern matching functions */ 117333828Sbostic static 117433828Sbostic nmatch(s, pat) 117533828Sbostic char *s, **pat; 117633828Sbostic { 117733828Sbostic if( !pat ) 117833828Sbostic return 1; 117933828Sbostic while(*pat) { 118033828Sbostic if((**pat == '!' && !gmatch(s, *pat+1)) 118133828Sbostic || gmatch(s, *pat)) 118233828Sbostic return 1; 118333828Sbostic ++pat; 118433828Sbostic } 118533828Sbostic return 0; 118633828Sbostic } 118733828Sbostic 118833828Sbostic 118933828Sbostic static 119033828Sbostic gmatch(s, p) 119133828Sbostic register char *s, *p; 119233828Sbostic { 119333828Sbostic register int c; 119433828Sbostic register cc, ok, lc, scc; 119533828Sbostic 119633828Sbostic scc = *s; 119733828Sbostic lc = 077777; 119833828Sbostic switch (c = *p) { 119933828Sbostic 120033828Sbostic case '[': 120133828Sbostic ok = 0; 120233828Sbostic while (cc = *++p) { 120333828Sbostic switch (cc) { 120433828Sbostic 120533828Sbostic case ']': 120633828Sbostic if (ok) 120733828Sbostic return(gmatch(++s, ++p)); 120833828Sbostic else 120933828Sbostic return(0); 121033828Sbostic 121133828Sbostic case '-': 121233828Sbostic ok |= ((lc <= scc) && (scc <= (cc=p[1]))); 121333828Sbostic } 121433828Sbostic if (scc==(lc=cc)) ok++; 121533828Sbostic } 121633828Sbostic return(0); 121733828Sbostic 121833828Sbostic case '?': 121933828Sbostic caseq: 122033828Sbostic if(scc) return(gmatch(++s, ++p)); 122133828Sbostic return(0); 122233828Sbostic case '*': 122333828Sbostic return(umatch(s, ++p)); 122433828Sbostic case 0: 122533828Sbostic return(!scc); 122633828Sbostic } 122733828Sbostic if (c==scc) goto caseq; 122833828Sbostic return(0); 122933828Sbostic } 123033828Sbostic 123133828Sbostic 123233828Sbostic 123333828Sbostic static 123433828Sbostic umatch(s, p) 123533828Sbostic register char *s, *p; 123633828Sbostic { 123733828Sbostic if(*p==0) return(1); 123833828Sbostic while(*s) 123933828Sbostic if (gmatch(s++,p)) return(1); 124033828Sbostic return(0); 124133828Sbostic } 124233828Sbostic 1243*33829Sbostic swap(buf, bytecount, bytes, halfwords) /* swap halfwords, bytes or both */ 1244*33829Sbostic char *buf; 1245*33829Sbostic int bytecount; 1246*33829Sbostic int bytes, halfwords; 124733828Sbostic { 1248*33829Sbostic register int count; 1249*33829Sbostic int n, i; 125033828Sbostic 1251*33829Sbostic if(bytes) { 1252*33829Sbostic register union swpbytes { 1253*33829Sbostic short shortw; 1254*33829Sbostic char charv[2]; 1255*33829Sbostic } *pbuf; 1256*33829Sbostic register char c; 125733828Sbostic 1258*33829Sbostic count = bytecount; 1259*33829Sbostic pbuf = (union swpbytes *)buf; 1260*33829Sbostic if (count % sizeof(union swpbytes)) 1261*33829Sbostic pbuf->charv[count] = 0; 1262*33829Sbostic count = (count + (sizeof(union swpbytes) - 1)) / sizeof(union swpbytes); 1263*33829Sbostic while (count--) { 1264*33829Sbostic c = pbuf->charv[0]; 1265*33829Sbostic pbuf->charv[0] = pbuf->charv[1]; 1266*33829Sbostic pbuf->charv[1] = c; 1267*33829Sbostic ++pbuf; 126833828Sbostic } 126933828Sbostic } 1270*33829Sbostic if (halfwords) { 1271*33829Sbostic register union swphalf { 1272*33829Sbostic long longw; 1273*33829Sbostic short shortv[2]; 1274*33829Sbostic char charv[4]; 1275*33829Sbostic } *pbuf; 1276*33829Sbostic register short cc; 1277*33829Sbostic 1278*33829Sbostic count = bytecount; 1279*33829Sbostic pbuf = (union swphalf *)buf; 1280*33829Sbostic if (n = count % sizeof(union swphalf)) 1281*33829Sbostic if(bytes && n % 2) 1282*33829Sbostic for(i = count + 1; i <= count + (sizeof(union swphalf) - n); i++) 1283*33829Sbostic pbuf->charv[i] = 0; 1284*33829Sbostic else 1285*33829Sbostic for (i = count; i < count + (sizeof(union swphalf) - n); i++) 1286*33829Sbostic pbuf->charv[i] = 0; 1287*33829Sbostic count = (count + (sizeof(union swphalf) - 1)) / sizeof(union swphalf); 1288*33829Sbostic while (count--) { 128933828Sbostic cc = pbuf->shortv[0]; 129033828Sbostic pbuf->shortv[0] = pbuf->shortv[1]; 129133828Sbostic pbuf->shortv[1] = cc; 129233828Sbostic ++pbuf; 129333828Sbostic } 129433828Sbostic } 129533828Sbostic } 129633828Sbostic 129733828Sbostic 129833828Sbostic static 129933828Sbostic set_time(namep, atime, mtime) /* set access and modification times */ 130033828Sbostic register char *namep; 130133828Sbostic time_t atime, mtime; 130233828Sbostic { 1303*33829Sbostic static struct utimbuf timevec; 130433828Sbostic 130533828Sbostic if(!Mod_time) 130633828Sbostic return; 1307*33829Sbostic timevec.actime = atime; 1308*33829Sbostic timevec.modtime = mtime; 1309*33829Sbostic (void)utime(namep, &timevec); 131033828Sbostic } 131133828Sbostic 131233828Sbostic 131333828Sbostic 131433828Sbostic static 131533828Sbostic chgreel(x, fl, rv) 131633828Sbostic { 131733828Sbostic register f; 131833828Sbostic char str[BUFSIZ]; 131933828Sbostic struct stat statb; 132033828Sbostic 132133828Sbostic fstat(fl, &statb); 132233828Sbostic if((statb.st_mode&S_IFMT) != S_IFCHR) { 132333828Sbostic fperrno("Can't %s: ", x? "write output": "read input"); 132433828Sbostic exit(2); 132533828Sbostic } 132633828Sbostic if( rv == 0 || 132733828Sbostic ( rv == -1 && ( errno == ENOSPC || errno == ENXIO ) ) ) 1328*33829Sbostic fperr( "\007Reached end of medium on %s", 132933828Sbostic x? "output":"input" ); 133033828Sbostic else { 133133828Sbostic fperrno( "\007Encountered an error on %s", 133233828Sbostic x? "output":"input" ); 133333828Sbostic exit(2); 133433828Sbostic } 1335*33829Sbostic if( Rtty == NULL ) { 1336*33829Sbostic Rtty = fopen(ttyname, "r"); 1337*33829Sbostic if( Rtty == NULL ) { 1338*33829Sbostic fperrno("Cannot prompt (can't open %s)", ttyname); 1339*33829Sbostic exit(2); 1340*33829Sbostic } 1341*33829Sbostic } 134233828Sbostic close(fl); 134333828Sbostic reelcount++; 134433828Sbostic again: 134533828Sbostic if( swfile ) { 134633828Sbostic askagain: 134733828Sbostic fperr( eommsg, reelcount ); 134833828Sbostic fgets(str, sizeof str, Rtty); 134933828Sbostic switch( *str ) { 135033828Sbostic case '\n': 135133828Sbostic strcpy( str, swfile ); 135233828Sbostic break; 135333828Sbostic case 'q': 135433828Sbostic exit(2); 135533828Sbostic default: 135633828Sbostic goto askagain; 135733828Sbostic } 135833828Sbostic } 135933828Sbostic else { 1360*33829Sbostic fperr("If you want to go on, type device/file name when ready."); 136133828Sbostic fgets(str, sizeof str, Rtty); 136233828Sbostic str[strlen(str) - 1] = '\0'; 136333828Sbostic if(!*str) 136433828Sbostic exit(2); 136533828Sbostic } 136633828Sbostic if((f = open(str, x? 1: 0)) < 0) { 1367*33829Sbostic fperrno("Can't open <%s>", str); 136833828Sbostic goto again; 136933828Sbostic } 137033828Sbostic return f; 137133828Sbostic } 137233828Sbostic 137333828Sbostic 137433828Sbostic 137533828Sbostic static 137633828Sbostic missdir(namep) 137733828Sbostic register char *namep; 137833828Sbostic { 137933828Sbostic register char *np; 138033828Sbostic register ct = 2; 138133828Sbostic 138233828Sbostic for(np = namep; *np; ++np) 138333828Sbostic if(*np == '/') { 138433828Sbostic if(np == namep) continue; /* skip over 'root slash' */ 138533828Sbostic *np = '\0'; 138633828Sbostic if(stat(namep, &Xstatb) == -1) { 138733828Sbostic if(Dir) { 1388*33829Sbostic if((ct = mkdir(namep, 0777)) != 0) { 138933828Sbostic *np = '/'; 139033828Sbostic return(ct); 139133828Sbostic } 139233828Sbostic }else { 1393*33829Sbostic fperr("missing 'd' option"); 139433828Sbostic return(-1); 139533828Sbostic } 139633828Sbostic } 139733828Sbostic *np = '/'; 139833828Sbostic } 139933828Sbostic if (ct == 2) ct = 0; /* the file already exists */ 140033828Sbostic return ct; 140133828Sbostic } 140233828Sbostic 140333828Sbostic 140433828Sbostic 140533828Sbostic static 140633828Sbostic pwd() /* get working directory */ 140733828Sbostic { 1408*33829Sbostic if (getwd(Fullname) == 0) { 1409*33829Sbostic (void)fprintf(stderr, "cpio: %s\n", 1410*33829Sbostic Fullname); 141133828Sbostic exit(2); 1412*33829Sbostic } 141333828Sbostic Pathend = strlen(Fullname); 1414*33829Sbostic Fullname[Pathend++] = '/'; 1415*33829Sbostic Fullname[Pathend] = '\0'; 141633828Sbostic } 141733828Sbostic 141833828Sbostic 141933828Sbostic /* 142033828Sbostic print message on the stderr 142133828Sbostic */ 142233828Sbostic static 142333828Sbostic fperr( va_alist ) 142433828Sbostic va_dcl 142533828Sbostic { 142633828Sbostic va_list args; 142733828Sbostic char *fmt; 142833828Sbostic 142933828Sbostic va_start( args ); 1430*33829Sbostic fprintf( stderr, "cpio: "); 143133828Sbostic fmt = va_arg( args, char * ); 143233828Sbostic vfprintf( stderr, fmt, args ); 1433*33829Sbostic putc( '\n', stderr); 143433828Sbostic fflush( stderr ); 143533828Sbostic } 143633828Sbostic 143733828Sbostic /* 143833828Sbostic print message on the stderr followed by error number and meaning. 143933828Sbostic */ 144033828Sbostic static 144133828Sbostic fperrno( va_alist ) 144233828Sbostic va_dcl 144333828Sbostic { 144433828Sbostic va_list args; 144533828Sbostic char *fmt; 144633828Sbostic 144733828Sbostic va_start( args ); 1448*33829Sbostic fprintf( stderr, "cpio: "); 144933828Sbostic fmt = va_arg( args, char * ); 145033828Sbostic vfprintf( stderr, fmt, args ); 1451*33829Sbostic fprintf( stderr, ": " ); 145233828Sbostic fflush( stderr ); 145333828Sbostic perror(""); 145433828Sbostic } 145533828Sbostic 145633828Sbostic 1457*33829Sbostic /* Safe memory copy. 1458*33829Sbostic Fast if the to and from strings do not overlap, 1459*33829Sbostic slower but safe if they do. 1460*33829Sbostic */ 1461*33829Sbostic 1462*33829Sbostic static char * 1463*33829Sbostic smemcpy( to, from, count ) 1464*33829Sbostic register char *to, *from; 1465*33829Sbostic register unsigned count; 146633828Sbostic { 1467*33829Sbostic char *savedto; 1468*33829Sbostic 1469*33829Sbostic if( &to[ count ] <= from || &from[ count ] <= to ) 1470*33829Sbostic return memcpy( to, from, count ); 1471*33829Sbostic 1472*33829Sbostic if( to == from ) 1473*33829Sbostic return to; 1474*33829Sbostic 1475*33829Sbostic savedto = to; 1476*33829Sbostic if( to < from ) 1477*33829Sbostic while( count-- ) 1478*33829Sbostic *(to++) = *(from++); 1479*33829Sbostic else { 1480*33829Sbostic to += count; 1481*33829Sbostic from += count; 1482*33829Sbostic while( count-- ) 1483*33829Sbostic *(--to) = *(--from); 148433828Sbostic } 148533828Sbostic 1486*33829Sbostic return savedto; 148733828Sbostic } 1488