Fortran Library Reference

topen, tclose, tread,..., tstate: Tape I/O

(FORTRAN 77 Only) These routines provide an alternative way to manipulate magnetic tape:

topen

Associate a device name with a tape logical unit.  

tclose

Write EOF, close tape device channel, and remove association with tlu.

tread

Read next physical record from tape into buffer.  

twrite

Write the next physical record from buffer to tape.  

trewin

Rewind the tape to the beginning of the first data file.  

tskipf

Skip forward over files and/or records, and reset EOF status.  

tstate

Determine the logical state of the tape I/O channel.  

On any one unit, do not mix these functions with standard FORTRAN I/O.

You must first use topen() to open a tape logical unit, tlu, for the specified device. Then you do all other operations on the specified tlu. tlu has no relationship at all to any normal FORTRAN logical unit.

Before you use one of these functions, its name must be in an INTEGER*4 type statement.

topen: Associate a Device with a Tape Logical Unit

The function is called by:

INTEGER*4 topen

n = topen( tlu, devnam, islabeled )

tlu

INTEGER*4

Input 

Tape logical unit, in the range 0 to 7.  

devnam 

CHARACTER 

Input 

Device name; for example: '/dev/rst0'

islabeled

LOGICAL

Input 

True=the tape is labeled 

A label is the first file on the tape. 

Return value 

INTEGER*4

Output 

n=0: OK

n<0: Error

This function does not move the tape. See perror(3F) for details.

Example: topen()--open a 1/4-inch tape file:


    CHARACTER devnam*9 / '/dev/rst0' /
    INTEGER*4 n / 0 /, tlu / 1 /, topen
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    IF ( n .LT. 0 ) STOP "topen: cannot open"
    WRITE(*,'("topen ok:", 2I3, 1X, A10)') n, tlu,  devnam
    END

The output is:


topen ok: 0 1 /dev/rst0 

tclose: Write EOF, Close Tape Channel, Disconnect tlu

The function is called by:

INTEGER*4 tclose

n = tclose ( tlu )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7 

n

INTEGER*4

Return value 

n=0: OK

n<0: Error


Caution - Caution -

tclose() places an EOF marker immediately after the current location of the unit pointer, and then closes the unit. So if you trewin() a unit before you tclose() it, its contents are discarded.


Example: tclose()--close an opened 1/4-inch tape file:


    CHARACTER devnam*9 / '/dev/rst0' /
    INTEGER*4 n / 0 /, tlu / 1 /, tclose, topen
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    n = tclose( tlu )
    IF ( n .LT. 0 ) STOP "tclose: cannot close"
    WRITE(*, '("tclose ok:", 2I3, 1X, A10)')  n, tlu,  devnam
    END

The output is:


tclose ok: 0 1  /dev/rst0

twrite: Write Next Physical Record to Tape

The function is called by:

INTEGER*4 twrite

n = twrite( tlu, buffer )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7 

buffer

character

Input 

Must be sized at a multiple of 512 

n

INTEGER*4

Return value 

n>0: OK, and n = the number of bytes written

n=0: End of Tape

n<0: Error

The physical record length is the size of buffer.

Example: twrite()--write a 2-record file:


    CHARACTER devnam*9 / '/dev/rst0' /, rec1*512 / "abcd" /, 
&            rec2*512 / "wxyz" /
    INTEGER*4 n / 0 /, tlu / 1 /, tclose, topen, twrite
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    IF ( n .LT. 0 ) STOP "topen: cannot open"
    n = twrite( tlu, rec1 )
    IF ( n .LT. 0 ) STOP "twrite: cannot write 1"
    n = twrite( tlu, rec2 )
    IF ( n .LT. 0 ) STOP "twrite: cannot write 2"
    WRITE(*, '("twrite ok:", 2I4, 1X, A10)')  n, tlu, devnam
    END

The output is:


twrite ok: 512 1 /dev/rst0 

tread: Read Next Physical Record from Tape

The function is called by:

INTEGER*4 tread

n = tread( tlu, buffer )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7.  

buffer

character

Input 

