xref: /onnv-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c (revision 8800:dbcc21c0ec0f)
17917SReza.Sabdar@Sun.COM /*
2*8800SReza.Sabdar@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37917SReza.Sabdar@Sun.COM  * Use is subject to license terms.
47917SReza.Sabdar@Sun.COM  */
57917SReza.Sabdar@Sun.COM 
67917SReza.Sabdar@Sun.COM /*
77917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
87917SReza.Sabdar@Sun.COM  *
97917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
107917SReza.Sabdar@Sun.COM  *
117917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
127917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
137917SReza.Sabdar@Sun.COM  * are met:
147917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
157917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
167917SReza.Sabdar@Sun.COM  *
177917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
187917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
197917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
207917SReza.Sabdar@Sun.COM  *	  distribution.
217917SReza.Sabdar@Sun.COM  *
227917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
237917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
247917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
257917SReza.Sabdar@Sun.COM  *	  permission.
267917SReza.Sabdar@Sun.COM  *
277917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
287917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
297917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
307917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
317917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
327917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
337917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
347917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
357917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
367917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
377917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
387917SReza.Sabdar@Sun.COM  */
397917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
407917SReza.Sabdar@Sun.COM 
417917SReza.Sabdar@Sun.COM #include <sys/stat.h>
427917SReza.Sabdar@Sun.COM #include <sys/types.h>
437917SReza.Sabdar@Sun.COM #include <sys/socket.h>
447917SReza.Sabdar@Sun.COM #include <errno.h>
457917SReza.Sabdar@Sun.COM #include <stdio.h>
467917SReza.Sabdar@Sun.COM #include <string.h>
477917SReza.Sabdar@Sun.COM #include <unistd.h>
487917SReza.Sabdar@Sun.COM #include <time.h>
497917SReza.Sabdar@Sun.COM #include <cstack.h>
507917SReza.Sabdar@Sun.COM #include <dirent.h>
517917SReza.Sabdar@Sun.COM #include <traverse.h>
527917SReza.Sabdar@Sun.COM #include "bitmap.h"
537917SReza.Sabdar@Sun.COM #include "ndmpd.h"
547917SReza.Sabdar@Sun.COM #include "tlm_buffers.h"
557917SReza.Sabdar@Sun.COM 
567917SReza.Sabdar@Sun.COM 
577917SReza.Sabdar@Sun.COM typedef struct ndmp_run_args {
587917SReza.Sabdar@Sun.COM 	char *nr_chkp_nm;
597917SReza.Sabdar@Sun.COM 	char *nr_unchkp_nm;
607917SReza.Sabdar@Sun.COM 	char **nr_excls;
617917SReza.Sabdar@Sun.COM } ndmp_run_args_t;
627917SReza.Sabdar@Sun.COM 
637917SReza.Sabdar@Sun.COM 
647917SReza.Sabdar@Sun.COM /*
657917SReza.Sabdar@Sun.COM  * backup_create_structs
667917SReza.Sabdar@Sun.COM  *
677917SReza.Sabdar@Sun.COM  * Allocate the structures before performing backup
687917SReza.Sabdar@Sun.COM  *
697917SReza.Sabdar@Sun.COM  * Parameters:
707917SReza.Sabdar@Sun.COM  *   sesison (input) - session handle
717917SReza.Sabdar@Sun.COM  *   jname (input) - backup job name
727917SReza.Sabdar@Sun.COM  *
737917SReza.Sabdar@Sun.COM  * Returns:
747917SReza.Sabdar@Sun.COM  *   0: on success
757917SReza.Sabdar@Sun.COM  *  -1: otherwise
767917SReza.Sabdar@Sun.COM  */
777917SReza.Sabdar@Sun.COM static int
787917SReza.Sabdar@Sun.COM backup_create_structs(ndmpd_session_t *session, char *jname)
797917SReza.Sabdar@Sun.COM {
807917SReza.Sabdar@Sun.COM 	int n;
817917SReza.Sabdar@Sun.COM 	long xfer_size;
827917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
837917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
847917SReza.Sabdar@Sun.COM 
857917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
867917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
877917SReza.Sabdar@Sun.COM 		return (-1);
887917SReza.Sabdar@Sun.COM 	}
897917SReza.Sabdar@Sun.COM 
907917SReza.Sabdar@Sun.COM 	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
917917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
927917SReza.Sabdar@Sun.COM 		return (-1);
937917SReza.Sabdar@Sun.COM 	}
947917SReza.Sabdar@Sun.COM 
957917SReza.Sabdar@Sun.COM 	cmds = &nlp->nlp_cmds;
967917SReza.Sabdar@Sun.COM 	(void) memset(cmds, 0, sizeof (*cmds));
977917SReza.Sabdar@Sun.COM 
987917SReza.Sabdar@Sun.COM 	xfer_size = ndmp_buffer_get_size(session);
997917SReza.Sabdar@Sun.COM 	if (xfer_size < 512*KILOBYTE) {
1007917SReza.Sabdar@Sun.COM 		/*
1017917SReza.Sabdar@Sun.COM 		 * Read multiple of mover_record_size near to 512K.  This
1027917SReza.Sabdar@Sun.COM 		 * will prevent the data being copied in the mover buffer
1037917SReza.Sabdar@Sun.COM 		 * when we write the data.
1047917SReza.Sabdar@Sun.COM 		 */
1057917SReza.Sabdar@Sun.COM 		if ((n = (512 * KILOBYTE/xfer_size)) <= 0)
1067917SReza.Sabdar@Sun.COM 			n = 1;
1077917SReza.Sabdar@Sun.COM 		xfer_size *= n;
1087917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Adjusted read size: %d", xfer_size);
1097917SReza.Sabdar@Sun.COM 	}
1107917SReza.Sabdar@Sun.COM 
1117917SReza.Sabdar@Sun.COM 	cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, xfer_size);
1127917SReza.Sabdar@Sun.COM 	if (cmds->tcs_command == NULL) {
1137917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
1147917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(jname);
1157917SReza.Sabdar@Sun.COM 		return (-1);
1167917SReza.Sabdar@Sun.COM 	}
1177917SReza.Sabdar@Sun.COM 
1187917SReza.Sabdar@Sun.COM 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1197917SReza.Sabdar@Sun.COM 	    ndmpd_file_history_path,
1207917SReza.Sabdar@Sun.COM 	    ndmpd_file_history_dir,
1217917SReza.Sabdar@Sun.COM 	    ndmpd_file_history_node);
1227917SReza.Sabdar@Sun.COM 	if (nlp->nlp_logcallbacks == NULL) {
1237917SReza.Sabdar@Sun.COM 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1247917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(jname);
1257917SReza.Sabdar@Sun.COM 		return (-1);
1267917SReza.Sabdar@Sun.COM 	}
1277917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1287917SReza.Sabdar@Sun.COM 
1297917SReza.Sabdar@Sun.COM 	return (0);
1307917SReza.Sabdar@Sun.COM }
1317917SReza.Sabdar@Sun.COM 
1327917SReza.Sabdar@Sun.COM 
1337917SReza.Sabdar@Sun.COM /*
1347917SReza.Sabdar@Sun.COM  * restore_create_structs
1357917SReza.Sabdar@Sun.COM  *
1367917SReza.Sabdar@Sun.COM  * Allocate structures for performing a restore
1377917SReza.Sabdar@Sun.COM  *
1387917SReza.Sabdar@Sun.COM  * Parameters:
1397917SReza.Sabdar@Sun.COM  *   sesison (input) - session handle
1407917SReza.Sabdar@Sun.COM  *   jname (input) - backup job name
1417917SReza.Sabdar@Sun.COM  *
1427917SReza.Sabdar@Sun.COM  * Returns:
1437917SReza.Sabdar@Sun.COM  *   0: on success
1447917SReza.Sabdar@Sun.COM  *  -1: otherwise
1457917SReza.Sabdar@Sun.COM  */
1467917SReza.Sabdar@Sun.COM static int
1477917SReza.Sabdar@Sun.COM restore_create_structs(ndmpd_session_t *session, char *jname)
1487917SReza.Sabdar@Sun.COM {
1497917SReza.Sabdar@Sun.COM 	int i;
1507917SReza.Sabdar@Sun.COM 	long xfer_size;
1517917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
1527917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
1537917SReza.Sabdar@Sun.COM 
1547917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1557917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1567917SReza.Sabdar@Sun.COM 		return (-1);
1577917SReza.Sabdar@Sun.COM 	}
1587917SReza.Sabdar@Sun.COM 	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
1597917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
1607917SReza.Sabdar@Sun.COM 		return (-1);
1617917SReza.Sabdar@Sun.COM 	}
1627917SReza.Sabdar@Sun.COM 
1637917SReza.Sabdar@Sun.COM 	cmds = &nlp->nlp_cmds;
1647917SReza.Sabdar@Sun.COM 	(void) memset(cmds, 0, sizeof (*cmds));
1657917SReza.Sabdar@Sun.COM 
1667917SReza.Sabdar@Sun.COM 	xfer_size = ndmp_buffer_get_size(session);
1677917SReza.Sabdar@Sun.COM 	cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
1687917SReza.Sabdar@Sun.COM 	if (cmds->tcs_command == NULL) {
1697917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
1707917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(jname);
1717917SReza.Sabdar@Sun.COM 		return (-1);
1727917SReza.Sabdar@Sun.COM 	}
1737917SReza.Sabdar@Sun.COM 
1747917SReza.Sabdar@Sun.COM 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1757917SReza.Sabdar@Sun.COM 	    ndmpd_path_restored, NULL, NULL);
1767917SReza.Sabdar@Sun.COM 	if (nlp->nlp_logcallbacks == NULL) {
1777917SReza.Sabdar@Sun.COM 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1787917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(jname);
1797917SReza.Sabdar@Sun.COM 		return (-1);
1807917SReza.Sabdar@Sun.COM 	}
1817917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1827917SReza.Sabdar@Sun.COM 
1837917SReza.Sabdar@Sun.COM 	nlp->nlp_restored = ndmp_malloc(sizeof (boolean_t) * nlp->nlp_nfiles);
1847917SReza.Sabdar@Sun.COM 	if (nlp->nlp_restored == NULL) {
1857917SReza.Sabdar@Sun.COM 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
1867917SReza.Sabdar@Sun.COM 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1877917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(jname);
1887917SReza.Sabdar@Sun.COM 		return (-1);
1897917SReza.Sabdar@Sun.COM 	}
1907917SReza.Sabdar@Sun.COM 	for (i = 0; i < (int)nlp->nlp_nfiles; i++)
1917917SReza.Sabdar@Sun.COM 		nlp->nlp_restored[i] = FALSE;
1927917SReza.Sabdar@Sun.COM 
1937917SReza.Sabdar@Sun.COM 	return (0);
1947917SReza.Sabdar@Sun.COM }
1957917SReza.Sabdar@Sun.COM 
1967917SReza.Sabdar@Sun.COM 
1977917SReza.Sabdar@Sun.COM /*
1987917SReza.Sabdar@Sun.COM  * send_unrecovered_list
1997917SReza.Sabdar@Sun.COM  *
2007917SReza.Sabdar@Sun.COM  * Creates a list of restored files
2017917SReza.Sabdar@Sun.COM  *
2027917SReza.Sabdar@Sun.COM  * Parameters:
2037917SReza.Sabdar@Sun.COM  *   params (input) - NDMP parameters
2047917SReza.Sabdar@Sun.COM  *   nlp (input) - NDMP/LBR parameters
2057917SReza.Sabdar@Sun.COM  *
2067917SReza.Sabdar@Sun.COM  * Returns:
2077917SReza.Sabdar@Sun.COM  *   0: on success
2087917SReza.Sabdar@Sun.COM  *  -1: otherwise
2097917SReza.Sabdar@Sun.COM  */
2107917SReza.Sabdar@Sun.COM static int
2117917SReza.Sabdar@Sun.COM send_unrecovered_list(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
2127917SReza.Sabdar@Sun.COM {
2137917SReza.Sabdar@Sun.COM 	int i, rv;
2147917SReza.Sabdar@Sun.COM 	ndmp_name *ent;
2157917SReza.Sabdar@Sun.COM 
2167917SReza.Sabdar@Sun.COM 	if (params == NULL) {
2177917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "params == NULL");
2187917SReza.Sabdar@Sun.COM 		return (-1);
2197917SReza.Sabdar@Sun.COM 	}
2207917SReza.Sabdar@Sun.COM 	if (nlp == NULL) {
2217917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2227917SReza.Sabdar@Sun.COM 		return (-1);
2237917SReza.Sabdar@Sun.COM 	}
2247917SReza.Sabdar@Sun.COM 
2257917SReza.Sabdar@Sun.COM 	rv = 0;
2267917SReza.Sabdar@Sun.COM 	for (i = 0; i < (int)nlp->nlp_nfiles; i++) {
2277917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp->nlp_restored[%d]: %s", i,
2287917SReza.Sabdar@Sun.COM 		    nlp->nlp_restored[i] ? "TRUE" : "FALSE");
2297917SReza.Sabdar@Sun.COM 
2307917SReza.Sabdar@Sun.COM 		if (!nlp->nlp_restored[i]) {
2317917SReza.Sabdar@Sun.COM 			ent = (ndmp_name *)MOD_GETNAME(params, i);
2327917SReza.Sabdar@Sun.COM 			if (ent == NULL) {
2337917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "ent == NULL");
2347917SReza.Sabdar@Sun.COM 				rv = -1;
2357917SReza.Sabdar@Sun.COM 				break;
2367917SReza.Sabdar@Sun.COM 			}
2377917SReza.Sabdar@Sun.COM 			if (ent->name == NULL) {
2387917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "ent->name == NULL");
2397917SReza.Sabdar@Sun.COM 				rv = -1;
2407917SReza.Sabdar@Sun.COM 				break;
2417917SReza.Sabdar@Sun.COM 			}
2427917SReza.Sabdar@Sun.COM 
2437917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "ent.name: \"%s\"", ent->name);
2447917SReza.Sabdar@Sun.COM 
2457917SReza.Sabdar@Sun.COM 			rv = MOD_FILERECOVERD(params, ent->name, ENOENT);
2467917SReza.Sabdar@Sun.COM 			if (rv < 0)
2477917SReza.Sabdar@Sun.COM 				break;
2487917SReza.Sabdar@Sun.COM 		}
2497917SReza.Sabdar@Sun.COM 	}
2507917SReza.Sabdar@Sun.COM 
2517917SReza.Sabdar@Sun.COM 	return (rv);
2527917SReza.Sabdar@Sun.COM }
2537917SReza.Sabdar@Sun.COM 
2547917SReza.Sabdar@Sun.COM 
2557917SReza.Sabdar@Sun.COM /*
2567917SReza.Sabdar@Sun.COM  * backup_release_structs
2577917SReza.Sabdar@Sun.COM  *
2587917SReza.Sabdar@Sun.COM  * Deallocated the NDMP/LBR specific parameters
2597917SReza.Sabdar@Sun.COM  *
2607917SReza.Sabdar@Sun.COM  * Parameters:
2617917SReza.Sabdar@Sun.COM  *   session (input) - session handle
2627917SReza.Sabdar@Sun.COM  *
2637917SReza.Sabdar@Sun.COM  * Returns:
2647917SReza.Sabdar@Sun.COM  *   void
2657917SReza.Sabdar@Sun.COM  */
2667917SReza.Sabdar@Sun.COM /*ARGSUSED*/
2677917SReza.Sabdar@Sun.COM static void
2687917SReza.Sabdar@Sun.COM backup_release_structs(ndmpd_session_t *session)
2697917SReza.Sabdar@Sun.COM {
2707917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
2717917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
2727917SReza.Sabdar@Sun.COM 
2737917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
2747917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2757917SReza.Sabdar@Sun.COM 		return;
2767917SReza.Sabdar@Sun.COM 	}
2777917SReza.Sabdar@Sun.COM 	cmds = &nlp->nlp_cmds;
2787917SReza.Sabdar@Sun.COM 	if (cmds == NULL) {
2797917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
2807917SReza.Sabdar@Sun.COM 		return;
2817917SReza.Sabdar@Sun.COM 	}
2827917SReza.Sabdar@Sun.COM 
2837917SReza.Sabdar@Sun.COM 	if (nlp->nlp_logcallbacks != NULL) {
2847917SReza.Sabdar@Sun.COM 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
2857917SReza.Sabdar@Sun.COM 		nlp->nlp_logcallbacks = NULL;
2867917SReza.Sabdar@Sun.COM 	} else {
2877917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
2887917SReza.Sabdar@Sun.COM 	}
2897917SReza.Sabdar@Sun.COM 
2907917SReza.Sabdar@Sun.COM 	if (cmds->tcs_command != NULL) {
2917917SReza.Sabdar@Sun.COM 		if (cmds->tcs_command->tc_buffers != NULL)
2927917SReza.Sabdar@Sun.COM 			tlm_release_reader_writer_ipc(cmds->tcs_command);
2937917SReza.Sabdar@Sun.COM 		else
2947917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
2957917SReza.Sabdar@Sun.COM 		cmds->tcs_command = NULL;
2967917SReza.Sabdar@Sun.COM 	} else {
2977917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
2987917SReza.Sabdar@Sun.COM 	}
2997917SReza.Sabdar@Sun.COM 
3007917SReza.Sabdar@Sun.COM 	if (nlp->nlp_bkmap >= 0) {
3017917SReza.Sabdar@Sun.COM 		(void) dbm_free(nlp->nlp_bkmap);
3027917SReza.Sabdar@Sun.COM 		nlp->nlp_bkmap = -1;
3037917SReza.Sabdar@Sun.COM 	}
3047917SReza.Sabdar@Sun.COM 
3057917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER &&
3067917SReza.Sabdar@Sun.COM 	    nlp->nlp_restored != NULL) {
3077917SReza.Sabdar@Sun.COM 		free(nlp->nlp_restored);
3087917SReza.Sabdar@Sun.COM 		nlp->nlp_restored = NULL;
3097917SReza.Sabdar@Sun.COM 	} else {
3107917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp_restored == NULL");
3117917SReza.Sabdar@Sun.COM 	}
3127917SReza.Sabdar@Sun.COM }
3137917SReza.Sabdar@Sun.COM 
3147917SReza.Sabdar@Sun.COM /*
3157917SReza.Sabdar@Sun.COM  * ndmp_write_utf8magic
3167917SReza.Sabdar@Sun.COM  *
3177917SReza.Sabdar@Sun.COM  * Write a magic pattern to the tar header. This is used
3187917SReza.Sabdar@Sun.COM  * as a crest to indicate that tape belongs to us.
3197917SReza.Sabdar@Sun.COM  */
3207917SReza.Sabdar@Sun.COM int
3217917SReza.Sabdar@Sun.COM ndmp_write_utf8magic(tlm_cmd_t *cmd)
3227917SReza.Sabdar@Sun.COM {
3237917SReza.Sabdar@Sun.COM 	char *cp;
3247917SReza.Sabdar@Sun.COM 	long actual_size;
3257917SReza.Sabdar@Sun.COM 
3267917SReza.Sabdar@Sun.COM 	if (cmd->tc_buffers == NULL) {
3277917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
3287917SReza.Sabdar@Sun.COM 		return (-1);
3297917SReza.Sabdar@Sun.COM 	}
3307917SReza.Sabdar@Sun.COM 
3317917SReza.Sabdar@Sun.COM 	cp = tlm_get_write_buffer(RECORDSIZE, &actual_size,
3327917SReza.Sabdar@Sun.COM 	    cmd->tc_buffers, TRUE);
3337917SReza.Sabdar@Sun.COM 	if (actual_size < RECORDSIZE) {
3347917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Couldn't get enough buffer");
3357917SReza.Sabdar@Sun.COM 		return (-1);
3367917SReza.Sabdar@Sun.COM 	}
3377917SReza.Sabdar@Sun.COM 
3387917SReza.Sabdar@Sun.COM 	(void) strlcpy(cp, NDMPUTF8MAGIC, RECORDSIZE);
3397917SReza.Sabdar@Sun.COM 	return (0);
3407917SReza.Sabdar@Sun.COM }
3417917SReza.Sabdar@Sun.COM 
3427917SReza.Sabdar@Sun.COM 
3437917SReza.Sabdar@Sun.COM /*
3447917SReza.Sabdar@Sun.COM  * timecmp
3457917SReza.Sabdar@Sun.COM  *
3467917SReza.Sabdar@Sun.COM  * This callback function is used during backup.  It checks
3477917SReza.Sabdar@Sun.COM  * if the object specified by the 'attr' should be backed
3487917SReza.Sabdar@Sun.COM  * up or not.
3497917SReza.Sabdar@Sun.COM  *
3507917SReza.Sabdar@Sun.COM  * Directories are backed up anyways for dump format.
3517917SReza.Sabdar@Sun.COM  * If this function is called, then the directory is
3527917SReza.Sabdar@Sun.COM  * marked in the bitmap vector, it shows that either the
3537917SReza.Sabdar@Sun.COM  * directory itself is modified or there is something below
3547917SReza.Sabdar@Sun.COM  * it that will be backed up.
3557917SReza.Sabdar@Sun.COM  *
3567917SReza.Sabdar@Sun.COM  * Directories for tar format are backed up if and only if
3577917SReza.Sabdar@Sun.COM  * they are modified.
3587917SReza.Sabdar@Sun.COM  *
3597917SReza.Sabdar@Sun.COM  * By setting ndmp_force_bk_dirs global variable to a non-zero
3607917SReza.Sabdar@Sun.COM  * value, directories are backed up anyways.
3617917SReza.Sabdar@Sun.COM  *
3627917SReza.Sabdar@Sun.COM  * Backing up the directories unconditionally, helps
3637917SReza.Sabdar@Sun.COM  * restoring the metadata of directories as well, when one
3647917SReza.Sabdar@Sun.COM  * of the objects below them are being restored.
3657917SReza.Sabdar@Sun.COM  *
3667917SReza.Sabdar@Sun.COM  * For non-directory objects, if the modification or change
3677917SReza.Sabdar@Sun.COM  * time of the object is after the date specified by the
3687917SReza.Sabdar@Sun.COM  * bk_selector_t, the the object must be backed up.
3697917SReza.Sabdar@Sun.COM  *
3707917SReza.Sabdar@Sun.COM  */
3717917SReza.Sabdar@Sun.COM static boolean_t
3727917SReza.Sabdar@Sun.COM timecmp(bk_selector_t *bksp,
3737917SReza.Sabdar@Sun.COM 		struct stat64 *attr)
3747917SReza.Sabdar@Sun.COM {
3757917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
3767917SReza.Sabdar@Sun.COM 
3777917SReza.Sabdar@Sun.COM 	nlp = (ndmp_lbr_params_t *)bksp->bs_cookie;
3787917SReza.Sabdar@Sun.COM 	if (S_ISDIR(attr->st_mode) && ndmp_force_bk_dirs) {
3797917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "d(%lu)",
3807917SReza.Sabdar@Sun.COM 		    (uint_t)attr->st_ino);
3817917SReza.Sabdar@Sun.COM 		return (TRUE);
3827917SReza.Sabdar@Sun.COM 	}
3837917SReza.Sabdar@Sun.COM 	if (S_ISDIR(attr->st_mode) &&
3847917SReza.Sabdar@Sun.COM 	    dbm_getone(nlp->nlp_bkmap, (u_longlong_t)attr->st_ino) &&
3857917SReza.Sabdar@Sun.COM 	    ((NLP_ISDUMP(nlp) && ndmp_dump_path_node) ||
3867917SReza.Sabdar@Sun.COM 	    (NLP_ISTAR(nlp) && ndmp_tar_path_node))) {
3877917SReza.Sabdar@Sun.COM 		/*
3887917SReza.Sabdar@Sun.COM 		 * If the object is a directory and it leads to a modified
3897917SReza.Sabdar@Sun.COM 		 * object (that should be backed up) and for that type of
3907917SReza.Sabdar@Sun.COM 		 * backup the path nodes should be backed up, then return
3917917SReza.Sabdar@Sun.COM 		 * TRUE.
3927917SReza.Sabdar@Sun.COM 		 *
3937917SReza.Sabdar@Sun.COM 		 * This is required by some DMAs like Backup Express, which
3947917SReza.Sabdar@Sun.COM 		 * needs to receive ADD_NODE (for dump) or ADD_PATH (for tar)
3957917SReza.Sabdar@Sun.COM 		 * for the intermediate directories of a modified object.
3967917SReza.Sabdar@Sun.COM 		 * Other DMAs, like net_backup and net_worker, do not have such
3977917SReza.Sabdar@Sun.COM 		 * requirement.  This requirement makes sense for dump format
3987917SReza.Sabdar@Sun.COM 		 * but for 'tar' format, it does not.  In provision to the
3997917SReza.Sabdar@Sun.COM 		 * NDMP-v4 spec, for 'tar' format the intermediate directories
4007917SReza.Sabdar@Sun.COM 		 * need not to be reported.
4017917SReza.Sabdar@Sun.COM 		 */
4027917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "p(%lu)", (u_longlong_t)attr->st_ino);
4037917SReza.Sabdar@Sun.COM 		return (TRUE);
4047917SReza.Sabdar@Sun.COM 	}
4057917SReza.Sabdar@Sun.COM 	if (attr->st_mtime > bksp->bs_ldate) {
4067917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "m(%lu): %lu > %lu",
4077917SReza.Sabdar@Sun.COM 		    (uint_t)attr->st_ino, (uint_t)attr->st_mtime,
4087917SReza.Sabdar@Sun.COM 		    (uint_t)bksp->bs_ldate);
4097917SReza.Sabdar@Sun.COM 		return (TRUE);
4107917SReza.Sabdar@Sun.COM 	}
4117917SReza.Sabdar@Sun.COM 	if (attr->st_ctime > bksp->bs_ldate) {
4127917SReza.Sabdar@Sun.COM 		if (NLP_IGNCTIME(nlp)) {
4137917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "ign c(%lu): %lu > %lu",
4147917SReza.Sabdar@Sun.COM 			    (uint_t)attr->st_ino, (uint_t)attr->st_ctime,
4157917SReza.Sabdar@Sun.COM 			    (uint_t)bksp->bs_ldate);
4167917SReza.Sabdar@Sun.COM 			return (FALSE);
4177917SReza.Sabdar@Sun.COM 		}
4187917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "c(%lu): %lu > %lu",
4197917SReza.Sabdar@Sun.COM 		    (uint_t)attr->st_ino, (uint_t)attr->st_ctime,
4207917SReza.Sabdar@Sun.COM 		    (uint_t)bksp->bs_ldate);
4217917SReza.Sabdar@Sun.COM 		return (TRUE);
4227917SReza.Sabdar@Sun.COM 	}
4237917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "mc(%lu): (%lu,%lu) < %lu",
4247917SReza.Sabdar@Sun.COM 	    (uint_t)attr->st_ino, (uint_t)attr->st_mtime,
4257917SReza.Sabdar@Sun.COM 	    (uint_t)attr->st_ctime, (uint_t)bksp->bs_ldate);
4267917SReza.Sabdar@Sun.COM 	return (FALSE);
4277917SReza.Sabdar@Sun.COM }
4287917SReza.Sabdar@Sun.COM 
4297917SReza.Sabdar@Sun.COM 
4307917SReza.Sabdar@Sun.COM /*
4317917SReza.Sabdar@Sun.COM  * get_acl_info
4327917SReza.Sabdar@Sun.COM  *
4337917SReza.Sabdar@Sun.COM  * load up all the access and attribute info
4347917SReza.Sabdar@Sun.COM  */
4357917SReza.Sabdar@Sun.COM static int
4367917SReza.Sabdar@Sun.COM get_acl_info(char *name, tlm_acls_t *tlm_acls)
4377917SReza.Sabdar@Sun.COM {
4387917SReza.Sabdar@Sun.COM 	int erc;
4397917SReza.Sabdar@Sun.COM 	acl_t *aclp = NULL;
4407917SReza.Sabdar@Sun.COM 	char *acltp;
4417917SReza.Sabdar@Sun.COM 
4427917SReza.Sabdar@Sun.COM 	erc = lstat64(name, &tlm_acls->acl_attr);
4437917SReza.Sabdar@Sun.COM 	if (erc != 0) {
4447917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Could not find file %s.", name);
4457917SReza.Sabdar@Sun.COM 		erc = TLM_NO_SOURCE_FILE;
4467917SReza.Sabdar@Sun.COM 		return (erc);
4477917SReza.Sabdar@Sun.COM 	}
4487917SReza.Sabdar@Sun.COM 	erc = acl_get(name, ACL_NO_TRIVIAL, &aclp);
4497917SReza.Sabdar@Sun.COM 	if (erc != 0) {
4507917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
4517917SReza.Sabdar@Sun.COM 		    "Could not read ACL for file [%s]", name);
4527917SReza.Sabdar@Sun.COM 		erc = TLM_NO_SOURCE_FILE;
4537917SReza.Sabdar@Sun.COM 		return (erc);
4547917SReza.Sabdar@Sun.COM 	}
4557917SReza.Sabdar@Sun.COM 	if (aclp && (acltp = acl_totext(aclp,
4567917SReza.Sabdar@Sun.COM 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
4577917SReza.Sabdar@Sun.COM 		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
4587917SReza.Sabdar@Sun.COM 		    TLM_MAX_ACL_TXT);
4597917SReza.Sabdar@Sun.COM 		acl_free(aclp);
4607917SReza.Sabdar@Sun.COM 		free(acltp);
4617917SReza.Sabdar@Sun.COM 	}
4627917SReza.Sabdar@Sun.COM 	return (erc);
4637917SReza.Sabdar@Sun.COM }
4647917SReza.Sabdar@Sun.COM /*
4657917SReza.Sabdar@Sun.COM  * get_dir_acl_info
4667917SReza.Sabdar@Sun.COM  *
4677917SReza.Sabdar@Sun.COM  * load up all ACL and attr info about a directory
4687917SReza.Sabdar@Sun.COM  */
4697917SReza.Sabdar@Sun.COM static int
4707917SReza.Sabdar@Sun.COM get_dir_acl_info(char *dir, tlm_acls_t *tlm_acls, tlm_job_stats_t *js)
4717917SReza.Sabdar@Sun.COM {
4727917SReza.Sabdar@Sun.COM 	int	erc;
4737917SReza.Sabdar@Sun.COM 	char	*checkpointed_dir;
4747917SReza.Sabdar@Sun.COM 	char	root_dir[TLM_VOLNAME_MAX_LENGTH];
4757917SReza.Sabdar@Sun.COM 	char	*spot;
4767917SReza.Sabdar@Sun.COM 	char	*fil;
4777917SReza.Sabdar@Sun.COM 	acl_t	*aclp = NULL;
4787917SReza.Sabdar@Sun.COM 	char 	*acltp;
4797917SReza.Sabdar@Sun.COM 
4807917SReza.Sabdar@Sun.COM 	checkpointed_dir = ndmp_malloc(TLM_MAX_PATH_NAME);
4817917SReza.Sabdar@Sun.COM 	if (checkpointed_dir == NULL)
4827917SReza.Sabdar@Sun.COM 		return (-1);
4837917SReza.Sabdar@Sun.COM 
4847917SReza.Sabdar@Sun.COM 	if (tlm_acls->acl_checkpointed)
4857917SReza.Sabdar@Sun.COM 		fil = tlm_build_snapshot_name(dir, checkpointed_dir,
4867917SReza.Sabdar@Sun.COM 		    js->js_job_name);
4877917SReza.Sabdar@Sun.COM 	else
4887917SReza.Sabdar@Sun.COM 		fil = dir;
4897917SReza.Sabdar@Sun.COM 	erc = lstat64(fil, &tlm_acls->acl_attr);
4907917SReza.Sabdar@Sun.COM 	if (erc != 0) {
4917917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Could not find directory %s.", dir);
4927917SReza.Sabdar@Sun.COM 		free(checkpointed_dir);
4937917SReza.Sabdar@Sun.COM 		return (-1);
4947917SReza.Sabdar@Sun.COM 	}
4957917SReza.Sabdar@Sun.COM 
4967917SReza.Sabdar@Sun.COM 	spot = strchr(&fil[1], '/');
4977917SReza.Sabdar@Sun.COM 	if (spot == NULL) {
4987917SReza.Sabdar@Sun.COM 		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
4997917SReza.Sabdar@Sun.COM 	} else {
5007917SReza.Sabdar@Sun.COM 		*spot = 0;
5017917SReza.Sabdar@Sun.COM 		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
5027917SReza.Sabdar@Sun.COM 		*spot = '/';
5037917SReza.Sabdar@Sun.COM 	}
5047917SReza.Sabdar@Sun.COM 	if (strcmp(root_dir, tlm_acls->acl_root_dir) != 0) {
5057917SReza.Sabdar@Sun.COM 		struct stat64 attr;
5067917SReza.Sabdar@Sun.COM 
5077917SReza.Sabdar@Sun.COM 		erc = lstat64(root_dir, &attr);
5087917SReza.Sabdar@Sun.COM 		if (erc != 0) {
5097917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Cannot find root directory %s.",
5107917SReza.Sabdar@Sun.COM 			    root_dir);
5117917SReza.Sabdar@Sun.COM 			free(checkpointed_dir);
5127917SReza.Sabdar@Sun.COM 			return (-1);
5137917SReza.Sabdar@Sun.COM 		}
5147917SReza.Sabdar@Sun.COM 		(void) strlcpy(tlm_acls->acl_root_dir, root_dir,
5157917SReza.Sabdar@Sun.COM 		    TLM_VOLNAME_MAX_LENGTH);
5167917SReza.Sabdar@Sun.COM 	}
5177917SReza.Sabdar@Sun.COM 	erc = acl_get(fil, ACL_NO_TRIVIAL, &aclp);
5187917SReza.Sabdar@Sun.COM 	if (erc != 0) {
5197917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
5207917SReza.Sabdar@Sun.COM 		    "Could not read metadata for directory [%s]", dir);
5217917SReza.Sabdar@Sun.COM 		free(checkpointed_dir);
5227917SReza.Sabdar@Sun.COM 		return (-1);
5237917SReza.Sabdar@Sun.COM 	}
5247917SReza.Sabdar@Sun.COM 	if (aclp && (acltp = acl_totext(aclp,
5257917SReza.Sabdar@Sun.COM 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
5267917SReza.Sabdar@Sun.COM 		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
5277917SReza.Sabdar@Sun.COM 		    TLM_MAX_ACL_TXT);
5287917SReza.Sabdar@Sun.COM 		acl_free(aclp);
5297917SReza.Sabdar@Sun.COM 		free(acltp);
5307917SReza.Sabdar@Sun.COM 	}
5317917SReza.Sabdar@Sun.COM 
5327917SReza.Sabdar@Sun.COM 	free(checkpointed_dir);
5337917SReza.Sabdar@Sun.COM 	return (0);
5347917SReza.Sabdar@Sun.COM }
5357917SReza.Sabdar@Sun.COM 
5367917SReza.Sabdar@Sun.COM /*
5377917SReza.Sabdar@Sun.COM  * backup_dir
5387917SReza.Sabdar@Sun.COM  *
5397917SReza.Sabdar@Sun.COM  * Create a TAR entry record for a directory
5407917SReza.Sabdar@Sun.COM  */
5417917SReza.Sabdar@Sun.COM static int
5427917SReza.Sabdar@Sun.COM backup_dir(char *dir, tlm_acls_t *tlm_acls,
5437917SReza.Sabdar@Sun.COM     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats,
5447917SReza.Sabdar@Sun.COM     bk_selector_t *bksp)
5457917SReza.Sabdar@Sun.COM {
5467917SReza.Sabdar@Sun.COM 	int erc;
5477917SReza.Sabdar@Sun.COM 
5487917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "\"%s\"", dir);
5497917SReza.Sabdar@Sun.COM 
5507917SReza.Sabdar@Sun.COM 	erc = get_dir_acl_info(dir, tlm_acls, job_stats);
5517917SReza.Sabdar@Sun.COM 	if (erc != 0) {
5527917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
5537917SReza.Sabdar@Sun.COM 		    "Could not read directory info for %s", dir);
5547917SReza.Sabdar@Sun.COM 		job_stats->js_errors++;
5557917SReza.Sabdar@Sun.COM 	} else {
5567917SReza.Sabdar@Sun.COM 		/*
5577917SReza.Sabdar@Sun.COM 		 * See if the directory must be backed up.
5587917SReza.Sabdar@Sun.COM 		 */
5597917SReza.Sabdar@Sun.COM 		if (bksp && !(*bksp->bs_fn)(bksp, &tlm_acls->acl_attr)) {
5607917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "[%s] dir skipped", dir);
5617917SReza.Sabdar@Sun.COM 			return (erc);
5627917SReza.Sabdar@Sun.COM 		}
5637917SReza.Sabdar@Sun.COM 
5647917SReza.Sabdar@Sun.COM 		if (tm_tar_ops.tm_putdir != NULL)
5657917SReza.Sabdar@Sun.COM 			(void) (tm_tar_ops.tm_putdir)(dir, tlm_acls,
5667917SReza.Sabdar@Sun.COM 			    local_commands, job_stats);
5677917SReza.Sabdar@Sun.COM 	}
5687917SReza.Sabdar@Sun.COM 
5697917SReza.Sabdar@Sun.COM 	return (erc);
5707917SReza.Sabdar@Sun.COM }
5717917SReza.Sabdar@Sun.COM 
5727917SReza.Sabdar@Sun.COM 
5737917SReza.Sabdar@Sun.COM /*
5747917SReza.Sabdar@Sun.COM  * backup_file
5757917SReza.Sabdar@Sun.COM  *
5767917SReza.Sabdar@Sun.COM  * Create a TAR record entry for a file
5777917SReza.Sabdar@Sun.COM  */
5787917SReza.Sabdar@Sun.COM static longlong_t
5797917SReza.Sabdar@Sun.COM backup_file(char *dir, char *name, tlm_acls_t *tlm_acls,
5807917SReza.Sabdar@Sun.COM     tlm_commands_t *commands, tlm_cmd_t *local_commands,
5817917SReza.Sabdar@Sun.COM     tlm_job_stats_t *job_stats, bk_selector_t *bksp)
5827917SReza.Sabdar@Sun.COM {
5837917SReza.Sabdar@Sun.COM 
5847917SReza.Sabdar@Sun.COM 	int erc;
5857917SReza.Sabdar@Sun.COM 	char buf[TLM_MAX_PATH_NAME];
5867917SReza.Sabdar@Sun.COM 	longlong_t rv;
5877917SReza.Sabdar@Sun.COM 
5887917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", dir, name);
5897917SReza.Sabdar@Sun.COM 
5907917SReza.Sabdar@Sun.COM 	(void) strlcpy(buf, dir, sizeof (buf));
5917917SReza.Sabdar@Sun.COM 	(void) strlcat(buf, "/", sizeof (buf));
5927917SReza.Sabdar@Sun.COM 	(void) strlcat(buf, name, sizeof (buf));
5937917SReza.Sabdar@Sun.COM 
5947917SReza.Sabdar@Sun.COM 	/*
5957917SReza.Sabdar@Sun.COM 	 * get_acl_info extracts file handle, attributes and ACLs of the file.
5967917SReza.Sabdar@Sun.COM 	 * This is not efficient when the attributes and file handle of
5977917SReza.Sabdar@Sun.COM 	 * the file is already known.
5987917SReza.Sabdar@Sun.COM 	 */
5997917SReza.Sabdar@Sun.COM 	erc = get_acl_info(buf, tlm_acls);
6007917SReza.Sabdar@Sun.COM 	if (erc != TLM_NO_ERRORS) {
6017917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Could not open file %s/%s.", dir, name);
6027917SReza.Sabdar@Sun.COM 		return (-ENOENT);
6037917SReza.Sabdar@Sun.COM 	}
6047917SReza.Sabdar@Sun.COM 
6057917SReza.Sabdar@Sun.COM 	/* Should the file be backed up? */
6067917SReza.Sabdar@Sun.COM 	if (!bksp) {
6077917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
6087917SReza.Sabdar@Sun.COM 		    "[%s/%s] has no selection criteria", dir, name);
6097917SReza.Sabdar@Sun.COM 
6107917SReza.Sabdar@Sun.COM 	} else if (!((*bksp->bs_fn)(bksp, &tlm_acls->acl_attr))) {
6117917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "[%s/%s] file skipped", dir, name);
6127917SReza.Sabdar@Sun.COM 		return (0);
6137917SReza.Sabdar@Sun.COM 	}
6147917SReza.Sabdar@Sun.COM 
6157917SReza.Sabdar@Sun.COM 	/* Only the regular files and symbolic links can be backed up. */
6167917SReza.Sabdar@Sun.COM 	if (!S_ISLNK(tlm_acls->acl_attr.st_mode) &&
6177917SReza.Sabdar@Sun.COM 	    !S_ISREG(tlm_acls->acl_attr.st_mode)) {
6187917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
6197917SReza.Sabdar@Sun.COM 		    "Warning: skip backing up [%s][%s]", dir, name);
6207917SReza.Sabdar@Sun.COM 		return (-EINVAL);
6217917SReza.Sabdar@Sun.COM 	}
6227917SReza.Sabdar@Sun.COM 
6237917SReza.Sabdar@Sun.COM 
6247917SReza.Sabdar@Sun.COM 	if (tm_tar_ops.tm_putfile != NULL)
6257917SReza.Sabdar@Sun.COM 		rv = (tm_tar_ops.tm_putfile)(dir, name, tlm_acls, commands,
6267917SReza.Sabdar@Sun.COM 		    local_commands, job_stats);
6277917SReza.Sabdar@Sun.COM 
6287917SReza.Sabdar@Sun.COM 	return (rv);
6297917SReza.Sabdar@Sun.COM }
6307917SReza.Sabdar@Sun.COM 
6317917SReza.Sabdar@Sun.COM 
6327917SReza.Sabdar@Sun.COM 
6337917SReza.Sabdar@Sun.COM /*
6347917SReza.Sabdar@Sun.COM  * backup_work
6357917SReza.Sabdar@Sun.COM  *
6367917SReza.Sabdar@Sun.COM  * Start the NDMP backup (V2 only).
6377917SReza.Sabdar@Sun.COM  */
6387917SReza.Sabdar@Sun.COM int
6397917SReza.Sabdar@Sun.COM backup_work(char *bk_path, tlm_job_stats_t *job_stats,
6407917SReza.Sabdar@Sun.COM     ndmp_run_args_t *np, tlm_commands_t *commands,
6417917SReza.Sabdar@Sun.COM     ndmp_lbr_params_t *nlp)
6427917SReza.Sabdar@Sun.COM {
6437917SReza.Sabdar@Sun.COM 	struct full_dir_info dir_info; /* the blob to push/pop with cstack_t */
6447917SReza.Sabdar@Sun.COM 	struct full_dir_info *t_dir_info, *p_dir_info;
6457917SReza.Sabdar@Sun.COM 	struct stat64 ret_attr; /* attributes of current file name */
6467917SReza.Sabdar@Sun.COM 	fs_fhandle_t ret_fh;
6477917SReza.Sabdar@Sun.COM 	char *first_name; /* where the first name is located */
6487917SReza.Sabdar@Sun.COM 	char *dname;
6497917SReza.Sabdar@Sun.COM 	int erc;
6507917SReza.Sabdar@Sun.COM 	int retval;
6517917SReza.Sabdar@Sun.COM 	cstack_t *stk;
6527917SReza.Sabdar@Sun.COM 	unsigned long fileid;
6537917SReza.Sabdar@Sun.COM 	tlm_acls_t tlm_acls;
6547917SReza.Sabdar@Sun.COM 	int dname_size;
6557917SReza.Sabdar@Sun.COM 	longlong_t fsize;
6567917SReza.Sabdar@Sun.COM 	bk_selector_t bks;
6577917SReza.Sabdar@Sun.COM 	tlm_cmd_t *local_commands;
6587917SReza.Sabdar@Sun.COM 	long 	dpos;
6597917SReza.Sabdar@Sun.COM 
6607917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "nr_chkpnted %d nr_ldate: %u bk_path: \"%s\"",
6617917SReza.Sabdar@Sun.COM 	    NLP_ISCHKPNTED(nlp), nlp->nlp_ldate, bk_path);
6627917SReza.Sabdar@Sun.COM 
6637917SReza.Sabdar@Sun.COM 	/* Get every name in this directory */
6647917SReza.Sabdar@Sun.COM 	dname = ndmp_malloc(TLM_MAX_PATH_NAME);
6657917SReza.Sabdar@Sun.COM 	if (dname == NULL)
6667917SReza.Sabdar@Sun.COM 		return (-ENOMEM);
6677917SReza.Sabdar@Sun.COM 
6687917SReza.Sabdar@Sun.COM 	local_commands = commands->tcs_command;
6697917SReza.Sabdar@Sun.COM 	retval = 0;
6707917SReza.Sabdar@Sun.COM 	(void) memset(&bks, 0, sizeof (bks));
6717917SReza.Sabdar@Sun.COM 	bks.bs_cookie = (void *)nlp;
6727917SReza.Sabdar@Sun.COM 	bks.bs_level = nlp->nlp_clevel;
6737917SReza.Sabdar@Sun.COM 	bks.bs_ldate = nlp->nlp_ldate;
6747917SReza.Sabdar@Sun.COM 	bks.bs_fn = timecmp;
6757917SReza.Sabdar@Sun.COM 
6767917SReza.Sabdar@Sun.COM 	/*
6777917SReza.Sabdar@Sun.COM 	 * should we skip the whole thing?
6787917SReza.Sabdar@Sun.COM 	 */
6797917SReza.Sabdar@Sun.COM 	if (tlm_is_excluded("", bk_path, np->nr_excls)) {
6807917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "%s excluded", bk_path);
6817917SReza.Sabdar@Sun.COM 		free(dname);
6827917SReza.Sabdar@Sun.COM 		return (0);
6837917SReza.Sabdar@Sun.COM 	}
6847917SReza.Sabdar@Sun.COM 
6857917SReza.Sabdar@Sun.COM 	/*
6867917SReza.Sabdar@Sun.COM 	 * Search for the top-level file-directory
6877917SReza.Sabdar@Sun.COM 	 */
6887917SReza.Sabdar@Sun.COM 	if (NLP_ISCHKPNTED(nlp)) {
6897917SReza.Sabdar@Sun.COM 		first_name = np->nr_chkp_nm;
6907917SReza.Sabdar@Sun.COM 		(void) strlcpy(first_name, bk_path, TLM_MAX_PATH_NAME);
6917917SReza.Sabdar@Sun.COM 	} else {
6927917SReza.Sabdar@Sun.COM 		first_name = tlm_build_snapshot_name(bk_path, np->nr_chkp_nm,
6937917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_job_name);
6947917SReza.Sabdar@Sun.COM 	}
6957917SReza.Sabdar@Sun.COM 
6967917SReza.Sabdar@Sun.COM 	(void) memset(&ret_fh, 0, sizeof (ret_fh));
6977917SReza.Sabdar@Sun.COM 	erc = fs_getstat(first_name, &ret_fh, &ret_attr, NULL);
6987917SReza.Sabdar@Sun.COM 	if (erc != 0) {
6997917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Path %s not found.", first_name);
7007917SReza.Sabdar@Sun.COM 		free(dname);
7017917SReza.Sabdar@Sun.COM 		return (-EINVAL);
7027917SReza.Sabdar@Sun.COM 	}
7037917SReza.Sabdar@Sun.COM 
7047917SReza.Sabdar@Sun.COM 	if ((stk = cstack_new()) == NULL) {
7057917SReza.Sabdar@Sun.COM 		free(dname);
7067917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_new failed");
7077917SReza.Sabdar@Sun.COM 		return (-ENOMEM);
7087917SReza.Sabdar@Sun.COM 	}
7097917SReza.Sabdar@Sun.COM 	(void) strlcpy(dir_info.fd_dir_name, first_name, TLM_MAX_PATH_NAME);
7107917SReza.Sabdar@Sun.COM 	(void) memcpy(&dir_info.fd_dir_fh, &ret_fh, sizeof (fs_fhandle_t));
7117917SReza.Sabdar@Sun.COM 	p_dir_info = dup_dir_info(&dir_info);
7127917SReza.Sabdar@Sun.COM 
7137917SReza.Sabdar@Sun.COM 	/*
7147917SReza.Sabdar@Sun.COM 	 * Push the first name onto the stack so that we can pop it back
7157917SReza.Sabdar@Sun.COM 	 * off as part of the normal cycle
7167917SReza.Sabdar@Sun.COM 	 */
7177917SReza.Sabdar@Sun.COM 	if (cstack_push(stk, p_dir_info, 0)) {
7187917SReza.Sabdar@Sun.COM 		free(dname);
7197917SReza.Sabdar@Sun.COM 		free(p_dir_info);
7207917SReza.Sabdar@Sun.COM 		cstack_delete(stk);
7217917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_push failed");
7227917SReza.Sabdar@Sun.COM 		return (-ENOMEM);
7237917SReza.Sabdar@Sun.COM 	}
7247917SReza.Sabdar@Sun.COM 
7257917SReza.Sabdar@Sun.COM 	(void) memset(&tlm_acls, 0, sizeof (tlm_acls));
7267917SReza.Sabdar@Sun.COM 	/*
7277917SReza.Sabdar@Sun.COM 	 * Did NDMP create a checkpoint?
7287917SReza.Sabdar@Sun.COM 	 */
7297917SReza.Sabdar@Sun.COM 	if (NLP_ISCHKPNTED(nlp) || fs_is_rdonly(bk_path)) {
7307917SReza.Sabdar@Sun.COM 		tlm_acls.acl_checkpointed = FALSE;
7317917SReza.Sabdar@Sun.COM 	} else {
7327917SReza.Sabdar@Sun.COM 		/* Use the checkpoint created by NDMP */
7337917SReza.Sabdar@Sun.COM 		tlm_acls.acl_checkpointed = TRUE;
7347917SReza.Sabdar@Sun.COM 	}
7357917SReza.Sabdar@Sun.COM 
7367917SReza.Sabdar@Sun.COM 	/*
7377917SReza.Sabdar@Sun.COM 	 * This is level-backup.  It never resets the archive bit.
7387917SReza.Sabdar@Sun.COM 	 */
7397917SReza.Sabdar@Sun.COM 	tlm_acls.acl_clear_archive = FALSE;
7407917SReza.Sabdar@Sun.COM 
7417917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "acls.chkpnt: %c acls.clear_arcbit: %c",
7427917SReza.Sabdar@Sun.COM 	    NDMP_YORN(tlm_acls.acl_checkpointed),
7437917SReza.Sabdar@Sun.COM 	    NDMP_YORN(tlm_acls.acl_clear_archive));
7447917SReza.Sabdar@Sun.COM 
7457917SReza.Sabdar@Sun.COM 	while (commands->tcs_reader == TLM_BACKUP_RUN &&
7467917SReza.Sabdar@Sun.COM 	    local_commands->tc_reader == TLM_BACKUP_RUN &&
7477917SReza.Sabdar@Sun.COM 	    cstack_pop(stk, (void **)&p_dir_info, 0) == 0) {
7487917SReza.Sabdar@Sun.COM 
7497917SReza.Sabdar@Sun.COM 		if (NLP_ISCHKPNTED(nlp))
7507917SReza.Sabdar@Sun.COM 			(void) strlcpy(np->nr_unchkp_nm,
7517917SReza.Sabdar@Sun.COM 			    p_dir_info->fd_dir_name, TLM_MAX_PATH_NAME);
7527917SReza.Sabdar@Sun.COM 		else
7537917SReza.Sabdar@Sun.COM 			(void) tlm_remove_checkpoint(p_dir_info->fd_dir_name,
7547917SReza.Sabdar@Sun.COM 			    np->nr_unchkp_nm);
7557917SReza.Sabdar@Sun.COM 
7567917SReza.Sabdar@Sun.COM 		(void) backup_dir(np->nr_unchkp_nm, &tlm_acls, local_commands,
7577917SReza.Sabdar@Sun.COM 		    job_stats, &bks);
7587917SReza.Sabdar@Sun.COM 
7597917SReza.Sabdar@Sun.COM 
7607917SReza.Sabdar@Sun.COM 		while (commands->tcs_reader == TLM_BACKUP_RUN &&
7617917SReza.Sabdar@Sun.COM 		    local_commands->tc_reader == TLM_BACKUP_RUN) {
7627917SReza.Sabdar@Sun.COM 
7637917SReza.Sabdar@Sun.COM 			dname_size = TLM_MAX_PATH_NAME - 1;
7647917SReza.Sabdar@Sun.COM 
7657917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
7667917SReza.Sabdar@Sun.COM 			    "dir_name: %s", p_dir_info->fd_dir_name);
7677917SReza.Sabdar@Sun.COM 
7687917SReza.Sabdar@Sun.COM 			(void) memset(&ret_fh, 0, sizeof (ret_fh));
7697917SReza.Sabdar@Sun.COM 			erc = fs_readdir(&p_dir_info->fd_dir_fh,
7707917SReza.Sabdar@Sun.COM 			    p_dir_info->fd_dir_name, &dpos,
7717917SReza.Sabdar@Sun.COM 			    dname, &dname_size, &ret_fh, &ret_attr,
7727917SReza.Sabdar@Sun.COM 			    NULL);
7737917SReza.Sabdar@Sun.COM 			if (erc == 0) {
7747917SReza.Sabdar@Sun.COM 				fileid = ret_fh.fh_fid;
7757917SReza.Sabdar@Sun.COM 			} else {
7767917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
7777917SReza.Sabdar@Sun.COM 				    "Filesystem readdir in [%s]",
7787917SReza.Sabdar@Sun.COM 				    p_dir_info->fd_dir_name);
7797917SReza.Sabdar@Sun.COM 				retval = -ENOENT;
7807917SReza.Sabdar@Sun.COM 				break;
7817917SReza.Sabdar@Sun.COM 			}
7827917SReza.Sabdar@Sun.COM 
7837917SReza.Sabdar@Sun.COM 			/* an empty name size marks the end of the list */
7847917SReza.Sabdar@Sun.COM 			if (dname_size == 0)
7857917SReza.Sabdar@Sun.COM 				break;
7867917SReza.Sabdar@Sun.COM 			dname[dname_size] = '\0';
7877917SReza.Sabdar@Sun.COM 
7887917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "dname: \"%s\"", dname);
7897917SReza.Sabdar@Sun.COM 
7907917SReza.Sabdar@Sun.COM 			/*
7917917SReza.Sabdar@Sun.COM 			 * If name refers to a directory, push its file
7927917SReza.Sabdar@Sun.COM 			 *   handle onto the stack  (skip "." and "..").
7937917SReza.Sabdar@Sun.COM 			 */
7947917SReza.Sabdar@Sun.COM 			if (rootfs_dot_or_dotdot(dname)) {
7957917SReza.Sabdar@Sun.COM 				fileid = 0;
7967917SReza.Sabdar@Sun.COM 				continue;
7977917SReza.Sabdar@Sun.COM 			}
7987917SReza.Sabdar@Sun.COM 
7997917SReza.Sabdar@Sun.COM 			/*
8007917SReza.Sabdar@Sun.COM 			 * Skip the:
8017917SReza.Sabdar@Sun.COM 			 * non-dir entries which should not be backed up
8027917SReza.Sabdar@Sun.COM 			 * Or
8037917SReza.Sabdar@Sun.COM 			 * dir-type entries which have have nothing under
8047917SReza.Sabdar@Sun.COM 			 * their hierarchy to be backed up.
8057917SReza.Sabdar@Sun.COM 			 */
8067917SReza.Sabdar@Sun.COM 			if (!dbm_getone(nlp->nlp_bkmap, (u_longlong_t)fileid)) {
8077917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "Skipping %s/%s",
8087917SReza.Sabdar@Sun.COM 				    p_dir_info->fd_dir_name, dname);
8097917SReza.Sabdar@Sun.COM 				fileid = 0;
8107917SReza.Sabdar@Sun.COM 				continue;
8117917SReza.Sabdar@Sun.COM 			}
8127917SReza.Sabdar@Sun.COM 
8137917SReza.Sabdar@Sun.COM 			if (tlm_is_excluded(np->nr_unchkp_nm, dname,
8147917SReza.Sabdar@Sun.COM 			    np->nr_excls)) {
8157917SReza.Sabdar@Sun.COM 				fileid = 0;
8167917SReza.Sabdar@Sun.COM 				continue;
8177917SReza.Sabdar@Sun.COM 			}
8187917SReza.Sabdar@Sun.COM 			if (S_ISDIR(ret_attr.st_mode)) {
8197917SReza.Sabdar@Sun.COM 				/*
8207917SReza.Sabdar@Sun.COM 				 * only directories get pushed onto this stack,
8217917SReza.Sabdar@Sun.COM 				 * so we do not have to test for regular files.
8227917SReza.Sabdar@Sun.COM 				 */
8237917SReza.Sabdar@Sun.COM 				t_dir_info = tlm_new_dir_info(&ret_fh,
8247917SReza.Sabdar@Sun.COM 				    p_dir_info->fd_dir_name, dname);
8257917SReza.Sabdar@Sun.COM 				if (t_dir_info == NULL) {
8267917SReza.Sabdar@Sun.COM 					NDMP_LOG(LOG_DEBUG,
8277917SReza.Sabdar@Sun.COM 					    "While backing up [%s][%s]",
8287917SReza.Sabdar@Sun.COM 					    p_dir_info->fd_dir_name, dname);
8297917SReza.Sabdar@Sun.COM 				} else if (cstack_push(stk, t_dir_info,
8307917SReza.Sabdar@Sun.COM 				    0) != 0) {
8317917SReza.Sabdar@Sun.COM 					NDMP_LOG(LOG_DEBUG,
8327917SReza.Sabdar@Sun.COM 					    "No enough memory stack_push");
8337917SReza.Sabdar@Sun.COM 					retval = -ENOMEM;
8347917SReza.Sabdar@Sun.COM 					break;
8357917SReza.Sabdar@Sun.COM 				}
8367917SReza.Sabdar@Sun.COM 			} else if (S_ISREG(ret_attr.st_mode) ||
8377917SReza.Sabdar@Sun.COM 			    S_ISLNK(ret_attr.st_mode)) {
8387917SReza.Sabdar@Sun.COM 
8397917SReza.Sabdar@Sun.COM 				fsize = backup_file(np->nr_unchkp_nm, dname,
8407917SReza.Sabdar@Sun.COM 				    &tlm_acls, commands, local_commands,
8417917SReza.Sabdar@Sun.COM 				    job_stats, &bks);
8427917SReza.Sabdar@Sun.COM 
8437917SReza.Sabdar@Sun.COM 				if (fsize >= 0) {
8447917SReza.Sabdar@Sun.COM 					job_stats->js_files_so_far++;
8457917SReza.Sabdar@Sun.COM 					job_stats->js_bytes_total += fsize;
8467917SReza.Sabdar@Sun.COM 				} else
8477917SReza.Sabdar@Sun.COM 					job_stats->js_errors++;
8487917SReza.Sabdar@Sun.COM 				fileid = 0;
8497917SReza.Sabdar@Sun.COM 			}
8507917SReza.Sabdar@Sun.COM 		}
8517917SReza.Sabdar@Sun.COM 		fileid = 0;
8527917SReza.Sabdar@Sun.COM 		free(p_dir_info);
8537917SReza.Sabdar@Sun.COM 		if (retval != 0)
8547917SReza.Sabdar@Sun.COM 			break;
8557917SReza.Sabdar@Sun.COM 	}
8567917SReza.Sabdar@Sun.COM 
8577917SReza.Sabdar@Sun.COM 	free(dname);
8587917SReza.Sabdar@Sun.COM 
8597917SReza.Sabdar@Sun.COM 	while (cstack_pop(stk, (void **)&p_dir_info, 0) == 0) {
8607917SReza.Sabdar@Sun.COM 		free(p_dir_info);
8617917SReza.Sabdar@Sun.COM 	}
8627917SReza.Sabdar@Sun.COM 
8637917SReza.Sabdar@Sun.COM 	cstack_delete(stk);
8647917SReza.Sabdar@Sun.COM 	return (retval);
8657917SReza.Sabdar@Sun.COM }
8667917SReza.Sabdar@Sun.COM 
8677917SReza.Sabdar@Sun.COM 
8687917SReza.Sabdar@Sun.COM /*
8697917SReza.Sabdar@Sun.COM  * free_paths
8707917SReza.Sabdar@Sun.COM  *
8717917SReza.Sabdar@Sun.COM  * Free the path names
8727917SReza.Sabdar@Sun.COM  */
8737917SReza.Sabdar@Sun.COM static void
8747917SReza.Sabdar@Sun.COM free_paths(ndmp_run_args_t *np)
8757917SReza.Sabdar@Sun.COM {
8767917SReza.Sabdar@Sun.COM 	free(np->nr_chkp_nm);
8777917SReza.Sabdar@Sun.COM 	free(np->nr_unchkp_nm);
8787917SReza.Sabdar@Sun.COM 	free(np->nr_excls);
8797917SReza.Sabdar@Sun.COM }
8807917SReza.Sabdar@Sun.COM 
8817917SReza.Sabdar@Sun.COM 
8827917SReza.Sabdar@Sun.COM /*
8837917SReza.Sabdar@Sun.COM  * malloc_paths
8847917SReza.Sabdar@Sun.COM  *
8857917SReza.Sabdar@Sun.COM  * Allocate the path names (direct and checkpointed paths)
8867917SReza.Sabdar@Sun.COM  */
8877917SReza.Sabdar@Sun.COM static boolean_t
8887917SReza.Sabdar@Sun.COM malloc_paths(ndmp_run_args_t *np)
8897917SReza.Sabdar@Sun.COM {
8907917SReza.Sabdar@Sun.COM 	boolean_t rv;
8917917SReza.Sabdar@Sun.COM 
8927917SReza.Sabdar@Sun.COM 	rv = TRUE;
8937917SReza.Sabdar@Sun.COM 	np->nr_chkp_nm = ndmp_malloc(TLM_MAX_PATH_NAME);
8947917SReza.Sabdar@Sun.COM 	np->nr_unchkp_nm = ndmp_malloc(TLM_MAX_PATH_NAME);
8957917SReza.Sabdar@Sun.COM 	if (!np->nr_chkp_nm || !np->nr_unchkp_nm) {
8967917SReza.Sabdar@Sun.COM 		free_paths(np);
8977917SReza.Sabdar@Sun.COM 		rv = FALSE;
8987917SReza.Sabdar@Sun.COM 	} else if ((np->nr_excls = ndmpd_make_exc_list()) == NULL) {
8997917SReza.Sabdar@Sun.COM 		free_paths(np);
9007917SReza.Sabdar@Sun.COM 		rv = FALSE;
9017917SReza.Sabdar@Sun.COM 	}
9027917SReza.Sabdar@Sun.COM 	return (rv);
9037917SReza.Sabdar@Sun.COM }
9047917SReza.Sabdar@Sun.COM 
9057917SReza.Sabdar@Sun.COM 
9067917SReza.Sabdar@Sun.COM /*
9077917SReza.Sabdar@Sun.COM  * ndmp_backup_reader
9087917SReza.Sabdar@Sun.COM  *
9097917SReza.Sabdar@Sun.COM  * Backup reader thread which uses backup_work to read and TAR
9107917SReza.Sabdar@Sun.COM  * the files/dirs to be backed up (V2 only)
9117917SReza.Sabdar@Sun.COM  */
9127917SReza.Sabdar@Sun.COM static int
9137917SReza.Sabdar@Sun.COM ndmp_backup_reader(tlm_commands_t *commands, ndmp_lbr_params_t *nlp,
9147917SReza.Sabdar@Sun.COM     char *job_name)
9157917SReza.Sabdar@Sun.COM {
9167917SReza.Sabdar@Sun.COM 	int retval;
9177917SReza.Sabdar@Sun.COM 	ndmp_run_args_t np;
9187917SReza.Sabdar@Sun.COM 	tlm_job_stats_t *job_stats;
9197917SReza.Sabdar@Sun.COM 	tlm_cmd_t *local_commands;
9207917SReza.Sabdar@Sun.COM 
9217917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "bk_path: \"%s\"", nlp->nlp_backup_path);
9227917SReza.Sabdar@Sun.COM 
9237917SReza.Sabdar@Sun.COM 	local_commands = commands->tcs_command;
9247917SReza.Sabdar@Sun.COM 	(void) memset(&np, 0, sizeof (np));
9257917SReza.Sabdar@Sun.COM 	if (!malloc_paths(&np))
9267917SReza.Sabdar@Sun.COM 		return (-1);
9277917SReza.Sabdar@Sun.COM 	local_commands->tc_ref++;
9287917SReza.Sabdar@Sun.COM 	commands->tcs_reader_count++;
9297917SReza.Sabdar@Sun.COM 
9307917SReza.Sabdar@Sun.COM 	job_stats = tlm_ref_job_stats(job_name);
9317917SReza.Sabdar@Sun.COM 
9327917SReza.Sabdar@Sun.COM 	retval = backup_work(nlp->nlp_backup_path, job_stats, &np,
9337917SReza.Sabdar@Sun.COM 	    commands, nlp);
9347917SReza.Sabdar@Sun.COM 	write_tar_eof(local_commands);
9357917SReza.Sabdar@Sun.COM 
9367917SReza.Sabdar@Sun.COM 	commands->tcs_reader_count--;
9377917SReza.Sabdar@Sun.COM 	local_commands->tc_writer = TLM_STOP;
9387917SReza.Sabdar@Sun.COM 	tlm_release_reader_writer_ipc(local_commands);
9397917SReza.Sabdar@Sun.COM 	tlm_un_ref_job_stats(job_name);
9407917SReza.Sabdar@Sun.COM 
9417917SReza.Sabdar@Sun.COM 	free_paths(&np);
9427917SReza.Sabdar@Sun.COM 	return (retval);
9437917SReza.Sabdar@Sun.COM 
9447917SReza.Sabdar@Sun.COM }
9457917SReza.Sabdar@Sun.COM 
9467917SReza.Sabdar@Sun.COM 
9477917SReza.Sabdar@Sun.COM /*
9487917SReza.Sabdar@Sun.COM  * ndmp_tar_writer
9497917SReza.Sabdar@Sun.COM  *
9507917SReza.Sabdar@Sun.COM  * The backup writer thread that writes the TAR records to the
9517917SReza.Sabdar@Sun.COM  * tape media (V2 only)
9527917SReza.Sabdar@Sun.COM  */
9537917SReza.Sabdar@Sun.COM int
9547917SReza.Sabdar@Sun.COM ndmp_tar_writer(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
9557917SReza.Sabdar@Sun.COM     tlm_commands_t *cmds)
9567917SReza.Sabdar@Sun.COM {
9577917SReza.Sabdar@Sun.COM 	int bidx, nw;
9587917SReza.Sabdar@Sun.COM 	int err;
9597917SReza.Sabdar@Sun.COM 	tlm_buffer_t *buf;
9607917SReza.Sabdar@Sun.COM 	tlm_buffers_t *bufs;
9617917SReza.Sabdar@Sun.COM 	tlm_cmd_t *lcmd;	/* Local command */
9627917SReza.Sabdar@Sun.COM 
9637917SReza.Sabdar@Sun.COM 	err = 0;
9647917SReza.Sabdar@Sun.COM 	if (session == NULL) {
9657917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "session == NULL");
9667917SReza.Sabdar@Sun.COM 		err = -1;
9677917SReza.Sabdar@Sun.COM 	} else if (mod_params == NULL) {
9687917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "mod_params == NULL");
9697917SReza.Sabdar@Sun.COM 		err = -1;
9707917SReza.Sabdar@Sun.COM 	} else if (cmds == NULL) {
9717917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
9727917SReza.Sabdar@Sun.COM 		err = -1;
9737917SReza.Sabdar@Sun.COM 	}
9747917SReza.Sabdar@Sun.COM 
9757917SReza.Sabdar@Sun.COM 	if (err != 0)
9767917SReza.Sabdar@Sun.COM 		return (err);
9777917SReza.Sabdar@Sun.COM 
9787917SReza.Sabdar@Sun.COM 	lcmd = cmds->tcs_command;
9797917SReza.Sabdar@Sun.COM 	bufs = lcmd->tc_buffers;
9807917SReza.Sabdar@Sun.COM 
9817917SReza.Sabdar@Sun.COM 	lcmd->tc_ref++;
9827917SReza.Sabdar@Sun.COM 	cmds->tcs_writer_count++;
9837917SReza.Sabdar@Sun.COM 
9847917SReza.Sabdar@Sun.COM 	nw = 0;
9857917SReza.Sabdar@Sun.COM 	buf = tlm_buffer_out_buf(bufs, &bidx);
9867917SReza.Sabdar@Sun.COM 	while (cmds->tcs_writer != (int)TLM_ABORT &&
9877917SReza.Sabdar@Sun.COM 	    lcmd->tc_writer != (int)TLM_ABORT) {
9887917SReza.Sabdar@Sun.COM 		if (buf->tb_full) {
9897917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "w%d", bidx);
9907917SReza.Sabdar@Sun.COM 
9917917SReza.Sabdar@Sun.COM 			if (MOD_WRITE(mod_params, buf->tb_buffer_data,
9927917SReza.Sabdar@Sun.COM 			    buf->tb_buffer_size) != 0) {
9937917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
9947917SReza.Sabdar@Sun.COM 				    "Writing buffer %d, pos: %lld",
9957917SReza.Sabdar@Sun.COM 				    bidx, session->ns_mover.md_position);
9967917SReza.Sabdar@Sun.COM 				err = -1;
9977917SReza.Sabdar@Sun.COM 				break;
9987917SReza.Sabdar@Sun.COM 			}
9997917SReza.Sabdar@Sun.COM 
10007917SReza.Sabdar@Sun.COM 			tlm_buffer_mark_empty(buf);
10017917SReza.Sabdar@Sun.COM 			(void) tlm_buffer_advance_out_idx(bufs);
10027917SReza.Sabdar@Sun.COM 			buf = tlm_buffer_out_buf(bufs, &bidx);
10037917SReza.Sabdar@Sun.COM 			tlm_buffer_release_out_buf(bufs);
10047917SReza.Sabdar@Sun.COM 			nw++;
10057917SReza.Sabdar@Sun.COM 		} else {
10067917SReza.Sabdar@Sun.COM 			if (lcmd->tc_writer != TLM_BACKUP_RUN) {
10077917SReza.Sabdar@Sun.COM 				/* No more data is comming; time to exit. */
10087917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
10097917SReza.Sabdar@Sun.COM 				    "tc_writer!=TLM_BACKUP_RUN; time to exit");
10107917SReza.Sabdar@Sun.COM 				break;
10117917SReza.Sabdar@Sun.COM 			} else {
10127917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "W%d", bidx);
1013*8800SReza.Sabdar@Sun.COM 				tlm_buffer_in_buf_timed_wait(bufs, 100);
10147917SReza.Sabdar@Sun.COM 			}
10157917SReza.Sabdar@Sun.COM 		}
10167917SReza.Sabdar@Sun.COM 	}
10177917SReza.Sabdar@Sun.COM 
10187917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "nw: %d", nw);
10197917SReza.Sabdar@Sun.COM 	if (cmds->tcs_writer != (int)TLM_ABORT) {
10207917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "tcs_writer != TLM_ABORT");
10217917SReza.Sabdar@Sun.COM 	} else {
10227917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "tcs_writer == TLM_ABORT");
10237917SReza.Sabdar@Sun.COM 	}
10247917SReza.Sabdar@Sun.COM 
10257917SReza.Sabdar@Sun.COM 	if (lcmd->tc_writer != (int)TLM_ABORT) {
10267917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "tc_writer != TLM_ABORT");
10277917SReza.Sabdar@Sun.COM 	} else {
10287917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "tc_writer == TLM_ABORT");
10297917SReza.Sabdar@Sun.COM 	}
10307917SReza.Sabdar@Sun.COM 	cmds->tcs_writer_count--;
10317917SReza.Sabdar@Sun.COM 	lcmd->tc_reader = TLM_STOP;
10327917SReza.Sabdar@Sun.COM 	lcmd->tc_ref--;
10337917SReza.Sabdar@Sun.COM 
10347917SReza.Sabdar@Sun.COM 	return (err);
10357917SReza.Sabdar@Sun.COM }
10367917SReza.Sabdar@Sun.COM 
10377917SReza.Sabdar@Sun.COM 
10387917SReza.Sabdar@Sun.COM /*
10397917SReza.Sabdar@Sun.COM  * read_one_buf
10407917SReza.Sabdar@Sun.COM  *
10417917SReza.Sabdar@Sun.COM  * Read one buffer from the tape
10427917SReza.Sabdar@Sun.COM  */
10437917SReza.Sabdar@Sun.COM static int
10447917SReza.Sabdar@Sun.COM read_one_buf(ndmpd_module_params_t *mod_params, tlm_buffers_t *bufs,
10457917SReza.Sabdar@Sun.COM     tlm_buffer_t *buf)
10467917SReza.Sabdar@Sun.COM {
10477917SReza.Sabdar@Sun.COM 	int rv;
10487917SReza.Sabdar@Sun.COM 
10497917SReza.Sabdar@Sun.COM 	if ((rv = MOD_READ(mod_params, buf->tb_buffer_data,
10507917SReza.Sabdar@Sun.COM 	    bufs->tbs_data_transfer_size)) == 0) {
10517917SReza.Sabdar@Sun.COM 		buf->tb_eof = buf->tb_eot = FALSE;
10527917SReza.Sabdar@Sun.COM 		buf->tb_errno = 0;
10537917SReza.Sabdar@Sun.COM 		buf->tb_buffer_size = bufs->tbs_data_transfer_size;
10547917SReza.Sabdar@Sun.COM 		buf->tb_buffer_spot = 0;
10557917SReza.Sabdar@Sun.COM 		buf->tb_full = TRUE;
10567917SReza.Sabdar@Sun.COM 		(void) tlm_buffer_advance_in_idx(bufs);
10577917SReza.Sabdar@Sun.COM 	}
10587917SReza.Sabdar@Sun.COM 
10597917SReza.Sabdar@Sun.COM 	return (rv);
10607917SReza.Sabdar@Sun.COM }
10617917SReza.Sabdar@Sun.COM 
10627917SReza.Sabdar@Sun.COM 
10637917SReza.Sabdar@Sun.COM /*
10647917SReza.Sabdar@Sun.COM  * ndmp_tar_reader
10657917SReza.Sabdar@Sun.COM  *
10667917SReza.Sabdar@Sun.COM  * NDMP Tar reader thread. This threads keep reading the tar
10677917SReza.Sabdar@Sun.COM  * file from the tape and wakes up the consumer thread to extract
10687917SReza.Sabdar@Sun.COM  * it on the disk
10697917SReza.Sabdar@Sun.COM  */
10707917SReza.Sabdar@Sun.COM int
10717917SReza.Sabdar@Sun.COM ndmp_tar_reader(ndmp_tar_reader_arg_t *argp)
10727917SReza.Sabdar@Sun.COM {
10737917SReza.Sabdar@Sun.COM 	int bidx;
10747917SReza.Sabdar@Sun.COM 	int err;
10757917SReza.Sabdar@Sun.COM 	tlm_buffer_t *buf;
10767917SReza.Sabdar@Sun.COM 	tlm_buffers_t *bufs;
10777917SReza.Sabdar@Sun.COM 	tlm_cmd_t *lcmd;	/* Local command */
10787917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session;
10797917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *mod_params;
10807917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
10817917SReza.Sabdar@Sun.COM 
10827917SReza.Sabdar@Sun.COM 	if (!argp)
10837917SReza.Sabdar@Sun.COM 		return (-1);
10847917SReza.Sabdar@Sun.COM 
10857917SReza.Sabdar@Sun.COM 	session = argp->tr_session;
10867917SReza.Sabdar@Sun.COM 	mod_params = argp->tr_mod_params;
10877917SReza.Sabdar@Sun.COM 	cmds = argp->tr_cmds;
10887917SReza.Sabdar@Sun.COM 
10897917SReza.Sabdar@Sun.COM 	err = 0;
10907917SReza.Sabdar@Sun.COM 	if (session == NULL) {
10917917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "session == NULL");
10927917SReza.Sabdar@Sun.COM 		err = -1;
10937917SReza.Sabdar@Sun.COM 	} else if (cmds == NULL) {
10947917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
10957917SReza.Sabdar@Sun.COM 		err = -1;
10967917SReza.Sabdar@Sun.COM 	}
10977917SReza.Sabdar@Sun.COM 
10987917SReza.Sabdar@Sun.COM 	if (err != 0) {
10997917SReza.Sabdar@Sun.COM 		tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
11007917SReza.Sabdar@Sun.COM 		return (err);
11017917SReza.Sabdar@Sun.COM 	}
11027917SReza.Sabdar@Sun.COM 
11037917SReza.Sabdar@Sun.COM 	lcmd = cmds->tcs_command;
11047917SReza.Sabdar@Sun.COM 	bufs = lcmd->tc_buffers;
11057917SReza.Sabdar@Sun.COM 
11067917SReza.Sabdar@Sun.COM 	lcmd->tc_ref++;
11077917SReza.Sabdar@Sun.COM 	cmds->tcs_reader_count++;
11087917SReza.Sabdar@Sun.COM 
11097917SReza.Sabdar@Sun.COM 	/*
11107917SReza.Sabdar@Sun.COM 	 * Synchronize with our parent thread.
11117917SReza.Sabdar@Sun.COM 	 */
11127917SReza.Sabdar@Sun.COM 	tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
11137917SReza.Sabdar@Sun.COM 
11147917SReza.Sabdar@Sun.COM 	buf = tlm_buffer_in_buf(bufs, &bidx);
11157917SReza.Sabdar@Sun.COM 	while (cmds->tcs_reader == TLM_RESTORE_RUN &&
11167917SReza.Sabdar@Sun.COM 	    lcmd->tc_reader == TLM_RESTORE_RUN) {
11177917SReza.Sabdar@Sun.COM 
11187917SReza.Sabdar@Sun.COM 		if (buf->tb_full) {
11197917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "R%d", bidx);
11207917SReza.Sabdar@Sun.COM 			/*
11217917SReza.Sabdar@Sun.COM 			 * The buffer is still full, wait for the consumer
11227917SReza.Sabdar@Sun.COM 			 * thread to use it.
11237917SReza.Sabdar@Sun.COM 			 */
11247917SReza.Sabdar@Sun.COM 			tlm_buffer_out_buf_timed_wait(bufs, 100);
11257917SReza.Sabdar@Sun.COM 			buf = tlm_buffer_in_buf(bufs, NULL);
11267917SReza.Sabdar@Sun.COM 		} else {
11277917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "r%d", bidx);
11287917SReza.Sabdar@Sun.COM 
11297917SReza.Sabdar@Sun.COM 			err = read_one_buf(mod_params, bufs, buf);
11307917SReza.Sabdar@Sun.COM 			if (err < 0) {
11317917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
11327917SReza.Sabdar@Sun.COM 				    "Reading buffer %d, pos: %lld",
11337917SReza.Sabdar@Sun.COM 				    bidx, session->ns_mover.md_position);
11347917SReza.Sabdar@Sun.COM 
11357917SReza.Sabdar@Sun.COM 				/* Force the writer to stop. */
11367917SReza.Sabdar@Sun.COM 				buf->tb_eot = buf->tb_eof = TRUE;
11377917SReza.Sabdar@Sun.COM 				break;
11387917SReza.Sabdar@Sun.COM 			} else if (err == 1) {
11397917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
11407917SReza.Sabdar@Sun.COM 				    "operation aborted or session terminated");
11417917SReza.Sabdar@Sun.COM 				err = 0;
11427917SReza.Sabdar@Sun.COM 				break;
11437917SReza.Sabdar@Sun.COM 			}
11447917SReza.Sabdar@Sun.COM 
11457917SReza.Sabdar@Sun.COM 			buf = tlm_buffer_in_buf(bufs, &bidx);
11467917SReza.Sabdar@Sun.COM 			tlm_buffer_release_in_buf(bufs);
11477917SReza.Sabdar@Sun.COM 		}
11487917SReza.Sabdar@Sun.COM 	}
11497917SReza.Sabdar@Sun.COM 
11507917SReza.Sabdar@Sun.COM 	/*
11517917SReza.Sabdar@Sun.COM 	 * If the consumer is waiting for us, wake it up so that it detects
11527917SReza.Sabdar@Sun.COM 	 * we're quiting.
11537917SReza.Sabdar@Sun.COM 	 */
11547917SReza.Sabdar@Sun.COM 	lcmd->tc_writer = TLM_STOP;
11557917SReza.Sabdar@Sun.COM 	tlm_buffer_release_in_buf(bufs);
11567917SReza.Sabdar@Sun.COM 	(void) usleep(1000);
11577917SReza.Sabdar@Sun.COM 
11587917SReza.Sabdar@Sun.COM 	/*
11597917SReza.Sabdar@Sun.COM 	 * Clean up.
11607917SReza.Sabdar@Sun.COM 	 */
11617917SReza.Sabdar@Sun.COM 	cmds->tcs_reader_count--;
11627917SReza.Sabdar@Sun.COM 	lcmd->tc_ref--;
11637917SReza.Sabdar@Sun.COM 	return (err);
11647917SReza.Sabdar@Sun.COM }
11657917SReza.Sabdar@Sun.COM 
11667917SReza.Sabdar@Sun.COM 
11677917SReza.Sabdar@Sun.COM /*
11687917SReza.Sabdar@Sun.COM  * ndmpd_tar_backup
11697917SReza.Sabdar@Sun.COM  *
11707917SReza.Sabdar@Sun.COM  * Check must have been done that backup work directory exists, before
11717917SReza.Sabdar@Sun.COM  * calling this function.
11727917SReza.Sabdar@Sun.COM  */
11737917SReza.Sabdar@Sun.COM static int
11747917SReza.Sabdar@Sun.COM ndmpd_tar_backup(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
11757917SReza.Sabdar@Sun.COM     ndmp_lbr_params_t *nlp)
11767917SReza.Sabdar@Sun.COM {
11777917SReza.Sabdar@Sun.COM 	char jname[TLM_MAX_BACKUP_JOB_NAME];
11787917SReza.Sabdar@Sun.COM 	int err;
11797917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
11807917SReza.Sabdar@Sun.COM 
11817917SReza.Sabdar@Sun.COM 	if (mod_params->mp_operation != NDMP_DATA_OP_BACKUP) {
11827917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
11837917SReza.Sabdar@Sun.COM 		    "mod_params->mp_operation != NDMP_DATA_OP_BACKUP");
11847917SReza.Sabdar@Sun.COM 		err = -1;
11857917SReza.Sabdar@Sun.COM 	} else {
11867917SReza.Sabdar@Sun.COM 		if (ndmpd_mark_inodes_v2(session, nlp) != 0)
11877917SReza.Sabdar@Sun.COM 			err = -1;
11887917SReza.Sabdar@Sun.COM 		else if (ndmp_get_bk_dir_ino(nlp))
11897917SReza.Sabdar@Sun.COM 			err = -1;
11907917SReza.Sabdar@Sun.COM 		else
11917917SReza.Sabdar@Sun.COM 			err = 0;
11927917SReza.Sabdar@Sun.COM 	}
11937917SReza.Sabdar@Sun.COM 
11947917SReza.Sabdar@Sun.COM 	if (err != 0)
11957917SReza.Sabdar@Sun.COM 		return (err);
11967917SReza.Sabdar@Sun.COM 
11977917SReza.Sabdar@Sun.COM 	(void) ndmp_new_job_name(jname);
11987917SReza.Sabdar@Sun.COM 	if (backup_create_structs(session, jname) < 0)
11997917SReza.Sabdar@Sun.COM 		return (-1);
12007917SReza.Sabdar@Sun.COM 
12017917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_start_ltime = time(NULL);
12027917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
12037917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_chkpnt_time = nlp->nlp_cdate;
12047917SReza.Sabdar@Sun.COM 
12057917SReza.Sabdar@Sun.COM 	if (!session->ns_data.dd_abort) {
12067917SReza.Sabdar@Sun.COM 
12077917SReza.Sabdar@Sun.COM 		cmds = &nlp->nlp_cmds;
12087917SReza.Sabdar@Sun.COM 		cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN;
12097917SReza.Sabdar@Sun.COM 		cmds->tcs_command->tc_reader = TLM_BACKUP_RUN;
12107917SReza.Sabdar@Sun.COM 		cmds->tcs_command->tc_writer = TLM_BACKUP_RUN;
12117917SReza.Sabdar@Sun.COM 
12127917SReza.Sabdar@Sun.COM 		if (ndmp_write_utf8magic(cmds->tcs_command) < 0) {
12137917SReza.Sabdar@Sun.COM 			backup_release_structs(session);
12147917SReza.Sabdar@Sun.COM 			return (-1);
12157917SReza.Sabdar@Sun.COM 		}
12167917SReza.Sabdar@Sun.COM 
12177917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" started.",
12187917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path);
12197917SReza.Sabdar@Sun.COM 
12207917SReza.Sabdar@Sun.COM 		err = ndmp_backup_reader(cmds, nlp, jname);
12217917SReza.Sabdar@Sun.COM 		if (err != 0) {
12227917SReza.Sabdar@Sun.COM 			backup_release_structs(session);
12237917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "Launch ndmp_backup_reader: %s",
12247917SReza.Sabdar@Sun.COM 			    strerror(err));
12257917SReza.Sabdar@Sun.COM 			return (-1);
12267917SReza.Sabdar@Sun.COM 		}
12277917SReza.Sabdar@Sun.COM 
12287917SReza.Sabdar@Sun.COM 		/* Act as the writer thread. */
12297917SReza.Sabdar@Sun.COM 		err = ndmp_tar_writer(session, mod_params, cmds);
12307917SReza.Sabdar@Sun.COM 
12317917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat->js_stop_time = time(NULL);
12327917SReza.Sabdar@Sun.COM 
12337917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
12347917SReza.Sabdar@Sun.COM 		    "Runtime [%s] %llu bytes (%llu): %d seconds",
12357917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path, session->ns_mover.md_data_written,
12367917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_data_written,
12377917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_stop_time -
12387917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_start_ltime);
12397917SReza.Sabdar@Sun.COM 		MOD_LOG(mod_params,
12407917SReza.Sabdar@Sun.COM 		    "Runtime [%s] %llu bytes (%llu): %d seconds",
12417917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path, session->ns_mover.md_data_written,
12427917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_data_written,
12437917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_stop_time -
12447917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_start_ltime);
12457917SReza.Sabdar@Sun.COM 
12467917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_abort)
12477917SReza.Sabdar@Sun.COM 			err = -1;
12487917SReza.Sabdar@Sun.COM 
12497917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" finished. (%d)",
12507917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path, err);
12517917SReza.Sabdar@Sun.COM 	} else {
12527917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat->js_stop_time = time(NULL);
12537917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" aborted.",
12547917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path);
12557917SReza.Sabdar@Sun.COM 		err = 0;
12567917SReza.Sabdar@Sun.COM 	}
12577917SReza.Sabdar@Sun.COM 
12587917SReza.Sabdar@Sun.COM 	backup_release_structs(session);
12597917SReza.Sabdar@Sun.COM 	return (err);
12607917SReza.Sabdar@Sun.COM }
12617917SReza.Sabdar@Sun.COM 
12627917SReza.Sabdar@Sun.COM 
12637917SReza.Sabdar@Sun.COM /*
12647917SReza.Sabdar@Sun.COM  * ndmpd_tar_restore
12657917SReza.Sabdar@Sun.COM  *
12667917SReza.Sabdar@Sun.COM  * Restore function that launches TAR reader thread to read from the
12677917SReza.Sabdar@Sun.COM  * tape and writes the extracted files/dirs to the filesystem
12687917SReza.Sabdar@Sun.COM  */
12697917SReza.Sabdar@Sun.COM static int
12707917SReza.Sabdar@Sun.COM ndmpd_tar_restore(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
12717917SReza.Sabdar@Sun.COM     ndmp_lbr_params_t *nlp)
12727917SReza.Sabdar@Sun.COM {
12737917SReza.Sabdar@Sun.COM 	char jname[TLM_MAX_BACKUP_JOB_NAME];
12747917SReza.Sabdar@Sun.COM 	char *rspath;
12757917SReza.Sabdar@Sun.COM 	int err;
12767917SReza.Sabdar@Sun.COM 	tlm_commands_t *cmds;
12777917SReza.Sabdar@Sun.COM 	ndmp_tar_reader_arg_t arg;
12787917SReza.Sabdar@Sun.COM 	tlm_backup_restore_arg_t tlm_arg;
12797917SReza.Sabdar@Sun.COM 	ndmp_name *ent;
12807917SReza.Sabdar@Sun.COM 	pthread_t rdtp, wrtp;
12817917SReza.Sabdar@Sun.COM 	int i;
12827917SReza.Sabdar@Sun.COM 
12837917SReza.Sabdar@Sun.COM 	if (mod_params->mp_operation != NDMP_DATA_OP_RECOVER) {
12847917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
12857917SReza.Sabdar@Sun.COM 		    "mod_params->mp_operation != NDMP_DATA_OP_RECOVER");
12867917SReza.Sabdar@Sun.COM 		return (-1);
12877917SReza.Sabdar@Sun.COM 	}
12887917SReza.Sabdar@Sun.COM 
12897917SReza.Sabdar@Sun.COM 	if (nlp->nlp_restore_path[0] != '\0')
12907917SReza.Sabdar@Sun.COM 		rspath = nlp->nlp_restore_path;
12917917SReza.Sabdar@Sun.COM 	else if (nlp->nlp_restore_bk_path[0] != '\0')
12927917SReza.Sabdar@Sun.COM 		rspath = nlp->nlp_restore_bk_path;
12937917SReza.Sabdar@Sun.COM 	else
12947917SReza.Sabdar@Sun.COM 		rspath = "";
12957917SReza.Sabdar@Sun.COM 
12967917SReza.Sabdar@Sun.COM 	(void) ndmp_new_job_name(jname);
12977917SReza.Sabdar@Sun.COM 	if (restore_create_structs(session, jname) < 0)
12987917SReza.Sabdar@Sun.COM 		return (-1);
12997917SReza.Sabdar@Sun.COM 
13007917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_start_ltime = time(NULL);
13017917SReza.Sabdar@Sun.COM 	nlp->nlp_jstat->js_start_time = time(NULL);
13027917SReza.Sabdar@Sun.COM 
13037917SReza.Sabdar@Sun.COM 	if (!session->ns_data.dd_abort) {
13047917SReza.Sabdar@Sun.COM 		cmds = &nlp->nlp_cmds;
13057917SReza.Sabdar@Sun.COM 		cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
13067917SReza.Sabdar@Sun.COM 		cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
13077917SReza.Sabdar@Sun.COM 		cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
13087917SReza.Sabdar@Sun.COM 
13097917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" started.", rspath);
13107917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Restoring from %s tape(s).",
13117917SReza.Sabdar@Sun.COM 		    ndmp_data_get_mover_mode(session));
13127917SReza.Sabdar@Sun.COM 
13137917SReza.Sabdar@Sun.COM 		arg.tr_session = session;
13147917SReza.Sabdar@Sun.COM 		arg.tr_mod_params = mod_params;
13157917SReza.Sabdar@Sun.COM 		arg.tr_cmds = cmds;
13167917SReza.Sabdar@Sun.COM 
13177917SReza.Sabdar@Sun.COM 		err = pthread_create(&rdtp, NULL, (funct_t)ndmp_tar_reader,
13187917SReza.Sabdar@Sun.COM 		    (void *)&arg);
13197917SReza.Sabdar@Sun.COM 		if (err == 0) {
13207917SReza.Sabdar@Sun.COM 			tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
13217917SReza.Sabdar@Sun.COM 		} else {
13227917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "Launch ndmp_tar_reader: %m");
13237917SReza.Sabdar@Sun.COM 			return (-1);
13247917SReza.Sabdar@Sun.COM 		}
13257917SReza.Sabdar@Sun.COM 
13267917SReza.Sabdar@Sun.COM 		if (!ndmp_check_utf8magic(cmds->tcs_command)) {
13277917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "UTF8Magic not found!");
13287917SReza.Sabdar@Sun.COM 		} else {
13297917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "UTF8Magic found");
13307917SReza.Sabdar@Sun.COM 		}
13317917SReza.Sabdar@Sun.COM 
13327917SReza.Sabdar@Sun.COM 		(void) memset(&tlm_arg, 0, sizeof (tlm_backup_restore_arg_t));
13337917SReza.Sabdar@Sun.COM 		(void) pthread_barrier_init(&tlm_arg.ba_barrier, 0, 2);
13347917SReza.Sabdar@Sun.COM 
13357917SReza.Sabdar@Sun.COM 		/*
13367917SReza.Sabdar@Sun.COM 		 * Set up restore parameters
13377917SReza.Sabdar@Sun.COM 		 */
13387917SReza.Sabdar@Sun.COM 		tlm_arg.ba_commands = cmds;
13397917SReza.Sabdar@Sun.COM 		tlm_arg.ba_cmd = cmds->tcs_command;
13407917SReza.Sabdar@Sun.COM 		tlm_arg.ba_job = nlp->nlp_jstat->js_job_name;
13417917SReza.Sabdar@Sun.COM 		tlm_arg.ba_dir = nlp->nlp_restore_path;
13427917SReza.Sabdar@Sun.COM 		for (i = 0; i < nlp->nlp_nfiles; i++) {
13437917SReza.Sabdar@Sun.COM 			ent = (ndmp_name *)MOD_GETNAME(mod_params, i);
13447917SReza.Sabdar@Sun.COM 			tlm_arg.ba_sels[i] = ent->name;
13457917SReza.Sabdar@Sun.COM 		}
13467917SReza.Sabdar@Sun.COM 
13477917SReza.Sabdar@Sun.COM 
13487917SReza.Sabdar@Sun.COM 		if (tm_tar_ops.tm_getfile != NULL) {
13497917SReza.Sabdar@Sun.COM 			err = pthread_create(&wrtp, NULL,
13507917SReza.Sabdar@Sun.COM 			    (funct_t)tm_tar_ops.tm_getfile, (void *)&tlm_arg);
13517917SReza.Sabdar@Sun.COM 		} else {
13527917SReza.Sabdar@Sun.COM 			(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13537917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
13547917SReza.Sabdar@Sun.COM 			    "Thread create tm_getfile: ops NULL");
13557917SReza.Sabdar@Sun.COM 			return (-1);
13567917SReza.Sabdar@Sun.COM 		}
13577917SReza.Sabdar@Sun.COM 		if (err == 0) {
13587917SReza.Sabdar@Sun.COM 			(void) pthread_barrier_wait(&tlm_arg.ba_barrier);
13597917SReza.Sabdar@Sun.COM 		} else {
13607917SReza.Sabdar@Sun.COM 			(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13617917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "thread create tm_getfile: %m");
13627917SReza.Sabdar@Sun.COM 			return (-1);
13637917SReza.Sabdar@Sun.COM 		}
13647917SReza.Sabdar@Sun.COM 
13657917SReza.Sabdar@Sun.COM 		(void) pthread_join(rdtp, NULL);
13667917SReza.Sabdar@Sun.COM 		(void) pthread_join(wrtp, NULL);
13677917SReza.Sabdar@Sun.COM 		(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13687917SReza.Sabdar@Sun.COM 
13697917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat->js_stop_time = time(NULL);
13707917SReza.Sabdar@Sun.COM 
13717917SReza.Sabdar@Sun.COM 		/* Send the list of un-recovered files/dirs to the client.  */
13727917SReza.Sabdar@Sun.COM 		(void) send_unrecovered_list(mod_params, nlp);
13737917SReza.Sabdar@Sun.COM 
13747917SReza.Sabdar@Sun.COM 		ndmp_stop_local_reader(session, cmds);
13757917SReza.Sabdar@Sun.COM 		ndmp_wait_for_reader(cmds);
13767917SReza.Sabdar@Sun.COM 		ndmp_stop_remote_reader(session);
13777917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
13787917SReza.Sabdar@Sun.COM 		    rspath, err);
13797917SReza.Sabdar@Sun.COM 	} else {
13807917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat->js_stop_time = time(NULL);
13817917SReza.Sabdar@Sun.COM 
13827917SReza.Sabdar@Sun.COM 		/* nothing restored. */
13837917SReza.Sabdar@Sun.COM 		(void) send_unrecovered_list(mod_params, nlp);
13847917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
13857917SReza.Sabdar@Sun.COM 		    rspath);
13867917SReza.Sabdar@Sun.COM 		err = -1;
13877917SReza.Sabdar@Sun.COM 	}
13887917SReza.Sabdar@Sun.COM 
13897917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_restore_path);
13907917SReza.Sabdar@Sun.COM 	backup_release_structs(session);
13917917SReza.Sabdar@Sun.COM 
13927917SReza.Sabdar@Sun.COM 	return (err);
13937917SReza.Sabdar@Sun.COM }
13947917SReza.Sabdar@Sun.COM 
13957917SReza.Sabdar@Sun.COM 
13967917SReza.Sabdar@Sun.COM /*
13977917SReza.Sabdar@Sun.COM  * prefixdir
13987917SReza.Sabdar@Sun.COM  *
13997917SReza.Sabdar@Sun.COM  * Extract the path for a given full path entry
14007917SReza.Sabdar@Sun.COM  */
14017917SReza.Sabdar@Sun.COM static char *
14027917SReza.Sabdar@Sun.COM prefixdir(char *dir, char *suffix)
14037917SReza.Sabdar@Sun.COM {
14047917SReza.Sabdar@Sun.COM 	static char tmp[TLM_MAX_PATH_NAME];
14057917SReza.Sabdar@Sun.COM 	char *tend, *send; /* tmp and suffix end */
14067917SReza.Sabdar@Sun.COM 
14077917SReza.Sabdar@Sun.COM 	if (dir == NULL || suffix == NULL)
14087917SReza.Sabdar@Sun.COM 		return (NULL);
14097917SReza.Sabdar@Sun.COM 
14107917SReza.Sabdar@Sun.COM 	if (*suffix == '\0')
14117917SReza.Sabdar@Sun.COM 		return (dir);
14127917SReza.Sabdar@Sun.COM 
14137917SReza.Sabdar@Sun.COM 	if (*dir == '\0')
14147917SReza.Sabdar@Sun.COM 		return (NULL);
14157917SReza.Sabdar@Sun.COM 
14167917SReza.Sabdar@Sun.COM 	(void) strlcpy(tmp, dir, TLM_MAX_PATH_NAME);
14177917SReza.Sabdar@Sun.COM 	tend = &tmp[strlen(tmp)];
14187917SReza.Sabdar@Sun.COM 	send = &suffix[strlen(suffix)];
14197917SReza.Sabdar@Sun.COM 
14207917SReza.Sabdar@Sun.COM 	/*
14217917SReza.Sabdar@Sun.COM 	 * Move backward as far as the last part of the dir and
14227917SReza.Sabdar@Sun.COM 	 * the suffix match.
14237917SReza.Sabdar@Sun.COM 	 */
14247917SReza.Sabdar@Sun.COM 	while (tend >= tmp && send >= suffix)
14257917SReza.Sabdar@Sun.COM 		if (*tend == *send)
14267917SReza.Sabdar@Sun.COM 			tend--, send--;
14277917SReza.Sabdar@Sun.COM 		else
14287917SReza.Sabdar@Sun.COM 			break;
14297917SReza.Sabdar@Sun.COM 
14307917SReza.Sabdar@Sun.COM 	*++tend = '\0';
14317917SReza.Sabdar@Sun.COM 	return (tmp);
14327917SReza.Sabdar@Sun.COM }
14337917SReza.Sabdar@Sun.COM 
14347917SReza.Sabdar@Sun.COM 
14357917SReza.Sabdar@Sun.COM /*
14367917SReza.Sabdar@Sun.COM  * get_backup_path
14377917SReza.Sabdar@Sun.COM  *
14387917SReza.Sabdar@Sun.COM  * Find the backup path from the environment variables
14397917SReza.Sabdar@Sun.COM  */
14407917SReza.Sabdar@Sun.COM static char *
14417917SReza.Sabdar@Sun.COM get_backup_path(ndmpd_module_params_t *params)
14427917SReza.Sabdar@Sun.COM {
14437917SReza.Sabdar@Sun.COM 	char *bkpath;
14447917SReza.Sabdar@Sun.COM 
14457917SReza.Sabdar@Sun.COM 	bkpath = MOD_GETENV(params, "PREFIX");
14467917SReza.Sabdar@Sun.COM 	if (bkpath == NULL)
14477917SReza.Sabdar@Sun.COM 		bkpath = MOD_GETENV(params, "FILESYSTEM");
14487917SReza.Sabdar@Sun.COM 
14497917SReza.Sabdar@Sun.COM 	if (bkpath == NULL) {
14507917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: restore path not specified.\n");
14517917SReza.Sabdar@Sun.COM 		return (NULL);
14527917SReza.Sabdar@Sun.COM 	}
14537917SReza.Sabdar@Sun.COM 
14547917SReza.Sabdar@Sun.COM 	if (*bkpath != '/') {
14557917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: relative backup path not allowed.\n");
14567917SReza.Sabdar@Sun.COM 		return (NULL);
14577917SReza.Sabdar@Sun.COM 	}
14587917SReza.Sabdar@Sun.COM 
14597917SReza.Sabdar@Sun.COM 	return (bkpath);
14607917SReza.Sabdar@Sun.COM }
14617917SReza.Sabdar@Sun.COM 
14627917SReza.Sabdar@Sun.COM 
14637917SReza.Sabdar@Sun.COM /*
14647917SReza.Sabdar@Sun.COM  * get_nfiles
14657917SReza.Sabdar@Sun.COM  *
14667917SReza.Sabdar@Sun.COM  * Get the count of files to be restored
14677917SReza.Sabdar@Sun.COM  */
14687917SReza.Sabdar@Sun.COM static int
14697917SReza.Sabdar@Sun.COM get_nfiles(ndmpd_session_t *session, ndmpd_module_params_t *params)
14707917SReza.Sabdar@Sun.COM {
14717917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_nlist_len == 0) {
14727917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: nothing specified to be restored.\n");
14737917SReza.Sabdar@Sun.COM 		return (-1);
14747917SReza.Sabdar@Sun.COM 	}
14757917SReza.Sabdar@Sun.COM 
14767917SReza.Sabdar@Sun.COM 	return (session->ns_data.dd_nlist_len);
14777917SReza.Sabdar@Sun.COM }
14787917SReza.Sabdar@Sun.COM 
14797917SReza.Sabdar@Sun.COM 
14807917SReza.Sabdar@Sun.COM /*
14817917SReza.Sabdar@Sun.COM  * get_restore_dest
14827917SReza.Sabdar@Sun.COM  *
14837917SReza.Sabdar@Sun.COM  * Get the full pathname of where the entries should be restored to.
14847917SReza.Sabdar@Sun.COM  */
14857917SReza.Sabdar@Sun.COM static char *
14867917SReza.Sabdar@Sun.COM get_restore_dest(ndmpd_module_params_t *params)
14877917SReza.Sabdar@Sun.COM {
14887917SReza.Sabdar@Sun.COM 	ndmp_name *ent;
14897917SReza.Sabdar@Sun.COM 	char *cp;
14907917SReza.Sabdar@Sun.COM 
14917917SReza.Sabdar@Sun.COM 	/*
14927917SReza.Sabdar@Sun.COM 	 * Destination of restore:
14937917SReza.Sabdar@Sun.COM 	 * NetBackup of Veritas(C) sends the entries like this:
14947917SReza.Sabdar@Sun.COM 	 *
14957917SReza.Sabdar@Sun.COM 	 *	ent[i].name: is the relative pathname of what is selected in
14967917SReza.Sabdar@Sun.COM 	 *	  the GUI.
14977917SReza.Sabdar@Sun.COM 	 *	ent[i].dest: is the full pathname of where the dir/file must
14987917SReza.Sabdar@Sun.COM 	 *	  be restored to.
14997917SReza.Sabdar@Sun.COM 	 *	ent[i].ssi: 0
15007917SReza.Sabdar@Sun.COM 	 *	ent[i].fh_info: 0
15017917SReza.Sabdar@Sun.COM 	 *
15027917SReza.Sabdar@Sun.COM 	 */
15037917SReza.Sabdar@Sun.COM 	ent = (ndmp_name *)MOD_GETNAME(params, 0);
15047917SReza.Sabdar@Sun.COM 	cp = prefixdir(ent->dest, ent->name);
15057917SReza.Sabdar@Sun.COM 	if (cp == NULL) {
15067917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: empty restore path.\n");
15077917SReza.Sabdar@Sun.COM 		return (NULL);
15087917SReza.Sabdar@Sun.COM 	}
15097917SReza.Sabdar@Sun.COM 
15107917SReza.Sabdar@Sun.COM 	return (cp);
15117917SReza.Sabdar@Sun.COM }
15127917SReza.Sabdar@Sun.COM 
15137917SReza.Sabdar@Sun.COM 
15147917SReza.Sabdar@Sun.COM /*
15157917SReza.Sabdar@Sun.COM  * correct_ents
15167917SReza.Sabdar@Sun.COM  *
15177917SReza.Sabdar@Sun.COM  * Correct the entries in the restore list by appending the appropriate
15187917SReza.Sabdar@Sun.COM  * path to them
15197917SReza.Sabdar@Sun.COM  */
15207917SReza.Sabdar@Sun.COM static int
15217917SReza.Sabdar@Sun.COM correct_ents(ndmpd_module_params_t *params, int n, char *bkpath)
15227917SReza.Sabdar@Sun.COM {
15237917SReza.Sabdar@Sun.COM 	char *cp, *pathname;
15247917SReza.Sabdar@Sun.COM 	int i, len, rv;
15257917SReza.Sabdar@Sun.COM 	ndmp_name *ent;
15267917SReza.Sabdar@Sun.COM 
15277917SReza.Sabdar@Sun.COM 	if ((pathname = ndmp_malloc(TLM_MAX_PATH_NAME)) == NULL) {
15287917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: insufficient memory.\n");
15297917SReza.Sabdar@Sun.COM 		return (-1);
15307917SReza.Sabdar@Sun.COM 	}
15317917SReza.Sabdar@Sun.COM 
15327917SReza.Sabdar@Sun.COM 	rv = 0;
15337917SReza.Sabdar@Sun.COM 	/* Append the backup path to all the "ent[].name"s. */
15347917SReza.Sabdar@Sun.COM 	for (i = 0; i < n; i++) {
15357917SReza.Sabdar@Sun.COM 		ent = (ndmp_name *)MOD_GETNAME(params, i);
15367917SReza.Sabdar@Sun.COM 
15377917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
15387917SReza.Sabdar@Sun.COM 		    "Old: ent[%d].name: \"%s\"", i, ent->name);
15397917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
15407917SReza.Sabdar@Sun.COM 		    "Old: ent[%d].dest: \"%s\"", i, ent->dest);
15417917SReza.Sabdar@Sun.COM 
15427917SReza.Sabdar@Sun.COM 		/* remove trailing slash */
15437917SReza.Sabdar@Sun.COM 		len = strlen(ent->name);
15447917SReza.Sabdar@Sun.COM 		if (ent->name[len - 1] == '/')
15457917SReza.Sabdar@Sun.COM 			ent->name[len - 1] = '\0';
15467917SReza.Sabdar@Sun.COM 
15477917SReza.Sabdar@Sun.COM 		if (!tlm_cat_path(pathname, bkpath, ent->name)) {
15487917SReza.Sabdar@Sun.COM 			MOD_LOG(params, "Error: path too long.\n");
15497917SReza.Sabdar@Sun.COM 			rv = -1;
15507917SReza.Sabdar@Sun.COM 			break;
15517917SReza.Sabdar@Sun.COM 		}
15527917SReza.Sabdar@Sun.COM 
15537917SReza.Sabdar@Sun.COM 		/* Make a copy of the new string and save it in ent->name. */
15547917SReza.Sabdar@Sun.COM 		cp = strdup(pathname);
15557917SReza.Sabdar@Sun.COM 		if (cp == NULL) {
15567917SReza.Sabdar@Sun.COM 			MOD_LOG(params, "Error: insufficient memory.\n");
15577917SReza.Sabdar@Sun.COM 			rv = -1;
15587917SReza.Sabdar@Sun.COM 			break;
15597917SReza.Sabdar@Sun.COM 		}
15607917SReza.Sabdar@Sun.COM 		free(ent->name);
15617917SReza.Sabdar@Sun.COM 		ent->name = cp;
15627917SReza.Sabdar@Sun.COM 
15637917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
15647917SReza.Sabdar@Sun.COM 		    "New: ent[%d].name: \"%s\"", i, ent->name);
15657917SReza.Sabdar@Sun.COM 	}
15667917SReza.Sabdar@Sun.COM 
15677917SReza.Sabdar@Sun.COM 	free(pathname);
15687917SReza.Sabdar@Sun.COM 	return (rv);
15697917SReza.Sabdar@Sun.COM }
15707917SReza.Sabdar@Sun.COM 
15717917SReza.Sabdar@Sun.COM 
15727917SReza.Sabdar@Sun.COM /*
15737917SReza.Sabdar@Sun.COM  * check_restore_paths
15747917SReza.Sabdar@Sun.COM  *
15757917SReza.Sabdar@Sun.COM  * Go through the restore list and check the validity of the
15767917SReza.Sabdar@Sun.COM  * restore path.
15777917SReza.Sabdar@Sun.COM  */
15787917SReza.Sabdar@Sun.COM static int
15797917SReza.Sabdar@Sun.COM check_restore_paths(ndmpd_module_params_t *params, int n, char *rspath)
15807917SReza.Sabdar@Sun.COM {
15817917SReza.Sabdar@Sun.COM 	int i, rv;
15827917SReza.Sabdar@Sun.COM 	ndmp_name *ent;
15837917SReza.Sabdar@Sun.COM 
15847917SReza.Sabdar@Sun.COM 	rv = 0;
15857917SReza.Sabdar@Sun.COM 	if (rspath != NULL && *rspath != '\0') {
15867917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "rspath: \"%s\"", rspath);
15877917SReza.Sabdar@Sun.COM 		if (!fs_volexist(rspath)) {
15887917SReza.Sabdar@Sun.COM 			MOD_LOG(params,
15897917SReza.Sabdar@Sun.COM 			    "Error: Invalid volume name for restore.");
15907917SReza.Sabdar@Sun.COM 			rv = -1;
15917917SReza.Sabdar@Sun.COM 		}
15927917SReza.Sabdar@Sun.COM 	} else {
15937917SReza.Sabdar@Sun.COM 		for (i = 0; i < n; i++) {
15947917SReza.Sabdar@Sun.COM 			ent = (ndmp_name *)MOD_GETNAME(params, i);
15957917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
15967917SReza.Sabdar@Sun.COM 			    "ent[%d].name: \"%s\"", i, ent->name);
15977917SReza.Sabdar@Sun.COM 
15987917SReza.Sabdar@Sun.COM 			if (!fs_volexist(ent->name)) {
15997917SReza.Sabdar@Sun.COM 				MOD_LOG(params,
16007917SReza.Sabdar@Sun.COM 				    "Error: Invalid volume name for restore.",
16017917SReza.Sabdar@Sun.COM 				    ent->name);
16027917SReza.Sabdar@Sun.COM 				rv = -1;
16037917SReza.Sabdar@Sun.COM 				break;
16047917SReza.Sabdar@Sun.COM 			}
16057917SReza.Sabdar@Sun.COM 		}
16067917SReza.Sabdar@Sun.COM 	}
16077917SReza.Sabdar@Sun.COM 
16087917SReza.Sabdar@Sun.COM 	return (rv);
16097917SReza.Sabdar@Sun.COM }
16107917SReza.Sabdar@Sun.COM 
16117917SReza.Sabdar@Sun.COM 
16127917SReza.Sabdar@Sun.COM /*
16137917SReza.Sabdar@Sun.COM  * check_backup_dir_validity
16147917SReza.Sabdar@Sun.COM  *
16157917SReza.Sabdar@Sun.COM  * Check if the backup directory is valid. Make sure it exists and
16167917SReza.Sabdar@Sun.COM  * is writable. Check for snapshot and readonly cases.
16177917SReza.Sabdar@Sun.COM  */
16187917SReza.Sabdar@Sun.COM static int
16197917SReza.Sabdar@Sun.COM check_backup_dir_validity(ndmpd_module_params_t *params, char *bkpath)
16207917SReza.Sabdar@Sun.COM {
16217917SReza.Sabdar@Sun.COM 	char *msg;
16227917SReza.Sabdar@Sun.COM 	int rv;
16237917SReza.Sabdar@Sun.COM 	struct stat64 st;
16247917SReza.Sabdar@Sun.COM 
16257917SReza.Sabdar@Sun.COM 	rv = NDMP_NO_ERR;
16267917SReza.Sabdar@Sun.COM 	if (stat64(bkpath, &st) < 0) {
16277917SReza.Sabdar@Sun.COM 		msg = strerror(errno);
16287917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: stat(%s): %s.\n", bkpath, msg);
16297917SReza.Sabdar@Sun.COM 		rv = NDMP_ILLEGAL_ARGS_ERR;
16307917SReza.Sabdar@Sun.COM 	} else if (!S_ISDIR(st.st_mode)) {
16317917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: %s is not a directory.\n", bkpath);
16327917SReza.Sabdar@Sun.COM 		rv = NDMP_ILLEGAL_ARGS_ERR;
16337917SReza.Sabdar@Sun.COM 	} else if (ndmp_is_chkpnt_root(bkpath)) {
16347917SReza.Sabdar@Sun.COM 		/* It's a .chkpnt directory */
16357917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: %s is a checkpoint root directory.\n",
16367917SReza.Sabdar@Sun.COM 		    bkpath);
16377917SReza.Sabdar@Sun.COM 		rv = NDMP_BAD_FILE_ERR;
16387917SReza.Sabdar@Sun.COM 	} else if (fs_is_rdonly(bkpath) && !fs_is_chkpntvol(bkpath) &&
16397917SReza.Sabdar@Sun.COM 	    fs_is_chkpnt_enabled(bkpath)) {
16407917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: %s is not a checkpointed path.\n",
16417917SReza.Sabdar@Sun.COM 		    bkpath);
16427917SReza.Sabdar@Sun.COM 		rv = NDMP_BAD_FILE_ERR;
16437917SReza.Sabdar@Sun.COM 	}
16447917SReza.Sabdar@Sun.COM 
16457917SReza.Sabdar@Sun.COM 	return (rv);
16467917SReza.Sabdar@Sun.COM }
16477917SReza.Sabdar@Sun.COM 
16487917SReza.Sabdar@Sun.COM 
16497917SReza.Sabdar@Sun.COM /*
16507917SReza.Sabdar@Sun.COM  * ndmp_backup_extract_params
16517917SReza.Sabdar@Sun.COM  *
16527917SReza.Sabdar@Sun.COM  * Go through the backup parameters and check the validity
16537917SReza.Sabdar@Sun.COM  * for each one. Then set the NLP flags according to the parameters.
16547917SReza.Sabdar@Sun.COM  */
16557917SReza.Sabdar@Sun.COM int
16567917SReza.Sabdar@Sun.COM ndmp_backup_extract_params(ndmpd_session_t *session,
16577917SReza.Sabdar@Sun.COM     ndmpd_module_params_t *params)
16587917SReza.Sabdar@Sun.COM {
16597917SReza.Sabdar@Sun.COM 	char *cp;
16607917SReza.Sabdar@Sun.COM 	int rv;
16617917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
16627917SReza.Sabdar@Sun.COM 
16637917SReza.Sabdar@Sun.COM 	/* Extract directory to be backed up from env variables */
16647917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
16657917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: Internal error: nlp == NULL.\n");
16667917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
16677917SReza.Sabdar@Sun.COM 	}
16687917SReza.Sabdar@Sun.COM 	if ((nlp->nlp_backup_path = get_backup_path(params)) == NULL)
16697917SReza.Sabdar@Sun.COM 		return (NDMP_FILE_NOT_FOUND_ERR);
16707917SReza.Sabdar@Sun.COM 
16717917SReza.Sabdar@Sun.COM 	if ((rv = check_backup_dir_validity(params,
16727917SReza.Sabdar@Sun.COM 	    nlp->nlp_backup_path)) != NDMP_NO_ERR)
16737917SReza.Sabdar@Sun.COM 		return (rv);
16747917SReza.Sabdar@Sun.COM 
16757917SReza.Sabdar@Sun.COM 	/* Should the st_ctime be ignored when backing up? */
16767917SReza.Sabdar@Sun.COM 	if (ndmp_ignore_ctime) {
16777917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "ignoring st_ctime");
16787917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_IGNCTIME);
16797917SReza.Sabdar@Sun.COM 	} else
16807917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_IGNCTIME);
16817917SReza.Sabdar@Sun.COM 
16827917SReza.Sabdar@Sun.COM 	/* Should the st_lmtime be ignored when backing up? */
16837917SReza.Sabdar@Sun.COM 	if (ndmp_include_lmtime) {
16847917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "including st_lmtime");
16857917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_INCLMTIME);
16867917SReza.Sabdar@Sun.COM 	} else
16877917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_INCLMTIME);
16887917SReza.Sabdar@Sun.COM 
16897917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
16907917SReza.Sabdar@Sun.COM 
16917917SReza.Sabdar@Sun.COM 	/* Is backup history requested? */
16927917SReza.Sabdar@Sun.COM 	cp = MOD_GETENV(params, "HIST");
16937917SReza.Sabdar@Sun.COM 	if (cp == NULL) {
16947917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "env(HIST) not specified");
16957917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_FH);
16967917SReza.Sabdar@Sun.COM 	} else {
16977917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "env(HIST): \"%s\"", cp);
16987917SReza.Sabdar@Sun.COM 
16997917SReza.Sabdar@Sun.COM 		if (strchr("t_ty_y", *cp))
17007917SReza.Sabdar@Sun.COM 			NLP_SET(nlp, NLPF_FH);
17017917SReza.Sabdar@Sun.COM 		else
17027917SReza.Sabdar@Sun.COM 			NLP_UNSET(nlp, NLPF_FH);
17037917SReza.Sabdar@Sun.COM 	}
17047917SReza.Sabdar@Sun.COM 
17057917SReza.Sabdar@Sun.COM 	nlp->nlp_clevel = 0;
17067917SReza.Sabdar@Sun.COM 	/* Is it an incremental backup? */
17077917SReza.Sabdar@Sun.COM 	cp = MOD_GETENV(params, "LEVEL");
17087917SReza.Sabdar@Sun.COM 	if (cp == NULL) {
17097917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
17107917SReza.Sabdar@Sun.COM 		    "env(LEVEL) not specified, default to 0");
17117917SReza.Sabdar@Sun.COM 	} else if (*cp < '0' || *cp > '9' || *(cp+1) != '\0') {
17127917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid backup level '%s'", cp);
17137917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
17147917SReza.Sabdar@Sun.COM 	} else
17157917SReza.Sabdar@Sun.COM 		nlp->nlp_clevel = *cp - '0';
17167917SReza.Sabdar@Sun.COM 
17177917SReza.Sabdar@Sun.COM 	/* Extract last backup time from the dumpdates file */
17187917SReza.Sabdar@Sun.COM 	nlp->nlp_llevel = nlp->nlp_clevel;
17197917SReza.Sabdar@Sun.COM 	nlp->nlp_ldate = 0;
17207917SReza.Sabdar@Sun.COM 	if (ndmpd_get_dumptime(nlp->nlp_backup_path, &nlp->nlp_llevel,
17217917SReza.Sabdar@Sun.COM 	    &nlp->nlp_ldate) < 0) {
17227917SReza.Sabdar@Sun.COM 		MOD_LOG(params, "Error: getting dumpdate for %s level %d\n",
17237917SReza.Sabdar@Sun.COM 		    nlp->nlp_backup_path, nlp->nlp_clevel);
17247917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
17257917SReza.Sabdar@Sun.COM 	}
17267917SReza.Sabdar@Sun.COM 
17277917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG,
17287917SReza.Sabdar@Sun.COM 	    "Date of this level %d on \"%s\": %s",
17297917SReza.Sabdar@Sun.COM 	    nlp->nlp_clevel, nlp->nlp_backup_path, cctime(&nlp->nlp_cdate));
17307917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG,
17317917SReza.Sabdar@Sun.COM 	    "Date of last level %d on \"%s\": %s",
17327917SReza.Sabdar@Sun.COM 	    nlp->nlp_llevel, nlp->nlp_backup_path, cctime(&nlp->nlp_ldate));
17337917SReza.Sabdar@Sun.COM 
17347917SReza.Sabdar@Sun.COM 	/* Should the dumpdate file be updated? */
17357917SReza.Sabdar@Sun.COM 	cp = MOD_GETENV(params, "UPDATE");
17367917SReza.Sabdar@Sun.COM 	if (cp == NULL) {
17377917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
17387917SReza.Sabdar@Sun.COM 		    "env(UPDATE) not specified, default to TRUE");
17397917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_UPDATE);
17407917SReza.Sabdar@Sun.COM 	} else {
17417917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "env(UPDATE): \"%s\"", cp);
17427917SReza.Sabdar@Sun.COM 		if (strchr("t_ty_y", *cp) != NULL)
17437917SReza.Sabdar@Sun.COM 			NLP_SET(nlp, NLPF_UPDATE);
17447917SReza.Sabdar@Sun.COM 		else
17457917SReza.Sabdar@Sun.COM 			NLP_UNSET(nlp, NLPF_UPDATE);
17467917SReza.Sabdar@Sun.COM 	}
17477917SReza.Sabdar@Sun.COM 
17487917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
17497917SReza.Sabdar@Sun.COM }
17507917SReza.Sabdar@Sun.COM 
17517917SReza.Sabdar@Sun.COM 
17527917SReza.Sabdar@Sun.COM 
17537917SReza.Sabdar@Sun.COM /*
17547917SReza.Sabdar@Sun.COM  * log_bk_params_v2
17557917SReza.Sabdar@Sun.COM  *
17567917SReza.Sabdar@Sun.COM  * Dump the value of the parameters in the log file for debugging.
17577917SReza.Sabdar@Sun.COM  */
17587917SReza.Sabdar@Sun.COM void
17597917SReza.Sabdar@Sun.COM log_bk_params_v2(ndmpd_session_t *session, ndmpd_module_params_t *params,
17607917SReza.Sabdar@Sun.COM     ndmp_lbr_params_t *nlp)
17617917SReza.Sabdar@Sun.COM {
17627917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Date of this level %d on \"%s\": %s\n",
17637917SReza.Sabdar@Sun.COM 	    nlp->nlp_clevel, nlp->nlp_backup_path, cctime(&nlp->nlp_cdate));
17647917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Date of last level %d on \"%s\": %s\n",
17657917SReza.Sabdar@Sun.COM 	    nlp->nlp_llevel, nlp->nlp_backup_path, cctime(&nlp->nlp_ldate));
17667917SReza.Sabdar@Sun.COM 
17677917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Backing up: \"%s\".\n", nlp->nlp_backup_path);
17687917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Record size: %d\n", session->ns_mover.md_record_size);
17697917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "File history: %c.\n",
17707917SReza.Sabdar@Sun.COM 	    NDMP_YORN(NLP_ISSET(nlp, NLPF_FH)));
17717917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Update: %s\n",
17727917SReza.Sabdar@Sun.COM 	    NLP_ISSET(nlp, NLPF_UPDATE) ? "TRUE" : "FALSE");
17737917SReza.Sabdar@Sun.COM 
17747917SReza.Sabdar@Sun.COM }
17757917SReza.Sabdar@Sun.COM 
17767917SReza.Sabdar@Sun.COM 
17777917SReza.Sabdar@Sun.COM /*
17787917SReza.Sabdar@Sun.COM  * same_path
17797917SReza.Sabdar@Sun.COM  *
17807917SReza.Sabdar@Sun.COM  * Find out if the paths are the same regardless of the ending slash
17817917SReza.Sabdar@Sun.COM  *
17827917SReza.Sabdar@Sun.COM  * Examples :
17837917SReza.Sabdar@Sun.COM  *   /a/b/c == /a/b/c
17847917SReza.Sabdar@Sun.COM  *   /a/b/c/ == /a/b/c
17857917SReza.Sabdar@Sun.COM  *   /a/b/c == /a/b/c/
17867917SReza.Sabdar@Sun.COM  */
17877917SReza.Sabdar@Sun.COM static boolean_t
17887917SReza.Sabdar@Sun.COM same_path(char *s, char *t)
17897917SReza.Sabdar@Sun.COM {
17907917SReza.Sabdar@Sun.COM 	boolean_t rv;
17917917SReza.Sabdar@Sun.COM 	int slen, tlen;
17927917SReza.Sabdar@Sun.COM 
17937917SReza.Sabdar@Sun.COM 	rv = FALSE;
17947917SReza.Sabdar@Sun.COM 	slen = strlen(s);
17957917SReza.Sabdar@Sun.COM 	tlen = strlen(t);
17967917SReza.Sabdar@Sun.COM 	if (slen == tlen && strcmp(s, t) == 0) {
17977917SReza.Sabdar@Sun.COM 		rv = TRUE;
17987917SReza.Sabdar@Sun.COM 	} else {
17997917SReza.Sabdar@Sun.COM 		if (slen == tlen - 1) {
18007917SReza.Sabdar@Sun.COM 			if (strncmp(s, t, slen) == 0 && t[tlen - 1] == '/')
18017917SReza.Sabdar@Sun.COM 				rv = TRUE;
18027917SReza.Sabdar@Sun.COM 		} else if (tlen == slen -1) {
18037917SReza.Sabdar@Sun.COM 			if (strncmp(s, t, tlen) == 0 && s[slen - 1] == '/')
18047917SReza.Sabdar@Sun.COM 				rv = TRUE;
18057917SReza.Sabdar@Sun.COM 		}
18067917SReza.Sabdar@Sun.COM 	}
18077917SReza.Sabdar@Sun.COM 
18087917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "rv: %d", rv);
18097917SReza.Sabdar@Sun.COM 	return (rv);
18107917SReza.Sabdar@Sun.COM }
18117917SReza.Sabdar@Sun.COM 
18127917SReza.Sabdar@Sun.COM 
18137917SReza.Sabdar@Sun.COM /*
18147917SReza.Sabdar@Sun.COM  * ndmp_restore_extract_params
18157917SReza.Sabdar@Sun.COM  *
18167917SReza.Sabdar@Sun.COM  * Go through the restore parameters and check them and extract them
18177917SReza.Sabdar@Sun.COM  * by setting NLP flags and other values.
18187917SReza.Sabdar@Sun.COM  *
18197917SReza.Sabdar@Sun.COM  * Parameters:
18207917SReza.Sabdar@Sun.COM  *
18217917SReza.Sabdar@Sun.COM  * Returns:
18227917SReza.Sabdar@Sun.COM  *   0: on success
18237917SReza.Sabdar@Sun.COM  *  -1: otherwise
18247917SReza.Sabdar@Sun.COM  */
18257917SReza.Sabdar@Sun.COM int
18267917SReza.Sabdar@Sun.COM ndmp_restore_extract_params(ndmpd_session_t *session,
18277917SReza.Sabdar@Sun.COM     ndmpd_module_params_t *params)
18287917SReza.Sabdar@Sun.COM {
18297917SReza.Sabdar@Sun.COM 	char *bkpath, *rspath;
18307917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
18317917SReza.Sabdar@Sun.COM 
18327917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
18337917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
18347917SReza.Sabdar@Sun.COM 		return (-1);
18357917SReza.Sabdar@Sun.COM 	}
18367917SReza.Sabdar@Sun.COM 
18377917SReza.Sabdar@Sun.COM 	/* Extract directory from where the backup was made. */
18387917SReza.Sabdar@Sun.COM 	if ((bkpath = get_backup_path(params)) == NULL)
18397917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18407917SReza.Sabdar@Sun.COM 
18417917SReza.Sabdar@Sun.COM 	nlp->nlp_restore_bk_path = bkpath;
18427917SReza.Sabdar@Sun.COM 
18437917SReza.Sabdar@Sun.COM 	/* The number of the selections. */
18447917SReza.Sabdar@Sun.COM 	if ((nlp->nlp_nfiles = get_nfiles(session, params)) == 0)
18457917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18467917SReza.Sabdar@Sun.COM 
18477917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "nfiles: %d", nlp->nlp_nfiles);
18487917SReza.Sabdar@Sun.COM 
18497917SReza.Sabdar@Sun.COM 	if ((rspath = get_restore_dest(params)) == NULL)
18507917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18517917SReza.Sabdar@Sun.COM 
18527917SReza.Sabdar@Sun.COM 	if (fs_is_rdonly(rspath)) {
18537917SReza.Sabdar@Sun.COM 		MOD_LOG(params,
18547917SReza.Sabdar@Sun.COM 		    "Error: Can't restore to a read-only volume: \"%s\"\n",
18557917SReza.Sabdar@Sun.COM 		    rspath);
18567917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18577917SReza.Sabdar@Sun.COM 	}
18587917SReza.Sabdar@Sun.COM 	if (fs_is_chkpntvol(rspath)) {
18597917SReza.Sabdar@Sun.COM 		MOD_LOG(params,
18607917SReza.Sabdar@Sun.COM 		    "Error: Can't restore to a checkpoint: \"%s\"\n", rspath);
18617917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18627917SReza.Sabdar@Sun.COM 	}
18637917SReza.Sabdar@Sun.COM 
18647917SReza.Sabdar@Sun.COM 	if (same_path(bkpath, rspath))
18657917SReza.Sabdar@Sun.COM 		rspath = "";
18667917SReza.Sabdar@Sun.COM 
18677917SReza.Sabdar@Sun.COM 	if ((nlp->nlp_restore_path = strdup(rspath)) == NULL)
18687917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
18697917SReza.Sabdar@Sun.COM 
18707917SReza.Sabdar@Sun.COM 	bkpath = trim_name(bkpath);
18717917SReza.Sabdar@Sun.COM 	if (correct_ents(params, nlp->nlp_nfiles, bkpath) < 0) {
18727917SReza.Sabdar@Sun.COM 		free(nlp->nlp_restore_path);
18737917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18747917SReza.Sabdar@Sun.COM 	}
18757917SReza.Sabdar@Sun.COM 
18767917SReza.Sabdar@Sun.COM 	if (check_restore_paths(params, nlp->nlp_nfiles, rspath) < 0) {
18777917SReza.Sabdar@Sun.COM 		free(nlp->nlp_restore_path);
18787917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
18797917SReza.Sabdar@Sun.COM 	}
18807917SReza.Sabdar@Sun.COM 
18817917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Restoring %d files.\n", nlp->nlp_nfiles);
18827917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Restoring to: \"%s\".\n", nlp->nlp_restore_path);
18837917SReza.Sabdar@Sun.COM 	MOD_LOG(params, "Record size: %d\n", session->ns_mover.md_record_size);
18847917SReza.Sabdar@Sun.COM 
18857917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
18867917SReza.Sabdar@Sun.COM }
18877917SReza.Sabdar@Sun.COM 
18887917SReza.Sabdar@Sun.COM /*
18897917SReza.Sabdar@Sun.COM  * ndmpd_tar_backup_starter (V2 only)
18907917SReza.Sabdar@Sun.COM  *
18917917SReza.Sabdar@Sun.COM  * The main backup starter function. It creates a snapshot if necessary
18927917SReza.Sabdar@Sun.COM  * and calls ndmp_tar_backup to perform the actual backup. It does the cleanup
18937917SReza.Sabdar@Sun.COM  * and release the snapshot at the end.
18947917SReza.Sabdar@Sun.COM  */
18957917SReza.Sabdar@Sun.COM int
18967917SReza.Sabdar@Sun.COM ndmpd_tar_backup_starter(ndmpd_module_params_t *mod_params)
18977917SReza.Sabdar@Sun.COM {
18987917SReza.Sabdar@Sun.COM 	int err;
18997917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session;
19007917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
19017917SReza.Sabdar@Sun.COM 
19027917SReza.Sabdar@Sun.COM 	session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie);
19037917SReza.Sabdar@Sun.COM 	*(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
19047917SReza.Sabdar@Sun.COM 	ndmp_session_ref(session);
19057917SReza.Sabdar@Sun.COM 
19067917SReza.Sabdar@Sun.COM 	err = 0;
19077917SReza.Sabdar@Sun.COM 	if (fs_is_chkpntvol(nlp->nlp_backup_path) ||
19087917SReza.Sabdar@Sun.COM 	    fs_is_rdonly(nlp->nlp_backup_path) ||
19097917SReza.Sabdar@Sun.COM 	    !fs_is_chkpnt_enabled(nlp->nlp_backup_path))
19107917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_CHKPNTED_PATH);
19117917SReza.Sabdar@Sun.COM 	else {
19127917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_CHKPNTED_PATH);
19137917SReza.Sabdar@Sun.COM 		if (ndmp_start_check_point(nlp->nlp_backup_path,
19147917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_job_name) < 0) {
19157917SReza.Sabdar@Sun.COM 			MOD_LOG(mod_params,
19167917SReza.Sabdar@Sun.COM 			    "Error: creating checkpoint on %s\n",
19177917SReza.Sabdar@Sun.COM 			    nlp->nlp_backup_path);
19187917SReza.Sabdar@Sun.COM 			/* -1 causes halt reason to become internal error. */
19197917SReza.Sabdar@Sun.COM 			err = -1;
19207917SReza.Sabdar@Sun.COM 		}
19217917SReza.Sabdar@Sun.COM 	}
19227917SReza.Sabdar@Sun.COM 
19237917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "NLPF_CHKPNTED_PATH: %c",
19247917SReza.Sabdar@Sun.COM 	    NDMP_YORN(NLP_ISCHKPNTED(nlp)));
19257917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "err: %d, update %c",
19267917SReza.Sabdar@Sun.COM 	    err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
19277917SReza.Sabdar@Sun.COM 
19287917SReza.Sabdar@Sun.COM 	if (err == 0) {
19297917SReza.Sabdar@Sun.COM 		err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate,
19307917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_job_name);
19317917SReza.Sabdar@Sun.COM 		if (err != 0) {
19327917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "err %d", err);
19337917SReza.Sabdar@Sun.COM 		} else {
19347917SReza.Sabdar@Sun.COM 			log_bk_params_v2(session, mod_params, nlp);
19357917SReza.Sabdar@Sun.COM 			err = ndmpd_tar_backup(session, mod_params, nlp);
19367917SReza.Sabdar@Sun.COM 		}
19377917SReza.Sabdar@Sun.COM 	}
19387917SReza.Sabdar@Sun.COM 
19397917SReza.Sabdar@Sun.COM 	if (nlp->nlp_bkmap >= 0) {
19407917SReza.Sabdar@Sun.COM 		(void) dbm_free(nlp->nlp_bkmap);
19417917SReza.Sabdar@Sun.COM 		nlp->nlp_bkmap = -1;
19427917SReza.Sabdar@Sun.COM 	}
19437917SReza.Sabdar@Sun.COM 
19447917SReza.Sabdar@Sun.COM 	if (!NLP_ISCHKPNTED(nlp))
19457917SReza.Sabdar@Sun.COM 		(void) ndmp_release_check_point(nlp->nlp_backup_path,
19467917SReza.Sabdar@Sun.COM 		    nlp->nlp_jstat->js_job_name);
19477917SReza.Sabdar@Sun.COM 
19487917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "err %d, update %c",
19497917SReza.Sabdar@Sun.COM 	    err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
19507917SReza.Sabdar@Sun.COM 
19517917SReza.Sabdar@Sun.COM 	if (err == 0 && NLP_SHOULD_UPDATE(nlp)) {
19527917SReza.Sabdar@Sun.COM 		if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel,
19537917SReza.Sabdar@Sun.COM 		    nlp->nlp_cdate) < 0) {
19547917SReza.Sabdar@Sun.COM 			err = EPERM;
19557917SReza.Sabdar@Sun.COM 			MOD_LOG(mod_params,
19567917SReza.Sabdar@Sun.COM 			    "Error: updating the dumpdates file on %s\n",
19577917SReza.Sabdar@Sun.COM 			    nlp->nlp_backup_path);
19587917SReza.Sabdar@Sun.COM 		}
19597917SReza.Sabdar@Sun.COM 	}
19607917SReza.Sabdar@Sun.COM 
19617917SReza.Sabdar@Sun.COM 	MOD_DONE(mod_params, err);
19627917SReza.Sabdar@Sun.COM 
19637917SReza.Sabdar@Sun.COM 	/* nlp_params is allocated in start_backup() */
19647917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
19657917SReza.Sabdar@Sun.COM 
19667917SReza.Sabdar@Sun.COM 	NS_DEC(nbk);
19677917SReza.Sabdar@Sun.COM 	ndmp_session_unref(session);
19687917SReza.Sabdar@Sun.COM 	return (err);
19697917SReza.Sabdar@Sun.COM }
19707917SReza.Sabdar@Sun.COM 
19717917SReza.Sabdar@Sun.COM 
19727917SReza.Sabdar@Sun.COM /*
19737917SReza.Sabdar@Sun.COM  * ndmpd_tar_backup_abort
19747917SReza.Sabdar@Sun.COM  *
19757917SReza.Sabdar@Sun.COM  * Abort the running backup by stopping the reader thread (V2 only)
19767917SReza.Sabdar@Sun.COM  */
19777917SReza.Sabdar@Sun.COM int
19787917SReza.Sabdar@Sun.COM ndmpd_tar_backup_abort(void *module_cookie)
19797917SReza.Sabdar@Sun.COM {
19807917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
19817917SReza.Sabdar@Sun.COM 
19827917SReza.Sabdar@Sun.COM 	nlp = (ndmp_lbr_params_t *)module_cookie;
19837917SReza.Sabdar@Sun.COM 	if (nlp != NULL && nlp->nlp_session != NULL) {
19847917SReza.Sabdar@Sun.COM 		if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
19857917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP && nlp->nlp_session->ns_data.dd_sock != -1) {
19867917SReza.Sabdar@Sun.COM 			(void) close(nlp->nlp_session->ns_data.dd_sock);
19877917SReza.Sabdar@Sun.COM 			nlp->nlp_session->ns_data.dd_sock = -1;
19887917SReza.Sabdar@Sun.COM 		}
19897917SReza.Sabdar@Sun.COM 		ndmp_stop_reader_thread(nlp->nlp_session);
19907917SReza.Sabdar@Sun.COM 	}
19917917SReza.Sabdar@Sun.COM 
19927917SReza.Sabdar@Sun.COM 	return (0);
19937917SReza.Sabdar@Sun.COM }
19947917SReza.Sabdar@Sun.COM 
19957917SReza.Sabdar@Sun.COM /*
19967917SReza.Sabdar@Sun.COM  * ndmpd_tar_restore_starter
19977917SReza.Sabdar@Sun.COM  *
19987917SReza.Sabdar@Sun.COM  * Starts the restore by running ndmpd_tar_restore function (V2 only)
19997917SReza.Sabdar@Sun.COM  */
20007917SReza.Sabdar@Sun.COM 
20017917SReza.Sabdar@Sun.COM int
20027917SReza.Sabdar@Sun.COM ndmpd_tar_restore_starter(ndmpd_module_params_t *mod_params)
20037917SReza.Sabdar@Sun.COM {
20047917SReza.Sabdar@Sun.COM 	int err;
20057917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session;
20067917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
20077917SReza.Sabdar@Sun.COM 
20087917SReza.Sabdar@Sun.COM 	session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie);
20097917SReza.Sabdar@Sun.COM 	*(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
20107917SReza.Sabdar@Sun.COM 	ndmp_session_ref(session);
20117917SReza.Sabdar@Sun.COM 
20127917SReza.Sabdar@Sun.COM 	err = ndmpd_tar_restore(session, mod_params, nlp);
20137917SReza.Sabdar@Sun.COM 	MOD_DONE(mod_params, err);
20147917SReza.Sabdar@Sun.COM 
20157917SReza.Sabdar@Sun.COM 	/* nlp_params is allocated in start_recover() */
20167917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
20177917SReza.Sabdar@Sun.COM 
20187917SReza.Sabdar@Sun.COM 	NS_DEC(nrs);
20197917SReza.Sabdar@Sun.COM 	ndmp_session_unref(session);
20207917SReza.Sabdar@Sun.COM 	return (err);
20217917SReza.Sabdar@Sun.COM }
20227917SReza.Sabdar@Sun.COM 
20237917SReza.Sabdar@Sun.COM 
20247917SReza.Sabdar@Sun.COM /*
20257917SReza.Sabdar@Sun.COM  * ndmpd_tar_restore_abort
20267917SReza.Sabdar@Sun.COM  *
20277917SReza.Sabdar@Sun.COM  * Aborts the restore operation by stopping the writer thread (V2 only)
20287917SReza.Sabdar@Sun.COM  */
20297917SReza.Sabdar@Sun.COM int
20307917SReza.Sabdar@Sun.COM ndmpd_tar_restore_abort(void *module_cookie)
20317917SReza.Sabdar@Sun.COM {
20327917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
20337917SReza.Sabdar@Sun.COM 
20347917SReza.Sabdar@Sun.COM 	nlp = (ndmp_lbr_params_t *)module_cookie;
20357917SReza.Sabdar@Sun.COM 	if (nlp != NULL && nlp->nlp_session != NULL) {
20367917SReza.Sabdar@Sun.COM 		if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
20377917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP && nlp->nlp_session->ns_data.dd_sock != -1) {
20387917SReza.Sabdar@Sun.COM 			(void) close(nlp->nlp_session->ns_data.dd_sock);
20397917SReza.Sabdar@Sun.COM 			nlp->nlp_session->ns_data.dd_sock = -1;
20407917SReza.Sabdar@Sun.COM 		}
20417917SReza.Sabdar@Sun.COM 		nlp_event_nw(nlp->nlp_session);
20427917SReza.Sabdar@Sun.COM 		ndmp_stop_writer_thread(nlp->nlp_session);
20437917SReza.Sabdar@Sun.COM 	}
20447917SReza.Sabdar@Sun.COM 
20457917SReza.Sabdar@Sun.COM 	return (0);
20467917SReza.Sabdar@Sun.COM }
2047