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