111240Smckusick /* Copyright (c) 1983 Regents of the University of California */
211240Smckusick
311240Smckusick #ifndef lint
4*33397Smckusick static char sccsid[] = "@(#)cpio.c 4.3 (Berkeley) 01/26/88";
511240Smckusick #endif not lint
611240Smckusick
711240Smckusick /* cpio COMPILE: cc -O cpio.c -s -i -o cpio
811240Smckusick cpio -- copy file collections
911240Smckusick
1011240Smckusick */
1111240Smckusick #include <stdio.h>
1211240Smckusick #include <sys/types.h>
1311240Smckusick #include <sys/stat.h>
1411240Smckusick #include <signal.h>
1511240Smckusick #ifdef RT
1611240Smckusick #define S_IFEXT 0120000 /* allocated by extents */
1711240Smckusick #define S_IF1EXT 0130000 /* one extent */
1811240Smckusick #endif
1911240Smckusick #define EQ(x,y) (strcmp(x,y)==0)
2011240Smckusick /* for VAX, Interdata, ... */
2111240Smckusick #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];}
2211240Smckusick #define MAGIC 070707
2311240Smckusick #define IN 1
2411240Smckusick #define OUT 2
2511240Smckusick #define PASS 3
2611240Smckusick #define HDRSIZE ((sizeof Hdr)-256)
2711240Smckusick #define LINKS 1000
2811240Smckusick #define MERT 0
2911240Smckusick #define CHARS 76
3011240Smckusick #ifdef RT
3111240Smckusick #define MERT 1 /* yes = 1 ; no = 0 */
3211240Smckusick extern long filespace;
3311240Smckusick #endif
3411240Smckusick
3511240Smckusick struct stat Statb, Xstatb;
3611240Smckusick
3711240Smckusick struct header {
3811240Smckusick short h_magic,
3911240Smckusick h_dev;
4011240Smckusick unsigned short h_ino,
4111240Smckusick h_mode,
4211240Smckusick h_uid,
4311240Smckusick h_gid;
4411240Smckusick short h_nlink,
4511240Smckusick h_rdev,
4611240Smckusick h_mtime[2],
4711240Smckusick h_namesize,
4811240Smckusick h_filesize[2];
4911240Smckusick char h_name[256];
5011240Smckusick } Hdr;
5111240Smckusick
5211240Smckusick int Bufsize = 512;
5311240Smckusick short Buf[256], *Dbuf;
5411240Smckusick char BBuf[512];
5511240Smckusick char *Cbuf;
5611240Smckusick int Wct,Wc;
5711240Smckusick short *Wp;
5811240Smckusick char *Cp;
5911240Smckusick #ifdef RT
6011240Smckusick short Actual_size[2]; /* MERT variable */
6111240Smckusick struct{
6211240Smckusick long long_size;
6311240Smckusick };
6411240Smckusick #endif
6511240Smckusick
6611240Smckusick short Option,
6711240Smckusick Dir,
6811240Smckusick Uncond,
6911240Smckusick Link,
7011240Smckusick Rename,
7111240Smckusick Toc,
7211240Smckusick Verbose,
7311240Smckusick Select,
7411240Smckusick Mod_time,
7511240Smckusick Acc_time,
7611240Smckusick Cflag,
7711240Smckusick Swap;
7811240Smckusick
7911240Smckusick int Ifile,
8011240Smckusick Ofile,
8111240Smckusick Input = 0,
8211240Smckusick Output = 1;
8311240Smckusick long Blocks,
8411240Smckusick Longfile,
8511240Smckusick Longtime;
8611240Smckusick
8711240Smckusick char Fullname[256],
8811240Smckusick Name[256];
8911240Smckusick int Pathend;
9011240Smckusick
9111240Smckusick FILE *Rtty,
9211240Smckusick *Wtty;
9311240Smckusick
9411240Smckusick char *Pattern[100];
9511240Smckusick char Strhdr[500];
9611240Smckusick char *Chdr = Strhdr;
9711240Smckusick short Dev,
9811240Smckusick Uid,
9911240Smckusick Gid,
10011240Smckusick A_directory,
10111240Smckusick A_special,
10211240Smckusick #ifdef RT
10311240Smckusick One_extent,
10411240Smckusick Multi_extent,
10511240Smckusick #endif
10611240Smckusick Filetype = S_IFMT;
10711240Smckusick #ifdef RT
10811240Smckusick short Remove_mode = 0007777;
10911240Smckusick short New_mode;
11011240Smckusick #endif
11111240Smckusick
11211240Smckusick extern errno;
11311240Smckusick char *malloc();
11411240Smckusick char *cd();
11511240Smckusick char *Cd_name;
11611240Smckusick FILE *popen();
11711240Smckusick
11811240Smckusick union { long l; short s[2]; char c[4]; } U;
11911240Smckusick
12011240Smckusick /* for VAX, Interdata, ... */
mklong(v)12111240Smckusick long mklong(v)
12211240Smckusick short v[];
12311240Smckusick {
12411240Smckusick U.l = 1;
12511240Smckusick if(U.c[0])
12611240Smckusick U.s[0] = v[1], U.s[1] = v[0];
12711240Smckusick else
12811240Smckusick U.s[0] = v[0], U.s[1] = v[1];
12911240Smckusick return U.l;
13011240Smckusick }
13111240Smckusick
main(argc,argv)13211240Smckusick main(argc, argv)
13311240Smckusick char **argv;
13411240Smckusick {
13511240Smckusick register ct;
13611240Smckusick long filesz;
13711240Smckusick long lng;
13811240Smckusick register char *fullp;
13911240Smckusick register i;
14011240Smckusick
14111240Smckusick signal(SIGSYS, 1);
14211240Smckusick if(*argv[1] != '-')
14311240Smckusick usage();
14411240Smckusick Uid = getuid();
14511240Smckusick umask(0);
14611240Smckusick Gid = getgid();
14711240Smckusick Pattern[0] = "*";
14811240Smckusick
14911240Smckusick while(*++argv[1]) {
15011240Smckusick switch(*argv[1]) {
15111240Smckusick case 'a':
15211240Smckusick Acc_time++;
15311240Smckusick break;
15411240Smckusick case 'B':
15511240Smckusick Bufsize = 5120;
15611240Smckusick break;
15711240Smckusick case 'i':
15811240Smckusick Option = IN;
15911240Smckusick if(argc > 2 ) {
16011240Smckusick for(i = 0; (i+2) < argc; ++i)
16111240Smckusick Pattern[i] = argv[i+2];
16211240Smckusick }
16311240Smckusick break;
16411240Smckusick case 'o':
16511240Smckusick if(argc != 2)
16611240Smckusick usage();
16711240Smckusick Option = OUT;
16811240Smckusick break;
16911240Smckusick case 'p':
17011240Smckusick if(argc != 3)
17111240Smckusick usage();
17211240Smckusick if(access(argv[2], 2) == -1) {
17311240Smckusick accerr:
17411240Smckusick err("cannot write in <%s>\n", argv[2]);
17511240Smckusick exit(2);
17611240Smckusick }
17711240Smckusick strcpy(Fullname, argv[2]);
17811240Smckusick strcat(Fullname, "/");
17911240Smckusick stat(Fullname, &Xstatb);
18011240Smckusick if((Xstatb.st_mode&S_IFMT) != S_IFDIR)
18111240Smckusick goto accerr;
18211240Smckusick Option = PASS;
18311240Smckusick Dev = Xstatb.st_dev;
18411240Smckusick break;
18511240Smckusick case 'c':
18611240Smckusick Cflag++;
18711240Smckusick break;
18811240Smckusick case 'd':
18911240Smckusick Dir++;
19011240Smckusick break;
19111240Smckusick case 'l':
19211240Smckusick Link++;
19311240Smckusick break;
19411240Smckusick case 'm':
19511240Smckusick Mod_time++;
19611240Smckusick break;
19711240Smckusick case 'r':
19811240Smckusick Rename++;
19911240Smckusick Rtty = fopen("/dev/tty", "r");
20011240Smckusick Wtty = fopen("/dev/tty", "w");
20111240Smckusick if(Rtty==NULL || Wtty==NULL) {
20211240Smckusick err(
20311240Smckusick "Cannot rename (/dev/tty missing)\n");
20411240Smckusick exit(2);
20511240Smckusick }
20611240Smckusick break;
20711240Smckusick case 's':
20811240Smckusick Swap++;
20911240Smckusick break;
21011240Smckusick case 't':
21111240Smckusick Toc++;
21211240Smckusick break;
21311240Smckusick case 'u':
21411240Smckusick Uncond++;
21511240Smckusick break;
21611240Smckusick case 'v':
21711240Smckusick Verbose++;
21811240Smckusick break;
21911240Smckusick case '6':
22011240Smckusick Filetype = 060000;
22111240Smckusick break;
22211240Smckusick default:
22311240Smckusick usage();
22411240Smckusick }
22511240Smckusick }
22611240Smckusick if(!Option) {
22711240Smckusick err("Options must include o|i|p\n");
22811240Smckusick exit(2);
22911240Smckusick }
23011240Smckusick
23111240Smckusick if (Cflag && Swap) {
23211240Smckusick err("Swap flag is ignored with Cflag\n");
23311240Smckusick Swap = 0;
23411240Smckusick }
23511240Smckusick
23611240Smckusick if(Option != PASS) {
23711240Smckusick Wp = Dbuf = (short *)malloc(Bufsize);
23811240Smckusick Cp = Cbuf = (char *)malloc(Bufsize);
23911240Smckusick }
24011240Smckusick Wct = Bufsize >> 1;
24111240Smckusick Wc = Bufsize;
24211240Smckusick
24311240Smckusick if(Option == PASS && Rename) {
24411240Smckusick err("Pass and Rename cannot be used together");
24511240Smckusick exit(2);
24611240Smckusick }
24711240Smckusick switch(Option) {
24811240Smckusick
24911240Smckusick case OUT:
25011240Smckusick while(getname()) {
25111240Smckusick if( mklong(Hdr.h_filesize) == 0L) {
25211240Smckusick if ( Cflag )
25311240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize);
25411240Smckusick else
25511240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
25611240Smckusick #ifdef RT
25711240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
25811240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
25911240Smckusick actsize();
26011240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
26111240Smckusick }
26211240Smckusick #endif
26311240Smckusick continue;
26411240Smckusick }
26511240Smckusick if((Ifile = open(Hdr.h_name, 0)) < 0) {
26611240Smckusick err("<%s> ?\n", Hdr.h_name);
26711240Smckusick continue;
26811240Smckusick }
26911240Smckusick if ( Cflag )
27011240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize);
27111240Smckusick else
27211240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
27311240Smckusick #ifdef RT
27411240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
27511240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
27611240Smckusick actsize();
27711240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
27811240Smckusick }
27911240Smckusick #endif
28011240Smckusick for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
28111240Smckusick ct = filesz>512? 512: filesz;
28211240Smckusick if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) {
28311240Smckusick err("Cannot read %s\n", Hdr.h_name);
28411240Smckusick continue;
28511240Smckusick }
28611240Smckusick Cflag? writehdr(BBuf,ct): bwrite(Buf,ct);
28711240Smckusick }
28811240Smckusick close(Ifile);
28911240Smckusick if(Acc_time)
29011240Smckusick utime(Hdr.h_name, &Statb.st_atime);
29111240Smckusick if(Verbose)
29211240Smckusick err("%s\n", Hdr.h_name);
29311240Smckusick }
29411240Smckusick strcpy(Hdr.h_name, "TRAILER!!!");
29511240Smckusick Hdr.h_magic = MAGIC;
29611240Smckusick MKSHORT(Hdr.h_filesize, 0L);
29711240Smckusick Hdr.h_namesize = strlen("TRAILER!!!") + 1;
29811240Smckusick if ( Cflag ) {
29911240Smckusick lng = 0;
30011240Smckusick bintochar(lng);
30111240Smckusick writehdr(Chdr,CHARS+Hdr.h_namesize);
30211240Smckusick }
30311240Smckusick else
30411240Smckusick bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
30511240Smckusick Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize);
30611240Smckusick break;
30711240Smckusick
30811240Smckusick case IN:
30911240Smckusick pwd();
31011240Smckusick while(gethdr()) {
31111240Smckusick Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0;
31211240Smckusick for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
31311240Smckusick ct = filesz>512? 512: filesz;
31411240Smckusick Cflag? readhdr(BBuf, ct): bread(Buf, ct);
31511240Smckusick if(Ofile) {
31611240Smckusick if(Swap)
31711240Smckusick swap(Buf, ct);
31811240Smckusick if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) {
31911240Smckusick err("Cannot write %s\n", Hdr.h_name);
32011240Smckusick continue;
32111240Smckusick }
32211240Smckusick }
32311240Smckusick }
32411240Smckusick if(Ofile) {
32511240Smckusick close(Ofile);
32611240Smckusick set_time(Cd_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
32711240Smckusick }
32811240Smckusick if(!Select)
32911240Smckusick continue;
33011240Smckusick if(Verbose)
33111240Smckusick if(Toc)
33211240Smckusick pentry(Hdr.h_name);
33311240Smckusick else
33411240Smckusick puts(Hdr.h_name);
33511240Smckusick else if(Toc)
33611240Smckusick puts(Hdr.h_name);
33711240Smckusick }
33811240Smckusick break;
33911240Smckusick
34011240Smckusick case PASS:
34111240Smckusick fullp = Fullname + strlen(Fullname);
34211240Smckusick
34311240Smckusick while(getname()) {
34411240Smckusick if(!ckname(Hdr.h_name))
34511240Smckusick continue;
34611240Smckusick strcpy(fullp, Hdr.h_name);
34711240Smckusick
34811240Smckusick if(Link
34911240Smckusick && !A_directory
35011240Smckusick && Dev == Statb.st_dev) {
35111240Smckusick /* ??? && (Uid == Statb.st_uid || !Uid)) {*/
35211240Smckusick if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
35311240Smckusick unlink(Fullname);
35411240Smckusick missdir(Fullname);
35511240Smckusick if(link(Hdr.h_name, Fullname) < 0) {
35611240Smckusick err(
35711240Smckusick "Cannot link <%s> & <%s>\n",
35811240Smckusick Hdr.h_name, Fullname);
35911240Smckusick continue;
36011240Smckusick }
36111240Smckusick }
36211240Smckusick set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
36311240Smckusick goto ckverbose;
36411240Smckusick }
36511240Smckusick if(!(Ofile = openout(Fullname)))
36611240Smckusick continue;
36711240Smckusick if((Ifile = open(Hdr.h_name, 0)) < 0) {
36811240Smckusick err("<%s> ?\n", Hdr.h_name);
36911240Smckusick close(Ofile);
37011240Smckusick continue;
37111240Smckusick }
37211240Smckusick filesz = Statb.st_size;
37311240Smckusick for(; filesz > 0; filesz -= 512) {
37411240Smckusick ct = filesz>512? 512: filesz;
37511240Smckusick if(read(Ifile, Buf, ct) < 0) {
37611240Smckusick err("Cannot read %s\n", Hdr.h_name);
37711240Smckusick break;
37811240Smckusick }
37911240Smckusick if(Ofile)
38011240Smckusick if(write(Ofile, Buf, ct) < 0) {
38111240Smckusick err("Cannot write %s\n", Hdr.h_name);
38211240Smckusick break;
38311240Smckusick }
38411240Smckusick ++Blocks;
38511240Smckusick }
38611240Smckusick close(Ifile);
38711240Smckusick if(Acc_time)
38811240Smckusick utime(Hdr.h_name, &Statb.st_atime);
38911240Smckusick if(Ofile) {
39011240Smckusick close(Ofile);
39111240Smckusick set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
39211240Smckusick ckverbose:
39311240Smckusick if(Verbose)
39411240Smckusick puts(Fullname);
39511240Smckusick }
39611240Smckusick }
39711240Smckusick }
39811240Smckusick err("%ld blocks\n", Blocks * (Bufsize>>9));
39911240Smckusick exit(0);
40011240Smckusick }
usage()40111240Smckusick usage()
40211240Smckusick {
40311240Smckusick err("Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n",
40411240Smckusick " cpio -i[cdmrstuvB6] [pattern ...] <collection",
40511240Smckusick " cpio -p[adlmruv] directory <name-list");
40611240Smckusick exit(2);
40711240Smckusick }
40811240Smckusick
getname()40911240Smckusick getname()
41011240Smckusick {
41111240Smckusick register char *namep = Name;
41211240Smckusick long tlong;
41311240Smckusick
41411240Smckusick for(;;) {
41511240Smckusick if(gets(namep) == NULL)
41611240Smckusick return 0;
41711240Smckusick if(*namep == '.' && namep[1] == '/')
41811240Smckusick namep += 2;
41911240Smckusick strcpy(Hdr.h_name, namep);
42011240Smckusick if(stat(namep, &Statb) < 0) {
42111240Smckusick err("< %s > ?\n", Hdr.h_name);
42211240Smckusick continue;
42311240Smckusick }
42411240Smckusick A_directory = (Statb.st_mode & Filetype) == S_IFDIR;
42511240Smckusick A_special = ((Statb.st_mode & Filetype) == S_IFBLK)
42611240Smckusick || ((Statb.st_mode & Filetype) == S_IFCHR);
42711240Smckusick #ifdef RT
42811240Smckusick if(MERT) {
42911240Smckusick One_extent = (Statb.st_mode & Filetype) == S_IF1EXT;
43011240Smckusick Multi_extent = (Statb.st_mode & Filetype) == S_IFEXT;
43111240Smckusick }
43211240Smckusick #endif
43311240Smckusick Hdr.h_magic = MAGIC;
43411240Smckusick Hdr.h_namesize = strlen(Hdr.h_name) + 1;
43511240Smckusick Hdr.h_uid = Statb.st_uid;
43611240Smckusick Hdr.h_gid = Statb.st_gid;
43711240Smckusick Hdr.h_dev = Statb.st_dev;
43811240Smckusick Hdr.h_ino = Statb.st_ino;
43911240Smckusick Hdr.h_mode = Statb.st_mode;
44011240Smckusick MKSHORT(Hdr.h_mtime, Statb.st_mtime);
44111240Smckusick Hdr.h_nlink = Statb.st_nlink;
44211240Smckusick tlong = Hdr.h_mode & S_IFREG? Statb.st_size: 0L;
44311240Smckusick MKSHORT(Hdr.h_filesize, tlong);
44411240Smckusick Hdr.h_rdev = Statb.st_rdev;
44511240Smckusick if(Cflag)
44611240Smckusick bintochar(tlong);
44711240Smckusick return 1;
44811240Smckusick }
44911240Smckusick }
45011240Smckusick
bintochar(t)45111240Smckusick bintochar(t)
45211240Smckusick long t;
45311240Smckusick {
45411240Smckusick sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
45511240Smckusick MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,Statb.st_uid,
45611240Smckusick Statb.st_gid,Statb.st_nlink,Statb.st_rdev & 00000177777,
45711240Smckusick Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name);
45811240Smckusick }
45911240Smckusick
chartobin()46011240Smckusick chartobin()
46111240Smckusick {
462*33397Smckusick sscanf(Chdr,"%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
46311240Smckusick &Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid,
46411240Smckusick &Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize,
46511240Smckusick &Longfile);
46611240Smckusick MKSHORT(Hdr.h_filesize, Longfile);
46711240Smckusick MKSHORT(Hdr.h_mtime, Longtime);
46811240Smckusick }
46911240Smckusick
gethdr()47011240Smckusick gethdr()
47111240Smckusick {
47211240Smckusick
47311240Smckusick if ( Cflag ) {
47411240Smckusick readhdr(Chdr,CHARS);
47511240Smckusick chartobin();
47611240Smckusick }
47711240Smckusick else
47811240Smckusick bread(&Hdr, HDRSIZE);
47911240Smckusick
48011240Smckusick if(Hdr.h_magic != MAGIC) {
48127508Sbloom err("Out of phase--get help\n");
48211240Smckusick exit(2);
48311240Smckusick }
48411240Smckusick if(!Cflag)
48511240Smckusick bread(Hdr.h_name, Hdr.h_namesize);
48611240Smckusick else
48711240Smckusick readhdr(Hdr.h_name, Hdr.h_namesize);
48811240Smckusick if(Swap)
48911240Smckusick swap(Hdr.h_name, Hdr.h_namesize);
49011240Smckusick if(EQ(Hdr.h_name, "TRAILER!!!"))
49111240Smckusick return 0;
49211240Smckusick A_directory = (Hdr.h_mode & Filetype) == S_IFDIR;
49311240Smckusick A_special =((Hdr.h_mode & Filetype) == S_IFBLK)
49411240Smckusick || ((Hdr.h_mode & Filetype) == S_IFCHR);
49511240Smckusick #ifdef RT
49611240Smckusick if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
49711240Smckusick || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
49811240Smckusick One_extent = (Hdr.h_mode & Filetype) == S_IF1EXT;
49911240Smckusick Multi_extent = (Hdr.h_mode & Filetype) == S_IFEXT;
50011240Smckusick Actual_size[0] = Hdr.h_filesize[0];
50111240Smckusick Actual_size[1] = Hdr.h_filesize[1];
50211240Smckusick bread(&Hdr, HDRSIZE);
50311240Smckusick if(Hdr.h_magic != MAGIC) {
50427508Sbloom err("Out of phase--get MERT help\n");
50511240Smckusick exit(2);
50611240Smckusick }
50711240Smckusick bread(Hdr.h_name, Hdr.h_namesize);
50811240Smckusick }
50911240Smckusick #endif
51011240Smckusick return 1;
51111240Smckusick }
51211240Smckusick
ckname(namep)51311240Smckusick ckname(namep)
51411240Smckusick register char *namep;
51511240Smckusick {
51611240Smckusick ++Select;
51711240Smckusick if(!nmatch(namep, Pattern)) {
51811240Smckusick Select = 0;
51911240Smckusick return 0;
52011240Smckusick }
52111240Smckusick if(Rename && !A_directory) {
52211240Smckusick fprintf(Wtty, "Rename <%s>\n", namep);
52311240Smckusick fflush(Wtty);
52411240Smckusick fgets(namep, 128, Rtty);
52511240Smckusick if(feof(Rtty))
52611240Smckusick exit(2);
52711240Smckusick namep[strlen(namep) - 1] = '\0';
52811240Smckusick if(EQ(namep, "")) {
52911240Smckusick printf("Skipped\n");
53011240Smckusick return 0;
53111240Smckusick }
53211240Smckusick }
53311240Smckusick return !Toc;
53411240Smckusick }
53511240Smckusick
openout(namep)53611240Smckusick openout(namep)
53711240Smckusick register char *namep;
53811240Smckusick {
53911240Smckusick register f;
54011240Smckusick register char *np;
54111240Smckusick
54211240Smckusick if(!strncmp(namep, "./", 2))
54311240Smckusick namep += 2;
54411240Smckusick np = namep;
54511240Smckusick if(Option == IN)
54611240Smckusick Cd_name = namep = cd(namep);
54711240Smckusick if(A_directory) {
54811240Smckusick if(!Dir
54911240Smckusick || Rename
55011240Smckusick || EQ(namep, ".")
55111240Smckusick || EQ(namep, "..")
55211240Smckusick || stat(namep, &Xstatb) == 0)
55311240Smckusick return 0;
55411240Smckusick
55511240Smckusick if(!makdir(namep)) {
55611240Smckusick missdir(namep);
55711240Smckusick }
55811240Smckusick ret:
55911240Smckusick chmod(namep, Hdr.h_mode);
56011240Smckusick if(Uid == 0)
56111240Smckusick chown(namep, Hdr.h_uid, Hdr.h_gid);
56211240Smckusick set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
56311240Smckusick return 0;
56411240Smckusick }
56511240Smckusick if(Hdr.h_nlink > 1)
56611240Smckusick if(!postml(namep, np))
56711240Smckusick return 0;
56811240Smckusick if(A_special) {
56911240Smckusick s_again:
57011240Smckusick if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
57111240Smckusick if(missdir(namep))
57211240Smckusick goto s_again;
57311240Smckusick err("Cannot mknod <%s>\n", namep);
57411240Smckusick return 0;
57511240Smckusick }
57611240Smckusick goto ret;
57711240Smckusick }
57811240Smckusick if(stat(namep, &Xstatb) == 0) {
57911240Smckusick if(Uncond && !(Xstatb.st_mode & S_IWRITE))
58011240Smckusick unlink(namep);
58111240Smckusick if(!Uncond && (mklong(Hdr.h_mtime) < Xstatb.st_mtime)) {
58211240Smckusick err("current <%s> newer\n", namep);
58311240Smckusick return 0;
58411240Smckusick }
58511240Smckusick }
58611240Smckusick if(Option == PASS
58711240Smckusick && Hdr.h_ino == Xstatb.st_ino
58811240Smckusick && Hdr.h_dev == Xstatb.st_dev) {
58911240Smckusick err("Attempt to pass file to self!\n");
59011240Smckusick exit(2);
59111240Smckusick }
59211240Smckusick #ifdef RT
59311240Smckusick one_again:
59411240Smckusick if(One_extent || Multi_extent) {
59511240Smckusick if((f = falloc(namep, Hdr.h_mode, Hdr.h_filesize[0].long_size)) < 0) {
59611240Smckusick if(missdir(namep))
59711240Smckusick goto one_again;
59811240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno);
59911240Smckusick return 0;
60011240Smckusick }
60111240Smckusick if(filespace < Hdr.h_filesize[0].long_size){
60211240Smckusick err("Cannot create contiguous file <%s> proper size\n", namep);
60311240Smckusick err(" <%s> will be created as a regular file\n", namep);
60411240Smckusick if(unlink(Fullname) != 0)
60511240Smckusick err("<%s> not removed\n", namep);
60611240Smckusick New_mode = Hdr.h_mode & Remove_mode;
60711240Smckusick New_mode = New_mode | S_IFREG;
60811240Smckusick once_again:
60911240Smckusick if((f = creat(namep, New_mode)) < 0){
61011240Smckusick if(missdir(namep))
61111240Smckusick goto once_again;
61211240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno);
61311240Smckusick return (0);
61411240Smckusick }
61511240Smckusick }
61611240Smckusick }
61711240Smckusick #endif
61811240Smckusick #ifdef RT
61911240Smckusick if(MERT && (One_extent || Multi_extent))
62011240Smckusick goto skip_c;
62111240Smckusick #endif
62211240Smckusick c_again:
62311240Smckusick if((f = creat(namep, Hdr.h_mode)) < 0) {
62411240Smckusick if(missdir(namep))
62511240Smckusick goto c_again;
62611240Smckusick err("Cannot create <%s> (errno:%d)\n", namep, errno);
62711240Smckusick return 0;
62811240Smckusick }
62911240Smckusick #ifdef RT
63011240Smckusick skip_c:
63111240Smckusick #endif
63211240Smckusick if(Uid == 0)
63311240Smckusick chown(namep, Hdr.h_uid, Hdr.h_gid);
63411240Smckusick return f;
63511240Smckusick }
63611240Smckusick
bread(b,c)63711240Smckusick bread(b, c)
63811240Smckusick register c;
63911240Smckusick register short *b;
64011240Smckusick {
64111240Smckusick static nleft = 0;
64211240Smckusick static short *ip;
64311240Smckusick register short *p = ip;
64411240Smckusick
64511240Smckusick c = (c+1)>>1;
64611240Smckusick while(c--) {
64711240Smckusick if(!nleft) {
64811240Smckusick again:
64911240Smckusick if(read(Input, Dbuf, Bufsize)!=Bufsize) {
65011240Smckusick Input = chgreel(0, Input);
65111240Smckusick goto again;
65211240Smckusick }
65311240Smckusick nleft = Bufsize >> 1;
65411240Smckusick p = Dbuf;
65511240Smckusick ++Blocks;
65611240Smckusick }
65711240Smckusick *b++ = *p++;
65811240Smckusick --nleft;
65911240Smckusick }
66011240Smckusick ip = p;
66111240Smckusick }
66211240Smckusick
readhdr(b,c)66311240Smckusick readhdr(b, c)
66411240Smckusick register c;
66511240Smckusick register char *b;
66611240Smckusick {
66711240Smckusick static nleft = 0;
66811240Smckusick static char *ip;
66911240Smckusick register char *p = ip;
67011240Smckusick
67111240Smckusick while(c--) {
67211240Smckusick if(!nleft) {
67311240Smckusick again:
67411240Smckusick if(read(Input, Cbuf, Bufsize) != Bufsize) {
67511240Smckusick Input = chgreel(0, Input);
67611240Smckusick goto again;
67711240Smckusick }
67811240Smckusick nleft = Bufsize;
67911240Smckusick p = Cbuf;
68011240Smckusick ++Blocks;
68111240Smckusick }
68211240Smckusick *b++ = *p++;
68311240Smckusick --nleft;
68411240Smckusick }
68511240Smckusick ip = p;
68611240Smckusick }
68711240Smckusick
bwrite(rp,c)68811240Smckusick bwrite(rp, c)
68911240Smckusick register short *rp;
69011240Smckusick register c;
69111240Smckusick {
69211240Smckusick register short *wp = Wp;
69311240Smckusick
69411240Smckusick c = (c+1) >> 1;
69511240Smckusick while(c--) {
69611240Smckusick if(!Wct) {
69711240Smckusick again:
69811240Smckusick if(write(Output, Dbuf, Bufsize)<0) {
69911240Smckusick Output = chgreel(1, Output);
70011240Smckusick goto again;
70111240Smckusick }
70211240Smckusick Wct = Bufsize >> 1;
70311240Smckusick wp = Dbuf;
70411240Smckusick ++Blocks;
70511240Smckusick }
70611240Smckusick *wp++ = *rp++;
70711240Smckusick --Wct;
70811240Smckusick }
70911240Smckusick Wp = wp;
71011240Smckusick }
writehdr(rp,c)71111240Smckusick writehdr(rp,c)
71211240Smckusick register char *rp;
71311240Smckusick register c;
71411240Smckusick {
71511240Smckusick register char *cp = Cp;
71611240Smckusick
71711240Smckusick while(c--) {
71811240Smckusick if(!Wc) {
71911240Smckusick again:
72011240Smckusick if(write(Output,Cbuf,Bufsize)<0) {
72111240Smckusick Output = chgreel(1, Output);
72211240Smckusick goto again;
72311240Smckusick }
72411240Smckusick Wc = Bufsize;
72511240Smckusick cp = Cbuf;
72611240Smckusick ++Blocks;
72711240Smckusick }
72811240Smckusick *cp++ = *rp++;
72911240Smckusick --Wc;
73011240Smckusick }
73111240Smckusick Cp = cp;
73211240Smckusick }
73311240Smckusick
73411240Smckusick
postml(namep,np)73511240Smckusick postml(namep, np)
73611240Smckusick register char *namep, *np;
73711240Smckusick {
73811240Smckusick register i;
73911240Smckusick static struct ml {
74011240Smckusick short m_dev,
74111240Smckusick m_ino;
74211240Smckusick char m_name[2];
74311240Smckusick } *ml[LINKS];
74411240Smckusick static mlinks = 0;
74511240Smckusick char *mlp;
74611240Smckusick
74711240Smckusick for(i = 0; i < mlinks; ++i) {
74811240Smckusick if(mlinks == LINKS) break;
74911240Smckusick if(ml[i]->m_ino==Hdr.h_ino &&
75011240Smckusick ml[i]->m_dev==Hdr.h_dev) {
75111240Smckusick if(Verbose)
75211240Smckusick printf("%s linked to %s\n", ml[i]->m_name,
75311240Smckusick np);
75411240Smckusick unlink(namep);
75511240Smckusick if(Option == IN) {
75611240Smckusick Fullname[Pathend] = '\0';
75711240Smckusick strcat(Fullname, ml[i]->m_name);
75811240Smckusick mlp = Fullname;
75911240Smckusick } else
76011240Smckusick mlp = ml[i]->m_name;
76111240Smckusick l_again:
76211240Smckusick if(link(mlp, namep) < 0) {
76311240Smckusick if(missdir(np))
76411240Smckusick goto l_again;
76511240Smckusick err("Cannot link <%s>&<%s>.\n",
76611240Smckusick ml[i]->m_name, np);
76711240Smckusick }
76811240Smckusick set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
76911240Smckusick return 0;
77011240Smckusick }
77111240Smckusick }
77211240Smckusick if(mlinks == LINKS
77311240Smckusick || !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
77411240Smckusick static int first=1;
77511240Smckusick
77611240Smckusick if(first)
77711240Smckusick if(mlinks == LINKS)
77811240Smckusick err("Too many links\n");
77911240Smckusick else
78011240Smckusick err("No memory for links\n");
78111240Smckusick mlinks = LINKS;
78211240Smckusick first = 0;
78311240Smckusick return 1;
78411240Smckusick }
78511240Smckusick ml[mlinks]->m_dev = Hdr.h_dev;
78611240Smckusick ml[mlinks]->m_ino = Hdr.h_ino;
78711240Smckusick strcpy(ml[mlinks]->m_name, np);
78811240Smckusick ++mlinks;
78911240Smckusick return 1;
79011240Smckusick }
79111240Smckusick
pentry(namep)79211240Smckusick pentry(namep)
79311240Smckusick register char *namep;
79411240Smckusick {
79511240Smckusick
79611240Smckusick register i;
79711240Smckusick static short lastid = -1;
79811240Smckusick #include <pwd.h>
79911240Smckusick static struct passwd *pw;
80011240Smckusick struct passwd *getpwuid();
80111240Smckusick static char tbuf[32];
80211240Smckusick
80311240Smckusick printf("%-7o", Hdr.h_mode & 0177777);
80411240Smckusick if(lastid == Hdr.h_uid)
80511240Smckusick printf("%-6s", pw->pw_name);
80611240Smckusick else {
80711240Smckusick setpwent();
80811240Smckusick if(pw = getpwuid(Hdr.h_uid)) {
80911240Smckusick printf("%-6s", pw->pw_name);
81011240Smckusick lastid = Hdr.h_uid;
81111240Smckusick } else {
81211240Smckusick printf("%-6d", Hdr.h_uid);
81311240Smckusick lastid = -1;
81411240Smckusick }
81511240Smckusick }
81611240Smckusick printf("%7ld ", mklong(Hdr.h_filesize));
81711240Smckusick U.l = mklong(Hdr.h_mtime);
81811240Smckusick strcpy(tbuf, ctime(&U.l));
81911240Smckusick tbuf[24] = '\0';
82011240Smckusick printf(" %s %s\n", &tbuf[4], namep);
82111240Smckusick }
82211240Smckusick
nmatch(s,pat)82311240Smckusick nmatch(s, pat)
82411240Smckusick char *s, **pat;
82511240Smckusick {
82611240Smckusick if(EQ(*pat, "*"))
82711240Smckusick return 1;
82811240Smckusick while(*pat) {
82911240Smckusick if((**pat == '!' && !gmatch(s, *pat+1))
83011240Smckusick || gmatch(s, *pat))
83111240Smckusick return 1;
83211240Smckusick ++pat;
83311240Smckusick }
83411240Smckusick return 0;
83511240Smckusick }
gmatch(s,p)83611240Smckusick gmatch(s, p)
83711240Smckusick register char *s, *p;
83811240Smckusick {
83911240Smckusick register int c;
84011240Smckusick register cc, ok, lc, scc;
84111240Smckusick
84211240Smckusick scc = *s;
84311240Smckusick lc = 077777;
84411240Smckusick switch (c = *p) {
84511240Smckusick
84611240Smckusick case '[':
84711240Smckusick ok = 0;
84811240Smckusick while (cc = *++p) {
84911240Smckusick switch (cc) {
85011240Smckusick
85111240Smckusick case ']':
85211240Smckusick if (ok)
85311240Smckusick return(gmatch(++s, ++p));
85411240Smckusick else
85511240Smckusick return(0);
85611240Smckusick
85711240Smckusick case '-':
85811240Smckusick ok |= (lc <= scc & scc <= (cc=p[1]));
85911240Smckusick }
86011240Smckusick if (scc==(lc=cc)) ok++;
86111240Smckusick }
86211240Smckusick return(0);
86311240Smckusick
86411240Smckusick case '?':
86511240Smckusick caseq:
86611240Smckusick if(scc) return(gmatch(++s, ++p));
86711240Smckusick return(0);
86811240Smckusick case '*':
86911240Smckusick return(umatch(s, ++p));
87011240Smckusick case 0:
87111240Smckusick return(!scc);
87211240Smckusick }
87311240Smckusick if (c==scc) goto caseq;
87411240Smckusick return(0);
87511240Smckusick }
87611240Smckusick
umatch(s,p)87711240Smckusick umatch(s, p)
87811240Smckusick register char *s, *p;
87911240Smckusick {
88011240Smckusick if(*p==0) return(1);
88111240Smckusick while(*s)
88211240Smckusick if (gmatch(s++,p)) return(1);
88311240Smckusick return(0);
88411240Smckusick }
88511240Smckusick
makdir(namep)88611240Smckusick makdir(namep)
88711240Smckusick register char *namep;
88811240Smckusick {
88911240Smckusick static status;
89011240Smckusick register pid;
89111240Smckusick
89211240Smckusick if(pid = fork())
89311240Smckusick while(wait(&status) != pid);
89411240Smckusick else {
89511240Smckusick close(2);
89611240Smckusick execl("/bin/mkdir", "mkdir", namep, 0);
89711240Smckusick exit(2);
89811240Smckusick }
89911240Smckusick return ((status>>8) & 0377)? 0: 1;
90011240Smckusick }
90111240Smckusick
swap(buf,ct)90211240Smckusick swap(buf, ct)
90311240Smckusick register ct;
90411240Smckusick register union swp { short shortw; char charv[2]; } *buf;
90511240Smckusick {
90611240Smckusick register char c;
90711240Smckusick
90811240Smckusick ct = (ct + 1) >> 1;
90911240Smckusick
91011240Smckusick while(ct--) {
91111240Smckusick c = buf->charv[0];
91211240Smckusick buf->charv[0] = buf->charv[1];
91311240Smckusick buf->charv[1] = c;
91411240Smckusick ++buf;
91511240Smckusick }
91611240Smckusick }
set_time(namep,atime,mtime)91711240Smckusick set_time(namep, atime, mtime)
91811240Smckusick register *namep;
91911240Smckusick long atime, mtime;
92011240Smckusick {
92111240Smckusick static long timevec[2];
92211240Smckusick
92311240Smckusick if(!Mod_time)
92411240Smckusick return;
92511240Smckusick timevec[0] = atime;
92611240Smckusick timevec[1] = mtime;
92711240Smckusick utime(namep, timevec);
92811240Smckusick }
chgreel(x,fl)92911240Smckusick chgreel(x, fl)
93011240Smckusick {
93111240Smckusick register f;
93211240Smckusick char str[22];
93311240Smckusick FILE *devtty;
93411240Smckusick struct stat statb;
93511240Smckusick
93611240Smckusick err("errno: %d, ", errno);
93711240Smckusick err("Can't %s\n", x? "write output": "read input");
93811240Smckusick fstat(fl, &statb);
93911240Smckusick #ifdef RT
94011240Smckusick if(!MERT){
94111240Smckusick if((statb.st_mode&S_IFMT) != S_IFCHR)
94211240Smckusick exit(2);
94311240Smckusick }
94411240Smckusick else if((statb.st_mode & (S_IFBLK|S_IFREC))==0)
94511240Smckusick exit(2);
94611240Smckusick #endif
94711240Smckusick #ifndef RT
94811240Smckusick if((statb.st_mode&S_IFMT) != S_IFCHR)
94911240Smckusick exit(2);
95011240Smckusick #endif
95111240Smckusick again:
95211240Smckusick err("If you want to go on, type device/file name when ready\n");
95311240Smckusick devtty = fopen("/dev/tty", "r");
95411240Smckusick fgets(str, 20, devtty);
95511240Smckusick str[strlen(str) - 1] = '\0';
95611240Smckusick if(!*str)
95711240Smckusick exit(2);
95811240Smckusick close(fl);
95911240Smckusick if((f = open(str, x? 1: 0)) < 0) {
96011240Smckusick err("That didn't work");
96111240Smckusick fclose(devtty);
96211240Smckusick goto again;
96311240Smckusick }
96411240Smckusick return f;
96511240Smckusick }
missdir(namep)96611240Smckusick missdir(namep)
96711240Smckusick register char *namep;
96811240Smckusick {
96911240Smckusick register char *np;
97011240Smckusick register ct = 0;
97111240Smckusick
97211240Smckusick if(!Dir)
97311240Smckusick return 0;
97411240Smckusick for(np = namep; *np; ++np)
97511240Smckusick if(*np == '/') {
97611240Smckusick *np = '\0';
97711240Smckusick if(stat(namep, &Xstatb) == -1)
97811240Smckusick makdir(namep), ++ct;
97911240Smckusick *np = '/';
98011240Smckusick }
98111240Smckusick return ct;
98211240Smckusick }
err(a,b,c)98311240Smckusick err(a, b, c)
98411240Smckusick {
98511240Smckusick fprintf(stderr, a, b, c);
98611240Smckusick }
pwd()98711240Smckusick pwd()
98811240Smckusick {
98911240Smckusick FILE *dir;
99011240Smckusick
99111240Smckusick dir = popen("pwd", "r");
99211240Smckusick fgets(Fullname, 256, dir);
99311240Smckusick if(pclose(dir))
99411240Smckusick exit(2);
99511240Smckusick Pathend = strlen(Fullname);
99611240Smckusick Fullname[Pathend - 1] = '/';
99711240Smckusick }
cd(n)99811240Smckusick char * cd(n)
99911240Smckusick register char *n;
100011240Smckusick {
100111240Smckusick char *p_save = Name, *n_save = n, *p_end = 0;
100211240Smckusick register char *p = Name;
100311240Smckusick static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../";
100411240Smckusick int slashes;
100511240Smckusick
100611240Smckusick if(*n == '/') /* don't try to chdir on full pathnames */
100711240Smckusick return n;
100811240Smckusick for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */
100911240Smckusick if(*p == '/')
101011240Smckusick p_save = p+1, n_save = n+1;
101111240Smckusick }
101211240Smckusick
101311240Smckusick p = p_save;
101411240Smckusick *p++ = '\0';
101511240Smckusick for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */
101611240Smckusick if(*p == '/')
101711240Smckusick ++slashes;
101811240Smckusick }
101911240Smckusick p = p_save;
102011240Smckusick if(slashes) {
102111240Smckusick slashes = slashes * 3 - 1;
102211240Smckusick dotdot[slashes] = '\0';
102311240Smckusick chdir(dotdot);
102411240Smckusick dotdot[slashes] = '/';
102511240Smckusick }
102611240Smckusick
102711240Smckusick n = n_save;
102811240Smckusick for(; *n; ++n, ++p) {
102911240Smckusick *p = *n;
103011240Smckusick if(*n == '/')
103111240Smckusick p_end = p+1, n_save = n+1;
103211240Smckusick }
103311240Smckusick *p = '\0';
103411240Smckusick
103511240Smckusick if(p_end) {
103611240Smckusick *p_end = '\0';
103711240Smckusick if(chdir(p_save) == -1) {
103811240Smckusick if(!missdir(p_save)) {
103911240Smckusick cd_err:
104011240Smckusick err("Cannot chdir (no `d' option)\n");
104111240Smckusick exit(2);
104211240Smckusick } else if(chdir(p_save) == -1)
104311240Smckusick goto cd_err;
104411240Smckusick }
104511240Smckusick } else
104611240Smckusick *p_save = '\0';
104711240Smckusick return n_save;
104811240Smckusick }
104911240Smckusick #ifdef RT
actsize()105011240Smckusick actsize()
105111240Smckusick {
105211240Smckusick }
105311240Smckusick #endif
1054