/*
 * 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));
}
Esempio n. 2
0
/*
 * ndmpd_api_file_history_node_v3
 *
 * Add a file history node entry to the buffer.
 * History data is buffered until the buffer is filled.
 * Full buffers are then sent to the client.
 *
 * Parameters:
 *   cookie   (input) - session pointer.
 *   node     (input) - file inode.
 *		must match a node from a prior ndmpd_api_file_history_dir()
 *		      call.
 *   file_stat (input) - file status pointer.
 *		      0 forces buffered data to be sent.
 *   fh_info  (input) - data stream position of file data used during
 *		      fast restore.
 *
 * Returns:
 *   0 - success
 *  -1 - error.
 */
int
ndmpd_api_file_history_node_v3(void *cookie, ulong_t node,
    struct stat64 *file_stat, u_longlong_t fh_info)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_node_v3 *node_entry;
	ndmp_file_stat_v3 *file_stat_entry;
	ndmp_fh_add_node_request_v3 request;

	if (file_stat == NULL && session->ns_fh_v3.fh_node_index == 0)
		return (0);

	/*
	 * If the buffer does not have space
	 * for the current entry, send the buffered data to the client.
	 * A 0 file_stat pointer indicates that any buffered data should
	 * be sent.
	 */
	if (file_stat == NULL ||
	    session->ns_fh_v3.fh_node_index == N_NODE_ENTRIES) {
		syslog(LOG_DEBUG, "sending %ld entries",
		    session->ns_fh_v3.fh_node_index);

		/*
		 * Need to send Dir entry as well. Since Dir entry is more
		 * than a Node entry, we may send a Node entry that hasn't
		 * had its Dir entry sent. Therefore, we need to flush Dir
		 * entry as well every time the Dir entry is sent.
		 */
		(void) ndmpd_api_file_history_dir_v3(session, 0, 0, 0);

		request.nodes.nodes_len = session->ns_fh_v3.fh_node_index;
		request.nodes.nodes_val = session->ns_fh_v3.fh_nodes;

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_FH_ADD_NODE,
		    NDMP_NO_ERR, (void *) &request, 0) < 0) {
			syslog(LOG_ERR,
			    "Sending ndmp_fh_add_node request failed");
			return (-1);
		}

		session->ns_fh_v3.fh_node_index = 0;
	}

	if (file_stat == NULL)
		return (0);

	if (session->ns_fh_v3.fh_nodes == 0) {
		session->ns_fh_v3.fh_nodes =
		    ndmp_malloc(sizeof (ndmp_node_v3) * N_NODE_ENTRIES);
		if (session->ns_fh_v3.fh_nodes == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_node_stats == 0) {
		session->ns_fh_v3.fh_node_stats =
		    ndmp_malloc(sizeof (ndmp_file_stat_v3) * N_NODE_ENTRIES);
		if (session->ns_fh_v3.fh_node_stats == 0)
			return (-1);
	}

	node_entry =
	    &session->ns_fh_v3.fh_nodes[session->ns_fh_v3.fh_node_index];

	file_stat_entry =
	    &session->ns_fh_v3.fh_node_stats[session->ns_fh_v3.fh_node_index];
	ndmpd_get_file_entry_type(file_stat->st_mode, &file_stat_entry->ftype);

	file_stat_entry->invalid = 0;
	file_stat_entry->fs_type = NDMP_FS_UNIX;
	file_stat_entry->mtime = file_stat->st_mtime;
	file_stat_entry->atime = file_stat->st_atime;
	file_stat_entry->ctime = file_stat->st_ctime;
	file_stat_entry->owner = file_stat->st_uid;
	file_stat_entry->group = file_stat->st_gid;
	file_stat_entry->fattr = file_stat->st_mode & 0x0fff;
	file_stat_entry->size =
	    long_long_to_quad((u_longlong_t)file_stat->st_size);
	file_stat_entry->links = file_stat->st_nlink;

	node_entry->stats.stats_len = 1;
	node_entry->stats.stats_val = file_stat_entry;
	node_entry->node = long_long_to_quad((u_longlong_t)node);
	node_entry->fh_info = long_long_to_quad(fh_info);

	session->ns_fh_v3.fh_node_index++;

	return (0);
}
Esempio n. 3
0
/*
 * ndmpd_api_file_history_dir_v3
 *
 * Add a file history dir entry to the buffer.
 * History data is buffered until the buffer is filled.
 * Full buffers are then sent to the client.
 *
 * Parameters:
 *   cookie (input) - session pointer.
 *   name   (input) - file name.
 *		    NULL forces buffered data to be sent.
 *   node   (input) - file inode.
 *   parent (input) - file parent inode.
 *		    Should equal node if the file is the root of
 *		    the filesystem and has no parent.
 *
 * Returns:
 *   0 - success
 *  -1 - error
 */
