From 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 Mon Sep 17 00:00:00 2001
From: Joe Hunkeler <jhunkeler@gmail.com>
Date: Tue, 11 Aug 2015 16:51:37 -0400
Subject: Repatch (from linux) of OSX IRAF

---
 sys/mtio/doc/mtio.hlp | 814 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 814 insertions(+)
 create mode 100644 sys/mtio/doc/mtio.hlp

(limited to 'sys/mtio/doc/mtio.hlp')

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.
-- 
cgit 

