tlm_restore_writer.c revision 2654012f83cec5dc15b61dfe3e4a4915f186e7a6
1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6/*
7 * BSD 3 Clause License
8 *
9 * Copyright (c) 2007, The Storage Networking Industry Association.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 	- Redistributions of source code must retain the above copyright
15 *	  notice, this list of conditions and the following disclaimer.
16 *
17 * 	- Redistributions in binary form must reproduce the above copyright
18 *	  notice, this list of conditions and the following disclaimer in
19 *	  the documentation and/or other materials provided with the
20 *	  distribution.
21 *
22 *	- Neither the name of The Storage Networking Industry Association (SNIA)
23 *	  nor the names of its contributors may be used to endorse or promote
24 *	  products derived from this software without specific prior written
25 *	  permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39#include <stdlib.h>
40#include <ctype.h>
41#include <stdio.h>
42#include <limits.h>
43#include <string.h>
44#include <time.h>
45#include <sys/types.h>
46#include <sys/acl.h>
47#include <utime.h>
48#include <unistd.h>
49#include <pthread.h>
50#include <archives.h>
51#include <priv.h>
52#include <tlm.h>
53#include <libzfs.h>
54#include <ndmpd_prop.h>
55#include "tlm_proto.h"
56
57
58#define	PM_EXACT_OR_CHILD(m)	((m) == PM_EXACT || (m) == PM_CHILD)
59
60typedef boolean_t name_match_fp_t(char *s, char *t);
61
62static void set_acl(char *name,
63    tlm_acls_t *acls);
64static long restore_file(int *fp,
65    char *real_name,
66    long size,
67    longlong_t huge_size,
68    tlm_acls_t *,
69    boolean_t want_this_file,
70    tlm_cmd_t *,
71    tlm_job_stats_t *);
72static long restore_xattr_hdr(int *fp,
73    char *name,
74    char *fname,
75    long size,
76    tlm_acls_t *acls,
77    tlm_cmd_t *local_commands,
78    tlm_job_stats_t *job_stats);
79static int get_long_name(int lib,
80    int drv,
81    long recsize,
82    char *name,
83    long *buf_spot,
84    tlm_cmd_t *local_commands);
85static int get_humongus_file_header(int lib,
86    int	drv,
87    long recsize,
88    longlong_t *size,
89    char *name,
90    tlm_cmd_t *);
91static int create_directory(char *dir,
92    tlm_job_stats_t *);
93static int create_hard_link(char *name,
94    char *link,
95    tlm_acls_t *,
96    tlm_job_stats_t *);
97static int create_sym_link(char *dst,
98    char *target,
99    tlm_acls_t *,
100    tlm_job_stats_t *);
101static int create_fifo(char *name,
102    tlm_acls_t *);
103static long load_acl_info(int lib,
104    int	drv,
105    long size,
106    tlm_acls_t *,
107    long *acl_spot,
108    tlm_cmd_t *);
109static char *get_read_buffer(int want,
110    int	*error,
111    int	*actual_size,
112    tlm_cmd_t *);
113static boolean_t wildcard_enabled(void);
114static boolean_t is_file_wanted(char *name,
115    char **sels,
116    char **exls,
117    int	flags,
118    int	*mchtype,
119    int	*pos);
120static char *catnames(struct rs_name_maker *rnp,
121    char *buf,
122    int	pos,
123    char *path);
124
125static char *rs_new_name(struct rs_name_maker *rnp,
126    char *real_name,
127    int pos,
128    char *path);
129
130typedef struct stack_ent {
131	char *se_name;
132	tlm_acls_t se_acls;
133} stack_ent_t;
134
135
136/*
137 * dtree_push
138 */
139int
140dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls)
141{
142	int len;
143	stack_ent_t *sp;
144
145	sp = ndmp_malloc(sizeof (stack_ent_t));
146	if (!sp || !nmp || !acls) {
147		free(sp);
148		return (-1);
149	}
150
151	len = strlen(nmp) + 1;
152	sp->se_name = ndmp_malloc(len);
153	if (!sp->se_name) {
154		free(sp);
155		return (-1);
156	}
157
158	(void) strlcpy(sp->se_name, nmp, len);
159	(void) memcpy(&sp->se_acls, acls, sizeof (*acls));
160
161	return (cstack_push(stp, (void *)sp, sizeof (*sp)));
162}
163
164/*
165 * dtree_pop
166 */
167int
168dtree_pop(cstack_t *stp)
169{
170	int err;
171	stack_ent_t *sp;
172
173	err = cstack_pop(stp, (void **)&sp, (void *)NULL);
174	if (err)
175		return (-1);
176
177	set_acl(sp->se_name, &sp->se_acls);
178
179	free(sp->se_name);
180	free(sp);
181	return (err);
182}
183
184
185/*
186 * dtree_peek
187 */
188char *
189dtree_peek(cstack_t *stp)
190{
191	int err;
192	stack_ent_t *sp;
193
194	err = cstack_top(stp, (void **)&sp, (void *)NULL);
195	if (err)
196		return (NULL);
197
198	return (sp->se_name);
199}
200
201/*
202 * NBU and EBS may not send us the correct file list containing hardlinks
203 * during a DAR restore, e.g. they appear always send the first name
204 * associated with an inode, even if other link names were
205 * selected for the restore.  As a workaround, we use the file name entry
206 * in sels[] (ignore the name in the tar header) as restore target.
207 */
208static char *
209rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos,
210    char *longname)
211{
212	int x;
213
214	for (x = 0; sels[x] != NULL; x++) {
215		if (strcmp(sels[x], " ")) {
216			*pos = x;
217			(void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME);
218			NDMP_LOG(LOG_DEBUG,
219			    "to replace hardlink name [%s], pos [%d]",
220			    longname, *pos);
221
222			return (rs_new_name(rnp, name, *pos, longname));
223		}
224	}
225
226	return (NULL);
227}
228
229
230/*
231 * Main dir restore funciton for tar
232 */
233int
234tar_getdir(tlm_commands_t *commands,
235    tlm_cmd_t *local_commands,
236    tlm_job_stats_t *job_stats,
237    struct rs_name_maker *rnp,
238    int	lib,
239    int	drv,
240    char **sels, /* what to get off the tape */
241    char **exls, /* what to leave behind */
242    int	flags,
243    int	DAR, struct hardlink_q *hardlink_q)
244{
245	int	fp = 0;		/* file being restored ... */
246				/*  ...need to preserve across volume changes */
247	tlm_acls_t *acls;	/* file access info */
248	char	*longname;
249	boolean_t is_long_name = FALSE;
250	char	*longlink;
251	char	*hugename;
252	longlong_t huge_size = 0;	/* size of a HUGE file */
253	long	acl_spot;		/* any ACL info on the next volume */
254	long	file_size;		/* size of file to restore */
255	long	size_left = 0;		/* need this after volume change */
256	int	last_action = 0;	/* what we are doing at EOT */
257	boolean_t multi_volume = FALSE;	/* is this a multi-volume switch ? */
258	int	chk_rv;			/* scratch area */
259
260	int	mchtype, pos;
261					/*
262					 * if an exact match is found for
263					 * restore and its position in the
264					 * selections list
265					 */
266	int	nzerohdr;		/* the number of empty tar headers */
267	boolean_t break_flg;		/* exit the while loop */
268	int	rv;
269	long nm_end, lnk_end;
270	char	*name, *nmp;
271	cstack_t *stp;
272	char 	*bkpath;
273	char 	*parentlnk;
274	/*
275	 * The directory where temporary files may be created during a partial
276	 * non-DAR restore of hardlinks.  It is intended to be initialized by
277	 * an environment variable that can be set by user.
278	 *
279	 * It is not initialized for now.   We keep it here for future use.
280	 */
281	char *tmplink_dir = NULL;
282
283	/*
284	 * startup
285	 */
286
287	longname = ndmp_malloc(TLM_MAX_PATH_NAME);
288	longlink = ndmp_malloc(TLM_MAX_PATH_NAME);
289	hugename = ndmp_malloc(TLM_MAX_PATH_NAME);
290	parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME);
291	name = ndmp_malloc(TLM_MAX_PATH_NAME);
292	acls = ndmp_malloc(sizeof (tlm_acls_t));
293	stp = cstack_new();
294	if (longname == NULL || longlink == NULL || hugename == NULL ||
295	    name == NULL || acls == NULL || stp == NULL || parentlnk == NULL) {
296		cstack_delete(stp);
297		free(longname);
298		free(longlink);
299		free(hugename);
300		free(parentlnk);
301		free(name);
302		free(acls);
303		return (-TLM_NO_SCRATCH_SPACE);
304	}
305
306	acl_spot = 0;
307	*hugename = '\0';
308	*parentlnk = '\0';
309	nm_end = 0;
310	*longname = '\0';
311	lnk_end = 0;
312	*longlink = '\0';
313	(void) memset(acls, 0, sizeof (tlm_acls_t));
314	if (IS_SET(flags, RSFLG_OVR_ALWAYS)) {
315		acls->acl_overwrite = TRUE;
316		NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS");
317	} else if (IS_SET(flags, RSFLG_OVR_UPDATE)) {
318		acls->acl_update = TRUE;
319		NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE");
320	}
321
322	/*
323	 * work
324	 */
325	rv = 0;
326	nzerohdr = 0;
327	break_flg = FALSE;
328	while (commands->tcs_writer != TLM_ABORT &&
329	    local_commands->tc_writer != TLM_STOP) {
330		tlm_tar_hdr_t fake_tar_hdr;
331		char	*file_name;
332		char	*link_name;
333		int	erc;
334		int	actual_size;
335		boolean_t want_this_file;
336		int	want = sizeof (tlm_tar_hdr_t);
337		tlm_tar_hdr_t *tar_hdr;
338
339		/* The inode of an LF_LINK type. */
340		unsigned long hardlink_inode = 0;
341
342		/*
343		 * Indicate whether a file with the same inode has been
344		 * restored.
345		 */
346		int hardlink_done = 0;
347
348		/* The path of the restored hardlink file */
349		char *hardlink_target = NULL;
350		int is_hardlink = 0;
351
352		/*
353		 * Whether a temporary file should be created for restoring
354		 * hardlink.
355		 */
356		int hardlink_tmp_file = 0;
357		char *hardlink_tmp_name = ".tmphlrsnondar";
358
359		/* used to make up hardlink_tmp_name */
360		static int hardlink_tmp_idx = 0;
361
362		if (break_flg) {
363			NDMP_LOG(LOG_DEBUG,
364			    "Exiting writer thread drive %d", drv);
365			break;
366		}
367
368		if (multi_volume) {
369			NDMP_LOG(LOG_DEBUG, "multi_volume %c %d",
370			    last_action, size_left);
371
372			/*
373			 * the previous volume is out of data
374			 * and is back in the rack, a new tape
375			 * is loaded and ready to read.
376			 *
377			 * We need to pick up where we left off.
378			 */
379			(void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr));
380			file_size = size_left;
381			tar_hdr = &fake_tar_hdr;
382			tar_hdr->th_linkflag = last_action;
383
384			multi_volume = FALSE;
385			last_action = 0;
386		} else {
387			tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want,
388			    &erc, &actual_size, local_commands);
389			/*
390			 * we can ignore read errors here because
391			 *   1) they are logged by Restore Reader
392			 *   2) we are not doing anything important here
393			 *	just looking for the next work record.
394			 */
395			if (actual_size < want) {
396				/*
397				 * EOF hits here
398				 *
399				 * wait for another buffer to come along
400				 * or until the Reader thread tells us
401				 * that no more tapes will be loaded ...
402				 * time to stop.
403				 */
404				continue;
405			}
406
407			/*
408			 * check for "we are lost"
409			 */
410			chk_rv = tlm_vfy_tar_checksum(tar_hdr);
411			if (chk_rv == 0) {
412				/* one of the end of tar file marks */
413				if (++nzerohdr >= 2) {
414					NDMP_LOG(LOG_DEBUG,
415					    "nzerohdr %d, breaking",
416					    nzerohdr);
417					/* end of tar file */
418					break;
419				}
420				NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing",
421				    nzerohdr);
422				continue;
423			} else if (chk_rv < 0) {
424				nzerohdr = 0;
425				/* skip this record */
426				continue;
427			}
428			nzerohdr = 0;
429
430			/*
431			 * When files are spanned to the next tape, the
432			 * information of the acls must not be over-written
433			 * by the information of the LF_MULTIVOL and LF_VOLHDR
434			 * header, whose information is irrelevant to the file.
435			 * The information of the original header must be
436			 * kept in the 'acl'.
437			 */
438			if (tar_hdr->th_linkflag != LF_MULTIVOL &&
439			    tar_hdr->th_linkflag != LF_VOLHDR) {
440				acls->acl_attr.st_mode =
441				    oct_atoi(tar_hdr->th_mode);
442				acls->acl_attr.st_size =
443				    oct_atoi(tar_hdr->th_size);
444				acls->acl_attr.st_uid =
445				    oct_atoi(tar_hdr->th_uid);
446				acls->acl_attr.st_gid =
447				    oct_atoi(tar_hdr->th_gid);
448				acls->acl_attr.st_mtime =
449				    oct_atoi(tar_hdr->th_mtime);
450				file_size = oct_atoi(tar_hdr->th_size);
451				acl_spot = 0;
452				last_action = tar_hdr->th_linkflag;
453			}
454		}
455
456		NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d",
457		    tar_hdr->th_name, tar_hdr->th_linkflag,
458		    acls->acl_attr.st_size, acls->acl_attr.st_mode,
459		    acls->acl_attr.st_uid, acls->acl_attr.st_gid,
460		    acls->acl_attr.st_mtime);
461
462		switch (tar_hdr->th_linkflag) {
463		case LF_MULTIVOL:
464			multi_volume = TRUE;
465			break;
466		case LF_LINK:
467			is_hardlink = 1;
468			hardlink_inode =
469			    oct_atoi(tar_hdr->th_shared.th_hlink_ino);
470
471			/*
472			 * Check if we have restored a link with the same inode
473			 * If the inode is 0, we have to restore it as a
474			 * regular file.
475			 */
476			if (hardlink_inode) {
477				hardlink_done = !hardlink_q_get(hardlink_q,
478				    hardlink_inode, 0, &hardlink_target);
479			}
480
481			if (hardlink_done) {
482				NDMP_LOG(LOG_DEBUG,
483				    "found hardlink, inode = %u, target = [%s]",
484				    hardlink_inode,
485				    hardlink_target? hardlink_target : "--");
486
487				/* create a hardlink to hardlink_target */
488				file_name = (*longname == 0) ?
489				    tar_hdr->th_name : longname;
490				if (!is_file_wanted(file_name, sels, exls,
491				    flags, &mchtype, &pos)) {
492					nmp = NULL;
493					/*
494					 * This means that DMA did not send us
495					 * the correct fh_info for the file
496					 * in restore list.  We use the file
497					 * name entry in sels[] (ignore the
498					 * name in the tar header) as restore
499					 * target.
500					 */
501					if (DAR) {
502						nmp = rs_darhl_new_name(rnp,
503						    name, sels, &pos,
504						    file_name);
505					}
506				} else {
507					nmp = rs_new_name(rnp, name, pos,
508					    file_name);
509					if (!nmp) {
510						NDMP_LOG(LOG_DEBUG,
511						    "can't make name for %s",
512						    longname);
513					}
514				}
515
516				if (nmp) {
517					if (hardlink_target) {
518						erc = create_hard_link(
519						    hardlink_target, nmp,
520						    acls, job_stats);
521						if (erc == 0) {
522							(void)
523							    tlm_entry_restored(
524							    job_stats,
525							    file_name, pos);
526							NDMP_LOG(LOG_DEBUG,
527							    "restored %s -> %s",
528							    nmp,
529							    hardlink_target);
530						}
531					} else {
532						NDMP_LOG(LOG_DEBUG,
533						    "no target for hardlink %s",
534						    nmp);
535					}
536
537					name[0] = 0;
538					is_long_name = FALSE;
539				}
540
541				nm_end = 0;
542				longname[0] = 0;
543				lnk_end = 0;
544				longlink[0] = 0;
545
546				break;
547			}
548			/* otherwise fall through, restore like a normal file */
549			/*FALLTHROUGH*/
550		case LF_OLDNORMAL:
551			/*
552			 * check for TAR's end-of-tape method
553			 * of zero filled records.
554			 */
555			if (tar_hdr->th_name[0] == 0) {
556				break;
557			}
558			/*
559			 * otherwise fall through,
560			 * this is an old style normal file header
561			 */
562			/*FALLTHROUGH*/
563		case LF_NORMAL:
564		case LF_CONTIG:
565			job_stats->js_files_so_far++;
566			if (*hugename != 0) {
567				(void) strlcpy(longname, hugename,
568				    TLM_MAX_PATH_NAME);
569			} else if (*longname == 0) {
570				if (tar_hdr->th_name[0] != '/') {
571					/*
572					 * check for old tar format, it
573					 * does not have a leading "/"
574					 */
575					longname[0] = '/';
576					longname[1] = 0;
577					(void) strlcat(longname,
578					    tar_hdr->th_name,
579					    TLM_MAX_PATH_NAME);
580				} else {
581					(void) strlcpy(longname,
582					    tar_hdr->th_name,
583					    TLM_MAX_PATH_NAME);
584				}
585			}
586
587			want_this_file = is_file_wanted(longname, sels, exls,
588			    flags, &mchtype, &pos);
589			if (!want_this_file) {
590				nmp = NULL;
591				/*
592				 * This means that DMA did not send us valid
593				 * fh_info for the file in restore list.  We
594				 * use the file name entry in sels[] (ignore
595				 * the name in the tar header) as restore
596				 * target.
597				 */
598				if (DAR && (tar_hdr->th_linkflag == LF_LINK)) {
599					nmp = rs_darhl_new_name(rnp, name,
600					    sels, &pos, longname);
601
602					if (nmp) {
603						want_this_file = TRUE;
604						mchtype = PM_EXACT;
605					} else {
606						break_flg = TRUE;
607						break;
608					}
609				}
610			} else {
611				nmp = rs_new_name(rnp, name, pos, longname);
612				if (!nmp)
613					want_this_file = FALSE;
614			}
615
616			if (nmp)
617				(void) strlcpy(parentlnk, nmp, strlen(nmp) + 1);
618
619			/*
620			 * For a hardlink, even if it's not asked to be
621			 * restored, we restore it to a temporary location,
622			 * in case other links to the same file need to be
623			 * restored later.
624			 *
625			 * The temp files are created in tmplink_dir, with
626			 * names like ".tmphlrsnondar*".  They are cleaned up
627			 * at the completion of a restore.  However, if a
628			 * restore were interrupted, e.g. by a system reboot,
629			 * they would have to be cleaned up manually in order
630			 * for the disk space to be freed.
631			 *
632			 * If tmplink_dir is NULL, no temperorary files are
633			 * created during a restore.  This may result in some
634			 * hardlinks not being restored during a partial
635			 * restore.
636			 */
637			if (is_hardlink && !DAR && !want_this_file && !nmp) {
638				if (tmplink_dir) {
639					(void) snprintf(name, TLM_MAX_PATH_NAME,
640					    "%s/%s_%d", tmplink_dir,
641					    hardlink_tmp_name,
642					    hardlink_tmp_idx);
643					nmp = name;
644
645					hardlink_tmp_idx++;
646					hardlink_tmp_file = 1;
647					want_this_file = TRUE;
648					NDMP_LOG(LOG_DEBUG,
649					    "To restore temp hardlink file %s.",
650					    nmp);
651				} else {
652					NDMP_LOG(LOG_DEBUG,
653					    "No tmplink_dir specified.");
654				}
655			}
656
657			size_left = restore_file(&fp, nmp, file_size,
658			    huge_size, acls, want_this_file, local_commands,
659			    job_stats);
660
661			/*
662			 * In the case of non-DAR, we have to record the first
663			 * link for an inode that has multiple links. That's
664			 * the only link with data records actually backed up.
665			 * In this way, when we run into the other links, they
666			 * will be treated as links, and we won't go to look
667			 * for the data records to restore.  This is not a
668			 * problem for DAR, where DMA tells the tape where
669			 * to locate the data records.
670			 */
671			if (is_hardlink && !DAR) {
672				if (hardlink_q_add(hardlink_q, hardlink_inode,
673				    0, nmp, hardlink_tmp_file))
674					NDMP_LOG(LOG_DEBUG,
675					    "failed to add (%u, %s) to HL q",
676					    hardlink_inode, nmp);
677			}
678
679			/* remove / reverse the temporary stuff */
680			if (hardlink_tmp_file) {
681				nmp = NULL;
682				want_this_file = FALSE;
683				hardlink_tmp_file = 0;
684			}
685
686			/*
687			 * Check if it is time to set the attribute
688			 * of the restored directory
689			 */
690			while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) {
691				if (strstr(nmp, bkpath))
692					break;
693
694				(void) dtree_pop(stp);
695			}
696
697			NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname,
698			    size_left, huge_size);
699
700			if (size_left == -TLM_STOP) {
701				break_flg = TRUE;
702				rv = -1;
703				commands->tcs_reader = TLM_ABORT;
704				NDMP_LOG(LOG_DEBUG, "restoring [%s] failed",
705				    longname);
706				break;
707			}
708
709			if (want_this_file) {
710				job_stats->js_bytes_total += file_size;
711				job_stats->js_files_total++;
712			}
713
714			huge_size -= file_size;
715			if (huge_size < 0) {
716				huge_size = 0;
717			}
718			if (size_left == 0 && huge_size == 0) {
719				if (PM_EXACT_OR_CHILD(mchtype)) {
720					(void) tlm_entry_restored(job_stats,
721					    longname, pos);
722
723					/*
724					 * Add an entry to hardlink_q to record
725					 * this hardlink.
726					 */
727					if (is_hardlink) {
728						NDMP_LOG(LOG_DEBUG,
729						    "Restored hardlink file %s",
730						    nmp);
731
732						if (DAR) {
733							(void) hardlink_q_add(
734							    hardlink_q,
735							    hardlink_inode, 0,
736							    nmp, 0);
737						}
738					}
739				}
740
741				nm_end = 0;
742				longname[0] = 0;
743				lnk_end = 0;
744				longlink[0] = 0;
745				hugename[0] = 0;
746				name[0] = 0;
747				is_long_name = FALSE;
748			}
749			break;
750		case LF_XATTR:
751			file_name = (*longname == 0) ? tar_hdr->th_name :
752			    longname;
753
754			size_left = restore_xattr_hdr(&fp, parentlnk,
755			    file_name, file_size, acls, local_commands,
756			    job_stats);
757
758			break;
759		case LF_SYMLINK:
760			file_name = (*longname == 0) ? tar_hdr->th_name :
761			    longname;
762			link_name = (*longlink == 0) ?
763			    tar_hdr->th_linkname : longlink;
764			NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name);
765			NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name);
766			if (is_file_wanted(file_name, sels, exls, flags,
767			    &mchtype, &pos)) {
768				nmp = rs_new_name(rnp, name, pos, file_name);
769				if (nmp) {
770					erc = create_sym_link(nmp, link_name,
771					    acls, job_stats);
772					if (erc == 0 &&
773					    PM_EXACT_OR_CHILD(mchtype))
774						(void) tlm_entry_restored(
775						    job_stats, file_name, pos);
776					name[0] = 0;
777				}
778			}
779			nm_end = 0;
780			longname[0] = 0;
781			lnk_end = 0;
782			longlink[0] = 0;
783			break;
784		case LF_DIR:
785			file_name = *longname == 0 ? tar_hdr->th_name :
786			    longname;
787			if (is_file_wanted(file_name, sels, exls, flags,
788			    &mchtype, &pos)) {
789				nmp = rs_new_name(rnp, name, pos, file_name);
790				if (nmp && mchtype != PM_PARENT) {
791					(void) strlcpy(parentlnk, nmp,
792					    strlen(nmp));
793					erc = create_directory(nmp, job_stats);
794					if (erc == 0 &&
795					    PM_EXACT_OR_CHILD(mchtype))
796						(void) tlm_entry_restored(
797						    job_stats, file_name, pos);
798					/*
799					 * Check if it is time to set
800					 * the attribute of the restored
801					 * directory
802					 */
803					while ((bkpath = dtree_peek(stp))
804					    != NULL) {
805						if (strstr(nmp, bkpath))
806							break;
807						(void) dtree_pop(stp);
808					}
809
810					(void) dtree_push(stp, nmp, acls);
811					name[0] = 0;
812				}
813			}
814			nm_end = 0;
815			longname[0] = 0;
816			lnk_end = 0;
817			longlink[0] = 0;
818			break;
819		case LF_FIFO:
820			file_name = *longname == 0 ? tar_hdr->th_name :
821			    longname;
822			if (is_file_wanted(file_name, sels, exls, flags,
823			    &mchtype, &pos)) {
824				nmp = rs_new_name(rnp, name, pos, file_name);
825				if (nmp) {
826					erc = create_fifo(nmp, acls);
827					if (erc == 0 &&
828					    PM_EXACT_OR_CHILD(mchtype))
829						(void) tlm_entry_restored(
830						    job_stats, file_name, pos);
831					name[0] = 0;
832				}
833			}
834			nm_end = 0;
835			longname[0] = 0;
836			lnk_end = 0;
837			longlink[0] = 0;
838			break;
839		case LF_LONGLINK:
840			file_size = min(file_size, TLM_MAX_PATH_NAME - lnk_end);
841			file_size = max(0, file_size);
842			size_left = get_long_name(lib, drv, file_size, longlink,
843			    &lnk_end, local_commands);
844
845			if (size_left != 0)
846				NDMP_LOG(LOG_DEBUG,
847				    "fsize %d sleft %d lnkend %d",
848				    file_size, size_left, lnk_end);
849			break;
850		case LF_LONGNAME:
851			file_size = min(file_size, TLM_MAX_PATH_NAME - nm_end);
852			file_size = max(0, file_size);
853			size_left = get_long_name(lib, drv, file_size, longname,
854			    &nm_end, local_commands);
855
856			if (size_left != 0)
857				NDMP_LOG(LOG_DEBUG,
858				    "fsize %d sleft %d nmend %d",
859				    file_size, size_left, nm_end);
860			is_long_name = TRUE;
861			break;
862		case LF_ACL:
863			size_left = load_acl_info(lib, drv, file_size, acls,
864			    &acl_spot, local_commands);
865			break;
866		case LF_VOLHDR:
867			break;
868		case LF_HUMONGUS:
869			(void) memset(hugename, 0, TLM_MAX_PATH_NAME);
870			(void) get_humongus_file_header(lib, drv, file_size,
871			    &huge_size, hugename, local_commands);
872			break;
873		default:
874			break;
875
876		}
877
878		/*
879		 * If the restore is running using DAR we should check for
880		 * long file names and HUGE file sizes.
881		 */
882		if (DAR && tar_hdr->th_linkflag != LF_ACL &&
883		    !huge_size && !is_long_name)
884			break;
885	}
886
887	/*
888	 * tear down
889	 */
890	if (fp != 0) {
891		(void) close(fp);
892	}
893	while (dtree_pop(stp) != -1)
894		;
895	cstack_delete(stp);
896	free(acls);
897	free(longname);
898	free(parentlnk);
899	free(longlink);
900	free(hugename);
901	free(name);
902	return (rv);
903}
904
905/*
906 * Main file restore function for tar (should run as a thread)
907 */
908int
909tar_getfile(tlm_backup_restore_arg_t *argp)
910{
911	tlm_job_stats_t	*job_stats;
912	char	**sels;		/* list of files desired */
913	char	**exls;		/* list of files not wanted */
914	char	*dir;		/* where to restore the files */
915	char	job[TLM_MAX_BACKUP_JOB_NAME+1];
916				/* the restore job name */
917	int	erc;		/* error return codes */
918	int	flags;
919	struct	rs_name_maker rn;
920	tlm_commands_t *commands;
921	tlm_cmd_t *local_commands;
922	char *list = NULL;
923
924	commands = argp->ba_commands;
925	local_commands = argp->ba_cmd;
926
927	flags = 0;
928
929	dir = ndmp_malloc(TLM_MAX_PATH_NAME);
930	if (dir == NULL) {
931		local_commands->tc_reader = TLM_STOP;
932		(void) pthread_barrier_wait(&argp->ba_barrier);
933		return (-1);
934	}
935
936	(void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1);
937	(void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME);
938
939	flags |= RSFLG_OVR_ALWAYS;
940	flags |= RSFLG_IGNORE_CASE;
941
942	/*
943	 * do not test for "dir" having no string, since that
944	 * is a legal condition.  Restore to origional location
945	 * will not have a restore directory.
946	 */
947	if (*job == '\0') {
948		NDMP_LOG(LOG_DEBUG, "No job defined");
949		local_commands->tc_reader = TLM_STOP;
950		free(dir);
951		(void) pthread_barrier_wait(&argp->ba_barrier);
952		return (-1);
953	}
954
955	sels = argp->ba_sels;
956	if (sels == NULL) {
957		local_commands->tc_reader = TLM_STOP;
958		free(dir);
959		(void) pthread_barrier_wait(&argp->ba_barrier);
960		return (-1);
961	}
962	exls = &list;
963
964	tlm_log_list("selections", sels);
965	tlm_log_list("exclusions", exls);
966
967	if (wildcard_enabled())
968		flags |= RSFLG_MATCH_WCARD;
969
970	local_commands->tc_ref++;
971	commands->tcs_writer_count++;
972
973	/*
974	 * let the launcher continue
975	 */
976	(void) pthread_barrier_wait(&argp->ba_barrier);
977
978	job_stats = tlm_ref_job_stats(job);
979
980	rn.rn_fp = catnames;
981	rn.rn_nlp = dir;
982
983	/*
984	 * work
985	 */
986	NDMP_LOG(LOG_DEBUG, "start restore job %s", job);
987	erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1,
988	    sels, exls, flags, 0, NULL);
989
990	/*
991	 * teardown
992	 */
993	NDMP_LOG(LOG_DEBUG, "end restore job %s", job);
994	tlm_un_ref_job_stats(job);
995	tlm_release_list(sels);
996	tlm_release_list(exls);
997
998	commands->tcs_writer_count--;
999	local_commands->tc_reader = TLM_STOP;
1000	tlm_release_reader_writer_ipc(local_commands);
1001	free(dir);
1002	return (erc);
1003}
1004
1005/*
1006 * Creates the directories all the way down to the
1007 * end if they dont exist
1008 */
1009int
1010make_dirs(char *dir)
1011{
1012	char c;
1013	char *cp, *end;
1014	struct stat64 st;
1015
1016	cp = dir;
1017	cp += strspn(cp, "/");
1018	end = dir + strlen(dir);
1019	do {
1020		if (*cp == '\0' || *cp == '/') {
1021			c = *cp;
1022			*cp = '\0';
1023			if (lstat64(dir, &st) < 0)
1024				if (mkdir(dir, 0777) < 0) {
1025					NDMP_LOG(LOG_DEBUG, "Error %d"
1026					    " creating directory %s",
1027					    errno, dir);
1028					*cp = c;
1029					return (-1);
1030				}
1031
1032			*cp = c;
1033		}
1034	} while (++cp <= end);
1035
1036	return (0);
1037}
1038
1039/*
1040 * Creates the directories leading to the given path
1041 */
1042int
1043mkbasedir(char *path)
1044{
1045	int rv;
1046	char *cp;
1047	struct stat64 st;
1048
1049	if (!path || !*path) {
1050		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1051		return (-1);
1052	}
1053
1054	cp = strrchr(path, '/');
1055	if (cp)
1056		*cp = '\0';
1057	rv = lstat64(path, &st);
1058	if (rv < 0)	/* need new directories */
1059		rv = make_dirs(path);
1060	if (cp)
1061		*cp = '/';
1062
1063	return (rv);
1064}
1065
1066
1067/*
1068 * read the file off the tape back onto disk
1069 */
1070static long
1071restore_file(int *fp,
1072    char *real_name,
1073    long size,
1074    longlong_t huge_size,
1075    tlm_acls_t *acls,
1076    boolean_t want_this_file,
1077    tlm_cmd_t *local_commands,
1078    tlm_job_stats_t *job_stats)
1079{
1080	struct stat64	attr;
1081
1082	if (!real_name) {
1083		if (want_this_file) {
1084			NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1085			want_this_file = FALSE;
1086		}
1087	} else
1088		NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name);
1089
1090	/*
1091	 * OK, some FM is creeping in here ...
1092	 * int *fp is used to keep the
1093	 * backup file channel open through
1094	 * the interruption of EOT and
1095	 * processing the headers of the
1096	 * next tape.  So, if *fp is zero
1097	 * then no file is open yet and all
1098	 * is normal.  If *fp has a number
1099	 * then we are returning after an
1100	 * EOT break.
1101	 *
1102	 * *fp is now also open for HUGE files
1103	 * that are put back in sections.
1104	 */
1105
1106	if (*fp == 0 && want_this_file) {
1107		int	erc_stat;
1108
1109		if (mkbasedir(real_name) < 0)
1110			job_stats->js_errors++;
1111
1112		erc_stat = stat64(real_name, (struct stat64 *)&attr);
1113		if (erc_stat < 0) {
1114			/*EMPTY*/
1115			/* new file */
1116		} else if (acls->acl_overwrite) {
1117			/*EMPTY*/
1118			/* take this file no matter what */
1119		} else if (acls->acl_update) {
1120			if (attr.st_mtime < acls->acl_attr.st_mtime) {
1121				/*EMPTY*/
1122				/* tape is newer */
1123			} else {
1124				/* disk file is newer */
1125				want_this_file = FALSE;
1126			}
1127		} else {
1128			/*
1129			 * no overwrite, no update,
1130			 * do not ever replace old files.
1131			 */
1132			want_this_file = TRUE;
1133		}
1134		if (want_this_file) {
1135
1136			*fp = open(real_name, O_CREAT | O_WRONLY,
1137			    S_IRUSR | S_IWUSR);
1138			if (*fp == -1) {
1139				NDMP_LOG(LOG_ERR,
1140				    "Could not open %s for restore.",
1141				    real_name);
1142				NDMP_LOG(LOG_DEBUG,
1143				    "fp=%d err=%d ", *fp, errno);
1144				job_stats->js_errors++;
1145				want_this_file = FALSE;
1146				/*
1147				 * we cannot return here,
1148				 * the file is still on
1149				 * the tape and must be
1150				 * skipped over.
1151				 */
1152			}
1153		}
1154		(void) strlcpy(local_commands->tc_file_name, real_name,
1155		    TLM_MAX_PATH_NAME);
1156	}
1157
1158	/*
1159	 * this is the size left in the next segment
1160	 */
1161	huge_size -= size;
1162
1163	/*
1164	 * work
1165	 */
1166	while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1167		int	actual_size;
1168		int	error;
1169		char	*rec;
1170		int	write_size;
1171
1172		/*
1173		 * Use bytes_in_file field to tell reader the amount
1174		 * of data still need to be read for this file.
1175		 */
1176		job_stats->js_bytes_in_file = size;
1177
1178		error = 0;
1179		rec = get_read_buffer(size, &error, &actual_size,
1180		    local_commands);
1181		if (actual_size <= 0) {
1182			NDMP_LOG(LOG_DEBUG,
1183			    "RESTORE WRITER> error %d, actual_size %d",
1184			    error, actual_size);
1185
1186			/* no more data for this file for now */
1187			job_stats->js_bytes_in_file = 0;
1188
1189			return (size);
1190		} else if (error) {
1191			NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1192			    error, local_commands->tc_file_name);
1193			break;
1194		} else {
1195			write_size = min(size, actual_size);
1196			if (want_this_file) {
1197				write_size = write(*fp, rec, write_size);
1198			}
1199			NS_ADD(wdisk, write_size);
1200			NS_INC(wfile);
1201			size -= write_size;
1202		}
1203	}
1204
1205	/* no more data for this file for now */
1206	job_stats->js_bytes_in_file = 0;
1207
1208	/*
1209	 * teardown
1210	 */
1211	if (*fp != 0 && huge_size <= 0) {
1212		(void) close(*fp);
1213		*fp = 0;
1214		set_acl(real_name, acls);
1215	}
1216	return (0);
1217}
1218
1219/*
1220 * Set the extended attributes file attribute
1221 */
1222static void
1223set_xattr(int fd, struct stat64 st)
1224{
1225	struct timeval times[2];
1226
1227	times[0].tv_sec = st.st_atime;
1228	times[1].tv_sec = st.st_mtime;
1229
1230	(void) fchmod(fd, st.st_mode);
1231	(void) fchown(fd, st.st_uid, st.st_gid);
1232	(void) futimesat(fd, ".", times);
1233}
1234
1235/*
1236 * read the extended attribute header and write
1237 * it to the file
1238 */
1239static long
1240restore_xattr_hdr(int *fp,
1241    char *name,
1242    char *fname,
1243    long size,
1244    tlm_acls_t *acls,
1245    tlm_cmd_t *local_commands,
1246    tlm_job_stats_t *job_stats)
1247{
1248	tlm_tar_hdr_t *tar_hdr;
1249	struct xattr_hdr *xhdr;
1250	struct xattr_buf *xbuf;
1251	int namelen;
1252	char *xattrname;
1253	int actual_size;
1254	int error;
1255
1256	if (!fname) {
1257		NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1258	} else {
1259		NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname);
1260	}
1261
1262	error = 0;
1263	xhdr = (struct xattr_hdr *)get_read_buffer(size, &error,
1264	    &actual_size, local_commands);
1265	if (error) {
1266		NDMP_LOG(LOG_DEBUG,
1267		    "Could not read xattr [%s:%s] for restore. ",
1268		    name, fname);
1269		job_stats->js_errors++;
1270		return (0);
1271	}
1272
1273	/* Check extended attribute header */
1274	if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) {
1275		NDMP_LOG(LOG_DEBUG,
1276		    "Unrecognized header format [%s]", xhdr->h_version);
1277		return (0);
1278	}
1279	xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr));
1280
1281	(void) sscanf(xbuf->h_namesz, "%7d", &namelen);
1282	xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1;
1283
1284	if (*fp == 0) {
1285		int fd;
1286
1287		fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755);
1288		if (fd == -1) {
1289			NDMP_LOG(LOG_DEBUG,
1290			    "Could not open xattr [%s:%s] for restore.",
1291			    name, xattrname);
1292			NDMP_LOG(LOG_DEBUG, "err=%d ", errno);
1293			job_stats->js_errors++;
1294		}
1295		(void) strlcpy(local_commands->tc_file_name, xattrname,
1296		    TLM_MAX_PATH_NAME);
1297		*fp = fd;
1298	}
1299
1300	/* Get the actual extended attribute file */
1301	tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr),
1302	    &error, &actual_size, local_commands);
1303	if (error) {
1304		NDMP_LOG(LOG_DEBUG,
1305		    "Could not read xattr data [%s:%s] for restore. ",
1306		    fname, xattrname);
1307		job_stats->js_errors++;
1308		return (0);
1309	}
1310	acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode);
1311	acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size);
1312	acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid);
1313	acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid);
1314	acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime);
1315
1316	size = acls->acl_attr.st_size;
1317	while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1318		char	*rec;
1319		int	write_size;
1320
1321		error = 0;
1322		rec = get_read_buffer(size, &error, &actual_size,
1323		    local_commands);
1324		if (actual_size <= 0) {
1325			NDMP_LOG(LOG_DEBUG,
1326			    "RESTORE WRITER> error %d, actual_size %d",
1327			    error, actual_size);
1328
1329			return (size);
1330		} else if (error) {
1331			NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1332			    error, local_commands->tc_file_name);
1333			break;
1334		} else {
1335			write_size = min(size, actual_size);
1336			write_size = write(*fp, rec, write_size);
1337			NS_ADD(wdisk, write_size);
1338			NS_INC(wfile);
1339			size -= write_size;
1340		}
1341	}
1342
1343	if (*fp != 0) {
1344		set_xattr(*fp, acls->acl_attr);
1345		(void) close(*fp);
1346		*fp = 0;
1347	}
1348	return (0);
1349}
1350
1351/*
1352 * Match the name with the list
1353 */
1354static int
1355exact_find(char *name, char **list)
1356{
1357	boolean_t found;
1358	int i;
1359	char *cp;
1360
1361	found = FALSE;
1362	for (i = 0; *list != NULL; list++, i++) {
1363		cp = *list + strspn(*list, "/");
1364		if (match(cp, name)) {
1365			found = TRUE;
1366			NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp);
1367			break;
1368		}
1369	}
1370
1371	return (found);
1372}
1373
1374/*
1375 * On error, return FALSE and prevent restoring(probably) unwanted data.
1376 */
1377static int
1378is_parent(char *parent, char *child, int flags)
1379{
1380	char tmp[TLM_MAX_PATH_NAME];
1381	boolean_t rv;
1382
1383	if (IS_SET(flags, RSFLG_MATCH_WCARD)) {
1384		if (!tlm_cat_path(tmp, parent, "*")) {
1385			NDMP_LOG(LOG_DEBUG,
1386			    "is_parent> path too long [%s]", parent);
1387			rv = FALSE;
1388		} else
1389			rv = (match(tmp, child) != 0) ? TRUE : FALSE;
1390	} else {
1391		if (!tlm_cat_path(tmp, parent, "/")) {
1392			NDMP_LOG(LOG_DEBUG,
1393			    "is_parent> path too long [%s]", parent);
1394			rv = FALSE;
1395		} else
1396			rv = (strncmp(tmp, child, strlen(tmp)) == 0) ?
1397			    TRUE : FALSE;
1398	}
1399
1400	return (rv);
1401}
1402
1403/*
1404 * Used to match the filename inside the list
1405 */
1406static boolean_t
1407strexactcmp(char *s, char *t)
1408{
1409	return ((strcmp(s, t) == 0) ? TRUE : FALSE);
1410}
1411
1412/*
1413 * Check if the file is needed to be restored
1414 */
1415static boolean_t
1416is_file_wanted(char *name,
1417    char **sels,
1418    char **exls,
1419    int flags,
1420    int *mchtype,
1421    int *pos)
1422{
1423	char *p_sel;
1424	char *uc_name, *retry, *namep;
1425	boolean_t found;
1426	int i;
1427	name_match_fp_t *cmp_fp;
1428
1429	if (name == NULL || sels == NULL || exls == NULL)
1430		return (FALSE);
1431
1432	found = FALSE;
1433	if (mchtype != NULL)
1434		*mchtype = PM_NONE;
1435	if (pos != NULL)
1436		*pos = 0;
1437
1438	/*
1439	 * For empty selection, restore everything
1440	 */
1441	if (*sels == NULL || **sels == '\0') {
1442		NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all");
1443		return (TRUE);
1444	}
1445
1446	uc_name = ndmp_malloc(TLM_MAX_PATH_NAME);
1447	retry = ndmp_malloc(TLM_MAX_PATH_NAME);
1448	if (uc_name == NULL || retry == NULL) {
1449		free(uc_name);
1450		free(retry);
1451		return (FALSE);
1452	}
1453
1454	if (IS_SET(flags, RSFLG_MATCH_WCARD))
1455		cmp_fp = match;
1456	else
1457		cmp_fp = strexactcmp;
1458
1459	namep = name + strspn(name, "/");
1460	if (IS_SET(flags, RSFLG_IGNORE_CASE)) {
1461		(void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME);
1462		(void) strupr(uc_name);
1463		namep = uc_name;
1464	}
1465	NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]",
1466	    flags, name);
1467
1468	for (i = 0; *sels != NULL; sels++, i++) {
1469		p_sel = *sels + strspn(*sels, "/");
1470
1471		/*
1472		 * Try exact match.
1473		 */
1474		if ((*cmp_fp)(p_sel, namep)) {
1475			NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]",
1476			    i, p_sel, name);
1477			found = TRUE;
1478			if (mchtype != NULL)
1479				*mchtype = PM_EXACT;
1480			break;
1481		}
1482		/*
1483		 * Try "entry/" and the current selection.  The
1484		 * current selection may be something like "<something>/".
1485		 */
1486		(void) tlm_cat_path(retry, namep, "/");
1487		if ((*cmp_fp)(p_sel, retry)) {
1488			NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]",
1489			    i, p_sel, name);
1490			found = TRUE;
1491			if (mchtype != NULL)
1492				*mchtype = PM_EXACT;
1493			break;
1494		}
1495		/*
1496		 * If the following check returns true it means that the
1497		 * 'name' is an entry below the 'p_sel' hierarchy.
1498		 */
1499		if (is_parent(p_sel, namep, flags)) {
1500			NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]",
1501			    i, p_sel, name);
1502			found = TRUE;
1503			if (mchtype != NULL)
1504				*mchtype = PM_CHILD;
1505			break;
1506		}
1507
1508		/*
1509		 * There is a special case for parent directories of a
1510		 * selection.  If 'p_sel' is something like "*d1", the
1511		 * middle directories of the final entry can't be determined
1512		 * until the final entry matches with 'p_sel'.  At that
1513		 * time the middle directories of the entry have been passed
1514		 * and they can't be restored.
1515		 */
1516		if (is_parent(namep, p_sel, flags)) {
1517			NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]",
1518			    i, p_sel, name);
1519			found = TRUE;
1520			if (mchtype != NULL)
1521				*mchtype = PM_PARENT;
1522			break;
1523		}
1524	}
1525
1526	/* Check for exclusions.  */
1527	if (found && exact_find(namep, exls)) {
1528		if (mchtype != NULL)
1529			*mchtype = PM_NONE;
1530		found = FALSE;
1531	}
1532	if (found && pos != NULL)
1533		*pos = i;
1534
1535	free(uc_name);
1536	free(retry);
1537	return (found);
1538}
1539
1540/*
1541 * Read the specified amount data into the buffer.  Detects EOT or EOF
1542 * during read.
1543 *
1544 * Returns the number of bytes actually read.  On error returns -1.
1545 */
1546static int
1547input_mem(int l,
1548    int d,
1549    tlm_cmd_t *lcmds,
1550    char *mem,
1551    int len)
1552{
1553	int err;
1554	int toread, actual_size, rec_size;
1555	char *rec;
1556
1557	if (l <= 0 || d <= 0 || !lcmds || !mem) {
1558		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1559		return (-1);
1560	}
1561
1562	toread = len;
1563	while (toread > 0) {
1564		rec = get_read_buffer(toread, &err, &actual_size, lcmds);
1565		if (actual_size <= 0) {
1566			NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected",
1567			    err, actual_size);
1568			break;
1569		} else if (err) {
1570			NDMP_LOG(LOG_DEBUG, "error %d reading data", err);
1571			return (-1);
1572		}
1573		rec_size = min(actual_size, toread);
1574		(void) memcpy(mem, rec, rec_size);
1575		mem += rec_size;
1576		toread -= rec_size;
1577	}
1578
1579	return (len - toread);
1580}
1581
1582/*
1583 * pick up the name and size of a HUGE file
1584 */
1585static	int
1586get_humongus_file_header(int lib,
1587    int	drv,
1588    long recsize,
1589    longlong_t *size,
1590    char *name,
1591    tlm_cmd_t *local_commands)
1592{
1593	char *p_record, *value;
1594	int rv;
1595
1596	NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize);
1597
1598	rv = 0;
1599	if (recsize == 0) {
1600		/*
1601		 * The humongus_file_header was written in a
1602		 * RECORDSIZE block and the header.size field of this
1603		 * record was 0 before this fix.  For backward compatiblity
1604		 * read only one RECORDSIZE-size block if the header.size
1605		 * field is 0.  Otherwise the header.size field should show
1606		 * the length of the data of this header.
1607		 */
1608		NDMP_LOG(LOG_DEBUG, "Old HUGE record found");
1609		recsize = RECORDSIZE;
1610	}
1611
1612	if (input_mem(lib, drv, local_commands, name, recsize) != recsize) {
1613		rv = -1;
1614		*size = 0;
1615		*name = '\0';
1616		NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name");
1617	} else {
1618		NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name);
1619
1620		p_record = name;
1621		value = parse(&p_record, " ");
1622		*size = atoll(value);
1623		/*
1624		 * Note: Since the backed up names are not longer than
1625		 * NAME_MAX and the buffer passed to us is
1626		 * TLM_MAX_PATH_NAME, it should be safe to use strlcpy
1627		 * without check on the buffer size.
1628		 */
1629		(void) strlcpy(name, p_record, TLM_MAX_PATH_NAME);
1630	}
1631
1632	NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name);
1633
1634	return (rv);
1635}
1636
1637/*
1638 * pick up the long name from the special tape file
1639 */
1640static int
1641get_long_name(int lib,
1642    int drv,
1643    long recsize,
1644    char *name,
1645    long *buf_spot,
1646    tlm_cmd_t *local_commands)
1647{
1648	int nread;
1649
1650	NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize,
1651	    *buf_spot);
1652
1653	if (*buf_spot < 0)
1654		*buf_spot = 0;
1655
1656	nread = input_mem(lib, drv, local_commands, name + *buf_spot,
1657	    recsize);
1658	if (nread < 0) {
1659		nread = recsize; /* return 0 as size left */
1660		name[*buf_spot] = '\0';
1661		NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.",
1662		    nread, name);
1663	} else {
1664		*buf_spot += nread;
1665		name[*buf_spot] = '\0';
1666		NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name);
1667	}
1668
1669	return (recsize - nread);
1670}
1671
1672/*
1673 * create a new directory
1674 */
1675static	int
1676create_directory(char *dir, tlm_job_stats_t *job_stats)
1677{
1678	struct stat64 attr;
1679	char	*p;
1680	char	temp;
1681	int	erc;
1682
1683	/*
1684	 * Make sure all directories in this path exist, create them if
1685	 * needed.
1686	 */
1687	NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir);
1688
1689	erc = 0;
1690	p = &dir[1];
1691	do {
1692		temp = *p;
1693		if (temp == '/' || temp == 0) {
1694			*p = 0;
1695			if (stat64(dir, &attr) < 0) {
1696				erc = mkdir(dir, 0777);
1697				if (erc < 0) {
1698					job_stats->js_errors++;
1699					NDMP_LOG(LOG_DEBUG,
1700					    "Could not create directory %s",
1701					    dir);
1702					break;
1703				}
1704			}
1705			*p = temp;
1706		}
1707		p++;
1708	} while (temp != 0);
1709
1710	return (erc);
1711}
1712
1713/*
1714 * create a new hardlink
1715 */
1716static int
1717create_hard_link(char *name_old, char *name_new,
1718    tlm_acls_t *acls, tlm_job_stats_t *job_stats)
1719{
1720	int erc;
1721
1722	if (mkbasedir(name_new)) {
1723		NDMP_LOG(LOG_DEBUG, "faile to make base dir for [%s]",
1724		    name_new);
1725
1726		return (-1);
1727	}
1728
1729	erc = link(name_old, name_new);
1730	if (erc) {
1731		job_stats->js_errors++;
1732		NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]",
1733		    erc, errno, name_new, name_old);
1734	} else {
1735		set_acl(name_new, acls);
1736	}
1737	return (erc);
1738}
1739
1740/*
1741 * create a new symlink
1742 */
1743/*ARGSUSED*/
1744static int
1745create_sym_link(char *dst, char *target, tlm_acls_t *acls,
1746    tlm_job_stats_t *job_satats)
1747{
1748	int erc;
1749
1750	if (mkbasedir(dst) < 0)
1751		return (-1);
1752
1753	erc = symlink(target, dst);
1754	if (erc) {
1755		job_satats->js_errors++;
1756		NDMP_LOG(LOG_DEBUG, "error %d (errno %d) softlink [%s] to [%s]",
1757		    erc, errno, dst, target);
1758	}
1759
1760	return (erc);
1761}
1762
1763/*
1764 * create a new FIFO
1765 */
1766static int
1767create_fifo(char *name, tlm_acls_t *acls)
1768{
1769	(void) mknod(name, 0777 + S_IFIFO, 0);
1770	set_acl(name, acls);
1771	return (0);
1772}
1773
1774/*
1775 * read in the ACLs for the next file
1776 */
1777static long
1778load_acl_info(int lib,
1779    int drv,
1780    long file_size,
1781    tlm_acls_t *acls,
1782    long *acl_spot,
1783    tlm_cmd_t *local_commands)
1784{
1785	char *bp;
1786	int nread;
1787
1788	/*
1789	 * If the ACL is spanned on tapes, then the acl_spot should NOT be
1790	 * 0 on next calls to this function to read the rest of the ACL
1791	 * on next tapes.
1792	 */
1793	if (*acl_spot == 0) {
1794		(void) memset(acls, 0, sizeof (tlm_acls_t));
1795	}
1796
1797	bp = ((char *)&acls->acl_info) + *acl_spot;
1798	nread = input_mem(lib, drv, local_commands, (void *)bp, file_size);
1799	if (nread < 0) {
1800		*acl_spot = 0;
1801		(void) memset(acls, 0, sizeof (tlm_acls_t));
1802		NDMP_LOG(LOG_DEBUG, "Error reading ACL data");
1803		return (0);
1804	}
1805	*acl_spot += nread;
1806	acls->acl_non_trivial = TRUE;
1807
1808	return (file_size - nread);
1809}
1810
1811static int
1812ndmp_set_eprivs_least(void)
1813{
1814	priv_set_t *priv_set;
1815
1816	if ((priv_set = priv_allocset()) == NULL) {
1817		NDMP_LOG(LOG_ERR, "Out of memory.");
1818		return (-1);
1819	}
1820	priv_emptyset(priv_set);
1821	(void) priv_addset(priv_set, "basic");
1822	(void) priv_addset(priv_set, "proc_audit");
1823	(void) priv_addset(priv_set, "proc_setid");
1824	(void) priv_addset(priv_set, "proc_owner");
1825	(void) priv_addset(priv_set, "file_chown");
1826	(void) priv_addset(priv_set, "file_chown_self");
1827	(void) priv_addset(priv_set, "file_dac_read");
1828	(void) priv_addset(priv_set, "file_dac_search");
1829	(void) priv_addset(priv_set, "file_dac_write");
1830	(void) priv_addset(priv_set, "file_owner");
1831	(void) priv_addset(priv_set, "file_setid");
1832	(void) priv_addset(priv_set, "sys_linkdir");
1833	(void) priv_addset(priv_set, "sys_devices");
1834	(void) priv_addset(priv_set, "sys_mount");
1835	(void) priv_addset(priv_set, "sys_config");
1836
1837	if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
1838		NDMP_LOG(LOG_ERR, "Additional privileges required.");
1839		priv_freeset(priv_set);
1840		return (-1);
1841	}
1842	priv_freeset(priv_set);
1843	return (0);
1844}
1845
1846static int
1847ndmp_set_eprivs_all(void)
1848{
1849	priv_set_t *priv_set;
1850
1851	if ((priv_set = priv_str_to_set("all", ",", NULL)) == NULL) {
1852		NDMP_LOG(LOG_ERR, "Could not set privileges to 'all'.");
1853		return (-1);
1854	}
1855	if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) {
1856		NDMP_LOG(LOG_ERR, "Additional privileges required.");
1857		return (-1);
1858	}
1859	priv_freeset(priv_set);
1860	return (0);
1861}
1862
1863/*
1864 * Set the standard attributes of the file
1865 */
1866static void
1867set_attr(char *name, struct stat64 *st)
1868{
1869	struct utimbuf tbuf;
1870	boolean_t priv_all = FALSE;
1871
1872	if (!name || !st)
1873		return;
1874
1875	NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d mode %o", name,
1876	    st->st_uid, st->st_gid, st->st_mode);
1877
1878	if (chown(name, st->st_uid, st->st_gid))
1879		NDMP_LOG(LOG_ERR,
1880		    "Could not set uid or/and gid for file %s.", name);
1881
1882	if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) {
1883		/*
1884		 * Change effective privileges to 'all' which is required to
1885		 * change setuid bit for 'root' owned files. If fails, just
1886		 * send error to log file and proceed.
1887		 */
1888		if (ndmp_set_eprivs_all()) {
1889			NDMP_LOG(LOG_ERR,
1890			    "Could not set effective privileges to 'all'.");
1891		} else {
1892			priv_all = TRUE;
1893		}
1894	}
1895
1896	if (chmod(name, st->st_mode))
1897		NDMP_LOG(LOG_ERR,
1898		    "Could not set correct file permission for file %s.", name);
1899
1900	if (priv_all == TRUE) {
1901		/*
1902		 * Give up the 'all' privileges for effective sets and go back
1903		 * to least required privileges. If fails, just send error to
1904		 * log file and proceed.
1905		 */
1906		if (ndmp_set_eprivs_least())
1907			NDMP_LOG(LOG_ERR,
1908			    "Could not set least required privileges.");
1909	}
1910
1911	tbuf.modtime = st->st_mtime;
1912	tbuf.actime = st->st_atime;
1913	(void) utime(name, &tbuf);
1914}
1915
1916/*
1917 * Set the ACL info for the file
1918 */
1919static void
1920set_acl(char *name, tlm_acls_t *acls)
1921{
1922	int erc;
1923	acl_t *aclp = NULL;
1924
1925	if (name)
1926		NDMP_LOG(LOG_DEBUG, "set_acl: %s", name);
1927	if (acls != 0) {
1928		/* Need a place to save real modification time */
1929
1930		set_attr(name, &acls->acl_attr);
1931
1932		if (!acls->acl_non_trivial) {
1933			(void) memset(acls, 0, sizeof (tlm_acls_t));
1934			NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial");
1935			return;
1936		}
1937
1938		erc = acl_fromtext(acls->acl_info.attr_info, &aclp);
1939		if (erc != 0) {
1940			NDMP_LOG(LOG_DEBUG,
1941			    "TAPE RESTORE> acl_fromtext errno %d", erc);
1942		}
1943		if (aclp) {
1944			erc = acl_set(name, aclp);
1945			if (erc < 0) {
1946				NDMP_LOG(LOG_DEBUG,
1947				    "TAPE RESTORE> acl_set errno %d", errno);
1948			}
1949			acl_free(aclp);
1950		}
1951		(void) memset(acls, 0, sizeof (tlm_acls_t));
1952	}
1953}
1954
1955/*
1956 * a wrapper to tlm_get_read_buffer so that
1957 * we can cleanly detect ABORT commands
1958 * without involving the TLM library with
1959 * our problems.
1960 */
1961static char *
1962get_read_buffer(int want,
1963    int	*error,
1964    int	*actual_size,
1965    tlm_cmd_t *local_commands)
1966{
1967	while (local_commands->tc_writer == TLM_RESTORE_RUN) {
1968		char	*rec;
1969		rec = tlm_get_read_buffer(want, error,
1970		    local_commands->tc_buffers, actual_size);
1971		if (rec != 0) {
1972			return (rec);
1973		}
1974	}
1975
1976	/*
1977	 * the job is ending, give Writer a buffer that will never be read ...
1978	 * it does not matter anyhow, we are aborting.
1979	 */
1980	*actual_size = RECORDSIZE;
1981	return (NULL);
1982}
1983
1984/*
1985 * Enable wildcard for restore options
1986 */
1987static boolean_t
1988wildcard_enabled(void)
1989{
1990	char *cp;
1991
1992	cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n");
1993	return ((toupper(*cp) == 'Y') ? TRUE : FALSE);
1994}
1995
1996
1997/*
1998 * Concatenate two names
1999 */
2000/*ARGSUSED*/
2001static char *
2002catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2003{
2004	char *rv;
2005
2006	rv = NULL;
2007	if (!buf) {
2008		NDMP_LOG(LOG_DEBUG, "buf is NULL");
2009	} else if (!path) {
2010		NDMP_LOG(LOG_DEBUG, "path is NULL");
2011	} else if (!rnp->rn_nlp) {
2012		NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path);
2013	} else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) {
2014		NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
2015		    rnp->rn_nlp, path);
2016	} else
2017		rv = buf;
2018
2019	return (rv);
2020}
2021
2022
2023/*
2024 * Create a new name path for restore
2025 */
2026static char *
2027rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2028{
2029	if (!rnp || !rnp->rn_fp)
2030		return (NULL);
2031
2032	return (*rnp->rn_fp)(rnp, buf, pos, path);
2033}
2034
2035/*
2036 * Iterate over ZFS metadata stored in the backup stream and use the callback
2037 * to restore it.
2038 */
2039int
2040ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *,
2041    void *), void *ptr)
2042{
2043	tlm_commands_t *cmds;
2044	ndmp_metadata_header_t *mhp;
2045	ndmp_metadata_property_t *mpp;
2046	tlm_cmd_t *lcmd;
2047	int actual_size;
2048	nvlist_t *nvl;
2049	nvlist_t *nvl_head;
2050	nvlist_t *valp;
2051	nvpair_t *nvp = NULL;
2052	nvpair_t *nvph = NULL;
2053	char plname[100];
2054	char *mhbuf, *pp, *tp;
2055	int rv, i;
2056	int size, lsize, sz;
2057	int align = RECORDSIZE - 1;
2058
2059	if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2060		return (-1);
2061
2062	nctx->nc_plname = plname;
2063	if ((lcmd = cmds->tcs_command) == NULL ||
2064	    lcmd->tc_buffers == NULL)
2065		return (-1);
2066
2067	size = sizeof (ndmp_metadata_header_t) +
2068	    ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t);
2069	size += align;
2070	size &= ~align;
2071
2072	/* For nvlist cleanup */
2073	if (nvlist_alloc(&nvl_head, NV_UNIQUE_NAME, 0) != 0)
2074		return (-1);
2075
2076	if ((mhbuf = malloc(size)) == NULL)
2077		return (-1);
2078
2079	/* LINTED improper alignment */
2080	while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2081	    &actual_size, lcmd)) != NULL) {
2082		pp = mhbuf;
2083
2084		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2085		    sizeof (mhp->nh_magic)) != 0) {
2086			/* No more metadata */
2087			tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2088			nvlist_free(nvl_head);
2089			return (0);
2090		}
2091
2092		(void) memcpy(pp, (char *)mhp, (actual_size < size) ?
2093		    actual_size : size);
2094		pp += (actual_size < size) ? actual_size : size;
2095
2096		sz = actual_size;
2097		while (sz < size &&
2098		    ((tp = get_read_buffer(size - sz, &rv, &lsize,
2099		    lcmd))) != NULL) {
2100			(void) memcpy(pp, tp, size - sz);
2101			sz += lsize;
2102			pp += lsize;
2103		}
2104		if (sz > size) {
2105			tlm_unget_read_buffer(lcmd->tc_buffers, sz - size);
2106		}
2107		/* LINTED improper alignment */
2108		mhp = (ndmp_metadata_header_t *)mhbuf;
2109
2110		nctx->nc_plversion = mhp->nh_plversion;
2111		(void) strlcpy(plname, mhp->nh_plname, sizeof (plname));
2112
2113		if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
2114			goto nvlist_err;
2115
2116		mpp = &mhp->nh_property[0];
2117		for (i = 0; i < mhp->nh_count && mpp; i++) {
2118			if (nvlist_alloc(&valp, NV_UNIQUE_NAME, 0) != 0 ||
2119			    nvlist_add_string(valp, "value",
2120			    mpp->mp_value) != 0 ||
2121			    nvlist_add_string(valp, "source",
2122			    mpp->mp_source) != 0 ||
2123			    nvlist_add_nvlist(nvl, mpp->mp_name, valp) != 0)
2124				goto nvlist_err;
2125			mpp++;
2126		}
2127
2128		if (np_restore_property(nvl, ptr) != 0)
2129			goto nvlist_err;
2130
2131		(void) nvlist_add_nvlist(nvl_head, "_", nvl);
2132	}
2133	free(mhbuf);
2134
2135	nvlist_free(nvl_head);
2136	return (0);
2137
2138nvlist_err:
2139	free(mhbuf);
2140	while ((nvph = nvlist_next_nvpair(nvl_head, nvph)) != NULL &&
2141	    nvpair_value_nvlist(nvph, &nvl) == 0) {
2142		while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL &&
2143		    nvpair_value_nvlist(nvp, &valp) == 0) {
2144			nvlist_free(valp);
2145		}
2146		nvlist_free(nvl);
2147	}
2148	nvlist_free(nvl_head);
2149	return (-1);
2150}
2151
2152/*
2153 * Returns the version number of the plugin which created the metadata
2154 */
2155uint_t
2156ndmp_context_get_version(ndmp_context_t *nctx)
2157{
2158	tlm_commands_t *cmds;
2159	ndmp_metadata_header_t *mhp;
2160	tlm_cmd_t *lcmd;
2161	int actual_size;
2162	int rv;
2163	int size;
2164	int align = RECORDSIZE - 1;
2165
2166	if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2167		return (0);
2168
2169	if ((lcmd = cmds->tcs_command) == NULL ||
2170	    lcmd->tc_buffers == NULL)
2171		return (0);
2172
2173	size = sizeof (ndmp_metadata_header_t);
2174	size += align;
2175	size &= ~align;
2176
2177	/* LINTED improper alignment */
2178	if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2179	    &actual_size, lcmd)) != NULL) {
2180		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2181		    sizeof (mhp->nh_magic)) != 0) {
2182			/* No more metadata */
2183			tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2184			return (0);
2185		}
2186
2187		nctx->nc_plversion = mhp->nh_plversion;
2188		tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2189	}
2190
2191	return (nctx->nc_plversion);
2192}
2193