Skip to content

Commit

Permalink
Fix Large/Extended dataset truncation in dasdseq utility:
Browse files Browse the repository at this point in the history
Closes GitHub Issue #602.

THANK YOU to Gregory ("GregoryTwin") for the help!
  • Loading branch information
Fish-Git committed Jan 16, 2024
1 parent 148e0ed commit f2bbab8
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 37 deletions.
98 changes: 70 additions & 28 deletions dasdblks.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,38 +152,80 @@ struct DSXTENT { /* Dataset extent descriptor */
#define XTTYPE_SHARCYL 0x80 /* Shared cylinders */
#define XTTYPE_CYLBOUND 0x81 /* Extent on cyl boundary */

struct FORMAT1_DSCB { /* DSCB1: Dataset descriptor */
BYTE ds1dsnam[44]; /* Key (44 byte dataset name)*/
BYTE ds1fmtid; /* Format identifier (0xF1) */
BYTE ds1dssn[6]; /* Volume serial number */
HWORD ds1volsq; /* Volume sequence number */
BYTE ds1credt[3]; /* Dataset creation date...
struct FORMAT1_DSCB /* DSCB1: Dataset descriptor */
{
/*00*/ BYTE ds1dsnam[44]; /* Key (44 byte dataset name)*/
/*2C*/ BYTE ds1fmtid; /* Format identifier (0xF1) */
/*2D*/ BYTE ds1dssn[6]; /* Volume serial number */
/*33*/ HWORD ds1volsq; /* Volume sequence number */
/*35*/ BYTE ds1credt[3]; /* Dataset creation date...
...byte 0: Binary year-1900
...bytes 1-2: Binary day */
BYTE ds1expdt[3]; /* Dataset expiry date */
BYTE ds1noepv; /* Number of extents */
BYTE ds1bodbd; /* #bytes used in last dirblk*/
BYTE resv1; /* Reserved */
BYTE ds1syscd[13]; /* System code (IBMOSVS2) */
BYTE resv2[7]; /* Reserved */
BYTE ds1dsorg[2]; /* Dataset organization */
BYTE ds1recfm; /* Record format */
BYTE ds1optcd; /* Option codes */
HWORD ds1blkl; /* Block length */
HWORD ds1lrecl; /* Logical record length */
BYTE ds1keyl; /* Key length */
HWORD ds1rkp; /* Relative key position */
BYTE ds1dsind; /* Dataset indicators */
FWORD ds1scalo; /* Secondary allocation...
/*38*/ BYTE ds1expdt[3]; /* Dataset expiry date */
/*3B*/ BYTE ds1noepv; /* Number of extents */
/*3C*/ BYTE ds1bodbd; /* #bytes used in last dirblk*/
/*3D*/ BYTE ds1flag1; /* Flags byte */
#define DS1LARGE 0x08 /* Large format data set */

/*3E*/ BYTE ds1syscd[13]; /* System code (IBMOSVS2) */
/*4B*/ BYTE ds1refdt[3]; /* Last reference date ('YDD'
or 0 if not maintained).
Add 1900 to 'Y' for year. */
/*4E*/ BYTE ds1smsfg; /* SMS indicators */
#define DS1STRP 0x04 /* Extended-format data set */

/*4F*/ BYTE ds1scext[3]; /* Secondary space extension */
/*52*/ BYTE ds1dsorg[2]; /* Dataset organization */
/*54*/ BYTE ds1recfm; /* Record format */
/*55*/ BYTE ds1optcd; /* Option codes */
/*56*/ HWORD ds1blkl; /* Block length */
/*58*/ HWORD ds1lrecl; /* Logical record length */
/*5A*/ BYTE ds1keyl; /* Key length */
/*5B*/ HWORD ds1rkp; /* Relative key position */
/*5D*/ BYTE ds1dsind; /* Dataset indicators */
/*5E*/ FWORD ds1scalo; /* Secondary allocation...
...byte 0: Allocation units
...bytes 1-3: Quantity */
BYTE ds1lstar[3]; /* Last used TTR */
HWORD ds1trbal; /* Bytes unused on last trk */
BYTE resv3[2]; /* Reserved */
DSXTENT ds1ext1; /* First extent descriptor */
DSXTENT ds1ext2; /* Second extent descriptor */
DSXTENT ds1ext3; /* Third extent descriptor */
BYTE ds1ptrds[5]; /* CCHHR of F2 or F3 DSCB */
/*62*/ BYTE ds1lstar[3]; /* Last used TTR (see below) */

/* PROGRAMMING NOTE
For NORMAL datasets, the last block pointer (TTR) is in the
DS1LSTAR field. So the size of the dataset in number of tracks
is in the first two bytes (TT) of DS1LSTAR. (The last right-
most byte of DS1LSTAR being the 'R' part of the 'TTR'.)
For DSNTYPE=LARGE however, the size of the dataset is 3 bytes
in size (i.e. TTT, not just TT). So you use the first two
high-order bytes of DS1LSTAR (just like you do for for normal
format datasets), but in addition to that, the high-order byte
of the 3-byte TTT is kept in the DS1TTTHI field.
For DSNTYPE=EXTENDED, the size of the dataset in tracks is of
course 4 bytes in size (TTTT), with the low-order 2 bytes of
that 4-byte TTTT coming from the high-order two bytes of the
DS1LSTAR field (just for for normal/large format datasets),
but the two HIGH-order bytes of the 4-byte TTTT is in DS1TRBAL.
SUMMARY OF DATASET SIZE IN NUMBER OF TRACKS:
Normal: TT = high-order 2 bytes of ds1lstar
Large: TTT = ds1ttthi(1), high-order 2 bytes of ds1lstar
Extended: TTTT = ds1trbal(2), high-order 2 bytes of ds1lstar
*/
/*65*/ HWORD ds1trbal; /* Normal/Large: bytes unused
on last track.
Extended: high-order bytes
of TTTTTR. */
/*67*/ BYTE resv1; /* Reserved */
/*68*/ BYTE ds1ttthi; /* Large format: high-order
byte of TTTR. */
/*69*/ DSXTENT ds1ext1; /* First extent descriptor */
/*73*/ DSXTENT ds1ext2; /* Second extent descriptor */
/*7D*/ DSXTENT ds1ext3; /* Third extent descriptor */
/*87*/ BYTE ds1ptrds[5]; /* CCHHR of F2 or F3 DSCB */
/*8C*/ /* Total len/size: 140 bytes */
};

/* Bit definitions for ds1dsind */
Expand Down
2 changes: 0 additions & 2 deletions dasdls.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,6 @@ int list_contents( CIFBLK *cif, char *volser, DSXTENT *extent )

/* REFDT */

#define ds1refdt resv2

if (runflgs & rf_refdate)
pdatex( f1dscb->ds1refdt, runflgs );

Expand Down
59 changes: 53 additions & 6 deletions dasdseq.c
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,47 @@ void showf1( FORMAT1_DSCB *f1dscb,
}
}

//---------------------------------------------------------------------
// Calculate lstartrack value
//---------------------------------------------------------------------

u_int calc_lstartrack( FORMAT1_DSCB* f1dscb, int verbose )
{
u_int numtracks;
const char* ds_format;

// Extended: TTTT = ds1trbal(2), high-order 2 bytes of ds1lstar
// Large: TTT = ds1ttthi(1), high-order 2 bytes of ds1lstar
// Normal: TT = high-order 2 bytes of ds1lstar

if (f1dscb->ds1smsfg & DS1STRP)
{
ds_format = "Extended";
numtracks = (f1dscb->ds1trbal[0] << 24) | (f1dscb->ds1trbal[1] << 16)
| (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1] << 0);
}
else if (f1dscb->ds1flag1 & DS1LARGE)
{
ds_format = "Large";
numtracks = (f1dscb->ds1ttthi << 16)
| (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1] << 0);
}
else
{
ds_format = "Normal";
numtracks = 0
| (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1] << 0);
}

