|
|
1.1 root 1: /* @(#)cpio.c 1.17 */
2: /* cpio COMPILE: cc -O cpio.c -s -i -o cpio
3: cpio -- copy file collections
4:
5: */
6: #include <stdio.h>
7: #include <signal.h>
8: #ifdef RT
9: #include <rt/macro.h>
10: #include <rt/types.h>
11: #include <rt/stat.h>
12: #else
13: #include <sys/types.h>
14: #include <sys/stat.h>
15: #include <errno.h>
16: #endif
17: #define EQ(x,y) (strcmp(x,y)==0)
18: /* for VAX, Interdata, ... */
19: #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];}
20: #define MAGIC 070707 /* cpio magic number */
21: #define IN 1 /* copy in */
22: #define OUT 2 /* copy out */
23: #define PASS 3 /* direct copy */
24: #define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */
25: #define LINKS 10000 /* max no. of links allowed */
26: #define CHARS 76 /* ASCII header size minus filename field */
27: #undef BUFSIZE
28: #define BUFSIZE 512 /* In u370, can't use BUFSIZ nor BSIZE */
29: #define CPIOBSZ 4096 /* file read/write */
30: #define MAXFILENAME 14
31: #ifdef RT
32: extern long filespace;
33: #endif
34:
35: struct stat Statb, Xstatb;
36:
37: /* Cpio header format */
38: struct header {
39: short h_magic,
40: h_dev;
41: unsigned
42: short h_ino,
43: h_mode,
44: h_uid,
45: h_gid;
46: short h_nlink,
47: h_rdev,
48: h_mtime[2],
49: h_namesize,
50: h_filesize[2];
51: char h_name[256];
52: } Hdr;
53:
54: unsigned Bufsize = BUFSIZE; /* default record size */
55: short Buf[CPIOBSZ/2], *Dbuf;
56: char BBuf[CPIOBSZ], *Cbuf;
57: int Wct, Wc;
58: short *Wp;
59: char *Cp;
60:
61: #ifdef RT
62: short Actual_size[2];
63: #endif
64:
65: short Option,
66: Dir,
67: Uncond,
68: Link,
69: Rename,
70: Toc,
71: Verbose,
72: Select,
73: Mod_time,
74: Acc_time,
75: Cflag,
76: fflag,
77: #ifdef RT
78: Extent,
79: #endif
80: Swap,
81: byteswap,
82: bothswap,
83: halfswap;
84:
85: int Ifile,
86: Ofile,
87: Input = 0,
88: Output = 1;
89: long Blocks,
90: Longfile,
91: Longtime;
92:
93: char Fullname[256],
94: Name[256];
95: int Pathend;
96: int usrmask;
97:
98: FILE *Rtty,
99: *Wtty;
100:
101: char *Pattern[100];
102: char Strhdr[500];
103: char *Chdr = Strhdr;
104: short Dev,
105: Uid,
106: A_directory,
107: A_special,
108: #ifdef RT
109: One_extent,
110: Multi_extent,
111: #endif
112: Filetype = S_IFMT;
113:
114: extern errno;
115: char *malloc();
116: char *strchr();
117: char *gets();
118: char *cd();
119: /* char *Cd_name; */
120: FILE *popen();
121:
122: union { long l; short s[2]; char c[4]; } U;
123:
124: /* for VAX, Interdata, ... */
125: long mklong(v)
126: short v[];
127: {
128: U.l = 1;
129: if(U.c[0])
130: U.s[0] = v[1], U.s[1] = v[0];
131: else
132: U.s[0] = v[0], U.s[1] = v[1];
133: return U.l;
134: }
135:
136: main(argc, argv)
137: char **argv;
138: {
139: register ct;
140: long filesz;
141: register char *fullp;
142: register i;
143: int ans;
144:
145: signal(SIGSYS, 1);
146: if(*argv[1] != '-')
147: usage();
148: Uid = geteuid();
149: usrmask = umask(0);
150: umask(usrmask);
151: Pattern[0] = "*";
152:
153: while(*++argv[1]) {
154: switch(*argv[1]) {
155: case 'a': /* reset access time */
156: Acc_time++;
157: break;
158: case 'B': /* change record size to 5120 bytes */
159: Bufsize = 5120;
160: break;
161: case 'i':
162: Option = IN;
163: if(argc > 2 ) { /* save patterns, if any */
164: for(i = 0; (i+2) < argc; ++i)
165: Pattern[i] = argv[i+2];
166: }
167: break;
168: case 'f': /* do not consider patterns in cmd line */
169: fflag++;
170: break;
171: case 'o':
172: if(argc != 2)
173: usage();
174: Option = OUT;
175: break;
176: case 'p':
177: if(argc != 3)
178: usage();
179: if(access(argv[2], 2) == -1) {
180: accerr:
181: fprintf(stderr,"cannot write in <%s>\n", argv[2]);
182: exit(2);
183: }
184: strcpy(Fullname, argv[2]); /* destination directory */
185: strcat(Fullname, "/");
186: stat(Fullname, &Xstatb);
187: if((Xstatb.st_mode&S_IFMT) != S_IFDIR)
188: goto accerr;
189: Option = PASS;
190: Dev = Xstatb.st_dev;
191: break;
192: case 'c': /* ASCII header */
193: Cflag++;
194: break;
195: case 'd': /* create directories when needed */
196: Dir++;
197: break;
198: case 'l': /* link files, when necessary */
199: Link++;
200: break;
201: case 'm': /* retain mod time */
202: Mod_time++;
203: break;
204: case 'r': /* rename files interactively */
205: Rename++;
206: Rtty = fopen("/dev/tty", "r");
207: Wtty = fopen("/dev/tty", "w");
208: if(Rtty==NULL || Wtty==NULL) {
209: fprintf(stderr,
210: "Cannot rename (/dev/tty missing)\n");
211: exit(2);
212: }
213: break;
214: case 'S': /* swap halfwords */
215: halfswap++;
216: Swap++;
217: break;
218: case 's': /* swap bytes */
219: byteswap++;
220: Swap++;
221: break;
222: case 'b':
223: bothswap++;
224: Swap++;
225: break;
226: case 't': /* table of contents */
227: Toc++;
228: break;
229: case 'u': /* copy unconditionally */
230: Uncond++;
231: break;
232: case 'v': /* verbose table of contents */
233: Verbose++;
234: break;
235: case '6': /* for old, sixth-edition files */
236: Filetype = 060000;
237: break;
238: #ifdef RT
239: case 'e':
240: Extent++;
241: break;
242: #endif
243: default:
244: usage();
245: }
246: }
247: if(!Option) {
248: fprintf(stderr,"Options must include o|i|p\n");
249: exit(2);
250: }
251: #ifdef RT
252: setio(-1,1); /* turn on physio */
253: #endif
254:
255: if(Option == PASS) {
256: if(Rename) {
257: fprintf(stderr,"Pass and Rename cannot be used together\n");
258: exit(2);
259: }
260: if(Bufsize == 5120) {
261: printf("`B' option is irrelevant with the '-p' option\n");
262: Bufsize = BUFSIZE;
263: }
264:
265: }else {
266: if(Cflag)
267: Cp = Cbuf = (char *)malloc(Bufsize);
268: else
269: Wp = Dbuf = (short *)malloc(Bufsize);
270: }
271: Wct = Bufsize >> 1;
272: Wc = Bufsize;
273:
274: switch(Option) {
275:
276: case OUT: /* get filename, copy header and file out */
277: while(getname()) {
278: if( mklong(Hdr.h_filesize) == 0L) {
279: if( Cflag )
280: writehdr(Chdr,CHARS+Hdr.h_namesize);
281: else
282: bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
283: #ifdef RT
284: if (One_extent || Multi_extent) {
285: actsize(0);
286: if( Cflag )
287: writehdr(Chdr,CHARS+Hdr.h_namesize);
288: else
289: bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
290: }
291: #endif
292: continue;
293: }
294: if((Ifile = open(Hdr.h_name, 0)) < 0) {
295: fprintf(stderr,"<%s> ?\n", Hdr.h_name);
296: continue;
297: }
298: if ( Cflag )
299: writehdr(Chdr,CHARS+Hdr.h_namesize);
300: else
301: bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
302: #ifdef RT
303: if (One_extent || Multi_extent) {
304: actsize(Ifile);
305: if(Cflag)
306: writehdr(Chdr,CHARS+Hdr.h_namesize);
307: else
308: bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
309: Hdr.h_filesize[0] = Actual_size[0];
310: Hdr.h_filesize[1] = Actual_size[1];
311: }
312: #endif
313: for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
314: ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
315: if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) {
316: fprintf(stderr,"Cannot read %s\n", Hdr.h_name);
317: continue;
318: }
319: Cflag? writehdr(BBuf,ct): bwrite(Buf,ct);
320: }
321: close(Ifile);
322: if(Acc_time)
323: utime(Hdr.h_name, &Statb.st_atime);
324: if(Verbose)
325: fprintf(stderr,"%s\n", Hdr.h_name);
326: }
327:
328: /* copy trailer, after all files have been copied */
329: strcpy(Hdr.h_name, "TRAILER!!!");
330: Hdr.h_magic = MAGIC;
331: MKSHORT(Hdr.h_filesize, 0L);
332: Hdr.h_namesize = strlen("TRAILER!!!") + 1;
333: if ( Cflag ) {
334: bintochar(0L);
335: writehdr(Chdr,CHARS+Hdr.h_namesize);
336: }
337: else
338: bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
339: Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize);
340: break;
341:
342: case IN:
343: pwd();
344: while(gethdr()) {
345: Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0;
346: for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
347: ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
348: Cflag? readhdr(BBuf,ct): bread(Buf, ct);
349: if(Ofile) {
350: if(Swap)
351: Cflag? swap(BBuf,ct): swap(Buf,ct);
352: if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) {
353: fprintf(stderr,"Cannot write %s\n", Hdr.h_name);
354: continue;
355: }
356: }
357: }
358: if(Ofile) {
359: close(Ofile);
360: if(chmod(Hdr.h_name, Hdr.h_mode) < 0) {
361: fprintf(stderr,"Cannot chmod <%s> (errno:%d)\n", Hdr.h_name, errno);
362: }
363: set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
364: }
365: if(!Select)
366: continue;
367: if(Verbose)
368: if(Toc)
369: pentry(Hdr.h_name);
370: else
371: puts(Hdr.h_name);
372: else if(Toc)
373: puts(Hdr.h_name);
374: }
375: break;
376:
377: case PASS: /* move files around */
378: fullp = Fullname + strlen(Fullname);
379:
380: while(getname()) {
381: if (A_directory && !Dir)
382: fprintf(stderr,"Use `-d' option to copy <%s>\n",Hdr.h_name);
383: if(!ckname(Hdr.h_name))
384: continue;
385: i = 0;
386: while(Hdr.h_name[i] == '/')
387: i++;
388: strcpy(fullp, &(Hdr.h_name[i]));
389:
390: if(Link
391: && !A_directory
392: && Dev == Statb.st_dev) {
393: /* ??? && (Uid == Statb.st_uid || !Uid)) {*/
394: if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
395: if(errno == EEXIST)
396: fprintf(stderr, "Cannot link <%s> & <%s> (errno:%d)\n",
397: Hdr.h_name, Fullname, errno);
398: else {
399: unlink(Fullname);
400: missdir(Fullname);
401: if(link(Hdr.h_name, Fullname) < 0) {
402: fprintf(stderr, "Cannot link <%s> & <%s> (errno:%d)\n", Hdr.h_name, Fullname, errno);
403: continue;
404: }
405: }
406: }
407:
408: /* try creating (only twice) */
409: ans = 0;
410: do {
411: if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
412: if(errno == EEXIST) {
413: ans = 3;
414: break;
415: }
416: else
417: unlink(Fullname);
418: ans += 1;
419: }else {
420: ans = 0;
421: break;
422: }
423: }while(ans < 2 && missdir(Fullname) == 0);
424: if(ans == 1) {
425: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", Fullname, errno);
426: exit(0);
427: }else if(ans == 2) {
428: fprintf(stderr,"Cannot link <%s> & <%s> (errno:%d)\n", Hdr.h_name, Fullname, errno);
429: exit(0);
430: }
431:
432: if(!Link)
433: if(chmod(Hdr.h_name, Hdr.h_mode) < 0) {
434: fprintf(stderr,"Cannot chmod <%s> (errno:%d)\n", Hdr.h_name, errno);
435: }
436: set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
437: goto ckverbose;
438: }
439: #ifdef RT
440: if (One_extent || Multi_extent)
441: actsize(0);
442: #endif
443: if(!(Ofile = openout(Fullname)))
444: continue;
445: if((Ifile = open(Hdr.h_name, 0)) < 0) {
446: fprintf(stderr,"<%s> ?\n", Hdr.h_name);
447: close(Ofile);
448: continue;
449: }
450: filesz = Statb.st_size;
451: for(; filesz > 0; filesz -= CPIOBSZ) {
452: ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
453: if(read(Ifile, Buf, ct) < 0) {
454: fprintf(stderr,"Cannot read %s\n", Hdr.h_name);
455: break;
456: }
457: if(Ofile)
458: if(write(Ofile, Buf, ct) < 0) {
459: fprintf(stderr,"Cannot write %s\n", Hdr.h_name);
460: break;
461: }
462: #ifndef u370
463: Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE);
464: #else
465: ++Blocks;
466: #endif
467: }
468: close(Ifile);
469: if(Acc_time)
470: utime(Hdr.h_name, &Statb.st_atime);
471: if(Ofile) {
472: close(Ofile);
473: if(chmod(Fullname, Hdr.h_mode) < 0) {
474: fprintf(stderr,"Cannot chmod <%s> (errno:%d)\n", Fullname, errno);
475: }
476: set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
477: ckverbose:
478: if(Verbose)
479: puts(Fullname);
480: }
481: }
482: }
483: /* print number of blocks actually copied */
484: fprintf(stderr,"%ld blocks\n", Blocks * (Bufsize>>9));
485: exit(0);
486: }
487: usage()
488: {
489: fprintf(stderr,"Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n",
490: " cpio -i[cdmrstuvfB6] [pattern ...] <collection",
491: " cpio -p[adlmruv] directory <name-list");
492: exit(2);
493: }
494:
495: getname() /* get file name, get info for header */
496: {
497: register char *namep = Name;
498: register unsigned short ftype;
499: long tlong;
500:
501: for(;;) {
502: if(gets(namep,sizeof(Name)) == NULL)
503: return 0;
504: if(*namep == '.' && namep[1] == '/') {
505: namep++;
506: while(*namep == '/') namep++;
507: }
508: strcpy(Hdr.h_name, namep);
509: if(stat(namep, &Statb) < 0) {
510: fprintf(stderr,"< %s > ?\n", Hdr.h_name);
511: continue;
512: }
513: ftype = Statb.st_mode & Filetype;
514: A_directory = (ftype == S_IFDIR);
515: A_special = (ftype == S_IFBLK)
516: || (ftype == S_IFCHR)
517: #ifdef UX3
518: || (ftype == S_IFIFO)
519: #endif
520: ;
521: #ifdef RT
522: A_special |= (ftype == S_IFREC);
523: One_extent = (ftype == S_IF1EXT);
524: Multi_extent = (ftype == S_IFEXT);
525: #endif
526: Hdr.h_magic = MAGIC;
527: Hdr.h_namesize = strlen(Hdr.h_name) + 1;
528: Hdr.h_uid = Statb.st_uid;
529: Hdr.h_gid = Statb.st_gid;
530: Hdr.h_dev = Statb.st_dev;
531: Hdr.h_ino = Statb.st_ino;
532: Hdr.h_mode = Statb.st_mode;
533: MKSHORT(Hdr.h_mtime, Statb.st_mtime);
534: Hdr.h_nlink = Statb.st_nlink;
535: tlong = (Hdr.h_mode&S_IFMT) == S_IFREG? Statb.st_size: 0L;
536: #ifdef RT
537: if (One_extent || Multi_extent) tlong = Statb.st_size;
538: #endif
539: MKSHORT(Hdr.h_filesize, tlong);
540: Hdr.h_rdev = Statb.st_rdev;
541: if( Cflag )
542: bintochar(tlong);
543: return 1;
544: }
545: }
546:
547: bintochar(t) /* ASCII header write */
548: long t;
549: {
550: sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
551: MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,
552: Statb.st_uid & 00000177777, Statb.st_gid & 00000177777,
553: Statb.st_nlink,Statb.st_rdev & 00000177777,
554: Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name);
555: }
556:
557: chartobin() /* ASCII header read */
558: {
559: sscanf(Chdr,"%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
560: &Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid,
561: &Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize,
562: &Longfile);
563: MKSHORT(Hdr.h_filesize, Longfile);
564: MKSHORT(Hdr.h_mtime, Longtime);
565: }
566:
567: gethdr() /* get file headers */
568: {
569: register unsigned short ftype;
570:
571: if (Cflag) {
572: readhdr(Chdr,CHARS);
573: chartobin();
574: }
575: else
576: bread(&Hdr, HDRSIZE);
577:
578: if(Hdr.h_magic != MAGIC) {
579: fprintf(stderr,"Out of phase--get help\n");
580: fprintf(stderr,"Perhaps the \"-c\" option should be used\n");
581: exit(2);
582: }
583: if(Cflag)
584: readhdr(Hdr.h_name, Hdr.h_namesize);
585: else
586: bread(Hdr.h_name, Hdr.h_namesize);
587: if(EQ(Hdr.h_name, "TRAILER!!!"))
588: return 0;
589: ftype = Hdr.h_mode & Filetype;
590: A_directory = (ftype == S_IFDIR);
591: A_special =(ftype == S_IFBLK)
592: || (ftype == S_IFCHR)
593: #ifdef UX3
594: || (ftype == S_IFIFO)
595: #endif
596: ;
597: #ifdef RT
598: A_special |= (ftype == S_IFREC);
599: One_extent = (ftype == S_IF1EXT);
600: Multi_extent = (ftype == S_IFEXT);
601: if (One_extent || Multi_extent) {
602: Actual_size[0] = Hdr.h_filesize[0];
603: Actual_size[1] = Hdr.h_filesize[1];
604: if (Cflag) {
605: readhdr(Chdr,CHARS);
606: chartobin();
607: }
608: else
609: bread(&Hdr, HDRSIZE);
610:
611: if(Hdr.h_magic != MAGIC) {
612: fprintf(stderr,"Out of phase--get RT help\n");
613: fprintf(stderr,"Perhaps the \"-c\" option should be used\n");
614: exit(2);
615: }
616: if(Cflag)
617: readhdr(Hdr.h_name, Hdr.h_namesize);
618: else
619: bread(Hdr.h_name, Hdr.h_namesize);
620: }
621: #endif
622: return 1;
623: }
624:
625: ckname(namep) /* check filenames with patterns given on cmd line */
626: register char *namep;
627: {
628: ++Select;
629: if(fflag ^ !nmatch(namep, Pattern)) {
630: Select = 0;
631: return 0;
632: }
633: if(Rename && !A_directory) { /* rename interactively */
634: fprintf(Wtty, "Rename <%s>\n", namep);
635: fflush(Wtty);
636: fgets(namep, 128, Rtty);
637: if(feof(Rtty))
638: exit(2);
639: namep[strlen(namep) - 1] = '\0';
640: if(EQ(namep, "")) {
641: printf("Skipped\n");
642: return 0;
643: }
644: }
645: return !Toc;
646: }
647:
648: openout(namep) /* open files for writing, set all necessary info */
649: register char *namep;
650: {
651: register f;
652: register char *np;
653: int ans;
654:
655: if(!strncmp(namep, "./", 2))
656: namep += 2;
657: fixname(namep);
658: np = namep;
659: /*
660: if(Option == IN)
661: Cd_name = namep = cd(namep);
662: */
663: if(A_directory) {
664: if(!Dir
665: || Rename
666: || EQ(namep, ".")
667: || EQ(namep, "..")) /* do not consider . or .. files */
668: return 0;
669: if(stat(namep, &Xstatb) == -1) {
670:
671: /* try creating (only twice) */
672: ans = 0;
673: do {
674: if(makdir(namep) != 0) {
675: ans += 1;
676: }else {
677: ans = 0;
678: break;
679: }
680: }while(ans < 2 && missdir(namep) == 0);
681: if(ans == 1) {
682: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", namep, errno);
683: return(0);
684: }else if(ans == 2) {
685: fprintf(stderr,"Cannot create directory <%s> (errno:%d)\n", namep, errno);
686: return(0);
687: }
688: }
689:
690: ret:
691: if(chmod(namep, Hdr.h_mode) < 0) {
692: fprintf(stderr,"Cannot chmod <%s> (errno:%d)\n", namep, errno);
693: }
694: if(Uid == 0)
695: if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0) {
696: fprintf(stderr,"Cannot chown <%s> (errno:%d)\n", namep, errno);
697: }
698: set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
699: return 0;
700: }
701: if(Hdr.h_nlink > 1)
702: if(!postml(namep, np))
703: return 0;
704: if(stat(namep, &Xstatb) == 0) {
705: if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) {
706: if(unlink(namep) < 0) {
707: fprintf(stderr,"cannot unlink current <%s> (errno:%d)\n", namep, errno);
708: }
709: }
710: if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) {
711: /* There's a newer version of file on destination */
712: if(mklong(Hdr.h_mtime) < Xstatb.st_mtime)
713: fprintf(stderr,"current <%s> newer\n", np);
714: return 0;
715: }
716: }
717: if(Option == PASS
718: && Hdr.h_ino == Xstatb.st_ino
719: && Hdr.h_dev == Xstatb.st_dev) {
720: fprintf(stderr,"Attempt to pass file to self!\n");
721: exit(2);
722: }
723: if(A_special) {
724: #ifdef UX3
725: if((Hdr.h_mode & Filetype) == S_IFIFO)
726: Hdr.h_rdev = 0;
727: #endif
728:
729: /* try creating (only twice) */
730: ans = 0;
731: do {
732: if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
733: ans += 1;
734: }else {
735: ans = 0;
736: break;
737: }
738: }while(ans < 2 && missdir(np) == 0);
739: if(ans == 1) {
740: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", namep, errno);
741: return(0);
742: }else if(ans == 2) {
743: fprintf(stderr,"Cannot mknod <%s> (errno:%d)\n", namep, errno);
744: return(0);
745: }
746:
747: goto ret;
748: }
749: #ifdef RT
750: if(One_extent || Multi_extent) {
751:
752: /* try creating (only twice) */
753: ans = 0;
754: do {
755: if((f = falloc(namep, Hdr.h_mode, longword(Hdr.h_filesize[0]))) < 0) {
756: ans += 1;
757: }else {
758: ans = 0;
759: break;
760: }
761: }while(ans < 2 && missdir(np) == 0);
762: if(ans == 1) {
763: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", namep, errno);
764: return(0);
765: }else if(ans == 2) {
766: fprintf(stderr,"Cannot create <%s> (errno:%d)\n", namep, errno);
767: return(0);
768: }
769:
770: if(filespace < longword(Hdr.h_filesize[0])){
771: fprintf(stderr,"Cannot create contiguous file <%s> proper size\n", namep);
772: fprintf(stderr," <%s> will be created as a regular file\n", namep);
773: if(unlink(Fullname) != 0)
774: fprintf(stderr,"<%s> not removed\n", namep);
775: Hdr.h_mode = (Hdr.h_mode & !S_IFMT) | S_IFREG;
776: One_extent = Multi_extent = 0;
777: }
778: Hdr.h_filesize[0] = Actual_size[0];
779: Hdr.h_filesize[1] = Actual_size[1];
780: }
781: if (!(One_extent || Multi_extent)) {
782: #endif
783:
784: /* try creating (only twice) */
785: ans = 0;
786: do {
787: if((f = creat(namep, ~usrmask)) < 0) {
788: ans += 1;
789: }else {
790: ans = 0;
791: break;
792: }
793: }while(ans < 2 && missdir(np) == 0);
794: if(ans == 1) {
795: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", namep, errno);
796: return(0);
797: }else if(ans == 2) {
798: fprintf(stderr,"Cannot create <%s> (errno:%d)\n", namep, errno);
799: return(0);
800: }
801:
802: #ifdef RT
803: }
804: #endif
805: if(Uid == 0)
806: chown(namep, Hdr.h_uid, Hdr.h_gid);
807: return f;
808: }
809:
810: bread(b, c)
811: register c;
812: register short *b;
813: {
814: static nleft = 0;
815: static short *ip;
816: register int rv;
817: register short *p = ip;
818: register int in;
819:
820: c = (c+1)>>1;
821: while(c--) {
822: if(nleft == 0) {
823: in = 0;
824: while((rv=read(Input, &(((char *)Dbuf)[in]), Bufsize - in)) != Bufsize - in) {
825: if(rv <= 0) {
826: Input = chgreel(0, Input);
827: continue;
828: }
829: in += rv;
830: nleft += (rv >> 1);
831: }
832: nleft += (rv >> 1);
833: p = Dbuf;
834: ++Blocks;
835: }
836: *b++ = *p++;
837: --nleft;
838: }
839: ip = p;
840: }
841:
842: readhdr(b, c)
843: register c;
844: register char *b;
845: {
846: static nleft = 0;
847: static char *ip;
848: register int rv;
849: register char *p = ip;
850: register int in;
851:
852: while(c--) {
853: if(nleft == 0) {
854: in = 0;
855: while((rv=read(Input, &(((char *)Cbuf)[in]), Bufsize - in)) != Bufsize - in) {
856: if(rv <= 0) {
857: Input = chgreel(0, Input);
858: continue;
859: }
860: in += rv;
861: nleft += rv;
862: }
863: nleft += rv;
864: p = Cbuf;
865: ++Blocks;
866: }
867: *b++ = *p++;
868: --nleft;
869: }
870: ip = p;
871: }
872:
873: bwrite(rp, c)
874: register short *rp;
875: register c;
876: {
877: register short *wp = Wp;
878:
879: c = (c+1) >> 1;
880: while(c--) {
881: if(!Wct) {
882: again:
883: if(write(Output, Dbuf, Bufsize)<0) {
884: Output = chgreel(1, Output);
885: goto again;
886: }
887: Wct = Bufsize >> 1;
888: wp = Dbuf;
889: ++Blocks;
890: }
891: *wp++ = *rp++;
892: --Wct;
893: }
894: Wp = wp;
895: }
896:
897: writehdr(rp, c)
898: register char *rp;
899: register c;
900: {
901: register char *cp = Cp;
902:
903: while(c--) {
904: if(!Wc) {
905: again:
906: if(write(Output,Cbuf,Bufsize)<0) {
907: Output = chgreel(1,Output);
908: goto again;
909: }
910: Wc = Bufsize;
911: cp = Cbuf;
912: ++Blocks;
913: }
914: *cp++ = *rp++;
915: --Wc;
916: }
917: Cp = cp;
918: }
919:
920: postml(namep, np) /* linking funtion */
921: register char *namep, *np;
922: {
923: register i;
924: static struct ml {
925: short m_dev,
926: m_ino;
927: char m_name[2];
928: } *ml[LINKS];
929: static mlinks = 0;
930: char *mlp;
931: int ans;
932:
933: for(i = 0; i < mlinks; ++i) {
934: if(mlinks == LINKS) break;
935: if(ml[i]->m_ino==Hdr.h_ino &&
936: ml[i]->m_dev==Hdr.h_dev) {
937: if(Verbose)
938: printf("%s linked to %s\n", ml[i]->m_name,
939: np);
940: unlink(namep);
941: if(Option == IN && *ml[i]->m_name != '/') {
942: Fullname[Pathend] = '\0';
943: strcat(Fullname, ml[i]->m_name);
944: mlp = Fullname;
945: }
946: mlp = ml[i]->m_name;
947:
948: /* try linking (only twice) */
949: ans = 0;
950: do {
951: if(link(mlp, namep) < 0) {
952: ans += 1;
953: }else {
954: ans = 0;
955: break;
956: }
957: }while(ans < 2 && missdir(np) == 0);
958: if(ans == 1) {
959: fprintf(stderr,"Cannot create directory for <%s> (errno:%d)\n", np, errno);
960: return(0);
961: }else if(ans == 2) {
962: fprintf(stderr,"Cannot link <%s> & <%s> (errno:%d)\n", ml[i]->m_name, np, errno);
963: return(0);
964: }
965:
966: set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
967: return 0;
968: }
969: }
970: if(mlinks == LINKS
971: || !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
972: static int first=1;
973:
974: if(first)
975: if(mlinks == LINKS)
976: fprintf(stderr,"Too many links\n");
977: else
978: fprintf(stderr,"No memory for links\n");
979: mlinks = LINKS;
980: first = 0;
981: return 1;
982: }
983: ml[mlinks]->m_dev = Hdr.h_dev;
984: ml[mlinks]->m_ino = Hdr.h_ino;
985: strcpy(ml[mlinks]->m_name, np);
986: ++mlinks;
987: return 1;
988: }
989:
990: pentry(namep) /* print verbose table of contents */
991: register char *namep;
992: {
993:
994: static short lastid = -1;
995: #include <pwd.h>
996: static struct passwd *pw;
997: struct passwd *getpwuid();
998: static char tbuf[32];
999: char *ctime();
1000:
1001: printf("%-7o", Hdr.h_mode & 0177777);
1002: if(lastid == Hdr.h_uid)
1003: printf("%-6s", pw->pw_name);
1004: else {
1005: setpwent();
1006: if(pw = getpwuid((int)Hdr.h_uid)) {
1007: printf("%-6s", pw->pw_name);
1008: lastid = Hdr.h_uid;
1009: } else {
1010: printf("%-6d", Hdr.h_uid);
1011: lastid = -1;
1012: }
1013: }
1014: printf("%7ld ", mklong(Hdr.h_filesize));
1015: U.l = mklong(Hdr.h_mtime);
1016: strcpy(tbuf, ctime((long *)&U.l));
1017: tbuf[24] = '\0';
1018: printf(" %s %s\n", &tbuf[4], namep);
1019: }
1020:
1021: /* pattern matching functions */
1022: nmatch(s, pat)
1023: char *s, **pat;
1024: {
1025: if(EQ(*pat, "*"))
1026: return 1;
1027: while(*pat) {
1028: if((**pat == '!' && !gmatch(s, *pat+1))
1029: || gmatch(s, *pat))
1030: return 1;
1031: ++pat;
1032: }
1033: return 0;
1034: }
1035: gmatch(s, p)
1036: register char *s, *p;
1037: {
1038: register int c;
1039: register cc, ok, lc, scc;
1040:
1041: scc = *s;
1042: lc = 077777;
1043: switch (c = *p) {
1044:
1045: case '[':
1046: ok = 0;
1047: while (cc = *++p) {
1048: switch (cc) {
1049:
1050: case ']':
1051: if (ok)
1052: return(gmatch(++s, ++p));
1053: else
1054: return(0);
1055:
1056: case '-':
1057: ok |= ((lc <= scc) && (scc <= (cc=p[1])));
1058: }
1059: if (scc==(lc=cc)) ok++;
1060: }
1061: return(0);
1062:
1063: case '?':
1064: caseq:
1065: if(scc) return(gmatch(++s, ++p));
1066: return(0);
1067: case '*':
1068: return(umatch(s, ++p));
1069: case 0:
1070: return(!scc);
1071: }
1072: if (c==scc) goto caseq;
1073: return(0);
1074: }
1075:
1076: umatch(s, p)
1077: register char *s, *p;
1078: {
1079: if(*p==0) return(1);
1080: while(*s)
1081: if (gmatch(s++,p)) return(1);
1082: return(0);
1083: }
1084:
1085: makdir(namep) /* make needed directories */
1086: register char *namep;
1087: {
1088: static status;
1089: register pid;
1090:
1091: if(pid = fork())
1092: while(wait(&status) != pid);
1093: else if(pid == -1) {
1094: fprintf(stderr,"Cannot fork, try again\n");
1095: exit(2);
1096: }
1097: else {
1098: close(2);
1099: execl("/bin/mkdir", "mkdir", namep, 0);
1100: exit(2);
1101: }
1102: return ((status>>8) & 0377)? 1: 0;
1103: }
1104:
1105: swap(buf, ct) /* swap halfwords, bytes or both */
1106: register ct;
1107: register char *buf;
1108: {
1109: register char c;
1110: register union swp { long longw; short shortv[2]; char charv[4]; } *pbuf;
1111: int savect, n, i;
1112: char *savebuf;
1113: short cc;
1114:
1115: savect = ct; savebuf = buf;
1116: if(byteswap || bothswap) {
1117: if (ct % 2) buf[ct] = 0;
1118: ct = (ct + 1) / 2;
1119: while (ct--) {
1120: c = *buf;
1121: *buf = *(buf + 1);
1122: *(buf + 1) = c;
1123: buf += 2;
1124: }
1125: if (bothswap) {
1126: ct = savect;
1127: pbuf = (union swp *)savebuf;
1128: if (n = ct % sizeof(union swp)) {
1129: if(n % 2)
1130: for(i = ct + 1; i <= ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0;
1131: else
1132: for (i = ct; i < ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0;
1133: }
1134: ct = (ct + (sizeof(union swp) -1)) / sizeof(union swp);
1135: while(ct--) {
1136: cc = pbuf->shortv[0];
1137: pbuf->shortv[0] = pbuf->shortv[1];
1138: pbuf->shortv[1] = cc;
1139: ++pbuf;
1140: }
1141: }
1142: }
1143: else if (halfswap) {
1144: pbuf = (union swp *)buf;
1145: if (n = ct % sizeof(union swp))
1146: for (i = ct; i < ct + (sizeof(union swp) - n); i++) pbuf->charv[i] = 0;
1147: ct = (ct + (sizeof(union swp) -1)) / sizeof(union swp);
1148: while (ct--) {
1149: cc = pbuf->shortv[0];
1150: pbuf->shortv[0] = pbuf->shortv[1];
1151: pbuf->shortv[1] = cc;
1152: ++pbuf;
1153: }
1154: }
1155: }
1156: set_time(namep, atime, mtime) /* set access and modification times */
1157: register *namep;
1158: long atime, mtime;
1159: {
1160: static long timevec[2];
1161:
1162: if(!Mod_time)
1163: return;
1164: timevec[0] = atime;
1165: timevec[1] = mtime;
1166: utime(namep, timevec);
1167: }
1168: chgreel(x, fl)
1169: {
1170: register f;
1171: char str[22];
1172: FILE *devtty;
1173: struct stat statb;
1174:
1175: fprintf(stderr,"errno: %d, ", errno);
1176: fprintf(stderr,"Can't %s\n", x? "write output": "read input");
1177: fstat(fl, &statb);
1178: #ifndef RT
1179: if((statb.st_mode&S_IFMT) != S_IFCHR)
1180: exit(2);
1181: #else
1182: if((statb.st_mode & (S_IFBLK|S_IFREC))==0)
1183: exit(2);
1184: #endif
1185: again:
1186: fprintf(stderr,"If you want to go on, type device/file name when ready\n");
1187: devtty = fopen("/dev/tty", "r");
1188: fgets(str, 20, devtty);
1189: str[strlen(str) - 1] = '\0';
1190: if(!*str)
1191: exit(2);
1192: close(fl);
1193: if((f = open(str, x? 1: 0)) < 0) {
1194: fprintf(stderr,"That didn't work");
1195: fclose(devtty);
1196: goto again;
1197: }
1198: fclose(devtty);
1199: return f;
1200: }
1201: missdir(namep)
1202: register char *namep;
1203: {
1204: register char *np;
1205: register ct = 2;
1206:
1207: for(np = namep; *np; ++np)
1208: if(*np == '/') {
1209: if(np == namep) continue; /* skip over 'root slash' */
1210: *np = '\0';
1211: if(stat(namep, &Xstatb) == -1) {
1212: if(Dir) {
1213: if((ct = makdir(namep)) != 0) {
1214: *np = '/';
1215: return(ct);
1216: }
1217: }else {
1218: fprintf(stderr,"missing 'd' option\n");
1219: return(-1);
1220: }
1221: }
1222: *np = '/';
1223: }
1224: if (ct == 2) ct = 0; /* the file already exists */
1225: return ct;
1226: }
1227:
1228: pwd() /* get working directory */
1229: {
1230: FILE *dir;
1231:
1232: dir = popen("pwd", "r");
1233: fgets(Fullname, 256, dir);
1234: if(pclose(dir))
1235: exit(2);
1236: Pathend = strlen(Fullname);
1237: Fullname[Pathend - 1] = '/';
1238: }
1239: char * cd(n) /* change directories */
1240: register char *n;
1241: {
1242: char *p_save = Name, *n_save = n, *p_end = 0;
1243: register char *p = Name;
1244: static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../";
1245: int slashes, ans;
1246:
1247: if(*n == '/') /* don't try to chdir on full pathnames */
1248: return n;
1249: for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */
1250: if(*p == '/')
1251: p_save = p+1, n_save = n+1;
1252: }
1253:
1254: p = p_save;
1255: *p++ = '\0';
1256: for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */
1257: if(*p == '/')
1258: ++slashes;
1259: }
1260: p = p_save;
1261: if(slashes) {
1262: slashes = slashes * 3 - 1;
1263: dotdot[slashes] = '\0';
1264: chdir(dotdot);
1265: dotdot[slashes] = '/';
1266: }
1267:
1268: n = n_save;
1269: for(; *n; ++n, ++p) {
1270: *p = *n;
1271: if(*n == '/')
1272: p_end = p+1, n_save = n+1;
1273: }
1274: *p = '\0';
1275:
1276: if(p_end) {
1277: *p_end = '\0';
1278: if(chdir(p_save) == -1) {
1279: if((ans = missdir(p_save)) == -1) {
1280: fprintf(stderr,"Cannot chdir (no `d' option)\n");
1281: exit(2);
1282: } else if (ans > 0) {
1283: fprintf(stderr,"Cannot chdir - no write permission\n");
1284: exit(2);
1285: } else if(chdir(p_save) == -1) {
1286: fprintf(stderr,"Cannot chdir\n");
1287: exit(2);
1288: }
1289: }
1290: } else
1291: *p_save = '\0';
1292: return n_save;
1293: }
1294:
1295: char *
1296: gets(s,n)
1297: char *s;
1298: {
1299: int c;
1300: char *t = s;
1301: while(--n>0) {
1302: c = getchar();
1303: if(c==EOF)
1304: return 0;
1305: if(c=='\n')
1306: break;
1307: *t++ = c;
1308: }
1309: *t = 0;
1310: return s;
1311: }
1312: #ifdef RT
1313: actsize(file)
1314: register int file;
1315: {
1316: long tlong;
1317: long fsize();
1318: register int tfile;
1319:
1320: Actual_size[0] = Hdr.h_filesize[0];
1321: Actual_size[1] = Hdr.h_filesize[1];
1322: if (!Extent)
1323: return;
1324: if (file)
1325: tfile = file;
1326: else if ((tfile = open(Hdr.h_name,0)) < 0)
1327: return;
1328: tlong = fsize(tfile);
1329: MKSHORT(Hdr.h_filesize,tlong);
1330: if (Cflag)
1331: bintochar(tlong);
1332: if (!file)
1333: close(tfile);
1334: }
1335: #endif
1336:
1337: #ifdef MAXFILENAME
1338: FILE *longnamefd;
1339:
1340: affix(n,ptr)
1341: int n;
1342: char *ptr;
1343: {
1344: int i=0,m;
1345: char ext[5];
1346:
1347: while(1) {
1348: if((m=n%52)<26) ext[i++] = m + 'a';
1349: else ext[i++] = m + 'A' - 26;
1350: if(n < 52)break;
1351: n = n/52 - 1; /* so we have Z,aa not Z,ba */
1352: }
1353:
1354: while(--i >= 0)*ptr++ = ext[i];
1355: *ptr = '\0';
1356: }
1357:
1358: #define MAXOVER 1000
1359: struct {
1360: char *longname,
1361: *shortname;
1362: } pairs[MAXOVER];
1363: int npairs = 0; /* no. of tabulated pairs */
1364:
1365: int ntoolong = 0; /* no. of overlong pathnames */
1366:
1367: char *
1368: findname(key)
1369: char *key;
1370: {
1371: int i, nprevious = 0, nprefix;
1372: char *longptr, *shortptr, *malloc(), *endbit, *strrchr();
1373:
1374: endbit = strrchr(key,'/');
1375: if(endbit == 0)endbit = key;
1376: else endbit++;
1377: nprefix = endbit - key;
1378:
1379: for(i=0;i<npairs;i++){
1380: if(strcmp(key,pairs[i].longname) == 0)
1381: return(pairs[i].shortname);
1382: if(strncmp(key,pairs[i].longname,nprefix+MAXFILENAME-4) == 0)
1383: nprevious++;
1384: }
1385: longptr = pairs[npairs].longname = malloc(strlen(key)+1);
1386: shortptr = pairs[npairs].shortname = malloc(MAXFILENAME+1);
1387: strcpy(longptr,key);
1388: strncpy(shortptr,endbit,MAXFILENAME-4);
1389: sprintf(shortptr+MAXFILENAME-4,"..");
1390: affix(nprevious,shortptr+MAXFILENAME-2);
1391: npairs++;
1392: return(shortptr);
1393: }
1394:
1395: fixname(original)
1396: char *original;
1397: {
1398: int length;
1399: char newname[100];
1400: register char *inend, *outptr=newname, *instart=original,
1401: *outstart;
1402: int changed = 0;
1403:
1404: while(1){
1405: if(*instart == '\0')break;
1406: if(*instart == '/')*outptr++ = *instart++;
1407: outstart = outptr;
1408: for(inend=instart;*inend != '\0' && *inend != '/';)
1409: *outptr++ = *inend++;
1410: *outptr = '\0';
1411: length = strlen(outstart);
1412: if(length > MAXFILENAME){
1413: changed++;
1414: strcpy(outstart,findname(newname));
1415: }
1416: outptr = outstart + strlen(outstart);
1417: instart = inend;
1418: }
1419:
1420: if(changed){
1421: if(ntoolong == 0) {
1422: longnamefd = fopen("longnamelist","a");
1423: if(longnamefd == NULL){
1424: fprintf(stderr,
1425: "can't create longnamelist file\n");
1426: exit(1);
1427: }
1428: fprintf(stderr,"check out file 'longnamelist'\n");
1429: }
1430: printf("%s changed to %s\n",original,newname);
1431: fprintf(longnamefd,"%s\t%s\n",original, newname);
1432: fflush(longnamefd);
1433: strcpy(original,newname);
1434: ntoolong++;
1435: }
1436: }
1437: #else /* MAXFILESIZE */
1438: fixname(){}
1439: #endif /* MAXFILESIZE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.