Exemple #1
0
/*
 * backup_dir
 *
 * Create a TAR entry record for a directory
 */
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)
{
	int erc;

	NDMP_LOG(LOG_DEBUG, "\"%s\"", dir);

	erc = get_dir_acl_info(dir, tlm_acls, job_stats);
	if (erc != 0) {
		NDMP_LOG(LOG_DEBUG,
		    "Could not read directory info for %s", dir);
		job_stats->js_errors++;
	} else {
		/*
		 * See if the directory must be backed up.
		 */
		if (bksp && !(*bksp->bs_fn)(bksp, &tlm_acls->acl_attr)) {
			NDMP_LOG(LOG_DEBUG, "[%s] dir skipped", dir);
			return (erc);
		}

		if (tm_tar_ops.tm_putdir != NULL)
			(void) (tm_tar_ops.tm_putdir)(dir, tlm_acls,
			    local_commands, job_stats);
	}

	return (erc);
}
Exemple #2
0
/*
 * check_restore_paths
 *
 * Go through the restore list and check the validity of the
 * restore path.
 */
static int
check_restore_paths(ndmpd_module_params_t *params, int n, char *rspath)
{
	int i, rv;
	ndmp_name *ent;

	rv = 0;
	if (rspath != NULL && *rspath != '\0') {
		NDMP_LOG(LOG_DEBUG, "rspath: \"%s\"", rspath);
		if (!fs_volexist(rspath)) {
			MOD_LOG(params,
			    "Error: Invalid volume name for restore.");
			rv = -1;
		}
	} else {
		for (i = 0; i < n; i++) {
			ent = (ndmp_name *)MOD_GETNAME(params, i);
			NDMP_LOG(LOG_DEBUG,
			    "ent[%d].name: \"%s\"", i, ent->name);

			if (!fs_volexist(ent->name)) {
				MOD_LOG(params,
				    "Error: Invalid volume name for restore.",
				    ent->name);
				rv = -1;
				break;
			}
		}
	}

	return (rv);
}
Exemple #3
0
int
snapshot_release(char *volname, char *snapname, char *jname,
    boolean_t recursive)
{
	zfs_handle_t *zhp;
	char *p;
	int rv = 0;

	if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
		NDMP_LOG(LOG_ERR, "Cannot open volume %s", volname);
		return (-1);
	}

	p = strchr(snapname, '@') + 1;
	if (zfs_release(zhp, p, jname, recursive) != 0) {
		NDMP_LOG(LOG_DEBUG, "Cannot release snapshot %s", p);
		rv = -1;
	}
	if (cleanup_fd != -1) {
		(void) close(cleanup_fd);
		cleanup_fd = -1;
	}
	zfs_close(zhp);
	return (rv);
}
Exemple #4
0
/*
 * Get the checkpoint (snapshot) creation time.
 * This is necessary to check for checkpoints not being stale.
 */
int
tlm_get_chkpnt_time(char *path, int auto_checkpoint, time_t *tp, char *jname)
{
    char volname[TLM_VOLNAME_MAX_LENGTH];
    char chk_name[PATH_MAX];
    char *cp_nm;

    NDMP_LOG(LOG_DEBUG, "path [%s] auto_checkpoint: %d",
             path, auto_checkpoint);

    if (path == NULL || *path == '\0' || tp == NULL)
        return (-1);

    if (get_zfsvolname(volname, TLM_VOLNAME_MAX_LENGTH,
                       path) == -1)
        return (-1);

    if (auto_checkpoint) {
        NDMP_LOG(LOG_DEBUG, "volname [%s]", volname);
        (void) snprintf(chk_name, PATH_MAX, "%s", jname);
        return (chkpnt_creationtime_bypattern(volname, chk_name, tp));
    }
    cp_nm = strchr(volname, '@');
    NDMP_LOG(LOG_DEBUG, "volname [%s] cp_nm [%s]", volname, cp_nm);

    return (chkpnt_creationtime_bypattern(volname, cp_nm, tp));
}
Exemple #5
0
/*ARGSUSED*/
void
ndmpd_scsi_reset_device_v2(ndmp_connection_t *connection, void *body)
{
	ndmp_scsi_reset_device_reply reply;


	ndmpd_session_t *session = ndmp_get_client_data(connection);
	struct uscsi_cmd  cmd;

	if (session->ns_scsi.sd_devid == -1) {
		NDMP_LOG(LOG_ERR, "SCSI device is not open.");
		reply.error = NDMP_DEV_NOT_OPEN_ERR;
	} else {
		reply.error = NDMP_NO_ERR;
		(void) memset((void*)&cmd, 0, sizeof (cmd));
		cmd.uscsi_flags |= USCSI_RESET;
		if (ioctl(session->ns_scsi.sd_devid, USCSICMD, &cmd) < 0) {
			NDMP_LOG(LOG_ERR, "USCSI reset failed: %m.");
			NDMP_LOG(LOG_DEBUG,
			    "ioctl(USCSICMD) USCSI_RESET failed: %m.");
			reply.error = NDMP_IO_ERR;
		}
	}

	ndmp_send_reply(connection, (void *) &reply,
	    "sending scsi_reset_device reply");
}
Exemple #6
0
/*
 * Put a hold on snapshot
 */
