📄 mover.c
字号:
/* -*- Mode: C -*- * mover.c * * Description : Data mover functions. * * Copyright (c) 1996,1997 PDC, Network Appliance. All Rights Reserved. * * $Id: mover.c,v 1.15 1998/05/26 03:52:19 tim Exp $ */#if !defined(lint) && !defined(SABER)static char rcsId[] __attribute__ ((unused)) = "@(#) $Id: mover.c,v 1.15 1998/05/26 03:52:19 tim Exp $";#endif#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/mtio.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <errno.h>#include <sys/utsname.h>#include <fcntl.h>#include <string.h>#include "ndmp_common.h"#include "ndmpd.h"/* * Set the following to force EOT processing to occur after * DEBUG_TAPE_SIZE records have been read/written. * This makes it easier to do EOT testing. * Define to 0xffffffff for production. */#define DEBUG_TAPE_SIZE 0xffffffffstatic intmoverListen(NdmpdSession* session, u_long *addr, u_short *port);static voidmoverAcceptConnection(void* cookie, int fd, u_long mode);static voidmoverDataRead(void* cookie, int fd, u_long mode);static voidmoverDataWrite(void* cookie, int fd, u_long mode);static intmoverChangeTape(NdmpdSession* session);static intmoverTapeWrite(NdmpdSession* session, char* data, ssize_t length);static intmoverTapeFlush(NdmpdSession* session);static intmoverTapeRead(NdmpdSession* session, char* data);/* * ndmpdMoverGetState * * This handler handles the ndmp_mover_get_state_request. * Status information for the mover state machine is returned. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverGetState(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_mover_get_state_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverGetState:\n"); memset((void*)&reply, 0, sizeof(reply)); reply.error = NDMP_NO_ERR; reply.state = session->mover.state; reply.pause_reason = session->mover.pauseReason; reply.halt_reason = session->mover.haltReason; reply.record_size = session->mover.recordSize; reply.record_num = session->mover.recordNum; reply.data_written = longLongToQuad(session->mover.dataWritten); reply.seek_position = longLongToQuad(session->mover.seekPosition); reply.bytes_left_to_read = longLongToQuad(session->mover.bytesLeftToRead); reply.window_offset = longLongToQuad(session->mover.windowOffset); reply.window_length = longLongToQuad(session->mover.windowLength); if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverGetState: error sending ndmp_mover_get_state_reply.\n");}/* * ndmpdMoverListen * * This handler handles ndmp_mover_listen_requests. * A TCP/IP socket is created that is used to listen for * and accept data connections initiated by a remote * data server. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverListen(NdmpConnection connection, void* body){ ndmp_mover_listen_request* request = (ndmp_mover_listen_request*)body; ndmp_mover_listen_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverListen: mode:%s type:%s.\n", request->mode == NDMP_MOVER_MODE_READ ? "READ" : "WRITE", request->addr_type == NDMP_ADDR_LOCAL ? "LOCAL" : request->addr_type == NDMP_ADDR_TCP ? "TCP" : request->addr_type == NDMP_ADDR_FC ? "FC" : request->addr_type == NDMP_ADDR_IPC ? "IPC" : "undefined"); memset((void*)&reply, 0, sizeof(reply)); if (session->mover.state != NDMP_MOVER_STATE_IDLE) { Error(LOG_ERR, "ndmpdMoverListen: invalid mover state to process listen request.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending ndmp_mover_listen_reply.\n"); return; } if (session->data.state != NDMP_DATA_STATE_IDLE) { Error(LOG_ERR, "ndmpdMoverListen: invalid data state to process listen request.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending ndmp_mover_listen_reply.\n"); return; } if (session->tape.fd == -1) { Error(LOG_ERR, "ndmpdMoverListen: no tape device open.\n"); reply.error = NDMP_DEV_NOT_OPEN_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending ndmp_mover_listen_reply.\n"); return; } if (request->mode == NDMP_MOVER_MODE_READ && session->tape.mode == NDMP_TAPE_READ_MODE) { Error(LOG_ERR, "ndmpdMoverListen: write protected device.\n"); reply.error = NDMP_WRITE_PROTECT_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending ndmp_mover_listen_reply.\n"); return; } switch (request->addr_type) { case NDMP_ADDR_LOCAL: { reply.data_connection_addr.addr_type = NDMP_ADDR_LOCAL; reply.error = NDMP_NO_ERR; break; } case NDMP_ADDR_TCP: { u_long addr; u_short port; if (moverListen(session, &addr, &port) < 0) { reply.error = NDMP_IO_ERR; break; } reply.error = NDMP_NO_ERR; reply.data_connection_addr.addr_type = NDMP_ADDR_TCP; reply.data_connection_addr.ndmp_addr_u.tcp_addr.ip_addr = htonl(addr); reply.data_connection_addr.ndmp_addr_u.tcp_addr.port = htons(port); break; } default: { Error(LOG_ERR, "ndmpdMoverListen: invalid address type: %d.\n", request->addr_type); reply.error = NDMP_ILLEGAL_ARGS_ERR; } } if (reply.error != NDMP_NO_ERR) { if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending ndmp_mover_listen_reply.\n"); return; } session->mover.mode = request->mode; session->mover.state = NDMP_MOVER_STATE_LISTEN; /* Set the default window. */ session->mover.windowOffset = 0; session->mover.windowLength = 0xffffffffffffffffLL; session->mover.position = 0; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverListen: error sending mover_listen reply.\n");}/* * ndmpdMoverContinue * * This handler handles ndmp_mover_continue_requests. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverContinue(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_mover_continue_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverContinue.\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->mover.state != NDMP_MOVER_STATE_PAUSED) { Error(LOG_ERR, "ndmpdMoverContinue: invalid state.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverContinue: error sending mover_continue reply.\n"); return; } session->mover.state = NDMP_MOVER_STATE_ACTIVE; /* * Restore the file handler if the mover is remote to the data * server and the handler was removed pending the continuation of a * seek request. The handler is removed in moverDataWrite(). */ if (session->mover.pauseReason == NDMP_MOVER_PAUSE_SEEK && session->mover.sock != -1) { if (ndmpdAddFileHandler(session, (void*)session, session->mover.sock, NDMPD_SELECT_MODE_WRITE, HC_MOVER, moverDataWrite) < 0) ndmpdMoverError(session, NDMP_MOVER_HALT_INTERNAL_ERROR); } reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverContinue: error sending mover_continue reply.\n");} /* * ndmpdMoverAbort * * This handler handles ndmp_mover_abort_requests. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverAbort(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_mover_abort_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverAbort.\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->mover.state == NDMP_MOVER_STATE_IDLE || session->mover.state == NDMP_MOVER_STATE_HALTED) { Error(LOG_ERR, "ndmpdMoverAbort: invalid state.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverAbort: error sending mover_abort reply.\n"); return; } reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverAbort: error sending mover_abort reply.\n"); ndmpdMoverError(session, NDMP_MOVER_HALT_ABORTED);}/* * ndmpdMoverStop * * This handler handles ndmp_mover_stop_requests. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverStop(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_mover_stop_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverStop.\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->mover.state != NDMP_MOVER_STATE_HALTED) { Error(LOG_ERR, "ndmpdMoverStop: invalid state.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverStop: error sending mover_stop reply.\n"); return; } reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverStop: error sending mover_stop reply.\n"); ndmpdMoverCleanup(session); ndmpdMoverInit(session);}/* * ndmpdMoverSetWindow * * This handler handles ndmp_mover_set_window_requests. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverSetWindow(NdmpConnection connection, void* body){ ndmp_mover_set_window_request* request = (ndmp_mover_set_window_request*)body; ndmp_mover_set_window_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverSetWindow: offset:%llu length:%llu.\n", request->offset, request->length); memset((void*)&reply, 0, sizeof(reply)); if (!(session->mover.state == NDMP_MOVER_STATE_LISTEN || session->mover.state == NDMP_MOVER_STATE_PAUSED)) { Error(LOG_ERR, "ndmpdMoverSetWindow: invalid state.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverSetWindow: error sending ndmp_mover_set_window_reply.\n"); return; } session->mover.windowOffset = quadToLongLong(request->offset); session->mover.windowLength = quadToLongLong(request->length); session->mover.position = session->mover.windowOffset; reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverSetWindow: error sending mover_set_window reply.\n");}/* * ndmpdMoverRead * * This handler handles ndmp_mover_read_requests. * If the requested offset is outside of the current window, * the mover is paused and a notify_mover_paused request is sent * notifying the client that a seek is required. * If the requested offest is within the window but not within the * current record, then the tape is positioned to the record containing * the requested offest. * The requested amount of data is then read from the tape device and * written to the data connection. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdMoverRead(NdmpConnection connection, void* body){ ndmp_mover_read_request* request = (ndmp_mover_read_request*)body; ndmp_mover_read_reply reply; NdmpdSession* session = ndmpGetClientData(connection); int err; Debug(DBG_CAT_MOVER|DBG_FOC_FLOW, "ndmpdMoverRead: offset:%llu len:%llu.\n", quadToLongLong(request->offset), quadToLongLong(request->length)); memset((void*)&reply, 0, sizeof(reply)); if (session->mover.state != NDMP_MOVER_STATE_ACTIVE || session->mover.bytesLeftToRead != 0 || session->mover.mode != NDMP_MOVER_MODE_WRITE) { Error(LOG_ERR, "ndmpdMoverRead: invalid state.\n"); reply.error = NDMP_ILLEGAL_STATE_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdMoverRead: error sending ndmp_mover_read_reply.\n"); return; } if (session->tape.fd == -1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -