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