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 */
990int
991tar_getfile(tlm_backup_restore_arg_t *argp)
992{
993	tlm_job_stats_t	*job_stats;
994	char	**sels;		/* list of files desired */
995	char	**exls;		/* list of files not wanted */
996	char	*dir;		/* where to restore the files */
997	char	job[TLM_MAX_BACKUP_JOB_NAME+1];
998				/* the restore job name */
999	int	erc;		/* error return codes */
1000	int	flags;
1001	struct	rs_name_maker rn;
1002	tlm_commands_t *commands;
1003	tlm_cmd_t *local_commands;
1004	char *list = NULL;
1005
1006	commands = argp->ba_commands;
1007	local_commands = argp->ba_cmd;
1008
1009	flags = 0;
1010
1011	dir = ndmp_malloc(TLM_MAX_PATH_NAME);
1012	if (dir == NULL) {
1013		local_commands->tc_reader = TLM_STOP;
1014		(void) pthread_barrier_wait(&argp->ba_barrier);
1015		return (-1);
1016	}
1017
1018	(void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1);
1019	(void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME);
1020
1021	flags |= RSFLG_OVR_ALWAYS;
1022	flags |= RSFLG_IGNORE_CASE;
1023
1024	/*
1025	 * do not test for "dir" having no string, since that
1026	 * is a legal condition.  Restore to origional location
1027	 * will not have a restore directory.
1028	 */
1029	if (*job == '\0') {
1030		NDMP_LOG(LOG_DEBUG, "No job defined");
1031		local_commands->tc_reader = TLM_STOP;
1032		free(dir);
1033		(void) pthread_barrier_wait(&argp->ba_barrier);
1034		return (-1);
1035	}
1036
1037	sels = argp->ba_sels;
1038	if (sels == NULL) {
1039		local_commands->tc_reader = TLM_STOP;
1040		free(dir);
1041		(void) pthread_barrier_wait(&argp->ba_barrier);
1042		return (-1);
1043	}
1044	exls = &list;
1045
1046	tlm_log_list("selections", sels);
1047	tlm_log_list("exclusions", exls);
1048
1049	if (wildcard_enabled())
1050		flags |= RSFLG_MATCH_WCARD;
1051
1052	local_commands->tc_ref++;
1053	commands->tcs_writer_count++;
1054
1055	/*
1056	 * let the launcher continue
1057	 */
1058	(void) pthread_barrier_wait(&argp->ba_barrier);
1059
1060	job_stats = tlm_ref_job_stats(job);
1061
1062	rn.rn_fp = catnames;
1063	rn.rn_nlp = dir;
1064
1065	/*
1066	 * work
1067	 */
1068	NDMP_LOG(LOG_DEBUG, "start restore job %s", job);
1069	erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1,
1070	    sels, exls, flags, 0, NULL, NULL);
1071
1072	/*
1073	 * teardown
1074	 */
1075	NDMP_LOG(LOG_DEBUG, "end restore job %s", job);
1076	tlm_un_ref_job_stats(job);
1077	tlm_release_list(sels);
1078	tlm_release_list(exls);
1079
1080	commands->tcs_writer_count--;
1081	local_commands->tc_reader = TLM_STOP;
1082	tlm_release_reader_writer_ipc(local_commands);
1083	free(dir);
1084	return (erc);
1085}
1086
1087/*
1088 * Creates the directories all the way down to the
1089 * end if they dont exist
1090 */
1091int
1092make_dirs(char *dir)
1093{
1094	char c;
1095	char *cp, *end;
1096	struct stat64 st;
1097
1098	cp = dir;
1099	cp += strspn(cp, "/");
1100	end = dir + strlen(dir);
1101	do {
1102		if (*cp == '\0' || *cp == '/') {
1103			c = *cp;
1104			*cp = '\0';
1105			if (lstat64(dir, &st) < 0)
1106				if (mkdir(dir, 0777) < 0) {
1107					NDMP_LOG(LOG_DEBUG, "Error %d"
1108					    " creating directory %s",
1109					    errno, dir);
1110					*cp = c;
1111					return (errno);
1112				}
1113
1114			*cp = c;
1115		}
1116	} while (++cp <= end);
1117
1118	return (0);
1119}
1120
1121/*
1122 * Creates the directories leading to the given path
1123 */
1124int
1125mkbasedir(char *path)
1126{
1127	int rv;
1128	char *cp;
1129	struct stat64 st;
1130
1131	if (!path || !*path) {
1132		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1133		return (-1);
1134	}
1135
1136	cp = strrchr(path, '/');
1137	if (cp)
1138		*cp = '\0';
1139	rv = lstat64(path, &st);
1140	if (rv < 0)	/* need new directories */
1141		rv = make_dirs(path);
1142	if (cp)
1143		*cp = '/';
1144
1145	return (rv);
1146}
1147
1148
1149/*
1150 * read the file off the tape back onto disk
1151 *
1152 * If the function returns a non-zero return code, it means that fatal error
1153 * was encountered and restore should terminate immediately.
1154 */
1155static int
1156restore_file(int *fp,
1157    char *real_name,
1158    long size,
1159    longlong_t huge_size,
1160    tlm_acls_t *acls,
1161    boolean_t want_this_file,
1162    tlm_cmd_t *local_commands,
1163    tlm_job_stats_t *job_stats,
1164    long *size_left)
1165{
1166	struct stat64	attr;
1167	int	ret, rv;
1168
1169	*size_left = 0;
1170	if (!real_name) {
1171		if (want_this_file) {
1172			NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1173			want_this_file = FALSE;
1174		}
1175	} else
1176		NDMP_LOG(LOG_DEBUG, "new file[%s]", real_name);
1177
1178	/*
1179	 * OK, some FM is creeping in here ...
1180	 * int *fp is used to keep the
1181	 * backup file channel open through
1182	 * the interruption of EOT and
1183	 * processing the headers of the
1184	 * next tape.  So, if *fp is zero
1185	 * then no file is open yet and all
1186	 * is normal.  If *fp has a number
1187	 * then we are returning after an
1188	 * EOT break.
1189	 *
1190	 * *fp is now also open for HUGE files
1191	 * that are put back in sections.
1192	 */
1193
1194	if (*fp == 0 && want_this_file) {
1195
1196		ret = mkbasedir(real_name);
1197		if (ret != 0) {
1198			job_stats->js_errors++;
1199			if (ERROR_IS_FATAL(ret))
1200				return (ret);
1201		}
1202
1203		ret = stat64(real_name, (struct stat64 *)&attr);
1204		if (ret < 0) {
1205			/*EMPTY*/
1206			/* new file */
1207		} else if (acls->acl_overwrite) {
1208			/*EMPTY*/
1209			/* take this file no matter what */
1210		} else if (acls->acl_update) {
1211			if (attr.st_mtime < acls->acl_attr.st_mtime) {
1212				/*EMPTY*/
1213				/* tape is newer */
1214			} else {
1215				/* disk file is newer */
1216				want_this_file = FALSE;
1217			}
1218		} else {
1219			/*
1220			 * no overwrite, no update,
1221			 * do not ever replace old files.
1222			 */
1223			want_this_file = TRUE;
1224		}
1225		if (want_this_file) {
1226
1227			*fp = open(real_name, O_CREAT | O_TRUNC | O_WRONLY,
1228			    S_IRUSR | S_IWUSR);
1229			if (*fp == -1) {
1230				NDMP_LOG(LOG_ERR,
1231				    "Could not open %s for restore: %d",
1232				    real_name, errno);
1233				job_stats->js_errors++;
1234				want_this_file = FALSE;
1235				/*
1236				 * In case of non-fatal error we cannot return
1237				 * here, because the file is still on the tape
1238				 * and must be skipped over.
1239				 */
1240				if (ERROR_IS_FATAL(errno))
1241					return (errno);
1242			}
1243		}
1244		(void) strlcpy(local_commands->tc_file_name, real_name,
1245		    TLM_MAX_PATH_NAME);
1246	}
1247
1248	/*
1249	 * this is the size left in the next segment
1250	 */
1251	huge_size -= size;
1252
1253	/*
1254	 * work
1255	 */
1256	rv = 0;
1257	while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1258		int	actual_size;
1259		int	error;
1260		char	*rec;
1261		int	write_size;
1262
1263		/*
1264		 * Use bytes_in_file field to tell reader the amount
1265		 * of data still need to be read for this file.
1266		 */
1267		job_stats->js_bytes_in_file = size;
1268
1269		error = 0;
1270		rec = get_read_buffer(size, &error, &actual_size,
1271		    local_commands);
1272		if (actual_size <= 0) {
1273			NDMP_LOG(LOG_DEBUG,
1274			    "RESTORE WRITER> error %d, actual_size %d",
1275			    error, actual_size);
1276
1277			/* no more data for this file for now */
1278			job_stats->js_bytes_in_file = 0;
1279			*size_left = size;
1280			return (0);
1281		} else if (error) {
1282			NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1283			    error, local_commands->tc_file_name);
1284			break;
1285		}
1286
1287		write_size = min(size, actual_size);
1288		if (want_this_file) {
1289			ret = write(*fp, rec, write_size);
1290			if (ret < 0) {
1291				NDMP_LOG(LOG_ERR,
1292				    "Write error %d for file [%s]", errno,
1293				    local_commands->tc_file_name);
1294				job_stats->js_errors++;
1295				if (ERROR_IS_FATAL(errno)) {
1296					rv = errno;
1297					break;
1298				}
1299			} else {
1300				NS_ADD(wdisk, ret);
1301				NS_INC(wfile);
1302				if (ret < write_size) {
1303					NDMP_LOG(LOG_ERR,
1304					    "Partial write for file [%s]",
1305					    local_commands->tc_file_name);
1306				}
1307			}
1308		}
1309		size -= write_size;
1310	}
1311
1312	/* no more data for this file for now */
1313	job_stats->js_bytes_in_file = 0;
1314
1315	/*
1316	 * teardown
1317	 */
1318	if (*fp != 0 && huge_size <= 0) {
1319		(void) close(*fp);
1320		*fp = 0;
1321		if (rv == 0) {
1322			ret = set_acl(real_name, acls);
1323			if (ERROR_IS_FATAL(ret))
1324				return (ret);
1325		}
1326	}
1327	return (rv);
1328}
1329
1330/*
1331 * Set the extended attributes file attribute
1332 */
1333static void
1334set_xattr(int fd, struct stat64 st)
1335{
1336	struct timeval times[2];
1337
1338	times[0].tv_sec = st.st_atime;
1339	times[1].tv_sec = st.st_mtime;
1340
1341	(void) fchmod(fd, st.st_mode);
1342	(void) fchown(fd, st.st_uid, st.st_gid);
1343	(void) futimesat(fd, ".", times);
1344}
1345
1346/*
1347 * Read the system attribute file in a single buffer to write
1348 * it as a single write. A partial write to system attribute would
1349 * cause an EINVAL on write.
1350 */
1351static char *
1352get_read_one_buf(char *rec, int actual_size, int size, int *error,
1353    tlm_cmd_t *lc)
1354{
1355	char *buf, *p;
1356	int read_size;
1357	int len;
1358
1359	if (actual_size > size)
1360		return (rec);
1361
1362	buf = ndmp_malloc(size);
1363	if (buf == NULL) {
1364		*error = ENOMEM;
1365		return (NULL);
1366	}
1367	(void) memcpy(buf, rec, actual_size);
1368	rec = buf;
1369	buf += actual_size;
1370	while (actual_size < size) {
1371		p = get_read_buffer(size - actual_size, error, &read_size, lc);
1372		len = min(size - actual_size, read_size);
1373		(void) memcpy(buf, p, len);
1374		actual_size += len;
1375		buf += len;
1376	}
1377	return (rec);
1378}
1379
1380
1381/*
1382 * read the extended attribute header and write
1383 * it to the file
1384 */
1385static long
1386restore_xattr_hdr(int *fp,
1387    char *name,
1388    char *fname,
1389    long size,
1390    tlm_acls_t *acls,
1391    tlm_cmd_t *local_commands,
1392    tlm_job_stats_t *job_stats)
1393{
1394	tlm_tar_hdr_t *tar_hdr;
1395	struct xattr_hdr *xhdr;
1396	struct xattr_buf *xbuf;
1397	int namelen;
1398	char *xattrname;
1399	int actual_size;
1400	int error;
1401
1402	if (!fname) {
1403		NDMP_LOG(LOG_DEBUG, "No file name but wanted!");
1404	} else {
1405		NDMP_LOG(LOG_DEBUG, "new xattr[%s]", fname);
1406	}
1407
1408	error = 0;
1409	xhdr = (struct xattr_hdr *)get_read_buffer(size, &error,
1410	    &actual_size, local_commands);
1411	if (xhdr == NULL || error != 0) {
1412		NDMP_LOG(LOG_DEBUG,
1413		    "Could not read xattr [%s:%s] for restore. ",
1414		    name, fname);
1415		job_stats->js_errors++;
1416		return (0);
1417	}
1418
1419	/* Check extended attribute header */
1420	if (strcmp(xhdr->h_version, XATTR_ARCH_VERS) != 0) {
1421		NDMP_LOG(LOG_DEBUG,
1422		    "Unrecognized header format [%s]", xhdr->h_version);
1423		return (0);
1424	}
1425	xbuf = (struct xattr_buf *)(((char *)xhdr) + sizeof (struct xattr_hdr));
1426
1427	(void) sscanf(xbuf->h_namesz, "%7d", &namelen);
1428	xattrname = xbuf->h_names + strlen(xbuf->h_names) + 1;
1429
1430	if (*fp == 0) {
1431		int fd;
1432
1433		fd = attropen(name, xattrname, O_CREAT | O_RDWR, 0755);
1434		if (fd == -1) {
1435			NDMP_LOG(LOG_DEBUG,
1436			    "Could not open xattr [%s:%s] for restore err=%d.",
1437			    name, xattrname, errno);
1438			job_stats->js_errors++;
1439			return (0);
1440		}
1441		(void) strlcpy(local_commands->tc_file_name, xattrname,
1442		    TLM_MAX_PATH_NAME);
1443		*fp = fd;
1444	}
1445
1446	/* Get the actual extended attribute file */
1447	tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(sizeof (*tar_hdr),
1448	    &error, &actual_size, local_commands);
1449	if (tar_hdr == NULL || error != 0) {
1450		NDMP_LOG(LOG_DEBUG,
1451		    "Could not read xattr data [%s:%s] for restore. ",
1452		    fname, xattrname);
1453		job_stats->js_errors++;
1454		return (0);
1455	}
1456	acls->acl_attr.st_mode = oct_atoi(tar_hdr->th_mode);
1457	acls->acl_attr.st_size = oct_atoi(tar_hdr->th_size);
1458	acls->acl_attr.st_uid = oct_atoi(tar_hdr->th_uid);
1459	acls->acl_attr.st_gid = oct_atoi(tar_hdr->th_gid);
1460	acls->acl_attr.st_mtime = oct_atoi(tar_hdr->th_mtime);
1461
1462	NDMP_LOG(LOG_DEBUG, "xattr_hdr: %s size %d mode %06o uid %d gid %d",
1463	    xattrname, acls->acl_attr.st_size, acls->acl_attr.st_mode,
1464	    acls->acl_attr.st_uid, acls->acl_attr.st_gid);
1465
1466	size = acls->acl_attr.st_size;
1467	while (size > 0 && local_commands->tc_writer == TLM_RESTORE_RUN) {
1468		char	*rec;
1469		int	write_size;
1470		int	sysattr_write = 0;
1471
1472		error = 0;
1473		rec = get_read_buffer(size, &error, &actual_size,
1474		    local_commands);
1475
1476		if ((actual_size < size) && sysattr_rw(xattrname)) {
1477			rec = get_read_one_buf(rec, actual_size, size, &error,
1478			    local_commands);
1479			if (rec == NULL) {
1480				NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1481				    error, xattrname);
1482				return (size);
1483			}
1484			actual_size = size;
1485			sysattr_write = 1;
1486		}
1487		if (actual_size <= 0) {
1488			NDMP_LOG(LOG_DEBUG,
1489			    "RESTORE WRITER> error %d, actual_size %d",
1490			    error, actual_size);
1491
1492			return (size);
1493		} else if (error) {
1494			NDMP_LOG(LOG_DEBUG, "Error %d in file [%s]",
1495			    error, local_commands->tc_file_name);
1496			break;
1497		} else {
1498			write_size = min(size, actual_size);
1499			if ((write_size = write(*fp, rec, write_size)) < 0) {
1500				if (sysattr_write)
1501					free(rec);
1502
1503				break;
1504			}
1505
1506			NS_ADD(wdisk, write_size);
1507			NS_INC(wfile);
1508			size -= write_size;
1509		}
1510		if (sysattr_write)
1511			free(rec);
1512	}
1513
1514	if (*fp != 0) {
1515		set_xattr(*fp, acls->acl_attr);
1516		(void) close(*fp);
1517		*fp = 0;
1518	}
1519	return (0);
1520}
1521
1522/*
1523 * Match the name with the list
1524 */
1525static int
1526exact_find(char *name, char **list)
1527{
1528	boolean_t found;
1529	int i;
1530	char *cp;
1531
1532	found = FALSE;
1533	for (i = 0; *list != NULL; list++, i++) {
1534		cp = *list + strspn(*list, "/");
1535		if (match(cp, name)) {
1536			found = TRUE;
1537			NDMP_LOG(LOG_DEBUG, "exact_find> found[%s]", cp);
1538			break;
1539		}
1540	}
1541
1542	return (found);
1543}
1544
1545/*
1546 * On error, return FALSE and prevent restoring(probably) unwanted data.
1547 */
1548static int
1549is_parent(char *parent, char *child, int flags)
1550{
1551	char tmp[TLM_MAX_PATH_NAME];
1552	boolean_t rv;
1553
1554	if (IS_SET(flags, RSFLG_MATCH_WCARD)) {
1555		if (!tlm_cat_path(tmp, parent, "*")) {
1556			NDMP_LOG(LOG_DEBUG,
1557			    "is_parent> path too long [%s]", parent);
1558			rv = FALSE;
1559		} else
1560			rv = (match(tmp, child) != 0) ? TRUE : FALSE;
1561	} else {
1562		if (!tlm_cat_path(tmp, parent, "/")) {
1563			NDMP_LOG(LOG_DEBUG,
1564			    "is_parent> path too long [%s]", parent);
1565			rv = FALSE;
1566		} else
1567			rv = (strncmp(tmp, child, strlen(tmp)) == 0) ?
1568			    TRUE : FALSE;
1569	}
1570
1571	return (rv);
1572}
1573
1574/*
1575 * Used to match the filename inside the list
1576 */
1577static boolean_t
1578strexactcmp(char *s, char *t)
1579{
1580	return ((strcmp(s, t) == 0) ? TRUE : FALSE);
1581}
1582
1583/*
1584 * Check if the file is needed to be restored
1585 */
1586static boolean_t
1587is_file_wanted(char *name,
1588    char **sels,
1589    char **exls,
1590    int flags,
1591    int *mchtype,
1592    int *pos)
1593{
1594	char *p_sel;
1595	char *uc_name, *retry, *namep;
1596	boolean_t found;
1597	int i;
1598	name_match_fp_t *cmp_fp;
1599
1600	if (name == NULL || sels == NULL || exls == NULL)
1601		return (FALSE);
1602
1603	found = FALSE;
1604	if (mchtype != NULL)
1605		*mchtype = PM_NONE;
1606	if (pos != NULL)
1607		*pos = 0;
1608
1609	/*
1610	 * For empty selection, restore everything
1611	 */
1612	if (*sels == NULL || **sels == '\0') {
1613		NDMP_LOG(LOG_DEBUG, "is_file_wanted: Restore all");
1614		return (TRUE);
1615	}
1616
1617	retry = ndmp_malloc(TLM_MAX_PATH_NAME);
1618	if (retry == NULL)
1619		return (FALSE);
1620
1621	if (IS_SET(flags, RSFLG_MATCH_WCARD))
1622		cmp_fp = match;
1623	else
1624		cmp_fp = strexactcmp;
1625
1626	namep = name + strspn(name, "/");
1627
1628	if (IS_SET(flags, RSFLG_IGNORE_CASE)) {
1629		uc_name = ndmp_malloc(TLM_MAX_PATH_NAME);
1630		if (uc_name == NULL) {
1631			free(retry);
1632			return (FALSE);
1633		}
1634		(void) strlcpy(uc_name, namep, TLM_MAX_PATH_NAME);
1635		(void) strupr(uc_name);
1636		namep = uc_name;
1637	}
1638	NDMP_LOG(LOG_DEBUG, "is_file_wanted> flg: 0x%x name: [%s]",
1639	    flags, name);
1640
1641	for (i = 0; *sels != NULL; sels++, i++) {
1642		p_sel = *sels + strspn(*sels, "/");
1643
1644		/*
1645		 * Try exact match.
1646		 */
1647		if ((*cmp_fp)(p_sel, namep)) {
1648			NDMP_LOG(LOG_DEBUG, "match1> pos: %d [%s][%s]",
1649			    i, p_sel, name);
1650			found = TRUE;
1651			if (mchtype != NULL)
1652				*mchtype = PM_EXACT;
1653			break;
1654		}
1655		/*
1656		 * Try "entry/" and the current selection.  The
1657		 * current selection may be something like "<something>/".
1658		 */
1659		(void) tlm_cat_path(retry, namep, "/");
1660		if ((*cmp_fp)(p_sel, retry)) {
1661			NDMP_LOG(LOG_DEBUG, "match2> pos %d [%s][%s]",
1662			    i, p_sel, name);
1663			found = TRUE;
1664			if (mchtype != NULL)
1665				*mchtype = PM_EXACT;
1666			break;
1667		}
1668		/*
1669		 * If the following check returns true it means that the
1670		 * 'name' is an entry below the 'p_sel' hierarchy.
1671		 */
1672		if (is_parent(p_sel, namep, flags)) {
1673			NDMP_LOG(LOG_DEBUG, "parent1> pos %d [%s][%s]",
1674			    i, p_sel, name);
1675			found = TRUE;
1676			if (mchtype != NULL)
1677				*mchtype = PM_CHILD;
1678			break;
1679		}
1680		/*
1681		 * There is a special case for parent directories of a
1682		 * selection.  If 'p_sel' is something like "*d1", the
1683		 * middle directories of the final entry can't be determined
1684		 * until the final entry matches with 'p_sel'.  At that
1685		 * time the middle directories of the entry have been passed
1686		 * and they can't be restored.
1687		 */
1688		if (is_parent(namep, p_sel, flags)) {
1689			NDMP_LOG(LOG_DEBUG, "parent2> pos %d [%s][%s]",
1690			    i, p_sel, name);
1691			found = TRUE;
1692			if (mchtype != NULL)
1693				*mchtype = PM_PARENT;
1694			break;
1695		}
1696	}
1697
1698	/* Check for exclusions.  */
1699	if (found && exact_find(namep, exls)) {
1700		if (mchtype != NULL)
1701			*mchtype = PM_NONE;
1702		found = FALSE;
1703	}
1704	if (found && pos != NULL)
1705		*pos = i;
1706
1707	if (IS_SET(flags, RSFLG_IGNORE_CASE))
1708		free(uc_name);
1709	free(retry);
1710	return (found);
1711}
1712
1713/*
1714 * Read the specified amount data into the buffer.  Detects EOT or EOF
1715 * during read.
1716 *
1717 * Returns the number of bytes actually read.  On error returns -1.
1718 */
1719static int
1720input_mem(int l,
1721    int d,
1722    tlm_cmd_t *lcmds,
1723    char *mem,
1724    int len)
1725{
1726	int err;
1727	int toread, actual_size, rec_size;
1728	char *rec;
1729
1730	if (l <= 0 || d <= 0 || !lcmds || !mem) {
1731		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1732		return (-1);
1733	}
1734
1735	toread = len;
1736	while (toread > 0) {
1737		rec = get_read_buffer(toread, &err, &actual_size, lcmds);
1738		if (actual_size <= 0) {
1739			NDMP_LOG(LOG_DEBUG, "err %d act_size %d detected",
1740			    err, actual_size);
1741			break;
1742		} else if (err) {
1743			NDMP_LOG(LOG_DEBUG, "error %d reading data", err);
1744			return (-1);
1745		}
1746		rec_size = min(actual_size, toread);
1747		(void) memcpy(mem, rec, rec_size);
1748		mem += rec_size;
1749		toread -= rec_size;
1750	}
1751
1752	return (len - toread);
1753}
1754
1755/*
1756 * pick up the name and size of a HUGE file
1757 */
1758static	int
1759get_humongus_file_header(int lib,
1760    int	drv,
1761    long recsize,
1762    longlong_t *size,
1763    char *name,
1764    tlm_cmd_t *local_commands)
1765{
1766	char *p_record, *value;
1767	int rv;
1768
1769	NDMP_LOG(LOG_DEBUG, "HUGE Record found: %d", recsize);
1770
1771	rv = 0;
1772	if (recsize == 0) {
1773		/*
1774		 * The humongus_file_header was written in a
1775		 * RECORDSIZE block and the header.size field of this
1776		 * record was 0 before this fix.  For backward compatiblity
1777		 * read only one RECORDSIZE-size block if the header.size
1778		 * field is 0.  Otherwise the header.size field should show
1779		 * the length of the data of this header.
1780		 */
1781		NDMP_LOG(LOG_DEBUG, "Old HUGE record found");
1782		recsize = RECORDSIZE;
1783	}
1784
1785	if (input_mem(lib, drv, local_commands, name, recsize) != recsize) {
1786		rv = -1;
1787		*size = 0;
1788		*name = '\0';
1789		NDMP_LOG(LOG_DEBUG, "Error reading a HUGE file name");
1790	} else {
1791		NDMP_LOG(LOG_DEBUG, "HUGE [%s]", name);
1792
1793		p_record = name;
1794		value = parse(&p_record, " ");
1795		*size = atoll(value);
1796		/*
1797		 * Note: Since the backed up names are not longer than
1798		 * NAME_MAX and the buffer passed to us is
1799		 * TLM_MAX_PATH_NAME, it should be safe to use strlcpy
1800		 * without check on the buffer size.
1801		 */
1802		(void) strlcpy(name, p_record, TLM_MAX_PATH_NAME);
1803	}
1804
1805	NDMP_LOG(LOG_DEBUG, "HUGE Record %lld [%s]", *size, name);
1806
1807	return (rv);
1808}
1809
1810/*
1811 * pick up the long name from the special tape file
1812 */
1813static int
1814get_long_name(int lib,
1815    int drv,
1816    long recsize,
1817    char *name,
1818    long *buf_spot,
1819    tlm_cmd_t *local_commands)
1820{
1821	int nread;
1822
1823	NDMP_LOG(LOG_DEBUG, "LONGNAME Record found rs %d bs %d", recsize,
1824	    *buf_spot);
1825
1826	if (*buf_spot < 0)
1827		*buf_spot = 0;
1828
1829	nread = input_mem(lib, drv, local_commands, name + *buf_spot,
1830	    recsize);
1831	if (nread < 0) {
1832		nread = recsize; /* return 0 as size left */
1833		name[*buf_spot] = '\0';
1834		NDMP_LOG(LOG_ERR, "Error %d reading a long file name %s.",
1835		    nread, name);
1836	} else {
1837		*buf_spot += nread;
1838		name[*buf_spot] = '\0';
1839		NDMP_LOG(LOG_DEBUG, "LONGNAME [%s]", name);
1840	}
1841
1842	return (recsize - nread);
1843}
1844
1845/*
1846 * create a new directory
1847 */
1848static int
1849create_directory(char *dir, tlm_job_stats_t *job_stats)
1850{
1851	struct stat64 attr;
1852	char	*p;
1853	char	temp;
1854	int	erc;
1855
1856	/*
1857	 * Make sure all directories in this path exist, create them if
1858	 * needed.
1859	 */
1860	NDMP_LOG(LOG_DEBUG, "new dir[%s]", dir);
1861
1862	erc = 0;
1863	p = &dir[1];
1864	do {
1865		temp = *p;
1866		if (temp == '/' || temp == 0) {
1867			*p = 0;
1868			if (stat64(dir, &attr) < 0) {
1869				if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
1870					erc = errno;
1871					job_stats->js_errors++;
1872					NDMP_LOG(LOG_DEBUG,
1873					    "Could not create directory %s: %d",
1874					    dir, errno);
1875					break;
1876				}
1877			}
1878			*p = temp;
1879		}
1880		p++;
1881	} while (temp != 0);
1882
1883	return (erc);
1884}
1885
1886/*
1887 * create a new hardlink
1888 */
1889static int
1890create_hard_link(char *name_old, char *name_new,
1891    tlm_acls_t *acls, tlm_job_stats_t *job_stats)
1892{
1893	int erc;
1894
1895	erc = mkbasedir(name_new);
1896	if (erc != 0)
1897		return (erc);
1898
1899	if (link(name_old, name_new) != 0)
1900		erc = errno;
1901
1902	if (erc) {
1903		/* Nothing to do if the destination already exists */
1904		if (erc == EEXIST)
1905			return (0);
1906		job_stats->js_errors++;
1907		NDMP_LOG(LOG_DEBUG, "error %d (errno %d) hardlink [%s] to [%s]",
1908		    erc, errno, name_new, name_old);
1909		return (erc);
1910	}
1911	return (set_acl(name_new, acls));
1912}
1913
1914/*
1915 * create a new symlink
1916 */
1917/*ARGSUSED*/
1918static int
1919create_sym_link(char *dst, char *target, tlm_acls_t *acls,
1920    tlm_job_stats_t *job_stats)
1921{
1922	int erc;
1923	struct stat64 *st;
1924
1925	erc = mkbasedir(dst);
1926	if (erc != 0)
1927		return (erc);
1928
1929	st = &acls->acl_attr;
1930	if (symlink(target, dst) != 0) {
1931		erc = errno;
1932		job_stats->js_errors++;
1933		NDMP_LOG(LOG_DEBUG, "error %d softlink [%s] to [%s]",
1934		    errno, dst, target);
1935	} else {
1936		st->st_mode |= S_IFLNK;
1937		erc = set_acl(dst, acls);
1938	}
1939
1940	return (erc);
1941}
1942
1943/*
1944 * create a new FIFO, char/block device special files
1945 */
1946static int
1947create_special(char flag, char *name, tlm_acls_t *acls, int major, int minor,
1948    tlm_job_stats_t *job_stats)
1949{
1950	dev_t dev;
1951	mode_t mode;
1952
1953	switch (flag) {
1954	case LF_CHR:
1955		mode = S_IFCHR;
1956		dev = makedev(major, minor);
1957		break;
1958	case LF_BLK:
1959		mode = S_IFBLK;
1960		dev = makedev(major, minor);
1961		break;
1962	case LF_FIFO:
1963		mode = S_IFIFO;
1964		dev = 0;
1965		break;
1966	default:
1967		NDMP_LOG(LOG_ERR, "unsupported flag %d", flag);
1968		return (-1);
1969	}
1970
1971	/* Remove the old entry first */
1972	if (rmdir(name) < 0) {
1973		if (errno == ENOTDIR)
1974			(void) unlink(name);
1975	}
1976	if (mknod(name, 0777 | mode, dev) != 0) {
1977		job_stats->js_errors++;
1978		NDMP_LOG(LOG_DEBUG, "error %d mknod [%s] major"
1979		    " %d minor %d", errno, name, major, minor);
1980		return (errno);
1981	}
1982	return (set_acl(name, acls));
1983}
1984
1985/*
1986 * read in the ACLs for the next file
1987 */
1988static long
1989load_acl_info(int lib,
1990    int drv,
1991    long file_size,
1992    tlm_acls_t *acls,
1993    long *acl_spot,
1994    tlm_cmd_t *local_commands)
1995{
1996	char *bp;
1997	int nread;
1998
1999	/*
2000	 * If the ACL is spanned on tapes, then the acl_spot should NOT be
2001	 * 0 on next calls to this function to read the rest of the ACL
2002	 * on next tapes.
2003	 */
2004	if (*acl_spot == 0) {
2005		(void) memset(acls, 0, sizeof (tlm_acls_t));
2006	}
2007
2008	bp = ((char *)&acls->acl_info) + *acl_spot;
2009	nread = input_mem(lib, drv, local_commands, (void *)bp, file_size);
2010	if (nread < 0) {
2011		*acl_spot = 0;
2012		(void) memset(acls, 0, sizeof (tlm_acls_t));
2013		NDMP_LOG(LOG_DEBUG, "Error reading ACL data");
2014		return (0);
2015	}
2016	*acl_spot += nread;
2017	acls->acl_non_trivial = TRUE;
2018
2019	return (file_size - nread);
2020}
2021
2022static int
2023ndmp_set_eprivs_least(void)
2024{
2025	priv_set_t *priv_set;
2026
2027	if ((priv_set = priv_allocset()) == NULL) {
2028		NDMP_LOG(LOG_ERR, "Out of memory.");
2029		return (-1);
2030	}
2031
2032	priv_basicset(priv_set);
2033
2034	(void) priv_addset(priv_set, PRIV_PROC_AUDIT);
2035	(void) priv_addset(priv_set, PRIV_PROC_SETID);
2036	(void) priv_addset(priv_set, PRIV_PROC_OWNER);
2037	(void) priv_addset(priv_set, PRIV_FILE_CHOWN);
2038	(void) priv_addset(priv_set, PRIV_FILE_CHOWN_SELF);
2039	(void) priv_addset(priv_set, PRIV_FILE_DAC_READ);
2040	(void) priv_addset(priv_set, PRIV_FILE_DAC_SEARCH);
2041	(void) priv_addset(priv_set, PRIV_FILE_DAC_WRITE);
2042	(void) priv_addset(priv_set, PRIV_FILE_OWNER);
2043	(void) priv_addset(priv_set, PRIV_FILE_SETID);
2044	(void) priv_addset(priv_set, PRIV_SYS_LINKDIR);
2045	(void) priv_addset(priv_set, PRIV_SYS_DEVICES);
2046	(void) priv_addset(priv_set, PRIV_SYS_MOUNT);
2047	(void) priv_addset(priv_set, PRIV_SYS_CONFIG);
2048
2049	if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) == -1) {
2050		NDMP_LOG(LOG_ERR, "Additional privileges required.");
2051		priv_freeset(priv_set);
2052		return (-1);
2053	}
2054	priv_freeset(priv_set);
2055	return (0);
2056}
2057
2058static int
2059ndmp_set_eprivs_all(void)
2060{
2061	priv_set_t *priv_set;
2062
2063	if ((priv_set = priv_allocset()) == NULL) {
2064		NDMP_LOG(LOG_ERR, "Out of memory.");
2065		return (-1);
2066	}
2067
2068	priv_fillset(priv_set);
2069
2070	if (setppriv(PRIV_SET, PRIV_EFFECTIVE, priv_set) != 0) {
2071		NDMP_LOG(LOG_ERR, "Additional privileges required.");
2072		return (-1);
2073	}
2074	priv_freeset(priv_set);
2075	return (0);
2076}
2077
2078/*
2079 * Set the standard attributes of the file
2080 */
2081static int
2082set_attr(char *name, tlm_acls_t *acls)
2083{
2084	struct utimbuf tbuf;
2085	boolean_t priv_all = FALSE;
2086	struct stat64 *st;
2087	uid_t uid;
2088	gid_t gid;
2089	struct passwd *pwd;
2090	struct group *grp;
2091	int erc = 0;
2092
2093
2094	if (!name || !acls)
2095		return (0);
2096
2097	st = &acls->acl_attr;
2098	NDMP_LOG(LOG_DEBUG, "set_attr: %s uid %d gid %d uname %s gname %s "
2099	    "mode %o", name, st->st_uid, st->st_gid, acls->uname, acls->gname,
2100	    st->st_mode);
2101
2102	uid = st->st_uid;
2103	if ((pwd = getpwnam(acls->uname)) != NULL) {
2104		NDMP_LOG(LOG_DEBUG, "set_attr: new uid %d old %d",
2105		    pwd->pw_uid, uid);
2106		uid = pwd->pw_uid;
2107	}
2108
2109	gid = st->st_gid;
2110	if ((grp = getgrnam(acls->gname)) != NULL) {
2111		NDMP_LOG(LOG_DEBUG, "set_attr: new gid %d old %d",
2112		    grp->gr_gid, gid);
2113		gid = grp->gr_gid;
2114	}
2115
2116	erc = lchown(name, uid, gid);
2117	if (erc != 0) {
2118		erc = errno;
2119		NDMP_LOG(LOG_ERR,
2120		    "Could not set uid or/and gid for file %s.", name);
2121	}
2122
2123	if ((st->st_mode & (S_ISUID | S_ISGID)) != 0) {
2124		/*
2125		 * Change effective privileges to 'all' which is required to
2126		 * change setuid bit for 'root' owned files. If fails, just
2127		 * send error to log file and proceed.
2128		 */
2129		if (ndmp_set_eprivs_all()) {
2130			NDMP_LOG(LOG_ERR,
2131			    "Could not set effective privileges to 'all'.");
2132		} else {
2133			priv_all = TRUE;
2134		}
2135	}
2136
2137	if (!S_ISLNK(st->st_mode)) {
2138		erc = chmod(name, st->st_mode);
2139		if (erc != 0) {
2140			erc = errno;
2141			NDMP_LOG(LOG_ERR, "Could not set correct file"
2142			    " permission for file %s: %d", name, errno);
2143		}
2144
2145		tbuf.modtime = st->st_mtime;
2146		tbuf.actime = st->st_atime;
2147		(void) utime(name, &tbuf);
2148	}
2149
2150	if (priv_all == TRUE) {
2151		/*
2152		 * Give up the 'all' privileges for effective sets and go back
2153		 * to least required privileges. If fails, just send error to
2154		 * log file and proceed.
2155		 */
2156		if (ndmp_set_eprivs_least())
2157			NDMP_LOG(LOG_ERR,
2158			    "Could not set least required privileges.");
2159	}
2160
2161	return (erc);
2162}
2163
2164/*
2165 * Set the ACL info for the file
2166 */
2167static int
2168set_acl(char *name, tlm_acls_t *acls)
2169{
2170	int erc;
2171	acl_t *aclp = NULL;
2172
2173	if (name)
2174		NDMP_LOG(LOG_DEBUG, "set_acl: %s", name);
2175	if (acls == NULL)
2176		return (0);
2177
2178	/* Need a place to save real modification time */
2179
2180	erc = set_attr(name, acls);
2181	if (ERROR_IS_FATAL(erc))
2182		return (erc);
2183
2184	if (!acls->acl_non_trivial) {
2185		(void) memset(acls, 0, sizeof (tlm_acls_t));
2186		NDMP_LOG(LOG_DEBUG, "set_acl: skipping trivial");
2187		return (erc);
2188	}
2189
2190	erc = acl_fromtext(acls->acl_info.attr_info, &aclp);
2191	if (erc != 0) {
2192		NDMP_LOG(LOG_DEBUG,
2193		    "TAPE RESTORE> acl_fromtext errno %d", erc);
2194	}
2195	if (aclp) {
2196		erc = acl_set(name, aclp);
2197		if (erc < 0) {
2198			erc = errno;
2199			NDMP_LOG(LOG_DEBUG,
2200			    "TAPE RESTORE> acl_set errno %d", errno);
2201		}
2202		acl_free(aclp);
2203	}
2204	(void) memset(acls, 0, sizeof (tlm_acls_t));
2205	return (erc);
2206}
2207
2208/*
2209 * a wrapper to tlm_get_read_buffer so that
2210 * we can cleanly detect ABORT commands
2211 * without involving the TLM library with
2212 * our problems.
2213 */
2214static char *
2215get_read_buffer(int want,
2216    int	*error,
2217    int	*actual_size,
2218    tlm_cmd_t *local_commands)
2219{
2220	while (local_commands->tc_writer == TLM_RESTORE_RUN) {
2221		char	*rec;
2222		rec = tlm_get_read_buffer(want, error,
2223		    local_commands->tc_buffers, actual_size);
2224		if (rec != 0) {
2225			return (rec);
2226		}
2227	}
2228
2229	/*
2230	 * the job is ending, give Writer a buffer that will never be read ...
2231	 * it does not matter anyhow, we are aborting.
2232	 */
2233	*actual_size = RECORDSIZE;
2234	return (NULL);
2235}
2236
2237/*
2238 * Enable wildcard for restore options
2239 */
2240static boolean_t
2241wildcard_enabled(void)
2242{
2243	char *cp;
2244
2245	cp = ndmpd_get_prop_default(NDMP_RESTORE_WILDCARD_ENABLE, "n");
2246	return ((toupper(*cp) == 'Y') ? TRUE : FALSE);
2247}
2248
2249
2250/*
2251 * Concatenate two names
2252 */
2253/*ARGSUSED*/
2254static char *
2255catnames(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2256{
2257	char *rv;
2258
2259	rv = NULL;
2260	if (!buf) {
2261		NDMP_LOG(LOG_DEBUG, "buf is NULL");
2262	} else if (!path) {
2263		NDMP_LOG(LOG_DEBUG, "path is NULL");
2264	} else if (!rnp->rn_nlp) {
2265		NDMP_LOG(LOG_DEBUG, "rn_nlp is NULL [%s]", path);
2266	} else if (!tlm_cat_path(buf, rnp->rn_nlp, path)) {
2267		NDMP_LOG(LOG_DEBUG, "Path too long [%s][%s]",
2268		    rnp->rn_nlp, path);
2269	} else
2270		rv = buf;
2271
2272	return (rv);
2273}
2274
2275
2276/*
2277 * Create a new name path for restore
2278 */
2279static char *
2280rs_new_name(struct rs_name_maker *rnp, char *buf, int pos, char *path)
2281{
2282	if (!rnp || !rnp->rn_fp)
2283		return (NULL);
2284
2285	return (*rnp->rn_fp)(rnp, buf, pos, path);
2286}
2287
2288/*
2289 * Clear the extra "/" in the tar header if exists
2290 */
2291static void
2292rs_create_new_bkpath(char *bk_path, char *path, char *pbuf)
2293{
2294	char *p, *slashp;
2295
2296	if ((p = strstr(path, bk_path)) == NULL) {
2297		(void) strlcpy(pbuf, path, TLM_MAX_PATH_NAME);
2298		return;
2299	}
2300	if (*(p += strlen(bk_path)) == '/')
2301		p++;
2302
2303	slashp = bk_path + strlen(bk_path) - 1;
2304	if (*slashp == '/')
2305		(void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s%s", bk_path, p);
2306	else
2307		(void) snprintf(pbuf, TLM_MAX_PATH_NAME, "%s/%s", bk_path, p);
2308
2309	NDMP_LOG(LOG_DEBUG, "old path [%s] new path [%s]", path, pbuf);
2310}
2311
2312
2313/*
2314 * Iterate over ZFS metadata stored in the backup stream and use the callback
2315 * to restore it.
2316 */
2317int
2318ndmp_iter_zfs(ndmp_context_t *nctx, int (*np_restore_property)(nvlist_t *,
2319    void *), void *ptr)
2320{
2321	tlm_commands_t *cmds;
2322	ndmp_metadata_header_t *mhp;
2323	ndmp_metadata_header_ext_t *mhpx;
2324	ndmp_metadata_property_t *mpp;
2325	ndmp_metadata_property_ext_t *mppx;
2326	tlm_cmd_t *lcmd;
2327	int actual_size;
2328	nvlist_t *nvl;
2329	nvlist_t *valp;
2330	nvpair_t *nvp = NULL;
2331	char plname[100];
2332	char *mhbuf, *pp, *tp;
2333	int rv, i;
2334	int size, lsize, sz;
2335	int align = RECORDSIZE - 1;
2336
2337	if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2338		return (-1);
2339
2340	nctx->nc_plname = plname;
2341	if ((lcmd = cmds->tcs_command) == NULL ||
2342	    lcmd->tc_buffers == NULL)
2343		return (-1);
2344
2345	/* Default minimum bytes needed */
2346	size = sizeof (ndmp_metadata_header_t) +
2347	    ZFS_MAX_PROPS * sizeof (ndmp_metadata_property_t);
2348	size += align;
2349	size &= ~align;
2350
2351	if ((mhbuf = malloc(size)) == NULL)
2352		return (-1);
2353
2354	/* LINTED improper alignment */
2355	while ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2356	    &actual_size, lcmd)) != NULL) {
2357		pp = mhbuf;
2358
2359		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2360		    sizeof (mhp->nh_magic)) != 0 &&
2361		    strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2362		    sizeof (mhp->nh_magic)) != 0) {
2363			/* No more metadata */
2364			tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2365			free(mhbuf);
2366			return (0);
2367		}
2368
2369		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2370		    sizeof (mhp->nh_magic)) == 0) {
2371			mhpx = (ndmp_metadata_header_ext_t *)mhp;
2372			if (mhpx->nh_total_bytes > size) {
2373				if ((pp = realloc(mhbuf, mhpx->nh_total_bytes))
2374				    == NULL) {
2375					free(mhbuf);
2376					return (-1);
2377				}
2378				mhbuf = pp;
2379			}
2380			size = mhpx->nh_total_bytes;
2381		}
2382
2383		(void) memcpy(pp, (char *)mhp, (actual_size < size) ?
2384		    actual_size : size);
2385		pp += (actual_size < size) ? actual_size : size;
2386
2387		sz = actual_size;
2388		while (sz < size &&
2389		    ((tp = get_read_buffer(size - sz, &rv, &lsize,
2390		    lcmd))) != NULL) {
2391			(void) memcpy(pp, tp, lsize);
2392			sz += lsize;
2393			pp += lsize;
2394		}
2395		if (sz > size) {
2396			tlm_unget_read_buffer(lcmd->tc_buffers, sz - size);
2397		}
2398
2399		/* LINTED improper alignment */
2400		mhp = (ndmp_metadata_header_t *)mhbuf;
2401
2402		nvl = NULL;
2403		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC_EXT,
2404		    sizeof (mhp->nh_magic)) == 0) {
2405			/* New metadata format */
2406			/* LINTED improper alignment */
2407			mhpx = (ndmp_metadata_header_ext_t *)mhbuf;
2408
2409			if (mhpx->nh_major > META_HDR_MAJOR_VERSION) {
2410				/* Major header mismatch */
2411				NDMP_LOG(LOG_ERR, "metadata header mismatch",
2412				    "M%d != M%d", mhpx->nh_major,
2413				    META_HDR_MAJOR_VERSION);
2414				free(mhbuf);
2415				return (-1);
2416			}
2417			if (mhpx->nh_major == META_HDR_MAJOR_VERSION &&
2418			    mhpx->nh_minor > META_HDR_MINOR_VERSION) {
2419				/* Minor header mismatch */
2420				NDMP_LOG(LOG_ERR, "Warning:"
2421				    "metadata header mismatch m%d != m%d",
2422				    mhpx->nh_minor,
2423				    META_HDR_MINOR_VERSION);
2424				continue;
2425			}
2426
2427			nctx->nc_plversion = mhpx->nh_plversion;
2428			(void) strlcpy(plname, mhpx->nh_plname,
2429			    sizeof (plname));
2430
2431			if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
2432				goto nvlist_err;
2433
2434			mppx = &mhpx->nh_property[0];
2435			for (i = 0; i < mhpx->nh_count && mppx; i++, mppx++) {
2436				if (!*mppx->mp_name)
2437					continue;
2438				valp = NULL;
2439				if (nvlist_alloc(&valp,
2440				    NV_UNIQUE_NAME, 0) != 0 ||
2441				    nvlist_add_string(valp, "value",
2442				    mppx->mp_value) != 0 ||
2443				    nvlist_add_string(valp, "source",
2444				    mppx->mp_source) != 0 ||
2445				    nvlist_add_nvlist(nvl, mppx->mp_name,
2446				    valp) != 0) {
2447					nvlist_free(valp);
2448					goto nvlist_err;
2449				}
2450				nvlist_free(valp);
2451			}
2452		} else {
2453			nctx->nc_plversion = mhp->nh_plversion;
2454			(void) strlcpy(plname, mhp->nh_plname,
2455			    sizeof (plname));
2456
2457			if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0)
2458				goto nvlist_err;
2459
2460			mpp = &mhp->nh_property[0];
2461			for (i = 0; i < mhp->nh_count && mpp; i++, mpp++) {
2462				if (!*mpp->mp_name)
2463					continue;
2464				valp = NULL;
2465				if (nvlist_alloc(&valp,
2466				    NV_UNIQUE_NAME, 0) != 0 ||
2467				    nvlist_add_string(valp, "value",
2468				    mpp->mp_value) != 0 ||
2469				    nvlist_add_string(valp, "source",
2470				    mpp->mp_source) != 0 ||
2471				    nvlist_add_nvlist(nvl, mpp->mp_name,
2472				    valp) != 0) {
2473					nvlist_free(valp);
2474					goto nvlist_err;
2475				}
2476				nvlist_free(valp);
2477			}
2478		}
2479
2480		if (np_restore_property(nvl, ptr) != 0)
2481			goto nvlist_err;
2482
2483		while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL &&
2484		    nvpair_value_nvlist(nvp, &valp) == 0) {
2485			nvlist_free(valp);
2486		}
2487		nvlist_free(nvl);
2488	}
2489
2490	free(mhbuf);
2491	return (0);
2492
2493nvlist_err:
2494	free(mhbuf);
2495
2496	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL &&
2497	    nvpair_value_nvlist(nvp, &valp) == 0) {
2498		nvlist_free(valp);
2499	}
2500	nvlist_free(nvl);
2501	return (-1);
2502}
2503
2504/*
2505 * Returns the version number of the plugin which created the metadata
2506 */
2507uint_t
2508ndmp_context_get_version(ndmp_context_t *nctx)
2509{
2510	tlm_commands_t *cmds;
2511	ndmp_metadata_header_t *mhp;
2512	tlm_cmd_t *lcmd;
2513	int actual_size;
2514	int rv;
2515	int size;
2516	int align = RECORDSIZE - 1;
2517
2518	if (nctx == NULL || (cmds = (tlm_commands_t *)nctx->nc_cmds) == NULL)
2519		return (0);
2520
2521	if ((lcmd = cmds->tcs_command) == NULL ||
2522	    lcmd->tc_buffers == NULL)
2523		return (0);
2524
2525	size = sizeof (ndmp_metadata_header_t);
2526	size += align;
2527	size &= ~align;
2528
2529	/* LINTED improper alignment */
2530	if ((mhp = (ndmp_metadata_header_t *)get_read_buffer(size, &rv,
2531	    &actual_size, lcmd)) != NULL) {
2532		if (strncmp(mhp->nh_magic, ZFS_META_MAGIC,
2533		    sizeof (mhp->nh_magic)) != 0) {
2534			/* No more metadata */
2535			tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2536			return (0);
2537		}
2538
2539		nctx->nc_plversion = mhp->nh_plversion;
2540		tlm_unget_read_buffer(lcmd->tc_buffers, actual_size);
2541	}
2542
2543	return (nctx->nc_plversion);
2544}
2545