xref: /original-bsd/local/local.cmd/ncpio.c (revision f052b07a)
1 static 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
35 extern long filespace;
36 #endif
37 
38 struct	stat	Statb, Xstatb;
39 
40 	/* Cpio header format */
41 struct 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 
56 unsigned	Bufsize = BUFSIZE;		/* default record size */
57 short	Buf[CPIOBSZ/2], *Dbuf;
58 char	BBuf[CPIOBSZ], *Cbuf;
59 int	Wct, Wc;
60 short	*Wp;
61 char	*Cp;
62 
63 #ifdef RT
64 short	Actual_size[2];
65 #endif
66 
67 short	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 
88 int	Ifile,
89 	Ofile,
90 	Input = 0,
91 	Output = 1;
92 long	Blocks,
93 	Longfile,
94 	Longtime;
95 
96 char	Fullname[MAXPATHLEN+1],
97 	Name[MAXPATHLEN+1];
98 int	Pathend;
99 
100 FILE	*Rtty,
101 	*Wtty;
102 
103 char	*Pattern[100];
104 char	Strhdr[500];
105 char	*Chdr = Strhdr;
106 short	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 
118 extern	errno;
119 char	*malloc();
120 char 	*cd();
121 /*	char	*Cd_name;	*/
122 FILE 	*popen();
123 
124 union { long l; short s[2]; char c[4]; } U;
125 
126 /* for VAX, Interdata, ... */
127 long mklong(v)
128 short 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 
138 main(argc, argv)
139 char **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) {
183 accerr:
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));
489 ckverbose:
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 }
499 usage()
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 
507 getname()		/* 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 
572 bintochar(t)		/* ASCII header write */
573 long 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 
581 chartobin()		/* 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 
591 gethdr()		/* 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 
655 ckname(namep)	/* check filenames with patterns given on cmd line */
656 register 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 
686 openout(namep)	/* open files for writing, set all necessary info */
687 register 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 
727 ret:
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 
855 bread(b, c)
856 register c;
857 register 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 
887 readhdr(b, c)
888 register c;
889 register 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 
918 bwrite(rp, c)
919 register short *rp;
920 register c;
921 {
922 	register short *wp = Wp;
923 
924 	c = (c+1) >> 1;
925 	while(c--) {
926 		if(!Wct) {
927 again:
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 
942 writehdr(rp, c)
943 register char *rp;
944 register c;
945 {
946 	register char *cp = Cp;
947 
948 	while(c--)  {
949 		if(!Wc)  {
950 again:
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 
965 postml(namep, np)		/* linking funtion */
966 register 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 
1035 pentry(namep)		/* print verbose table of contents */
1036 register 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 */
1067 nmatch(s, pat)
1068 char *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 }
1080 gmatch(s, p)
1081 register 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 
1121 umatch(s, p)
1122 register 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 .. */
1132 makdir(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
1141 makdir(namep)		/* make needed directories */
1142 register 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 
1158 swap(buf, ct)		/* swap halfwords, bytes or both */
1159 register ct;
1160 register 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 }
1209 set_time(namep, atime, mtime)	/* set access and modification times */
1210 register *namep;
1211 long 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 }
1221 chgreel(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
1238 again:
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 }
1253 missdir(namep)
1254 register 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 
1280 pwd()		/* 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 }
1291 char * cd(n)		/* change directories */
1292 register 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
1347 actsize(file)
1348 register 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
1372 outsymlink()
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 
1398 ipsymlink(namep)
1399 char *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
1496 symlink()
1497 {
1498 	return(-1);
1499 }
1500 lstat(name, statb)
1501 char *name
1502 struct stat *statb;
1503 {
1504 	stat(name, statb);
1505 }
1506 #endif
1507 
1508 discardfile(len)
1509 long 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 }
1524