int
ndmpd_api_file_history_dir_v3(void *cookie, char *name, ulong_t node,
    ulong_t parent)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_dir_v3 *dir_entry;
	ndmp_file_name_v3 *dir_name_entry;
	ndmp_fh_add_dir_request_v3 request;

	if (name == NULL && session->ns_fh_v3.fh_dir_index == 0)
		return (0);

	/*
	 * If the buffer does not have space
	 * for the current entry, send the buffered data to the client.
	 * A NULL name indicates that any buffered data should be sent.
	 */
	if (name == NULL ||
	    session->ns_fh_v3.fh_dir_index == N_DIR_ENTRIES ||
	    session->ns_fh_v3.fh_dir_name_buf_index + strlen(name) + 1 >
	    DIR_NAMEBUF_SIZE) {

		syslog(LOG_DEBUG, "sending %ld entries",
		    session->ns_fh_v3.fh_dir_index);

		request.dirs.dirs_val = session->ns_fh_v3.fh_dirs;
		request.dirs.dirs_len = session->ns_fh_v3.fh_dir_index;

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_FH_ADD_DIR, NDMP_NO_ERR, (void *) &request, 0) < 0) {
			syslog(LOG_ERR,
			    "Sending ndmp_fh_add_dir request failed");
			return (-1);
		}

		session->ns_fh_v3.fh_dir_index = 0;
		session->ns_fh_v3.fh_dir_name_buf_index = 0;
	}

	if (name == NULL)
		return (0);

	if (session->ns_fh_v3.fh_dirs == 0) {
		session->ns_fh_v3.fh_dirs =
		    ndmp_malloc(sizeof (ndmp_dir_v3) * N_DIR_ENTRIES);
		if (session->ns_fh_v3.fh_dirs == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_dir_names == 0) {
		session->ns_fh_v3.fh_dir_names =
		    ndmp_malloc(sizeof (ndmp_file_name_v3) * N_DIR_ENTRIES);
		if (session->ns_fh_v3.fh_dir_names == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_dir_name_buf == 0) {
		session->ns_fh_v3.fh_dir_name_buf =
		    ndmp_malloc(sizeof (char) * DIR_NAMEBUF_SIZE);
		if (session->ns_fh_v3.fh_dir_name_buf == 0)
			return (-1);
	}

	dir_entry = &session->ns_fh_v3.fh_dirs[session->ns_fh_v3.fh_dir_index];
	dir_name_entry =
	    &session->ns_fh_v3.fh_dir_names[session->ns_fh_v3.fh_dir_index];

	dir_name_entry->fs_type = NDMP_FS_UNIX;
	dir_name_entry->ndmp_file_name_v3_u.unix_name =
	    &session->ns_fh_v3.fh_dir_name_buf[session->
	    ns_fh_v3.fh_dir_name_buf_index];

	(void) strlcpy(&session->ns_fh_v3.fh_dir_name_buf[session->
	    ns_fh_v3.fh_dir_name_buf_index], name, PATH_NAMEBUF_SIZE);
	session->ns_fh_v3.fh_dir_name_buf_index += strlen(name) + 1;

	dir_entry->names.names_len = 1;
	dir_entry->names.names_val = dir_name_entry;
	dir_entry->node = long_long_to_quad(node);
	dir_entry->parent = long_long_to_quad(parent);

	session->ns_fh_v3.fh_dir_index++;

	return (0);
}
Esempio n. 4
0
/*
 * ndmpd_api_file_history_file_v3
 *
 * Add a file history file entry to the buffer.
 * History data is buffered until the buffer is filled.
 * Full buffers are then sent to the client.
 *
 * Parameters:
 *   cookie   (input) - session pointer.
 *   name     (input) - file name.
 *		      NULL forces buffered data to be sent.
 *   file_stat (input) - file status pointer.
 *   fh_info  (input) - data stream position of file data used during
 *		      fast restore.
 *
 * Returns:
 *   0 - success
 *  -1 - error
 */
int
ndmpd_api_file_history_file_v3(void *cookie, char *name,
    struct stat64 *file_stat, u_longlong_t fh_info)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_file_v3 *file_entry;
	ndmp_file_name_v3 *file_name_entry;
	ndmp_file_stat_v3 *file_stat_entry;
	ndmp_fh_add_file_request_v3 request;

	if (name == NULL && session->ns_fh_v3.fh_file_index == 0)
		return (0);

	/*
	 * If the buffer does not have space
	 * for the current entry, send the buffered data to the client.
	 * A NULL name indicates that any buffered data should be sent.
	 */
	if (name == NULL ||
	    session->ns_fh_v3.fh_file_index == N_FILE_ENTRIES ||
	    session->ns_fh_v3.fh_file_name_buf_index + strlen(name) + 1 >
	    PATH_NAMEBUF_SIZE) {

		syslog(LOG_DEBUG, "sending %ld entries",
		    session->ns_fh_v3.fh_file_index);

		request.files.files_len = session->ns_fh_v3.fh_file_index;
		request.files.files_val = session->ns_fh_v3.fh_files;

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_FH_ADD_FILE, NDMP_NO_ERR, (void *) &request, 0) < 0) {
			syslog(LOG_ERR,
			    "Sending ndmp_fh_add_file request failed");
			return (-1);
		}

		session->ns_fh_v3.fh_file_index = 0;
		session->ns_fh_v3.fh_file_name_buf_index = 0;
	}

	if (name == NULL)
		return (0);

	if (session->ns_fh_v3.fh_files == 0) {
		session->ns_fh_v3.fh_files = ndmp_malloc(sizeof (ndmp_file_v3) *
		    N_FILE_ENTRIES);
		if (session->ns_fh_v3.fh_files == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_file_names == 0) {
		session->ns_fh_v3.fh_file_names =
		    ndmp_malloc(sizeof (ndmp_file_name_v3) * N_FILE_ENTRIES);
		if (session->ns_fh_v3.fh_file_names == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_file_name_buf == 0) {
		session->ns_fh_v3.fh_file_name_buf =
		    ndmp_malloc(sizeof (char) * PATH_NAMEBUF_SIZE);
		if (session->ns_fh_v3.fh_file_name_buf == 0)
			return (-1);
	}

	if (session->ns_fh_v3.fh_file_stats == 0) {
		session->ns_fh_v3.fh_file_stats =
		    ndmp_malloc(sizeof (ndmp_file_stat_v3) * N_FILE_ENTRIES);
		if (session->ns_fh_v3.fh_file_stats == 0)
			return (-1);
	}

	file_entry =
	    &session->ns_fh_v3.fh_files[session->ns_fh_v3.fh_file_index];
	file_name_entry =
	    &session->ns_fh_v3.fh_file_names[session->ns_fh_v3.fh_file_index];
	file_stat_entry =
	    &session->ns_fh_v3.fh_file_stats[session->ns_fh_v3.fh_file_index];
	file_entry->names.names_len = 1;
	file_entry->names.names_val = file_name_entry;
	file_entry->stats.stats_len = 1;
	file_entry->stats.stats_val = file_stat_entry;
	file_entry->node = long_long_to_quad(file_stat->st_ino);
	file_entry->fh_info = long_long_to_quad(fh_info);

	file_name_entry->fs_type = NDMP_FS_UNIX;
	file_name_entry->ndmp_file_name_v3_u.unix_name =
	    &session->ns_fh_v3.fh_file_name_buf[session->
	    ns_fh_v3.fh_file_name_buf_index];
	(void) strlcpy(&session->ns_fh_v3.fh_file_name_buf[session->
	    ns_fh_v3.fh_file_name_buf_index], name, PATH_NAMEBUF_SIZE);
	session->ns_fh_v3.fh_file_name_buf_index += strlen(name) + 1;
	ndmpd_get_file_entry_type(file_stat->st_mode, &file_stat_entry->ftype);

	file_stat_entry->invalid = 0;
	file_stat_entry->fs_type = NDMP_FS_UNIX;
	file_stat_entry->mtime = file_stat->st_mtime;
	file_stat_entry->atime = file_stat->st_atime;
	file_stat_entry->ctime = file_stat->st_ctime;
	file_stat_entry->owner = file_stat->st_uid;
	file_stat_entry->group = file_stat->st_gid;
	file_stat_entry->fattr = file_stat->st_mode & 0x0fff;
	file_stat_entry->size =
	    long_long_to_quad((u_longlong_t)file_stat->st_size);
	file_stat_entry->links = file_stat->st_nlink;

	session->ns_fh_v3.fh_file_index++;

	return (0);
}
Esempio n. 5
0
/*
 * ndmpd_api_file_history_node_v2
 *
 * Add a file history node entry to the buffer.
 * History data is buffered until the buffer is filled.
 * Full buffers are then sent to the client.
 *
 * Parameters:
 *   cookie   (input) - session pointer.
 *   node     (input) - file inode.
 *	      must match a node from a prior ndmpd_api_file_history_dir()
 *		      call.
 *   file_stat (input) - file status pointer.
 *		      0 forces buffered data to be sent.
 *   fh_info  (input) - data stream position of file data used during
 *		      fast restore.
 *
 * Returns:
 *   0 - success
 *  -1 - error.
 */
int
ndmpd_api_file_history_node_v2(void *cookie, ulong_t node,
    struct stat64 *file_stat, u_longlong_t fh_info)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_fh_unix_node *entry;

	if (file_stat == NULL && session->ns_fh.fh_node_index == 0)
		return (-1);

	/*
	 * If the buffer does not have space
	 * for the current entry, send the buffered data to the client.
	 * A 0 file_stat pointer indicates that any buffered data should
	 * be sent.
	 */
	if (file_stat == NULL ||
	    (ndmp_syncfh && session->ns_fh.fh_node_index != 0) ||
	    session->ns_fh.fh_node_index == N_NODE_ENTRIES) {
		ndmp_fh_add_unix_node_request request;

		syslog(LOG_DEBUG,
		    "sending %ld entries", session->ns_fh.fh_node_index);

		request.nodes.nodes_val = session->ns_fh.fh_node_entries;
		request.nodes.nodes_len = session->ns_fh.fh_node_index;
		/*
		 * Need to send Dir entry as well. Since Dir entry is more than
		 * Node entry, we may send a Node entry that hasn't have
		 * its dir entry sent. Therefore, we need to flush Dir entry
		 * as well everytime the Dir entry is send.
		 */
		(void) ndmpd_api_file_history_dir_v2(session, 0, 0, 0);

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_FH_ADD_UNIX_NODE, NDMP_NO_ERR, (void *) &request,
		    0) < 0) {
			syslog(LOG_ERR, "Sending file history data failed");
			return (-1);
		}
		session->ns_fh.fh_node_index = 0;
	}
	if (file_stat == NULL)
		return (0);

	if (session->ns_fh.fh_node_entries == 0) {
		session->ns_fh.fh_node_entries = ndmp_malloc(N_NODE_ENTRIES
		    * sizeof (ndmp_fh_unix_node));
		if (session->ns_fh.fh_node_entries == 0)
			return (-1);
	}
	entry = &session->ns_fh.fh_node_entries[session->ns_fh.fh_node_index];
	ndmpd_get_file_entry_type(file_stat->st_mode, &entry->fstat.ftype);

	entry->node = node;
	entry->fstat.mtime = (ulong_t)file_stat->st_mtime;
	entry->fstat.atime = (ulong_t)file_stat->st_atime;
	entry->fstat.ctime = (ulong_t)file_stat->st_ctime;
	entry->fstat.uid = file_stat->st_uid;
	entry->fstat.gid = file_stat->st_gid;
	entry->fstat.mode = (file_stat->st_mode) & 0x0fff;
	entry->fstat.size = long_long_to_quad((u_longlong_t)file_stat->st_size);
	entry->fstat.fh_info = long_long_to_quad(fh_info);

	session->ns_fh.fh_node_index++;
	return (0);
}
Esempio n. 6
0
/*
 * ndmpd_api_file_history_path_v2
 *
 * Add a file history path entry to the buffer.
 * History data is buffered until the buffer is filled.
 * Full buffers are then sent to the client.
 *
 * Parameters:
 *   cookie   (input) - session pointer.
 *   name     (input) - file name.
 *		      NULL forces buffered data to be sent.
 *   file_stat (input) - file status pointer.
 *   fh_info  (input) - data stream position of file data used during
 *		      fast restore.
 *
 * Returns:
 *   0 - success
 *  -1 - error
 */
