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