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>
21*46224Storek #include <stdio.h>
2233828Sbostic #include <fcntl.h>
2333828Sbostic #include <memory.h>
24*46224Storek #include <pwd.h>
2533828Sbostic #include <string.h>
2633828Sbostic #include <signal.h>
2733828Sbostic #include <varargs.h>
2833829Sbostic #include <sys/param.h>
2933829Sbostic #include <sys/types.h>
3033828Sbostic #include <sys/stat.h>
3137871Sbostic #include <paths.h>
3233828Sbostic
3333829Sbostic struct utimbuf {
3433829Sbostic time_t actime;
3533829Sbostic time_t modtime;
3633829Sbostic };
3733829Sbostic #ifndef S_IFIFO
3833829Sbostic #define S_IFIFO 010000
3933829Sbostic #endif
4033829Sbostic
4133828Sbostic #define EQ(x,y) (strcmp(x,y)==0)
4233828Sbostic
4333828Sbostic /* MKSHORT: for VAX, Interdata, ... */
4433828Sbostic /* Take a 4-byte long, lv, and turn it */
4533828Sbostic /* into an array of two 2-byte shorts, v*/
4633828Sbostic #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];}
4733828Sbostic
4833828Sbostic #define MAGIC 070707 /* cpio magic number */
4933829Sbostic #define BSMAGIC 0143561 /* byte-swapped cpio magic number */
5033828Sbostic #define IN 'i' /* copy in */
5133828Sbostic #define OUT 'o' /* copy out */
5233828Sbostic #define PASS 'p' /* direct copy */
5333828Sbostic #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */
5433828Sbostic #define LINKS 500 /* no. of links allocated per bunch */
5533828Sbostic #define CHARS 76 /* ASCII header size minus filename field */
5633828Sbostic #define BUFSIZE 512 /* In u370, can't use BUFSIZ or BSIZE */
5733828Sbostic #define CPIOBSZ 4096 /* file read/write */
5833828Sbostic #define MK_USHORT(a) (a & 00000177777) /* Make unsigned shorts for portable */
5933828Sbostic /* header. Hardware may only know */
6033828Sbostic /* integer operations and sign extend */
6133828Sbostic /* the large unsigned short resulting */
6233828Sbostic /* in 8 rather than 6 octal char in */
6333828Sbostic /* the header. */
6433828Sbostic
6533828Sbostic static struct stat Statb, Xstatb;
6633828Sbostic
6733828Sbostic /* Cpio header format */
6833828Sbostic static struct header {
6933828Sbostic short h_magic;
7033828Sbostic short h_dev;
7133828Sbostic ushort h_ino;
7233828Sbostic ushort h_mode,
7333828Sbostic h_uid,
7433828Sbostic h_gid;
7533828Sbostic short h_nlink;
7633828Sbostic short h_rdev;
7733828Sbostic short h_mtime[2],
7833828Sbostic h_namesize,
7933828Sbostic h_filesize[2];
8033828Sbostic char h_name[256];
8133828Sbostic } Hdr;
8233828Sbostic
8333829Sbostic char Symlbuf[MAXPATHLEN + 1]; /* target of symbolic link */
8433828Sbostic static unsigned Bufsize = BUFSIZE; /* default record size */
8533828Sbostic static char Buf[CPIOBSZ], *Cbuf;
8633828Sbostic static char *Cp;
8733828Sbostic
8833828Sbostic
8933828Sbostic static
9033828Sbostic short Option,
9133828Sbostic Dir,
9233828Sbostic Uncond,
9333828Sbostic PassLink,
9433828Sbostic Rename,
9533828Sbostic Toc,
9633828Sbostic Verbose,
9733828Sbostic Mod_time,
9833828Sbostic Acc_time,
9933828Sbostic Cflag,
10033828Sbostic fflag,
10133828Sbostic Swap,
10233828Sbostic byteswap,
10333828Sbostic halfswap;
10433828Sbostic
10533828Sbostic static
10633828Sbostic int Ifile,
10733828Sbostic Ofile,
10833828Sbostic Input = 0,
10933828Sbostic Output = 1;
11033828Sbostic /* sBlocks: short Blocks. Cumulative character */
11133828Sbostic /* count for short reads in bread(). Encountered */
11233828Sbostic /* with communication lines and pipes as in: */
11333828Sbostic /* split -100 cpio_archive; cat xa* | cpio -icd */
11433828Sbostic static
11533828Sbostic long sBlocks,
11633828Sbostic Blocks,
11733828Sbostic Longfile,
11833828Sbostic Longtime;
11933828Sbostic
12033828Sbostic static
12133828Sbostic char Fullname[256],
12233828Sbostic Name[256];
12333828Sbostic static
12433828Sbostic int Pathend;
12533828Sbostic static
12633828Sbostic char *swfile;
12733828Sbostic static
12833828Sbostic char *eommsg = "Change to part %d and press RETURN key. [q] ";
12933828Sbostic
13033828Sbostic static
13133828Sbostic FILE *Rtty,
13233828Sbostic *Wtty;
13333828Sbostic static
13437871Sbostic char ttyname[] = _PATH_TTY;
13533828Sbostic
13633828Sbostic static
13733828Sbostic char **Pattern = 0;
13833828Sbostic static
13933828Sbostic char Chdr[500];
14033828Sbostic static
14133828Sbostic short Dev;
14233828Sbostic ushort Uid,
14333828Sbostic A_directory,
14433828Sbostic A_special,
14533829Sbostic A_symlink,
14633828Sbostic Filetype = S_IFMT;
14733828Sbostic
14833828Sbostic extern errno;
14933828Sbostic extern void exit();
15033828Sbostic char *malloc();
15133828Sbostic FILE *popen();
15233828Sbostic
15333829Sbostic static char *smemcpy();
15433829Sbostic
15533828Sbostic static
15633828Sbostic union {
15733828Sbostic long l;
15833828Sbostic short s[2];
15933828Sbostic char c[4];
16033828Sbostic } U;
16133828Sbostic
16233828Sbostic /* for VAX, Interdata, ... */
16333828Sbostic static
mklong(v)16433828Sbostic long mklong(v)
16533828Sbostic short v[];
16633828Sbostic {
16733828Sbostic U.l = 1;
16833828Sbostic if(U.c[0])
16933828Sbostic U.s[0] = v[1], U.s[1] = v[0];
17033828Sbostic else
17133828Sbostic U.s[0] = v[0], U.s[1] = v[1];
17233828Sbostic return U.l;
17333828Sbostic }
17433828Sbostic
175*46224Storek static usage(), chkswfile(), getname(), bintochar(), chkhdr(), gethdr();
176*46224Storek static ckname(), openout(), breread(), bread(), bwrite(), eomchgreel();
177*46224Storek static postml(), pentry(), nmatch(), gmatch(), umatch(), set_time();
178*46224Storek static chgreel(), missdir(), pwd(), fperr(), fperrno();
179*46224Storek
main(argc,argv)18033828Sbostic main(argc, argv)
181*46224Storek int argc;
18233828Sbostic char **argv;
18333828Sbostic {
18433828Sbostic register ct;
18533828Sbostic long filesz;
18633829Sbostic int symlsz;
18733828Sbostic register char *fullp;
18833828Sbostic register i;
18933828Sbostic int ans;
19033829Sbostic register char *symlinkp;
19133828Sbostic short select; /* set when files are selected */
19233828Sbostic extern char *optarg;
19333828Sbostic extern int optind;
19433828Sbostic
19533829Sbostic signal(SIGSYS, SIG_IGN);
19633829Sbostic if(argc <= 1 || *argv[1] != '-')
19733828Sbostic usage();
19833828Sbostic Uid = getuid();
19933828Sbostic
20033829Sbostic while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvM:6eI:O:")) != EOF ) {
20133828Sbostic
20233828Sbostic switch( ans ) {
20333828Sbostic case 'a': /* reset access time */
20433828Sbostic Acc_time++;
20533828Sbostic break;
20633828Sbostic case 'B': /* change record size to 5120 bytes */
20733828Sbostic Bufsize = 5120;
20833828Sbostic break;
20933828Sbostic case 'C': /* reset buffer size to arbitrary valu
21033828Sbostic */
21133828Sbostic Bufsize = atoi( optarg );
21233829Sbostic if( Bufsize == 0 ) {
21333829Sbostic fperr("Illegal argument to -%c, '%s'",
21433828Sbostic ans, optarg );
21533829Sbostic exit(2);
21633829Sbostic }
21733828Sbostic break;
21833828Sbostic case 'i':
21933828Sbostic Option = IN;
22033828Sbostic break;
22133828Sbostic case 'f': /* copy files not matched by patterns */
22233828Sbostic fflag++;
22333828Sbostic break;
22433828Sbostic case 'o':
22533828Sbostic Option = OUT;
22633828Sbostic break;
22733828Sbostic case 'p':
22833828Sbostic Option = PASS;
22933828Sbostic break;
23033828Sbostic case 'c': /* ASCII header */
23133828Sbostic Cflag++;
23233828Sbostic break;
23333828Sbostic case 'd': /* create directories when needed */
23433828Sbostic Dir++;
23533828Sbostic break;
23633828Sbostic case 'l': /* link files, when necessary */
23733828Sbostic PassLink++;
23833828Sbostic break;
23933828Sbostic case 'm': /* retain mod time */
24033828Sbostic Mod_time++;
24133828Sbostic break;
24233828Sbostic case 'r': /* rename files interactively */
24333828Sbostic Rename++;
24433828Sbostic Rtty = fopen(ttyname, "r");
24533828Sbostic Wtty = fopen(ttyname, "w");
24633828Sbostic if(Rtty==NULL || Wtty==NULL) {
24733829Sbostic fperrno("Cannot rename (%s missing)",
24833828Sbostic ttyname );
24933829Sbostic exit(2);
25033828Sbostic }
25133828Sbostic break;
25233828Sbostic case 'S': /* swap halfwords */
25333828Sbostic halfswap++;
25433828Sbostic Swap++;
25533828Sbostic break;
25633828Sbostic case 's': /* swap bytes */
25733828Sbostic byteswap++;
25833828Sbostic Swap++;
25933828Sbostic break;
26033828Sbostic case 'b': /* swap both bytes and halfwords */
26133829Sbostic halfswap++;
26233829Sbostic byteswap++;
26333828Sbostic Swap++;
26433828Sbostic break;
26533828Sbostic case 't': /* table of contents */
26633828Sbostic Toc++;
26733828Sbostic break;
26833828Sbostic case 'u': /* copy unconditionally */
26933828Sbostic Uncond++;
27033828Sbostic break;
27133828Sbostic case 'v': /* verbose - print out file names */
27233829Sbostic Verbose++;
27333828Sbostic break;
27433828Sbostic case 'M': /* alternate message for end-of-media */
27533828Sbostic eommsg = optarg;
27633828Sbostic break;
27733828Sbostic case '6': /* for old, sixth-edition files */
27833828Sbostic Filetype = 060000;
27933828Sbostic break;
28033828Sbostic case 'I':
28133828Sbostic chkswfile( swfile, ans, Option );
28233829Sbostic if( (i = open( optarg, O_RDONLY ) ) < 0) {
28333829Sbostic fperrno("Cannot open <%s> for input", optarg);
28433829Sbostic exit(2);
28533829Sbostic }
28633829Sbostic if( dup2(i, Input ) < 0 ) {
28733829Sbostic fperrno("Cannot dup to standard input");
28833829Sbostic exit(2);
28933829Sbostic }
29033828Sbostic swfile = optarg;
29133828Sbostic break;
29233828Sbostic case 'O':
29333828Sbostic chkswfile( swfile, ans, Option );
29433829Sbostic if( (i = open( optarg, O_WRONLY | O_CREAT | O_TRUNC,
29533829Sbostic 0666 ) ) < 0) {
29633829Sbostic fperrno("Cannot open <%s> for output", optarg);
29733829Sbostic exit(2);
29833829Sbostic }
29933829Sbostic if( dup2(i, Output ) < 0 ) {
30033829Sbostic fperrno("Cannot dup to standard output");
30133829Sbostic exit(2);
30233829Sbostic }
30333828Sbostic swfile = optarg;
30433828Sbostic break;
30533828Sbostic default:
30633828Sbostic usage();
30733828Sbostic }
30833828Sbostic }
30933828Sbostic if(!Option) {
31033829Sbostic (void) fprintf(stderr,
31133829Sbostic "Options must include one of -o, -i, or -p\n");
31233829Sbostic exit(2);
31333828Sbostic }
31433828Sbostic
31533828Sbostic if(Option == PASS) {
31633828Sbostic if(Rename) {
31733829Sbostic (void) fprintf(stderr,
31833829Sbostic "Pass and Rename cannot be used together\n");
31933829Sbostic exit(2);
32033828Sbostic }
32133828Sbostic if( Bufsize != BUFSIZE ) {
32233828Sbostic fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n");
32333828Sbostic Bufsize = BUFSIZE;
32433828Sbostic }
32533828Sbostic
32633828Sbostic }else {
32733829Sbostic Cp = Cbuf = (char *)malloc(Bufsize);
32833829Sbostic if(Cp == NULL) {
32933829Sbostic perror("cpio");
33033829Sbostic exit(2);
33133829Sbostic }
33233828Sbostic }
33333828Sbostic argc -= optind;
33433828Sbostic argv += optind;
33533828Sbostic
33633828Sbostic switch(Option) {
33733828Sbostic case OUT:
33833828Sbostic if(argc != 0)
33933828Sbostic usage();
34033828Sbostic /* get filename, copy header and file out */
34133828Sbostic while(getname()) {
34233828Sbostic if( mklong(Hdr.h_filesize) == 0L) {
34333828Sbostic if( Cflag )
34433828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize);
34533828Sbostic else
34633828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
34733828Sbostic if(Verbose)
34833829Sbostic (void) fprintf(stderr, "%s\n",
34933829Sbostic Hdr.h_name);
35033828Sbostic continue;
35133829Sbostic } else if( A_symlink ) {
35233829Sbostic symlsz = (int) mklong(Hdr.h_filesize);
35333829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) {
35433829Sbostic fperrno("Cannot read symbolic link <%s>",
35533829Sbostic Hdr.h_name);
35633829Sbostic continue;
35733829Sbostic }
35833829Sbostic Symlbuf[symlsz] = '\0';
35933829Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
36033829Sbostic bwrite(Symlbuf, symlsz);
36133829Sbostic if(Verbose)
36233829Sbostic (void) fprintf(stderr, "%s\n",
36333829Sbostic Hdr.h_name);
36433829Sbostic continue;
36533828Sbostic }
36633828Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) {
36733829Sbostic fperrno("Cannot open <%s>", Hdr.h_name);
36833828Sbostic continue;
36933828Sbostic }
37033828Sbostic if ( Cflag )
37133828Sbostic bwrite(Chdr,CHARS+Hdr.h_namesize);
37233828Sbostic else
37333828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
37433828Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
37533828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
37633828Sbostic if(read(Ifile, Buf, ct) < 0) {
37733829Sbostic fperrno("Cannot read %s", Hdr.h_name);
37833828Sbostic continue;
37933828Sbostic }
38033828Sbostic bwrite(Buf,ct);
38133828Sbostic }
38233828Sbostic close(Ifile);
38333829Sbostic if(Acc_time) {
38433829Sbostic struct utimbuf utb;
38533829Sbostic
38633829Sbostic utb.actime = Statb.st_atime;
38733829Sbostic utb.modtime = Statb.st_mtime;
38833829Sbostic (void)utime(Hdr.h_name, &utb);
38933829Sbostic }
39033828Sbostic if(Verbose)
39133829Sbostic (void) fprintf(stderr, "%s\n", Hdr.h_name);
39233828Sbostic }
39333828Sbostic
39433828Sbostic /* copy trailer, after all files have been copied */
39533828Sbostic strcpy(Hdr.h_name, "TRAILER!!!");
39633828Sbostic Hdr.h_magic = MAGIC;
39733828Sbostic MKSHORT(Hdr.h_filesize, 0L);
39833828Sbostic Hdr.h_namesize = strlen("TRAILER!!!") + 1;
39933828Sbostic if ( Cflag ) {
40033828Sbostic bintochar(0L);
40133828Sbostic bwrite(Chdr, CHARS+Hdr.h_namesize);
40233828Sbostic }
40333828Sbostic else
40433828Sbostic bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
40533828Sbostic bwrite(Cbuf, Bufsize);
40633828Sbostic break;
40733828Sbostic
40833828Sbostic case IN:
40933828Sbostic if(argc > 0 ) { /* save patterns, if any */
41033828Sbostic Pattern = argv;
41133828Sbostic }
41233828Sbostic pwd();
41333828Sbostic chkhdr();
41433828Sbostic while(gethdr()) {
41533829Sbostic if (A_symlink) {
41633829Sbostic symlsz = (int) mklong(Hdr.h_filesize);
41733829Sbostic bread(Symlbuf, symlsz);
41833829Sbostic Symlbuf[symlsz] = '\0';
41933830Sbostic if( ckname(Hdr.h_name) && !Toc)
42033829Sbostic (void)openout(Hdr.h_name, Symlbuf);
42133829Sbostic } else {
42233829Sbostic if( (select = ckname(Hdr.h_name)) && !Toc )
42333829Sbostic Ofile = openout(Hdr.h_name, (char *)0);
42433829Sbostic else
42533829Sbostic Ofile = 0;
42633829Sbostic for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
42733829Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
42833829Sbostic bread(Buf, ct);
42933829Sbostic if(Ofile) {
43033829Sbostic if(Swap)
43133829Sbostic swap(Buf,ct,byteswap,halfswap);
43233829Sbostic if(write(Ofile, Buf, ct) < 0) {
43333829Sbostic fperrno("Cannot write %s", Hdr.h_name);
43433829Sbostic continue;
43533829Sbostic }
43633828Sbostic }
43733828Sbostic }
43833829Sbostic if( Ofile ) {
43933829Sbostic (void) close(Ofile);
44033829Sbostic if(chmod(Hdr.h_name, Hdr.h_mode) < 0)
44133829Sbostic fperrno("Cannot change mode of <%s>",
44233829Sbostic Hdr.h_name);
44333829Sbostic set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
44433829Sbostic }
44533828Sbostic }
44633828Sbostic if(select) {
44733828Sbostic if(Verbose)
44833828Sbostic if(Toc)
44933828Sbostic pentry(Hdr.h_name);
45033828Sbostic else
45133829Sbostic puts(Hdr.h_name);
45233828Sbostic else if(Toc)
45333828Sbostic puts(Hdr.h_name);
45433828Sbostic }
45533828Sbostic }
45633828Sbostic break;
45733828Sbostic
45833828Sbostic case PASS: /* move files around */
45933828Sbostic if(argc != 1)
46033828Sbostic usage();
46133828Sbostic if(access(argv[0], 2) == -1) {
46233829Sbostic (void) fperrno("Cannot write in <%s>", argv[0]);
46333829Sbostic exit(2);
46433828Sbostic }
46533828Sbostic strcpy(Fullname, argv[0]); /* destination directory */
46633829Sbostic if(stat(Fullname, &Xstatb) < 0) {
46733829Sbostic fperrno("Cannot stat <%s>", Fullname);
46833829Sbostic exit(2);
46933829Sbostic }
47033829Sbostic if((Xstatb.st_mode&S_IFMT) != S_IFDIR) {
47133829Sbostic (void) fprintf(stderr, "<%s> is not a directory",
47233829Sbostic Fullname);
47333829Sbostic exit(2);
47433829Sbostic }
47533828Sbostic Dev = Xstatb.st_dev;
47633828Sbostic if( Fullname[ strlen(Fullname) - 1 ] != '/' )
47733828Sbostic strcat(Fullname, "/");
47833828Sbostic fullp = Fullname + strlen(Fullname);
47933828Sbostic
48033828Sbostic while(getname()) {
48133828Sbostic if (A_directory && !Dir)
48233829Sbostic fperr("Use `-d' option to copy <%s>",
48333828Sbostic Hdr.h_name);
48433828Sbostic if(!ckname(Hdr.h_name))
48533828Sbostic continue;
48633828Sbostic i = 0;
48733828Sbostic while(Hdr.h_name[i] == '/')
48833828Sbostic i++;
48933828Sbostic strcpy(fullp, &(Hdr.h_name[i]));
49033828Sbostic
49133828Sbostic if( PassLink && !A_directory && Dev == Statb.st_dev ) {
49233828Sbostic if(link(Hdr.h_name, Fullname) < 0) {
49333828Sbostic switch(errno) {
49433828Sbostic case ENOENT:
49533828Sbostic if(missdir(Fullname) != 0) {
49633829Sbostic fperrno("Cannot create directory for <%s>",
49733829Sbostic Fullname);
49833828Sbostic continue;
49933828Sbostic }
50033828Sbostic break;
50133828Sbostic case EEXIST:
50233828Sbostic if(unlink(Fullname) < 0) {
50333829Sbostic fperrno("Cannot unlink <%s>",
50433829Sbostic Fullname);
50533828Sbostic continue;
50633828Sbostic }
50733828Sbostic break;
50833828Sbostic default:
50933829Sbostic fperrno("Cannot link <%s> to <%s>",
51033829Sbostic Hdr.h_name, Fullname);
51133828Sbostic continue;
51233828Sbostic }
51333828Sbostic if(link(Hdr.h_name, Fullname) < 0) {
51433829Sbostic fperrno("Cannot link <%s> to <%s>",
51533829Sbostic Hdr.h_name, Fullname);
51633828Sbostic continue;
51733828Sbostic }
51833828Sbostic }
51933828Sbostic
52033828Sbostic goto ckverbose;
52133828Sbostic }
52233829Sbostic if( A_symlink ) {
52333829Sbostic symlsz = (int) mklong(Hdr.h_filesize);
52433829Sbostic if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) {
52533829Sbostic fperrno("Cannot read symbolic link <%s>",
52633829Sbostic Hdr.h_name);
52733828Sbostic continue;
52833829Sbostic }
52933829Sbostic Symlbuf[symlsz] = '\0';
53033829Sbostic if(!openout(Fullname, Symlbuf))
53133829Sbostic continue;
53233829Sbostic Blocks += ((symlsz + (BUFSIZE - 1)) / BUFSIZE);
53333829Sbostic if(Verbose)
53433829Sbostic puts(Fullname);
53533829Sbostic continue;
53633829Sbostic }
53733829Sbostic if(!(Ofile = openout(Fullname, (char *)0)))
53833829Sbostic continue;
53933829Sbostic if((Ifile = open(Hdr.h_name, 0)) < 0) {
54033829Sbostic fperrno("Cannot open <%s>", Hdr.h_name);
54133828Sbostic close(Ofile);
54233828Sbostic continue;
54333828Sbostic }
54433828Sbostic filesz = Statb.st_size;
54533828Sbostic for(; filesz > 0; filesz -= CPIOBSZ) {
54633828Sbostic ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
54733828Sbostic if(read(Ifile, Buf, ct) < 0) {
54833829Sbostic fperrno("Cannot read %s", Hdr.h_name);
54933828Sbostic break;
55033828Sbostic }
55133829Sbostic if(write(Ofile, Buf, ct) < 0) {
55233829Sbostic fperrno("Cannot write %s", Hdr.h_name);
55333829Sbostic break;
55433829Sbostic }
55533829Sbostic /* Removed u370 ifdef which caused cpio */
55633829Sbostic /* to report blocks in terms of 4096 bytes. */
55733828Sbostic
55833828Sbostic Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE);
55933828Sbostic }
56033828Sbostic close(Ifile);
56133829Sbostic if(Acc_time) {
56233829Sbostic struct utimbuf utb;
56333829Sbostic
56433829Sbostic utb.actime = Statb.st_atime;
56533829Sbostic utb.modtime = Statb.st_mtime;
56633829Sbostic (void)utime(Hdr.h_name, &utb);
56733829Sbostic }
56833828Sbostic if(Ofile) {
56933828Sbostic close(Ofile);
57033829Sbostic if(chmod(Fullname, Hdr.h_mode) < 0)
57133829Sbostic fperrno("Cannot change mode of <%s>",
57233829Sbostic Fullname);
57333828Sbostic set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
57433828Sbostic ckverbose:
57533828Sbostic if(Verbose)
57633829Sbostic puts(Fullname);
57733828Sbostic }
57833828Sbostic }
57933828Sbostic }
58033828Sbostic /* print number of blocks actually copied */
58133828Sbostic Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE);
58233829Sbostic (void) fprintf(stderr, "%ld blocks\n", Blocks * (Bufsize>>9));
58333828Sbostic exit(0);
58433828Sbostic }
58533828Sbostic
58633828Sbostic static
usage()58733828Sbostic usage()
58833828Sbostic {
589*46224Storek (void) fprintf(stderr,
590*46224Storek "Usage: %s\n %s\n %s\n %s\n %s\n",
59133829Sbostic "cpio -o[acvB] <name-list >collection",
59233829Sbostic "cpio -o[acvB] -Ocollection <name-list",
59333829Sbostic "cpio -i[cdmrstuvfB6] [ pattern ... ] <collection",
59433829Sbostic "cpio -i[cdmrstuvfB6] -Icollection [ pattern ... ]",
59533829Sbostic "cpio -p[adlmruv] directory <name-list");
59633828Sbostic }
59733828Sbostic
59833828Sbostic static
chkswfile(sp,c,option)59933828Sbostic chkswfile( sp, c, option )
60033828Sbostic char *sp;
60133828Sbostic char c;
60233828Sbostic short option;
60333828Sbostic {
60433829Sbostic if( !option ) {
60533829Sbostic fperr( "-%c must be specified before -%c option",
60633828Sbostic c == 'I' ? 'i' : 'o', c );
60733829Sbostic exit(2);
60833829Sbostic }
60933829Sbostic if( (c == 'I' && option != IN) || (c == 'O' && option != OUT) ) {
61033829Sbostic fperr( "-%c option not permitted with -%c option", c,
61133828Sbostic option );
61233829Sbostic exit(2);
61333829Sbostic }
61433828Sbostic if( !sp )
61533828Sbostic return;
61633829Sbostic fperr("No more than one -I or -O flag permitted");
61733829Sbostic exit(2);
61833828Sbostic }
61933828Sbostic
62033828Sbostic static
getname()62133828Sbostic getname() /* get file name, get info for header */
62233828Sbostic {
62333828Sbostic register char *namep = Name;
62433828Sbostic register ushort ftype;
62533829Sbostic struct stat Lstatb;
62633828Sbostic long tlong;
62733828Sbostic
62833828Sbostic for(;;) {
62933828Sbostic if(gets(namep) == NULL)
63033828Sbostic return 0;
63133828Sbostic while(*namep == '.' && namep[1] == '/') {
63233828Sbostic namep++;
63333828Sbostic while(*namep == '/') namep++;
63433828Sbostic }
63533828Sbostic strcpy(Hdr.h_name, namep);
63633829Sbostic if(lstat(namep, &Statb) < 0) {
63733829Sbostic fperrno("Cannot stat <%s>", Hdr.h_name);
63833828Sbostic continue;
63933828Sbostic }
64033828Sbostic ftype = Statb.st_mode & Filetype;
64133828Sbostic A_directory = (ftype == S_IFDIR);
64233828Sbostic A_special = (ftype == S_IFBLK)
64333828Sbostic || (ftype == S_IFCHR)
64433828Sbostic || (ftype == S_IFIFO);
64533829Sbostic A_symlink = (ftype == S_IFLNK);
64633828Sbostic Hdr.h_magic = MAGIC;
64733828Sbostic Hdr.h_namesize = strlen(Hdr.h_name) + 1;
64833828Sbostic Hdr.h_uid = Statb.st_uid;
64933828Sbostic Hdr.h_gid = Statb.st_gid;
65033828Sbostic Hdr.h_dev = Statb.st_dev;
65133828Sbostic Hdr.h_ino = Statb.st_ino;
65233828Sbostic Hdr.h_mode = Statb.st_mode;
65333828Sbostic MKSHORT(Hdr.h_mtime, Statb.st_mtime);
65433828Sbostic Hdr.h_nlink = Statb.st_nlink;
65533829Sbostic tlong = ((Hdr.h_mode&S_IFMT) == S_IFREG ||
65633829Sbostic (Hdr.h_mode&S_IFMT) == S_IFLNK)? Statb.st_size: 0L;
65733828Sbostic MKSHORT(Hdr.h_filesize, tlong);
65833828Sbostic Hdr.h_rdev = Statb.st_rdev;
65933828Sbostic if( Cflag )
66033828Sbostic bintochar(tlong);
66133828Sbostic return 1;
66233828Sbostic }
66333828Sbostic }
66433828Sbostic
66533828Sbostic static
bintochar(t)66633828Sbostic bintochar(t) /* ASCII header write */
66733828Sbostic long t;
66833828Sbostic {
66933828Sbostic sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
67033828Sbostic MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid,
67133828Sbostic Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev),
67233828Sbostic Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name);
67333828Sbostic }
67433828Sbostic
67533828Sbostic static
chartobin()67633828Sbostic chartobin() /* ASCII header read */
67733828Sbostic {
67833828Sbostic sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
67933828Sbostic &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid,
68033828Sbostic &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime,
68133828Sbostic &Hdr.h_namesize, &Longfile);
68233828Sbostic MKSHORT(Hdr.h_filesize, Longfile);
68333828Sbostic MKSHORT(Hdr.h_mtime, Longtime);
68433828Sbostic }
68533828Sbostic
68633828Sbostic
68733828Sbostic /* Check the header for the magic number. Switch modes automatically to
68833828Sbostic match the type of header found.
68933828Sbostic */
69033828Sbostic static
chkhdr()69133828Sbostic chkhdr()
69233828Sbostic {
69333828Sbostic bread(Chdr, CHARS);
69433828Sbostic chartobin();
69533828Sbostic if( Hdr.h_magic == MAGIC )
69633828Sbostic Cflag = 1;
69733828Sbostic else {
69833828Sbostic breread(&Hdr.h_magic, sizeof Hdr.h_magic);
69933829Sbostic if( Hdr.h_magic == MAGIC || Hdr.h_magic == (short)BSMAGIC )
70033828Sbostic Cflag = 0;
70133829Sbostic else {
70233829Sbostic fperr("This is not a cpio file. Bad magic number.");
70333829Sbostic exit(2);
70433829Sbostic }
70533828Sbostic }
70633828Sbostic breread(Chdr, 0);
70733828Sbostic }
70833828Sbostic
70933828Sbostic
71033828Sbostic static
gethdr()71133828Sbostic gethdr() /* get file headers */
71233828Sbostic {
71333828Sbostic register ushort ftype;
71433828Sbostic
71533828Sbostic if (Cflag) {
71633828Sbostic bread(Chdr, CHARS);
71733828Sbostic chartobin();
71833828Sbostic }
71933828Sbostic else
72033828Sbostic bread(&Hdr, HDRSIZE);
72133828Sbostic
72233829Sbostic if(Hdr.h_magic == (short)BSMAGIC)
72333829Sbostic swap((char *)&Hdr, HDRSIZE, 1, 0);
72433829Sbostic else if( Hdr.h_magic != MAGIC ) {
72533829Sbostic fperr("Out of phase--get help");
72633829Sbostic exit(2);
72733828Sbostic }
72833828Sbostic bread(Hdr.h_name, Hdr.h_namesize);
72933828Sbostic if(EQ(Hdr.h_name, "TRAILER!!!"))
73033828Sbostic return 0;
73133828Sbostic ftype = Hdr.h_mode & Filetype;
73233828Sbostic A_directory = (ftype == S_IFDIR);
73333828Sbostic A_special = (ftype == S_IFBLK)
73433828Sbostic || (ftype == S_IFCHR)
73533828Sbostic || (ftype == S_IFIFO);
73633829Sbostic A_symlink = (ftype == S_IFLNK);
73733828Sbostic return 1;
73833828Sbostic }
73933828Sbostic
74033828Sbostic static
ckname(namep)74133828Sbostic ckname(namep) /* check filenames with patterns given on cmd line */
74233828Sbostic register char *namep;
74333828Sbostic {
74433828Sbostic char buf[sizeof Hdr.h_name];
74533828Sbostic
74633828Sbostic if(fflag ^ !nmatch(namep, Pattern)) {
74733828Sbostic return 0;
74833828Sbostic }
74933828Sbostic if(Rename && !A_directory) { /* rename interactively */
75033828Sbostic fprintf(Wtty, "Rename <%s>\n", namep);
75133828Sbostic fflush(Wtty);
75233828Sbostic fgets(buf, sizeof buf, Rtty);
75333828Sbostic if(feof(Rtty))
75433828Sbostic exit(2);
75533828Sbostic buf[strlen(buf) - 1] = '\0';
75633828Sbostic if(EQ(buf, "")) {
75733828Sbostic strcpy(namep,buf);
75833828Sbostic printf("Skipped\n");
75933828Sbostic return 0;
76033828Sbostic }
76133828Sbostic else if(EQ(buf, "."))
76233828Sbostic printf("Same name\n");
76333828Sbostic else
76433828Sbostic strcpy(namep,buf);
76533828Sbostic }
76633828Sbostic return 1;
76733828Sbostic }
76833828Sbostic
76933828Sbostic static
openout(namep,symlname)77033829Sbostic openout(namep, symlname) /* open files for writing, set all necessary info */
77133828Sbostic register char *namep;
77233829Sbostic char *symlname;
77333828Sbostic {
77433828Sbostic register f;
77533828Sbostic register char *np;
77633828Sbostic int ans;
77733828Sbostic
77833828Sbostic if(!strncmp(namep, "./", 2))
77933828Sbostic namep += 2;
78033828Sbostic np = namep;
78133828Sbostic if(A_directory) {
78233828Sbostic if( !Dir || Rename || EQ(namep, ".") || EQ(namep, "..") )
78333828Sbostic /* do not consider . or .. files */
78433828Sbostic return 0;
78533828Sbostic if(stat(namep, &Xstatb) == -1) {
78633828Sbostic
78733828Sbostic /* try creating (only twice) */
78833828Sbostic ans = 0;
78933828Sbostic do {
79033829Sbostic if(mkdir(namep, Hdr.h_mode) != 0) {
79133828Sbostic ans += 1;
79233828Sbostic }else {
79333828Sbostic ans = 0;
79433828Sbostic break;
79533828Sbostic }
79633828Sbostic }while(ans < 2 && missdir(namep) == 0);
79733828Sbostic if(ans == 1) {
79833828Sbostic fperrno("Cannot create directory for <%s>",
79933828Sbostic namep);
80033828Sbostic return(0);
80133828Sbostic }else if(ans == 2) {
80233828Sbostic fperrno("Cannot create directory <%s>", namep);
80333828Sbostic return(0);
80433828Sbostic }
80533828Sbostic }
80633828Sbostic
80733828Sbostic ret:
80833829Sbostic if(chmod(namep, Hdr.h_mode) < 0)
80933829Sbostic fperrno("Cannot change mode of <%s>", namep);
81033828Sbostic if(Uid == 0)
81133829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0)
81233829Sbostic fperrno("Cannot change ownership of <%s>",
81333829Sbostic namep);
81433828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
81533828Sbostic return 0;
81633828Sbostic }
81733828Sbostic if(Hdr.h_nlink > 1)
81833828Sbostic if(!postml(namep, np))
81933828Sbostic return 0;
82033829Sbostic if(lstat(namep, &Xstatb) == 0) {
82133828Sbostic if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) {
82233828Sbostic if(unlink(namep) < 0) {
82333828Sbostic fperrno("cannot unlink current <%s>", namep);
82433828Sbostic }
82533828Sbostic }
82633828Sbostic if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) {
82733828Sbostic /* There's a newer or same aged version of file on destination */
82833829Sbostic fperr("current <%s> newer or same age", np);
82933828Sbostic return 0;
83033828Sbostic }
83133828Sbostic }
83233828Sbostic if( Option == PASS
83333828Sbostic && Hdr.h_ino == Xstatb.st_ino
83433828Sbostic && Hdr.h_dev == Xstatb.st_dev) {
83533829Sbostic fperr("Attempt to pass file to self!");
83633829Sbostic exit(2);
83733828Sbostic }
83833829Sbostic if(A_symlink) {
83933829Sbostic /* try symlinking (only twice) */
84033829Sbostic ans = 0;
84133829Sbostic do {
84233829Sbostic if(symlink(
84333829Sbostic symlname, namep) < 0) {
84433829Sbostic ans += 1;
84533829Sbostic }else {
84633829Sbostic ans = 0;
84733829Sbostic break;
84833829Sbostic }
84933829Sbostic }while(ans < 2 && missdir(np) == 0);
85033829Sbostic if(ans == 1) {
85133829Sbostic fperrno("Cannot create directory for <%s>", namep);
85233829Sbostic return(0);
85333829Sbostic }else if(ans == 2) {
85433829Sbostic fperrno("Cannot symlink <%s> and <%s>", namep, symlname);
85533829Sbostic return(0);
85633829Sbostic }
85733829Sbostic
85833829Sbostic return 0;
85933829Sbostic }
86033828Sbostic if(A_special) {
86133828Sbostic if((Hdr.h_mode & Filetype) == S_IFIFO)
86233828Sbostic Hdr.h_rdev = 0;
86333828Sbostic
86433828Sbostic /* try creating (only twice) */
86533828Sbostic ans = 0;
86633828Sbostic do {
86733828Sbostic if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
86833828Sbostic ans += 1;
86933828Sbostic }else {
87033828Sbostic ans = 0;
87133828Sbostic break;
87233828Sbostic }
87333828Sbostic }while(ans < 2 && missdir(np) == 0);
87433828Sbostic if(ans == 1) {
87533828Sbostic fperrno("Cannot create directory for <%s>", namep);
87633828Sbostic return(0);
87733828Sbostic }else if(ans == 2) {
87833828Sbostic fperrno("Cannot mknod <%s>", namep);
87933828Sbostic return(0);
88033828Sbostic }
88133828Sbostic
88233828Sbostic goto ret;
88333828Sbostic }
88433828Sbostic
88533828Sbostic /* try creating (only twice) */
88633828Sbostic ans = 0;
88733828Sbostic do {
88833828Sbostic if((f = creat(namep, Hdr.h_mode)) < 0) {
88933828Sbostic ans += 1;
89033828Sbostic }else {
89133828Sbostic ans = 0;
89233828Sbostic break;
89333828Sbostic }
89433828Sbostic }while(ans < 2 && missdir(np) == 0);
89533828Sbostic if(ans == 1) {
89633828Sbostic fperrno("Cannot create directory for <%s>", namep);
89733828Sbostic return(0);
89833828Sbostic }else if(ans == 2) {
89933828Sbostic fperrno("Cannot create <%s>", namep);
90033828Sbostic return(0);
90133828Sbostic }
90233828Sbostic
90333828Sbostic if(Uid == 0)
90433829Sbostic if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0)
90533829Sbostic fperrno("Cannot change ownership of <%s>", namep);
90633828Sbostic return f;
90733828Sbostic }
90833828Sbostic
90933828Sbostic
91033828Sbostic /* Shared by bread() and breread()
91133828Sbostic */
91233828Sbostic static int nleft = 0; /* unread chars left in Cbuf */
91333828Sbostic static char *ip; /* pointer to next char to be read from Cbuf */
91433828Sbostic
91533828Sbostic /* Reread the current buffer Cbuf.
91633828Sbostic A character count, c, of 0 simply resets the pointer so next bread gets
91733828Sbostic the same data again.
91833828Sbostic */
91933828Sbostic static
breread(b,c)92033828Sbostic breread(b, c)
92133828Sbostic char *b;
92233828Sbostic int c;
92333828Sbostic {
92433828Sbostic ip = Cbuf;
92533828Sbostic if( nleft )
92633828Sbostic nleft = Bufsize;
92733828Sbostic if( !c )
92833828Sbostic return;
92933828Sbostic bread(b, c);
93033828Sbostic }
93133828Sbostic
93233828Sbostic static
bread(b,c)93333828Sbostic bread(b, c)
93433828Sbostic register char *b;
93533828Sbostic register int c;
93633828Sbostic {
93733828Sbostic register int rv;
93833828Sbostic register char *p = ip;
93933828Sbostic
94033828Sbostic if( !Cflag ) {
94133828Sbostic /* round c up to an even number */
94233828Sbostic c = (c+1)/2;
94333828Sbostic c *= 2;
94433828Sbostic }
94533828Sbostic while( c ) {
94633828Sbostic if( nleft == 0 ) {
94733828Sbostic while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) {
94833828Sbostic Input = chgreel(0, Input, rv);
94933828Sbostic }
95033828Sbostic if( rv == Bufsize ) {
95133828Sbostic nleft = Bufsize;
95233828Sbostic p = Cbuf;
95333828Sbostic ++Blocks;
95433828Sbostic }
95533829Sbostic else if( rv == -1 ) {
95633829Sbostic fperrno("Read error on archive");
95733829Sbostic exit(2);
95833829Sbostic }
95933828Sbostic else if( rv < Bufsize ) { /* short read */
96033828Sbostic smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv );
96133828Sbostic nleft = rv;
96233828Sbostic p = &Cbuf[ Bufsize - rv ];
96333828Sbostic sBlocks += rv;
96433828Sbostic }
96533828Sbostic }
96633828Sbostic if( nleft <= c ) {
96733828Sbostic memcpy( b, p, nleft );
96833828Sbostic c -= nleft;
96933828Sbostic b += nleft;
97033828Sbostic p += nleft;
97133828Sbostic nleft = 0;
97233828Sbostic }
97333828Sbostic else {
97433828Sbostic memcpy( b, p, c );
97533828Sbostic nleft -= c;
97633828Sbostic b += c;
97733828Sbostic p += c;
97833828Sbostic c = 0;
97933828Sbostic }
98033828Sbostic }
98133828Sbostic ip = p;
98233828Sbostic }
98333828Sbostic
98433828Sbostic
98533828Sbostic static
bwrite(rp,c)98633828Sbostic bwrite(rp, c)
98733828Sbostic register char *rp;
98833828Sbostic register c;
98933828Sbostic {
99033828Sbostic register char *cp = Cp;
99133828Sbostic static unsigned Ccnt = 0;
99233828Sbostic register unsigned Cleft;
99333828Sbostic register int rv;
99433828Sbostic
99533828Sbostic if( !Cflag ) {
99633828Sbostic /* round c up to an even number */
99733828Sbostic c = (c+1)/2;
99833828Sbostic c *= 2;
99933828Sbostic }
100033828Sbostic while( c ) {
100133828Sbostic if( (Cleft = Bufsize - Ccnt) <= c ) {
100233828Sbostic memcpy( cp, rp, Cleft );
100333828Sbostic rv = write(Output, Cbuf, Bufsize);
100433828Sbostic if( rv == 0 || ( rv == -1 && errno == ENXIO ) ) {
100533828Sbostic rv = eomchgreel();
100633828Sbostic }
100733828Sbostic if( rv == Bufsize ) {
100833828Sbostic Ccnt = 0;
100933828Sbostic cp = Cbuf;
101033828Sbostic }
101133829Sbostic else if( rv == -1 ) {
101233829Sbostic fperrno("Write error on archive");
101333829Sbostic exit(2);
101433829Sbostic }
101533828Sbostic else if( rv < Bufsize ) {
101633828Sbostic Output = chgreel(1, Output, 0);
101733828Sbostic smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv );
101833828Sbostic Ccnt = Bufsize - rv;
101933828Sbostic cp = &Cbuf[ rv ];
102033828Sbostic }
102133828Sbostic ++Blocks;
102233828Sbostic rp += Cleft;
102333828Sbostic c -= Cleft;
102433828Sbostic }
102533828Sbostic else {
102633828Sbostic memcpy( cp, rp, c );
102733828Sbostic Ccnt += c;
102833828Sbostic cp += c;
102933828Sbostic rp += c;
103033828Sbostic c = 0;
103133828Sbostic }
103233828Sbostic }
103333828Sbostic Cp = cp;
103433828Sbostic }
103533828Sbostic
103633828Sbostic
103733828Sbostic static int reelcount = 1; /* used below and in chgreel() */
103833828Sbostic
103933828Sbostic /* Change reel due to reaching end-of-media.
104033828Sbostic Keep trying to get a successful write before considering the
104133828Sbostic change-of-reel as successful.
104233828Sbostic */
104333828Sbostic static
104433828Sbostic int
eomchgreel()104533828Sbostic eomchgreel()
104633828Sbostic {
104733828Sbostic int rv;
104833828Sbostic
104933828Sbostic while( 1 ) {
105033828Sbostic Output = chgreel(1, Output, 0);
105133828Sbostic rv = write(Output, Cbuf, Bufsize);
105233828Sbostic if( rv == Bufsize )
105333828Sbostic return rv;
105433829Sbostic if( rv == -1 )
105533829Sbostic fperrno( "Unable to write this medium" );
105633829Sbostic else
105733829Sbostic fperr( "Unable to write this medium: Premature EOF" );
105833829Sbostic (void) fprintf(stderr, "Try again.\n");
105933828Sbostic reelcount--;
106033828Sbostic }
106133828Sbostic /*NOTREACHED*/
106233828Sbostic }
106333828Sbostic
106433828Sbostic
106533828Sbostic static
postml(namep,np)106633828Sbostic postml(namep, np) /* linking funtion: Postml() is called after */
106733828Sbostic register char *namep, *np; /* namep is created. Postml() checks to see */
106833828Sbostic { /* if namep should be linked to np. If so, */
106933828Sbostic /* postml() removes the independent instance */
107033828Sbostic register i; /* of namep and links namep to np. */
107133828Sbostic static struct ml {
107233828Sbostic short m_dev;
107333828Sbostic ushort m_ino;
107433828Sbostic char m_name[2];
107533828Sbostic } **ml = 0;
107633828Sbostic register struct ml *mlp;
107733828Sbostic static unsigned mlsize = 0;
107833828Sbostic static unsigned mlinks = 0;
107933828Sbostic char *lnamep;
108033828Sbostic int ans;
108133828Sbostic
108233828Sbostic if( !ml ) {
108333828Sbostic mlsize = LINKS;
108433829Sbostic ml = (struct ml **) malloc(mlsize * sizeof(struct ml));
108533828Sbostic }
108633828Sbostic else if( mlinks == mlsize ) {
108733828Sbostic mlsize += LINKS;
108833829Sbostic ml = (struct ml **) realloc((char *) ml,
108933829Sbostic mlsize * sizeof(struct ml));
109033828Sbostic }
109133829Sbostic if (ml == NULL) {
109233829Sbostic fperr("Out of memory for links");
109333829Sbostic exit(2);
109433829Sbostic }
109533828Sbostic for(i = 0; i < mlinks; ++i) {
109633828Sbostic mlp = ml[i];
109733828Sbostic if(mlp->m_ino==Hdr.h_ino && mlp->m_dev==Hdr.h_dev) {
109833828Sbostic if(Verbose)
109933829Sbostic printf("%s linked to %s\n", ml[i]->m_name,
110033829Sbostic np);
110133828Sbostic unlink(namep);
110233828Sbostic if(Option == IN && *(mlp->m_name) != '/') {
110333828Sbostic Fullname[Pathend] = '\0';
110433828Sbostic strcat(Fullname, mlp->m_name);
110533828Sbostic lnamep = Fullname;
110633828Sbostic }
110733828Sbostic lnamep = mlp->m_name;
110833828Sbostic
110933828Sbostic /* try linking (only twice) */
111033828Sbostic ans = 0;
111133828Sbostic do {
111233828Sbostic if(link(lnamep, namep) < 0) {
111333828Sbostic ans += 1;
111433828Sbostic }else {
111533828Sbostic ans = 0;
111633828Sbostic break;
111733828Sbostic }
111833828Sbostic }while(ans < 2 && missdir(np) == 0);
111933828Sbostic if(ans == 1) {
112033828Sbostic fperrno("Cannot create directory for <%s>", np);
112133828Sbostic return(0);
112233828Sbostic }else if(ans == 2) {
112333828Sbostic fperrno("Cannot link <%s> & <%s>", lnamep, np);
112433828Sbostic return(0);
112533828Sbostic }
112633828Sbostic
112733828Sbostic set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
112833828Sbostic return 0;
112933828Sbostic }
113033828Sbostic }
113133829Sbostic if( !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
113233828Sbostic static int first=1;
113333828Sbostic
113433828Sbostic if(first)
113533829Sbostic fperr("Out of memory for links");
113633828Sbostic first = 0;
113733828Sbostic return 1;
113833828Sbostic }
113933828Sbostic ml[mlinks]->m_dev = Hdr.h_dev;
114033828Sbostic ml[mlinks]->m_ino = Hdr.h_ino;
114133828Sbostic strcpy(ml[mlinks]->m_name, np);
114233828Sbostic ++mlinks;
114333828Sbostic return 1;
114433828Sbostic }
114533828Sbostic
114633828Sbostic static
pentry(namep)114733828Sbostic pentry(namep) /* print verbose table of contents */
114833828Sbostic register char *namep;
114933828Sbostic {
115033828Sbostic static short lastid = -1;
115133828Sbostic static struct passwd *pw;
115233828Sbostic static char tbuf[32];
115333828Sbostic char *ctime();
115433828Sbostic
115533828Sbostic printf("%-7o", MK_USHORT(Hdr.h_mode));
115633828Sbostic if(lastid == Hdr.h_uid)
115733828Sbostic printf("%-6s", pw->pw_name);
115833828Sbostic else {
115933828Sbostic setpwent();
116033828Sbostic if(pw = getpwuid((int)Hdr.h_uid)) {
116133828Sbostic printf("%-6s", pw->pw_name);
116233828Sbostic lastid = Hdr.h_uid;
116333828Sbostic } else {
116433828Sbostic printf("%-6d", Hdr.h_uid);
116533828Sbostic lastid = -1;
116633828Sbostic }
116733828Sbostic }
116833828Sbostic printf("%7ld ", mklong(Hdr.h_filesize));
116933828Sbostic U.l = mklong(Hdr.h_mtime);
117033828Sbostic strcpy(tbuf, ctime((long *)&U.l));
117133828Sbostic tbuf[24] = '\0';
117233829Sbostic printf(" %s %s", &tbuf[4], namep);
117333829Sbostic if (A_symlink)
117433829Sbostic printf(" -> %s", Symlbuf);
117533829Sbostic putchar('\n');
117633828Sbostic }
117733828Sbostic
117833828Sbostic /* pattern matching functions */
117933828Sbostic static
nmatch(s,pat)118033828Sbostic nmatch(s, pat)
118133828Sbostic char *s, **pat;
118233828Sbostic {
118333828Sbostic if( !pat )
118433828Sbostic return 1;
118533828Sbostic while(*pat) {
118633828Sbostic if((**pat == '!' && !gmatch(s, *pat+1))
118733828Sbostic || gmatch(s, *pat))
118833828Sbostic return 1;
118933828Sbostic ++pat;
119033828Sbostic }
119133828Sbostic return 0;
119233828Sbostic }
119333828Sbostic
119433828Sbostic
119533828Sbostic static
gmatch(s,p)119633828Sbostic gmatch(s, p)
119733828Sbostic register char *s, *p;
119833828Sbostic {
119933828Sbostic register int c;
120033828Sbostic register cc, ok, lc, scc;
120133828Sbostic
120233828Sbostic scc = *s;
120333828Sbostic lc = 077777;
120433828Sbostic switch (c = *p) {
120533828Sbostic
120633828Sbostic case '[':
120733828Sbostic ok = 0;
120833828Sbostic while (cc = *++p) {
120933828Sbostic switch (cc) {
121033828Sbostic
121133828Sbostic case ']':
121233828Sbostic if (ok)
121333828Sbostic return(gmatch(++s, ++p));
121433828Sbostic else
121533828Sbostic return(0);
121633828Sbostic
121733828Sbostic case '-':
121833828Sbostic ok |= ((lc <= scc) && (scc <= (cc=p[1])));
121933828Sbostic }
122033828Sbostic if (scc==(lc=cc)) ok++;
122133828Sbostic }
122233828Sbostic return(0);
122333828Sbostic
122433828Sbostic case '?':
122533828Sbostic caseq:
122633828Sbostic if(scc) return(gmatch(++s, ++p));
122733828Sbostic return(0);
122833828Sbostic case '*':
122933828Sbostic return(umatch(s, ++p));
123033828Sbostic case 0:
123133828Sbostic return(!scc);
123233828Sbostic }
123333828Sbostic if (c==scc) goto caseq;
123433828Sbostic return(0);
123533828Sbostic }
123633828Sbostic
123733828Sbostic
123833828Sbostic
123933828Sbostic static
umatch(s,p)124033828Sbostic umatch(s, p)
124133828Sbostic register char *s, *p;
124233828Sbostic {
124333828Sbostic if(*p==0) return(1);
124433828Sbostic while(*s)
124533828Sbostic if (gmatch(s++,p)) return(1);
124633828Sbostic return(0);
124733828Sbostic }
124833828Sbostic
swap(buf,bytecount,bytes,halfwords)124933829Sbostic swap(buf, bytecount, bytes, halfwords) /* swap halfwords, bytes or both */
125033829Sbostic char *buf;
125133829Sbostic int bytecount;
125233829Sbostic int bytes, halfwords;
125333828Sbostic {
125433829Sbostic register int count;
125533829Sbostic int n, i;
125633828Sbostic
125733829Sbostic if(bytes) {
125833829Sbostic register union swpbytes {
125933829Sbostic short shortw;
126033829Sbostic char charv[2];
126133829Sbostic } *pbuf;
126233829Sbostic register char c;
126333828Sbostic
126433829Sbostic count = bytecount;
126533829Sbostic pbuf = (union swpbytes *)buf;
126633829Sbostic if (count % sizeof(union swpbytes))
126733829Sbostic pbuf->charv[count] = 0;
126833829Sbostic count = (count + (sizeof(union swpbytes) - 1)) / sizeof(union swpbytes);
126933829Sbostic while (count--) {
127033829Sbostic c = pbuf->charv[0];
127133829Sbostic pbuf->charv[0] = pbuf->charv[1];
127233829Sbostic pbuf->charv[1] = c;
127333829Sbostic ++pbuf;
127433828Sbostic }
127533828Sbostic }
127633829Sbostic if (halfwords) {
127733829Sbostic register union swphalf {
127833829Sbostic long longw;
127933829Sbostic short shortv[2];
128033829Sbostic char charv[4];
128133829Sbostic } *pbuf;
128233829Sbostic register short cc;
128333829Sbostic
128433829Sbostic count = bytecount;
128533829Sbostic pbuf = (union swphalf *)buf;
128633829Sbostic if (n = count % sizeof(union swphalf))
128733829Sbostic if(bytes && n % 2)
128833829Sbostic for(i = count + 1; i <= count + (sizeof(union swphalf) - n); i++)
128933829Sbostic pbuf->charv[i] = 0;
129033829Sbostic else
129133829Sbostic for (i = count; i < count + (sizeof(union swphalf) - n); i++)
129233829Sbostic pbuf->charv[i] = 0;
129333829Sbostic count = (count + (sizeof(union swphalf) - 1)) / sizeof(union swphalf);
129433829Sbostic while (count--) {
129533828Sbostic cc = pbuf->shortv[0];
129633828Sbostic pbuf->shortv[0] = pbuf->shortv[1];
129733828Sbostic pbuf->shortv[1] = cc;
129833828Sbostic ++pbuf;
129933828Sbostic }
130033828Sbostic }
130133828Sbostic }
130233828Sbostic
130333828Sbostic
130433828Sbostic static
set_time(namep,atime,mtime)130533828Sbostic set_time(namep, atime, mtime) /* set access and modification times */
130633828Sbostic register char *namep;
130733828Sbostic time_t atime, mtime;
130833828Sbostic {
130933829Sbostic static struct utimbuf timevec;
131033828Sbostic
131133828Sbostic if(!Mod_time)
131233828Sbostic return;
131333829Sbostic timevec.actime = atime;
131433829Sbostic timevec.modtime = mtime;
131533829Sbostic (void)utime(namep, &timevec);
131633828Sbostic }
131733828Sbostic
131833828Sbostic
131933828Sbostic
132033828Sbostic static
chgreel(x,fl,rv)132133828Sbostic chgreel(x, fl, rv)
1322*46224Storek int x, fl, rv;
132333828Sbostic {
132433828Sbostic register f;
132533828Sbostic char str[BUFSIZ];
132633828Sbostic struct stat statb;
132733828Sbostic
132833828Sbostic fstat(fl, &statb);
132933828Sbostic if((statb.st_mode&S_IFMT) != S_IFCHR) {
133033828Sbostic fperrno("Can't %s: ", x? "write output": "read input");
133133828Sbostic exit(2);
133233828Sbostic }
133333828Sbostic if( rv == 0 ||
133433828Sbostic ( rv == -1 && ( errno == ENOSPC || errno == ENXIO ) ) )
133533829Sbostic fperr( "\007Reached end of medium on %s",
133633828Sbostic x? "output":"input" );
133733828Sbostic else {
133833828Sbostic fperrno( "\007Encountered an error on %s",
133933828Sbostic x? "output":"input" );
134033828Sbostic exit(2);
134133828Sbostic }
134233829Sbostic if( Rtty == NULL ) {
134333829Sbostic Rtty = fopen(ttyname, "r");
134433829Sbostic if( Rtty == NULL ) {
134533829Sbostic fperrno("Cannot prompt (can't open %s)", ttyname);
134633829Sbostic exit(2);
134733829Sbostic }
134833829Sbostic }
134933828Sbostic close(fl);
135033828Sbostic reelcount++;
135133828Sbostic again:
135233828Sbostic if( swfile ) {
135333828Sbostic askagain:
135433828Sbostic fperr( eommsg, reelcount );
135533828Sbostic fgets(str, sizeof str, Rtty);
135633828Sbostic switch( *str ) {
135733828Sbostic case '\n':
135833828Sbostic strcpy( str, swfile );
135933828Sbostic break;
136033828Sbostic case 'q':
136133828Sbostic exit(2);
136233828Sbostic default:
136333828Sbostic goto askagain;
136433828Sbostic }
136533828Sbostic }
136633828Sbostic else {
136733829Sbostic fperr("If you want to go on, type device/file name when ready.");
136833828Sbostic fgets(str, sizeof str, Rtty);
136933828Sbostic str[strlen(str) - 1] = '\0';
137033828Sbostic if(!*str)
137133828Sbostic exit(2);
137233828Sbostic }
137333828Sbostic if((f = open(str, x? 1: 0)) < 0) {
137433829Sbostic fperrno("Can't open <%s>", str);
137533828Sbostic goto again;
137633828Sbostic }
137733828Sbostic return f;
137833828Sbostic }
137933828Sbostic
138033828Sbostic
138133828Sbostic
138233828Sbostic static
missdir(namep)138333828Sbostic missdir(namep)
138433828Sbostic register char *namep;
138533828Sbostic {
138633828Sbostic register char *np;
138733828Sbostic register ct = 2;
138833828Sbostic
138933828Sbostic for(np = namep; *np; ++np)
139033828Sbostic if(*np == '/') {
139133828Sbostic if(np == namep) continue; /* skip over 'root slash' */
139233828Sbostic *np = '\0';
139333828Sbostic if(stat(namep, &Xstatb) == -1) {
139433828Sbostic if(Dir) {
139533829Sbostic if((ct = mkdir(namep, 0777)) != 0) {
139633828Sbostic *np = '/';
139733828Sbostic return(ct);
139833828Sbostic }
139933828Sbostic }else {
140033829Sbostic fperr("missing 'd' option");
140133828Sbostic return(-1);
140233828Sbostic }
140333828Sbostic }
140433828Sbostic *np = '/';
140533828Sbostic }
140633828Sbostic if (ct == 2) ct = 0; /* the file already exists */
140733828Sbostic return ct;
140833828Sbostic }
140933828Sbostic
141033828Sbostic
141133828Sbostic
141233828Sbostic static
pwd()141333828Sbostic pwd() /* get working directory */
141433828Sbostic {
141533829Sbostic if (getwd(Fullname) == 0) {
141633829Sbostic (void)fprintf(stderr, "cpio: %s\n",
141733829Sbostic Fullname);
141833828Sbostic exit(2);
141933829Sbostic }
142033828Sbostic Pathend = strlen(Fullname);
142133829Sbostic Fullname[Pathend++] = '/';
142233829Sbostic Fullname[Pathend] = '\0';
142333828Sbostic }
142433828Sbostic
142533828Sbostic
142633828Sbostic /*
142733828Sbostic print message on the stderr
142833828Sbostic */
142933828Sbostic static
fperr(va_alist)143033828Sbostic fperr( va_alist )
143133828Sbostic va_dcl
143233828Sbostic {
143333828Sbostic va_list args;
143433828Sbostic char *fmt;
143533828Sbostic
143633828Sbostic va_start( args );
143733829Sbostic fprintf( stderr, "cpio: ");
143833828Sbostic fmt = va_arg( args, char * );
143933828Sbostic vfprintf( stderr, fmt, args );
144033829Sbostic putc( '\n', stderr);
144133828Sbostic fflush( stderr );
144233828Sbostic }
144333828Sbostic
144433828Sbostic /*
144533828Sbostic print message on the stderr followed by error number and meaning.
144633828Sbostic */
144733828Sbostic static
fperrno(va_alist)144833828Sbostic fperrno( va_alist )
144933828Sbostic va_dcl
145033828Sbostic {
145133828Sbostic va_list args;
145233828Sbostic char *fmt;
145333828Sbostic
145433828Sbostic va_start( args );
145533829Sbostic fprintf( stderr, "cpio: ");
145633828Sbostic fmt = va_arg( args, char * );
145733828Sbostic vfprintf( stderr, fmt, args );
145833829Sbostic fprintf( stderr, ": " );
145933828Sbostic fflush( stderr );
146033828Sbostic perror("");
146133828Sbostic }
146233828Sbostic
146333828Sbostic
146433829Sbostic /* Safe memory copy.
146533829Sbostic Fast if the to and from strings do not overlap,
146633829Sbostic slower but safe if they do.
146733829Sbostic */
146833829Sbostic
146933829Sbostic static char *
smemcpy(to,from,count)147033829Sbostic smemcpy( to, from, count )
147133829Sbostic register char *to, *from;
147233829Sbostic register unsigned count;
147333828Sbostic {
147433829Sbostic char *savedto;
147533829Sbostic
147633829Sbostic if( &to[ count ] <= from || &from[ count ] <= to )
147733829Sbostic return memcpy( to, from, count );
147833829Sbostic
147933829Sbostic if( to == from )
148033829Sbostic return to;
148133829Sbostic
148233829Sbostic savedto = to;
148333829Sbostic if( to < from )
148433829Sbostic while( count-- )
148533829Sbostic *(to++) = *(from++);
148633829Sbostic else {
148733829Sbostic to += count;
148833829Sbostic from += count;
148933829Sbostic while( count-- )
149033829Sbostic *(--to) = *(--from);
149133828Sbostic }
149233828Sbostic
149333829Sbostic return savedto;
149433828Sbostic }
1495