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