MVS TOOLS AND TRICKS OF THE TRADE September 1991 Sam Golob MVS Systems Programmer sbgolob@cbttape.org EXPLOITING PARTITIONED DATASET DIRECTORY FIELDS - PART I. This month, I'd like to talk about utilizing information contained in partitioned dataset directory entries. The fields and bits in the directory, especially in the directory entries of a load module library, contain crucial information that is used by the MVS operating system. Knowing about these fields can help you in some startling ways. It may not have occurred to you to look in such a place for help in problem situations. That's why I thought it appropriate to mention the subject here in the "tools and tricks" column, rather than in a separate tutorial article. We shall try to point out some cases where information from directory entry fields will make a great impact on our effective work as systems programmers. As is well known, "source-type" partitioned datasets have very different directory entries than do "load libraries" which contain executable load modules as their members. We therefore shall discuss these different types of partitioned datasets separately, concentrating in areas where the most "gain by manipulation" is to be had. We shall discuss "source-type" pds members that have "ISPF statistics" in their directory entries as opposed to members that don't have stats. This subject will be continued next month. FUNDAMENTALS - THE STRUCTURE OF PARTITIONED DATASET DIRECTORIES. The partitioned dataset directory is located at the beginning of the first disk extent for a partitioned dataset. Although the DCB attributes of the DATA in a partitioned dataset will vary, the external physical structure of the DIRECTORY does not vary. The directory of a pds consists of "directory blocks" and "directory entries". The directory blocks of a pds may be conceptualized as the "physical" part of the pds directory. Considered as raw data, each directory block is of fixed length, and is 255 bytes long with a 9-byte key--264 bytes in all. The size of a directory block is fixed by the architecture of partitioned datasets, and is not subject to user software control, for all practical purposes. Each directory block contains a number of directory entries of variable length. The directory entries, in contrast to the directory blocks, may be pictured conceptually as the "logical" part of the directory data. We say "logical", because the contents of the directory entries is variable, and is subject to much more software control. Our discussion will be concerned with directory entries, which contain information that is useful for our needs as programmers. There is exactly one directory entry for each member of a pds. Each directory entry defines an area of data in the physical pds data extents, as belonging to one member. A pointer field in the pds directory entry points to the start of each member, while an EOF (end-of-file) marker in the data itself, defines the end of that member. Some fields of each directory entry are required by pds design. These fields constitute the first 12 bytes of any directory entry. An example of a required field is the TTR pointer in the directory entry which points to the start of that member's data. The 'TTR' is the "relative track and record number for a data record, starting from the beginning of the dataset". Another required field is the 8-byte member name in the directory entry. Every pds directory has to contain a member name and a TTR pointer to the beginning of that member's data. The last required field in a directory entry is a flag byte. Descriptions of the required flag byte will be found in the Figures. The required fields may, or may not, be followed by user-defined directory entry fields of variable length, to a maximum of 62 bytes. User fields, while not required by general pds structure, are created by an MVS component which uses the pds structure as a base for its own requirements. The most notable example of MVS component use of user fields, is the load library, whose "data" consists of executable programs, or "load modules". PDS directory entries for load library members contain far more 'required' user fields than do most other pds directory entries. The MVS component called "program fetch" utilizes those extra load library directory entry fields to affect program execution of the load module. In this article we will learn how to take advantage of the accessibility of these directory entry fields to us. We may be able to fix load modules, for example, without having to re-linkedit them. Merely flipping one or more directory entry bits could accomplish the fix that we need. SOME QUICK EXAMPLES. Let's whet your appetite by showing a few examples. Load module linkedit attributes are all reflected in the directory entry user fields. If you were linkediting a module, and you forgot to mention 'RENT' in the linkedit parms, you need only go to the 'reentrancy' and 'reusability' bits of the module's directory entry and turn those bits on. That will have the same effect as if the linkage editor turned them on when it was creating the member. Similarly, if a module had to be authorized, and you forgot to say "SETCODE AC(1)" in the linkage editor control statements, you need only go to the directory entry of the module and turn the proper "auth" bit on. In all of these cases, you do not have to re-linkedit the module. Similar considerations apply if those attributes needed to be turned off. Knowing these facts can save you a lot of work. HOW TO START LEARNING ABOUT DIRECTORY ENTRY FIELDS. The macro IHAPDS (in SYS1.AMODGEN) describes many (but not all) types of pds directory entry fields. You can find a description of many directory entry fields in the IBM manual, "SPL Debugging Handbook" under entries: "PDS" and "PDS2". In MVS/ESA, the equivalent manuals are: "MVS/ESA Diagnosis: Data Areas". Because in many cases, directory entry fields are user-defined or application-defined, a single IBM descriptive macro cannot cover all the ground. In particular, ISPF directory entry field descriptions are not too readily available (see Figure Three). I am providing some descriptions of directory entry fields here. (See Figures One thru Three). These descriptions were taken from the source member @DIALOG of the PDS product Version 8.4, on the CBT MVS Utilities Tape, File 182. It is hoped that these descriptions will be sufficient to help the reader learn this material. Let's begin by learning about the required directory entry fields. These comprise 12 bytes. In other words, a single directory entry has to be at least 12 bytes long. The first eight bytes of a directory entry consist of the member name, left justified. It is necessary that all directory entries be sorted ascendingly in member name order. Therefore, some directory entries need to be rearranged each time a new member is added. This is an overhead-consuming process. The next 3-byte field is a relative TTR pointer to the beginning of that member's data. Finally, there is a 1-byte field, "officially" consisting of binary flags. This flag byte is crucial to the rest of the directory entry, so we shall study this byte in more detail. Look at Figure Two. The high-order bit, X'10000000' of the flag byte, is turned on to mark the member as an alias member. Strictly speaking, although the purpose of an alias member is to provide an alternate name for a main member, any pds member can theoretically be flagged as an "alias" if this bit is on. For load modules, the alias bit on will be accompanied by a user field (the "real member name" field) containing the name of a "main member", filled in by the linkage editor at the time of alias creation. The next two bits, X'01100000', are relevant to load module directory entries. All load modules contain one extra TTR location, which is the TTR of the first TEXT record, needed by MVS program fetch. For certain load modules such as OVERLAY modules and SCATTER LOADED modules, extra control records must be available to ensure their proper functioning. Notelist tables (for OVERLAY) and scatter tables (for SCATTER) may be imbedded amongst the load module text data. In order to be found, these tables need an extra TTR pointer in user fields of the module's directory entry. The second bit of the flag byte, turned on, denotes that two extra TTR pointers need to be constantly updated for the load module member. The third bit on, denotes that only one extra TTR pointer needs to be continually kept track of for that member. The last five bits in the flag byte denote a binary quantity that varies from 0 thru 31. That denotes the number of halfwords of user data which will be appended to the required 12 bytes of the directory entry. This is clear enough. As many as 62 bytes of user data may be added to the minimum 12 bytes. ISPF STATISTICS IN A SOURCE-TYPE MEMBER. A pds member that was edited by the ISPF editor, receives "ISPF statistics" in its directory entry when the member is saved. The statistics consist of 28 extra bytes of user data appended to the first 12 bytes. When ISPF statistics are present, required flag bits X'00001111' might be turned on; also bits X'01110000' should be turned off. This should be a fairly accurate test for the presence of ISPF statistics. (Hint is courtesy of Steve Smith). These statistics (or most of them) are displayed during an ISPF member listing for non-load type members, and are familiar to many of us. A DSECT-type description of the "ISPF" user directory fields is at the bottom of Figure Three. During study of Figure Three, it will become apparent how to change any of the statistics in the directory. We must somehow be able to display them in their native format, and then zap the changes in. ISPF Option 3.5, which changes the contents of some of these directory fields, actually does this zapping for us. Source-type pds members that don't have ISPF stats, usually have just 12-byte directory entries, with the lower five bits of the required flag byte set to zeros. It is apparent that the process of adding ISPF statistics to a member that didn't have them, is not trivial. A re-creation of the directory entry, possibly through the use of the STOW macro, becomes necessary. Directory space consumed, for the same number of members, will have to increase noticeably. We've come to the end of our time for this month. Next month, I'll go into more detail about the STOW macro, ISPF statistics alteration, and load module directory user fields. Good luck. * * * * * * * * * * * * * * * * * * * * * * FIGURE ONE. DSECT Descriptions of Partitioned Dataset Directory Entries. The required portion of the directory entry (first 12 bytes) is shown here. This description was mostly taken from source code for the "PDS Program Product, Version 8.4", which can be found on File 182 of the CBT MVS Utilities Tape, member @DIALOG. You can refer to the macro IHAPDS in SYS1.AMODGEN for "IBM Official" field names. DIRLINK DS 0F *** DIRECTORY AREA MAPPING *** * DIRNAME DS CL8 Member Name DIRTTR DS XL3 TTR of beginning of the Member DIRFLAG DS X Contains 3 flags in high-order bits. * Low-order 5 bits contain number of * halfwords in user-defined fields to * follow this point (62 bytes maximum). * DIRALIAS EQU X'80' This member is an alias. DIR2TTR EQU X'40' Two TTR's to update DIR1TTR EQU X'20' One TTR to update * DIRUSER DS XL62 Maximum length of directory entry * user fields. Actual length depends on * the number of halfwords indicated by * the 5 low-order bits of DIRFLAG * (the 12th byte of the directory entry). * * * * * * * * * * * * * * * * * * * * * * FIGURE TWO. A DSECT Description of Partitioned Dataset Directory Entries for Load Modules. Load modules use the User Fields of the directory entry in a special way, that is defined by the Linkage Editor and the MVS Program Fetch component. Labels in this illustration are from source code in the PDS V8.4 product, module @DIALOG. This source code is on the CBT Tape, File 182. For more standard names, see macro IHAPDS on SYS1.AMODGEN. DIRLINK DS 0F *** DIRECTORY AREA MAPPING *** * DIRNAME DS CL8 Member Name DIRTTR DS XL3 TTR of beginning of the Member DIRFLAG DS X Flags for required direntry fields. * DIRCALIS EQU B'10000000' This member is an alias. DIRCTTRN EQU B'01100000' There is more than 1 TTR to update DIRCUDHW EQU B'00011111' Halfword count bits. Size of user bytes. * DIRUSER DS XL62 Directory USER Fields * ORG DIRUSER FOLLOWING FOR LOAD MODULES DIRSTART DS XL4 TTR of first Text block DIRNOTE DS XL3 TTR of Notelist DIRNOTE# DS X Number of Notelist entries DIRATTR DS XL2 Member Attributes * EQUATES for First Byte ORG DIRATTR DIRAT1ST DS X DIRRENT EQU B'10000000' Reentrant DIRREUS EQU B'01000000' Reusable DIROVLY EQU B'00100000' Overlay Module DIRTEST EQU B'00010000' Test DIRLOAD EQU B'00001000' Only Loadable DIRSCTR EQU B'00000100' Scatter Load DIREXEC EQU B'00000010' Executable DIRF1 EQU B'00000001' * EQUATES for Second Byte ORG DIRATTR+1 DIRAT2ND DS X DIRNODC EQU B'10000000' Not DC (Downward Compatible) DIRF2 EQU B'01000000' DIRF3 EQU B'00100000' DIRF4 EQU B'00010000' DIRNOED EQU B'00001000' Not Editable DIRF5 EQU B'00000100' DIRLKEDF EQU B'00000010' F Level Linkage Editor DIRREFR EQU B'00000001' Refreshable * DIRSTORE DS XL3 Size of Load Module DIRTEXTL DS XL2 Length of 1st Text Record DIREPA DS XL3 Entry Point Address * DIRATTR2 DS X ADDITIONAL ATTRIBUTE BYTES: DIRAOSLE EQU B'10000000' VS Linkage Editor created this module DIR2PAGA EQU B'00100000' Page Alignment is required DIR2SSI EQU B'00010000' SSI Information present for module DIRAPFLG EQU B'00001000' APF Information for this module is valid * DIRATTR3 DS X ADDITIONAL ATTRIBUTE BYTES: DIRRMANY EQU B'00010000' RMODE=ANY DIRAA31 EQU B'00001000' AMODE=31 (Alias entry) DIRAA24 EQU B'00000100' AMODE=24 (Alias entry) DIRAM31 EQU B'00000010' AMODE=31 (Main entry) DIRAM24 EQU B'00000001' AMODE=24 (Main entry) * DIRATTR4 DS X Count of RLD Entries after first Text * DIRAPF DS 0XL2 APF (If not SCATTER, SSI or ALIAS) DIREP DS XL3 Entry Point of Main Member DIRREAL DS CL8 Real Name of Member DIRAPF2 DS XL2 APF Information (ALIAS, no SCAT or SSI) DIREND2 EQU * End of ALIAS Section * ORG DIRAPF FOLLOWING IS FOR SCATTER LOADED MODULES. DIRSCLL DS XL2 Length of Scatter List DIRSCTL DS XL2 Length of Translate Table DIRSCET DS XL2 ESDID of First Text Record DIRSCEP DS XL2 ESDID of Entry Point DIRAPF3 DS 0XL2 APF Info (If SCATTER, no SSI and no ALIAS) DIREPSC DS XL3 Entry Point (Main Membewr) DIRREALS DS CL8 Real Name of Member DIRAPF4 DS XL2 APF Info (SCATTER, no SSI and ALIAS) DIREND3 EQU * End of SCATTER, ALIAS Section * * * * * * * * * * * * * * * * * * * * * * FIGURE THREE. DSECT Description of Partitioned Dataset Directory Entries for Source-type members which have "ISPF Statistics". ISPF Statistics are merely a special use of partitioned dataset directory user fields. DIRLINK DS 0F *** DIRECTORY AREA MAPPING *** * DIRNAME DS CL8 Member Name DIRTTR DS XL3 TTR of beginning of the Member DIRFLAG DS X Contains 3 flags in high-order bits. * Low-order 5 bits contain number of * halfwords in user-defined fields to * follow this point (62 bytes maximum). * DIRALIAS EQU X'80' This member is an alias. DIR2TTR EQU X'40' Two TTR's to update DIR1TTR EQU X'20' One TTR to update DIRSPFOF EQU B'01110000' BITS ARE OFF IN ISPF STATS. DIRSPFON EQU B'00001111' BITS ARE ON IN ISPF STATS. * DIRUSER DS XL62 Directory Entry User Fields. 62 bytes max. (28 Bytes are used by ISPF Stats) * ORG DIRUSER FOLLOWING FOR MODULES SAVED BY ISPF EDIT. DIRSPFV DS XL1 Version Number in Binary DIRSPFR DS XL1 Revision Number in Binary DIRSPFZ DS XL2 Not currently used DIRSPFCR DS XL4 Creation Date in format 00YYDDDF DIRSPFCD DS XL4 Last Change Date in format 00YYDDDF DIRSPFCT DS XL2 Last Change Time in format HHMM DIRSPFSI DS XL2 Current Size in Binary (max 65535) DIRSPFIN DS XL2 Initial Size in Binary DIRSPFMD DS XL2 Modified Lines in Binary DIRSPFID DS CL8 ID of Last Person to Update