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