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
|