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> 2733829Sbostic #include <sys/param.h> 2833829Sbostic #include <sys/types.h> 2933828Sbostic #include <sys/stat.h> 30*37871Sbostic #include <paths.h> 3133828Sbostic 3233829Sbostic struct utimbuf { 3333829Sbostic time_t actime; 3433829Sbostic time_t modtime; 3533829Sbostic }; 3633829Sbostic #ifndef S_IFIFO 3733829Sbostic #define S_IFIFO 010000 3833829Sbostic #endif 3933829Sbostic 4033828Sbostic #define EQ(x,y) (strcmp(x,y)==0) 4133828Sbostic 4233828Sbostic /* MKSHORT: for VAX, Interdata, ... */ 4333828Sbostic /* Take a 4-byte long, lv, and turn it */ 4433828Sbostic /* into an array of two 2-byte shorts, v*/ 4533828Sbostic #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];} 4633828Sbostic 4733828Sbostic #define MAGIC 070707 /* cpio magic number */ 4833829Sbostic #define BSMAGIC 0143561 /* byte-swapped cpio magic number */ 4933828Sbostic #define IN 'i' /* copy in */ 5033828Sbostic #define OUT 'o' /* copy out */ 5133828Sbostic #define PASS 'p' /* direct copy */ 5233828Sbostic #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */ 5333828Sbostic #define LINKS 500 /* no. of links allocated per bunch */ 5433828Sbostic #define CHARS 76 /* ASCII header size minus filename field */ 5533828Sbostic #define BUFSIZE 512 /* In u370, can't use BUFSIZ or BSIZE */ 5633828Sbostic #define CPIOBSZ 4096 /* file read/write */ 5733828Sbostic #define MK_USHORT(a) (a & 00000177777) /* Make unsigned shorts for portable */ 5833828Sbostic /* header. Hardware may only know */ 5933828Sbostic /* integer operations and sign extend */ 6033828Sbostic /* the large unsigned short resulting */ 6133828Sbostic /* in 8 rather than 6 octal char in */ 6233828Sbostic /* the header. */ 6333828Sbostic 6433828Sbostic static struct stat Statb, Xstatb; 6533828Sbostic 6633828Sbostic /* Cpio header format */ 6733828Sbostic static struct header { 6833828Sbostic short h_magic; 6933828Sbostic short h_dev; 7033828Sbostic ushort h_ino; 7133828Sbostic ushort h_mode, 7233828Sbostic h_uid, 7333828Sbostic h_gid; 7433828Sbostic short h_nlink; 7533828Sbostic short h_rdev; 7633828Sbostic short h_mtime[2], 7733828Sbostic h_namesize, 7833828Sbostic h_filesize[2]; 7933828Sbostic char h_name[256]; 8033828Sbostic } Hdr; 8133828Sbostic 8233829Sbostic char Symlbuf[MAXPATHLEN + 1]; /* target of symbolic link */ 8333828Sbostic static unsigned Bufsize = BUFSIZE; /* default record size */ 8433828Sbostic static char Buf[CPIOBSZ], *Cbuf; 8533828Sbostic static char *Cp; 8633828Sbostic 8733828Sbostic 8833828Sbostic static 8933828Sbostic short Option, 9033828Sbostic Dir, 9133828Sbostic Uncond, 9233828Sbostic PassLink, 9333828Sbostic Rename, 9433828Sbostic Toc, 9533828Sbostic Verbose, 9633828Sbostic Mod_time, 9733828Sbostic Acc_time, 9833828Sbostic Cflag, 9933828Sbostic fflag, 10033828Sbostic Swap, 10133828Sbostic byteswap, 10233828Sbostic halfswap; 10333828Sbostic 10433828Sbostic static 10533828Sbostic int Ifile, 10633828Sbostic Ofile, 10733828Sbostic Input = 0, 10833828Sbostic Output = 1; 10933828Sbostic /* sBlocks: short Blocks. Cumulative character */ 11033828Sbostic /* count for short reads in bread(). Encountered */ 11133828Sbostic /* with communication lines and pipes as in: */ 11233828Sbostic /* split -100 cpio_archive; cat xa* | cpio -icd */ 11333828Sbostic static 11433828Sbostic long sBlocks, 11533828Sbostic Blocks, 11633828Sbostic Longfile, 11733828Sbostic Longtime; 11833828Sbostic 11933828Sbostic static 12033828Sbostic char Fullname[256], 12133828Sbostic Name[256]; 12233828Sbostic static 12333828Sbostic int Pathend; 12433828Sbostic static 12533828Sbostic char *swfile; 12633828Sbostic static 12733828Sbostic char *eommsg = "Change to part %d and press RETURN key. [q] "; 12833828Sbostic 12933828Sbostic static 13033828Sbostic FILE *Rtty, 13133828Sbostic *Wtty; 13233828Sbostic static 133*37871Sbostic char ttyname[] = _PATH_TTY; 13433828Sbostic 13533828Sbostic static 13633828Sbostic char **Pattern = 0; 13733828Sbostic static 13833828Sbostic char Chdr[500]; 13933828Sbostic static 14033828Sbostic short Dev; 14133828Sbostic ushort Uid, 14233828Sbostic A_directory, 14333828Sbostic A_special, 14433829Sbostic A_symlink, 14533828Sbostic Filetype = S_IFMT; 14633828Sbostic 14733828Sbostic extern errno; 14833828Sbostic extern void exit(); 14933828Sbostic char *malloc(); 15033828Sbostic FILE *popen(); 15133828Sbostic 15233829Sbostic static char *smemcpy(); 15333829Sbostic 15433828Sbostic static 15533828Sbostic union { 15633828Sbostic long l; 15733828Sbostic short s[2]; 15833828Sbostic char c[4]; 15933828Sbostic } U; 16033828Sbostic 16133828Sbostic /* for VAX, Interdata, ... */ 16233828Sbostic static 16333828Sbostic long mklong(v) 16433828Sbostic short v[]; 16533828Sbostic { 16633828Sbostic U.l = 1; 16733828Sbostic if(U.c[0]) 16833828Sbostic U.s[0] = v[1], U.s[1] = v[0]; 16933828Sbostic else 17033828Sbostic U.s[0] = v[0], U.s[1] = v[1]; 17133828Sbostic return U.l; 17233828Sbostic } 17333828Sbostic 17433828Sbostic main(argc, argv) 17533828Sbostic char **argv; 17633828Sbostic { 17733828Sbostic register ct; 17833828Sbostic long filesz; 17933829Sbostic int symlsz; 18033828Sbostic register char *fullp; 18133828Sbostic register i; 18233828Sbostic int ans; 18333829Sbostic register char *symlinkp; 18433828Sbostic short select; /* set when files are selected */ 18533828Sbostic extern char *optarg; 18633828Sbostic extern int optind; 18733828Sbostic 18833829Sbostic signal(SIGSYS, SIG_IGN); 18933829Sbostic if(argc <= 1 || *argv[1] != '-') 19033828Sbostic usage(); 19133828Sbostic Uid = getuid(); 19233828Sbostic 19333829Sbostic while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvM:6eI:O:")) != EOF ) { 19433828Sbostic 19533828Sbostic switch( ans ) { 19633828Sbostic case 'a': /* reset access time */ 19733828Sbostic Acc_time++; 19833828Sbostic break; 19933828Sbostic case 'B': /* change record size to 5120 bytes */ 20033828Sbostic Bufsize = 5120; 20133828Sbostic break; 20233828Sbostic case 'C': /* reset buffer size to arbitrary valu 20333828Sbostic */ 20433828Sbostic Bufsize = atoi( optarg ); 20533829Sbostic if( Bufsize == 0 ) { 20633829Sbostic fperr("Illegal argument to -%c, '%s'", 20733828Sbostic ans, optarg ); 20833829Sbostic exit(2); 20933829Sbostic } 21033828Sbostic break; 21133828Sbostic case 'i': 21233828Sbostic Option = IN; 21333828Sbostic break; 21433828Sbostic case 'f': /* copy files not matched by patterns */ 21533828Sbostic fflag++; 21633828Sbostic break; 21733828Sbostic case 'o': 21833828Sbostic Option = OUT; 21933828Sbostic break; 22033828Sbostic case 'p': 22133828Sbostic Option = PASS; 22233828Sbostic break; 22333828Sbostic case 'c': /* ASCII header */ 22433828Sbostic Cflag++; 22533828Sbostic break; 22633828Sbostic case 'd': /* create directories when needed */ 22733828Sbostic Dir++; 22833828Sbostic break; 22933828Sbostic case 'l': /* link files, when necessary */ 23033828Sbostic PassLink++; 23133828Sbostic break; 23233828Sbostic case 'm': /* retain mod time */ 23333828Sbostic Mod_time++; 23433828Sbostic break; 23533828Sbostic case 'r': /* rename files interactively */ 23633828Sbostic Rename++; 23733828Sbostic Rtty = fopen(ttyname, "r"); 23833828Sbostic Wtty = fopen(ttyname, "w"); 23933828Sbostic if(Rtty==NULL || Wtty==NULL) { 24033829Sbostic fperrno("Cannot rename (%s missing)", 24133828Sbostic ttyname ); 24233829Sbostic exit(2); 24333828Sbostic } 24433828Sbostic break; 24533828Sbostic case 'S': /* swap halfwords */ 24633828Sbostic halfswap++; 24733828Sbostic Swap++; 24833828Sbostic break; 24933828Sbostic case 's': /* swap bytes */ 25033828Sbostic byteswap++; 25133828Sbostic Swap++; 25233828Sbostic break; 25333828Sbostic case 'b': /* swap both bytes and halfwords */ 25433829Sbostic halfswap++; 25533829Sbostic byteswap++; 25633828Sbostic Swap++; 25733828Sbostic break; 25833828Sbostic case 't': /* table of contents */ 25933828Sbostic Toc++; 26033828Sbostic break; 26133828Sbostic case 'u': /* copy unconditionally */ 26233828Sbostic Uncond++; 26333828Sbostic break; 26433828Sbostic case 'v': /* verbose - print out file names */ 26533829Sbostic Verbose++; 26633828Sbostic break; 26733828Sbostic case 'M': /* alternate message for end-of-media */ 26833828Sbostic eommsg = optarg; 26933828Sbostic break; 27033828Sbostic case '6': /* for old, sixth-edition files */ 27133828Sbostic Filetype = 060000; 27233828Sbostic break; 27333828Sbostic case 'I': 27433828Sbostic chkswfile( swfile, ans, Option ); 27533829Sbostic if( (i = open( optarg, O_RDONLY ) ) < 0) { 27633829Sbostic fperrno("Cannot open <%s> for input", optarg); 27733829Sbostic exit(2); 27833829Sbostic } 27933829Sbostic if( dup2(i, Input ) < 0 ) { 28033829Sbostic fperrno("Cannot dup to standard input"); 28133829Sbostic exit(2); 28233829Sbostic } 28333828Sbostic swfile = optarg; 28433828Sbostic break; 28533828Sbostic case 'O': 28633828Sbostic chkswfile( swfile, ans, Option ); 28733829Sbostic if( (i = open( optarg, O_WRONLY | O_CREAT | O_TRUNC, 28833829Sbostic 0666 ) ) < 0) { 28933829Sbostic fperrno("Cannot open <%s> for output", optarg); 29033829Sbostic exit(2); 29133829Sbostic } 29233829Sbostic if( dup2(i, Output ) < 0 ) { 29333829Sbostic fperrno("Cannot dup to standard output"); 29433829Sbostic exit(2); 29533829Sbostic } 29633828Sbostic swfile = optarg; 29733828Sbostic break; 29833828Sbostic default: 29933828Sbostic usage(); 30033828Sbostic } 30133828Sbostic } 30233828Sbostic if(!Option) { 30333829Sbostic (void) fprintf(stderr, 30433829Sbostic "Options must include one of -o, -i, or -p\n"); 30533829Sbostic exit(2); 30633828Sbostic } 30733828Sbostic 30833828Sbostic if(Option == PASS) { 30933828Sbostic if(Rename) { 31033829Sbostic (void) fprintf(stderr, 31133829Sbostic "Pass and Rename cannot be used together\n"); 31233829Sbostic exit(2); 31333828Sbostic } 31433828Sbostic if( Bufsize != BUFSIZE ) { 31533828Sbostic fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n"); 31633828Sbostic Bufsize = BUFSIZE; 31733828Sbostic } 31833828Sbostic 31933828Sbostic }else { 32033829Sbostic Cp = Cbuf = (char *)malloc(Bufsize); 32133829Sbostic if(Cp == NULL) { 32233829Sbostic perror("cpio"); 32333829Sbostic exit(2); 32433829Sbostic } 32533828Sbostic } 32633828Sbostic argc -= optind; 32733828Sbostic argv += optind; 32833828Sbostic 32933828Sbostic switch(Option) { 33033828Sbostic case OUT: 33133828Sbostic if(argc != 0) 33233828Sbostic usage(); 33333828Sbostic /* get filename, copy header and file out */ 33433828Sbostic while(getname()) { 33533828Sbostic if( mklong(Hdr.h_filesize) == 0L) { 33633828Sbostic if( Cflag ) 33733828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 33833828Sbostic else 33933828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 34033828Sbostic if(Verbose) 34133829Sbostic (void) fprintf(stderr, "%s\n", 34233829Sbostic Hdr.h_name); 34333828Sbostic continue; 34433829Sbostic } else if( A_symlink ) { 34533829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 34633829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 34733829Sbostic fperrno("Cannot read symbolic link <%s>", 34833829Sbostic Hdr.h_name); 34933829Sbostic continue; 35033829Sbostic } 35133829Sbostic Symlbuf[symlsz] = '\0'; 35233829Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 35333829Sbostic bwrite(Symlbuf, symlsz); 35433829Sbostic if(Verbose) 35533829Sbostic (void) fprintf(stderr, "%s\n", 35633829Sbostic Hdr.h_name); 35733829Sbostic continue; 35833828Sbostic } 35933828Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) { 36033829Sbostic fperrno("Cannot open <%s>", Hdr.h_name); 36133828Sbostic continue; 36233828Sbostic } 36333828Sbostic if ( Cflag ) 36433828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize); 36533828Sbostic else 36633828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 36733828Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 36833828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 36933828Sbostic if(read(Ifile, Buf, ct) < 0) { 37033829Sbostic fperrno("Cannot read %s", Hdr.h_name); 37133828Sbostic continue; 37233828Sbostic } 37333828Sbostic bwrite(Buf,ct); 37433828Sbostic } 37533828Sbostic close(Ifile); 37633829Sbostic if(Acc_time) { 37733829Sbostic struct utimbuf utb; 37833829Sbostic 37933829Sbostic utb.actime = Statb.st_atime; 38033829Sbostic utb.modtime = Statb.st_mtime; 38133829Sbostic (void)utime(Hdr.h_name, &utb); 38233829Sbostic } 38333828Sbostic if(Verbose) 38433829Sbostic (void) fprintf(stderr, "%s\n", Hdr.h_name); 38533828Sbostic } 38633828Sbostic 38733828Sbostic /* copy trailer, after all files have been copied */ 38833828Sbostic strcpy(Hdr.h_name, "TRAILER!!!"); 38933828Sbostic Hdr.h_magic = MAGIC; 39033828Sbostic MKSHORT(Hdr.h_filesize, 0L); 39133828Sbostic Hdr.h_namesize = strlen("TRAILER!!!") + 1; 39233828Sbostic if ( Cflag ) { 39333828Sbostic bintochar(0L); 39433828Sbostic bwrite(Chdr, CHARS+Hdr.h_namesize); 39533828Sbostic } 39633828Sbostic else 39733828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); 39833828Sbostic bwrite(Cbuf, Bufsize); 39933828Sbostic break; 40033828Sbostic 40133828Sbostic case IN: 40233828Sbostic if(argc > 0 ) { /* save patterns, if any */ 40333828Sbostic Pattern = argv; 40433828Sbostic } 40533828Sbostic pwd(); 40633828Sbostic chkhdr(); 40733828Sbostic while(gethdr()) { 40833829Sbostic if (A_symlink) { 40933829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 41033829Sbostic bread(Symlbuf, symlsz); 41133829Sbostic Symlbuf[symlsz] = '\0'; 41233830Sbostic if( ckname(Hdr.h_name) && !Toc) 41333829Sbostic (void)openout(Hdr.h_name, Symlbuf); 41433829Sbostic } else { 41533829Sbostic if( (select = ckname(Hdr.h_name)) && !Toc ) 41633829Sbostic Ofile = openout(Hdr.h_name, (char *)0); 41733829Sbostic else 41833829Sbostic Ofile = 0; 41933829Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ 42033829Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 42133829Sbostic bread(Buf, ct); 42233829Sbostic if(Ofile) { 42333829Sbostic if(Swap) 42433829Sbostic swap(Buf,ct,byteswap,halfswap); 42533829Sbostic if(write(Ofile, Buf, ct) < 0) { 42633829Sbostic fperrno("Cannot write %s", Hdr.h_name); 42733829Sbostic continue; 42833829Sbostic } 42933828Sbostic } 43033828Sbostic } 43133829Sbostic if( Ofile ) { 43233829Sbostic (void) close(Ofile); 43333829Sbostic if(chmod(Hdr.h_name, Hdr.h_mode) < 0) 43433829Sbostic fperrno("Cannot change mode of <%s>", 43533829Sbostic Hdr.h_name); 43633829Sbostic set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 43733829Sbostic } 43833828Sbostic } 43933828Sbostic if(select) { 44033828Sbostic if(Verbose) 44133828Sbostic if(Toc) 44233828Sbostic pentry(Hdr.h_name); 44333828Sbostic else 44433829Sbostic puts(Hdr.h_name); 44533828Sbostic else if(Toc) 44633828Sbostic puts(Hdr.h_name); 44733828Sbostic } 44833828Sbostic } 44933828Sbostic break; 45033828Sbostic 45133828Sbostic case PASS: /* move files around */ 45233828Sbostic if(argc != 1) 45333828Sbostic usage(); 45433828Sbostic if(access(argv[0], 2) == -1) { 45533829Sbostic (void) fperrno("Cannot write in <%s>", argv[0]); 45633829Sbostic exit(2); 45733828Sbostic } 45833828Sbostic strcpy(Fullname, argv[0]); /* destination directory */ 45933829Sbostic if(stat(Fullname, &Xstatb) < 0) { 46033829Sbostic fperrno("Cannot stat <%s>", Fullname); 46133829Sbostic exit(2); 46233829Sbostic } 46333829Sbostic if((Xstatb.st_mode&S_IFMT) != S_IFDIR) { 46433829Sbostic (void) fprintf(stderr, "<%s> is not a directory", 46533829Sbostic Fullname); 46633829Sbostic exit(2); 46733829Sbostic } 46833828Sbostic Dev = Xstatb.st_dev; 46933828Sbostic if( Fullname[ strlen(Fullname) - 1 ] != '/' ) 47033828Sbostic strcat(Fullname, "/"); 47133828Sbostic fullp = Fullname + strlen(Fullname); 47233828Sbostic 47333828Sbostic while(getname()) { 47433828Sbostic if (A_directory && !Dir) 47533829Sbostic fperr("Use `-d' option to copy <%s>", 47633828Sbostic Hdr.h_name); 47733828Sbostic if(!ckname(Hdr.h_name)) 47833828Sbostic continue; 47933828Sbostic i = 0; 48033828Sbostic while(Hdr.h_name[i] == '/') 48133828Sbostic i++; 48233828Sbostic strcpy(fullp, &(Hdr.h_name[i])); 48333828Sbostic 48433828Sbostic if( PassLink && !A_directory && Dev == Statb.st_dev ) { 48533828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 48633828Sbostic switch(errno) { 48733828Sbostic case ENOENT: 48833828Sbostic if(missdir(Fullname) != 0) { 48933829Sbostic fperrno("Cannot create directory for <%s>", 49033829Sbostic Fullname); 49133828Sbostic continue; 49233828Sbostic } 49333828Sbostic break; 49433828Sbostic case EEXIST: 49533828Sbostic if(unlink(Fullname) < 0) { 49633829Sbostic fperrno("Cannot unlink <%s>", 49733829Sbostic Fullname); 49833828Sbostic continue; 49933828Sbostic } 50033828Sbostic break; 50133828Sbostic default: 50233829Sbostic fperrno("Cannot link <%s> to <%s>", 50333829Sbostic Hdr.h_name, Fullname); 50433828Sbostic continue; 50533828Sbostic } 50633828Sbostic if(link(Hdr.h_name, Fullname) < 0) { 50733829Sbostic fperrno("Cannot link <%s> to <%s>", 50833829Sbostic Hdr.h_name, Fullname); 50933828Sbostic continue; 51033828Sbostic } 51133828Sbostic } 51233828Sbostic 51333828Sbostic goto ckverbose; 51433828Sbostic } 51533829Sbostic if( A_symlink ) { 51633829Sbostic symlsz = (int) mklong(Hdr.h_filesize); 51733829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) { 51833829Sbostic fperrno("Cannot read symbolic link <%s>", 51933829Sbostic Hdr.h_name); 52033828Sbostic continue; 52133829Sbostic } 52233829Sbostic Symlbuf[symlsz] = '\0'; 52333829Sbostic if(!openout(Fullname, Symlbuf)) 52433829Sbostic continue; 52533829Sbostic Blocks += ((symlsz + (BUFSIZE - 1)) / BUFSIZE); 52633829Sbostic if(Verbose) 52733829Sbostic puts(Fullname); 52833829Sbostic continue; 52933829Sbostic } 53033829Sbostic if(!(Ofile = openout(Fullname, (char *)0))) 53133829Sbostic continue; 53233829Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) { 53333829Sbostic fperrno("Cannot open <%s>", Hdr.h_name); 53433828Sbostic close(Ofile); 53533828Sbostic continue; 53633828Sbostic } 53733828Sbostic filesz = Statb.st_size; 53833828Sbostic for(; filesz > 0; filesz -= CPIOBSZ) { 53933828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz; 54033828Sbostic if(read(Ifile, Buf, ct) < 0) { 54133829Sbostic fperrno("Cannot read %s", Hdr.h_name); 54233828Sbostic break; 54333828Sbostic } 54433829Sbostic if(write(Ofile, Buf, ct) < 0) { 54533829Sbostic fperrno("Cannot write %s", Hdr.h_name); 54633829Sbostic break; 54733829Sbostic } 54833829Sbostic /* Removed u370 ifdef which caused cpio */ 54933829Sbostic /* to report blocks in terms of 4096 bytes. */ 55033828Sbostic 55133828Sbostic Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE); 55233828Sbostic } 55333828Sbostic close(Ifile); 55433829Sbostic if(Acc_time) { 55533829Sbostic struct utimbuf utb; 55633829Sbostic 55733829Sbostic utb.actime = Statb.st_atime; 55833829Sbostic utb.modtime = Statb.st_mtime; 55933829Sbostic (void)utime(Hdr.h_name, &utb); 56033829Sbostic } 56133828Sbostic if(Ofile) { 56233828Sbostic close(Ofile); 56333829Sbostic if(chmod(Fullname, Hdr.h_mode) < 0) 56433829Sbostic fperrno("Cannot change mode of <%s>", 56533829Sbostic Fullname); 56633828Sbostic set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime)); 56733828Sbostic ckverbose: 56833828Sbostic if(Verbose) 56933829Sbostic puts(Fullname); 57033828Sbostic } 57133828Sbostic } 57233828Sbostic } 57333828Sbostic /* print number of blocks actually copied */ 57433828Sbostic Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE); 57533829Sbostic (void) fprintf(stderr, "%ld blocks\n", Blocks * (Bufsize>>9)); 57633828Sbostic exit(0); 57733828Sbostic } 57833828Sbostic 57933828Sbostic static 58033828Sbostic usage() 58133828Sbostic { 58233829Sbostic (void) fprintf("Usage: %s\n %s\n %s\n %s\n %s\n", 58333829Sbostic "cpio -o[acvB] <name-list >collection", 58433829Sbostic "cpio -o[acvB] -Ocollection <name-list", 58533829Sbostic "cpio -i[cdmrstuvfB6] [ pattern ... ] <collection", 58633829Sbostic "cpio -i[cdmrstuvfB6] -Icollection [ pattern ... ]", 58733829Sbostic "cpio -p[adlmruv] directory <name-list"); 58833828Sbostic } 58933828Sbostic 59033828Sbostic static 59133828Sbostic chkswfile( sp, c, option ) 59233828Sbostic char *sp; 59333828Sbostic char c; 59433828Sbostic short option; 59533828Sbostic { 59633829Sbostic if( !option ) { 59733829Sbostic fperr( "-%c must be specified before -%c option", 59833828Sbostic c == 'I' ? 'i' : 'o', c ); 59933829Sbostic exit(2); 60033829Sbostic } 60133829Sbostic if( (c == 'I' && option != IN) || (c == 'O' && option != OUT) ) { 60233829Sbostic fperr( "-%c option not permitted with -%c option", c, 60333828Sbostic option ); 60433829Sbostic exit(2); 60533829Sbostic } 60633828Sbostic if( !sp ) 60733828Sbostic return; 60833829Sbostic fperr("No more than one -I or -O flag permitted"); 60933829Sbostic exit(2); 61033828Sbostic } 61133828Sbostic 61233828Sbostic static 61333828Sbostic getname() /* get file name, get info for header */ 61433828Sbostic { 61533828Sbostic register char *namep = Name; 61633828Sbostic register ushort ftype; 61733829Sbostic struct stat Lstatb; 61833828Sbostic long tlong; 61933828Sbostic 62033828Sbostic for(;;) { 62133828Sbostic if(gets(namep) == NULL) 62233828Sbostic return 0; 62333828Sbostic while(*namep == '.' && namep[1] == '/') { 62433828Sbostic namep++; 62533828Sbostic while(*namep == '/') namep++; 62633828Sbostic } 62733828Sbostic strcpy(Hdr.h_name, namep); 62833829Sbostic if(lstat(namep, &Statb) < 0) { 62933829Sbostic fperrno("Cannot stat <%s>", Hdr.h_name); 63033828Sbostic continue; 63133828Sbostic } 63233828Sbostic ftype = Statb.st_mode & Filetype; 63333828Sbostic A_directory = (ftype == S_IFDIR); 63433828Sbostic A_special = (ftype == S_IFBLK) 63533828Sbostic || (ftype == S_IFCHR) 63633828Sbostic || (ftype == S_IFIFO); 63733829Sbostic A_symlink = (ftype == S_IFLNK); 63833828Sbostic Hdr.h_magic = MAGIC; 63933828Sbostic Hdr.h_namesize = strlen(Hdr.h_name) + 1; 64033828Sbostic Hdr.h_uid = Statb.st_uid; 64133828Sbostic Hdr.h_gid = Statb.st_gid; 64233828Sbostic Hdr.h_dev = Statb.st_dev; 64333828Sbostic Hdr.h_ino = Statb.st_ino; 64433828Sbostic Hdr.h_mode = Statb.st_mode; 64533828Sbostic MKSHORT(Hdr.h_mtime, Statb.st_mtime); 64633828Sbostic Hdr.h_nlink = Statb.st_nlink; 64733829Sbostic tlong = ((Hdr.h_mode&S_IFMT) == S_IFREG || 64833829Sbostic (Hdr.h_mode&S_IFMT) == S_IFLNK)? Statb.st_size: 0L; 64933828Sbostic MKSHORT(Hdr.h_filesize, tlong); 65033828Sbostic Hdr.h_rdev = Statb.st_rdev; 65133828Sbostic if( Cflag ) 65233828Sbostic bintochar(tlong); 65333828Sbostic return 1; 65433828Sbostic } 65533828Sbostic } 65633828Sbostic 65733828Sbostic static 65833828Sbostic bintochar(t) /* ASCII header write */ 65933828Sbostic long t; 66033828Sbostic { 66133828Sbostic sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s", 66233828Sbostic MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid, 66333828Sbostic Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev), 66433828Sbostic Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name); 66533828Sbostic } 66633828Sbostic 66733828Sbostic static 66833828Sbostic chartobin() /* ASCII header read */ 66933828Sbostic { 67033828Sbostic sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo", 67133828Sbostic &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid, 67233828Sbostic &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime, 67333828Sbostic &Hdr.h_namesize, &Longfile); 67433828Sbostic MKSHORT(Hdr.h_filesize, Longfile); 67533828Sbostic MKSHORT(Hdr.h_mtime, Longtime); 67633828Sbostic } 67733828Sbostic 67833828Sbostic 67933828Sbostic /* Check the header for the magic number. Switch modes automatically to 68033828Sbostic match the type of header found. 68133828Sbostic */ 68233828Sbostic static 68333828Sbostic chkhdr() 68433828Sbostic { 68533828Sbostic bread(Chdr, CHARS); 68633828Sbostic chartobin(); 68733828Sbostic if( Hdr.h_magic == MAGIC ) 68833828Sbostic Cflag = 1; 68933828Sbostic else { 69033828Sbostic breread(&Hdr.h_magic, sizeof Hdr.h_magic); 69133829Sbostic if( Hdr.h_magic == MAGIC || Hdr.h_magic == (short)BSMAGIC ) 69233828Sbostic Cflag = 0; 69333829Sbostic else { 69433829Sbostic fperr("This is not a cpio file. Bad magic number."); 69533829Sbostic exit(2); 69633829Sbostic } 69733828Sbostic } 69833828Sbostic breread(Chdr, 0); 69933828Sbostic } 70033828Sbostic 70133828Sbostic 70233828Sbostic static 70333828Sbostic gethdr() /* get file headers */ 70433828Sbostic { 70533828Sbostic register ushort ftype; 70633828Sbostic 70733828Sbostic if (Cflag) { 70833828Sbostic bread(Chdr, CHARS); 70933828Sbostic chartobin(); 71033828Sbostic } 71133828Sbostic else 71233828Sbostic bread(&Hdr, HDRSIZE); 71333828Sbostic 71433829Sbostic if(Hdr.h_magic == (short)BSMAGIC) 71533829Sbostic swap((char *)&Hdr, HDRSIZE, 1, 0); 71633829Sbostic else if( Hdr.h_magic != MAGIC ) { 71733829Sbostic fperr("Out of phase--get help"); 71833829Sbostic exit(2); 71933828Sbostic } 72033828Sbostic bread(Hdr.h_name, Hdr.h_namesize); 72133828Sbostic if(EQ(Hdr.h_name, "TRAILER!!!")) 72233828Sbostic return 0; 72333828Sbostic ftype = Hdr.h_mode & Filetype; 72433828Sbostic A_directory = (ftype == S_IFDIR); 72533828Sbostic A_special = (ftype == S_IFBLK) 72633828Sbostic || (ftype == S_IFCHR) 72733828Sbostic || (ftype == S_IFIFO); 72833829Sbostic A_symlink = (ftype == S_IFLNK); 72933828Sbostic return 1; 73033828Sbostic } 73133828Sbostic 73233828Sbostic static 73333828Sbostic ckname(namep) /* check filenames with patterns given on cmd line */ 73433828Sbostic register char *namep; 73533828Sbostic { 73633828Sbostic char buf[sizeof Hdr.h_name]; 73733828Sbostic 73833828Sbostic if(fflag ^ !nmatch(namep, Pattern)) { 73933828Sbostic return 0; 74033828Sbostic } 74133828Sbostic if(Rename && !A_directory) { /* rename interactively */ 74233828Sbostic fprintf(Wtty, "Rename <%s>\n", namep); 74333828Sbostic fflush(Wtty); 74433828Sbostic fgets(buf, sizeof buf, Rtty); 74533828Sbostic if(feof(Rtty)) 74633828Sbostic exit(2); 74733828Sbostic buf[strlen(buf) - 1] = '\0'; 74833828Sbostic if(EQ(buf, "")) { 74933828Sbostic strcpy(namep,buf); 75033828Sbostic printf("Skipped\n"); 75133828Sbostic return 0; 75233828Sbostic } 75333828Sbostic else if(EQ(buf, ".")) 75433828Sbostic printf("Same name\n"); 75533828Sbostic else 75633828Sbostic strcpy(namep,buf); 75733828Sbostic } 75833828Sbostic return 1; 75933828Sbostic } 76033828Sbostic 76133828Sbostic static 76233829Sbostic openout(namep, symlname) /* open files for writing, set all necessary info */ 76333828Sbostic register char *namep; 76433829Sbostic char *symlname; 76533828Sbostic { 76633828Sbostic register f; 76733828Sbostic register char *np; 76833828Sbostic int ans; 76933828Sbostic 77033828Sbostic if(!strncmp(namep, "./", 2)) 77133828Sbostic namep += 2; 77233828Sbostic np = namep; 77333828Sbostic if(A_directory) { 77433828Sbostic if( !Dir || Rename || EQ(namep, ".") || EQ(namep, "..") ) 77533828Sbostic /* do not consider . or .. files */ 77633828Sbostic return 0; 77733828Sbostic if(stat(namep, &Xstatb) == -1) { 77833828Sbostic 77933828Sbostic /* try creating (only twice) */ 78033828Sbostic ans = 0; 78133828Sbostic do { 78233829Sbostic if(mkdir(namep, Hdr.h_mode) != 0) { 78333828Sbostic ans += 1; 78433828Sbostic }else { 78533828Sbostic ans = 0; 78633828Sbostic break; 78733828Sbostic } 78833828Sbostic }while(ans < 2 && missdir(namep) == 0); 78933828Sbostic if(ans == 1) { 79033828Sbostic fperrno("Cannot create directory for <%s>", 79133828Sbostic namep); 79233828Sbostic return(0); 79333828Sbostic }else if(ans == 2) { 79433828Sbostic fperrno("Cannot create directory <%s>", namep); 79533828Sbostic return(0); 79633828Sbostic } 79733828Sbostic } 79833828Sbostic 79933828Sbostic ret: 80033829Sbostic if(chmod(namep, Hdr.h_mode) < 0) 80133829Sbostic fperrno("Cannot change mode of <%s>", namep); 80233828Sbostic if(Uid == 0) 80333829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 80433829Sbostic fperrno("Cannot change ownership of <%s>", 80533829Sbostic namep); 80633828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 80733828Sbostic return 0; 80833828Sbostic } 80933828Sbostic if(Hdr.h_nlink > 1) 81033828Sbostic if(!postml(namep, np)) 81133828Sbostic return 0; 81233829Sbostic if(lstat(namep, &Xstatb) == 0) { 81333828Sbostic if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) { 81433828Sbostic if(unlink(namep) < 0) { 81533828Sbostic fperrno("cannot unlink current <%s>", namep); 81633828Sbostic } 81733828Sbostic } 81833828Sbostic if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) { 81933828Sbostic /* There's a newer or same aged version of file on destination */ 82033829Sbostic fperr("current <%s> newer or same age", np); 82133828Sbostic return 0; 82233828Sbostic } 82333828Sbostic } 82433828Sbostic if( Option == PASS 82533828Sbostic && Hdr.h_ino == Xstatb.st_ino 82633828Sbostic && Hdr.h_dev == Xstatb.st_dev) { 82733829Sbostic fperr("Attempt to pass file to self!"); 82833829Sbostic exit(2); 82933828Sbostic } 83033829Sbostic if(A_symlink) { 83133829Sbostic /* try symlinking (only twice) */ 83233829Sbostic ans = 0; 83333829Sbostic do { 83433829Sbostic if(symlink( 83533829Sbostic symlname, namep) < 0) { 83633829Sbostic ans += 1; 83733829Sbostic }else { 83833829Sbostic ans = 0; 83933829Sbostic break; 84033829Sbostic } 84133829Sbostic }while(ans < 2 && missdir(np) == 0); 84233829Sbostic if(ans == 1) { 84333829Sbostic fperrno("Cannot create directory for <%s>", namep); 84433829Sbostic return(0); 84533829Sbostic }else if(ans == 2) { 84633829Sbostic fperrno("Cannot symlink <%s> and <%s>", namep, symlname); 84733829Sbostic return(0); 84833829Sbostic } 84933829Sbostic 85033829Sbostic return 0; 85133829Sbostic } 85233828Sbostic if(A_special) { 85333828Sbostic if((Hdr.h_mode & Filetype) == S_IFIFO) 85433828Sbostic Hdr.h_rdev = 0; 85533828Sbostic 85633828Sbostic /* try creating (only twice) */ 85733828Sbostic ans = 0; 85833828Sbostic do { 85933828Sbostic if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) { 86033828Sbostic ans += 1; 86133828Sbostic }else { 86233828Sbostic ans = 0; 86333828Sbostic break; 86433828Sbostic } 86533828Sbostic }while(ans < 2 && missdir(np) == 0); 86633828Sbostic if(ans == 1) { 86733828Sbostic fperrno("Cannot create directory for <%s>", namep); 86833828Sbostic return(0); 86933828Sbostic }else if(ans == 2) { 87033828Sbostic fperrno("Cannot mknod <%s>", namep); 87133828Sbostic return(0); 87233828Sbostic } 87333828Sbostic 87433828Sbostic goto ret; 87533828Sbostic } 87633828Sbostic 87733828Sbostic /* try creating (only twice) */ 87833828Sbostic ans = 0; 87933828Sbostic do { 88033828Sbostic if((f = creat(namep, Hdr.h_mode)) < 0) { 88133828Sbostic ans += 1; 88233828Sbostic }else { 88333828Sbostic ans = 0; 88433828Sbostic break; 88533828Sbostic } 88633828Sbostic }while(ans < 2 && missdir(np) == 0); 88733828Sbostic if(ans == 1) { 88833828Sbostic fperrno("Cannot create directory for <%s>", namep); 88933828Sbostic return(0); 89033828Sbostic }else if(ans == 2) { 89133828Sbostic fperrno("Cannot create <%s>", namep); 89233828Sbostic return(0); 89333828Sbostic } 89433828Sbostic 89533828Sbostic if(Uid == 0) 89633829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) 89733829Sbostic fperrno("Cannot change ownership of <%s>", namep); 89833828Sbostic return f; 89933828Sbostic } 90033828Sbostic 90133828Sbostic 90233828Sbostic /* Shared by bread() and breread() 90333828Sbostic */ 90433828Sbostic static int nleft = 0; /* unread chars left in Cbuf */ 90533828Sbostic static char *ip; /* pointer to next char to be read from Cbuf */ 90633828Sbostic 90733828Sbostic /* Reread the current buffer Cbuf. 90833828Sbostic A character count, c, of 0 simply resets the pointer so next bread gets 90933828Sbostic the same data again. 91033828Sbostic */ 91133828Sbostic static 91233828Sbostic breread(b, c) 91333828Sbostic char *b; 91433828Sbostic int c; 91533828Sbostic { 91633828Sbostic ip = Cbuf; 91733828Sbostic if( nleft ) 91833828Sbostic nleft = Bufsize; 91933828Sbostic if( !c ) 92033828Sbostic return; 92133828Sbostic bread(b, c); 92233828Sbostic } 92333828Sbostic 92433828Sbostic static 92533828Sbostic bread(b, c) 92633828Sbostic register char *b; 92733828Sbostic register int c; 92833828Sbostic { 92933828Sbostic register int rv; 93033828Sbostic register char *p = ip; 93133828Sbostic 93233828Sbostic if( !Cflag ) { 93333828Sbostic /* round c up to an even number */ 93433828Sbostic c = (c+1)/2; 93533828Sbostic c *= 2; 93633828Sbostic } 93733828Sbostic while( c ) { 93833828Sbostic if( nleft == 0 ) { 93933828Sbostic while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) { 94033828Sbostic Input = chgreel(0, Input, rv); 94133828Sbostic } 94233828Sbostic if( rv == Bufsize ) { 94333828Sbostic nleft = Bufsize; 94433828Sbostic p = Cbuf; 94533828Sbostic ++Blocks; 94633828Sbostic } 94733829Sbostic else if( rv == -1 ) { 94833829Sbostic fperrno("Read error on archive"); 94933829Sbostic exit(2); 95033829Sbostic } 95133828Sbostic else if( rv < Bufsize ) { /* short read */ 95233828Sbostic smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv ); 95333828Sbostic nleft = rv; 95433828Sbostic p = &Cbuf[ Bufsize - rv ]; 95533828Sbostic sBlocks += rv; 95633828Sbostic } 95733828Sbostic } 95833828Sbostic if( nleft <= c ) { 95933828Sbostic memcpy( b, p, nleft ); 96033828Sbostic c -= nleft; 96133828Sbostic b += nleft; 96233828Sbostic p += nleft; 96333828Sbostic nleft = 0; 96433828Sbostic } 96533828Sbostic else { 96633828Sbostic memcpy( b, p, c ); 96733828Sbostic nleft -= c; 96833828Sbostic b += c; 96933828Sbostic p += c; 97033828Sbostic c = 0; 97133828Sbostic } 97233828Sbostic } 97333828Sbostic ip = p; 97433828Sbostic } 97533828Sbostic 97633828Sbostic 97733828Sbostic static 97833828Sbostic bwrite(rp, c) 97933828Sbostic register char *rp; 98033828Sbostic register c; 98133828Sbostic { 98233828Sbostic register char *cp = Cp; 98333828Sbostic static unsigned Ccnt = 0; 98433828Sbostic register unsigned Cleft; 98533828Sbostic register int rv; 98633828Sbostic 98733828Sbostic if( !Cflag ) { 98833828Sbostic /* round c up to an even number */ 98933828Sbostic c = (c+1)/2; 99033828Sbostic c *= 2; 99133828Sbostic } 99233828Sbostic while( c ) { 99333828Sbostic if( (Cleft = Bufsize - Ccnt) <= c ) { 99433828Sbostic memcpy( cp, rp, Cleft ); 99533828Sbostic rv = write(Output, Cbuf, Bufsize); 99633828Sbostic if( rv == 0 || ( rv == -1 && errno == ENXIO ) ) { 99733828Sbostic rv = eomchgreel(); 99833828Sbostic } 99933828Sbostic if( rv == Bufsize ) { 100033828Sbostic Ccnt = 0; 100133828Sbostic cp = Cbuf; 100233828Sbostic } 100333829Sbostic else if( rv == -1 ) { 100433829Sbostic fperrno("Write error on archive"); 100533829Sbostic exit(2); 100633829Sbostic } 100733828Sbostic else if( rv < Bufsize ) { 100833828Sbostic Output = chgreel(1, Output, 0); 100933828Sbostic smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv ); 101033828Sbostic Ccnt = Bufsize - rv; 101133828Sbostic cp = &Cbuf[ rv ]; 101233828Sbostic } 101333828Sbostic ++Blocks; 101433828Sbostic rp += Cleft; 101533828Sbostic c -= Cleft; 101633828Sbostic } 101733828Sbostic else { 101833828Sbostic memcpy( cp, rp, c ); 101933828Sbostic Ccnt += c; 102033828Sbostic cp += c; 102133828Sbostic rp += c; 102233828Sbostic c = 0; 102333828Sbostic } 102433828Sbostic } 102533828Sbostic Cp = cp; 102633828Sbostic } 102733828Sbostic 102833828Sbostic 102933828Sbostic static int reelcount = 1; /* used below and in chgreel() */ 103033828Sbostic 103133828Sbostic /* Change reel due to reaching end-of-media. 103233828Sbostic Keep trying to get a successful write before considering the 103333828Sbostic change-of-reel as successful. 103433828Sbostic */ 103533828Sbostic static 103633828Sbostic int 103733828Sbostic eomchgreel() 103833828Sbostic { 103933828Sbostic int rv; 104033828Sbostic 104133828Sbostic while( 1 ) { 104233828Sbostic Output = chgreel(1, Output, 0); 104333828Sbostic rv = write(Output, Cbuf, Bufsize); 104433828Sbostic if( rv == Bufsize ) 104533828Sbostic return rv; 104633829Sbostic if( rv == -1 ) 104733829Sbostic fperrno( "Unable to write this medium" ); 104833829Sbostic else 104933829Sbostic fperr( "Unable to write this medium: Premature EOF" ); 105033829Sbostic (void) fprintf(stderr, "Try again.\n"); 105133828Sbostic reelcount--; 105233828Sbostic } 105333828Sbostic /*NOTREACHED*/ 105433828Sbostic } 105533828Sbostic 105633828Sbostic 105733828Sbostic static 105833828Sbostic postml(namep, np) /* linking funtion: Postml() is called after */ 105933828Sbostic register char *namep, *np; /* namep is created. Postml() checks to see */ 106033828Sbostic { /* if namep should be linked to np. If so, */ 106133828Sbostic /* postml() removes the independent instance */ 106233828Sbostic register i; /* of namep and links namep to np. */ 106333828Sbostic static struct ml { 106433828Sbostic short m_dev; 106533828Sbostic ushort m_ino; 106633828Sbostic char m_name[2]; 106733828Sbostic } **ml = 0; 106833828Sbostic register struct ml *mlp; 106933828Sbostic static unsigned mlsize = 0; 107033828Sbostic static unsigned mlinks = 0; 107133828Sbostic char *lnamep; 107233828Sbostic int ans; 107333828Sbostic 107433828Sbostic if( !ml ) { 107533828Sbostic mlsize = LINKS; 107633829Sbostic ml = (struct ml **) malloc(mlsize * sizeof(struct ml)); 107733828Sbostic } 107833828Sbostic else if( mlinks == mlsize ) { 107933828Sbostic mlsize += LINKS; 108033829Sbostic ml = (struct ml **) realloc((char *) ml, 108133829Sbostic mlsize * sizeof(struct ml)); 108233828Sbostic } 108333829Sbostic if (ml == NULL) { 108433829Sbostic fperr("Out of memory for links"); 108533829Sbostic exit(2); 108633829Sbostic } 108733828Sbostic for(i = 0; i < mlinks; ++i) { 108833828Sbostic mlp = ml[i]; 108933828Sbostic if(mlp->m_ino==Hdr.h_ino && mlp->m_dev==Hdr.h_dev) { 109033828Sbostic if(Verbose) 109133829Sbostic printf("%s linked to %s\n", ml[i]->m_name, 109233829Sbostic np); 109333828Sbostic unlink(namep); 109433828Sbostic if(Option == IN && *(mlp->m_name) != '/') { 109533828Sbostic Fullname[Pathend] = '\0'; 109633828Sbostic strcat(Fullname, mlp->m_name); 109733828Sbostic lnamep = Fullname; 109833828Sbostic } 109933828Sbostic lnamep = mlp->m_name; 110033828Sbostic 110133828Sbostic /* try linking (only twice) */ 110233828Sbostic ans = 0; 110333828Sbostic do { 110433828Sbostic if(link(lnamep, namep) < 0) { 110533828Sbostic ans += 1; 110633828Sbostic }else { 110733828Sbostic ans = 0; 110833828Sbostic break; 110933828Sbostic } 111033828Sbostic }while(ans < 2 && missdir(np) == 0); 111133828Sbostic if(ans == 1) { 111233828Sbostic fperrno("Cannot create directory for <%s>", np); 111333828Sbostic return(0); 111433828Sbostic }else if(ans == 2) { 111533828Sbostic fperrno("Cannot link <%s> & <%s>", lnamep, np); 111633828Sbostic return(0); 111733828Sbostic } 111833828Sbostic 111933828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime)); 112033828Sbostic return 0; 112133828Sbostic } 112233828Sbostic } 112333829Sbostic if( !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) { 112433828Sbostic static int first=1; 112533828Sbostic 112633828Sbostic if(first) 112733829Sbostic fperr("Out of memory for links"); 112833828Sbostic first = 0; 112933828Sbostic return 1; 113033828Sbostic } 113133828Sbostic ml[mlinks]->m_dev = Hdr.h_dev; 113233828Sbostic ml[mlinks]->m_ino = Hdr.h_ino; 113333828Sbostic strcpy(ml[mlinks]->m_name, np); 113433828Sbostic ++mlinks; 113533828Sbostic return 1; 113633828Sbostic } 113733828Sbostic 113833828Sbostic static 113933828Sbostic pentry(namep) /* print verbose table of contents */ 114033828Sbostic register char *namep; 114133828Sbostic { 114233828Sbostic 114333828Sbostic static short lastid = -1; 114433828Sbostic #include <pwd.h> 114533828Sbostic static struct passwd *pw; 114633828Sbostic struct passwd *getpwuid(); 114733828Sbostic static char tbuf[32]; 114833828Sbostic char *ctime(); 114933828Sbostic 115033828Sbostic printf("%-7o", MK_USHORT(Hdr.h_mode)); 115133828Sbostic if(lastid == Hdr.h_uid) 115233828Sbostic printf("%-6s", pw->pw_name); 115333828Sbostic else { 115433828Sbostic setpwent(); 115533828Sbostic if(pw = getpwuid((int)Hdr.h_uid)) { 115633828Sbostic printf("%-6s", pw->pw_name); 115733828Sbostic lastid = Hdr.h_uid; 115833828Sbostic } else { 115933828Sbostic printf("%-6d", Hdr.h_uid); 116033828Sbostic lastid = -1; 116133828Sbostic } 116233828Sbostic } 116333828Sbostic printf("%7ld ", mklong(Hdr.h_filesize)); 116433828Sbostic U.l = mklong(Hdr.h_mtime); 116533828Sbostic strcpy(tbuf, ctime((long *)&U.l)); 116633828Sbostic tbuf[24] = '\0'; 116733829Sbostic printf(" %s %s", &tbuf[4], namep); 116833829Sbostic if (A_symlink) 116933829Sbostic printf(" -> %s", Symlbuf); 117033829Sbostic putchar('\n'); 117133828Sbostic } 117233828Sbostic 117333828Sbostic /* pattern matching functions */ 117433828Sbostic static 117533828Sbostic nmatch(s, pat) 117633828Sbostic char *s, **pat; 117733828Sbostic { 117833828Sbostic if( !pat ) 117933828Sbostic return 1; 118033828Sbostic while(*pat) { 118133828Sbostic if((**pat == '!' && !gmatch(s, *pat+1)) 118233828Sbostic || gmatch(s, *pat)) 118333828Sbostic return 1; 118433828Sbostic ++pat; 118533828Sbostic } 118633828Sbostic return 0; 118733828Sbostic } 118833828Sbostic 118933828Sbostic 119033828Sbostic static 119133828Sbostic gmatch(s, p) 119233828Sbostic register char *s, *p; 119333828Sbostic { 119433828Sbostic register int c; 119533828Sbostic register cc, ok, lc, scc; 119633828Sbostic 119733828Sbostic scc = *s; 119833828Sbostic lc = 077777; 119933828Sbostic switch (c = *p) { 120033828Sbostic 120133828Sbostic case '[': 120233828Sbostic ok = 0; 120333828Sbostic while (cc = *++p) { 120433828Sbostic switch (cc) { 120533828Sbostic 120633828Sbostic case ']': 120733828Sbostic if (ok) 120833828Sbostic return(gmatch(++s, ++p)); 120933828Sbostic else 121033828Sbostic return(0); 121133828Sbostic 121233828Sbostic case '-': 121333828Sbostic ok |= ((lc <= scc) && (scc <= (cc=p[1]))); 121433828Sbostic } 121533828Sbostic if (scc==(lc=cc)) ok++; 121633828Sbostic } 121733828Sbostic return(0); 121833828Sbostic 121933828Sbostic case '?': 122033828Sbostic caseq: 122133828Sbostic if(scc) return(gmatch(++s, ++p)); 122233828Sbostic return(0); 122333828Sbostic case '*': 122433828Sbostic return(umatch(s, ++p)); 122533828Sbostic case 0: 122633828Sbostic return(!scc); 122733828Sbostic } 122833828Sbostic if (c==scc) goto caseq; 122933828Sbostic return(0); 123033828Sbostic } 123133828Sbostic 123233828Sbostic 123333828Sbostic 123433828Sbostic static 123533828Sbostic umatch(s, p) 123633828Sbostic register char *s, *p; 123733828Sbostic { 123833828Sbostic if(*p==0) return(1); 123933828Sbostic while(*s) 124033828Sbostic if (gmatch(s++,p)) return(1); 124133828Sbostic return(0); 124233828Sbostic } 124333828Sbostic 124433829Sbostic swap(buf, bytecount, bytes, halfwords) /* swap halfwords, bytes or both */ 124533829Sbostic char *buf; 124633829Sbostic int bytecount; 124733829Sbostic int bytes, halfwords; 124833828Sbostic { 124933829Sbostic register int count; 125033829Sbostic int n, i; 125133828Sbostic 125233829Sbostic if(bytes) { 125333829Sbostic register union swpbytes { 125433829Sbostic short shortw; 125533829Sbostic char charv[2]; 125633829Sbostic } *pbuf; 125733829Sbostic register char c; 125833828Sbostic 125933829Sbostic count = bytecount; 126033829Sbostic pbuf = (union swpbytes *)buf; 126133829Sbostic if (count % sizeof(union swpbytes)) 126233829Sbostic pbuf->charv[count] = 0; 126333829Sbostic count = (count + (sizeof(union swpbytes) - 1)) / sizeof(union swpbytes); 126433829Sbostic while (count--) { 126533829Sbostic c = pbuf->charv[0]; 126633829Sbostic pbuf->charv[0] = pbuf->charv[1]; 126733829Sbostic pbuf->charv[1] = c; 126833829Sbostic ++pbuf; 126933828Sbostic } 127033828Sbostic } 127133829Sbostic if (halfwords) { 127233829Sbostic register union swphalf { 127333829Sbostic long longw; 127433829Sbostic short shortv[2]; 127533829Sbostic char charv[4]; 127633829Sbostic } *pbuf; 127733829Sbostic register short cc; 127833829Sbostic 127933829Sbostic count = bytecount; 128033829Sbostic pbuf = (union swphalf *)buf; 128133829Sbostic if (n = count % sizeof(union swphalf)) 128233829Sbostic if(bytes && n % 2) 128333829Sbostic for(i = count + 1; i <= count + (sizeof(union swphalf) - n); i++) 128433829Sbostic pbuf->charv[i] = 0; 128533829Sbostic else 128633829Sbostic for (i = count; i < count + (sizeof(union swphalf) - n); i++) 128733829Sbostic pbuf->charv[i] = 0; 128833829Sbostic count = (count + (sizeof(union swphalf) - 1)) / sizeof(union swphalf); 128933829Sbostic while (count--) { 129033828Sbostic cc = pbuf->shortv[0]; 129133828Sbostic pbuf->shortv[0] = pbuf->shortv[1]; 129233828Sbostic pbuf->shortv[1] = cc; 129333828Sbostic ++pbuf; 129433828Sbostic } 129533828Sbostic } 129633828Sbostic } 129733828Sbostic 129833828Sbostic 129933828Sbostic static 130033828Sbostic set_time(namep, atime, mtime) /* set access and modification times */ 130133828Sbostic register char *namep; 130233828Sbostic time_t atime, mtime; 130333828Sbostic { 130433829Sbostic static struct utimbuf timevec; 130533828Sbostic 130633828Sbostic if(!Mod_time) 130733828Sbostic return; 130833829Sbostic timevec.actime = atime; 130933829Sbostic timevec.modtime = mtime; 131033829Sbostic (void)utime(namep, &timevec); 131133828Sbostic } 131233828Sbostic 131333828Sbostic 131433828Sbostic 131533828Sbostic static 131633828Sbostic chgreel(x, fl, rv) 131733828Sbostic { 131833828Sbostic register f; 131933828Sbostic char str[BUFSIZ]; 132033828Sbostic struct stat statb; 132133828Sbostic 132233828Sbostic fstat(fl, &statb); 132333828Sbostic if((statb.st_mode&S_IFMT) != S_IFCHR) { 132433828Sbostic fperrno("Can't %s: ", x? "write output": "read input"); 132533828Sbostic exit(2); 132633828Sbostic } 132733828Sbostic if( rv == 0 || 132833828Sbostic ( rv == -1 && ( errno == ENOSPC || errno == ENXIO ) ) ) 132933829Sbostic fperr( "\007Reached end of medium on %s", 133033828Sbostic x? "output":"input" ); 133133828Sbostic else { 133233828Sbostic fperrno( "\007Encountered an error on %s", 133333828Sbostic x? "output":"input" ); 133433828Sbostic exit(2); 133533828Sbostic } 133633829Sbostic if( Rtty == NULL ) { 133733829Sbostic Rtty = fopen(ttyname, "r"); 133833829Sbostic if( Rtty == NULL ) { 133933829Sbostic fperrno("Cannot prompt (can't open %s)", ttyname); 134033829Sbostic exit(2); 134133829Sbostic } 134233829Sbostic } 134333828Sbostic close(fl); 134433828Sbostic reelcount++; 134533828Sbostic again: 134633828Sbostic if( swfile ) { 134733828Sbostic askagain: 134833828Sbostic fperr( eommsg, reelcount ); 134933828Sbostic fgets(str, sizeof str, Rtty); 135033828Sbostic switch( *str ) { 135133828Sbostic case '\n': 135233828Sbostic strcpy( str, swfile ); 135333828Sbostic break; 135433828Sbostic case 'q': 135533828Sbostic exit(2); 135633828Sbostic default: 135733828Sbostic goto askagain; 135833828Sbostic } 135933828Sbostic } 136033828Sbostic else { 136133829Sbostic fperr("If you want to go on, type device/file name when ready."); 136233828Sbostic fgets(str, sizeof str, Rtty); 136333828Sbostic str[strlen(str) - 1] = '\0'; 136433828Sbostic if(!*str) 136533828Sbostic exit(2); 136633828Sbostic } 136733828Sbostic if((f = open(str, x? 1: 0)) < 0) { 136833829Sbostic fperrno("Can't open <%s>", str); 136933828Sbostic goto again; 137033828Sbostic } 137133828Sbostic return f; 137233828Sbostic } 137333828Sbostic 137433828Sbostic 137533828Sbostic 137633828Sbostic static 137733828Sbostic missdir(namep) 137833828Sbostic register char *namep; 137933828Sbostic { 138033828Sbostic register char *np; 138133828Sbostic register ct = 2; 138233828Sbostic 138333828Sbostic for(np = namep; *np; ++np) 138433828Sbostic if(*np == '/') { 138533828Sbostic if(np == namep) continue; /* skip over 'root slash' */ 138633828Sbostic *np = '\0'; 138733828Sbostic if(stat(namep, &Xstatb) == -1) { 138833828Sbostic if(Dir) { 138933829Sbostic if((ct = mkdir(namep, 0777)) != 0) { 139033828Sbostic *np = '/'; 139133828Sbostic return(ct); 139233828Sbostic } 139333828Sbostic }else { 139433829Sbostic fperr("missing 'd' option"); 139533828Sbostic return(-1); 139633828Sbostic } 139733828Sbostic } 139833828Sbostic *np = '/'; 139933828Sbostic } 140033828Sbostic if (ct == 2) ct = 0; /* the file already exists */ 140133828Sbostic return ct; 140233828Sbostic } 140333828Sbostic 140433828Sbostic 140533828Sbostic 140633828Sbostic static 140733828Sbostic pwd() /* get working directory */ 140833828Sbostic { 140933829Sbostic if (getwd(Fullname) == 0) { 141033829Sbostic (void)fprintf(stderr, "cpio: %s\n", 141133829Sbostic Fullname); 141233828Sbostic exit(2); 141333829Sbostic } 141433828Sbostic Pathend = strlen(Fullname); 141533829Sbostic Fullname[Pathend++] = '/'; 141633829Sbostic Fullname[Pathend] = '\0'; 141733828Sbostic } 141833828Sbostic 141933828Sbostic 142033828Sbostic /* 142133828Sbostic print message on the stderr 142233828Sbostic */ 142333828Sbostic static 142433828Sbostic fperr( va_alist ) 142533828Sbostic va_dcl 142633828Sbostic { 142733828Sbostic va_list args; 142833828Sbostic char *fmt; 142933828Sbostic 143033828Sbostic va_start( args ); 143133829Sbostic fprintf( stderr, "cpio: "); 143233828Sbostic fmt = va_arg( args, char * ); 143333828Sbostic vfprintf( stderr, fmt, args ); 143433829Sbostic putc( '\n', stderr); 143533828Sbostic fflush( stderr ); 143633828Sbostic } 143733828Sbostic 143833828Sbostic /* 143933828Sbostic print message on the stderr followed by error number and meaning. 144033828Sbostic */ 144133828Sbostic static 144233828Sbostic fperrno( va_alist ) 144333828Sbostic va_dcl 144433828Sbostic { 144533828Sbostic va_list args; 144633828Sbostic char *fmt; 144733828Sbostic 144833828Sbostic va_start( args ); 144933829Sbostic fprintf( stderr, "cpio: "); 145033828Sbostic fmt = va_arg( args, char * ); 145133828Sbostic vfprintf( stderr, fmt, args ); 145233829Sbostic fprintf( stderr, ": " ); 145333828Sbostic fflush( stderr ); 145433828Sbostic perror(""); 145533828Sbostic } 145633828Sbostic 145733828Sbostic 145833829Sbostic /* Safe memory copy. 145933829Sbostic Fast if the to and from strings do not overlap, 146033829Sbostic slower but safe if they do. 146133829Sbostic */ 146233829Sbostic 146333829Sbostic static char * 146433829Sbostic smemcpy( to, from, count ) 146533829Sbostic register char *to, *from; 146633829Sbostic register unsigned count; 146733828Sbostic { 146833829Sbostic char *savedto; 146933829Sbostic 147033829Sbostic if( &to[ count ] <= from || &from[ count ] <= to ) 147133829Sbostic return memcpy( to, from, count ); 147233829Sbostic 147333829Sbostic if( to == from ) 147433829Sbostic return to; 147533829Sbostic 147633829Sbostic savedto = to; 147733829Sbostic if( to < from ) 147833829Sbostic while( count-- ) 147933829Sbostic *(to++) = *(from++); 148033829Sbostic else { 148133829Sbostic to += count; 148233829Sbostic from += count; 148333829Sbostic while( count-- ) 148433829Sbostic *(--to) = *(--from); 148533828Sbostic } 148633828Sbostic 148733829Sbostic return savedto; 148833828Sbostic } 148933831Sbostic 149033831Sbostic extern int _doprnt(); 149133831Sbostic 149233831Sbostic /*VARARGS2*/ 149333831Sbostic int 149433831Sbostic vfprintf(iop, format, ap) 149533831Sbostic FILE *iop; 149633831Sbostic char *format; 149733831Sbostic va_list ap; 149833831Sbostic { 149933831Sbostic register int count; 150033831Sbostic 150133831Sbostic if (!(iop->_flag | _IOWRT)) { 150233831Sbostic /* if no write flag */ 150333831Sbostic if (iop->_flag | _IORW) { 150433831Sbostic /* if ok, cause read-write */ 150533831Sbostic iop->_flag |= _IOWRT; 150633831Sbostic } else { 150733831Sbostic /* else error */ 150833831Sbostic return EOF; 150933831Sbostic } 151033831Sbostic } 151133831Sbostic count = _doprnt(format, ap, iop); 151233831Sbostic return(ferror(iop)? EOF: count); 151333831Sbostic } 1514