12654012fSReza Sabdar /*
25181c2afSReza Sabdar  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
32efb3bf9SJan Kryl  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
42654012fSReza Sabdar  */
52654012fSReza Sabdar 
62654012fSReza Sabdar /*
72654012fSReza Sabdar  * BSD 3 Clause License
82654012fSReza Sabdar  *
92654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
102654012fSReza Sabdar  *
112654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
122654012fSReza Sabdar  * modification, are permitted provided that the following conditions
132654012fSReza Sabdar  * are met:
14*82049ff5SToomas Soome  *	- Redistributions of source code must retain the above copyright
152654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
162654012fSReza Sabdar  *
17*82049ff5SToomas Soome  *	- Redistributions in binary form must reproduce the above copyright
182654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
192654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
202654012fSReza Sabdar  *	  distribution.
212654012fSReza Sabdar  *
222654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
232654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
242654012fSReza Sabdar  *	  products derived from this software without specific prior written
252654012fSReza Sabdar  *	  permission.
262654012fSReza Sabdar  *
372654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
382654012fSReza Sabdar  */
392654012fSReza Sabdar #include <stdlib.h>
402654012fSReza Sabdar #include <ctype.h>
412654012fSReza Sabdar #include <stdio.h>
422654012fSReza Sabdar #include <limits.h>
432654012fSReza Sabdar #include <string.h>
442654012fSReza Sabdar #include <time.h>
452654012fSReza Sabdar #include <sys/types.h>
462654012fSReza Sabdar #include <sys/acl.h>
475181c2afSReza Sabdar #include <sys/mkdev.h>
482654012fSReza Sabdar #include <utime.h>
492654012fSReza Sabdar #include <unistd.h>
502654012fSReza Sabdar #include <pthread.h>
512654012fSReza Sabdar #include <archives.h>
522654012fSReza Sabdar #include <priv.h>
532654012fSReza Sabdar #include <tlm.h>
542654012fSReza Sabdar #include <libzfs.h>
55b6b15642SReza Sabdar #include <pwd.h>
56b6b15642SReza Sabdar #include <grp.h>
572654012fSReza Sabdar #include <ndmpd_prop.h>
582654012fSReza Sabdar #include "tlm_proto.h"
592654012fSReza Sabdar 
602654012fSReza Sabdar 
612654012fSReza Sabdar #define	PM_EXACT_OR_CHILD(m)	((m) == PM_EXACT || (m) == PM_CHILD)
622efb3bf9SJan Kryl #define	ERROR_IS_FATAL(err)	((err) == ENOSPC || (err) == EDQUOT)
632654012fSReza Sabdar 
642654012fSReza Sabdar typedef boolean_t name_match_fp_t(char *s, char *t);
652654012fSReza Sabdar 
662efb3bf9SJan Kryl static int set_acl(char *name, tlm_acls_t *acls);
672efb3bf9SJan Kryl static int restore_file(int *fp,
682654012fSReza Sabdar     char *real_name,
692654012fSReza Sabdar     long size,
702654012fSReza Sabdar     longlong_t huge_size,
712654012fSReza Sabdar     tlm_acls_t *,
722654012fSReza Sabdar     boolean_t want_this_file,
732654012fSReza Sabdar     tlm_cmd_t *,
742efb3bf9SJan Kryl     tlm_job_stats_t *,
752efb3bf9SJan Kryl     long *);
762654012fSReza Sabdar static long restore_xattr_hdr(int *fp,
772654012fSReza Sabdar     char *name,
782654012fSReza Sabdar     char *fname,
792654012fSReza Sabdar     long size,
802654012fSReza Sabdar     tlm_acls_t *acls,
812654012fSReza Sabdar     tlm_cmd_t *local_commands,
822654012fSReza Sabdar     tlm_job_stats_t *job_stats);
832654012fSReza Sabdar static int get_long_name(int lib,
842654012fSReza Sabdar     int drv,
852654012fSReza Sabdar     long recsize,
862654012fSReza Sabdar     char *name,
872654012fSReza Sabdar     long *buf_spot,
882654012fSReza Sabdar     tlm_cmd_t *local_commands);
892654012fSReza Sabdar static int get_humongus_file_header(int lib,
902654012fSReza Sabdar     int	drv,
912654012fSReza Sabdar     long recsize,
922654012fSReza Sabdar     longlong_t *size,
932654012fSReza Sabdar     char *name,
942654012fSReza Sabdar     tlm_cmd_t *);
952654012fSReza Sabdar static int create_directory(char *dir,
962654012fSReza Sabdar     tlm_job_stats_t *);
972654012fSReza Sabdar static int create_hard_link(char *name,
982654012fSReza Sabdar     char *link,
992654012fSReza Sabdar     tlm_acls_t *,
1002654012fSReza Sabdar     tlm_job_stats_t *);
1012654012fSReza Sabdar static int create_sym_link(char *dst,
1022654012fSReza Sabdar     char *target,
1032654012fSReza Sabdar     tlm_acls_t *,
1042654012fSReza Sabdar     tlm_job_stats_t *);
1055181c2afSReza Sabdar static int create_special(char,
1065181c2afSReza Sabdar     char *name,
1075181c2afSReza Sabdar     tlm_acls_t *,
1085181c2afSReza Sabdar     int,
1095181c2afSReza Sabdar     int,
1105181c2afSReza Sabdar     tlm_job_stats_t *);
1112654012fSReza Sabdar static long load_acl_info(int lib,
1122654012fSReza Sabdar     int	drv,
1132654012fSReza Sabdar     long size,
1142654012fSReza Sabdar     tlm_acls_t *,
1152654012fSReza Sabdar     long *acl_spot,
1162654012fSReza Sabdar     tlm_cmd_t *);
1172654012fSReza Sabdar static char *get_read_buffer(int want,
1182654012fSReza Sabdar     int	*error,
1192654012fSReza Sabdar     int	*actual_size,
1202654012fSReza Sabdar     tlm_cmd_t *);
1212654012fSReza Sabdar static boolean_t wildcard_enabled(void);
1222654012fSReza Sabdar static boolean_t is_file_wanted(char *name,
1232654012fSReza Sabdar     char **sels,
1242654012fSReza Sabdar     char **exls,
1252654012fSReza Sabdar     int	flags,
1262654012fSReza Sabdar     int	*mchtype,
1272654012fSReza Sabdar     int	*pos);
1282654012fSReza Sabdar static char *catnames(struct rs_name_maker *rnp,
1292654012fSReza Sabdar     char *buf,
1302654012fSReza Sabdar     int	pos,
1312654012fSReza Sabdar     char *path);
1322654012fSReza Sabdar 
1332654012fSReza Sabdar static char *rs_new_name(struct rs_name_maker *rnp,
1342654012fSReza Sabdar     char *real_name,
1352654012fSReza Sabdar     int pos,
1362654012fSReza Sabdar     char *path);
1372654012fSReza Sabdar 
138fb4eb4e8SReza Sabdar static void rs_create_new_bkpath(char *bk_path,
139fb4eb4e8SReza Sabdar     char *path,
140fb4eb4e8SReza Sabdar     char *pbuf);
141fb4eb4e8SReza Sabdar 
1422654012fSReza Sabdar typedef struct stack_ent {
1432654012fSReza Sabdar 	char *se_name;
1442654012fSReza Sabdar 	tlm_acls_t se_acls;
1452654012fSReza Sabdar } stack_ent_t;
1462654012fSReza Sabdar 
1472654012fSReza Sabdar 
1482654012fSReza Sabdar /*
1492654012fSReza Sabdar  * dtree_push
1502654012fSReza Sabdar  */
1512654012fSReza Sabdar int
dtree_push(cstack_t * stp,char * nmp,tlm_acls_t * acls)1522654012fSReza Sabdar dtree_push(cstack_t *stp, char *nmp, tlm_acls_t *acls)
1532654012fSReza Sabdar {
1542654012fSReza Sabdar 	int len;
1552654012fSReza Sabdar 	stack_ent_t *sp;
1562654012fSReza Sabdar 
1572654012fSReza Sabdar 	sp = ndmp_malloc(sizeof (stack_ent_t));
1582654012fSReza Sabdar 	if (!sp || !nmp || !acls) {
1592654012fSReza Sabdar 		free(sp);
1602654012fSReza Sabdar 		return (-1);
1612654012fSReza Sabdar 	}
1622654012fSReza Sabdar 
1632654012fSReza Sabdar 	len = strlen(nmp) + 1;
1642654012fSReza Sabdar 	sp->se_name = ndmp_malloc(len);
1652654012fSReza Sabdar 	if (!sp->se_name) {
1662654012fSReza Sabdar 		free(sp);
1672654012fSReza Sabdar 		return (-1);
1682654012fSReza Sabdar 	}
1692654012fSReza Sabdar 
1702654012fSReza Sabdar 	(void) strlcpy(sp->se_name, nmp, len);
1712654012fSReza Sabdar 	(void) memcpy(&sp->se_acls, acls, sizeof (*acls));
17286c48bbfSReza Sabdar 	(void) memset(acls, 0, sizeof (tlm_acls_t));
1732654012fSReza Sabdar 
1742654012fSReza Sabdar 	return (cstack_push(stp, (void *)sp, sizeof (*sp)));
1752654012fSReza Sabdar }
1762654012fSReza Sabdar 
1772654012fSReza Sabdar /*
1782654012fSReza Sabdar  * dtree_pop
1792654012fSReza Sabdar  */
1802654012fSReza Sabdar int
dtree_pop(cstack_t * stp)1812654012fSReza Sabdar dtree_pop(cstack_t *stp)
1822654012fSReza Sabdar {
1832654012fSReza Sabdar 	int err;
1842654012fSReza Sabdar 	stack_ent_t *sp;
1852654012fSReza Sabdar 
1862654012fSReza Sabdar 	err = cstack_pop(stp, (void **)&sp, (void *)NULL);
1872654012fSReza Sabdar 	if (err)
1882654012fSReza Sabdar 		return (-1);
1892654012fSReza Sabdar 
1902efb3bf9SJan Kryl 	err = set_acl(sp->se_name, &sp->se_acls);
1912654012fSReza Sabdar 
1922654012fSReza Sabdar 	free(sp->se_name);
1932654012fSReza Sabdar 	free(sp);
1942654012fSReza Sabdar 	return (err);
1952654012fSReza Sabdar }
1962654012fSReza Sabdar 
1972654012fSReza Sabdar 
1982654012fSReza Sabdar /*
1992654012fSReza Sabdar  * dtree_peek
2002654012fSReza Sabdar  */
2012654012fSReza Sabdar char *
dtree_peek(cstack_t * stp)2022654012fSReza Sabdar dtree_peek(cstack_t *stp)
2032654012fSReza Sabdar {
2042654012fSReza Sabdar 	int err;
2052654012fSReza Sabdar 	stack_ent_t *sp;
2062654012fSReza Sabdar 
2072654012fSReza Sabdar 	err = cstack_top(stp, (void **)&sp, (void *)NULL);
2082654012fSReza Sabdar 	if (err)
2092654012fSReza Sabdar 		return (NULL);
2102654012fSReza Sabdar 
2112654012fSReza Sabdar 	return (sp->se_name);
2122654012fSReza Sabdar }
2132654012fSReza Sabdar 
2142654012fSReza Sabdar /*
2152654012fSReza Sabdar  * NBU and EBS may not send us the correct file list containing hardlinks
2162654012fSReza Sabdar  * during a DAR restore, e.g. they appear always send the first name
2172654012fSReza Sabdar  * associated with an inode, even if other link names were
2182654012fSReza Sabdar  * selected for the restore.  As a workaround, we use the file name entry
2192654012fSReza Sabdar  * in sels[] (ignore the name in the tar header) as restore target.
2202654012fSReza Sabdar  */
2212654012fSReza Sabdar static char *
rs_darhl_new_name(struct rs_name_maker * rnp,char * name,char ** sels,int * pos,char * longname)2222654012fSReza Sabdar rs_darhl_new_name(struct rs_name_maker *rnp, char *name, char **sels, int *pos,
2232654012fSReza Sabdar     char *longname)
2242654012fSReza Sabdar {
2252654012fSReza Sabdar 	int x;
2262654012fSReza Sabdar 
2272654012fSReza Sabdar 	for (x = 0; sels[x] != NULL; x++) {
2282654012fSReza Sabdar 		if (strcmp(sels[x], " ")) {
2292654012fSReza Sabdar 			*pos = x;
2302654012fSReza Sabdar 			(void) strlcpy(longname, sels[x], TLM_MAX_PATH_NAME);
2312654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
2322654012fSReza Sabdar 			    "to replace hardlink name [%s], pos [%d]",
2332654012fSReza Sabdar 			    longname, *pos);
2342654012fSReza Sabdar 
2352654012fSReza Sabdar 			return (rs_new_name(rnp, name, *pos, longname));
2362654012fSReza Sabdar 		}
2372654012fSReza Sabdar 	}
2382654012fSReza Sabdar 
2392654012fSReza Sabdar 	return (NULL);
2402654012fSReza Sabdar }
2412654012fSReza Sabdar 
2422654012fSReza Sabdar 
2432654012fSReza Sabdar /*
244859b7745SReza Sabdar  * Main dir restore function for tar
2452efb3bf9SJan Kryl  *
2462efb3bf9SJan Kryl  * If this function returns non-zero return value it means that fatal error
2472efb3bf9SJan Kryl  * was encountered.
2482654012fSReza Sabdar  */
2492654012fSReza Sabdar int
tar_getdir(tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,struct rs_name_maker * rnp,int lib,int drv,char ** sels,char ** exls,int flags,int DAR,char * bk_path,struct hardlink_q * hardlink_q)2502654012fSReza Sabdar tar_getdir(tlm_commands_t *commands,
2512654012fSReza Sabdar     tlm_cmd_t *local_commands,
2522654012fSReza Sabdar     tlm_job_stats_t *job_stats,
2532654012fSReza Sabdar     struct rs_name_maker *rnp,
2542654012fSReza Sabdar     int	lib,
2552654012fSReza Sabdar     int	drv,
2562654012fSReza Sabdar     char **sels, /* what to get off the tape */
2572654012fSReza Sabdar     char **exls, /* what to leave behind */
2582654012fSReza Sabdar     int	flags,
259fb4eb4e8SReza Sabdar     int	DAR,
260fb4eb4e8SReza Sabdar     char *bk_path,
261fb4eb4e8SReza Sabdar     struct hardlink_q *hardlink_q)
2622654012fSReza Sabdar {
2632654012fSReza Sabdar 	int	fp = 0;		/* file being restored ... */
2642654012fSReza Sabdar 				/*  ...need to preserve across volume changes */
2652654012fSReza Sabdar 	tlm_acls_t *acls;	/* file access info */
2662654012fSReza Sabdar 	char	*longname;
2672654012fSReza Sabdar 	boolean_t is_long_name = FALSE;
2682654012fSReza Sabdar 	char	*longlink;
2692654012fSReza Sabdar 	char	*hugename;
2702654012fSReza Sabdar 	longlong_t huge_size = 0;	/* size of a HUGE file */
2712654012fSReza Sabdar 	long	acl_spot;		/* any ACL info on the next volume */
2722654012fSReza Sabdar 	long	file_size;		/* size of file to restore */
2732654012fSReza Sabdar 	long	size_left = 0;		/* need this after volume change */
2742654012fSReza Sabdar 	int	last_action = 0;	/* what we are doing at EOT */
2752654012fSReza Sabdar 	boolean_t multi_volume = FALSE;	/* is this a multi-volume switch ? */
2762654012fSReza Sabdar 	int	chk_rv;			/* scratch area */
2772654012fSReza Sabdar 
2782654012fSReza Sabdar 	int	mchtype, pos;
2792654012fSReza Sabdar 					/*
2802654012fSReza Sabdar 					 * if an exact match is found for
2812654012fSReza Sabdar 					 * restore and its position in the
2822654012fSReza Sabdar 					 * selections list
2832654012fSReza Sabdar 					 */
2842654012fSReza Sabdar 	int	nzerohdr;		/* the number of empty tar headers */
2852654012fSReza Sabdar 	int	rv;
2862654012fSReza Sabdar 	long nm_end, lnk_end;
2872654012fSReza Sabdar 	char	*name, *nmp;
2882654012fSReza Sabdar 	cstack_t *stp;
289*82049ff5SToomas Soome 	char	*bkpath;
290*82049ff5SToomas Soome 	char	*parentlnk;
291c9fd6b31SReza Sabdar 	int dir_dar = 0;
292c9fd6b31SReza Sabdar 
2932654012fSReza Sabdar 	/*
2942654012fSReza Sabdar 	 * The directory where temporary files may be created during a partial
2952654012fSReza Sabdar 	 * non-DAR restore of hardlinks.  It is intended to be initialized by
2962654012fSReza Sabdar 	 * an environment variable that can be set by user.
2972654012fSReza Sabdar 	 *
2982654012fSReza Sabdar 	 * It is not initialized for now.   We keep it here for future use.
2992654012fSReza Sabdar 	 */
3002654012fSReza Sabdar 	char *tmplink_dir = NULL;
301b6b15642SReza Sabdar 	int dar_recovered = 0;
302fb4eb4e8SReza Sabdar 	char *thname_buf;
3032654012fSReza Sabdar 
3042654012fSReza Sabdar 	/*
3052654012fSReza Sabdar 	 * startup
3062654012fSReza Sabdar 	 */
3072654012fSReza Sabdar 
3082654012fSReza Sabdar 	longname = ndmp_malloc(TLM_MAX_PATH_NAME);
3092654012fSReza Sabdar 	longlink = ndmp_malloc(TLM_MAX_PATH_NAME);
3102654012fSReza Sabdar 	hugename = ndmp_malloc(TLM_MAX_PATH_NAME);
3112654012fSReza Sabdar 	parentlnk = ndmp_malloc(TLM_MAX_PATH_NAME);
312fb4eb4e8SReza Sabdar 	thname_buf = ndmp_malloc(TLM_MAX_PATH_NAME);
3132654012fSReza Sabdar 	name = ndmp_malloc(TLM_MAX_PATH_NAME);
3142654012fSReza Sabdar 	acls = ndmp_malloc(sizeof (tlm_acls_t));
3152654012fSReza Sabdar 	stp = cstack_new();
3162654012fSReza Sabdar 	if (longname == NULL || longlink == NULL || hugename == NULL ||
317fb4eb4e8SReza Sabdar 	    name == NULL || acls == NULL || stp == NULL || parentlnk == NULL ||
318fb4eb4e8SReza Sabdar 	    thname_buf == NULL) {
3192654012fSReza Sabdar 		cstack_delete(stp);
3202654012fSReza Sabdar 		free(longname);
3212654012fSReza Sabdar 		free(longlink);
3222654012fSReza Sabdar 		free(hugename);
3232654012fSReza Sabdar 		free(parentlnk);
3242654012fSReza Sabdar 		free(name);
3252654012fSReza Sabdar 		free(acls);
326fb4eb4e8SReza Sabdar 		free(thname_buf);
3272654012fSReza Sabdar 		return (-TLM_NO_SCRATCH_SPACE);
3282654012fSReza Sabdar 	}
3292654012fSReza Sabdar 
3302654012fSReza Sabdar 	acl_spot = 0;
3312654012fSReza Sabdar 	*hugename = '\0';
3322654012fSReza Sabdar 	*parentlnk = '\0';
3332654012fSReza Sabdar 	nm_end = 0;
3342654012fSReza Sabdar 	*longname = '\0';
3352654012fSReza Sabdar 	lnk_end = 0;
3362654012fSReza Sabdar 	*longlink = '\0';
3372654012fSReza Sabdar 	(void) memset(acls, 0, sizeof (tlm_acls_t));
3382654012fSReza Sabdar 	if (IS_SET(flags, RSFLG_OVR_ALWAYS)) {
3392654012fSReza Sabdar 		acls->acl_overwrite = TRUE;
3402654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_ALWAYS");
3412654012fSReza Sabdar 	} else if (IS_SET(flags, RSFLG_OVR_UPDATE)) {
3422654012fSReza Sabdar 		acls->acl_update = TRUE;
3432654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "RSFLG_OVR_UPDATE");
3442654012fSReza Sabdar 	}
3452654012fSReza Sabdar 
3462654012fSReza Sabdar 	/*
3472654012fSReza Sabdar 	 * work
3482654012fSReza Sabdar 	 */
3492654012fSReza Sabdar 	rv = 0;
3502654012fSReza Sabdar 	nzerohdr = 0;
3512654012fSReza Sabdar 	while (commands->tcs_writer != TLM_ABORT &&
3522efb3bf9SJan Kryl 	    local_commands->tc_writer != TLM_STOP && rv == 0) {
3532654012fSReza Sabdar 		tlm_tar_hdr_t fake_tar_hdr;
3542654012fSReza Sabdar 		char	*file_name;
3552654012fSReza Sabdar 		char	*link_name;
3562654012fSReza Sabdar 		int	erc;
3572654012fSReza Sabdar 		int	actual_size;
3582654012fSReza Sabdar 		boolean_t want_this_file;
3592654012fSReza Sabdar 		int	want = sizeof (tlm_tar_hdr_t);
3602654012fSReza Sabdar 		tlm_tar_hdr_t *tar_hdr;
3612654012fSReza Sabdar 
3622654012fSReza Sabdar 		/* The inode of an LF_LINK type. */
3632654012fSReza Sabdar 		unsigned long hardlink_inode = 0;
3642654012fSReza Sabdar 
3652654012fSReza Sabdar 		/*
3662654012fSReza Sabdar 		 * Indicate whether a file with the same inode has been
3672654012fSReza Sabdar 		 * restored.
3682654012fSReza Sabdar 		 */
3692654012fSReza Sabdar 		int hardlink_done = 0;
3702654012fSReza Sabdar 
3712654012fSReza Sabdar 		/* The path of the restored hardlink file */
3722654012fSReza Sabdar 		char *hardlink_target = NULL;
3732654012fSReza Sabdar 		int is_hardlink = 0;
3742654012fSReza Sabdar 
3752654012fSReza Sabdar 		/*
3762654012fSReza Sabdar 		 * Whether a temporary file should be created for restoring
3772654012fSReza Sabdar 		 * hardlink.
3782654012fSReza Sabdar 		 */
3792654012fSReza Sabdar 		int hardlink_tmp_file = 0;
3802654012fSReza Sabdar 		char *hardlink_tmp_name = ".tmphlrsnondar";
3812654012fSReza Sabdar 
3822654012fSReza Sabdar 		/* used to make up hardlink_tmp_name */
3832654012fSReza Sabdar 		static int hardlink_tmp_idx = 0;
3842654012fSReza Sabdar 
3852654012fSReza Sabdar 		if (multi_volume) {
3862654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "multi_volume %c %d",
3872654012fSReza Sabdar 			    last_action, size_left);
3882654012fSReza Sabdar 
3892654012fSReza Sabdar 			/*
3902654012fSReza Sabdar 			 * the previous volume is out of data
3912654012fSReza Sabdar 			 * and is back in the rack, a new tape
3922654012fSReza Sabdar 			 * is loaded and ready to read.
3932654012fSReza Sabdar 			 *
3942654012fSReza Sabdar 			 * We need to pick up where we left off.
3952654012fSReza Sabdar 			 */
3962654012fSReza Sabdar 			(void) memset(&fake_tar_hdr, 0, sizeof (fake_tar_hdr));
3972654012fSReza Sabdar 			file_size = size_left;
3982654012fSReza Sabdar 			tar_hdr = &fake_tar_hdr;
3992654012fSReza Sabdar 			tar_hdr->th_linkflag = last_action;
4002654012fSReza Sabdar 
4012654012fSReza Sabdar 			multi_volume = FALSE;
4022654012fSReza Sabdar 			last_action = 0;
4032654012fSReza Sabdar 		} else {
4042654012fSReza Sabdar 			tar_hdr = (tlm_tar_hdr_t *)get_read_buffer(want,
4052654012fSReza Sabdar 			    &erc, &actual_size, local_commands);
4067bc22e45SReza Sabdar 
4077bc22e45SReza Sabdar 			if (tar_hdr == NULL) {
4087bc22e45SReza Sabdar 				rv = -1;
4097bc22e45SReza Sabdar 				continue;
4107bc22e45SReza Sabdar 			}
4117bc22e45SReza Sabdar 
4122654012fSReza Sabdar 			/*
4132654012fSReza Sabdar 			 * we can ignore read errors here because
4142654012fSReza Sabdar 			 *   1) they are logged by Restore Reader
4152654012fSReza Sabdar 			 *   2) we are not doing anything important here
4162654012fSReza Sabdar 			 *	just looking for the next work record.
4172654012fSReza Sabdar 			 */
4182654012fSReza Sabdar 			if (actual_size < want) {
4192654012fSReza Sabdar 				/*
4202654012fSReza Sabdar 				 * EOF hits here
4212654012fSReza Sabdar 				 *
4222654012fSReza Sabdar 				 * wait for another buffer to come along
4232654012fSReza Sabdar 				 * or until the Reader thread tells us
4242654012fSReza Sabdar 				 * that no more tapes will be loaded ...
4252654012fSReza Sabdar 				 * time to stop.
4262654012fSReza Sabdar 				 */
4272654012fSReza Sabdar 				continue;
4282654012fSReza Sabdar 			}
4292654012fSReza Sabdar 
4302654012fSReza Sabdar 			/*
4312654012fSReza Sabdar 			 * check for "we are lost"
4322654012fSReza Sabdar 			 */
4332654012fSReza Sabdar 			chk_rv = tlm_vfy_tar_checksum(tar_hdr);
4342654012fSReza Sabdar 			if (chk_rv == 0) {
4352654012fSReza Sabdar 				/* one of the end of tar file marks */
4362654012fSReza Sabdar 				if (++nzerohdr >= 2) {
4372654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
4382654012fSReza Sabdar 					    "nzerohdr %d, breaking",
4392654012fSReza Sabdar 					    nzerohdr);
4402654012fSReza Sabdar 					/* end of tar file */
4412654012fSReza Sabdar 					break;
4422654012fSReza Sabdar 				}
4432654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "nzerohdr %d, continuing",
4442654012fSReza Sabdar 				    nzerohdr);
4452654012fSReza Sabdar 				continue;
4462654012fSReza Sabdar 			} else if (chk_rv < 0) {
4472654012fSReza Sabdar 				nzerohdr = 0;
4482654012fSReza Sabdar 				/* skip this record */
4492654012fSReza Sabdar 				continue;
4502654012fSReza Sabdar 			}
4512654012fSReza Sabdar 			nzerohdr = 0;
4522654012fSReza Sabdar 
4532654012fSReza Sabdar 			/*
4542654012fSReza Sabdar 			 * When files are spanned to the next tape, the
4552654012fSReza Sabdar 			 * information of the acls must not be over-written
4562654012fSReza Sabdar 			 * by the information of the LF_MULTIVOL and LF_VOLHDR
4572654012fSReza Sabdar 			 * header, whose information is irrelevant to the file.
4582654012fSReza Sabdar 			 * The information of the original header must be
4592654012fSReza Sabdar 			 * kept in the 'acl'.
4602654012fSReza Sabdar 			 */
4612654012fSReza Sabdar 			if (tar_hdr->th_linkflag != LF_MULTIVOL &&
4622654012fSReza Sabdar 			    tar_hdr->th_linkflag != LF_VOLHDR) {
46386c48bbfSReza Sabdar 				if (tar_hdr->th_linkflag != LF_HUMONGUS) {
46486c48bbfSReza Sabdar 					acls->acl_attr.st_mode =
46586c48bbfSReza Sabdar 					    oct_atoi(tar_hdr->th_mode);
46686c48bbfSReza Sabdar 					acls->acl_attr.st_size =
46786c48bbfSReza Sabdar 					    oct_atoi(tar_hdr->th_size);
46886c48bbfSReza Sabdar 					acls->acl_attr.st_uid =
46986c48bbfSReza Sabdar 					    oct_atoi(tar_hdr->th_uid);
47086c48bbfSReza Sabdar 					acls->acl_attr.st_gid =
47186c48bbfSReza Sabdar 					    oct_atoi(tar_hdr->th_gid);
47286c48bbfSReza Sabdar 					acls->acl_attr.st_mtime =
47386c48bbfSReza Sabdar 					    oct_atoi(tar_hdr->th_mtime);
47486c48bbfSReza Sabdar 					(void) strlcpy(acls->uname,
47586c48bbfSReza Sabdar 					    tar_hdr->th_uname,
47686c48bbfSReza Sabdar 					    sizeof (acls->uname));
47786c48bbfSReza Sabdar 					(void) strlcpy(acls->gname,
47886c48bbfSReza Sabdar 					    tar_hdr->th_gname,
47986c48bbfSReza Sabdar 					    sizeof (acls->gname));
48086c48bbfSReza Sabdar 				}
4812654012fSReza Sabdar 				file_size = oct_atoi(tar_hdr->th_size);
4822654012fSReza Sabdar 				acl_spot = 0;
4832654012fSReza Sabdar 				last_action = tar_hdr->th_linkflag;
4842654012fSReza Sabdar 			}
4852654012fSReza Sabdar 		}
4862654012fSReza Sabdar 
4872654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "n [%s] f [%c] s %lld m %o u %d g %d t %d",
4882654012fSReza Sabdar 		    tar_hdr->th_name, tar_hdr->th_linkflag,
4892654012fSReza Sabdar 		    acls->acl_attr.st_size, acls->acl_attr.st_mode,
4902654012fSReza Sabdar 		    acls->acl_attr.st_uid, acls->acl_attr.st_gid,
4912654012fSReza Sabdar 		    acls->acl_attr.st_mtime);
4922654012fSReza Sabdar 
493b6b15642SReza Sabdar 		/*
494b6b15642SReza Sabdar 		 * If the restore is running using DAR we should check for
49586c48bbfSReza Sabdar 		 * extended attribute entries
496b6b15642SReza Sabdar 		 */
497b6b15642SReza Sabdar 		if (dar_recovered &&
498b6b15642SReza Sabdar 		    tar_hdr->th_linkflag != LF_XATTR)
499b6b15642SReza Sabdar 			break;
500b6b15642SReza Sabdar 
501fb4eb4e8SReza Sabdar 		rs_create_new_bkpath(bk_path, tar_hdr->th_name, thname_buf);
502fb4eb4e8SReza Sabdar 
5032654012fSReza Sabdar 		switch (tar_hdr->th_linkflag) {
5042654012fSReza Sabdar 		case LF_MULTIVOL:
5052654012fSReza Sabdar 			multi_volume = TRUE;
5062654012fSReza Sabdar 			break;
5072654012fSReza Sabdar 		case LF_LINK:
5082654012fSReza Sabdar 			is_hardlink = 1;
5092654012fSReza Sabdar 			hardlink_inode =
5102654012fSReza Sabdar 			    oct_atoi(tar_hdr->th_shared.th_hlink_ino);
5112654012fSReza Sabdar 
5122654012fSReza Sabdar 			/*
5132654012fSReza Sabdar 			 * Check if we have restored a link with the same inode
5142654012fSReza Sabdar 			 * If the inode is 0, we have to restore it as a
5152654012fSReza Sabdar 			 * regular file.
5162654012fSReza Sabdar 			 */
5172654012fSReza Sabdar 			if (hardlink_inode) {
5182654012fSReza Sabdar 				hardlink_done = !hardlink_q_get(hardlink_q,
5192654012fSReza Sabdar 				    hardlink_inode, 0, &hardlink_target);
5202654012fSReza Sabdar 			}
5212654012fSReza Sabdar 
5222654012fSReza Sabdar 			if (hardlink_done) {
5232654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
5242654012fSReza Sabdar 				    "found hardlink, inode = %u, target = [%s]",
5252654012fSReza Sabdar 				    hardlink_inode,
5262654012fSReza Sabdar 				    hardlink_target? hardlink_target : "--");
5272654012fSReza Sabdar 
5282654012fSReza Sabdar 				/* create a hardlink to hardlink_target */
5292654012fSReza Sabdar 				file_name = (*longname == 0) ?
530fb4eb4e8SReza Sabdar 				    thname_buf : longname;
531fb4eb4e8SReza Sabdar 
5322654012fSReza Sabdar 				if (!is_file_wanted(file_name, sels, exls,
5332654012fSReza Sabdar 				    flags, &mchtype, &pos)) {
5342654012fSReza Sabdar 					nmp = NULL;
5352654012fSReza Sabdar 					/*
5362654012fSReza Sabdar 					 * This means that DMA did not send us
5372654012fSReza Sabdar 					 * the correct fh_info for the file
5382654012fSReza Sabdar 					 * in restore list.  We use the file
5392654012fSReza Sabdar 					 * name entry in sels[] (ignore the
5402654012fSReza Sabdar 					 * name in the tar header) as restore
5412654012fSReza Sabdar 					 * target.
5422654012fSReza Sabdar 					 */
5432654012fSReza Sabdar 					if (DAR) {
5442654012fSReza Sabdar 						nmp = rs_darhl_new_name(rnp,
5452654012fSReza Sabdar 						    name, sels, &pos,
5462654012fSReza Sabdar 						    file_name);
5472654012fSReza Sabdar 					}
5482654012fSReza Sabdar 				} else {
5492654012fSReza Sabdar 					nmp = rs_new_name(rnp, name, pos,
5502654012fSReza Sabdar 					    file_name);
5512654012fSReza Sabdar 					if (!nmp) {
5522654012fSReza Sabdar 						NDMP_LOG(LOG_DEBUG,
5532654012fSReza Sabdar 						    "can't make name for %s",
5542654012fSReza Sabdar 						    longname);
5552654012fSReza Sabdar 					}
5562654012fSReza Sabdar 				}
5572654012fSReza Sabdar 
5582654012fSReza Sabdar 				if (nmp) {
5592654012fSReza Sabdar 					if (hardlink_target) {
5602654012fSReza Sabdar 						erc = create_hard_link(
5612654012fSReza Sabdar 						    hardlink_target, nmp,
5622654012fSReza Sabdar 						    acls, job_stats);
5632efb3bf9SJan Kryl 						if (ERROR_IS_FATAL(erc)) {
5642efb3bf9SJan Kryl 							rv = erc;
5652efb3bf9SJan Kryl 							continue;
5662efb3bf9SJan Kryl 						}
5672654012fSReza Sabdar 						if (erc == 0) {
5682654012fSReza Sabdar 							(void)
5692654012fSReza Sabdar 							    tlm_entry_restored(
5702654012fSReza Sabdar 							    job_stats,
5712654012fSReza Sabdar 							    file_name, pos);
5722654012fSReza Sabdar 							NDMP_LOG(LOG_DEBUG,
5732654012fSReza Sabdar 							    "restored %s -> %s",
5742654012fSReza Sabdar 							    nmp,
5752654012fSReza Sabdar 							    hardlink_target);
5762654012fSReza Sabdar 						}
5772654012fSReza Sabdar 					} else {
5782654012fSReza Sabdar 						NDMP_LOG(LOG_DEBUG,
5792654012fSReza Sabdar 						    "no target for hardlink %s",
5802654012fSReza Sabdar 						    nmp);
5812654012fSReza Sabdar 					}
5822654012fSReza Sabdar 
5832654012fSReza Sabdar 					name[0] = 0;
5842654012fSReza Sabdar 					is_long_name = FALSE;
5852654012fSReza Sabdar 				}
5862654012fSReza Sabdar 
5872654012fSReza Sabdar 				nm_end = 0;
5882654012fSReza Sabdar 				longname[0] = 0;
5892654012fSReza Sabdar 				lnk_end = 0;
5902654012fSReza Sabdar 				longlink[0] = 0;
5912654012fSReza Sabdar 
5922654012fSReza Sabdar 				break;
5932654012fSReza Sabdar 			}
5942654012fSReza Sabdar 			/* otherwise fall through, restore like a normal file */
5952654012fSReza Sabdar 			/*FALLTHROUGH*/
5962654012fSReza Sabdar 		case LF_OLDNORMAL:
5972654012fSReza Sabdar 			/*
5982654012fSReza Sabdar 			 * check for TAR's end-of-tape method
5992654012fSReza Sabdar 			 * of zero filled records.
6002654012fSReza Sabdar 			 */
6012654012fSReza Sabdar 			if (tar_hdr->th_name[0] == 0) {
6022654012fSReza Sabdar 				break;
6032654012fSReza Sabdar 			}
6042654012fSReza Sabdar 			/*
6052654012fSReza Sabdar 			 * otherwise fall through,
6062654012fSReza Sabdar 			 * this is an old style normal file header
6072654012fSReza Sabdar 			 */
6082654012fSReza Sabdar 			/*FALLTHROUGH*/
6092654012fSReza Sabdar 		case LF_NORMAL:
6102654012fSReza Sabdar 		case LF_CONTIG:
6112654012fSReza Sabdar 			job_stats->js_files_so_far++;
6122654012fSReza Sabdar 			if (*hugename != 0) {
6132654012fSReza Sabdar 				(void) strlcpy(longname, hugename,
6142654012fSReza Sabdar 				    TLM_MAX_PATH_NAME);
6152654012fSReza Sabdar 			} else if (*longname == 0) {
6162654012fSReza Sabdar 				if (tar_hdr->th_name[0] != '/') {
6172654012fSReza Sabdar 					/*
6182654012fSReza Sabdar 					 * check for old tar format, it
6192654012fSReza Sabdar 					 * does not have a leading "/"
6202654012fSReza Sabdar 					 */
6212654012fSReza Sabdar 					longname[0] = '/';
6222654012fSReza Sabdar 					longname[1] = 0;
6232654012fSReza Sabdar 					(void) strlcat(longname,
6242654012fSReza Sabdar 					    tar_hdr->th_name,
6252654012fSReza Sabdar 					    TLM_MAX_PATH_NAME);
6262654012fSReza Sabdar 				} else {
6272654012fSReza Sabdar 					(void) strlcpy(longname,
628fb4eb4e8SReza Sabdar 					    thname_buf,
6292654012fSReza Sabdar 					    TLM_MAX_PATH_NAME);
6302654012fSReza Sabdar 				}
6312654012fSReza Sabdar 			}
6322654012fSReza Sabdar 
6332654012fSReza Sabdar 			want_this_file = is_file_wanted(longname, sels, exls,
6342654012fSReza Sabdar 			    flags, &mchtype, &pos);
6352654012fSReza Sabdar 			if (!want_this_file) {
6362654012fSReza Sabdar 				nmp = NULL;
6372654012fSReza Sabdar 				/*
6382654012fSReza Sabdar 				 * This means that DMA did not send us valid
6392654012fSReza Sabdar 				 * fh_info for the file in restore list.  We
6402654012fSReza Sabdar 				 * use the file name entry in sels[] (ignore
6412654012fSReza Sabdar 				 * the name in the tar header) as restore
6422654012fSReza Sabdar 				 * target.
6432654012fSReza Sabdar 				 */
6442654012fSReza Sabdar 				if (DAR && (tar_hdr->th_linkflag == LF_LINK)) {
6452654012fSReza Sabdar 					nmp = rs_darhl_new_name(rnp, name,
6462654012fSReza Sabdar 					    sels, &pos, longname);
6472efb3bf9SJan Kryl 					if (nmp == NULL) {
6482efb3bf9SJan Kryl 						rv = ENOMEM;
6492efb3bf9SJan Kryl 						continue;
6502654012fSReza Sabdar 					}
6512efb3bf9SJan Kryl 
6522efb3bf9SJan Kryl 					want_this_file = TRUE;
6532efb3bf9SJan Kryl 					mchtype = PM_EXACT;
6542654012fSReza Sabdar 				}
6552654012fSReza Sabdar 			} else {
6562654012fSReza Sabdar 				nmp = rs_new_name(rnp, name, pos, longname);
6572654012fSReza Sabdar 				if (!nmp)
6582654012fSReza Sabdar 					want_this_file = FALSE;
6592654012fSReza Sabdar 			}
6602654012fSReza Sabdar 
6612654012fSReza Sabdar 			if (nmp)
6622654012fSReza Sabdar 				(void) strlcpy(parentlnk, nmp, strlen(nmp) + 1);
6632654012fSReza Sabdar 
6642654012fSReza Sabdar 			/*
6652654012fSReza Sabdar 			 * For a hardlink, even if it's not asked to be
6662654012fSReza Sabdar 			 * restored, we restore it to a temporary location,
6672654012fSReza Sabdar 			 * in case other links to the same file need to be
6682654012fSReza Sabdar 			 * restored later.
6692654012fSReza Sabdar 			 *
6702654012fSReza Sabdar 			 * The temp files are created in tmplink_dir, with
6712654012fSReza Sabdar 			 * names like ".tmphlrsnondar*".  They are cleaned up
6722654012fSReza Sabdar 			 * at the completion of a restore.  However, if a
6732654012fSReza Sabdar 			 * restore were interrupted, e.g. by a system reboot,
6742654012fSReza Sabdar 			 * they would have to be cleaned up manually in order
6752654012fSReza Sabdar 			 * for the disk space to be freed.
6762654012fSReza Sabdar 			 *
6772654012fSReza Sabdar 			 * If tmplink_dir is NULL, no temperorary files are
6782654012fSReza Sabdar 			 * created during a restore.  This may result in some
6792654012fSReza Sabdar 			 * hardlinks not being restored during a partial
6802654012fSReza Sabdar 			 * restore.
6812654012fSReza Sabdar 			 */
6822654012fSReza Sabdar 			if (is_hardlink && !DAR && !want_this_file && !nmp) {
6832654012fSReza Sabdar 				if (tmplink_dir) {
6842654012fSReza Sabdar 					(void) snprintf(name, TLM_MAX_PATH_NAME,
6852654012fSReza Sabdar 					    "%s/%s_%d", tmplink_dir,
6862654012fSReza Sabdar 					    hardlink_tmp_name,
6872654012fSReza Sabdar 					    hardlink_tmp_idx);
6882654012fSReza Sabdar 					nmp = name;
6892654012fSReza Sabdar 
6902654012fSReza Sabdar 					hardlink_tmp_idx++;
6912654012fSReza Sabdar 					hardlink_tmp_file = 1;
6922654012fSReza Sabdar 					want_this_file = TRUE;
6932654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
6942654012fSReza Sabdar 					    "To restore temp hardlink file %s.",
6952654012fSReza Sabdar 					    nmp);
6962654012fSReza Sabdar 				} else {
6972654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
6982654012fSReza Sabdar 					    "No tmplink_dir specified.");
6992654012fSReza Sabdar 				}
7002654012fSReza Sabdar 			}
7012654012fSReza Sabdar 
7022efb3bf9SJan Kryl 			rv = restore_file(&fp, nmp, file_size,
7032654012fSReza Sabdar 			    huge_size, acls, want_this_file, local_commands,
7042efb3bf9SJan Kryl 			    job_stats, &size_left);
7052efb3bf9SJan Kryl 			if (rv != 0)
7062efb3bf9SJan Kryl 				continue;
7072654012fSReza Sabdar 
7082654012fSReza Sabdar 			/*
7092654012fSReza Sabdar 			 * In the case of non-DAR, we have to record the first
7102654012fSReza Sabdar 			 * link for an inode that has multiple links. That's
7112654012fSReza Sabdar 			 * the only link with data records actually backed up.
7122654012fSReza Sabdar 			 * In this way, when we run into the other links, they
7132654012fSReza Sabdar 			 * will be treated as links, and we won't go to look
7142654012fSReza Sabdar 			 * for the data records to restore.  This is not a
7152654012fSReza Sabdar 			 * problem for DAR, where DMA tells the tape where
7162654012fSReza Sabdar 			 * to locate the data records.
7172654012fSReza Sabdar 			 */
7182654012fSReza Sabdar 			if (is_hardlink && !DAR) {
7192654012fSReza Sabdar 				if (hardlink_q_add(hardlink_q, hardlink_inode,
7202654012fSReza Sabdar 				    0, nmp, hardlink_tmp_file))
7212654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
7222654012fSReza Sabdar 					    "failed to add (%u, %s) to HL q",
7232654012fSReza Sabdar 					    hardlink_inode, nmp);
7242654012fSReza Sabdar 			}
7252654012fSReza Sabdar 
7262654012fSReza Sabdar 			/* remove / reverse the temporary stuff */
7272654012fSReza Sabdar 			if (hardlink_tmp_file) {
7282654012fSReza Sabdar 				nmp = NULL;
7292654012fSReza Sabdar 				want_this_file = FALSE;
7302654012fSReza Sabdar 				hardlink_tmp_file = 0;
7312654012fSReza Sabdar 			}
7322654012fSReza Sabdar 
7332654012fSReza Sabdar 			/*
7342654012fSReza Sabdar 			 * Check if it is time to set the attribute
7352654012fSReza Sabdar 			 * of the restored directory
7362654012fSReza Sabdar 			 */
7372654012fSReza Sabdar 			while (nmp && ((bkpath = dtree_peek(stp)) != NULL)) {
7382efb3bf9SJan Kryl 				int erc;
7392efb3bf9SJan Kryl 
7402654012fSReza Sabdar 				if (strstr(nmp, bkpath))
7412654012fSReza Sabdar 					break;
7422654012fSReza Sabdar 
7432efb3bf9SJan Kryl 				erc = dtree_pop(stp);
7442efb3bf9SJan Kryl 				if (ERROR_IS_FATAL(erc)) {
7452efb3bf9SJan Kryl 					rv = erc;
7462efb3bf9SJan Kryl 					break;
7472efb3bf9SJan Kryl 				}
7482654012fSReza Sabdar 			}
7492efb3bf9SJan Kryl 			if (rv != 0)
7502efb3bf9SJan Kryl 				continue;
7512654012fSReza Sabdar 
7522654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "sizeleft %s %d, %lld", longname,
7532654012fSReza Sabdar 			    size_left, huge_size);
7542654012fSReza Sabdar 
7552654012fSReza Sabdar 			if (want_this_file) {
7562654012fSReza Sabdar 				job_stats->js_bytes_total += file_size;
7572654012fSReza Sabdar 				job_stats->js_files_total++;
7582654012fSReza Sabdar 			}
7592654012fSReza Sabdar 
7602654012fSReza Sabdar 			huge_size -= file_size;
7612654012fSReza Sabdar 			if (huge_size < 0) {
7622654012fSReza Sabdar 				huge_size = 0;
7632654012fSReza Sabdar 			}
7642654012fSReza Sabdar 			if (size_left == 0 && huge_size == 0) {
7652654012fSReza Sabdar 				if (PM_EXACT_OR_CHILD(mchtype)) {
7662654012fSReza Sabdar 					(void) tlm_entry_restored(job_stats,
7672654012fSReza Sabdar 					    longname, pos);
7682654012fSReza Sabdar 
7692654012fSReza Sabdar 					/*
7702654012fSReza Sabdar 					 * Add an entry to hardlink_q to record
7712654012fSReza Sabdar 					 * this hardlink.
7722654012fSReza Sabdar 					 */
7732654012fSReza Sabdar 					if (is_hardlink) {
7742654012fSReza Sabdar 						NDMP_LOG(LOG_DEBUG,
7752654012fSReza Sabdar 						    "Restored hardlink file %s",
7762654012fSReza Sabdar 						    nmp);
7772654012fSReza Sabdar 
7782654012fSReza Sabdar 						if (DAR) {
7792654012fSReza Sabdar 							(void) hardlink_q_add(
7802654012fSReza Sabdar 							    hardlink_q,
7812654012fSReza Sabdar 							    hardlink_inode, 0,
7822654012fSReza Sabdar 							    nmp, 0);
7832654012fSReza Sabdar 						}
7842654012fSReza Sabdar 					}
7852654012fSReza Sabdar 				}
7862654012fSReza Sabdar 
7872654012fSReza Sabdar 				nm_end = 0;
7882654012fSReza Sabdar 				longname[0] = 0;
7892654012fSReza Sabdar 				lnk_end = 0;
7902654012fSReza Sabdar 				longlink[0] = 0;
7912654012fSReza Sabdar 				hugename[0] = 0;
7922654012fSReza Sabdar 				name[0] = 0;
7932654012fSReza Sabdar 				is_long_name = FALSE;
7942654012fSReza Sabdar 			}
7952654012fSReza Sabdar 			break;
7962654012fSReza Sabdar 		case LF_XATTR:
797fb4eb4e8SReza Sabdar 			file_name = (*longname == 0) ? thname_buf :
7982654012fSReza Sabdar 			    longname;
7992654012fSReza Sabdar 
8002654012fSReza Sabdar 			size_left = restore_xattr_hdr(&fp, parentlnk,
8012654012fSReza Sabdar 			    file_name, file_size, acls, local_commands,
8022654012fSReza Sabdar 			    job_stats);
8032654012fSReza Sabdar 
8042654012fSReza Sabdar 			break;
8052654012fSReza Sabdar 		case LF_SYMLINK:
806fb4eb4e8SReza Sabdar 			file_name = (*longname == 0) ? thname_buf :
8072654012fSReza Sabdar 			    longname;
8082654012fSReza Sabdar 			link_name = (*longlink == 0) ?
8092654012fSReza Sabdar 			    tar_hdr->th_linkname : longlink;
8102654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "file_name[%s]", file_name);
8112654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "link_name[%s]", link_name);
8122654012fSReza Sabdar 			if (is_file_wanted(file_name, sels, exls, flags,
8132654012fSReza Sabdar 			    &mchtype, &pos)) {
8142654012fSReza Sabdar 				nmp = rs_new_name(rnp, name, pos, file_name);
8152654012fSReza Sabdar 				if (nmp) {
8162654012fSReza Sabdar 					erc = create_sym_link(nmp, link_name,
8172654012fSReza Sabdar 					    acls, job_stats);
8182efb3bf9SJan Kryl 					if (ERROR_IS_FATAL(erc)) {
8192efb3bf9SJan Kryl 						rv = erc;
8202efb3bf9SJan Kryl 						continue;
8212efb3bf9SJan Kryl 					}
8222654012fSReza Sabdar 					if (erc == 0 &&
8232654012fSReza Sabdar 					    PM_EXACT_OR_CHILD(mchtype))
8242654012fSReza Sabdar 						(void) tlm_entry_restored(
8252654012fSReza Sabdar 						    job_stats, file_name, pos);
8262654012fSReza Sabdar 					name[0] = 0;
8272654012fSReza Sabdar 				}
8282654012fSReza Sabdar 			}
8292654012fSReza Sabdar 			nm_end = 0;
8302654012fSReza Sabdar 			longname[0] = 0;
8312654012fSReza Sabdar 			lnk_end = 0;
8322654012fSReza Sabdar 			longlink[0] = 0;
8332654012fSReza Sabdar 			break;
8342654012fSReza Sabdar 		case LF_DIR:
835fb4eb4e8SReza Sabdar 			file_name = *longname == 0 ? thname_buf :
8362654012fSReza Sabdar 			    longname;
8372654012fSReza Sabdar 			if (is_file_wanted(file_name, sels, exls, flags,
8382654012fSReza Sabdar 			    &mchtype, &pos)) {
839c9fd6b31SReza Sabdar 				dir_dar = DAR;
8402654012fSReza Sabdar 				nmp = rs_new_name(rnp, name, pos, file_name);
8412654012fSReza Sabdar 				if (nmp && mchtype != PM_PARENT) {
8422654012fSReza Sabdar 					(void) strlcpy(parentlnk, nmp,
8432654012fSReza Sabdar 					    strlen(nmp));
8442654012fSReza Sabdar 					erc = create_directory(nmp, job_stats);
8452efb3bf9SJan Kryl 					if (ERROR_IS_FATAL(erc)) {
8462efb3bf9SJan Kryl 						rv = erc;
8472efb3bf9SJan Kryl 						continue;
8482efb3bf9SJan Kryl 					}
8492654012fSReza Sabdar 					if (erc == 0 &&
8502654012fSReza Sabdar 					    PM_EXACT_OR_CHILD(mchtype))
8512654012fSReza Sabdar 						(void) tlm_entry_restored(
8522654012fSReza Sabdar 						    job_stats, file_name, pos);
8532654012fSReza Sabdar 					/*
8542654012fSReza Sabdar 					 * Check if it is time to set
8552654012fSReza Sabdar 					 * the attribute of the restored
8562654012fSReza Sabdar 					 * directory
8572654012fSReza Sabdar 					 */
8582654012fSReza Sabdar 					while ((bkpath = dtree_peek(stp))
8592654012fSReza Sabdar 					    != NULL) {
8602efb3bf9SJan Kryl 						int rc;
8612efb3bf9SJan Kryl 
8622654012fSReza Sabdar 						if (strstr(nmp, bkpath))
8632654012fSReza Sabdar 							break;
8642efb3bf9SJan Kryl 						rc = dtree_pop(stp);
8652efb3bf9SJan Kryl 						if (ERROR_IS_FATAL(rc)) {
8662efb3bf9SJan Kryl 							rv = rc;
8672efb3bf9SJan Kryl 							break;
8682efb3bf9SJan Kryl 						}
8692654012fSReza Sabdar 					}
8702efb3bf9SJan Kryl 					if (rv != 0)
8712efb3bf9SJan Kryl 						continue;
8722654012fSReza Sabdar 
8732654012fSReza Sabdar 					(void) dtree_push(stp, nmp, acls);
8742654012fSReza Sabdar 					name[0] = 0;
8752654012fSReza Sabdar 				}
876c9fd6b31SReza Sabdar 			} else {
877c9fd6b31SReza Sabdar 				dir_dar = 0;
8782654012fSReza Sabdar 			}
8792654012fSReza Sabdar 			nm_end = 0;
8802654012fSReza Sabdar 			longname[0] = 0;
8812654012fSReza Sabdar 			lnk_end = 0;
8822654012fSReza Sabdar 			longlink[0] = 0;
8832654012fSReza Sabdar 			break;
8842654012fSReza Sabdar 		case LF_FIFO:
8855181c2afSReza Sabdar 		case LF_BLK:
8865181c2afSReza Sabdar 		case LF_CHR:
887fb4eb4e8SReza Sabdar 			file_name = *longname == 0 ? thname_buf :
8882654012fSReza Sabdar 			    longname;
8892654012fSReza Sabdar 			if (is_file_wanted(file_name, sels, exls, flags,
8902654012fSReza Sabdar 			    &mchtype, &pos)) {
8912654012fSReza Sabdar 				nmp = rs_new_name(rnp, name, pos, file_name);
8922654012fSReza Sabdar 				if (nmp) {
8935181c2afSReza Sabdar 					erc = create_special(
8945181c2afSReza Sabdar 					    tar_hdr->th_linkflag, nmp, acls,
8955181c2afSReza Sabdar 					    oct_atoi(tar_hdr->th_shared.
8965181c2afSReza Sabdar 					    th_dev.th_devmajor),
8975181c2afSReza Sabdar 					    oct_atoi(tar_hdr->th_shared.
8985181c2afSReza Sabdar 					    th_dev.th_devminor), job_stats);
8992efb3bf9SJan Kryl 					if (ERROR_IS_FATAL(erc)) {
9002efb3bf9SJan Kryl 						rv = erc;
9012efb3bf9SJan Kryl 						continue;
9022efb3bf9SJan Kryl 					}
9032654012fSReza Sabdar 					if (erc == 0 &&
9042654012fSReza Sabdar 					    PM_EXACT_OR_CHILD(mchtype))
9052654012fSReza Sabdar 						(void) tlm_entry_restored(
9062654012fSReza Sabdar 						    job_stats, file_name, pos);
9072654012fSReza Sabdar 					name[0] = 0;
9082654012fSReza Sabdar 				}
9092654012fSReza Sabdar 			}
9102654012fSReza Sabdar 			nm_end = 0;
9112654012fSReza Sabdar 			longname[0] = 0;
9122654012fSReza Sabdar 			lnk_end = 0;
9132654012fSReza Sabdar 			longlink[0] = 0;
9142654012fSReza Sabdar 			break;
9152654012fSReza Sabdar 		case LF_LONGLINK:
916859b7745SReza Sabdar 			file_size = min(file_size,
917859b7745SReza Sabdar 			    TLM_MAX_PATH_NAME - lnk_end - 1);
9182654012fSReza Sabdar 			file_size = max(0, file_size);
9192654012fSReza Sabdar 			size_left = get_long_name(lib, drv, file_size, longlink,
9202654012fSReza Sabdar 			    &lnk_end, local_commands);
9212654012fSReza Sabdar 
9222654012fSReza Sabdar 			if (size_left != 0)
9232654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
9242654012fSReza Sabdar 				    "fsize %d sleft %d lnkend %d",
9252654012fSReza Sabdar 				    file_size, size_left, lnk_end);
9262654012fSReza Sabdar 			break;
9272654012fSReza Sabdar 		case LF_LONGNAME:
928859b7745SReza Sabdar 			file_size = min(file_size,
929859b7745SReza Sabdar 			    TLM_MAX_PATH_NAME - nm_end - 1);
9302654012fSReza Sabdar 			file_size = max(0, file_size);
9312654012fSReza Sabdar 			size_left = get_long_name(lib, drv, file_size, longname,
9322654012fSReza Sabdar 			    &nm_end, local_commands);
9332654012fSReza Sabdar 
9342654012fSReza Sabdar 			if (size_left != 0)
9352654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
9362654012fSReza Sabdar 				    "fsize %d sleft %d nmend %d",
9372654012fSReza Sabdar 				    file_size, size_left, nm_end);
9382654012fSReza Sabdar 			is_long_name = TRUE;
9392654012fSReza Sabdar 			break;
9402654012fSReza Sabdar 		case LF_ACL:
9412654012fSReza Sabdar 			size_left = load_acl_info(lib, drv, file_size, acls,
9422654012fSReza Sabdar 			    &acl_spot, local_commands);
9432654012fSReza Sabdar 			break;
9442654012fSReza Sabdar 		case LF_VOLHDR:
9452654012fSReza Sabdar 			break;
9462654012fSReza Sabdar 		case LF_HUMONGUS:
9472654012fSReza Sabdar 			(void) memset(hugename, 0, TLM_MAX_PATH_NAME);
9482654012fSReza Sabdar 			(void) get_humongus_file_header(lib, drv, file_size,
9492654012fSReza Sabdar 			    &huge_size, hugename, local_commands);
9502654012fSReza Sabdar 			break;
9512654012fSReza Sabdar 		default:
9522654012fSReza Sabdar 			break;
9532654012fSReza Sabdar 
9542654012fSReza Sabdar 		}
9552654012fSReza Sabdar 
9562654012fSReza Sabdar 		/*
9572654012fSReza Sabdar 		 * If the restore is running using DAR we should check for
9582654012fSReza Sabdar 		 * long file names and HUGE file sizes.
9592654012fSReza Sabdar 		 */
9602654012fSReza Sabdar 		if (DAR && tar_hdr->th_linkflag != LF_ACL &&
961b6b15642SReza Sabdar 		    tar_hdr->th_linkflag != LF_XATTR &&
962c9fd6b31SReza Sabdar 		    !huge_size && !is_long_name && !dir_dar)
963b6b15642SReza Sabdar 			dar_recovered = 1;
9642654012fSReza Sabdar 	}
9652654012fSReza Sabdar 
9662654012fSReza Sabdar 	/*
9672654012fSReza Sabdar 	 * tear down
9682654012fSReza Sabdar 	 */
9692efb3bf9SJan Kryl 	if (rv != 0)
9702efb3bf9SJan Kryl 		commands->tcs_reader = TLM_ABORT;
9712654012fSReza Sabdar 	if (fp != 0) {
9722654012fSReza Sabdar 		(void) close(fp);
9732654012fSReza Sabdar 	}
9742654012fSReza Sabdar 	while (dtree_pop(stp) != -1)
9752654012fSReza Sabdar 		;
9762654012fSReza Sabdar 	cstack_delete(stp);
9772654012fSReza Sabdar 	free(acls);
9782654012fSReza Sabdar 	free(longname);
9792654012fSReza Sabdar 	free(parentlnk);
9802654012fSReza Sabdar 	free(longlink);
9812654012fSReza Sabdar 	free(hugename);
9822654012fSReza Sabdar 	free(name);
983fb4eb4e8SReza Sabdar 	free(thname_buf);
9842654012fSReza Sabdar 	return (rv);
9852654012fSReza Sabdar }
9862654012fSReza Sabdar 
9872654012fSReza Sabdar /*
9882654012fSReza Sabdar  * Main file restore function for tar (should run as a thread)
9892654012fSReza Sabdar  */
990*82049ff5SToomas Soome void *
tar_getfile(void * ptr)991*82049ff5SToomas Soome tar_getfile(void *ptr)
9922654012fSReza Sabdar {
993*82049ff5SToomas Soome 	tlm_backup_restore_arg_t *argp = ptr;
9942654012fSReza Sabdar 	tlm_job_stats_t	*job_stats;
9952654012fSReza Sabdar 	char	**sels;		/* list of files desired */
9962654012fSReza Sabdar 	char	**exls;		/* list of files not wanted */
9972654012fSReza Sabdar 	char	*dir;		/* where to restore the files */
9982654012fSReza Sabdar 	char	job[TLM_MAX_BACKUP_JOB_NAME+1];
9992654012fSReza Sabdar 				/* the restore job name */
10002654012fSReza Sabdar 	int	erc;		/* error return codes */
10012654012fSReza Sabdar 	int	flags;
10022654012fSReza Sabdar 	struct	rs_name_maker rn;
10032654012fSReza Sabdar 	tlm_commands_t *commands;
10042654012fSReza Sabdar 	tlm_cmd_t *local_commands;
10052654012fSReza Sabdar 	char *list = NULL;
10062654012fSReza Sabdar 
10072654012fSReza Sabdar 	commands = argp->ba_commands;
10082654012fSReza Sabdar 	local_commands = argp->ba_cmd;
10092654012fSReza Sabdar 
10102654012fSReza Sabdar 	flags = 0;
10112654012fSReza Sabdar 
10122654012fSReza Sabdar 	dir = ndmp_malloc(TLM_MAX_PATH_NAME);
10132654012fSReza Sabdar 	if (dir == NULL) {
10142654012fSReza Sabdar 		local_commands->tc_reader = TLM_STOP;
10152654012fSReza Sabdar 		(void) pthread_barrier_wait(&argp->ba_barrier);
1016*82049ff5SToomas Soome 		return ((void *)(uintptr_t)-1);
10172654012fSReza Sabdar 	}
10182654012fSReza Sabdar 
10192654012fSReza Sabdar 	(void) strlcpy(job, argp->ba_job, TLM_MAX_BACKUP_JOB_NAME+1);
10202654012fSReza Sabdar 	(void) strlcpy(dir, argp->ba_dir, TLM_MAX_PATH_NAME);
10212654012fSReza Sabdar 
10222654012fSReza Sabdar 	flags |= RSFLG_OVR_ALWAYS;
10232654012fSReza Sabdar 	flags |= RSFLG_IGNORE_CASE;
10242654012fSReza Sabdar 
10252654012fSReza Sabdar 	/*
10262654012fSReza Sabdar 	 * do not test for "dir" having no string, since that
10272654012fSReza Sabdar 	 * is a legal condition.  Restore to origional location
10282654012fSReza Sabdar 	 * will not have a restore directory.
10292654012fSReza Sabdar 	 */
10302654012fSReza Sabdar 	if (*job == '\0') {
10312654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "No job defined");
10322654012fSReza Sabdar 		local_commands->tc_reader = TLM_STOP;
10332654012fSReza Sabdar 		free(dir);
10342654012fSReza Sabdar 		(void) pthread_barrier_wait(&argp->ba_barrier);
1035*82049ff5SToomas Soome 		return ((void *)(uintptr_t)-1);
10362654012fSReza Sabdar 	}
10372654012fSReza Sabdar 
10382654012fSReza Sabdar 	sels = argp->ba_sels;
10392654012fSReza Sabdar 	if (sels == NULL) {
10402654012fSReza Sabdar 		local_commands->tc_reader = TLM_STOP;
10412654012fSReza Sabdar 		free(dir);
10422654012fSReza Sabdar 		(void) pthread_barrier_wait(&argp->ba_barrier);
1043*82049ff5SToomas Soome 		return ((void *)(uintptr_t)-1);
10442654012fSReza Sabdar 	}
10452654012fSReza Sabdar 	exls = &list;
10462654012fSReza Sabdar 
10472654012fSReza Sabdar 	tlm_log_list("selections", sels);
10482654012fSReza Sabdar 	tlm_log_list("exclusions", exls);
10492654012fSReza Sabdar 
10502654012fSReza Sabdar 	if (wildcard_enabled())
10512654012fSReza Sabdar 		flags |= RSFLG_MATCH_WCARD;
10522654012fSReza Sabdar 
10532654012fSReza Sabdar 	local_commands->tc_ref++;
10542654012fSReza Sabdar 	commands->tcs_writer_count++;
10552654012fSReza Sabdar 
10562654012fSReza Sabdar 	/*
10572654012fSReza Sabdar 	 * let the launcher continue
10582654012fSReza Sabdar 	 */
10592654012fSReza Sabdar 	(void) pthread_barrier_wait(&argp->ba_barrier);
10602654012fSReza Sabdar 
10612654012fSReza Sabdar 	job_stats = tlm_ref_job_stats(job);
10622654012fSReza Sabdar 
10632654012fSReza Sabdar 	rn.rn_fp = catnames;
10642654012fSReza Sabdar 	rn.rn_nlp = dir;
10652654012fSReza Sabdar 
10662654012fSReza Sabdar 	/*
10672654012fSReza Sabdar 	 * work
10682654012fSReza Sabdar 	 */
10692654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "start restore job %s", job);
10702654012fSReza Sabdar 	erc = tar_getdir(commands, local_commands, job_stats, &rn, 1, 1,
1071fb4eb4e8SReza Sabdar 	    sels, exls, flags, 0, NULL, NULL);
10722654012fSReza Sabdar 
10732654012fSReza Sabdar 	/*
10742654012fSReza Sabdar 	 * teardown
10752654012fSReza Sabdar 	 */
10762654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "end restore job %s", job);
10772654012fSReza Sabdar 	tlm_un_ref_job_stats(job);
10782654012fSReza Sabdar 	tlm_release_list(sels);
10792654012fSReza Sabdar 	tlm_release_list(exls);
10802654012fSReza Sabdar 
10812654012fSReza Sabdar 	commands->tcs_writer_count--;
10822654012fSReza Sabdar 	local_commands->tc_reader = TLM_STOP;
10832654012fSReza Sabdar 	tlm_release_reader_writer_ipc(local_commands);
10842654012fSReza Sabdar 	free(dir);
1085*82049ff5SToomas Soome 	return ((void *)(uintptr_t)erc);
10862654012fSReza Sabdar }
10872654012fSReza Sabdar 
10882654012fSReza Sabdar /*
10892654012fSReza Sabdar  * Creates the directories all the way down to the
10902654012fSReza Sabdar  * end if they dont exist
10912654012fSReza Sabdar  */
10922654012fSReza Sabdar int
make_dirs(char * dir)10932654012fSReza Sabdar make_dirs(char *dir)
10942654012fSReza Sabdar {
10952654012fSReza Sabdar 	char c;