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