/* * 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)); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }