1 /* @(#)extract.c	1.170 20/07/08 Copyright 1985-2020 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)extract.c	1.170 20/07/08 Copyright 1985-2020 J. Schilling";
6 #endif
7 /*
8  *	extract files from archive
9  *
10  *	Copyright (c) 1985-2020 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/stdio.h>
27 #include <schily/standard.h>
28 #include "star.h"
29 #include "props.h"
30 #include "table.h"
31 #include <schily/dirent.h>	/* XXX Wegen S_IFLNK */
32 #include <schily/unistd.h>
33 #include <schily/fcntl.h>
34 #include <schily/string.h>
35 #include <schily/jmpdefs.h>	/* For __fjmalloc() */
36 #define	GT_COMERR		/* #define comerr gtcomerr */
37 #define	GT_ERROR		/* #define error gterror   */
38 #include <schily/schily.h>
39 #include <schily/stdlib.h>
40 #include <schily/errno.h>
41 #ifdef	USE_FIND
42 #include <schily/walk.h>
43 #endif
44 
45 #ifdef	JOS
46 #define	mkdir	makedir
47 #endif
48 #include "dirtime.h"
49 #include "restore.h"
50 #include "starsubs.h"
51 #include "checkerr.h"
52 #include <schily/fetchdir.h>
53 
54 #define	ROOT_UID	0
55 
56 #if defined(ENOTEMPTY) && ENOTEMPTY != EEXIST
57 #define	is_eexist(err)	((err) == EEXIST || (err) == ENOTEMPTY)
58 #else
59 #define	is_eexist(err)	((err) == EEXIST)
60 #endif
61 #if defined(EMISSDIR)
62 #define	is_enoent(err)	((err) == ENOENT || (err) == EMISSDIR)
63 #else
64 #define	is_enoent(err)	((err) == ENOENT)
65 #endif
66 #if defined(ELOOP)
67 #define	is_eloop(err)	((err) == ELOOP)
68 #else
69 #define	is_eloop(err)	(FALSE)
70 #endif
71 
72 /*
73  * Used for _make_copy()/make_copies()/copy_file()
74  */
75 #define	HIDE_ENOENT	0x01
76 
77 /*
78  * Used by the what paramater of same_file()
79  */
80 #define	IS_COPY		0
81 #define	IS_LINK		1
82 
83 extern	FILE	*vpr;
84 
85 extern	char	*listfile;
86 
87 extern	long	bufsize;
88 extern	char	*bigptr;
89 
90 extern	uid_t	dir_uid;
91 extern	gid_t	dir_gid;
92 extern	uid_t	my_uid;
93 extern	BOOL	no_fsync;
94 extern	BOOL	havepat;
95 extern	dev_t	curfs;
96 extern	int	xdebug;
97 extern	int	verbose;
98 extern	BOOL	prblockno;
99 extern	BOOL	nflag;
100 extern	BOOL	interactive;
101 extern	BOOL	noxdir;
102 extern	BOOL	follow;
103 extern	BOOL	paxfollow;
104 extern	BOOL	nospec;
105 extern	BOOL	xdir;
106 extern	BOOL	xdot;
107 extern	BOOL	uncond;
108 extern	BOOL	uncond_rename;
109 extern	BOOL	keep_old;
110 extern	BOOL	refresh_old;
111 extern	BOOL	abs_path;
112 extern	BOOL	allow_dotdot;
113 extern	BOOL	secure_links;
114 extern	BOOL	nowarn;
115 extern	BOOL	force_hole;
116 extern	BOOL	to_stdout;
117 extern	BOOL	force_remove;
118 extern	BOOL	remove_first;
119 extern	BOOL	remove_recursive;
120 extern	BOOL	do_install;
121 extern	BOOL	copyhardlinks;
122 extern	BOOL	copysymlinks;
123 extern	BOOL	copydlinks;
124 extern	BOOL	hardlinks;
125 extern	BOOL	symlinks;
126 extern	BOOL	dorestore;
127 extern	BOOL	dometa;
128 extern	BOOL	xmeta;
129 extern	BOOL	lowmem;
130 extern	BOOL	do_subst;
131 #ifdef	USE_SELINUX
132 extern	BOOL	selinux_enabled;
133 #endif
134 
135 #ifdef	USE_FIND
136 extern	BOOL	dofind;
137 #endif
138 
139 LOCAL	void	init_umask	__PR((void));
140 EXPORT	void	extract		__PR((char *vhname));
141 EXPORT	BOOL	extracti	__PR((FINFO *info, imap_t *imp));
142 EXPORT	BOOL	newer		__PR((FINFO *info, FINFO *cinfo));
143 EXPORT	BOOL	same_symlink	__PR((FINFO *info));
144 LOCAL	BOOL	_create_dirs	__PR((char *name));
145 LOCAL	void	_dir_setownwer	__PR((char *name));
146 EXPORT	BOOL	create_dirs	__PR((char *name));
147 EXPORT	BOOL	make_adir	__PR((FINFO *info));
148 LOCAL	BOOL	make_dir	__PR((FINFO *info));
149 LOCAL	BOOL	make_link	__PR((FINFO *info));
150 LOCAL	BOOL	make_symlink	__PR((FINFO *info));
151 LOCAL	BOOL	emul_symlink	__PR((FINFO *info));
152 LOCAL	BOOL	emul_link	__PR((FINFO *info));
153 LOCAL	BOOL	same_file	__PR((FINFO *info, int what, BOOL do_follow));
154 LOCAL	BOOL	make_copy	__PR((FINFO *info, BOOL do_symlink, int eflags));
155 #ifdef COPY_LINKS_DELAYED
156 LOCAL	void	add_copy	__PR((FINFO *info, BOOL do_symlink));
157 LOCAL	void	make_copies	__PR((void));
158 LOCAL	BOOL	_make_dcopy	__PR((FINFO *info, BOOL do_symlink, int *retp, int eflags));
159 #endif
160 LOCAL	BOOL	_make_copy	__PR((FINFO *info, BOOL do_symlink, int eflags));
161 LOCAL	int	copy_file	__PR((char *from, char *to, BOOL do_symlink, int eflags));
162 LOCAL	BOOL	make_fifo	__PR((FINFO *info));
163 LOCAL	BOOL	make_special	__PR((FINFO *info));
164 LOCAL	BOOL	file_tmpname	__PR((FINFO *info, pathstore_t *path));
165 LOCAL	FILE	*file_open	__PR((FINFO *info, char *name));
166 LOCAL	BOOL	get_file	__PR((FINFO *info));
167 LOCAL	BOOL	install_rename	__PR((FINFO *info, char *xname));
168 LOCAL	BOOL	name_exists	__PR((char *name));
169 LOCAL	void	remove_tmpname	__PR((char *name));
170 LOCAL	BOOL	get_ofile	__PR((FILE *f, FINFO *info));
171 LOCAL	ssize_t	void_func	__PR((void *vp, char *p, size_t amount));
172 EXPORT	BOOL	void_file	__PR((FINFO * info));
173 LOCAL	BOOL	void_bad	__PR((FINFO * info));
174 EXPORT	int	xt_file		__PR((FINFO * info,
175 					ssize_t (*)(void *, char *, size_t),
176 					void *arg, long amt, char *text));
177 EXPORT	void	skip_slash	__PR((FINFO * info));
178 LOCAL	BOOL	has_dotdot	__PR((char *name));
179 LOCAL	BOOL	inside_tree	__PR((FINFO * info));
180 
181 #ifdef COPY_LINKS_DELAYED
182 typedef	struct _mcq {
183 	struct _mcq *next;
184 	FINFO	info;
185 	BOOL	do_symlink;
186 } MCQ;
187 
188 LOCAL	MCQ	*mcq_1st	= NULL;
189 LOCAL	MCQ	*mcq_last	= NULL;
190 
191 #endif
192 
193 /*
194  * This is used to allow extracting archives as non root when they
195  * contain read only directories. It tries to stay as close as possible
196  * to the user's umask when creating intermediate directories.
197  * We do not modify the umask in a way that would even grant unepected
198  * permissions to others for a short time.
199  */
200 LOCAL	mode_t	old_umask;
201 LOCAL	mode_t	mode_mask;
202 
203 #define	PERM_BITS	(S_IRWXU|S_IRWXG|S_IRWXO)	/* u/g/o basic perm */
204 
205 LOCAL void
init_umask()206 init_umask()
207 {
208 	old_umask = umask((mode_t)0);
209 	mode_mask = PERM_BITS & ~old_umask;
210 	if (my_uid != ROOT_UID)
211 		umask(old_umask & ~S_IRWXU);
212 	else
213 		umask(old_umask);
214 }
215 
216 EXPORT void
extract(vhname)217 extract(vhname)
218 	char	*vhname;
219 {
220 #ifdef	USE_FIND
221 extern	struct WALK walkstate;
222 #endif
223 		FINFO	finfo;
224 		TCB	tb;
225 	register TCB 	*ptb = &tb;
226 		BOOL	restore_init = FALSE;
227 		imap_t	*imp = NULL;
228 
229 	init_umask();		/* Needed to extract read only directories */
230 
231 	if (dorestore)		/* With incremental restore, we need to open */
232 		sym_open(NULL);	/* the 'star-symtable' first.		    */
233 
234 	fillbytes((char *)&finfo, sizeof (finfo), '\0');
235 
236 	if (init_pspace(PS_STDERR, &finfo.f_pname) < 0)
237 		return;
238 	if (init_pspace(PS_STDERR, &finfo.f_plname) < 0)
239 		return;
240 
241 #ifdef	USE_FIND
242 	if (dofind) {
243 		walkopen(&walkstate);
244 		walkgethome(&walkstate);	/* Needed in case we chdir */
245 	}
246 #endif
247 	finfo.f_tcb = ptb;
248 	for (;;) {
249 		if (get_tcb(ptb) == EOF)
250 			break;
251 		finfo.f_name = finfo.f_pname.ps_path;
252 		finfo.f_lname = finfo.f_plname.ps_path;
253 		if (tcb_to_info(ptb, &finfo) == EOF)
254 			break;
255 		if (xdebug > 0)
256 			dump_info(&finfo);
257 		if (prblockno)
258 			(void) tblocks();		/* set curblockno */
259 
260 		if (is_volhdr(&finfo)) {
261 			if (!get_volhdr(&finfo, vhname)) {
262 				excomerrno(EX_BAD,
263 				"Volume Header '%s' does not match '%s'.\n",
264 							finfo.f_name, vhname);
265 			}
266 			void_file(&finfo);
267 			continue;
268 		}
269 #ifdef	USE_FIND
270 		if (dofind && !findinfo(&finfo)) {
271 			void_file(&finfo);
272 			continue;
273 		}
274 #endif
275 		if (finfo.f_flags & F_BAD_META) {
276 			if (!void_bad(&finfo))
277 				break;
278 			continue;
279 		}
280 
281 		if (!abs_path &&	/* XXX VVV siehe skip_slash() */
282 		    (finfo.f_name[0] == '/' /* || finfo.f_lname[0] == '/'*/))
283 			skip_slash(&finfo);
284 
285 		if (dorestore) {
286 			extern	GINFO	*grip;	/* Global read info pointer */
287 
288 			if (!restore_init) {
289 				curfs = finfo.f_dev;
290 				sym_init(grip);
291 				restore_init = TRUE;
292 			}
293 
294 			imp = sym_addrec(&finfo);
295 			if (is_dir(&finfo) && grip->dumplevel > 0)
296 				imp = sym_dirprepare(&finfo, imp);
297 		}
298 
299 #ifdef	USE_SELINUX
300 		if (!to_stdout && selinux_enabled) {
301 			/*
302 			 * Set up security context for next file.
303 			 */
304 			if (!setselinux(&finfo))
305 				xstats.s_selinuxerrs++;
306 		}
307 #endif
308 		/*
309 		 * Special treatment for the idiosyncratic way of dealing with
310 		 * hard links in the SVr4 CRC cpio archive format.
311 		 * The link count is handled by calling read_link() in
312 		 * cpiotcb_to_info() before.
313 		 */
314 		if ((props.pr_flags & PR_SV_CPIO_LINKS) != 0 &&
315 		    !is_dir(&finfo) &&
316 		    (is_link(&finfo) || finfo.f_nlink > 1)) {
317 			if (!last_cpio_link(&finfo))	/* Ign. all but last */
318 				continue;
319 			if (xcpio_link(&finfo))		/* Now extract all   */
320 				continue;
321 		}
322 		if (extracti(&finfo, imp) > TRUE) {
323 			errmsgno(EX_BAD, "Exiting as -one-file was specified\n");
324 			break;
325 		}
326 	}
327 #ifdef	USE_FIND
328 	if (dofind) {
329 		walkhome(&walkstate);
330 		walkclose(&walkstate);
331 		free(walkstate.twprivate);
332 	}
333 #endif
334 
335 #ifdef COPY_LINKS_DELAYED
336 	if (copyhardlinks || copysymlinks)
337 		make_copies();
338 #endif
339 	flushdirtimes();	/* Flush directory stack */
340 	if (dorestore)
341 		sym_close();
342 }
343 
344 /*
345  * Extract one file from archive
346  */
347 EXPORT BOOL
extracti(info,imp)348 extracti(info, imp)
349 		FINFO	*info;
350 		imap_t	*imp;
351 {
352 		FINFO	cinfo;
353 		TCB	tb;
354 	register TCB 	*ptb = &tb;
355 		char	*name = info->f_name;
356 		BOOL	didmatch = FALSE;
357 	extern	BOOL	one_file;
358 
359 	if (listfile && !hash_lookup(info->f_name)) {
360 		void_file(info);
361 		return (FALSE);
362 	}
363 	if (hash_xlookup(info->f_name)) {
364 		void_file(info);
365 		return (FALSE);
366 	}
367 	if (havepat) {
368 		if (!match(info->f_name)) {
369 			void_file(info);
370 			return (FALSE);
371 		}
372 		if (one_file)
373 			didmatch = TRUE;
374 	}
375 	if (!is_file(info) && to_stdout) {
376 		void_file(info);
377 		return (FALSE);
378 	}
379 	if (is_special(info) && nospec) {
380 		if (!errhidden(E_SPECIALFILE, info->f_name)) {
381 			if (!errwarnonly(E_SPECIALFILE, info->f_name))
382 				xstats.s_isspecial++;
383 			errmsgno(EX_BAD,
384 				"'%s' is not a file. Not created.\n",
385 							info->f_name);
386 			(void) errabort(E_SPECIALFILE, info->f_name, TRUE);
387 		}
388 		void_file(info);
389 		return (FALSE);
390 	}
391 	/*
392 	 * If uncond is set and neither keep_old nor refresh_old is set,
393 	 * then newer() doesn't call getinfo(&cinfo).
394 	 * As newer() calls getinfo(&cinfo), it also checks for refresh_old.
395 	 */
396 	if (!uncond_rename) {
397 		/*
398 		 * -uncond-rename was not specified, so check whether newer.
399 		 */
400 		if (newer(info, &cinfo) && !(xdir && is_dir(info))) {
401 			void_file(info);
402 			return (FALSE);
403 		}
404 		if (is_symlink(info) && same_symlink(info)) {
405 			void_file(info);
406 			return (FALSE);
407 		}
408 	}
409 	/*
410 	 * Name substitution and interactive name changing need to happen before
411 	 * we check whether the file is newer than an existing file of the same
412 	 * name in the filesystem.
413 	 */
414 	if (do_subst && subst(info)) {
415 		if (info->f_name[0] == '\0') {
416 			/*
417 			 * Changed to empty name: skip...
418 			 */
419 			if (verbose)
420 				fgtprintf(vpr,
421 				"'%s' substitutes to null string, skipping ...\n",
422 							name);
423 			void_file(info);
424 			return (FALSE);
425 		}
426 		/*
427 		 * Changed name to a probably existing file,
428 		 * check whether file in archive is newer.
429 		 */
430 		if (newer(info, &cinfo) && !(xdir && is_dir(info))) {
431 			void_file(info);
432 			return (FALSE);
433 		}
434 		if (is_symlink(info) && same_symlink(info)) {
435 			void_file(info);
436 			return (FALSE);
437 		}
438 	}
439 	if (interactive && !ia_change(ptb, info)) {
440 		if (!nflag)
441 			fgtprintf(vpr, "Skipping ...\n");
442 		void_file(info);
443 		return (FALSE);
444 	}
445 	/*
446 	 * If uncond is set and neither keep_old nor refresh_old is set,
447 	 * then newer() doesn't call getinfo(&cinfo).
448 	 * As newer() calls getinfo(&cinfo), it also checks for refresh_old.
449 	 */
450 	if (uncond_rename) {
451 		/*
452 		 * -uncond-rename was specified
453 		 * If the file was not renamed we now need to check whether
454 		 * the file in the archive is newer than the file with the
455 		 * new name on disk.
456 		 */
457 		if (newer(info, &cinfo) && !(xdir && is_dir(info))) {
458 			void_file(info);
459 			return (FALSE);
460 		}
461 		if (is_symlink(info) && same_symlink(info)) {
462 			void_file(info);
463 			return (FALSE);
464 		}
465 	}
466 	if (!(interactive || allow_dotdot) && has_dotdot(info->f_name)) {
467 		if (!errhidden(E_SECURITY, info->f_name)) {
468 			if (!errwarnonly(E_SECURITY, info->f_name))
469 				xstats.s_security++;
470 			errmsgno(EX_BAD,
471 			"'%s' contains '..', skipping ...\n", info->f_name);
472 			(void) errabort(E_SECURITY, info->f_name, TRUE);
473 		}
474 		void_file(info);
475 		return (FALSE);
476 	}
477 	if (secure_links && (is_link(info) || is_symlink(info)) &&
478 	    (info->f_lname[0] == '/' || has_dotdot(info->f_lname))) {
479 		if (info->f_lname[0] != '/') {
480 			/*
481 			 * Absolute paths are always a problem, but symlinks
482 			 * should be allowed as long as they do not point
483 			 * outside the current tree.
484 			 */
485 			if (inside_tree(info))
486 				goto link_ok;
487 		}
488 		if (!errhidden(E_LSECURITY, info->f_lname)) {
489 			if (!errwarnonly(E_LSECURITY, info->f_lname))
490 				xstats.s_lsecurity++;
491 			errmsgno(EX_BAD,
492 			"'%s' potentially insecure link, skipping ...\n", info->f_name);
493 			(void) errabort(E_LSECURITY, info->f_lname, TRUE);
494 		}
495 		void_file(info);
496 		return (FALSE);
497 	}
498 link_ok:
499 	vprint(info);
500 	if (dorestore) {
501 		/*
502 		 * Check whether the target file exists and has a
503 		 * different type or is a dev node with different
504 		 * major/minor numbers. In this case, we need to
505 		 * remove the file. This happend when the original
506 		 * file has been removed and a new (different) file
507 		 * with the same name did get the same inode number.
508 		 */
509 		imp = sym_typecheck(info, &cinfo, imp);
510 
511 	} else if (remove_first && !dometa) {
512 		/*
513 		 * With keep_old we do not come here.
514 		 *
515 		 * Even if the archive and the current node are both
516 		 * directories call remove_file() because the new dir
517 		 * may get our ownership this way if we are not root.
518 		 *
519 		 * In order to avoid annoying messages, call remove_file()
520 		 * only if the file exists.
521 		 */
522 		if (name_exists(info->f_name))
523 			(void) remove_file(info->f_name, TRUE);
524 	}
525 	if (is_dir(info)) {
526 #ifdef	MKD_DEBUG
527 		{ extern char *mkdwhy; mkdwhy = "extract"; }
528 #endif
529 		if (!make_adir(info)) {
530 			void_file(info);
531 			return (FALSE);
532 		}
533 		void_file(info);
534 	} else if (is_link(info)) {
535 		if (!make_link(info)) {
536 			void_file(info);
537 			return (FALSE);
538 		}
539 		void_file(info);
540 	} else if (is_symlink(info)) {
541 		if (dorestore && imp) {
542 			/*
543 			 * Do not create a new link if the old one is the same.
544 			 */
545 			if (cinfo.f_rxftype != XT_NONE && (cinfo.f_flags & F_SAME))
546 				goto set_modes;
547 		}
548 		if (!make_symlink(info)) {
549 			void_file(info);
550 			return (FALSE);
551 		}
552 		void_file(info);
553 	} else if (is_special(info)) {
554 		if (dorestore && imp) {
555 			/*
556 			 * Do not create a new node if the old one is the same.
557 			 */
558 			if (cinfo.f_rxftype != XT_NONE && (cinfo.f_flags & F_SAME))
559 				goto set_modes;
560 		}
561 		if (is_door(info)) {
562 			if (!nowarn) {
563 				errmsgno(EX_BAD,
564 				"WARNING: Extracting door '%s' as plain file.\n",
565 						info->f_name);
566 			}
567 			if (!get_file(info))
568 				return (FALSE);
569 		} else if (is_fifo(info)) {
570 			if (!make_fifo(info)) {
571 				void_file(info);
572 				return (FALSE);
573 			}
574 			void_file(info);
575 		} else {
576 			if (!make_special(info)) {
577 				void_file(info);
578 				return (FALSE);
579 			}
580 			void_file(info);
581 		}
582 	} else if (is_meta(info)) {
583 		FINFO	finfo;
584 
585 		/*
586 		 * Make sure not to overwrite existing files.
587 		 */
588 		if (xmeta && !_getinfo(info->f_name, &finfo)) {
589 			if (!get_file(info))
590 				return (FALSE);
591 		} else {
592 			void_file(info);
593 		}
594 	} else if (!get_file(info)) {
595 		return (FALSE);
596 	}
597 
598 #ifdef COPY_LINKS_DELAYED
599 	if ((copyhardlinks && is_link(info)) ||
600 	    (copysymlinks && is_symlink(info)))
601 		return (TRUE+didmatch);
602 #endif
603 set_modes:
604 	if (!to_stdout)
605 		setmodes(info);
606 #ifdef	TEST_DEBUG
607 if (info->f_mode == 0700)
608 error("-->setmode(%s, %llo)\n", info->f_name, (Ullong)info->f_mode);
609 #endif
610 	if (dorestore)
611 		sym_addstat(info, imp);
612 	return (TRUE+didmatch);
613 }
614 
615 /*
616  * Return TRUE if the file on disk is newer than the file on the archive.
617  */
618 EXPORT BOOL
newer(info,cinfo)619 newer(info, cinfo)
620 	FINFO	*info;	/* The FINFO for the file in the archive */
621 	FINFO	*cinfo;	/* The FINFO for the file in the file system */
622 {
623 	BOOL	havenano;
624 
625 	if (uncond && !keep_old && !refresh_old)
626 		return (FALSE);
627 	if (!_getinfo(info->f_name, cinfo)) {
628 		if (refresh_old) {
629 			errmsgno(EX_BAD, "file '%s' does not exists.\n", info->f_name);
630 			return (TRUE);
631 		}
632 		return (FALSE);
633 	}
634 	if (keep_old) {
635 		if (!nowarn)
636 			errmsgno(EX_BAD, "file '%s' exists.\n", info->f_name);
637 		return (TRUE);
638 	}
639 	if (uncond)
640 		return (FALSE);
641 
642 	if (xdot) {
643 		if (info->f_name[0] == '.' &&
644 		    (info->f_name[1] == '\0' ||
645 		    (info->f_name[1] == '/' &&
646 		    info->f_name[2] == '\0'))) {
647 
648 			return (FALSE);
649 		}
650 	}
651 
652 	/*
653 	 * Honor nsecs if part of the archive.
654 	 */
655 	havenano = (info->f_xflags & XF_MTIME) && (cinfo->f_flags & F_NSECS);
656 	if ((cinfo->f_mtime > info->f_mtime) ||
657 	    (!havenano && cinfo->f_mtime == info->f_mtime)) {
658 
659 	isnewer:
660 		if (xdir && is_dir(info))	/* Be silent, we handle it later */
661 			return (TRUE);
662 		if (!nowarn)
663 			errmsgno(EX_BAD, "current '%s' newer.\n", info->f_name);
664 		return (TRUE);
665 	} else if ((cinfo->f_mtime == info->f_mtime) && havenano) {
666 		/*
667 		 * If we have nanoseconds != 0, this cannot be a DOS file and
668 		 * for this reason, the f_mtime resolution is one second.
669 		 * An archive with nanosecond resolution and a filesystem with
670 		 * microsecond resolution could result in a file in the archive
671 		 * that is always newer than the file in the filesystem because
672 		 * the timestamp in the filesystem was rounded down. If the
673 		 * nanoseconds in the local file are greater than in the
674 		 * archive, this is the easy case.
675 		 */
676 		if (cinfo->f_mnsec >= info->f_mnsec)
677 			goto isnewer;
678 		/*
679 		 * If the local filesystem resolution is only microseconds and
680 		 * the resolution in the archive is nanoseconds, we need to
681 		 * check based on microseconds to prevent extracting the
682 		 * file from the archive again and again.
683 		 * This is the UFS variant.
684 		 */
685 		if ((cinfo->f_mnsec % 1000 == 0) &&
686 		    ((cinfo->f_mnsec / 1000) >= (info->f_mnsec / 1000)))
687 			goto isnewer;
688 
689 		/*
690 		 * This is the NTFS (Win-DOS) variant that is based on
691 		 * 1/10 microseconds since 1601.
692 		 */
693 		if ((cinfo->f_mnsec % 100 == 0) &&
694 		    ((cinfo->f_mnsec / 100) >= (info->f_mnsec / 100)))
695 			goto isnewer;
696 	} else if ((cinfo->f_mtime % 2) == 0 && (cinfo->f_mtime + 1) == info->f_mtime) {
697 		/*
698 		 * The DOS FAT filestem does only support a time granularity
699 		 * of 2 seconds. So we need to be a bit more generous.
700 		 * XXX We should be able to test the filesytem type.
701 		 */
702 		goto isnewer;
703 	}
704 	return (FALSE);
705 }
706 
707 EXPORT BOOL
same_symlink(info)708 same_symlink(info)
709 	FINFO	*info;
710 {
711 	FINFO	finfo;
712 	char	lname[PATH_MAX+1];	/* This limit cannot be overruled */
713 	TCB	tb;
714 
715 	finfo.f_lname = lname;
716 	finfo.f_lnamelen = 0;
717 
718 	if (uncond || !_getinfo(info->f_name, &finfo))
719 		return (FALSE);
720 
721 	/*
722 	 * Bei symlinks gehen nicht: lchmod lchtime & teilweise lchown
723 	 */
724 #ifdef	S_IFLNK
725 	if (!is_symlink(&finfo))	/* File on disk */
726 		return (FALSE);
727 
728 	fillbytes(&tb, sizeof (TCB), '\0');
729 	info_to_tcb(&finfo, &tb);	/* XXX ist das noch n�tig ??? */
730 					/* z.Zt. wegen linkflag/uname/gname */
731 
732 	if (read_symlink(info->f_name, info->f_name, &finfo, &tb)) {
733 		if (streql(info->f_lname, finfo.f_lname)) {
734 			if (!nowarn)
735 				errmsgno(EX_BAD, "current '%s' is same symlink.\n",
736 								info->f_name);
737 			return (TRUE);
738 		}
739 	}
740 #ifdef	XXX
741 	/*
742 	 * XXX nsec beachten wenn im Archiv!
743 	 */
744 	if (finfo.f_mtime >= info->f_mtime) {
745 		if (!nowarn)
746 			errmsgno(EX_BAD, "current '%s' newer.\n", info->f_name);
747 		return (TRUE);
748 	}
749 #endif	/* XXX */
750 
751 #endif
752 	return (FALSE);
753 }
754 
755 EXPORT BOOL
same_special(info)756 same_special(info)
757 	FINFO	*info;
758 {
759 	FINFO	finfo;
760 
761 	if (uncond || !_getinfo(info->f_name, &finfo))
762 		return (FALSE);
763 
764 	if (info->f_xftype != finfo.f_xftype)
765 		return (FALSE);
766 
767 	if (is_bdev(info) || is_cdev(info)) {
768 		if (info->f_rdevmaj != finfo.f_rdevmaj)
769 			return (FALSE);
770 		if (info->f_rdevmin != finfo.f_rdevmin)
771 			return (FALSE);
772 	}
773 	return (TRUE);
774 }
775 
776 /*
777  * Create intermediate directories.
778  * If the user is not root and the umask is degenerated or read-only,
779  * we add 0700 to the granted permissions. For this reason, we may need
780  * to correct the permissins of intermediate directories later from the
781  * directory stack.
782  */
783 LOCAL BOOL
_create_dirs(name)784 _create_dirs(name)
785 	register char	*name;
786 {
787 	mode_t	mode;
788 
789 	mode = mode_mask;				/* used to be 0777 */
790 	if (my_uid != ROOT_UID)
791 		mode |= S_IRWXU;	/* Make sure we will be able write */
792 
793 	if (lmkdir(name, mode) < 0) {
794 		if (create_dirs(name) &&
795 		    lmkdir(name, mode) >= 0) {
796 			_dir_setownwer(name);
797 			if (mode != mode_mask)
798 				sdirmode(name, mode_mask); /* Push umask */
799 			return (TRUE);
800 		}
801 		return (FALSE);
802 	}
803 	_dir_setownwer(name);
804 	if (mode != mode_mask)
805 		sdirmode(name, mode_mask);	/* Push umask on dirstack */
806 	return (TRUE);
807 }
808 
809 /*
810  * Set the owner/group of intermedia directories.
811  * Be very careful not to overwrite sgid directory semantics.
812  */
813 LOCAL void
_dir_setownwer(name)814 _dir_setownwer(name)
815 	char	*name;
816 {
817 	FINFO	dinfo;
818 
819 	if (my_uid != ROOT_UID)
820 		return;
821 
822 	if (dir_uid == _BAD_UID && dir_gid == _BAD_GID)
823 		return;
824 
825 	if (!_getinfo(name, &dinfo) || !is_dir(&dinfo))
826 		return;
827 
828 	if (dir_uid != _BAD_UID)
829 		dinfo.f_uid = dir_uid;
830 	if (dir_gid != _BAD_GID)
831 		dinfo.f_gid = dir_gid;
832 
833 	lchownat(name, dinfo.f_uid, dinfo.f_gid, 0);
834 }
835 
836 EXPORT BOOL
create_dirs(name)837 create_dirs(name)
838 	register char	*name;
839 {
840 	register char	*np;
841 	register char	*dp;
842 		int	err;
843 		int	olderr = 0;
844 
845 	if (noxdir) {
846 		errmsgno(EX_BAD, "Directories not created.\n");
847 		return (FALSE);
848 	}
849 	np = dp = name;
850 	do {
851 		if (*np == '/')
852 			dp = np;
853 	} while (*np++);
854 	if (dp == name) {
855 		/*
856 		 * Do not create the very last directory
857 		 */
858 		return (TRUE);
859 	}
860 	*dp = '\0';
861 	if (laccess(name, F_OK) < 0) {
862 		if (_create_dirs(name)) {
863 			*dp = '/';
864 			return (TRUE);
865 		}
866 		err = geterrno();
867 		if ((err == EACCES || is_eexist(err) || is_eloop(err))) {
868 			olderr = err;
869 			goto exists;
870 		}
871 		*dp = '/';
872 		return (FALSE);
873 	} else {
874 		FINFO	dinfo;
875 
876 	exists:
877 		if (_getinfo(name, &dinfo)) {
878 			if (is_dir(&dinfo)) {
879 				*dp = '/';
880 				return (TRUE);
881 			}
882 
883 			if (remove_file(name, FALSE)) {
884 				if (_create_dirs(name)) {
885 					*dp = '/';
886 					return (TRUE);
887 				}
888 				*dp = '/';
889 				return (FALSE);
890 			} else {
891 				*dp = '/';
892 				return (FALSE);
893 			}
894 		}
895 		*dp = '/';
896 		if (olderr == EACCES)
897 			seterrno(olderr);
898 		return (FALSE);
899 	}
900 }
901 
902 #ifdef	MKD_DEBUG
903 EXPORT char	*mkdwhy;
904 #endif
905 
906 EXPORT BOOL
make_adir(info)907 make_adir(info)
908 	FINFO	*info;
909 {
910 	if (is_link(info))
911 		return (make_link(info));
912 	else
913 		return (make_dir(info));
914 }
915 
916 /*
917  * This function is used only to create directories found on the archive.
918  * Intermediate directories are created using create_dirs().
919  */
920 LOCAL BOOL
make_dir(info)921 make_dir(info)
922 	FINFO	*info;
923 {
924 	FINFO	dinfo;
925 	mode_t	mode;
926 	int	err;
927 
928 	if (dometa)
929 		return (TRUE);
930 
931 	mode = osmode(info->f_mode);	/* Convert TAR modes to OS modes */
932 	mode &= mode_mask;		/* Apply current umask */
933 	if (my_uid != ROOT_UID)
934 		mode |= S_IRWXU;	/* Make sure we will be able write */
935 
936 	if (_getinfo(info->f_name, &dinfo) && is_dir(&dinfo))
937 		return (TRUE);
938 
939 	if (create_dirs(info->f_name)) {
940 		if (_getinfo(info->f_name, &dinfo) && is_dir(&dinfo))
941 			return (TRUE);
942 		if (lmkdir(info->f_name, mode) >= 0)
943 			return (TRUE);
944 		err = geterrno();
945 		if ((err == EACCES || is_eexist(err) || is_eloop(err)) &&
946 				remove_file(info->f_name, FALSE)) {
947 			if (lmkdir(info->f_name, mode) >= 0)
948 				return (TRUE);
949 		}
950 	}
951 #ifdef	MKD_DEBUG
952 	errmsgno(EX_BAD, "make_dir(%s) called from '%s'\n", info->f_name, mkdwhy);
953 #endif
954 	if (!errhidden(E_OPEN, info->f_name)) {
955 		if (!errwarnonly(E_OPEN, info->f_name))
956 			xstats.s_openerrs++;
957 		errmsg("Cannot make dir '%s'.\n", info->f_name);
958 		(void) errabort(E_OPEN, info->f_name, TRUE);
959 	}
960 	return (FALSE);
961 }
962 
963 LOCAL BOOL
make_link(info)964 make_link(info)
965 	FINFO	*info;
966 {
967 	int	err;
968 #ifdef	USE_FFLAGS
969 	FINFO	linfo;
970 	Ulong	oldflags = 0L;
971 #endif
972 	pathstore_t	path;
973 	char	xname[PATH_MAX+1];
974 	char	*name = info->f_name;
975 	BOOL	ret = TRUE;
976 
977 	/*
978 	 * void_file() is needed for CPIO and done by our callers.
979 	 */
980 
981 	if (dometa)
982 		return (TRUE);
983 
984 	path.ps_path = xname;
985 
986 #ifdef	HAVE_LINK_NOFOLLOW
987 	/*
988 	 * This OS allows hard links to symlinks and does not follow symlinks
989 	 * when making hard links to symlinks. We may not follow symlinks while
990 	 * we check if source & sestination are the same.
991 	 */
992 	if (same_file(info, IS_LINK, FALSE)) {
993 #else
994 	/*
995 	 * This OS either does not allow hard links to symlinks or follows
996 	 * symlinks if possible before making a hard link to a symlink.
997 	 * We need not follow symlinks while we check if source & sestination
998 	 * are the same.
999 	 */
1000 	if (same_file(info, IS_LINK, TRUE)) {
1001 #endif
1002 		/*
1003 		 * As it seems that from/to for the hard link are already
1004 		 * identical files, return TRUE to indicate success with
1005 		 * creating the hard link.
1006 		 */
1007 		return (TRUE);
1008 	}
1009 
1010 	if (copyhardlinks)
1011 		return (make_copy(info, FALSE, 0));
1012 	else if (hardlinks)
1013 		return (emul_link(info));
1014 
1015 #ifdef	HAVE_LINK
1016 	xname[0] = '\0';
1017 	if (do_install && name_exists(name)) {
1018 		if (!file_tmpname(info, &path)) {
1019 			ret = FALSE;
1020 			goto out;
1021 		}
1022 		name = path.ps_path;
1023 	}
1024 	if (llink(info->f_lname, name) >= 0)
1025 		goto ok;
1026 	err = geterrno();
1027 	if (info->f_rsize > 0 && is_enoent(err)) {
1028 		ret = get_file(info);
1029 		goto out;
1030 	}
1031 #ifdef	USE_FFLAGS
1032 	/*
1033 	 * SF_IMMUTABLE might be set on the source-file. Clear the flags
1034 	 * and try again.
1035 	 */
1036 	if (_getinfo(info->f_lname, &linfo) && (linfo.f_xflags & XF_FFLAGS)) {
1037 		oldflags = linfo.f_fflags;
1038 		linfo.f_fflags = 0L;
1039 		set_fflags(&linfo);
1040 		if (llink(info->f_lname, name) >= 0)
1041 			goto restore_flags;
1042 		err = geterrno();
1043 	}
1044 #endif
1045 	if (create_dirs(info->f_name)) {
1046 		if (llink(info->f_lname, name) >= 0)
1047 			goto restore_flags;
1048 		err = geterrno();
1049 	}
1050 	if ((err == EACCES || is_eexist(err) || is_eloop(err)) &&
1051 			remove_file(name, FALSE)) {
1052 		if (llink(info->f_lname, name) >= 0)
1053 			goto restore_flags;
1054 	}
1055 	if (!errhidden(E_OPEN, info->f_name)) {
1056 		if (!errwarnonly(E_OPEN, info->f_name))
1057 			xstats.s_openerrs++;
1058 		errmsg("Cannot link '%s' to '%s'.\n",
1059 				info->f_name, info->f_lname);
1060 		(void) errabort(E_OPEN, info->f_name, TRUE);
1061 	}
1062 	if (do_install)
1063 		remove_tmpname(path.ps_path);
1064 	ret = FALSE;
1065 	goto out;
1066 
1067 restore_flags:
1068 #ifdef	USE_FFLAGS
1069 	if (oldflags != 0L) {
1070 		linfo.f_fflags = oldflags;
1071 		set_fflags(&linfo);
1072 	}
1073 #endif
1074 ok:
1075 	if (do_install)
1076 		ret = install_rename(info, path.ps_path);
1077 out:
1078 	if (path.ps_path != xname)
1079 		free_pspace(&path);
1080 	return (ret);
1081 
1082 #else	/* HAVE_LINK */
1083 	if (!errhidden(E_SPECIALFILE, info->f_name)) {
1084 		if (!errwarnonly(E_SPECIALFILE, info->f_name))
1085 			xstats.s_isspecial++;
1086 		errmsgno(EX_BAD,
1087 		"Not supported. Cannot link '%s' to '%s'.\n",
1088 						info->f_name, info->f_lname);
1089 		(void) errabort(E_SPECIALFILE, info->f_name, TRUE);
1090 	}
1091 	return (FALSE);
1092 #endif	/* HAVE_LINK */
1093 }
1094 
1095 LOCAL BOOL
make_symlink(info)1096 make_symlink(info)
1097 	FINFO	*info;
1098 {
1099 	int	err;
1100 	pathstore_t	path;
1101 	char	xname[PATH_MAX+1];
1102 	char	*name = info->f_name;
1103 	BOOL	ret = TRUE;
1104 
1105 	if (dometa)
1106 		return (TRUE);
1107 
1108 	path.ps_path = xname;
1109 
1110 	if (copysymlinks)
1111 		return (make_copy(info, TRUE, 0));
1112 	else if (symlinks)
1113 		return (emul_symlink(info));
1114 
1115 #ifdef	S_IFLNK
1116 	xname[0] = '\0';
1117 	if (do_install && name_exists(name)) {
1118 		if (!file_tmpname(info, &path)) {
1119 			ret = FALSE;
1120 			goto out;
1121 		}
1122 		name = path.ps_path;
1123 	}
1124 	if (sxsymlink(name, info) >= 0)
1125 		goto ok;
1126 	err = geterrno();
1127 	if (create_dirs(info->f_name)) {
1128 		if (sxsymlink(name, info) >= 0)
1129 			goto ok;
1130 		err = geterrno();
1131 	}
1132 	/*
1133 	 * XXX at least with same symlinks we should return success
1134 	 */
1135 	if ((err == EACCES || is_eexist(err) || is_eloop(err)) &&
1136 			remove_file(name, FALSE)) {
1137 		if (sxsymlink(name, info) >= 0)
1138 			goto ok;
1139 	}
1140 	if (!errhidden(E_OPEN, info->f_name)) {
1141 		if (!errwarnonly(E_OPEN, info->f_name))
1142 			xstats.s_openerrs++;
1143 		errmsg("Cannot create symbolic link '%s' to '%s'.\n",
1144 						info->f_name, info->f_lname);
1145 		(void) errabort(E_OPEN, info->f_name, TRUE);
1146 	}
1147 	if (do_install)
1148 		remove_tmpname(path.ps_path);
1149 	ret = FALSE;
1150 	goto out;
1151 ok:
1152 	if (do_install)
1153 		ret = install_rename(info, path.ps_path);
1154 out:
1155 	if (path.ps_path != xname)
1156 		free_pspace(&path);
1157 	return (ret);
1158 #else	/* S_IFLNK */
1159 	if (!errhidden(E_SPECIALFILE, info->f_name)) {
1160 		if (!errwarnonly(E_SPECIALFILE, info->f_name))
1161 			xstats.s_isspecial++;
1162 		errmsgno(EX_BAD,
1163 		"Not supported. Cannot create symbolic link '%s' to '%s'.\n",
1164 						info->f_name, info->f_lname);
1165 		(void) errabort(E_SPECIALFILE, info->f_name, TRUE);
1166 	}
1167 	return (FALSE);
1168 #endif	/* S_IFLNK */
1169 }
1170 
1171 LOCAL BOOL
emul_symlink(info)1172 emul_symlink(info)
1173 	FINFO	*info;
1174 {
1175 	errmsgno(EX_BAD, "Option -symlinks not yet implemented.\n");
1176 	errmsgno(EX_BAD, "Cannot create symbolic link '%s' to '%s'.\n",
1177 						info->f_name, info->f_lname);
1178 	return (FALSE);
1179 }
1180 
1181 LOCAL BOOL
emul_link(info)1182 emul_link(info)
1183 	FINFO	*info;
1184 {
1185 	errmsgno(EX_BAD, "Option -hardlinks not yet implemented.\n");
1186 	errmsgno(EX_BAD, "Cannot link '%s' to '%s'.\n", info->f_name, info->f_lname);
1187 #ifdef	HAVE_LINK
1188 	return (FALSE);
1189 #else
1190 	return (FALSE);
1191 #endif	/* S_IFLNK */
1192 }
1193 
1194 LOCAL BOOL
same_file(info,what,do_follow)1195 same_file(info, what, do_follow)
1196 	FINFO	*info;
1197 	int	what;
1198 	BOOL	do_follow;
1199 {
1200 	FINFO	finfo;
1201 	FINFO	linfo;
1202 	BOOL	ofollow = follow;
1203 	BOOL	ret = FALSE;
1204 
1205 	follow = do_follow;
1206 	if (_getinfo(info->f_name, &finfo) && _getinfo(info->f_lname, &linfo)) {
1207 		if (finfo.f_dev == linfo.f_dev && finfo.f_ino == linfo.f_ino) {
1208 			if (what == IS_COPY) {
1209 				if (!errhidden(E_SAMEFILE, info->f_lname)) {
1210 					if (!errwarnonly(E_SAMEFILE, info->f_lname))
1211 						xstats.s_samefile++;
1212 					errmsgno(EX_BAD,
1213 					"copy_file: '%s' from/to identical, skipping ...\n",
1214 						info->f_name);
1215 					(void) errabort(E_SAMEFILE,
1216 							info->f_lname, TRUE);
1217 				}
1218 			} else {
1219 				/*
1220 				 * If in restore mode, we do not like to see
1221 				 * this informational message. The hard link
1222 				 * is already present and this is all we need.
1223 				 * If -force-remove has been specified (default
1224 				 * for "tar") we do not like to see this message
1225 				 * either.
1226 				 */
1227 				if (!nowarn && !dorestore && !force_remove) {
1228 					errmsgno(EX_BAD,
1229 					"Notice: link_file: '%s' from/to identical, skipping ...\n",
1230 						info->f_name);
1231 				}
1232 			}
1233 			ret = TRUE;
1234 		}
1235 	}
1236 	follow = ofollow;
1237 	return (ret);
1238 }
1239 
1240 LOCAL BOOL
make_copy(info,do_symlink,eflags)1241 make_copy(info, do_symlink, eflags)
1242 	FINFO	*info;
1243 	BOOL	do_symlink;
1244 	int	eflags;
1245 {
1246 #ifdef COPY_LINKS_DELAYED
1247 	if (!lowmem) {
1248 		add_copy(info, do_symlink);
1249 		return (TRUE);
1250 	} else {
1251 		return (_make_copy(info, do_symlink, eflags));
1252 	}
1253 #else
1254 	return (_make_copy(info, do_symlink, eflags));
1255 #endif
1256 }
1257 
1258 LOCAL BOOL
_make_copy(info,do_symlink,eflags)1259 _make_copy(info, do_symlink, eflags)
1260 	FINFO	*info;
1261 	BOOL	do_symlink;
1262 	int	eflags;
1263 {
1264 	int	ret;
1265 	int	err;
1266 
1267 #ifdef COPY_LINKS_DELAYED
1268 	if (!lowmem && copydlinks) {
1269 		if (_make_dcopy(info, do_symlink, &ret, eflags))
1270 			return (ret);
1271 	}
1272 #endif
1273 	/*
1274 	 * As we can only copy plain files, we need to follow symlinks when
1275 	 * we check if source & destination are the same file.
1276 	 */
1277 	if (same_file(info, IS_COPY, TRUE)) {
1278 		return (FALSE);
1279 	}
1280 
1281 	if ((ret = copy_file(info->f_lname, info->f_name, do_symlink, eflags)) >= 0)
1282 		return (TRUE);
1283 	err = geterrno();
1284 	if (ret != -2 && create_dirs(info->f_name)) {
1285 		if (copy_file(info->f_lname, info->f_name, do_symlink, eflags) >= 0)
1286 			return (TRUE);
1287 		err = geterrno();
1288 	}
1289 	if ((err == EACCES || is_eexist(err) || err == EISDIR || is_eloop(err)) &&
1290 			remove_file(info->f_name, FALSE)) {
1291 		if (copy_file(info->f_lname, info->f_name, do_symlink, eflags) >= 0)
1292 			return (TRUE);
1293 	}
1294 	if (!errhidden(E_OPEN, info->f_name) &&
1295 	    ((eflags & HIDE_ENOENT) == 0 || geterrno() != ENOENT)) {
1296 		if (!errwarnonly(E_OPEN, info->f_name))
1297 			xstats.s_openerrs++;
1298 		errmsg("Cannot create link copy '%s' from '%s'.\n",
1299 					info->f_name, info->f_lname);
1300 		(void) errabort(E_OPEN, info->f_name, TRUE);
1301 	}
1302 	return (FALSE);
1303 }
1304 
1305 #ifdef COPY_LINKS_DELAYED
1306 LOCAL void
add_copy(info,do_symlink)1307 add_copy(info, do_symlink)
1308 	FINFO	*info;
1309 	BOOL	do_symlink;
1310 {
1311 	MCQ	*mcqp	   = ___malloc(sizeof (MCQ), "make_copy()");
1312 	char	*f_namep   = ___savestr(info->f_name);
1313 	char	*f_lnamep  = ___savestr(info->f_lname);
1314 
1315 	mcqp->next	   = NULL;
1316 	mcqp->do_symlink   = do_symlink;
1317 	mcqp->info	   = *info;
1318 	mcqp->info.f_name  = f_namep;
1319 	mcqp->info.f_lname = f_lnamep;
1320 
1321 	if (mcq_last) {
1322 		mcq_last->next = mcqp;
1323 		mcq_last = mcqp;
1324 	} else {
1325 		mcq_1st = mcqp;
1326 		mcq_last = mcqp;
1327 	}
1328 }
1329 
1330 LOCAL void
make_copies()1331 make_copies()
1332 {
1333 	int	eflags	= HIDE_ENOENT;
1334 
1335 	do {
1336 		MCQ	*mcqp		= mcq_1st;
1337 		MCQ	*mcqp_prev	= NULL;
1338 		int	mcq_removed	= 0;
1339 
1340 		while (mcqp) {
1341 			MCQ	*mcqp_save	= mcqp;
1342 			BOOL	ret		= _make_copy(&mcqp->info,
1343 							mcqp->do_symlink,
1344 							eflags);
1345 
1346 			if (ret) {
1347 				if (!to_stdout)
1348 					setmodes(&mcqp->info);
1349 				if (dorestore)
1350 					sym_addstat(&mcqp->info, NULL);
1351 			}
1352 			mcqp = mcqp->next;
1353 
1354 			if (ret || (eflags & HIDE_ENOENT) == 0 || geterrno() != ENOENT) {
1355 
1356 				if (mcqp_prev)
1357 					mcqp_prev->next = mcqp;
1358 				if (mcq_1st == mcqp_save)
1359 					mcq_1st = mcqp;
1360 				if (mcq_last == mcqp_save)
1361 					mcq_last = mcqp;
1362 
1363 				free(mcqp_save->info.f_name);
1364 				free(mcqp_save->info.f_lname);
1365 				free(mcqp_save);
1366 
1367 				mcq_removed++;
1368 
1369 			} else {
1370 				mcqp_prev = mcqp_save;
1371 			}
1372 		}
1373 		if (!mcq_removed)
1374 			eflags = 0;	/* queue has not decreased - last attempt */
1375 
1376 	} while (mcq_1st);
1377 }
1378 
1379 LOCAL BOOL
_make_dcopy(info,do_symlink,retp,eflags)1380 _make_dcopy(info, do_symlink, retp, eflags)
1381 	FINFO	*info;
1382 	BOOL	do_symlink;
1383 	int	*retp;
1384 	int	eflags;
1385 {
1386 	char	nbuf[PATH_MAX+1];
1387 	char	*nbufp = nbuf;
1388 	char	*dir = info->f_lname;
1389 	DIR	*dirp;
1390 	char	*dp;
1391 	size_t	nents;
1392 	int	ret = TRUE;
1393 	FINFO	ninfo;
1394 
1395 	if (do_symlink && info->f_lname[0] != '/') {
1396 
1397 		char	*p = strrchr(info->f_name, '/');
1398 		size_t	len;
1399 
1400 		if (p) {
1401 			size_t	llen;
1402 
1403 			len = p - info->f_name + 1;
1404 			if ((len + (llen = strlen(info->f_lname))) > PATH_MAX) {
1405 				nbufp = __fjmalloc(stderr, len+llen,
1406 						"link dir name", JM_RETURN);
1407 			}
1408 			if (nbufp == NULL) {
1409 				if (!errhidden(E_NAMETOOLONG, info->f_lname)) {
1410 					if (!errwarnonly(E_NAMETOOLONG, info->f_lname))
1411 						xstats.s_toolong++;
1412 					errmsgno(EX_BAD,
1413 					"Name too long. Cannot copy from '%s'.\n",
1414 					info->f_lname);
1415 					(void) errabort(E_NAMETOOLONG,
1416 							info->f_lname, TRUE);
1417 				}
1418 				if (retp)
1419 					*retp = FALSE;
1420 				return (TRUE);
1421 			}
1422 			strncpy(nbufp, info->f_name, len);
1423 			strcpy(&nbufp[len], info->f_lname);
1424 			dir = nbufp;
1425 		}
1426 	}
1427 
1428 	dirp = lopendir(dir);
1429 	if (dirp == NULL)
1430 		return (FALSE);
1431 	if ((dp = dfetchdir(dirp, dir, &nents, NULL, NULL)) == NULL) {
1432 		closedir(dirp);
1433 		return (FALSE);
1434 	}
1435 	closedir(dirp);
1436 
1437 	if (!_getinfo(info->f_name, &ninfo)) {
1438 		_getinfo(dir, &ninfo);
1439 		ninfo.f_name = info->f_name;
1440 		make_dir(&ninfo);
1441 	}
1442 	if (nbufp != nbuf)
1443 		free(nbufp);
1444 
1445 	while (nents > 0) {
1446 		char	*name;
1447 		size_t	nlen;
1448 
1449 		name = &dp[1];
1450 		nlen = strlen(name);
1451 
1452 		ninfo.f_name = ___malloc(strlen(info->f_name) +
1453 					1 + nlen + 1, "make_copy()");
1454 
1455 		strcpy(ninfo.f_name, info->f_name);
1456 		if (ninfo.f_name[strlen(ninfo.f_name)-1] != '/')
1457 			strcat(ninfo.f_name, "/");
1458 		strcat(ninfo.f_name, name);
1459 
1460 		ninfo.f_lname = ___malloc(3 +
1461 					strlen(info->f_lname) +	1 +
1462 					nlen + 1, "make_copy()");
1463 
1464 		ninfo.f_lname[0] = '\0';
1465 		if (do_symlink)
1466 			strcpy(ninfo.f_lname, "../");
1467 		strcat(ninfo.f_lname, info->f_lname);
1468 		if (ninfo.f_lname[strlen(ninfo.f_lname)-1] != '/')
1469 			strcat(ninfo.f_lname, "/");
1470 		strcat(ninfo.f_lname, name);
1471 
1472 		if (!_make_copy(&ninfo, do_symlink, eflags))
1473 			ret = FALSE;
1474 
1475 		free(ninfo.f_lname);
1476 		free(ninfo.f_name);
1477 
1478 		nents--;
1479 		dp += nlen +2;
1480 	}
1481 	if (retp)
1482 		*retp = ret;
1483 	return (TRUE);
1484 }
1485 #endif	/* COPY_LINKS_DELAYED */
1486 
1487 LOCAL int
copy_file(from,to,do_symlink,eflags)1488 copy_file(from, to, do_symlink, eflags)
1489 	char	*from;
1490 	char	*to;
1491 	BOOL	do_symlink;
1492 	int	eflags;
1493 {
1494 	FINFO	finfo;
1495 	FILE	*fin;
1496 	FILE	*fout;
1497 	int	cnt = -1;
1498 	char	buf[8192];
1499 	char	nbuf[PATH_MAX+1];
1500 	char	*nbufp = nbuf;
1501 
1502 	/*
1503 	 * When tar archives hard links, both names (from/to) are relative to
1504 	 * the current directory. With symlinks this does not work. Symlinks
1505 	 * are always evaluated relative to the directory they reside in.
1506 	 * For this reason, we cannot simply open the from/to files if we
1507 	 * like to emulate a symbolic link. To emulate the behavior of a
1508 	 * symbolic link, we concat the the directory part of the 'to' name
1509 	 * (which is the path that becomes the sombolic link) to the complete
1510 	 * 'from' name (which is the path the symbolic linkc pints to) in case
1511 	 * the 'from' name is a relative path name.
1512 	 */
1513 	if (do_symlink && from[0] != '/') {
1514 		char	*p = strrchr(to, '/');
1515 		size_t	len;
1516 
1517 		if (p) {
1518 			int	llen;
1519 
1520 			len = p - to + 1;
1521 
1522 			if ((len + (llen = strlen(from))) > PATH_MAX) {
1523 				nbufp = __fjmalloc(stderr, len+llen,
1524 						"link name", JM_RETURN);
1525 			}
1526 			if (nbufp == NULL) {
1527 				if (!errhidden(E_NAMETOOLONG, from)) {
1528 					if (!errwarnonly(E_NAMETOOLONG, from))
1529 						xstats.s_toolong++;
1530 					errmsgno(EX_BAD,
1531 					"Name too long. Cannot copy from '%s'.\n",
1532 					from);
1533 					(void) errabort(E_NAMETOOLONG, from,
1534 									TRUE);
1535 				}
1536 				cnt = -2;
1537 				goto out;
1538 			}
1539 			strncpy(nbuf, to, len);
1540 			strcpy(&nbuf[len], from);
1541 			from = nbuf;
1542 		}
1543 	}
1544 	if (!_getinfo(from, &finfo)) {
1545 
1546 		if (!errhidden(E_STAT, from) &&
1547 		    ((eflags & HIDE_ENOENT) == 0 || geterrno() != ENOENT)) {
1548 			if (!errwarnonly(E_STAT, from))
1549 				xstats.s_staterrs++;
1550 			errmsg("Cannot stat '%s'.\n", from);
1551 			(void) errabort(E_STAT, from, TRUE);
1552 		}
1553 		cnt = -2;
1554 		goto out;
1555 	}
1556 	if (!is_file(&finfo)) {
1557 		errmsgno(EX_BAD, "Not a file. Cannot copy from '%s'.\n", from);
1558 		seterrno(EINVAL);
1559 		cnt = -2;
1560 		goto out;
1561 	}
1562 
1563 rretry:
1564 	if ((fin = lfilemopen(from, "rub", S_IREAD|S_IWRITE)) == 0) {
1565 		if (geterrno() == EINTR)
1566 			goto rretry;
1567 		errmsg("Cannot open '%s'.\n", from);
1568 	} else {
1569 wretry:
1570 		if ((fout = lfilemopen(to, "wtcub", S_IREAD|S_IWRITE)) == 0) {
1571 			if (geterrno() == EINTR)
1572 				goto wretry;
1573 #ifdef	__really__
1574 			errmsg("Cannot create '%s'.\n", to);
1575 #endif
1576 			cnt = -1;
1577 			goto out;
1578 		} else {
1579 			while ((cnt = ffileread(fin, buf, sizeof (buf))) > 0)
1580 				ffilewrite(fout, buf, cnt);
1581 			fclose(fout);
1582 		}
1583 		fclose(fin);
1584 	}
1585 out:
1586 	if (nbufp != nbuf)
1587 		free(nbufp);
1588 	return (cnt);
1589 }
1590 
1591 LOCAL BOOL
make_fifo(info)1592 make_fifo(info)
1593 	FINFO	*info;
1594 {
1595 	mode_t	mode;
1596 	int	err;
1597 	pathstore_t	path;
1598 	char	xname[PATH_MAX+1];
1599 	char	*name = info->f_name;
1600 	BOOL	ret = TRUE;
1601 
1602 	if (dometa)
1603 		return (TRUE);
1604 
1605 	path.ps_path = xname;
1606 
1607 #ifdef	HAVE_MKFIFO
1608 	xname[0] = '\0';
1609 	if (do_install && name_exists(name)) {
1610 		if (!file_tmpname(info, &path)) {
1611 			ret = FALSE;
1612 			goto out;
1613 		}
1614 		name = path.ps_path;
1615 	}
1616 	mode = osmode(info->f_mode);
1617 	mode &= mode_mask;
1618 	if (lmkfifo(name, mode) >= 0)
1619 		goto ok;
1620 	err = geterrno();
1621 	if (create_dirs(info->f_name)) {
1622 		if (lmkfifo(name, mode) >= 0)
1623 			goto ok;
1624 		err = geterrno();
1625 	}
1626 	if ((err == EACCES || is_eexist(err) || is_eloop(err)) &&
1627 			remove_file(name, FALSE)) {
1628 		if (lmkfifo(name, mode) >= 0)
1629 			goto ok;
1630 	}
1631 	if (!errhidden(E_OPEN, info->f_name)) {
1632 		if (!errwarnonly(E_OPEN, info->f_name))
1633 			xstats.s_openerrs++;
1634 		errmsg("Cannot make fifo '%s'.\n", info->f_name);
1635 		(void) errabort(E_OPEN, info->f_name, TRUE);
1636 	}
1637 	if (do_install)
1638 		remove_tmpname(path.ps_path);
1639 	ret = FALSE;
1640 	goto out;
1641 ok:
1642 	if (do_install)
1643 		ret = install_rename(info, path.ps_path);
1644 out:
1645 	if (path.ps_path != xname)
1646 		free_pspace(&path);
1647 	return (ret);
1648 #else
1649 #ifdef	HAVE_MKNOD
1650 	return (make_special(info));
1651 #endif
1652 	if (!errhidden(E_SPECIALFILE, info->f_name)) {
1653 		if (!errwarnonly(E_SPECIALFILE, info->f_name))
1654 			xstats.s_isspecial++;
1655 		errmsgno(EX_BAD,
1656 			"Not supported. Cannot make fifo '%s'.\n",
1657 							info->f_name);
1658 		(void) errabort(E_SPECIALFILE, info->f_name, TRUE);
1659 	}
1660 	return (FALSE);
1661 #endif
1662 }
1663 
1664 LOCAL BOOL
make_special(info)1665 make_special(info)
1666 	FINFO	*info;
1667 {
1668 	mode_t	mode;
1669 	dev_t	dev;
1670 	int	err;
1671 	pathstore_t	path;
1672 	char	xname[PATH_MAX+1];
1673 	char	*name = info->f_name;
1674 	BOOL	ret = TRUE;
1675 
1676 	if (dometa)
1677 		return (TRUE);
1678 
1679 	path.ps_path = xname;
1680 
1681 #ifdef	HAVE_MKNOD
1682 	xname[0] = '\0';
1683 	if (do_install && name_exists(name)) {
1684 		if (!file_tmpname(info, &path)) {
1685 			ret = FALSE;
1686 			goto out;
1687 		}
1688 		name = path.ps_path;
1689 	}
1690 	mode = osmode(info->f_mode);
1691 	mode &= mode_mask;
1692 	mode |= info->f_type;	/* Add file type bits */
1693 	dev = info->f_rdev;
1694 	if (lmknod(name, mode, dev) >= 0)
1695 		goto ok;
1696 	err = geterrno();
1697 	if (create_dirs(info->f_name)) {
1698 		if (lmknod(name, mode, dev) >= 0)
1699 			goto ok;
1700 		err = geterrno();
1701 	}
1702 	if ((err == EACCES || is_eexist(err) || is_eloop(err)) &&
1703 			remove_file(name, FALSE)) {
1704 		if (lmknod(name, mode, dev) >= 0)
1705 			goto ok;
1706 	}
1707 	if (!errhidden(E_OPEN, info->f_name)) {
1708 		if (!errwarnonly(E_OPEN, info->f_name))
1709 			xstats.s_openerrs++;
1710 		errmsg("Cannot make %s '%s'.\n",
1711 					is_fifo(info)?"fifo":"special",
1712 							info->f_name);
1713 		(void) errabort(E_OPEN, info->f_name, TRUE);
1714 	}
1715 	if (do_install)
1716 		remove_tmpname(path.ps_path);
1717 	ret = FALSE;
1718 	goto out;
1719 ok:
1720 	if (do_install)
1721 		ret = install_rename(info, path.ps_path);
1722 out:
1723 	if (path.ps_path != xname)
1724 		free_pspace(&path);
1725 	return (ret);
1726 #else
1727 	if (!errhidden(E_SPECIALFILE, info->f_name)) {
1728 		if (!errwarnonly(E_SPECIALFILE, info->f_name))
1729 			xstats.s_isspecial++;
1730 		errmsgno(EX_BAD, "Not supported. Cannot make %s '%s'.\n",
1731 					is_fifo(info)?"fifo":"special",
1732 							info->f_name);
1733 		(void) errabort(E_SPECIALFILE, info->f_name, TRUE);
1734 	}
1735 	return (FALSE);
1736 #endif
1737 }
1738 
1739 /*
1740  * Create a temporary path name for the extraction in -install mode.
1741  */
1742 LOCAL BOOL
file_tmpname(info,path)1743 file_tmpname(info, path)
1744 	FINFO	*info;
1745 	pathstore_t	*path;
1746 {
1747 	register char	*xp;
1748 	register char	*np;
1749 	register char	*dp;
1750 		size_t	nlen;
1751 
1752 	np = info->f_name;
1753 	nlen = info->f_namelen;
1754 	if (nlen == 0)				/* 0 in case name is in TCB */
1755 		nlen = NAMSIZ + 1 + PFXSIZ;	/* 256 chars fit into TCB   */
1756 	if (nlen >= (PATH_MAX-6)) {
1757 		path->ps_path = NULL;		/* initialize so we don't   */
1758 		path->ps_size = 0;		/* need to call init_pspace() */
1759 		path->ps_tail = 0;
1760 		if (set_pspace(PS_STDERR, path, nlen+6) < 0)
1761 			return (FALSE);
1762 	}
1763 	xp = path->ps_path;
1764 	dp = xp;
1765 	do {
1766 		if ((*xp++ = *np) == '/')
1767 			dp = xp;
1768 	} while (*np++);
1769 
1770 	strcpy(dp, "XXXXXX");
1771 	seterrno(0);
1772 	lmktemp(path->ps_path);
1773 	if (path->ps_path[0] == '\0') {
1774 		errmsg("Cannot make temporary name for '%s'.\n",
1775 				info->f_name);
1776 		return (FALSE);
1777 	}
1778 	return (TRUE);
1779 }
1780 
1781 LOCAL FILE *
file_open(info,name)1782 file_open(info, name)
1783 	FINFO	*info;
1784 	char	*name;
1785 {
1786 	FILE	*f;
1787 
1788 	while ((f = lfilemopen(name, "wctub",
1789 				osmode(info->f_mode) & mode_mask)) == NULL &&
1790 				geterrno() == EINTR)
1791 		;
1792 	return (f);
1793 }
1794 
1795 /*
1796  * Rename the temporary path to the official path name when in -install mode.
1797  */
1798 LOCAL BOOL
install_rename(info,xname)1799 install_rename(info, xname)
1800 	FINFO	*info;
1801 	char	*xname;
1802 {
1803 	int	err;
1804 	BOOL	oforce_remove = force_remove;
1805 
1806 	/*
1807 	 * If xname is empty, then we do not need to rename the file as
1808 	 * there was no temporary name.
1809 	 */
1810 	if (xname[0] == '\0')
1811 		return (TRUE);
1812 
1813 	if (lrename(xname, info->f_name) >= 0)
1814 		return (TRUE);
1815 	err = geterrno();
1816 	/*
1817 	 * EISDIR is the error code if we try to rename a non-directory to the
1818 	 * name of an existing directory. In this case we silently remove this
1819 	 * directory if it is empty.
1820 	 */
1821 	if (err == EISDIR)
1822 		force_remove = TRUE;
1823 	if ((err == EACCES || is_eexist(err) || err == EISDIR || is_eloop(err)) &&
1824 					remove_file(info->f_name, FALSE)) {
1825 		if (lrename(xname, info->f_name) >= 0) {
1826 			force_remove = oforce_remove;
1827 			return (TRUE);
1828 		}
1829 	}
1830 	force_remove = oforce_remove;
1831 	/*
1832 	 * Rename to the official name did not work, remove the temporary name
1833 	 */
1834 	remove_tmpname(xname);
1835 	return (FALSE);
1836 }
1837 
1838 LOCAL BOOL
name_exists(name)1839 name_exists(name)
1840 	char	*name;
1841 {
1842 	FINFO	finfo;
1843 
1844 	if (!_lgetinfo(name, &finfo))
1845 		return (FALSE);
1846 
1847 	return (TRUE);
1848 }
1849 
1850 /*
1851  * remove_tmpname() is used to remove the temporary file used with -install
1852  * in case that the extraction did fail. For this reason make the remove
1853  * silent and unconditionally.
1854  */
1855 LOCAL void
remove_tmpname(name)1856 remove_tmpname(name)
1857 	char	*name;
1858 {
1859 	BOOL	oforce_remove = force_remove;
1860 	BOOL	oremove_recursive = remove_recursive;
1861 
1862 	/*
1863 	 * Rename to the official name did not work, remove the temporary name
1864 	 * in case that the temporary file still exists.
1865 	 */
1866 	if (name[0] == '\0')
1867 		return;
1868 	if (!name_exists(name))
1869 		return;
1870 	/*
1871 	 * In order to avoid annoying messages, call remove_file()
1872 	 * only if the file exists.
1873 	 */
1874 	force_remove = TRUE;
1875 	remove_recursive = TRUE;
1876 	remove_file(name, FALSE);
1877 	remove_recursive = oremove_recursive;
1878 	force_remove = oforce_remove;
1879 }
1880 
1881 LOCAL BOOL
get_file(info)1882 get_file(info)
1883 		FINFO	*info;
1884 {
1885 		FILE	*f;
1886 		int	err;
1887 	pathstore_t	path;
1888 		char	xname[PATH_MAX+1];
1889 		char	*name = info->f_name;
1890 		BOOL	ret = TRUE;
1891 
1892 	if (dometa) {
1893 		void_file(info);
1894 		return (TRUE);
1895 	}
1896 
1897 	path.ps_path = xname;
1898 	xname[0] = '\0';
1899 
1900 	if (to_stdout) {
1901 		f = stdout;
1902 		goto ofile;
1903 	}
1904 	if (do_install && name_exists(name)) {
1905 		if (!file_tmpname(info, &path)) {
1906 			ret = FALSE;
1907 			goto out;
1908 		}
1909 		name = path.ps_path;
1910 	}
1911 	if ((f = file_open(info, name)) == (FILE *)NULL) {
1912 		err = geterrno();
1913 		if (err == EMISSDIR && create_dirs(info->f_name)) {
1914 			if ((f = file_open(info, name)) != (FILE *)NULL) {
1915 				goto ofile;
1916 			}
1917 			err = geterrno();
1918 		}
1919 		if ((err == EACCES || is_eexist(err) || err == EISDIR ||
1920 		    is_eloop(err)) &&
1921 		    remove_file(name, FALSE)) {
1922 			if ((f = file_open(info, name)) != (FILE *)NULL) {
1923 				goto ofile;
1924 			}
1925 		}
1926 
1927 		if (!errhidden(E_OPEN, info->f_name)) {
1928 			if (!errwarnonly(E_OPEN, info->f_name))
1929 				xstats.s_openerrs++;
1930 			errmsg("Cannot create '%s'.\n", info->f_name);
1931 			(void) errabort(E_OPEN, info->f_name, TRUE);
1932 		}
1933 		void_file(info);
1934 		ret = FALSE;
1935 		goto out;
1936 	}
1937 ofile:
1938 	if (!get_ofile(f, info)) {
1939 		if (!to_stdout && do_install)
1940 			remove_tmpname(path.ps_path);
1941 		ret = FALSE;
1942 		goto out;
1943 	}
1944 	if (!to_stdout && do_install)
1945 		ret = install_rename(info, path.ps_path);
1946 out:
1947 	if (path.ps_path != xname)
1948 		free_pspace(&path);
1949 	return (ret);
1950 }
1951 
1952 LOCAL BOOL
get_ofile(f,info)1953 get_ofile(f, info)
1954 		FILE	*f;
1955 		FINFO	*info;
1956 {
1957 		int	err;
1958 		int	ret;
1959 
1960 	file_raise(f, FALSE);
1961 
1962 #if	defined(F_GETFL) && defined(O_DSYNC)
1963 	/*
1964 	 * Try to write file data as soon as possible to avoid
1965 	 * longer wait when fsync() is called later.
1966 	 */
1967 	if (!no_fsync) {
1968 		int	fl;
1969 
1970 		fl = fcntl(fdown(f), F_GETFL, 0);
1971 		fl |= O_DSYNC;
1972 		fcntl(fdown(f), F_SETFL, fl);
1973 	}
1974 #endif
1975 
1976 	if (is_sparse(info)) {
1977 		ret = get_sparse(f, info);
1978 	} else if (force_hole) {
1979 		if (xmeta)
1980 			ret = get_as_hole(f, info);
1981 		else
1982 			ret = get_forced_hole(f, info);
1983 	} else {
1984 		ret = xt_file(info, (ssize_t(*)__PR((void *, char *, size_t)))ffilewrite,
1985 						f, 0, "writing");
1986 	}
1987 	if (ret < 0) {
1988 		if (!to_stdout)
1989 			snulltimes(info->f_name, info);
1990 		die(EX_BAD);
1991 	}
1992 	if (!to_stdout) {
1993 #ifdef	HAVE_FSYNC
1994 		int	cnt;
1995 #endif
1996 		if (ret == FALSE)
1997 			xstats.s_rwerrs--;	/* Compensate overshoot below */
1998 
1999 		if (fflush(f) != 0)
2000 			ret = FALSE;
2001 #ifdef	HAVE_FSYNC
2002 		err = 0;
2003 		cnt = 0;
2004 		do {
2005 			if (!no_fsync && fsync(fdown(f)) != 0)
2006 				err = geterrno();
2007 
2008 			if (err == EINVAL)
2009 				err = 0;
2010 		} while (err == EINTR && ++cnt < 10);
2011 		if (err != 0)
2012 			ret = FALSE;
2013 #endif
2014 		if (fclose(f) != 0)
2015 			ret = FALSE;
2016 		if (ret == FALSE) {
2017 			xstats.s_rwerrs++;
2018 			if (!to_stdout)
2019 				snulltimes(info->f_name, info);
2020 		}
2021 	}
2022 	return (ret);
2023 }
2024 
2025 /* ARGSUSED */
2026 LOCAL ssize_t
void_func(vp,p,amount)2027 void_func(vp, p, amount)
2028 	void	*vp;
2029 	char	*p;
2030 	size_t	amount;
2031 {
2032 	return (amount);
2033 }
2034 
2035 EXPORT BOOL
void_file(info)2036 void_file(info)
2037 		FINFO	*info;
2038 {
2039 	int	ret = TRUE;
2040 	Ullong	llsize = info->f_llsize;
2041 	off_t	size   = info->f_rsize;
2042 
2043 	/*
2044 	 * handle botch in gnu sparse file definitions
2045 	 */
2046 	if (props.pr_flags & PR_GNU_SPARSE_BUG)
2047 		if (gnu_skip_extended(info) < 0)
2048 			die(EX_BAD);
2049 
2050 	if (info->f_flags & F_DATA_SKIPPED)
2051 		return (ret);
2052 
2053 	/*
2054 	 * Try to do our best to skip even files with a size that
2055 	 * is more then off_t may handle on the local machine.
2056 	 */
2057 	do {
2058 		if (info->f_flags & F_BAD_SIZE) {
2059 			if (llsize > 1024*1024*1024)
2060 				info->f_rsize = 1024*1024*1024;
2061 			else
2062 				info->f_rsize = llsize;
2063 		}
2064 
2065 		ret = xt_file(info, void_func, 0, 0, "void");
2066 		if (ret < 0)
2067 			die(EX_BAD);
2068 
2069 		llsize -= info->f_rsize;
2070 
2071 	} while ((info->f_flags & F_BAD_SIZE) && llsize > 0);
2072 
2073 	info->f_rsize = size;
2074 	info->f_flags |= F_DATA_SKIPPED;
2075 
2076 	return (ret);
2077 }
2078 
2079 LOCAL BOOL
void_bad(info)2080 void_bad(info)
2081 		FINFO	*info;
2082 {
2083 	int	ret;
2084 
2085 	if (!nowarn)
2086 		errmsgno(EX_BAD,
2087 			"WARNING: bad metadata for '%s', skipping...\n",
2088 			info->f_name);
2089 	ret = void_file(info);
2090 	return (ret);
2091 }
2092 
2093 /*
2094  * Extract file using callback function "func"
2095  * Returns:
2096  *	TRUE	Extract OK
2097  *	FALSE	Extract not OK, may continue
2098  *	-1	An error occured, max not continue
2099  */
2100 EXPORT int
xt_file(info,func,arg,amt,text)2101 xt_file(info, func, arg, amt, text)
2102 		FINFO	*info;
2103 		ssize_t	(*func) __PR((void *, char *, size_t));
2104 		void	*arg;
2105 		long	amt;
2106 		char	*text;
2107 {
2108 	register long	amount; /* XXX ??? */
2109 	register off_t	size;
2110 	register long	tasize;
2111 		BOOL	ret = TRUE;
2112 
2113 	size = info->f_rsize;
2114 	if (amt == 0)
2115 		amt = bufsize;
2116 	while (size > 0) {
2117 
2118 		if ((props.pr_flags & PR_CPIO) == 0) {
2119 			amount = buf_rwait(TBLOCK);
2120 			if (amount < TBLOCK) {
2121 				goto waseof;
2122 			}
2123 			amount = (amount / TBLOCK) * TBLOCK;
2124 			amount = min(size, amount);
2125 			amount = min(amount, amt);
2126 			tasize = tarsize(amount);
2127 		} else {
2128 			amount = buf_rwait(1);	/* Request what is available */
2129 			if (amount <= 0) {
2130 				goto waseof;
2131 			}
2132 			amount = min(size, amount);
2133 			amount = min(amount, amt);
2134 			tasize = amount;
2135 		}
2136 
2137 		if ((*func)(arg, bigptr, amount) != amount) {
2138 			ret = FALSE;
2139 			if (!errhidden(E_WRITE, info->f_name)) {
2140 				if (!errwarnonly(E_WRITE, info->f_name))
2141 					xstats.s_rwerrs++;
2142 				errmsg("Error %s '%s'.\n", text, info->f_name);
2143 				(void) errabort(E_WRITE, info->f_name, TRUE);
2144 			}
2145 			/*
2146 			 * func -> void_func() to skip the rest of the file.
2147 			 */
2148 			func = void_func;
2149 		}
2150 
2151 		size -= amount;
2152 		buf_rwake(tasize);
2153 	}
2154 	info->f_flags |= F_DATA_SKIPPED;
2155 	/*
2156 	 * Honour CPIO padding
2157 	 */
2158 	if ((amount = props.pr_pad) != 0) {
2159 		size = info->f_rsize;
2160 		if (info->f_flags & F_LONGNAME)
2161 			size += props.pr_hdrsize;
2162 		amount = (amount + 1 - (size & amount)) & amount;
2163 		if (amount > 0) {
2164 			buf_rwait(amount);
2165 			buf_rwake(amount);
2166 		}
2167 	}
2168 	return (ret);
2169 waseof:
2170 	errmsgno(EX_BAD, "Tar file too small (amount: %ld bytes).\n", amount);
2171 	errmsgno(EX_BAD, "Unexpected EOF on input.\n");
2172 	return (-1);
2173 }
2174 
2175 EXPORT void
skip_slash(info)2176 skip_slash(info)
2177 	FINFO	*info;
2178 {
2179 	static	BOOL	warned = FALSE;
2180 
2181 	if (!warned && !nowarn) {
2182 		errmsgno(EX_BAD, "WARNING: skipping leading '/' on filenames.\n");
2183 		warned = TRUE;
2184 	}
2185 	/*
2186 	 * XXX
2187 	 * XXX ACHTUNG: ia_change kann es n�tig machen, den String umzukopieren
2188 	 * XXX denn sonst ist die L�nge des Speicherplatzes unbestimmt!
2189 	 *
2190 	 * XXX ACHTUNG: mir ist noch unklar, ob es richtig ist, auch in jedem
2191 	 * XXX Fall F�hrende slashes vom Linknamen zu entfernen.
2192 	 * XXX Bei Hard-Link ist das sicher richtig und ergibt sich auch
2193 	 * XXX automatisch, wenn man nur vor dem Aufruf von skip_slash()
2194 	 * XXX auf f_name[0] == '/' abfragt.
2195 	 */
2196 	while (info->f_name[0] == '/')
2197 		info->f_name++;
2198 
2199 	/*
2200 	 * Don't strip leading '/' from targets of symlinks.
2201 	 */
2202 	if (is_symlink(info))
2203 		return;
2204 
2205 	while (info->f_lname[0] == '/')
2206 		info->f_lname++;
2207 }
2208 
2209 #if PATH_DELIM == '\\' || defined(IS_CYGWIN)
2210 #define	NEED_BACKSLASH
2211 #endif
2212 
2213 LOCAL BOOL
has_dotdot(name)2214 has_dotdot(name)
2215 	char	*name;
2216 {
2217 	register char	*p = name;
2218 
2219 	while (*p) {
2220 		if ((p[0] == '.' && p[1] == '.') &&
2221 		    (p[2] == '/' ||
2222 #ifdef	NEED_BACKSLASH
2223 		    p[2] == '\\' ||
2224 #endif
2225 		    p[2] == '\0')) {
2226 			return (TRUE);
2227 		}
2228 		do {
2229 			if (*p++ == '\0')
2230 				return (FALSE);
2231 #ifdef	NEED_BACKSLASH
2232 		} while (*p != '/' && *p != '\\');
2233 #else
2234 		} while (*p != '/');
2235 #endif
2236 		p++;
2237 #ifdef	NEED_BACKSLASH
2238 		while (*p == '/' || *p == '\\')
2239 			p++;
2240 #else
2241 		while (*p == '/')	/* Skip multiple slashes */
2242 			p++;
2243 #endif
2244 	}
2245 	return (FALSE);
2246 }
2247 
2248 LOCAL BOOL
inside_tree(info)2249 inside_tree(info)
2250 	FINFO	*info;
2251 {
2252 	char	_rpath[PATH_MAX+1];
2253 	char	_npath[PATH_MAX+1];
2254 	char	*rpath = _rpath;
2255 	char	*npath = _npath;
2256 	char	*p;
2257 	size_t	len;
2258 	int	nlen;			/* Solaris resolvepath() returns int */
2259 	BOOL	ret = FALSE;
2260 extern	const	char	*wdir;
2261 
2262 	/*
2263 	 * If we are in the root directory, any unusual pathname is critical.
2264 	 */
2265 	if (wdir != NULL && wdir[0] == '/' && wdir[1] == '\0')
2266 		return (FALSE);
2267 
2268 	if (info->f_namelen > 0)
2269 		len = info->f_namelen;
2270 	else
2271 		len = strlen(info->f_name);
2272 
2273 	if (info->f_lnamelen > 0)
2274 		len += info->f_lnamelen;
2275 	else
2276 		len += strlen(info->f_lname);
2277 
2278 	if (++len > sizeof (_rpath)) {
2279 		rpath = __jmalloc(len, "name buffer", JM_RETURN);
2280 		if (rpath == NULL)
2281 			return (FALSE);
2282 	}
2283 	if (len > sizeof (_npath)) {
2284 		npath = __jmalloc(len, "name buffer", JM_RETURN);
2285 		if (npath == NULL)
2286 			goto out;
2287 	}
2288 
2289 	/*
2290 	 * Create combined path name.
2291 	 */
2292 	if (info->f_lname[0] != '/') {
2293 		strcpy(rpath, info->f_name);
2294 		p = strrchr(rpath, '/');
2295 		if (p == NULL)
2296 			rpath[0] = '\0';
2297 		else
2298 			*++p = '\0';
2299 	} else {
2300 		rpath[0] = '\0';
2301 	}
2302 	strcat(rpath, info->f_lname);
2303 
2304 	/*
2305 	 * Normalize combined path name.
2306 	 */
2307 	nlen = resolvenpath(rpath, npath, len);
2308 	if (nlen < 0)
2309 		goto out;
2310 	npath[nlen] = '\0';
2311 
2312 	/*
2313 	 * Check if it points outside our working directory.
2314 	 */
2315 	if (npath[0] != '/' && !has_dotdot(npath))
2316 		ret = TRUE;
2317 
2318 out:
2319 	if (rpath != _rpath)
2320 		free(rpath);
2321 	if (npath != _npath)
2322 		free(npath);
2323 
2324 	return (ret);
2325 }
2326