int
ndmpd_api_file_history_path_v2(void *cookie, char *name,
    struct stat64 *file_stat, u_longlong_t fh_info)
{
	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
	ndmp_fh_unix_path *entry;

	if (name == NULL && session->ns_fh.fh_path_index == 0)
		return (0);

	/*
	 * If the buffer does not have space
	 * for the current entry, send the buffered data to the client.
	 * A NULL name indicates that any buffered data should be sent.
	 */
	if (name == NULL ||
	    (ndmp_syncfh && session->ns_fh.fh_path_index != 0) ||
	    session->ns_fh.fh_path_index == N_PATH_ENTRIES ||
	    session->ns_fh.fh_path_name_buf_index + strlen(name) + 1 >
	    PATH_NAMEBUF_SIZE) {
		ndmp_fh_add_unix_path_request request;

		syslog(LOG_DEBUG,
		    "sending %ld entries", session->ns_fh.fh_path_index);

		request.paths.paths_val = session->ns_fh.fh_path_entries;
		request.paths.paths_len = session->ns_fh.fh_path_index;

		if (ndmp_send_request_lock(session->ns_connection,
		    NDMP_FH_ADD_UNIX_PATH, NDMP_NO_ERR, (void *) &request,
		    0) < 0) {
			syslog(LOG_ERR, "Sending file history data failed");
			return (-1);
		}
		session->ns_fh.fh_path_index = 0;
		session->ns_fh.fh_path_name_buf_index = 0;
	}
	if (name == NULL)
		return (0);

