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