|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Copyright (c) 1998,1999,2000
|
|
Packit Service |
392537 |
* Traakan, Inc., Los Altos, CA
|
|
Packit Service |
392537 |
* All rights reserved.
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit Service |
392537 |
* modification, are permitted provided that the following conditions
|
|
Packit Service |
392537 |
* are met:
|
|
Packit Service |
392537 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit Service |
392537 |
* notice unmodified, this list of conditions, and the following
|
|
Packit Service |
392537 |
* disclaimer.
|
|
Packit Service |
392537 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit Service |
392537 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit Service |
392537 |
* documentation and/or other materials provided with the distribution.
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit Service |
392537 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit Service |
392537 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit Service |
392537 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
Packit Service |
392537 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit Service |
392537 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit Service |
392537 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit Service |
392537 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit Service |
392537 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit Service |
392537 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit Service |
392537 |
* SUCH DAMAGE.
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* Project: NDMJOB
|
|
Packit Service |
392537 |
* Ident: $Id: $
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
* Description:
|
|
Packit Service |
392537 |
*
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#include "ndmagents.h"
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#ifndef NDMOS_OPTION_NO_TAPE_AGENT
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int simu_back_one (struct ndm_session *sess, int over_file_mark);
|
|
Packit Service |
392537 |
int simu_forw_one (struct ndm_session *sess, int over_file_mark);
|
|
Packit Service |
392537 |
int simu_flush_weof (struct ndm_session *sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#ifdef NDMOS_OPTION_TAPE_SIMULATOR
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
struct simu_gap {
|
|
Packit Service |
392537 |
u_long magic;
|
|
Packit Service |
392537 |
u_long rectype;
|
|
Packit Service |
392537 |
u_long prev_size;
|
|
Packit Service |
392537 |
u_long size;
|
|
Packit Service |
392537 |
};
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#define SIMU_GAP_MAGIC 0x0BEEFEE0
|
|
Packit Service |
392537 |
#define SIMU_GAP_RT_(a,b,c,d) ((a<<0)+(b<<8)+(c<<16)+(d<<24))
|
|
Packit Service |
392537 |
#define SIMU_GAP_RT_BOT SIMU_GAP_RT_('B','O','T','_')
|
|
Packit Service |
392537 |
#define SIMU_GAP_RT_DATA SIMU_GAP_RT_('D','A','T','A')
|
|
Packit Service |
392537 |
#define SIMU_GAP_RT_FILE SIMU_GAP_RT_('F','I','L','E')
|
|
Packit Service |
392537 |
#define SIMU_GAP_RT_EOT SIMU_GAP_RT_('E','O','T','_')
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* send logical EOM with a bit less than 2 32k blocks left (due to SIMU_GAPs) */
|
|
Packit Service |
392537 |
#define TAPE_SIM_LOGICAL_EOM 32768*2
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* we sneak a peek at this global variable - probably not the best way, but
|
|
Packit Service |
392537 |
* it works */
|
|
Packit Service |
392537 |
extern off_t o_tape_limit;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
ndmos_tape_initialize (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_fd = -1;
|
|
Packit Service |
392537 |
NDMOS_MACRO_ZEROFILL (&ta->tape_state);
|
|
Packit Service |
392537 |
ta->tape_state.error = NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
ta->tape_state.state = NDMP9_TAPE_STATE_IDLE;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
static int
|
|
Packit Service |
392537 |
touch_tape_lockfile(char *drive_name)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
char *lockfile_name;
|
|
Packit Service |
392537 |
int fd;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lockfile_name = g_strdup_printf("%s.lck", drive_name);
|
|
Packit Service |
392537 |
if ((fd = open(lockfile_name, O_CREAT|O_EXCL, 0666)) < 0) {
|
|
Packit Service |
392537 |
g_free(lockfile_name);
|
|
Packit Service |
392537 |
return -1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
close(fd);
|
|
Packit Service |
392537 |
g_free(lockfile_name);
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
static void
|
|
Packit Service |
392537 |
unlink_tape_lockfile(char *drive_name)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
char *lockfile_name;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lockfile_name = g_strdup_printf("%s.lck", drive_name);
|
|
Packit Service |
392537 |
unlink(lockfile_name);
|
|
Packit Service |
392537 |
g_free(lockfile_name);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_open (struct ndm_session *sess, char *drive_name, int will_write)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
struct stat st;
|
|
Packit Service |
392537 |
int read_only, omode;
|
|
Packit Service |
392537 |
int rc, fd;
|
|
Packit Service |
392537 |
char *pos_symlink_name;
|
|
Packit Service |
392537 |
char pos_buf[32];
|
|
Packit Service |
392537 |
off_t pos = -1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd >= 0) {
|
|
Packit Service |
392537 |
ndma_send_logmsg(sess, NDMP9_LOG_ERROR, sess->plumb.control,
|
|
Packit Service |
392537 |
"device simulator is already open");
|
|
Packit Service |
392537 |
return NDMP9_DEVICE_OPENED_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (stat (drive_name, &st) < 0) {
|
|
Packit Service |
392537 |
return NDMP9_NO_DEVICE_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
read_only = (st.st_mode & 0222) == 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (!will_write) {
|
|
Packit Service |
392537 |
omode = 0;
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
if (read_only)
|
|
Packit Service |
392537 |
return NDMP9_WRITE_PROTECT_ERR;
|
|
Packit Service |
392537 |
omode = 2; /* ndmp_write means read/write */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (touch_tape_lockfile(drive_name) < 0)
|
|
Packit Service |
392537 |
return NDMP9_DEVICE_BUSY_ERR;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
fd = open (drive_name, omode);
|
|
Packit Service |
392537 |
if (fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_PERMISSION_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
pos_symlink_name = g_strdup_printf("%s.pos", drive_name);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (st.st_size == 0) {
|
|
Packit Service |
392537 |
remove (pos_symlink_name);
|
|
Packit Service |
392537 |
if (will_write) {
|
|
Packit Service |
392537 |
gap.magic = SIMU_GAP_MAGIC;
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_BOT;
|
|
Packit Service |
392537 |
gap.size = 0;
|
|
Packit Service |
392537 |
gap.prev_size = 0;
|
|
Packit Service |
392537 |
if (write (fd, &gap, sizeof gap) < (int)sizeof gap) {
|
|
Packit Service |
392537 |
close(fd);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_EOT;
|
|
Packit Service |
392537 |
if (write (fd, &gap, sizeof gap) < (int)sizeof gap) {
|
|
Packit Service |
392537 |
close(fd);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
lseek (fd, (off_t)0, 0);
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
goto skip_header_check;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap) {
|
|
Packit Service |
392537 |
close (fd);
|
|
Packit Service |
392537 |
return NDMP9_NO_TAPE_LOADED_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#if 1
|
|
Packit Service |
392537 |
if (gap.magic != SIMU_GAP_MAGIC) {
|
|
Packit Service |
392537 |
close (fd);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
#else
|
|
Packit Service |
392537 |
if (gap.magic != SIMU_GAP_MAGIC
|
|
Packit Service |
392537 |
|| gap.rectype != SIMU_GAP_RT_BOT
|
|
Packit Service |
392537 |
|| gap.size != 0) {
|
|
Packit Service |
392537 |
close (fd);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
#endif
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = readlink (pos_symlink_name, pos_buf, sizeof pos_buf);
|
|
Packit Service |
392537 |
if (rc > 0) {
|
|
Packit Service |
392537 |
pos_buf[sizeof pos_buf - 1] = 0;
|
|
Packit Service |
392537 |
if (rc < sizeof pos_buf)
|
|
Packit Service |
392537 |
pos_buf[rc] = 0;
|
|
Packit Service |
392537 |
pos = strtol (pos_buf, 0, 0);
|
|
Packit Service |
392537 |
lseek (fd, pos, 0);
|
|
Packit Service |
392537 |
rc = read (fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc == sizeof gap && gap.magic == SIMU_GAP_MAGIC) {
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
pos = sizeof gap;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
lseek (fd, pos, 0);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
skip_header_check:
|
|
Packit Service |
392537 |
remove (pos_symlink_name);
|
|
Packit Service |
392537 |
g_free(pos_symlink_name);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_fd = fd;
|
|
Packit Service |
392537 |
NDMOS_API_BZERO (ta->drive_name, sizeof ta->drive_name);
|
|
Packit Service |
392537 |
g_strlcpy (ta->drive_name, drive_name, sizeof ta->drive_name);
|
|
Packit Service |
392537 |
bzero (&ta->tape_state, sizeof ta->tape_state);
|
|
Packit Service |
392537 |
ta->tape_state.error = NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
ta->tape_state.state = NDMP9_TAPE_STATE_OPEN;
|
|
Packit Service |
392537 |
ta->tape_state.open_mode =
|
|
Packit Service |
392537 |
will_write ? NDMP9_TAPE_RDWR_MODE : NDMP9_TAPE_READ_MODE;
|
|
Packit Service |
392537 |
ta->tape_state.file_num.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.soft_errors.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.block_size.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.total_space.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
ta->tape_state.space_remain.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->sent_leom = 0;
|
|
Packit Service |
392537 |
if (o_tape_limit) {
|
|
Packit Service |
392537 |
g_assert(o_tape_limit > st.st_size);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_state.total_space.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.total_space.value = o_tape_limit;
|
|
Packit Service |
392537 |
ta->tape_state.space_remain.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.space_remain.value = o_tape_limit - st.st_size;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_close (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* TODO this is not called on an EOF from the DMA, so the lockfile
|
|
Packit Service |
392537 |
* will remain, although the spec says the tape service should be
|
|
Packit Service |
392537 |
* automatically closed */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#if 0
|
|
Packit Service |
392537 |
u_long resid;
|
|
Packit Service |
392537 |
ndmos_tape_mtio (sess, NDMP9_MTIO_REW, 1, &resid);
|
|
Packit Service |
392537 |
#endif
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
if (cur_pos != -1) {
|
|
Packit Service |
392537 |
char *pos_symlink_name;
|
|
Packit Service |
392537 |
char pos_buf[32];
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
pos_symlink_name = g_strdup_printf("%s.pos", ta->drive_name);
|
|
Packit Service |
392537 |
sprintf (pos_buf, "%ld", (long) cur_pos);
|
|
Packit Service |
392537 |
if (symlink (pos_buf, pos_symlink_name) < 0) {
|
|
Packit Service |
392537 |
; /* ignore error during close */
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
g_free(pos_symlink_name);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
close (ta->tape_fd);
|
|
Packit Service |
392537 |
ta->tape_fd = -1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
unlink_tape_lockfile(ta->drive_name);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmos_tape_initialize (sess);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
void
|
|
Packit Service |
392537 |
ndmos_tape_sync_state (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
ta->tape_state.error = NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
ta->tape_state.state = NDMP9_TAPE_STATE_IDLE;
|
|
Packit Service |
392537 |
ta->tape_state.file_num.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
ta->tape_state.soft_errors.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
ta->tape_state.block_size.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.valid = NDMP9_VALIDITY_INVALID;
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
ta->tape_state.error = NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
if (ta->mover_state.state == NDMP9_MOVER_STATE_ACTIVE)
|
|
Packit Service |
392537 |
ta->tape_state.state = NDMP9_TAPE_STATE_MOVER;
|
|
Packit Service |
392537 |
else
|
|
Packit Service |
392537 |
ta->tape_state.state = NDMP9_TAPE_STATE_OPEN;
|
|
Packit Service |
392537 |
ta->tape_state.file_num.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.soft_errors.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.block_size.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.valid = NDMP9_VALIDITY_VALID;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
simu_back_one (struct ndm_session *sess, int over_file_mark)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
off_t new_pos;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap || gap.magic != SIMU_GAP_MAGIC)
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
new_pos = cur_pos;
|
|
Packit Service |
392537 |
new_pos -= sizeof gap + gap.prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->sent_leom = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* This is the new position. We need to update simu_prev_gap.
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, new_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap || gap.magic != SIMU_GAP_MAGIC)
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (gap.rectype) {
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_BOT:
|
|
Packit Service |
392537 |
/* can't actually back up to this, but update stuff */
|
|
Packit Service |
392537 |
ta->tape_state.file_num.value = 0;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value = 0;
|
|
Packit Service |
392537 |
/* cur_pos is now just right */
|
|
Packit Service |
392537 |
return 0; /* can't back up */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_EOT:
|
|
Packit Service |
392537 |
/* this just isn't suppose to happen */
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_DATA:
|
|
Packit Service |
392537 |
/* this is always OK */
|
|
Packit Service |
392537 |
if (ta->tape_state.blockno.value > 0)
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value--;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, new_pos, 0);
|
|
Packit Service |
392537 |
return SIMU_GAP_RT_DATA;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_FILE:
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value = 0;
|
|
Packit Service |
392537 |
if (!over_file_mark) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
if (ta->tape_state.file_num.value > 0)
|
|
Packit Service |
392537 |
ta->tape_state.file_num.value--;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, new_pos, 0);
|
|
Packit Service |
392537 |
return SIMU_GAP_RT_FILE;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
/* this just isn't suppose to happen */
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
bail_out:
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return -1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
simu_forw_one (struct ndm_session *sess, int over_file_mark)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
off_t new_pos;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap || gap.magic != SIMU_GAP_MAGIC)
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->sent_leom = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
new_pos = cur_pos;
|
|
Packit Service |
392537 |
new_pos += gap.size + sizeof gap;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
switch (gap.rectype) {
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_BOT:
|
|
Packit Service |
392537 |
/* this just isn't suppose to happen */
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_EOT:
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return 0; /* can't go forward */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_DATA:
|
|
Packit Service |
392537 |
/* this is always OK */
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value++;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, new_pos, 0);
|
|
Packit Service |
392537 |
return SIMU_GAP_RT_DATA;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case SIMU_GAP_RT_FILE:
|
|
Packit Service |
392537 |
if (!over_file_mark) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value = 0;
|
|
Packit Service |
392537 |
ta->tape_state.file_num.value++;
|
|
Packit Service |
392537 |
/* cur_pos is just right */
|
|
Packit Service |
392537 |
return SIMU_GAP_RT_FILE;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
/* this just isn't suppose to happen */
|
|
Packit Service |
392537 |
goto bail_out;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
bail_out:
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return -1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
int
|
|
Packit Service |
392537 |
simu_flush_weof (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->weof_on_close) {
|
|
Packit Service |
392537 |
/* best effort */
|
|
Packit Service |
392537 |
ndmos_tape_wfm (sess);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
return 0;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_mtio (struct ndm_session *sess,
|
|
Packit Service |
392537 |
ndmp9_tape_mtio_op op, u_long count, u_long *resid)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
*resid = count;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* audit for valid op and for tape mode */
|
|
Packit Service |
392537 |
switch (op) {
|
|
Packit Service |
392537 |
case NDMP9_MTIO_FSF:
|
|
Packit Service |
392537 |
while (*resid > 0) {
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
rc = simu_forw_one (sess, 1);
|
|
Packit Service |
392537 |
if (rc < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
if (rc == 0)
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
if (rc == SIMU_GAP_RT_FILE)
|
|
Packit Service |
392537 |
*resid -= 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_BSF:
|
|
Packit Service |
392537 |
while (*resid > 0) {
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
rc = simu_back_one (sess, 1);
|
|
Packit Service |
392537 |
if (rc < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
if (rc == 0)
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
if (rc == SIMU_GAP_RT_FILE)
|
|
Packit Service |
392537 |
*resid -= 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_FSR:
|
|
Packit Service |
392537 |
while (*resid > 0) {
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
rc = simu_forw_one (sess, 0);
|
|
Packit Service |
392537 |
if (rc < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
if (rc == 0)
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
*resid -= 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_BSR:
|
|
Packit Service |
392537 |
while (*resid > 0) {
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
rc = simu_back_one (sess, 0);
|
|
Packit Service |
392537 |
if (rc < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
if (rc == 0)
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
*resid -= 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_REW:
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
*resid = 0;
|
|
Packit Service |
392537 |
ta->tape_state.file_num.value = 0;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value = 0;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, (off_t)(sizeof (struct simu_gap)), 0);
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_OFF:
|
|
Packit Service |
392537 |
simu_flush_weof(sess);
|
|
Packit Service |
392537 |
/* Hmmm. */
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
case NDMP9_MTIO_EOF: /* should be "WFM" write-file-mark */
|
|
Packit Service |
392537 |
if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
|
|
Packit Service |
392537 |
return NDMP9_PERMISSION_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
while (*resid > 0) {
|
|
Packit Service |
392537 |
ndmp9_error err;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
err = ndmos_tape_wfm (sess);
|
|
Packit Service |
392537 |
if (err != NDMP9_NO_ERR)
|
|
Packit Service |
392537 |
return err;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
*resid -= 1;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
break;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
default:
|
|
Packit Service |
392537 |
return NDMP9_ILLEGAL_ARGS_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_write (struct ndm_session *sess,
|
|
Packit Service |
392537 |
char *buf, u_long count, u_long *done_count)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
ndmp9_error err;
|
|
Packit Service |
392537 |
u_long prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
|
|
Packit Service |
392537 |
return NDMP9_PERMISSION_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (count == 0) {
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* NDMPv4 clarification -- a tape read or write with
|
|
Packit Service |
392537 |
* a count==0 is a no-op. This is undoubtedly influenced
|
|
Packit Service |
392537 |
* by the SCSI Sequential Access specification which
|
|
Packit Service |
392537 |
* says much the same thing.
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
*done_count = 0;
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (o_tape_limit) {
|
|
Packit Service |
392537 |
/* if cur_pos is past LEOM, but we haven't sent NDMP9_EOM_ERR yet,
|
|
Packit Service |
392537 |
* then do so now */
|
|
Packit Service |
392537 |
if (!ta->sent_leom && cur_pos > o_tape_limit - TAPE_SIM_LOGICAL_EOM) {
|
|
Packit Service |
392537 |
ta->sent_leom = 1;
|
|
Packit Service |
392537 |
return NDMP9_EOM_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* if this write will put us over PEOM, then send NDMP9_IO_ERR */
|
|
Packit Service |
392537 |
if ((off_t)(cur_pos + sizeof gap + count) > o_tape_limit) {
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap
|
|
Packit Service |
392537 |
|| gap.magic != SIMU_GAP_MAGIC) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
prev_size = gap.prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
gap.magic = SIMU_GAP_MAGIC;
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_DATA;
|
|
Packit Service |
392537 |
gap.prev_size = prev_size;
|
|
Packit Service |
392537 |
gap.size = count;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (write (ta->tape_fd, &gap, sizeof gap) == sizeof gap
|
|
Packit Service |
392537 |
&& (u_long)write (ta->tape_fd, buf, count) == count) {
|
|
Packit Service |
392537 |
cur_pos += count + sizeof gap;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
prev_size = count;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value++;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
*done_count = count;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
err = NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
err = NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ftruncate (ta->tape_fd, cur_pos) < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_EOT;
|
|
Packit Service |
392537 |
gap.size = 0;
|
|
Packit Service |
392537 |
gap.prev_size = prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (write (ta->tape_fd, &gap, sizeof gap) < (int)sizeof gap)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (o_tape_limit) {
|
|
Packit Service |
392537 |
ta->tape_state.space_remain.value = o_tape_limit - cur_pos;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->weof_on_close = 1;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return err;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_wfm (struct ndm_session *sess)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
ndmp9_error err;
|
|
Packit Service |
392537 |
u_long prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->weof_on_close = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (!NDMTA_TAPE_IS_WRITABLE(ta)) {
|
|
Packit Service |
392537 |
return NDMP9_PERMISSION_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (o_tape_limit) {
|
|
Packit Service |
392537 |
/* note: filemarks *never* trigger NDMP9_EOM_ERR */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
/* if this write will put us over PEOM, then send NDMP9_IO_ERR */
|
|
Packit Service |
392537 |
if ((off_t)(cur_pos + sizeof gap) > o_tape_limit) {
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap
|
|
Packit Service |
392537 |
|| gap.magic != SIMU_GAP_MAGIC) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
prev_size = gap.prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
gap.magic = SIMU_GAP_MAGIC;
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_FILE;
|
|
Packit Service |
392537 |
gap.prev_size = prev_size;
|
|
Packit Service |
392537 |
gap.size = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (write (ta->tape_fd, &gap, sizeof gap) == sizeof gap) {
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos += sizeof gap;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
prev_size = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_state.file_num.value++;
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value = 0;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
err = NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
err = NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ftruncate (ta->tape_fd, cur_pos) < 0)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
gap.rectype = SIMU_GAP_RT_EOT;
|
|
Packit Service |
392537 |
gap.size = 0;
|
|
Packit Service |
392537 |
gap.prev_size = prev_size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (write (ta->tape_fd, &gap, sizeof gap) < (int)sizeof gap)
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (o_tape_limit) {
|
|
Packit Service |
392537 |
ta->tape_state.space_remain.value = o_tape_limit - cur_pos;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
return err;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ndmp9_error
|
|
Packit Service |
392537 |
ndmos_tape_read (struct ndm_session *sess,
|
|
Packit Service |
392537 |
char *buf, u_long count, u_long *done_count)
|
|
Packit Service |
392537 |
{
|
|
Packit Service |
392537 |
struct ndm_tape_agent * ta = &sess->tape_acb;
|
|
Packit Service |
392537 |
int rc;
|
|
Packit Service |
392537 |
struct simu_gap gap;
|
|
Packit Service |
392537 |
off_t cur_pos;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (ta->tape_fd < 0) {
|
|
Packit Service |
392537 |
return NDMP9_DEV_NOT_OPEN_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (count == 0) {
|
|
Packit Service |
392537 |
/*
|
|
Packit Service |
392537 |
* NDMPv4 clarification -- a tape read or write with
|
|
Packit Service |
392537 |
* a count==0 is a no-op. This is undoubtedly influenced
|
|
Packit Service |
392537 |
* by the SCSI Sequential Access specification which
|
|
Packit Service |
392537 |
* says much the same thing.
|
|
Packit Service |
392537 |
*/
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
*done_count = 0;
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
cur_pos = lseek (ta->tape_fd, (off_t)0, 1);
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, &gap, sizeof gap);
|
|
Packit Service |
392537 |
if (rc != sizeof gap
|
|
Packit Service |
392537 |
|| gap.magic != SIMU_GAP_MAGIC) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (gap.rectype == SIMU_GAP_RT_DATA) {
|
|
Packit Service |
392537 |
unsigned nb;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
nb = count;
|
|
Packit Service |
392537 |
if (nb > gap.size)
|
|
Packit Service |
392537 |
nb = gap.size;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
rc = read (ta->tape_fd, buf, nb);
|
|
Packit Service |
392537 |
if (rc != (int)nb) {
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
return NDMP9_IO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
if (gap.size != nb) {
|
|
Packit Service |
392537 |
cur_pos += sizeof gap + gap.size;
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
ta->tape_state.blockno.value++;
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
*done_count = nb;
|
|
Packit Service |
392537 |
} else {
|
|
Packit Service |
392537 |
/* all other record types are interpretted as EOF */
|
|
Packit Service |
392537 |
lseek (ta->tape_fd, cur_pos, 0);
|
|
Packit Service |
392537 |
*done_count = 0;
|
|
Packit Service |
392537 |
return NDMP9_EOF_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
return NDMP9_NO_ERR;
|
|
Packit Service |
392537 |
}
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#endif /* NDMOS_OPTION_TAPE_SIMULATOR */
|
|
Packit Service |
392537 |
|
|
Packit Service |
392537 |
#endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
|