Examples
Example 8. Catalog Search Interface Routine
This routine was an attempt to emulate the Linux "stat" of a dataset by retrieving information from the VTOC and the catalog search interface (CSI). Information from the VTOC is obtan by use of the OBTAIN / CAMLST macros along with TRKCALC to perform DASD track capacity calculations. The routine works for non-VSAM and VSAM datasets. Information for TAPE datasets is limited to that returned from the catalog.
Struct fileStat
The struct filestat is the passed to the routine with the dsname field as the only input parameter.
/* Parameter List Passed To/Returned From This Program. */
struct fileStat
{
int size;
int returnCode;
int reasonCode;
int dsnameLength;
char dsname[44]; // Input dataset Name
char volume[6];
char datasetOnIsTape;
char datasetIsOnDASD;
char datasetIsVSAM;
char datasetIsNonVSAM;
char datasetIsGDS;
char datasetIsPDS;
char datasetIsPDSE;
char datasetIsPS;
char datasetIsLargeFormat;
char datsetIsBasicFormat;
char datasetIsExtendedFormat;
char datasetIsHFS;
int lrecl;
long long int approxSize; // Approximate size in bytes
struct ucbtype devtype;
struct date createDate;
// Union Depends on VSAM/Non-VSAM boolean Values
union
{
struct nonVSAMAttr _nonVSAMAttr;
struct VSAMAttr _VSAMAttr;
} ;
} ;
struct recfm
{
char datasetIsFixed;
char datasetIsVariable;
char datasetIsBlocked;
char datasetIsFixedStandardBks;
char datasetIsVarSpannedBlks;
char datasetIsUnformatted;
char datasetIsASA;
char datasetIsMachine;
char _recfm[4];
} ;
struct extents
{
long long int tracks;
} ;
struct spaceAllocation
{
char isInTrks;
char isInCylinders;
char isInAverageBlock;
int secondary; // secondary allocation in tracks
int used; // Used amount from DLSTAR
int numberOfExtents;
struct extents _extents[16]; // 1st 16 extents
} ;
struct nonVSAMAttr
{
int blksize;
int genLevel;
char dsorg[5];
char allocation[10]; // text 'trks', 'blks', 'cyls'
struct recfm _recfm;
struct date lastReferredDate;
struct spaceAllocation _spaceAllocation;
} ;
C Source
#ifdef __MVS__
#pragma export(fileStat)
#endif
#ifndef __MVS__
#include <stdio.h>
#endif
#include <ctype.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define true 1
#define false 0
#define ZOS_FILESIZE 44
#define WorkAreaSize 65536
#define bytesPerTrack 56664
/*
FORMAT1 DSCB Date Format - 3 bytes
DATA SET CREATION DATE in the format: 'YYDDDD'
in which the year is an offset from 1900, i.e.
1989 is 1900 + 89. The 89 in hex is 59, in
this case January 8, 1989 would be 590008.
*/
struct dscbDate
{
char yy;
char ddd[2];
} ;
/*
CSI Date Format - 4 bytes
Packed decimal YYDDDF for 3 bytes appended with one byte
century indicator. If the century byte is 00 then add
1900 to get the year; if 01, add 2000.
*/
struct csiDate
{
struct dscbDate _dscbDate;
char centuary;
} ;
struct date
{
char year[4];
char ddd[3];
} ;
struct ucbtype
{
struct
{
unsigned char _ucb1;
unsigned char _ucb2;
unsigned char _ucb3;
unsigned char _ucb4;
} ucb_1_4;
} ;
#define ucb1 ucb_1_4._ucb1
#define ucb2 ucb_1_4._ucb2
#define ucb3 ucb_1_4._ucb3
#define ucb4 ucb_1_4._ucb4
/* Values for field "ucb3" */
#define tape_device 0x80
#define dasd_device 0x20
/* Values for field "ucb_1_4" */
#define type_3380 0x3010200E /* 3380, all models */
#define type_3390 0x3010200F /* 3390, all models */
#define type_9345 0x30102004 /* 9345, all models */
#define type_34002 0x30C08003 /* 3420 Models 3, 5, and 7 */
#define type_34005 0x32008003 /* 3420 Models 4, 6, and 8 */
#define type_34006 0x32108003 /* 3420 Models 4, 6, and 8 */
#define type_34009 0x33008003 /* 3420C (3480 coexistence mode) */
#define type_34003 0x34008003 /* 3430, 9 track, 1600/6250 BPI tape */
#define type_3480 0x78008080 /* 3480 Magnetic Tape Unit and */
#define type_3480x 0x78048080 /* 3480 Magnetic Tape Unit with */
#define type_3490 0x78048081 /* 3490 Magnetic Tape */
#define type_35901 0x78048083 /* IBM 3590 High Performance Tape */
#ifdef __MVS__
#pragma pack(packed)
#endif
#define TRACKS_PER_CYLINDER 15
/* First 3 extents are in F1 DSCB */
struct dsextents
{
unsigned char ds1extByte1;
unsigned char ds1extSeqNo;
union
{
struct
{
unsigned int ds1extLowerLimitCCHH;
unsigned int ds1extUpperLimitCCHH;
} Format1;
struct
{
unsigned short int ds1extLowerLimitCC;
unsigned short int ds1extLowerLimitHH;
unsigned short int ds1extUpperLimitCC;
unsigned short int ds1extUpperLimitHH;
} Format2;
} ext;
} ;
struct format1
{
// unsigned char ds1dsnam[44]; /* DATA SET NAME */
unsigned char ds1fmtid; /* FORMAT IDENTIFIER @LvC */
unsigned char ds1dssn[6]; /* DATA SET SERIAL NUMBER */
unsigned char ds1volsq[2]; /* VOLUME SEQUENCE NUMBER (1-9999) @P1C */
struct dscbDate ds1credt; /* CREATION DATE */
struct dscbDate ds1expdt; /* EXPIRATION DATE */
unsigned char ds1noepv; /* NUMBER OF DATA EXTENTS ON VOLUME@P1C */
unsigned char ds1nobdb; /* NUMBER OF BYTES USED IN LAST */
unsigned char ds1flag1; /* FLAG 1 @LAA */
unsigned char ds1syscd[13]; /* SYSTEM CODE */
struct dscbDate ds1refd; /* DATE LAST REFERENCED @01C */
unsigned char ds1smsfg; /* SYSTEM MANAGED STORAGE INDICATORS */
struct
{
unsigned char _ds1scxtf; /* SECONDARY SPACE EXTENSION FLAG - */
unsigned char _ds1scxtv[2]; /* SECONDARY SPACE EXTENSION VALUE @L4A */
} ds1scext;
unsigned char ds1dsorg1; /* DATA SET ORGANIZATION - Byte 1 */
unsigned char ds1dsorg2; /* DATA SET ORGANIZATION - Byte 2 */
unsigned char ds1recfm; /* RECORD FORMAT */
unsigned char ds1optcd; /* OPTION CODES -- INDICATES THE @P1C */
short unsigned int ds1blkl; /* BLOCK LENGTH (TYPE F RECORDS), @L3C */
short unsigned int ds1lrecl; /* LOGICAL RECORD LENGTH */
unsigned char ds1keyl; /* KEY LENGTH (0 - 255) */
unsigned char ds1rkp[2]; /* RELATIVE KEY POSITION */
unsigned char ds1dsind; /* DATA SET INDICATORS */
// Used Allocation
struct
{
unsigned char _ds1scal1; /* SPACE PARAMETERS P1C */
unsigned char _ds1scal3[3]; /* SECONDARY ALLOCATION QUANTITY 1C */
} ds1scalo;
unsigned char ds1lstar[3]; /* LAST USED TRACK AND BLOCK ON 1C */
unsigned char ds1trbal[2]; /* FOR EXTENDED FORMAT: 2 HIGH @02C */
unsigned char _filler1; /* RESERVED */
unsigned char ds1ttthi; /* HIGH ORDER BYTE OF DS1LSTAR @LCA */
struct dsextents ds1ext1[3]; /* FIRST EXTENT DESCRIPTION */
/* SECOND EXTENT DESCRIPTION */
/* THIRD EXTENT DESCRIPTION */
unsigned char ds1ptrds[5]; /* DS1FMTID="1": Zeroes or pointer */
struct
{
unsigned char ds1ptrds[5]; // Track address of this DSCB
unsigned short dscbCnt; // Total number of DSCB's for this dataset
unsigned char filler[37];
} extension;
} ;
/*
95(X'5F') Binary 3 DS1SCAL3 Secondary allocation quantity.
98(X'62') Binary 3 DS1LSTAR Last used track and block on track (TTR).
Not defined for VSAM, PDSE, HFS and direct (BDAM).
See bit DS1LARGE at +61 and byte DS1TTTHI at +104.
101(X'65') Binary 2 DS1TRBAL If not extended format, this is the value from TRKCALC
indicating space remaining on last track used.
For extended format data sets this is the high order two
bytes(TT) of the four-byte last used track number.
See DS1LSTAR. Zero for VSAM, PDSE, and HFS.
104(X'68') Character 1 DS1TTTHI High order byte of track number in DS1LSTAR.
Valid if DS1Large is on.
*/
#define ds1scxtf ds1scext._ds1scxtf
#define ds1scxtv ds1scext._ds1scxtv
#define ds1scal1 ds1scalo._ds1scal1
#define ds1scal3 ds1scalo._ds1scal3
/* Values for field "ds1fmtid" */
#define ds1idc 0xF1 /* FORMAT 1 IDENTIFIER @LvA */
#define ds8idc 0xF8 /* FORMAT 8 IDENTIFIER @LvA */
/* Values for field "ds1flag1" */
#define ds1compr 0x80 /* 1... .... COMPRESSABLE EXTENDED FORMAT @LAA */
#define ds1cpoit 0x40 /* .1.. .... CHECKPOINTED DATASET @03A */
#define ds1expby 0x20 /* ..1. .... VSE EXP DATE SPEC BY RET PERIOD @08C */
#define ds1recal 0x10 /* ...1 .... DATA SET HAS BEEN RECALLED @LDA */
#define ds1large 0x08 /* .... 1... >64K TRACK DATA SET COEXISTENCE @08M */
#define ds1eattr 0x03 /* .... ..11 Extended attribute setting */
#define ds1eattr_ns 0x00 /* '0' - EATTR has not been @V2A */
#define ds1eattr_no 0x01 /* '1' - EATTR=NO has been */
#define ds1eattr_opt 0x02 /* '2' - EATTR=OPT has been */
#define ds1eattr_req 0x03 /* '3' - Not Used. EATTR treated as not */
/* Values for field "ds1smsfg" */
#define ds1smsds 0x80 /* 1... .... SYSTEM MANAGED DATA SET @L4A */
#define ds1smsuc 0x40 /* .1.. .... NO BCS ENTRY EXISTS FOR DATA SET */
#define ds1reblk 0x20 /* ..1. .... SDB AND D.S. MAY BE REBLOCKED @02C */
#define ds1crsdb 0x10 /* ...1 .... DADSM CREATE ORIGINATED BLKSIZE @P5A */
#define ds1pdse 0x08 /* .... 1... PDSE DATA SET @P7C */
#define ds1strp 0x04 /* .... .1.. EXTENDED FORMAT DATA SET @LAC */
#define ds1pdsex 0x02 /* .... ..1. HFS DATA SET @L8A */
#define ds1dsae 0x01 /* ........1 Extended attributes are @L9C */
/* Values for field "ds1scxtf" */
#define ds1scavb 0x80 /* 1... .... IF 1, DS1SCXTV IS THE ORIGINAL @L4A */
#define ds1scmb 0x40 /* .1.. .... IF 1, DS1SCXTV IS IN MEGABYTES @L4A */
#define ds1sckb 0x20 /* ..1. .... IF 1, DS1SCXTV IS IN KILOBYTES @L4A */
#define ds1scub 0x10 /* ...1 .... IF 1, DS1SCXTV IS IN BYTES @L4A */
#define ds1sccp1 0x08 /* .... 1... IF 1, DS1SCXTV HAS BEEN COMPACTED */
#define ds1sccp2 0x04 /* .... .1.. IF 1, DS1SCXTV HAS BEEN COMPACTED */
/* Values for field "ds1dsorg" Byte 1 */
#define ds1dsgis 0x80 /* 1... .... IS - INDEXED SEQUENTIAL @L1A */
#define ds1dsgps 0x40 /* .1.. .... PS - PHYSICAL SEQUENTIAL @L1A */
#define ds1dsgda 0x20 /* ..1. .... DA - DIRECT ORGANIZATION @L1A */
#define ds1dsgcx 0x10 /* ...1 .... CX - BTAM OR QTAM LINE GROUP @L1A */
#define ds1dsgpo 0x02 /* .... ..1. PO - PARTITIONED ORGANIZATION @L1A */
#define ds1dsgu 0x01 /* .... ...1 U - UNMOVABLE, THE DATA SET @P1C */
/* Values for field "ds1dsorg" Byte 2 */
#define ds1dsggs 0x80 /* 1... .... GS - GRAPHICS ORGANIZATION @L1A */
#define ds1dsgtx 0x40 /* .1.. .... TX - TCAM LINE GROUP @L1A */
#define ds1dsgtq 0x20 /* ..1. .... TQ - TCAM MESSAGE QUEUE @L1A */
#define ds1acbm 0x08 /* .... 1... AM - ACCESS METHOD CONTROL BLOCK@P1C */
#define ds1orgam 0x08 /* .... 1... AM - VSAM DATA SET/SPACE @P1M */
#define ds1dsgtr 0x04 /* .... .1.. TR - TCAM 3705 @L1A */
/* Values for field "ds1recfm" */
#define ds1recff 0x80 /* 10.. .... F - FIXED LENGTH @L3A */
#define ds1recfv 0x40 /* 01.. .... V - VARIABLE LENGTH @L3A */
#define ds1recfu 0xC0 /* 11.. .... U - UNDEFINED LENGTH @L3A */
#define ds1recft 0x20 /* ..1. .... T - TRACK OVERFLOW @L3A */
#define ds1recfb 0x10 /* ...1 .... B - BLOCKED: MAY NOT OCCUR WITH @L3A */
#define ds1recfs 0x08 /* .... 1... FIXED LENGTH: (X'88') @L3A */
#define ds1recfa 0x04 /* .... .10. ANSI CONTROL CHARACTER @L3A */
#define ds1recmc 0x02 /* .... .01. MACHINE CONTROL CHARACTER @L3A */
/* Values for field "ds1optcd" */
#define ds1optic 0x80 /* 1... .... DATA SET CATALOGED IN ICF CTLG @P1C */
#define ds1optbc 0x40 /* .1.. .... DATA SET IS ICF CATALOG @P1C */
/* Values for field "ds1dsind" */
#define ds1ind80 0x80 /* 1... .... LAST VOLUME CONTAINING DATA IN @P1C */
#define ds1ind40 0x40 /* .1.. .... DATA SET IS RACF DEFINED @G60ASBJ */
#define ds1racdf 0x40 /* SAME USE AS BIT DS1IND40 @LBA */
#define ds1ind20 0x20 /* ..1. .... BLOCK LENGTH IS A MULTIPLE @G60ASBJ */
#define ds1ind10 0x10 /* ...1 .... PASSWORD IS REQUIRED TO @G60ASBJ */
#define ds1secty 0x10 /* SAME USE AS BIT DS1IND10 @LBA */
#define ds1ind08 0x08 /* .... 1... DS MODIFIED SINCE RECALL @LDC */
#define ds1ind04 0x04 /* .... .1.. IF DS1IND10 IS 1 THEN @P1C */
#define ds1wrsec 0x04 /* SAME USE AS BIT DS1IND04 @LBA */
#define ds1ind02 0x02 /* .... ..1. DATA SET OPENED FOR OTHER @G60ASBJ */
#define ds1dscha 0x02 /* SAME USE AS BIT DS1IND02 @G60ASBJ */
#define ds1ind01 0x01 /* .... ...1 SECURE CHECKPOINT DATA SET @01C */
#define ds1chkpt 0x01 /* SAME AS DS1IND01 @L3C */
/* Values for field "ds1scal1" */
#define ds1dspac 0xC0 /* XX.. .... BIT PATTERN FOR SPACE REQUEST @L3A */
#define ds1cyl 0xC0 /* 11.. .... CYLINDER REQUEST @L3A */
#define ds1trk 0x80 /* 10.. .... TRACK REQUEST @L3A */
#define ds1avr 0x40 /* 01.. .... AVERAGE BLOCK LENGTH REQUEST @L3A */
#define ds1avrnd 0x41 /* 01.. ...1 AVERAGE BLOCK AND ROUND REQUEST @P1C */
#define ds1msgp 0x20 /* ..1. .... RESERVED (WAS MSGP) @02C */
#define ds1ext 0x10 /* ...1 .... EXTENSION TO SECONDARY SPACE @L4A */
#define ds1contg 0x08 /* .... 1... CONTIGUOUS REQUEST @L3A */
#define ds1mxig 0x04 /* .... .1.. MXIG REQUEST @L3A */
#define ds1alx 0x02 /* .... ..1. ALX REQUEST @L3A */
#define ds1dsabs 0x00 /* 0000 0000 ABSOLUTE TRACK REQUEST @L3A */
struct format3
{
struct
{
unsigned char _ds3keyid[4]; /* KEY IDENTIFIER (X'03030303') */
struct dsextents _ds3extnt[4]; /* FOUR EXTENT DESCRIPTIONS */
unsigned char _ds3fmtid; /* FORMAT IDENTIFIER (X'F3') */
struct dsextents _ds3adext[9]; /* NINE ADDITIONAL EXTENT DESCRIPTIONS */
unsigned char _ds3ptrds[5]; /* FORWARD CHAIN POINTER (CCHHR) @P1C */
} ds3dscb;
} ;
#define ds3keyid ds3dscb._ds3keyid
#define ds3extnt ds3dscb._ds3extnt
#define ds3fmtid ds3dscb._ds3fmtid
#define ds3adext ds3dscb._ds3adext
#define ds3ptrds ds3dscb._ds3ptrds
#define format3Key 0x03030303
/* Values for field "ds3fmtid" */
#define ds3idc 0xF3 /* FORMAT 3 IDENTIFIER @LvA */
#define Format1Size sizeof(struct format1)
#define Format3Size sizeof(struct format3)
/* First Word of the Parameter List */
struct reasonCode
{
char moduleId[2];
char returnCode;
char reasonCode;
} ;
#ifdef __MVS__
#pragma pack(reset)
#endif
/*
1. DEVTYP yes Fixed 4 DEVTYP UCB device type
2. VOLSER yes Character 6 volume serial number.
3. ENTNAME no Character 44 ENTNAME The name of the entry
4. DSCRDT2 no Mixed 4 Creation date. Packed decimal YYDDDF with one byte century indicator
5. ENTYPE no Character 1 ENTYPE Entry type, ex., 'C' is cluster, 'A' is non-VSAM, etc.
6. XHURBADS no Fixed 8 Data-set high-used RBA
7. LRECL no Fixed 4 LRECL Average logical record size
8. VSAMTYPE no Bitstring 2 VSAMTYPE VSAM data set type information
9. VSAMSTAT no fixed 46 Statistics information for VSAM components.
10. AMDKEY no Fixed 4 Relative position of KSDS key for 2 bytes and key
length of KSDS key for 2 bytes
*/
#ifdef __MVS__
#pragma pack(packed)
#endif
/* Second Word of the Parameter List */
struct filterKey
{
char genericFilterKey[44];
char catalogName[44];
char resumeName[44];
char entryTypes[16];
char returnDataorIndex;
char resumeIndicator;
char searchOneCatalogOnly;
char options;
unsigned short NoOfTableEnties;
char fieldName[12][8];
} ;
#ifdef __MVS__
#pragma pack(reset)
#endif
#ifdef __MVS__
#pragma pack(packed)
#endif
// no fixed 46 VSAMSTAT Statistics information for VSAM components.
struct VSAMSTAT
{
char CI_CA_Percentage;
char FreeBytesCI_Percentage;
short int NumberOf_CI_CA;
int Free_CI_CA;
short int Free_bytes_CI;
int NumberOfLogicalRecords;
int NumberOfDeletedRecords;
int NumberOfInsertedRecords;
int NumberOfUpdatedRecords;
int NumberOfRetrievedRecords;
int BytesOfFreeSpaceInComponent;
int NumberOfCISplits;
int NumberOfCASplits;
int NumberOfEXCPs;
} ;
struct KSDSKey
{
short int RKP;
short int length;
} ;
/* Requested Data Return Area */
struct fieldData
{
int devtype_length;
int volser_length;
int name_length;
int createDate_length;
int entryType_length;
int xHurba_length;
int lrecl_length;
int VSAMType_length;
int VSAMStat_length;
int AMDKEY_length;
// Field Data Returned Here
char data[256];
} ;
/* Values for field "flag" */
/* Values for field "type" */
#define catalogtype 0xF0
#define primaryEntry 0x80
#define errorForThisEntry 0x40
#define dataReturnedForThisEntry 0x20
struct catalogEntry
{
char flag;
char type;
char name[44];
int totalDataLength; // Total Length of All Data Returned + This Field Length
char reserved[4];
} ;
/* Values for field "flag" */
#define notsupported 0x80
#define noentryfound 0x40
#define datanotcomplete 0x20
#define wholecatalognotprocessed 0x10
#define catalogpartiallyprocessed 0x08
struct catalogInfo
{
char flag;
char type; // Catalog Type returned by CSI and equal to x'F0'
char name[44];
char moduleId[2];
char reasonCode;
char returnCode;
} ;
/* Third Word of the Parameter List*/
struct workArea
{
int workAreaLength; // User Provided - Size of Work Area Including itself.
int minRequiredLength; // Minimum Required area - Provide by CSI Upon Return
int usedWorkAreaLength; // Actual Space Used by CSI
short numberOfFields; // number of field names + 1
struct catalogInfo _catalogInfo;
struct catalogEntry _catalogEntry;
char _work[65224];
} ;
#ifdef __MVS__
#pragma pack(reset)
#endif
/* For VSAM Type Field */
#define KSDS_type 0x80
#define _not_KSDS_type 0x00
#define RRDS_type 0x02
#define LDS_type 0x04
/* --- Define the IGGCSI00 Program as External With OS Parms -------- */
extern int iggcsi00
(
void * __iggrsn, /* Input - fullword for reason code*/
void * __iggfield, /* Input - selection criteria fields */
void * __iggwork); /* Output - workarea */
#pragma map(iggcsi00, "IGGCSI00")
struct amdKey
{
short int rkp;
short int keyLength;
} ;
struct VSAMAttr
{
char VSAMType;
char datasetIsKSDS;
char datasetIsRRDS;
char datasetIsLDS;
struct amdKey _key;
long long int xhurbads; // Data-set high-used RBA
struct VSAMSTAT _VSAMSTAT;
struct date createDate;
} ;
/* For Field nonVSAMAttr */
#define ActiveGDS 'H'
#define DeferredGDS 'N'
#define RolledOffGDS 'M'
#define PDSE 'L'
#define POSIXDataSet 'P'
#define SimpleNonVSAMDataset 0x00
struct recfm
{
char datasetIsFixed;
char datasetIsVariable;
char datasetIsBlocked;
char datasetIsFixedStandardBks;
char datasetIsVarSpannedBlks;
char datasetIsUnformatted;
char datasetIsASA;
char datasetIsMachine;
char _recfm[4];
} ;
struct extents
{
long long int tracks;
} ;
struct spaceAllocation
{
char isInTrks;
char isInCylinders;
char isInAverageBlock;
int secondary; // secondary allocation in tracks
int used; // Used amount from DLSTAR
int numberOfExtents;
struct extents _extents[16]; // 1st 16 extents
} ;
struct nonVSAMAttr
{
int blksize;
int genLevel;
char dsorg[5];
char allocation[10]; // text 'trks', 'blks', 'cyls'
struct recfm _recfm;
struct date lastReferredDate;
struct spaceAllocation _spaceAllocation;
} ;
/* Parameter List Passed To/ Returned From This Program. */
struct fileStat
{
int size;
int returnCode;
int reasonCode;
int dsnameLength;
char dsname[44]; // Input dataset Name
char volume[6];
char datasetOnIsTape;
char datasetIsOnDASD;
char datasetIsVSAM;
char datasetIsNonVSAM;
char datasetIsGDS;
char datasetIsPDS;
char datasetIsPDSE;
char datasetIsPS;
char datasetIsLargeFormat;
char datsetIsBasicFormat;
char datasetIsExtendedFormat;
char datasetIsHFS;
int lrecl;
long long int approxSize; // Approximate size in bytes
struct ucbtype devtype;
struct date createDate;
// Union Depends on VSAM/Non-VSAM boolean Values
union
{
struct nonVSAMAttr _nonVSAMAttr;
struct VSAMAttr _VSAMAttr;
} ;
} ;
static int obtain(char *, char *, struct format1 *);
static void convertCSIDate(struct csiDate *, struct date *);
static void convertDSCBDate(struct dscbDate *, struct date *);
static void tracks (struct fileStat *, struct dsextents *);
/*
Packed decimal YY DD DD CC for 3 bytes appended with one byte
century indicator. If the century byte is 00 then add
1900 to get the year; if 01, add 2000.
void __unpk (unsigned char *OP1, unsigned char len1, unsigned char *OP2, unsigned char len2)
Operands:
- The format of op2 is changed from signed-packed-decimal to
zoned, and the result is placed at op1 location.
int __oc (unsigned char *OP1, unsigned char *OP2, unsigned char length)
void __cvd(int op1, char *op2);
- op1 is a 32-bit signed binary integer value that gets converted
into a packed-decimal value.
- op2 points to an 8-byte storage area that receives the
converted packed-decimal value.
Length fields for all Assembler instructions follow HLASM conventions of length - 1.
*/
void convertCSIDate(struct csiDate *_packedDate, struct date *_date)
{
long long int x;
char work8[8];
char work3[3];
char work5[5];
int year;
year = 0;
memset(work3, 0, sizeof(work3));
memset(work5, 0, sizeof(work5));
memset(work8, 0, sizeof(work8));
memset(_date, 0, sizeof(struct date));
// YY DD DD CC
#ifdef __MVS__
__unpk ((char*) &work3, 2, (char*) &_packedDate->_dscbDate.ddd, 1);
__oc ((char*) &work3[2], "\xF0", 0);
#endif
memcpy(_date->ddd, &work3, 3);
year = (int) _packedDate->_dscbDate.yy;
if (_packedDate->centuary == 0)
{
year += 6400; // 1900
}
else
{
year += 8192; // 2000
}
year = (year * 16) + 15;
memset(work3, 0, sizeof(work3));
memset(work5, 0, sizeof(work5));
memset(work8, 0, sizeof(work8));
#ifdef __MVS__
__unpk ((char*) &work5, 4, (char*) &year, 3);
__oc ((char*) &work5[4], "\xF0", 0);
#endif
memcpy(_date->year, &work5[1], 4);
}
/*
FORMAT1 DSCB Date Format - 3 bytes
DATA SET CREATION DATE in the format: 'YY DD DD'
in which the year is an offset from 1900, i.e.
1989 is 1900 + 89. The 89 in hex is 59, in
this case January 8, 1989 would be 590008.
*/
void convertDSCBDate(struct dscbDate *_packedDate, struct date *_date)
{
long long int x;
char work8[8];
char work3[3];
char work5[5];
short int ddd;
int year;
year = 0;
memset(work3, 0, sizeof(work3));
memset(work5, 0, sizeof(work5));
memset(work8, 0, sizeof(work8));
memset(_date, 0, sizeof(struct date));
memcpy(&ddd, _packedDate->ddd, 2);
#ifdef __MVS__
// YY DD DD
__cvd(ddd, (char*) &work8);
__unpk ((char*) &work3, 2, (char*) &work8[6], 1);
__oc ((char*) &work3[2], "\xF0", 0);
#endif
memcpy(_date->ddd, &work3, 3);
year = (int) _packedDate->yy;
year += 1900;
#ifdef __MVS__
__cvd(year, (char*) &work8);
__unpk ((char*) &work5, 4, (char*) &work8[5], 2);
__oc ((char*) &work5[4], "\xF0", 0);
#endif
memcpy(_date->year, &work5[1], 4);
}
int trackCalc(struct ucbtype *devtype, unsigned short int lrecl, int *count)
{
int rc;
int balance;
char workarea[256];
memset(&workarea, 0, sizeof(workarea));
#ifdef __MVS__
__asm( (" TRKCALC FUNCTN=TRKCAP,"
"TYPE=%0,"
"R=1,K=0,"
"DD=%1,"
"MF=(E,(%2))")
:
: "m"(devtype->ucb_1_4._ucb4),
"m"(lrecl),
"r"(workarea)
: "r0", "r15"); // clobber list
__asm(" ST 0,%0 "
: "=m"(balance)
:
: "r0", "r15");
__asm(" ST 15,%0 "
: "=m"(rc)
:
: "r15");
#endif
*count = balance;
return rc;
}
/*
Obtain a Format-1 DSCB
Reading a DSCB by Data Set Name
To read one or more DSCBs into virtual storage, use the OBTAIN and CAMLST
macro instructions. Identify the DSCB to be read using the name of the data
set associated with the DSCB. Provide a 140-byte data area in virtual
storage to contain the DSCB.
When you specify the name of the data set, an identifier (format-1, format-4, or format-8)
DSCB is read into virtual storage.
LAB0100 OBTAIN DSCB,NUMBERDSCB=12,EADSCB=OK
LAB0100 LA 1,DSCB load parameter reg
OI 2(1),B'00001000' Set Obtain option flags on
MVI 3(1),12 Set number of possible DSCBs
SVC 27 Issue OBTAIN SVC
WORK DSECT
DSCB CAMLST SEARCH,DSNAME,VOLUME,WORKAREA
DSCB DS 0F align on full word
DC AL1(193) three bytes of flags
DC AL1(0) indicating the function
DC AL1(0) to be performed
DC AL1(0) no option three
DC A(DSNAME) parameter two
DC A(VOLUME) parameter three
DC A(WORKAREA) parameter four
Dsname DC CL44'A.B.C' dsname
Volume DC CL6'770655' volume serial number
workarea DS 12CL140 140-byte work area
DADSM OBTAIN Return Codes
Return Code Description
0(X'00') Successful completion of OBTAIN routine.
4(X'04') The required volume was not mounted.
8(X'08') The format-1 DSCB was not found in the VTOC of the specified volume.
12(X'0C') A permanent I/O error was encountered, or an invalid format-1 DSCB was found
when processing the specified volume, or an unexpected error return code
was received from CVAF (common VTOC access facility).
16(X'10') Invalid work area pointer.
24(X'18') Data set has a format-8 DSCB and EADSCB=NOTOK is in effect
24(X'1C') Internal error with EADSCB=NOTOK in effect.
On return from SEARCH requests, the first 103 bytes of the first 140 byte return
area will contain:
- The 96 byte data portion of the format-1, format-4, or format-8 DSCB
- Followed by 5 bytes that contain the absolute track address (CCHHR) of this
DSCB.
- Followed by a 2 byte count of the total number of DSCBs associated with the
data set DSCB, even if there are insufficient return areas into which to read them
all. This count includes all DSCB types that could describe a data set. Set to
zero for DSCBs constructed from catalog when DSCBs are not present in the
VTOC.
*/
int obtain(char *dsname, char *volume, struct format1 *_dscb)
{
int rc;
char workarea[1680];
struct camlist
{
unsigned char field1;
unsigned char flag1;
unsigned char flag2;
unsigned char flag3;
void *dsname;
void *volume;
void *workarea;
} ;
struct camlist _work;
memset(&_work, 0, sizeof(struct camlist));
memset(&workarea, 0, sizeof(workarea));
_work.field1 = 193;
_work.dsname = dsname;
_work.volume = volume;
_work.workarea = &workarea;
#ifdef __MVS__
__asm(" LR 1,%0 load parameter reg 1\n"
" OI 2(1),B'00001000' set obtain option flags off\n"
" MVI 3(1),12 set number of possible dscbs\n"
" SVC 27 issue OBTAIN SVC\n"
:
: "r"(&_work)
: "r1");
__asm(" ST 15,%0 "
: "=m"(rc)
:
: "r0", "r1", "r14", "r15");
#endif
memcpy(_dscb, _work.workarea, sizeof(workarea));
return rc;
}
int nonVSAMDataset(struct fileStat *_fileStatData, struct workArea *_workAreaPtr)
{
_Bool _continue;
char dsname[ZOS_FILESIZE];
char volume[6];
int secondary;
int count;
int dscbCount;
int i;
int lengthRemaining;
int rc;
int totalDataLength;
unsigned char r;
unsigned char recfm;
unsigned long long blksize2;
unsigned long long int used2;
unsigned short int blksize;
unsigned short int lrecl;
unsigned short int used;
void *dataPtr;
struct date createDate;
struct date referredDate;
struct fieldData *_fieldData;
struct format1 _dscb[12];
struct format3 *_dscb3;
memset(&_dscb, 0, sizeof(_dscb));
memset(&createDate, 0, sizeof(struct date ));
memset(&referredDate, 0, sizeof(struct date ));
/*
CSI Returns
1. devtype
2. volser
3. name
Total Length Field is equal to the length of the length field +
the total length of the length fields +
the total length of the data fields.
*/
rc = 0;
dscbCount = 0;
count = 0;
lrecl = 0;
totalDataLength = 0;
_fileStatData->datasetIsNonVSAM = true;
_fieldData = (struct fieldData *) &_workAreaPtr->_work;
dataPtr = &_fieldData->data;
totalDataLength = _workAreaPtr->_catalogEntry.totalDataLength;
if (!_workAreaPtr->_catalogEntry.flag & dataReturnedForThisEntry)
{
return 4;
}
if (totalDataLength <= 0)
{
return 4;
}
lengthRemaining = totalDataLength;
// Process CSI Fields
if (_fieldData->devtype_length > 0)
{
memcpy(&_fileStatData->devtype, dataPtr, _fieldData->devtype_length);
dataPtr += _fieldData->devtype_length;
lengthRemaining -= _fieldData->devtype_length;
lengthRemaining -= 4;
// Use UCB Information to determine if tape or dasd dataset
if (_fileStatData->devtype.ucb_1_4._ucb3 & tape_device)
{
_fileStatData->datasetOnIsTape = true;
}
else if (_fileStatData->devtype.ucb_1_4._ucb3 & dasd_device)
{
_fileStatData->datasetIsOnDASD = true;
}
}
if ((_fieldData->volser_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->volume, dataPtr, _fieldData->volser_length);
dataPtr += _fieldData->volser_length;
lengthRemaining -= _fieldData->volser_length;
lengthRemaining -= 4;
}
if ((_fieldData->name_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->dsname, dataPtr, _fieldData->name_length);
_fileStatData->dsnameLength = _fieldData->name_length;
dataPtr += _fieldData->name_length;
lengthRemaining -= _fieldData->name_length;
lengthRemaining -= 4;
}
if (lengthRemaining < 0)
{
return 4;
}
// Use OBTAIN to retrieve Format-1 DSCB
if ((_fileStatData->dsnameLength > 0) && (_fileStatData->datasetIsOnDASD == true))
{
rc = obtain((char*) &_fileStatData->dsname, (char*) &_fileStatData->volume,
(struct format1*) &_dscb);
}
else
{
return 0;
}
// Check for Format 1 ('1') or Format 8 ('8') DSCB
if ((_dscb[0].ds1fmtid != ds1idc) &&
(_dscb[0].ds1fmtid != ds8idc))
{
return 4;
}
// DSORG - 2 byte field
if ((_dscb[0].ds1dsorg1 & ds1dsgpo) &&
!(_dscb[0].ds1smsfg & ds1pdse) &&
!(_dscb[0].ds1smsfg & ds1pdsex))
{
_fileStatData->datasetIsPDS = true;
strncpy(_fileStatData->_nonVSAMAttr.dsorg, "PO", 4);
}
else if ((_dscb[0].ds1smsfg & ds1pdse) &&
!(_dscb[0].ds1smsfg & ds1pdsex))
{
_fileStatData->datasetIsPDSE = true;
strncpy(_fileStatData->_nonVSAMAttr.dsorg, "PO-E", 4);
}
else if ((_dscb[0].ds1smsfg & ds1pdse) && (_dscb[0].ds1smsfg & ds1pdsex))
{
_fileStatData->datasetIsHFS = true;
strncpy(_fileStatData->_nonVSAMAttr.dsorg, "HFS", 4);
}
else if (_dscb[0].ds1dsorg1 & ds1dsgps)
{
_fileStatData->datasetIsPS = true;
strncpy(_fileStatData->_nonVSAMAttr.dsorg, "PS", 4);
}
recfm = _dscb[0].ds1recfm;
_continue = true;
// Test for VBS or FBS
// VBS - Variable Blocked Spanned
if ((recfm & ds1recfv) && (recfm & ds1recfs))
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsVarSpannedBlks = true;
strncpy(_fileStatData->_nonVSAMAttr._recfm._recfm, "VBS", 4);
_continue = false;
}
// FBS - Fixed Blocked Standard
else if ((recfm & ds1recfv) && (recfm & ds1recff))
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsFixedStandardBks = true;
strncpy(_fileStatData->_nonVSAMAttr._recfm._recfm, "FBS", 4);
_continue = false;
}
if (_continue)
{
// First Output Byte - 'F', 'V', or 'U'
if ((recfm & 0x80) && (recfm & 0x40))
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsUnformatted = true;
_fileStatData->_nonVSAMAttr._recfm._recfm[0] = 'U';
}
else if (recfm & ds1recff)
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsFixed = true;
_fileStatData->_nonVSAMAttr._recfm._recfm[0] = 'F';
}
else if (recfm & ds1recfv)
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsVariable = true;
_fileStatData->_nonVSAMAttr._recfm._recfm[0] = 'V';
}
// Second Output Byte - 'B'
if (recfm & ds1recfb)
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsBlocked = true;
_fileStatData->_nonVSAMAttr._recfm._recfm[1] = 'B';
}
// Second or Third Output Byte - 'A', 'M'
if (recfm & ds1recfa)
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsASA = true;
strncat(_fileStatData->_nonVSAMAttr._recfm._recfm, "A", 1);
}
else if (recfm & ds1recmc)
{
_fileStatData->_nonVSAMAttr._recfm.datasetIsMachine = true;
strncat(_fileStatData->_nonVSAMAttr._recfm._recfm, "M", 1);
}
}
if ((_dscb[0].ds1scal1 & 0x80) && (_dscb[0].ds1scal1 & 0x40))
{
_fileStatData->_nonVSAMAttr._spaceAllocation.isInCylinders = true;
strncpy(_fileStatData->_nonVSAMAttr.allocation, "Cylinders", 10);
}
else if (_dscb[0].ds1scal1 & ds1trk)
{
_fileStatData->_nonVSAMAttr._spaceAllocation.isInTrks = true;
strncpy(_fileStatData->_nonVSAMAttr.allocation, "Tracks", 10);
}
else if (_dscb[0].ds1scal1 & ds1avr)
{
_fileStatData->_nonVSAMAttr._spaceAllocation.isInAverageBlock = true;
strncpy(_fileStatData->_nonVSAMAttr.allocation, "Blocks", 10);
}
_fileStatData->lrecl = _dscb[0].ds1lrecl;
_fileStatData->_nonVSAMAttr.blksize = _dscb[0].ds1blkl;
convertDSCBDate(&_dscb[0].ds1credt, &createDate);
convertDSCBDate(&_dscb[0].ds1refd, &referredDate);
_fileStatData->createDate = createDate;
_fileStatData->_nonVSAMAttr.lastReferredDate = referredDate;
secondary = 0;
memcpy(&secondary, &_dscb[0].ds1scalo, 4);
secondary &= 0x00ffffff;
used = 0;
r = 0;
r = _dscb[0].ds1lstar[2];
memcpy(&used, _dscb[0].ds1lstar, 2);
_fileStatData->_nonVSAMAttr._spaceAllocation.used = used;
blksize = _fileStatData->_nonVSAMAttr.blksize;
_fileStatData->_nonVSAMAttr._spaceAllocation.secondary = secondary;
// Determine Number of blocks on track
rc = trackCalc(&_fileStatData->devtype, blksize, &count);
if (rc == 0)
{
used2 = (unsigned long long int) used;
blksize2 = (unsigned long long int) blksize;
_fileStatData->approxSize = used2 * blksize2 * count + (unsigned int) (r * blksize);
}
// Total allocation for first 16 extents
// Extents 1 - 3 are in Format 1 DSCB
for (i = 0; i < 3; i++)
{
tracks(_fileStatData, &_dscb[0].ds1ext1[i]);
}
dscbCount = _dscb[0].extension.dscbCnt;
// Check DSCB Count
if (dscbCount == 1)
{
return 0;
}
_dscb3 = (struct format3 *) &_dscb[1];
// Check for Format Identifier of '3'
if (_dscb3->ds3fmtid != ds3idc)
{
return 0;
}
// Extents 4 - 16 are in Format 3 DSCB - discontiguous
for (i = 0; i < 4; i++)
{
tracks(_fileStatData, &_dscb3->ds3dscb._ds3extnt[i]);
}
for (i = 0; i < 9; i++)
{
tracks(_fileStatData, &_dscb3->ds3dscb._ds3adext[i]);
}
return rc;
}
int VSAMDataset(struct fileStat *_fileStatData, struct workArea *_workAreaPtr)
{
int lengthRemaining;
int totalDataLength;
char *dataPtr;
struct csiDate tmpDate;
char vsamType[2];
char entryType;
struct fieldData *_fieldData;
struct catalogEntry *_catalogEntry;
_fileStatData->datasetIsVSAM = true;
/*
CSI Returns
1. devtype
2. volser
3. name
4. createDate
5. entryType
6. xHurba
7. lrecl
8. VSAMType
9. VSAMStat
10. AMDKEY
*/
_fileStatData->datasetIsOnDASD = true;
if (!_workAreaPtr->_catalogEntry.flag & dataReturnedForThisEntry)
{
return 4;
}
if (_workAreaPtr->usedWorkAreaLength <= 0)
{
return 4;
}
// Check to see if this is a VSAM Cluster
if (_workAreaPtr->_catalogEntry.type != 'C')
{
return 4;
}
/* Set data pointer to start of Catalog Entry area.
1st Entry is for Cluster.
2nd Entry is for Data Component.
3rd Entry is for Index Component.
*/
// Use Cluster Name for Returned Data Set Name
memcpy(&_fileStatData->dsname, _workAreaPtr->_catalogEntry.name, ZOS_FILESIZE);
// Point to 1st Catalog Entry - Cluster
dataPtr = (char*) &_workAreaPtr->_catalogEntry;
// Point to 2nd Catalog Entry - Data Component
dataPtr += _workAreaPtr->_catalogEntry.totalDataLength;
dataPtr += 46;
_catalogEntry = (struct catalogEntry *) dataPtr;
totalDataLength = _workAreaPtr->_catalogEntry.totalDataLength;
dataPtr += 46;
dataPtr += 8;
_fieldData = (struct fieldData *) dataPtr;
lengthRemaining = totalDataLength;
dataPtr = (char*) &_fieldData->data;
// Process CSI Fields
if ((_fieldData->devtype_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->devtype, dataPtr, _fieldData->devtype_length);
dataPtr += _fieldData->devtype_length;
lengthRemaining -= _fieldData->devtype_length;
lengthRemaining -= 4;
}
if ((_fieldData->volser_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->volume, dataPtr, _fieldData->volser_length);
dataPtr += _fieldData->volser_length;
lengthRemaining -= _fieldData->devtype_length;
lengthRemaining -= 4;
}
if ((_fieldData->name_length > 0) && (lengthRemaining > 0))
{
// Don't Move Data Component Name.
dataPtr += _fieldData->name_length;
_fileStatData->dsnameLength = _fieldData->name_length;
lengthRemaining -= _fieldData->name_length;
lengthRemaining -= 4;
}
if ((_fieldData->createDate_length > 0) && (lengthRemaining > 0))
{
memcpy(&tmpDate, dataPtr, _fieldData->createDate_length);
convertCSIDate(&tmpDate, &_fileStatData->_VSAMAttr.createDate);
dataPtr += _fieldData->createDate_length;
lengthRemaining -= _fieldData->createDate_length;
lengthRemaining -= 4;
}
if ((_fieldData->entryType_length > 0) && (lengthRemaining > 0))
{
entryType = 'C';
dataPtr += _fieldData->entryType_length;
lengthRemaining -= _fieldData->entryType_length;
lengthRemaining -= 4;
}
if ((_fieldData->xHurba_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->_VSAMAttr.xhurbads, dataPtr, _fieldData->xHurba_length);
dataPtr += _fieldData->xHurba_length;
lengthRemaining -= _fieldData->xHurba_length;
lengthRemaining -= 4;
}
if ((_fieldData->lrecl_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->lrecl, dataPtr, _fieldData->lrecl_length);
dataPtr += _fieldData->lrecl_length;
lengthRemaining -= _fieldData->lrecl_length;
lengthRemaining -= 4;
}
if ((_fieldData->VSAMType_length > 0) && (lengthRemaining > 0))
{
memcpy(&vsamType, dataPtr, _fieldData->VSAMType_length);
lengthRemaining -= _fieldData->VSAMType_length;
lengthRemaining -= 4;
if (vsamType[0] & KSDS_type)
{
_fileStatData->_VSAMAttr.datasetIsKSDS = true;
_fileStatData->_VSAMAttr.VSAMType = 'K';
}
else if (vsamType[0] & RRDS_type)
{
_fileStatData->_VSAMAttr.datasetIsRRDS = true;
_fileStatData->_VSAMAttr.VSAMType = 'R';
}
else if (vsamType[1] & LDS_type)
{
_fileStatData->_VSAMAttr.datasetIsLDS = true;
_fileStatData->_VSAMAttr.VSAMType = 'L';
}
else if (vsamType[0] & _not_KSDS_type)
{
_fileStatData->_VSAMAttr.VSAMType = 'E';
}
}
if ((_fieldData->VSAMStat_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->_VSAMAttr._VSAMSTAT, dataPtr, _fieldData->VSAMStat_length);
dataPtr += _fieldData->VSAMStat_length;
lengthRemaining -= _fieldData->VSAMStat_length;
lengthRemaining -= 4;
}
if ((_fieldData->AMDKEY_length > 0) && (lengthRemaining > 0))
{
memcpy(&_fileStatData->_VSAMAttr._key, dataPtr, _fieldData->AMDKEY_length);
dataPtr += _fieldData->AMDKEY_length;
lengthRemaining -= _fieldData->AMDKEY_length;
lengthRemaining -= 4;
}
_fileStatData->approxSize = _fileStatData->lrecl *
_fileStatData->_VSAMAttr._VSAMSTAT.NumberOfLogicalRecords;
return 0;
}
void tracks (struct fileStat *_fileStatData,
struct dsextents *_extent)
{
unsigned int trackLow;
unsigned int trackUpper;
unsigned int tracks;
int index;
trackLow = 0;
trackUpper = 0;
tracks = 0;
trackLow = (_extent->ext.Format2.ds1extLowerLimitCC * TRACKS_PER_CYLINDER) +
_extent->ext.Format2.ds1extLowerLimitHH;
trackUpper = (_extent->ext.Format2.ds1extUpperLimitCC * TRACKS_PER_CYLINDER) +
_extent->ext.Format2.ds1extUpperLimitHH;
tracks = trackUpper - trackLow;
index = _fileStatData->_nonVSAMAttr._spaceAllocation.numberOfExtents;
if (trackLow > 0)
{
tracks++;
_fileStatData->_nonVSAMAttr._spaceAllocation._extents[index].tracks = tracks;
_fileStatData->_nonVSAMAttr._spaceAllocation.numberOfExtents++;
}
}
int GDSDataset(struct fileStat *_fileStatData, struct workArea *_workAreaPtr)
{
int rc;
_fileStatData->datasetIsGDS = true;
rc = nonVSAMDataset(_fileStatData, _workAreaPtr);
return rc;
}
/* This Routine Performs a CSI Catalog Search for 1 Dataset
Return Codes for General Purpose Register 15
On return, general-purpose register 15 can contain the following:
Return Code Description
0 No errors or return messages
4 Information was returned from Catalog Management processing.
Further information is returned in the 4-byte reason area pointed to
by the first address in the parameter list.
8 Failure in Catalog Search Interface routine. Further information is
returned in the 4-byte reason area pointed to by the first address in
the parameter list.
C Error in Catalog Search Interface routine parameter list - check for
zero entries.
10 Parameter list pointer in general-purpose register 1 is zero.
Return Codes 100 and 122
Return
Code Description/Programmer Response
100 Catalog Management has detected an error while processing the request.
• Reason Code 4: at least one data set entry is returned with an error.
• Reason Code 8: at least one catalog entry is returned with an error.
• Reason Code 4: locate the entry or entries with the CSIENTER flag set and inspect the
CSIRETN field for further information.
• Reason Code 8: inspect the return code and reason code for the catalog entry for further information.
122 An invalid filter key was provided. For all reason codes: fix filter key and resubmit.
Note: This return code may also indicate an invalid data set name in the catalog being searched.
Valid types for CSIDTYPS are:
Type Description
A non-VSAM data set
B Generation data group
C Cluster
G Alternate index
H Generation data set
L Tape volume catalog library entry
R VSAM path
U User catalog connector entry
W Tape volume catalog volume entry
X Alias
*/
extern int fileStat(struct fileStat *_fileStat)
{
char dsname[64];
int i;
int rc;
int returnCode;
_Bool continueProcessing;
struct reasonCode _reasonCode;
struct filterKey _filterKey;
struct workArea _workArea;
returnCode = 0;
continueProcessing = true;
memset(dsname, 0, sizeof(dsname));
// Only Parameter Supplied by Calling Program is dsname
memcpy(dsname, _fileStat->dsname, ZOS_FILESIZE);
memset(_fileStat, 0, sizeof(struct fileStat));
_fileStat->size = sizeof(struct fileStat);
// CSI Sets Return Code / Reason Code Fields
memset(&_reasonCode, 0, sizeof(struct reasonCode));
// Caller Supplies Filter Key
memset(&_filterKey, ' ', sizeof(struct filterKey));
// Allocate for CSI Data Returned Area
memset(&_workArea, 0, sizeof(struct workArea));
_workArea.workAreaLength = WorkAreaSize;
memcpy(_filterKey.genericFilterKey, _fileStat->dsname, ZOS_FILESIZE);
memcpy(_filterKey.entryTypes, "ACH ", 16);
_filterKey.returnDataorIndex = 'Y';
_filterKey.options = 'F'; // Return Fullword Lengths
_filterKey.NoOfTableEnties = 10;
/* Fields to be Returned From CSI Call */
memcpy(_filterKey.fieldName[0], "DEVTYP ", 8);
memcpy(_filterKey.fieldName[1], "VOLSER ", 8);
memcpy(_filterKey.fieldName[2], "ENTNAME ", 8);
memcpy(_filterKey.fieldName[3], "DSCRDT2 ", 8);
memcpy(_filterKey.fieldName[4], "ENTYPE ", 8);
memcpy(_filterKey.fieldName[5], "XHURBADS", 8);
memcpy(_filterKey.fieldName[6], "LRECL ", 8);
memcpy(_filterKey.fieldName[7], "VSAMTYPE", 8);
memcpy(_filterKey.fieldName[8], "VSAMSTAT", 8);
memcpy(_filterKey.fieldName[9], "AMDKEY ", 8);
#ifdef __MVS__
// Call to z/OS CSI
returnCode = iggcsi00((void*) &_reasonCode, (void*) &_filterKey, (void*) &_workArea);
#endif
switch (returnCode)
{
case 0:
case 4:
{
continueProcessing = true;
break;
}
case 8:
case 12:
case 16:
{
continueProcessing = false;
_fileStat->returnCode = returnCode;
_fileStat->reasonCode = _reasonCode.reasonCode;
break;
}
default:
{
continueProcessing = false;
_fileStat->returnCode = returnCode;
_fileStat->reasonCode = _reasonCode.reasonCode;
break;
}
}
// Check for catalog name entry
if (_workArea._catalogInfo.type != 0xf0)
{
continueProcessing = false;
}
if (!continueProcessing)
{
return 8;
}
/*
Type Description
A non-VSAM data set
B Generation data group
C Cluster
H Generation data set
*/
switch (_workArea._catalogEntry.type)
{
// Non-VSAM Dataset
case 'A':
{
returnCode = nonVSAMDataset(_fileStat, &_workArea);
break;
}
// VSAM Cluster
case 'C':
{
returnCode = VSAMDataset(_fileStat, &_workArea);
break;
}
// Generation Dataset
case 'H':
{
returnCode = GDSDataset(_fileStat, &_workArea);
break;
}
default:
{
returnCode = 8;
}
}
return returnCode;
}