17917SReza.Sabdar@Sun.COM /* 2*8800SReza.Sabdar@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37917SReza.Sabdar@Sun.COM * Use is subject to license terms. 47917SReza.Sabdar@Sun.COM */ 57917SReza.Sabdar@Sun.COM 67917SReza.Sabdar@Sun.COM /* 77917SReza.Sabdar@Sun.COM * BSD 3 Clause License 87917SReza.Sabdar@Sun.COM * 97917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association. 107917SReza.Sabdar@Sun.COM * 117917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without 127917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions 137917SReza.Sabdar@Sun.COM * are met: 147917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright 157917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer. 167917SReza.Sabdar@Sun.COM * 177917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright 187917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in 197917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the 207917SReza.Sabdar@Sun.COM * distribution. 217917SReza.Sabdar@Sun.COM * 227917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA) 237917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote 247917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written 257917SReza.Sabdar@Sun.COM * permission. 267917SReza.Sabdar@Sun.COM * 277917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 287917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 297917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 307917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 317917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 327917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 337917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 347917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 357917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 367917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 377917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 387917SReza.Sabdar@Sun.COM */ 397917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */ 407917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 417917SReza.Sabdar@Sun.COM 427917SReza.Sabdar@Sun.COM #include <sys/param.h> 437917SReza.Sabdar@Sun.COM #include <fcntl.h> 447917SReza.Sabdar@Sun.COM #include <sys/mtio.h> 457917SReza.Sabdar@Sun.COM #include <errno.h> 467917SReza.Sabdar@Sun.COM #include <stdio.h> 477917SReza.Sabdar@Sun.COM #include <string.h> 487917SReza.Sabdar@Sun.COM #include <unistd.h> 497917SReza.Sabdar@Sun.COM #include "ndmpd_common.h" 507917SReza.Sabdar@Sun.COM #include "ndmpd.h" 517917SReza.Sabdar@Sun.COM 527917SReza.Sabdar@Sun.COM static void tape_open_send_reply(ndmp_connection_t *connection, int err); 537917SReza.Sabdar@Sun.COM static void unbuffered_read(ndmpd_session_t *session, char *buf, long wanted, 547917SReza.Sabdar@Sun.COM ndmp_tape_read_reply *reply); 557917SReza.Sabdar@Sun.COM static boolean_t validmode(int mode); 567917SReza.Sabdar@Sun.COM static void common_tape_open(ndmp_connection_t *connection, char *devname, 577917SReza.Sabdar@Sun.COM int ndmpmode); 587917SReza.Sabdar@Sun.COM static void common_tape_close(ndmp_connection_t *connection); 597917SReza.Sabdar@Sun.COM 607917SReza.Sabdar@Sun.COM /* 617917SReza.Sabdar@Sun.COM * Configurable delay & time when the tape is 627917SReza.Sabdar@Sun.COM * busy during opening the tape. 637917SReza.Sabdar@Sun.COM */ 647917SReza.Sabdar@Sun.COM int ndmp_tape_open_retries = 5; 657917SReza.Sabdar@Sun.COM int ndmp_tape_open_delay = 1000; 667917SReza.Sabdar@Sun.COM 677917SReza.Sabdar@Sun.COM /* 687917SReza.Sabdar@Sun.COM * ************************************************************************ 697917SReza.Sabdar@Sun.COM * NDMP V2 HANDLERS 707917SReza.Sabdar@Sun.COM * ************************************************************************ 717917SReza.Sabdar@Sun.COM */ 727917SReza.Sabdar@Sun.COM 737917SReza.Sabdar@Sun.COM /* 747917SReza.Sabdar@Sun.COM * ndmpd_tape_open_v2 757917SReza.Sabdar@Sun.COM * 767917SReza.Sabdar@Sun.COM * This handler opens the specified tape device. 777917SReza.Sabdar@Sun.COM * 787917SReza.Sabdar@Sun.COM * Parameters: 797917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 807917SReza.Sabdar@Sun.COM * body (input) - request message body. 817917SReza.Sabdar@Sun.COM * 827917SReza.Sabdar@Sun.COM * Returns: 837917SReza.Sabdar@Sun.COM * void 847917SReza.Sabdar@Sun.COM */ 857917SReza.Sabdar@Sun.COM void 867917SReza.Sabdar@Sun.COM ndmpd_tape_open_v2(ndmp_connection_t *connection, void *body) 877917SReza.Sabdar@Sun.COM { 887917SReza.Sabdar@Sun.COM ndmp_tape_open_request_v2 *request = (ndmp_tape_open_request_v2 *) body; 897917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 907917SReza.Sabdar@Sun.COM char adptnm[SCSI_MAX_NAME]; 917917SReza.Sabdar@Sun.COM int mode; 927917SReza.Sabdar@Sun.COM int sid, lun; 937917SReza.Sabdar@Sun.COM int err; 947917SReza.Sabdar@Sun.COM scsi_adapter_t *sa; 957917SReza.Sabdar@Sun.COM int devid; 967917SReza.Sabdar@Sun.COM 977917SReza.Sabdar@Sun.COM err = NDMP_NO_ERR; 987917SReza.Sabdar@Sun.COM 997917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) { 1007917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_INFO, 1017917SReza.Sabdar@Sun.COM "Connection already has a tape or scsi device open"); 1027917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_OPENED_ERR; 1037917SReza.Sabdar@Sun.COM } else if (request->mode != NDMP_TAPE_READ_MODE && 1047917SReza.Sabdar@Sun.COM request->mode != NDMP_TAPE_WRITE_MODE && 1057917SReza.Sabdar@Sun.COM request->mode != NDMP_TAPE_RAW1_MODE) { 1067917SReza.Sabdar@Sun.COM err = NDMP_ILLEGAL_ARGS_ERR; 1077917SReza.Sabdar@Sun.COM } 1087917SReza.Sabdar@Sun.COM 1097917SReza.Sabdar@Sun.COM if ((sa = scsi_get_adapter(0)) != NULL) { 1107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 1117917SReza.Sabdar@Sun.COM "Adapter device opened: %s", request->device.name); 1127917SReza.Sabdar@Sun.COM (void) strlcpy(adptnm, request->device.name, SCSI_MAX_NAME-2); 1137917SReza.Sabdar@Sun.COM adptnm[SCSI_MAX_NAME-1] = '\0'; 1147917SReza.Sabdar@Sun.COM sid = lun = -1; 1157917SReza.Sabdar@Sun.COM } 1167917SReza.Sabdar@Sun.COM /* try to get the scsi id etc.... */ 1177917SReza.Sabdar@Sun.COM if (sa) { 1187917SReza.Sabdar@Sun.COM scsi_find_sid_lun(sa, request->device.name, &sid, &lun); 1197917SReza.Sabdar@Sun.COM if (ndmp_open_list_find(request->device.name, sid, lun) == 0 && 1207917SReza.Sabdar@Sun.COM (devid = tape_open(request->device.name, 1217917SReza.Sabdar@Sun.COM O_RDWR | O_NDELAY)) < 0) { 1227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Failed to open device %s: %m.", 1237917SReza.Sabdar@Sun.COM request->device.name); 1247917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 1257917SReza.Sabdar@Sun.COM } 1267917SReza.Sabdar@Sun.COM else 1277917SReza.Sabdar@Sun.COM (void) close(devid); 1287917SReza.Sabdar@Sun.COM } else { 1297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "%s: No such tape device.", 1307917SReza.Sabdar@Sun.COM request->device.name); 1317917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 1327917SReza.Sabdar@Sun.COM } 1337917SReza.Sabdar@Sun.COM if (err != NDMP_NO_ERR) { 1347917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 1357917SReza.Sabdar@Sun.COM return; 1367917SReza.Sabdar@Sun.COM } 1377917SReza.Sabdar@Sun.COM 1387917SReza.Sabdar@Sun.COM switch (ndmp_open_list_add(connection, adptnm, sid, lun, devid)) { 1397917SReza.Sabdar@Sun.COM case 0: 1407917SReza.Sabdar@Sun.COM err = NDMP_NO_ERR; 1417917SReza.Sabdar@Sun.COM break; 1427917SReza.Sabdar@Sun.COM case EBUSY: 1437917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_BUSY_ERR; 1447917SReza.Sabdar@Sun.COM break; 1457917SReza.Sabdar@Sun.COM case ENOMEM: 1467917SReza.Sabdar@Sun.COM err = NDMP_NO_MEM_ERR; 1477917SReza.Sabdar@Sun.COM break; 1487917SReza.Sabdar@Sun.COM default: 1497917SReza.Sabdar@Sun.COM err = NDMP_IO_ERR; 1507917SReza.Sabdar@Sun.COM } 1517917SReza.Sabdar@Sun.COM if (err != NDMP_NO_ERR) { 1527917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 1537917SReza.Sabdar@Sun.COM return; 1547917SReza.Sabdar@Sun.COM } 1557917SReza.Sabdar@Sun.COM 1567917SReza.Sabdar@Sun.COM /* 1577917SReza.Sabdar@Sun.COM * According to Connectathon 2001, the 0x7fffffff is a secret 1587917SReza.Sabdar@Sun.COM * code between "Workstartion Solutions" and * net_app. 1597917SReza.Sabdar@Sun.COM * If mode is set to this value, tape_open() won't fail if 1607917SReza.Sabdar@Sun.COM * the tape device is not ready. 1617917SReza.Sabdar@Sun.COM */ 1627917SReza.Sabdar@Sun.COM if (request->mode != NDMP_TAPE_RAW1_MODE && 1637917SReza.Sabdar@Sun.COM !is_tape_unit_ready(adptnm, 0)) { 1647917SReza.Sabdar@Sun.COM (void) ndmp_open_list_del(adptnm, sid, lun); 1657917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, NDMP_NO_TAPE_LOADED_ERR); 1667917SReza.Sabdar@Sun.COM return; 1677917SReza.Sabdar@Sun.COM } 1687917SReza.Sabdar@Sun.COM 1697917SReza.Sabdar@Sun.COM mode = (request->mode == NDMP_TAPE_READ_MODE) ? O_RDONLY : O_RDWR; 1707917SReza.Sabdar@Sun.COM mode |= O_NDELAY; 1717917SReza.Sabdar@Sun.COM if ((session->ns_tape.td_fd = open(request->device.name, mode)) < 0) { 1727917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Failed to open tape device %s: %m.", 1737917SReza.Sabdar@Sun.COM request->device.name); 1747917SReza.Sabdar@Sun.COM switch (errno) { 1757917SReza.Sabdar@Sun.COM case EACCES: 1767917SReza.Sabdar@Sun.COM err = NDMP_WRITE_PROTECT_ERR; 1777917SReza.Sabdar@Sun.COM break; 1787917SReza.Sabdar@Sun.COM case ENXIO: 1797917SReza.Sabdar@Sun.COM case ENOENT: 1807917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 1817917SReza.Sabdar@Sun.COM break; 1827917SReza.Sabdar@Sun.COM case EBUSY: 1837917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_BUSY_ERR; 1847917SReza.Sabdar@Sun.COM break; 1857917SReza.Sabdar@Sun.COM default: 1867917SReza.Sabdar@Sun.COM err = NDMP_IO_ERR; 1877917SReza.Sabdar@Sun.COM } 1887917SReza.Sabdar@Sun.COM 1897917SReza.Sabdar@Sun.COM (void) ndmp_open_list_del(adptnm, sid, lun); 1907917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 1917917SReza.Sabdar@Sun.COM return; 1927917SReza.Sabdar@Sun.COM } 1937917SReza.Sabdar@Sun.COM 1947917SReza.Sabdar@Sun.COM session->ns_tape.td_mode = request->mode; 1957917SReza.Sabdar@Sun.COM session->ns_tape.td_sid = sid; 1967917SReza.Sabdar@Sun.COM session->ns_tape.td_lun = lun; 1977917SReza.Sabdar@Sun.COM (void) strlcpy(session->ns_tape.td_adapter_name, adptnm, SCSI_MAX_NAME); 1987917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 1997917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 2007917SReza.Sabdar@Sun.COM 2017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Tape is opened fd: %d", session->ns_tape.td_fd); 2027917SReza.Sabdar@Sun.COM 2037917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, NDMP_NO_ERR); 2047917SReza.Sabdar@Sun.COM } 2057917SReza.Sabdar@Sun.COM 2067917SReza.Sabdar@Sun.COM 2077917SReza.Sabdar@Sun.COM /* 2087917SReza.Sabdar@Sun.COM * ndmpd_tape_close_v2 2097917SReza.Sabdar@Sun.COM * 2107917SReza.Sabdar@Sun.COM * This handler closes the currently open tape device. 2117917SReza.Sabdar@Sun.COM * 2127917SReza.Sabdar@Sun.COM * Parameters: 2137917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 2147917SReza.Sabdar@Sun.COM * body (input) - request message body. 2157917SReza.Sabdar@Sun.COM * 2167917SReza.Sabdar@Sun.COM * Returns: 2177917SReza.Sabdar@Sun.COM * void 2187917SReza.Sabdar@Sun.COM */ 2197917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 2207917SReza.Sabdar@Sun.COM void 2217917SReza.Sabdar@Sun.COM ndmpd_tape_close_v2(ndmp_connection_t *connection, void *body) 2227917SReza.Sabdar@Sun.COM { 2237917SReza.Sabdar@Sun.COM ndmp_tape_close_reply reply; 2247917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 2257917SReza.Sabdar@Sun.COM 2267917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 2277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 2287917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 2297917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2307917SReza.Sabdar@Sun.COM "sending tape_close reply"); 2317917SReza.Sabdar@Sun.COM return; 2327917SReza.Sabdar@Sun.COM } 2337917SReza.Sabdar@Sun.COM common_tape_close(connection); 2347917SReza.Sabdar@Sun.COM 2357917SReza.Sabdar@Sun.COM } 2367917SReza.Sabdar@Sun.COM 2377917SReza.Sabdar@Sun.COM /* 2387917SReza.Sabdar@Sun.COM * ndmpd_tape_get_state_v2 2397917SReza.Sabdar@Sun.COM * 2407917SReza.Sabdar@Sun.COM * This handler handles the tape_get_state request. 2417917SReza.Sabdar@Sun.COM * Status information for the currently open tape device is returned. 2427917SReza.Sabdar@Sun.COM * 2437917SReza.Sabdar@Sun.COM * Parameters: 2447917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 2457917SReza.Sabdar@Sun.COM * body (input) - request message body. 2467917SReza.Sabdar@Sun.COM * 2477917SReza.Sabdar@Sun.COM * Returns: 2487917SReza.Sabdar@Sun.COM * void 2497917SReza.Sabdar@Sun.COM */ 2507917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 2517917SReza.Sabdar@Sun.COM void 2527917SReza.Sabdar@Sun.COM ndmpd_tape_get_state_v2(ndmp_connection_t *connection, void *body) 2537917SReza.Sabdar@Sun.COM 2547917SReza.Sabdar@Sun.COM { 2557917SReza.Sabdar@Sun.COM ndmp_tape_get_state_reply_v2 reply; 2567917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 2577917SReza.Sabdar@Sun.COM struct mtget mtstatus; 2587917SReza.Sabdar@Sun.COM struct mtdrivetype_request dtpr; 2597917SReza.Sabdar@Sun.COM struct mtdrivetype dtp; 2607917SReza.Sabdar@Sun.COM 2617917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 2627917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 2637917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 2647917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 2657917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 2667917SReza.Sabdar@Sun.COM return; 2677917SReza.Sabdar@Sun.COM } 2687917SReza.Sabdar@Sun.COM 2697917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) < 0) { 2707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Failed to get status from tape: %m."); 2717917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m."); 2727917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 2737917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 2747917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 2757917SReza.Sabdar@Sun.COM return; 2767917SReza.Sabdar@Sun.COM } 2777917SReza.Sabdar@Sun.COM 2787917SReza.Sabdar@Sun.COM dtpr.size = sizeof (struct mtdrivetype); 2797917SReza.Sabdar@Sun.COM dtpr.mtdtp = &dtp; 2807917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) { 2817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 2827917SReza.Sabdar@Sun.COM "Failed to get drive type information from tape: %m."); 2837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m."); 2847917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 2857917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 2867917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 2877917SReza.Sabdar@Sun.COM return; 2887917SReza.Sabdar@Sun.COM } 2897917SReza.Sabdar@Sun.COM 2907917SReza.Sabdar@Sun.COM reply.flags = 0; 2917917SReza.Sabdar@Sun.COM 2927917SReza.Sabdar@Sun.COM reply.file_num = mtstatus.mt_fileno; 2937917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 2947917SReza.Sabdar@Sun.COM reply.block_size = dtp.bsize; 2957917SReza.Sabdar@Sun.COM if (dtp.bsize == 0) 2967917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno; 2977917SReza.Sabdar@Sun.COM else 2987917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno * 2997917SReza.Sabdar@Sun.COM (session->ns_mover.md_record_size / dtp.bsize); 3007917SReza.Sabdar@Sun.COM 3017917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 3027917SReza.Sabdar@Sun.COM reply.total_space = long_long_to_quad(0); /* not supported */ 3037917SReza.Sabdar@Sun.COM reply.space_remain = long_long_to_quad(0); /* not supported */ 3047917SReza.Sabdar@Sun.COM 3057917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 3067917SReza.Sabdar@Sun.COM "flags: 0x%x, file_num: %d, block_size: %d, blockno: %d", 3077917SReza.Sabdar@Sun.COM reply.flags, reply.file_num, reply.block_size, reply.blockno); 3087917SReza.Sabdar@Sun.COM 3097917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 3107917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 3117917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 3127917SReza.Sabdar@Sun.COM } 3137917SReza.Sabdar@Sun.COM 3147917SReza.Sabdar@Sun.COM 3157917SReza.Sabdar@Sun.COM /* 3167917SReza.Sabdar@Sun.COM * ndmpd_tape_mtio_v2 3177917SReza.Sabdar@Sun.COM * 3187917SReza.Sabdar@Sun.COM * This handler handles tape_mtio requests. 3197917SReza.Sabdar@Sun.COM * 3207917SReza.Sabdar@Sun.COM * Parameters: 3217917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 3227917SReza.Sabdar@Sun.COM * body (input) - request message body. 3237917SReza.Sabdar@Sun.COM * 3247917SReza.Sabdar@Sun.COM * Returns: 3257917SReza.Sabdar@Sun.COM * void 3267917SReza.Sabdar@Sun.COM */ 3277917SReza.Sabdar@Sun.COM void 3287917SReza.Sabdar@Sun.COM ndmpd_tape_mtio_v2(ndmp_connection_t *connection, void *body) 3297917SReza.Sabdar@Sun.COM { 3307917SReza.Sabdar@Sun.COM ndmp_tape_mtio_request *request = (ndmp_tape_mtio_request *) body; 3317917SReza.Sabdar@Sun.COM ndmp_tape_mtio_reply reply; 3327917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 3337917SReza.Sabdar@Sun.COM 3347917SReza.Sabdar@Sun.COM struct mtop tapeop; 3357917SReza.Sabdar@Sun.COM struct mtget mtstatus; 3367917SReza.Sabdar@Sun.COM int retry = 0; 3377917SReza.Sabdar@Sun.COM int rc; 3387917SReza.Sabdar@Sun.COM 3397917SReza.Sabdar@Sun.COM reply.resid_count = 0; 3407917SReza.Sabdar@Sun.COM 3417917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 3427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 3437917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 3447917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 3457917SReza.Sabdar@Sun.COM "sending tape_mtio reply"); 3467917SReza.Sabdar@Sun.COM return; 3477917SReza.Sabdar@Sun.COM } 3487917SReza.Sabdar@Sun.COM 3497917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 3507917SReza.Sabdar@Sun.COM switch (request->tape_op) { 3517917SReza.Sabdar@Sun.COM case NDMP_MTIO_FSF: 3527917SReza.Sabdar@Sun.COM tapeop.mt_op = MTFSF; 3537917SReza.Sabdar@Sun.COM break; 3547917SReza.Sabdar@Sun.COM case NDMP_MTIO_BSF: 3557917SReza.Sabdar@Sun.COM tapeop.mt_op = MTBSF; 3567917SReza.Sabdar@Sun.COM break; 3577917SReza.Sabdar@Sun.COM case NDMP_MTIO_FSR: 3587917SReza.Sabdar@Sun.COM tapeop.mt_op = MTFSR; 3597917SReza.Sabdar@Sun.COM break; 3607917SReza.Sabdar@Sun.COM case NDMP_MTIO_BSR: 3617917SReza.Sabdar@Sun.COM tapeop.mt_op = MTBSR; 3627917SReza.Sabdar@Sun.COM break; 3637917SReza.Sabdar@Sun.COM case NDMP_MTIO_REW: 3647917SReza.Sabdar@Sun.COM tapeop.mt_op = MTREW; 3657917SReza.Sabdar@Sun.COM break; 3667917SReza.Sabdar@Sun.COM case NDMP_MTIO_EOF: 3677917SReza.Sabdar@Sun.COM if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) 3687917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 3697917SReza.Sabdar@Sun.COM tapeop.mt_op = MTWEOF; 3707917SReza.Sabdar@Sun.COM break; 3717917SReza.Sabdar@Sun.COM case NDMP_MTIO_OFF: 3727917SReza.Sabdar@Sun.COM tapeop.mt_op = MTOFFL; 3737917SReza.Sabdar@Sun.COM break; 3747917SReza.Sabdar@Sun.COM 3757917SReza.Sabdar@Sun.COM case NDMP_MTIO_TUR: /* test unit ready */ 3767917SReza.Sabdar@Sun.COM 3777917SReza.Sabdar@Sun.COM if (is_tape_unit_ready(session->ns_tape.td_adapter_name, 3787917SReza.Sabdar@Sun.COM session->ns_tape.td_fd) == 0) 3797917SReza.Sabdar@Sun.COM /* tape not ready ? */ 3807917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_TAPE_LOADED_ERR; 3817917SReza.Sabdar@Sun.COM break; 3827917SReza.Sabdar@Sun.COM 3837917SReza.Sabdar@Sun.COM default: 3847917SReza.Sabdar@Sun.COM reply.error = NDMP_ILLEGAL_ARGS_ERR; 3857917SReza.Sabdar@Sun.COM } 3867917SReza.Sabdar@Sun.COM 3877917SReza.Sabdar@Sun.COM if (reply.error == NDMP_NO_ERR && request->tape_op != NDMP_MTIO_TUR) { 3887917SReza.Sabdar@Sun.COM tapeop.mt_count = request->count; 3897917SReza.Sabdar@Sun.COM 3907917SReza.Sabdar@Sun.COM do { 3917917SReza.Sabdar@Sun.COM NS_UPD(twait, trun); 3927917SReza.Sabdar@Sun.COM rc = ioctl(session->ns_tape.td_fd, MTIOCTOP, &tapeop); 3937917SReza.Sabdar@Sun.COM NS_UPD(trun, twait); 3947917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 3957917SReza.Sabdar@Sun.COM "ioctl MTIO rc:%d, cmd:%d, retry:%d, error: %d", 3967917SReza.Sabdar@Sun.COM rc, tapeop.mt_op, retry, errno); 3977917SReza.Sabdar@Sun.COM } while (rc < 0 && errno == EIO && 3987917SReza.Sabdar@Sun.COM retry++ < 5); 3997917SReza.Sabdar@Sun.COM 4007917SReza.Sabdar@Sun.COM /* 4017917SReza.Sabdar@Sun.COM * Ignore I/O errors since these usually are the result of 4027917SReza.Sabdar@Sun.COM * attempting to position past the beginning or end of the tape. 4037917SReza.Sabdar@Sun.COM * The residual count will be returned and can be used to 4047917SReza.Sabdar@Sun.COM * determine that the call was not completely successful. 4057917SReza.Sabdar@Sun.COM */ 4067917SReza.Sabdar@Sun.COM if (rc < 0) { 4077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 4087917SReza.Sabdar@Sun.COM "Failed to send command to tape: %m."); 4097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCTOP) error: %m."); 4107917SReza.Sabdar@Sun.COM 4117917SReza.Sabdar@Sun.COM /* MTWEOF doesnt have residual count */ 4127917SReza.Sabdar@Sun.COM if (tapeop.mt_op == MTWEOF) 4137917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 4147917SReza.Sabdar@Sun.COM else 4157917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 4167917SReza.Sabdar@Sun.COM reply.resid_count = tapeop.mt_count; 4177917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 4187917SReza.Sabdar@Sun.COM "sending tape_mtio reply"); 4197917SReza.Sabdar@Sun.COM return; 4207917SReza.Sabdar@Sun.COM } 4217917SReza.Sabdar@Sun.COM 4227917SReza.Sabdar@Sun.COM if (request->tape_op != NDMP_MTIO_REW && 4237917SReza.Sabdar@Sun.COM request->tape_op != NDMP_MTIO_OFF) { 4247917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGET, 4257917SReza.Sabdar@Sun.COM &mtstatus) < 0) { 4267917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 4277917SReza.Sabdar@Sun.COM "Failed to send command to tape: %m."); 4287917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 4297917SReza.Sabdar@Sun.COM "ioctl(MTIOCGET) error: %m."); 4307917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 4317917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 4327917SReza.Sabdar@Sun.COM "sending tape_mtio reply"); 4337917SReza.Sabdar@Sun.COM 4347917SReza.Sabdar@Sun.COM return; 4357917SReza.Sabdar@Sun.COM } 4367917SReza.Sabdar@Sun.COM 4377917SReza.Sabdar@Sun.COM reply.resid_count = labs(mtstatus.mt_resid); 4387917SReza.Sabdar@Sun.COM } 4397917SReza.Sabdar@Sun.COM } 4407917SReza.Sabdar@Sun.COM 4417917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "resid_count: %d", 4427917SReza.Sabdar@Sun.COM reply.resid_count); 4437917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, "sending tape_mtio reply"); 4447917SReza.Sabdar@Sun.COM } 4457917SReza.Sabdar@Sun.COM 4467917SReza.Sabdar@Sun.COM 4477917SReza.Sabdar@Sun.COM /* 4487917SReza.Sabdar@Sun.COM * ndmpd_tape_write_v2 4497917SReza.Sabdar@Sun.COM * 4507917SReza.Sabdar@Sun.COM * This handler handles tape_write requests. 4517917SReza.Sabdar@Sun.COM * This interface is a non-buffered interface. Each write request 4527917SReza.Sabdar@Sun.COM * maps directly to a write to the tape device. It is the responsibility 4537917SReza.Sabdar@Sun.COM * of the NDMP client to pad the data to the desired record size. 4547917SReza.Sabdar@Sun.COM * It is the responsibility of the NDMP client to ensure that the 4557917SReza.Sabdar@Sun.COM * length is a multiple of the tape block size if the tape device 4567917SReza.Sabdar@Sun.COM * is in fixed block mode. 4577917SReza.Sabdar@Sun.COM * 4587917SReza.Sabdar@Sun.COM * Parameters: 4597917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 4607917SReza.Sabdar@Sun.COM * body (input) - request message body. 4617917SReza.Sabdar@Sun.COM * 4627917SReza.Sabdar@Sun.COM * Returns: 4637917SReza.Sabdar@Sun.COM * void 4647917SReza.Sabdar@Sun.COM */ 4657917SReza.Sabdar@Sun.COM void 4667917SReza.Sabdar@Sun.COM ndmpd_tape_write_v2(ndmp_connection_t *connection, void *body) 4677917SReza.Sabdar@Sun.COM { 4687917SReza.Sabdar@Sun.COM ndmp_tape_write_request *request = (ndmp_tape_write_request *) body; 4697917SReza.Sabdar@Sun.COM ndmp_tape_write_reply reply; 4707917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 4717917SReza.Sabdar@Sun.COM ssize_t n; 4727917SReza.Sabdar@Sun.COM 4737917SReza.Sabdar@Sun.COM reply.count = 0; 4747917SReza.Sabdar@Sun.COM 4757917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 4767917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 4777917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 4787917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 4797917SReza.Sabdar@Sun.COM "sending tape_write reply"); 4807917SReza.Sabdar@Sun.COM return; 4817917SReza.Sabdar@Sun.COM } 4827917SReza.Sabdar@Sun.COM if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 4837917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_INFO, "Tape device opened in read-only mode"); 4847917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 4857917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 4867917SReza.Sabdar@Sun.COM "sending tape_write reply"); 4877917SReza.Sabdar@Sun.COM return; 4887917SReza.Sabdar@Sun.COM } 4897917SReza.Sabdar@Sun.COM if (request->data_out.data_out_len == 0) { 4907917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 4917917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 4927917SReza.Sabdar@Sun.COM "sending tape_write reply"); 4937917SReza.Sabdar@Sun.COM return; 4947917SReza.Sabdar@Sun.COM } 4957917SReza.Sabdar@Sun.COM 4967917SReza.Sabdar@Sun.COM if (session->ns_tape.td_eom_seen) { 4977917SReza.Sabdar@Sun.COM /* 4987917SReza.Sabdar@Sun.COM * Refer to the comment at the top of this file for 4997917SReza.Sabdar@Sun.COM * Mammoth2 tape drives. 5007917SReza.Sabdar@Sun.COM */ 5017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "eom_seen"); 5027917SReza.Sabdar@Sun.COM ndmpd_write_eom(session->ns_tape.td_fd); 5037917SReza.Sabdar@Sun.COM 5047917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 5057917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 5067917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 5077917SReza.Sabdar@Sun.COM "sending tape_write reply"); 5087917SReza.Sabdar@Sun.COM return; 5097917SReza.Sabdar@Sun.COM } 5107917SReza.Sabdar@Sun.COM 5117917SReza.Sabdar@Sun.COM n = write(session->ns_tape.td_fd, request->data_out.data_out_val, 5127917SReza.Sabdar@Sun.COM request->data_out.data_out_len); 5137917SReza.Sabdar@Sun.COM if (n >= 0) { 5147917SReza.Sabdar@Sun.COM session->ns_tape.td_write = 1; 5157917SReza.Sabdar@Sun.COM NS_ADD(wtape, n); 5167917SReza.Sabdar@Sun.COM } 5177917SReza.Sabdar@Sun.COM if (n == 0) { 5187917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "n == 0"); 5197917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 5207917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 5217917SReza.Sabdar@Sun.COM } else if (n < 0) { 5227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape write error: %m."); 5237917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 5247917SReza.Sabdar@Sun.COM } else { 5257917SReza.Sabdar@Sun.COM reply.count = n; 5267917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 5277917SReza.Sabdar@Sun.COM 5287917SReza.Sabdar@Sun.COM /* 5297917SReza.Sabdar@Sun.COM * a logical end of tape will return number of bytes written 5307917SReza.Sabdar@Sun.COM * less than rquested, and one more request to write will 5317917SReza.Sabdar@Sun.COM * give 0, and then no-space 5327917SReza.Sabdar@Sun.COM */ 5337917SReza.Sabdar@Sun.COM if (n < request->data_out.data_out_len) { 5347917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "LEOT: n: %d", n); 5357917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = TRUE; 5367917SReza.Sabdar@Sun.COM } else { 5377917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 5387917SReza.Sabdar@Sun.COM } 5397917SReza.Sabdar@Sun.COM } 5407917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, &reply, 5417917SReza.Sabdar@Sun.COM "sending tape_write reply"); 5427917SReza.Sabdar@Sun.COM } 5437917SReza.Sabdar@Sun.COM 5447917SReza.Sabdar@Sun.COM 5457917SReza.Sabdar@Sun.COM /* 5467917SReza.Sabdar@Sun.COM * ndmpd_tape_read_v2 5477917SReza.Sabdar@Sun.COM * 5487917SReza.Sabdar@Sun.COM * This handler handles tape_read requests. 5497917SReza.Sabdar@Sun.COM * This interface is a non-buffered interface. Each read request 5507917SReza.Sabdar@Sun.COM * maps directly to a read to the tape device. It is the responsibility 5517917SReza.Sabdar@Sun.COM * of the NDMP client to issue read requests with a length that is at 5527917SReza.Sabdar@Sun.COM * least as large as the record size used write the tape. The tape driver 5537917SReza.Sabdar@Sun.COM * always reads a full record. Data is discarded if the read request is 5547917SReza.Sabdar@Sun.COM * smaller than the record size. 5557917SReza.Sabdar@Sun.COM * It is the responsibility of the NDMP client to ensure that the 5567917SReza.Sabdar@Sun.COM * length is a multiple of the tape block size if the tape device 5577917SReza.Sabdar@Sun.COM * is in fixed block mode. 5587917SReza.Sabdar@Sun.COM * 5597917SReza.Sabdar@Sun.COM * Parameters: 5607917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 5617917SReza.Sabdar@Sun.COM * body (input) - request message body. 5627917SReza.Sabdar@Sun.COM * 5637917SReza.Sabdar@Sun.COM * Returns: 5647917SReza.Sabdar@Sun.COM * void 5657917SReza.Sabdar@Sun.COM */ 5667917SReza.Sabdar@Sun.COM void 5677917SReza.Sabdar@Sun.COM ndmpd_tape_read_v2(ndmp_connection_t *connection, void *body) 5687917SReza.Sabdar@Sun.COM { 5697917SReza.Sabdar@Sun.COM ndmp_tape_read_request *request = (ndmp_tape_read_request *) body; 5707917SReza.Sabdar@Sun.COM ndmp_tape_read_reply reply; 5717917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 5727917SReza.Sabdar@Sun.COM char *buf; 5737917SReza.Sabdar@Sun.COM 5747917SReza.Sabdar@Sun.COM reply.data_in.data_in_len = 0; 5757917SReza.Sabdar@Sun.COM 5767917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 5777917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 5787917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 5797917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 5807917SReza.Sabdar@Sun.COM "sending tape_read reply"); 5817917SReza.Sabdar@Sun.COM return; 5827917SReza.Sabdar@Sun.COM } 5837917SReza.Sabdar@Sun.COM if (request->count == 0) { 5847917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 5857917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 5867917SReza.Sabdar@Sun.COM "sending tape_read reply"); 5877917SReza.Sabdar@Sun.COM return; 5887917SReza.Sabdar@Sun.COM } 5897917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(request->count)) == 0) { 5907917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_MEM_ERR; 5917917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 5927917SReza.Sabdar@Sun.COM "sending tape_read reply"); 5937917SReza.Sabdar@Sun.COM return; 5947917SReza.Sabdar@Sun.COM } 5957917SReza.Sabdar@Sun.COM 5967917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 5977917SReza.Sabdar@Sun.COM 5987917SReza.Sabdar@Sun.COM unbuffered_read(session, buf, request->count, &reply); 5997917SReza.Sabdar@Sun.COM 6007917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, "sending tape_read reply"); 6017917SReza.Sabdar@Sun.COM (void) free(buf); 6027917SReza.Sabdar@Sun.COM } 6037917SReza.Sabdar@Sun.COM 6047917SReza.Sabdar@Sun.COM 6057917SReza.Sabdar@Sun.COM /* 6067917SReza.Sabdar@Sun.COM * ndmpd_tape_execute_cdb_v2 6077917SReza.Sabdar@Sun.COM * 6087917SReza.Sabdar@Sun.COM * This handler handles tape_execute_cdb requests. 6097917SReza.Sabdar@Sun.COM * 6107917SReza.Sabdar@Sun.COM * Parameters: 6117917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 6127917SReza.Sabdar@Sun.COM * body (input) - request message body. 6137917SReza.Sabdar@Sun.COM * 6147917SReza.Sabdar@Sun.COM * Returns: 6157917SReza.Sabdar@Sun.COM * void 6167917SReza.Sabdar@Sun.COM */ 6177917SReza.Sabdar@Sun.COM void 6187917SReza.Sabdar@Sun.COM ndmpd_tape_execute_cdb_v2(ndmp_connection_t *connection, void *body) 6197917SReza.Sabdar@Sun.COM { 6207917SReza.Sabdar@Sun.COM ndmp_tape_execute_cdb_request *request; 6217917SReza.Sabdar@Sun.COM ndmp_tape_execute_cdb_reply reply; 6227917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 6237917SReza.Sabdar@Sun.COM 6247917SReza.Sabdar@Sun.COM request = (ndmp_tape_execute_cdb_request *) body; 6257917SReza.Sabdar@Sun.COM 6267917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 6277917SReza.Sabdar@Sun.COM (void) memset((void *) &reply, 0, sizeof (reply)); 6287917SReza.Sabdar@Sun.COM 6297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 6307917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 6317917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 6327917SReza.Sabdar@Sun.COM "sending tape_execute_cdb reply"); 6337917SReza.Sabdar@Sun.COM } else { 6347917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 6357917SReza.Sabdar@Sun.COM ndmp_execute_cdb(session, session->ns_tape.td_adapter_name, 6367917SReza.Sabdar@Sun.COM session->ns_tape.td_sid, session->ns_tape.td_lun, 6377917SReza.Sabdar@Sun.COM (ndmp_execute_cdb_request *)request); 6387917SReza.Sabdar@Sun.COM } 6397917SReza.Sabdar@Sun.COM } 6407917SReza.Sabdar@Sun.COM 6417917SReza.Sabdar@Sun.COM 6427917SReza.Sabdar@Sun.COM /* 6437917SReza.Sabdar@Sun.COM * ************************************************************************ 6447917SReza.Sabdar@Sun.COM * NDMP V3 HANDLERS 6457917SReza.Sabdar@Sun.COM * ************************************************************************ 6467917SReza.Sabdar@Sun.COM */ 6477917SReza.Sabdar@Sun.COM 6487917SReza.Sabdar@Sun.COM /* 6497917SReza.Sabdar@Sun.COM * ndmpd_tape_open_v3 6507917SReza.Sabdar@Sun.COM * 6517917SReza.Sabdar@Sun.COM * This handler opens the specified tape device. 6527917SReza.Sabdar@Sun.COM * 6537917SReza.Sabdar@Sun.COM * Parameters: 6547917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 6557917SReza.Sabdar@Sun.COM * body (input) - request message body. 6567917SReza.Sabdar@Sun.COM * 6577917SReza.Sabdar@Sun.COM * Returns: 6587917SReza.Sabdar@Sun.COM * void 6597917SReza.Sabdar@Sun.COM */ 6607917SReza.Sabdar@Sun.COM void 6617917SReza.Sabdar@Sun.COM ndmpd_tape_open_v3(ndmp_connection_t *connection, void *body) 6627917SReza.Sabdar@Sun.COM { 6637917SReza.Sabdar@Sun.COM ndmp_tape_open_request_v3 *request = (ndmp_tape_open_request_v3 *)body; 6647917SReza.Sabdar@Sun.COM 6657917SReza.Sabdar@Sun.COM common_tape_open(connection, request->device, request->mode); 6667917SReza.Sabdar@Sun.COM } 6677917SReza.Sabdar@Sun.COM 6687917SReza.Sabdar@Sun.COM 6697917SReza.Sabdar@Sun.COM /* 6707917SReza.Sabdar@Sun.COM * ndmpd_tape_get_state_v3 6717917SReza.Sabdar@Sun.COM * 6727917SReza.Sabdar@Sun.COM * This handler handles the ndmp_tape_get_state_request. 6737917SReza.Sabdar@Sun.COM * Status information for the currently open tape device is returned. 6747917SReza.Sabdar@Sun.COM * 6757917SReza.Sabdar@Sun.COM * Parameters: 6767917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 6777917SReza.Sabdar@Sun.COM * body (input) - request message body. 6787917SReza.Sabdar@Sun.COM * 6797917SReza.Sabdar@Sun.COM * Returns: 6807917SReza.Sabdar@Sun.COM * void 6817917SReza.Sabdar@Sun.COM */ 6827917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 6837917SReza.Sabdar@Sun.COM void 6847917SReza.Sabdar@Sun.COM ndmpd_tape_get_state_v3(ndmp_connection_t *connection, void *body) 6857917SReza.Sabdar@Sun.COM { 6867917SReza.Sabdar@Sun.COM ndmp_tape_get_state_reply_v3 reply; 6877917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 6887917SReza.Sabdar@Sun.COM struct mtdrivetype_request dtpr; 6897917SReza.Sabdar@Sun.COM struct mtdrivetype dtp; 6907917SReza.Sabdar@Sun.COM struct mtget mtstatus; 6917917SReza.Sabdar@Sun.COM 6927917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 6937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 6947917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 6957917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 6967917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 6977917SReza.Sabdar@Sun.COM return; 6987917SReza.Sabdar@Sun.COM } 6997917SReza.Sabdar@Sun.COM 7007917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == -1) { 7017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Failed to get status from tape: %m."); 7027917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m."); 7037917SReza.Sabdar@Sun.COM 7047917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 7057917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 7067917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 7077917SReza.Sabdar@Sun.COM return; 7087917SReza.Sabdar@Sun.COM } 7097917SReza.Sabdar@Sun.COM 7107917SReza.Sabdar@Sun.COM dtpr.size = sizeof (struct mtdrivetype); 7117917SReza.Sabdar@Sun.COM dtpr.mtdtp = &dtp; 7127917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) { 7137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 7147917SReza.Sabdar@Sun.COM "Failed to get drive type information from tape: %m."); 7157917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m."); 7167917SReza.Sabdar@Sun.COM 7177917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 7187917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 7197917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 7207917SReza.Sabdar@Sun.COM return; 7217917SReza.Sabdar@Sun.COM } 7227917SReza.Sabdar@Sun.COM 7237917SReza.Sabdar@Sun.COM reply.flags = 0; 7247917SReza.Sabdar@Sun.COM 7257917SReza.Sabdar@Sun.COM reply.file_num = mtstatus.mt_fileno; 7267917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 7277917SReza.Sabdar@Sun.COM reply.block_size = dtp.bsize; 7287917SReza.Sabdar@Sun.COM if (dtp.bsize == 0) 7297917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno; 7307917SReza.Sabdar@Sun.COM else 7317917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno * 7327917SReza.Sabdar@Sun.COM (session->ns_mover.md_record_size / dtp.bsize); 7337917SReza.Sabdar@Sun.COM reply.total_space = long_long_to_quad(0); /* not supported */ 7347917SReza.Sabdar@Sun.COM reply.space_remain = long_long_to_quad(0); /* not supported */ 7357917SReza.Sabdar@Sun.COM reply.partition = 0; /* not supported */ 7367917SReza.Sabdar@Sun.COM 7377917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 7387917SReza.Sabdar@Sun.COM reply.total_space = long_long_to_quad(0LL); 7397917SReza.Sabdar@Sun.COM reply.space_remain = long_long_to_quad(0LL); 7407917SReza.Sabdar@Sun.COM 7417917SReza.Sabdar@Sun.COM reply.invalid = NDMP_TAPE_STATE_SOFT_ERRORS_INVALID | 7427917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_TOTAL_SPACE_INVALID | 7437917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_SPACE_REMAIN_INVALID | 7447917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_PARTITION_INVALID; 7457917SReza.Sabdar@Sun.COM 7467917SReza.Sabdar@Sun.COM 7477917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "f 0x%x, fnum %d, bsize %d, bno: %d", 7487917SReza.Sabdar@Sun.COM reply.flags, reply.file_num, reply.block_size, reply.blockno); 7497917SReza.Sabdar@Sun.COM 7507917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 7517917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7527917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 7537917SReza.Sabdar@Sun.COM } 7547917SReza.Sabdar@Sun.COM 7557917SReza.Sabdar@Sun.COM 7567917SReza.Sabdar@Sun.COM /* 7577917SReza.Sabdar@Sun.COM * ndmpd_tape_write_v3 7587917SReza.Sabdar@Sun.COM * 7597917SReza.Sabdar@Sun.COM * This handler handles tape_write requests. 7607917SReza.Sabdar@Sun.COM * This interface is a non-buffered interface. Each write request 7617917SReza.Sabdar@Sun.COM * maps directly to a write to the tape device. It is the responsibility 7627917SReza.Sabdar@Sun.COM * of the NDMP client to pad the data to the desired record size. 7637917SReza.Sabdar@Sun.COM * It is the responsibility of the NDMP client to ensure that the 7647917SReza.Sabdar@Sun.COM * length is a multiple of the tape block size if the tape device 7657917SReza.Sabdar@Sun.COM * is in fixed block mode. 7667917SReza.Sabdar@Sun.COM * 7677917SReza.Sabdar@Sun.COM * Parameters: 7687917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 7697917SReza.Sabdar@Sun.COM * body (input) - request message body. 7707917SReza.Sabdar@Sun.COM * 7717917SReza.Sabdar@Sun.COM * Returns: 7727917SReza.Sabdar@Sun.COM * void 7737917SReza.Sabdar@Sun.COM */ 7747917SReza.Sabdar@Sun.COM void 7757917SReza.Sabdar@Sun.COM ndmpd_tape_write_v3(ndmp_connection_t *connection, void *body) 7767917SReza.Sabdar@Sun.COM { 7777917SReza.Sabdar@Sun.COM ndmp_tape_write_request *request = (ndmp_tape_write_request *) body; 7787917SReza.Sabdar@Sun.COM ndmp_tape_write_reply reply; 7797917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 7807917SReza.Sabdar@Sun.COM ssize_t n; 7817917SReza.Sabdar@Sun.COM 7827917SReza.Sabdar@Sun.COM reply.count = 0; 7837917SReza.Sabdar@Sun.COM 7847917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 7857917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 7867917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 7877917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7887917SReza.Sabdar@Sun.COM "sending tape_write reply"); 7897917SReza.Sabdar@Sun.COM return; 7907917SReza.Sabdar@Sun.COM } 7917917SReza.Sabdar@Sun.COM if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) { 7927917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_INFO, "Tape device opened in read-only mode"); 7937917SReza.Sabdar@Sun.COM reply.error = NDMP_PERMISSION_ERR; 7947917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 7957917SReza.Sabdar@Sun.COM "sending tape_write reply"); 7967917SReza.Sabdar@Sun.COM return; 7977917SReza.Sabdar@Sun.COM } 7987917SReza.Sabdar@Sun.COM if (request->data_out.data_out_len == 0) { 7997917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 8007917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8017917SReza.Sabdar@Sun.COM "sending tape_write reply"); 8027917SReza.Sabdar@Sun.COM return; 8037917SReza.Sabdar@Sun.COM } 8047917SReza.Sabdar@Sun.COM 8057917SReza.Sabdar@Sun.COM /* 8067917SReza.Sabdar@Sun.COM * V4 suggests that this should not be accepted 8077917SReza.Sabdar@Sun.COM * when mover is in listen or active state 8087917SReza.Sabdar@Sun.COM */ 8097917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4 && 8107917SReza.Sabdar@Sun.COM (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 8117917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE)) { 8127917SReza.Sabdar@Sun.COM 8137917SReza.Sabdar@Sun.COM reply.error = NDMP_DEVICE_BUSY_ERR; 8147917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8157917SReza.Sabdar@Sun.COM "sending tape_write reply"); 8167917SReza.Sabdar@Sun.COM return; 8177917SReza.Sabdar@Sun.COM } 8187917SReza.Sabdar@Sun.COM 8197917SReza.Sabdar@Sun.COM /* 8207917SReza.Sabdar@Sun.COM * Refer to the comment at the top of this file for 8217917SReza.Sabdar@Sun.COM * Mammoth2 tape drives. 8227917SReza.Sabdar@Sun.COM */ 8237917SReza.Sabdar@Sun.COM if (session->ns_tape.td_eom_seen) { 8247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "eom_seen"); 8257917SReza.Sabdar@Sun.COM ndmpd_write_eom(session->ns_tape.td_fd); 8267917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 8277917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 8287917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8297917SReza.Sabdar@Sun.COM "sending tape_write reply"); 8307917SReza.Sabdar@Sun.COM return; 8317917SReza.Sabdar@Sun.COM } 8327917SReza.Sabdar@Sun.COM 8337917SReza.Sabdar@Sun.COM n = write(session->ns_tape.td_fd, request->data_out.data_out_val, 8347917SReza.Sabdar@Sun.COM request->data_out.data_out_len); 8357917SReza.Sabdar@Sun.COM 8367917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 8377917SReza.Sabdar@Sun.COM if (n >= 0) { 8387917SReza.Sabdar@Sun.COM session->ns_tape.td_write = 1; 8397917SReza.Sabdar@Sun.COM NS_ADD(wtape, n); 8407917SReza.Sabdar@Sun.COM } 8417917SReza.Sabdar@Sun.COM if (n == 0) { 8427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_INFO, "EOM detected"); 8437917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 8447917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = TRUE; 8457917SReza.Sabdar@Sun.COM } else if (n < 0) { 8467917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape write error: %m."); 8477917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 8487917SReza.Sabdar@Sun.COM } else { 8497917SReza.Sabdar@Sun.COM reply.count = n; 8507917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 8517917SReza.Sabdar@Sun.COM } 8527917SReza.Sabdar@Sun.COM 8537917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8547917SReza.Sabdar@Sun.COM "sending tape_write reply"); 8557917SReza.Sabdar@Sun.COM } 8567917SReza.Sabdar@Sun.COM 8577917SReza.Sabdar@Sun.COM 8587917SReza.Sabdar@Sun.COM /* 8597917SReza.Sabdar@Sun.COM * ndmpd_tape_read_v3 8607917SReza.Sabdar@Sun.COM * 8617917SReza.Sabdar@Sun.COM * This handler handles tape_read requests. 8627917SReza.Sabdar@Sun.COM * This interface is a non-buffered interface. Each read request 8637917SReza.Sabdar@Sun.COM * maps directly to a read to the tape device. It is the responsibility 8647917SReza.Sabdar@Sun.COM * of the NDMP client to issue read requests with a length that is at 8657917SReza.Sabdar@Sun.COM * least as large as the record size used write the tape. The tape driver 8667917SReza.Sabdar@Sun.COM * always reads a full record. Data is discarded if the read request is 8677917SReza.Sabdar@Sun.COM * smaller than the record size. 8687917SReza.Sabdar@Sun.COM * It is the responsibility of the NDMP client to ensure that the 8697917SReza.Sabdar@Sun.COM * length is a multiple of the tape block size if the tape device 8707917SReza.Sabdar@Sun.COM * is in fixed block mode. 8717917SReza.Sabdar@Sun.COM * 8727917SReza.Sabdar@Sun.COM * Parameters: 8737917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 8747917SReza.Sabdar@Sun.COM * body (input) - request message body. 8757917SReza.Sabdar@Sun.COM * 8767917SReza.Sabdar@Sun.COM * Returns: 8777917SReza.Sabdar@Sun.COM * void 8787917SReza.Sabdar@Sun.COM */ 8797917SReza.Sabdar@Sun.COM void 8807917SReza.Sabdar@Sun.COM ndmpd_tape_read_v3(ndmp_connection_t *connection, void *body) 8817917SReza.Sabdar@Sun.COM { 8827917SReza.Sabdar@Sun.COM ndmp_tape_read_request *request = (ndmp_tape_read_request *) body; 8837917SReza.Sabdar@Sun.COM ndmp_tape_read_reply reply; 8847917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 8857917SReza.Sabdar@Sun.COM char *buf; 8867917SReza.Sabdar@Sun.COM int n, len; 8877917SReza.Sabdar@Sun.COM 8887917SReza.Sabdar@Sun.COM reply.data_in.data_in_len = 0; 8897917SReza.Sabdar@Sun.COM 8907917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 8917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 8927917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 8937917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 8947917SReza.Sabdar@Sun.COM "sending tape_read reply"); 8957917SReza.Sabdar@Sun.COM return; 8967917SReza.Sabdar@Sun.COM } 8977917SReza.Sabdar@Sun.COM if (request->count == 0) { 8987917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 8997917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 9007917SReza.Sabdar@Sun.COM "sending tape_read reply"); 9017917SReza.Sabdar@Sun.COM return; 9027917SReza.Sabdar@Sun.COM } 9037917SReza.Sabdar@Sun.COM 9047917SReza.Sabdar@Sun.COM /* 9057917SReza.Sabdar@Sun.COM * V4 suggests that this should not be accepted 9067917SReza.Sabdar@Sun.COM * when mover is in listen or active state 9077917SReza.Sabdar@Sun.COM */ 9087917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4 && 9097917SReza.Sabdar@Sun.COM (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 9107917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE)) { 9117917SReza.Sabdar@Sun.COM 9127917SReza.Sabdar@Sun.COM reply.error = NDMP_DEVICE_BUSY_ERR; 9137917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 9147917SReza.Sabdar@Sun.COM "sending tape_read reply"); 9157917SReza.Sabdar@Sun.COM return; 9167917SReza.Sabdar@Sun.COM } 9177917SReza.Sabdar@Sun.COM 9187917SReza.Sabdar@Sun.COM if ((buf = ndmp_malloc(request->count)) == NULL) { 9197917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_MEM_ERR; 9207917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 9217917SReza.Sabdar@Sun.COM "sending tape_read reply"); 9227917SReza.Sabdar@Sun.COM return; 9237917SReza.Sabdar@Sun.COM } 9247917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 9257917SReza.Sabdar@Sun.COM 9267917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, buf, request->count); 9277917SReza.Sabdar@Sun.COM if (n < 0) { 9287917SReza.Sabdar@Sun.COM /* 9297917SReza.Sabdar@Sun.COM * This fix is for Symantec during importing 9307917SReza.Sabdar@Sun.COM * of spanned data between the tapes. 9317917SReza.Sabdar@Sun.COM */ 9327917SReza.Sabdar@Sun.COM if (errno == ENOSPC) { 9337917SReza.Sabdar@Sun.COM reply.error = NDMP_EOF_ERR; 9347917SReza.Sabdar@Sun.COM } else { 9357917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape read error: %m."); 9367917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 9377917SReza.Sabdar@Sun.COM } 9387917SReza.Sabdar@Sun.COM } else if (n == 0) { 9397917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1); 9407917SReza.Sabdar@Sun.COM 9417917SReza.Sabdar@Sun.COM len = strlen(NDMP_EOM_MAGIC); 9427917SReza.Sabdar@Sun.COM (void) memset(buf, 0, len); 9437917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, buf, len); 9447917SReza.Sabdar@Sun.COM buf[len] = '\0'; 9457917SReza.Sabdar@Sun.COM 9467917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Checking EOM: nread %d [%s]", n, buf); 9477917SReza.Sabdar@Sun.COM 9487917SReza.Sabdar@Sun.COM if (strncmp(buf, NDMP_EOM_MAGIC, len) == 0 || n == 0) { 9497917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 9507917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NDMP_EOM_ERR"); 9517917SReza.Sabdar@Sun.COM } else { 9527917SReza.Sabdar@Sun.COM reply.error = NDMP_EOF_ERR; 9537917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NDMP_EOF_ERR"); 9547917SReza.Sabdar@Sun.COM } 9557917SReza.Sabdar@Sun.COM if (n > 0) 9567917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTBSR, 1); 9577917SReza.Sabdar@Sun.COM } else { 9587917SReza.Sabdar@Sun.COM /* 9597917SReza.Sabdar@Sun.COM * Symantec fix for import phase 9607917SReza.Sabdar@Sun.COM * 9617917SReza.Sabdar@Sun.COM * As import process from symantec skips filemarks 9627917SReza.Sabdar@Sun.COM * they can come across to NDMP_EOM_MAGIC and treat 9637917SReza.Sabdar@Sun.COM * it as data. This fix prevents the magic to be 9647917SReza.Sabdar@Sun.COM * sent to the client and the read will return zero bytes 9657917SReza.Sabdar@Sun.COM * and set the NDMP_EOM_ERR error. The tape should 9667917SReza.Sabdar@Sun.COM * be positioned at the EOT side of the file mark. 9677917SReza.Sabdar@Sun.COM */ 9687917SReza.Sabdar@Sun.COM len = strlen(NDMP_EOM_MAGIC); 9697917SReza.Sabdar@Sun.COM if (n == len && strncmp(buf, NDMP_EOM_MAGIC, len) == 0) { 9707917SReza.Sabdar@Sun.COM reply.error = NDMP_EOM_ERR; 9717917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1); 9727917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NDMP_EOM_ERR"); 9737917SReza.Sabdar@Sun.COM } else { 9747917SReza.Sabdar@Sun.COM session->ns_tape.td_pos += n; 9757917SReza.Sabdar@Sun.COM reply.data_in.data_in_len = n; 9767917SReza.Sabdar@Sun.COM reply.data_in.data_in_val = buf; 9777917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 9787917SReza.Sabdar@Sun.COM } 9797917SReza.Sabdar@Sun.COM NS_ADD(rtape, n); 9807917SReza.Sabdar@Sun.COM } 9817917SReza.Sabdar@Sun.COM 9827917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, "sending tape_read reply"); 9837917SReza.Sabdar@Sun.COM free(buf); 9847917SReza.Sabdar@Sun.COM } 9857917SReza.Sabdar@Sun.COM 9867917SReza.Sabdar@Sun.COM 9877917SReza.Sabdar@Sun.COM /* 9887917SReza.Sabdar@Sun.COM * ************************************************************************ 9897917SReza.Sabdar@Sun.COM * NDMP V4 HANDLERS 9907917SReza.Sabdar@Sun.COM * ************************************************************************ 9917917SReza.Sabdar@Sun.COM */ 9927917SReza.Sabdar@Sun.COM 9937917SReza.Sabdar@Sun.COM /* 9947917SReza.Sabdar@Sun.COM * ndmpd_tape_get_state_v4 9957917SReza.Sabdar@Sun.COM * 9967917SReza.Sabdar@Sun.COM * This handler handles the ndmp_tape_get_state_request. 9977917SReza.Sabdar@Sun.COM * Status information for the currently open tape device is returned. 9987917SReza.Sabdar@Sun.COM * 9997917SReza.Sabdar@Sun.COM * Parameters: 10007917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 10017917SReza.Sabdar@Sun.COM * body (input) - request message body. 10027917SReza.Sabdar@Sun.COM * 10037917SReza.Sabdar@Sun.COM * Returns: 10047917SReza.Sabdar@Sun.COM * void 10057917SReza.Sabdar@Sun.COM */ 10067917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 10077917SReza.Sabdar@Sun.COM void 10087917SReza.Sabdar@Sun.COM ndmpd_tape_get_state_v4(ndmp_connection_t *connection, void *body) 10097917SReza.Sabdar@Sun.COM { 10107917SReza.Sabdar@Sun.COM ndmp_tape_get_state_reply_v4 reply; 10117917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 10127917SReza.Sabdar@Sun.COM struct mtget mtstatus; 10137917SReza.Sabdar@Sun.COM struct mtdrivetype_request dtpr; 10147917SReza.Sabdar@Sun.COM struct mtdrivetype dtp; 10157917SReza.Sabdar@Sun.COM 10167917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 10177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 10187917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 10197917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 10207917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 10217917SReza.Sabdar@Sun.COM return; 10227917SReza.Sabdar@Sun.COM } 10237917SReza.Sabdar@Sun.COM 10247917SReza.Sabdar@Sun.COM /* 10257917SReza.Sabdar@Sun.COM * Need code to detect NDMP_TAPE_STATE_NOREWIND 10267917SReza.Sabdar@Sun.COM */ 10277917SReza.Sabdar@Sun.COM 10287917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGET, &mtstatus) == -1) { 10297917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 10307917SReza.Sabdar@Sun.COM "Failed to get status information from tape: %m."); 10317917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGET) error: %m."); 10327917SReza.Sabdar@Sun.COM 10337917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 10347917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 10357917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 10367917SReza.Sabdar@Sun.COM return; 10377917SReza.Sabdar@Sun.COM } 10387917SReza.Sabdar@Sun.COM 10397917SReza.Sabdar@Sun.COM dtpr.size = sizeof (struct mtdrivetype); 10407917SReza.Sabdar@Sun.COM dtpr.mtdtp = &dtp; 10417917SReza.Sabdar@Sun.COM if (ioctl(session->ns_tape.td_fd, MTIOCGETDRIVETYPE, &dtpr) == -1) { 10427917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 10437917SReza.Sabdar@Sun.COM "Failed to get drive type information from tape: %m."); 10447917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "ioctl(MTIOCGETDRIVETYPE) error: %m."); 10457917SReza.Sabdar@Sun.COM 10467917SReza.Sabdar@Sun.COM reply.error = NDMP_IO_ERR; 10477917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *)&reply, 10487917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 10497917SReza.Sabdar@Sun.COM return; 10507917SReza.Sabdar@Sun.COM } 10517917SReza.Sabdar@Sun.COM 1052*8800SReza.Sabdar@Sun.COM reply.flags = NDMP_TAPE_NOREWIND; 10537917SReza.Sabdar@Sun.COM 10547917SReza.Sabdar@Sun.COM reply.file_num = mtstatus.mt_fileno; 10557917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 10567917SReza.Sabdar@Sun.COM reply.block_size = dtp.bsize; 10577917SReza.Sabdar@Sun.COM 10587917SReza.Sabdar@Sun.COM if (dtp.bsize == 0) 10597917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno; 10607917SReza.Sabdar@Sun.COM else 10617917SReza.Sabdar@Sun.COM reply.blockno = mtstatus.mt_blkno * 10627917SReza.Sabdar@Sun.COM (session->ns_mover.md_record_size / dtp.bsize); 10637917SReza.Sabdar@Sun.COM 10647917SReza.Sabdar@Sun.COM reply.total_space = long_long_to_quad(0); /* not supported */ 10657917SReza.Sabdar@Sun.COM reply.space_remain = long_long_to_quad(0); /* not supported */ 10667917SReza.Sabdar@Sun.COM 10677917SReza.Sabdar@Sun.COM reply.soft_errors = 0; 10687917SReza.Sabdar@Sun.COM reply.total_space = long_long_to_quad(0LL); 10697917SReza.Sabdar@Sun.COM reply.space_remain = long_long_to_quad(0LL); 10707917SReza.Sabdar@Sun.COM reply.unsupported = NDMP_TAPE_STATE_SOFT_ERRORS_INVALID | 10717917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_TOTAL_SPACE_INVALID | 10727917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_SPACE_REMAIN_INVALID | 10737917SReza.Sabdar@Sun.COM NDMP_TAPE_STATE_PARTITION_INVALID; 10747917SReza.Sabdar@Sun.COM 10757917SReza.Sabdar@Sun.COM 10767917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "f 0x%x, fnum %d, bsize %d, bno: %d", 10777917SReza.Sabdar@Sun.COM reply.flags, reply.file_num, reply.block_size, reply.blockno); 10787917SReza.Sabdar@Sun.COM 10797917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 10807917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 10817917SReza.Sabdar@Sun.COM "sending tape_get_state reply"); 10827917SReza.Sabdar@Sun.COM } 10837917SReza.Sabdar@Sun.COM /* 10847917SReza.Sabdar@Sun.COM * ndmpd_tape_close_v4 10857917SReza.Sabdar@Sun.COM * 10867917SReza.Sabdar@Sun.COM * This handler (v4) closes the currently open tape device. 10877917SReza.Sabdar@Sun.COM * 10887917SReza.Sabdar@Sun.COM * Parameters: 10897917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 10907917SReza.Sabdar@Sun.COM * body (input) - request message body. 10917917SReza.Sabdar@Sun.COM * 10927917SReza.Sabdar@Sun.COM * Returns: 10937917SReza.Sabdar@Sun.COM * void 10947917SReza.Sabdar@Sun.COM */ 10957917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 10967917SReza.Sabdar@Sun.COM void 10977917SReza.Sabdar@Sun.COM ndmpd_tape_close_v4(ndmp_connection_t *connection, void *body) 10987917SReza.Sabdar@Sun.COM { 10997917SReza.Sabdar@Sun.COM ndmp_tape_close_reply reply; 11007917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 11017917SReza.Sabdar@Sun.COM 11027917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd == -1) { 11037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape device is not open."); 11047917SReza.Sabdar@Sun.COM reply.error = NDMP_DEV_NOT_OPEN_ERR; 11057917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 11067917SReza.Sabdar@Sun.COM "sending tape_close reply"); 11077917SReza.Sabdar@Sun.COM return; 11087917SReza.Sabdar@Sun.COM } 11097917SReza.Sabdar@Sun.COM 11107917SReza.Sabdar@Sun.COM /* 11117917SReza.Sabdar@Sun.COM * V4 suggests that this should not be accepted 11127917SReza.Sabdar@Sun.COM * when mover is in listen or active state 11137917SReza.Sabdar@Sun.COM */ 11147917SReza.Sabdar@Sun.COM if (session->ns_mover.md_state == NDMP_MOVER_STATE_LISTEN || 11157917SReza.Sabdar@Sun.COM session->ns_mover.md_state == NDMP_MOVER_STATE_ACTIVE) { 11167917SReza.Sabdar@Sun.COM 11177917SReza.Sabdar@Sun.COM reply.error = NDMP_DEVICE_BUSY_ERR; 11187917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 11197917SReza.Sabdar@Sun.COM "sending tape_close reply"); 11207917SReza.Sabdar@Sun.COM return; 11217917SReza.Sabdar@Sun.COM } 11227917SReza.Sabdar@Sun.COM 11237917SReza.Sabdar@Sun.COM common_tape_close(connection); 11247917SReza.Sabdar@Sun.COM } 11257917SReza.Sabdar@Sun.COM 11267917SReza.Sabdar@Sun.COM 11277917SReza.Sabdar@Sun.COM /* 11287917SReza.Sabdar@Sun.COM * ************************************************************************ 11297917SReza.Sabdar@Sun.COM * LOCALS 11307917SReza.Sabdar@Sun.COM * ************************************************************************ 11317917SReza.Sabdar@Sun.COM */ 11327917SReza.Sabdar@Sun.COM /* 11337917SReza.Sabdar@Sun.COM * tape_open_send_reply 11347917SReza.Sabdar@Sun.COM * 11357917SReza.Sabdar@Sun.COM * Send a reply to the tape open message 11367917SReza.Sabdar@Sun.COM * 11377917SReza.Sabdar@Sun.COM * Parameters: 11387917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 11397917SReza.Sabdar@Sun.COM * err (input) - NDMP error 11407917SReza.Sabdar@Sun.COM * 11417917SReza.Sabdar@Sun.COM * Returns: 11427917SReza.Sabdar@Sun.COM * void 11437917SReza.Sabdar@Sun.COM */ 11447917SReza.Sabdar@Sun.COM static void 11457917SReza.Sabdar@Sun.COM tape_open_send_reply(ndmp_connection_t *connection, int err) 11467917SReza.Sabdar@Sun.COM { 11477917SReza.Sabdar@Sun.COM ndmp_tape_open_reply reply; 11487917SReza.Sabdar@Sun.COM 11497917SReza.Sabdar@Sun.COM reply.error = err; 11507917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, "sending tape_open reply"); 11517917SReza.Sabdar@Sun.COM } 11527917SReza.Sabdar@Sun.COM 11537917SReza.Sabdar@Sun.COM /* 11547917SReza.Sabdar@Sun.COM * unbuffered_read 11557917SReza.Sabdar@Sun.COM * 11567917SReza.Sabdar@Sun.COM * Perform tape read without read-ahead 11577917SReza.Sabdar@Sun.COM * 11587917SReza.Sabdar@Sun.COM * Parameters: 11597917SReza.Sabdar@Sun.COM * session (input) - session handle 11607917SReza.Sabdar@Sun.COM * bp (output) - read buffer 11617917SReza.Sabdar@Sun.COM * wanted (input) - number of bytes wanted 11627917SReza.Sabdar@Sun.COM * reply (output) - tape read reply message 11637917SReza.Sabdar@Sun.COM * 11647917SReza.Sabdar@Sun.COM * Returns: 11657917SReza.Sabdar@Sun.COM * void 11667917SReza.Sabdar@Sun.COM */ 11677917SReza.Sabdar@Sun.COM static void 11687917SReza.Sabdar@Sun.COM unbuffered_read(ndmpd_session_t *session, char *buf, long wanted, 11697917SReza.Sabdar@Sun.COM ndmp_tape_read_reply *reply) 11707917SReza.Sabdar@Sun.COM { 11717917SReza.Sabdar@Sun.COM int n, len; 11727917SReza.Sabdar@Sun.COM 11737917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, buf, wanted); 11747917SReza.Sabdar@Sun.COM if (n < 0) { 11757917SReza.Sabdar@Sun.COM /* 11767917SReza.Sabdar@Sun.COM * This fix is for Symantec during importing 11777917SReza.Sabdar@Sun.COM * of spanned data between the tapes. 11787917SReza.Sabdar@Sun.COM */ 11797917SReza.Sabdar@Sun.COM if (errno == ENOSPC) { 11807917SReza.Sabdar@Sun.COM reply->error = NDMP_EOF_ERR; 11817917SReza.Sabdar@Sun.COM } else { 11827917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Tape read error: %m."); 11837917SReza.Sabdar@Sun.COM reply->error = NDMP_IO_ERR; 11847917SReza.Sabdar@Sun.COM } 11857917SReza.Sabdar@Sun.COM } else if (n == 0) { 11867917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "NDMP_EOF_ERR"); 11877917SReza.Sabdar@Sun.COM 11887917SReza.Sabdar@Sun.COM reply->error = NDMP_EOF_ERR; 11897917SReza.Sabdar@Sun.COM 11907917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1); 11917917SReza.Sabdar@Sun.COM 11927917SReza.Sabdar@Sun.COM len = strlen(NDMP_EOM_MAGIC); 11937917SReza.Sabdar@Sun.COM (void) memset(buf, 0, len); 11947917SReza.Sabdar@Sun.COM n = read(session->ns_tape.td_fd, buf, len); 11957917SReza.Sabdar@Sun.COM buf[len] = '\0'; 11967917SReza.Sabdar@Sun.COM 11977917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Checking EOM: nread %d [%s]", n, buf); 11987917SReza.Sabdar@Sun.COM 11997917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTBSF, 1); 12007917SReza.Sabdar@Sun.COM 12017917SReza.Sabdar@Sun.COM if (strncmp(buf, NDMP_EOM_MAGIC, len) != 0) 12027917SReza.Sabdar@Sun.COM (void) ndmp_mtioctl(session->ns_tape.td_fd, MTFSF, 1); 12037917SReza.Sabdar@Sun.COM } else { 12047917SReza.Sabdar@Sun.COM session->ns_tape.td_pos += n; 12057917SReza.Sabdar@Sun.COM reply->data_in.data_in_len = n; 12067917SReza.Sabdar@Sun.COM reply->data_in.data_in_val = buf; 12077917SReza.Sabdar@Sun.COM reply->error = NDMP_NO_ERR; 12087917SReza.Sabdar@Sun.COM NS_ADD(rtape, n); 12097917SReza.Sabdar@Sun.COM } 12107917SReza.Sabdar@Sun.COM } 12117917SReza.Sabdar@Sun.COM 12127917SReza.Sabdar@Sun.COM 12137917SReza.Sabdar@Sun.COM /* 12147917SReza.Sabdar@Sun.COM * validmode 12157917SReza.Sabdar@Sun.COM * 12167917SReza.Sabdar@Sun.COM * Check the tape read mode is valid 12177917SReza.Sabdar@Sun.COM */ 12187917SReza.Sabdar@Sun.COM static boolean_t 12197917SReza.Sabdar@Sun.COM validmode(int mode) 12207917SReza.Sabdar@Sun.COM { 12217917SReza.Sabdar@Sun.COM boolean_t rv; 12227917SReza.Sabdar@Sun.COM 12237917SReza.Sabdar@Sun.COM switch (mode) { 12247917SReza.Sabdar@Sun.COM case NDMP_TAPE_READ_MODE: 12257917SReza.Sabdar@Sun.COM case NDMP_TAPE_WRITE_MODE: 12267917SReza.Sabdar@Sun.COM case NDMP_TAPE_RAW1_MODE: 12277917SReza.Sabdar@Sun.COM case NDMP_TAPE_RAW2_MODE: 12287917SReza.Sabdar@Sun.COM rv = TRUE; 12297917SReza.Sabdar@Sun.COM break; 12307917SReza.Sabdar@Sun.COM default: 12317917SReza.Sabdar@Sun.COM rv = FALSE; 12327917SReza.Sabdar@Sun.COM } 12337917SReza.Sabdar@Sun.COM 12347917SReza.Sabdar@Sun.COM return (rv); 12357917SReza.Sabdar@Sun.COM } 12367917SReza.Sabdar@Sun.COM 12377917SReza.Sabdar@Sun.COM 12387917SReza.Sabdar@Sun.COM /* 12397917SReza.Sabdar@Sun.COM * common_tape_open 12407917SReza.Sabdar@Sun.COM * 12417917SReza.Sabdar@Sun.COM * Generic function for opening the tape for all versions 12427917SReza.Sabdar@Sun.COM * 12437917SReza.Sabdar@Sun.COM * Parameters: 12447917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 12457917SReza.Sabdar@Sun.COM * devname (input) - tape device name to open. 12467917SReza.Sabdar@Sun.COM * ndmpmode (input) - mode of opening (read, write, raw) 12477917SReza.Sabdar@Sun.COM * 12487917SReza.Sabdar@Sun.COM * Returns: 12497917SReza.Sabdar@Sun.COM * void 12507917SReza.Sabdar@Sun.COM */ 12517917SReza.Sabdar@Sun.COM static void 12527917SReza.Sabdar@Sun.COM common_tape_open(ndmp_connection_t *connection, char *devname, int ndmpmode) 12537917SReza.Sabdar@Sun.COM { 12547917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 12557917SReza.Sabdar@Sun.COM char adptnm[SCSI_MAX_NAME]; 12567917SReza.Sabdar@Sun.COM int err; 12577917SReza.Sabdar@Sun.COM int mode; 12587917SReza.Sabdar@Sun.COM int sid, lun; 12597917SReza.Sabdar@Sun.COM scsi_adapter_t *sa; 12607917SReza.Sabdar@Sun.COM int devid; 12617917SReza.Sabdar@Sun.COM 12627917SReza.Sabdar@Sun.COM err = NDMP_NO_ERR; 12637917SReza.Sabdar@Sun.COM 12647917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) { 12657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_INFO, 12667917SReza.Sabdar@Sun.COM "Connection already has a tape or scsi device open"); 12677917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_OPENED_ERR; 12687917SReza.Sabdar@Sun.COM } else if (!validmode(ndmpmode)) 12697917SReza.Sabdar@Sun.COM err = NDMP_ILLEGAL_ARGS_ERR; 12707917SReza.Sabdar@Sun.COM if ((sa = scsi_get_adapter(0)) != NULL) { 12717917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Adapter device opened: %s", devname); 12727917SReza.Sabdar@Sun.COM (void) strlcpy(adptnm, devname, SCSI_MAX_NAME-2); 12737917SReza.Sabdar@Sun.COM adptnm[SCSI_MAX_NAME-1] = '\0'; 12747917SReza.Sabdar@Sun.COM sid = lun = -1; 12757917SReza.Sabdar@Sun.COM } 12767917SReza.Sabdar@Sun.COM if (sa) { 12777917SReza.Sabdar@Sun.COM scsi_find_sid_lun(sa, devname, &sid, &lun); 12787917SReza.Sabdar@Sun.COM if (ndmp_open_list_find(devname, sid, lun) == 0 && 12797917SReza.Sabdar@Sun.COM (devid = open(devname, O_RDWR | O_NDELAY)) < 0) { 12807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 12817917SReza.Sabdar@Sun.COM "Failed to open device %s: %m.", devname); 12827917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 12837917SReza.Sabdar@Sun.COM } else { 12847917SReza.Sabdar@Sun.COM (void) close(devid); 12857917SReza.Sabdar@Sun.COM } 12867917SReza.Sabdar@Sun.COM } else { 12877917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "%s: No such tape device.", devname); 12887917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 12897917SReza.Sabdar@Sun.COM } 12907917SReza.Sabdar@Sun.COM 12917917SReza.Sabdar@Sun.COM if (err != NDMP_NO_ERR) { 12927917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 12937917SReza.Sabdar@Sun.COM return; 12947917SReza.Sabdar@Sun.COM } 12957917SReza.Sabdar@Sun.COM 12967917SReza.Sabdar@Sun.COM /* 12977917SReza.Sabdar@Sun.COM * If tape is not opened in raw mode and tape is not loaded 12987917SReza.Sabdar@Sun.COM * return error. 12997917SReza.Sabdar@Sun.COM */ 13007917SReza.Sabdar@Sun.COM if (ndmpmode != NDMP_TAPE_RAW1_MODE && 13017917SReza.Sabdar@Sun.COM ndmpmode != NDMP_TAPE_RAW2_MODE && 13027917SReza.Sabdar@Sun.COM !is_tape_unit_ready(adptnm, 0)) { 13037917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, NDMP_NO_TAPE_LOADED_ERR); 13047917SReza.Sabdar@Sun.COM return; 13057917SReza.Sabdar@Sun.COM } 13067917SReza.Sabdar@Sun.COM 13077917SReza.Sabdar@Sun.COM mode = (ndmpmode == NDMP_TAPE_READ_MODE) ? O_RDONLY : O_RDWR; 13087917SReza.Sabdar@Sun.COM mode |= O_NDELAY; 13097917SReza.Sabdar@Sun.COM session->ns_tape.td_fd = open(devname, mode); 13107917SReza.Sabdar@Sun.COM if (session->ns_protocol_version == NDMPV4 && 13117917SReza.Sabdar@Sun.COM session->ns_tape.td_fd < 0 && 13127917SReza.Sabdar@Sun.COM ndmpmode == NDMP_TAPE_RAW_MODE && errno == EACCES) { 13137917SReza.Sabdar@Sun.COM /* 13147917SReza.Sabdar@Sun.COM * V4 suggests that if the tape is open in raw mode 13157917SReza.Sabdar@Sun.COM * and could not be opened with write access, it should 13167917SReza.Sabdar@Sun.COM * be opened read only instead. 13177917SReza.Sabdar@Sun.COM */ 13187917SReza.Sabdar@Sun.COM ndmpmode = NDMP_TAPE_READ_MODE; 13197917SReza.Sabdar@Sun.COM session->ns_tape.td_fd = open(devname, O_RDONLY); 13207917SReza.Sabdar@Sun.COM } 13217917SReza.Sabdar@Sun.COM if (session->ns_tape.td_fd < 0) { 13227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Failed to open tape device %s: %m.", 13237917SReza.Sabdar@Sun.COM devname); 13247917SReza.Sabdar@Sun.COM switch (errno) { 13257917SReza.Sabdar@Sun.COM case EACCES: 13267917SReza.Sabdar@Sun.COM err = NDMP_WRITE_PROTECT_ERR; 13277917SReza.Sabdar@Sun.COM break; 13287917SReza.Sabdar@Sun.COM case ENOENT: 13297917SReza.Sabdar@Sun.COM err = NDMP_NO_DEVICE_ERR; 13307917SReza.Sabdar@Sun.COM break; 13317917SReza.Sabdar@Sun.COM case EBUSY: 13327917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_BUSY_ERR; 13337917SReza.Sabdar@Sun.COM break; 13347917SReza.Sabdar@Sun.COM case EPERM: 13357917SReza.Sabdar@Sun.COM err = NDMP_PERMISSION_ERR; 13367917SReza.Sabdar@Sun.COM break; 13377917SReza.Sabdar@Sun.COM default: 13387917SReza.Sabdar@Sun.COM err = NDMP_IO_ERR; 13397917SReza.Sabdar@Sun.COM } 13407917SReza.Sabdar@Sun.COM 13417917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 13427917SReza.Sabdar@Sun.COM return; 13437917SReza.Sabdar@Sun.COM } 13447917SReza.Sabdar@Sun.COM 13457917SReza.Sabdar@Sun.COM switch (ndmp_open_list_add(connection, 13467917SReza.Sabdar@Sun.COM adptnm, sid, lun, session->ns_tape.td_fd)) { 13477917SReza.Sabdar@Sun.COM case 0: 13487917SReza.Sabdar@Sun.COM err = NDMP_NO_ERR; 13497917SReza.Sabdar@Sun.COM break; 13507917SReza.Sabdar@Sun.COM case EBUSY: 13517917SReza.Sabdar@Sun.COM err = NDMP_DEVICE_BUSY_ERR; 13527917SReza.Sabdar@Sun.COM break; 13537917SReza.Sabdar@Sun.COM case ENOMEM: 13547917SReza.Sabdar@Sun.COM err = NDMP_NO_MEM_ERR; 13557917SReza.Sabdar@Sun.COM break; 13567917SReza.Sabdar@Sun.COM default: 13577917SReza.Sabdar@Sun.COM err = NDMP_IO_ERR; 13587917SReza.Sabdar@Sun.COM } 13597917SReza.Sabdar@Sun.COM if (err != NDMP_NO_ERR) { 13607917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, err); 13617917SReza.Sabdar@Sun.COM return; 13627917SReza.Sabdar@Sun.COM } 13637917SReza.Sabdar@Sun.COM 13647917SReza.Sabdar@Sun.COM session->ns_tape.td_mode = ndmpmode; 13657917SReza.Sabdar@Sun.COM session->ns_tape.td_sid = sid; 13667917SReza.Sabdar@Sun.COM session->ns_tape.td_lun = lun; 13677917SReza.Sabdar@Sun.COM (void) strlcpy(session->ns_tape.td_adapter_name, adptnm, SCSI_MAX_NAME); 13687917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 13697917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 13707917SReza.Sabdar@Sun.COM 13717917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Tape is opened fd: %d", session->ns_tape.td_fd); 13727917SReza.Sabdar@Sun.COM 13737917SReza.Sabdar@Sun.COM tape_open_send_reply(connection, NDMP_NO_ERR); 13747917SReza.Sabdar@Sun.COM } 13757917SReza.Sabdar@Sun.COM 13767917SReza.Sabdar@Sun.COM 13777917SReza.Sabdar@Sun.COM /* 13787917SReza.Sabdar@Sun.COM * common_tape_close 13797917SReza.Sabdar@Sun.COM * 13807917SReza.Sabdar@Sun.COM * Generic function for closing the tape 13817917SReza.Sabdar@Sun.COM * 13827917SReza.Sabdar@Sun.COM * Parameters: 13837917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 13847917SReza.Sabdar@Sun.COM * 13857917SReza.Sabdar@Sun.COM * Returns: 13867917SReza.Sabdar@Sun.COM * void 13877917SReza.Sabdar@Sun.COM */ 13887917SReza.Sabdar@Sun.COM static void 13897917SReza.Sabdar@Sun.COM common_tape_close(ndmp_connection_t *connection) 13907917SReza.Sabdar@Sun.COM { 13917917SReza.Sabdar@Sun.COM ndmpd_session_t *session = ndmp_get_client_data(connection); 13927917SReza.Sabdar@Sun.COM ndmp_tape_close_reply reply; 13937917SReza.Sabdar@Sun.COM 13947917SReza.Sabdar@Sun.COM (void) ndmp_open_list_del(session->ns_tape.td_adapter_name, 13957917SReza.Sabdar@Sun.COM session->ns_tape.td_sid, session->ns_tape.td_lun); 13967917SReza.Sabdar@Sun.COM (void) close(session->ns_tape.td_fd); 13977917SReza.Sabdar@Sun.COM session->ns_tape.td_fd = -1; 13987917SReza.Sabdar@Sun.COM session->ns_tape.td_sid = 0; 13997917SReza.Sabdar@Sun.COM session->ns_tape.td_lun = 0; 14007917SReza.Sabdar@Sun.COM session->ns_tape.td_write = 0; 14017917SReza.Sabdar@Sun.COM (void) memset(session->ns_tape.td_adapter_name, 0, 14027917SReza.Sabdar@Sun.COM sizeof (session->ns_tape.td_adapter_name)); 14037917SReza.Sabdar@Sun.COM session->ns_tape.td_record_count = 0; 14047917SReza.Sabdar@Sun.COM session->ns_tape.td_eom_seen = FALSE; 14057917SReza.Sabdar@Sun.COM 14067917SReza.Sabdar@Sun.COM reply.error = NDMP_NO_ERR; 14077917SReza.Sabdar@Sun.COM ndmp_send_reply(connection, (void *) &reply, 14087917SReza.Sabdar@Sun.COM "sending tape_close reply"); 14097917SReza.Sabdar@Sun.COM } 14107917SReza.Sabdar@Sun.COM 14117917SReza.Sabdar@Sun.COM /* 14127917SReza.Sabdar@Sun.COM * tape_open 14137917SReza.Sabdar@Sun.COM * 14147917SReza.Sabdar@Sun.COM * Will try to open the tape with the given flags and 14157917SReza.Sabdar@Sun.COM * path using the given retries and delay intervals 14167917SReza.Sabdar@Sun.COM */ 14177917SReza.Sabdar@Sun.COM int 14187917SReza.Sabdar@Sun.COM tape_open(char *path, int flags) 14197917SReza.Sabdar@Sun.COM { 14207917SReza.Sabdar@Sun.COM int fd; 14217917SReza.Sabdar@Sun.COM int i = 0; 14227917SReza.Sabdar@Sun.COM 14237917SReza.Sabdar@Sun.COM while ((fd = open(path, flags)) == -1 && 14247917SReza.Sabdar@Sun.COM i++ < ndmp_tape_open_retries) { 14257917SReza.Sabdar@Sun.COM if (errno != EBUSY) 14267917SReza.Sabdar@Sun.COM break; 14277917SReza.Sabdar@Sun.COM (void) usleep(ndmp_tape_open_delay); 14287917SReza.Sabdar@Sun.COM } 14297917SReza.Sabdar@Sun.COM return (fd); 14307917SReza.Sabdar@Sun.COM } 1431