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