1 /* DASDCAT.C (c) Copyright Roger Bowler, 1999-2012 */
2 /* DASD "cat" functions */
3
4 /*
5 * dasdcat
6 *
7 * Vast swathes copied from dasdpdsu.c (c) Copyright Roger Bowler, 1999-2009
8 * Changes and additions Copyright 2000-2009 by Malcolm Beattie
9 */
10
11 #include "hstdinc.h"
12
13 #include "hercules.h"
14 #include "dasdblks.h"
15 #ifdef WIN32
16 #include <io.h> // (setmode)
17 #endif
18
19 /* Option flags */
20 #define OPT_ASCIIFY 0x1
21 #define OPT_CARDS 0x2
22 #define OPT_PDS_WILDCARD 0x4
23 #define OPT_PDS_LISTONLY 0x8
24 #define OPT_SEQNO 0x10
25
end_of_track(BYTE * p)26 int end_of_track(BYTE *p)
27 {
28 return p[0] == 0xff && p[1] == 0xff && p[2] == 0xff && p[3] == 0xff
29 && p[4] == 0xff && p[5] == 0xff && p[6] == 0xff && p[7] == 0xff;
30 }
31
do_cat_cards(BYTE * buf,int len,unsigned long optflags)32 int do_cat_cards(BYTE *buf, int len, unsigned long optflags)
33 {
34 if (len % 80 != 0) {
35 fprintf(stderr,
36 _("HHCDT002E Can't make 80 column card images from block length %d\n"), len);
37 return -1;
38 }
39
40 while (len) {
41 char card[81];
42 make_asciiz(card, sizeof(card), buf, (optflags & OPT_SEQNO) ? 80 : 72);
43 if (optflags & OPT_PDS_WILDCARD) {
44 putchar('|');
45 putchar(' ');
46 }
47
48 puts(card);
49 len -= 80;
50 buf += 80;
51 }
52 return 0;
53 }
54
process_member(CIFBLK * cif,int noext,DSXTENT extent[],BYTE * ttr,unsigned long optflags)55 int process_member(CIFBLK *cif, int noext, DSXTENT extent[],
56 BYTE *ttr, unsigned long optflags)
57 {
58 int rc, trk, len, cyl, head, rec;
59 BYTE *buf;
60
61 set_codepage(NULL);
62
63 trk = (ttr[0] << 8) | ttr[1];
64 rec = ttr[2];
65
66 while (1) {
67 rc = convert_tt(trk, noext, extent, cif->heads, &cyl, &head);
68 if (rc < 0)
69 return -1;
70
71 rc = read_block(cif, cyl, head, rec, 0, 0, &buf, &len);
72 if (rc < 0)
73 return -1;
74
75 if (rc > 0) {
76 trk++;
77 rec = 1;
78 continue;
79 }
80
81 if (len == 0)
82 break;
83
84 if (optflags & OPT_CARDS)
85 do_cat_cards(buf, len, optflags);
86 else if (optflags & OPT_ASCIIFY) {
87 BYTE *p;
88 for (p = buf; len--; p++)
89 putchar(guest_to_host(*p));
90 } else {
91 #if O_BINARY != 0
92 setmode(fileno(stdout),O_BINARY);
93 #endif
94 fwrite(buf, len, 1, stdout);
95 }
96
97 rec++;
98 }
99 return 0;
100 }
101
process_dirblk(CIFBLK * cif,int noext,DSXTENT extent[],BYTE * dirblk,char * pdsmember,unsigned long optflags)102 int process_dirblk(CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk,
103 char *pdsmember, unsigned long optflags)
104 {
105 int rc;
106 int dirrem;
107 char memname[9];
108
109 /* Load number of bytes in directory block */
110 dirrem = (dirblk[0] << 8) | dirblk[1];
111 if (dirrem < 2 || dirrem > 256) {
112 fprintf(stderr, _("HHCDT003E Directory block byte count is invalid\n"));
113 return -1;
114 }
115
116 if (!strcmp(pdsmember, "*"))
117 optflags |= OPT_PDS_WILDCARD;
118 else if (!strcmp(pdsmember, "?"))
119 optflags |= OPT_PDS_LISTONLY;
120
121 /* Point to first directory entry */
122 dirblk += 2;
123 dirrem -= 2;
124
125 while (dirrem > 0) {
126 PDSDIR *dirent = (PDSDIR*)dirblk;
127 int k, size;
128
129 if (end_of_track(dirent->pds2name))
130 return 1;
131
132 make_asciiz(memname, sizeof(memname), dirent->pds2name, 8);
133
134 if (optflags & OPT_PDS_LISTONLY) {
135 char memname_lc[9];
136 memcpy(memname_lc, memname, sizeof(memname));
137 string_to_lower(memname_lc);
138 puts(memname_lc);
139 }
140 else if ((optflags & OPT_PDS_WILDCARD) || !strcmp(pdsmember, memname)) {
141 if (optflags & OPT_PDS_WILDCARD)
142 printf("> Member %s\n", memname);
143 rc = process_member(cif, noext, extent, dirent->pds2ttrp, optflags);
144 if (rc < 0)
145 return -1;
146 }
147
148 /* Load the user data halfword count */
149 k = dirent->pds2indc & PDS2INDC_LUSR;
150
151 /* Point to next directory entry */
152 size = 12 + k*2;
153 dirblk += size;
154 dirrem -= size;
155 }
156
157 return 0;
158 }
159
do_cat_pdsmember(CIFBLK * cif,DSXTENT * extent,int noext,char * pdsmember,unsigned long optflags)160 int do_cat_pdsmember(CIFBLK *cif, DSXTENT *extent, int noext,
161 char *pdsmember, unsigned long optflags)
162 {
163 int rc, trk, rec;
164
165 /* Point to the start of the directory */
166 trk = 0;
167 rec = 1;
168
169 /* Read the directory */
170 while (1) {
171 BYTE *blkptr;
172 BYTE dirblk[256];
173 int cyl, head, len;
174 #ifdef EXTERNALGUI
175 if (extgui) fprintf(stderr,"CTRK=%d\n",trk);
176 #endif /*EXTERNALGUI*/
177 rc = convert_tt(trk, noext, extent, cif->heads, &cyl, &head);
178 if (rc < 0)
179 return -1;
180
181 rc = read_block(cif, cyl, head, rec, 0, 0, &blkptr, &len);
182 if (rc < 0)
183 return -1;
184
185 if (rc > 0) {
186 trk++;
187 rec = 1;
188 continue;
189 }
190
191 if (len == 0)
192 break;
193
194 memcpy(dirblk, blkptr, sizeof(dirblk));
195
196 rc = process_dirblk(cif, noext, extent, dirblk, pdsmember, optflags);
197 if (rc < 0)
198 return -1;
199 if (rc > 0)
200 break;
201
202 rec++;
203 }
204 return rc;
205 }
206
do_cat_nonpds(CIFBLK * cif,DSXTENT * extent,int noext,unsigned long optflags)207 int do_cat_nonpds(CIFBLK *cif, DSXTENT *extent, int noext,
208 unsigned long optflags)
209 {
210 UNREFERENCED(cif);
211 UNREFERENCED(extent);
212 UNREFERENCED(noext);
213 UNREFERENCED(optflags);
214 fprintf(stderr, _("HHCDT004E non-PDS-members not yet supported\n"));
215 return -1;
216 }
217
do_cat(CIFBLK * cif,char * file)218 int do_cat(CIFBLK *cif, char *file)
219 {
220 int rc;
221 DSXTENT extent[16];
222 int noext;
223 char buff[100]; /* must fit max length DSNAME/MEMBER..OPTS */
224 char dsname[45];
225 unsigned long optflags = 0;
226 char *p;
227 char *pdsmember = 0;
228
229 if (!cif)
230 return 1;
231
232 strncpy(buff, file, sizeof(buff));
233 buff[sizeof(buff)-1] = 0;
234
235 p = strchr(buff, ':');
236 if (p) {
237 *p++ = 0;
238 for (; *p; p++) {
239 if (*p == 'a')
240 optflags |= OPT_ASCIIFY;
241 else if (*p == 'c')
242 optflags |= OPT_CARDS;
243 else if (*p == 's')
244 optflags |= OPT_SEQNO;
245 else
246 fprintf(stderr, _("HHCDT005E unknown dataset name option: '%c'\n"), *p);
247 }
248 }
249
250 p = strchr(buff, '/');
251 if (p) {
252 *p = 0;
253 pdsmember = p + 1;
254 string_to_upper(pdsmember);
255 }
256
257 strncpy(dsname, buff, sizeof(dsname));
258 dsname[sizeof(dsname)-1] = 0;
259 string_to_upper(dsname);
260
261 rc = build_extent_array(cif, dsname, extent, &noext);
262 if (rc < 0)
263 return -1;
264
265 #ifdef EXTERNALGUI
266 /* Calculate ending relative track */
267 if (extgui) {
268 int bcyl; /* Extent begin cylinder */
269 int btrk; /* Extent begin head */
270 int ecyl; /* Extent end cylinder */
271 int etrk; /* Extent end head */
272 int trks; /* total tracks in dataset */
273 int i; /* loop control */
274 for (i = 0, trks = 0; i < noext; i++) {
275 bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1];
276 btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1];
277 ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1];
278 etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1];
279 trks += (((ecyl*cif->heads)+etrk)-((bcyl*cif->heads)+btrk))+1;
280 }
281 fprintf(stderr,"ETRK=%d\n",trks-1);
282 }
283 #endif /*EXTERNALGUI*/
284
285 if (pdsmember)
286 rc = do_cat_pdsmember(cif, extent, noext, pdsmember, optflags);
287 else
288 rc = do_cat_nonpds(cif, extent, noext, optflags);
289
290 return rc;
291 }
292
main(int argc,char ** argv)293 int main(int argc, char **argv)
294 {
295 int rc = 0;
296 CIFBLK *cif = 0;
297 char *fn, *sfn;
298
299 INITIALIZE_UTILITY("dasdcat");
300
301 /* Display program info message */
302 display_version (stderr, "Hercules DASD cat program ", FALSE);
303
304 if (argc < 2) {
305 fprintf(stderr, "Usage: dasdcat [-i dasd_image [sf=shadow-file-name] dsname...]...\n");
306 fprintf(stderr, " dsname can (currently must) be pdsname/spec\n");
307 fprintf(stderr, " spec is memname[:flags], * (all) or ? (list)\n");
308 fprintf(stderr, " flags can include (c)ard images, (a)scii\n");
309 exit(2);
310 }
311
312 /*
313 * If your version of Hercules doesn't have support in its
314 * dasdutil.c for turning off verbose messages, then remove
315 * the following line but you'll have to live with chatty
316 * progress output on stdout.
317 */
318 set_verbose_util(0);
319
320 while (*++argv)
321 {
322 if (!strcmp(*argv, "-i"))
323 {
324 fn = *++argv;
325 if (*(argv+1) && strlen (*(argv+1)) > 3 && !memcmp(*(argv+1), "sf=", 3))
326 sfn = *++argv;
327 else sfn = NULL;
328 if (cif)
329 {
330 close_ckd_image(cif);
331 cif = 0;
332 }
333 cif = open_ckd_image(fn, sfn, O_RDONLY | O_BINARY, 0);
334 if (!cif)
335 fprintf(stderr, _("HHCDT001E failed to open image %s\n"), *argv);
336 }
337 else
338 {
339 if (do_cat(cif, *argv))
340 rc = 1;
341 }
342 }
343
344 if (cif)
345 close_ckd_image(cif);
346
347 return rc;
348 }
349