int
snapshot_hold(char *volname, char *snapname, char *jname, boolean_t recursive)
{
	zfs_handle_t *zhp;
	char *p;

	if ((zhp = zfs_open(zlibh, volname, ZFS_TYPE_DATASET)) == 0) {
		NDMP_LOG(LOG_ERR, "Cannot open volume %s.", volname);
		return (-1);
	}

	if (cleanup_fd == -1 && (cleanup_fd = open(ZFS_DEV,
	    O_RDWR|O_EXCL)) < 0) {
		NDMP_LOG(LOG_ERR, "Cannot open dev %d", errno);
		zfs_close(zhp);
		return (-1);
	}

	p = strchr(snapname, '@') + 1;
	if (zfs_hold(zhp, p, jname, recursive, cleanup_fd) != 0) {
		NDMP_LOG(LOG_ERR, "Cannot hold snapshot %s", p);
		zfs_close(zhp);
		return (-1);
	}
	zfs_close(zhp);
	return (0);
}
Exemple #7
0
/*
 * get_acl_info
 *
 * load up all the access and attribute info
 */
static int
get_acl_info(char *name, tlm_acls_t *tlm_acls)
{
	int erc;
	acl_t *aclp = NULL;
	char *acltp;

	erc = lstat64(name, &tlm_acls->acl_attr);
	if (erc != 0) {
		NDMP_LOG(LOG_ERR, "Could not find file %s.", name);
		erc = TLM_NO_SOURCE_FILE;
		return (erc);
	}
	erc = acl_get(name, ACL_NO_TRIVIAL, &aclp);
	if (erc != 0) {
		NDMP_LOG(LOG_DEBUG,
		    "Could not read ACL for file [%s]", name);
		erc = TLM_NO_SOURCE_FILE;
		return (erc);
	}
	if (aclp && (acltp = acl_totext(aclp,
	    ACL_APPEND_ID | ACL_SID_FMT | ACL_COMPACT_FMT)) != NULL) {
		(void) strlcpy(tlm_acls->acl_info.attr_info, acltp,
		    TLM_MAX_ACL_TXT);
		acl_free(aclp);
		free(acltp);
	}
	return (erc);
}
Exemple #8
0
/*
 * cstack_pop
 *
 * Pop an element off the stack. Set up the data and len references for
 * the caller, advance the stack head and free the popped stack node.
 *
 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
 */
int
cstack_pop(cstack_t *stk, void **data, int *len)
{
	cstack_t *stk_node;

	if (stk == NULL) {
		NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
		return (-1);
	}

	if ((stk_node = stk->next) == NULL) {
		NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
		return (-1);
	}

	if (data)
		*data = stk_node->data;

	if (len)
		*len = stk_node->len;

	stk->next = stk_node->next;
	NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node);

	free(stk_node);
	return (0);
}
Exemple #9
0
/*
 * backup_create_structs
 *
 * Allocate the structures before performing backup
 *
 * Parameters:
 *   sesison (input) - session handle
 *   jname (input) - backup job name
 *
 * Returns:
 *   0: on success
 *  -1: otherwise
 */
