1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <knet.h>
include <config.h>
include <syserr.h>
include <fset.h>
include <mach.h>
include "mtio.h"
# MTOPEN -- Open a magtape file, or a regular binary file if the file name is
# not "mt" prefixed. Access modes are restricted to read_only, write_only,
# append, and new_tape. The buffer size argument specifies the size of the
# FIO buffer used to access the tape; a system and device dependent default
# is supplied if the buffer size is given as zero. If the device is a fixed
# block size device the buffer size will be adjusted to an integral multiple
# of the device block size. For variable size record devices, the buffer size
# determines the size of the tape record on a write, or the maximum record
# size on a read.
#
# The device to be accessed is specified as follows:
#
# [node!] mtX [ '[' file[.record] [:attr-list] ']' ]
#
# for example,
#
# mtexb1[4:nb:se@:ts=1200:so=/dev/ttya8]
#
# The "mt" prefix is required for the object to be considered a magtape device
# reference. The device name returned is "mtX" as shown above; there must be
# an entry for device mtX in the tapecap file in DEV.
#
# The file and record numbers are optional. Files and records are numbered
# starting with 1. A sequence such as "mtX[eot]" will cause the tape to be
# positioned to end of tape. "mtX[0]" causes the tape to be opened at the
# current position, i.e., without being moved.
#
# The optional attr-list field consists of a sequence of colon-delimited
# tapecap fields. These will override any values given in the tapecap entry
# for the device. The syntax for attr-list is the same as in tapecap.
#
# If the filespec does not have the prefix "mt", we assume that the file is
# a regular binary file and try to open that. If a tape file is specified
# then the drive must be allocated before we are called. We allocate and
# initialize an MTIO file descriptor and call FOPNBF to install the magtape
# device in FIO and open the device/file.
int procedure mtopen (mtname, acmode, bufsize)
char mtname[ARB] #I device to be opened
int acmode #I access mode
int bufsize #I fio buffer size (record size) or 0
bool first_time
pointer sp, devcap, fname, gty
int mt, fd, nskip, new_file, new_record
bool streq()
pointer mt_gtyopen(), gtycaps()
int open(), fopnbf(), gtygets(), access()
int mt_skip_record(), mtfile(), mt_devallocated()
extern zopnmt(), zardmt(), zawrmt(), zawtmt(), zsttmt(), zclsmt()
errchk open, fopnbf, fseti, syserrs, mtparse
errchk mt_getpos, mt_skip_record, mt_gtyopen, gtygets, mt_glock, mtallocate
data first_time /true/
include "mtio.com"
begin
call smark (sp)
call salloc (fname, SZ_PATHNAME, TY_CHAR)
call salloc (devcap, SZ_DEVCAP, TY_CHAR)
# Runtime initialization of the mtio file descriptor common.
# Make each file descriptor available for use.
if (first_time) {
call mt_clrcache()
do mt = 1, MT_MAXTAPES
MT_OSCHAN(mt) = NULL
first_time = false
}
# If regular binary file, we are done.
if (mtfile(mtname) == NO) {
call sfree (sp)
return (open (mtname, acmode, BINARY_FILE))
}
# Get mtio file descriptor slot, but do not allocate it until
# we are ready to open the file.
for (mt=1; mt <= MT_MAXTAPES && MT_OSCHAN(mt) != NULL; mt=mt+1)
;
if (mt > MT_MAXTAPES)
call syserrs (SYS_MTMULTOPEN, mtname)
# Break mtname into drive name, file and record number, etc.
call mtparse (mtname, MT_DEVICE(mt), SZ_DEVICE,
new_file, new_record, Memc[devcap], SZ_DEVCAP)
if (new_record == ERR)
new_record = 1
# Get tapecap info.
gty = mt_gtyopen (MT_DEVICE(mt), Memc[devcap])
MT_DEVCAP(mt) = gtycaps (gty)
if (gtygets (gty, "dv", MT_IODEV(mt), SZ_IODEV) <= 0) {
call eprintf ("missing `dv' parameter in tapecap entry for %s\n")
call pargstr (mtname)
call syserrs (SYS_MTTAPECAP, mtname)
}
call ki_xnode (MT_DEVICE(mt), MT_IODEV(mt), SZ_IODEV)
# If the device has not been allocated, at least write out the
# lock file. This will not physically allocate the device, but
# the lock file is required to be able to access the device.
call mt_glock (mtname, MT_LKNAME(mt), SZ_LKNAME)
if (mt_devallocated (MT_IODEV(mt)) == NO)
if (access (MT_LKNAME(mt), 0,0) == NO)
call mtallocate (mtname)
# Get current tape position.
call mt_getpos (mtname, mt)
MT_FILE(mt) = new_file
MT_RECORD(mt) = new_record
MT_ATEOF(mt) = NO
# If tape is opened for writing but no file number is given, default
# to EOT. Defaulting to current file or BOT could result in
# destruction of the tape. Note that this default WILL RESULT IN TAPE
# RUNAWAY if used on a blank tape. Blank tapes must be explicitly
# written at file [1], or opened with access mode NEW_TAPE.
if ((acmode == WRITE_ONLY && MT_FILE(mt) == -1) || (acmode == APPEND)) {
MT_FILE(mt) = EOT
MT_RECORD(mt) = 1
} else if (acmode == NEW_TAPE) {
MT_FILE(mt) = 1
MT_RECORD(mt) = 1
}
# Make sure that we are not reopening a drive which is already open.
for (fd=1; fd <= MT_MAXTAPES; fd=fd+1)
if (fd != mt && MT_OSCHAN(fd) != NULL)
if (streq (MT_DEVICE(fd), MT_DEVICE(mt)))
call syserrs (SYS_MTMULTOPEN, mtname)
# Initialize the remaining fields in the file descriptor and open the
# device. ZOPNMT will position the tape. Note that we pass the index
# of the new mtio descriptor slot to ZOPNMT in the common. This is a
# bit ugly, but is safe enough, since we know that FOPNBF is going to
# call ZOPNMT.
switch (acmode) {
case READ_ONLY:
MT_ACMODE(mt) = READ_ONLY
case WRITE_ONLY, APPEND, NEW_TAPE:
MT_ACMODE(mt) = WRITE_ONLY
default:
call syserrs (SYS_MTACMODE, mtname)
}
new_mtchan = mt
fd = fopnbf (MT_IODEV(mt), acmode,
zopnmt, zardmt, zawrmt, zawtmt, zsttmt, zclsmt)
# Set the file buffer size (record size for variable block devices).
if (bufsize > 0)
call fseti (fd, F_BUFSIZE, bufsize)
# If the user specified a record offset, skip records up to there.
# Zero means leave positioned to old record.
if (MT_RECORD(mt) == 0)
MT_RECORD(mt) = MT_RECNO(mt)
if (MT_RECORD(mt) > 1) {
nskip = MT_RECORD(mt) - 1
MT_RECORD(mt) = 1
if (mt_skip_record (fd, nskip) != nskip)
call syserrs (SYS_MTSKIPREC, mtname)
}
call mt_savepos (mt)
call sfree (sp)
return (fd)
end
|