aboutsummaryrefslogtreecommitdiff
path: root/sys/mtio/doc/mtio.hlp
diff options
context:
space:
mode:
Diffstat (limited to 'sys/mtio/doc/mtio.hlp')
-rw-r--r--sys/mtio/doc/mtio.hlp814
1 files changed, 814 insertions, 0 deletions
diff --git a/sys/mtio/doc/mtio.hlp b/sys/mtio/doc/mtio.hlp
new file mode 100644
index 00000000..e00643a5
--- /dev/null
+++ b/sys/mtio/doc/mtio.hlp
@@ -0,0 +1,814 @@
+.help mtio Aug83 "Magnetic Tape I/O"
+.sh
+1. Introduction
+
+ This document describes the Magnetic Tape I/O (MTIO) package,
+i.e., the interface by which IRAF programs access magnetic tapes.
+Included are the requirements and specifications for the package,
+and a discussion of the interface between MTIO and FIO.
+
+.sh
+2. MTIO Requirements
+.ls 4
+.ls (1)
+The machine independent part of the MTIO package shall be written in
+the SPP language in compliance with the standards and conventions of IRAF.
+.le
+.ls (2)
+The MTIO package shall provide a single interface to all magtape
+devices on all IRAF target machines.
+.le
+.ls (3)
+MTIO shall interface to FIO, making it possible to read and write a magtape
+file via the FIO interface in a device independent fashion.
+.le
+.ls (4)
+All functions shall take an error action if a hardware error occurs,
+or if an illegal function is requested.
+No hardware exception or trap shall occur while accessing a magtape
+file via MTIO which is not caught by MTIO and converted into an
+IRAF error action.
+.le
+.ls (5)
+All error actions shall be defined symbolically in the system error
+code file <syserr.h>. The MTIO error messages shall have the
+form SYS_MT<function>, i.e., SYS_MTOPEN. The error message strings
+shall be placed in the system error message file, "syserrmsg".
+.le
+.ls (6)
+The MTIO code shall be divided into a machine independent part and
+a machine dependent part. All machine independent function and error
+checking shall be done in the machine independent part, to minimize
+the size and complexity of the machine dependent part, and therefore
+maximize the transportability of the package.
+.le
+.ls (7)
+MTIO shall interface to FIO by implementing the standard FIO binary file
+z-routines ZOPNMT, ZCLSMT, ZARDMT, ZAWRMT, ZAWTMT, and ZSTTMT.
+The specifications for these routines are given elsewhere.
+.le
+
+.sh
+3. MTIO Specifications
+
+ A magtape file is opened with MTOPEN and then accessed as a binary
+file via the device independent FIO interface. Upon input, FIO merges
+all tape records together into a binary byte stream. Upon output,
+FIO writes records equal in size to the FIO buffers, unless FLUSH or
+CLOSE is called, causing a partially filled buffer to be flushed to tape.
+The data within a tape file may not be randomly accessed; only sequential
+accesses are permitted. When i/o is complete, CLOSE should be called
+to close the file and return all buffer space.
+
+ fd = mtopen (filename, access_mode, buf_size)
+
+The format of a nonblank magnetic tape consists of beginning-of-tape (BOT),
+followed by zero or more files, followed by end-of-tape (EOT).
+Each file consists of one or more records, followed by a tape mark (EOF).
+EOT is defined as two consecutive tape marks, i.e., as a file containing
+zero records. MTIO knows nothing about labeled tapes.
+
+Tape records need not all be the same length, but for transportability
+reasons records should be an integral number of computer words in length,
+and very short records should be avoided (short records are used by some
+operating systems for special purposes). The term "computer word"
+is not well defined; the size of a tape record in bytes should be evenly
+divisible by 2, 4, or 8, where the transportability increases with the
+size of the divisor. To avoid loss of data when reading a tape,
+the FIO buffer must be at least as large as the longest record on the tape.
+
+.sh
+3.1 Opening a Magtape
+
+ MTOPEN opens a file on the named magtape device. The following
+device naming convention determines the tape drive and density:
+
+ mt[a-z][800|1600|6250]
+
+The letter in the second field determines which drive is to be used,
+and the third field, which is optional, determines the density.
+If the density is not specified, a system or drive dependent default
+density will be selected. Thus, to access a file on drive A at 1600 bpi,
+one would open the file "mta1600".
+
+The significance of the terms "drive A", "drive B", etc., is installation
+dependent, and need not imply distinct physical drives. A tape drive may
+have to be allocated before it can be opened by MTIO; MTIO does not attempt
+to allocate devices.
+
+The device name may optionally be followed by a subscript specifying
+the index of the file to which the tape is to be positioned.
+Thus, opening "mta[3]" causes device A to be opened with the default
+density, positioned to BOF of the third file on the tape.
+The field N, as in "mta[N]" may have the following values:
+
+.ls 4
+.ls 12 absent
+If the entire subscript is absent, or if N is absent the tape is opened
+at the current position, i.e., the tape is not physically moved.
+.le
+.ls N >= 1
+If an integer number greater than or equal to 1 (one) is given,
+the tape is opened positioned to that file.
+.le
+.ls N == EOT
+If the file number is given as "EOT" or as "eot", the tape is opened
+positioned at EOT.
+.le
+.le
+
+If called with a non "mt"-prefixed file name, MTOPEN assumes that the file
+is a regular disk resident binary file, and attempts to open the named
+file. A program which normally reads directly from a magtape device may
+therefore be used to read from a regular binary file, or from the
+standard input (the special file "STDIN").
+
+The following access modes are recognized by MTOPEN:
+.ls 4
+.ls 12 READ_ONLY
+The device is opened for reading, positioned to the beginning of
+a file, BOT, EOT, or to the "current position".
+Any attempt to write to the device will cause an error.
+.le
+.ls WRITE_ONLY
+The device is opened for writing, positioned to the beginning of a file,
+BOT, EOT, or to the "current position". When the file is subsequently
+closed, a new EOT mark will be written. Existing tape files may be overwritten.
+.le
+.ls APPEND
+The device is opened for writing, positioned at the end of tape (EOT).
+Append mode must not be used with blank tapes. Note that the significance
+of APPEND mode is different for MTOPEN than for a regular file open;
+the tape is to be extended by adding a new file, whereas in FIO it is
+the file itself which is extended.
+.le
+.ls NEW_TAPE
+The device is opened for writing, positioned at BOT. Any existing
+data on the tape is overwritten. Recommended mode for blank tapes.
+.le
+.le
+
+FIO can read any tape with a maximum record size less than or equal
+to the buffer size. In buffered mode, FIO normally writes records equal
+in size to the FIO internal buffers. Smaller records may be written if
+FLUSH or CLOSE is called; records of any size may be written in unbuffered
+mode.
+
+The third argument to MTOPEN is used to set the FIO buffer size.
+If the buffer size is given as zero, a default value is used.
+The default value chosen depends on the mode of access and upon the
+maximum record size permitted by the host system. MTOPEN will automatically
+allocate the maximum size FIO buffer if the tape is opened for reading.
+The FIO buffer size may be changed in an FSET call anytime before
+the first buffered i/o on the file.
+
+.sh
+3.2 Ordinary I/O to a Magtape Device
+
+ Seeks are not permitted on magtape files. A tape may be opened for
+reading or for writing, but not for both at the same time. A magtape
+device is much like the standard input and output; STDIN is read only,
+STDOUT is write only, and seeking is not permitted on either. STDIN
+differs from ordinary files in that data may continue to be read after
+an EOF; the same is true of magtape files. If a read returning EOF is
+followed by another read on a magtape device, the second read will
+access the first record of the next file. Once EOT is reached, every
+read will return EOF. There is no way to advance beyond EOT on a read.
+An EOF mark may only be written by closing the tape (see next section).
+
+.sh
+3.3 Closing a Magtape
+
+ The CLOSE function is called either explicitly by the user task,
+or implicilty by the IRAF main upon normal or abnormal task termination.
+If the file was opened for writing, CLOSE flushes the output buffer and
+writes an EOT mark at the current position. A file opened for writing
+is left positioned ready to write the first record of the next file on
+the tape (i.e., after the EOF of the file just written). A file opened
+for reading, if closed immediately after reading EOF, is left positioned
+ready to read or write the first record of the next file on the tape.
+
+.sh
+3.4 Bytes and Records
+
+ Upon input, the size of a record will be rounded up to an integral
+number of "chars". No data will be lost, but one or more extra bytes of
+data may be added. A tape conversion program which must deal with
+odd-sized records must know the size of tape records to properly extract
+the data. FIO cannot write odd-sized records.
+
+The binary i/o routines do not transform the data in any way,
+including byte swapping. If byte swapping is necessary, the conversion
+program must do the byte swapping explicitly. The predefined machine
+constants BYTE_SWAP and WORD_SWAP indicate whether byte or word swapping
+is necessary on the local machine (word swapping refers to the two 16 bit
+words in a long integer). Floating point data should not be stored in
+binary on tape, unless the tape is to be read only by the machine which
+wrote it.
+
+Routines are available elsewhere in the PI for manipulating bytes.
+The routines BYTMOV, BYTSWP, and BYTPAK are particularly useful for cracking
+foreign tapes.
+
+.sh
+3.5 Low level I/O to a Magtape
+
+ The asynchronous, unbuffered FIO routines AREAD, AWRITE, and AWAIT
+may be used to perform record i/o on a magtape. A single tape record
+is read or written by each call; the FIO buffer is not used. AWAIT must
+be called after each read or write, before initiating the next i/o transfer.
+Although in general it is unwise to mix buffered and unbuffered i/o on
+the same file, it is safe to perform one or more unbuffered transfers
+immediately after opening a file, before performing any buffered i/o.
+
+If an application must do something peculiar, like write an odd-sized
+record, the MTIO z-routines may be called directly. The z-routines transfer
+data in units of machine bytes.
+
+.sh
+3.6 CL level tape commands
+
+ The four routines ALLOCATE, DEALLOCATE, REWIND and MTSTATUS will be
+available at the CL level. A tape drive ("mta", "mtb", etc.) must be
+explicitly allocated before it can be accessed with MTOPEN.
+A drive may be allocated to only one user at a time. MTIO keeps track
+of the position of an allocated tape; once a drive has been allocated,
+the tape must not be manually positioned by the user. Tapes can be
+changed without reallocating the drive provided REWIND is first used to
+rewind the tape. DEALLOCATE automatically rewinds the tape before
+deallocating the drive. MTSTATUS tells whether or not a particular drive
+has been allocated, and if so, gives the name of the owner, the density,
+whether not the device is physically open, and so on.
+
+.sh
+3.6 Example
+
+ The following program reads an ASCII card image file from the
+input tape and converts it to an ordinary text stream, which is written
+to the standard output. This program is insensitive to the number of
+cards per tape record, and may be used to read card image disk files
+as well as tape files.
+
+The following CL commands might be entered to read the second card image
+file on the 800 bpi input tape into file "myfile", converting to lower case:
+
+.ks
+.nf
+ cl> allocate mta
+ cl> rcardimage "mta800[2]" | lcase > myfile
+.fi
+.ke
+
+
+The source for the program "rcardimage" follows:
+
+
+.ks
+.nf
+# RCARDIMAGE -- CL callable task which reads a card image
+# file, writing the converted cards to the standard output.
+
+procedure rcardimage()
+
+char filename[SZ_FNAME]
+int input, mtopen()
+
+begin
+ call clgstr ("filename", filename, SZ_FNAME)
+ input = mtopen (filename, READ_ONLY, 0)
+ call read_card_image_file (input, STDOUT)
+ call close (input)
+end
+.fi
+.ke
+
+
+
+.ks
+.nf
+define SZ_CARD 80
+
+# READ_CARD_IMAGE_FILE -- Read the named card image file, convert
+# to a regular character stream, and write to the output file.
+
+procedure read_card_image_file (input, output)
+
+int input, output # input, output files
+char cardbuf[SZ_CARD] # raw card
+char linebuf[SZ_CARD+1] # add 1 char for newline
+int last_char
+int read()
+errchk read, putline
+
+begin
+ # Read successive cards until EOF is reached. Unpack the
+ # card, strip trailing whitespace, and write the processed
+ # line to the output file.
+
+ while (read (input, cardbuf, SZ_CARD) != EOF) {
+ call chrupk (cardbuf, 1, linebuf, 1, SZ_CARD)
+
+ # Strip trailing whitespace, add newline.
+ last_char = 0
+ for (ip=1; ip <= SZ_CARD; ip=ip+1)
+ if (! IS_WHITE (linebuf[ip]))
+ last_char = ip
+
+ linebuf[last_char+1] = '\n'
+ linebuf[last_char+2] = EOS
+
+ call putline (output, linebuf)
+ }
+end
+.fi
+.ke
+.endhelp
+
+
+.helpsys mtio Nov83 "MTIO Interface Detailed Design"
+.sh
+Strategies for Interfacing MTIO
+
+ The specifications for MTIO have been kept as simple as possible for maximum
+machine independence. There is only one high level call, MTOPEN, which is
+used to open the device; it does little more than call FIO. Thereafter
+everything is done through the six FIO z-routines:
+
+.nf
+ zopnmt (filespec, access_mode; channel|ERR)
+ zclsmt (channel)
+ zardmt (channel, buffer, maxbytes, one_indexed_byte_offset)
+ zawrmt (channel, buffer, nbytes, one_indexed_byte_offset)
+ zawtmt (channel; nbytes|ERR)
+ zsttmt (channel, parameter; long_value)
+.fi
+
+These z-routines may be written in any language so long as they are SPP (i.e.,
+Fortran) callable. The "filespec" argument is a packed string. The access
+modes and ERR code are system constants defined in <iraf.h>. Channel may be
+anything you wish. The file offsets will always be zero since the magtape
+device is a streaming (sequential) device.
+
+Be sure that the z-routines, if written partially in the SPP language, do not
+make calls to high level program interface routines, especially any which do
+i/o. Doing so violates the reentrancy restrictions of the SPP language (and
+of Fortran). It may also lead to problems with the way libraries are searched.
+More explicitly, any calls to error or iferr, to any of the FIO routines, or to
+any of the printf or scan routines are absolutely forbidden. It is ok to use
+the string primitives (because they do not do any i/o or call error), but it
+is best to avoid even those if possible. It is perfectly all right to call
+other z-routines provided they do not directly or indirectly call you back
+(none will call mtio).
+
+.sh
+Virtual Device Model
+
+ Though in general the z-routines may have to be completely rewritten for
+a new OS, in fact many systems have functionally similar primitive magtape
+interfaces. If your system can be described by the model defined below,
+the "z?*.x" files in this directory can be used unchanged, and all you need to
+provide are the equivalents of the "zz" prefixed files.
+
+ Basically, the model requires that the zz-routine which opens the magtape
+be capable of positioning the tape to the first record of any file, given the
+file number to which the tape is positioned at open time. The high level MTIO
+interface code is charged with keeping track of the position of the tape at
+all times, including while the tape is closed. The high level code does not
+explicitly move the tape, though it does implicitly move it during open and when
+it commands an i/o operation. The high level code assumes nothing about tape
+motions; all zz-primitives return status values stating how many records or
+files the tape moved in the last operation. Thus, the details of the function
+of a zz-routine can vary depending on the system, without requiring
+modifications to the z-routines.
+
+.ls 4
+.ls (1)
+The following open/close primitives are required. ZZOPMT opens a tape
+drive positioned ready to read or write the first record of the specified
+file.
+.ls zzopmt (drive,density,acmode, oldrec,oldfile; newfile; oschan|ERR)
+.br
+.ls 10 drive
+Logical drive number (1,2,3,...).
+.le
+.ls density
+Drive density. A positive integer, i.e., 800, 1600 or 6250. A value
+of zero implies that an OS default density is to be selected.
+.le
+.ls acmode
+Access mode. Read_only or write_only. Modes new_file and append are
+dealt with by the "newfile" file number parameter.
+.le
+.ls oldrecord
+The number of the record to which we are currently positioned in the
+oldfile. We have to know this to know whether or not the file has to
+be rewound. The first record is number one.
+.le
+.ls oldfile
+The number of the file to which the tape is currently positioned.
+.le
+.ls newfile
+The number of the file to be opened, where 1 specifies that the tape is
+to be rewound. If newfile <= 0, open at EOT. On output, contains the
+actual file number of the new file; this may differ from the requested
+value if EOT is encountered. It is not an error (as far as the zz-routine
+is concerned) to attempt to position to a file beyond EOT.
+.le
+.ls oschan
+The channel number by which the file is to be referred in calls to the
+other zz-routines, or ERR if the file cannot be opened. ZZOPMT should
+set oschan IMMEDIATELY AFTER PHYSICALLY OPENING THE DEVICE, so that the
+error recovery code can close the file if an interrupt occurs.
+.le
+.le
+
+.ls 4 zzclmt (oschan, access_mode; nfile)
+Close tape. Write a new EOT at the current position if writing.
+Returns the file number increment (in the event that a file mark or two
+has to be written).
+.le
+.le
+
+.ls (2)
+The following i/o primitives are required.
+.ls zzrdmt (oschan, buf, maxbytes)
+Initiate a read of up to maxbytes bytes from the next tape
+record into buffer buf. It is not an error if fewer than "maxbytes"
+bytes are read; in fact maxbytes will normally be larger than the largest
+record on the tape. In general it is difficult to tell if the tape record
+was larger than maxbytes; the user code should select a large maxbytes and
+consider it an error if the full maxbytes are read. If EOF is encountered,
+return a zero byte count in the next call to zzwtmt.
+.le
+.ls zzwrmt (oschan, buf, nbytes)
+Initiate a write of "nbytes" bytes to the tape. It is an error
+if all data is not written.
+.le
+.ls zzwtmt (oschan; nbytes|ERR, nrecord, nfile)
+Wait for i/o to complete, and return the number of bytes read or
+written in the last transfer; return 0 if we read a tape mark.
+Keep returning the same thing in redundant calls. If an error
+occurs the error status should be cleared when the next i/o
+transfer is initiated. Return nrecord=1 for each tape record read,
+but not for file marks. Return nfile=1 if a filemark is skipped.
+A read of 0 bytes signifies that EOF was seen, but does not necessarily
+imply that a tape mark has been skipped.
+.le
+.le
+.le
+
+.sh
+Program Structure
+
+ The drive must be allocated before MTOPEN is called; MTOPEN verifies
+that the drive has been allocated and then calls FIO to install the magtape
+device and open the desired file on the drive. Allocating a file involves
+a call to the OS to allocate and/or mount the device, followed by creation
+of the device lock file in the dev$ directory. The lock file is used to
+indicate that the drive has been allocated, and to keep track of the tape
+position when the drive is closed.
+
+
+.ks
+.nf
+ mtopen
+ mt_parse_filespec
+ mt_get_tape_position
+ various FIO routines
+ fopnbf
+ zopnmt
+ zzopmt
+ zsttmt
+ fset [to set buffer size]
+
+
+ Structure of the MTOPEN Procedure
+.fi
+.ke
+
+
+The ZCLSMT procedure is called by CLOSE to close a file opened with MTOPEN.
+CLOSE may be called by the user, by the IRAF main if the task completes w/o
+closing the file, or during error recovery. An error occurring during MTOPEN
+may result in a call to CLOSE. We do not have to worry about reentrancy here
+because none of the MTIO z-routines called by ZOPNMT call error (they will
+return an ERR status to FOPNBF and therefore terminate before ZCLSMT is called).
+
+
+.ks
+.nf
+ close
+ zclsmt
+ mt_update_lockfile
+ smark,salloc,sfree
+ fvfn_to_osfn
+ mktemp
+ zopntx
+ zputtx
+ zclstx
+ zfdele
+ zfrnam
+ fatal
+ zzclmt
+
+
+ Structure of the ZCLSMT procedure
+.fi
+.ke
+
+
+The i/o procedures keep track of the number of records read or written and
+ensure that we do not read past EOF or EOT. We need to keep track of the
+number of records written so that we can detect a null file write.
+
+
+.ks
+.nf
+ aread awrite
+ zardmt zawrmt
+ zzrdmt zzwrmt
+
+
+ await
+ zawtmt
+ zzwtmt
+
+
+ Structure of the I/O Procedures
+.fi
+.ke
+
+
+The final routine is the ZSTTMT status procedure. This routine is self
+contained, except that access to the MTIO common is required to get the
+access mode (which determines the default buffer size).
+
+
+.sh
+Semicode
+
+ We do as much of the work in MTOPEN as we can, since it is the only
+high level, machine independent routine we have (we can call anything in this
+routine without reentrancy problems). We check that the drive has been
+allocated (to us), allocate an mtio device descriptor, check that the same
+drive has not been reopened, parse the filespec and save the pieces in the
+descriptor (for later use by ZOPNMT), read in the current tape position from
+the lock file, and then call fopnbf which in turn calls ZOPNMT to open the
+drive and position to the desired file.
+
+
+.tp 8
+.nf
+int procedure mtopen (filespec, access_mode, bufsize)
+
+begin
+ if (file not mt-prefixed) {
+ call open to open regular binary file
+ return (file descriptor returned by open)
+ }
+
+ get mtio device descriptor slot but do not allocate it yet
+ if (slots all taken)
+ error: magtape device multiply opened (filespec)
+ call mt_parse_filespec to break out drivename, density,
+ filenumber and set up mtio device descriptor
+ if (drive is already open)
+ error: magtape device multiply opened (filespec)
+ check that the named drive has been allocated to us
+ if (drive not allocated to us)
+ error: magtape not allocated (filespec)
+ decode lock file to get old position of drive, save in
+ device descriptor
+
+ call fopnbf to install the magtape device and open file
+ if (bufsize is nonzero)
+ call fset to set non-default FIO buffer size
+
+ return (file descriptor)
+end
+.fi
+
+
+ZOPNMT is passed a mostly initialized magtape file descriptor in the mtio
+common by MTOPEN. The "filespec" string is not actually used by ZOPNMT.
+We physically open the file and set up the remaining fields in the tape file
+descriptor. NOTE: if an interrupt occurs during the call to ZZOPMT,
+ZCLSMT will be called to perform error recovery. If this happens the
+position of the tape is undefined.
+
+
+.ks
+.nf
+procedure zopnmt (filespec, access_mode; chan|ERR)
+
+[we are passed the mtio file descriptor in the mtio common]
+
+begin
+ set flag for ZCLSMT in case we are interrupted
+ call ZZOPMT to open tape positioned to the beginning of the
+ indicated file.
+
+ if (cannot open tape)
+ return (chan = ERR)
+ if (actual file < requested file)
+ if (reading)
+ set at-eof flag and at_eot flag, so that reads return EOF
+ else {
+ call zzclmt to close device
+ return (mtchan = ERR)
+ }
+
+ save oschan in descriptor
+ save actual file number in descriptor
+ initialize the remaining descriptor fields
+
+ return (chan = mtio descriptor index)
+end
+.fi
+.ke
+
+
+Opening a file for writing and then immediately closing it poses problems.
+There is no way to write a zero-length file on an unlabeled tape. We cannot
+just write a tape mark because that might mean writing a spurious double
+tapemark (false EOT) in the middle of the tape. We could just ignore the
+request and not write any file, but that is not quite right either (if a
+disk file is opened for writing and then immediately closed, a file is
+still created). We compromise by writing a single short record containing
+the packed ASCII character string "NULLFILE". The actual length of the
+physical nullfile record is machine dependent.
+
+We may or may not need to bump the file counter when the file is closed;
+the OS tells us which. If we have just written a file and ZZCLMT must
+write a tape mark, for example, we might be left positioned before EOT,
+between the tape marks, or (unlikely) after the tape marks.
+
+If an error (i.e., console interrupt) occurs while the tape is being
+positioned by ZZOPMT, we will be called by the error recovery system
+with a garbage mtchan argument. We must be able to detect this type
+of call and modify the lock file, marking the position of the tape
+as UNDEFINED. The next open call will then automatically rewind the
+tape, ensuring accurate positioning. In a normal close we write out
+a lockfile identifying the file and record to which the tape is positioned.
+
+
+.ks
+.nf
+procedure zclsmt (mtchan)
+
+begin
+ if (error recovery in progress for ZOPNMT)
+ mark current position as undefined
+ else {
+ if (file was opened for writing but nothing was written)
+ write out "null file" short record
+
+ call zzclmt (oschan, access_mode; nfiles)
+ file += nfiles
+ if (nfiles > 0)
+ record = 1
+ }
+
+ call mt_update_lockfile to save tape status, position
+ deallocate the mtio device descriptor slot
+end
+.fi
+.ke
+
+
+Ignore all read requests once EOF or EOT has been reached. The only operation
+possible at that point is to close the device; there is no rewind or backskip
+function for a streaming device. We do not "know" what would happen if we
+called ZZRDMT after reaching EOF; this is OS dependent, and we do not want
+to require any particular behavior (some systems would return the first
+record of the next file, others would keep returning EOF).
+
+
+.ks
+.nf
+procedure zardmt (mtchan, buf, maxbytes, offset)
+
+begin
+ if (not at EOF or EOT)
+ call zzrdmt (oschan, buf, maxbytes)
+end
+.fi
+.ke
+
+
+We cannot hit EOF or EOT on a write, so merely post the request and return.
+Ignore the "offset" parameter since magtape is a streaming device.
+
+
+.ks
+.nf
+procedure zawrmt (mtchan, buf, nbytes, offset)
+
+begin
+ call zzwrmt (oschan, buf, nbytes)
+end
+.fi
+.ke
+
+
+FIO insures that ZAWTMT is called once and only once after every asynchronous
+i/o read or write request. Once we hit EOF or EOT on a read, we return
+EOF (nchars = 0) on every subsequent request until the file is closed.
+After each real data transfer we update the record,file counters as
+directed by the OS.
+
+
+.ks
+.nf
+procedure zawtmt (mtchan; status)
+
+begin
+ if (reading and at EOF or EOT)
+ return (status = 0)
+
+ call zzwtmt (oschan, nchars, nrecords_skipped, nfiles_skipped)
+ if (nfiles_skipped > 0) {
+ set at-EOF flag
+ record = 1
+ }
+
+ file += nfiles_skipped # keep track of position
+ record += nrecords_skipped
+ nrecords += nrecords_skipped # count records rd|wr
+
+ status = nchars
+end
+.fi
+.ke
+
+.sh
+Error Recovery
+
+ Error recovery during magtape operations is tricky since we are trying
+to keep track of the position of the drive. If an error occurs while the
+tape is being positioned by ZZOPMT we must detect the condition and mark the
+position of the tape as indefinite (forcing a rewind on the next open).
+If an interrupt occurs while positioning to EOT for a write, we do not
+want ZZCLMT to write the new EOT mark somewhere in the middle of the tape,
+truncating the tape.
+
+ Interrupts or other errors while reading or writing are comparatively
+harmless. Interrupting a write results in a short but otherwise normal
+file on the tape; interrupting a read leaves us positioned to some
+arbitrary record within the file (harmless). Conceivably a read
+could be interrupted just as we were reading a tape mark, causing the
+file position to be lost. We have not protected against this.
+
+.sh
+Data Structures
+
+ The mtio device descriptor structure describes the status of each magtape
+device in use. The maximum number of magtape files which can be open at one
+time is the maximum number of tape drives. Only one file can be open on each
+drive at a time.
+
+
+.ks
+.nf
+ struct mtiodes {
+ int mt_drive # 1,2, etc. (c.t. a,b,...)
+ int mt_density # 0,800,1600,6250, etc.
+ int mt_oldfile # file number at open time
+ int mt_oldrecord # record number at open time
+ int mt_file # file being accessed (0=EOT)
+ int mt_record # next record to be accessed
+ int mt_nrecords # nrecords read/written
+ int mt_acmode # access mode
+ int mt_oschan # OS channel number
+ int mt_ateof # true when at EOF
+ int mt_ateot # true when at EOT
+ } mtiocom[MAX_TAPES]
+.fi
+.ke
+
+
+When a device is allocated, a lock file is created in the system logical device
+directory "dev$". For example, the lock file for magtape unit A is the
+file "dev$mta.lok". This is a human readable text file; it is typed out on
+the terminal when the user types "devstatus mta". The lock file is updated
+when the drive is closed and deleted when the drive is deallocated. The drive
+is automatically deallocated when the user logs out of the CL.
+
+
+.ks
+.nf
+Sample Lock File:
+
+ # Magtape unit 'mta' allocated to 'user' Sun 20:06:13 27-Nov-83
+ current file = 4
+ current record = 1
+ 72 records read, EOF seen
+.fi
+.ke
+
+
+The preliminary comments are written when the lock file is created, i.e.,
+when the device is allocated. Any number of comment lines are permitted.
+They are merely copied when ZCLSMT updates the lock file. The remaining
+records are written by ZCLSMT to record the current position of the tape,
+and to inform the user of the device status.