static int
backup_create_structs(ndmpd_session_t *session, char *jname)
{
	int n;
	long xfer_size;
	ndmp_lbr_params_t *nlp;
	tlm_commands_t *cmds;

	if ((nlp = ndmp_get_nlp(session)) == NULL) {
		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
		return (-1);
	}

	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
		NDMP_LOG(LOG_DEBUG, "Creating job stats");
		return (-1);
	}

	cmds = &nlp->nlp_cmds;
	(void) memset(cmds, 0, sizeof (*cmds));

	xfer_size = ndmp_buffer_get_size(session);
	if (xfer_size < 512*KILOBYTE) {
		/*
		 * Read multiple of mover_record_size near to 512K.  This
		 * will prevent the data being copied in the mover buffer
		 * when we write the data.
		 */
		if ((n = (512 * KILOBYTE/xfer_size)) <= 0)
			n = 1;
		xfer_size *= n;
		NDMP_LOG(LOG_DEBUG, "Adjusted read size: %d", xfer_size);
	}

	cmds->tcs_command = tlm_create_reader_writer_ipc(TRUE, xfer_size);
	if (cmds->tcs_command == NULL) {
		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
		tlm_un_ref_job_stats(jname);
		return (-1);
	}

	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
	    ndmpd_file_history_path,
	    ndmpd_file_history_dir,
	    ndmpd_file_history_node);
	if (nlp->nlp_logcallbacks == NULL) {
		tlm_release_reader_writer_ipc(cmds->tcs_command);
		tlm_un_ref_job_stats(jname);
		return (-1);
	}
	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);

	return (0);
}
Exemple #10
0
/*
 * backup_file
 *
 * Create a TAR record entry for a file
 */
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)
{

	int erc;
	char buf[TLM_MAX_PATH_NAME];
	longlong_t rv;

	NDMP_LOG(LOG_DEBUG, "\"%s/%s\"", dir, name);

	(void) strlcpy(buf, dir, sizeof (buf));
	(void) strlcat(buf, "/", sizeof (buf));
	(void) strlcat(buf, name, sizeof (buf));

	/*
	 * get_acl_info extracts file handle, attributes and ACLs of the file.
	 * This is not efficient when the attributes and file handle of
	 * the file is already known.
	 */
	erc = get_acl_info(buf, tlm_acls);
	if (erc != TLM_NO_ERRORS) {
		NDMP_LOG(LOG_ERR, "Could not open file %s/%s.", dir, name);
		return (-ENOENT);
	}

	/* Should the file be backed up? */
	if (!bksp) {
		NDMP_LOG(LOG_DEBUG,
		    "[%s/%s] has no selection criteria", dir, name);

	} else if (!((*bksp->bs_fn)(bksp, &tlm_acls->acl_attr))) {
		NDMP_LOG(LOG_DEBUG, "[%s/%s] file skipped", dir, name);
		return (0);
	}

	/* Only the regular files and symbolic links can be backed up. */
	if (!S_ISLNK(tlm_acls->acl_attr.st_mode) &&
	    !S_ISREG(tlm_acls->acl_attr.st_mode)) {
		NDMP_LOG(LOG_DEBUG,
		    "Warning: skip backing up [%s][%s]", dir, name);
		return (-EINVAL);
	}


	if (tm_tar_ops.tm_putfile != NULL)
		rv = (tm_tar_ops.tm_putfile)(dir, name, tlm_acls, commands,
		    local_commands, job_stats);

	return (rv);
}
Exemple #11
0
/*
 * Print the list of array of strings in the backup log
 */
void
tlm_log_list(char *title, char **lpp)
{
    int i;

    if (!lpp)
        return;

    NDMP_LOG(LOG_DEBUG, "%s:", title);

    for (i = 0; *lpp; lpp++, i++)
        NDMP_LOG(LOG_DEBUG, "%d: [%s]", i, *lpp);
}
/*
 * ndmp_run
 *
 * Creates a socket for listening and accepting connections
 * from NDMP clients.
 * Accepts connections and passes each connection to the connection
 * handler.
 *
 * Parameters:
 *   port (input)   -  NDMP server port.
 *		     If 0, the port number will be retrieved from
 *		     the network service database. If not found there,
 *		     the default NDMP port number (from ndmp.x)
 *		     will be used.
 *   handler (input) - connection handler function.
 *
 * Returns:
 *   This function normally never returns unless there's error.
 *   -1 : error
 *
 * Notes:
 *   This function does not return unless encountering an error
 *   related to the listen socket.
 */
