xref: /illumos-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_tar.c (revision 82049ff5)
12654012fSReza Sabdar /*
28c4f9701SJanice Chang  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
32654012fSReza Sabdar  */
42654012fSReza Sabdar 
52654012fSReza Sabdar /*
62654012fSReza Sabdar  * BSD 3 Clause License
72654012fSReza Sabdar  *
82654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
92654012fSReza Sabdar  *
102654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
112654012fSReza Sabdar  * modification, are permitted provided that the following conditions
122654012fSReza Sabdar  * are met:
13*82049ff5SToomas Soome  *	- Redistributions of source code must retain the above copyright
142654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
152654012fSReza Sabdar  *
16*82049ff5SToomas Soome  *	- Redistributions in binary form must reproduce the above copyright
172654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
182654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
192654012fSReza Sabdar  *	  distribution.
202654012fSReza Sabdar  *
212654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
222654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
232654012fSReza Sabdar  *	  products derived from this software without specific prior written
242654012fSReza Sabdar  *	  permission.
252654012fSReza Sabdar  *
262654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
272654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
282654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
292654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
302654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
312654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
322654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
332654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
342654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
352654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
362654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
372654012fSReza Sabdar  */
388c4f9701SJanice Chang /* Copyright (c) 2007, The Storage Networking Industry Association. */
392654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
40a23888a3SJan Kryl /* Copyright 2014 Nexenta Systems, Inc. All rights reserved. */
412654012fSReza Sabdar 
422654012fSReza Sabdar #include <sys/stat.h>
432654012fSReza Sabdar #include <sys/types.h>
442654012fSReza Sabdar #include <sys/socket.h>
452654012fSReza Sabdar #include <errno.h>
462654012fSReza Sabdar #include <stdio.h>
472654012fSReza Sabdar #include <string.h>
482654012fSReza Sabdar #include <unistd.h>
492654012fSReza Sabdar #include <time.h>
502654012fSReza Sabdar #include <cstack.h>
512654012fSReza Sabdar #include <dirent.h>
522654012fSReza Sabdar #include <traverse.h>
532654012fSReza Sabdar #include "bitmap.h"
542654012fSReza Sabdar #include "ndmpd.h"
552654012fSReza Sabdar #include "tlm_buffers.h"
562654012fSReza Sabdar 
572654012fSReza Sabdar 
582654012fSReza Sabdar typedef struct ndmp_run_args {
592654012fSReza Sabdar 	char *nr_chkp_nm;
602654012fSReza Sabdar 	char *nr_unchkp_nm;
612654012fSReza Sabdar 	char **nr_excls;
622654012fSReza Sabdar } ndmp_run_args_t;
632654012fSReza Sabdar 
642654012fSReza Sabdar 
652654012fSReza Sabdar /*
662654012fSReza Sabdar  * backup_create_structs
672654012fSReza Sabdar  *
682654012fSReza Sabdar  * Allocate the structures before performing backup
692654012fSReza Sabdar  *
702654012fSReza Sabdar  * Parameters:
712654012fSReza Sabdar  *   sesison (input) - session handle
722654012fSReza Sabdar  *   jname (input) - backup job name
732654012fSReza Sabdar  *
742654012fSReza Sabdar  * Returns:
752654012fSReza Sabdar  *   0: on success
762654012fSReza Sabdar  *  -1: otherwise
772654012fSReza Sabdar  */
782654012fSReza Sabdar static int
backup_create_structs(ndmpd_session_t * session,char * jname)792654012fSReza Sabdar backup_create_structs(ndmpd_session_t *session, char *jname)
802654012fSReza Sabdar {
812654012fSReza Sabdar 	int n;
822654012fSReza Sabdar 	long xfer_size;
832654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
842654012fSReza Sabdar 	tlm_commands_t *cmds;
852654012fSReza Sabdar 
862654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
872654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
882654012fSReza Sabdar 		return (-1);
892654012fSReza Sabdar 	}
902654012fSReza Sabdar 
912654012fSReza Sabdar 	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
922654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
932654012fSReza Sabdar 		return (-1);
942654012fSReza Sabdar 	}
952654012fSReza Sabdar 
962654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
972654012fSReza Sabdar 	(void) memset(cmds, 0, sizeof (*cmds));
982654012fSReza Sabdar 
992654012fSReza Sabdar 	xfer_size = ndmp_buffer_get_size(session);
1002654012fSReza Sabdar 	if (xfer_size < 512*KILOBYTE) {
1012654012fSReza Sabdar 		/*
1022654012fSReza Sabdar 		 * Read multiple of mover_record_size near to 512K.  This
1032654012fSReza Sabdar 		 * will prevent the data being copied in the mover buffer
1042654012fSReza Sabdar 		 * when we write the data.
1052654012fSReza Sabdar 		 */
1062654012fSReza Sabdar 		if ((n = (512 * KILOBYTE/xfer_size)) <= 0)
1072654012fSReza Sabdar 			n = 1;
1082654012fSReza Sabdar 		xfer_size *= n;
1092654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Adjusted read size: %d", xfer_size);
1102654012fSReza Sabdar 	}
1112654012fSReza Sabdar 
1122654012fSReza Sabdar 	cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, xfer_size);
1132654012fSReza Sabdar 	if (cmds->tcs_command == NULL) {
1142654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
1152654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
1162654012fSReza Sabdar 		return (-1);
1172654012fSReza Sabdar 	}
1182654012fSReza Sabdar 
1192654012fSReza Sabdar 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1202654012fSReza Sabdar 	    ndmpd_file_history_path,
1212654012fSReza Sabdar 	    ndmpd_file_history_dir,
1222654012fSReza Sabdar 	    ndmpd_file_history_node);
1232654012fSReza Sabdar 	if (nlp->nlp_logcallbacks == NULL) {
1242654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1252654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
1262654012fSReza Sabdar 		return (-1);
1272654012fSReza Sabdar 	}
1282654012fSReza Sabdar 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1292654012fSReza Sabdar 
1302654012fSReza Sabdar 	return (0);
1312654012fSReza Sabdar }
1322654012fSReza Sabdar 
1332654012fSReza Sabdar 
1342654012fSReza Sabdar /*
1352654012fSReza Sabdar  * restore_create_structs
1362654012fSReza Sabdar  *
1372654012fSReza Sabdar  * Allocate structures for performing a restore
1382654012fSReza Sabdar  *
1392654012fSReza Sabdar  * Parameters:
1402654012fSReza Sabdar  *   sesison (input) - session handle
1412654012fSReza Sabdar  *   jname (input) - backup job name
1422654012fSReza Sabdar  *
1432654012fSReza Sabdar  * Returns:
1442654012fSReza Sabdar  *   0: on success
1452654012fSReza Sabdar  *  -1: otherwise
1462654012fSReza Sabdar  */
1472654012fSReza Sabdar static int
restore_create_structs(ndmpd_session_t * session,char * jname)1482654012fSReza Sabdar restore_create_structs(ndmpd_session_t *session, char *jname)
1492654012fSReza Sabdar {
1502654012fSReza Sabdar 	int i;
1512654012fSReza Sabdar 	long xfer_size;
1522654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1532654012fSReza Sabdar 	tlm_commands_t *cmds;
1542654012fSReza Sabdar 
1552654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1562654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1572654012fSReza Sabdar 		return (-1);
1582654012fSReza Sabdar 	}
1592654012fSReza Sabdar 	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
1602654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Creating job stats");
1612654012fSReza Sabdar 		return (-1);
1622654012fSReza Sabdar 	}
1632654012fSReza Sabdar 
1642654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
1652654012fSReza Sabdar 	(void) memset(cmds, 0, sizeof (*cmds));
1662654012fSReza Sabdar 
1672654012fSReza Sabdar 	xfer_size = ndmp_buffer_get_size(session);
1682654012fSReza Sabdar 	cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
1692654012fSReza Sabdar 	if (cmds->tcs_command == NULL) {
1702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
1712654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
1722654012fSReza Sabdar 		return (-1);
1732654012fSReza Sabdar 	}
1742654012fSReza Sabdar 
1752654012fSReza Sabdar 	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
1762654012fSReza Sabdar 	    ndmpd_path_restored, NULL, NULL);
1772654012fSReza Sabdar 	if (nlp->nlp_logcallbacks == NULL) {
1782654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1792654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
1802654012fSReza Sabdar 		return (-1);
1812654012fSReza Sabdar 	}
1822654012fSReza Sabdar 	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);
1832654012fSReza Sabdar 
1842654012fSReza Sabdar 	nlp->nlp_restored = ndmp_malloc(sizeof (boolean_t) * nlp->nlp_nfiles);
1852654012fSReza Sabdar 	if (nlp->nlp_restored == NULL) {
1862654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
1872654012fSReza Sabdar 		tlm_release_reader_writer_ipc(cmds->tcs_command);
1882654012fSReza Sabdar 		tlm_un_ref_job_stats(jname);
1892654012fSReza Sabdar 		return (-1);
1902654012fSReza Sabdar 	}
1912654012fSReza Sabdar 	for (i = 0; i < (int)nlp->nlp_nfiles; i++)
1922654012fSReza Sabdar 		nlp->nlp_restored[i] = FALSE;
1932654012fSReza Sabdar 
1942654012fSReza Sabdar 	return (0);
1952654012fSReza Sabdar }
1962654012fSReza Sabdar 
1972654012fSReza Sabdar 
1982654012fSReza Sabdar /*
1992654012fSReza Sabdar  * send_unrecovered_list
2002654012fSReza Sabdar  *
2012654012fSReza Sabdar  * Creates a list of restored files
2022654012fSReza Sabdar  *
2032654012fSReza Sabdar  * Parameters:
2042654012fSReza Sabdar  *   params (input) - NDMP parameters
2052654012fSReza Sabdar  *   nlp (input) - NDMP/LBR parameters
2062654012fSReza Sabdar  *
2072654012fSReza Sabdar  * Returns:
2082654012fSReza Sabdar  *   0: on success
2092654012fSReza Sabdar  *  -1: otherwise
2102654012fSReza Sabdar  */
2112654012fSReza Sabdar static int
send_unrecovered_list(ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)2122654012fSReza Sabdar send_unrecovered_list(ndmpd_module_params_t *params, ndmp_lbr_params_t *nlp)
2132654012fSReza Sabdar {
2142654012fSReza Sabdar 	int i, rv;
2152654012fSReza Sabdar 	ndmp_name *ent;
2162654012fSReza Sabdar 
2172654012fSReza Sabdar 	if (params == NULL) {
2182654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "params == NULL");
2192654012fSReza Sabdar 		return (-1);
2202654012fSReza Sabdar 	}
2212654012fSReza Sabdar 	if (nlp == NULL) {
2222654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2232654012fSReza Sabdar 		return (-1);
2242654012fSReza Sabdar 	}
2252654012fSReza Sabdar 
2262654012fSReza Sabdar 	rv = 0;
2272654012fSReza Sabdar 	for (i = 0; i < (int)nlp->nlp_nfiles; i++) {
2282654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp->nlp_restored[%d]: %s", i,
2292654012fSReza Sabdar 		    nlp->nlp_restored[i] ? "TRUE" : "FALSE");
2302654012fSReza Sabdar 
2312654012fSReza Sabdar 		if (!nlp->nlp_restored[i]) {
2322654012fSReza Sabdar 			ent = (ndmp_name *)MOD_GETNAME(params, i);
2332654012fSReza Sabdar 			if (ent == NULL) {
2342654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "ent == NULL");
2352654012fSReza Sabdar 				rv = -1;
2362654012fSReza Sabdar 				break;
2372654012fSReza Sabdar 			}
2382654012fSReza Sabdar 			if (ent->name == NULL) {
2392654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "ent->name == NULL");
2402654012fSReza Sabdar 				rv = -1;
2412654012fSReza Sabdar 				break;
2422654012fSReza Sabdar 			}
2432654012fSReza Sabdar 
2442654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "ent.name: \"%s\"", ent->name);
2452654012fSReza Sabdar 
2462654012fSReza Sabdar 			rv = MOD_FILERECOVERD(params, ent->name, ENOENT);
2472654012fSReza Sabdar 			if (rv < 0)
2482654012fSReza Sabdar 				break;
2492654012fSReza Sabdar 		}
2502654012fSReza Sabdar 	}
2512654012fSReza Sabdar 
2522654012fSReza Sabdar 	return (rv);
2532654012fSReza Sabdar }
2542654012fSReza Sabdar 
2552654012fSReza Sabdar 
2562654012fSReza Sabdar /*
2572654012fSReza Sabdar  * backup_release_structs
2582654012fSReza Sabdar  *
2592654012fSReza Sabdar  * Deallocated the NDMP/LBR specific parameters
2602654012fSReza Sabdar  *
2612654012fSReza Sabdar  * Parameters:
2622654012fSReza Sabdar  *   session (input) - session handle
2632654012fSReza Sabdar  *
2642654012fSReza Sabdar  * Returns:
2652654012fSReza Sabdar  *   void
2662654012fSReza Sabdar  */
2672654012fSReza Sabdar /*ARGSUSED*/
2682654012fSReza Sabdar static void
backup_release_structs(ndmpd_session_t * session)2692654012fSReza Sabdar backup_release_structs(ndmpd_session_t *session)
2702654012fSReza Sabdar {
2712654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
2722654012fSReza Sabdar 	tlm_commands_t *cmds;
2732654012fSReza Sabdar 
2742654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
2752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
2762654012fSReza Sabdar 		return;
2772654012fSReza Sabdar 	}
2782654012fSReza Sabdar 	cmds = &nlp->nlp_cmds;
2792654012fSReza Sabdar 	if (cmds == NULL) {
2802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
2812654012fSReza Sabdar 		return;
2822654012fSReza Sabdar 	}
2832654012fSReza Sabdar 
2842654012fSReza Sabdar 	if (nlp->nlp_logcallbacks != NULL) {
2852654012fSReza Sabdar 		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
2862654012fSReza Sabdar 		nlp->nlp_logcallbacks = NULL;
2872654012fSReza Sabdar 	} else {
2882654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "FH CALLBACKS == NULL");
2892654012fSReza Sabdar 	}
2902654012fSReza Sabdar 
2912654012fSReza Sabdar 	if (cmds->tcs_command != NULL) {
2922654012fSReza Sabdar 		if (cmds->tcs_command->tc_buffers != NULL)
2932654012fSReza Sabdar 			tlm_release_reader_writer_ipc(cmds->tcs_command);
2942654012fSReza Sabdar 		else
2952654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "BUFFERS == NULL");
2962654012fSReza Sabdar 		cmds->tcs_command = NULL;
2972654012fSReza Sabdar 	} else {
2982654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "COMMAND == NULL");
2992654012fSReza Sabdar 	}
3002654012fSReza Sabdar 
3012654012fSReza Sabdar 	if (nlp->nlp_bkmap >= 0) {
3022654012fSReza Sabdar 		(void) dbm_free(nlp->nlp_bkmap);
3032654012fSReza Sabdar 		nlp->nlp_bkmap = -1;
3042654012fSReza Sabdar 	}
3052654012fSReza Sabdar 
3062654012fSReza Sabdar 	if (session->ns_data.dd_operation == NDMP_DATA_OP_RECOVER &&
3072654012fSReza Sabdar 	    nlp->nlp_restored != NULL) {
3082654012fSReza Sabdar 		free(nlp->nlp_restored);
3092654012fSReza Sabdar 		nlp->nlp_restored = NULL;
3102654012fSReza Sabdar 	} else {
3112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp_restored == NULL");
3122654012fSReza Sabdar 	}
3132654012fSReza Sabdar }
3142654012fSReza Sabdar 
3152654012fSReza Sabdar /*
3162654012fSReza Sabdar  * ndmp_write_utf8magic
3172654012fSReza Sabdar  *
3182654012fSReza Sabdar  * Write a magic pattern to the tar header. This is used
3192654012fSReza Sabdar  * as a crest to indicate that tape belongs to us.
3202654012fSReza Sabdar  */
3212654012fSReza Sabdar int
ndmp_write_utf8magic(tlm_cmd_t * cmd)3222654012fSReza Sabdar ndmp_write_utf8magic(tlm_cmd_t *cmd)
3232654012fSReza Sabdar {
3242654012fSReza Sabdar 	char *cp;
3252654012fSReza Sabdar 	long actual_size;
3262654012fSReza Sabdar 
3272654012fSReza Sabdar 	if (cmd->tc_buffers == NULL) {
3282654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
3292654012fSReza Sabdar 		return (-1);
3302654012fSReza Sabdar 	}
3312654012fSReza Sabdar 
3322654012fSReza Sabdar 	cp = tlm_get_write_buffer(RECORDSIZE, &actual_size,
3332654012fSReza Sabdar 	    cmd->tc_buffers, TRUE);
3342654012fSReza Sabdar 	if (actual_size < RECORDSIZE) {
3352654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Couldn't get enough buffer");
3362654012fSReza Sabdar 		return (-1);
3372654012fSReza Sabdar 	}
3382654012fSReza Sabdar 
3392654012fSReza Sabdar 	(void) strlcpy(cp, NDMPUTF8MAGIC, RECORDSIZE);
3402654012fSReza Sabdar 	return (0);
3412654012fSReza Sabdar }
3422654012fSReza Sabdar 
3432654012fSReza Sabdar 
3442654012fSReza Sabdar /*
3452654012fSReza Sabdar  * timecmp
3462654012fSReza Sabdar  *
3472654012fSReza Sabdar  * This callback function is used during backup.  It checks
3482654012fSReza Sabdar  * if the object specified by the 'attr' should be backed
3492654012fSReza Sabdar  * up or not.
3502654012fSReza Sabdar  *
3512654012fSReza Sabdar  * Directories are backed up anyways for dump format.
3522654012fSReza Sabdar  * If this function is called, then the directory is
3532654012fSReza Sabdar  * marked in the bitmap vector, it shows that either the
3542654012fSReza Sabdar  * directory itself is modified or there is something below
3552654012fSReza Sabdar  * it that will be backed up.
3562654012fSReza Sabdar  *
3572654012fSReza Sabdar  * Directories for tar format are backed up if and only if
3582654012fSReza Sabdar  * they are modified.
3592654012fSReza Sabdar  *
3602654012fSReza Sabdar  * By setting ndmp_force_bk_dirs global variable to a non-zero
3612654012fSReza Sabdar  * value, directories are backed up anyways.
3622654012fSReza Sabdar  *
3632654012fSReza Sabdar  * Backing up the directories unconditionally, helps
3642654012fSReza Sabdar  * restoring the metadata of directories as well, when one
3652654012fSReza Sabdar  * of the objects below them are being restored.
3662654012fSReza Sabdar  *
3672654012fSReza Sabdar  * For non-directory objects, if the modification or change
3682654012fSReza Sabdar  * time of the object is after the date specified by the
3692654012fSReza Sabdar  * bk_selector_t, the the object must be backed up.
3702654012fSReza Sabdar  *
3712654012fSReza Sabdar  */
3722654012fSReza Sabdar static boolean_t
timecmp(bk_selector_t * bksp,struct stat64 * attr)373*82049ff5SToomas Soome timecmp(bk_selector_t *bksp, struct stat64 *attr)
3742654012fSReza Sabdar {
3752654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
3762654012fSReza Sabdar 
3772654012fSReza Sabdar 	nlp = (ndmp_lbr_params_t *)bksp->bs_cookie;
3782654012fSReza Sabdar 	if (S_ISDIR(attr->st_mode) && ndmp_force_bk_dirs) {
3792654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "d(%lu)",
3802654012fSReza Sabdar 		    (uint_t)attr->st_ino);
3812654012fSReza Sabdar 		return (TRUE);
3822654012fSReza Sabdar 	}
3832654012fSReza Sabdar 	if (S_ISDIR(attr->st_mode) &&
3842654012fSReza Sabdar 	    dbm_getone(nlp->nlp_bkmap, (u_longlong_t)attr->st_ino) &&
3852654012fSReza Sabdar 	    ((NLP_ISDUMP(nlp) && ndmp_dump_path_node) ||
3862654012fSReza Sabdar 	    (NLP_ISTAR(nlp) && ndmp_tar_path_node))) {
3872654012fSReza Sabdar 		/*
3882654012fSReza Sabdar 		 * If the object is a directory and it leads to a modified
3892654012fSReza Sabdar 		 * object (that should be backed up) and for that type of
3902654012fSReza Sabdar 		 * backup the path nodes should be backed up, then return
3912654012fSReza Sabdar 		 * TRUE.
3922654012fSReza Sabdar 		 *
3932654012fSReza Sabdar 		 * This is required by some DMAs like Backup Express, which
3942654012fSReza Sabdar 		 * needs to receive ADD_NODE (for dump) or ADD_PATH (for tar)
3952654012fSReza Sabdar 		 * for the intermediate directories of a modified object.
3962654012fSReza Sabdar 		 * Other DMAs, like net_backup and net_worker, do not have such
3972654012fSReza Sabdar 		 * requirement.  This requirement makes sense for dump format
3982654012fSReza Sabdar 		 * but for 'tar' format, it does not.  In provision to the
3992654012fSReza Sabdar 		 * NDMP-v4 spec, for 'tar' format the intermediate directories
4002654012fSReza Sabdar 		 * need not to be reported.
4012654012fSReza Sabdar 		 */
4022654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "p(%lu)", (u_longlong_t)attr->st_ino);
4032654012fSReza Sabdar 		return (TRUE);
4042654012fSReza Sabdar 	}
4052654012fSReza Sabdar 	if (attr->st_mtime > bksp->bs_ldate) {
4062654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "m(%lu): %lu > %lu",
4072654012fSReza Sabdar 		    (uint_t)attr->st_ino, (uint_t)attr->st_mtime,
4082654012fSReza Sabdar 		    (uint_t)bksp->bs_ldate);
4092654012fSReza Sabdar 		return (TRUE);
4102654012fSReza Sabdar 	}
4112654012fSReza Sabdar 	if (attr->st_ctime > bksp->bs_ldate) {
4122654012fSReza Sabdar 		if (NLP_IGNCTIME(nlp)) {
4132654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "ign c(%lu): %lu > %lu",
4142654012fSReza Sabdar 			    (uint_t)attr->st_ino, (uint_t)attr->st_ctime,
4152654012fSReza Sabdar 			    (uint_t)bksp->bs_ldate);
4162654012fSReza Sabdar 			return (FALSE);
4172654012fSReza Sabdar 		}
4182654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "c(%lu): %lu > %lu",
4192654012fSReza Sabdar 		    (uint_t)attr->st_ino, (uint_t)attr->st_ctime,
4202654012fSReza Sabdar 		    (uint_t)bksp->bs_ldate);
4212654012fSReza Sabdar 		return (TRUE);
4222654012fSReza Sabdar 	}
4232654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "mc(%lu): (%lu,%lu) < %lu",
4242654012fSReza Sabdar 	    (uint_t)attr->st_ino, (uint_t)attr->st_mtime,
4252654012fSReza Sabdar 	    (uint_t)attr->st_ctime, (uint_t)bksp->bs_ldate);
4262654012fSReza Sabdar 	return (FALSE);
4272654012fSReza Sabdar }
4282654012fSReza Sabdar 
4292654012fSReza Sabdar 
4302654012fSReza Sabdar /*
4312654012fSReza Sabdar  * get_acl_info
4322654012fSReza Sabdar  *
4332654012fSReza Sabdar  * load up all the access and attribute info
4342654012fSReza Sabdar  */
4352654012fSReza Sabdar static int
get_acl_info(char * name,tlm_acls_t * tlm_acls)4362654012fSReza Sabdar get_acl_info(char *name, tlm_acls_t *tlm_acls)
4372654012fSReza Sabdar {
4382654012fSReza Sabdar 	int erc;
4392654012fSReza Sabdar 	acl_t *aclp = NULL;
4402654012fSReza Sabdar 	char *acltp;
4412654012fSReza Sabdar 
4422654012fSReza Sabdar 	erc = lstat64(name, &tlm_acls->acl_attr);
4432654012fSReza Sabdar 	if (erc != 0) {
4442654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Could not find file %s.", name);
4452654012fSReza Sabdar 		erc = TLM_NO_SOURCE_FILE;
4462654012fSReza Sabdar 		return (erc);
4472654012fSReza Sabdar 	}
4482654012fSReza Sabdar 	erc = acl_get(name, ACL_NO_TRIVIAL, &aclp);
4492654012fSReza Sabdar 	if (erc != 0) {
4502654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
4512654012fSReza Sabdar 		    "Could not read ACL for file [%s]", name);
4522654012fSReza Sabdar 		erc = TLM_NO_SOURCE_FILE;
4532654012fSReza Sabdar 		return (erc);
4542654012fSReza Sabdar 	}
4552654012fSReza Sabdar 	if (aclp && (acltp = acl_totext(aclp,
4562654012fSReza Sabdar 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
4572654012fSReza Sabdar 		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
4582654012fSReza Sabdar 		    TLM_MAX_ACL_TXT);
4592654012fSReza Sabdar 		acl_free(aclp);
4602654012fSReza Sabdar 		free(acltp);
4612654012fSReza Sabdar 	}
4622654012fSReza Sabdar 	return (erc);
4632654012fSReza Sabdar }
4642654012fSReza Sabdar /*
4652654012fSReza Sabdar  * get_dir_acl_info
4662654012fSReza Sabdar  *
4672654012fSReza Sabdar  * load up all ACL and attr info about a directory
4682654012fSReza Sabdar  */
4692654012fSReza Sabdar static int
get_dir_acl_info(char * dir,tlm_acls_t * tlm_acls,tlm_job_stats_t * js)4702654012fSReza Sabdar get_dir_acl_info(char *dir, tlm_acls_t *tlm_acls, tlm_job_stats_t *js)
4712654012fSReza Sabdar {
4722654012fSReza Sabdar 	int	erc;
4732654012fSReza Sabdar 	char	*checkpointed_dir;
4742654012fSReza Sabdar 	char	root_dir[TLM_VOLNAME_MAX_LENGTH];
4752654012fSReza Sabdar 	char	*spot;
4762654012fSReza Sabdar 	char	*fil;
4772654012fSReza Sabdar 	acl_t	*aclp = NULL;
478*82049ff5SToomas Soome 	char	*acltp;
4792654012fSReza Sabdar 
4802654012fSReza Sabdar 	checkpointed_dir = ndmp_malloc(TLM_MAX_PATH_NAME);
4812654012fSReza Sabdar 	if (checkpointed_dir == NULL)
4822654012fSReza Sabdar 		return (-1);
4832654012fSReza Sabdar 
4842654012fSReza Sabdar 	if (tlm_acls->acl_checkpointed)
4852654012fSReza Sabdar 		fil = tlm_build_snapshot_name(dir, checkpointed_dir,
4862654012fSReza Sabdar 		    js->js_job_name);
4872654012fSReza Sabdar 	else
4882654012fSReza Sabdar 		fil = dir;
4892654012fSReza Sabdar 	erc = lstat64(fil, &tlm_acls->acl_attr);
4902654012fSReza Sabdar 	if (erc != 0) {
4912654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Could not find directory %s.", dir);
4922654012fSReza Sabdar 		free(checkpointed_dir);
4932654012fSReza Sabdar 		return (-1);
4942654012fSReza Sabdar 	}
4952654012fSReza Sabdar 
4962654012fSReza Sabdar 	spot = strchr(&fil[1], '/');
4972654012fSReza Sabdar 	if (spot == NULL) {
4982654012fSReza Sabdar 		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
4992654012fSReza Sabdar 	} else {
5002654012fSReza Sabdar 		*spot = 0;
5012654012fSReza Sabdar 		(void) strlcpy(root_dir, fil, TLM_VOLNAME_MAX_LENGTH);
5022654012fSReza Sabdar 		*spot = '/';
5032654012fSReza Sabdar 	}
5042654012fSReza Sabdar 	if (strcmp(root_dir, tlm_acls->acl_root_dir) != 0) {
5052654012fSReza Sabdar 		struct stat64 attr;
5062654012fSReza Sabdar 
5072654012fSReza Sabdar 		erc = lstat64(root_dir, &attr);
5082654012fSReza Sabdar 		if (erc != 0) {
5092654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Cannot find root directory %s.",
5102654012fSReza Sabdar 			    root_dir);
5112654012fSReza Sabdar 			free(checkpointed_dir);
5122654012fSReza Sabdar 			return (-1);
5132654012fSReza Sabdar 		}
5142654012fSReza Sabdar 		(void) strlcpy(tlm_acls->acl_root_dir, root_dir,
5152654012fSReza Sabdar 		    TLM_VOLNAME_MAX_LENGTH);
5162654012fSReza Sabdar 	}
5172654012fSReza Sabdar 	erc = acl_get(fil, ACL_NO_TRIVIAL, &aclp);
5182654012fSReza Sabdar 	if (erc != 0) {
5192654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
5202654012fSReza Sabdar 		    "Could not read metadata for directory [%s]", dir);
5212654012fSReza Sabdar 		free(checkpointed_dir);
5222654012fSReza Sabdar 		return (-1);
5232654012fSReza Sabdar 	}
5242654012fSReza Sabdar 	if (aclp && (acltp = acl_totext(aclp,
5252654012fSReza Sabdar 	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
5262654012fSReza Sabdar 		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
5272654012fSReza Sabdar 		    TLM_MAX_ACL_TXT);
5282654012fSReza Sabdar 		acl_free(aclp);
5292654012fSReza Sabdar 		free(acltp);
5302654012fSReza Sabdar 	}
5312654012fSReza Sabdar 
5322654012fSReza Sabdar 	free(checkpointed_dir);
5332654012fSReza Sabdar 	return (0);
5342654012fSReza Sabdar }
5352654012fSReza Sabdar 
5362654012fSReza Sabdar /*
5372654012fSReza Sabdar  * backup_dir
5382654012fSReza Sabdar  *
5392654012fSReza Sabdar  * Create a TAR entry record for a directory
5402654012fSReza Sabdar  */
5412654012fSReza Sabdar static int
backup_dir(char * dir,tlm_acls_t * tlm_acls,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,bk_selector_t * bksp)5422654012fSReza Sabdar backup_dir(char *dir, tlm_acls_t *tlm_acls,
5432654012fSReza Sabdar     tlm_cmd_t *local_commands, tlm_job_stats_t *job_stats,
5442654012fSReza Sabdar     bk_selector_t *bksp)
5452654012fSReza Sabdar {
5462654012fSReza Sabdar 	int erc;
5472654012fSReza Sabdar 
5482654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "\"%s\"", dir);
5492654012fSReza Sabdar 
5502654012fSReza Sabdar 	erc = get_dir_acl_info(dir, tlm_acls, job_stats);
5512654012fSReza Sabdar 	if (erc != 0) {
5522654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
5532654012fSReza Sabdar 		    "Could not read directory info for %s", dir);
5542654012fSReza Sabdar 		job_stats->js_errors++;
5552654012fSReza Sabdar 	} else {
5562654012fSReza Sabdar 		/*
5572654012fSReza Sabdar 		 * See if the directory must be backed up.
5582654012fSReza Sabdar 		 */
5592654012fSReza Sabdar 		if (bksp && !(*bksp->bs_fn)(bksp, &tlm_acls->acl_attr)) {
5602654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "[%s] dir skipped", dir);
5612654012fSReza Sabdar 			return (erc);
5622654012fSReza Sabdar 		}
5632654012fSReza Sabdar 
5642654012fSReza Sabdar 		if (tm_tar_ops.tm_putdir != NULL)
5652654012fSReza Sabdar 			(void) (tm_tar_ops.tm_putdir)(dir, tlm_acls,
5662654012fSReza Sabdar 			    local_commands, job_stats);
5672654012fSReza Sabdar 	}
5682654012fSReza Sabdar 
5692654012fSReza Sabdar 	return (erc);
5702654012fSReza Sabdar }
5712654012fSReza Sabdar 
5722654012fSReza Sabdar 
5732654012fSReza Sabdar /*
5742654012fSReza Sabdar  * backup_file
5752654012fSReza Sabdar  *
5762654012fSReza Sabdar  * Create a TAR record entry for a file
5772654012fSReza Sabdar  */
5782654012fSReza Sabdar static longlong_t
backup_file(char * dir,char * name,tlm_acls_t * tlm_acls,tlm_commands_t * commands,tlm_cmd_t * local_commands,tlm_job_stats_t * job_stats,bk_selector_t * bksp)5792654012fSReza Sabdar backup_file(char *dir, char *name, tlm_acls_t *tlm_acls,
5802654012fSReza Sabdar     tlm_commands_t *commands, tlm_cmd_t *local_commands,
5812654012fSReza Sabdar     tlm_job_stats_t *job_stats, bk_selector_t *bksp)
5822654012fSReza Sabdar {
5832654012fSReza Sabdar 
5842654012fSReza Sabdar 	int erc;
5852654012fSReza Sabdar 	char buf[TLM_MAX_PATH_NAME];
5862654012fSReza Sabdar 	longlong_t rv;
5872654012fSReza Sabdar 
5882654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", dir, name);
5892654012fSReza Sabdar 
5902654012fSReza Sabdar 	(void) strlcpy(buf, dir, sizeof (buf));
5912654012fSReza Sabdar 	(void) strlcat(buf, "/", sizeof (buf));
5922654012fSReza Sabdar 	(void) strlcat(buf, name, sizeof (buf));
5932654012fSReza Sabdar 
5942654012fSReza Sabdar 	/*
5952654012fSReza Sabdar 	 * get_acl_info extracts file handle, attributes and ACLs of the file.
5962654012fSReza Sabdar 	 * This is not efficient when the attributes and file handle of
5972654012fSReza Sabdar 	 * the file is already known.
5982654012fSReza Sabdar 	 */
5992654012fSReza Sabdar 	erc = get_acl_info(buf, tlm_acls);
6002654012fSReza Sabdar 	if (erc != TLM_NO_ERRORS) {
6012654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Could not open file %s/%s.", dir, name);
6022654012fSReza Sabdar 		return (-ENOENT);
6032654012fSReza Sabdar 	}
6042654012fSReza Sabdar 
6052654012fSReza Sabdar 	/* Should the file be backed up? */
6062654012fSReza Sabdar 	if (!bksp) {
6072654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
6082654012fSReza Sabdar 		    "[%s/%s] has no selection criteria", dir, name);
6092654012fSReza Sabdar 
6102654012fSReza Sabdar 	} else if (!((*bksp->bs_fn)(bksp, &tlm_acls->acl_attr))) {
6112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "[%s/%s] file skipped", dir, name);
6122654012fSReza Sabdar 		return (0);
6132654012fSReza Sabdar 	}
6142654012fSReza Sabdar 
6152654012fSReza Sabdar 	/* Only the regular files and symbolic links can be backed up. */
6162654012fSReza Sabdar 	if (!S_ISLNK(tlm_acls->acl_attr.st_mode) &&
6172654012fSReza Sabdar 	    !S_ISREG(tlm_acls->acl_attr.st_mode)) {
6182654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
6192654012fSReza Sabdar 		    "Warning: skip backing up [%s][%s]", dir, name);
6202654012fSReza Sabdar 		return (-EINVAL);
6212654012fSReza Sabdar 	}
6222654012fSReza Sabdar 
6232654012fSReza Sabdar 
6242654012fSReza Sabdar 	if (tm_tar_ops.tm_putfile != NULL)
6252654012fSReza Sabdar 		rv = (tm_tar_ops.tm_putfile)(dir, name, tlm_acls, commands,
6262654012fSReza Sabdar 		    local_commands, job_stats);
6272654012fSReza Sabdar 
6282654012fSReza Sabdar 	return (rv);
6292654012fSReza Sabdar }
6302654012fSReza Sabdar 
6312654012fSReza Sabdar 
6322654012fSReza Sabdar 
6332654012fSReza Sabdar /*
6342654012fSReza Sabdar  * backup_work
6352654012fSReza Sabdar  *
6362654012fSReza Sabdar  * Start the NDMP backup (V2 only).
6372654012fSReza Sabdar  */
6382654012fSReza Sabdar int
backup_work(char * bk_path,tlm_job_stats_t * job_stats,ndmp_run_args_t * np,tlm_commands_t * commands,ndmp_lbr_params_t * nlp)6392654012fSReza Sabdar backup_work(char *bk_path, tlm_job_stats_t *job_stats,
6402654012fSReza Sabdar     ndmp_run_args_t *np, tlm_commands_t *commands,
6412654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
6422654012fSReza Sabdar {
6432654012fSReza Sabdar 	struct full_dir_info dir_info; /* the blob to push/pop with cstack_t */
6442654012fSReza Sabdar 	struct full_dir_info *t_dir_info, *p_dir_info;
6452654012fSReza Sabdar 	struct stat64 ret_attr; /* attributes of current file name */
6462654012fSReza Sabdar 	fs_fhandle_t ret_fh;
6472654012fSReza Sabdar 	char *first_name; /* where the first name is located */
6482654012fSReza Sabdar 	char *dname;
6492654012fSReza Sabdar 	int erc;
6502654012fSReza Sabdar 	int retval;
6512654012fSReza Sabdar 	cstack_t *stk;
6522654012fSReza Sabdar 	unsigned long fileid;
6532654012fSReza Sabdar 	tlm_acls_t tlm_acls;
6542654012fSReza Sabdar 	int dname_size;
6552654012fSReza Sabdar 	longlong_t fsize;
6562654012fSReza Sabdar 	bk_selector_t bks;
6572654012fSReza Sabdar 	tlm_cmd_t *local_commands;
658*82049ff5SToomas Soome 	long	dpos;
6592654012fSReza Sabdar 
6602654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "nr_chkpnted %d nr_ldate: %u bk_path: \"%s\"",
6612654012fSReza Sabdar 	    NLP_ISCHKPNTED(nlp), nlp->nlp_ldate, bk_path);
6622654012fSReza Sabdar 
6632654012fSReza Sabdar 	/* Get every name in this directory */
6642654012fSReza Sabdar 	dname = ndmp_malloc(TLM_MAX_PATH_NAME);
6652654012fSReza Sabdar 	if (dname == NULL)
6662654012fSReza Sabdar 		return (-ENOMEM);
6672654012fSReza Sabdar 
6682654012fSReza Sabdar 	local_commands = commands->tcs_command;
6692654012fSReza Sabdar 	retval = 0;
6702654012fSReza Sabdar 	(void) memset(&bks, 0, sizeof (bks));
6712654012fSReza Sabdar 	bks.bs_cookie = (void *)nlp;
6722654012fSReza Sabdar 	bks.bs_level = nlp->nlp_clevel;
6732654012fSReza Sabdar 	bks.bs_ldate = nlp->nlp_ldate;
6742654012fSReza Sabdar 	bks.bs_fn = timecmp;
6752654012fSReza Sabdar 
6762654012fSReza Sabdar 	/*
6772654012fSReza Sabdar 	 * should we skip the whole thing?
6782654012fSReza Sabdar 	 */
6792654012fSReza Sabdar 	if (tlm_is_excluded("", bk_path, np->nr_excls)) {
6802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s excluded", bk_path);
6812654012fSReza Sabdar 		free(dname);
6822654012fSReza Sabdar 		return (0);
6832654012fSReza Sabdar 	}
6842654012fSReza Sabdar 
6852654012fSReza Sabdar 	/*
6862654012fSReza Sabdar 	 * Search for the top-level file-directory
6872654012fSReza Sabdar 	 */
6882654012fSReza Sabdar 	if (NLP_ISCHKPNTED(nlp)) {
6892654012fSReza Sabdar 		first_name = np->nr_chkp_nm;
6902654012fSReza Sabdar 		(void) strlcpy(first_name, bk_path, TLM_MAX_PATH_NAME);
6912654012fSReza Sabdar 	} else {
6922654012fSReza Sabdar 		first_name = tlm_build_snapshot_name(bk_path, np->nr_chkp_nm,
6932654012fSReza Sabdar 		    nlp->nlp_jstat->js_job_name);
6942654012fSReza Sabdar 	}
6952654012fSReza Sabdar 
6962654012fSReza Sabdar 	(void) memset(&ret_fh, 0, sizeof (ret_fh));
69784bf06e9SReza Sabdar 	erc = fs_getstat(first_name, &ret_fh, &ret_attr);
6982654012fSReza Sabdar 	if (erc != 0) {
6992654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Path %s not found.", first_name);
7002654012fSReza Sabdar 		free(dname);
7012654012fSReza Sabdar 		return (-EINVAL);
7022654012fSReza Sabdar 	}
7032654012fSReza Sabdar 
7042654012fSReza Sabdar 	if ((stk = cstack_new()) == NULL) {
7052654012fSReza Sabdar 		free(dname);
7062654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cstack_new failed");
7072654012fSReza Sabdar 		return (-ENOMEM);
7082654012fSReza Sabdar 	}
7092654012fSReza Sabdar 	(void) strlcpy(dir_info.fd_dir_name, first_name, TLM_MAX_PATH_NAME);
7102654012fSReza Sabdar 	(void) memcpy(&dir_info.fd_dir_fh, &ret_fh, sizeof (fs_fhandle_t));
7112654012fSReza Sabdar 	p_dir_info = dup_dir_info(&dir_info);
7122654012fSReza Sabdar 
7132654012fSReza Sabdar 	/*
7142654012fSReza Sabdar 	 * Push the first name onto the stack so that we can pop it back
7152654012fSReza Sabdar 	 * off as part of the normal cycle
7162654012fSReza Sabdar 	 */
7172654012fSReza Sabdar 	if (cstack_push(stk, p_dir_info, 0)) {
7182654012fSReza Sabdar 		free(dname);
7192654012fSReza Sabdar 		free(p_dir_info);
7202654012fSReza Sabdar 		cstack_delete(stk);
7212654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cstack_push failed");
7222654012fSReza Sabdar 		return (-ENOMEM);
7232654012fSReza Sabdar 	}
7242654012fSReza Sabdar 
7252654012fSReza Sabdar 	(void) memset(&tlm_acls, 0, sizeof (tlm_acls));
7262654012fSReza Sabdar 	/*
7272654012fSReza Sabdar 	 * Did NDMP create a checkpoint?
7282654012fSReza Sabdar 	 */
7292654012fSReza Sabdar 	if (NLP_ISCHKPNTED(nlp) || fs_is_rdonly(bk_path)) {
7302654012fSReza Sabdar 		tlm_acls.acl_checkpointed = FALSE;
7312654012fSReza Sabdar 	} else {
7322654012fSReza Sabdar 		/* Use the checkpoint created by NDMP */
7332654012fSReza Sabdar 		tlm_acls.acl_checkpointed = TRUE;
7342654012fSReza Sabdar 	}
7352654012fSReza Sabdar 
7362654012fSReza Sabdar 	/*
7372654012fSReza Sabdar 	 * This is level-backup.  It never resets the archive bit.
7382654012fSReza Sabdar 	 */
7392654012fSReza Sabdar 	tlm_acls.acl_clear_archive = FALSE;
7402654012fSReza Sabdar 
7412654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "acls.chkpnt: %c acls.clear_arcbit: %c",
7422654012fSReza Sabdar 	    NDMP_YORN(tlm_acls.acl_checkpointed),
7432654012fSReza Sabdar 	    NDMP_YORN(tlm_acls.acl_clear_archive));
7442654012fSReza Sabdar 
7452654012fSReza Sabdar 	while (commands->tcs_reader == TLM_BACKUP_RUN &&
7462654012fSReza Sabdar 	    local_commands->tc_reader == TLM_BACKUP_RUN &&
7472654012fSReza Sabdar 	    cstack_pop(stk, (void **)&p_dir_info, 0) == 0) {
7482654012fSReza Sabdar 
7492654012fSReza Sabdar 		if (NLP_ISCHKPNTED(nlp))
7502654012fSReza Sabdar 			(void) strlcpy(np->nr_unchkp_nm,
7512654012fSReza Sabdar 			    p_dir_info->fd_dir_name, TLM_MAX_PATH_NAME);
7522654012fSReza Sabdar 		else
7532654012fSReza Sabdar 			(void) tlm_remove_checkpoint(p_dir_info->fd_dir_name,
7542654012fSReza Sabdar 			    np->nr_unchkp_nm);
7552654012fSReza Sabdar 
7562654012fSReza Sabdar 		(void) backup_dir(np->nr_unchkp_nm, &tlm_acls, local_commands,
7572654012fSReza Sabdar 		    job_stats, &bks);
7582654012fSReza Sabdar 
7592654012fSReza Sabdar 
7602654012fSReza Sabdar 		while (commands->tcs_reader == TLM_BACKUP_RUN &&
7612654012fSReza Sabdar 		    local_commands->tc_reader == TLM_BACKUP_RUN) {
7622654012fSReza Sabdar 
7632654012fSReza Sabdar 			dname_size = TLM_MAX_PATH_NAME - 1;
7642654012fSReza Sabdar 
7652654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
7662654012fSReza Sabdar 			    "dir_name: %s", p_dir_info->fd_dir_name);
7672654012fSReza Sabdar 
7682654012fSReza Sabdar 			(void) memset(&ret_fh, 0, sizeof (ret_fh));
7692654012fSReza Sabdar 			erc = fs_readdir(&p_dir_info->fd_dir_fh,
7702654012fSReza Sabdar 			    p_dir_info->fd_dir_name, &dpos,
77184bf06e9SReza Sabdar 			    dname, &dname_size, &ret_fh, &ret_attr);
7722654012fSReza Sabdar 			if (erc == 0) {
7732654012fSReza Sabdar 				fileid = ret_fh.fh_fid;
7742654012fSReza Sabdar 			} else {
7752654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
7762654012fSReza Sabdar 				    "Filesystem readdir in [%s]",
7772654012fSReza Sabdar 				    p_dir_info->fd_dir_name);
7782654012fSReza Sabdar 				retval = -ENOENT;
7792654012fSReza Sabdar 				break;
7802654012fSReza Sabdar 			}
7812654012fSReza Sabdar 
7822654012fSReza Sabdar 			/* an empty name size marks the end of the list */
7832654012fSReza Sabdar 			if (dname_size == 0)
7842654012fSReza Sabdar 				break;
7852654012fSReza Sabdar 			dname[dname_size] = '\0';
7862654012fSReza Sabdar 
7872654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "dname: \"%s\"", dname);
7882654012fSReza Sabdar 
7892654012fSReza Sabdar 			/*
7902654012fSReza Sabdar 			 * If name refers to a directory, push its file
7912654012fSReza Sabdar 			 *   handle onto the stack  (skip "." and "..").
7922654012fSReza Sabdar 			 */
7932654012fSReza Sabdar 			if (rootfs_dot_or_dotdot(dname)) {
7942654012fSReza Sabdar 				fileid = 0;
7952654012fSReza Sabdar 				continue;
7962654012fSReza Sabdar 			}
7972654012fSReza Sabdar 
7982654012fSReza Sabdar 			/*
7992654012fSReza Sabdar 			 * Skip the:
8002654012fSReza Sabdar 			 * non-dir entries which should not be backed up
8012654012fSReza Sabdar 			 * Or
8022654012fSReza Sabdar 			 * dir-type entries which have have nothing under
8032654012fSReza Sabdar 			 * their hierarchy to be backed up.
8042654012fSReza Sabdar 			 */
8052654012fSReza Sabdar 			if (!dbm_getone(nlp->nlp_bkmap, (u_longlong_t)fileid)) {
8062654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "Skipping %s/%s",
8072654012fSReza Sabdar 				    p_dir_info->fd_dir_name, dname);
8082654012fSReza Sabdar 				fileid = 0;
8092654012fSReza Sabdar 				continue;
8102654012fSReza Sabdar 			}
8112654012fSReza Sabdar 
8122654012fSReza Sabdar 			if (tlm_is_excluded(np->nr_unchkp_nm, dname,
8132654012fSReza Sabdar 			    np->nr_excls)) {
8142654012fSReza Sabdar 				fileid = 0;
8152654012fSReza Sabdar 				continue;
8162654012fSReza Sabdar 			}
8172654012fSReza Sabdar 			if (S_ISDIR(ret_attr.st_mode)) {
8182654012fSReza Sabdar 				/*
8192654012fSReza Sabdar 				 * only directories get pushed onto this stack,
8202654012fSReza Sabdar 				 * so we do not have to test for regular files.
8212654012fSReza Sabdar 				 */
8222654012fSReza Sabdar 				t_dir_info = tlm_new_dir_info(&ret_fh,
8232654012fSReza Sabdar 				    p_dir_info->fd_dir_name, dname);
8242654012fSReza Sabdar 				if (t_dir_info == NULL) {
8252654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
8262654012fSReza Sabdar 					    "While backing up [%s][%s]",
8272654012fSReza Sabdar 					    p_dir_info->fd_dir_name, dname);
8282654012fSReza Sabdar 				} else if (cstack_push(stk, t_dir_info,
8292654012fSReza Sabdar 				    0) != 0) {
8302654012fSReza Sabdar 					NDMP_LOG(LOG_DEBUG,
8312654012fSReza Sabdar 					    "No enough memory stack_push");
8322654012fSReza Sabdar 					retval = -ENOMEM;
8332654012fSReza Sabdar 					break;
8342654012fSReza Sabdar 				}
8352654012fSReza Sabdar 			} else if (S_ISREG(ret_attr.st_mode) ||
8362654012fSReza Sabdar 			    S_ISLNK(ret_attr.st_mode)) {
8372654012fSReza Sabdar 
8382654012fSReza Sabdar 				fsize = backup_file(np->nr_unchkp_nm, dname,
8392654012fSReza Sabdar 				    &tlm_acls, commands, local_commands,
8402654012fSReza Sabdar 				    job_stats, &bks);
8412654012fSReza Sabdar 
8422654012fSReza Sabdar 				if (fsize >= 0) {
8432654012fSReza Sabdar 					job_stats->js_files_so_far++;
8442654012fSReza Sabdar 					job_stats->js_bytes_total += fsize;
8452654012fSReza Sabdar 				} else
8462654012fSReza Sabdar 					job_stats->js_errors++;
8472654012fSReza Sabdar 				fileid = 0;
8482654012fSReza Sabdar 			}
8492654012fSReza Sabdar 		}
8502654012fSReza Sabdar 		fileid = 0;
8512654012fSReza Sabdar 		free(p_dir_info);
8522654012fSReza Sabdar 		if (retval != 0)
8532654012fSReza Sabdar 			break;
8542654012fSReza Sabdar 	}
8552654012fSReza Sabdar 
8562654012fSReza Sabdar 	free(dname);
8572654012fSReza Sabdar 
8582654012fSReza Sabdar 	while (cstack_pop(stk, (void **)&p_dir_info, 0) == 0) {
8592654012fSReza Sabdar 		free(p_dir_info);
8602654012fSReza Sabdar 	}
8612654012fSReza Sabdar 
8622654012fSReza Sabdar 	cstack_delete(stk);
8632654012fSReza Sabdar 	return (retval);
8642654012fSReza Sabdar }
8652654012fSReza Sabdar 
8662654012fSReza Sabdar 
8672654012fSReza Sabdar /*
8682654012fSReza Sabdar  * free_paths
8692654012fSReza Sabdar  *
8702654012fSReza Sabdar  * Free the path names
8712654012fSReza Sabdar  */
8722654012fSReza Sabdar static void
free_paths(ndmp_run_args_t * np)8732654012fSReza Sabdar free_paths(ndmp_run_args_t *np)
8742654012fSReza Sabdar {
8752654012fSReza Sabdar 	free(np->nr_chkp_nm);
8762654012fSReza Sabdar 	free(np->nr_unchkp_nm);
8772654012fSReza Sabdar 	free(np->nr_excls);
8782654012fSReza Sabdar }
8792654012fSReza Sabdar 
8802654012fSReza Sabdar 
8812654012fSReza Sabdar /*
8822654012fSReza Sabdar  * malloc_paths
8832654012fSReza Sabdar  *
8842654012fSReza Sabdar  * Allocate the path names (direct and checkpointed paths)
8852654012fSReza Sabdar  */
8862654012fSReza Sabdar static boolean_t
malloc_paths(ndmp_run_args_t * np)8872654012fSReza Sabdar malloc_paths(ndmp_run_args_t *np)
8882654012fSReza Sabdar {
8892654012fSReza Sabdar 	boolean_t rv;
8902654012fSReza Sabdar 
8912654012fSReza Sabdar 	rv = TRUE;
8922654012fSReza Sabdar 	np->nr_chkp_nm = ndmp_malloc(TLM_MAX_PATH_NAME);
8932654012fSReza Sabdar 	np->nr_unchkp_nm = ndmp_malloc(TLM_MAX_PATH_NAME);
8942654012fSReza Sabdar 	if (!np->nr_chkp_nm || !np->nr_unchkp_nm) {
8952654012fSReza Sabdar 		free_paths(np);
8962654012fSReza Sabdar 		rv = FALSE;
8972654012fSReza Sabdar 	} else if ((np->nr_excls = ndmpd_make_exc_list()) == NULL) {
8982654012fSReza Sabdar 		free_paths(np);
8992654012fSReza Sabdar 		rv = FALSE;
9002654012fSReza Sabdar 	}
9012654012fSReza Sabdar 	return (rv);
9022654012fSReza Sabdar }
9032654012fSReza Sabdar 
9042654012fSReza Sabdar 
9052654012fSReza Sabdar /*
9062654012fSReza Sabdar  * ndmp_backup_reader
9072654012fSReza Sabdar  *
9082654012fSReza Sabdar  * Backup reader thread which uses backup_work to read and TAR
9092654012fSReza Sabdar  * the files/dirs to be backed up (V2 only)
9102654012fSReza Sabdar  */
9112654012fSReza Sabdar static int
ndmp_backup_reader(tlm_commands_t * commands,ndmp_lbr_params_t * nlp,char * job_name)9122654012fSReza Sabdar ndmp_backup_reader(tlm_commands_t *commands, ndmp_lbr_params_t *nlp,
9132654012fSReza Sabdar     char *job_name)
9142654012fSReza Sabdar {
9152654012fSReza Sabdar 	int retval;
9162654012fSReza Sabdar 	ndmp_run_args_t np;
9172654012fSReza Sabdar 	tlm_job_stats_t *job_stats;
9182654012fSReza Sabdar 	tlm_cmd_t *local_commands;
9192654012fSReza Sabdar 
9202654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "bk_path: \"%s\"", nlp->nlp_backup_path);
9212654012fSReza Sabdar 
9222654012fSReza Sabdar 	local_commands = commands->tcs_command;
9232654012fSReza Sabdar 	(void) memset(&np, 0, sizeof (np));
9242654012fSReza Sabdar 	if (!malloc_paths(&np))
9252654012fSReza Sabdar 		return (-1);
9262654012fSReza Sabdar 	local_commands->tc_ref++;
9272654012fSReza Sabdar 	commands->tcs_reader_count++;
9282654012fSReza Sabdar 
9292654012fSReza Sabdar 	job_stats = tlm_ref_job_stats(job_name);
9302654012fSReza Sabdar 
9312654012fSReza Sabdar 	retval = backup_work(nlp->nlp_backup_path, job_stats, &np,
9322654012fSReza Sabdar 	    commands, nlp);
9332654012fSReza Sabdar 	write_tar_eof(local_commands);
9342654012fSReza Sabdar 
9352654012fSReza Sabdar 	commands->tcs_reader_count--;
9362654012fSReza Sabdar 	local_commands->tc_writer = TLM_STOP;
9372654012fSReza Sabdar 	tlm_release_reader_writer_ipc(local_commands);
9382654012fSReza Sabdar 	tlm_un_ref_job_stats(job_name);
9392654012fSReza Sabdar 
9402654012fSReza Sabdar 	free_paths(&np);
9412654012fSReza Sabdar 	return (retval);
9422654012fSReza Sabdar 
9432654012fSReza Sabdar }
9442654012fSReza Sabdar 
9452654012fSReza Sabdar 
9462654012fSReza Sabdar /*
9472654012fSReza Sabdar  * ndmp_tar_writer
9482654012fSReza Sabdar  *
9492654012fSReza Sabdar  * The backup writer thread that writes the TAR records to the
9502654012fSReza Sabdar  * tape media (V2 only)
9512654012fSReza Sabdar  */
9522654012fSReza Sabdar int
ndmp_tar_writer(ndmpd_session_t * session,ndmpd_module_params_t * mod_params,tlm_commands_t * cmds)9532654012fSReza Sabdar ndmp_tar_writer(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
9542654012fSReza Sabdar     tlm_commands_t *cmds)
9552654012fSReza Sabdar {
9562654012fSReza Sabdar 	int bidx, nw;
9572654012fSReza Sabdar 	int err;
9582654012fSReza Sabdar 	tlm_buffer_t *buf;
9592654012fSReza Sabdar 	tlm_buffers_t *bufs;
9602654012fSReza Sabdar 	tlm_cmd_t *lcmd;	/* Local command */
9612654012fSReza Sabdar 
9622654012fSReza Sabdar 	err = 0;
9632654012fSReza Sabdar 	if (session == NULL) {
9642654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "session == NULL");
9652654012fSReza Sabdar 		err = -1;
9662654012fSReza Sabdar 	} else if (mod_params == NULL) {
9672654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "mod_params == NULL");
9682654012fSReza Sabdar 		err = -1;
9692654012fSReza Sabdar 	} else if (cmds == NULL) {
9702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
9712654012fSReza Sabdar 		err = -1;
9722654012fSReza Sabdar 	}
9732654012fSReza Sabdar 
9742654012fSReza Sabdar 	if (err != 0)
9752654012fSReza Sabdar 		return (err);
9762654012fSReza Sabdar 
9772654012fSReza Sabdar 	lcmd = cmds->tcs_command;
9782654012fSReza Sabdar 	bufs = lcmd->tc_buffers;
9792654012fSReza Sabdar 
9802654012fSReza Sabdar 	lcmd->tc_ref++;
9812654012fSReza Sabdar 	cmds->tcs_writer_count++;
9822654012fSReza Sabdar 
9832654012fSReza Sabdar 	nw = 0;
9842654012fSReza Sabdar 	buf = tlm_buffer_out_buf(bufs, &bidx);
9852654012fSReza Sabdar 	while (cmds->tcs_writer != (int)TLM_ABORT &&
9862654012fSReza Sabdar 	    lcmd->tc_writer != (int)TLM_ABORT) {
9872654012fSReza Sabdar 		if (buf->tb_full) {
9882654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "w%d", bidx);
9892654012fSReza Sabdar 
9902654012fSReza Sabdar 			if (MOD_WRITE(mod_params, buf->tb_buffer_data,
9912654012fSReza Sabdar 			    buf->tb_buffer_size) != 0) {
9922654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
9932654012fSReza Sabdar 				    "Writing buffer %d, pos: %lld",
9942654012fSReza Sabdar 				    bidx, session->ns_mover.md_position);
9952654012fSReza Sabdar 				err = -1;
9962654012fSReza Sabdar 				break;
9972654012fSReza Sabdar 			}
9982654012fSReza Sabdar 
9992654012fSReza Sabdar 			tlm_buffer_mark_empty(buf);
10002654012fSReza Sabdar 			(void) tlm_buffer_advance_out_idx(bufs);
10012654012fSReza Sabdar 			buf = tlm_buffer_out_buf(bufs, &bidx);
10022654012fSReza Sabdar 			tlm_buffer_release_out_buf(bufs);
10032654012fSReza Sabdar 			nw++;
10042654012fSReza Sabdar 		} else {
10052654012fSReza Sabdar 			if (lcmd->tc_writer != TLM_BACKUP_RUN) {
10062654012fSReza Sabdar 				/* No more data is comming; time to exit. */
10072654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
10082654012fSReza Sabdar 				    "tc_writer!=TLM_BACKUP_RUN; time to exit");
10092654012fSReza Sabdar 				break;
10102654012fSReza Sabdar 			} else {
10112654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "W%d", bidx);
101286c48bbfSReza Sabdar 				tlm_buffer_in_buf_timed_wait(bufs, 100);
10132654012fSReza Sabdar 			}
10142654012fSReza Sabdar 		}
10152654012fSReza Sabdar 	}
10162654012fSReza Sabdar 
10172654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "nw: %d", nw);
10182654012fSReza Sabdar 	if (cmds->tcs_writer != (int)TLM_ABORT) {
10192654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "tcs_writer != TLM_ABORT");
10202654012fSReza Sabdar 	} else {
10212654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "tcs_writer == TLM_ABORT");
10222654012fSReza Sabdar 	}
10232654012fSReza Sabdar 
10242654012fSReza Sabdar 	if (lcmd->tc_writer != (int)TLM_ABORT) {
10252654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "tc_writer != TLM_ABORT");
10262654012fSReza Sabdar 	} else {
10272654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "tc_writer == TLM_ABORT");
10282654012fSReza Sabdar 	}
10292654012fSReza Sabdar 	cmds->tcs_writer_count--;
10302654012fSReza Sabdar 	lcmd->tc_reader = TLM_STOP;
10312654012fSReza Sabdar 	lcmd->tc_ref--;
10322654012fSReza Sabdar 
10332654012fSReza Sabdar 	return (err);
10342654012fSReza Sabdar }
10352654012fSReza Sabdar 
10362654012fSReza Sabdar 
10372654012fSReza Sabdar /*
10382654012fSReza Sabdar  * read_one_buf
10392654012fSReza Sabdar  *
10402654012fSReza Sabdar  * Read one buffer from the tape
10412654012fSReza Sabdar  */
10422654012fSReza Sabdar static int
read_one_buf(ndmpd_module_params_t * mod_params,tlm_buffers_t * bufs,tlm_buffer_t * buf)10432654012fSReza Sabdar read_one_buf(ndmpd_module_params_t *mod_params, tlm_buffers_t *bufs,
10442654012fSReza Sabdar     tlm_buffer_t *buf)
10452654012fSReza Sabdar {
10462654012fSReza Sabdar 	int rv;
10472654012fSReza Sabdar 
10482654012fSReza Sabdar 	if ((rv = MOD_READ(mod_params, buf->tb_buffer_data,
10492654012fSReza Sabdar 	    bufs->tbs_data_transfer_size)) == 0) {
10502654012fSReza Sabdar 		buf->tb_eof = buf->tb_eot = FALSE;
10512654012fSReza Sabdar 		buf->tb_errno = 0;
10522654012fSReza Sabdar 		buf->tb_buffer_size = bufs->tbs_data_transfer_size;
10532654012fSReza Sabdar 		buf->tb_buffer_spot = 0;
10542654012fSReza Sabdar 		buf->tb_full = TRUE;
10552654012fSReza Sabdar 		(void) tlm_buffer_advance_in_idx(bufs);
10562654012fSReza Sabdar 	}
10572654012fSReza Sabdar 
10582654012fSReza Sabdar 	return (rv);
10592654012fSReza Sabdar }
10602654012fSReza Sabdar 
10612654012fSReza Sabdar 
10622654012fSReza Sabdar /*
10632654012fSReza Sabdar  * ndmp_tar_reader
10642654012fSReza Sabdar  *
10652654012fSReza Sabdar  * NDMP Tar reader thread. This threads keep reading the tar
10662654012fSReza Sabdar  * file from the tape and wakes up the consumer thread to extract
10672654012fSReza Sabdar  * it on the disk
10682654012fSReza Sabdar  */
1069*82049ff5SToomas Soome void *
ndmp_tar_reader(void * ptr)1070*82049ff5SToomas Soome ndmp_tar_reader(void *ptr)
10712654012fSReza Sabdar {
10722654012fSReza Sabdar 	int bidx;
10732654012fSReza Sabdar 	int err;
10742654012fSReza Sabdar 	tlm_buffer_t *buf;
10752654012fSReza Sabdar 	tlm_buffers_t *bufs;
10762654012fSReza Sabdar 	tlm_cmd_t *lcmd;	/* Local command */
10772654012fSReza Sabdar 	ndmpd_session_t *session;
10782654012fSReza Sabdar 	ndmpd_module_params_t *mod_params;
10792654012fSReza Sabdar 	tlm_commands_t *cmds;
1080*82049ff5SToomas Soome 	ndmp_tar_reader_arg_t *argp = ptr;
10812654012fSReza Sabdar 
10822654012fSReza Sabdar 	if (!argp)
1083*82049ff5SToomas Soome 		return ((void *)(uintptr_t)-1);
10842654012fSReza Sabdar 
10852654012fSReza Sabdar 	session = argp->tr_session;
10862654012fSReza Sabdar 	mod_params = argp->tr_mod_params;
10872654012fSReza Sabdar 	cmds = argp->tr_cmds;
10882654012fSReza Sabdar 
10892654012fSReza Sabdar 	err = 0;
10902654012fSReza Sabdar 	if (session == NULL) {
10912654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "session == NULL");
10922654012fSReza Sabdar 		err = -1;
10932654012fSReza Sabdar 	} else if (cmds == NULL) {
10942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
10952654012fSReza Sabdar 		err = -1;
10962654012fSReza Sabdar 	}
10972654012fSReza Sabdar 
10982654012fSReza Sabdar 	if (err != 0) {
10992654012fSReza Sabdar 		tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
1100*82049ff5SToomas Soome 		return ((void *)(uintptr_t)err);
11012654012fSReza Sabdar 	}
11022654012fSReza Sabdar 
11032654012fSReza Sabdar 	lcmd = cmds->tcs_command;
11042654012fSReza Sabdar 	bufs = lcmd->tc_buffers;
11052654012fSReza Sabdar 
11062654012fSReza Sabdar 	lcmd->tc_ref++;
11072654012fSReza Sabdar 	cmds->tcs_reader_count++;
11082654012fSReza Sabdar 
11092654012fSReza Sabdar 	/*
11102654012fSReza Sabdar 	 * Synchronize with our parent thread.
11112654012fSReza Sabdar 	 */
11122654012fSReza Sabdar 	tlm_cmd_signal(cmds->tcs_command, TLM_TAR_READER);
11132654012fSReza Sabdar 
11142654012fSReza Sabdar 	buf = tlm_buffer_in_buf(bufs, &bidx);
11152654012fSReza Sabdar 	while (cmds->tcs_reader == TLM_RESTORE_RUN &&
11162654012fSReza Sabdar 	    lcmd->tc_reader == TLM_RESTORE_RUN) {
11172654012fSReza Sabdar 
11182654012fSReza Sabdar 		if (buf->tb_full) {
11192654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "R%d", bidx);
11202654012fSReza Sabdar 			/*
11212654012fSReza Sabdar 			 * The buffer is still full, wait for the consumer
11222654012fSReza Sabdar 			 * thread to use it.
11232654012fSReza Sabdar 			 */
11242654012fSReza Sabdar 			tlm_buffer_out_buf_timed_wait(bufs, 100);
11252654012fSReza Sabdar 			buf = tlm_buffer_in_buf(bufs, NULL);
11262654012fSReza Sabdar 		} else {
11272654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "r%d", bidx);
11282654012fSReza Sabdar 
11292654012fSReza Sabdar 			err = read_one_buf(mod_params, bufs, buf);
11302654012fSReza Sabdar 			if (err < 0) {
11312654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
11322654012fSReza Sabdar 				    "Reading buffer %d, pos: %lld",
11332654012fSReza Sabdar 				    bidx, session->ns_mover.md_position);
11342654012fSReza Sabdar 
11352654012fSReza Sabdar 				/* Force the writer to stop. */
11362654012fSReza Sabdar 				buf->tb_eot = buf->tb_eof = TRUE;
11372654012fSReza Sabdar 				break;
11382654012fSReza Sabdar 			} else if (err == 1) {
11392654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
11402654012fSReza Sabdar 				    "operation aborted or session terminated");
11412654012fSReza Sabdar 				err = 0;
11422654012fSReza Sabdar 				break;
11432654012fSReza Sabdar 			}
11442654012fSReza Sabdar 
11452654012fSReza Sabdar 			buf = tlm_buffer_in_buf(bufs, &bidx);
11462654012fSReza Sabdar 			tlm_buffer_release_in_buf(bufs);
11472654012fSReza Sabdar 		}
11482654012fSReza Sabdar 	}
11492654012fSReza Sabdar 
11502654012fSReza Sabdar 	/*
11512654012fSReza Sabdar 	 * If the consumer is waiting for us, wake it up so that it detects
11522654012fSReza Sabdar 	 * we're quiting.
11532654012fSReza Sabdar 	 */
11542654012fSReza Sabdar 	lcmd->tc_writer = TLM_STOP;
11552654012fSReza Sabdar 	tlm_buffer_release_in_buf(bufs);
11562654012fSReza Sabdar 	(void) usleep(1000);
11572654012fSReza Sabdar 
11582654012fSReza Sabdar 	/*
11592654012fSReza Sabdar 	 * Clean up.
11602654012fSReza Sabdar 	 */
11612654012fSReza Sabdar 	cmds->tcs_reader_count--;
11622654012fSReza Sabdar 	lcmd->tc_ref--;
1163*82049ff5SToomas Soome 	return ((void *)(uintptr_t)err);
11642654012fSReza Sabdar }
11652654012fSReza Sabdar 
11662654012fSReza Sabdar 
11672654012fSReza Sabdar /*
11682654012fSReza Sabdar  * ndmpd_tar_backup
11692654012fSReza Sabdar  *
11702654012fSReza Sabdar  * Check must have been done that backup work directory exists, before
11712654012fSReza Sabdar  * calling this function.
11722654012fSReza Sabdar  */
11732654012fSReza Sabdar static int
ndmpd_tar_backup(ndmpd_session_t * session,ndmpd_module_params_t * mod_params,ndmp_lbr_params_t * nlp)11742654012fSReza Sabdar ndmpd_tar_backup(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
11752654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
11762654012fSReza Sabdar {
11772654012fSReza Sabdar 	char jname[TLM_MAX_BACKUP_JOB_NAME];
11782654012fSReza Sabdar 	int err;
11792654012fSReza Sabdar 	tlm_commands_t *cmds;
11802654012fSReza Sabdar 
11812654012fSReza Sabdar 	if (mod_params->mp_operation != NDMP_DATA_OP_BACKUP) {
11822654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
11832654012fSReza Sabdar 		    "mod_params->mp_operation != NDMP_DATA_OP_BACKUP");
11842654012fSReza Sabdar 		err = -1;
11852654012fSReza Sabdar 	} else {
11862654012fSReza Sabdar 		if (ndmpd_mark_inodes_v2(session, nlp) != 0)
11872654012fSReza Sabdar 			err = -1;
11882654012fSReza Sabdar 		else if (ndmp_get_bk_dir_ino(nlp))
11892654012fSReza Sabdar 			err = -1;
11902654012fSReza Sabdar 		else
11912654012fSReza Sabdar 			err = 0;
11922654012fSReza Sabdar 	}
11932654012fSReza Sabdar 
11942654012fSReza Sabdar 	if (err != 0)
11952654012fSReza Sabdar 		return (err);
11962654012fSReza Sabdar 
11972654012fSReza Sabdar 	(void) ndmp_new_job_name(jname);
11982654012fSReza Sabdar 	if (backup_create_structs(session, jname) < 0)
11992654012fSReza Sabdar 		return (-1);
12002654012fSReza Sabdar 
12012654012fSReza Sabdar 	nlp->nlp_jstat->js_start_ltime = time(NULL);
12022654012fSReza Sabdar 	nlp->nlp_jstat->js_start_time = nlp->nlp_jstat->js_start_ltime;
12032654012fSReza Sabdar 	nlp->nlp_jstat->js_chkpnt_time = nlp->nlp_cdate;
12042654012fSReza Sabdar 
12052654012fSReza Sabdar 	if (!session->ns_data.dd_abort) {
12062654012fSReza Sabdar 
12072654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
12082654012fSReza Sabdar 		cmds->tcs_reader = cmds->tcs_writer = TLM_BACKUP_RUN;
12092654012fSReza Sabdar 		cmds->tcs_command->tc_reader = TLM_BACKUP_RUN;
12102654012fSReza Sabdar 		cmds->tcs_command->tc_writer = TLM_BACKUP_RUN;
12112654012fSReza Sabdar 
12122654012fSReza Sabdar 		if (ndmp_write_utf8magic(cmds->tcs_command) < 0) {
12132654012fSReza Sabdar 			backup_release_structs(session);
12142654012fSReza Sabdar 			return (-1);
12152654012fSReza Sabdar 		}
12162654012fSReza Sabdar 
12172654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" started.",
12182654012fSReza Sabdar 		    nlp->nlp_backup_path);
12192654012fSReza Sabdar 
12202654012fSReza Sabdar 		err = ndmp_backup_reader(cmds, nlp, jname);
12212654012fSReza Sabdar 		if (err != 0) {
12222654012fSReza Sabdar 			backup_release_structs(session);
12232654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Launch ndmp_backup_reader: %s",
12242654012fSReza Sabdar 			    strerror(err));
12252654012fSReza Sabdar 			return (-1);
12262654012fSReza Sabdar 		}
12272654012fSReza Sabdar 
12282654012fSReza Sabdar 		/* Act as the writer thread. */
12292654012fSReza Sabdar 		err = ndmp_tar_writer(session, mod_params, cmds);
12302654012fSReza Sabdar 
12312654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
12322654012fSReza Sabdar 
12332654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
12342654012fSReza Sabdar 		    "Runtime [%s] %llu bytes (%llu): %d seconds",
12352654012fSReza Sabdar 		    nlp->nlp_backup_path, session->ns_mover.md_data_written,
12362654012fSReza Sabdar 		    session->ns_mover.md_data_written,
12372654012fSReza Sabdar 		    nlp->nlp_jstat->js_stop_time -
12382654012fSReza Sabdar 		    nlp->nlp_jstat->js_start_ltime);
12392654012fSReza Sabdar 		MOD_LOG(mod_params,
12402654012fSReza Sabdar 		    "Runtime [%s] %llu bytes (%llu): %d seconds",
12412654012fSReza Sabdar 		    nlp->nlp_backup_path, session->ns_mover.md_data_written,
12422654012fSReza Sabdar 		    session->ns_mover.md_data_written,
12432654012fSReza Sabdar 		    nlp->nlp_jstat->js_stop_time -
12442654012fSReza Sabdar 		    nlp->nlp_jstat->js_start_ltime);
12452654012fSReza Sabdar 
12462654012fSReza Sabdar 		if (session->ns_data.dd_abort)
12472654012fSReza Sabdar 			err = -1;
12482654012fSReza Sabdar 
12492654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" finished. (%d)",
12502654012fSReza Sabdar 		    nlp->nlp_backup_path, err);
12512654012fSReza Sabdar 	} else {
12522654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
12532654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Backing up \"%s\" aborted.",
12542654012fSReza Sabdar 		    nlp->nlp_backup_path);
12552654012fSReza Sabdar 		err = 0;
12562654012fSReza Sabdar 	}
12572654012fSReza Sabdar 
12582654012fSReza Sabdar 	backup_release_structs(session);
12592654012fSReza Sabdar 	return (err);
12602654012fSReza Sabdar }
12612654012fSReza Sabdar 
12622654012fSReza Sabdar 
12632654012fSReza Sabdar /*
12642654012fSReza Sabdar  * ndmpd_tar_restore
12652654012fSReza Sabdar  *
12662654012fSReza Sabdar  * Restore function that launches TAR reader thread to read from the
12672654012fSReza Sabdar  * tape and writes the extracted files/dirs to the filesystem
12682654012fSReza Sabdar  */
12692654012fSReza Sabdar static int
ndmpd_tar_restore(ndmpd_session_t * session,ndmpd_module_params_t * mod_params,ndmp_lbr_params_t * nlp)12702654012fSReza Sabdar ndmpd_tar_restore(ndmpd_session_t *session, ndmpd_module_params_t *mod_params,
12712654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
12722654012fSReza Sabdar {
12732654012fSReza Sabdar 	char jname[TLM_MAX_BACKUP_JOB_NAME];
12742654012fSReza Sabdar 	char *rspath;
12752654012fSReza Sabdar 	int err;
12762654012fSReza Sabdar 	tlm_commands_t *cmds;
12772654012fSReza Sabdar 	ndmp_tar_reader_arg_t arg;
12782654012fSReza Sabdar 	tlm_backup_restore_arg_t tlm_arg;
12792654012fSReza Sabdar 	ndmp_name *ent;
12802654012fSReza Sabdar 	pthread_t rdtp, wrtp;
12812654012fSReza Sabdar 	int i;
12822654012fSReza Sabdar 
12832654012fSReza Sabdar 	if (mod_params->mp_operation != NDMP_DATA_OP_RECOVER) {
12842654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
12852654012fSReza Sabdar 		    "mod_params->mp_operation != NDMP_DATA_OP_RECOVER");
12862654012fSReza Sabdar 		return (-1);
12872654012fSReza Sabdar 	}
12882654012fSReza Sabdar 
12892654012fSReza Sabdar 	if (nlp->nlp_restore_path[0] != '\0')
12902654012fSReza Sabdar 		rspath = nlp->nlp_restore_path;
12912654012fSReza Sabdar 	else if (nlp->nlp_restore_bk_path[0] != '\0')
12922654012fSReza Sabdar 		rspath = nlp->nlp_restore_bk_path;
12932654012fSReza Sabdar 	else
12942654012fSReza Sabdar 		rspath = "";
12952654012fSReza Sabdar 
12962654012fSReza Sabdar 	(void) ndmp_new_job_name(jname);
12972654012fSReza Sabdar 	if (restore_create_structs(session, jname) < 0)
12982654012fSReza Sabdar 		return (-1);
12992654012fSReza Sabdar 
13002654012fSReza Sabdar 	nlp->nlp_jstat->js_start_ltime = time(NULL);
13012654012fSReza Sabdar 	nlp->nlp_jstat->js_start_time = time(NULL);
13022654012fSReza Sabdar 
13032654012fSReza Sabdar 	if (!session->ns_data.dd_abort) {
13042654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
13052654012fSReza Sabdar 		cmds->tcs_reader = cmds->tcs_writer = TLM_RESTORE_RUN;
13062654012fSReza Sabdar 		cmds->tcs_command->tc_reader = TLM_RESTORE_RUN;
13072654012fSReza Sabdar 		cmds->tcs_command->tc_writer = TLM_RESTORE_RUN;
13082654012fSReza Sabdar 
13092654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" started.", rspath);
13102654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring from %s tape(s).",
13112654012fSReza Sabdar 		    ndmp_data_get_mover_mode(session));
13122654012fSReza Sabdar 
13132654012fSReza Sabdar 		arg.tr_session = session;
13142654012fSReza Sabdar 		arg.tr_mod_params = mod_params;
13152654012fSReza Sabdar 		arg.tr_cmds = cmds;
13162654012fSReza Sabdar 
1317*82049ff5SToomas Soome 		err = pthread_create(&rdtp, NULL, ndmp_tar_reader, &arg);
13182654012fSReza Sabdar 		if (err == 0) {
13192654012fSReza Sabdar 			tlm_cmd_wait(cmds->tcs_command, TLM_TAR_READER);
13202654012fSReza Sabdar 		} else {
13212654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Launch ndmp_tar_reader: %m");
13222654012fSReza Sabdar 			return (-1);
13232654012fSReza Sabdar 		}
13242654012fSReza Sabdar 
13252654012fSReza Sabdar 		if (!ndmp_check_utf8magic(cmds->tcs_command)) {
13262654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "UTF8Magic not found!");
13272654012fSReza Sabdar 		} else {
13282654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "UTF8Magic found");
13292654012fSReza Sabdar 		}
13302654012fSReza Sabdar 
13312654012fSReza Sabdar 		(void) memset(&tlm_arg, 0, sizeof (tlm_backup_restore_arg_t));
13322654012fSReza Sabdar 		(void) pthread_barrier_init(&tlm_arg.ba_barrier, 0, 2);
13332654012fSReza Sabdar 
13342654012fSReza Sabdar 		/*
13352654012fSReza Sabdar 		 * Set up restore parameters
13362654012fSReza Sabdar 		 */
13372654012fSReza Sabdar 		tlm_arg.ba_commands = cmds;
13382654012fSReza Sabdar 		tlm_arg.ba_cmd = cmds->tcs_command;
13392654012fSReza Sabdar 		tlm_arg.ba_job = nlp->nlp_jstat->js_job_name;
13402654012fSReza Sabdar 		tlm_arg.ba_dir = nlp->nlp_restore_path;
13412654012fSReza Sabdar 		for (i = 0; i < nlp->nlp_nfiles; i++) {
13422654012fSReza Sabdar 			ent = (ndmp_name *)MOD_GETNAME(mod_params, i);
13432654012fSReza Sabdar 			tlm_arg.ba_sels[i] = ent->name;
13442654012fSReza Sabdar 		}
13452654012fSReza Sabdar 
13462654012fSReza Sabdar 
13472654012fSReza Sabdar 		if (tm_tar_ops.tm_getfile != NULL) {
1348*82049ff5SToomas Soome 			err = pthread_create(&wrtp, NULL, tm_tar_ops.tm_getfile,
1349*82049ff5SToomas Soome 			    &tlm_arg);
13502654012fSReza Sabdar 		} else {
13512654012fSReza Sabdar 			(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13522654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
13532654012fSReza Sabdar 			    "Thread create tm_getfile: ops NULL");
13542654012fSReza Sabdar 			return (-1);
13552654012fSReza Sabdar 		}
13562654012fSReza Sabdar 		if (err == 0) {
13572654012fSReza Sabdar 			(void) pthread_barrier_wait(&tlm_arg.ba_barrier);
13582654012fSReza Sabdar 		} else {
13592654012fSReza Sabdar 			(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13602654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "thread create tm_getfile: %m");
13612654012fSReza Sabdar 			return (-1);
13622654012fSReza Sabdar 		}
13632654012fSReza Sabdar 
13642654012fSReza Sabdar 		(void) pthread_join(rdtp, NULL);
13652654012fSReza Sabdar 		(void) pthread_join(wrtp, NULL);
13662654012fSReza Sabdar 		(void) pthread_barrier_destroy(&tlm_arg.ba_barrier);
13672654012fSReza Sabdar 
13682654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
13692654012fSReza Sabdar 
13702654012fSReza Sabdar 		/* Send the list of un-recovered files/dirs to the client.  */
13712654012fSReza Sabdar 		(void) send_unrecovered_list(mod_params, nlp);
13722654012fSReza Sabdar 
13732654012fSReza Sabdar 		ndmp_stop_local_reader(session, cmds);
13742654012fSReza Sabdar 		ndmp_wait_for_reader(cmds);
13752654012fSReza Sabdar 		ndmp_stop_remote_reader(session);
13762654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" finished. (%d)",
13772654012fSReza Sabdar 		    rspath, err);
13782654012fSReza Sabdar 	} else {
13792654012fSReza Sabdar 		nlp->nlp_jstat->js_stop_time = time(NULL);
13802654012fSReza Sabdar 
13812654012fSReza Sabdar 		/* nothing restored. */
13822654012fSReza Sabdar 		(void) send_unrecovered_list(mod_params, nlp);
13832654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Restoring to \"%s\" aborted.",
13842654012fSReza Sabdar 		    rspath);
13852654012fSReza Sabdar 		err = -1;
13862654012fSReza Sabdar 	}
13872654012fSReza Sabdar 
13882654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_restore_path);
13892654012fSReza Sabdar 	backup_release_structs(session);
13902654012fSReza Sabdar 
13912654012fSReza Sabdar 	return (err);
13922654012fSReza Sabdar }
13932654012fSReza Sabdar 
13942654012fSReza Sabdar 
13952654012fSReza Sabdar /*
13962654012fSReza Sabdar  * prefixdir
13972654012fSReza Sabdar  *
13982654012fSReza Sabdar  * Extract the path for a given full path entry
13992654012fSReza Sabdar  */
14002654012fSReza Sabdar static char *
prefixdir(char * dir,char * suffix)14012654012fSReza Sabdar prefixdir(char *dir, char *suffix)
14022654012fSReza Sabdar {
14032654012fSReza Sabdar 	static char tmp[TLM_MAX_PATH_NAME];
14042654012fSReza Sabdar 	char *tend, *send; /* tmp and suffix end */
14052654012fSReza Sabdar 
14062654012fSReza Sabdar 	if (dir == NULL || suffix == NULL)
14072654012fSReza Sabdar 		return (NULL);
14082654012fSReza Sabdar 
14092654012fSReza Sabdar 	if (*suffix == '\0')
14102654012fSReza Sabdar 		return (dir);
14112654012fSReza Sabdar 
14122654012fSReza Sabdar 	if (*dir == '\0')
14132654012fSReza Sabdar 		return (NULL);
14142654012fSReza Sabdar 
14152654012fSReza Sabdar 	(void) strlcpy(tmp, dir, TLM_MAX_PATH_NAME);
14162654012fSReza Sabdar 	tend = &tmp[strlen(tmp)];
14172654012fSReza Sabdar 	send = &suffix[strlen(suffix)];
14182654012fSReza Sabdar 
14192654012fSReza Sabdar 	/*
14202654012fSReza Sabdar 	 * Move backward as far as the last part of the dir and
14212654012fSReza Sabdar 	 * the suffix match.
14222654012fSReza Sabdar 	 */
14232654012fSReza Sabdar 	while (tend >= tmp && send >= suffix)
14242654012fSReza Sabdar 		if (*tend == *send)
14252654012fSReza Sabdar 			tend--, send--;
14262654012fSReza Sabdar 		else
14272654012fSReza Sabdar 			break;
14282654012fSReza Sabdar 
14292654012fSReza Sabdar 	*++tend = '\0';
14302654012fSReza Sabdar 	return (tmp);
14312654012fSReza Sabdar }
14322654012fSReza Sabdar 
14332654012fSReza Sabdar 
14342654012fSReza Sabdar /*
14352654012fSReza Sabdar  * get_nfiles
14362654012fSReza Sabdar  *
14372654012fSReza Sabdar  * Get the count of files to be restored
14382654012fSReza Sabdar  */
14392654012fSReza Sabdar static int
get_nfiles(ndmpd_session_t * session,ndmpd_module_params_t * params)14402654012fSReza Sabdar get_nfiles(ndmpd_session_t *session, ndmpd_module_params_t *params)
14412654012fSReza Sabdar {
14422654012fSReza Sabdar 	if (session->ns_data.dd_nlist_len == 0) {
14432654012fSReza Sabdar 		MOD_LOG(params, "Error: nothing specified to be restored.\n");
14442654012fSReza Sabdar 		return (-1);
14452654012fSReza Sabdar 	}
14462654012fSReza Sabdar 
14472654012fSReza Sabdar 	return (session->ns_data.dd_nlist_len);
14482654012fSReza Sabdar }
14492654012fSReza Sabdar 
14502654012fSReza Sabdar 
14512654012fSReza Sabdar /*
14522654012fSReza Sabdar  * get_restore_dest
14532654012fSReza Sabdar  *
14542654012fSReza Sabdar  * Get the full pathname of where the entries should be restored to.
14552654012fSReza Sabdar  */
14562654012fSReza Sabdar static char *
get_restore_dest(ndmpd_module_params_t * params)14572654012fSReza Sabdar get_restore_dest(ndmpd_module_params_t *params)
14582654012fSReza Sabdar {
14592654012fSReza Sabdar 	ndmp_name *ent;
14602654012fSReza Sabdar 	char *cp;
14612654012fSReza Sabdar 
14622654012fSReza Sabdar 	/*
14632654012fSReza Sabdar 	 * Destination of restore:
14642654012fSReza Sabdar 	 * NetBackup of Veritas(C) sends the entries like this:
14652654012fSReza Sabdar 	 *
14662654012fSReza Sabdar 	 *	ent[i].name: is the relative pathname of what is selected in
14672654012fSReza Sabdar 	 *	  the GUI.
14682654012fSReza Sabdar 	 *	ent[i].dest: is the full pathname of where the dir/file must
14692654012fSReza Sabdar 	 *	  be restored to.
14702654012fSReza Sabdar 	 *	ent[i].ssi: 0
14712654012fSReza Sabdar 	 *	ent[i].fh_info: 0
14722654012fSReza Sabdar 	 *
14732654012fSReza Sabdar 	 */
14742654012fSReza Sabdar 	ent = (ndmp_name *)MOD_GETNAME(params, 0);
14752654012fSReza Sabdar 	cp = prefixdir(ent->dest, ent->name);
14762654012fSReza Sabdar 	if (cp == NULL) {
14772654012fSReza Sabdar 		MOD_LOG(params, "Error: empty restore path.\n");
14782654012fSReza Sabdar 		return (NULL);
14792654012fSReza Sabdar 	}
14802654012fSReza Sabdar 
14812654012fSReza Sabdar 	return (cp);
14822654012fSReza Sabdar }
14832654012fSReza Sabdar 
14842654012fSReza Sabdar 
14852654012fSReza Sabdar /*
14862654012fSReza Sabdar  * correct_ents
14872654012fSReza Sabdar  *
14882654012fSReza Sabdar  * Correct the entries in the restore list by appending the appropriate
14892654012fSReza Sabdar  * path to them
14902654012fSReza Sabdar  */
14912654012fSReza Sabdar static int
correct_ents(ndmpd_module_params_t * params,int n,char * bkpath)14922654012fSReza Sabdar correct_ents(ndmpd_module_params_t *params, int n, char *bkpath)
14932654012fSReza Sabdar {
14942654012fSReza Sabdar 	char *cp, *pathname;
14952654012fSReza Sabdar 	int i, len, rv;
14962654012fSReza Sabdar 	ndmp_name *ent;
14972654012fSReza Sabdar 
14982654012fSReza Sabdar 	if ((pathname = ndmp_malloc(TLM_MAX_PATH_NAME)) == NULL) {
14992654012fSReza Sabdar 		MOD_LOG(params, "Error: insufficient memory.\n");
15002654012fSReza Sabdar 		return (-1);
15012654012fSReza Sabdar 	}
15022654012fSReza Sabdar 
15032654012fSReza Sabdar 	rv = 0;
15042654012fSReza Sabdar 	/* Append the backup path to all the "ent[].name"s. */
15052654012fSReza Sabdar 	for (i = 0; i < n; i++) {
15062654012fSReza Sabdar 		ent = (ndmp_name *)MOD_GETNAME(params, i);
15072654012fSReza Sabdar 
15082654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
15092654012fSReza Sabdar 		    "Old: ent[%d].name: \"%s\"", i, ent->name);
15102654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
15112654012fSReza Sabdar 		    "Old: ent[%d].dest: \"%s\"", i, ent->dest);
15122654012fSReza Sabdar 
15132654012fSReza Sabdar 		/* remove trailing slash */
15142654012fSReza Sabdar 		len = strlen(ent->name);
15152654012fSReza Sabdar 		if (ent->name[len - 1] == '/')
15162654012fSReza Sabdar 			ent->name[len - 1] = '\0';
15172654012fSReza Sabdar 
15182654012fSReza Sabdar 		if (!tlm_cat_path(pathname, bkpath, ent->name)) {
15192654012fSReza Sabdar 			MOD_LOG(params, "Error: path too long.\n");
15202654012fSReza Sabdar 			rv = -1;
15212654012fSReza Sabdar 			break;
15222654012fSReza Sabdar 		}
15232654012fSReza Sabdar 
15242654012fSReza Sabdar 		/* Make a copy of the new string and save it in ent->name. */
15252654012fSReza Sabdar 		cp = strdup(pathname);
15262654012fSReza Sabdar 		if (cp == NULL) {
15272654012fSReza Sabdar 			MOD_LOG(params, "Error: insufficient memory.\n");
15282654012fSReza Sabdar 			rv = -1;
15292654012fSReza Sabdar 			break;
15302654012fSReza Sabdar 		}
15312654012fSReza Sabdar 		free(ent->name);
15322654012fSReza Sabdar 		ent->name = cp;
15332654012fSReza Sabdar 
15342654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
15352654012fSReza Sabdar 		    "New: ent[%d].name: \"%s\"", i, ent->name);
15362654012fSReza Sabdar 	}
15372654012fSReza Sabdar 
15382654012fSReza Sabdar 	free(pathname);
15392654012fSReza Sabdar 	return (rv);
15402654012fSReza Sabdar }
15412654012fSReza Sabdar 
15422654012fSReza Sabdar 
15432654012fSReza Sabdar /*
15442654012fSReza Sabdar  * check_restore_paths
15452654012fSReza Sabdar  *
15462654012fSReza Sabdar  * Go through the restore list and check the validity of the
15472654012fSReza Sabdar  * restore path.
15482654012fSReza Sabdar  */
15492654012fSReza Sabdar static int
check_restore_paths(ndmpd_module_params_t * params,int n,char * rspath)15502654012fSReza Sabdar check_restore_paths(ndmpd_module_params_t *params, int n, char *rspath)
15512654012fSReza Sabdar {
15522654012fSReza Sabdar 	int i, rv;
15532654012fSReza Sabdar 	ndmp_name *ent;
15542654012fSReza Sabdar 
15552654012fSReza Sabdar 	rv = 0;
15562654012fSReza Sabdar 	if (rspath != NULL && *rspath != '\0') {
15572654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "rspath: \"%s\"", rspath);
15582654012fSReza Sabdar 		if (!fs_volexist(rspath)) {
15592654012fSReza Sabdar 			MOD_LOG(params,
15602654012fSReza Sabdar 			    "Error: Invalid volume name for restore.");
15612654012fSReza Sabdar 			rv = -1;
15622654012fSReza Sabdar 		}
15632654012fSReza Sabdar 	} else {
15642654012fSReza Sabdar 		for (i = 0; i < n; i++) {
15652654012fSReza Sabdar 			ent = (ndmp_name *)MOD_GETNAME(params, i);
15662654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
15672654012fSReza Sabdar 			    "ent[%d].name: \"%s\"", i, ent->name);
15682654012fSReza Sabdar 
15692654012fSReza Sabdar 			if (!fs_volexist(ent->name)) {
15702654012fSReza Sabdar 				MOD_LOG(params,
15712654012fSReza Sabdar 				    "Error: Invalid volume name for restore.",
15722654012fSReza Sabdar 				    ent->name);
15732654012fSReza Sabdar 				rv = -1;
15742654012fSReza Sabdar 				break;
15752654012fSReza Sabdar 			}
15762654012fSReza Sabdar 		}
15772654012fSReza Sabdar 	}
15782654012fSReza Sabdar 
15792654012fSReza Sabdar 	return (rv);
15802654012fSReza Sabdar }
15812654012fSReza Sabdar 
15822654012fSReza Sabdar 
15832654012fSReza Sabdar /*
15842654012fSReza Sabdar  * check_backup_dir_validity
15852654012fSReza Sabdar  *
15862654012fSReza Sabdar  * Check if the backup directory is valid. Make sure it exists and
15872654012fSReza Sabdar  * is writable. Check for snapshot and readonly cases.
15882654012fSReza Sabdar  */
15892654012fSReza Sabdar static int
check_backup_dir_validity(ndmpd_module_params_t * params,char * bkpath)15902654012fSReza Sabdar check_backup_dir_validity(ndmpd_module_params_t *params, char *bkpath)
15912654012fSReza Sabdar {
15922654012fSReza Sabdar 	char *msg;
15932654012fSReza Sabdar 	int rv;
15942654012fSReza Sabdar 	struct stat64 st;
15952654012fSReza Sabdar 
15962654012fSReza Sabdar 	rv = NDMP_NO_ERR;
15972654012fSReza Sabdar 	if (stat64(bkpath, &st) < 0) {
15982654012fSReza Sabdar 		msg = strerror(errno);
15992654012fSReza Sabdar 		MOD_LOG(params, "Error: stat(%s): %s.\n", bkpath, msg);
16002654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
16012654012fSReza Sabdar 	} else if (!S_ISDIR(st.st_mode)) {
16022654012fSReza Sabdar 		MOD_LOG(params, "Error: %s is not a directory.\n", bkpath);
16032654012fSReza Sabdar 		rv = NDMP_ILLEGAL_ARGS_ERR;
16042654012fSReza Sabdar 	} else if (fs_is_rdonly(bkpath) && !fs_is_chkpntvol(bkpath) &&
16052654012fSReza Sabdar 	    fs_is_chkpnt_enabled(bkpath)) {
16062654012fSReza Sabdar 		MOD_LOG(params, "Error: %s is not a checkpointed path.\n",
16072654012fSReza Sabdar 		    bkpath);
16082654012fSReza Sabdar 		rv = NDMP_BAD_FILE_ERR;
16092654012fSReza Sabdar 	}
16102654012fSReza Sabdar 
16112654012fSReza Sabdar 	return (rv);
16122654012fSReza Sabdar }
16132654012fSReza Sabdar 
16142654012fSReza Sabdar 
16152654012fSReza Sabdar /*
16162654012fSReza Sabdar  * ndmp_backup_extract_params
16172654012fSReza Sabdar  *
16182654012fSReza Sabdar  * Go through the backup parameters and check the validity
16192654012fSReza Sabdar  * for each one. Then set the NLP flags according to the parameters.
16202654012fSReza Sabdar  */
16212654012fSReza Sabdar int
ndmp_backup_extract_params(ndmpd_session_t * session,ndmpd_module_params_t * params)16222654012fSReza Sabdar ndmp_backup_extract_params(ndmpd_session_t *session,
16232654012fSReza Sabdar     ndmpd_module_params_t *params)
16242654012fSReza Sabdar {
16252654012fSReza Sabdar 	char *cp;
16262654012fSReza Sabdar 	int rv;
16272654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
16282654012fSReza Sabdar 
16292654012fSReza Sabdar 	/* Extract directory to be backed up from env variables */
16302654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
16312654012fSReza Sabdar 		MOD_LOG(params, "Error: Internal error: nlp == NULL.\n");
16322654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
16332654012fSReza Sabdar 	}
16348c4f9701SJanice Chang 	if ((nlp->nlp_backup_path = get_backup_path_v2(params)) == NULL)
16352654012fSReza Sabdar 		return (NDMP_FILE_NOT_FOUND_ERR);
16362654012fSReza Sabdar 
16372654012fSReza Sabdar 	if ((rv = check_backup_dir_validity(params,
16382654012fSReza Sabdar 	    nlp->nlp_backup_path)) != NDMP_NO_ERR)
16392654012fSReza Sabdar 		return (rv);
16402654012fSReza Sabdar 
16412654012fSReza Sabdar 	/* Should the st_ctime be ignored when backing up? */
16422654012fSReza Sabdar 	if (ndmp_ignore_ctime) {
16432654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ignoring st_ctime");
16442654012fSReza Sabdar 		NLP_SET(nlp, NLPF_IGNCTIME);
16452654012fSReza Sabdar 	} else
16462654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_IGNCTIME);
16472654012fSReza Sabdar 
16482654012fSReza Sabdar 	/* Should the st_lmtime be ignored when backing up? */
16492654012fSReza Sabdar 	if (ndmp_include_lmtime) {
16502654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "including st_lmtime");
16512654012fSReza Sabdar 		NLP_SET(nlp, NLPF_INCLMTIME);
16522654012fSReza Sabdar 	} else
16532654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_INCLMTIME);
16542654012fSReza Sabdar 
16552654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "flags %x", nlp->nlp_flags);
16562654012fSReza Sabdar 
16572654012fSReza Sabdar 	/* Is backup history requested? */
16582654012fSReza Sabdar 	cp = MOD_GETENV(params, "HIST");
16592654012fSReza Sabdar 	if (cp == NULL) {
16602654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(HIST) not specified");
16612654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_FH);
16622654012fSReza Sabdar 	} else {
16632654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(HIST): \"%s\"", cp);
16642654012fSReza Sabdar 
16652654012fSReza Sabdar 		if (strchr("t_ty_y", *cp))
16662654012fSReza Sabdar 			NLP_SET(nlp, NLPF_FH);
16672654012fSReza Sabdar 		else
16682654012fSReza Sabdar 			NLP_UNSET(nlp, NLPF_FH);
16692654012fSReza Sabdar 	}
16702654012fSReza Sabdar 
16712654012fSReza Sabdar 	nlp->nlp_clevel = 0;
16722654012fSReza Sabdar 	/* Is it an incremental backup? */
16732654012fSReza Sabdar 	cp = MOD_GETENV(params, "LEVEL");
16742654012fSReza Sabdar 	if (cp == NULL) {
16752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
16762654012fSReza Sabdar 		    "env(LEVEL) not specified, default to 0");
16772654012fSReza Sabdar 	} else if (*cp < '0' || *cp > '9' || *(cp+1) != '\0') {
16782654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid backup level '%s'", cp);
16792654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
16802654012fSReza Sabdar 	} else
16812654012fSReza Sabdar 		nlp->nlp_clevel = *cp - '0';
16822654012fSReza Sabdar 
16832654012fSReza Sabdar 	/* Extract last backup time from the dumpdates file */
16842654012fSReza Sabdar 	nlp->nlp_llevel = nlp->nlp_clevel;
16852654012fSReza Sabdar 	nlp->nlp_ldate = 0;
16862654012fSReza Sabdar 	if (ndmpd_get_dumptime(nlp->nlp_backup_path, &nlp->nlp_llevel,
16872654012fSReza Sabdar 	    &nlp->nlp_ldate) < 0) {
16882654012fSReza Sabdar 		MOD_LOG(params, "Error: getting dumpdate for %s level %d\n",
16892654012fSReza Sabdar 		    nlp->nlp_backup_path, nlp->nlp_clevel);
16902654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
16912654012fSReza Sabdar 	}
16922654012fSReza Sabdar 
16932654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG,
16942654012fSReza Sabdar 	    "Date of this level %d on \"%s\": %s",
16952654012fSReza Sabdar 	    nlp->nlp_clevel, nlp->nlp_backup_path, cctime(&nlp->nlp_cdate));
16962654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG,
16972654012fSReza Sabdar 	    "Date of last level %d on \"%s\": %s",
16982654012fSReza Sabdar 	    nlp->nlp_llevel, nlp->nlp_backup_path, cctime(&nlp->nlp_ldate));
16992654012fSReza Sabdar 
17002654012fSReza Sabdar 	/* Should the dumpdate file be updated? */
17012654012fSReza Sabdar 	cp = MOD_GETENV(params, "UPDATE");
17022654012fSReza Sabdar 	if (cp == NULL) {
17032654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
17042654012fSReza Sabdar 		    "env(UPDATE) not specified, default to TRUE");
17052654012fSReza Sabdar 		NLP_SET(nlp, NLPF_UPDATE);
17062654012fSReza Sabdar 	} else {
17072654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(UPDATE): \"%s\"", cp);
17082654012fSReza Sabdar 		if (strchr("t_ty_y", *cp) != NULL)
17092654012fSReza Sabdar 			NLP_SET(nlp, NLPF_UPDATE);
17102654012fSReza Sabdar 		else
17112654012fSReza Sabdar 			NLP_UNSET(nlp, NLPF_UPDATE);
17122654012fSReza Sabdar 	}
17132654012fSReza Sabdar 
17142654012fSReza Sabdar 	return (NDMP_NO_ERR);
17152654012fSReza Sabdar }
17162654012fSReza Sabdar 
17172654012fSReza Sabdar 
17182654012fSReza Sabdar 
17192654012fSReza Sabdar /*
17202654012fSReza Sabdar  * log_bk_params_v2
17212654012fSReza Sabdar  *
17222654012fSReza Sabdar  * Dump the value of the parameters in the log file for debugging.
17232654012fSReza Sabdar  */
17242654012fSReza Sabdar void
log_bk_params_v2(ndmpd_session_t * session,ndmpd_module_params_t * params,ndmp_lbr_params_t * nlp)17252654012fSReza Sabdar log_bk_params_v2(ndmpd_session_t *session, ndmpd_module_params_t *params,
17262654012fSReza Sabdar     ndmp_lbr_params_t *nlp)
17272654012fSReza Sabdar {
17282654012fSReza Sabdar 	MOD_LOG(params, "Date of this level %d on \"%s\": %s\n",
17292654012fSReza Sabdar 	    nlp->nlp_clevel, nlp->nlp_backup_path, cctime(&nlp->nlp_cdate));
17302654012fSReza Sabdar 	MOD_LOG(params, "Date of last level %d on \"%s\": %s\n",
17312654012fSReza Sabdar 	    nlp->nlp_llevel, nlp->nlp_backup_path, cctime(&nlp->nlp_ldate));
17322654012fSReza Sabdar 
17332654012fSReza Sabdar 	MOD_LOG(params, "Backing up: \"%s\".\n", nlp->nlp_backup_path);
17342654012fSReza Sabdar 	MOD_LOG(params, "Record size: %d\n", session->ns_mover.md_record_size);
17352654012fSReza Sabdar 	MOD_LOG(params, "File history: %c.\n",
17362654012fSReza Sabdar 	    NDMP_YORN(NLP_ISSET(nlp, NLPF_FH)));
17372654012fSReza Sabdar 	MOD_LOG(params, "Update: %s\n",
17382654012fSReza Sabdar 	    NLP_ISSET(nlp, NLPF_UPDATE) ? "TRUE" : "FALSE");
17392654012fSReza Sabdar 
17402654012fSReza Sabdar }
17412654012fSReza Sabdar 
17422654012fSReza Sabdar 
17432654012fSReza Sabdar /*
17442654012fSReza Sabdar  * same_path
17452654012fSReza Sabdar  *
17462654012fSReza Sabdar  * Find out if the paths are the same regardless of the ending slash
17472654012fSReza Sabdar  *
17482654012fSReza Sabdar  * Examples :
17492654012fSReza Sabdar  *   /a/b/c == /a/b/c
17502654012fSReza Sabdar  *   /a/b/c/ == /a/b/c
17512654012fSReza Sabdar  *   /a/b/c == /a/b/c/
17522654012fSReza Sabdar  */
17532654012fSReza Sabdar static boolean_t
same_path(char * s,char * t)17542654012fSReza Sabdar same_path(char *s, char *t)
17552654012fSReza Sabdar {
17562654012fSReza Sabdar 	boolean_t rv;
17572654012fSReza Sabdar 	int slen, tlen;
17582654012fSReza Sabdar 
17592654012fSReza Sabdar 	rv = FALSE;
17602654012fSReza Sabdar 	slen = strlen(s);
17612654012fSReza Sabdar 	tlen = strlen(t);
17622654012fSReza Sabdar 	if (slen == tlen && strcmp(s, t) == 0) {
17632654012fSReza Sabdar 		rv = TRUE;
17642654012fSReza Sabdar 	} else {
17652654012fSReza Sabdar 		if (slen == tlen - 1) {
17662654012fSReza Sabdar 			if (strncmp(s, t, slen) == 0 && t[tlen - 1] == '/')
17672654012fSReza Sabdar 				rv = TRUE;
17682654012fSReza Sabdar 		} else if (tlen == slen -1) {
17692654012fSReza Sabdar 			if (strncmp(s, t, tlen) == 0 && s[slen - 1] == '/')
17702654012fSReza Sabdar 				rv = TRUE;
17712654012fSReza Sabdar 		}
17722654012fSReza Sabdar 	}
17732654012fSReza Sabdar 
17742654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "rv: %d", rv);
17752654012fSReza Sabdar 	return (rv);
17762654012fSReza Sabdar }
17772654012fSReza Sabdar 
17782654012fSReza Sabdar 
17792654012fSReza Sabdar /*
17802654012fSReza Sabdar  * ndmp_restore_extract_params
17812654012fSReza Sabdar  *
17822654012fSReza Sabdar  * Go through the restore parameters and check them and extract them
17832654012fSReza Sabdar  * by setting NLP flags and other values.
17842654012fSReza Sabdar  *
17852654012fSReza Sabdar  * Parameters:
17862654012fSReza Sabdar  *
17872654012fSReza Sabdar  * Returns:
17882654012fSReza Sabdar  *   0: on success
17892654012fSReza Sabdar  *  -1: otherwise
17902654012fSReza Sabdar  */
17912654012fSReza Sabdar int
ndmp_restore_extract_params(ndmpd_session_t * session,ndmpd_module_params_t * params)17922654012fSReza Sabdar ndmp_restore_extract_params(ndmpd_session_t *session,
17932654012fSReza Sabdar     ndmpd_module_params_t *params)
17942654012fSReza Sabdar {
17952654012fSReza Sabdar 	char *bkpath, *rspath;
17962654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
17972654012fSReza Sabdar 
17982654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
17992654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
18002654012fSReza Sabdar 		return (-1);
18012654012fSReza Sabdar 	}
18022654012fSReza Sabdar 
18032654012fSReza Sabdar 	/* Extract directory from where the backup was made. */
18048c4f9701SJanice Chang 	if ((bkpath = get_backup_path_v2(params)) == NULL)
18052654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18062654012fSReza Sabdar 
18072654012fSReza Sabdar 	nlp->nlp_restore_bk_path = bkpath;
18082654012fSReza Sabdar 
18092654012fSReza Sabdar 	/* The number of the selections. */
18102654012fSReza Sabdar 	if ((nlp->nlp_nfiles = get_nfiles(session, params)) == 0)
18112654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18122654012fSReza Sabdar 
18132654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "nfiles: %d", nlp->nlp_nfiles);
18142654012fSReza Sabdar 
18152654012fSReza Sabdar 	if ((rspath = get_restore_dest(params)) == NULL)
18162654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18172654012fSReza Sabdar 
18182654012fSReza Sabdar 	if (fs_is_rdonly(rspath)) {
18192654012fSReza Sabdar 		MOD_LOG(params,
18202654012fSReza Sabdar 		    "Error: Can't restore to a read-only volume: \"%s\"\n",
18212654012fSReza Sabdar 		    rspath);
18222654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18232654012fSReza Sabdar 	}
18242654012fSReza Sabdar 	if (fs_is_chkpntvol(rspath)) {
18252654012fSReza Sabdar 		MOD_LOG(params,
18262654012fSReza Sabdar 		    "Error: Can't restore to a checkpoint: \"%s\"\n", rspath);
18272654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18282654012fSReza Sabdar 	}
18292654012fSReza Sabdar 
18302654012fSReza Sabdar 	if (same_path(bkpath, rspath))
18312654012fSReza Sabdar 		rspath = "";
18322654012fSReza Sabdar 
18332654012fSReza Sabdar 	if ((nlp->nlp_restore_path = strdup(rspath)) == NULL)
18342654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
18352654012fSReza Sabdar 
18362654012fSReza Sabdar 	bkpath = trim_name(bkpath);
18372654012fSReza Sabdar 	if (correct_ents(params, nlp->nlp_nfiles, bkpath) < 0) {
18382654012fSReza Sabdar 		free(nlp->nlp_restore_path);
18392654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18402654012fSReza Sabdar 	}
18412654012fSReza Sabdar 
18422654012fSReza Sabdar 	if (check_restore_paths(params, nlp->nlp_nfiles, rspath) < 0) {
18432654012fSReza Sabdar 		free(nlp->nlp_restore_path);
18442654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
18452654012fSReza Sabdar 	}
18462654012fSReza Sabdar 
18472654012fSReza Sabdar 	MOD_LOG(params, "Restoring %d files.\n", nlp->nlp_nfiles);
18482654012fSReza Sabdar 	MOD_LOG(params, "Restoring to: \"%s\".\n", nlp->nlp_restore_path);
18492654012fSReza Sabdar 	MOD_LOG(params, "Record size: %d\n", session->ns_mover.md_record_size);
18502654012fSReza Sabdar 
18512654012fSReza Sabdar 	return (NDMP_NO_ERR);
18522654012fSReza Sabdar }
18532654012fSReza Sabdar 
18542654012fSReza Sabdar /*
18552654012fSReza Sabdar  * ndmpd_tar_backup_starter (V2 only)
18562654012fSReza Sabdar  *
18572654012fSReza Sabdar  * The main backup starter function. It creates a snapshot if necessary
18582654012fSReza Sabdar  * and calls ndmp_tar_backup to perform the actual backup. It does the cleanup
18592654012fSReza Sabdar  * and release the snapshot at the end.
18602654012fSReza Sabdar  */
1861*82049ff5SToomas Soome void *
ndmpd_tar_backup_starter(void * arg)18628c4f9701SJanice Chang ndmpd_tar_backup_starter(void *arg)
18632654012fSReza Sabdar {
18648c4f9701SJanice Chang 	ndmpd_module_params_t *mod_params = arg;
18652654012fSReza Sabdar 	int err;
18662654012fSReza Sabdar 	ndmpd_session_t *session;
18672654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
18682654012fSReza Sabdar 
18692654012fSReza Sabdar 	session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie);
18702654012fSReza Sabdar 	*(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
18712654012fSReza Sabdar 	ndmp_session_ref(session);
18722654012fSReza Sabdar 
18732654012fSReza Sabdar 	err = 0;
18742654012fSReza Sabdar 	if (fs_is_chkpntvol(nlp->nlp_backup_path) ||
18752654012fSReza Sabdar 	    fs_is_rdonly(nlp->nlp_backup_path) ||
18762654012fSReza Sabdar 	    !fs_is_chkpnt_enabled(nlp->nlp_backup_path))
18772654012fSReza Sabdar 		NLP_SET(nlp, NLPF_CHKPNTED_PATH);
18782654012fSReza Sabdar 	else {
18792654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_CHKPNTED_PATH);
1880876b86efSReza Sabdar 		if (ndmp_create_snapshot(nlp->nlp_backup_path,
18812654012fSReza Sabdar 		    nlp->nlp_jstat->js_job_name) < 0) {
18822654012fSReza Sabdar 			MOD_LOG(mod_params,
18832654012fSReza Sabdar 			    "Error: creating checkpoint on %s\n",
18842654012fSReza Sabdar 			    nlp->nlp_backup_path);
18852654012fSReza Sabdar 			/* -1 causes halt reason to become internal error. */
18862654012fSReza Sabdar 			err = -1;
18872654012fSReza Sabdar 		}
18882654012fSReza Sabdar 	}
18892654012fSReza Sabdar 
18902654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "NLPF_CHKPNTED_PATH: %c",
18912654012fSReza Sabdar 	    NDMP_YORN(NLP_ISCHKPNTED(nlp)));
18922654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "err: %d, update %c",
18932654012fSReza Sabdar 	    err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
18942654012fSReza Sabdar 
18952654012fSReza Sabdar 	if (err == 0) {
18962654012fSReza Sabdar 		err = ndmp_get_cur_bk_time(nlp, &nlp->nlp_cdate,
18972654012fSReza Sabdar 		    nlp->nlp_jstat->js_job_name);
18982654012fSReza Sabdar 		if (err != 0) {
18992654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "err %d", err);
19002654012fSReza Sabdar 		} else {
19012654012fSReza Sabdar 			log_bk_params_v2(session, mod_params, nlp);
19022654012fSReza Sabdar 			err = ndmpd_tar_backup(session, mod_params, nlp);
19032654012fSReza Sabdar 		}
19042654012fSReza Sabdar 	}
19052654012fSReza Sabdar 
19062654012fSReza Sabdar 	if (nlp->nlp_bkmap >= 0) {
19072654012fSReza Sabdar 		(void) dbm_free(nlp->nlp_bkmap);
19082654012fSReza Sabdar 		nlp->nlp_bkmap = -1;
19092654012fSReza Sabdar 	}
19102654012fSReza Sabdar 
19112654012fSReza Sabdar 	if (!NLP_ISCHKPNTED(nlp))
1912876b86efSReza Sabdar 		(void) ndmp_remove_snapshot(nlp->nlp_backup_path,
19132654012fSReza Sabdar 		    nlp->nlp_jstat->js_job_name);
19142654012fSReza Sabdar 
19152654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "err %d, update %c",
19162654012fSReza Sabdar 	    err, NDMP_YORN(NLP_SHOULD_UPDATE(nlp)));
19172654012fSReza Sabdar 
19182654012fSReza Sabdar 	if (err == 0 && NLP_SHOULD_UPDATE(nlp)) {
19192654012fSReza Sabdar 		if (ndmpd_put_dumptime(nlp->nlp_backup_path, nlp->nlp_clevel,
19202654012fSReza Sabdar 		    nlp->nlp_cdate) < 0) {
19212654012fSReza Sabdar 			err = EPERM;
19222654012fSReza Sabdar 			MOD_LOG(mod_params,
19232654012fSReza Sabdar 			    "Error: updating the dumpdates file on %s\n",
19242654012fSReza Sabdar 			    nlp->nlp_backup_path);
19252654012fSReza Sabdar 		}
19262654012fSReza Sabdar 	}
19272654012fSReza Sabdar 
19282654012fSReza Sabdar 	MOD_DONE(mod_params, err);
19292654012fSReza Sabdar 
19302654012fSReza Sabdar 	/* nlp_params is allocated in start_backup() */
19312654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
19322654012fSReza Sabdar 
19332654012fSReza Sabdar 	NS_DEC(nbk);
19342654012fSReza Sabdar 	ndmp_session_unref(session);
1935*82049ff5SToomas Soome 	return ((void *)(uintptr_t)err);
19362654012fSReza Sabdar }
19372654012fSReza Sabdar 
19382654012fSReza Sabdar 
19392654012fSReza Sabdar /*
19402654012fSReza Sabdar  * ndmpd_tar_backup_abort
19412654012fSReza Sabdar  *
19422654012fSReza Sabdar  * Abort the running backup by stopping the reader thread (V2 only)
19432654012fSReza Sabdar  */
19442654012fSReza Sabdar int
ndmpd_tar_backup_abort(void * module_cookie)19452654012fSReza Sabdar ndmpd_tar_backup_abort(void *module_cookie)
19462654012fSReza Sabdar {
19472654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
19482654012fSReza Sabdar 
19492654012fSReza Sabdar 	nlp = (ndmp_lbr_params_t *)module_cookie;
19502654012fSReza Sabdar 	if (nlp != NULL && nlp->nlp_session != NULL) {
19512654012fSReza Sabdar 		if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
19522654012fSReza Sabdar 		    NDMP_ADDR_TCP && nlp->nlp_session->ns_data.dd_sock != -1) {
19532654012fSReza Sabdar 			(void) close(nlp->nlp_session->ns_data.dd_sock);
19542654012fSReza Sabdar 			nlp->nlp_session->ns_data.dd_sock = -1;
19552654012fSReza Sabdar 		}
19562654012fSReza Sabdar 		ndmp_stop_reader_thread(nlp->nlp_session);
19572654012fSReza Sabdar 	}
19582654012fSReza Sabdar 
19592654012fSReza Sabdar 	return (0);
19602654012fSReza Sabdar }
19612654012fSReza Sabdar 
19622654012fSReza Sabdar /*
19632654012fSReza Sabdar  * ndmpd_tar_restore_starter
19642654012fSReza Sabdar  *
19652654012fSReza Sabdar  * Starts the restore by running ndmpd_tar_restore function (V2 only)
19662654012fSReza Sabdar  */
19672654012fSReza Sabdar 
1968*82049ff5SToomas Soome void *
ndmpd_tar_restore_starter(void * arg)19698c4f9701SJanice Chang ndmpd_tar_restore_starter(void *arg)
19702654012fSReza Sabdar {
19718c4f9701SJanice Chang 	ndmpd_module_params_t *mod_params = arg;
19722654012fSReza Sabdar 	int err;
19732654012fSReza Sabdar 	ndmpd_session_t *session;
19742654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
19752654012fSReza Sabdar 
19762654012fSReza Sabdar 	session = (ndmpd_session_t *)(mod_params->mp_daemon_cookie);
19772654012fSReza Sabdar 	*(mod_params->mp_module_cookie) = nlp = ndmp_get_nlp(session);
19782654012fSReza Sabdar 	ndmp_session_ref(session);
19792654012fSReza Sabdar 
19802654012fSReza Sabdar 	err = ndmpd_tar_restore(session, mod_params, nlp);
19812654012fSReza Sabdar 	MOD_DONE(mod_params, err);
19822654012fSReza Sabdar 
19832654012fSReza Sabdar 	/* nlp_params is allocated in start_recover() */
19842654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
19852654012fSReza Sabdar 
19862654012fSReza Sabdar 	NS_DEC(nrs);
19872654012fSReza Sabdar 	ndmp_session_unref(session);
1988*82049ff5SToomas Soome 	return ((void *)(uintptr_t)err);
19892654012fSReza Sabdar }
19902654012fSReza Sabdar 
19912654012fSReza Sabdar 
19922654012fSReza Sabdar /*
19932654012fSReza Sabdar  * ndmpd_tar_restore_abort
19942654012fSReza Sabdar  *
19952654012fSReza Sabdar  * Aborts the restore operation by stopping the writer thread (V2 only)
19962654012fSReza Sabdar  */
19972654012fSReza Sabdar int
ndmpd_tar_restore_abort(void * module_cookie)19982654012fSReza Sabdar ndmpd_tar_restore_abort(void *module_cookie)
19992654012fSReza Sabdar {
20002654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
20012654012fSReza Sabdar 
20022654012fSReza Sabdar 	nlp = (ndmp_lbr_params_t *)module_cookie;
20032654012fSReza Sabdar 	if (nlp != NULL && nlp->nlp_session != NULL) {
2004a23888a3SJan Kryl 		(void) mutex_lock(&nlp->nlp_mtx);
20052654012fSReza Sabdar 		if (nlp->nlp_session->ns_data.dd_mover.addr_type ==
20062654012fSReza Sabdar 		    NDMP_ADDR_TCP && nlp->nlp_session->ns_data.dd_sock != -1) {
20072654012fSReza Sabdar 			(void) close(nlp->nlp_session->ns_data.dd_sock);
20082654012fSReza Sabdar 			nlp->nlp_session->ns_data.dd_sock = -1;
20092654012fSReza Sabdar 		}
2010a23888a3SJan Kryl 		(void) cond_broadcast(&nlp->nlp_cv);
2011a23888a3SJan Kryl 		(void) mutex_unlock(&nlp->nlp_mtx);
20122654012fSReza Sabdar 		ndmp_stop_writer_thread(nlp->nlp_session);
20132654012fSReza Sabdar 	}
20142654012fSReza Sabdar 
20152654012fSReza Sabdar 	return (0);
20162654012fSReza Sabdar }
2017