xref: /titanic_51/usr/src/cmd/ndmpd/ndmp/ndmpd_tar3.c (revision a23888a301b4822208e58d55cccf1b42c8e46cc7)
12654012fSReza Sabdar /*
28c4f9701SJanice Chang  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
32654012fSReza Sabdar  */
42654012fSReza Sabdar 
52654012fSReza Sabdar /*
62654012fSReza Sabdar  * BSD 3 Clause License
72654012fSReza Sabdar  *
82654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
92654012fSReza Sabdar  *
102654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
112654012fSReza Sabdar  * modification, are permitted provided that the following conditions
122654012fSReza Sabdar  * are met:
132654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
142654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
152654012fSReza Sabdar  *
162654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
172654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
182654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
192654012fSReza Sabdar  *	  distribution.
202654012fSReza Sabdar  *
212654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
222654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
232654012fSReza Sabdar  *	  products derived from this software without specific prior written
242654012fSReza Sabdar  *	  permission.
252654012fSReza Sabdar  *
262654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
272654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
282654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
292654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
302654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
312654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
322654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
332654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
342654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
352654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
362654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
372654012fSReza Sabdar  */
388c4f9701SJanice Chang /* Copyright (c) 2007, The Storage Networking Industry Association. */
398c4f9701SJanice Chang /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40*a23888a3SJan Kryl /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
41*a23888a3SJan Kryl 
422654012fSReza Sabdar #include <sys/stat.h>
432654012fSReza Sabdar #include <sys/types.h>
442654012fSReza Sabdar #include <sys/time.h>
452654012fSReza Sabdar #include <ctype.h>
462654012fSReza Sabdar #include <sys/socket.h>
472654012fSReza Sabdar #include <sys/acl.h>
482654012fSReza Sabdar #include <netinet/in.h>
492654012fSReza Sabdar #include <arpa/inet.h>
502654012fSReza Sabdar #include <errno.h>
512654012fSReza Sabdar #include <stdio.h>
522654012fSReza Sabdar #include <string.h>
532654012fSReza Sabdar #include <time.h>
542654012fSReza Sabdar #include <cstack.h>
552654012fSReza Sabdar #include "ndmp.h"
562654012fSReza Sabdar #include "ndmpd.h"
572654012fSReza Sabdar #include <bitmap.h>
582654012fSReza Sabdar #include <traverse.h>
592654012fSReza Sabdar 
602654012fSReza Sabdar 
612654012fSReza Sabdar /*
622654012fSReza Sabdar  * Maximum length of the string-representation of u_longlong_t type.
632654012fSReza Sabdar  */
642654012fSReza Sabdar #define	QUAD_DECIMAL_LEN	20
652654012fSReza Sabdar 
662654012fSReza Sabdar 
67416eec61SReza Sabdar /* Is Y=yes or T=true */
682654012fSReza Sabdar #define	IS_YORT(c)	(strchr("YT", toupper(c)))
692654012fSReza Sabdar 
70416eec61SReza Sabdar /* Is F=file format (vs D=node-dir format) */
71416eec61SReza Sabdar #define	IS_F(c)		(toupper(c) == 'F')
722654012fSReza Sabdar 
732654012fSReza Sabdar /*
742654012fSReza Sabdar  * If path is defined.
752654012fSReza Sabdar  */
762654012fSReza Sabdar #define	ISDEFINED(cp)	((cp) && *(cp))
772654012fSReza Sabdar #define	SHOULD_LBRBK(bpp)	(!((bpp)->bp_opr & TLM_OP_CHOOSE_ARCHIVE))
782654012fSReza Sabdar 
792654012fSReza Sabdar /*
802654012fSReza Sabdar  * Component boundary means end of path or on a '/'.  At this
812654012fSReza Sabdar  * point both paths should be on component boundary.
822654012fSReza Sabdar  */
832654012fSReza Sabdar #define	COMPBNDRY(p)	(!*(p) || (*p) == '/')
842654012fSReza Sabdar 
852654012fSReza Sabdar typedef struct bk_param_v3 {
862654012fSReza Sabdar 	ndmpd_session_t *bp_session;
872654012fSReza Sabdar 	ndmp_lbr_params_t *bp_nlp;
882654012fSReza Sabdar 	tlm_job_stats_t *bp_js;
892654012fSReza Sabdar 	tlm_cmd_t *bp_lcmd;
902654012fSReza Sabdar 	tlm_commands_t *bp_cmds;
912654012fSReza Sabdar 	tlm_acls_t *bp_tlmacl;
922654012fSReza Sabdar 	int bp_opr;
932654012fSReza Sabdar 	char *bp_tmp;
942654012fSReza Sabdar 	char *bp_chkpnm;
952654012fSReza Sabdar 	char **bp_excls;
962654012fSReza Sabdar 	char *bp_unchkpnm;
972654012fSReza Sabdar } bk_param_v3_t;
982654012fSReza Sabdar 
992654012fSReza Sabdar 
1002654012fSReza Sabdar /*
1012654012fSReza Sabdar  * Multiple destination restore mode
1022654012fSReza Sabdar  */
1032654012fSReza Sabdar #define	MULTIPLE_DEST_DIRS 128
1042654012fSReza Sabdar 
1052654012fSReza Sabdar int multiple_dest_restore = 0;
1062654012fSReza Sabdar 
1072654012fSReza Sabdar /*
1082654012fSReza Sabdar  * Plug-in module ops
1092654012fSReza Sabdar  */
1102654012fSReza Sabdar ndmp_plugin_t *ndmp_pl;
1112654012fSReza Sabdar 
1122654012fSReza Sabdar /*
1132654012fSReza Sabdar  * NDMP exclusion list
1142654012fSReza Sabdar  */
1152654012fSReza Sabdar char **ndmp_excl_list = NULL;
1162654012fSReza Sabdar 
1172654012fSReza Sabdar /*
1182654012fSReza Sabdar  * split_env
1192654012fSReza Sabdar  *
1202654012fSReza Sabdar  * Splits the string into list of sections separated by the
1212654012fSReza Sabdar  * sep character.
1222654012fSReza Sabdar  *
1232654012fSReza Sabdar  * Parameters:
1242654012fSReza Sabdar  *   envp (input) - the environment variable that should be broken
1252654012fSReza Sabdar  *   sep (input) - the separator character
1262654012fSReza Sabdar  *
1272654012fSReza Sabdar  * Returns:
1282654012fSReza Sabdar  *   Array of character pointers: On success.  The array is allocated
1292654012fSReza Sabdar  *	as well as all its entries.  They all should be freed by the
1302654012fSReza Sabdar  *	caller.
1312654012fSReza Sabdar  *   NULL: on error
1322654012fSReza Sabdar  */
1332654012fSReza Sabdar static char **
1342654012fSReza Sabdar split_env(char *envp, char sep)
1352654012fSReza Sabdar {
1362654012fSReza Sabdar 	char *bp, *cp, *ep;
1372654012fSReza Sabdar 	char *save;
1382654012fSReza Sabdar 	char **cpp;
1392654012fSReza Sabdar 	int n;
1402654012fSReza Sabdar 
1412654012fSReza Sabdar 	if (!envp)
1422654012fSReza Sabdar 		return (NULL);
1432654012fSReza Sabdar 
1442654012fSReza Sabdar 	while (isspace(*envp))
1452654012fSReza Sabdar 		envp++;
1462654012fSReza Sabdar 
1472654012fSReza Sabdar 	if (!*envp)
1482654012fSReza Sabdar 		return (NULL);
1492654012fSReza Sabdar 
1502654012fSReza Sabdar 	bp = save = strdup(envp);
1512654012fSReza Sabdar 	if (!bp)
1522654012fSReza Sabdar 		return (NULL);
1532654012fSReza Sabdar 
1542654012fSReza Sabdar 	/*
1552654012fSReza Sabdar 	 * Since the env variable is not empty, it contains at least one
1562654012fSReza Sabdar 	 * component
1572654012fSReza Sabdar 	 */
1582654012fSReza Sabdar 	n = 1;
1592654012fSReza Sabdar 	while ((cp = strchr(bp, sep))) {
1602654012fSReza Sabdar 		if (cp > save && *(cp-1) != '\\')
1612654012fSReza Sabdar 			n++;
1622654012fSReza Sabdar 
1632654012fSReza Sabdar 		bp = cp + 1;
1642654012fSReza Sabdar 	}
1652654012fSReza Sabdar 
1662654012fSReza Sabdar 	n++; /* for the terminating NULL pointer */
1672654012fSReza Sabdar 	cpp = ndmp_malloc(sizeof (char *) * n);
1682654012fSReza Sabdar 	if (!cpp) {
1692654012fSReza Sabdar 		free(save);
1702654012fSReza Sabdar 		return (NULL);
1712654012fSReza Sabdar 	}
1722654012fSReza Sabdar 
1732654012fSReza Sabdar 	(void) memset(cpp, 0, n * sizeof (char *));
1742654012fSReza Sabdar 	n = 0;
1752654012fSReza Sabdar 	cp = bp = ep = save;
1762654012fSReza Sabdar 	while (*cp)
1772654012fSReza Sabdar 		if (*cp == sep) {
1782654012fSReza Sabdar 			*ep = '\0';
1792654012fSReza Sabdar 			if (strlen(bp) > 0) {
1802654012fSReza Sabdar 				cpp[n] = strdup(bp);
1812654012fSReza Sabdar 				if (!cpp[n++]) {
1822654012fSReza Sabdar 					tlm_release_list(cpp);
1832654012fSReza Sabdar 					cpp = NULL;
1842654012fSReza Sabdar 					break;
1852654012fSReza Sabdar 				}
1862654012fSReza Sabdar 			}
1872654012fSReza Sabdar 			ep = bp = ++cp;
1882654012fSReza Sabdar 		} else if (*cp == '\\') {
1892654012fSReza Sabdar 			++cp;
1902654012fSReza Sabdar 			if (*cp == 'n') {	/* "\n" */
1912654012fSReza Sabdar 				*ep++ = '\n';
1922654012fSReza Sabdar 				cp++;
1932654012fSReza Sabdar 			} else if (*cp == 't') {	/* "\t" */
1942654012fSReza Sabdar 				*ep++ = '\t';
1952654012fSReza Sabdar 				cp++;
1962654012fSReza Sabdar 			} else
1972654012fSReza Sabdar 				*ep++ = *cp++;
1982654012fSReza Sabdar 		} else
1992654012fSReza Sabdar 			*ep++ = *cp++;
2002654012fSReza Sabdar 
2012654012fSReza Sabdar 	*ep = '\0';
2022654012fSReza Sabdar 	if (cpp) {
2032654012fSReza Sabdar 		if (strlen(bp) > 0) {
2042654012fSReza Sabdar 			cpp[n] = strdup(bp);
2052654012fSReza Sabdar 			if (!cpp[n++]) {
2062654012fSReza Sabdar 				tlm_release_list(cpp);
2072654012fSReza Sabdar 				cpp = NULL;
2082654012fSReza Sabdar 			} else
2092654012fSReza Sabdar 				cpp[n] = NULL;
2102654012fSReza Sabdar 		}
2112654012fSReza Sabdar 
2122654012fSReza Sabdar 		if (n == 0 && cpp != NULL) {
2132654012fSReza Sabdar 			tlm_release_list(cpp);
2142654012fSReza Sabdar 			cpp = NULL;
2152654012fSReza Sabdar 		}
2162654012fSReza Sabdar 	}
2172654012fSReza Sabdar 
2182654012fSReza Sabdar 	free(save);
2192654012fSReza Sabdar 	return (cpp);
2202654012fSReza Sabdar }
2212654012fSReza Sabdar 
2222654012fSReza Sabdar 
2232654012fSReza Sabdar /*
2242654012fSReza Sabdar  * prl
2252654012fSReza Sabdar  *
2262654012fSReza Sabdar  * Print the array of character pointers passed to it.  This is
2272654012fSReza Sabdar  * used for debugging purpose.
2282654012fSReza Sabdar  *
2292654012fSReza Sabdar  * Parameters:
2302654012fSReza Sabdar  *   lpp (input) - pointer to the array of strings
2312654012fSReza Sabdar  *
2322654012fSReza Sabdar  * Returns:
2332654012fSReza Sabdar  *   void
2342654012fSReza Sabdar  */
2352654012fSReza Sabdar static void
2362654012fSReza Sabdar prl(char **lpp)
2372654012fSReza Sabdar {
2382654012fSReza Sabdar 	if (!lpp) {
2392654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "empty");
2402654012fSReza Sabdar 		return;
2412654012fSReza Sabdar 	}
2422654012fSReza Sabdar 
2432654012fSReza Sabdar 	while (*lpp)
2442654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "\"%s\"", *lpp++);
2452654012fSReza Sabdar }
2462654012fSReza Sabdar 
2472654012fSReza Sabdar 
2482654012fSReza Sabdar /*
2492654012fSReza Sabdar  * inlist
2502654012fSReza Sabdar  *
2512654012fSReza Sabdar  * Looks through all the strings of the array to see if the ent
2522654012fSReza Sabdar  * matches any of the strings.  The strings are patterns.
2532654012fSReza Sabdar  *
2542654012fSReza Sabdar  * Parameters:
2552654012fSReza Sabdar  *   lpp (input) - pointer to the array of strings
2562654012fSReza Sabdar  *   ent (input) - the entry to be matched
2572654012fSReza Sabdar  *
2582654012fSReza Sabdar  * Returns:
2592654012fSReza Sabdar  *   TRUE: if there is a match
2602654012fSReza Sabdar  *   FALSE: invalid argument or no match
2612654012fSReza Sabdar  */
2622654012fSReza Sabdar static boolean_t
2632654012fSReza Sabdar inlist(char **lpp, char *ent)
2642654012fSReza Sabdar {
2652654012fSReza Sabdar 	if (!lpp || !ent) {
2662654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "empty list");
2672654012fSReza Sabdar 		return (FALSE);
2682654012fSReza Sabdar 	}
2692654012fSReza Sabdar 
2702654012fSReza Sabdar 	while (*lpp) {
2712654012fSReza Sabdar 		/*
2722654012fSReza Sabdar 		 * Fixing the sync_sort NDMPV3 problem, it sends the inclusion
2732654012fSReza Sabdar 		 * like "./" which we should skip the "./"
2742654012fSReza Sabdar 		 */
2752654012fSReza Sabdar 		char *pattern = *lpp;
2762654012fSReza Sabdar 		if (strncmp(pattern, "./", 2) == 0)
2772654012fSReza Sabdar 			pattern += 2;
2782654012fSReza Sabdar 
2792654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "pattern %s, ent %s", pattern, ent);
2802654012fSReza Sabdar 
2812654012fSReza Sabdar 		if (match(pattern, ent)) {
2822654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "match(%s,%s)", pattern, ent);
2832654012fSReza Sabdar 			return (TRUE);
2842654012fSReza Sabdar 		}
2852654012fSReza Sabdar 		lpp++;
2862654012fSReza Sabdar 	}
2872654012fSReza Sabdar 
2882654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "no match");
2892654012fSReza Sabdar 	return (FALSE);
2902654012fSReza Sabdar }
2912654012fSReza Sabdar 
2922654012fSReza Sabdar 
2932654012fSReza Sabdar /*
2942654012fSReza Sabdar  * inexl
2952654012fSReza Sabdar  *
2962654012fSReza Sabdar  * Checks if the entry is in the list.  This is used for exclusion
2972654012fSReza Sabdar  * list.  If the exclusion list is empty, FALSE should be returned
2982654012fSReza Sabdar  * showing that nothing should be excluded by default.
2992654012fSReza Sabdar  *
3002654012fSReza Sabdar  * Parameters:
3012654012fSReza Sabdar  *   lpp (input) - pointer to the array of strings
3022654012fSReza Sabdar  *   ent (input) - the entry to be matched
3032654012fSReza Sabdar  *
3042654012fSReza Sabdar  * Returns:
3052654012fSReza Sabdar  *   TRUE: if there is a match
3062654012fSReza Sabdar  *   FALSE: invalid argument or no match
3072654012fSReza Sabdar  *
3082654012fSReza Sabdar  */
3092654012fSReza Sabdar static boolean_t
3102654012fSReza Sabdar inexl(char **lpp, char *ent)
3112654012fSReza Sabdar {
3122654012fSReza Sabdar 	if (!lpp || !ent)
3132654012fSReza Sabdar 		return (FALSE);
3142654012fSReza Sabdar 
3152654012fSReza Sabdar 	return (inlist(lpp, ent));
3162654012fSReza Sabdar }
3172654012fSReza Sabdar 
3182654012fSReza Sabdar 
3192654012fSReza Sabdar /*
3202654012fSReza Sabdar  * ininc
3212654012fSReza Sabdar  *
3222654012fSReza Sabdar  * Checks if the entry is in the list.  This is used for inclusion
3232654012fSReza Sabdar  * list.  If the inclusion list is empty, TRUE should be returned
3242654012fSReza Sabdar  * showing that everything should be included by default.
3252654012fSReza Sabdar  *
3262654012fSReza Sabdar  * Parameters:
3272654012fSReza Sabdar  *   lpp (input) - pointer to the array of strings
3282654012fSReza Sabdar  *   ent (input) - the entry to be matched
3292654012fSReza Sabdar  *
3302654012fSReza Sabdar  * Returns:
3312654012fSReza Sabdar  *   TRUE: if there is a match or the list is empty
3322654012fSReza Sabdar  *   FALSE: no match
3332654012fSReza Sabdar  */
3342654012fSReza Sabdar static boolean_t
3352654012fSReza Sabdar ininc(char **lpp, char *ent)
3362654012fSReza Sabdar {
3372654012fSReza Sabdar 	if (!lpp || !ent || !*ent)
3382654012fSReza Sabdar 		return (TRUE);
3392654012fSReza Sabdar 
3402654012fSReza Sabdar 	return (inlist(lpp, ent));
3412654012fSReza Sabdar }
3422654012fSReza Sabdar 
3432654012fSReza Sabdar 
3442654012fSReza Sabdar /*
3452654012fSReza Sabdar  * setupsels
3462654012fSReza Sabdar  *
3472654012fSReza Sabdar  * Set up the selection list for Local B/R functions.  A new array of
3482654012fSReza Sabdar  * "char *" is created and the pointers point to the original paths of
3492654012fSReza Sabdar  * the Nlist.
3502654012fSReza Sabdar  *
3512654012fSReza Sabdar  * Parameters:
3522654012fSReza Sabdar  *   session (input) - pointer to the session
3532654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
3542654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
3552654012fSReza Sabdar  *   index(input) - If not zero is the DAR entry position
3562654012fSReza Sabdar  *
3572654012fSReza Sabdar  * Returns:
3582654012fSReza Sabdar  *   list pointer: on success
3592654012fSReza Sabdar  *   NULL: on error
3602654012fSReza Sabdar  */
3612654012fSReza Sabdar /*ARGSUSED*/
3622654012fSReza Sabdar char **
3632654012fSReza Sabdar setupsels(ndmpd_session_t *session, ndmpd_module_params_t *params,
3642654012fSReza Sabdar     ndmp_lbr_params_t *nlp, int index)
3652654012fSReza Sabdar {
3662654012fSReza Sabdar 	char **lpp, **save;
3672654012fSReza Sabdar 	int i, n;
3682654012fSReza Sabdar 	int len;
3692654012fSReza Sabdar 	int start, end;
3702654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
3712654012fSReza Sabdar 
3722654012fSReza Sabdar 	n = session->ns_data.dd_nlist_len;
3732654012fSReza Sabdar 
3742654012fSReza Sabdar 	save = lpp = ndmp_malloc(sizeof (char *) * (n + 1));
3752654012fSReza Sabdar 	if (!lpp) {
3762654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR, "Insufficient memory.\n");
3772654012fSReza Sabdar 		return (NULL);
3782654012fSReza Sabdar 	}
3792654012fSReza Sabdar 
3802654012fSReza Sabdar 	if (index) { /* DAR, just one entry */
3812654012fSReza Sabdar 		/*
3822654012fSReza Sabdar 		 * We have to setup a list of strings that will not match any
3832654012fSReza Sabdar 		 * file. One DAR entry will be added in the right position later
3842654012fSReza Sabdar 		 * in this function.
3852654012fSReza Sabdar 		 * When the match is called from tar_getdir the
3862654012fSReza Sabdar 		 * location of the selection that matches the entry is
3872654012fSReza Sabdar 		 * important
3882654012fSReza Sabdar 		 */
3892654012fSReza Sabdar 		for (i = 0; i < n; ++i)
3902654012fSReza Sabdar 			*(lpp+i) = " ";
3912654012fSReza Sabdar 		n = 1;
3922654012fSReza Sabdar 		start = index-1;
3932654012fSReza Sabdar 		end = start+1;
3942654012fSReza Sabdar 		lpp += start; /* Next selection entry will be in lpp[start] */
3952654012fSReza Sabdar 	} else {
3962654012fSReza Sabdar 		start = 0;
3972654012fSReza Sabdar 		end = n;
3982654012fSReza Sabdar 	}
3992654012fSReza Sabdar 
4002654012fSReza Sabdar 	for (i = start; i < end; i++) {
4012654012fSReza Sabdar 		ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
4022654012fSReza Sabdar 		if (!ep)
4032654012fSReza Sabdar 			continue;
4042654012fSReza Sabdar 
4052654012fSReza Sabdar 		/*
4062654012fSReza Sabdar 		 * Check for clients that send original path as "."(like
4072654012fSReza Sabdar 		 * CA products). In this situation opath is something like
4082654012fSReza Sabdar 		 * "/v1/." and we should change it to "/v1/"
4092654012fSReza Sabdar 		 */
4102654012fSReza Sabdar 		len = strlen(ep->nm3_opath);
4112654012fSReza Sabdar 		if (len > 1 && ep->nm3_opath[len-2] == '/' &&
4122654012fSReza Sabdar 		    ep->nm3_opath[len-1] == '.') {
4132654012fSReza Sabdar 			ep->nm3_opath[len-1] = '\0';
4142654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
4152654012fSReza Sabdar 			    "nm3_opath changed from %s. to %s",
4162654012fSReza Sabdar 			    ep->nm3_opath, ep->nm3_opath);
4172654012fSReza Sabdar 		}
4182654012fSReza Sabdar 		*lpp++ = ep->nm3_opath;
4192654012fSReza Sabdar 	}
4202654012fSReza Sabdar 
4212654012fSReza Sabdar 	/* list termination indicator is a null pointer */
4222654012fSReza Sabdar 	*lpp = NULL;
4232654012fSReza Sabdar 
4242654012fSReza Sabdar 	return (save);
4252654012fSReza Sabdar }
4262654012fSReza Sabdar 
4272654012fSReza Sabdar 
4282654012fSReza Sabdar /*
4292654012fSReza Sabdar  * mkrsp
4302654012fSReza Sabdar  *
4312654012fSReza Sabdar  * Make Restore Path.
4322654012fSReza Sabdar  * It gets a path, a selection (with which the path has matched) a new
4332654012fSReza Sabdar  * name and makes a new name for the path.
4342654012fSReza Sabdar  * All the components of the path and the selection are skipped as long
4352654012fSReza Sabdar  * as they are the same.  If either of the path or selection are not on
4362654012fSReza Sabdar  * a component boundary, the match was reported falsefully and no new name
4372654012fSReza Sabdar  * is generated(Except the situation in which both path and selection
4382654012fSReza Sabdar  * end with trailing '/' and selection is the prefix of the path).
4392654012fSReza Sabdar  * Otherwise, the remaining of the path is appended to the
4402654012fSReza Sabdar  * new name.  The result is saved in the buffer passed.
4412654012fSReza Sabdar  *
4422654012fSReza Sabdar  * Parameters:
4432654012fSReza Sabdar  *   bp (output) - pointer to the result buffer
4442654012fSReza Sabdar  *   pp (input) - pointer to the path
4452654012fSReza Sabdar  *   sp (input) - pointer to the selection
4462654012fSReza Sabdar  *   np (input) - pointer to the new name
4472654012fSReza Sabdar  *
4482654012fSReza Sabdar  * Returns:
4492654012fSReza Sabdar  *   pointer to the bp: on success
4502654012fSReza Sabdar  *   NULL: otherwise
4512654012fSReza Sabdar  */
4522654012fSReza Sabdar char *
4532654012fSReza Sabdar mkrsp(char *bp, char *pp, char *sp, char *np)
4542654012fSReza Sabdar {
4552654012fSReza Sabdar 	if (!bp || !pp)
4562654012fSReza Sabdar 		return (NULL);
4572654012fSReza Sabdar 
4582654012fSReza Sabdar 
4592654012fSReza Sabdar 	pp += strspn(pp, "/");
4602654012fSReza Sabdar 	if (sp) {
4612654012fSReza Sabdar 		sp += strspn(sp, "/");
4622654012fSReza Sabdar 
4632654012fSReza Sabdar 		/* skip as much as match */
4642654012fSReza Sabdar 		while (*sp && *pp && *sp == *pp) {
4652654012fSReza Sabdar 			sp++;
4662654012fSReza Sabdar 			pp++;
4672654012fSReza Sabdar 		}
4682654012fSReza Sabdar 
4692654012fSReza Sabdar 		if (!COMPBNDRY(pp) || !COMPBNDRY(sp))
4702654012fSReza Sabdar 			/* An exception to the boundary rule */
4712654012fSReza Sabdar 			/* (!(!*sp && (*(pp - 1)) == '/')) */
4722654012fSReza Sabdar 			if (*sp || (*(pp - 1)) != '/')
4732654012fSReza Sabdar 				return (NULL);
4742654012fSReza Sabdar 
4752654012fSReza Sabdar 		/* if pp shorter than sp, it should not be restored */
4762654012fSReza Sabdar 		if (!*pp && *sp) {
4772654012fSReza Sabdar 			sp += strspn(sp, "/");
4782654012fSReza Sabdar 			if (strlen(sp) > 0)
4792654012fSReza Sabdar 				return (NULL);
4802654012fSReza Sabdar 		}
4812654012fSReza Sabdar 	}
4822654012fSReza Sabdar 
4832654012fSReza Sabdar 	if (np)
4842654012fSReza Sabdar 		np += strspn(np, "/");
4852654012fSReza Sabdar 	else
4862654012fSReza Sabdar 		np = "";
4872654012fSReza Sabdar 
4882654012fSReza Sabdar 	if (!tlm_cat_path(bp, np, pp)) {
4892654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Restore path too long %s/%s.", np, pp);
4902654012fSReza Sabdar 		return (NULL);
4912654012fSReza Sabdar 	}
4922654012fSReza Sabdar 
4932654012fSReza Sabdar 	return (bp);
4942654012fSReza Sabdar }
4952654012fSReza Sabdar 
4962654012fSReza Sabdar 
4972654012fSReza Sabdar /*
4982654012fSReza Sabdar  * mknewname
4992654012fSReza Sabdar  *
5002654012fSReza Sabdar  * This is used as callback for creating the restore path. This function
5012654012fSReza Sabdar  * can handle both single destination and multiple restore paths.
5022654012fSReza Sabdar  *
5032654012fSReza Sabdar  * Make up the restore destination path for a particular file/directory, path,
5042654012fSReza Sabdar  * based on nm3_opath and nm3_dpath.  path should have matched nm3_opath
5052654012fSReza Sabdar  * in some way.
5062654012fSReza Sabdar  */
5072654012fSReza Sabdar char *
5082654012fSReza Sabdar mknewname(struct rs_name_maker *rnp, char *buf, int idx, char *path)
5092654012fSReza Sabdar {
5102654012fSReza Sabdar 	char *rv;
5112654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
5122654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
5132654012fSReza Sabdar 
5142654012fSReza Sabdar 	rv = NULL;
5152654012fSReza Sabdar 	if (!buf) {
5162654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "buf is NULL");
5172654012fSReza Sabdar 	} else if (!path) {
5182654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "path is NULL");
5192654012fSReza Sabdar 	} else if ((nlp = rnp->rn_nlp) == 0) {
5202654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "rnp->rn_nlp is NULL");
5212654012fSReza Sabdar 	} else if (!nlp->nlp_params) {
5222654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp->nlp_params is NULL");
5232654012fSReza Sabdar 	} else
5242654012fSReza Sabdar 		if (!ndmp_full_restore_path) {
5252654012fSReza Sabdar 			if (idx < 0 || idx >= (int)nlp->nlp_nfiles) {
5262654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
5272654012fSReza Sabdar 				    "Invalid idx %d range (0, %d)",
5282654012fSReza Sabdar 				    idx, nlp->nlp_nfiles);
5292654012fSReza Sabdar 			} else if (!(ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(
5302654012fSReza Sabdar 			    nlp->nlp_params, idx))) {
5312654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
5322654012fSReza Sabdar 				    "nlist entry %d is NULL", idx);
5332654012fSReza Sabdar 			} else {
5342654012fSReza Sabdar 				rv = mkrsp(buf, path, ep->nm3_opath,
5352654012fSReza Sabdar 				    ep->nm3_dpath);
5362654012fSReza Sabdar 
5372654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
5382654012fSReza Sabdar 				    "idx %d org \"%s\" dst \"%s\"",
5392654012fSReza Sabdar 				    idx, ep->nm3_opath, ep->nm3_dpath);
5402654012fSReza Sabdar 				if (rv) {
5412654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
5422654012fSReza Sabdar 					    "path \"%s\": \"%s\"", path, rv);
5432654012fSReza Sabdar 				} else {
5442654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
5452654012fSReza Sabdar 					    "path \"%s\": NULL", path);
5462654012fSReza Sabdar 				}
5472654012fSReza Sabdar 			}
5482654012fSReza Sabdar 		} else {
5492654012fSReza Sabdar 			if (!tlm_cat_path(buf, nlp->nlp_restore_path, path)) {
5502654012fSReza Sabdar 				NDMP_LOG(LOG_ERR, "Path too long %s/%s.",
5512654012fSReza Sabdar 				    nlp->nlp_restore_path, path);
5522654012fSReza Sabdar 				rv = NULL;
5532654012fSReza Sabdar 			} else {
5542654012fSReza Sabdar 				rv = buf;
5552654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
5562654012fSReza Sabdar 				    "path \"%s\": \"%s\"", path, rv);
5572654012fSReza Sabdar 			}
5582654012fSReza Sabdar 		}
5592654012fSReza Sabdar 
5602654012fSReza Sabdar 	return (rv);
5612654012fSReza Sabdar }
5622654012fSReza Sabdar 
5632654012fSReza Sabdar 
5642654012fSReza Sabdar /*
5652654012fSReza Sabdar  * chopslash
5662654012fSReza Sabdar  *
5672654012fSReza Sabdar  * Remove the slash from the end of the given path
5682654012fSReza Sabdar  */
5692654012fSReza Sabdar static void
5702654012fSReza Sabdar chopslash(char *cp)
5712654012fSReza Sabdar {
5722654012fSReza Sabdar 	int ln;
5732654012fSReza Sabdar 
5742654012fSReza Sabdar 	if (!cp || !*cp)
5752654012fSReza Sabdar 		return;
5762654012fSReza Sabdar 
5772654012fSReza Sabdar 	ln = strlen(cp);
5782654012fSReza Sabdar 	cp += ln - 1; /* end of the string */
5792654012fSReza Sabdar 	while (ln > 0 && *cp == '/') {
5802654012fSReza Sabdar 		*cp-- = '\0';
5812654012fSReza Sabdar 		ln--;
5822654012fSReza Sabdar 	}
5832654012fSReza Sabdar }
5842654012fSReza Sabdar 
5852654012fSReza Sabdar 
5862654012fSReza Sabdar /*
5872654012fSReza Sabdar  * joinpath
5882654012fSReza Sabdar  *
5892654012fSReza Sabdar  * Join two given paths
5902654012fSReza Sabdar  */
5912654012fSReza Sabdar static char *
5922654012fSReza Sabdar joinpath(char *bp, char *pp, char *np)
5932654012fSReza Sabdar {
5942654012fSReza Sabdar 	if (pp && *pp) {
5952654012fSReza Sabdar 		if (np && *np)
5962654012fSReza Sabdar 			(void) tlm_cat_path(bp, pp, np);
5972654012fSReza Sabdar 		else
5982654012fSReza Sabdar 			(void) strlcpy(bp, pp, TLM_MAX_PATH_NAME);
5992654012fSReza Sabdar 	} else {
6002654012fSReza Sabdar 		if (np && *np)
6012654012fSReza Sabdar 			(void) strlcpy(bp, np, TLM_MAX_PATH_NAME);
6022654012fSReza Sabdar 		else
6032654012fSReza Sabdar 			bp = NULL;
6042654012fSReza Sabdar 	}
6052654012fSReza Sabdar 
6062654012fSReza Sabdar 	return (bp);
6072654012fSReza Sabdar }
6082654012fSReza Sabdar 
6092654012fSReza Sabdar 
6102654012fSReza Sabdar /*
6112654012fSReza Sabdar  * voliswr
6122654012fSReza Sabdar  *
6132654012fSReza Sabdar  * Is the volume writable?
6142654012fSReza Sabdar  */
6152654012fSReza Sabdar static int
6162654012fSReza Sabdar voliswr(char *path)
6172654012fSReza Sabdar {
6182654012fSReza Sabdar 	int rv;
6192654012fSReza Sabdar 
6202654012fSReza Sabdar 	if (!path)
6212654012fSReza Sabdar 		return (0);
6222654012fSReza Sabdar 
6232654012fSReza Sabdar 	rv = !fs_is_rdonly(path) && !fs_is_chkpntvol(path);
6242654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "%d path \"%s\"", rv, path);
6252654012fSReza Sabdar 	return (rv);
6262654012fSReza Sabdar 
6272654012fSReza Sabdar }
6282654012fSReza Sabdar 
6292654012fSReza Sabdar 
6302654012fSReza Sabdar /*
6312654012fSReza Sabdar  * is_valid_backup_dir_v3
6322654012fSReza Sabdar  *
6332654012fSReza Sabdar  * Checks the validity of the backup path.  Backup path should
6342654012fSReza Sabdar  * have the following characteristics to be valid:
6352654012fSReza Sabdar  *	1) It should be an absolute path.
6362654012fSReza Sabdar  *	2) It should be a directory.
6372654012fSReza Sabdar  *	3) It should not be checkpoint root directory
6382654012fSReza Sabdar  *	4) If the file system is read-only, the backup path
6392654012fSReza Sabdar  *	    should be a checkpointed path.  Checkpoint cannot
6402654012fSReza Sabdar  *	    be created on a read-only file system.
6412654012fSReza Sabdar  *
6422654012fSReza Sabdar  * Parameters:
6432654012fSReza Sabdar  *   params (input) - pointer to the parameters structure.
6442654012fSReza Sabdar  *   bkpath (input) - the backup path
6452654012fSReza Sabdar  *
6462654012fSReza Sabdar  * Returns:
6472654012fSReza Sabdar  *   TRUE: if everything's OK
6482654012fSReza Sabdar  *   FALSE: otherwise.
6492654012fSReza Sabdar  */
6502654012fSReza Sabdar static boolean_t
6512654012fSReza Sabdar is_valid_backup_dir_v3(ndmpd_module_params_t *params, char *bkpath)
6522654012fSReza Sabdar {
6532654012fSReza Sabdar 	char *msg;
6542654012fSReza Sabdar 	struct stat64 st;
6552654012fSReza Sabdar 
6562654012fSReza Sabdar 	if (*bkpath != '/') {
6572654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
6582654012fSReza Sabdar 		    "Relative backup path not allowed \"%s\".\n", bkpath);
6592654012fSReza Sabdar 		return (FALSE);
6602654012fSReza Sabdar 	}
6612654012fSReza Sabdar 	if (stat64(bkpath, &st) < 0) {
6622654012fSReza Sabdar 		msg = strerror(errno);
6632654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR, "\"%s\" %s.\n",
6642654012fSReza Sabdar 		    bkpath, msg);
6652654012fSReza Sabdar 		return (FALSE);
6662654012fSReza Sabdar 	}
6672654012fSReza Sabdar 	if (!S_ISDIR(st.st_mode)) {
6682654012fSReza Sabdar 		/* only directories can be specified as the backup path */
6692654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
6702654012fSReza Sabdar 		    "\"%s\" is not a directory.\n", bkpath);
6712654012fSReza Sabdar 		return (FALSE);
6722654012fSReza Sabdar 	}
6732654012fSReza Sabdar 	if (fs_is_rdonly(bkpath) && !fs_is_chkpntvol(bkpath) &&
6742654012fSReza Sabdar 	    fs_is_chkpnt_enabled(bkpath)) {
6752654012fSReza Sabdar 		/* it is not a chkpnted path */
6762654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
6772654012fSReza Sabdar 		    "\"%s\" is not a checkpointed path.\n", bkpath);
6782654012fSReza Sabdar 		return (FALSE);
6792654012fSReza Sabdar 	}
6802654012fSReza Sabdar 
6812654012fSReza Sabdar 	return (TRUE);
6822654012fSReza Sabdar }
6832654012fSReza Sabdar 
6842654012fSReza Sabdar 
6852654012fSReza Sabdar /*
6862654012fSReza Sabdar  * log_date_token_v3
6872654012fSReza Sabdar  *
6882654012fSReza Sabdar  * Log the token sequence number and also the date of the
6892654012fSReza Sabdar  * last backup for token-based backup in the system log
6902654012fSReza Sabdar  * and also send them as normal log to the client.
6912654012fSReza Sabdar  *
6922654012fSReza Sabdar  * Parameters:
6932654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
6942654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
6952654012fSReza Sabdar  *
6962654012fSReza Sabdar  * Returns:
6972654012fSReza Sabdar  *   void
6982654012fSReza Sabdar  */
6992654012fSReza Sabdar static void
7002654012fSReza Sabdar log_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
7012654012fSReza Sabdar {
7022654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "Token sequence counter: %d.\n",
7032654012fSReza Sabdar 	    nlp->nlp_tokseq);
7042654012fSReza Sabdar 
7052654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "Date of the last backup: %s.\n",
7062654012fSReza Sabdar 	    cctime(&nlp->nlp_tokdate));
7072654012fSReza Sabdar 
7082654012fSReza Sabdar 	if (nlp->nlp_dmpnm) {
7092654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
7102654012fSReza Sabdar 		    "Backup date log file name: \"%s\".\n", nlp->nlp_dmpnm);
7112654012fSReza Sabdar 	}
7122654012fSReza Sabdar }
7132654012fSReza Sabdar 
7142654012fSReza Sabdar 
7152654012fSReza Sabdar /*
7162654012fSReza Sabdar  * log_lbr_bk_v3
7172654012fSReza Sabdar  *
7182654012fSReza Sabdar  * Log the backup level and data of the backup for LBR-type
7192654012fSReza Sabdar  * backup in the system log and also send them as normal log
7202654012fSReza Sabdar  * to the client.
7212654012fSReza Sabdar  *
7222654012fSReza Sabdar  * Parameters:
7232654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
7242654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
7252654012fSReza Sabdar  *
7262654012fSReza Sabdar  * Returns:
7272654012fSReza Sabdar  *   void
7282654012fSReza Sabdar  */
7292654012fSReza Sabdar static void
7302654012fSReza Sabdar log_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
7312654012fSReza Sabdar {
7322654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL,
7332654012fSReza Sabdar 	    "Date of this level '%c': %s.\n", nlp->nlp_clevel,
7342654012fSReza Sabdar 	    cctime(&nlp->nlp_cdate));
7352654012fSReza Sabdar 
7362654012fSReza Sabdar 	if (nlp->nlp_dmpnm) {
7372654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
7382654012fSReza Sabdar 		    "Backup date log file name: \"%s\".\n", nlp->nlp_dmpnm);
7392654012fSReza Sabdar 	}
7402654012fSReza Sabdar }
7412654012fSReza Sabdar 
7422654012fSReza Sabdar 
7432654012fSReza Sabdar /*
7442654012fSReza Sabdar  * log_level_v3
7452654012fSReza Sabdar  *
7462654012fSReza Sabdar  * Log the backup level and date of the last and the current
7472654012fSReza Sabdar  * backup for level-type backup in the system log and also
7482654012fSReza Sabdar  * send them as normal log to the client.
7492654012fSReza Sabdar  *
7502654012fSReza Sabdar  * Parameters:
7512654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
7522654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
7532654012fSReza Sabdar  *
7542654012fSReza Sabdar  * Returns:
7552654012fSReza Sabdar  *   void
7562654012fSReza Sabdar  */
7572654012fSReza Sabdar static void
7582654012fSReza Sabdar log_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
7592654012fSReza Sabdar {
7602654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL,
7612654012fSReza Sabdar 	    "Date of the last level '%u': %s.\n", nlp->nlp_llevel,
7622654012fSReza Sabdar 	    cctime(&nlp->nlp_ldate));
7632654012fSReza Sabdar 
7642654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL,
7652654012fSReza Sabdar 	    "Date of this level '%u': %s.\n", nlp->nlp_clevel,
7662654012fSReza Sabdar 	    cctime(&nlp->nlp_cdate));
7672654012fSReza Sabdar 
7682654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "Update: %s.\n",
7692654012fSReza Sabdar 	    NDMP_TORF(NLP_ISSET(nlp, NLPF_UPDATE)));
7702654012fSReza Sabdar }
7712654012fSReza Sabdar 
7722654012fSReza Sabdar 
7732654012fSReza Sabdar /*
7742654012fSReza Sabdar  * log_bk_params_v3
7752654012fSReza Sabdar  *
7762654012fSReza Sabdar  * Dispatcher function which calls the appropriate function
7772654012fSReza Sabdar  * for logging the backup date and level in the system log
7782654012fSReza Sabdar  * and also send them as normal log message to the client.
7792654012fSReza Sabdar  *
7802654012fSReza Sabdar  * Parameters:
7812654012fSReza Sabdar  *   session (input) - pointer to the session
7822654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
7832654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
7842654012fSReza Sabdar  *
7852654012fSReza Sabdar  * Returns:
7862654012fSReza Sabdar  *   void
7872654012fSReza Sabdar  */
7882654012fSReza Sabdar static void
7892654012fSReza Sabdar log_bk_params_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
7902654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
7912654012fSReza Sabdar {
7922654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "Backing up \"%s\".\n",
7932654012fSReza Sabdar 	    nlp->nlp_backup_path);
7942654012fSReza Sabdar 
7952654012fSReza Sabdar 	if (session->ns_mover.md_data_addr.addr_type == NDMP_ADDR_LOCAL)
7962654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
7972654012fSReza Sabdar 		    "Tape record size: %d.\n",
7982654012fSReza Sabdar 		    session->ns_mover.md_record_size);
7992654012fSReza Sabdar 
8002654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "File history: %c.\n",
8012654012fSReza Sabdar 	    NDMP_YORN(NLP_ISSET(nlp, NLPF_FH)));
8022654012fSReza Sabdar 
8032654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_TOKENBK))
8042654012fSReza Sabdar 		log_date_token_v3(params, nlp);
8052654012fSReza Sabdar 	else if (NLP_ISSET(nlp, NLPF_LBRBK))
8062654012fSReza Sabdar 		log_lbr_bk_v3(params, nlp);
8072654012fSReza Sabdar 	else if (NLP_ISSET(nlp, NLPF_LEVELBK))
8082654012fSReza Sabdar 		log_level_v3(params, nlp);
8092654012fSReza Sabdar 	else {
8102654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
8112654012fSReza Sabdar 		    "Internal error: backup level not defined for \"%s\".\n",
8122654012fSReza Sabdar 		    nlp->nlp_backup_path);
8132654012fSReza Sabdar 	}
8142654012fSReza Sabdar }
8152654012fSReza Sabdar 
8162654012fSReza Sabdar 
8172654012fSReza Sabdar /*
8182654012fSReza Sabdar  * get_update_env_v3
8192654012fSReza Sabdar  *
8202654012fSReza Sabdar  * Is the UPDATE environment variable specified?  If it is
8212654012fSReza Sabdar  * the corresponding flag is set in the flags field of the
8222654012fSReza Sabdar  * nlp structure, otherwise the flag is cleared.
8232654012fSReza Sabdar  *
8242654012fSReza Sabdar  * Parameters:
8252654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
8262654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
8272654012fSReza Sabdar  *
8282654012fSReza Sabdar  * Returns:
8292654012fSReza Sabdar  *   void
8302654012fSReza Sabdar  */
8312654012fSReza Sabdar static void
8322654012fSReza Sabdar get_update_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
8332654012fSReza Sabdar {
8342654012fSReza Sabdar 	char *envp;
8352654012fSReza Sabdar 
8362654012fSReza Sabdar 	envp = MOD_GETENV(params, "UPDATE");
8372654012fSReza Sabdar 	if (!envp) {
8382654012fSReza Sabdar 		NLP_SET(nlp, NLPF_UPDATE);
8392654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
8402654012fSReza Sabdar 		    "env(UPDATE) not defined, default to TRUE");
8412654012fSReza Sabdar 	} else {
8422654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(UPDATE): \"%s\"", envp);
8432654012fSReza Sabdar 		if (IS_YORT(*envp))
8442654012fSReza Sabdar 			NLP_SET(nlp, NLPF_UPDATE);
8452654012fSReza Sabdar 		else
8462654012fSReza Sabdar 			NLP_UNSET(nlp, NLPF_UPDATE);
8472654012fSReza Sabdar 	}
8482654012fSReza Sabdar }
8492654012fSReza Sabdar 
8502654012fSReza Sabdar 
8512654012fSReza Sabdar /*
8522654012fSReza Sabdar  * get_hist_env_v3
8532654012fSReza Sabdar  *
8542654012fSReza Sabdar  * Is backup history requested?  If it is, the corresponding
8552654012fSReza Sabdar  * flag is set in the flags field of the nlp structure, otherwise
8562654012fSReza Sabdar  * the flag is cleared.
8572654012fSReza Sabdar  *
8582654012fSReza Sabdar  * Parameters:
8592654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
8602654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
8612654012fSReza Sabdar  *
8622654012fSReza Sabdar  * Returns:
8632654012fSReza Sabdar  *   void
8642654012fSReza Sabdar  */
8652654012fSReza Sabdar static void
8662654012fSReza Sabdar get_hist_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
8672654012fSReza Sabdar {
8682654012fSReza Sabdar 	char *envp;
8692654012fSReza Sabdar 
8702654012fSReza Sabdar 	envp = MOD_GETENV(params, "HIST");
8712654012fSReza Sabdar 	if (!envp) {
8722654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(HIST) not defined");
8732654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_FH);
8742654012fSReza Sabdar 	} else {
8752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(HIST): \"%s\"", envp);
876416eec61SReza Sabdar 		if (IS_YORT(*envp) || IS_F(*envp))
8772654012fSReza Sabdar 			NLP_SET(nlp, NLPF_FH);
8782654012fSReza Sabdar 		else
8792654012fSReza Sabdar 			NLP_UNSET(nlp, NLPF_FH);
880416eec61SReza Sabdar 
881416eec61SReza Sabdar 		/* Force file format if specified */
882416eec61SReza Sabdar 		if (IS_F(*envp)) {
883416eec61SReza Sabdar 			params->mp_file_history_path_func =
884416eec61SReza Sabdar 			    ndmpd_api_file_history_file_v3;
885416eec61SReza Sabdar 			params->mp_file_history_dir_func = 0;
886416eec61SReza Sabdar 			params->mp_file_history_node_func = 0;
887416eec61SReza Sabdar 		}
8882654012fSReza Sabdar 	}
8892654012fSReza Sabdar }
8902654012fSReza Sabdar 
8912654012fSReza Sabdar 
8922654012fSReza Sabdar /*
8932654012fSReza Sabdar  * get_exc_env_v3
8942654012fSReza Sabdar  *
8952654012fSReza Sabdar  * Gets the EXCLUDE environment variable and breaks it
8962654012fSReza Sabdar  * into strings.  The separator of the EXCLUDE environment
8972654012fSReza Sabdar  * variable is the ',' character.
8982654012fSReza Sabdar  *
8992654012fSReza Sabdar  * Parameters:
9002654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
9012654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
9022654012fSReza Sabdar  *
9032654012fSReza Sabdar  * Returns:
9042654012fSReza Sabdar  *   void
9052654012fSReza Sabdar  */
9062654012fSReza Sabdar static void
9072654012fSReza Sabdar get_exc_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
9082654012fSReza Sabdar {
9092654012fSReza Sabdar 	char *envp;
9102654012fSReza Sabdar 
9112654012fSReza Sabdar 	envp = MOD_GETENV(params, "EXCLUDE");
9122654012fSReza Sabdar 	if (!envp) {
9132654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(EXCLUDE) not defined");
9142654012fSReza Sabdar 		nlp->nlp_exl = NULL;
9152654012fSReza Sabdar 	} else {
9162654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(EXCLUDE): \"%s\"", envp);
9172654012fSReza Sabdar 		nlp->nlp_exl = split_env(envp, ',');
9182654012fSReza Sabdar 		prl(nlp->nlp_exl);
9192654012fSReza Sabdar 	}
9202654012fSReza Sabdar }
9212654012fSReza Sabdar 
9222654012fSReza Sabdar 
9232654012fSReza Sabdar /*
9242654012fSReza Sabdar  * get_inc_env_v3
9252654012fSReza Sabdar  *
9262654012fSReza Sabdar  * Gets the FILES environment variable that shows which files
9272654012fSReza Sabdar  * should be backed up, and breaks it into strings.  The
9282654012fSReza Sabdar  * separator of the FILES environment variable is the space
9292654012fSReza Sabdar  * character.
9302654012fSReza Sabdar  *
9312654012fSReza Sabdar  * Parameters:
9322654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
9332654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
9342654012fSReza Sabdar  *
9352654012fSReza Sabdar  * Returns:
9362654012fSReza Sabdar  *   void
9372654012fSReza Sabdar  */
9382654012fSReza Sabdar static void
9392654012fSReza Sabdar get_inc_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
9402654012fSReza Sabdar {
9412654012fSReza Sabdar 	char *envp;
9422654012fSReza Sabdar 
9432654012fSReza Sabdar 	envp = MOD_GETENV(params, "FILES");
9442654012fSReza Sabdar 	if (!envp) {
9452654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(FILES) not defined");
9462654012fSReza Sabdar 		nlp->nlp_inc = NULL;
9472654012fSReza Sabdar 	} else {
9482654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(FILES): \"%s\"", envp);
9492654012fSReza Sabdar 		nlp->nlp_inc = split_env(envp, ' ');
9502654012fSReza Sabdar 		prl(nlp->nlp_inc);
9512654012fSReza Sabdar 	}
9522654012fSReza Sabdar }
9532654012fSReza Sabdar 
9542654012fSReza Sabdar 
9552654012fSReza Sabdar /*
9562654012fSReza Sabdar  * get_direct_env_v3
9572654012fSReza Sabdar  *
9582654012fSReza Sabdar  * Gets the DIRECT environment variable that shows if the fh_info should
9592654012fSReza Sabdar  * be sent to the client or not.
9602654012fSReza Sabdar  *
9612654012fSReza Sabdar  * Parameters:
9622654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
9632654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
9642654012fSReza Sabdar  *
9652654012fSReza Sabdar  * Returns:
9662654012fSReza Sabdar  *   void
9672654012fSReza Sabdar  */
9682654012fSReza Sabdar static void
9692654012fSReza Sabdar get_direct_env_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
9702654012fSReza Sabdar {
9712654012fSReza Sabdar 	char *envp;
9722654012fSReza Sabdar 
9732654012fSReza Sabdar 	/*
9742654012fSReza Sabdar 	 * We should send the fh_info to the DMA, unless it is specified
9752654012fSReza Sabdar 	 * in the request that we should not send fh_info.
9762654012fSReza Sabdar 	 * At the moment we do not support DAR on directories, so if the user
9772654012fSReza Sabdar 	 * needs to restore a directory they should disable the DAR.
9782654012fSReza Sabdar 	 */
9792654012fSReza Sabdar 	if (params->mp_operation == NDMP_DATA_OP_RECOVER && !ndmp_dar_support) {
9802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Direct Access Restore Disabled");
9812654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_DIRECT);
9822654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
9832654012fSReza Sabdar 		    "DAR is disabled. Running Restore without DAR");
9842654012fSReza Sabdar 		return;
9852654012fSReza Sabdar 	}
9862654012fSReza Sabdar 
9872654012fSReza Sabdar 	/*
9882654012fSReza Sabdar 	 * Regardless of whether DIRECT is defined at backup time we send
9892654012fSReza Sabdar 	 * back the fh_info, for some clients do not use get_backup_attrs.
9902654012fSReza Sabdar 	 * If operation is restore we have to unset the DIRECT, for
9912654012fSReza Sabdar 	 * some clients do not set the MOVER window.
9922654012fSReza Sabdar 	 */
9932654012fSReza Sabdar 	if (params->mp_operation == NDMP_DATA_OP_BACKUP) {
9942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "backup default env(DIRECT): YES");
9952654012fSReza Sabdar 		NLP_SET(nlp, NLPF_DIRECT);
9962654012fSReza Sabdar 	} else {
9972654012fSReza Sabdar 
9982654012fSReza Sabdar 		envp = MOD_GETENV(params, "DIRECT");
9992654012fSReza Sabdar 		if (!envp) {
10002654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "env(DIRECT) not defined");
10012654012fSReza Sabdar 			NLP_UNSET(nlp, NLPF_DIRECT);
10022654012fSReza Sabdar 		} else {
10032654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "env(DIRECT): \"%s\"", envp);
10042654012fSReza Sabdar 			if (IS_YORT(*envp)) {
10052654012fSReza Sabdar 				NLP_SET(nlp, NLPF_DIRECT);
10062654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
10072654012fSReza Sabdar 				    "Direct Access Restore Enabled");
10082654012fSReza Sabdar 			} else {
10092654012fSReza Sabdar 				NLP_UNSET(nlp, NLPF_DIRECT);
10102654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
10112654012fSReza Sabdar 				    "Direct Access Restore Disabled");
10122654012fSReza Sabdar 			}
10132654012fSReza Sabdar 		}
10142654012fSReza Sabdar 	}
10152654012fSReza Sabdar 
10162654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_DIRECT)) {
10172654012fSReza Sabdar 		if (params->mp_operation == NDMP_DATA_OP_BACKUP)
10182654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_NORMAL,
10192654012fSReza Sabdar 			    "Direct Access Restore information is supported");
10202654012fSReza Sabdar 		else
10212654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_NORMAL,
10222654012fSReza Sabdar 			    "Running Restore with Direct Access Restore");
10232654012fSReza Sabdar 	} else {
10242654012fSReza Sabdar 		if (params->mp_operation == NDMP_DATA_OP_BACKUP)
10252654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_NORMAL,
10262654012fSReza Sabdar 			    "Direct Access Restore is not supported");
10272654012fSReza Sabdar 		else
10282654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_NORMAL,
10292654012fSReza Sabdar 			    "Running Restore without Direct Access Restore");
10302654012fSReza Sabdar 	}
10312654012fSReza Sabdar }
10322654012fSReza Sabdar 
10332654012fSReza Sabdar 
10342654012fSReza Sabdar /*
10352654012fSReza Sabdar  * get_date_token_v3
10362654012fSReza Sabdar  *
10372654012fSReza Sabdar  * Parse the token passed as the argument.  Evaluate it and
10382654012fSReza Sabdar  * issue any warning or error if needed.  Save the date and
10392654012fSReza Sabdar  * token sequence in the nlp structure fields.  The sequence
10402654012fSReza Sabdar  * number in the token should be less than hard-limit.  If
10412654012fSReza Sabdar  * it's between soft and hard limit, a warning is issued.
10422654012fSReza Sabdar  * There is a configurable limit which should be less than
10432654012fSReza Sabdar  * the soft-limit saved in ndmp_max_tok_seq variable.
10442654012fSReza Sabdar  *
10452654012fSReza Sabdar  * The NLPF_TOKENBK flag is set in the nlp flags field to
10462654012fSReza Sabdar  * show that the backup type is token-based.
10472654012fSReza Sabdar  *
10482654012fSReza Sabdar  * Parameters:
10492654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
10502654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
10512654012fSReza Sabdar  *   basedate (input) - the value of the BASE_DATE environment
10522654012fSReza Sabdar  *	variable.
10532654012fSReza Sabdar  *
10542654012fSReza Sabdar  * Returns:
10552654012fSReza Sabdar  *   NDMP_NO_ERR: on success
10562654012fSReza Sabdar  *   != NDMP_NO_ERR: Otherwise
10572654012fSReza Sabdar  *
10582654012fSReza Sabdar  */
10592654012fSReza Sabdar static ndmp_error
10602654012fSReza Sabdar get_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp,
10612654012fSReza Sabdar     char *basedate)
10622654012fSReza Sabdar {
10632654012fSReza Sabdar 	char *endp;
10642654012fSReza Sabdar 	uint_t seq;
10652654012fSReza Sabdar 	ndmp_error rv;
10662654012fSReza Sabdar 	time_t tstamp;
10672654012fSReza Sabdar 	u_longlong_t tok;
10682654012fSReza Sabdar 
10692654012fSReza Sabdar 	if (!params || !nlp || !basedate || !*basedate)
10702654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
10712654012fSReza Sabdar 
10722654012fSReza Sabdar 	if (MOD_GETENV(params, "LEVEL")) {
10732654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_WARNING,
10742654012fSReza Sabdar 		    "Both BASE_DATE and LEVEL environment variables "
10752654012fSReza Sabdar 		    "defined.\n");
10762654012fSReza Sabdar 		MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
10772654012fSReza Sabdar 		    "BASE_DATE is being used for this backup.\n");
10782654012fSReza Sabdar 	}
10792654012fSReza Sabdar 
10802654012fSReza Sabdar 	tok = strtoll(basedate, &endp, 10);
10812654012fSReza Sabdar 	if (endp == basedate) {
10822654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
10832654012fSReza Sabdar 		    "Invalid BASE_DATE environment variable: \"%s\".\n",
10842654012fSReza Sabdar 		    basedate);
10852654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
10862654012fSReza Sabdar 	}
10872654012fSReza Sabdar 
10882654012fSReza Sabdar 	tstamp = tok & 0xffffffff;
10892654012fSReza Sabdar 	seq = (tok >> 32) & 0xffffffff;
10902654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "basedate \"%s\" %lld seq %u tstamp %u",
10912654012fSReza Sabdar 	    basedate, tok, seq, tstamp);
10922654012fSReza Sabdar 
10932654012fSReza Sabdar 	if ((int)seq > ndmp_get_max_tok_seq()) {
10942654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
10952654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
10962654012fSReza Sabdar 		    "The sequence counter of the token exceeds the "
10972654012fSReza Sabdar 		    "maximum permitted value.\n");
10982654012fSReza Sabdar 		MOD_LOGCONTV3(params, NDMP_LOG_ERROR,
10992654012fSReza Sabdar 		    "Token sequence: %u, maxiumum value: %u.\n",
11002654012fSReza Sabdar 		    seq, ndmp_get_max_tok_seq());
11012654012fSReza Sabdar 	} else if (seq >= NDMP_TOKSEQ_HLIMIT) {
11022654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
11032654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
11042654012fSReza Sabdar 		    "The sequence counter the of token exceeds the "
11052654012fSReza Sabdar 		    "hard-limit.\n");
11062654012fSReza Sabdar 		MOD_LOGCONTV3(params, NDMP_LOG_ERROR,
11072654012fSReza Sabdar 		    "Token sequence: %u, hard-limit: %u.\n",
11082654012fSReza Sabdar 		    seq, NDMP_TOKSEQ_HLIMIT);
11092654012fSReza Sabdar 	} else {
11102654012fSReza Sabdar 		rv = NDMP_NO_ERR;
11112654012fSReza Sabdar 		/*
11122654012fSReza Sabdar 		 * Issue a warning if the seq is equal to the maximum
11132654012fSReza Sabdar 		 * permitted seq number or equal to the soft-limit.
11142654012fSReza Sabdar 		 */
11152654012fSReza Sabdar 		if (seq == NDMP_TOKSEQ_SLIMIT) {
11162654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_WARNING,
11172654012fSReza Sabdar 			    "The sequence counter of the token has reached "
11182654012fSReza Sabdar 			    "the soft-limit.\n");
11192654012fSReza Sabdar 			MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
11202654012fSReza Sabdar 			    "Token sequence: %u, soft-limit: %u.\n",
11212654012fSReza Sabdar 			    seq, NDMP_TOKSEQ_SLIMIT);
11222654012fSReza Sabdar 		} else if ((int)seq == ndmp_get_max_tok_seq()) {
11232654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_WARNING,
11242654012fSReza Sabdar 			    "The sequence counter of the token has reached "
11252654012fSReza Sabdar 			    "the maximum permitted value.\n");
11262654012fSReza Sabdar 			MOD_LOGCONTV3(params, NDMP_LOG_WARNING,
11272654012fSReza Sabdar 			    "Token sequence: %u, maxiumum value: %u.\n",
11282654012fSReza Sabdar 			    seq, ndmp_get_max_tok_seq());
11292654012fSReza Sabdar 		}
11302654012fSReza Sabdar 
11312654012fSReza Sabdar 		/*
11322654012fSReza Sabdar 		 * The current seq is equal to the seq field of the
11332654012fSReza Sabdar 		 * token.  It will be increased after successful backup
11342654012fSReza Sabdar 		 * before setting the DUMP_DATE environment variable.
11352654012fSReza Sabdar 		 */
11362654012fSReza Sabdar 		nlp->nlp_dmpnm = MOD_GETENV(params, "DMP_NAME");
11372654012fSReza Sabdar 		NLP_SET(nlp, NLPF_TOKENBK);
11382654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_LEVELBK);
11392654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_LBRBK);
11402654012fSReza Sabdar 		nlp->nlp_tokseq = seq;
11412654012fSReza Sabdar 		nlp->nlp_tokdate = tstamp;
11422654012fSReza Sabdar 		/*
11432654012fSReza Sabdar 		 * The value of nlp_cdate will be set to the checkpoint
11442654012fSReza Sabdar 		 * creation time after it is created.
11452654012fSReza Sabdar 		 */
11462654012fSReza Sabdar 	}
11472654012fSReza Sabdar 
11482654012fSReza Sabdar 	return (rv);
11492654012fSReza Sabdar }
11502654012fSReza Sabdar 
11512654012fSReza Sabdar 
11522654012fSReza Sabdar /*
11532654012fSReza Sabdar  * get_lbr_bk_v3
11542654012fSReza Sabdar  *
11552654012fSReza Sabdar  * Sets the level fields of the nlp structures for
11562654012fSReza Sabdar  * LBR-type backup.  The NLPF_LBRBK flag of the
11572654012fSReza Sabdar  * nlp flags is also set to show the backup type.
11582654012fSReza Sabdar  *
11592654012fSReza Sabdar  * Parameters:
11602654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
11612654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
11622654012fSReza Sabdar  *   type (input) - the backup level: 'F', 'A', 'I', 'D' or
11632654012fSReza Sabdar  *	their lower-case values.
11642654012fSReza Sabdar  *
11652654012fSReza Sabdar  * Returns:
11662654012fSReza Sabdar  *   NDMP_NO_ERR: on success
11672654012fSReza Sabdar  *   != NDMP_NO_ERR: Otherwise
11682654012fSReza Sabdar  */
11692654012fSReza Sabdar static ndmp_error
11702654012fSReza Sabdar get_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp, char *type)
11712654012fSReza Sabdar {
11722654012fSReza Sabdar 	if (!params || !nlp || !type || !*type)
11732654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
11742654012fSReza Sabdar 
11752654012fSReza Sabdar 	NLP_SET(nlp, NLPF_LBRBK);
11762654012fSReza Sabdar 	NLP_UNSET(nlp, NLPF_TOKENBK);
11772654012fSReza Sabdar 	NLP_UNSET(nlp, NLPF_LEVELBK);
11782654012fSReza Sabdar 	nlp->nlp_dmpnm = MOD_GETENV(params, "DMP_NAME");
11792654012fSReza Sabdar 	nlp->nlp_llevel = toupper(*type);
11802654012fSReza Sabdar 	nlp->nlp_ldate = (time_t)0;
11812654012fSReza Sabdar 	nlp->nlp_clevel = nlp->nlp_llevel;
11822654012fSReza Sabdar 	(void) time(&nlp->nlp_cdate);
11832654012fSReza Sabdar 
11842654012fSReza Sabdar 	return (NDMP_NO_ERR);
11852654012fSReza Sabdar }
11862654012fSReza Sabdar 
11872654012fSReza Sabdar 
11882654012fSReza Sabdar /*
11892654012fSReza Sabdar  * get_backup_level_v3
11902654012fSReza Sabdar  *
11912654012fSReza Sabdar  * Gets the backup level from the environment variables.  If
11922654012fSReza Sabdar  * BASE_DATE is specified, it will be used, otherwise LEVEL
11932654012fSReza Sabdar  * will be used.  If neither is specified, LEVEL = '0' is
11942654012fSReza Sabdar  * assumed.
11952654012fSReza Sabdar  *
11962654012fSReza Sabdar  * Parameters:
11972654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
11982654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
11992654012fSReza Sabdar  *
12002654012fSReza Sabdar  * Returns:
12012654012fSReza Sabdar  *   NDMP_NO_ERR: on success
12022654012fSReza Sabdar  *   != NDMP_NO_ERR: Otherwise
12032654012fSReza Sabdar  */
12042654012fSReza Sabdar static ndmp_error
12052654012fSReza Sabdar get_backup_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
12062654012fSReza Sabdar {
12072654012fSReza Sabdar 	char *envp;
12082654012fSReza Sabdar 	ndmp_error rv;
12092654012fSReza Sabdar 
12102654012fSReza Sabdar 	/*
12112654012fSReza Sabdar 	 * If the BASE_DATE env variable is specified use it, otherwise
12122654012fSReza Sabdar 	 * look to see if LEVEL is specified.  If LEVEL is not
12132654012fSReza Sabdar 	 * specified either, backup level '0' must be made. Level backup
12142654012fSReza Sabdar 	 * does not clear the archive bit.
12152654012fSReza Sabdar 	 *
12162654012fSReza Sabdar 	 * If LEVEL environment varaible is specified, values for
12172654012fSReza Sabdar 	 * 'F', 'D', 'I' and 'A' (for 'Full', 'Differential',
12182654012fSReza Sabdar 	 * 'Incremental', and 'Archive' is checked first.  Then
12192654012fSReza Sabdar 	 * level '0' to '9' will be checked.
12202654012fSReza Sabdar 	 *
12212654012fSReza Sabdar 	 * LEVEL environment variable can hold only one character.
12222654012fSReza Sabdar 	 * If its length is longer than 1, an error is returned.
12232654012fSReza Sabdar 	 */
12242654012fSReza Sabdar 	envp = MOD_GETENV(params, "BASE_DATE");
12252654012fSReza Sabdar 	if (envp)
12262654012fSReza Sabdar 		return (get_date_token_v3(params, nlp, envp));
12272654012fSReza Sabdar 
12282654012fSReza Sabdar 
12292654012fSReza Sabdar 	envp = MOD_GETENV(params, "LEVEL");
12302654012fSReza Sabdar 	if (!envp) {
12312654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(LEVEL) not defined, default to 0");
12322654012fSReza Sabdar 		NLP_SET(nlp, NLPF_LEVELBK);
12332654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_LBRBK);
12342654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_TOKENBK);
12352654012fSReza Sabdar 		nlp->nlp_llevel = 0;
12362654012fSReza Sabdar 		nlp->nlp_ldate = 0;
12372654012fSReza Sabdar 		nlp->nlp_clevel = 0;
12382654012fSReza Sabdar 		/*
12392654012fSReza Sabdar 		 * The value of nlp_cdate will be set to the checkpoint
12402654012fSReza Sabdar 		 * creation time after it is created.
12412654012fSReza Sabdar 		 */
12422654012fSReza Sabdar 		return (NDMP_NO_ERR);
12432654012fSReza Sabdar 	}
12442654012fSReza Sabdar 
12452654012fSReza Sabdar 	if (*(envp+1) != '\0') {
12462654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
12472654012fSReza Sabdar 		    "Invalid backup level \"%s\".\n", envp);
12482654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
12492654012fSReza Sabdar 	}
12502654012fSReza Sabdar 
12512654012fSReza Sabdar 	if (IS_LBR_BKTYPE(*envp))
12522654012fSReza Sabdar 		return (get_lbr_bk_v3(params, nlp, envp));
12532654012fSReza Sabdar 
12542654012fSReza Sabdar 	if (!isdigit(*envp)) {
12552654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
12562654012fSReza Sabdar 		    "Invalid backup level \"%s\".\n", envp);
12572654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
12582654012fSReza Sabdar 	}
12592654012fSReza Sabdar 
12602654012fSReza Sabdar 	NLP_SET(nlp, NLPF_LEVELBK);
12612654012fSReza Sabdar 	NLP_UNSET(nlp, NLPF_LBRBK);
12622654012fSReza Sabdar 	NLP_UNSET(nlp, NLPF_TOKENBK);
12632654012fSReza Sabdar 	nlp->nlp_llevel = *envp - '0';
12642654012fSReza Sabdar 	nlp->nlp_ldate = 0;
12652654012fSReza Sabdar 	nlp->nlp_clevel = nlp->nlp_llevel;
12662654012fSReza Sabdar 	/*
12672654012fSReza Sabdar 	 * The value of nlp_cdate will be set to the checkpoint
12682654012fSReza Sabdar 	 * creation time after it is created.
12692654012fSReza Sabdar 	 */
12702654012fSReza Sabdar 	if (ndmpd_get_dumptime(nlp->nlp_backup_path, &nlp->nlp_llevel,
12712654012fSReza Sabdar 	    &nlp->nlp_ldate) < 0) {
12722654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
12732654012fSReza Sabdar 		    "Getting dumpdates for %s level '%c'.\n",
12742654012fSReza Sabdar 		    nlp->nlp_backup_path, *envp);
12752654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
12762654012fSReza Sabdar 	} else {
12772654012fSReza Sabdar 		get_update_env_v3(params, nlp);
12782654012fSReza Sabdar 		rv = NDMP_NO_ERR;
12792654012fSReza Sabdar 	}
12802654012fSReza Sabdar 
12812654012fSReza Sabdar 	return (rv);
12822654012fSReza Sabdar }
12832654012fSReza Sabdar 
12842654012fSReza Sabdar 
12852654012fSReza Sabdar /*
12862654012fSReza Sabdar  * save_date_token_v3
12872654012fSReza Sabdar  *
12882654012fSReza Sabdar  * Make the value of DUMP_DATE env variable and append the values
12892654012fSReza Sabdar  * of the current backup in the file specified with the DMP_NAME
12902654012fSReza Sabdar  * env variable if any file is specified.  The file will be
12912654012fSReza Sabdar  * relative name in the backup directory path.
12922654012fSReza Sabdar  *
12932654012fSReza Sabdar  * Parameters:
12942654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
12952654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
12962654012fSReza Sabdar  *
12972654012fSReza Sabdar  * Returns:
12982654012fSReza Sabdar  *   void
12992654012fSReza Sabdar  */
13002654012fSReza Sabdar static void
13012654012fSReza Sabdar save_date_token_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
13022654012fSReza Sabdar {
13032654012fSReza Sabdar 	char val[QUAD_DECIMAL_LEN];
13042654012fSReza Sabdar 	u_longlong_t tok;
13052654012fSReza Sabdar 
13062654012fSReza Sabdar 	if (!params || !nlp)
13072654012fSReza Sabdar 		return;
13082654012fSReza Sabdar 
13092654012fSReza Sabdar 	nlp->nlp_tokseq++;
13102654012fSReza Sabdar 	tok = ((u_longlong_t)nlp->nlp_tokseq << 32) | nlp->nlp_cdate;
13112654012fSReza Sabdar 	(void) snprintf(val, sizeof (val), "%llu", tok);
13122654012fSReza Sabdar 
13132654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "tok: %lld %s", tok, val);
13142654012fSReza Sabdar 
13152654012fSReza Sabdar 	if (MOD_SETENV(params, "DUMP_DATE", val) != 0) {
13162654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
13172654012fSReza Sabdar 		    "Could not set DUMP_DATE to %s", val);
13182654012fSReza Sabdar 	} else if (!nlp->nlp_dmpnm) {
13192654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "No log file defined");
13202654012fSReza Sabdar 	} else if (ndmpd_append_dumptime(nlp->nlp_dmpnm, nlp->nlp_backup_path,
13212654012fSReza Sabdar 	    nlp->nlp_tokseq, nlp->nlp_tokdate) < 0) {
13222654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
13232654012fSReza Sabdar 		    "Saving backup date for \"%s\" in \"%s\".\n",
13242654012fSReza Sabdar 		    nlp->nlp_backup_path, nlp->nlp_dmpnm);
13252654012fSReza Sabdar 	}
13262654012fSReza Sabdar }
13272654012fSReza Sabdar 
13282654012fSReza Sabdar 
13292654012fSReza Sabdar /*
13302654012fSReza Sabdar  * save_lbr_bk_v3
13312654012fSReza Sabdar  *
13322654012fSReza Sabdar  * Append the backup type and date in the DMP_NAME file for
13332654012fSReza Sabdar  * LBR-type backup if any file is specified.
13342654012fSReza Sabdar  *
13352654012fSReza Sabdar  * Parameters:
13362654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
13372654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
13382654012fSReza Sabdar  *
13392654012fSReza Sabdar  * Returns:
13402654012fSReza Sabdar  *   void
13412654012fSReza Sabdar  */
13422654012fSReza Sabdar static void
13432654012fSReza Sabdar save_lbr_bk_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
13442654012fSReza Sabdar {
13452654012fSReza Sabdar 	if (!params || !nlp)
13462654012fSReza Sabdar 		return;
13472654012fSReza Sabdar 
13482654012fSReza Sabdar 	if (!nlp->nlp_dmpnm) {
13492654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "No log file defined");
13502654012fSReza Sabdar 	} else if (ndmpd_append_dumptime(nlp->nlp_dmpnm, nlp->nlp_backup_path,
13512654012fSReza Sabdar 	    nlp->nlp_clevel, nlp->nlp_cdate) < 0) {
13522654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
13532654012fSReza Sabdar 		    "Saving backup date for \"%s\" in \"%s\".\n",
13542654012fSReza Sabdar 		    nlp->nlp_backup_path, nlp->nlp_dmpnm);
13552654012fSReza Sabdar 	}
13562654012fSReza Sabdar }
13572654012fSReza Sabdar 
13582654012fSReza Sabdar 
13592654012fSReza Sabdar /*
13602654012fSReza Sabdar  * save_level_v3
13612654012fSReza Sabdar  *
13622654012fSReza Sabdar  * Save the date and level of the current backup in the dumpdates
13632654012fSReza Sabdar  * file.
13642654012fSReza Sabdar  *
13652654012fSReza Sabdar  * Parameters:
13662654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
13672654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
13682654012fSReza Sabdar  *
13692654012fSReza Sabdar  * Returns:
13702654012fSReza Sabdar  *   void
13712654012fSReza Sabdar  */
13722654012fSReza Sabdar static void
13732654012fSReza Sabdar save_level_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
13742654012fSReza Sabdar {
13752654012fSReza Sabdar 	if (!params || !nlp)
13762654012fSReza Sabdar 		return;
13772654012fSReza Sabdar 
13782654012fSReza Sabdar 	if (!NLP_SHOULD_UPDATE(nlp)) {
13792654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "update not requested");
13802654012fSReza Sabdar 	} else if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel,
13812654012fSReza Sabdar 	    nlp->nlp_cdate) < 0) {
13822654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR, "Logging backup date.\n");
13832654012fSReza Sabdar 	}
13842654012fSReza Sabdar }
13852654012fSReza Sabdar 
13862654012fSReza Sabdar 
13872654012fSReza Sabdar /*
13882654012fSReza Sabdar  * save_backup_date_v3
13892654012fSReza Sabdar  *
13902654012fSReza Sabdar  * A dispatcher function to call the corresponding save function
13912654012fSReza Sabdar  * based on the backup type.
13922654012fSReza Sabdar  *
13932654012fSReza Sabdar  * Parameters:
13942654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
13952654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
13962654012fSReza Sabdar  *
13972654012fSReza Sabdar  * Returns:
13982654012fSReza Sabdar  *   void
13992654012fSReza Sabdar  */
14002654012fSReza Sabdar static void
14012654012fSReza Sabdar save_backup_date_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
14022654012fSReza Sabdar {
14032654012fSReza Sabdar 	if (!params || !nlp)
14042654012fSReza Sabdar 		return;
14052654012fSReza Sabdar 
14062654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_TOKENBK))
14072654012fSReza Sabdar 		save_date_token_v3(params, nlp);
14082654012fSReza Sabdar 	else if (NLP_ISSET(nlp, NLPF_LBRBK))
14092654012fSReza Sabdar 		save_lbr_bk_v3(params, nlp);
14102654012fSReza Sabdar 	else if (NLP_ISSET(nlp, NLPF_LEVELBK))
14112654012fSReza Sabdar 		save_level_v3(params, nlp);
14122654012fSReza Sabdar 	else {
14132654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
14142654012fSReza Sabdar 		    "Internal error: lost backup level type for \"%s\".\n",
14152654012fSReza Sabdar 		    nlp->nlp_backup_path);
14162654012fSReza Sabdar 	}
14172654012fSReza Sabdar }
14182654012fSReza Sabdar 
14192654012fSReza Sabdar 
14202654012fSReza Sabdar /*
14212654012fSReza Sabdar  * backup_alloc_structs_v3
14222654012fSReza Sabdar  *
14232654012fSReza Sabdar  * Create the structures for V3 backup.  This includes:
14242654012fSReza Sabdar  *	Job stats
14252654012fSReza Sabdar  *	Reader writer IPC
14262654012fSReza Sabdar  *	File history callback structure
14272654012fSReza Sabdar  *
14282654012fSReza Sabdar  * Parameters:
14292654012fSReza Sabdar  *   session (input) - pointer to the session
14302654012fSReza Sabdar  *   jname (input) - name assigned to the current backup for
14312654012fSReza Sabdar  *	job stats strucure
14322654012fSReza Sabdar  *
14332654012fSReza Sabdar  * Returns:
14342654012fSReza Sabdar  *   0: on success
14352654012fSReza Sabdar  *   -1: otherwise
14362654012fSReza Sabdar  */
14372654012fSReza Sabdar static int
14382654012fSReza Sabdar backup_alloc_structs_v3(ndmpd_session_t *session, char *jname)
14392654012fSReza Sabdar {
14402654012fSReza Sabdar 	int n;
14412654012fSReza Sabdar 	long xfer_size;
14422654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
14432654012fSReza Sabdar 	tlm_commands_t *cmds;
14442654012fSReza Sabdar 
14452654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
14462654012fSReza Sabdar 	if (!nlp) {
14472654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
14482654012fSReza Sabdar 		return (-1);
14492654012fSReza Sabdar 	}
14502654012fSReza Sabdar 
14512654012fSReza Sabdar 	nlp->nlp_jstat = tlm_new_job_stats(jname);
14522654012fSReza Sabdar 	if (!nlp->nlp_jstat) {
14532654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
14542654012fSReza Sabdar 		return (-1);
14552654012fSReza Sabdar 	}
14562654012fSReza Sabdar 
14572654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
14582654012fSReza Sabdar 	(void) memset(cmds, 0, sizeof (*cmds));
14592654012fSReza Sabdar 
14602654012fSReza Sabdar 	xfer_size = ndmp_buffer_get_size(session);
14612654012fSReza Sabdar 	if (xfer_size < 512*KILOBYTE) {
14622654012fSReza Sabdar 		/*
14632654012fSReza Sabdar 		 * Read multiple of mover_record_size near to 512K.  This
14642654012fSReza Sabdar 		 * will prevent the data being copied in the mover buffer
14652654012fSReza Sabdar 		 * when we write the data.
14662654012fSReza Sabdar 		 */
14672654012fSReza Sabdar 		n = 512 * KILOBYTE / xfer_size;
14682654012fSReza Sabdar 		if (n <= 0)
14692654012fSReza Sabdar 			n = 1;
14702654012fSReza Sabdar 		xfer_size *= n;
14712654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Adjusted read size: %d",
14722654012fSReza Sabdar 		    xfer_size);
14732654012fSReza Sabdar 	}
14742654012fSReza Sabdar 
14752654012fSReza Sabdar 	cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, xfer_size);
14762654012fSReza Sabdar 	if (!cmds->tcs_command) {
14772654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
14782654012fSReza Sabdar 		return (-1);
14792654012fSReza Sabdar 	}
14802654012fSReza Sabdar 
14812654012fSReza Sabdar 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
14822654012fSReza Sabdar 	    ndmpd_fhpath_v3_cb, ndmpd_fhdir_v3_cb, ndmpd_fhnode_v3_cb);
14832654012fSReza Sabdar 	if (!nlp->nlp_logcallbacks) {
14842654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
14852654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
14862654012fSReza Sabdar 		return (-1);
14872654012fSReza Sabdar 	}
14882654012fSReza Sabdar 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
14892654012fSReza Sabdar 	nlp->nlp_restored = NULL;
14902654012fSReza Sabdar 
14912654012fSReza Sabdar 	return (0);
14922654012fSReza Sabdar }
14932654012fSReza Sabdar 
14942654012fSReza Sabdar 
14952654012fSReza Sabdar /*
14962654012fSReza Sabdar  * restore_alloc_structs_v3
14972654012fSReza Sabdar  *
14982654012fSReza Sabdar  * Create the structures for V3 Restore.  This includes:
14992654012fSReza Sabdar  *	Job stats
15002654012fSReza Sabdar  *	Reader writer IPC
15012654012fSReza Sabdar  *	File recovery callback structure
15022654012fSReza Sabdar  *
15032654012fSReza Sabdar  * Parameters:
15042654012fSReza Sabdar  *   session (input) - pointer to the session
15052654012fSReza Sabdar  *   jname (input) - name assigned to the current backup for
15062654012fSReza Sabdar  *	job stats strucure
15072654012fSReza Sabdar  *
15082654012fSReza Sabdar  * Returns:
15092654012fSReza Sabdar  *   0: on success
15102654012fSReza Sabdar  *   -1: otherwise
15112654012fSReza Sabdar  */
15122654012fSReza Sabdar int
15132654012fSReza Sabdar restore_alloc_structs_v3(ndmpd_session_t *session, char *jname)
15142654012fSReza Sabdar {
15152654012fSReza Sabdar 	long xfer_size;
15162654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
15172654012fSReza Sabdar 	tlm_commands_t *cmds;
15182654012fSReza Sabdar 
15192654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
15202654012fSReza Sabdar 	if (!nlp) {
15212654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
15222654012fSReza Sabdar 		return (-1);
15232654012fSReza Sabdar 	}
15242654012fSReza Sabdar 
15252654012fSReza Sabdar 	/* this is used in ndmpd_path_restored_v3() */
15262654012fSReza Sabdar 	nlp->nlp_lastidx = -1;
15272654012fSReza Sabdar 
15282654012fSReza Sabdar 	nlp->nlp_jstat = tlm_new_job_stats(jname);
15292654012fSReza Sabdar 	if (!nlp->nlp_jstat) {
15302654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
15312654012fSReza Sabdar 		return (-1);
15322654012fSReza Sabdar 	}
15332654012fSReza Sabdar 
15342654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
15352654012fSReza Sabdar 	(void) memset(cmds, 0, sizeof (*cmds));
15362654012fSReza Sabdar 
15372654012fSReza Sabdar 	xfer_size = ndmp_buffer_get_size(session);
15382654012fSReza Sabdar 	cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
15392654012fSReza Sabdar 	if (!cmds->tcs_command) {
15402654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
15412654012fSReza Sabdar 		return (-1);
15422654012fSReza Sabdar 	}
15432654012fSReza Sabdar 
15442654012fSReza Sabdar 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
15452654012fSReza Sabdar 	    ndmpd_path_restored_v3, NULL, NULL);
15462654012fSReza Sabdar 	if (!nlp->nlp_logcallbacks) {
15472654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
15482654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
15492654012fSReza Sabdar 		return (-1);
15502654012fSReza Sabdar 	}
15512654012fSReza Sabdar 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
15522654012fSReza Sabdar 
15532654012fSReza Sabdar 	nlp->nlp_rsbm = bm_alloc(nlp->nlp_nfiles, 0);
15542654012fSReza Sabdar 	if (nlp->nlp_rsbm < 0) {
15552654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Out of memory.");
15562654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
15572654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
15582654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
15592654012fSReza Sabdar 		return (-1);
15602654012fSReza Sabdar 	}
15612654012fSReza Sabdar 
15622654012fSReza Sabdar 	return (0);
15632654012fSReza Sabdar }
15642654012fSReza Sabdar 
15652654012fSReza Sabdar 
15662654012fSReza Sabdar /*
15672654012fSReza Sabdar  * free_structs_v3
15682654012fSReza Sabdar  *
15692654012fSReza Sabdar  * Release the resources allocated by backup_alloc_structs_v3
15702654012fSReza Sabdar  * function.
15712654012fSReza Sabdar  *
15722654012fSReza Sabdar  * Parameters:
15732654012fSReza Sabdar  *   session (input) - pointer to the session
15742654012fSReza Sabdar  *   jname (input) - name assigned to the current backup for
15752654012fSReza Sabdar  *	job stats strucure
15762654012fSReza Sabdar  *
15772654012fSReza Sabdar  * Returns:
15782654012fSReza Sabdar  *   void
15792654012fSReza Sabdar  */
15802654012fSReza Sabdar /*ARGSUSED*/
15812654012fSReza Sabdar static void
15822654012fSReza Sabdar free_structs_v3(ndmpd_session_t *session, char *jname)
15832654012fSReza Sabdar {
15842654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
15852654012fSReza Sabdar 	tlm_commands_t *cmds;
15862654012fSReza Sabdar 
15872654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
15882654012fSReza Sabdar 	if (!nlp) {
15892654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
15902654012fSReza Sabdar 		return;
15912654012fSReza Sabdar 	}
15922654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
15932654012fSReza Sabdar 	if (!cmds) {
15942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
15952654012fSReza Sabdar 		return;
15962654012fSReza Sabdar 	}
15972654012fSReza Sabdar 
15982654012fSReza Sabdar 	if (nlp->nlp_logcallbacks) {
15992654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
16002654012fSReza Sabdar 		nlp->nlp_logcallbacks = NULL;
16012654012fSReza Sabdar 	} else
16022654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
16032654012fSReza Sabdar 
16042654012fSReza Sabdar 	if (cmds->tcs_command) {
16052654012fSReza Sabdar 		if (cmds->tcs_command->tc_buffers != NULL)
16062654012fSReza Sabdar 			tlm_release_reader_writer_ipc(cmds->tcs_command);
16072654012fSReza Sabdar 		else
16082654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
16092654012fSReza Sabdar 		cmds->tcs_command = NULL;
16102654012fSReza Sabdar 	} else
16112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
16122654012fSReza Sabdar 
16132654012fSReza Sabdar 	if (nlp->nlp_bkmap >= 0) {
16142654012fSReza Sabdar 		(void) dbm_free(nlp->nlp_bkmap);
16152654012fSReza Sabdar 		nlp->nlp_bkmap = -1;
16162654012fSReza Sabdar 	}
16172654012fSReza Sabdar 
16182654012fSReza Sabdar 	if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER) {
16192654012fSReza Sabdar 		if (nlp->nlp_rsbm < 0) {
16202654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "nlp_rsbm < 0 %d", nlp->nlp_rsbm);
16212654012fSReza Sabdar 		} else {
16222654012fSReza Sabdar 			(void) bm_free(nlp->nlp_rsbm);
16232654012fSReza Sabdar 			nlp->nlp_rsbm = -1;
16242654012fSReza Sabdar 		}
16252654012fSReza Sabdar 	}
16262654012fSReza Sabdar }
16272654012fSReza Sabdar 
16282654012fSReza Sabdar 
16292654012fSReza Sabdar /*
16302654012fSReza Sabdar  * backup_dirv3
16312654012fSReza Sabdar  *
16322654012fSReza Sabdar  * Backup a directory and update the bytes processed field of the
16332654012fSReza Sabdar  * data server.
16342654012fSReza Sabdar  *
16352654012fSReza Sabdar  * Parameters:
16362654012fSReza Sabdar  *   bpp (input) - pointer to the backup parameters structure
16372654012fSReza Sabdar  *   pnp (input) - pointer to the path node
16382654012fSReza Sabdar  *   enp (input) - pointer to the entry node
16392654012fSReza Sabdar  *
16402654012fSReza Sabdar  * Returns:
16412654012fSReza Sabdar  *   0: on success
16422654012fSReza Sabdar  *   != 0: otherwise
16432654012fSReza Sabdar  */
16442654012fSReza Sabdar static int
16452654012fSReza Sabdar backup_dirv3(bk_param_v3_t *bpp, fst_node_t *pnp,
16462654012fSReza Sabdar     fst_node_t *enp)
16472654012fSReza Sabdar {
16482654012fSReza Sabdar 	longlong_t apos, bpos;
16492654012fSReza Sabdar 	acl_t *aclp = NULL;
16502654012fSReza Sabdar 	char *acltp;
16512654012fSReza Sabdar 	struct stat64 st;
16522654012fSReza Sabdar 	char fullpath[TLM_MAX_PATH_NAME];
16532654012fSReza Sabdar 	char *p;
16542654012fSReza Sabdar 
16552654012fSReza Sabdar 	if (!bpp || !pnp || !enp) {
16562654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
16572654012fSReza Sabdar 		return (-1);
16582654012fSReza Sabdar 	}
16592654012fSReza Sabdar 
16602654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "d(%s)", bpp->bp_tmp);
16612654012fSReza Sabdar 
16622654012fSReza Sabdar 	if (lstat64(bpp->bp_tmp, &st) != 0)
16632654012fSReza Sabdar 		return (0);
16642654012fSReza Sabdar 
16652654012fSReza Sabdar 	if (acl_get(bpp->bp_tmp, ACL_NO_TRIVIAL, &aclp) != 0) {
16662654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "acl_get error errno=%d", errno);
16672654012fSReza Sabdar 		return (-1);
16682654012fSReza Sabdar 	}
16692654012fSReza Sabdar 	if (aclp && (acltp = acl_totext(aclp,
16702654012fSReza Sabdar 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
16712654012fSReza Sabdar 		(void) strlcpy(bpp->bp_tlmacl->acl_info.attr_info,
16722654012fSReza Sabdar 		    acltp, TLM_MAX_ACL_TXT);
16732654012fSReza Sabdar 		acl_free(aclp);
16742654012fSReza Sabdar 		free(acltp);
16752654012fSReza Sabdar 	} else {
16762654012fSReza Sabdar 		*bpp->bp_tlmacl->acl_info.attr_info = '\0';
16772654012fSReza Sabdar 	}
16782654012fSReza Sabdar 
16792654012fSReza Sabdar 	bpos = tlm_get_data_offset(bpp->bp_lcmd);
16802654012fSReza Sabdar 
16812654012fSReza Sabdar 	p = bpp->bp_tmp + strlen(bpp->bp_chkpnm);
16827bc22e45SReza Sabdar 	if (*p == '/')
16837bc22e45SReza Sabdar 		(void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s%s",
16847bc22e45SReza Sabdar 		    bpp->bp_unchkpnm, p);
16857bc22e45SReza Sabdar 	else
16862654012fSReza Sabdar 		(void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s/%s",
16872654012fSReza Sabdar 		    bpp->bp_unchkpnm, p);
16882654012fSReza Sabdar 
16892654012fSReza Sabdar 	if (tm_tar_ops.tm_putdir != NULL)
16902654012fSReza Sabdar 		(void) (tm_tar_ops.tm_putdir)(fullpath, bpp->bp_tlmacl,
16912654012fSReza Sabdar 		    bpp->bp_lcmd, bpp->bp_js);
16922654012fSReza Sabdar 
16932654012fSReza Sabdar 	apos = tlm_get_data_offset(bpp->bp_lcmd);
16942654012fSReza Sabdar 	bpp->bp_session->ns_data.dd_module.dm_stats.ms_bytes_processed +=
16952654012fSReza Sabdar 	    apos - bpos;
16962654012fSReza Sabdar 
16972654012fSReza Sabdar 	return (0);
16982654012fSReza Sabdar }
16992654012fSReza Sabdar 
17002654012fSReza Sabdar 
17012654012fSReza Sabdar /*
17022654012fSReza Sabdar  * backup_filev3
17032654012fSReza Sabdar  *
17042654012fSReza Sabdar  * Backup a file and update the bytes processed field of the
17052654012fSReza Sabdar  * data server.
17062654012fSReza Sabdar  *
17072654012fSReza Sabdar  * Parameters:
17082654012fSReza Sabdar  *   bpp (input) - pointer to the backup parameters structure
17092654012fSReza Sabdar  *   pnp (input) - pointer to the path node
17102654012fSReza Sabdar  *   enp (input) - pointer to the entry node
17112654012fSReza Sabdar  *
17122654012fSReza Sabdar  * Returns:
17132654012fSReza Sabdar  *   0: on success
17142654012fSReza Sabdar  *   != 0: otherwise
17152654012fSReza Sabdar  */
17162654012fSReza Sabdar static int
17172654012fSReza Sabdar backup_filev3(bk_param_v3_t *bpp, fst_node_t *pnp,
17182654012fSReza Sabdar     fst_node_t *enp)
17192654012fSReza Sabdar {
17202654012fSReza Sabdar 	char *ent;
17212654012fSReza Sabdar 	longlong_t rv;
17222654012fSReza Sabdar 	longlong_t apos, bpos;
17232654012fSReza Sabdar 	acl_t *aclp = NULL;
17242654012fSReza Sabdar 	char *acltp;
17252654012fSReza Sabdar 	struct stat64 st;
17262654012fSReza Sabdar 	char fullpath[TLM_MAX_PATH_NAME];
17272654012fSReza Sabdar 	char *p;
17282654012fSReza Sabdar 
17292654012fSReza Sabdar 	if (!bpp || !pnp || !enp) {
17302654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
17312654012fSReza Sabdar 		return (-1);
17322654012fSReza Sabdar 	}
17332654012fSReza Sabdar 
17342654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "f(%s)", bpp->bp_tmp);
17352654012fSReza Sabdar 
17362654012fSReza Sabdar 	if (lstat64(bpp->bp_tmp, &st) != 0)
17372654012fSReza Sabdar 		return (0);
17382654012fSReza Sabdar 
17392654012fSReza Sabdar 	if (!S_ISLNK(bpp->bp_tlmacl->acl_attr.st_mode)) {
17402654012fSReza Sabdar 		if (acl_get(bpp->bp_tmp, ACL_NO_TRIVIAL, &aclp) != 0) {
17412654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "acl_get error");
17422654012fSReza Sabdar 			return (-1);
17432654012fSReza Sabdar 		}
17442654012fSReza Sabdar 
17452654012fSReza Sabdar 		if (aclp &&
17462654012fSReza Sabdar 		    (acltp = acl_totext(aclp,
17472654012fSReza Sabdar 		    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
17482654012fSReza Sabdar 			(void) strlcpy(bpp->bp_tlmacl->acl_info.attr_info,
17492654012fSReza Sabdar 			    acltp, TLM_MAX_ACL_TXT);
17502654012fSReza Sabdar 			acl_free(aclp);
17512654012fSReza Sabdar 			free(acltp);
17522654012fSReza Sabdar 		} else {
17532654012fSReza Sabdar 			*bpp->bp_tlmacl->acl_info.attr_info = '\0';
17542654012fSReza Sabdar 		}
17552654012fSReza Sabdar 	}
17562654012fSReza Sabdar 
17572654012fSReza Sabdar 	bpos = tlm_get_data_offset(bpp->bp_lcmd);
17582654012fSReza Sabdar 	ent = enp->tn_path ? enp->tn_path : "";
17592654012fSReza Sabdar 
17602654012fSReza Sabdar 	p = pnp->tn_path + strlen(bpp->bp_chkpnm);
17617bc22e45SReza Sabdar 	if (*p == '/')
17627bc22e45SReza Sabdar 		(void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s%s",
17637bc22e45SReza Sabdar 		    bpp->bp_unchkpnm, p);
17647bc22e45SReza Sabdar 	else
17652654012fSReza Sabdar 		(void) snprintf(fullpath, TLM_MAX_PATH_NAME, "%s/%s",
17662654012fSReza Sabdar 		    bpp->bp_unchkpnm, p);
17672654012fSReza Sabdar 
17682654012fSReza Sabdar 	if (tm_tar_ops.tm_putfile != NULL)
17692654012fSReza Sabdar 		rv = (tm_tar_ops.tm_putfile)(fullpath, ent, pnp->tn_path,
17702654012fSReza Sabdar 		    bpp->bp_tlmacl, bpp->bp_cmds, bpp->bp_lcmd, bpp->bp_js,
17712654012fSReza Sabdar 		    bpp->bp_session->hardlink_q);
17722654012fSReza Sabdar 
17732654012fSReza Sabdar 	apos = tlm_get_data_offset(bpp->bp_lcmd);
17742654012fSReza Sabdar 	bpp->bp_session->ns_data.dd_module.dm_stats.ms_bytes_processed +=
17752654012fSReza Sabdar 	    apos - bpos;
17762654012fSReza Sabdar 
17772654012fSReza Sabdar 	return (rv < 0 ? rv : 0);
17782654012fSReza Sabdar }
17792654012fSReza Sabdar 
17802654012fSReza Sabdar 
17812654012fSReza Sabdar /*
17822654012fSReza Sabdar  * check_bk_args
17832654012fSReza Sabdar  *
17842654012fSReza Sabdar  * Check the argument of the bpp.  This is shared function between
17852654012fSReza Sabdar  * timebk_v3 and lbrbk_v3 functions.  The checks include:
17862654012fSReza Sabdar  *	- The bpp itself.
17872654012fSReza Sabdar  *	- If the session pointer of the bpp is valid.
17882654012fSReza Sabdar  *	- If the session connection to the DMA is closed.
17892654012fSReza Sabdar  *	- If the nlp pointer of the bpp is valid.
17902654012fSReza Sabdar  *	- If the backup is aborted.
17912654012fSReza Sabdar  *
17922654012fSReza Sabdar  * Parameters:
17932654012fSReza Sabdar  *   bpp (input) - pointer to the backup parameters structure
17942654012fSReza Sabdar  *
17952654012fSReza Sabdar  * Returns:
17962654012fSReza Sabdar  *   0: if everything's OK
17972654012fSReza Sabdar  *   != 0: otherwise
17982654012fSReza Sabdar  */
17992654012fSReza Sabdar static int
18002654012fSReza Sabdar check_bk_args(bk_param_v3_t *bpp)
18012654012fSReza Sabdar {
18022654012fSReza Sabdar 	int rv;
18032654012fSReza Sabdar 
18042654012fSReza Sabdar 	if (!bpp) {
18052654012fSReza Sabdar 		rv = -1;
18062654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Lost bpp");
18072654012fSReza Sabdar 	} else if (!bpp->bp_session) {
18082654012fSReza Sabdar 		rv = -1;
18092654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Session is NULL");
18102654012fSReza Sabdar 	} else if (bpp->bp_session->ns_eof) {
18112654012fSReza Sabdar 		rv = -1;
18122654012fSReza Sabdar 		NDMP_LOG(LOG_INFO,
18132654012fSReza Sabdar 		    "Connection client is closed for backup \"%s\"",
18142654012fSReza Sabdar 		    bpp->bp_nlp->nlp_backup_path);
18152654012fSReza Sabdar 	} else if (!bpp->bp_nlp) {
18162654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Lost nlp");
18172654012fSReza Sabdar 		return (-1);
18182654012fSReza Sabdar 	} else if (bpp->bp_session->ns_data.dd_abort) {
18192654012fSReza Sabdar 		rv = -1;
18202654012fSReza Sabdar 		NDMP_LOG(LOG_INFO, "Backup aborted \"%s\"",
18212654012fSReza Sabdar 		    bpp->bp_nlp->nlp_backup_path);
18222654012fSReza Sabdar 	} else
18232654012fSReza Sabdar 		rv = 0;
18242654012fSReza Sabdar 
18252654012fSReza Sabdar 	return (rv);
18262654012fSReza Sabdar }
18272654012fSReza Sabdar 
18282654012fSReza Sabdar 
18292654012fSReza Sabdar /*
18302654012fSReza Sabdar  * shouldskip
18312654012fSReza Sabdar  *
18322654012fSReza Sabdar  * Determines if the current entry should be skipped or it
18332654012fSReza Sabdar  * should be backed up.
18342654012fSReza Sabdar  *
18352654012fSReza Sabdar  * Parameters:
18362654012fSReza Sabdar  *   bpp (input) - pointer to the backup parameters structure
18372654012fSReza Sabdar  *   pnp (input) - pointer to the path node
18382654012fSReza Sabdar  *   enp (input) - pointer to the entry node
18392654012fSReza Sabdar  *   errp (output) - pointer to the error value that should be
18402654012fSReza Sabdar  *	returned by the caller
18412654012fSReza Sabdar  *
18422654012fSReza Sabdar  * Returns:
18432654012fSReza Sabdar  *   TRUE: if the entry should not be backed up
18442654012fSReza Sabdar  *   FALSE: otherwise
18452654012fSReza Sabdar  */
18462654012fSReza Sabdar static boolean_t
18472654012fSReza Sabdar shouldskip(bk_param_v3_t *bpp, fst_node_t *pnp,
18482654012fSReza Sabdar     fst_node_t *enp, int *errp)
18492654012fSReza Sabdar {
18502654012fSReza Sabdar 	char *ent;
18512654012fSReza Sabdar 	boolean_t rv;
18522654012fSReza Sabdar 	struct stat64 *estp;
18532654012fSReza Sabdar 
18542654012fSReza Sabdar 	if (!bpp || !pnp || !enp || !errp) {
18552654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
18562654012fSReza Sabdar 		return (TRUE);
18572654012fSReza Sabdar 	}
18582654012fSReza Sabdar 
18592654012fSReza Sabdar 	if (!enp->tn_path) {
18602654012fSReza Sabdar 		ent = "";
18612654012fSReza Sabdar 		estp = pnp->tn_st;
18622654012fSReza Sabdar 	} else {
18632654012fSReza Sabdar 		ent = enp->tn_path;
18642654012fSReza Sabdar 		estp = enp->tn_st;
18652654012fSReza Sabdar 	}
18662654012fSReza Sabdar 
18672654012fSReza Sabdar 	/*
18682654012fSReza Sabdar 	 * When excluding or skipping entries, FST_SKIP should be
18692654012fSReza Sabdar 	 * returned, otherwise, 0 should be returned to
18702654012fSReza Sabdar 	 * get other entries in the directory of this entry.
18712654012fSReza Sabdar 	 */
18722654012fSReza Sabdar 	if (!dbm_getone(bpp->bp_nlp->nlp_bkmap, (u_longlong_t)estp->st_ino)) {
18732654012fSReza Sabdar 		rv = TRUE;
18742654012fSReza Sabdar 		*errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
18752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Skipping %d %s/%s",
18762654012fSReza Sabdar 		    *errp, pnp->tn_path, ent);
18772654012fSReza Sabdar 	} else if (tlm_is_excluded(pnp->tn_path, ent, bpp->bp_excls)) {
18782654012fSReza Sabdar 		rv = TRUE;
18792654012fSReza Sabdar 		*errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
18802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "excl %d \"%s/%s\"",
18812654012fSReza Sabdar 		    *errp, pnp->tn_path, ent);
18822654012fSReza Sabdar 	} else if (inexl(bpp->bp_nlp->nlp_exl, ent)) {
18832654012fSReza Sabdar 		rv = TRUE;
18842654012fSReza Sabdar 		*errp = S_ISDIR(estp->st_mode) ? FST_SKIP : 0;
18852654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "out %d \"%s/%s\"",
18862654012fSReza Sabdar 		    *errp, pnp->tn_path, ent);
18872654012fSReza Sabdar 	} else if (!S_ISDIR(estp->st_mode) &&
18882654012fSReza Sabdar 	    !ininc(bpp->bp_nlp->nlp_inc, ent)) {
18892654012fSReza Sabdar 		rv = TRUE;
18902654012fSReza Sabdar 		*errp = 0;
18912654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "!in \"%s/%s\"", pnp->tn_path, ent);
18922654012fSReza Sabdar 	} else
18932654012fSReza Sabdar 		rv = FALSE;
18942654012fSReza Sabdar 
18952654012fSReza Sabdar 	return (rv);
18962654012fSReza Sabdar }
18972654012fSReza Sabdar 
18982654012fSReza Sabdar 
18992654012fSReza Sabdar /*
19002654012fSReza Sabdar  * ischngd
19012654012fSReza Sabdar  *
19022654012fSReza Sabdar  * Check if the object specified should be backed up or not.
19032654012fSReza Sabdar  * If stp belongs to a directory and if it is marked in the
19042654012fSReza Sabdar  * bitmap vector, it shows that either the directory itself is
19052654012fSReza Sabdar  * modified or there is something below it that will be backed
19062654012fSReza Sabdar  * up.
19072654012fSReza Sabdar  *
19082654012fSReza Sabdar  * By setting ndmp_force_bk_dirs global variable to a non-zero
19092654012fSReza Sabdar  * value, directories are backed up anyways.
19102654012fSReza Sabdar  *
19112654012fSReza Sabdar  * Backing up the directories unconditionally helps
19122654012fSReza Sabdar  * restoring the metadata of directories as well, when one
19132654012fSReza Sabdar  * of the objects below them are being restored.
19142654012fSReza Sabdar  *
19152654012fSReza Sabdar  * For non-directory objects, if the modification or change
19162654012fSReza Sabdar  * time of the object is after the date specified by the
19172654012fSReza Sabdar  * bk_selector_t, the the object must be backed up.
19182654012fSReza Sabdar  */
19192654012fSReza Sabdar static boolean_t
19202654012fSReza Sabdar ischngd(struct stat64 *stp, time_t t, ndmp_lbr_params_t *nlp)
19212654012fSReza Sabdar {
19222654012fSReza Sabdar 	boolean_t rv;
19232654012fSReza Sabdar 
19242654012fSReza Sabdar 	if (!stp) {
19252654012fSReza Sabdar 		rv = FALSE;
19262654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "stp is NULL");
19272654012fSReza Sabdar 	} else if (!nlp) {
19282654012fSReza Sabdar 		rv = FALSE;
19292654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp is NULL");
19302654012fSReza Sabdar 	} else if (t == 0) {
19312654012fSReza Sabdar 		/*
19322654012fSReza Sabdar 		 * if we are doing base backup then we do not need to
19332654012fSReza Sabdar 		 * check the time, for we should backup everything.
19342654012fSReza Sabdar 		 */
19352654012fSReza Sabdar 		rv = TRUE;
19362654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Base Backup");
19372654012fSReza Sabdar 	} else if (S_ISDIR(stp->st_mode) && ndmp_force_bk_dirs) {
19382654012fSReza Sabdar 		rv = TRUE;
19392654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "d(%lu)", (uint_t)stp->st_ino);
19402654012fSReza Sabdar 	} else if (S_ISDIR(stp->st_mode) &&
19412654012fSReza Sabdar 	    dbm_getone(nlp->nlp_bkmap, (u_longlong_t)stp->st_ino) &&
19422654012fSReza Sabdar 	    ((NLP_ISDUMP(nlp) && ndmp_dump_path_node) ||
19432654012fSReza Sabdar 	    (NLP_ISTAR(nlp) && ndmp_tar_path_node))) {
19442654012fSReza Sabdar 		/*
19452654012fSReza Sabdar 		 * If the object is a directory and it leads to a modified
19462654012fSReza Sabdar 		 * object (that should be backed up) and for that type of
19472654012fSReza Sabdar 		 * backup the path nodes should be backed up, then return
19482654012fSReza Sabdar 		 * TRUE.
19492654012fSReza Sabdar 		 *
19502654012fSReza Sabdar 		 * This is required by some DMAs like Backup Express, which
19512654012fSReza Sabdar 		 * needs to receive ADD_NODE (for dump) or ADD_PATH (for tar)
19522654012fSReza Sabdar 		 * for the intermediate directories of a modified object.
19532654012fSReza Sabdar 		 * Other DMAs, like net_backup and net_worker, do not have such
19542654012fSReza Sabdar 		 * requirement.  This requirement makes sense for dump format
19552654012fSReza Sabdar 		 * but for 'tar' format, it does not.  In provision to the
19562654012fSReza Sabdar 		 * NDMP-v4 spec, for 'tar' format the intermediate directories
19572654012fSReza Sabdar 		 * need not to be reported.
19582654012fSReza Sabdar 		 */
19592654012fSReza Sabdar 		rv = TRUE;
19602654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "p(%lu)", (u_longlong_t)stp->st_ino);
19612654012fSReza Sabdar 	} else if (stp->st_mtime > t) {
19622654012fSReza Sabdar 		rv = TRUE;
19632654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "m(%lu): %lu > %lu",
19642654012fSReza Sabdar 		    (uint_t)stp->st_ino, (uint_t)stp->st_mtime, (uint_t)t);
19652654012fSReza Sabdar 	} else if (stp->st_ctime > t) {
19662654012fSReza Sabdar 		if (NLP_IGNCTIME(nlp)) {
19672654012fSReza Sabdar 			rv = FALSE;
19682654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "ign c(%lu): %lu > %lu",
19692654012fSReza Sabdar 			    (uint_t)stp->st_ino, (uint_t)stp->st_ctime,
19702654012fSReza Sabdar 			    (uint_t)t);
19712654012fSReza Sabdar 		} else {
19722654012fSReza Sabdar 			rv = TRUE;
19732654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "c(%lu): %lu > %lu",
19742654012fSReza Sabdar 			    (uint_t)stp->st_ino, (uint_t)stp->st_ctime,
19752654012fSReza Sabdar 			    (uint_t)t);
19762654012fSReza Sabdar 		}
19772654012fSReza Sabdar 	} else {
19782654012fSReza Sabdar 		rv = FALSE;
19792654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "mc(%lu): (%lu,%lu) < %lu",
19802654012fSReza Sabdar 		    (uint_t)stp->st_ino, (uint_t)stp->st_mtime,
19812654012fSReza Sabdar 		    (uint_t)stp->st_ctime, (uint_t)t);
19822654012fSReza Sabdar 	}
19832654012fSReza Sabdar 
19842654012fSReza Sabdar 	return (rv);
19852654012fSReza Sabdar }
19862654012fSReza Sabdar 
19872654012fSReza Sabdar 
19882654012fSReza Sabdar /*
19892654012fSReza Sabdar  * iscreated
19902654012fSReza Sabdar  *
19912654012fSReza Sabdar  * This function is used to check last mtime (currently inside the ACL
19922654012fSReza Sabdar  * structure) instead of ctime for checking if the file is to be backed up
19932654012fSReza Sabdar  * or not. See option "inc.lmtime" for more details
19942654012fSReza Sabdar  */
19952654012fSReza Sabdar /*ARGSUSED*/
19962654012fSReza Sabdar int iscreated(ndmp_lbr_params_t *nlp, char *name, tlm_acls_t *tacl,
19972654012fSReza Sabdar     time_t t)
19982654012fSReza Sabdar {
19992654012fSReza Sabdar 	int ret;
20002654012fSReza Sabdar 	acl_t *aclp = NULL;
20012654012fSReza Sabdar 	char *acltp;
20022654012fSReza Sabdar 
20032654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
20042654012fSReza Sabdar 	if (NLP_INCLMTIME(nlp) == FALSE)
20052654012fSReza Sabdar 		return (0);
20062654012fSReza Sabdar 
20072654012fSReza Sabdar 	ret = acl_get(name, ACL_NO_TRIVIAL, &aclp);
20082654012fSReza Sabdar 	if (ret != 0) {
20092654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
20102654012fSReza Sabdar 		    "Error getting the acl information: err %d", ret);
20112654012fSReza Sabdar 		return (0);
20122654012fSReza Sabdar 	}
20132654012fSReza Sabdar 	if (aclp && (acltp = acl_totext(aclp,
20142654012fSReza Sabdar 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
20152654012fSReza Sabdar 		(void) strlcpy(tacl->acl_info.attr_info, acltp,
20162654012fSReza Sabdar 		    TLM_MAX_ACL_TXT);
20172654012fSReza Sabdar 		acl_free(aclp);
20182654012fSReza Sabdar 		free(acltp);
20192654012fSReza Sabdar 	}
20202654012fSReza Sabdar 
20212654012fSReza Sabdar 	/* Need to add support for last mtime */
20222654012fSReza Sabdar 
20232654012fSReza Sabdar 	return (0);
20242654012fSReza Sabdar }
20252654012fSReza Sabdar 
20262654012fSReza Sabdar /*
20272654012fSReza Sabdar  * size_cb
20282654012fSReza Sabdar  *
20292654012fSReza Sabdar  * The callback function for calculating the size of
20302654012fSReza Sabdar  * the backup path. This is used to get an estimate
20312654012fSReza Sabdar  * of the progress of backup during NDMP backup
20322654012fSReza Sabdar  */
20332654012fSReza Sabdar static int
20342654012fSReza Sabdar size_cb(void *arg, fst_node_t *pnp, fst_node_t *enp)
20352654012fSReza Sabdar {
20362654012fSReza Sabdar 	struct stat64 *stp;
20372654012fSReza Sabdar 
20382654012fSReza Sabdar 	stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
20392654012fSReza Sabdar 	*((u_longlong_t *)arg) += stp->st_size;
20402654012fSReza Sabdar 
20412654012fSReza Sabdar 	return (0);
20422654012fSReza Sabdar }
20432654012fSReza Sabdar 
20442654012fSReza Sabdar /*
20452654012fSReza Sabdar  * timebk_v3
20462654012fSReza Sabdar  *
20472654012fSReza Sabdar  * The callback function for backing up objects based on
20482654012fSReza Sabdar  * their time stamp.  This is shared between token-based
20492654012fSReza Sabdar  * and level-based backup, which look at the time stamps
20502654012fSReza Sabdar  * of the objects to determine if they should be backed
20512654012fSReza Sabdar  * up.
20522654012fSReza Sabdar  *
20532654012fSReza Sabdar  * Parameters:
20542654012fSReza Sabdar  *   arg (input) - pointer to the backup parameters structure
20552654012fSReza Sabdar  *   pnp (input) - pointer to the path node
20562654012fSReza Sabdar  *   enp (input) - pointer to the entry node
20572654012fSReza Sabdar  *
20582654012fSReza Sabdar  * Returns:
20592654012fSReza Sabdar  *   0: if backup should continue
20602654012fSReza Sabdar  *   -1: if the backup should be stopped
20612654012fSReza Sabdar  *   FST_SKIP: if backing up the current directory is enough
20622654012fSReza Sabdar  */
20632654012fSReza Sabdar static int
20642654012fSReza Sabdar timebk_v3(void *arg, fst_node_t *pnp, fst_node_t *enp)
20652654012fSReza Sabdar {
20662654012fSReza Sabdar 	char *ent;
20672654012fSReza Sabdar 	int rv;
20682654012fSReza Sabdar 	time_t t;
20692654012fSReza Sabdar 	bk_param_v3_t *bpp;
20702654012fSReza Sabdar 	struct stat64 *stp;
20712654012fSReza Sabdar 	fs_fhandle_t *fhp;
20722654012fSReza Sabdar 
20732654012fSReza Sabdar 	bpp = (bk_param_v3_t *)arg;
20742654012fSReza Sabdar 
20752654012fSReza Sabdar 	rv = check_bk_args(bpp);
20762654012fSReza Sabdar 	if (rv != 0)
20772654012fSReza Sabdar 		return (rv);
20782654012fSReza Sabdar 
20792654012fSReza Sabdar 	stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
20802654012fSReza Sabdar 	if (shouldskip(bpp, pnp, enp, &rv))
20812654012fSReza Sabdar 		return (rv);
20822654012fSReza Sabdar 
20832654012fSReza Sabdar 	if (enp->tn_path) {
20842654012fSReza Sabdar 		ent = enp->tn_path;
20852654012fSReza Sabdar 		stp = enp->tn_st;
20862654012fSReza Sabdar 		fhp = enp->tn_fh;
20872654012fSReza Sabdar 	} else {
20882654012fSReza Sabdar 		ent = "";
20892654012fSReza Sabdar 		stp = pnp->tn_st;
20902654012fSReza Sabdar 		fhp = pnp->tn_fh;
20912654012fSReza Sabdar 	}
20922654012fSReza Sabdar 
20932654012fSReza Sabdar 
20942654012fSReza Sabdar 	if (!tlm_cat_path(bpp->bp_tmp, pnp->tn_path, ent)) {
20952654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Path too long %s/%s.", pnp->tn_path, ent);
20962654012fSReza Sabdar 		return (FST_SKIP);
20972654012fSReza Sabdar 	}
20982654012fSReza Sabdar 	if (NLP_ISSET(bpp->bp_nlp, NLPF_TOKENBK))
20992654012fSReza Sabdar 		t = bpp->bp_nlp->nlp_tokdate;
21002654012fSReza Sabdar 	else if (NLP_ISSET(bpp->bp_nlp, NLPF_LEVELBK)) {
21012654012fSReza Sabdar 		t = bpp->bp_nlp->nlp_ldate;
21022654012fSReza Sabdar 	} else {
21032654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unknown backup type on \"%s/%s\"",
21042654012fSReza Sabdar 		    pnp->tn_path, ent);
21052654012fSReza Sabdar 		return (-1);
21062654012fSReza Sabdar 	}
21072654012fSReza Sabdar 
21082654012fSReza Sabdar 	if (S_ISDIR(stp->st_mode)) {
21092654012fSReza Sabdar 		bpp->bp_tlmacl->acl_dir_fh = *fhp;
21102654012fSReza Sabdar 		(void) ndmpd_fhdir_v3_cb(bpp->bp_nlp->nlp_logcallbacks,
21112654012fSReza Sabdar 		    bpp->bp_tmp, stp);
21122654012fSReza Sabdar 
21132654012fSReza Sabdar 		if (ischngd(stp, t, bpp->bp_nlp)) {
21142654012fSReza Sabdar 			(void) memcpy(&bpp->bp_tlmacl->acl_attr, stp,
21152654012fSReza Sabdar 			    sizeof (struct stat64));
21162654012fSReza Sabdar 			rv = backup_dirv3(bpp, pnp, enp);
21172654012fSReza Sabdar 		}
21182654012fSReza Sabdar 	} else {
21192654012fSReza Sabdar 		if (ischngd(stp, t, bpp->bp_nlp) ||
21202654012fSReza Sabdar 		    iscreated(bpp->bp_nlp, bpp->bp_tmp, bpp->bp_tlmacl, t)) {
21212654012fSReza Sabdar 			rv = 0;
21222654012fSReza Sabdar 			(void) memcpy(&bpp->bp_tlmacl->acl_attr, stp,
21232654012fSReza Sabdar 			    sizeof (struct stat64));
21242654012fSReza Sabdar 			bpp->bp_tlmacl->acl_fil_fh = *fhp;
21252654012fSReza Sabdar 			(void) backup_filev3(bpp, pnp, enp);
21262654012fSReza Sabdar 		}
21272654012fSReza Sabdar 	}
21282654012fSReza Sabdar 
21292654012fSReza Sabdar 	return (rv);
21302654012fSReza Sabdar }
21312654012fSReza Sabdar 
21322654012fSReza Sabdar 
21332654012fSReza Sabdar /*
21342654012fSReza Sabdar  * lbrbk_v3
21352654012fSReza Sabdar  *
21362654012fSReza Sabdar  * The callback function for backing up objects based on
21372654012fSReza Sabdar  * their archive directory bit.  This is used in LBR-type
21382654012fSReza Sabdar  * backup.  In which the objects are backed up if their
21392654012fSReza Sabdar  * archive bit is set.
21402654012fSReza Sabdar  *
21412654012fSReza Sabdar  * Parameters:
21422654012fSReza Sabdar  *   arg (input) - pointer to the backup parameters structure
21432654012fSReza Sabdar  *   pnp (input) - pointer to the path node
21442654012fSReza Sabdar  *   enp (input) - pointer to the entry node
21452654012fSReza Sabdar  *
21462654012fSReza Sabdar  * Returns:
21472654012fSReza Sabdar  *   0: if backup should continue
21482654012fSReza Sabdar  *   -1: if the backup should be stopped
21492654012fSReza Sabdar  *   FST_SKIP: if backing up the current directory is enough
21502654012fSReza Sabdar  */
21512654012fSReza Sabdar static int
21522654012fSReza Sabdar lbrbk_v3(void *arg, fst_node_t *pnp, fst_node_t *enp)
21532654012fSReza Sabdar {
21542654012fSReza Sabdar 	char *ent;
21552654012fSReza Sabdar 	int rv;
21562654012fSReza Sabdar 	bk_param_v3_t *bpp;
21572654012fSReza Sabdar 	struct stat64 *stp;
21582654012fSReza Sabdar 	fs_fhandle_t *fhp;
21592654012fSReza Sabdar 
21602654012fSReza Sabdar 	bpp = (bk_param_v3_t *)arg;
21612654012fSReza Sabdar 	rv = check_bk_args(bpp);
21622654012fSReza Sabdar 	if (rv != 0)
21632654012fSReza Sabdar 		return (rv);
21642654012fSReza Sabdar 
21652654012fSReza Sabdar 	stp = enp->tn_path ? enp->tn_st : pnp->tn_st;
21662654012fSReza Sabdar 	if (shouldskip(bpp, pnp, enp, &rv))
21672654012fSReza Sabdar 		return (rv);
21682654012fSReza Sabdar 
21692654012fSReza Sabdar 	if (enp->tn_path) {
21702654012fSReza Sabdar 		ent = enp->tn_path;
21712654012fSReza Sabdar 		stp = enp->tn_st;
21722654012fSReza Sabdar 		fhp = enp->tn_fh;
21732654012fSReza Sabdar 	} else {
21742654012fSReza Sabdar 		ent = "";
21752654012fSReza Sabdar 		stp = pnp->tn_st;
21762654012fSReza Sabdar 		fhp = pnp->tn_fh;
21772654012fSReza Sabdar 	}
21782654012fSReza Sabdar 
21792654012fSReza Sabdar 	if (!tlm_cat_path(bpp->bp_tmp, pnp->tn_path, ent)) {
21802654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Path too long %s/%s.", pnp->tn_path, ent);
21812654012fSReza Sabdar 		return (FST_SKIP);
21822654012fSReza Sabdar 	}
21832654012fSReza Sabdar 	if (!NLP_ISSET(bpp->bp_nlp, NLPF_LBRBK)) {
21842654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "!NLPF_LBRBK");
21852654012fSReza Sabdar 		return (-1);
21862654012fSReza Sabdar 	}
21872654012fSReza Sabdar 
21882654012fSReza Sabdar 	if (S_ISDIR(stp->st_mode)) {
21892654012fSReza Sabdar 		bpp->bp_tlmacl->acl_dir_fh = *fhp;
21902654012fSReza Sabdar 		(void) ndmpd_fhdir_v3_cb(bpp->bp_nlp->nlp_logcallbacks,
21912654012fSReza Sabdar 		    bpp->bp_tmp, stp);
21922654012fSReza Sabdar 
21932654012fSReza Sabdar 		if (SHOULD_LBRBK(bpp)) {
21942654012fSReza Sabdar 			bpp->bp_tlmacl->acl_attr = *stp;
21952654012fSReza Sabdar 			rv = backup_dirv3(bpp, pnp, enp);
21962654012fSReza Sabdar 		}
21972654012fSReza Sabdar 	} else if (SHOULD_LBRBK(bpp)) {
21982654012fSReza Sabdar 		rv = 0;
21992654012fSReza Sabdar 		bpp->bp_tlmacl->acl_attr = *stp;
22002654012fSReza Sabdar 		bpp->bp_tlmacl->acl_fil_fh = *fhp;
22012654012fSReza Sabdar 		(void) backup_filev3(bpp, pnp, enp);
22022654012fSReza Sabdar 	}
22032654012fSReza Sabdar 
22042654012fSReza Sabdar 	return (rv);
22052654012fSReza Sabdar }
22062654012fSReza Sabdar 
22072654012fSReza Sabdar 
22082654012fSReza Sabdar /*
22092654012fSReza Sabdar  * backup_reader_v3
22102654012fSReza Sabdar  *
22112654012fSReza Sabdar  * The reader thread for the backup.  It sets up the callback
22122654012fSReza Sabdar  * parameters and traverses the backup hierarchy in level-order
22132654012fSReza Sabdar  * way.
22142654012fSReza Sabdar  *
22152654012fSReza Sabdar  * Parameters:
22162654012fSReza Sabdar  *   jname (input) - name assigned to the current backup for
22172654012fSReza Sabdar  *	job stats strucure
22182654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
22192654012fSReza Sabdar  *   cmds (input) - pointer to the tlm_commands_t structure
22202654012fSReza Sabdar  *
22212654012fSReza Sabdar  * Returns:
22222654012fSReza Sabdar  *   0: on success
22232654012fSReza Sabdar  *   != 0: otherwise
22242654012fSReza Sabdar  */
22252654012fSReza Sabdar static int
22262654012fSReza Sabdar backup_reader_v3(backup_reader_arg_t *argp)
22272654012fSReza Sabdar {
22282654012fSReza Sabdar 	int rv;
22292654012fSReza Sabdar 	tlm_cmd_t *lcmd;
22302654012fSReza Sabdar 	tlm_acls_t tlm_acls;
22312654012fSReza Sabdar 	longlong_t bpos, n;
22322654012fSReza Sabdar 	bk_param_v3_t bp;
22332654012fSReza Sabdar 	fs_traverse_t ft;
22342654012fSReza Sabdar 	char *jname;
22352654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
22362654012fSReza Sabdar 	tlm_commands_t *cmds;
22372654012fSReza Sabdar 
22382654012fSReza Sabdar 	if (!argp)
22392654012fSReza Sabdar 		return (-1);
22402654012fSReza Sabdar 
22412654012fSReza Sabdar 	jname = argp->br_jname;
22422654012fSReza Sabdar 	nlp = argp->br_nlp;
22432654012fSReza Sabdar 	cmds = argp->br_cmds;
22442654012fSReza Sabdar 
22452654012fSReza Sabdar 	rv = 0;
22462654012fSReza Sabdar 	lcmd = cmds->tcs_command;
22472654012fSReza Sabdar 	lcmd->tc_ref++;
22482654012fSReza Sabdar 	cmds->tcs_reader_count++;
22492654012fSReza Sabdar 
22502654012fSReza Sabdar 	(void) memset(&tlm_acls, 0, sizeof (tlm_acls));
22512654012fSReza Sabdar 
22522654012fSReza Sabdar 	/* NDMP parameters */
22532654012fSReza Sabdar 	bp.bp_session = nlp->nlp_session;
22542654012fSReza Sabdar 	bp.bp_nlp = nlp;
22552654012fSReza Sabdar 
22562654012fSReza Sabdar 	/* LBR-related parameters  */
22572654012fSReza Sabdar 	bp.bp_js = tlm_ref_job_stats(jname);
22582654012fSReza Sabdar 	bp.bp_cmds = cmds;
22592654012fSReza Sabdar 	bp.bp_lcmd = lcmd;
22602654012fSReza Sabdar 	bp.bp_tlmacl = &tlm_acls;
22612654012fSReza Sabdar 	bp.bp_opr = 0;
22622654012fSReza Sabdar 
22632654012fSReza Sabdar 	/* release the parent thread, after referencing the job stats */
22642654012fSReza Sabdar 	(void) pthread_barrier_wait(&argp->br_barrier);
22652654012fSReza Sabdar 
22662654012fSReza Sabdar 	bp.bp_tmp = ndmp_malloc(sizeof (char) * TLM_MAX_PATH_NAME);
22672654012fSReza Sabdar 	if (!bp.bp_tmp)
22682654012fSReza Sabdar 		return (-1);
22692654012fSReza Sabdar 
22702654012fSReza Sabdar 	/*
22712654012fSReza Sabdar 	 * Make the checkpointed paths for traversing the
22722654012fSReza Sabdar 	 * backup hierarchy, if we make the checkpoint.
22732654012fSReza Sabdar 	 */
22742654012fSReza Sabdar 	bp.bp_unchkpnm = nlp->nlp_backup_path;
22752654012fSReza Sabdar 	if (!NLP_ISCHKPNTED(nlp)) {
22762654012fSReza Sabdar 		tlm_acls.acl_checkpointed = TRUE;
22772654012fSReza Sabdar 		bp.bp_chkpnm = ndmp_malloc(sizeof (char) * TLM_MAX_PATH_NAME);
22782654012fSReza Sabdar 		if (!bp.bp_chkpnm) {
22792654012fSReza Sabdar 			NDMP_FREE(bp.bp_tmp);
22802654012fSReza Sabdar 			return (-1);
22812654012fSReza Sabdar 		}
22822654012fSReza Sabdar 		(void) tlm_build_snapshot_name(nlp->nlp_backup_path,
22832654012fSReza Sabdar 		    bp.bp_chkpnm, nlp->nlp_jstat->js_job_name);
22842654012fSReza Sabdar 	} else {
22852654012fSReza Sabdar 		tlm_acls.acl_checkpointed = FALSE;
22862654012fSReza Sabdar 		bp.bp_chkpnm = nlp->nlp_backup_path;
22872654012fSReza Sabdar 	}
22882654012fSReza Sabdar 	bp.bp_excls = ndmpd_make_exc_list();
22892654012fSReza Sabdar 
22902654012fSReza Sabdar 	/* set traversing arguments */
22912654012fSReza Sabdar 	ft.ft_path = nlp->nlp_backup_path;
22922654012fSReza Sabdar 	ft.ft_lpath = bp.bp_chkpnm;
22932654012fSReza Sabdar 
22942654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "path %s lpath %s", ft.ft_path, ft.ft_lpath);
22952654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_TOKENBK) || NLP_ISSET(nlp, NLPF_LEVELBK)) {
22962654012fSReza Sabdar 		ft.ft_callbk = timebk_v3;
22972654012fSReza Sabdar 		tlm_acls.acl_clear_archive = FALSE;
22982654012fSReza Sabdar 	} else if (NLP_ISSET(nlp, NLPF_LBRBK)) {
22992654012fSReza Sabdar 		ft.ft_callbk = lbrbk_v3;
23002654012fSReza Sabdar 		tlm_acls.acl_clear_archive = FALSE;
23012654012fSReza Sabdar 
23022654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "bp_opr %x clr_arc %c",
23032654012fSReza Sabdar 		    bp.bp_opr, NDMP_YORN(tlm_acls.acl_clear_archive));
23042654012fSReza Sabdar 	} else {
23052654012fSReza Sabdar 		rv = -1;
23062654012fSReza Sabdar 		MOD_LOGV3(nlp->nlp_params, NDMP_LOG_ERROR,
23072654012fSReza Sabdar 		    "Unknow backup type.\n");
23082654012fSReza Sabdar 	}
23092654012fSReza Sabdar 	ft.ft_arg = &bp;
23102654012fSReza Sabdar 	ft.ft_logfp = (ft_log_t)ndmp_log;
2311876b86efSReza Sabdar 	ft.ft_flags = FST_VERBOSE | FST_STOP_ONERR;
23122654012fSReza Sabdar 
23132654012fSReza Sabdar 	/* take into account the header written to the stream so far */
23142654012fSReza Sabdar 	n = tlm_get_data_offset(lcmd);
23152654012fSReza Sabdar 	nlp->nlp_session->ns_data.dd_module.dm_stats.ms_bytes_processed = n;
23162654012fSReza Sabdar 
23172654012fSReza Sabdar 	if (rv == 0) {
23182654012fSReza Sabdar 		/* start traversing the hierarchy and actual backup */
23192654012fSReza Sabdar 		rv = traverse_level(&ft);
23202654012fSReza Sabdar 		if (rv == 0) {
23212654012fSReza Sabdar 			/* write the trailer and update the bytes processed */
23222654012fSReza Sabdar 			bpos = tlm_get_data_offset(lcmd);
23232654012fSReza Sabdar 			(void) write_tar_eof(lcmd);
23242654012fSReza Sabdar 			n = tlm_get_data_offset(lcmd) - bpos;
23252654012fSReza Sabdar 			nlp->nlp_session->
23262654012fSReza Sabdar 			    ns_data.dd_module.dm_stats.ms_bytes_processed += n;
2327876b86efSReza Sabdar 		} else {
2328876b86efSReza Sabdar 			MOD_LOGV3(nlp->nlp_params, NDMP_LOG_ERROR,
2329876b86efSReza Sabdar 			    "Filesystem traverse error.\n");
2330876b86efSReza Sabdar 			ndmpd_data_error(nlp->nlp_session,
2331876b86efSReza Sabdar 			    NDMP_DATA_HALT_INTERNAL_ERROR);
23322654012fSReza Sabdar 		}
23332654012fSReza Sabdar 	}
23342654012fSReza Sabdar 
23352654012fSReza Sabdar 	if (!NLP_ISCHKPNTED(nlp))
23362654012fSReza Sabdar 		NDMP_FREE(bp.bp_chkpnm);
23372654012fSReza Sabdar 	NDMP_FREE(bp.bp_tmp);
23382654012fSReza Sabdar 	NDMP_FREE(bp.bp_excls);
23392654012fSReza Sabdar 
23402654012fSReza Sabdar 	cmds->tcs_reader_count--;
23412654012fSReza Sabdar 	lcmd->tc_writer = TLM_STOP;
23422654012fSReza Sabdar 	tlm_release_reader_writer_ipc(lcmd);
23432654012fSReza Sabdar 	tlm_un_ref_job_stats(jname);
23442654012fSReza Sabdar 	return (rv);
23452654012fSReza Sabdar 
23462654012fSReza Sabdar }
23472654012fSReza Sabdar 
23482654012fSReza Sabdar 
23492654012fSReza Sabdar /*
23502654012fSReza Sabdar  * tar_backup_v3
23512654012fSReza Sabdar  *
23522654012fSReza Sabdar  * Traverse the backup hierarchy if needed and make the bitmap.
23532654012fSReza Sabdar  * Then launch reader and writer threads to do the actual backup.
23542654012fSReza Sabdar  *
23552654012fSReza Sabdar  * Parameters:
23562654012fSReza Sabdar  *   session (input) - pointer to the session
23572654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
23582654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
23592654012fSReza Sabdar  *   jname (input) - job name
23602654012fSReza Sabdar  *
23612654012fSReza Sabdar  * Returns:
23622654012fSReza Sabdar  *   0: on success
23632654012fSReza Sabdar  *   != 0: otherwise
23642654012fSReza Sabdar  */
23652654012fSReza Sabdar static int
23662654012fSReza Sabdar tar_backup_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
23672654012fSReza Sabdar     ndmp_lbr_params_t *nlp, char *jname)
23682654012fSReza Sabdar {
23692654012fSReza Sabdar 	tlm_commands_t *cmds;
23702654012fSReza Sabdar 	backup_reader_arg_t arg;
23712654012fSReza Sabdar 	pthread_t rdtp;
23722654012fSReza Sabdar 	char info[256];
23732654012fSReza Sabdar 	int result;
23742654012fSReza Sabdar 	ndmp_context_t nctx;
23752654012fSReza Sabdar 	int err;
23762654012fSReza Sabdar 
23772654012fSReza Sabdar 	if (ndmp_get_bk_dir_ino(nlp))
23782654012fSReza Sabdar 		return (-1);
23792654012fSReza Sabdar 
23802654012fSReza Sabdar 	result = err = 0;
23812654012fSReza Sabdar 
23822654012fSReza Sabdar 	/* exit as if there was an internal error */
23832654012fSReza Sabdar 	if (session->ns_eof)
23842654012fSReza Sabdar 		return (-1);
23852654012fSReza Sabdar 
23862654012fSReza Sabdar 	if (!session->ns_data.dd_abort) {
23872654012fSReza Sabdar 		if (backup_alloc_structs_v3(session, jname) < 0) {
23882654012fSReza Sabdar 			nlp->nlp_bkmap = -1;
23892654012fSReza Sabdar 			return (-1);
23902654012fSReza Sabdar 		}
23912654012fSReza Sabdar 
23922654012fSReza Sabdar 		if (ndmpd_mark_inodes_v3(session, nlp) != 0) {
23932654012fSReza Sabdar 			if (nlp->nlp_bkmap != -1) {
23942654012fSReza Sabdar 				(void) dbm_free(nlp->nlp_bkmap);
23952654012fSReza Sabdar 				nlp->nlp_bkmap = -1;
23962654012fSReza Sabdar 			}
23972654012fSReza Sabdar 			free_structs_v3(session, jname);
23982654012fSReza Sabdar 			return (-1);
23992654012fSReza Sabdar 		}
24002654012fSReza Sabdar 
24012654012fSReza Sabdar 		nlp->nlp_jstat->js_start_ltime = time(NULL);
24022654012fSReza Sabdar 		nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
24032654012fSReza Sabdar 		nlp->nlp_jstat->js_chkpnt_time = nlp->nlp_cdate;
24042654012fSReza Sabdar 
24052654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
24062654012fSReza Sabdar 		cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN;
24072654012fSReza Sabdar 		cmds->tcs_command->tc_reader = TLM_BACKUP_RUN;
24082654012fSReza Sabdar 		cmds->tcs_command->tc_writer = TLM_BACKUP_RUN;
24092654012fSReza Sabdar 
24102654012fSReza Sabdar 		if (ndmp_write_utf8magic(cmds->tcs_command) < 0) {
24112654012fSReza Sabdar 			free_structs_v3(session, jname);
24122654012fSReza Sabdar 			return (-1);
24132654012fSReza Sabdar 		}
24142654012fSReza Sabdar 
24152654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
24162654012fSReza Sabdar 		    "Backing up \"%s\" started.", nlp->nlp_backup_path);
24172654012fSReza Sabdar 
24182654012fSReza Sabdar 		/* Plug-in module */
24192654012fSReza Sabdar 		if (ndmp_pl != NULL &&
24202654012fSReza Sabdar 		    ndmp_pl->np_pre_backup != NULL) {
24212654012fSReza Sabdar 			(void) memset(&nctx, 0, sizeof (ndmp_context_t));
24222654012fSReza Sabdar 			nctx.nc_plversion = ndmp_pl->np_plversion;
24232654012fSReza Sabdar 			nctx.nc_plname = ndmpd_get_prop(NDMP_PLUGIN_PATH);
24242654012fSReza Sabdar 			nctx.nc_cmds = cmds;
242542ed7838SReza Sabdar 			nctx.nc_params = params;
24268c4f9701SJanice Chang 			nctx.nc_ddata = (void *) session;
24272654012fSReza Sabdar 			if ((err = ndmp_pl->np_pre_backup(ndmp_pl, &nctx,
24282654012fSReza Sabdar 			    nlp->nlp_backup_path)) != 0) {
242942ed7838SReza Sabdar 				NDMP_LOG(LOG_ERR, "Pre-backup plug-in: %m");
24302654012fSReza Sabdar 				goto backup_out;
24312654012fSReza Sabdar 			}
24322654012fSReza Sabdar 		}
24332654012fSReza Sabdar 
24342654012fSReza Sabdar 		(void) memset(&arg, 0, sizeof (backup_reader_arg_t));
24352654012fSReza Sabdar 		arg.br_jname = jname;
24362654012fSReza Sabdar 		arg.br_nlp = nlp;
24372654012fSReza Sabdar 		arg.br_cmds = cmds;
24382654012fSReza Sabdar 
24392654012fSReza Sabdar 		(void) pthread_barrier_init(&arg.br_barrier, 0, 2);
24402654012fSReza Sabdar 
24412654012fSReza Sabdar 		err = pthread_create(&rdtp, NULL, (funct_t)backup_reader_v3,
24422654012fSReza Sabdar 		    (void *)&arg);
24432654012fSReza Sabdar 		if (err == 0) {
24442654012fSReza Sabdar 			(void) pthread_barrier_wait(&arg.br_barrier);
24452654012fSReza Sabdar 			(void) pthread_barrier_destroy(&arg.br_barrier);
24462654012fSReza Sabdar 		} else {
24472654012fSReza Sabdar 			(void) pthread_barrier_destroy(&arg.br_barrier);
24482654012fSReza Sabdar 			free_structs_v3(session, jname);
24492654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Launch backup_reader_v3: %m");
24502654012fSReza Sabdar 			return (-1);
24512654012fSReza Sabdar 		}
24522654012fSReza Sabdar 
24532654012fSReza Sabdar 		if ((err = ndmp_tar_writer(session, params, cmds)) != 0)
24542654012fSReza Sabdar 			result = EIO;
24552654012fSReza Sabdar 
24562654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
24572654012fSReza Sabdar 
24582654012fSReza Sabdar 		(void) snprintf(info, sizeof (info),
24592654012fSReza Sabdar 		    "Runtime [%s] %llu bytes (%llu): %d seconds\n",
24602654012fSReza Sabdar 		    nlp->nlp_backup_path,
24612654012fSReza Sabdar 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed,
24622654012fSReza Sabdar 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed,
24632654012fSReza Sabdar 		    nlp->nlp_jstat->js_stop_time -
24642654012fSReza Sabdar 		    nlp->nlp_jstat->js_start_ltime);
24652654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL, info);
24662654012fSReza Sabdar 
24672654012fSReza Sabdar 		ndmp_wait_for_reader(cmds);
24682654012fSReza Sabdar 		(void) pthread_join(rdtp, NULL);
24692654012fSReza Sabdar 
24702654012fSReza Sabdar 		/* exit as if there was an internal error */
24712654012fSReza Sabdar 		if (session->ns_eof) {
24722654012fSReza Sabdar 			result = EPIPE;
24732654012fSReza Sabdar 			err = -1;
24742654012fSReza Sabdar 		}
24752654012fSReza Sabdar 		if (!session->ns_data.dd_abort) {
24762654012fSReza Sabdar 			ndmpd_audit_backup(session->ns_connection,
24772654012fSReza Sabdar 			    nlp->nlp_backup_path,
24782654012fSReza Sabdar 			    session->ns_data.dd_data_addr.addr_type,
24792654012fSReza Sabdar 			    session->ns_tape.td_adapter_name, result);
24802654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" Finished.",
24812654012fSReza Sabdar 			    nlp->nlp_backup_path);
24822654012fSReza Sabdar 		}
24832654012fSReza Sabdar 	}
24842654012fSReza Sabdar 
24852654012fSReza Sabdar 	if (session->ns_data.dd_abort) {
24862654012fSReza Sabdar 		ndmpd_audit_backup(session->ns_connection,
24872654012fSReza Sabdar 		    nlp->nlp_backup_path,
24882654012fSReza Sabdar 		    session->ns_data.dd_data_addr.addr_type,
24892654012fSReza Sabdar 		    session->ns_tape.td_adapter_name, EINTR);
24902654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
24912654012fSReza Sabdar 		    "Backing up \"%s\" aborted.", nlp->nlp_backup_path);
24922654012fSReza Sabdar 		err = -1;
24932654012fSReza Sabdar 	} else {
24942654012fSReza Sabdar 
24952654012fSReza Sabdar backup_out:
24962654012fSReza Sabdar 		/* Plug-in module */
24972654012fSReza Sabdar 		if (ndmp_pl != NULL &&
24982654012fSReza Sabdar 		    ndmp_pl->np_post_backup != NULL &&
24992654012fSReza Sabdar 		    ndmp_pl->np_post_backup(ndmp_pl, &nctx, err) == -1) {
25002654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Post-backup plug-in: %m");
25012654012fSReza Sabdar 			return (-1);
25022654012fSReza Sabdar 		}
25032654012fSReza Sabdar 	}
25042654012fSReza Sabdar 
25052654012fSReza Sabdar 	free_structs_v3(session, jname);
25062654012fSReza Sabdar 	return (err);
25072654012fSReza Sabdar }
25082654012fSReza Sabdar 
25092654012fSReza Sabdar /*
25102654012fSReza Sabdar  * get_backup_size
25112654012fSReza Sabdar  *
25122654012fSReza Sabdar  * Find the estimate of backup size. This is used to get an estimate
25132654012fSReza Sabdar  * of the progress of backup during NDMP backup.
25142654012fSReza Sabdar  */
25152654012fSReza Sabdar void
2516416eec61SReza Sabdar get_backup_size(ndmp_bkup_size_arg_t *sarg)
25172654012fSReza Sabdar {
25182654012fSReza Sabdar 	fs_traverse_t ft;
25192654012fSReza Sabdar 	u_longlong_t bk_size;
2520416eec61SReza Sabdar 	char spath[PATH_MAX];
25212654012fSReza Sabdar 	int rv;
25222654012fSReza Sabdar 
25232654012fSReza Sabdar 	bk_size = 0;
2524416eec61SReza Sabdar 	if (fs_is_chkpntvol(sarg->bs_path)) {
2525416eec61SReza Sabdar 		ft.ft_path = sarg->bs_path;
2526416eec61SReza Sabdar 	} else {
2527416eec61SReza Sabdar 		(void) tlm_build_snapshot_name(sarg->bs_path,
2528416eec61SReza Sabdar 		    spath, sarg->bs_jname);
2529416eec61SReza Sabdar 		ft.ft_path = spath;
2530416eec61SReza Sabdar 	}
25312654012fSReza Sabdar 
2532416eec61SReza Sabdar 	ft.ft_lpath = ft.ft_path;
25332654012fSReza Sabdar 	ft.ft_callbk = size_cb;
25342654012fSReza Sabdar 	ft.ft_arg = &bk_size;
25352654012fSReza Sabdar 	ft.ft_logfp = (ft_log_t)ndmp_log;
2536416eec61SReza Sabdar 	ft.ft_flags = FST_VERBOSE;
25372654012fSReza Sabdar 
25382654012fSReza Sabdar 	if ((rv = traverse_level(&ft)) != 0) {
25392654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "bksize err=%d", rv);
25402654012fSReza Sabdar 		bk_size = 0;
25412654012fSReza Sabdar 	} else {
25422654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "bksize %lld, %lldKB, %lldMB\n",
25432654012fSReza Sabdar 		    bk_size, bk_size / 1024, bk_size /(1024 * 1024));
25442654012fSReza Sabdar 	}
2545416eec61SReza Sabdar 	sarg->bs_session->ns_data.dd_data_size = bk_size;
25462654012fSReza Sabdar }
25472654012fSReza Sabdar 
25482654012fSReza Sabdar /*
25492654012fSReza Sabdar  * get_rs_path_v3
25502654012fSReza Sabdar  *
25512654012fSReza Sabdar  * Find the restore path
25522654012fSReza Sabdar  */
25532654012fSReza Sabdar ndmp_error
25542654012fSReza Sabdar get_rs_path_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
25552654012fSReza Sabdar {
25562654012fSReza Sabdar 	char *dp;
25572654012fSReza Sabdar 	ndmp_error rv;
25582654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
25592654012fSReza Sabdar 	int i, nm_cnt;
25602654012fSReza Sabdar 	char *nm_dpath_list[MULTIPLE_DEST_DIRS];
25612654012fSReza Sabdar 	static char mdest_buf[256];
25622654012fSReza Sabdar 
25632654012fSReza Sabdar 	*mdest_buf = 0;
25642654012fSReza Sabdar 	*nm_dpath_list = "";
25652654012fSReza Sabdar 	for (i = 0, nm_cnt = 0; i < (int)nlp->nlp_nfiles; i++) {
25662654012fSReza Sabdar 		ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
25672654012fSReza Sabdar 		if (!ep) {
25682654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Can't get Nlist[%d]", i);
25692654012fSReza Sabdar 			return (NDMP_ILLEGAL_ARGS_ERR);
25702654012fSReza Sabdar 		}
25712654012fSReza Sabdar 		if (strcmp(nm_dpath_list[nm_cnt], ep->nm3_dpath) != 0 &&
25722654012fSReza Sabdar 		    nm_cnt < MULTIPLE_DEST_DIRS - 1)
25732654012fSReza Sabdar 			nm_dpath_list[++nm_cnt] = ep->nm3_dpath;
25742654012fSReza Sabdar 	}
25752654012fSReza Sabdar 
25762654012fSReza Sabdar 	multiple_dest_restore = (nm_cnt > 1);
25772654012fSReza Sabdar 	nlp->nlp_restore_path = mdest_buf;
25782654012fSReza Sabdar 
25792654012fSReza Sabdar 	for (i = 1; i < nm_cnt + 1; i++) {
25802654012fSReza Sabdar 		if (ISDEFINED(nm_dpath_list[i]))
25812654012fSReza Sabdar 			dp = nm_dpath_list[i];
25822654012fSReza Sabdar 		else
25832654012fSReza Sabdar 			/* the default destination path is backup directory */
25842654012fSReza Sabdar 			dp = nlp->nlp_backup_path;
25852654012fSReza Sabdar 
25862654012fSReza Sabdar 		/* check the destination directory exists and is writable */
25872654012fSReza Sabdar 		if (!fs_volexist(dp)) {
25882654012fSReza Sabdar 			rv = NDMP_ILLEGAL_ARGS_ERR;
25892654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
25902654012fSReza Sabdar 			    "Invalid destination path volume \"%s\".\n", dp);
25912654012fSReza Sabdar 		} else if (!voliswr(dp)) {
25922654012fSReza Sabdar 			rv = NDMP_ILLEGAL_ARGS_ERR;
25932654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
25942654012fSReza Sabdar 			    "The destination path volume"
25952654012fSReza Sabdar 			    " is not writable \"%s\".\n", dp);
25962654012fSReza Sabdar 		} else {
25972654012fSReza Sabdar 			rv = NDMP_NO_ERR;
25982654012fSReza Sabdar 			(void) strlcat(nlp->nlp_restore_path, dp,
25992654012fSReza Sabdar 			    sizeof (mdest_buf));
26002654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "rspath: \"%s\"", dp);
26012654012fSReza Sabdar 		}
26022654012fSReza Sabdar 
26032654012fSReza Sabdar 		/*
26042654012fSReza Sabdar 		 * Exit if there is an error or it is not a multiple
26052654012fSReza Sabdar 		 * destination restore mode
26062654012fSReza Sabdar 		 */
26072654012fSReza Sabdar 		if (rv != NDMP_NO_ERR || !multiple_dest_restore)
26082654012fSReza Sabdar 			break;
26092654012fSReza Sabdar 
26102654012fSReza Sabdar 		if (i < nm_cnt)
26112654012fSReza Sabdar 			(void) strlcat(nlp->nlp_restore_path, ", ",
26122654012fSReza Sabdar 			    sizeof (mdest_buf));
26132654012fSReza Sabdar 	}
26142654012fSReza Sabdar 
26152654012fSReza Sabdar 	return (rv);
26162654012fSReza Sabdar }
26172654012fSReza Sabdar 
26182654012fSReza Sabdar 
26192654012fSReza Sabdar /*
26202654012fSReza Sabdar  * fix_nlist_v3
26212654012fSReza Sabdar  *
26222654012fSReza Sabdar  * Check if the recovery list is valid and fix it if there are some
26232654012fSReza Sabdar  * unspecified entries in it. It checks for original, destination
26242654012fSReza Sabdar  * and new path for all NDMP names provided inside the list.
26252654012fSReza Sabdar  *
26262654012fSReza Sabdar  * V3: dpath is the destination directory.  If newnm is not NULL, the
26272654012fSReza Sabdar  * destination path is dpath/newnm.  Otherwise the destination path is
26282654012fSReza Sabdar  * dpath/opath_last_node, where opath_last_node is the last node in opath.
26292654012fSReza Sabdar  *
26302654012fSReza Sabdar  * V4: If newnm is not NULL, dpath is the destination directory, and
26312654012fSReza Sabdar  * dpath/newnm is the destination path.  If newnm is NULL, dpath is
26322654012fSReza Sabdar  * the destination path (opath is not involved in forming destination path).
26332654012fSReza Sabdar  */
26342654012fSReza Sabdar ndmp_error
26352654012fSReza Sabdar fix_nlist_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
26362654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
26372654012fSReza Sabdar {
26382654012fSReza Sabdar 	char *cp, *buf, *bp;
26392654012fSReza Sabdar 	int i, n;
26402654012fSReza Sabdar 	int iswrbk;
26412654012fSReza Sabdar 	int bvexists;
26422654012fSReza Sabdar 	ndmp_error rv;
26432654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
26442654012fSReza Sabdar 	char *dp;
26452654012fSReza Sabdar 	char *nm;
26462654012fSReza Sabdar 	int existsvol;
26472654012fSReza Sabdar 	int isrwdst;
26482654012fSReza Sabdar 
26492654012fSReza Sabdar 	buf = ndmp_malloc(TLM_MAX_PATH_NAME);
26502654012fSReza Sabdar 	if (!buf) {
26512654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR, "Insufficient memory.\n");
26522654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
26532654012fSReza Sabdar 	}
26542654012fSReza Sabdar 
26552654012fSReza Sabdar 	bvexists = fs_volexist(nlp->nlp_backup_path);
26562654012fSReza Sabdar 	iswrbk = voliswr(nlp->nlp_backup_path);
26572654012fSReza Sabdar 
26582654012fSReza Sabdar 	rv = NDMP_NO_ERR;
26592654012fSReza Sabdar 	n = session->ns_data.dd_nlist_len;
26602654012fSReza Sabdar 	for (i = 0; i < n; i++) {
26612654012fSReza Sabdar 		ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
26622654012fSReza Sabdar 		if (!ep)
26632654012fSReza Sabdar 			continue;
26642654012fSReza Sabdar 
26652654012fSReza Sabdar 		/* chop off the trailing slashes */
26662654012fSReza Sabdar 		chopslash(ep->nm3_opath);
26672654012fSReza Sabdar 
26682654012fSReza Sabdar 		chopslash(ep->nm3_dpath);
26692654012fSReza Sabdar 		chopslash(ep->nm3_newnm);
26702654012fSReza Sabdar 
26712654012fSReza Sabdar 		/* existing and non-empty destination path */
26722654012fSReza Sabdar 		if (ISDEFINED(ep->nm3_dpath)) {
26732654012fSReza Sabdar 			dp = ep->nm3_dpath;
26742654012fSReza Sabdar 			existsvol = fs_volexist(dp);
26752654012fSReza Sabdar 			isrwdst = voliswr(dp);
26762654012fSReza Sabdar 		} else {
26772654012fSReza Sabdar 			/* the default destination path is backup directory */
26782654012fSReza Sabdar 			dp = nlp->nlp_backup_path;
26792654012fSReza Sabdar 			existsvol = bvexists;
26802654012fSReza Sabdar 			isrwdst = iswrbk;
26812654012fSReza Sabdar 		}
26822654012fSReza Sabdar 
26832654012fSReza Sabdar 		/* check the destination directory exists and is writable */
26842654012fSReza Sabdar 		if (!existsvol) {
26852654012fSReza Sabdar 			rv = NDMP_ILLEGAL_ARGS_ERR;
26862654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
26872654012fSReza Sabdar 			    "Invalid destination path volume "
26882654012fSReza Sabdar 			    "\"%s\".\n", dp);
26892654012fSReza Sabdar 			break;
26902654012fSReza Sabdar 		}
26912654012fSReza Sabdar 		if (!isrwdst) {
26922654012fSReza Sabdar 			rv = NDMP_ILLEGAL_ARGS_ERR;
26932654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
26942654012fSReza Sabdar 			    "The destination path volume is not "
26952654012fSReza Sabdar 			    "writable \"%s\".\n", dp);
26962654012fSReza Sabdar 			break;
26972654012fSReza Sabdar 		}
26982654012fSReza Sabdar 
26992654012fSReza Sabdar 		/*
27002654012fSReza Sabdar 		 * If new name is not specified, the default new name is
27012654012fSReza Sabdar 		 * the last component of the original path, if any
27022654012fSReza Sabdar 		 * (except in V4).
27032654012fSReza Sabdar 		 */
27042654012fSReza Sabdar 		if (ISDEFINED(ep->nm3_newnm)) {
27052654012fSReza Sabdar 			nm = ep->nm3_newnm;
27062654012fSReza Sabdar 		} else {
2707c9fd6b31SReza Sabdar 			char *p, *q;
2708c9fd6b31SReza Sabdar 
27092654012fSReza Sabdar 			/*
27102654012fSReza Sabdar 			 * Find the last component of nm3_opath.
27112654012fSReza Sabdar 			 * nm3_opath has no trailing '/'.
27122654012fSReza Sabdar 			 */
2713c9fd6b31SReza Sabdar 			p = strrchr(ep->nm3_opath, '/');
2714c9fd6b31SReza Sabdar 			nm = p ? p + 1 : ep->nm3_opath;
2715c9fd6b31SReza Sabdar 
2716c9fd6b31SReza Sabdar 			/*
2717c9fd6b31SReza Sabdar 			 * In DDAR the last component could
2718c9fd6b31SReza Sabdar 			 * be repeated in nm3_dpath
2719c9fd6b31SReza Sabdar 			 */
2720c9fd6b31SReza Sabdar 			q = strrchr(ep->nm3_dpath, '/');
2721c9fd6b31SReza Sabdar 			q = q ? q + 1 : ep->nm3_dpath;
2722c9fd6b31SReza Sabdar 			if (strcmp(nm, q) == 0)
2723c9fd6b31SReza Sabdar 				nm = NULL;
2724c9fd6b31SReza Sabdar 
27252654012fSReza Sabdar 		}
27262654012fSReza Sabdar 
27272654012fSReza Sabdar 		bp = joinpath(buf, dp, nm);
27282654012fSReza Sabdar 		if (!bp) {
27292654012fSReza Sabdar 			/*
27302654012fSReza Sabdar 			 * Note: What should be done with this entry?
27312654012fSReza Sabdar 			 * We leave it untouched for now, hence no path in
27322654012fSReza Sabdar 			 * the backup image matches with this entry and will
27332654012fSReza Sabdar 			 * be reported as not found.
27342654012fSReza Sabdar 			 */
27352654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
27362654012fSReza Sabdar 			    "Destination path too long(%s/%s)", dp, nm);
27372654012fSReza Sabdar 			continue;
27382654012fSReza Sabdar 		}
27392654012fSReza Sabdar 		cp = strdup(bp);
27402654012fSReza Sabdar 		if (!cp) {
27412654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
27422654012fSReza Sabdar 			    "Insufficient memory.\n");
27432654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
27442654012fSReza Sabdar 			break;
27452654012fSReza Sabdar 		}
27462654012fSReza Sabdar 		free(ep->nm3_dpath);
27472654012fSReza Sabdar 		ep->nm3_dpath = cp;
27482654012fSReza Sabdar 		NDMP_FREE(ep->nm3_newnm);
27492654012fSReza Sabdar 
27502654012fSReza Sabdar 		bp = joinpath(buf, nlp->nlp_backup_path, ep->nm3_opath);
27512654012fSReza Sabdar 		if (!bp) {
27522654012fSReza Sabdar 			/*
27532654012fSReza Sabdar 			 * Note: The same problem of above with long path.
27542654012fSReza Sabdar 			 */
27552654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
27562654012fSReza Sabdar 			    "Path too long(%s/%s)",
27572654012fSReza Sabdar 			    nlp->nlp_backup_path, ep->nm3_opath);
27582654012fSReza Sabdar 			continue;
27592654012fSReza Sabdar 		}
27602654012fSReza Sabdar 		cp = strdup(bp);
27612654012fSReza Sabdar 		if (!cp) {
27622654012fSReza Sabdar 			MOD_LOGV3(params, NDMP_LOG_ERROR,
27632654012fSReza Sabdar 			    "Insufficient memory.\n");
27642654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
27652654012fSReza Sabdar 			break;
27662654012fSReza Sabdar 		}
27672654012fSReza Sabdar 		NDMP_FREE(ep->nm3_opath);
27682654012fSReza Sabdar 		ep->nm3_opath = cp;
27692654012fSReza Sabdar 
27702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "orig[%d]: \"%s\"", i, ep->nm3_opath);
27712654012fSReza Sabdar 		if (ep->nm3_dpath) {
27722654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
27732654012fSReza Sabdar 			    "dest[%d]: \"%s\"", i, ep->nm3_dpath);
27742654012fSReza Sabdar 		} else {
27752654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "dest[%d]: \"%s\"", i, "NULL");
27762654012fSReza Sabdar 		}
27772654012fSReza Sabdar 	}
27782654012fSReza Sabdar 
27792654012fSReza Sabdar 	free(buf);
27802654012fSReza Sabdar 
27812654012fSReza Sabdar 	return (rv);
27822654012fSReza Sabdar }
27832654012fSReza Sabdar 
27842654012fSReza Sabdar 
27852654012fSReza Sabdar /*
27862654012fSReza Sabdar  * allvalidfh
27872654012fSReza Sabdar  *
27882654012fSReza Sabdar  * Run a sanity check on the file history info. The file history
27892654012fSReza Sabdar  * info is the offset of the record starting the entry on the tape
27902654012fSReza Sabdar  * and is used in DAR (direct access restore mode).
27912654012fSReza Sabdar  */
27922654012fSReza Sabdar static boolean_t
27932654012fSReza Sabdar allvalidfh(ndmpd_session_t *session, ndmpd_module_params_t *params)
27942654012fSReza Sabdar {
27952654012fSReza Sabdar 	int i, n;
27962654012fSReza Sabdar 	boolean_t rv;
27972654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
27982654012fSReza Sabdar 
27992654012fSReza Sabdar 	rv = TRUE;
28002654012fSReza Sabdar 	n = session->ns_data.dd_nlist_len;
28012654012fSReza Sabdar 	for (i = 0; i < n; i++) {
28022654012fSReza Sabdar 		ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
28032654012fSReza Sabdar 		if (!ep)
28042654012fSReza Sabdar 			continue;
28052654012fSReza Sabdar 		/*
28062654012fSReza Sabdar 		 * The fh_info's sent from the client are multiples
28072654012fSReza Sabdar 		 * of RECORDSIZE which is 512 bytes.
28082654012fSReza Sabdar 		 *
28092654012fSReza Sabdar 		 * All our fh_info's are at the RECORDSIZE boundary.  If there
28102654012fSReza Sabdar 		 * is any fh_info that is less than RECORDSIZE (this covers 0
28112654012fSReza Sabdar 		 * and -1 values too), then the result is that DAR cannot be
28122654012fSReza Sabdar 		 * done.
28132654012fSReza Sabdar 		 */
28142654012fSReza Sabdar 		if (ep->nm3_fh_info < RECORDSIZE ||
28152654012fSReza Sabdar 		    ep->nm3_fh_info % RECORDSIZE != 0) {
28162654012fSReza Sabdar 			rv = FALSE;
28172654012fSReza Sabdar 			break;
28182654012fSReza Sabdar 		}
28192654012fSReza Sabdar 	}
28202654012fSReza Sabdar 
28212654012fSReza Sabdar 	return (rv);
28222654012fSReza Sabdar }
28232654012fSReza Sabdar 
28242654012fSReza Sabdar 
28252654012fSReza Sabdar /*
28262654012fSReza Sabdar  * log_rs_params_v3
28272654012fSReza Sabdar  *
28282654012fSReza Sabdar  * Log a copy of all values of the restore parameters
28292654012fSReza Sabdar  */
28302654012fSReza Sabdar void
28312654012fSReza Sabdar log_rs_params_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
28322654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
28332654012fSReza Sabdar {
28342654012fSReza Sabdar 	MOD_LOGV3(params, NDMP_LOG_NORMAL, "Restoring to \"%s\".\n",
28352654012fSReza Sabdar 	    (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
28362654012fSReza Sabdar 
28372654012fSReza Sabdar 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
28382654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL, "Tape server: local.\n");
28392654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
28402654012fSReza Sabdar 		    "Tape record size: %d.\n",
28412654012fSReza Sabdar 		    session->ns_mover.md_record_size);
28422654012fSReza Sabdar 	} else if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP)
28432654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
28442654012fSReza Sabdar 		    "Tape server: remote at %s:%d.\n",
28452654012fSReza Sabdar 		    inet_ntoa(IN_ADDR(session->ns_data.dd_data_addr.tcp_ip_v3)),
28462654012fSReza Sabdar 		    session->ns_data.dd_data_addr.tcp_port_v3);
28472654012fSReza Sabdar 	else
28482654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
28492654012fSReza Sabdar 		    "Unknown tape server address type.\n");
28502654012fSReza Sabdar 
28512654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_DIRECT))
28522654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_NORMAL,
28532654012fSReza Sabdar 		    "Direct Access Restore.\n");
28542654012fSReza Sabdar }
28552654012fSReza Sabdar 
28562654012fSReza Sabdar 
28572654012fSReza Sabdar /*
28582654012fSReza Sabdar  * send_unrecovered_list_v3
28592654012fSReza Sabdar  *
28602654012fSReza Sabdar  * Create the list of files that were in restore list but
28612654012fSReza Sabdar  * not recovered due to some errors.
28622654012fSReza Sabdar  */
28632654012fSReza Sabdar int
28642654012fSReza Sabdar send_unrecovered_list_v3(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
28652654012fSReza Sabdar {
28662654012fSReza Sabdar 	int i, rv;
28672654012fSReza Sabdar 	int err;
28682654012fSReza Sabdar 
28692654012fSReza Sabdar 	if (!params) {
28702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "params == NULL");
28712654012fSReza Sabdar 		return (-1);
28722654012fSReza Sabdar 	}
28732654012fSReza Sabdar 	if (!nlp) {
28742654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
28752654012fSReza Sabdar 		return (-1);
28762654012fSReza Sabdar 	}
28772654012fSReza Sabdar 
28782654012fSReza Sabdar 	if (nlp->nlp_lastidx != -1) {
28792654012fSReza Sabdar 		if (!bm_getone(nlp->nlp_rsbm, (u_longlong_t)nlp->nlp_lastidx))
28802654012fSReza Sabdar 			err = ENOENT;
28812654012fSReza Sabdar 		else
28822654012fSReza Sabdar 			err = 0;
28832654012fSReza Sabdar 		(void) ndmp_send_recovery_stat_v3(params, nlp,
28842654012fSReza Sabdar 		    nlp->nlp_lastidx, err);
28852654012fSReza Sabdar 		nlp->nlp_lastidx = -1;
28862654012fSReza Sabdar 	}
28872654012fSReza Sabdar 
28882654012fSReza Sabdar 	rv = 0;
28892654012fSReza Sabdar 	for (i = 0; i < (int)nlp->nlp_nfiles; i++) {
28902654012fSReza Sabdar 		if (!bm_getone(nlp->nlp_rsbm, (u_longlong_t)i)) {
28912654012fSReza Sabdar 			rv = ndmp_send_recovery_stat_v3(params, nlp, i, ENOENT);
28922654012fSReza Sabdar 			if (rv < 0)
28932654012fSReza Sabdar 				break;
28942654012fSReza Sabdar 		}
28952654012fSReza Sabdar 	}
28962654012fSReza Sabdar 
28972654012fSReza Sabdar 	return (rv);
28982654012fSReza Sabdar }
28992654012fSReza Sabdar 
29002654012fSReza Sabdar 
29012654012fSReza Sabdar 
29022654012fSReza Sabdar /*
29032654012fSReza Sabdar  * restore_dar_alloc_structs_v3
29042654012fSReza Sabdar  *
29052654012fSReza Sabdar  * Allocates the necessary structures for running DAR restore.
29062654012fSReza Sabdar  * It just creates the reader writer IPC.
29072654012fSReza Sabdar  * This function is called for each entry in the restore entry list.
29082654012fSReza Sabdar  *
29092654012fSReza Sabdar  * Parameters:
29102654012fSReza Sabdar  *   session (input) - pointer to the session
29112654012fSReza Sabdar  *   jname (input) - Job name
29122654012fSReza Sabdar  *
29132654012fSReza Sabdar  * Returns:
29142654012fSReza Sabdar  *    0: on success
29152654012fSReza Sabdar  *   -1: on error
29162654012fSReza Sabdar  */
29172654012fSReza Sabdar int
29182654012fSReza Sabdar restore_dar_alloc_structs_v3(ndmpd_session_t *session, char *jname)
29192654012fSReza Sabdar {
29202654012fSReza Sabdar 	long xfer_size;
29212654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
29222654012fSReza Sabdar 	tlm_commands_t *cmds;
29232654012fSReza Sabdar 
29242654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
29252654012fSReza Sabdar 	if (!nlp) {
29262654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
29272654012fSReza Sabdar 		return (-1);
29282654012fSReza Sabdar 	}
29292654012fSReza Sabdar 
29302654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
29312654012fSReza Sabdar 	(void) memset(cmds, 0, sizeof (*cmds));
29322654012fSReza Sabdar 
29332654012fSReza Sabdar 	xfer_size = ndmp_buffer_get_size(session);
29342654012fSReza Sabdar 	cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
29352654012fSReza Sabdar 	if (!cmds->tcs_command) {
29362654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
29372654012fSReza Sabdar 		return (-1);
29382654012fSReza Sabdar 	}
29392654012fSReza Sabdar 
29402654012fSReza Sabdar 	return (0);
29412654012fSReza Sabdar }
29422654012fSReza Sabdar 
29432654012fSReza Sabdar 
29442654012fSReza Sabdar /*
29452654012fSReza Sabdar  * free_dar_structs_v3
29462654012fSReza Sabdar  *
29472654012fSReza Sabdar  * To free the structures were created by restore_dar_alloc_structs_v3.
29482654012fSReza Sabdar  * This funnction is called for each entry in restore entry list.
29492654012fSReza Sabdar  *
29502654012fSReza Sabdar  * Parameters:
29512654012fSReza Sabdar  *   session (input) - pointer to the session
29522654012fSReza Sabdar  *   jname (input) - job name
29532654012fSReza Sabdar  *
29542654012fSReza Sabdar  * Returns:
29552654012fSReza Sabdar  *	NONE
29562654012fSReza Sabdar  */
29572654012fSReza Sabdar /*ARGSUSED*/
29582654012fSReza Sabdar static void
29592654012fSReza Sabdar free_dar_structs_v3(ndmpd_session_t *session, char *jname)
29602654012fSReza Sabdar {
29612654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
29622654012fSReza Sabdar 	tlm_commands_t *cmds;
29632654012fSReza Sabdar 
29642654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
29652654012fSReza Sabdar 	if (!nlp) {
29662654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
29672654012fSReza Sabdar 		return;
29682654012fSReza Sabdar 	}
29692654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
29702654012fSReza Sabdar 	if (!cmds) {
29712654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
29722654012fSReza Sabdar 		return;
29732654012fSReza Sabdar 	}
29742654012fSReza Sabdar 
29752654012fSReza Sabdar 	if (cmds->tcs_command) {
29762654012fSReza Sabdar 		if (cmds->tcs_command->tc_buffers != NULL)
29772654012fSReza Sabdar 			tlm_release_reader_writer_ipc(cmds->tcs_command);
29782654012fSReza Sabdar 		else
29792654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
29802654012fSReza Sabdar 		cmds->tcs_command = NULL;
29812654012fSReza Sabdar 	} else
29822654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
29832654012fSReza Sabdar }
29842654012fSReza Sabdar 
29852654012fSReza Sabdar 
29862654012fSReza Sabdar /*
29872654012fSReza Sabdar  * ndmp_dar_tar_init_v3
29882654012fSReza Sabdar  *
29892654012fSReza Sabdar  * Constructor for the DAR restore. Creates job name, allocates structures
29902654012fSReza Sabdar  * needed for keeping the statistics, and reports the start of restore action.
29912654012fSReza Sabdar  * It is called once for each DAR restore request.
29922654012fSReza Sabdar  *
29932654012fSReza Sabdar  * Parameters:
29942654012fSReza Sabdar  *   session (input) - pointer to the session
29952654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
29962654012fSReza Sabdar  *
29972654012fSReza Sabdar  * Returns:
29982654012fSReza Sabdar  *   char pointer: on success
29992654012fSReza Sabdar  *   NULL: on error
30002654012fSReza Sabdar  */
30012654012fSReza Sabdar static char *ndmpd_dar_tar_init_v3(ndmpd_session_t *session,
30022654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
30032654012fSReza Sabdar {
30042654012fSReza Sabdar 	char *jname;
30052654012fSReza Sabdar 
30062654012fSReza Sabdar 	jname = ndmp_malloc(TLM_MAX_BACKUP_JOB_NAME);
30072654012fSReza Sabdar 
30082654012fSReza Sabdar 	if (!jname)
30092654012fSReza Sabdar 		return (NULL);
30102654012fSReza Sabdar 
30112654012fSReza Sabdar 	(void) ndmp_new_job_name(jname);
30122654012fSReza Sabdar 
30132654012fSReza Sabdar 	if (!nlp) {
30142654012fSReza Sabdar 		free(jname);
30152654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
30162654012fSReza Sabdar 		return (NULL);
30172654012fSReza Sabdar 	}
30182654012fSReza Sabdar 
30192654012fSReza Sabdar 	nlp->nlp_jstat = tlm_new_job_stats(jname);
30202654012fSReza Sabdar 	if (!nlp->nlp_jstat) {
30212654012fSReza Sabdar 		free(jname);
30222654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
30232654012fSReza Sabdar 		return (NULL);
30242654012fSReza Sabdar 	}
30252654012fSReza Sabdar 
30262654012fSReza Sabdar 	nlp->nlp_jstat->js_start_ltime = time(NULL);
30272654012fSReza Sabdar 	nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
30282654012fSReza Sabdar 
30292654012fSReza Sabdar 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
30302654012fSReza Sabdar 	    ndmpd_path_restored_v3, NULL, NULL);
30312654012fSReza Sabdar 	if (!nlp->nlp_logcallbacks) {
30322654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
30332654012fSReza Sabdar 		free(jname);
30342654012fSReza Sabdar 		return (NULL);
30352654012fSReza Sabdar 	}
30362654012fSReza Sabdar 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
30372654012fSReza Sabdar 
30382654012fSReza Sabdar 	nlp->nlp_rsbm = bm_alloc(nlp->nlp_nfiles, 0);
30392654012fSReza Sabdar 	if (nlp->nlp_rsbm < 0) {
30402654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Out of memory.");
30412654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
30422654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
30432654012fSReza Sabdar 		free(jname);
30442654012fSReza Sabdar 		return (NULL);
30452654012fSReza Sabdar 	}
30462654012fSReza Sabdar 
30472654012fSReza Sabdar 	/* this is used in ndmpd_path_restored_v3() */
30482654012fSReza Sabdar 	nlp->nlp_lastidx = -1;
30492654012fSReza Sabdar 
30502654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "Restoring from %s tape(s).",
30512654012fSReza Sabdar 	    ndmp_data_get_mover_mode(session));
30522654012fSReza Sabdar 
30532654012fSReza Sabdar 	return (jname);
30542654012fSReza Sabdar }
30552654012fSReza Sabdar 
30562654012fSReza Sabdar /*
30572654012fSReza Sabdar  * ndmpd_dar_tar_end_v3
30582654012fSReza Sabdar  *
30592654012fSReza Sabdar  * Deconstructor for the DAR restore. This function is called once per
30602654012fSReza Sabdar  * DAR request. It deallocates memories allocated by ndmpd_dar_tar_init_v3.
30612654012fSReza Sabdar  *
30622654012fSReza Sabdar  * Parameters:
30632654012fSReza Sabdar  *   session (input) - pointer to the session
30642654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
30652654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
30662654012fSReza Sabdar  *   jname(input) - job name
30672654012fSReza Sabdar  *
30682654012fSReza Sabdar  * Returns:
30692654012fSReza Sabdar  *   0: on success
30702654012fSReza Sabdar  *   -1: on error
30712654012fSReza Sabdar  */
30722654012fSReza Sabdar static int ndmpd_dar_tar_end_v3(ndmpd_session_t *session,
30732654012fSReza Sabdar     ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp, char *jname)
30742654012fSReza Sabdar {
30752654012fSReza Sabdar 	int err = 0;
30762654012fSReza Sabdar 
30772654012fSReza Sabdar 
30782654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "lastidx %d", nlp->nlp_lastidx);
30792654012fSReza Sabdar 
30802654012fSReza Sabdar 	/* nothing restored. */
30812654012fSReza Sabdar 	(void) send_unrecovered_list_v3(params, nlp);
30822654012fSReza Sabdar 
30832654012fSReza Sabdar 	if (nlp->nlp_jstat) {
30842654012fSReza Sabdar 		nlp->nlp_bytes_total =
30852654012fSReza Sabdar 		    (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
30862654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
30872654012fSReza Sabdar 		nlp->nlp_jstat = NULL;
30882654012fSReza Sabdar 	} else {
30892654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
30902654012fSReza Sabdar 	}
30912654012fSReza Sabdar 
30922654012fSReza Sabdar 	if (nlp->nlp_logcallbacks) {
30932654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
30942654012fSReza Sabdar 		nlp->nlp_logcallbacks = NULL;
30952654012fSReza Sabdar 	} else {
30962654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
30972654012fSReza Sabdar 	}
30982654012fSReza Sabdar 
30992654012fSReza Sabdar 	if (session->ns_data.dd_abort) {
31002654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
31012654012fSReza Sabdar 		    (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
31022654012fSReza Sabdar 		err = EINTR;
31032654012fSReza Sabdar 	} else {
31042654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
31052654012fSReza Sabdar 		    (nlp->nlp_restore_path) ? nlp->nlp_restore_path :
31062654012fSReza Sabdar 		    "NULL", err);
31072654012fSReza Sabdar 	}
31082654012fSReza Sabdar 
31092654012fSReza Sabdar 	if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER) {
31102654012fSReza Sabdar 		if (nlp->nlp_rsbm < 0) {
31112654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "nlp_rsbm < 0 %d", nlp->nlp_rsbm);
31122654012fSReza Sabdar 		} else {
31132654012fSReza Sabdar 			(void) bm_free(nlp->nlp_rsbm);
31142654012fSReza Sabdar 			nlp->nlp_rsbm = -1;
31152654012fSReza Sabdar 		}
31162654012fSReza Sabdar 	}
31172654012fSReza Sabdar 
31182654012fSReza Sabdar 	free(jname);
31192654012fSReza Sabdar 
31202654012fSReza Sabdar 	return (err);
31212654012fSReza Sabdar }
31222654012fSReza Sabdar 
31232654012fSReza Sabdar 
31242654012fSReza Sabdar /*
31252654012fSReza Sabdar  * ndmpd_dar_tar_v3
31262654012fSReza Sabdar  *
31272654012fSReza Sabdar  * This function is called for each entry in DAR entry list. The window
31282654012fSReza Sabdar  * is already located and we should be in the right position to read
31292654012fSReza Sabdar  * the data from the tape.
31302654012fSReza Sabdar  * For each entry we setup selection list; so that, if the file name from
31312654012fSReza Sabdar  * tape is not as the name client asked for, error be returned.
31322654012fSReza Sabdar  *
31332654012fSReza Sabdar  * Parameters:
31342654012fSReza Sabdar  *   session (input) - pointer to the session
31352654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
31362654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
31372654012fSReza Sabdar  *   jname (input) - job name
31382654012fSReza Sabdar  *   dar_index(input) - Index of this entry in the restore list
31392654012fSReza Sabdar  *
31402654012fSReza Sabdar  * Returns:
31412654012fSReza Sabdar  *   0: on success
31422654012fSReza Sabdar  *   -1: on error
31432654012fSReza Sabdar  */
31442654012fSReza Sabdar static int
31452654012fSReza Sabdar ndmpd_dar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
31462654012fSReza Sabdar     ndmp_lbr_params_t *nlp, char *jname, int dar_index)
31472654012fSReza Sabdar {
31482654012fSReza Sabdar 	char *excl;
31492654012fSReza Sabdar 	char **sels;
31502654012fSReza Sabdar 	int flags;
31512654012fSReza Sabdar 	int err;
31522654012fSReza Sabdar 	tlm_commands_t *cmds;
31532654012fSReza Sabdar 	struct rs_name_maker rn;
31542654012fSReza Sabdar 	int data_addr_type = session->ns_data.dd_data_addr.addr_type;
31552654012fSReza Sabdar 	ndmp_tar_reader_arg_t arg;
31562654012fSReza Sabdar 	pthread_t rdtp;
31572654012fSReza Sabdar 	ndmp_context_t nctx;
31587bc22e45SReza Sabdar 	mem_ndmp_name_v3_t *ep;
31592654012fSReza Sabdar 
31602654012fSReza Sabdar 	err = 0;
31612654012fSReza Sabdar 
31622654012fSReza Sabdar 	/*
31632654012fSReza Sabdar 	 * We have to allocate and deallocate buffers every time we
31642654012fSReza Sabdar 	 * run the restore, for we need to flush the buffers.
31652654012fSReza Sabdar 	 */
31662654012fSReza Sabdar 	if (restore_dar_alloc_structs_v3(session, jname) < 0)
31672654012fSReza Sabdar 		return (-1);
31682654012fSReza Sabdar 
31692654012fSReza Sabdar 	sels = setupsels(session, params, nlp, dar_index);
31702654012fSReza Sabdar 	if (!sels) {
31712654012fSReza Sabdar 		free_dar_structs_v3(session, jname);
31722654012fSReza Sabdar 		return (-1);
31732654012fSReza Sabdar 	}
31742654012fSReza Sabdar 	excl = NULL;
31752654012fSReza Sabdar 	flags = RSFLG_OVR_ALWAYS;
31762654012fSReza Sabdar 	rn.rn_nlp = nlp;
31772654012fSReza Sabdar 	rn.rn_fp = mknewname;
31782654012fSReza Sabdar 
31792654012fSReza Sabdar 	if (!session->ns_data.dd_abort) {
31802654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
31812654012fSReza Sabdar 		cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
31822654012fSReza Sabdar 		cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
31832654012fSReza Sabdar 		cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
31842654012fSReza Sabdar 
31852654012fSReza Sabdar 		arg.tr_session = session;
31862654012fSReza Sabdar 		arg.tr_mod_params = params;
31872654012fSReza Sabdar 		arg.tr_cmds = cmds;
31882654012fSReza Sabdar 
31892654012fSReza Sabdar 		err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader,
31902654012fSReza Sabdar 		    (void *)&arg);
31912654012fSReza Sabdar 		if (err == 0) {
31922654012fSReza Sabdar 			tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
31932654012fSReza Sabdar 		} else {
31942654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "launch ndmp_tar_reader: %m");
31952654012fSReza Sabdar 			return (-1);
31962654012fSReza Sabdar 		}
31972654012fSReza Sabdar 
31982654012fSReza Sabdar 		cmds->tcs_command->tc_ref++;
31992654012fSReza Sabdar 		cmds->tcs_writer_count++;
32002654012fSReza Sabdar 
32012654012fSReza Sabdar 		/* Plug-in module */
32022654012fSReza Sabdar 		if (ndmp_pl != NULL &&
32032654012fSReza Sabdar 		    ndmp_pl->np_pre_restore != NULL) {
32048c4f9701SJanice Chang 			(void) memset(&nctx, 0, sizeof (ndmp_context_t));
32052654012fSReza Sabdar 			nctx.nc_cmds = cmds;
320642ed7838SReza Sabdar 			nctx.nc_params = params;
32078c4f9701SJanice Chang 			nctx.nc_ddata = (void *) session;
32087bc22e45SReza Sabdar 			ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params,
32097bc22e45SReza Sabdar 			    dar_index - 1);
32107bc22e45SReza Sabdar 
32112654012fSReza Sabdar 			if ((err = ndmp_pl->np_pre_restore(ndmp_pl, &nctx,
32127bc22e45SReza Sabdar 			    ep->nm3_opath, ep->nm3_dpath))
32132654012fSReza Sabdar 			    != 0) {
321442ed7838SReza Sabdar 				NDMP_LOG(LOG_ERR, "Pre-restore plug-in: %m");
32152654012fSReza Sabdar 				ndmp_stop_local_reader(session, cmds);
32162654012fSReza Sabdar 				ndmp_wait_for_reader(cmds);
32172654012fSReza Sabdar 				(void) pthread_join(rdtp, NULL);
32182654012fSReza Sabdar 				ndmp_stop_remote_reader(session);
32192654012fSReza Sabdar 				goto restore_out;
32202654012fSReza Sabdar 			}
32212654012fSReza Sabdar 		}
32222654012fSReza Sabdar 
32232654012fSReza Sabdar 		if (tm_tar_ops.tm_getdir != NULL) {
32242efb3bf9SJan Kryl 			char errbuf[256];
32252efb3bf9SJan Kryl 
32262654012fSReza Sabdar 			err = (tm_tar_ops.tm_getdir)(cmds, cmds->tcs_command,
32272654012fSReza Sabdar 			    nlp->nlp_jstat, &rn, 1, 1, sels, &excl, flags,
3228fb4eb4e8SReza Sabdar 			    dar_index, nlp->nlp_backup_path,
3229fb4eb4e8SReza Sabdar 			    session->hardlink_q);
32302efb3bf9SJan Kryl 			/*
32312efb3bf9SJan Kryl 			 * If the fatal error from tm_getdir looks like an
32322efb3bf9SJan Kryl 			 * errno code, we send the error description to DMA.
32332efb3bf9SJan Kryl 			 */
32342efb3bf9SJan Kryl 			if (err > 0 && strerror_r(err, errbuf,
32352efb3bf9SJan Kryl 			    sizeof (errbuf)) == 0) {
32362efb3bf9SJan Kryl 				MOD_LOGV3(params, NDMP_LOG_ERROR,
32372efb3bf9SJan Kryl 				    "Fatal error during the restore: %s\n",
32382efb3bf9SJan Kryl 				    errbuf);
32392efb3bf9SJan Kryl 			}
32402654012fSReza Sabdar 		}
32412654012fSReza Sabdar 
32422654012fSReza Sabdar 		cmds->tcs_writer_count--;
32432654012fSReza Sabdar 		cmds->tcs_command->tc_ref--;
32442654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "stop local reader.");
32452654012fSReza Sabdar 		ndmp_stop_local_reader(session, cmds);
32462654012fSReza Sabdar 
32472654012fSReza Sabdar 		ndmp_wait_for_reader(cmds);
32482654012fSReza Sabdar 		(void) pthread_join(rdtp, NULL);
32492654012fSReza Sabdar 
32502654012fSReza Sabdar 		/*
32512654012fSReza Sabdar 		 * If this is the last DAR entry and it is a three-way
32522654012fSReza Sabdar 		 * restore then we should close the connection.
32532654012fSReza Sabdar 		 */
32542654012fSReza Sabdar 		if ((data_addr_type == NDMP_ADDR_TCP) &&
32552654012fSReza Sabdar 		    (dar_index == (int)session->ns_data.dd_nlist_len)) {
32562654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "stop remote reader.");
32572654012fSReza Sabdar 			ndmp_stop_remote_reader(session);
32582654012fSReza Sabdar 		}
32592654012fSReza Sabdar 
32602654012fSReza Sabdar 		/* exit as if there was an internal error */
32612654012fSReza Sabdar 		if (session->ns_eof)
32622654012fSReza Sabdar 			err = -1;
32632654012fSReza Sabdar restore_out:
32642654012fSReza Sabdar 		/* Plug-in module */
32652654012fSReza Sabdar 		if (ndmp_pl != NULL &&
32662654012fSReza Sabdar 		    ndmp_pl->np_post_restore != NULL &&
32672654012fSReza Sabdar 		    ndmp_pl->np_post_restore(ndmp_pl, &nctx, err) == -1) {
32682654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Post-restore plug-in: %m");
32692654012fSReza Sabdar 			err = -1;
32702654012fSReza Sabdar 		}
32712654012fSReza Sabdar 	}
32722654012fSReza Sabdar 
32732654012fSReza Sabdar 	NDMP_FREE(sels);
32742654012fSReza Sabdar 
32752654012fSReza Sabdar 	free_dar_structs_v3(session, jname);
32762654012fSReza Sabdar 
32772654012fSReza Sabdar 	return (err);
32782654012fSReza Sabdar }
32792654012fSReza Sabdar 
32802654012fSReza Sabdar /*
32812654012fSReza Sabdar  * ndmpd_dar_locate_windwos_v3
32822654012fSReza Sabdar  *
32832654012fSReza Sabdar  * Locating the right window in which the requested file is backed up.
32842654012fSReza Sabdar  * We should go through windows to find the exact location, for the
32852654012fSReza Sabdar  * file can be located in for example 10th window after the current window.
32862654012fSReza Sabdar  *
32872654012fSReza Sabdar  * Parameters:
32882654012fSReza Sabdar  *   session (input) - pointer to the session
32892654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
32902654012fSReza Sabdar  *   fh_info (input) - index from the beginning of the backup stream
32912654012fSReza Sabdar  *   len (input) - Length of the mover window
32922654012fSReza Sabdar  *
32932654012fSReza Sabdar  * Returns:
32942654012fSReza Sabdar  *   0: on success
32952654012fSReza Sabdar  *   -1: on error
32962654012fSReza Sabdar  */
32977bc22e45SReza Sabdar static int
32987bc22e45SReza Sabdar ndmpd_dar_locate_window_v3(ndmpd_session_t *session,
32997bc22e45SReza Sabdar     ndmpd_module_params_t *params, u_longlong_t fh_info, u_longlong_t len)
33002654012fSReza Sabdar {
33012654012fSReza Sabdar 	int ret = 0;
33022654012fSReza Sabdar 
33032654012fSReza Sabdar 
33042654012fSReza Sabdar 	for (; ; ) {
33052654012fSReza Sabdar 		ret = (*params->mp_seek_func)(session, fh_info, len);
33062654012fSReza Sabdar 
33072654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ret %d", ret);
33082654012fSReza Sabdar 		if (ret == 0) /* Seek was done successfully */
33092654012fSReza Sabdar 			break;
33102654012fSReza Sabdar 		else if (ret < 0) {
33112654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Seek error");
33122654012fSReza Sabdar 			break;
33132654012fSReza Sabdar 		}
33142654012fSReza Sabdar 
33152654012fSReza Sabdar 		/*
33162654012fSReza Sabdar 		 * DMA moved to a new window.
33172654012fSReza Sabdar 		 * If we are reading the remainig of the file from
33182654012fSReza Sabdar 		 * new window, seek is handled by ndmpd_local_read_v3.
33192654012fSReza Sabdar 		 * Here we should continue the seek inside the new
33202654012fSReza Sabdar 		 * window.
33212654012fSReza Sabdar 		 */
33222654012fSReza Sabdar 		continue;
33232654012fSReza Sabdar 	}
33242654012fSReza Sabdar 	return (ret);
33252654012fSReza Sabdar }
33262654012fSReza Sabdar 
33272654012fSReza Sabdar /*
33282654012fSReza Sabdar  * ndmpd_rs_dar_tar_v3
33292654012fSReza Sabdar  *
33302654012fSReza Sabdar  * Main DAR function. It calls the constructor, then for each entry it
33312654012fSReza Sabdar  * calls the locate_window_v3 to find the exact position of the file. Then
33322654012fSReza Sabdar  * it restores the file.
33332654012fSReza Sabdar  * When all restore requests are done it calls the deconstructor to clean
33342654012fSReza Sabdar  * everything up.
33352654012fSReza Sabdar  *
33362654012fSReza Sabdar  * Parameters:
33372654012fSReza Sabdar  *   session (input) - pointer to the session
33382654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
33392654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
33402654012fSReza Sabdar  *
33412654012fSReza Sabdar  * Returns:
33422654012fSReza Sabdar  *   0: on success
33432654012fSReza Sabdar  *   -1: on error
33442654012fSReza Sabdar  */
33452654012fSReza Sabdar static int
33462654012fSReza Sabdar ndmpd_rs_dar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
33472654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
33482654012fSReza Sabdar {
33492654012fSReza Sabdar 	mem_ndmp_name_v3_t *ep;
33502654012fSReza Sabdar 	u_longlong_t len;
33512654012fSReza Sabdar 	char *jname;
33522654012fSReza Sabdar 	int n = session->ns_data.dd_nlist_len;
33532654012fSReza Sabdar 	int i, ret = 0;
33542654012fSReza Sabdar 	int result = 0;
33552654012fSReza Sabdar 
33562654012fSReza Sabdar 	jname = ndmpd_dar_tar_init_v3(session, nlp);
33572654012fSReza Sabdar 
33582654012fSReza Sabdar 	if (!jname)
33592654012fSReza Sabdar 		return (-1);
33602654012fSReza Sabdar 
33612654012fSReza Sabdar 	/*
33622654012fSReza Sabdar 	 * We set the length = sizeof (tlm_tar_hdr_t)
33632654012fSReza Sabdar 	 * This is important for three-way DAR restore, for we should
33642654012fSReza Sabdar 	 * read the header first (If we ask for more data then we have
33652654012fSReza Sabdar 	 * to read and discard the remaining data in the socket)
33662654012fSReza Sabdar 	 */
33672654012fSReza Sabdar 	len = tlm_tarhdr_size();
33682654012fSReza Sabdar 
33692654012fSReza Sabdar 	for (i = 0; i < n; ++i) {
33702654012fSReza Sabdar 		ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i);
33712654012fSReza Sabdar 		if (!ep) {
33722654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "ep NULL, i %d", i);
33732654012fSReza Sabdar 			continue;
33742654012fSReza Sabdar 		}
33752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
33762654012fSReza Sabdar 		    "restoring opath %s, dpath %s, fh_info %lld",
33772654012fSReza Sabdar 		    ep->nm3_opath ? ep->nm3_opath : "NULL",
33782654012fSReza Sabdar 		    ep->nm3_dpath ? ep->nm3_dpath : "NULL",
33792654012fSReza Sabdar 		    ep->nm3_fh_info);
33802654012fSReza Sabdar 
33812654012fSReza Sabdar 		/*
33822654012fSReza Sabdar 		 * We should seek till finding the window in which file
33832654012fSReza Sabdar 		 * is located.
33842654012fSReza Sabdar 		 */
33852654012fSReza Sabdar 		ret = ndmpd_dar_locate_window_v3(session, params,
33862654012fSReza Sabdar 		    ep->nm3_fh_info, len);
33872654012fSReza Sabdar 
33882654012fSReza Sabdar 		if (ret < 0) /* If seek fails, restore should be aborted */
33892654012fSReza Sabdar 			break;
33902654012fSReza Sabdar 		/*
33912654012fSReza Sabdar 		 * We are inside the target window.
33922654012fSReza Sabdar 		 * for each restore we will use one entry as selection list
33932654012fSReza Sabdar 		 */
33942654012fSReza Sabdar 		if ((ret = ndmpd_dar_tar_v3(session, params, nlp, jname, i+1))
33952654012fSReza Sabdar 		    != 0)
33962654012fSReza Sabdar 			result = EIO;
33972654012fSReza Sabdar 		ndmpd_audit_restore(session->ns_connection,
33982654012fSReza Sabdar 		    ep->nm3_opath ? ep->nm3_opath : "NULL",
33992654012fSReza Sabdar 		    session->ns_data.dd_data_addr.addr_type,
34002654012fSReza Sabdar 		    session->ns_tape.td_adapter_name, result);
34012654012fSReza Sabdar 	}
34022654012fSReza Sabdar 
34032654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "End of restore list");
34042654012fSReza Sabdar 
34052654012fSReza Sabdar 	(void) ndmpd_dar_tar_end_v3(session, params, nlp, jname);
34062654012fSReza Sabdar 
34072654012fSReza Sabdar 	return (ret);
34082654012fSReza Sabdar }
34092654012fSReza Sabdar 
34102654012fSReza Sabdar /*
34112654012fSReza Sabdar  * ndmp_plugin_pre_restore
34122654012fSReza Sabdar  *
34132654012fSReza Sabdar  * Wrapper for pre-restore callback with multiple path
34142654012fSReza Sabdar  */
34152654012fSReza Sabdar static int
34167bc22e45SReza Sabdar ndmp_plugin_pre_restore(ndmp_context_t *ctxp, ndmpd_module_params_t *params,
34177bc22e45SReza Sabdar     int ncount)
34182654012fSReza Sabdar {
34197bc22e45SReza Sabdar 	mem_ndmp_name_v3_t *ep;
34202654012fSReza Sabdar 	int err;
34217bc22e45SReza Sabdar 	int i;
34222654012fSReza Sabdar 
34237bc22e45SReza Sabdar 	for (i = 0; i < ncount; i++) {
34247bc22e45SReza Sabdar 		if (!(ep = (mem_ndmp_name_v3_t *)MOD_GETNAME(params, i)))
34257bc22e45SReza Sabdar 			continue;
34262654012fSReza Sabdar 		if ((err = ndmp_pl->np_pre_restore(ndmp_pl, ctxp,
34277bc22e45SReza Sabdar 		    ep->nm3_opath, ep->nm3_dpath)) != 0)
34282654012fSReza Sabdar 			return (err);
34292654012fSReza Sabdar 	}
34307bc22e45SReza Sabdar 
34312654012fSReza Sabdar 	return (0);
34322654012fSReza Sabdar }
34332654012fSReza Sabdar 
343442ed7838SReza Sabdar /*
3435fb4eb4e8SReza Sabdar  * get_absolute_path
3436fb4eb4e8SReza Sabdar  *
3437fb4eb4e8SReza Sabdar  * Get resolved path name which does not involve ".", ".." or extra
3438fb4eb4e8SReza Sabdar  * "/" or symbolic links.
3439fb4eb4e8SReza Sabdar  *
3440fb4eb4e8SReza Sabdar  * e.g.
3441fb4eb4e8SReza Sabdar  *
3442fb4eb4e8SReza Sabdar  * /backup/path/ -> /backup/path
3443fb4eb4e8SReza Sabdar  * /backup/path/. -> /backup/path
3444fb4eb4e8SReza Sabdar  * /backup/path/../path/ -> /backup/path
3445fb4eb4e8SReza Sabdar  * /link-to-backup-path -> /backup/path
3446fb4eb4e8SReza Sabdar  *
3447fb4eb4e8SReza Sabdar  * Returns:
3448fb4eb4e8SReza Sabdar  * 	Pointer to the new path (allocated)
3449fb4eb4e8SReza Sabdar  * 	NULL if the path doesnt exist
3450fb4eb4e8SReza Sabdar  */
3451fb4eb4e8SReza Sabdar static char *
3452fb4eb4e8SReza Sabdar get_absolute_path(const char *bkpath)
3453fb4eb4e8SReza Sabdar {
3454fb4eb4e8SReza Sabdar 	char *pbuf;
3455fb4eb4e8SReza Sabdar 	char *rv;
3456fb4eb4e8SReza Sabdar 
3457fb4eb4e8SReza Sabdar 	if (!(pbuf = ndmp_malloc(TLM_MAX_PATH_NAME)))
3458fb4eb4e8SReza Sabdar 		return (NULL);
3459fb4eb4e8SReza Sabdar 
3460fb4eb4e8SReza Sabdar 	if ((rv = realpath(bkpath, pbuf)) == NULL) {
3461fb4eb4e8SReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid path [%s] err=%d",
3462fb4eb4e8SReza Sabdar 		    bkpath, errno);
3463fb4eb4e8SReza Sabdar 	}
3464fb4eb4e8SReza Sabdar 	return (rv);
3465fb4eb4e8SReza Sabdar }
3466fb4eb4e8SReza Sabdar 
3467fb4eb4e8SReza Sabdar /*
346842ed7838SReza Sabdar  * Expands the format string and logs the resulting message to the
346942ed7838SReza Sabdar  * remote DMA
347042ed7838SReza Sabdar  */
347142ed7838SReza Sabdar void
347242ed7838SReza Sabdar ndmp_log_dma(ndmp_context_t *nctx, ndmp_log_dma_type_t lt, const char *fmt, ...)
347342ed7838SReza Sabdar {
347442ed7838SReza Sabdar 	va_list ap;
347542ed7838SReza Sabdar 	char buf[256];
347642ed7838SReza Sabdar 	ndmpd_module_params_t *params;
347742ed7838SReza Sabdar 
347842ed7838SReza Sabdar 	if (nctx == NULL ||
347942ed7838SReza Sabdar 	    (params = (ndmpd_module_params_t *)nctx->nc_params) == NULL)
348042ed7838SReza Sabdar 		return;
348142ed7838SReza Sabdar 
348242ed7838SReza Sabdar 	va_start(ap, fmt);
348342ed7838SReza Sabdar 	(void) vsnprintf(buf, sizeof (buf), fmt, ap);
348442ed7838SReza Sabdar 	va_end(ap);
348542ed7838SReza Sabdar 
348642ed7838SReza Sabdar 	MOD_LOGV3(params, (ndmp_log_type)lt, "%s", buf);
348742ed7838SReza Sabdar }
348842ed7838SReza Sabdar 
34892654012fSReza Sabdar 
34902654012fSReza Sabdar /*
34912654012fSReza Sabdar  * ndmpd_rs_sar_tar_v3
34922654012fSReza Sabdar  *
34932654012fSReza Sabdar  * Main non-DAR restore function. It will try to restore all the entries
34942654012fSReza Sabdar  * that have been backed up.
34952654012fSReza Sabdar  *
34962654012fSReza Sabdar  * Parameters:
34972654012fSReza Sabdar  *   session (input) - pointer to the session
34982654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
34992654012fSReza Sabdar  *   nlp (input) - pointer to the nlp structure
35002654012fSReza Sabdar  *
35012654012fSReza Sabdar  * Returns:
35022654012fSReza Sabdar  *   0: on success
35032654012fSReza Sabdar  *   -1: on error
35042654012fSReza Sabdar  */
35052654012fSReza Sabdar static int
35062654012fSReza Sabdar ndmpd_rs_sar_tar_v3(ndmpd_session_t *session, ndmpd_module_params_t *params,
35072654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
35082654012fSReza Sabdar {
35092654012fSReza Sabdar 	char jname[TLM_MAX_BACKUP_JOB_NAME];
35102654012fSReza Sabdar 	char *excl;
35112654012fSReza Sabdar 	char **sels;
35122654012fSReza Sabdar 	int flags;
35132654012fSReza Sabdar 	int err;
35142654012fSReza Sabdar 	tlm_commands_t *cmds;
35152654012fSReza Sabdar 	struct rs_name_maker rn;
35162654012fSReza Sabdar 	ndmp_tar_reader_arg_t arg;
35172654012fSReza Sabdar 	pthread_t rdtp;
35182654012fSReza Sabdar 	int result;
35192654012fSReza Sabdar 	ndmp_context_t nctx;
35202654012fSReza Sabdar 
35212654012fSReza Sabdar 	result = err = 0;
35222654012fSReza Sabdar 	(void) ndmp_new_job_name(jname);
35232654012fSReza Sabdar 	if (restore_alloc_structs_v3(session, jname) < 0)
35242654012fSReza Sabdar 		return (-1);
35252654012fSReza Sabdar 
35262654012fSReza Sabdar 	sels = setupsels(session, params, nlp, 0);
35272654012fSReza Sabdar 	if (!sels) {
35282654012fSReza Sabdar 		free_structs_v3(session, jname);
35292654012fSReza Sabdar 		return (-1);
35302654012fSReza Sabdar 	}
35312654012fSReza Sabdar 	excl = NULL;
35322654012fSReza Sabdar 	flags = RSFLG_OVR_ALWAYS;
35332654012fSReza Sabdar 	rn.rn_nlp = nlp;
35342654012fSReza Sabdar 	rn.rn_fp = mknewname;
35352654012fSReza Sabdar 
35362654012fSReza Sabdar 	nlp->nlp_jstat->js_start_ltime = time(NULL);
35372654012fSReza Sabdar 	nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
35382654012fSReza Sabdar 
35392654012fSReza Sabdar 	if (!session->ns_data.dd_abort && !session->ns_data.dd_abort) {
35402654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
35412654012fSReza Sabdar 		cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
35422654012fSReza Sabdar 		cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
35432654012fSReza Sabdar 		cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
35442654012fSReza Sabdar 
35452654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" started.",
35462654012fSReza Sabdar 		    (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
35472654012fSReza Sabdar 
35482654012fSReza Sabdar 		arg.tr_session = session;
35492654012fSReza Sabdar 		arg.tr_mod_params = params;
35502654012fSReza Sabdar 		arg.tr_cmds = cmds;
35512654012fSReza Sabdar 		err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader,
35522654012fSReza Sabdar 		    (void *)&arg);
35532654012fSReza Sabdar 		if (err == 0) {
35542654012fSReza Sabdar 			tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
35552654012fSReza Sabdar 		} else {
35562654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Launch ndmp_tar_reader: %m");
35572654012fSReza Sabdar 			free_structs_v3(session, jname);
35582654012fSReza Sabdar 			return (-1);
35592654012fSReza Sabdar 		}
35602654012fSReza Sabdar 
35612654012fSReza Sabdar 		if (!ndmp_check_utf8magic(cmds->tcs_command)) {
35622654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "UTF8Magic not found!");
35632654012fSReza Sabdar 		} else {
35642654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "UTF8Magic found");
35652654012fSReza Sabdar 		}
35662654012fSReza Sabdar 
35672654012fSReza Sabdar 		/* Plug-in module */
35682654012fSReza Sabdar 		if (ndmp_pl != NULL &&
35692654012fSReza Sabdar 		    ndmp_pl->np_pre_restore != NULL) {
35708c4f9701SJanice Chang 			(void) memset(&nctx, 0, sizeof (ndmp_context_t));
35712654012fSReza Sabdar 			nctx.nc_cmds = cmds;
357242ed7838SReza Sabdar 			nctx.nc_params = params;
35738c4f9701SJanice Chang 			nctx.nc_ddata = (void *) session;
35747bc22e45SReza Sabdar 			if ((err = ndmp_plugin_pre_restore(&nctx, params,
35757bc22e45SReza Sabdar 			    nlp->nlp_nfiles))
35762654012fSReza Sabdar 			    != 0) {
357742ed7838SReza Sabdar 				NDMP_LOG(LOG_ERR, "Pre-restore plug-in: %m");
35782654012fSReza Sabdar 				ndmp_stop_local_reader(session, cmds);
35792654012fSReza Sabdar 				ndmp_wait_for_reader(cmds);
35802654012fSReza Sabdar 				(void) pthread_join(rdtp, NULL);
35812654012fSReza Sabdar 				ndmp_stop_remote_reader(session);
35822654012fSReza Sabdar 				goto restore_out;
35832654012fSReza Sabdar 			}
35842654012fSReza Sabdar 		}
35852654012fSReza Sabdar 
35862654012fSReza Sabdar 		cmds->tcs_command->tc_ref++;
35872654012fSReza Sabdar 		cmds->tcs_writer_count++;
35882654012fSReza Sabdar 
35892efb3bf9SJan Kryl 		if (tm_tar_ops.tm_getdir != NULL) {
35902efb3bf9SJan Kryl 			char errbuf[256];
35912efb3bf9SJan Kryl 
35922654012fSReza Sabdar 			err = (tm_tar_ops.tm_getdir)(cmds, cmds->tcs_command,
35932654012fSReza Sabdar 			    nlp->nlp_jstat, &rn, 1, 1, sels, &excl, flags, 0,
3594fb4eb4e8SReza Sabdar 			    nlp->nlp_backup_path, session->hardlink_q);
35952efb3bf9SJan Kryl 			/*
35962efb3bf9SJan Kryl 			 * If the fatal error from tm_getdir looks like an
35972efb3bf9SJan Kryl 			 * errno code, we send the error description to DMA.
35982efb3bf9SJan Kryl 			 */
35992efb3bf9SJan Kryl 			if (err > 0 && strerror_r(err, errbuf,
36002efb3bf9SJan Kryl 			    sizeof (errbuf)) == 0) {
36012efb3bf9SJan Kryl 				MOD_LOGV3(params, NDMP_LOG_ERROR,
36022efb3bf9SJan Kryl 				    "Fatal error during the restore: %s\n",
36032efb3bf9SJan Kryl 				    errbuf);
36042efb3bf9SJan Kryl 			}
36052efb3bf9SJan Kryl 		}
36062654012fSReza Sabdar 
36072654012fSReza Sabdar 		cmds->tcs_writer_count--;
36082654012fSReza Sabdar 		cmds->tcs_command->tc_ref--;
36092654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
36102654012fSReza Sabdar 
36112654012fSReza Sabdar 		/* Send the list of un-recovered files/dirs to the client.  */
36122654012fSReza Sabdar 		(void) send_unrecovered_list_v3(params, nlp);
36132654012fSReza Sabdar 
36142654012fSReza Sabdar 		ndmp_stop_local_reader(session, cmds);
36152654012fSReza Sabdar 		ndmp_wait_for_reader(cmds);
36162654012fSReza Sabdar 		(void) pthread_join(rdtp, NULL);
36172654012fSReza Sabdar 
36182654012fSReza Sabdar 		ndmp_stop_remote_reader(session);
36192654012fSReza Sabdar 
36202654012fSReza Sabdar 		/* exit as if there was an internal error */
36212654012fSReza Sabdar 		if (session->ns_eof)
36222654012fSReza Sabdar 			err = -1;
36232654012fSReza Sabdar 		if (err == -1)
36242654012fSReza Sabdar 			result = EIO;
36252654012fSReza Sabdar 	}
36262654012fSReza Sabdar 
36272654012fSReza Sabdar 	(void) send_unrecovered_list_v3(params, nlp); /* nothing restored. */
36282654012fSReza Sabdar 	if (session->ns_data.dd_abort) {
36292654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
36302654012fSReza Sabdar 		    (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL");
36312654012fSReza Sabdar 		result = EINTR;
36322654012fSReza Sabdar 		ndmpd_audit_restore(session->ns_connection,
36332654012fSReza Sabdar 		    nlp->nlp_restore_path,
36342654012fSReza Sabdar 		    session->ns_data.dd_data_addr.addr_type,
36352654012fSReza Sabdar 		    session->ns_tape.td_adapter_name, result);
36362654012fSReza Sabdar 		err = -1;
36372654012fSReza Sabdar 	} else {
36382654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
36392654012fSReza Sabdar 		    (nlp->nlp_restore_path) ? nlp->nlp_restore_path : "NULL",
36402654012fSReza Sabdar 		    err);
36412654012fSReza Sabdar 		ndmpd_audit_restore(session->ns_connection,
36422654012fSReza Sabdar 		    nlp->nlp_restore_path,
36432654012fSReza Sabdar 		    session->ns_data.dd_data_addr.addr_type,
36442654012fSReza Sabdar 		    session->ns_tape.td_adapter_name, result);
36452654012fSReza Sabdar 
36462654012fSReza Sabdar restore_out:
36472654012fSReza Sabdar 		/* Plug-in module */
36482654012fSReza Sabdar 		if (ndmp_pl != NULL &&
36492654012fSReza Sabdar 		    ndmp_pl->np_post_restore != NULL &&
36502654012fSReza Sabdar 		    ndmp_pl->np_post_restore(ndmp_pl, &nctx, err) == -1) {
36512654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Post-restore plug-in: %m");
36522654012fSReza Sabdar 			err = -1;
36532654012fSReza Sabdar 		}
36542654012fSReza Sabdar 	}
36552654012fSReza Sabdar 
36562654012fSReza Sabdar 	NDMP_FREE(sels);
36572654012fSReza Sabdar 	free_structs_v3(session, jname);
36582654012fSReza Sabdar 
36592654012fSReza Sabdar 	return (err);
36602654012fSReza Sabdar }
36612654012fSReza Sabdar 
36622654012fSReza Sabdar 
36632654012fSReza Sabdar /*
36642654012fSReza Sabdar  * ndmp_backup_get_params_v3
36652654012fSReza Sabdar  *
36662654012fSReza Sabdar  * Get the backup parameters from the NDMP env variables
36672654012fSReza Sabdar  * and log them in the system log and as normal messages
36682654012fSReza Sabdar  * to the DMA.
36692654012fSReza Sabdar  *
36702654012fSReza Sabdar  * Parameters:
36712654012fSReza Sabdar  *   session (input) - pointer to the session
36722654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
36732654012fSReza Sabdar  *
36742654012fSReza Sabdar  * Returns:
36752654012fSReza Sabdar  *   NDMP_NO_ERR: on success
36762654012fSReza Sabdar  *   != NDMP_NO_ERR: otherwise
36772654012fSReza Sabdar  */
36782654012fSReza Sabdar ndmp_error
36792654012fSReza Sabdar ndmp_backup_get_params_v3(ndmpd_session_t *session,
36802654012fSReza Sabdar     ndmpd_module_params_t *params)
36812654012fSReza Sabdar {
36822654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
36832654012fSReza Sabdar 
36842654012fSReza Sabdar 	if (!session || !params)
36852654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
36862654012fSReza Sabdar 
36872654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
36882654012fSReza Sabdar 	if (!nlp) {
36892654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
36902654012fSReza Sabdar 		    "Internal error: NULL nlp.\n");
3691a8039bf3SJan Kryl 		return (NDMP_ILLEGAL_ARGS_ERR);
36922654012fSReza Sabdar 	} else {
3693a8039bf3SJan Kryl 		if (!(nlp->nlp_backup_path = get_backup_path_v3(params)) ||
3694a8039bf3SJan Kryl 		    !is_valid_backup_dir_v3(params, nlp->nlp_backup_path))
3695a8039bf3SJan Kryl 		return (NDMP_ILLEGAL_ARGS_ERR);
36962654012fSReza Sabdar 	}
36972654012fSReza Sabdar 
3698fb4eb4e8SReza Sabdar 	nlp->nlp_backup_path = get_absolute_path(nlp->nlp_backup_path);
3699fb4eb4e8SReza Sabdar 	if (!nlp->nlp_backup_path)
3700a8039bf3SJan Kryl 		return (NDMP_ILLEGAL_ARGS_ERR);
37012654012fSReza Sabdar 
37022654012fSReza Sabdar 	if (fs_is_chkpntvol(nlp->nlp_backup_path) ||
37032654012fSReza Sabdar 	    fs_is_rdonly(nlp->nlp_backup_path) ||
37042654012fSReza Sabdar 	    !fs_is_chkpnt_enabled(nlp->nlp_backup_path))
37052654012fSReza Sabdar 		NLP_SET(nlp, NLPF_CHKPNTED_PATH);
37062654012fSReza Sabdar 	else
37072654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_CHKPNTED_PATH);
37082654012fSReza Sabdar 
37092654012fSReza Sabdar 	/* Should the st_ctime be ignored when backing up? */
37102654012fSReza Sabdar 	if (ndmp_ignore_ctime) {
37112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ignoring st_ctime");
37122654012fSReza Sabdar 		NLP_SET(nlp, NLPF_IGNCTIME);
37132654012fSReza Sabdar 	} else {
37142654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_IGNCTIME);
37152654012fSReza Sabdar 	}
37162654012fSReza Sabdar 
37172654012fSReza Sabdar 	if (ndmp_include_lmtime == TRUE) {
37182654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "including st_lmtime");
37192654012fSReza Sabdar 		NLP_SET(nlp, NLPF_INCLMTIME);
37202654012fSReza Sabdar 	} else {
37212654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_INCLMTIME);
37222654012fSReza Sabdar 	}
37232654012fSReza Sabdar 
37242654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
37252654012fSReza Sabdar 
37262654012fSReza Sabdar 	get_hist_env_v3(params, nlp);
37272654012fSReza Sabdar 	get_exc_env_v3(params, nlp);
37282654012fSReza Sabdar 	get_inc_env_v3(params, nlp);
37292654012fSReza Sabdar 	get_direct_env_v3(params, nlp);
3730a8039bf3SJan Kryl 	return (get_backup_level_v3(params, nlp));
37312654012fSReza Sabdar }
37322654012fSReza Sabdar 
37332654012fSReza Sabdar 
37342654012fSReza Sabdar /*
37352654012fSReza Sabdar  * ndmpd_tar_backup_starter_v3
37362654012fSReza Sabdar  *
37372654012fSReza Sabdar  * Create the checkpoint for the backup and do the backup,
37382654012fSReza Sabdar  * then remove the backup checkpoint if we created it.
37392654012fSReza Sabdar  * Save the backup time information based on the backup
37402654012fSReza Sabdar  * type and stop the data server.
37412654012fSReza Sabdar  *
37422654012fSReza Sabdar  * Parameters:
37432654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
37442654012fSReza Sabdar  *
37452654012fSReza Sabdar  * Returns:
37462654012fSReza Sabdar  *   0: on success
37472654012fSReza Sabdar  *   != 0: otherwise
37482654012fSReza Sabdar  */
37492654012fSReza Sabdar int
37508c4f9701SJanice Chang ndmpd_tar_backup_starter_v3(void *arg)
37512654012fSReza Sabdar {
37528c4f9701SJanice Chang 	ndmpd_module_params_t *params = arg;
37532654012fSReza Sabdar 	int err;
37542654012fSReza Sabdar 	ndmpd_session_t *session;
37552654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
37562654012fSReza Sabdar 	char jname[TLM_MAX_BACKUP_JOB_NAME];
3757416eec61SReza Sabdar 	ndmp_bkup_size_arg_t sarg;
3758416eec61SReza Sabdar 	pthread_t tid;
37592654012fSReza Sabdar 
37602654012fSReza Sabdar 	session = (ndmpd_session_t *)(params->mp_daemon_cookie);
37612654012fSReza Sabdar 	*(params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
37622654012fSReza Sabdar 	ndmp_session_ref(session);
37632654012fSReza Sabdar 	(void) ndmp_new_job_name(jname);
37642654012fSReza Sabdar 
37652654012fSReza Sabdar 	err = 0;
37662654012fSReza Sabdar 	if (!NLP_ISCHKPNTED(nlp) &&
3767876b86efSReza Sabdar 	    ndmp_create_snapshot(nlp->nlp_backup_path, jname) < 0) {
37682654012fSReza Sabdar 		MOD_LOGV3(params, NDMP_LOG_ERROR,
37692654012fSReza Sabdar 		    "Creating checkpoint on \"%s\".\n",
37702654012fSReza Sabdar 		    nlp->nlp_backup_path);
37712654012fSReza Sabdar 		err = -1;
37722654012fSReza Sabdar 	}
37732654012fSReza Sabdar 
37742654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "err %d, chkpnted %c",
37752654012fSReza Sabdar 	    err, NDMP_YORN(NLP_ISCHKPNTED(nlp)));
37762654012fSReza Sabdar 
37772654012fSReza Sabdar 	if (err == 0) {
3778416eec61SReza Sabdar 		sarg.bs_session = session;
3779416eec61SReza Sabdar 		sarg.bs_jname = jname;
3780416eec61SReza Sabdar 		sarg.bs_path = nlp->nlp_backup_path;
3781416eec61SReza Sabdar 
3782416eec61SReza Sabdar 		/* Get an estimate of the data size */
3783416eec61SReza Sabdar 		if (pthread_create(&tid, NULL, (funct_t)get_backup_size,
3784416eec61SReza Sabdar 		    (void *)&sarg) == 0)
3785416eec61SReza Sabdar 			(void) pthread_detach(tid);
3786416eec61SReza Sabdar 
37872654012fSReza Sabdar 		err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate, jname);
37882654012fSReza Sabdar 		if (err != 0) {
37892654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "err %d", err);
37902654012fSReza Sabdar 		} else {
37912654012fSReza Sabdar 			log_bk_params_v3(session, params, nlp);
37922654012fSReza Sabdar 			err = tar_backup_v3(session, params, nlp, jname);
37932654012fSReza Sabdar 		}
37942654012fSReza Sabdar 	}
37952654012fSReza Sabdar 
37962654012fSReza Sabdar 	if (!NLP_ISCHKPNTED(nlp))
3797876b86efSReza Sabdar 		(void) ndmp_remove_snapshot(nlp->nlp_backup_path, jname);
37982654012fSReza Sabdar 
37992654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "err %d, update %c",
38002654012fSReza Sabdar 	    err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
38012654012fSReza Sabdar 
38022654012fSReza Sabdar 	if (err == 0)
38032654012fSReza Sabdar 		save_backup_date_v3(params, nlp);
38042654012fSReza Sabdar 
38052654012fSReza Sabdar 	MOD_DONE(params, err);
38062654012fSReza Sabdar 
38072654012fSReza Sabdar 	/* nlp_params is allocated in start_backup_v3() */
38082654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
3809fb4eb4e8SReza Sabdar 	NDMP_FREE(nlp->nlp_backup_path);
38102654012fSReza Sabdar 
38112654012fSReza Sabdar 	NS_DEC(nbk);
38122654012fSReza Sabdar 	ndmp_session_unref(session);
38132654012fSReza Sabdar 	return (err);
38142654012fSReza Sabdar 
38152654012fSReza Sabdar }
38162654012fSReza Sabdar 
38172654012fSReza Sabdar 
38182654012fSReza Sabdar /*
38192654012fSReza Sabdar  * ndmpd_tar_backup_abort_v3
38202654012fSReza Sabdar  *
38212654012fSReza Sabdar  * Abort the backup operation and stop the reader thread.
38222654012fSReza Sabdar  *
38232654012fSReza Sabdar  * Parameters:
38242654012fSReza Sabdar  *   module_cookie (input) - pointer to the nlp structure
38252654012fSReza Sabdar  *
38262654012fSReza Sabdar  * Returns:
38272654012fSReza Sabdar  *   0: always
38282654012fSReza Sabdar  */
38292654012fSReza Sabdar int
38302654012fSReza Sabdar ndmpd_tar_backup_abort_v3(void *module_cookie)
38312654012fSReza Sabdar {
38322654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
38332654012fSReza Sabdar 
38342654012fSReza Sabdar 	nlp = (ndmp_lbr_params_t *)module_cookie;
38352654012fSReza Sabdar 	if (nlp && nlp->nlp_session) {
38362654012fSReza Sabdar 		if (nlp->nlp_session->ns_data.dd_data_addr.addr_type ==
38372654012fSReza Sabdar 		    NDMP_ADDR_TCP &&
38382654012fSReza Sabdar 		    nlp->nlp_session->ns_data.dd_sock != -1) {
38392654012fSReza Sabdar 			(void) close(nlp->nlp_session->ns_data.dd_sock);
38402654012fSReza Sabdar 			nlp->nlp_session->ns_data.dd_sock = -1;
38412654012fSReza Sabdar 		}
38422654012fSReza Sabdar 		ndmp_stop_reader_thread(nlp->nlp_session);
38432654012fSReza Sabdar 	}
38442654012fSReza Sabdar 
38452654012fSReza Sabdar 	return (0);
38462654012fSReza Sabdar }
38472654012fSReza Sabdar 
38482654012fSReza Sabdar 
38492654012fSReza Sabdar /*
38502654012fSReza Sabdar  * ndmp_restore_get_params_v3
38512654012fSReza Sabdar  *
38522654012fSReza Sabdar  * Get the parameters specified for recovery such as restore path, type
38532654012fSReza Sabdar  * of restore (DAR, non-DAR) etc
38542654012fSReza Sabdar  *
38552654012fSReza Sabdar  * Parameters:
38562654012fSReza Sabdar  *   session (input) - pointer to the session
38572654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
38582654012fSReza Sabdar  *
38592654012fSReza Sabdar  * Returns:
38602654012fSReza Sabdar  *   NDMP_NO_ERR: on success
38612654012fSReza Sabdar  *   != NDMP_NO_ERR: otherwise
38622654012fSReza Sabdar  */
38632654012fSReza Sabdar ndmp_error
38642654012fSReza Sabdar ndmp_restore_get_params_v3(ndmpd_session_t *session,
38652654012fSReza Sabdar     ndmpd_module_params_t *params)
38662654012fSReza Sabdar {
38672654012fSReza Sabdar 	ndmp_error rv;
38682654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
38692654012fSReza Sabdar 
38702654012fSReza Sabdar 	if (!(nlp = ndmp_get_nlp(session))) {
38712654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp is NULL");
38722654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
38738c4f9701SJanice Chang 	} else if (!(nlp->nlp_backup_path = get_backup_path_v3(params)))
38742654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
38752654012fSReza Sabdar 	else if ((nlp->nlp_nfiles = session->ns_data.dd_nlist_len) == 0) {
38762654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nfiles: %d", nlp->nlp_nfiles);
38772654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
38782654012fSReza Sabdar 	} else if (get_rs_path_v3(params, nlp) != NDMP_NO_ERR) {
38792654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
38802654012fSReza Sabdar 	} else if ((rv = fix_nlist_v3(session, params, nlp)) != NDMP_NO_ERR) {
38812654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "fix_nlist_v3: %d", rv);
38822654012fSReza Sabdar 	} else {
38832654012fSReza Sabdar 		rv = NDMP_NO_ERR;
38842654012fSReza Sabdar 		get_direct_env_v3(params, nlp);
38852654012fSReza Sabdar 		if (NLP_ISSET(nlp, NLPF_DIRECT)) {
38862654012fSReza Sabdar 			if (NLP_ISSET(nlp, NLPF_RECURSIVE)) {
38872654012fSReza Sabdar 				/* Currently we dont support DAR on directory */
38882654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
38892654012fSReza Sabdar 				    "Can't have RECURSIVE and DIRECT together");
38902654012fSReza Sabdar 				rv = NDMP_ILLEGAL_ARGS_ERR;
38912654012fSReza Sabdar 				return (rv);
38922654012fSReza Sabdar 			}
38932654012fSReza Sabdar 
38942654012fSReza Sabdar 			/*
38952654012fSReza Sabdar 			 * DAR can be done if all the fh_info's are valid.
38962654012fSReza Sabdar 			 */
38972654012fSReza Sabdar 			if (allvalidfh(session, params)) {
38982654012fSReza Sabdar 				ndmp_sort_nlist_v3(session);
38992654012fSReza Sabdar 			} else {
39002654012fSReza Sabdar 				MOD_LOGV3(params, NDMP_LOG_WARNING,
39012654012fSReza Sabdar 				    "Cannot do direct access recovery. "
39022654012fSReza Sabdar 				    "Some 'fh_info'es are not valid.\n");
39032654012fSReza Sabdar 				NLP_UNSET(nlp, NLPF_DIRECT);
39042654012fSReza Sabdar 			}
39052654012fSReza Sabdar 		}
39062654012fSReza Sabdar 
39072654012fSReza Sabdar 		log_rs_params_v3(session, params, nlp);
39082654012fSReza Sabdar 	}
39092654012fSReza Sabdar 
39102654012fSReza Sabdar 	return (rv);
39112654012fSReza Sabdar }
39122654012fSReza Sabdar 
39132654012fSReza Sabdar 
39142654012fSReza Sabdar /*
39152654012fSReza Sabdar  * ndmpd_tar_restore_starter_v3
39162654012fSReza Sabdar  *
39172654012fSReza Sabdar  * The main restore starter function. It will start a DAR or
39182654012fSReza Sabdar  * non-DAR recovery based on the parameters. (V3 and V4 only)
39192654012fSReza Sabdar  *
39202654012fSReza Sabdar  * Parameters:
39212654012fSReza Sabdar  *   params (input) - pointer to the parameters structure
39222654012fSReza Sabdar  *
39232654012fSReza Sabdar  * Returns:
39242654012fSReza Sabdar  *   NDMP_NO_ERR: on success
39252654012fSReza Sabdar  *   != NDMP_NO_ERR: otherwise
39262654012fSReza Sabdar  */
39272654012fSReza Sabdar int
39288c4f9701SJanice Chang ndmpd_tar_restore_starter_v3(void *arg)
39292654012fSReza Sabdar {
39308c4f9701SJanice Chang 	ndmpd_module_params_t *params = arg;
39312654012fSReza Sabdar 	int err;
39322654012fSReza Sabdar 	ndmpd_session_t *session;
39332654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
39342654012fSReza Sabdar 
39352654012fSReza Sabdar 
39362654012fSReza Sabdar 	session = (ndmpd_session_t *)(params->mp_daemon_cookie);
39372654012fSReza Sabdar 	*(params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
39382654012fSReza Sabdar 	ndmp_session_ref(session);
39392654012fSReza Sabdar 
39402654012fSReza Sabdar 	if (NLP_ISSET(nlp, NLPF_DIRECT))
39412654012fSReza Sabdar 		err = ndmpd_rs_dar_tar_v3(session, params, nlp);
39422654012fSReza Sabdar 	else
39432654012fSReza Sabdar 		err = ndmpd_rs_sar_tar_v3(session, params, nlp);
39442654012fSReza Sabdar 
39452654012fSReza Sabdar 	MOD_DONE(params, err);
39462654012fSReza Sabdar 
39472654012fSReza Sabdar 	NS_DEC(nrs);
39482654012fSReza Sabdar 	/* nlp_params is allocated in start_recover() */
39492654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
39502654012fSReza Sabdar 	ndmp_session_unref(session);
39512654012fSReza Sabdar 	return (err);
39522654012fSReza Sabdar 
39532654012fSReza Sabdar }
39542654012fSReza Sabdar 
39552654012fSReza Sabdar /*
39562654012fSReza Sabdar  * ndmp_tar_restore_abort_v3
39572654012fSReza Sabdar  *
39582654012fSReza Sabdar  * Restore abort function (V3 and V4 only)
39592654012fSReza Sabdar  *
39602654012fSReza Sabdar  * Parameters:
39612654012fSReza Sabdar  *   module_cookie (input) - pointer to nlp
39622654012fSReza Sabdar  *
39632654012fSReza Sabdar  * Returns:
39642654012fSReza Sabdar  *   0
39652654012fSReza Sabdar  */
39662654012fSReza Sabdar int
39672654012fSReza Sabdar ndmpd_tar_restore_abort_v3(void *module_cookie)
39682654012fSReza Sabdar {
39692654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
39702654012fSReza Sabdar 
39712654012fSReza Sabdar 	nlp = (ndmp_lbr_params_t *)module_cookie;
39722654012fSReza Sabdar 	if (nlp != NULL && nlp->nlp_session != NULL) {
39732654012fSReza Sabdar 		if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
39742654012fSReza Sabdar 		    NDMP_ADDR_TCP &&
39752654012fSReza Sabdar 		    nlp->nlp_session->ns_data.dd_sock != -1) {
39762654012fSReza Sabdar 			(void) close(nlp->nlp_session->ns_data.dd_sock);
39772654012fSReza Sabdar 			nlp->nlp_session->ns_data.dd_sock = -1;
39782654012fSReza Sabdar 		}
39792654012fSReza Sabdar 		ndmp_stop_writer_thread(nlp->nlp_session);
39802654012fSReza Sabdar 	}
39812654012fSReza Sabdar 
39822654012fSReza Sabdar 	return (0);
39832654012fSReza Sabdar }
3984