int
ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func)
{
	int ns;
	int on;
	int server_socket;
	unsigned int ipaddr;
	struct sockaddr_in sin;
	ndmpd_worker_arg_t *argp;

	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = INADDR_ANY;
	sin.sin_port = htons(port);

	if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		NDMP_LOG(LOG_DEBUG, "Socket error: %m");
		return (-1);
	}

	on = 1;
	(void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR,
	    (char *)&on, sizeof (on));


	if (bind(server_socket, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
		NDMP_LOG(LOG_DEBUG, "bind error: %m");
		(void) close(server_socket);
		return (-1);
	}
	if (listen(server_socket, 5) < 0) {
		NDMP_LOG(LOG_DEBUG, "listen error: %m");
		(void) close(server_socket);
		return (-1);
	}

	for (; ; ) {
		if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) {
			NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m");
			continue;
		}
		NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns);
		set_socket_options(ns);

		if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) {
			argp->nw_sock = ns;
			argp->nw_ipaddr = ipaddr;
			argp->nw_con_handler_func = con_handler_func;
			(void) ndmp_start_worker(argp);
		}
	}
}
Exemple #13
0
/*
 * correct_ents
 *
 * Correct the entries in the restore list by appending the appropriate
 * path to them
 */
static int
correct_ents(ndmpd_module_params_t *params, int n, char *bkpath)
{
	char *cp, *pathname;
	int i, len, rv;
	ndmp_name *ent;

	if ((pathname = ndmp_malloc(TLM_MAX_PATH_NAME)) == NULL) {
		MOD_LOG(params, "Error: insufficient memory.\n");
		return (-1);
	}

	rv = 0;
	/* Append the backup path to all the "ent[].name"s. */
	for (i = 0; i < n; i++) {
		ent = (ndmp_name *)MOD_GETNAME(params, i);

		NDMP_LOG(LOG_DEBUG,
		    "Old: ent[%d].name: \"%s\"", i, ent->name);
		NDMP_LOG(LOG_DEBUG,
		    "Old: ent[%d].dest: \"%s\"", i, ent->dest);

		/* remove trailing slash */
		len = strlen(ent->name);
		if (ent->name[len - 1] == '/')
			ent->name[len - 1] = '\0';

		if (!tlm_cat_path(pathname, bkpath, ent->name)) {
			MOD_LOG(params, "Error: path too long.\n");
			rv = -1;
			break;
		}

		/* Make a copy of the new string and save it in ent->name. */
		cp = strdup(pathname);
		if (cp == NULL) {
			MOD_LOG(params, "Error: insufficient memory.\n");
			rv = -1;
			break;
		}
		free(ent->name);
		ent->name = cp;

		NDMP_LOG(LOG_DEBUG,
		    "New: ent[%d].name: \"%s\"", i, ent->name);
	}

	free(pathname);
	return (rv);
}
Exemple #14
0
/*
 * restore_create_structs
 *
 * Allocate structures for performing a restore
 *
 * Parameters:
 *   sesison (input) - session handle
 *   jname (input) - backup job name
 *
 * Returns:
 *   0: on success
 *  -1: otherwise
 */
static int
restore_create_structs(ndmpd_session_t *session, char *jname)
{
	int i;
	long xfer_size;
	ndmp_lbr_params_t *nlp;
	tlm_commands_t *cmds;

	if ((nlp = ndmp_get_nlp(session)) == NULL) {
		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
		return (-1);
	}
	if ((nlp->nlp_jstat = tlm_new_job_stats(jname)) == NULL) {
		NDMP_LOG(LOG_DEBUG, "Creating job stats");
		return (-1);
	}

	cmds = &nlp->nlp_cmds;
	(void) memset(cmds, 0, sizeof (*cmds));

	xfer_size = ndmp_buffer_get_size(session);
	cmds->tcs_command = tlm_create_reader_writer_ipc(FALSE, xfer_size);
	if (cmds->tcs_command == NULL) {
		NDMP_LOG(LOG_DEBUG, "Error creating ipc buffers");
		tlm_un_ref_job_stats(jname);
		return (-1);
	}

	nlp->nlp_logcallbacks = lbrlog_callbacks_init(session,
	    ndmpd_path_restored, NULL, NULL);
	if (nlp->nlp_logcallbacks == NULL) {
		tlm_release_reader_writer_ipc(cmds->tcs_command);
		tlm_un_ref_job_stats(jname);
		return (-1);
	}
	nlp->nlp_jstat->js_callbacks = (void *)(nlp->nlp_logcallbacks);

	nlp->nlp_restored = ndmp_malloc(sizeof (boolean_t) * nlp->nlp_nfiles);
	if (nlp->nlp_restored == NULL) {
		lbrlog_callbacks_done(nlp->nlp_logcallbacks);
		tlm_release_reader_writer_ipc(cmds->tcs_command);
		tlm_un_ref_job_stats(jname);
		return (-1);
	}
	for (i = 0; i < (int)nlp->nlp_nfiles; i++)
		nlp->nlp_restored[i] = FALSE;

	return (0);
}
/*
 * ndmpd_api_file_recovered_v3
 *
 * Notify the NDMP client that the specified file was recovered.
 *
 * Parameters:
 *   cookie (input) - session pointer.
 *   name   (input) - name of recovered file.
 *   ssid   (input) - selection set id.
 *   error  (input) - 0 if file successfully recovered.
 *		    otherwise, error code indicating why recovery failed.
 *
 * Returns:
 *   0 - success.
 *  -1 - error.
 */
int
ndmpd_api_file_recovered_v3(void *cookie, char *name, int error)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_log_file_request_v3 request;

	if (session == NULL)
		return (-1);

	request.name  = name;

	switch (error) {
	case 0:
		request.error = NDMP_NO_ERR;
		break;
	case ENOENT:
		request.error = NDMP_FILE_NOT_FOUND_ERR;
		break;
	default:
		request.error = NDMP_PERMISSION_ERR;
	}

	if (ndmp_send_request_lock(session->ns_connection, NDMP_LOG_FILE,
	    NDMP_NO_ERR, (void *)&request, 0) < 0) {
		NDMP_LOG(LOG_DEBUG, "Error sending log file request");
		return (-1);
	}

	return (0);
}
/*
 * ndmp_create_connection
 *
 * Allocate and initialize a connection structure.
 *
 * Parameters:
 *   handler_tbl (input) - message handlers.
 *
 * Returns:
 *   NULL - error
 *   connection pointer
 *
 * Notes:
 *   The returned connection should be destroyed using
 *   ndmp_destroy_connection().
 */
