int do_cat_cards(BYTE *buf, int len, unsigned long optflags) { if (len % 80 != 0) { // "Can't make 80 column card images from block length %d" FWRMSG( stderr, HHC02404, "E", len ); return -1; } while (len) { char card[81]; int srclen = (optflags & OPT_SEQNO) ? 80 : 72; make_asciiz(card, sizeof(card), buf, srclen); if (optflags & OPT_PDS_WILDCARD) { putchar('|'); putchar(' '); } puts(card); len -= 80; buf += 80; } return 0; }
int do_ls_cif(CIFBLK *cif) { int rc; U32 cyl; U8 head, rec; U16 rlen; U8 klen; unsigned char *vol1data; FORMAT4_DSCB *f4dscb; char volser[7]; rc = read_block(cif, 0, 0, 3, 0, 0, &vol1data, &rlen); if (rc < 0) return -1; if (rc > 0) { fprintf( stderr, MSG( HHC02471, "E", "VOL1" ) ); return -1; } make_asciiz(volser, sizeof(volser), vol1data+4, 6); cyl = (vol1data[11] << 8) | vol1data[12]; head = (vol1data[13] << 8) | vol1data[14]; rec = vol1data[15]; rc = read_block(cif, cyl, head, rec, (void *)&f4dscb, &klen, 0, 0); if (rc < 0) return -1; if (rc > 0) { fprintf( stderr, MSG( HHC02471, "E", "Format 4 DSCB" ) ); return -1; } return list_contents(cif, volser, &f4dscb->ds4vtoce); }
int do_ls_cif(CIFBLK *cif) { int rc, cyl, head, rec, len; unsigned char *vol1data; FORMAT4_DSCB *f4dscb; char volser[7]; rc = read_block(cif, 0, 0, 3, 0, 0, &vol1data, &len); if (rc < 0) return -1; if (rc > 0) { fprintf(stderr, "VOL1 record not found\n"); return -1; } make_asciiz(volser, sizeof(volser), vol1data+4, 6); cyl = (vol1data[11] << 8) | vol1data[12]; head = (vol1data[13] << 8) | vol1data[14]; rec = vol1data[15]; rc = read_block(cif, cyl, head, rec, (void *)&f4dscb, &len, 0, 0); if (rc < 0) return -1; if (rc > 0) { fprintf(stderr, "F4DSCB record not found\n"); return -1; } return list_contents(cif, volser, &f4dscb->ds4vtoce); }
int list_contents(CIFBLK *cif, char *volser, DSXTENT *extent) { u_int cext = 0; u_int ccyl = (extent[cext].xtbcyl[0] << 8) | extent[cext].xtbcyl[1]; u_int chead = (extent[cext].xtbtrk[0] << 8) | extent[cext].xtbtrk[1]; u_int ecyl = (extent[cext].xtecyl[0] << 8) | extent[cext].xtecyl[1]; u_int ehead = (extent[cext].xtetrk[0] << 8) | extent[cext].xtetrk[1]; #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"ETRK=%d\n",((ecyl*(cif->heads))+ehead)); #endif /*EXTERNALGUI*/ printf("%s%s: VOLSER=%s\n", needsep ? "\n" : "", cif->fname, volser); needsep = 1; do { BYTE *ptr; int rc = read_track(cif, ccyl, chead); #ifdef EXTERNALGUI if (extgui) fprintf(stderr,"CTRK=%d\n",((ccyl*(cif->heads))+chead)); #endif /*EXTERNALGUI*/ if (rc < 0) return -1; ptr = cif->trkbuf + CKDDASD_TRKHDR_SIZE; while (!end_of_track(ptr)) { char dsname[45]; CKDDASD_RECHDR *rechdr = (CKDDASD_RECHDR*)ptr; int kl = rechdr->klen; int dl = (rechdr->dlen[0] << 8) | rechdr->dlen[1]; make_asciiz(dsname, sizeof(dsname), ptr + CKDDASD_RECHDR_SIZE, kl); dsname[44] = '\0'; if ( valid_dsname( dsname ) ) printf("%s\n", dsname); ptr += CKDDASD_RECHDR_SIZE + kl + dl; } chead++; if (chead >= cif->heads) { ccyl++; chead = 0; } } while (ccyl < ecyl || (ccyl == ecyl && chead <= ehead)); return 0; }
/*-------------------------------------------------------------------*/ static int process_dirblk (CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk) { int rc; /* Return code */ int size; /* Size of directory entry */ int k; /* Userdata halfword count */ BYTE *dirptr; /* -> Next byte within block */ int dirrem; /* Number of bytes remaining */ PDSDIR *dirent; /* -> Directory entry */ char memname[9]; /* Member name (ASCIIZ) */ /* Load number of bytes in directory block */ dirptr = dirblk; dirrem = (dirptr[0] << 8) | dirptr[1]; if (dirrem < 2 || dirrem > 256) { FWRMSG( stderr, HHC02400, "E" ); return -1; } /* Point to first directory entry */ dirptr += 2; dirrem -= 2; /* Process each directory entry */ while (dirrem > 0) { /* Point to next directory entry */ dirent = (PDSDIR*)dirptr; /* Test for end of directory */ if (memcmp(dirent->pds2name, eighthexFF, 8) == 0) return +1; /* Extract the member name */ make_asciiz (memname, sizeof(memname), dirent->pds2name, 8); /* Process the member */ rc = process_member (cif, noext, extent, memname, dirent->pds2ttrp); if (rc < 0) return -1; /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirptr += size; dirrem -= size; } return 0; } /* end function process_dirblk */
int get_volser( CIFBLK *cif ) { unsigned char *vol1data; int rc; U16 rlen; rc = read_block( cif, 0, 0, 3, 0, 0, &vol1data, &rlen ); if (rc < 0) return -1; if (rc > 0) { // "%s record not found" FWRMSG( stderr, HHC02471, "E", "VOL1" ); return -1; } make_asciiz( volser, sizeof(volser), vol1data+4, 6 ); return 0; }
void showf1( FILE *fmsg, FORMAT1_DSCB *f1dscb, DSXTENT extent[], int verbose) { int i, dsorg, lrecl, blksize, volseq, x, y, num_extents; char volser[sizeof(f1dscb->ds1dssn) + 1]; char dsn[sizeof(f1dscb->ds1dsnam) + 1]; char txtcredt[9]; // creation date char txtexpdt[9] = "(n/a)"; // expiration date char txtscr[20]; char txtsyscd[14]; char txtdsorg[5] = ""; // dsorg text char txtrecfm[5] = ""; // recfm text if (verbose > 2) { fprintf(fmsg, "showf1 F1 DSCB\n"); data_dump(f1dscb, sizeof(FORMAT1_DSCB)); } make_asciiz(dsn, sizeof(dsn), f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam)); make_asciiz(volser, sizeof(volser), f1dscb->ds1dssn, sizeof(f1dscb->ds1dssn)); volseq = (f1dscb->ds1volsq[0] << 8) | (f1dscb->ds1volsq[1]); x = f1dscb->ds1credt[0] + 1900; y = (f1dscb->ds1credt[1] << 8) | f1dscb->ds1credt[2]; sprintf(txtcredt, "%4.4d", x); strcat(txtcredt, "."); sprintf(txtscr, "%3.3d", y); strcat(txtcredt, txtscr); if (f1dscb->ds1expdt[0] || f1dscb->ds1expdt[1] || f1dscb->ds1expdt[2]) { x = f1dscb->ds1expdt[0] + 1900; y = (f1dscb->ds1expdt[1] << 8) | f1dscb->ds1expdt[2]; sprintf(txtexpdt, "%4.4d", x); strcat(txtexpdt, "."); sprintf(txtscr, ".%3.3d", y); strcat(txtexpdt, txtscr); } num_extents = f1dscb->ds1noepv; // Field ignored: ds1nobdb (# bytes used in last PDS dir blk) make_asciiz(txtsyscd, sizeof(txtsyscd), f1dscb->ds1syscd, sizeof(f1dscb->ds1syscd)); dsorg = (f1dscb->ds1dsorg[0] << 8) | (f1dscb->ds1dsorg[1]); if (dsorg & (DSORG_IS * 256)) strcpy(txtdsorg, "IS"); if (dsorg & (DSORG_PS * 256)) strcpy(txtdsorg, "PS"); if (dsorg & (DSORG_DA * 256)) strcpy(txtdsorg, "DA"); if (dsorg & (DSORG_PO * 256)) strcpy(txtdsorg, "PO"); if (dsorg & DSORG_AM) strcpy(txtdsorg, "VS"); if (txtdsorg[0] == '\0') strcpy(txtdsorg, "??"); if (dsorg & (DSORG_U * 256)) strcat(txtdsorg, "U"); if (f1dscb->ds1recfm & RECFM_FORMAT_F) strcpy(txtrecfm, "F"); if (f1dscb->ds1recfm & RECFM_FORMAT_V) strcpy(txtrecfm, "V"); if ((f1dscb->ds1recfm & RECFM_FORMAT_U) == RECFM_FORMAT_U) strcpy(txtrecfm, "U"); if (f1dscb->ds1recfm & RECFM_BLOCKED) strcat(txtrecfm, "B"); if (f1dscb->ds1recfm & RECFM_SPANNED) strcat(txtrecfm, "S"); if (f1dscb->ds1recfm & RECFM_CTLCHAR_A) strcat(txtrecfm, "A"); if (f1dscb->ds1recfm & RECFM_CTLCHAR_M) strcat(txtrecfm, "M"); if (f1dscb->ds1recfm & RECFM_TRKOFLOW) strcat(txtrecfm, "T"); // Field ignored: ds1optcd (option codes, same as in DCB) blksize = (f1dscb->ds1blkl[0] << 8) | f1dscb->ds1blkl[1]; lrecl = (f1dscb->ds1lrecl[0] << 8) | f1dscb->ds1lrecl[1]; // Field ignored: ds1keyl (key length) // Field ignored: ds1rkp (relative key position) // Field ignored: ds1dsind (data set indicators) // Field ignored: ds1scalo (secondary allocation) // Field ignored: ds1lstar (pointer to last written block; ttr) // Field ignored: ds1trbal (bytes remaining on last track used) // Extent information was passed to us, so we ignore what's in F1DSCB fprintf(fmsg, "Dataset %s on volume %s sequence %d\n", dsn, volser, volseq); fprintf(fmsg, "Created %s expires %s\n", txtcredt, txtexpdt); fprintf(fmsg, "Dsorg=%s recfm=%s lrecl=%d blksize=%d\n", txtdsorg, txtrecfm, lrecl, blksize); fprintf(fmsg, "System code %s\n", txtsyscd); if (verbose > 1) { fprintf(stderr, "Dataset has %d extent(s)\n", num_extents); if (verbose > 2) data_dump((void *)extent, sizeof(extent) * MAX_EXTENTS); fprintf(stderr, "Extent Information:\n"); fprintf(stderr, " EXTENT --begin-- ---end---\n"); fprintf(stderr, "TYPE NUMBER CCCC HHHH CCCC HHHH\n"); for (i = 0; i < num_extents; i++) { int bcyl = (extent[i].xtbcyl[0] << 8) | extent[i].xtbcyl[1]; int btrk = (extent[i].xtbtrk[0] << 8) | extent[i].xtbtrk[1]; int ecyl = (extent[i].xtecyl[0] << 8) | extent[i].xtecyl[1]; int etrk = (extent[i].xtetrk[0] << 8) | extent[i].xtetrk[1]; fprintf(stderr, " %2.2X %2.2X %4.4X %4.4X %4.4X %4.4X\n", extent[i].xttype, extent[i].xtseqn, bcyl, btrk, ecyl, etrk); } } return; } /* showf1 */
int fbcopy( FILE *fout, CIFBLK *cif, DADSM *dadsm, int tran, int verbose) { FORMAT1_DSCB *f1dscb = &dadsm->f1buf; DSXTENT extent[MAX_EXTENTS]; int rc, trk = 0, trkconv = 999, rec = 1; int cyl = 0, head = 0, rc_rb, len, offset; int rc_copy = 0; int recs_written = 0, lrecl, num_extents; int lstartrack = 0, lstarrec = 0, lstarvalid = 0; BYTE *buffer; char *pascii = NULL; char zdsn[sizeof(f1dscb->ds1dsnam) + 1]; // ascii dsn // Kludge to avoid rewriting this code (for now): memcpy(&extent, (void *)&(dadsm->f1ext), sizeof(extent)); num_extents = f1dscb->ds1noepv; lrecl = (f1dscb->ds1lrecl[0] << 8) | (f1dscb->ds1lrecl[1]); if (absvalid) { strcpy(zdsn, argdsn); if (debug) fprintf(stderr, "fbcopy absvalid\n"); } else { make_asciiz(zdsn, sizeof(zdsn), f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam)); if ((f1dscb->ds1lstar[0] !=0) || (f1dscb->ds1lstar[1] != 0) || (f1dscb->ds1lstar[2] != 0)) { lstartrack = (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1]); lstarrec = f1dscb->ds1lstar[2]; lstarvalid = 1; // DS1LSTAR valid } } if (debug) { fprintf(stderr, "fbcopy zdsn %s\n", zdsn); fprintf(stderr, "fbcopy num_extents %d\n", num_extents); fprintf(stderr, "fbcopy lrecl %d\n", lrecl); fprintf(stderr, "fbcopy F1 DSCB\n"); data_dump(f1dscb, sizeof(FORMAT1_DSCB)); sayext(num_extents, (void *)&extent); } if (verbose) // DS1LSTAR = last block written TTR fprintf(stderr, "fbcopy DS1LSTAR %2.2X%2.2X%2.2X lstartrack %d " "lstarrec %d lstarvalid %d\n", f1dscb->ds1lstar[0], f1dscb->ds1lstar[1], f1dscb->ds1lstar[2], lstartrack, lstarrec, lstarvalid); if (tran) { // need ASCII translation buffer? pascii = malloc(lrecl + 1); if (pascii == NULL) { fprintf(stderr, "fbcopy unable to allocate ascii buffer\n"); return -1; } } while (1) { // output records until something stops us // Honor DS1LSTAR when valid if ((lstarvalid) && (trk == lstartrack) && (rec > lstarrec)) { if (verbose) fprintf(stderr, "fbcopy DS1LSTAR indicates EOF\n" "fbcopy DS1LSTAR %2.2X%2.2X%2.2X " "track %d record %d\n", f1dscb->ds1lstar[0], f1dscb->ds1lstar[1], f1dscb->ds1lstar[2], trk, rec); rc_copy = recs_written; break; } // Convert TT to CCHH for upcoming read_block call if (trkconv != trk) { // avoid converting for each block trkconv = trk; // current track converted rc = convert_tt(trk, num_extents, extent, cif->heads, &cyl, &head); if (rc < 0) { fprintf(stderr, "fbcopy convert_tt track %5.5d, rc %d\n", trk, rc); if (absvalid) rc_copy = recs_written; else rc_copy = -1; break; } if (verbose > 1) fprintf(stderr, "fbcopy convert TT %5.5d CCHH %4.4X %4.4X\n", trk, cyl, head); } // Read block from dasd if (verbose > 2) fprintf(stderr, "fbcopy reading track %d " "record %d CCHHR = %4.4X %4.4X %2.2X\n", trk, rec, cyl, head, rec); rc_rb = read_block(cif, cyl, head, rec, NULL, NULL, &buffer, &len); if (rc_rb < 0) { // error fprintf(stderr, "fbcopy error reading %s, rc %d\n", zdsn, rc_rb); rc_copy = -1; break; } // Handle end of track return from read_block if (rc_rb > 0) { // end of track if (verbose > 2) fprintf(stderr, "fbcopy End Of Track %d rec %d\n", trk, rec); trk++; // next track rec = 1; // record 1 on new track continue; } // Check for dataset EOF if (len == 0) { // EOF if (verbose) fprintf(stderr, "fbcopy EOF track %5.5d rec %d\n", trk, rec); if (absvalid) { // capture as much -abs data as possible if (verbose) fprintf(stderr, "fbcopy ignoring -abs EOF\n"); } else { rc_copy = recs_written; break; } } if (verbose > 3) fprintf(stderr, "fbcopy read %d bytes\n", len); if (verbose > 2) { data_dump(buffer, len); fprintf(stderr, "\n"); } // Deblock input dasd block, write records to output dataset for (offset = 0; offset < len; offset += lrecl) { if (verbose > 3) { fprintf(stderr, "fbcopy offset %d length %d rec %d\n", offset, lrecl, recs_written); } if (tran) { // ASCII output memset(pascii, 0, lrecl + 1); make_asciiz(pascii, lrecl + 1, buffer + offset, lrecl); if (verbose > 4) { fprintf(stderr, "fbcopy buffer offset %d rec %d\n", offset, rec); data_dump(buffer + offset, lrecl); } if (verbose > 3) { fprintf(stderr, "->%s<-\n", pascii); data_dump(pascii, lrecl); } fprintf(fout, "%s\n", pascii); } else { // EBCDIC output if (verbose > 3) { fprintf(stderr, "fbcopy EBCDIC buffer\n"); data_dump(buffer + offset, lrecl); } fwrite(buffer + offset, lrecl, 1, fout); } if (ferror(fout)) { fprintf(stderr, "fbcopy error writing %s\n", zdsn); fprintf(stderr, "%s\n", strerror(errno)); rc_copy = -1; } recs_written++; } if (rc_copy != 0) break; else rec++; // next record on track } /* while (1) */ if (pascii) free(pascii); // release ASCII conversion buffer return rc_copy; } /* fbcopy */
/*-------------------------------------------------------------------*/ static IFD open_input_image (char *ifname, U16 *devt, U32 *vcyls, U32 *itrkl, BYTE **itrkb, BYTE *volser) { int rc; /* Return code */ H30CKD_TRKHDR h30trkhdr; /* Input track header */ IFD ifd; /* Input file descriptor */ int len; /* Length of input */ U16 code; /* Device type code */ U16 dt; /* Device type */ U32 cyls; /* Device size (pri+alt cyls)*/ U32 alts; /* Number of alternate cyls */ BYTE *itrkbuf; /* -> Input track buffer */ U32 itrklen; /* Input track length */ BYTE *pbuf; /* Current byte in input buf */ BYTE klen; /* Key length */ U16 dlen; /* Data length */ BYTE *kptr; /* -> Key in input buffer */ BYTE *dptr; /* -> Data in input buffer */ U32 cyl; /* Cylinder number */ U32 head; /* Head number */ BYTE rec; /* Record number */ char pathname[MAX_PATH]; /* file path in host format */ hostpath(pathname, (char *)ifname, sizeof(pathname)); /* Open the HDR-30 CKD image file */ #if defined(HAVE_LIBZ) if (strcmp(ifname, "-") == 0) ifd = gzdopen (STDIN_FILENO, "rb"); else ifd = gzopen (pathname, "rb"); if (ifd == NULL) { fprintf (stderr, "Cannot open %s: %s\n", ifname, errno == 0 ? "gzopen error" : strerror(errno)); EXIT(3); } #else /*!defined(HAVE_LIBZ)*/ if (strcmp(ifname, "-") == 0) ifd = STDIN_FILENO; else { ifd = hopen(pathname, O_RDONLY | O_BINARY); if (ifd < 0) { fprintf (stderr, "Cannot open %s: %s\n", ifname, strerror(errno)); EXIT(3); } } #endif /*!defined(HAVE_LIBZ)*/ /* Read the first track header */ read_input_data (ifd, ifname, (BYTE*)&h30trkhdr, H30CKD_TRKHDR_SIZE, 0); #if !defined(HAVE_LIBZ) /* Reject input if compressed and we lack gzip support */ if (memcmp(h30trkhdr.devcode, gz_magic_id, sizeof(gz_magic_id)) == 0) { fprintf (stderr, "Input file %s appears to be a .gz file\n" "but this program was compiled without compression support\n", ifname); EXIT(3); } #endif /*!defined(HAVE_LIBZ)*/ /* Reject input if it is already in CKD or CCKD format */ if (memcmp((BYTE*)&h30trkhdr, ckd_ident, sizeof(ckd_ident)) == 0) { fprintf (stderr, "Input file %s is already in CKD format, use dasdcopy\n", ifname); EXIT(3); } /* Extract the device type code from the track header */ FETCH_HW (code, h30trkhdr.devcode); /* Determine the input device type and size from the device code */ switch (code) { case 0x01: dt=0x3330; cyls=411; alts=7; break; /* 3330 */ case 0x02: dt=0x3330; cyls=815; alts=7; break; /* 3330-11 */ case 0x03: dt=0x3340; cyls=351; alts=1; break; /* 3340-35 */ case 0x04: dt=0x3340; cyls=701; alts=1; break; /* 3340-70 */ case 0x05: dt=0x3350; cyls=562; alts=7; break; /* 3350 */ case 0x06: dt=0x3375; cyls=962; alts=3; break; /* 3375 */ case 0x08: dt=0x3380; cyls=888; alts=3; break; /* 3380-A,D,J*/ case 0x09: dt=0x3380; cyls=1774; alts=4; break; /* 3380-E */ case 0x0A: dt=0x3380; cyls=2660; alts=5; break; /* 3380-K */ case 0x0B: dt=0x3390; cyls=1117; alts=4; break; /* 3390-1 */ case 0x0C: dt=0x3390; cyls=2230; alts=4; break; /* 3390-2 */ case 0x0D: dt=0x3390; cyls=3343; alts=4; break; /* 3390-3 */ case 0x12: dt=0x2314; cyls=203; alts=3; break; /* 2314 */ case 0x13: dt=0x3390; cyls=10038; alts=21; break; /* 3390-9 */ case 0x14: dt=0x9345; cyls=1454; alts=14; break; /* 9345-1 */ case 0x15: dt=0x9345; cyls=2170; alts=14; break; /* 9345-2 */ default: fprintf (stderr, "Unknown device code %4.4X" \ " at offset 00000000 in input file %s\n", code, ifname); EXIT(3); } /* end switch(code) */ /* Use the device type to determine the input image track size */ switch (dt) { case 0x2314: itrklen = 0x2000; break; case 0x3330: itrklen = 0x3400; break; case 0x3340: itrklen = 0x2400; break; case 0x3350: itrklen = 0x4C00; break; case 0x3375: itrklen = 0x9000; break; case 0x3380: itrklen = 0xBC00; break; case 0x3390: itrklen = 0xE400; break; case 0x9345: itrklen = 0xBC00; break; default: fprintf (stderr, "Unknown device type: %4.4X\n", dt); EXIT(3); } /* end switch(dt) */ /* Obtain the input track buffer */ itrkbuf = malloc (itrklen); if (itrkbuf == NULL) { fprintf (stderr, "Cannot obtain storage for input track buffer: %s\n", strerror(errno)); EXIT(3); } /* Copy the first track header to the input track buffer */ memcpy (itrkbuf, &h30trkhdr, H30CKD_TRKHDR_SIZE); /* Read the remainder of the first track into the buffer */ read_input_data (ifd, ifname, itrkbuf + H30CKD_TRKHDR_SIZE, itrklen - H30CKD_TRKHDR_SIZE, H30CKD_TRKHDR_SIZE); /* Initialize the volume serial number */ strcpy ((char *)volser, "(NONE)"); /* Search for volume label in record 3 of first track */ pbuf = itrkbuf + H30CKD_TRKHDR_SIZE; len = itrklen - H30CKD_TRKHDR_SIZE; while (1) { /* Find next input record */ rc = find_input_record (itrkbuf, &pbuf, &len, &klen, &kptr, &dlen, &dptr, &cyl, &head, &rec); /* Give up if error or end of track */ if (rc != 0) break; /* Process when record 3 is found */ if (cyl == 0 && head == 0 && rec == 3) { /* Extract volser if it is a volume label */ if (klen == 4 && memcmp(kptr, ebcdicvol1, 4) == 0 && dlen == 80 && memcmp(dptr, ebcdicvol1, 4) == 0) make_asciiz ((char *)volser, 7, dptr+4, 6); break; } } /* end while */ /* Set output variables and return the input file descriptor */ *devt = dt; *vcyls = cyls - alts; *itrkl = itrklen; *itrkb = itrkbuf; return ifd; } /* end function open_input_image */
int process_dirblk(CIFBLK *cif, int noext, DSXTENT extent[], BYTE *dirblk, char* dsname, char *pdsmember, unsigned long optflags) { int rc; int dirrem; char memname[9]; static const BYTE endofdir[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; /* Load number of bytes in directory block */ dirrem = (dirblk[0] << 8) | dirblk[1]; if (dirrem < 2 || dirrem > 256) { // "Directory block byte count is invalid" FWRMSG( stderr, HHC02400, "E" ); return -1; } /* Point to first directory entry */ dirblk += 2; dirrem -= 2; while (dirrem > 0) { PDSDIR *dirent = (PDSDIR*)dirblk; int k, size; /* Check for end of directory */ if (memcmp( endofdir, dirent->pds2name, 8 ) == 0) return +1; /* (logical EOF) */ /* Extract this member's name */ make_asciiz(memname, sizeof(memname), dirent->pds2name, 8); if (optflags & OPT_PDS_LISTONLY) { char memname_lc[9]; /* List just the member names in this PDS */ memcpy(memname_lc, memname, sizeof(memname)); string_to_lower(memname_lc); puts(memname_lc); } else { /* Are we interested in this specific member? */ if (0 || (optflags & OPT_PDS_WILDCARD) || strcmp( pdsmember, memname ) == 0 ) { if (optflags & OPT_PDS_WILDCARD && !(optflags & OPT_MEMINFO_ONLY)) printf("> Member %s\n", memname); else if (1 && !(optflags & OPT_MEMINFO_ONLY) && !isatty( fileno( stdout )) ) { /* Delete any existing o/p file contents */ rewind( stdout ); ftruncate( fileno( stdout ), 0 ); } rc = process_member(cif, noext, extent, dirent->pds2ttrp, optflags, dsname, memname); if (rc < 0) return -1; /* If not ALL members then we're done */ if (!(optflags & OPT_PDS_WILDCARD)) { found = 1; return +1; /* (logical EOF) */ } } } /* Load the user data halfword count */ k = dirent->pds2indc & PDS2INDC_LUSR; /* Point to next directory entry */ size = 12 + k*2; dirblk += size; dirrem -= size; } return 0; }
/*-------------------------------------------------------------------*/ static int process_member (CIFBLK *cif, int noext, DSXTENT extent[], char *memname, BYTE *ttr) { int rc; /* Return code */ U16 len; /* Record length */ u_int trk; /* Relative track number */ U32 cyl; /* Cylinder number */ U8 head; /* Head number */ U8 rec; /* Record number */ BYTE *buf; /* -> Data block */ FILE *ofp; /* Output file pointer */ char ofname[256]; /* Output file name */ int offset; /* Offset of record in buffer*/ char card[81]; /* Logical record (ASCIIZ) */ char pathname[MAX_PATH]; /* ofname in host format */ /* Build the output file name */ memset (ofname, 0, sizeof(ofname)); strncpy (ofname, memname, 8); string_to_lower (ofname); strlcat (ofname, ".mac", sizeof(ofname)); /* Open the output file */ hostpath(pathname, ofname, sizeof(pathname)); ofp = fopen (pathname, (asciiflag? "w" : "wb")); if (ofp == NULL) { FWRMSG( stderr, HHC02468, "E", ofname, "fopen", strerror( errno )); return -1; } /* Point to the start of the member */ trk = (ttr[0] << 8) | ttr[1]; rec = ttr[2]; WRMSG( HHC02469, "I", memname, trk, rec ); /* Read the member */ while (1) { /* Convert relative track to cylinder and head */ rc = convert_tt (trk, noext, extent, cif->heads, &cyl, &head); if (rc < 0) return -1; // fprintf (stderr, // "CCHHR=%4.4X%4.4X%2.2X\n", // cyl, head, rec); /* Read a data block */ rc = read_block (cif, cyl, head, rec, NULL, NULL, &buf, &len); if (rc < 0) return -1; /* Move to next track if record not found */ if (rc > 0) { trk++; rec = 1; continue; } /* Exit at end of member */ if (len == 0) break; /* Check length of data block */ if (len % 80 != 0) { FWRMSG( stderr, HHC02470, "E", len, cyl, head, rec ); return -1; } /* Process each record in the data block */ for (offset = 0; offset < len; offset += 80) { if (asciiflag) { make_asciiz (card, sizeof(card), buf + offset, 72); fprintf (ofp, "%s\n", card); } else { fwrite (buf+offset, 80, 1, ofp); } if (ferror(ofp)) { FWRMSG( stderr, HHC02468, "E", ofname, "fwrite", strerror( errno )); return -1; } } /* end for(offset) */ /* Point to the next data block */ rec++; } /* end while */ /* Close the output file and exit */ fclose (ofp); return 0; } /* end function process_member */