#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "ndmpd.h"
int ndmp_log_msg_id = 0;
void
ndmpd_api_done_v2(void *cookie, int err)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ndmp_notify_data_halted_request req_v2;
if (session == NULL)
return;
if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
return;
NDMP_LOG(LOG_DEBUG, "data.operation: %d",
session->ns_data.dd_operation);
if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
ndmpd_file_history_cleanup(session, (err == 0 ? TRUE : FALSE));
if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_LOCAL &&
err == 0) {
if (ndmpd_local_write(session, 0, 0) < 0)
err = EIO;
}
}
session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
switch (err) {
case 0:
session->ns_data.dd_halt_reason = NDMP_DATA_HALT_SUCCESSFUL;
break;
case EINTR:
session->ns_data.dd_halt_reason = NDMP_DATA_HALT_ABORTED;
break;
case EIO:
session->ns_data.dd_halt_reason = NDMP_DATA_HALT_CONNECT_ERROR;
break;
default:
session->ns_data.dd_halt_reason = NDMP_DATA_HALT_INTERNAL_ERROR;
}
req_v2.reason = session->ns_data.dd_halt_reason;
req_v2.text_reason = "";
NDMP_LOG(LOG_DEBUG, "ndmp_send_request(NDMP_NOTIFY_DATA_HALTED)");
if (ndmp_send_request_lock(session->ns_connection,
NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, (void *)&req_v2, 0) < 0)
NDMP_LOG(LOG_DEBUG, "Sending notify_data_halted request");
if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
if (session->ns_mover.md_sock != session->ns_data.dd_sock) {
(void) close(session->ns_data.dd_sock);
} else {
NDMP_LOG(LOG_DEBUG, "Not closing as used by mover");
}
session->ns_data.dd_sock = -1;
} else {
ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
}
}
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);
(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);
}
int
ndmpd_api_read_v2(void *client_data, char *data, ulong_t length)
{
ndmpd_session_t *session = (ndmpd_session_t *)client_data;
if (session == NULL)
return (-1);
if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
return (ndmpd_remote_read(session, data, length));
else
return (ndmpd_local_read(session, data, length));
}
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;
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);
}
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);
return (ndmp_wait_for_mover(session));
}
int
ndmpd_api_file_recovered_v2(void *cookie, char *name, int error)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ndmp_log_file_request_v2 request;
if (session == NULL)
return (-1);
request.name = name;
request.ssid = 0;
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, "Sending log file request");
return (-1);
}
return (0);
}
int
ndmpd_api_write_v2(void *client_data, char *data, ulong_t length)
{
ndmpd_session_t *session = (ndmpd_session_t *)client_data;
if (session == NULL)
return (-1);
if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
return (ndmpd_remote_write(session, data, length));
else
return (ndmpd_local_write(session, data, length));
}
void
ndmpd_api_done_v3(void *cookie, int err)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ndmp_data_halt_reason reason;
switch (err) {
case 0:
reason = NDMP_DATA_HALT_SUCCESSFUL;
break;
case EINTR:
reason = NDMP_DATA_HALT_ABORTED;
break;
case EIO:
reason = NDMP_DATA_HALT_CONNECT_ERROR;
break;
default:
reason = NDMP_DATA_HALT_INTERNAL_ERROR;
}
ndmpd_data_error(session, reason);
}
int
ndmpd_api_log_v3(void *cookie, ndmp_log_type type, ulong_t msg_id,
char *format, ...)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ndmp_log_message_request_v3 request;
static char buf[1024];
va_list ap;
if (session == NULL)
return (-1);
va_start(ap, format);
(void) vsnprintf(buf, sizeof (buf), format, ap);
va_end(ap);
request.entry = buf;
request.log_type = type;
request.message_id = msg_id;
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);
}
int
ndmpd_api_write_v3(void *client_data, char *data, ulong_t length)
{
ndmpd_session_t *session = (ndmpd_session_t *)client_data;
if (session == NULL)
return (-1);
if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL)
return (ndmpd_local_write_v3(session, data, length));
else
return (ndmpd_remote_write(session, data, length));
}
int
ndmpd_api_read_v3(void *client_data, char *data, ulong_t length)
{
ndmpd_session_t *session = (ndmpd_session_t *)client_data;
if (session == NULL)
return (-1);
if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL)
return (ndmpd_local_read_v3(session, data, length));
else
return (ndmpd_remote_read_v3(session, data, length));
}
void *
ndmpd_api_get_name_v3(void *cookie, ulong_t name_index)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
if (session == NULL)
return (NULL);
if (name_index >= session->ns_data.dd_nlist_len)
return (NULL);
return (&session->ns_data.dd_nlist_v3[name_index]);
}
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);
}
int
ndmpd_api_seek_v3(void *cookie, u_longlong_t offset, u_longlong_t length)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
int err;
ndmp_notify_data_read_request request;
if (session == NULL)
return (-1);
session->ns_data.dd_read_offset = offset;
session->ns_data.dd_read_length = length;
if (session->ns_data.dd_data_addr.addr_type != NDMP_ADDR_LOCAL) {
session->ns_data.dd_discard_length =
session->ns_data.dd_bytes_left_to_read;
session->ns_data.dd_bytes_left_to_read = length;
session->ns_data.dd_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);
}
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);
err = ndmp_wait_for_mover(session);
if (err == 0)
err = 1;
return (err);
}
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);
(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);
}
int
ndmpd_api_file_recovered_v4(void *cookie, char *name, int error)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ndmp_log_file_request_v4 request;
if (session == NULL)
return (-1);
request.name = name;
switch (error) {
case 0:
request.recovery_status = NDMP_RECOVERY_SUCCESSFUL;
break;
case EPERM:
request.recovery_status = NDMP_RECOVERY_FAILED_PERMISSION;
break;
case ENOENT:
request.recovery_status = NDMP_RECOVERY_FAILED_NOT_FOUND;
break;
case ENOTDIR:
request.recovery_status = NDMP_RECOVERY_FAILED_NO_DIRECTORY;
break;
case ENOMEM:
request.recovery_status = NDMP_RECOVERY_FAILED_OUT_OF_MEMORY;
break;
case EIO:
request.recovery_status = NDMP_RECOVERY_FAILED_IO_ERROR;
break;
case EEXIST:
request.recovery_status = NDMP_RECOVERY_FAILED_FILE_PATH_EXISTS;
break;
default:
request.recovery_status = NDMP_RECOVERY_FAILED_UNDEFINED_ERROR;
break;
}
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_pval *
ndmpd_api_find_env(void *cookie, char *name)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
ulong_t i;
ndmp_pval *envp;
if (session == NULL)
return (NULL);
envp = session->ns_data.dd_env;
for (i = 0; envp && i < session->ns_data.dd_env_len; envp++, i++)
if (strcmp(name, envp->name) == 0)
return (envp);
return (NULL);
}
char *
ndmpd_api_get_env(void *cookie, char *name)
{
ndmp_pval *envp;
envp = ndmpd_api_find_env(cookie, name);
if (envp)
return (envp->value);
return (NULL);
}
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);
}
int
ndmpd_api_set_env(void *cookie, char *name, char *value)
{
char *valbuf;
int rv;
ndmp_pval *envp;
envp = ndmpd_api_find_env(cookie, name);
if (!envp) {
rv = ndmpd_api_add_env(cookie, name, value);
} else if (!(valbuf = strdup(value))) {
rv = -1;
} else {
rv = 0;
free(envp->value);
envp->value = valbuf;
}
return (rv);
}
void *
ndmpd_api_get_name(void *cookie, ulong_t name_index)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
if (session == NULL)
return (NULL);
if (name_index >= session->ns_data.dd_nlist_len)
return (NULL);
return (&session->ns_data.dd_nlist[name_index]);
}
int
ndmpd_api_dispatch(void *cookie, boolean_t block)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
int err;
if (session == NULL)
return (-1);
for (; ; ) {
err = ndmpd_select(session, block, HC_ALL);
if (err < 0 || session->ns_data.dd_abort == TRUE ||
session->ns_eof)
return (-1);
if (err == 0)
return (0);
block = FALSE;
}
}
int
ndmpd_api_add_file_handler(void *daemon_cookie, void *cookie, int fd,
ulong_t mode, ndmpd_file_handler_func_t *func)
{
ndmpd_session_t *session = (ndmpd_session_t *)daemon_cookie;
return (ndmpd_add_file_handler(session, cookie, fd, mode, HC_MODULE,
func));
}
int
ndmpd_api_remove_file_handler(void *cookie, int fd)
{
ndmpd_session_t *session = (ndmpd_session_t *)cookie;
return (ndmpd_remove_file_handler(session, fd));
}