ndmp_connection_t *
ndmp_create_connection(void)
{
	ndmp_connection_t *connection;

	connection = ndmp_malloc(sizeof (ndmp_connection_t));
	if (connection == NULL)
		return (NULL);

	connection->conn_sock = -1;
	connection->conn_my_sequence = 0;
	connection->conn_authorized = FALSE;
	connection->conn_eof = FALSE;
	connection->conn_msginfo.mi_body = 0;
	connection->conn_version = ndmp_ver;
	connection->conn_client_data = 0;
	(void) mutex_init(&connection->conn_lock, 0, NULL);
	connection->conn_xdrs.x_ops = 0;

	xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection,
	    ndmp_readit, ndmp_writeit);

	if (connection->conn_xdrs.x_ops == 0) {
		NDMP_LOG(LOG_DEBUG, "xdrrec_create failed");
		(void) mutex_destroy(&connection->conn_lock);
		(void) close(connection->conn_sock);
		free(connection);
		return (0);
	}
	return ((ndmp_connection_t *)connection);
}
Exemple #17
0
/*ARGSUSED*/
void
ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body)
{
	ndmp_scsi_close_reply reply;
	ndmpd_session_t *session = ndmp_get_client_data(connection);

	if (session->ns_scsi.sd_is_open == -1) {
		NDMP_LOG(LOG_ERR, "SCSI device is not open.");
		reply.error = NDMP_DEV_NOT_OPEN_ERR;
		ndmp_send_reply(connection, (void *) &reply,
		    "sending scsi_close reply");
		return;
	}
	(void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name,
	    session->ns_scsi.sd_sid,
	    session->ns_scsi.sd_lun);
	(void) close(session->ns_scsi.sd_devid);

	session->ns_scsi.sd_is_open = -1;
	session->ns_scsi.sd_devid = -1;
	session->ns_scsi.sd_sid = 0;
	session->ns_scsi.sd_lun = 0;
	session->ns_scsi.sd_valid_target_set = FALSE;
	(void) memset(session->ns_scsi.sd_adapter_name, 0,
	    sizeof (session->ns_scsi.sd_adapter_name));

	reply.error = NDMP_NO_ERR;
	ndmp_send_reply(connection, (void *) &reply,
	    "sending scsi_close reply");
}
/*ARGSUSED*/
int
ndmpd_api_log_v2(void *cookie, char *format, ...)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_log_log_request request;
	static char buf[1024];
	va_list ap;

	if (session == NULL)
		return (-1);

	va_start(ap, format);

	/*LINTED variable format specifier */
	(void) vsnprintf(buf, sizeof (buf), format, ap);
	va_end(ap);

	request.entry = buf;


	if (ndmp_send_request(session->ns_connection, _NDMP_LOG_LOG,
	    NDMP_NO_ERR, (void *)&request, 0) < 0) {
		NDMP_LOG(LOG_DEBUG, "Sending log request");
		return (-1);
	}
	return (0);

}
/*ARGSUSED*/
int
ndmpd_api_log_v4(void *cookie, ndmp_log_type type, ulong_t msg_id,
    char *format, ...)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_log_message_request_v4 request;
	static char buf[1024];
	va_list ap;

	if (session == NULL)
		return (-1);

	va_start(ap, format);

	/*LINTED variable format specifier */
	(void) vsnprintf(buf, sizeof (buf), format, ap);
	va_end(ap);

	request.entry = buf;
	request.log_type = type;
	request.message_id = msg_id;
	request.associated_message_valid = NDMP_NO_ASSOCIATED_MESSAGE;
	request.associated_message_sequence = 0;

	if (ndmp_send_request(session->ns_connection, NDMP_LOG_MESSAGE,
	    NDMP_NO_ERR, (void *)&request, 0) < 0) {
		NDMP_LOG(LOG_DEBUG, "Error sending log message request.");
		return (-1);
	}
	return (0);
}
Exemple #20
0
/*
 * Get the snapshot creation time
 */
int
chkpnt_creationtime_bypattern(char *volname, char *pattern, time_t *tp)
{
    char chk_name[PATH_MAX];
    zfs_handle_t *zhp;
    char *p;

    if (!volname || !*volname)
        return (-1);

    /* Should also return -1 if checkpoint not enabled */

    /* Remove the leading slash */
    p = volname;
    while (*p == '/')
        p++;

    (void) strlcpy(chk_name, p, PATH_MAX);
    (void) strlcat(chk_name, "@", PATH_MAX);
    (void) strlcat(chk_name, pattern, PATH_MAX);

    (void) mutex_lock(&zlib_mtx);
    if ((zhp = zfs_open(zlibh, chk_name, ZFS_TYPE_DATASET)) == NULL) {
        NDMP_LOG(LOG_DEBUG, "chkpnt_creationtime: open %s failed",
                 chk_name);
        (void) mutex_unlock(&zlib_mtx);
        return (-1);
    }

    *tp = zfs_prop_get_int(zhp, ZFS_PROP_CREATION);
    zfs_close(zhp);
    (void) mutex_unlock(&zlib_mtx);

    return (0);
}
/*
 * ndmpd_api_add_env
 *
 * Adds an environment variable name/value pair to the environment
 * variable list.
 *
 * Parameters:
 *   session (input) - session pointer.
 *   name    (input) - variable name.
 *   val     (input) - value.
 *
 * Returns:
 *   0 - success.
 *  -1 - error.
 */
