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