1 /* TAPEMAP.C    (c) Copyright Jay Maynard, 2000-2009                 */
2 /*              Map AWSTAPE format tape image                        */
3 
4 /*-------------------------------------------------------------------*/
5 /* This program reads an AWSTAPE format tape image file and produces */
6 /* a map of the tape, printing any standard label records it finds.  */
7 /*-------------------------------------------------------------------*/
8 
9 #include "hstdinc.h"
10 
11 #include "hercules.h"
12 
13 /*-------------------------------------------------------------------*/
14 /* Structure definition for AWSTAPE block header                     */
15 /*-------------------------------------------------------------------*/
16 typedef struct _AWSTAPE_BLKHDR {
17         HWORD   curblkl;                /* Length of this block      */
18         HWORD   prvblkl;                /* Length of previous block  */
19         BYTE    flags1;                 /* Flags byte 1              */
20         BYTE    flags2;                 /* Flags byte 2              */
21     } AWSTAPE_BLKHDR;
22 
23 /* Definitions for AWSTAPE_BLKHDR flags byte 1 */
24 #define AWSTAPE_FLAG1_NEWREC    0x80    /* Start of new record       */
25 #define AWSTAPE_FLAG1_TAPEMARK  0x40    /* Tape mark                 */
26 #define AWSTAPE_FLAG1_ENDREC    0x20    /* End of record             */
27 
28 /*-------------------------------------------------------------------*/
29 /* Static data areas                                                 */
30 /*-------------------------------------------------------------------*/
31 static BYTE vollbl[] = "\xE5\xD6\xD3";  /* EBCDIC characters "VOL"   */
32 static BYTE hdrlbl[] = "\xC8\xC4\xD9";  /* EBCDIC characters "HDR"   */
33 static BYTE eoflbl[] = "\xC5\xD6\xC6";  /* EBCDIC characters "EOF"   */
34 static BYTE eovlbl[] = "\xC5\xD6\xE5";  /* EBCDIC characters "EOV"   */
35 static BYTE buf[65536];
36 
37 #ifdef EXTERNALGUI
38 /* Report progress every this many bytes */
39 #define PROGRESS_MASK (~0x3FFFF /* 256K */)
40 /* How many bytes we've read so far. */
41 long  curpos = 0;
42 long  prevpos = 0;
43 #endif /*EXTERNALGUI*/
44 
45 /*-------------------------------------------------------------------*/
46 /* TAPEMAP main entry point                                          */
47 /*-------------------------------------------------------------------*/
main(int argc,char * argv[])48 int main (int argc, char *argv[])
49 {
50 int             i;                      /* Array subscript           */
51 int             len;                    /* Block length              */
52 int             prevlen;                /* Previous block length     */
53 char           *filename;               /* -> Input file name        */
54 int             infd = -1;              /* Input file descriptor     */
55 int             fileno;                 /* Tape file number          */
56 int             blkcount;               /* Block count               */
57 int             curblkl;                /* Current block length      */
58 int             minblksz;               /* Minimum block size        */
59 int             maxblksz;               /* Maximum block size        */
60 BYTE            labelrec[81];           /* Standard label (ASCIIZ)   */
61 AWSTAPE_BLKHDR  awshdr;                 /* AWSTAPE block header      */
62 char            pathname[MAX_PATH];     /* file path in host format  */
63 
64     INITIALIZE_UTILITY("tapemap");
65 
66     /* Display the program identification message */
67     display_version (stderr, "Hercules tape map program ", FALSE);
68 
69     /* The only argument is the tape image file name */
70     if (argc == 2 && argv[1] != NULL)
71     {
72         filename = argv[1];
73     }
74     else
75     {
76         printf ("Usage: tapemap filename\n");
77         exit (1);
78     }
79 
80     /* Open the tape device */
81     hostpath(pathname, filename, sizeof(pathname));
82     infd = hopen(pathname, O_RDONLY | O_BINARY);
83     if (infd < 0)
84     {
85         printf ("tapemap: Error opening %s: %s\n",
86                 filename, strerror(errno));
87         exit (2);
88     }
89 
90     /* Read blocks from the input file and report on them */
91     fileno = 1;
92     blkcount = 0;
93     minblksz = 0;
94     maxblksz = 0;
95     len = 0;
96 
97     while (1)
98     {
99 #ifdef EXTERNALGUI
100         if (extgui)
101         {
102             /* Report progress every nnnK */
103             if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) )
104             {
105                 prevpos = curpos;
106                 fprintf( stderr, "IPOS=%ld\n", curpos );
107             }
108         }
109 #endif /*EXTERNALGUI*/
110         /* Save previous block length */
111         prevlen = len;
112 
113         /* Read a block from the tape */
114         len = read (infd, buf, sizeof(AWSTAPE_BLKHDR));
115 #ifdef EXTERNALGUI
116         if (extgui) curpos += len;
117 #endif /*EXTERNALGUI*/
118         if (len < 0)
119         {
120             printf ("tapemap: error reading header block from %s: %s\n",
121                     filename, strerror(errno));
122             exit (3);
123         }
124 
125         /* Did we finish too soon? */
126         if ((len > 0) && (len < (int)sizeof(AWSTAPE_BLKHDR)))
127         {
128             printf ("tapemap: incomplete block header on %s\n",
129                     filename);
130             exit(4);
131         }
132 
133         /* Check for end of tape. */
134         if (len == 0)
135         {
136             printf ("End of tape.\n");
137             break;
138         }
139 
140         /* Parse the block header */
141         memcpy(&awshdr, buf, sizeof(AWSTAPE_BLKHDR));
142 
143         /* Tapemark? */
144         if ((awshdr.flags1 & AWSTAPE_FLAG1_TAPEMARK) != 0)
145         {
146             /* Print summary of current file */
147             printf ("File %u: Blocks=%u, block size min=%u, max=%u\n",
148                     fileno, blkcount, minblksz, maxblksz);
149 
150             /* Reset counters for next file */
151             fileno++;
152             minblksz = 0;
153             maxblksz = 0;
154             blkcount = 0;
155 
156         }
157         else /* if(tapemark) */
158         {
159             /* Count blocks and block sizes */
160             blkcount++;
161             curblkl = awshdr.curblkl[0] + (awshdr.curblkl[1] << 8);
162             if (curblkl > maxblksz) maxblksz = curblkl;
163             if (minblksz == 0 || curblkl < minblksz) minblksz = curblkl;
164 
165             /* Read the data block. */
166             len = read (infd, buf, curblkl);
167 #ifdef EXTERNALGUI
168             if (extgui) curpos += len;
169 #endif /*EXTERNALGUI*/
170             if (len < 0)
171             {
172                 printf ("tapemap: error reading data block from %s: %s\n",
173                         filename, strerror(errno));
174                 exit (5);
175             }
176 
177             /* Did we finish too soon? */
178             if ((len > 0) && (len < curblkl))
179             {
180                 printf ("tapemap: incomplete final data block on %s, "
181                         "expected %d bytes, got %d\n",
182                         filename, curblkl, len);
183                 exit(6);
184             }
185 
186             /* Check for end of tape */
187             if (len == 0)
188             {
189                 printf ("tapemap: header block with no data on %s\n",
190                         filename);
191                 exit(7);
192             }
193 
194             /* Print standard labels */
195             if (len == 80 && blkcount < 4
196                 && (memcmp(buf, vollbl, 3) == 0
197                     || memcmp(buf, hdrlbl, 3) == 0
198                     || memcmp(buf, eoflbl, 3) == 0
199                     || memcmp(buf, eovlbl, 3) == 0))
200             {
201                 for (i=0; i < 80; i++)
202                     labelrec[i] = guest_to_host(buf[i]);
203                 labelrec[i] = '\0';
204                 printf ("%s\n", labelrec);
205             }
206 
207         } /* end if(tapemark) */
208 
209     } /* end while */
210 
211     /* Close files and exit */
212     close (infd);
213 
214     return 0;
215 
216 } /* end function main */
217