int
ndmpd_api_add_env(void *cookie, char *name, char *value)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	char *namebuf;
	char *valbuf;

	if (session == NULL)
		return (-1);

	session->ns_data.dd_env = realloc((void *)session->ns_data.dd_env,
	    sizeof (ndmp_pval) * (session->ns_data.dd_env_len + 1));

	if (session->ns_data.dd_env == NULL) {
		NDMP_LOG(LOG_ERR, "Out of memory.");
		return (-1);
	}
	namebuf = strdup(name);
	if (namebuf == NULL)
		return (-1);

	valbuf = strdup(value);
	if (valbuf == NULL) {
		free(namebuf);
		return (-1);
	}

	(void) mutex_lock(&session->ns_lock);
	session->ns_data.dd_env[session->ns_data.dd_env_len].name = namebuf;
	session->ns_data.dd_env[session->ns_data.dd_env_len].value = valbuf;
	session->ns_data.dd_env_len++;
	(void) mutex_unlock(&session->ns_lock);

	return (0);
}
Exemple #22
0
/*
 * ndmp_backup_reader
 *
 * Backup reader thread which uses backup_work to read and TAR
 * the files/dirs to be backed up (V2 only)
 */
static int
ndmp_backup_reader(tlm_commands_t *commands, ndmp_lbr_params_t *nlp,
    char *job_name)
{
	int retval;
	ndmp_run_args_t np;
	tlm_job_stats_t *job_stats;
	tlm_cmd_t *local_commands;

	NDMP_LOG(LOG_DEBUG, "bk_path: \"%s\"", nlp->nlp_backup_path);

	local_commands = commands->tcs_command;
	(void) memset(&np, 0, sizeof (np));
	if (!malloc_paths(&np))
		return (-1);
	local_commands->tc_ref++;
	commands->tcs_reader_count++;

	job_stats = tlm_ref_job_stats(job_name);

	retval = backup_work(nlp->nlp_backup_path, job_stats, &np,
	    commands, nlp);
	write_tar_eof(local_commands);

	commands->tcs_reader_count--;
	local_commands->tc_writer = TLM_STOP;
	tlm_release_reader_writer_ipc(local_commands);
	tlm_un_ref_job_stats(job_name);

	free_paths(&np);
	return (retval);

}
Exemple #23
0
/*
 * Log call back to report the entry recovery
 */
int
tlm_entry_restored(tlm_job_stats_t *job_stats, char *name, int pos)
{
    lbr_fhlog_call_backs_t *cbp; /* callbacks pointer */

    NDMP_LOG(LOG_DEBUG, "name: \"%s\", pos: %d", name, pos);

    if (job_stats == NULL) {
        NDMP_LOG(LOG_DEBUG, "entry_restored: jstat is NULL");
        return (0);
    }
    cbp = (lbr_fhlog_call_backs_t *)job_stats->js_callbacks;
    if (cbp == NULL) {
        NDMP_LOG(LOG_DEBUG, "entry_restored is NULL");
        return (0);
    }
    return (*cbp->fh_logpname)(cbp, name, 0, (longlong_t)pos);
}
Exemple #24
0
/*
 * cstack_delete
 *
 * Deallocate the stack. This goes through the list freeing all of the
 * cstack nodes but not the data because we don't know how the data was
 * allocated. A stack really should be empty before it is deleted.
 */
void
cstack_delete(cstack_t *stk)
{
	cstack_t *tmp;

	if (stk == NULL) {
		NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
		return;
	}

	while ((tmp = stk->next) != NULL) {
		stk->next = tmp->next;
		NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp);
		free(tmp);
	}

	NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
	free(stk);
}
Exemple #25
0
/*
 * verify the tar header checksum
 */