if (verbose)
{
// "Data set format is %s"
WRMSG( HHC02696, "I", ds_format );
}

return numtracks;
}

//---------------------------------------------------------------------
// Copy DSORG=PS RECFM=F[B] dataset to output file
//
Expand Down Expand Up @@ -624,7 +665,8 @@ int fbcopy( FILE *fout,
U16 len, offset;
int rc_copy = 0;
int recs_written = 0, lrecl, num_extents;
u_int lstartrack = 0, lstarrec = 0, lstarvalid = 0;
u_int lstartrack = 0, lstarrec = 0;
bool lstarvalid = false;
BYTE *buffer;
char *pascii = NULL;
char zdsn[sizeof(f1dscb->ds1dsnam) + 1]; // ascii dsn
Expand All @@ -646,13 +688,18 @@ int fbcopy( FILE *fout,
{
make_asciiz(zdsn, sizeof(zdsn),
f1dscb->ds1dsnam, sizeof(f1dscb->ds1dsnam));
if ((f1dscb->ds1lstar[0] !=0) ||
(f1dscb->ds1lstar[1] != 0) ||
(f1dscb->ds1lstar[2] != 0))

// Valid ds1lstar value?
if (0
|| (f1dscb->ds1lstar[0] != 0)
|| (f1dscb->ds1lstar[1] != 0)
|| (f1dscb->ds1lstar[2] != 0)
)
{
lstartrack = (f1dscb->ds1lstar[0] << 8) | (f1dscb->ds1lstar[1]);
// Calculate last track
lstartrack = calc_lstartrack( f1dscb, verbose );
lstarrec = f1dscb->ds1lstar[2];
lstarvalid = 1; // DS1LSTAR valid
lstarvalid = true; // DS1LSTAR valid
}
}

Expand Down
3 changes: 2 additions & 1 deletion msgenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2072,7 +2072,8 @@ LOGM_DLL_IMPORT int panel_command_capture( char* cmd, char** resp, bool quiet )
#define HHC02693 "search_key_equal rc %d"
#define HHC02694 "writing %s"
#define HHC02695 "Closed output file %s"
//efine HHC02696 - HHC02699 (available)
#define HHC02696 "Data set format is %s"
//efine HHC02697 - HHC02699 (available)

#define HHC02700 "SCSI tapes are not supported with this build"
#define HHC02701 "Abnormal termination"
Expand Down

0 comments on commit f2bbab8

Please sign in to comment.