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