int
tlm_vfy_tar_checksum(tlm_tar_hdr_t *tar_hdr)
{
    int	chksum = oct_atoi(tar_hdr->th_chksum);
    uchar_t	*p = (uchar_t *)tar_hdr;
    int	sum = 0;	/* initial value of checksum */
    int	i;		/* loop counter */

    /*
     * compute the checksum
     */
    for (i = 0; i < RECORDSIZE; i++) {
        sum += p[i] & 0xFF;
    }

    if (sum == 0) {
        NDMP_LOG(LOG_DEBUG,
                 "should be %d, is 0", chksum);
        /* a zero record ==> end of tar file */
        return (0);
    }

    /*
     * subtract out the label's checksum values
     * this lets us undo the old checksum "in-
     * place", no need to swap blanks in and out
     */
    for (i = 0; i < 8; i++) {
        sum -= 0xFF & tar_hdr->th_chksum[i];
    }

    /*
     * replace the old checksum field with blanks
     */
    sum += ' ' * 8;

    if (sum != chksum)
        NDMP_LOG(LOG_DEBUG,
                 "should be %d, is %d", chksum, sum);

    return ((sum == chksum) ? 1 : -1);
}
Exemple #26
0
/*ARGSUSED*/
void
ndmpd_scsi_reset_bus_v2(ndmp_connection_t *connection, void *body)
{
	ndmp_scsi_reset_bus_reply reply;

	NDMP_LOG(LOG_DEBUG, "request not supported");
	reply.error = NDMP_NOT_SUPPORTED_ERR;

	ndmp_send_reply(connection, (void *) &reply,
	    "sending scsi_reset_bus reply");
}
Exemple #27
0
/*
 * Enable the barcode capability on the library
 */
void
tlm_enable_barcode(int l)
{
    tlm_library_t *lp;

    if ((lp = tlm_library(l))) {
        lp->tl_capability_barcodes = TRUE;
        NDMP_LOG(LOG_DEBUG,
                 "Barcode capability on library %d enabled.", l);
    }
}
/*
 * ndmpd_api_seek_v2
 *
 * Seek to the specified position in the data stream and start a
 * read for the specified amount of data.
 *
 * Parameters:
 *   cookie (input) - session pointer.
 *   offset (input) - stream position to seek to.
 *   length (input) - amount of data that will be read using ndmpd_api_read
 *
 * Returns:
 *   0 - seek successful.
 *  -1 - error.
 */
int
ndmpd_api_seek_v2(void *cookie, u_longlong_t offset, u_longlong_t length)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	int err;

	if (session == NULL)
		return (-1);

	session->ns_data.dd_read_offset = offset;
	session->ns_data.dd_read_length = length;

	/*
	 * Send a notify_data_read request if the mover is remote.
	 */
	if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
		ndmp_notify_data_read_request request;

		session->ns_mover.md_discard_length =
		    session->ns_mover.md_bytes_left_to_read;
		session->ns_mover.md_bytes_left_to_read = length;
		session->ns_mover.md_position = offset;

		request.offset = long_long_to_quad(offset);
		request.length = long_long_to_quad(length);

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
		    (void *)&request, 0) < 0) {

			NDMP_LOG(LOG_DEBUG,
			    "Sending notify_data_read request");
			return (-1);
		}
		return (0);
	}
	/* Mover is local. */

	err = ndmpd_mover_seek(session, offset, length);
	if (err < 0) {
		ndmpd_mover_error(session, NDMP_MOVER_HALT_INTERNAL_ERROR);
		return (-1);
	}
	if (err == 0)
		return (0);

	/*
	 * NDMP client intervention is required to perform the seek.
	 * Wait for the client to either do the seek and send a continue
	 * request or send an abort request.
	 */
	return (ndmp_wait_for_mover(session));
}
Exemple #29
0
/*
 * ndmp_write_utf8magic
 *
 * Write a magic pattern to the tar header. This is used
 * as a crest to indicate that tape belongs to us.
 */
int
ndmp_write_utf8magic(tlm_cmd_t *cmd)
{
	char *cp;
	long actual_size;

	if (cmd->tc_buffers == NULL) {
		NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
		return (-1);
	}

	cp = tlm_get_write_buffer(RECORDSIZE, &actual_size,
	    cmd->tc_buffers, TRUE);
	if (actual_size < RECORDSIZE) {
		NDMP_LOG(LOG_DEBUG, "Couldn't get enough buffer");
		return (-1);
	}

	(void) strlcpy(cp, NDMPUTF8MAGIC, RECORDSIZE);
	return (0);
}
Exemple #30
0
/*
 * cstack_top
 *
 * Returns the top data element on the stack without removing it.
 *
 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
 */
int
cstack_top(cstack_t *stk, void **data, int *len)
{
	if (stk == NULL) {
		NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
		return (-1);
	}

	if (stk->next == NULL) {
		NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
		return (-1);
	}

	if (data)
		*data = stk->next->data;

	if (len)
		*len = stk->next->len;

	return (0);
}