	if (session->ns_fh.fh_path_entries == 0) {
		session->ns_fh.fh_path_entries = ndmp_malloc(N_PATH_ENTRIES *
		    sizeof (ndmp_fh_unix_path));
		if (session->ns_fh.fh_path_entries == 0)
			return (-1);
	}
	if (session->ns_fh.fh_path_name_buf == 0) {
		session->ns_fh.fh_path_name_buf =
		    ndmp_malloc(PATH_NAMEBUF_SIZE);
		if (session->ns_fh.fh_path_name_buf == 0)
			return (-1);
	}
	entry = &session->ns_fh.fh_path_entries[session->ns_fh.fh_path_index];
	ndmpd_get_file_entry_type(file_stat->st_mode, &entry->fstat.ftype);

	entry->name = &session->
	    ns_fh.fh_path_name_buf[session->ns_fh.fh_path_name_buf_index];
	(void) strlcpy(entry->name, name, PATH_NAMEBUF_SIZE);
	session->ns_fh.fh_path_name_buf_index += strlen(name) + 1;
	entry->fstat.mtime = (ulong_t)file_stat->st_mtime;
	entry->fstat.atime = (ulong_t)file_stat->st_atime;
	entry->fstat.ctime = (ulong_t)file_stat->st_ctime;
	entry->fstat.uid = file_stat->st_uid;
	entry->fstat.gid = file_stat->st_gid;
	entry->fstat.mode = (file_stat->st_mode) & 0x0fff;
	entry->fstat.size = long_long_to_quad((u_longlong_t)file_stat->st_size);
	entry->fstat.fh_info = long_long_to_quad((u_longlong_t)fh_info);
	session->ns_fh.fh_path_index++;
	return (0);
}