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