Must be sized at a multiple of 512, and must be large enough to hold the largest physical record to be read.  

n

INTEGER*4

Return value 

n>0: OK, and n is the number of bytes read.

n<0: Error

n=0: EOF

If the tape is at EOF or EOT, then tread does a return; it does not read tapes.

Example: tread()--read the first record of the file written above:


    CHARACTER devnam*9 / '/dev/rst0' /, onerec*512 / " " /
    INTEGER*4 n / 0 /, tlu / 1 /, topen, tread
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    IF ( n .LT. 0 ) STOP "topen: cannot open"
    n = tread( tlu, onerec )
    IF ( n .LT. 0 ) STOP "tread: cannot read"
    WRITE(*,'("tread ok:", 2I4, 1X, A10)')  n, tlu,  devnam
    WRITE(*,'( A4)')  onerec
    END

The output is:


tread ok: 512 1 /dev/rst0
abcd

trewin: Rewind Tape to Beginning of First Data File

The function is called by:

INTEGER*4 trewin

n = trewin ( tlu )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7 

n

INTEGER*4

Return value 

n=0: OK

n<0: Error

If the tape is labeled, then the label is skipped over after rewinding.

Example 1: trewin()--typical fragment:


    CHARACTER devnam*9 / '/dev/rst0' / 
    INTEGER*4 n /0/, tlu /1/, tclose, topen, tread, trewin 
    ... 
    n = trewin( tlu ) 
    IF ( n .LT. 0 ) STOP "trewin: cannot rewind" 
    WRITE(*, '("trewin ok:", 2I4, 1X, A10)') n, tlu, devnam 
    ... 
    END 

Example 2: trewin()--in a two-record file, try to read three records, rewind, read one record:


    CHARACTER devnam*9 / '/dev/rst0' /, onerec*512 / " " /
    INTEGER*4 n / 0 /, r, tlu / 1 /, topen, tread, trewin
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    IF ( n .LT. 0 ) STOP "topen: cannot open"
    DO r = 1, 3
       n = tread( tlu, onerec )
       WRITE(*,'(1X, I2, 1X, A4)')  r, onerec
    END DO
    n = trewin( tlu )
    IF ( n .LT. 0 ) STOP "trewin: cannot rewind"
    WRITE(*, '("trewin ok:" 2I4, 1X, A10)')  n, tlu, devnam
    n = tread( tlu, onerec )
    IF ( n .LT. 0 ) STOP "tread: cannot read after rewind"
    WRITE(*,'(A4)')  onerec
    END

The output is:


1 abcd 
2 wxyz 
3 wxyz 
trewin ok: 0 1 /dev/rst0 
abcd 

tskipf: Skip Files and Records; Reset EoF Status

The function is called by:

INTEGER*4 tskipf

n = tskipf( tlu, nf, nr )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7 

nf

INTEGER*4

Input 

Number of end-of-file marks to skip over first 

nr

INTEGER*4

Input 

Number of physical records to skip over after skipping files 

n

INTEGER*4

Return value 

n=0: OK

n<0: Error

This function does not skip backward.

First, the function skips forward over nf end-of-file marks. Then, it skips forward over nr physical records. If the current file is at EOF, this counts as one file to skip. This function also resets the EOF status.

Example: tskipf()--typical fragment: skip four files and then skip one record:


    INTEGER*4 nfiles / 4 /, nrecords / 1 /, tskipf, tlu / 1 / 
    ... 
    n = tskipf( tlu, nfiles, nrecords ) 
    IF ( n .LT. 0 ) STOP "tskipf: cannot skip" 
    ...

Compare with tstate() .

tstate: Get Logical State of Tape I/O Channel

The function is called by:

INTEGER*4 tstate

n = tstate( tlu, fileno, recno, errf, eoff, eotf, tcsr )

tlu

INTEGER*4

Input 

Tape logical unit, in range 0 to 7 

fileno

INTEGER*4

Output 

Current file number  

recno

INTEGER*4

Output 

Current record number 

errf

LOGICAL

Output 

True=an error occurred  

eoff

LOGICAL

Output 

True=the current file is at EOF  

eotf

LOGICAL

Output 

True=tape has reached logical end-of-tape  

tcsr

INTEGER*4

Output 

True=hardware errors on the device. It contains the tape drive control status register. If the error is software, then tcsr is returned as zero. The values returned in this status register vary grossly with the brand and size of tape drive.

For details, see st(4s).

While eoff is true, you cannot read from that tlu. You can set this EOF status flag to false by using tskipf() to skip one file and zero records:


    n = tskipf( tlu, 1, 0). 

Then you can read any valid record that follows.

End-of-tape (EOT) is indicated by an empty file, often referred to as a double EOF mark. You cannot read past EOT, but you can write past it.

Example: Write three files of two records each:


    CHARACTER devnam*10 / '/dev/nrst0' /,
&                 f0rec1*512 / "eins" /, f0rec2*512 / "zwei" /,
&                 f1rec1*512 / "ichi" /, f1rec2*512 / "ni__" /,
&                 f2rec1*512 / "un__" /, f2rec2*512 / "deux" /
    INTEGER*4 n / 0 /, tlu / 1 /, tclose, topen, trewin, twrite
    LOGICAL islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    n = trewin( tlu )
    n = twrite( tlu, f0rec1 )
    n = twrite( tlu, f0rec2 )
    n = tclose( tlu )
    n = topen( tlu, devnam, islabeled )
    n = twrite( tlu, f1rec1 )
    n = twrite( tlu, f1rec2 )
    n = tclose( tlu )
    n = topen( tlu, devnam, islabeled )
    n = twrite( tlu, f2rec1 )
    n = twrite( tlu, f2rec2 )
    n = tclose( tlu )
    END

The next example uses tstate() to trap EOF and get at all files.

Example: Use tstate() in a loop that reads all records of the 3 files written in the previous example:


    CHARACTER devnam*10 / '/dev/nrst0' /, onerec*512 / " " /
    INTEGER*4 f, n / 0 /, tlu / 1 /, tcsr, topen, tread, 
&        trewin, tskipf, tstate
    LOGICAL errf, eoff, eotf, islabeled / .false. /
    n = topen( tlu, devnam, islabeled )
    n = tstate( tlu, fn, rn, errf, eoff, eotf, tcsr )
    WRITE(*,1)  'open:', fn, rn, errf, eoff, eotf, tcsr
1    FORMAT(1X, A10, 2I2, 1X, 1L, 1X, 1L,1X, 1L, 1X, I2 )
2    FORMAT(1X, A10,1X,A4,1X,2I2,1X,1L,1X,1L,1X,1L,1X,I2)
    n = trewin( tlu )
    n = tstate( tlu, fn, rn, errf, eoff, eotf, tcsr )
    WRITE(*,1)  'rewind:', fn, rn, errf, eoff, eotf, tcsr
    DO f = 1, 3
       eoff = .false.
       DO WHILE ( .NOT. eoff )
          n = tread( tlu, onerec )
          n = tstate( tlu, fn, rn, errf, eoff, eotf, tcsr )
          IF (.NOT. eoff) WRITE(*,2) 'read:', onerec, 
&            fn, rn, errf, eoff, eotf, tcsr
       END DO
       n = tskipf( tlu, 1, 0 )
       n = tstate( tlu, fn, rn, errf, eoff, eotf, tcsr )
       WRITE(*,1)  'tskip: ', fn, rn, errf, eoff, eotf, tcsr
    END DO
    END

The output is:


open: 0 0 F F F 0 
rewind: 0 0 F F F 0 
read: eins 0 1 F F F 0 
read: zwei 0 2 F F F 0 
tskip: 1 0 F F F 0 
read: ichi 1 1 F F F 0 
read: ni__ 1 2 F F F 0 
tskip: 2 0 F F F 0 
read: un__ 2 1 F F F 0 
read: deux 2 2 F F F 0 
tskip: 3 0 F F F 0 

A summary of EOF and EOT follows:

See also: ioctl(2), mtio(4s), perror(3F), read(2), st(4s), and write(2).