TAPE READ/WRITE SAMPLE PROGRAM
ITEM: RTA000037086
QUESTION:
Q575861
TITLE: 02/06/92 HOWTO AIX: WRITE LARGE DATA OBJECTS DIRECTLY TO
EITHER THE 8MM OR 1/4" TAPE DRIVE FROM FORTRAN
AND C PROGRAMS.
Q: PLATFORM: RISCSYSTEM
OPERATING SYSTEM:
AIX FOR RISC SYSTEM/6000 Version 3 Release 1 Modification 5
*********************************************************************
** This HOWTO item was written and tested with the above operating **
** system(s). The provided explanations, techniques and procedures**
** have been reviewed for technical accuracy and applicability. **
** Though the techniques and information contained in this item **
** may work on other levels of the operating system(s), it has not **
** necessarily been tested. Normal precautions should be taken in **
** adopting these same techniques and procedures in your own **
** environment. **
*********************************************************************
SCENARIO/EXPLANATION:
In porting customer code from a super-computer environment to the
RISC System/6000, a difference in mass storage tape devices caused
a major problem. In the super-computer environment, when a user's
time limit is met, the process is terminated in favor of the next
scheduled job. To prepare for such an eventuality, programmers often
save entire arrays of data to magnetic tape in what are referred to as
restart datasets. In the super-computer environment and some
workstation environments as well, a large data object such as an array
can be stored on magnetic tape using the same syntax as storing same
on a disk drive:
"WRITE ( UNIT, other_keywords ) DATA_OBJECT, ( LIST(I), I=1, ISIZE )"
or perhaps
"WRITE ( UNIT, other_keywords ) DATA_OBJECT_NAME".
In attempting to write to either the 1/4" or 8mm tape devices, if the
number of bytes being written exceeds the buffer size for the
device, an error occurs and the transfer stops. If variable length
records are being written, and a buffer size other than zero (0) has
been specified, an error occurs and the transfer stops.
It was also discovered that writing large objects to the tape drives
using C programs caused the same errors as encountered using FORTRAN.
SOLUTION:
To enable the creation of the customer's restart datasets, a small
C language program was written which writes large data objects on tape
as a series of buffer-size records with a small remainder record
appended to the tape. Two tape buffer sizes are coded to enable the
use of the largest legal buffer size for the tape device.
Included in this HOWTO item are 4 files: a makefile for generating the
sample programs; a C program for demonstrating the use of the tape
drives; a FORTRAN program for demonstrating the use of the tape
drives; and a C program which performs the actual writing of the data
to the tape device.
/*---------------------------- file ctape.c --------------------*/
#include
#define ERR -1
#define isize 128
#define jsize 512
void main(int argc, char *argv..)
int retval, element = 8, remainder, bytes;
int i, j;
char **tape_device.. = { "/dev/rmt0.1\0", "/dev/rmt1.1\0" };
double doubles.isize..jsize., bubbles.isize..jsize.;
bytes = isize * jsize * element;
for(i=0; i
#include
#include
#include
#include
#include
#define ERR -1
#define IBM7208 245760
#define IBM7207 32768
/* tape_write: write to a character special device in multiples
of n bytes. */
char *tape_write( char *device, char *mybuffer, int *nbytes)
int retval;
if((retval = do_tape_write( device, mybuffer, nbytes, IBM7208))
¢= ERR) return(retval);
if((retval = do_tape_write( device, mybuffer, nbytes, IBM7207))
¢= ERR) return(retval);
return(ERR);
/* tape_read: read to a character special device in multiples
of n bytes. */
char *tape_read( char *device, char *mybuffer, int *nbytes)
int retval;
if((retval = do_tape_read( device, mybuffer, nbytes, IBM7208)) ¢= ERR)
return(retval);
if((retval = do_tape_read( device, mybuffer, nbytes, IBM7207)) ¢= ERR)
return(retval);
return(ERR);
int do_tape_write( char *device,
char *mybuffer, int *nbytes, int tapesize)
int bytes_written, remainder, buffers;
int handle, i, retval, OLDTAPE;
char chdev_string.. = {"chdev -l xxxx -a block_size=0\0\0\0\0\0\0\0"};
char eof_string.. = {"tctl -f/dev/rmtx eof 1\0\0"};
struct devinfo myinfo;
for(i=0;i<4;i++)
chdev_string.9+i. = device.5+i.;
eof_string.15. = device.8.;
buffers = abs ( *nbytes/ tapesize);
remainder = *nbytes - ( buffers * tapesize );
if((handle =
open(device, O_RDWR|O_NONBLOCK|O_EXCL, _S_IFCHR )) == ERR) {
perror("\ntape_write: open failed "); return(ERR); }
if((retval = ioctl( handle, IOCINFO, &myinfo )) == ERR) {
perror("\ntape_write: ioinfo failed "); return(ERR); }
if (myinfo.devtype ¢= DD_SCTAPE) {
fprintf(stderr,"\ntape_write: wrong device type "); return(ERR); }
OLDTAPE = myinfo.un.scmt.blksize;
sprintf(&(chdev_string.28.)," d",OLDTAPE);
if((retval = close( handle)) == ERR) {
perror("\ntape_write: tape close failed "); return(ERR); }
if((retval = system( chdev_string )) == ERR) {
perror("\ntape_write: chdev failed "); return(ERR); }
fprintf(stderr,"\ntape_write: changed tape device buffer size to 0");
fprintf(stderr,"\ntape_write: writing d buffers of d bytes,
plus d bytes\n", buffers, tapesize, remainder);
if((handle =
open(device, O_RDWR|O_NONBLOCK|O_EXCL, _S_IFCHR )) == ERR) {
perror("\ntape_write: open failed "); return(ERR); }
for (i = 1; i < buffers+1; i++) {
bytes_written = write( handle, mybuffer, tapesize);
mybuffer += bytes_written;
fprintf(stderr,"tape_write: d buffers of d
bytes written\r",i,bytes_written,13);
if(bytes_written == ERR) {
perror("\ntape_write: write tape failed ");
if((retval = put_back( chdev_string, handle, OLDTAPE)) == ERR) {
fprintf(stderr,"\nbig trouble\n"); exit(ERR); }
return(bytes_written); } }
if(remainder > 0) {
bytes_written = write( handle, mybuffer, remainder);
fprintf(stderr,"tape_write: with a remainder of d
bytes written\n",bytes_written);
if(bytes_written == ERR) {
perror("\ntape_write: write tape failed ");
if((retval = put_back( chdev_string, handle, OLDTAPE)) == ERR) {
fprintf(stderr,"\nbig trouble\n"); exit(ERR); } } }
if((retval = close( handle)) == ERR) {
perror("\ntape_write: tape close failed "); return(ERR); }
if((retval = system( eof_string )) == ERR) {
perror("\ntape_write: eof failed "); return(ERR); }
if((retval = system( chdev_string )) == ERR) {
perror("\ntape_write: chdev failed "); return(ERR); }
fprintf(stderr,"\ntape_write: changed tape device
buffer size back to d\n", OLDTAPE);
return(bytes_written);
int do_tape_read( char *device,
char *mybuffer, int *nbytes, int tapesize)
int bytes_read, remainder, buffers;
int handle, i, retval, OLDTAPE;
char chdev_string.. = {"chdev -l xxxx -a block_size=0\0\0\0\0\0\0\0"};
char eof_string.. = {"tctl -f/dev/rmtx eof 1\0\0"};
struct devinfo myinfo;
for(i=0;i<4;i++)
chdev_string.9+i. = device.5+i.;
eof_string.15. = device.8.;
buffers = abs ( *nbytes/ tapesize);
remainder = *nbytes - ( buffers * tapesize );
if((handle =
open(device, O_RDWR|O_NONBLOCK|O_EXCL, _S_IFCHR )) == ERR) {
perror("\ntape_read: open failed "); return(ERR); }
if((retval = ioctl( handle, IOCINFO, &myinfo )) == ERR) {
fprintf(stderr,"\ntape_read: wrong device type "); return(ERR); }
OLDTAPE = myinfo.un.scmt.blksize;
sprintf(&(chdev_string.28.)," d",OLDTAPE);
if((retval = close( handle)) == ERR) {
perror("\ntape_read: tape close failed "); return(ERR); }
if((retval = system( chdev_string )) == ERR) {
perror("\ntape_read: chdev failed "); return(ERR); }
fprintf(stderr,"\ntape_read: changed tape device buffer size to 0");
fprintf(stderr,"\ntape_read: reading d buffers of d bytes,
plus d bytes\n", buffers, tapesize, remainder);
if((handle =
open(device, O_RDWR|O_NONBLOCK|O_EXCL, _S_IFCHR )) == ERR) {
perror("\ntape_read: open failed "); return(ERR); }
for (i = 1; i < buffers+1; i++) {
bytes_read = read( handle, mybuffer, tapesize);
mybuffer += bytes_read;
fprintf(stderr,"tape_read: d buffers of d
bytes read\r",i,bytes_read,13);
if(bytes_read == ERR) {
perror("\ntape_read: read tape failed ");
if((retval = put_back( chdev_string, handle, OLDTAPE)) == ERR) {
fprintf(stderr,"\nbig trouble\n"); exit(ERR); }
return(bytes_read); } }
if(remainder > 0) {
bytes_read = read( handle, mybuffer, remainder);
fprintf(stderr,"tape_read: with a remainder of d
bytes read\n",bytes_read);
if(bytes_read == ERR) {
perror("\ntape_read: read tape failed ");
if((retval = put_back( chdev_string, handle, OLDTAPE)) == ERR) {
fprintf(stderr,"\nbig trouble\n"); exit(ERR); } } }
if((retval = close( handle)) == ERR) {
perror("\ntape_read: tape close failed "); return(ERR); }
if((retval = system( chdev_string )) == ERR) {
perror("\ntape_read: chdev failed "); return(ERR); }
fprintf(stderr,"\ntape_read: changed tape device buffer
size back to d\n", OLDTAPE);
return(bytes_read);
int put_back(char *chdev_string, int handle, int OLDTAPE)
int retval;
if((retval = close( handle)) == ERR) {
perror("\nput_back: tape close failed "); return(ERR); }
if((retval = system( chdev_string )) == ERR) {
perror("\nput_back: chdev failed "); return(ERR); }
fprintf(stderr,"\nput_back: changed tape device
buffer size back to d\n", OLDTAPE);
return(retval);
C*---------------------------- file ftape.f --------------------*/
program ftape
parameter (isize=128)
parameter (jsize=512)
integer tape_write,tape_read ¢ c routines
external tape_write, tape_read ¢ again ...
integer retval ¢ results of calls to C
real*8 doubles(isize,jsize) ¢ array to write
real*8 bubbles(isize,jsize) ¢ array to read
integer element, remainder, bytes
character*12 tape_device(2)
data tape_device(1) /'/dev/rmt0.1'/ ¢ no rewind, retension
data tape_device(2) /'/dev/rmt1.1'/ ¢ no rewind, retension
tape_device(1)(12:12)=char(0) ¢ null terminate string
tape_device(2)(12:12)=char(0) ¢ null terminate string
element = 8
bytes = isize * jsize * element ¢ total bytes to write
do i = 1,isize
do j = 1,jsize
doubles(i,j) = i*j
end do
end do
bytes = isize * jsize * element ¢ total bytes to write
do i = 1,isize
do j = 1,jsize
doubles(i,j) = i*j
end do
end do
retval=tape_write(tape_device(1), doubles(1,1), bytes)
if(retval.eq.-1) stop
retval=tape_write(tape_device(2), doubles(1,1), bytes)
if(retval.eq.-1) stop
retval=tape_read(tape_device(1), bubbles(1,1), bytes)
if(retval.eq.-1) stop
do i = 1, isize
do j = 1, jsize
if(doubles(i,j).ne.bubbles(i,j)) then
end if
end do
end do
write(*,160)
retval=tape_read(tape_device(2), bubbles(1,1), bytes)
if(retval.eq.-1) stop
do i = 1, isize
do j = 1, jsize
if(doubles(i,j).ne.bubbles(i,j)) then
end if
end do
end do
write(*,160)
160 format('Arrays compare correctly.')
end
#*---------------------------- file makefile --------------------*/
CFLAGS = -O
FFLAGS = -O
all: ftape ctape
ftape: ftape.o glue.o
xlf $(FFLAGS) -o $@ ftape.o glue.o
ftape.o: ftape.f
xlf $(FFLAGS) -c ftape.f
ctape: ctape.o glue.o
cc $(CFLAGS) -o $@ ctape.o glue.o
ctape.o: ctape.c
cc $(CFLAGS) -c ctape.c -D_ALL_SOURCE
glue.o: glue.c
cc $(CFLAGS) -c glue.c -D_ALL_SOURCE
REFERENCES:
*****************************************************************
** If you have found this information to be informative and **
** useful, please let us know via a HONE FEEDBACK or via EQUAL.**
** Make sure in your evaluation to reference the appropriate **
** INFOSYS or FLASH number. **
*****************************************************************
---------- ---------- ---------- --------- ---------- ----------
This item was created from library item Q649413 CNMSJ
Additional search words:
CNMSJ EXAMPLE IX JAN94 OP OZIBM OZNEW PROG PROGRAM PROGRAMMABLE
PROGRAMMER PROGRAMMING READ RISCOSO RISCSYSTEM SAMPLE SOFTWARE SYS
TAPE WRITE
WWQA: ITEM: RTA000037086 ITEM: RTA000037086
Dated: 11/1996 Category: RISCOSO
This HTML file was generated 99/06/24~12:43:14
Comments or suggestions?
Contact us