xref: /original-bsd/bin/pax/ar_subs.c (revision 4ba124f7)
1 /*-
2  * Copyright (c) 1992 Keith Muller.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Keith Muller of the University of California, San Diego.
8  *
9  * %sccs.include.redist.c%
10  */
11 
12 #ifndef lint
13 static char sccsid[] = "@(#)ar_subs.c	8.2 (Berkeley) 04/18/94";
14 #endif /* not lint */
15 
16 #include <sys/types.h>
17 #include <sys/time.h>
18 #include <sys/stat.h>
19 #include <sys/param.h>
20 #include <signal.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <ctype.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include "pax.h"
29 #include "extern.h"
30 
31 static void wr_archive __P((register ARCHD *, int is_app));
32 static int get_arc __P((void));
33 static int next_head __P((register ARCHD *));
34 extern sigset_t s_mask;
35 
36 /*
37  * Routines which control the overall operation modes of pax as specified by
38  * the user: list, append, read ...
39  */
40 
41 static char hdbuf[BLKMULT];             /* space for archive header on read */
42 u_long flcnt;				/* number of files processed */
43 
44 /*
45  * list()
46  *	list the contents of an archive which match user supplied pattern(s)
47  *	(no pattern matches all).
48  */
49 
50 #if __STDC__
51 void
52 list(void)
53 #else
54 void
55 list()
56 #endif
57 {
58 	register ARCHD *arcn;
59 	register int res;
60 	ARCHD archd;
61 	time_t now;
62 
63 	arcn = &archd;
64 	/*
65 	 * figure out archive type; pass any format specific options to the
66 	 * archive option processing routine; call the format init routine. We
67 	 * also save current time for ls_list() so we do not make a system
68 	 * call for each file we need to print. If verbose (vflag) start up
69 	 * the name and group caches.
70 	 */
71 	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
72 	    ((*frmt->st_rd)() < 0))
73 		return;
74 
75 	if (vflag && ((uidtb_start() < 0) || (gidtb_start() < 0)))
76 		return;
77 
78 	now = time((time_t *)NULL);
79 
80 	/*
81 	 * step through the archive until the format says it is done
82 	 */
83 	while (next_head(arcn) == 0) {
84 		/*
85 		 * check for pattern, and user specified options match.
86 		 * When all patterns are matched we are done.
87 		 */
88 		if ((res = pat_match(arcn)) < 0)
89 			break;
90 
91 		if ((res == 0) && (sel_chk(arcn) == 0)) {
92 			/*
93 			 * pattern resulted in a selected file
94 			 */
95 			if (pat_sel(arcn) < 0)
96 				break;
97 
98 			/*
99 			 * modify the name as requested by the user if name
100 			 * survives modification, do a listing of the file
101 			 */
102 			if ((res = mod_name(arcn)) < 0)
103 				break;
104 			if (res == 0)
105 				ls_list(arcn, now);
106 		}
107 
108 		/*
109 		 * skip to next archive format header using values calculated
110 		 * by the format header read routine
111 		 */
112 		if (rd_skip(arcn->skip + arcn->pad) == 1)
113 			break;
114 	}
115 
116 	/*
117 	 * all done, let format have a chance to cleanup, and make sure that
118 	 * the patterns supplied by the user were all matched
119 	 */
120 	(void)(*frmt->end_rd)();
121 	(void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL);
122 	ar_close();
123 	pat_chk();
124 }
125 
126 /*
127  * extract()
128  *	extract the member(s) of an archive as specified by user supplied
129  *	pattern(s) (no patterns extracts all members)
130  */
131 
132 #if __STDC__
133 void
134 extract(void)
135 #else
136 void
137 extract()
138 #endif
139 {
140 	register ARCHD *arcn;
141 	register int res;
142 	off_t cnt;
143 	ARCHD archd;
144 	struct stat sb;
145 	int fd;
146 
147 	arcn = &archd;
148 	/*
149 	 * figure out archive type; pass any format specific options to the
150 	 * archive option processing routine; call the format init routine;
151 	 * start up the directory modification time and access mode database
152 	 */
153 	if ((get_arc() < 0) || ((*frmt->options)() < 0) ||
154 	    ((*frmt->st_rd)() < 0) || (dir_start() < 0))
155 		return;
156 
157 	/*
158 	 * When we are doing interactive rename, we store the mapping of names
159 	 * so we can fix up hard links files later in the archive.
160 	 */
161 	if (iflag && (name_start() < 0))
162 		return;
163 
164 	/*
165 	 * step through each entry on the archive until the format read routine
166 	 * says it is done
167 	 */
168 	while (next_head(arcn) == 0) {
169 
170 		/*
171 		 * check for pattern, and user specified options match. When
172 		 * all the patterns are matched we are done
173 		 */
174 		if ((res = pat_match(arcn)) < 0)
175 			break;
176 
177 		if ((res > 0) || (sel_chk(arcn) != 0)) {
178 			/*
179 			 * file is not selected. skip past any file data and
180 			 * padding and go back for the next archive member
181 			 */
182 			(void)rd_skip(arcn->skip + arcn->pad);
183 			continue;
184 		}
185 
186 		/*
187 		 * with -u or -D only extract when the archive member is newer
188 		 * than the file with the same name in the file system (nos
189 		 * test of being the same type is required).
190 		 * NOTE: this test is done BEFORE name modifications as
191 		 * specified by pax. this operation can be confusing to the
192 		 * user who might expect the test to be done on an existing
193 		 * file AFTER the name mod. In honesty the pax spec is probably
194 		 * flawed in this respect.
195 		 */
196 		if ((uflag || Dflag) && ((lstat(arcn->name, &sb) == 0))) {
197 			if (uflag && Dflag) {
198 				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
199 				    (arcn->sb.st_ctime <= sb.st_ctime)) {
200 					(void)rd_skip(arcn->skip + arcn->pad);
201 					continue;
202 				}
203 			} else if (Dflag) {
204 				if (arcn->sb.st_ctime <= sb.st_ctime) {
205 					(void)rd_skip(arcn->skip + arcn->pad);
206 					continue;
207 				}
208 			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
209 				(void)rd_skip(arcn->skip + arcn->pad);
210 				continue;
211 			}
212 		}
213 
214 		/*
215 		 * this archive member is now been selected. modify the name.
216 		 */
217 		if ((pat_sel(arcn) < 0) || ((res = mod_name(arcn)) < 0))
218 			break;
219 		if (res > 0) {
220 			/*
221 			 * a bad name mod, skip and purge name from link table
222 			 */
223 			purg_lnk(arcn);
224 			(void)rd_skip(arcn->skip + arcn->pad);
225 			continue;
226 		}
227 
228 		/*
229 		 * Non standard -Y and -Z flag. When the exisiting file is
230 		 * same age or newer skip
231 		 */
232 		if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
233 			if (Yflag && Zflag) {
234 				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
235 				    (arcn->sb.st_ctime <= sb.st_ctime)) {
236 					(void)rd_skip(arcn->skip + arcn->pad);
237 					continue;
238 				}
239 			} else if (Yflag) {
240 				if (arcn->sb.st_ctime <= sb.st_ctime) {
241 					(void)rd_skip(arcn->skip + arcn->pad);
242 					continue;
243 				}
244 			} else if (arcn->sb.st_mtime <= sb.st_mtime) {
245 				(void)rd_skip(arcn->skip + arcn->pad);
246 				continue;
247 			}
248 		}
249 
250 		if (vflag) {
251 			(void)fputs(arcn->name, stderr);
252 			vfpart = 1;
253 		}
254 
255 		/*
256 		 * all ok, extract this member based on type
257 		 */
258 		if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
259 			/*
260 			 * process archive members that are not regular files.
261 			 * throw out padding and any data that might follow the
262 			 * header (as determined by the format).
263 			 */
264 			if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
265 				res = lnk_creat(arcn);
266 			else
267 				res = node_creat(arcn);
268 
269 			(void)rd_skip(arcn->skip + arcn->pad);
270 			if (res < 0)
271 				purg_lnk(arcn);
272 
273 			if (vflag && vfpart) {
274 				(void)putc('\n', stderr);
275 				vfpart = 0;
276 			}
277 			continue;
278 		}
279 		/*
280 		 * we have a file with data here. If we can not create it, skip
281 		 * over the data and purge the name from hard link table
282 		 */
283 		if ((fd = file_creat(arcn)) < 0) {
284 			(void)rd_skip(arcn->skip + arcn->pad);
285 			purg_lnk(arcn);
286 			continue;
287 		}
288 		/*
289 		 * extract the file from the archive and skip over padding and
290 		 * any unprocessed data
291 		 */
292 		res = (*frmt->rd_data)(arcn, fd, &cnt);
293 		file_close(arcn, fd);
294 		if (vflag && vfpart) {
295 			(void)putc('\n', stderr);
296 			vfpart = 0;
297 		}
298 		if (!res)
299 			(void)rd_skip(cnt + arcn->pad);
300 	}
301 
302 	/*
303 	 * all done, restore directory modes and times as required; make sure
304 	 * all patterns supplied by the user were matched; block off signals
305 	 * to avoid chance for multiple entry into the cleanup code.
306 	 */
307 	(void)(*frmt->end_rd)();
308 	(void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL);
309 	ar_close();
310 	proc_dir();
311 	pat_chk();
312 }
313 
314 /*
315  * wr_archive()
316  *	Write an archive. used in both creating a new archive and appends on
317  *	previously written archive.
318  */
319 
320 #if __STDC__
321 static void
322 wr_archive(register ARCHD *arcn, int is_app)
323 #else
324 static void
325 wr_archive(arcn, is_app)
326 	register ARCHD *arcn;
327 	int is_app;
328 #endif
329 {
330 	register int res;
331 	register int hlk;
332 	register int wr_one;
333 	off_t cnt;
334 	int (*wrf)();
335 	int fd = -1;
336 
337 	/*
338 	 * if this format supports hard link storage, start up the database
339 	 * that detects them.
340 	 */
341 	if (((hlk = frmt->hlk) == 1) && (lnk_start() < 0))
342 		return;
343 
344 	/*
345 	 * start up the file traversal code and format specific write
346 	 */
347 	if ((ftree_start() < 0) || ((*frmt->st_wr)() < 0))
348 		return;
349 	wrf = frmt->wr;
350 
351 	/*
352 	 * When we are doing interactive rename, we store the mapping of names
353 	 * so we can fix up hard links files later in the archive.
354 	 */
355 	if (iflag && (name_start() < 0))
356 		return;
357 
358 	/*
359 	 * if this not append, and there are no files, we do no write a trailer
360 	 */
361 	wr_one = is_app;
362 
363 	/*
364 	 * while there are files to archive, process them one at at time
365 	 */
366 	while (next_file(arcn) == 0) {
367 		/*
368 		 * check if this file meets user specified options match.
369 		 */
370 		if (sel_chk(arcn) != 0)
371 			continue;
372 		fd = -1;
373 		if (uflag) {
374 			/*
375 			 * only archive if this file is newer than a file with
376 			 * the same name that is already stored on the archive
377 			 */
378 			if ((res = chk_ftime(arcn)) < 0)
379 				break;
380 			if (res > 0)
381 				continue;
382 		}
383 
384 		/*
385 		 * this file is considered selected now. see if this is a hard
386 		 * link to a file already stored
387 		 */
388 		ftree_sel(arcn);
389 		if (hlk && (chk_lnk(arcn) < 0))
390 			break;
391 
392 		if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) ||
393 		    (arcn->type == PAX_CTG)) {
394 			/*
395 			 * we will have to read this file. by opening it now we
396 			 * can avoid writing a header to the archive for a file
397 			 * we were later unable to read (we also purge it from
398 			 * the link table).
399 			 */
400 			if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {
401 				syswarn(1,errno, "Unable to open %s to read",
402 					arcn->org_name);
403 				purg_lnk(arcn);
404 				continue;
405 			}
406 		}
407 
408 		/*
409 		 * Now modify the name as requested by the user
410 		 */
411 		if ((res = mod_name(arcn)) < 0) {
412 			/*
413 			 * name modification says to skip this file, close the
414 			 * file and purge link table entry
415 			 */
416 			rdfile_close(arcn, &fd);
417 			purg_lnk(arcn);
418 			break;
419 		}
420 
421 		if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {
422 			/*
423 			 * unable to obtain the crc we need, close the file,
424 			 * purge link table entry
425 			 */
426 			rdfile_close(arcn, &fd);
427 			purg_lnk(arcn);
428 			continue;
429 		}
430 
431 		if (vflag) {
432 			(void)fputs(arcn->name, stderr);
433 			vfpart = 1;
434 		}
435 		++flcnt;
436 
437 		/*
438 		 * looks safe to store the file, have the format specific
439 		 * routine write routine store the file header on the archive
440 		 */
441 		if ((res = (*wrf)(arcn)) < 0) {
442 			rdfile_close(arcn, &fd);
443 			break;
444 		}
445 		wr_one = 1;
446 		if (res > 0) {
447 			/*
448 			 * format write says no file data needs to be stored
449 			 * so we are done messing with this file
450 			 */
451 			if (vflag && vfpart) {
452 				(void)putc('\n', stderr);
453 				vfpart = 0;
454 			}
455 			rdfile_close(arcn, &fd);
456 			continue;
457 		}
458 
459 		/*
460 		 * Add file data to the archive, quit on write error. if we
461 		 * cannot write the entire file contents to the archive we
462 		 * must pad the archive to replace the missing file data
463 		 * (otherwise during an extract the file header for the file
464 		 * which FOLLOWS this one will not be where we expect it to
465 		 * be).
466 		 */
467 		res = (*frmt->wr_data)(arcn, fd, &cnt);
468 		rdfile_close(arcn, &fd);
469 		if (vflag && vfpart) {
470 			(void)putc('\n', stderr);
471 			vfpart = 0;
472 		}
473 		if (res < 0)
474 			break;
475 
476 		/*
477 		 * pad as required, cnt is number of bytes not written
478 		 */
479 		if (((cnt > 0) && (wr_skip(cnt) < 0)) ||
480 		    ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0)))
481 			break;
482 	}
483 
484 	/*
485 	 * tell format to write trailer; pad to block boundry; reset directory
486 	 * mode/access times, and check if all patterns supplied by the user
487 	 * were matched. block off signals to avoid chance for multiple entry
488 	 * into the cleanup code
489 	 */
490 	if (wr_one) {
491 		(*frmt->end_wr)();
492 		wr_fin();
493 	}
494 	(void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL);
495 	ar_close();
496 	if (tflag)
497 		proc_dir();
498 	ftree_chk();
499 }
500 
501 /*
502  * append()
503  *	Add file to previously written archive. Archive format specified by the
504  *	user must agree with archive. The archive is read first to collect
505  *	modification times (if -u) and locate the archive trailer. The archive
506  *	is positioned in front of the record with the trailer and wr_archive()
507  *	is called to add the new members.
508  *	PAX IMPLEMENTATION DETAIL NOTE:
509  *	-u is implemented by adding the new members to the end of the archive.
510  *	Care is taken so that these do not end up as links to the older
511  *	version of the same file already stored in the archive. It is expected
512  *	when extraction occurs these newer versions will over-write the older
513  *	ones stored "earlier" in the archive (this may be a bad assumption as
514  *	it depends on the implementation of the program doing the extraction).
515  *	It is really difficult to splice in members without either re-writing
516  *	the entire archive (from the point were the old version was), or having
517  *	assistance of the format specification in terms of a special update
518  *	header that invalidates a previous archive record. The posix spec left
519  *	the method used to implement -u unspecified. This pax is able to
520  *	over write existing files that it creates.
521  */
522 
523 #if __STDC__
524 void
525 append(void)
526 #else
527 void
528 append()
529 #endif
530 {
531 	register ARCHD *arcn;
532 	register int res;
533 	ARCHD archd;
534 	FSUB *orgfrmt;
535 	int udev;
536 	off_t tlen;
537 
538 	arcn = &archd;
539 	orgfrmt = frmt;
540 
541 	/*
542 	 * Do not allow an append operation if the actual archive is of a
543 	 * different format than the user specified foramt.
544 	 */
545 	if (get_arc() < 0)
546 		return;
547 	if ((orgfrmt != NULL) && (orgfrmt != frmt)) {
548 		warn(1, "Cannot mix current archive format %s with %s",
549 		    frmt->name, orgfrmt->name);
550 		return;
551 	}
552 
553 	/*
554 	 * pass the format any options and start up format
555 	 */
556 	if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0))
557 		return;
558 
559 	/*
560 	 * if we only are adding members that are newer, we need to save the
561 	 * mod times for all files we see.
562 	 */
563 	if (uflag && (ftime_start() < 0))
564 		return;
565 
566 	/*
567 	 * some archive formats encode hard links by recording the device and
568 	 * file serial number (inode) but copy the file anyway (multiple times)
569 	 * to the archive. When we append, we run the risk that newly added
570 	 * files may have the same device and inode numbers as those recorded
571 	 * on the archive but during a previous run. If this happens, when the
572 	 * archive is extracted we get INCORRECT hard links. We avoid this by
573 	 * remapping the device numbers so that newly added files will never
574 	 * use the same device number as one found on the archive. remapping
575 	 * allows new members to safely have links among themselves. remapping
576 	 * also avoids problems with file inode (serial number) truncations
577 	 * when the inode number is larger than storage space in the archive
578 	 * header. See the remap routines for more details.
579 	 */
580 	if ((udev = frmt->udev) && (dev_start() < 0))
581 		return;
582 
583 	/*
584 	 * reading the archive may take a long time. If verbose tell the user
585 	 */
586 	if (vflag) {
587 		(void)fprintf(stderr,
588 			"%s: Reading archive to position at the end...", argv0);
589 		vfpart = 1;
590 	}
591 
592 	/*
593 	 * step through the archive until the format says it is done
594 	 */
595 	while (next_head(arcn) == 0) {
596 		/*
597 		 * check if this file meets user specified options.
598 		 */
599 		if (sel_chk(arcn) != 0) {
600 			if (rd_skip(arcn->skip + arcn->pad) == 1)
601 				break;
602 			continue;
603 		}
604 
605 		if (uflag) {
606 			/*
607 			 * see if this is the newest version of this file has
608 			 * already been seen, if so skip.
609 			 */
610 			if ((res = chk_ftime(arcn)) < 0)
611 				break;
612 			if (res > 0) {
613 				if (rd_skip(arcn->skip + arcn->pad) == 1)
614 					break;
615 				continue;
616 			}
617 		}
618 
619 		/*
620 		 * Store this device number. Device numbers seen during the
621 		 * read phase of append will cause newly appended files with a
622 		 * device number seen in the old part of the archive to be
623 		 * remapped to an unused device number.
624 		 */
625 		if ((udev && (add_dev(arcn) < 0)) ||
626 		    (rd_skip(arcn->skip + arcn->pad) == 1))
627 			break;
628 	}
629 
630 	/*
631 	 * done, finish up read and get the number of bytes to back up so we
632 	 * can add new members. The format might have used the hard link table,
633 	 * purge it.
634 	 */
635 	tlen = (*frmt->end_rd)();
636 	lnk_end();
637 
638 	/*
639 	 * try to postion for write, if this fails quit. if any error occurs,
640 	 * we will refuse to write
641 	 */
642 	if (appnd_start(tlen) < 0)
643 		return;
644 
645 	/*
646 	 * tell the user we are done reading.
647 	 */
648 	if (vflag && vfpart) {
649 		(void)fputs("done.\n", stderr);
650 		vfpart = 0;
651 	}
652 
653 	/*
654 	 * go to the writing phase to add the new members
655 	 */
656 	wr_archive(arcn, 1);
657 }
658 
659 /*
660  * archive()
661  *	write a new archive
662  */
663 
664 #if __STDC__
665 void
666 archive(void)
667 #else
668 void
669 archive()
670 #endif
671 {
672 	ARCHD archd;
673 
674 	/*
675 	 * if we only are adding members that are newer, we need to save the
676 	 * mod times for all files; set up for writing; pass the format any
677 	 * options write the archive
678 	 */
679 	if ((uflag && (ftime_start() < 0)) || (wr_start() < 0))
680 		return;
681 	if ((*frmt->options)() < 0)
682 		return;
683 
684 	wr_archive(&archd, 0);
685 }
686 
687 /*
688  * copy()
689  *	copy files from one part of the file system to another. this does not
690  *	use any archive storage. The EFFECT OF THE COPY IS THE SAME as if an
691  *	archive was written and then extracted in the destination directory
692  *	(except the files are forced to be under the destination directory).
693  */
694 
695 #if __STDC__
696 void
697 copy(void)
698 #else
699 void
700 copy()
701 #endif
702 {
703 	register ARCHD *arcn;
704 	register int res;
705 	register int fddest;
706 	register char *dest_pt;
707 	register int dlen;
708 	register int drem;
709 	int fdsrc = -1;
710 	struct stat sb;
711 	ARCHD archd;
712 	char dirbuf[PAXPATHLEN+1];
713 
714 	arcn = &archd;
715 	/*
716 	 * set up the destination dir path and make sure it is a directory. We
717 	 * make sure we have a trailing / on the destination
718 	 */
719 	dlen = l_strncpy(dirbuf, dirptr, PAXPATHLEN);
720 	dest_pt = dirbuf + dlen;
721 	if (*(dest_pt-1) != '/') {
722 		*dest_pt++ = '/';
723 		++dlen;
724 	}
725 	*dest_pt = '\0';
726 	drem = PAXPATHLEN - dlen;
727 
728 	if (stat(dirptr, &sb) < 0) {
729 		syswarn(1, errno, "Cannot access destination directory %s",
730 			dirptr);
731 		return;
732 	}
733 	if (!S_ISDIR(sb.st_mode)) {
734 		warn(1, "Destination is not a directory %s", dirptr);
735 		return;
736 	}
737 
738 	/*
739 	 * start up the hard link table; file traversal routines and the
740 	 * modification time and access mode database
741 	 */
742 	if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))
743 		return;
744 
745 	/*
746 	 * When we are doing interactive rename, we store the mapping of names
747 	 * so we can fix up hard links files later in the archive.
748 	 */
749 	if (iflag && (name_start() < 0))
750 		return;
751 
752 	/*
753 	 * set up to cp file trees
754 	 */
755 	cp_start();
756 
757 	/*
758 	 * while there are files to archive, process them
759 	 */
760 	while (next_file(arcn) == 0) {
761 		fdsrc = -1;
762 
763 		/*
764 		 * check if this file meets user specified options
765 		 */
766 		if (sel_chk(arcn) != 0)
767 			continue;
768 
769 		/*
770 		 * if there is already a file in the destination directory with
771 		 * the same name and it is newer, skip the one stored on the
772 		 * archive.
773 		 * NOTE: this test is done BEFORE name modifications as
774 		 * specified by pax. this can be confusing to the user who
775 		 * might expect the test to be done on an existing file AFTER
776 		 * the name mod. In honesty the pax spec is probably flawed in
777 		 * this respect
778 		 */
779 		if (uflag || Dflag) {
780 			/*
781 			 * create the destination name
782 			 */
783 			if (*(arcn->name) == '/')
784 				res = 1;
785 			else
786 				res = 0;
787 			if ((arcn->nlen - res) > drem) {
788 				warn(1, "Destination pathname too long %s",
789 					arcn->name);
790 				continue;
791 			}
792 			(void)strncpy(dest_pt, arcn->name + res, drem);
793 			dirbuf[PAXPATHLEN] = '\0';
794 
795 			/*
796 			 * if existing file is same age or newer skip
797 			 */
798 			res = lstat(dirbuf, &sb);
799 			*dest_pt = '\0';
800 
801 		    	if (res == 0) {
802 				if (uflag && Dflag) {
803 					if ((arcn->sb.st_mtime<=sb.st_mtime) &&
804 			    		    (arcn->sb.st_ctime<=sb.st_ctime))
805 						continue;
806 				} else if (Dflag) {
807 					if (arcn->sb.st_ctime <= sb.st_ctime)
808 						continue;
809 				} else if (arcn->sb.st_mtime <= sb.st_mtime)
810 					continue;
811 			}
812 		}
813 
814 		/*
815 		 * this file is considered selected. See if this is a hard link
816 		 * to a previous file; modify the name as requested by the
817 		 * user; set the final destination.
818 		 */
819 		ftree_sel(arcn);
820 		if ((chk_lnk(arcn) < 0) || ((res = mod_name(arcn)) < 0))
821 			break;
822 		if ((res > 0) || (set_dest(arcn, dirbuf, dlen) < 0)) {
823 			/*
824 			 * skip file, purge from link table
825 			 */
826 			purg_lnk(arcn);
827 			continue;
828 		}
829 
830 		/*
831 		 * Non standard -Y and -Z flag. When the exisiting file is
832 		 * same age or newer skip
833 		 */
834 		if ((Yflag || Zflag) && ((lstat(arcn->name, &sb) == 0))) {
835 			if (Yflag && Zflag) {
836 				if ((arcn->sb.st_mtime <= sb.st_mtime) &&
837 				    (arcn->sb.st_ctime <= sb.st_ctime))
838 					continue;
839 			} else if (Yflag) {
840 				if (arcn->sb.st_ctime <= sb.st_ctime)
841 					continue;
842 			} else if (arcn->sb.st_mtime <= sb.st_mtime)
843 				continue;
844 		}
845 
846 		if (vflag) {
847 			(void)fputs(arcn->name, stderr);
848 			vfpart = 1;
849 		}
850 		++flcnt;
851 
852 		/*
853 		 * try to create a hard link to the src file if requested
854 		 * but make sure we are not trying to overwrite ourselves.
855 		 */
856 		if (lflag)
857 			res = cross_lnk(arcn);
858 		else
859 			res = chk_same(arcn);
860 		if (res <= 0) {
861 			if (vflag && vfpart) {
862 				(void)putc('\n', stderr);
863 				vfpart = 0;
864 			}
865 			continue;
866 		}
867 
868 		/*
869 		 * have to create a new file
870 		 */
871 		if ((arcn->type != PAX_REG) && (arcn->type != PAX_CTG)) {
872 			/*
873 			 * create a link or special file
874 			 */
875 			if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG))
876 				res = lnk_creat(arcn);
877 			else
878 				res = node_creat(arcn);
879 			if (res < 0)
880 				purg_lnk(arcn);
881 			if (vflag && vfpart) {
882 				(void)putc('\n', stderr);
883 				vfpart = 0;
884 			}
885 			continue;
886 		}
887 
888 		/*
889 		 * have to copy a regular file to the destination directory.
890 		 * first open source file and then create the destination file
891 		 */
892 		if ((fdsrc = open(arcn->org_name, O_RDONLY, 0)) < 0) {
893 			syswarn(1, errno, "Unable to open %s to read",
894 			    arcn->org_name);
895 			purg_lnk(arcn);
896 			continue;
897 		}
898 		if ((fddest = file_creat(arcn)) < 0) {
899 			rdfile_close(arcn, &fdsrc);
900 			purg_lnk(arcn);
901 			continue;
902 		}
903 
904 		/*
905 		 * copy source file data to the destination file
906 		 */
907 		cp_file(arcn, fdsrc, fddest);
908 		file_close(arcn, fddest);
909 		rdfile_close(arcn, &fdsrc);
910 
911 		if (vflag && vfpart) {
912 			(void)putc('\n', stderr);
913 			vfpart = 0;
914 		}
915 	}
916 
917 	/*
918 	 * restore directory modes and times as required; make sure all
919 	 * patterns were selected block off signals to avoid chance for
920 	 * multiple entry into the cleanup code.
921 	 */
922 	(void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL);
923 	ar_close();
924 	proc_dir();
925 	ftree_chk();
926 }
927 
928 /*
929  * next_head()
930  *	try to find a valid header in the archive. Uses format specific
931  *	routines to extract the header and id the trailer. Trailers may be
932  *	located within a valid header or in an invalid header (the location
933  *	is format specific. The inhead field from the option table tells us
934  *	where to look for the trailer).
935  *	We keep reading (and resyncing) until we get enough contiguous data
936  *	to check for a header. If we cannot find one, we shift by a byte
937  *	add a new byte from the archive to the end of the buffer and try again.
938  *	If we get a read error, we throw out what we have (as we must have
939  *	contiguous data) and start over again.
940  *	ASSUMED: headers fit within a BLKMULT header.
941  * Return:
942  *	0 if we got a header, -1 if we are unable to ever find another one
943  *	(we reached the end of input, or we reached the limit on retries. see
944  *	the specs for rd_wrbuf() for more details)
945  */
946 
947 #if __STDC__
948 static int
949 next_head(register ARCHD *arcn)
950 #else
951 static int
952 next_head(arcn)
953 	register ARCHD *arcn;
954 #endif
955 {
956 	register int ret;
957 	register char *hdend;
958 	register int res;
959 	register int shftsz;
960 	register int hsz;
961 	register int in_resync = 0; 	/* set when we are in resync mode */
962 	int cnt = 0;			/* counter for trailer function */
963 
964 	/*
965 	 * set up initial conditions, we want a whole frmt->hsz block as we
966 	 * have no data yet.
967 	 */
968 	res = hsz = frmt->hsz;
969 	hdend = hdbuf;
970 	shftsz = hsz - 1;
971 	for(;;) {
972 		/*
973 		 * keep looping until we get a contiguous FULL buffer
974 		 * (frmt->hsz is the proper size)
975 		 */
976 		for (;;) {
977 			if ((ret = rd_wrbuf(hdend, res)) == res)
978 				break;
979 
980 			/*
981 			 * some kind of archive read problem, try to resync the
982 			 * storage device, better give the user the bad news.
983 			 */
984 			if ((ret == 0) || (rd_sync() < 0)) {
985 				warn(1,"Premature end of file on archive read");
986 				return(-1);
987 			}
988 			if (!in_resync) {
989 				if (act == APPND) {
990 					warn(1,
991 				          "Archive I/O error, cannot continue");
992 					return(-1);
993 				}
994 				warn(1,"Archive I/O error. Trying to recover.");
995 				++in_resync;
996 			}
997 
998 			/*
999 			 * oh well, throw it all out and start over
1000 			 */
1001 			res = hsz;
1002 			hdend = hdbuf;
1003 		}
1004 
1005 		/*
1006 		 * ok we have a contiguous buffer of the right size. Call the
1007 		 * format read routine. If this was not a valid header and this
1008 		 * format stores trailers outside of the header, call the
1009 		 * format specific trailer routine to check for a trailer. We
1010 		 * have to watch out that we do not mis-identify file data or
1011 		 * block padding as a header or trailer. Format specific
1012 		 * trailer functions must NOT check for the trailer while we
1013 		 * are running in resync mode. Some trailer functions may tell
1014 		 * us that this block cannot contain a valid header either, so
1015 		 * we then throw out the entire block and start over.
1016 		 */
1017 		if ((*frmt->rd)(arcn, hdbuf) == 0)
1018 			break;
1019 
1020 		if (!frmt->inhead) {
1021 			/*
1022 			 * this format has trailers outside of valid headers
1023 			 */
1024 			if ((ret = (*frmt->trail)(hdbuf,in_resync,&cnt)) == 0){
1025 				/*
1026 				 * valid trailer found, drain input as required
1027 				 */
1028 				ar_drain();
1029 				return(-1);
1030 			}
1031 
1032 			if (ret == 1) {
1033 				/*
1034 				 * we are in resync and we were told to throw
1035 				 * the whole block out because none of the
1036 				 * bytes in this block can be used to form a
1037 				 * valid header
1038 				 */
1039 				res = hsz;
1040 				hdend = hdbuf;
1041 				continue;
1042 			}
1043 		}
1044 
1045 		/*
1046 		 * Brute force section.
1047 		 * not a valid header. We may be able to find a header yet. So
1048 		 * we shift over by one byte, and set up to read one byte at a
1049 		 * time from the archive and place it at the end of the buffer.
1050 		 * We will keep moving byte at a time until we find a header or
1051 		 * get a read error and have to start over.
1052 		 */
1053 		if (!in_resync) {
1054 			if (act == APPND) {
1055 				warn(1,"Unable to append, archive header flaw");
1056 				return(-1);
1057 			}
1058 			warn(1,"Invalid header, starting valid header search.");
1059 			++in_resync;
1060 		}
1061 		bcopy(hdbuf+1, hdbuf, shftsz);
1062 		res = 1;
1063 		hdend = hdbuf + shftsz;
1064 	}
1065 
1066 	/*
1067 	 * ok got a valid header, check for trailer if format encodes it in the
1068 	 * the header. NOTE: the parameters are different than trailer routines
1069 	 * which encode trailers outside of the header!
1070 	 */
1071 	if (frmt->inhead && ((*frmt->trail)(arcn) == 0)) {
1072 		/*
1073 		 * valid trailer found, drain input as required
1074 		 */
1075 		ar_drain();
1076 		return(-1);
1077 	}
1078 
1079 	++flcnt;
1080 	return(0);
1081 }
1082 
1083 /*
1084  * get_arc()
1085  *	Figure out what format an archive is. Handles archive with flaws by
1086  *	brute force searches for a legal header in any supported format. The
1087  *	format id routines have to be careful to NOT mis-identify a format.
1088  *	ASSUMED: headers fit within a BLKMULT header.
1089  * Return:
1090  *	0 if archive found -1 otherwise
1091  */
1092 
1093 #if __STDC__
1094 static int
1095 get_arc(void)
1096 #else
1097 static int
1098 get_arc()
1099 #endif
1100 {
1101 	register int i;
1102 	register int hdsz = 0;
1103 	register int res;
1104 	register int minhd = BLKMULT;
1105 	char *hdend;
1106 	int notice = 0;
1107 
1108 	/*
1109 	 * find the smallest header size in all archive formats and then set up
1110 	 * to read the archive.
1111 	 */
1112 	for (i = 0; ford[i] >= 0; ++i) {
1113 		if (fsub[ford[i]].hsz < minhd)
1114 			minhd = fsub[ford[i]].hsz;
1115 	}
1116 	if (rd_start() < 0)
1117 		return(-1);
1118 	res = BLKMULT;
1119 	hdsz = 0;
1120 	hdend = hdbuf;
1121 	for(;;) {
1122 		for (;;) {
1123 			/*
1124 			 * fill the buffer with at least the smallest header
1125 			 */
1126 			i = rd_wrbuf(hdend, res);
1127 			if (i > 0)
1128 				hdsz += i;
1129 			if (hdsz >= minhd)
1130 				break;
1131 
1132 			/*
1133 			 * if we cannot recover from a read error quit
1134 			 */
1135 			if ((i == 0) || (rd_sync() < 0))
1136 				goto out;
1137 
1138 			/*
1139 			 * when we get an error none of the data we already
1140 			 * have can be used to create a legal header (we just
1141 			 * got an error in the middle), so we throw it all out
1142 			 * and refill the buffer with fresh data.
1143 			 */
1144 			res = BLKMULT;
1145 			hdsz = 0;
1146 			hdend = hdbuf;
1147 			if (!notice) {
1148 				if (act == APPND)
1149 					return(-1);
1150 				warn(1,"Cannot identify format. Searching...");
1151 				++notice;
1152 			}
1153 		}
1154 
1155 		/*
1156 		 * we have at least the size of the smallest header in any
1157 		 * archive format. Look to see if we have a match. The array
1158 		 * ford[] is used to specify the header id order to reduce the
1159 		 * chance of incorrectly id'ing a valid header (some formats
1160 		 * may be subsets of each other and the order would then be
1161 		 * important).
1162 		 */
1163 		for (i = 0; ford[i] >= 0; ++i) {
1164 			if ((*fsub[ford[i]].id)(hdbuf, hdsz) < 0)
1165 				continue;
1166 			frmt = &(fsub[ford[i]]);
1167 			/*
1168 			 * yuck, to avoid slow special case code in the extract
1169 			 * routines, just push this header back as if it was
1170 			 * not seen. We have left extra space at start of the
1171 			 * buffer for this purpose. This is a bit ugly, but
1172 			 * adding all the special case code is far worse.
1173 			 */
1174 			pback(hdbuf, hdsz);
1175 			return(0);
1176 		}
1177 
1178 		/*
1179 		 * We have a flawed archive, no match. we start searching, but
1180 		 * we never allow additions to flawed archives
1181 		 */
1182 		if (!notice) {
1183 			if (act == APPND)
1184 				return(-1);
1185 			warn(1, "Cannot identify format. Searching...");
1186 			++notice;
1187 		}
1188 
1189 		/*
1190 		 * brute force search for a header that we can id.
1191 		 * we shift through byte at a time. this is slow, but we cannot
1192 		 * determine the nature of the flaw in the archive in a
1193 		 * portable manner
1194 		 */
1195 		if (--hdsz > 0) {
1196 			bcopy(hdbuf+1, hdbuf, hdsz);
1197 			res = BLKMULT - hdsz;
1198 			hdend = hdbuf + hdsz;
1199 		} else {
1200 			res = BLKMULT;
1201 			hdend = hdbuf;
1202 			hdsz = 0;
1203 		}
1204 	}
1205 
1206     out:
1207 	/*
1208 	 * we cannot find a header, bow, apologize and quit
1209 	 */
1210 	warn(1, "Sorry, unable to determine archive format.");
1211 	return(-1);
1212 }
1213