scsi.c
来自「网络数据管理协议的开发」· C语言 代码 · 共 430 行
C
430 行
/* -*- Mode: C -*- * scsi.c * * Description : NDMP SCSI request handler functions. * * Copyright (c) 1996,1997 PDC, Network Appliance. All Rights Reserved. * * $Id: scsi.c,v 1.7 1998/02/09 06:52:38 tim Exp $ */#if !defined(lint) && !defined(SABER)static char rcsId[] __attribute__ ((unused)) = "@(#) $Id: scsi.c,v 1.7 1998/02/09 06:52:38 tim Exp $";#endif#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/scsi/scsi.h>#include <sys/scsi/impl/uscsi.h>#include "ndmp_common.h"#include "ndmpd.h"voidexecuteCdb(NdmpdSession* session, int fd, ndmp_execute_cdb_request* request);/* * ndmpdScsiOpen * * This handler opens the specified SCSI device. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiOpen(NdmpConnection connection, void* body){ ndmp_scsi_open_request* request = (ndmp_scsi_open_request *)body; ndmp_scsi_open_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiOpen: device:%s.\n", request->device); memset((void*)&reply, 0, sizeof(reply)); if (session->tape.fd != -1 || session->scsi.fd != -1) { Error(LOG_ERR, "ndmpdScsiOpen: connection already has a tape or scsi device open.\n"); reply.error = NDMP_DEVICE_OPENED_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n"); return; } if ((session->scsi.fd = open(request->device, O_RDONLY)) < 0) { Error(LOG_ERR, "ndmpdScsiOpen: error opening SCSI device: %s: %s.\n", request->device, strerror(errno)); switch (errno) { case EACCES: reply.error = NDMP_WRITE_PROTECT_ERR; break; case ENOENT: reply.error = NDMP_NO_DEVICE_ERR; break; case EBUSY: reply.error = NDMP_DEVICE_BUSY_ERR; break; default: reply.error = NDMP_IO_ERR; break; } if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n"); return; } reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiOpen: error sending scsi_open reply.\n");}/* * ndmpdScsiClose * * This handler closes the currently open SCSI device. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiClose(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_scsi_close_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiClose:\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->scsi.fd == -1) { Error(LOG_ERR, "ndmpdScsiClose: SCSI device is not open.\n"); reply.error = NDMP_DEV_NOT_OPEN_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpScsiClose: error sending scsi_close reply.\n"); return; } (void) close(session->scsi.fd); session->scsi.fd = -1; reply.error = NDMP_NO_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiClose: error sending scsi_close reply.\n");}/* * ndmpdScsiGetState * * This handler returns state information for the currently open SCSI device. * Since the implementation only supports the opening of a specific SCSI * device, as opposed to a device that can talk to multiple SCSI targets, * this request is not supported. This request is only appropriate for * implementations that support device files that can target multiple * SCSI devices. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiGetState(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_scsi_get_state_reply reply; Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiGetState:\n"); Error(LOG_ERR, "ndmpdScsiGetState: request not yet supported.\n"); reply.error = NDMP_NOT_SUPPORTED_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiGetState: error sending scsi_get_state reply.\n");}/* * ndmpdScsiSetTarget * * This handler sets the SCSI target of the SCSI device. * It is only valid to use this request if the opened SCSI device * is capable of talking to multiple SCSI targets. * Since the implementation only supports the opening of a specific SCSI * device, as opposed to a device that can talk to multiple SCSI targets, * this request is not supported. This request is only appropriate for * implementations that support device files that can target multiple * SCSI devices. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiSetTarget(NdmpConnection connection, void* body){ ndmp_scsi_set_target_request* request = (ndmp_scsi_set_target_request *)body; ndmp_scsi_set_target_reply reply; Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiSetTarget: device:%s.\n", request->device); memset((void*)&reply, 0, sizeof(reply)); Error(LOG_ERR, "ndmpdScsiSetTarget: request not yet supported.\n"); reply.error = NDMP_NOT_SUPPORTED_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiSetTarget: error sending scsi_set_target reply.\n");}/* * ndmpdScsiResetDevice * * This handler resets the currently targeted SCSI device. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiResetDevice(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_scsi_reset_device_reply reply; NdmpdSession* session = ndmpGetClientData(connection); struct uscsi_cmd cmd; Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiResetDevice:\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->scsi.fd == -1) { Error(LOG_ERR, "ndmpdScsiResetDevice: SCSI device is not open.\n"); reply.error = NDMP_DEV_NOT_OPEN_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiResetDevice: error sending scsi_reset_device reply.\n"); return; } reply.error = NDMP_NO_ERR; memset((void*)&cmd, 0, sizeof(cmd)); cmd.uscsi_flags |= USCSI_RESET; if (ioctl(session->scsi.fd, USCSICMD, &cmd) < 0) { Error(LOG_ERR, "ndmpdScsiResetDevice: ioctl(USCSICMD) error: %s.\n", strerror(errno)); reply.error = NDMP_IO_ERR; } if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiResetDevice: error sending scsi_reset_device reply.\n");}/* * ndmpdScsiResetBus * * This handler resets the currently targeted SCSI bus. * * Request not yet supported. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiResetBus(NdmpConnection connection, void* body __attribute__ ((unused))){ ndmp_scsi_reset_bus_reply reply; Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiResetBus:\n"); memset((void*)&reply, 0, sizeof(reply)); Error(LOG_ERR, "ndmpdScsiResetBus: request not supported.\n"); reply.error = NDMP_NOT_SUPPORTED_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiResetBus: error sending scsi_reset_bus reply.\n");}/* * ndmpdScsiExecuteCdb * * This handler sends the CDB to the currently targeted SCSI device. * * Parameters: * connection (input) - connection handle. * body (input) - request message body. * * Returns: * void */voidndmpdScsiExecuteCdb(NdmpConnection connection, void* body){ ndmp_execute_cdb_request* request = (ndmp_execute_cdb_request *)body; ndmp_execute_cdb_reply reply; NdmpdSession* session = ndmpGetClientData(connection); Debug(DBG_CAT_SCSI|DBG_FOC_FLOW, "ndmpdScsiExecuteCdb:\n"); memset((void*)&reply, 0, sizeof(reply)); if (session->scsi.fd == -1) { memset((void*)&reply, 0, sizeof(reply)); Error(LOG_ERR, "ndmpdScsiExecuteCdb: SCSI device is not open.\n"); reply.error = NDMP_DEV_NOT_OPEN_ERR; if (ndmpSendReply(connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "ndmpdScsiExecuteCdb: sending scsi_execute_cdb reply.\n"); return; } executeCdb(session, session->scsi.fd, request);}voidexecuteCdb(NdmpdSession* session, int fd, ndmp_execute_cdb_request* request){ ndmp_execute_cdb_reply reply; struct uscsi_cmd cmd; char rqBuf[255]; memset((void*)&cmd, 0, sizeof(cmd)); memset((void*)&reply, 0, sizeof(reply)); if (request->flags == NDMP_SCSI_DATA_IN) { cmd.uscsi_flags = USCSI_READ; if ((cmd.uscsi_bufaddr = (caddr_t)malloc(request->datain_len)) == 0) { Error(LOG_ERR, "executeCdb: malloc error: %s.\n", strerror(errno)); reply.error = NDMP_NO_MEM_ERR; if (ndmpSendReply(session->connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "executeCdb: error sending scsi_execute_cdb reply.\n"); return; } cmd.uscsi_buflen = request->datain_len; } else { cmd.uscsi_flags = USCSI_WRITE; cmd.uscsi_bufaddr = request->dataout.dataout_val; cmd.uscsi_buflen = request->dataout.dataout_len; } cmd.uscsi_timeout = request->timeout/1000; cmd.uscsi_cdb = (caddr_t) request->cdb.cdb_val; cmd.uscsi_cdblen = request->cdb.cdb_len; cmd.uscsi_rqlen = sizeof(rqBuf); cmd.uscsi_rqbuf = rqBuf; reply.error = NDMP_NO_ERR; if (ioctl(fd, USCSICMD, &cmd) < 0) { Error(LOG_ERR, "executeCdb: ioctl(USCSICMD) error: %s.\n", strerror(errno)); reply.error = NDMP_IO_ERR; } reply.status = cmd.uscsi_status; if (request->flags == NDMP_SCSI_DATA_IN) { reply.datain.datain_len = request->datain_len - cmd.uscsi_resid; reply.datain.datain_val = cmd.uscsi_bufaddr; } else { reply.dataout_len = request->dataout.dataout_len - cmd.uscsi_resid; } reply.ext_sense.ext_sense_len = sizeof(rqBuf) - cmd.uscsi_rqresid; reply.ext_sense.ext_sense_val = rqBuf; if (ndmpSendReply(session->connection, NDMP_NO_ERR, (void *)&reply) < 0) Error(LOG_ERR, "executeCdb: error sending scsi_execute_cdb reply.\n");}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?