1 /* HETMAP.C     (c) Copyright Leland Lucius, 2000-2009               */
2 /*              Displays information about a Hercules Emulated Tape  */
3 
4 /*
5 || ----------------------------------------------------------------------------
6 ||
7 || HETMAP.C     (c) Copyright Leland Lucius, 2000-2009
8 ||              Released under terms of the Q Public License.
9 ||
10 || Displays information about the structure of a Hercules Emulated Tape.
11 ||
12 || ----------------------------------------------------------------------------
13 */
14 
15 #include "hstdinc.h"
16 
17 #include "hercules.h"
18 #include "hetlib.h"
19 #include "sllib.h"
20 #include "herc_getopt.h"
21 
22 /*
23 || Local constant data
24 */
25 static const char sep[] = "---------------------\n";
26 static const char help_hetmap[] =
27     "%s - Print a map of an HET or AWS tape file\n\n"
28     "Usage: %s [options] filename\n\n"
29     "Options:\n"
30     "  -a  print all label and file information (default: on)\n"
31     "  -d  print only dataset information (default: off)\n"
32     "  -f  print only file information (default: off)\n"
33     "  -h  display usage summary\n"
34     "  -l  print only label information (default: off)\n"
35     "  -t  print TAPEMAP-compatible format output (default: off)\n";
36 static const char help_tapemap[] =
37     "%s - Print a map of an HET or AWS tape file\n\n"
38     "Usage: %s filename\n\n";
39 
40 #ifdef EXTERNALGUI
41 /* Previous reported file position */
42 static off_t prevpos = 0;
43 /* Report progress every this many bytes */
44 #define PROGRESS_MASK (~0x3FFFF /* 256K */)
45 #endif /*EXTERNALGUI*/
46 
47 /*
48 || Print terse dataset information (from VOL1/EOF1/EOF2)
49 */
50 void
printdataset(char * buf,int len,int fileno)51 printdataset( char *buf, int len, int fileno )
52 {
53     SLLABEL lab;
54     SLFMT fmt;
55     char crtdt[ 9 ];
56     char expdt[ 9 ];
57     char recfm[ 4 ];
58 
59     if( sl_islabel( &lab, buf, len ) == FALSE )
60     {
61         return;
62     }
63 
64     sl_fmtlab( &fmt, &lab );
65 
66     if( sl_isvol( buf, 1 ) )
67     {
68         printf( "vol=%-17.17s  owner=%s\n\n",
69                 fmt.slvol.volser,
70                 fmt.slvol.owner);
71     }
72     else if( sl_iseof( buf, 1 ) )
73     {
74         printf( "seq=%-17d  file#=%d\n",
75                 atoi( fmt.slds1.dsseq ),
76                 fileno );
77         printf( "dsn=%-17.17s  crtdt=%-8.8s  expdt=%-8.8s  blocks=%d\n",
78                 fmt.slds1.dsid,
79                 sl_fmtdate( crtdt, fmt.slds1.crtdt, TRUE ),
80                 sl_fmtdate( expdt, fmt.slds1.expdt, TRUE ),
81                 atoi( fmt.slds1.blkhi ) * 1000000 + atoi( fmt.slds1.blklo ) );
82     }
83     else if( sl_iseof( buf, 2 ) )
84     {
85         recfm[ 0 ] = '\0';
86         strcat( strcat( strcat( recfm,
87                                 fmt.slds2.recfm ),
88                         fmt.slds2.blkattr ),
89                 fmt.slds2.ctrl );
90         printf( "job=%17.17s  recfm=%-3.3s       lrecl=%-5d     blksize=%-5d\n\n",
91                 fmt.slds2.jobid,
92                 recfm,
93                 atoi( fmt.slds2.lrecl ),
94                 atoi( fmt.slds2.blksize ) );
95     }
96 
97     return;
98 }
99 
100 /*
101 || Print all label fields
102 */
103 void
printlabel(char * buf,int len)104 printlabel( char *buf, int len )
105 {
106     SLLABEL lab;
107     SLFMT fmt;
108     int i;
109 
110     if( sl_islabel( &lab, buf, len ) == FALSE )
111     {
112         return;
113     }
114 
115     sl_fmtlab( &fmt, &lab );
116 
117     printf( sep );
118 
119     for( i = 0; fmt.key[ i ] != NULL; i++ )
120     {
121         printf("%-20.20s: '%s'\n", fmt.key[ i ] , fmt.val[ i ] );
122     }
123 
124     return;
125 }
126 
127 /*
128 || Print label fields in TAPEMAP format
129  */
130 void
printlabeltapemap(char * buf,int len)131 printlabeltapemap( char *buf, int len )
132 {
133     SLLABEL lab;
134     BYTE labelrec[81];
135     int i;
136 
137     if( sl_islabel( &lab, buf, len ) == FALSE )
138     {
139         return;
140     }
141     for (i=0; i < 80; i++)
142     {
143         labelrec[i] = guest_to_host(buf[i]);
144     }
145     labelrec[i] = '\0';
146     printf("%s\n", labelrec);
147 }
148 
149 /*
150 || Prints usage information
151 */
152 void
usage(char * name)153 usage( char *name )
154 {
155     if  ((strcmp(name, "tapemap") == 0) || (strcmp(name, "TAPEMAP") == 0))
156     {
157         printf( help_tapemap, name, name );
158     }
159     else
160     {
161         printf( help_hetmap, name, name );
162     }
163 }
164 
165 /*
166 || Standard main
167 */
168 int
main(int argc,char * argv[])169 main( int argc, char *argv[] )
170 {
171     char buf[ HETMAX_BLOCKSIZE ];
172     HETB *hetb;
173     int rc;
174     int fileno;
175     U32  blocks;
176     U32  uminsz;
177     U32  umaxsz;
178     U32  ubytes;
179     U32  cminsz;
180     U32  cmaxsz;
181     U32  cbytes;
182     U32  totblocks;
183     U32  totubytes;
184     U32  totcbytes;
185     U32  opts = 0;
186     char pgmpath[MAX_PATH];
187     char *pgm;
188 
189 #define O_ALL           0xC0
190 #define O_FILES         0X80
191 #define O_LABELS        0X40
192 #define O_DATASETS      0X20
193 #define O_TAPEMAP_OUTPUT  0x10
194 #define O_TAPEMAP_INVOKED 0x08
195 
196     /* Figure out processing based on the program name */
197     hostpath(pgmpath, argv[0], sizeof(pgmpath));
198     pgm = strrchr(pgmpath, '/');
199     if (pgm)
200     {
201         pgm++;
202     }
203     else
204     {
205         pgm = argv[0];
206     }
207     strtok (pgm, ".");
208     if  ((strcmp(pgm, "tapemap") == 0) || (strcmp(pgm, "TAPEMAP") == 0))
209     {
210         opts = O_TAPEMAP_OUTPUT+O_TAPEMAP_INVOKED;
211     }
212 
213     INITIALIZE_UTILITY(pgm);
214 
215     /* Display the program identification message */
216     display_version (stderr, "Hercules HET and AWS tape map program ", FALSE);
217 
218     if (! (opts & O_TAPEMAP_INVOKED) )
219     {
220 
221         opts = O_ALL;
222 
223         while( TRUE )
224         {
225             rc = getopt( argc, argv, "adfhlt" );
226             if( rc == -1 )
227             {
228                 break;
229             }
230 
231             switch( rc )
232             {
233                 case 'a':
234                     opts = O_ALL;
235                 break;
236 
237                 case 'd':
238                     opts = O_DATASETS;
239                 break;
240 
241                 case 'f':
242                     opts = O_FILES;
243                 break;
244 
245                 case 'h':
246                     usage( pgm );
247                     exit( 1 );
248                 break;
249 
250                 case 'l':
251                     opts = O_LABELS;
252                 break;
253 
254                 case 't':
255                     opts = O_TAPEMAP_OUTPUT;
256                 break;
257 
258                 default:
259                     usage( pgm );
260                     exit( 1 );
261                 break;
262             }
263         }
264 
265     }  // end if (! (opts & O_TAPEMAP_INVOKED) )
266 
267     argc -= optind;
268     if( argc != 1 )
269     {
270         usage( pgm );
271         exit( 1 );
272     }
273 
274     if( opts & O_ALL )
275     {
276         printf( sep );
277         printf( "%-20.20s: %s\n", "Filename", argv[ optind ] );
278     }
279 
280     rc = het_open( &hetb, argv[ optind ], 0 );
281     if( rc < 0 )
282     {
283         printf( "het_open() returned %d\n", rc );
284         het_close( &hetb );
285         exit( 1 );
286     }
287 
288     fileno = 0;
289     blocks = 0;
290 
291     uminsz = 0;
292     umaxsz = 0;
293     ubytes = 0;
294     cminsz = 0;
295     cmaxsz = 0;
296     cbytes = 0;
297 
298     totblocks = 0;
299     totubytes = 0;
300     totcbytes = 0;
301 
302     while( TRUE )
303     {
304 #ifdef EXTERNALGUI
305         if( extgui )
306         {
307             /* Report progress every nnnK */
308             off_t curpos = ftell( hetb->fd );
309             if( ( curpos & PROGRESS_MASK ) != ( prevpos & PROGRESS_MASK ) )
310             {
311                 prevpos = curpos;
312                 fprintf( stderr, "IPOS=%" I64_FMT "d\n", (U64)curpos );
313             }
314         }
315 #endif /*EXTERNALGUI*/
316 
317         rc = het_read( hetb, buf );
318         if( rc == HETE_EOT )
319         {
320             if( opts & O_TAPEMAP_OUTPUT )
321             {
322                 printf ("End of tape.\n");
323             }
324             break;
325         }
326 
327         if( rc == HETE_TAPEMARK )
328         {
329             fileno += 1;
330 
331             if( opts & O_TAPEMAP_OUTPUT )
332             {
333                 printf ("File %u: Blocks=%u, block size min=%u, max=%u\n",
334                         fileno, blocks, uminsz, umaxsz      );
335             }
336 
337             if( opts & O_FILES )
338             {
339                 printf( sep );
340                 printf( "%-20.20s: %d\n", "File #", fileno );
341                 printf( "%-20.20s: %d\n", "Blocks", blocks );
342                 printf( "%-20.20s: %d\n", "Min Blocksize", uminsz );
343                 printf( "%-20.20s: %d\n", "Max Blocksize", umaxsz );
344                 printf( "%-20.20s: %d\n", "Uncompressed bytes", ubytes );
345                 printf( "%-20.20s: %d\n", "Min Blocksize-Comp", cminsz );
346                 printf( "%-20.20s: %d\n", "Max Blocksize-Comp", cmaxsz );
347                 printf( "%-20.20s: %d\n", "Compressed bytes", cbytes );
348             }
349 
350             totblocks += blocks;
351             totubytes += ubytes;
352             totcbytes += cbytes;
353 
354             blocks = 0;
355 
356             uminsz = 0;
357             umaxsz = 0;
358             ubytes = 0;
359             cminsz = 0;
360             cmaxsz = 0;
361             cbytes = 0;
362 
363             continue;
364         }
365 
366         if( rc < 0 )
367         {
368             printf( "het_read() returned %d\n", rc );
369             break;
370         }
371 
372         blocks += 1;
373         ubytes += hetb->ublksize;
374         cbytes += hetb->cblksize;
375 
376         if( uminsz == 0 || hetb->ublksize < uminsz ) uminsz = hetb->ublksize;
377         if( hetb->ublksize > umaxsz ) umaxsz = hetb->ublksize;
378         if( cminsz == 0 || hetb->cblksize < cminsz ) cminsz = hetb->cblksize;
379         if( hetb->cblksize > cmaxsz ) cmaxsz = hetb->cblksize;
380 
381         if( opts & O_LABELS )
382         {
383             printlabel( buf, rc );
384         }
385 
386         if( opts & O_TAPEMAP_OUTPUT )
387         {
388             printlabeltapemap( buf, rc );
389         }
390 
391         if( opts & O_DATASETS )
392         {
393             printdataset( buf, rc, fileno );
394         }
395     }
396 
397     if( opts & O_FILES )
398     {
399         printf( sep );
400         printf( "%-20.20s:\n", "Summary" );
401         printf( "%-20.20s: %d\n", "Files", fileno );
402         printf( "%-20.20s: %d\n", "Blocks", totblocks );
403         printf( "%-20.20s: %d\n", "Uncompressed bytes", totubytes );
404         printf( "%-20.20s: %d\n", "Compressed bytes", totcbytes );
405         printf( "%-20.20s: %d\n", "Reduction", totubytes - totcbytes );
406     }
407 
408     het_close( &hetb );
409 
410     return 0;
411 }
412