diff --git a/.gitignore b/.gitignore index d6e4780..2c1f029 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.o *.a *.swp +*.swo **/basicread **/basicwrite **/defaults.c diff --git a/Makefile b/Makefile index 681b88a..28edd20 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ endif ASAMODE := AMODE$(MODE) +LIBS = -lbpamiosvcs -lbpamiocore + + ifdef CJSON_INCLUDE_DIR CPPFLAGS += -I$(CJSON_INCLUDE_DIR) endif @@ -16,13 +19,21 @@ ifdef CJSON_LIBRARY LIBS += $(CJSON_LIBRARY) endif +ifdef METALDIO_INCLUDE_DIR + CPPFLAGS += -I$(METALDIO_INCLUDE_DIR) +endif + +ifdef METALDIO_LIBRARY + LDFLAGS += -L$(METALDIO_LIBRARY) +endif + # Toolchain and flags export AS := as export ASFLAGS := --SYSPARM\($(ASAMODE)\),GOFF,LIST,'SUPRWARN(425,434)' export CC := xlc export CFLAGS := -Wc,$(DATA_MODEL)',SUPP(CCN3764),AGGR,LIST(./)' -export CPPFLAGS := -DAMODE=$(MODE) -D_ALL_SOURCE=1 $(CPPFLAGS) -D_AE_BIMODAL=1 +export CPPFLAGS := -DAMODE=$(MODE) -D_ALL_SOURCE=1 -D_OPEN_SYS_FILE_EXT=1 $(CPPFLAGS) -D_AE_BIMODAL=1 -I../include -I../intinclude export LD := xlc export LDFLAGS := -Wc,$(DATA_MODEL) $(LDFLAGS) export LIBS := $(LIBS) diff --git a/include/.memdir.h.swo b/include/.memdir.h.swo new file mode 100644 index 0000000..6e93da0 Binary files /dev/null and b/include/.memdir.h.swo differ diff --git a/include/closecb.h b/include/closecb.h new file mode 100644 index 0000000..90f779b --- /dev/null +++ b/include/closecb.h @@ -0,0 +1,16 @@ +#ifndef __CLOSECB__ +#define __CLOSECB__ 1 + +#include "diocommon.h" + +#pragma pack(1) +struct closecb { + int last_entry:1; + int opts:7; + int reserved:24; + void* PTR32 dcb24; +}; + +#pragma pack(pop) + +#endif diff --git a/include/dcbe.h b/include/dcbe.h new file mode 100644 index 0000000..63506b3 --- /dev/null +++ b/include/dcbe.h @@ -0,0 +1,32 @@ +#ifndef __DCBE__ +#define __DCBE__ 1 + +#include "diocommon.h" + +#pragma pack(1) + +struct dcbe { + unsigned char dcbe_hdr[4]; /* 0 Alignment and identifier (DCBE) */ + short int dcbe_len; /* 4 DCBE V0 length, min is 56' @L8A */ + unsigned char _filler2[2]; /* 6 Reserved, should be zero */ + void* PTR32 _filler3; /* 8 0 if not open, OPEN points to DCB */ + unsigned char _filler4[4]; /* C Disk address of current member */ + unsigned char _filler5; /* 10 Flags set by system */ + unsigned char usrflags; /* 11 Flags set by user */ + short int _filler7; /* 12 Number of stripes if extended format */ + unsigned char _filler8; /* 14 Flags set by user @L3A */ + unsigned char _filler9; /* 15 Flags @L9A */ + unsigned char _filler10[2]; /* 16 Reserved @L9C */ + unsigned char _filler11[4]; /* 18 Reserved @L2A */ + int _filler12; /* 1C Block size @L2A */ + unsigned char _filler13[8]; /* 20 Reserved & number of blocks in ds @L2C */ + void * PTR32 eodad; /* 28 End of data routine address or 0 */ + void * PTR32 synad; /* 2C I/O error routine (synchronous) or 0 */ + unsigned char _filler16[4]; /* 30 Reserved, should be zero @MAC */ + short int _filler17; /* 34 tape files written before sync @MAA */ + unsigned char _filler18[2]; /* 36 MULTACC and MULTSDN */ + }; + +#pragma pack(pop) + +#endif diff --git a/include/decb.h b/include/decb.h new file mode 100644 index 0000000..f205804 --- /dev/null +++ b/include/decb.h @@ -0,0 +1,21 @@ +#ifndef __DECB__ +#define __DECB__ 1 + +#include "diocommon.h" + +#pragma pack(1) +struct decb { + unsigned int ecb; + unsigned short type; + unsigned short length; + unsigned int dcb24_hoB: 8; + unsigned int dcb24: 24; + void* PTR32 area; + void* PTR32 stat_addr; + void* PTR32 key_addr; + void* PTR32 block_addr; + void* PTR32 next_addr; +}; +#pragma pack(pop) + +#endif diff --git a/include/dio.h b/include/dio.h index 3a518fc..b54770d 100644 --- a/include/dio.h +++ b/include/dio.h @@ -5,6 +5,7 @@ #include #include #include + #include /* * Services that take a string or return a string are ASCII/EBCDIC aware. @@ -41,36 +42,56 @@ */ enum DIOERR { DIOERR_NOERROR=0, - DIOERR_SVC99INIT_FAILURE=1, - DIOERR_SVC99INIT_ALLOC_FAILURE=2, - DIOERR_SVC99INIT_FREE_FAILURE=3, - DIOERR_SVC99_ALLOC_FAILURE=4, - DIOERR_INVALID_DATASET_NAME=5, - DIOERR_LE_DATASET_NAME_TOO_LONG_OR_TOO_SHORT=6, - DIOERR_INVALID_LE_DATASET_NAME=7, - DIOERR_LE_DATASET_NAME_QUOTE_MISMATCH=8, - DIOERR_RELATIVE_DATASET_NAME_NOT_IMPLEMENTED_YET=9, - DIOERR_MEMBER_NAME_TOO_LONG=10, - DIOERR_LE_DATASET_NAME_PAREN_MISMATCH=11, - DIOERR_FCLOSE_FAILED_ON_READ=12, - DIOERR_OPENDD_FOR_READ_FAILED=13, - DIOERR_READ_BUFFER_ALLOC_FAILED=14, - DIOERR_LARGE_READ_BUFFER_NOT_IMPLEMENTED_YET=15, - DIOERR_INVALID_BUFFER_PASSED_TO_WRITE=16, - DIOERR_FCLOSE_FAILED_ON_WRITE=17, - DIOERR_OPENDD_FOR_WRITE_FAILED=18, - DIOERR_FCLOSE_FAILED_ON_CLOSE=19, - DIOERR_MALLOC_FAILED=20, - DIOERR_FLDATA_FAILED=21, - DIOERR_UNSUPPORTED_RECFM=22, - DIOERR_UNSUPPORTED_DSORG=23, - DIOERR_FOPEN_FOR_READ_FAILED=24, - DIOERR_FREAD_FAILED=25, - DIOERR_FWRITE_FAILED=26, - DIOERR_NOT_ENOUGH_QUALIFIERS=27, - DIOERR_HLQ_TOO_LONG=28, - DIOERR_MLQS_TOO_LONG=29, - DIOERR_LLQ_TOO_LONG=30, + DIOERR_SVC99INIT_FAILURE, + DIOERR_SVC99INIT_ALLOC_FAILURE, + DIOERR_SVC99INIT_FREE_FAILURE, + DIOERR_SVC99_ALLOC_FAILURE, + DIOERR_INVALID_DATASET_NAME, + DIOERR_LE_DATASET_NAME_TOO_LONG_OR_TOO_SHORT, + DIOERR_INVALID_LE_DATASET_NAME, + DIOERR_LE_DATASET_NAME_QUOTE_MISMATCH, + DIOERR_RELATIVE_DATASET_NAME_NOT_IMPLEMENTED_YET, + DIOERR_MEMBER_NAME_TOO_LONG, + DIOERR_LE_DATASET_NAME_PAREN_MISMATCH, + DIOERR_FCLOSE_FAILED_ON_READ, + DIOERR_OPENDD_FOR_READ_FAILED, + DIOERR_READ_BUFFER_ALLOC_FAILED, + DIOERR_READ_MEMDIR_ENTRY_FAILED, + DIOERR_LARGE_READ_BUFFER_NOT_IMPLEMENTED_YET, + DIOERR_INVALID_BUFFER_PASSED_TO_WRITE, + DIOERR_FCLOSE_FAILED_ON_WRITE, + DIOERR_OPENDD_FOR_WRITE_FAILED, + DIOERR_FCLOSE_FAILED_ON_CLOSE, + DIOERR_MALLOC_FAILED, + DIOERR_FLDATA_FAILED, + DIOERR_UNSUPPORTED_RECFM, + DIOERR_UNSUPPORTED_DSORG, + DIOERR_FOPEN_FOR_READ_FAILED, + DIOERR_FREAD_FAILED, + DIOERR_FWRITE_FAILED, + DIOERR_NOT_ENOUGH_QUALIFIERS, + DIOERR_HLQ_TOO_LONG, + DIOERR_MLQS_TOO_LONG, + DIOERR_LLQ_TOO_LONG, + DIOERR_READ_FAILED, + DIOERR_WRITE_FAILED, + DIOERR_MEMORY_ALLOCATION_FAILED, + DIOERR_BPAM_OPEN_WRITE_FAILED, + DIOERR_INIT_DESP_FAILED, + DIOERR_BPAM_ENQ_FAILED, + DIOERR_BPAM_WRITE_FAILED, + DIOERR_INVALID_BUFFER_FORMAT, // Input buffer format inconsistent (e.g., lengths don't match content) + DIOERR_RECORD_TOO_LONG, // Record length exceeds dataset LRECL + DIOERR_RECORD_TOO_LONG_FOR_BLK, // Single record length exceeds dataset BLKSIZE + DIOERR_BPAM_WRITE_BLOCK_FAILED, // BPAM WRITE macro failed + DIOERR_BPAM_WRITE_DIR_FAILED, // STOW or related directory update failed + DIOERR_BPAM_DEQ_FAILED, // ispf_deq_dataset_member failed +DIOERR_BPAM_CLOSE_FAILED, +DIOERR_BPAM_INTERNAL_ERROR, +DIOERR_BPAM_WRITE_BUFFER_ERROR, +DIOERR_BPAM_RECORD_TOO_LARGE_FOR_BLOCK, +DIOERR_BPAM_WRITEMEMDIR_FAILED, + DIOERR_FORCE_INT=INT_MAX }; @@ -88,8 +109,10 @@ int is_binary; FILE* logstream; void* internal; + DBG_Opts* opts; int txtflag; int ccsid; + int debug; }; /* CONSTANTS */ diff --git a/include/diocommon.h b/include/diocommon.h new file mode 100644 index 0000000..47aed2e --- /dev/null +++ b/include/diocommon.h @@ -0,0 +1,9 @@ +#ifndef __DIO_COMMON_H + #define __DIO_COMMON_H + + #ifdef VSCODE + #define PTR32 + #else + #define PTR32 __ptr32 + #endif +#endif diff --git a/include/findcb.h b/include/findcb.h new file mode 100644 index 0000000..329ca6c --- /dev/null +++ b/include/findcb.h @@ -0,0 +1,17 @@ +#ifndef __FINDCB__ +#define __FINDCB__ 1 + +#include "diocommon.h" + +#pragma pack(1) +struct findcb { + //unsigned short cb_len; + //unsigned short filler; + //unsigned int mname_len; + char mname[8]; + //unsigned int gen_num; +}; + +#pragma pack(pop) + +#endif diff --git a/include/igwsmde.h b/include/igwsmde.h new file mode 100644 index 0000000..d5d34b4 --- /dev/null +++ b/include/igwsmde.h @@ -0,0 +1,410 @@ +#ifndef __IGWSMDE_H__ +#define __IGWSMDE_H__ + +#include "diocommon.h" + +#pragma pack(1) + +struct smde { + union { + unsigned char smde_basic[44]; /* START OF BASIC SECTION */ + unsigned char smde_hdr[16]; /* HEADER */ + struct { + unsigned char smde_id[8]; /* EYECATCHER IGWSMDE */ + int smde_len; /* LENGTH OF CONTROL BLOCK. THIS */ + unsigned int : 7, + smde_lvl_val : 1; /* LEVEL CONSTANT */ + unsigned char _filler1[3]; /* RESERVED */ + unsigned char smde_libtype; /* SOURCE LIBRARY TYPE. POSSIBLE */ + unsigned int smde_flag_alias : 1, /* ENTRY IS AN ALIAS. */ + smde_flag_lmod : 1, /* MEMBER IS A PROGRAM. */ + smde_system_dcb : 1, /* DCB IS A SYSTEM DCB, THEREFORE */ + : 5; + unsigned char _filler2[2]; /* RESERVED. MUST BE ZERO. */ + unsigned char _filler3; /* RESERVED. MUST BE ZERO. */ + struct { + unsigned char smde_mlt[3]; /* MLT OF MEMBER (ZERO IF HFS) */ + unsigned char smde_cnct; /* CONCATENATION NUMBER */ + } smde_mltk; /* MLT AND CONCAT # */ + unsigned char smde_libf; /* LIBRARY FLAG (Z-BYTE) */ + short int smde_name_off; /* NAME OFFSET */ + struct { + short int smde_pmar_len; /* SUM OF LENGTHS OF PROGRAM */ + } smde_usrd_len; /* USER DATA LENGTH */ + struct { + short int smde_pmar_off; /* PROGRAM MANAGEMENT */ + } smde_usrd_off; /* USER DATA OFFSET */ + struct { + short int smde_gene_len; /* GENERATION SECTION LENGTH @L4A */ + } smde_token_len; /* TOKEN SECTION LENGTH @L4C */ + struct { + short int smde_gene_off; /* GENERATION SECTION OFFSET @L4A */ + } smde_token_off; /* TOKEN DATA OFFSET @L4C */ + short int smde_pname_off; /* PRIMARY NAME OFFSET. */ + short int smde_nlst_cnt; /* NUMBER OF NOTE LIST */ + short int smde_c370_attr_off; /* OFFSET TO C370LIB ATTRIBUTE @02A */ + short int smde_ext_attr_off; /* OFFSET TO EXTENDED ATTRIBUTES @L3A */ + __extension__ unsigned char smde_sections[0]; /* START OF ENTRY SECTIONS */ + }; + }; + }; + +/* Values for field "smde_libtype" */ +#define smde_libtype_c370lib 0x03 /* C370LIB LIBRARY TYPE @L2A */ +#define smde_libtype_hfs 0x02 /* HFS FILE TYPE */ +#define smde_libtype_pdse 0x01 /* PDSE LIBRARY TYPE */ +#define smde_libtype_pds 0x00 /* PDS LIBRARY TYPE */ + +/* Values for field "smde_libf" */ +#define smde_libf_tasklib 0x02 /* LIBRARY FOUND FLAG - TASKLIB */ +#define smde_libf_linklib 0x01 /* LIBRARY FOUND FLAG - LNKLST */ +#define smde_libf_private 0x00 /* LIBRARY FOUND FLAG - PRIVATE */ + +struct smde_name { + short int smde_name_len; /* LENGTH OF ENTRY NAME */ + __extension__ unsigned char smde_name_val[0]; /* ENTRY NAME */ + }; + +struct smde_nlst { + union { + unsigned char smde_nlst_entry[4]; /* NOTE LIST ENTRIES */ + struct { + unsigned char smde_nlst_rlt[3]; /* NOTE LIST RECORD LOCATION */ + unsigned char smde_nlst_num; /* NUMBER OF RLT DESCRIBED BY */ + }; + }; + }; + +struct smde_token { + union { + struct { + int smde_token_connid; /* CONNECT_IDENTIFIER */ + int smde_token_itemno; /* ITEM NUMBER */ + unsigned char smde_token_ft[24]; /* FILE TOKEN */ + }; + struct { + unsigned char _filler1[16]; /* RESERVED @L2A */ + unsigned char smde_token_bmf_ct[8]; /* BMF CONNECT TOKEN @L2A */ + unsigned char smde_token_cdm_ct[8]; /* JCDM CONNECT TOKEN @L2A */ + __extension__ unsigned char smde_token_end[0]; + }; + }; + }; + +struct smde_fd { + int smde_fd_token; /* FILE DESCRIPTOR */ + __extension__ unsigned char smde_fd_end[0]; + }; + +struct smde_pname { + short int smde_pname_len; /* LENGTH OF PRIMARY NAME */ + __extension__ unsigned char smde_pname_val[0]; /* PRIMARY NAME */ + }; + +struct smde_gene { + unsigned char smde_gene_name[8]; /* Generation Name */ + unsigned int smde_is_dummy : 1, /* Entry is dummy */ + : 7; + unsigned char smde_gene_flgs2; /* Flags */ + unsigned char smde_gene_flgs3; /* Flags */ + unsigned char smde_gene_flgs4; /* Flags */ + int smde_gene_number; /* Absolute Generation number */ + union { + unsigned char smde_gene_mltk[4]; /* MLT AND CONCAT # */ + struct { + unsigned char smde_gene_mlt[3]; /* MLT OF MEMBER */ + unsigned char smde_gene_cnct; /* CONCATENATION NUMBER */ + }; + }; + short int smde_gene_ccsid; /* CCSID or '0000'x if not defined */ + unsigned char _filler1[2]; /* Reserved */ + unsigned char smde_gene_userid[8]; /* Userid of creator or last updater */ + unsigned char smde_gene_timestamp[8]; /* Last member update or create timestamp */ + unsigned char smde_gene_gentimestamp[8]; /* Last generation update */ + __extension__ unsigned char smde_gene_end[0]; /* @03A */ + }; + +/* Values for field "smde_gene_end" */ +#define smde_po1_name_maxlen 63 /* Maximum length of names in a */ +#define smde_hfs_name_maxlen 256 /* Maximum length of names in a */ +#define smde_po2_name_maxlen 1024 /* Maximum length of names in a */ +#define smde_name_maxlen 1024 /* Maximum length of names @L1A */ +#define smde_pname_maxlen 8 /* Maximum length of primary */ +#define smde_maxlen 0x11F +#define smde_hfs_maxlen 0x4BA +#define smde_po2_maxlen 0x4E0 +#define smde_all_maxlen 0x4E0 /* Maximum length of SMDE for all */ +#define smde_pds_maxlen 0x42 + +struct smde_ext_attr { + short int smde_ext_attr_len; /* length of this section */ + unsigned char smde_ccsid[2]; /* CCSID, or x'0000' if CCSID was not defined */ + unsigned char smde_type_descriptor[16]; /* type descriptor */ + unsigned char smde_userid_last_change[8]; /* userid of creator or last updater */ + unsigned char smde_change_timestamp[8]; /* last member update or creation */ + }; + +struct pmar { + union { + unsigned char pmar_entry[30]; /* Alternative name for the PMAR section */ + struct { + short int pmar_slen; /* Section length. */ + unsigned char pmar_lvl; /* PMAR format level */ + unsigned char pmar_plvl; /* Bind processor creating object */ + struct { + unsigned int pmar_rent : 1, /* Reenterable */ + pmar_reus : 1, /* Reusable */ + pmar_ovly : 1, /* Overlay structure */ + pmar_test : 1, /* Module to be tested - TESTRAN */ + pmar_load : 1, /* Only loadable */ + pmar_sctr : 1, /* Scatter format */ + pmar_exec : 1, /* Executable */ + pmar_1blk : 1; /* Load module contains only one */ + unsigned int pmar_flvl : 1, /* If on, the program cannot be */ + pmar_org0 : 1, /* Linkage editor assigned origin */ + : 1, + pmar_nrld : 1, /* Program contains no RLD items */ + pmar_nrep : 1, /* Module cannot be reprocessed */ + pmar_tstn : 1, /* Module contains TESTRAN symbol */ + : 1, + pmar_refr : 1; /* Refreshable program */ + struct { + unsigned int : 1, + pmar_big : 1, /* This program requires 16M bytes */ + pmar_paga : 1, /* Page alignment is required */ + pmar_xssi : 1, /* SSI information present */ + pmar_xapf : 1, /* APF information present */ + pmar_lfmt : 1, /* PMARL follows PMAR. */ + pmar_signed : 1, /* Program is signed. Verified on */ + : 1; + } pmar_atr3; /* Third attribute byte. */ + struct { + unsigned char pmar_ftb2; /* Alternative name for flags byte */ + } pmar_atr4; /* Fourth attribute byte */ + } pmar_atr; /* Attribute bytes. */ + unsigned int : 7, + pmar_longparm : 1; /* Parm >100 chars allowed @LFA */ + unsigned char pmar_ac; /* APF authorization code */ + unsigned char pmar_stor[4]; /* Virtual storage required */ + unsigned char pmar_epm[4]; /* Main entry point offset */ + unsigned char pmar_epa[4]; /* This entry point offset */ + struct { + unsigned char pmar_chlv; /* Change level of member */ + unsigned char pmar_ssfb; /* SSI flag byte */ + unsigned char pmar_mser[2]; /* Member serial number */ + } pmar_ssi; /* SSI information */ + unsigned int pmar_system_le : 1, /* @L7A */ + pmar_lightweight_le : 1, /* @L7A */ + : 14; + unsigned char _filler1[2]; /* Reserved @L7A */ + __extension__ unsigned char pmar_end[0]; /* END OF BASIC SECTION */ + }; + }; + }; + +/* Values for field "pmar_lvl" */ +#define pmar_pm1_val 0x01 /* level constant for PO1 @L2A */ +#define pmar_pm2_val 0x02 /* level constant for PO2 @L2A */ +#define pmar_pm3_val 0x03 /* level constant for PO3 @L3A */ +#define pmar_pm4_val 0x04 /* level constant for PO4 @L7A */ +#define pmar_pm5_val 0x05 /* level constant for PO5 @LAA */ +#define pmar_lvl_val 0x05 /* level constant @LAC */ + +/* Values for field "pmar_plvl" */ +#define pmar_plvl_e_val 0x01 /* E-level constant */ +#define pmar_plvl_f_val 0x02 /* F-level constant */ +#define pmar_plvl_aos_val 0x03 /* AOS-level constant */ +#define pmar_plvl_xa_val 0x04 /* XA-level constant */ +#define pmar_plvl_b1_val 0x05 /* Binder version 1 */ +#define pmar_plvl_b2_val 0x06 /* Binder version 2 @L2A */ +#define pmar_plvl_b3_val 0x07 /* Binder version 3 @L3A */ +#define pmar_plvl_b4_val 0x08 /* Binder version 4 @L7A */ +#define pmar_plvl_b5_val 0x09 /* Binder version 5 @L8A */ + +/* Values for field "pmar_ftb2" */ +#define pmar_altp 0x80 /* Alternate primary flag. If on */ +#define pmar_rmode64 0x20 /* RMODE 64 @LGC */ +#define pmar_rmod 0x10 /* RMODE is 31 or 64 */ +#define pmar_aamd 0x0C /* Alias entry point addressing */ +#define pmar_aamd_maskoff 0xF3 /* Mask for AMODE flags */ +#define pmar_mamd 0x03 /* Main entry point addressing */ + +struct pmarl { + short int pmarl_slen; /* Section length */ + union { + unsigned char pmarl_data[48]; /* Section Data */ + unsigned char pmarl_atr[4]; /* Attribute bytes */ + struct { + unsigned char pmarl_atr1; /* 6th attribute byte */ + unsigned int pmarl_cmpr : 1, /* Compressed format module */ + pmarl_1rmod : 1, /* 1st segment is RMODE 31, @L2A */ + pmarl_2rmod : 1, /* 2nd segment is RMODE 31, @L2A */ + : 1, + pmarl_1alin : 1, /* 1st segment is page-aligned,@L2A */ + pmarl_2alin : 1, /* 2nd segment is page-aligned,@L2A */ + pmarl_fill : 1, /* FILL option specified @L2A */ + : 1; + unsigned char pmarl_fillval; /* FILL character value @L2A */ + unsigned char pmarl_po_sublvl; /* Program object sublevel @L7A */ + unsigned char pmarl_mpgs[4]; /* Total length of program on */ + struct { + unsigned char pmarl_txtl[4]; /* Length of initial load text on */ + void * PTR32 pmarl_txto; /* Offset to text */ + unsigned char pmarl_bdrl[4]; /* Length of Binder index */ + void * PTR32 pmarl_bdro; /* Offset to Binder index */ + unsigned char pmarl_rdtl[4]; /* Length of PRDT */ + void * PTR32 pmarl_rdto; /* Offset to PRDT */ + unsigned char pmarl_ratl[4]; /* Length of PRAT */ + void * PTR32 pmarl_rato; /* Offset to PRAT */ + struct { + unsigned char pmarl_lmdl[4]; /* Length of LSLoader data, */ + } pmarl_nvspgs; /* Number of virtual storage @L2A */ + void * PTR32 pmarl_lmdo; /* Offset to LSLoader data */ + } pmarl_mdat; /* DASD program descriptors */ + }; + struct { + unsigned char _filler1[48]; + struct { + unsigned char pmarl_nseg[2]; /* Number of loadable segments @L2A */ + unsigned char pmarl_ngas[2]; /* Count of entries in Gas @L2A */ + unsigned char pmarl_1stor[4]; /* Virtual storage required @L2A */ + unsigned char pmarl_2stor[4]; /* Virtual storage required @L2A */ + unsigned char pmarl_2txto[4]; /* Offset to second txt segment@L2A */ + unsigned char _filler2[8]; + } pmarl_pm2; /* New fields for PM2-Level @L2A */ + }; + struct { + unsigned char _filler3[64]; + struct { + unsigned char pmarl_date[4]; /* Date saved @L2A */ + unsigned char pmarl_time[4]; /* Time saved @L2A */ + unsigned char pmarl_user[8]; /* User or job identification @L2A */ + } pmarl_trace; /* Audit trace data @L2A */ + }; + struct { + unsigned char _filler4[80]; + struct { + unsigned int pmarl_hide : 1, /* Name is an alias that can @L3A */ + pmarl_dllena : 1, /* PO is DLL-enabled @L3A */ + pmarl_mustdelet : 1, /* If on and directed LOAD @L3A */ + pmarl_iewblitp : 1, /* If on, PMARL_IEWBLITO is @L3A */ + pmarl_mangled : 1, /* If on, name is mangled. @L3A */ + : 3; + unsigned int pmarl_cms_system : 1, /* SYSTEM module bit @L6A */ + pmarl_cms_noclean : 1, /* Do not cleanup at end of service @L6A */ + pmarl_cms_strinit : 1, /* STRINIT bit @L6A */ + pmarl_cms_moddos : 1, /* Gen'd with DOS @L6A */ + pmarl_cms_modall : 1, /* Gen'd with ALL @L6A */ + pmarl_cms_invalxa : 1, /* XA-mode invalid @L6A */ + pmarl_cms_invalxc : 1, /* XC-mode invalid @L6A */ + : 1; + unsigned char pmarl_ndefer[2]; /* Number of deferred classes @L3A */ + unsigned char pmarl_dtempl[4]; /* Total length of deferred @L3A */ + unsigned char pmarl_1dtxto[4]; /* Offset of 1st deferred @L3A */ + unsigned char pmarl_iewblito[4]; /* Byte offset of IEWBLIT @L3A */ + } pmarl_pm3; /* New fields for PM3-Level @L3A */ + }; + struct { + unsigned char _filler5[96]; + union { + unsigned char pmarl_pm4[8]; /* New fields for PM4-Level @L7A */ + struct { + unsigned int pmarl_1rmod64 : 1, /* 1st segment is RMODE 64 @L8A */ + pmarl_2rmod64 : 1, /* 2nd segment is RMODE 64 @L8A */ + : 6; + unsigned char _filler6[7]; /* Reserved @L7A */ + __extension__ unsigned char pmarl_pm5[0]; /* New fields for PM5-Level @LAA */ + __extension__ unsigned char pmarl_end[0]; /* END OF LSLOADER SECTION */ + }; + }; + }; + }; + }; + +/* Values for field "pmarl_atr1" */ +#define pmarl_nmig 0x80 /* This program object cannot be */ +#define pmarl_prim 0x40 /* FETCHOPT PRIME option */ +#define pmarl_pack 0x20 /* FETCHOPT PACK option */ +#define pmarl_xpl 0x10 /* Module requires XPLINK @L4A */ +#define pmarl_hpl 0x10 /* Module requires XPLINK @L4A */ + +/* Values for field "pmarl_po_sublvl" */ +#define pmarl_po_sublvl_zosv1r3 1 /* Value for z/OS V1 R3 / PO4 @L7A */ +#define pmarl_po_sublvl_zosv1r5 2 /* Value for z/OS V1 R5 / PO4 @L8A */ +#define pmarl_po_sublvl_zosv1r7 3 /* Value for z/OS V1 R7 / PO4 @L9A */ +#define pmarl_po_sublvl_zosv1r8 1 /* Value for z/OS V1 R8 / PO5 @LAA */ +#define pmarl_po_sublvl_zosv1r10 2 /* Value for z/OS V1 R10 / PO5 @LBA */ +#define pmarl_po_sublvl_zosv1r13 3 /* Value for z/OS V1 R13 / PO5 @LDA */ +#define pmarl_po_sublvl_zosv2r1 4 /* Value for z/OS V2 R1 / PO5 @LEA */ + +struct pmarr { + short int pmarr_slen; /* Section length */ + union { + unsigned char pmarr_data[21]; /* Section data */ + unsigned char pmarr_ttrs[8]; /* TTR fields */ + struct { + unsigned char pmarr_ttrt[3]; /* TTR of first block of text */ + unsigned char pmarr_zero; /* Zero */ + unsigned char pmarr_ttrn[3]; /* TTR of note list or scatter */ + unsigned char pmarr_nl; /* Number of entries in note list */ + unsigned char pmarr_ftbl[2]; /* Length of first block of text. */ + struct { + unsigned char _filler1[2]; /* Reserved */ + unsigned char pmarr_rlds; /* Number of RLD/CTL records which */ + } pmarr_org; /* Load module origin if ^0 */ + union { + unsigned char pmarr_scat[8]; /* Scatter load information */ + struct { + unsigned char pmarr_slsz[2]; /* Scatter list length */ + unsigned char pmarr_ttsz[2]; /* Translation table length */ + unsigned char pmarr_esdt[2]; /* ESDID of first text block */ + unsigned char pmarr_esdc[2]; /* ESDID of EP control section */ + __extension__ unsigned char pmarr_end[0]; /* END OF LOAD MODULE ATTRIBUTES */ + }; + }; + }; + }; + }; + +struct pmara { + short int pmara_len; /* Section length */ + union { + unsigned char pmara_data; /* Section data */ + unsigned char pmara_epa[4]; /* Entry point offset */ + struct { + unsigned char _filler1[4]; + union { + unsigned char pmara_atr; /* Attribute bytes */ + unsigned char pmara_atr1; /* First attribute byte */ + struct { + unsigned int pmara_altp : 1, /* Alternate Primary flag. */ + pmara_hide : 1, /* Alias name can be hidden @L3A */ + pmara_nexec : 1, /* Entry point is non-executable */ + pmara_mangled : 1, /* Alias is a mangled name @L3A */ + pmara_amd : 2, /* Alias entry addressing mode */ + : 2; + __extension__ unsigned char pmara_end[0]; /* END OF ALIAS ENTRY SECTION */ + }; + }; + }; + }; + }; + +/* Values for field "pmara_end" */ +#define pmar_maxlen 0x88 +#define pmar_maxlen_progobj 0x88 +#define pmar_maxlen_po1 0x50 +#define pmar_maxlen_po2 0x70 /* @L3C */ +#define pmar_maxlen_po3 0x80 /* @L7C */ +#define pmar_maxlen_po4 0x88 /* @LAC */ +#define pmar_maxlen_po5 0x88 /* @LAA */ +#define pmar_maxlen_loadmod 0x35 +#define pmarl_lvl1len 0x32 /* @L2A */ +#define pmarl_lvl2len 0x52 /* @L3A */ +#define pmarl_lvl3len 0x62 /* @L7A */ +#define pmarl_lvl4len 0x6A /* @LAA */ +#define pmarl_lvl5len 0x6A /* @LAA */ + +#pragma pack(pop) + +#endif // __IGWSMDE_H__ diff --git a/include/ihapds.h b/include/ihapds.h new file mode 100644 index 0000000..0308fab --- /dev/null +++ b/include/ihapds.h @@ -0,0 +1,171 @@ +#ifndef __IHAPDS_H__ +#define __IHAPDS_H__ + +#include "diocommon.h" + +#pragma pack(1) + +struct pds2 { + unsigned char pds2name[8]; /* MEMBER NAME OR ALIAS NAME */ + unsigned char pds2ttrp[3]; /* TTR OF FIRST BLOCK OF NAMED MEMBER */ + char pds2cnct; /* CONCATENATION NUMBER OF THE DATA SET */ + unsigned char pds2libf; /* LIBRARY FLAG FIELD */ + unsigned char pds2indc; /* INDICATOR BYTE */ + union { + unsigned char pds2usrd; /* START OF VARIABLE LENGTH USER DATA FIELD */ + unsigned char pds2ttrt[3]; /* TTR OF FIRST BLOCK OF TEXT */ + }; + unsigned char pds2zero; /* ZERO */ + unsigned char pds2ttrn[3]; /* TTR OF NOTE LIST OR SCATTER/TRANSLATION */ + char pds2nl; /* NUMBER OF ENTRIES IN NOTE LIST FOR */ + union { + unsigned char pds2atr[2]; /* TWO-BYTE PROGRAM ATTRIBUTE FIELD */ + struct { + unsigned char pds2atr1; /* FIRST BYTE OF PROGRAM ATTRIBUTE FIELD */ + unsigned int pds2flvl : 1, /* If one, the program cannot be processed */ + pds2org0 : 1, /* ORIGIN OF FIRST BLOCK OF TEXT IS ZERO */ + pds2ep0 : 1, /* ENTRY POINT IS ZERO */ + pds2nrld : 1, /* PROGRAM CONTAINS NO RLD ITEMS */ + pds2nrep : 1, /* PROGRAM CANNOT BE REPROCESSED BY LINKAGE */ + pds2tstn : 1, /* PROGRAM CONTAINS TESTRAN SYMBOL CARDS */ + pds2lef : 1, /* PROGRAM CREATED BY LINKAGE EDITOR F */ + pds2refr : 1; /* REFRESHABLE PROGRAM */ + }; + }; + int pds2stor : 24; /* TOTAL CONTIGUOUS MAIN STORAGE REQUIREMENT */ + short int pds2ftbl; /* LENGTH OF FIRST BLOCK OF TEXT */ + unsigned int pds2epa : 24; /* ENTRY POINT ADDRESS ASSOCIATED WITH */ + union { + unsigned char pds2ftbo[3]; /* FLAG BYTES (MVS USE OF FIELD) @LCC */ + struct { + unsigned char pds2ftb1; /* BYTE 1 OF PDS2FTBO */ + unsigned int pds2altp : 1, /* ALTERNATE PRIMARY FLAG. IF ON (FOR A @L8A */ + : 1, + pdslrm64 : 1, /* 0: RMODE is 24 or 31. @LDA */ + pdslrmod : 1, /* 0: RMODE 24 or reserved @LDA */ + pdsaamod : 2, /* ALIAS ENTRY POINT ADDRESSING MODE @L6A */ + pdsmamod : 2; /* MAIN ENTRY POINT ADDRESSING MODE @L6A */ + struct { + unsigned int pds2nmig : 1, /* THIS PROGRAM OBJECT CANNOT BE CONVERTED */ + pds2prim : 1, /* FETCHOPT PRIME WAS SPECIFIED @L7A */ + pds2pack : 1, /* FETCHOPT PACK WAS SPECIFIED @L7A */ + : 5; + } pds2rlds; /* NUMBER OF RLD/CONTROL RECORDS WHICH @L6A */ + }; + }; + short int pds2slsz; /* NUMBER OF BYTES IN SCATTER LIST */ + short int pds2ttsz; /* NUMBER OF BYTES IN TRANSLATION TABLE */ + unsigned char pds2esdt[2]; /* IDENTIFICATION OF ESD ITEM (ESDID) OF */ + unsigned char pds2esdc[2]; /* IDENTIFICATION OF ESD ITEM (ESDID) OF */ + unsigned int pds2epm : 24; /* ENTRY POINT FOR MEMBER NAME */ + unsigned char pds2mnm[8]; /* MEMBER NAME OF PROGRAM. WHEN THE */ + union { + short int pdss03; /* FORCE HALF-WORD ALIGNMENT FOR SSI */ + unsigned char pdsssiwd[4]; /* SSI INFORMATION WORD */ + struct { + char pdschlvl; /* CHANGE LEVEL OF MEMBER */ + unsigned char pdsssifb; /* SSI FLAG BYTE */ + unsigned char pdsmbrsn[2]; /* MEMBER SERIAL NUMBER */ + struct { + char pdsapfct; /* LENGTH OF PROGRAM AUTHORIZATION CODE */ + unsigned char pdsapfac; /* PROGRAM AUTHORIZATION CODE */ + } pdsapf; /* PROGRAM AUTHORIZATION FACILITY (APF) */ + }; + }; + union { + char pds2lpol; /* LARGE PROGRAM OBJECT SECTION LENGTH @L7A */ + char pds2llml; /* ALTERNATE NAME FOR PDS2LLML @L7A */ + }; + int pds2vstr; /* VIRTUAL STORAGE REQUIREMENT FOR THIS */ + int pds2mepa; /* MAIN ENTRY POINT OFFSET */ + int pds2aepa; /* ALIAS ENTRY POINT OFFSET. ONLY VALID */ + unsigned int : 4, + pds2xattr_optn_mask : 4; /* Bits 4-7 of PDS2XATTRBYTE0 identify the */ + unsigned int pds2longparm : 1, /* PARM > 100 chars allowed @LBA */ + : 7; + char _filler1; /* Reserved @LBA */ + }; + +/* Values for field "pds2libf" */ +#define pds2lnrm 0x00 /* NORMAL CASE */ +#define pds2llnk 0x01 /* IF DCB OPERAND IN BLDL MACRO INTRUCTION */ +#define pds2ljob 0x02 /* IF DCB OPERAND IN BLDL MACRO INTRUCTION */ + +/* Values for field "pds2indc" */ +#define pds2alis 0x80 /* NAME IN THE FIELD PDS2NAME IS AN ALIAS */ +#define dealias 0x80 /* --- ALIAS FOR PDS2ALIS */ +#define pds2nttr 0x60 /* NUMBER OF TTR'S IN THE USER DATA FIELD */ +#define pds2lusr 0x1F /* - LENGTH OF USER DATA FIELD */ + +/* Values for field "pds2atr1" */ +#define pds2rent 0x80 /* REENTERABLE */ +#define dereen 0x80 /* --- ALIAS FOR PDS2RENT */ +#define pds2reus 0x40 /* REUSABLE */ +#define pds2ovly 0x20 /* IN OVERLAY STRUCTURE */ +#define deovly 0x20 /* --- ALIAS FOR PDS2OVLY */ +#define pds2test 0x10 /* PROGRAM TO BE TESTED - TESTRAN */ +#define pds2load 0x08 /* ONLY LOADABLE */ +#define delody 0x08 /* --- ALIAS FOR PDS2LOAD */ +#define pds2sctr 0x04 /* SCATTER FORMAT */ +#define descat 0x04 /* --- ALIAS FOR PDS2SCTR */ +#define pds2exec 0x02 /* EXECUTABLE */ +#define dexcut 0x02 /* --- ALIAS FOR PDS2EXEC */ +#define pds21blk 0x01 /* IF ZERO, PROGRAM CONTAINS MULTIPLE */ + +/* Values for field "pds2ftb1" */ +#define pdsaosle 0x80 /* Program has been processed by OS/VS1 or */ +#define pds2big 0x40 /* THE LARGE PROGRAM OBJECT EXTENSION */ +#define pds2paga 0x20 /* PAGE ALIGNMENT REQUIRED FOR PROGRAM */ +#define pds2ssi 0x10 /* SSI INFORMATION PRESENT */ +#define pdsapflg 0x08 /* INFORMATION IN PDSAPF IS VALID */ +#define pds2pgmo 0x04 /* PROGRAM OBJECT. THE PDS2FTB3 */ +#define pds2lfmt 0x04 /* ALTERNATE NAME FOR PDS2PGMO @L7A */ +#define pds2sign 0x02 /* PROGRAM OBJECT IS SIGNED. VERIFIED ON */ +#define pds2xatr 0x01 /* PDS2XATTR SECTION @LBA */ + +/* Values for field "pdsssifb" */ +#define pdsforce 0x40 /* A FORCE CONTROL CARD WAS USED WHEN */ +#define pdsusrch 0x20 /* A CHANGE WAS MADE TO MEMBER BY THE */ +#define pdsemfix 0x10 /* SET WHEN AN EMERGENCY IBM-AUTHORIZED */ +#define pdsdepch 0x08 /* A CHANGE MADE TO THE MEMBER IS DEPENDENT */ +#define pdssysgn 0x06 /* FLAGS THAT INDICATE WHETHER A */ +#define pdsnosgn 0x00 /* NOT CRITICAL FOR SYSTEM GENERATION */ +#define pdscmsgn 0x02 /* MAY REQUIRE COMPLETE REGENERATION */ +#define pdsptsgn 0x04 /* MAY REQUIRE PARTIAL REGENERATION */ +#define pdsibmmb 0x01 /* MEMBER IS SUPPLIED BY IBM */ + +#define bit0 128 +#define bit1 64 +#define bit2 32 +#define bit3 16 +#define bit4 8 +#define bit5 4 +#define bit6 2 +#define bit7 1 +#define dezbyte 0x0C /* --- ALIAS */ +#define pdsbcend 0x23 /* END OF BASIC SECTION */ +#define pdsbcln 0x23 /* - LENGTH OF BASIC SECTION */ +#define pdss01 0x23 /* START OF SCATTER LOAD SECTION */ +#define pdss01nd 0x2B /* END OF SCATTER LOAD SECTION */ +#define pdss01ln 0x08 /* - LENGTH OF SCATTER LOAD SECTION */ +#define pdss02 0x2B /* START OF ALIAS SECTION */ +#define deentbk 0x2B /* --- ALIAS */ +#define pdss02nd 0x36 /* END OF ALIAS SECTION */ +#define pdss02ln 0x0B /* - LENGTH OF ALIAS SECTION */ +#define pdss03nd 0x3A /* END OF SSI SECTION */ +#define pdss03ln 0x04 /* LENGTH OF SSI SECTION */ +#define pdss04 0x3A /* START OF APF SECTION */ +#define pdss04nd 0x3C /* END OF APF SECTION */ +#define pdss04ln 0x02 /* LENGTH OF APF SECTION */ +#define pdslpo 0x3C /* START OF LARGE PROGRAM OBJECT SECTION@L7A */ +#define pdsllm 0x3C /* ALTERNATE NAME FOR PDSLPO @L7A */ +#define pdslpond 0x49 /* END OF LARGE PROGRAM OBJECT SECTION */ +#define pdsllmnd 0x49 /* ALTERNATE NAME FOR PDSLPOND */ +#define pdslpoln 0x0D /* LENGTH OF LLM SECTION @L7A */ +#define pdsllmln 0x0D /* ALTERNATE NAME FOR PDSLPOLN @L7A */ +#define pds2xattr 0x49 /* Start of extended attributes @LBA */ +#define pds2xattr_opt 0x4C /* Start of optional fields. Number of */ + +#pragma pack(pop) + +#endif // __IHAPDS_H__ diff --git a/include/iob.h b/include/iob.h new file mode 100644 index 0000000..fa8690b --- /dev/null +++ b/include/iob.h @@ -0,0 +1,429 @@ +#ifndef __IOB__ +#define __IOB__ 1 + +#include "diocommon.h" + +#pragma pack(1) +struct iob { + union { + struct { + unsigned int iobv6chn : 1, /* - I/O CHAINED BIT SET BY IGG019V6 @ZA56251 */ + iobrsv02 : 1, /* RESERVED */ + iobrsv03 : 1, /* RESERVED */ + iobrsv04 : 1, /* RESERVED */ + iobptst : 1, /* - NOTE OR POINT OPERATION IS IN PROCESS */ + iobabapp : 1, /* - ERROR HAS BEEN PROCESSED ONCE BY ABNORMAL-END */ + iobrstch : 1, /* - RESTART CHANNEL */ + iobpci : 1; /* - SET WHEN A PROGRAM-CONTROLLED INTERRUPTION */ + unsigned char iobrsv05; /* - RESERVED */ + unsigned char iobcinop; /* - OFFSET OF THE LAST I/O COMMAND FOR INPUT */ + unsigned char iobconop; /* - OFFSET OF THE LAST I/O COMMAND FOR AN OUTPUT */ + int iobcecb; /* - EVENT CONTROL BLOCK USED BY BSAM OR QSAM. */ + }; + struct { + int iobvidan; /* VIRTUAL IDAW FOR QSAM, BSAM, BPAM NORMAL @L3A */ + struct { + int ioblenrd; /* LENGTH OF BLOCK READ, LBI @L5A */ + } iobvida2; /* VIRTUAL IDAW WHEN NOT BEGINNING OF BUFFER,@L5C */ + }; + struct { + struct { + unsigned char iobflag1; /* - FLAG BYTE 1 */ + unsigned char iobflag2; /* - FLAG BYTE 2 */ + unsigned char iobsens0; /* - FIRST SENSE BYTE */ + unsigned int iobs1b0 : 1, /* - BIT 0 (DEVICE DEPENDENT) */ + iobs1b1 : 1, /* - BIT 1 (DEVICE DEPENDENT) */ + iobs1b2 : 1, /* - BIT 2 (DEVICE DEPENDENT) */ + iobs1b3 : 1, /* - BIT 3 (DEVICE DEPENDENT) */ + iobs1b4 : 1, /* - BIT 4 (DEVICE DEPENDENT) */ + iobs1b5 : 1, /* - BIT 5 (DEVICE DEPENDENT) */ + iobs1b6 : 1, /* - BIT 6 (DEVICE DEPENDENT) */ + iobs1b7 : 1; /* - BIT 7 (DEVICE DEPENDENT) */ + struct { + unsigned char iobecbcc; /* - COMPLETION CODE FOR AN I/O REQUEST. THIS CODE */ + unsigned int iobecbpb : 24; /* - ADDRESS OF THE ECB TO BE POSTED UPON THE */ + } iobecbpt; /* - ADDRESS OF ECB TO BE POSTED ON I/O COMPLETION */ + } iobstdrd; + }; + struct { + unsigned char _filler5[8]; + struct { + struct { + struct { + unsigned char iobfl3; /* - FLAG 3 - STATUS ERROR COUNTS FOR MAGNETIC */ + } iobflag3; /* - I/O SUPERVISOR ERROR ROUTINE FLAG BYTE */ + unsigned char _filler6[3]; + } iobcmd31; /* ENDING CCW ADDRESS IF IOBEFMT1 IS ON @P1A */ + unsigned char _filler7[4]; + } iobcsw8; /* 8 BYTE CSW IF IOBEFMT1 IS ON @P1A */ + }; + struct { + unsigned char _filler8[9]; + struct { + struct { + unsigned int iobcmda : 24; /* - COMMAND ADDRESS (3890) MDC023 */ + struct { + unsigned int iobusb0 : 1, /* - ATTENTION (MDC312) @Z40MP9A */ + iobusb1 : 1, /* - STATUS MODIFIER (MDC313) @Z40MP9A */ + iobusb2 : 1, /* - CONTROL UNIT END (MDC314) @Z40MP9A */ + iobusb3 : 1, /* - BUSY (MDC315) @Z40MP9A */ + iobusb4 : 1, /* - CHANNEL END (MDC316) @Z40MP9A */ + iobusb5 : 1, /* - DEVICE END (MDC317) @Z40MP9A */ + iobusb6 : 1, /* - UNIT CHECK (MDC318) @Z40MP9A */ + iobusb7 : 1; /* - UNIT EXCEPTION (MDC319) @Z40MP9A */ + unsigned int iobcsb0 : 1, /* - PROGRAM CONTROL INTERRUPT (MDC321) @Z40MP9A */ + iobcsb1 : 1, /* - INCORRECT LENGTH (MDC322) @Z40MP9A */ + iobcsb2 : 1, /* - PROGRAM CHECK (MDC323) @Z40MP9A */ + iobcsb3 : 1, /* - PROTECTION CHECK (MDC324) @Z40MP9A */ + iobcsb4 : 1, /* - CHANNEL DATA CHECK (MDC325) @Z40MP9A */ + iobcsb5 : 1, /* - CHANNEL CONTROL CHECK (MDC326) @Z40MP9A */ + iobcsb6 : 1, /* - INTERFACE CONTROL CHECK (MDC327) @Z40MP9A */ + iobcsb7 : 1; /* - CHAINING CHECK (MDC328) @Z40MP9A */ + } iobstbyt; /* - STATUS BITS 32-47 (3890) MDC024 */ + } iobiocsw; /* - LOW-ORDER BYTES OF CSW FOR MAGNETIC DOCUMENT */ + unsigned short iobresct; /* - RESIDUAL COUNT @L6C */ + } iobcsw; /* - LOW-ORDER SEVEN BYTES OF THE LAST CSW THAT */ + }; + struct { + unsigned char _filler9[16]; + struct { + unsigned char iobsiocc; /* - SIO CODE. BITS 2 AND 3 CONTAIN CONDITION CODE */ + unsigned int iobstrtb : 24; /* - ADDRESS OF CHANNEL PROGRAM TO BE EXECUTED */ + } iobstart; /* - ADDRESS OF CHANNEL PROGRAM TO BE EXECUTED IF */ + }; + struct { + unsigned char _filler10[20]; + struct { + unsigned int iobgdpol : 1, /* - RE-ENTER SIO APPENDAGE FOR OLTEP GUARANTEED */ + iobcc3we : 1, /* - USER REQUESTS THAT IOS POST A X'6D' FOR A */ + iobpmerr : 1, /* - VTAM SETS THIS BIT ON TO INDICATE TO IOS THAT */ + iobcef : 1, /* - IOB COMMON EXTENSION IS AVAILABLE @02C */ + iobrsv41 : 1, /* - RESERVED */ + iobrsv42 : 1, /* - RESERVED */ + iobjes3i : 1, /* - JES3 INTERVENTION REQUIRED NOTIFICATION. */ + iobrsv44 : 1; /* - RESERVED */ + unsigned int iobdcbpb : 24; /* - ADDRESS OF DCB ASSOCIATED WITH THIS IOB */ + } iobdcbpt; /* - ADDRESS OF DCB ASSOCIATED WITH THIS IOB */ + }; + struct { + unsigned char _filler11[24]; + struct { + unsigned char iobrepos; /* - DURING I/O ERROR CORRECTION (MEANINGFUL ONLY */ + unsigned int iobrstrb : 24; /* - SAME AS IOBRESTR ABOVE */ + } iobrestr; /* - AFTER SVC 16 (PURGE) - QUIESCE - ADDRESS OF */ + }; + struct { + unsigned char _filler12[28]; + struct { + unsigned int iobprmer : 1, /* - SAD OR ENABLE ISSUED BY OPEN RESULTED IN A */ + iobinuse : 1, /* - THIS IOB IS CURRENTLY IN USE BY AN I/O */ + iobrsv14 : 1, /* RESERVED */ + iobrsv15 : 1, /* RESERVED */ + iobrsv16 : 1, /* RESERVED */ + iobrsv17 : 1, /* RESERVED */ + iobrftmg : 1, /* - A REQUEST-FOR-TEST MESSAGE RECEIVED FROM A */ + ioboltst : 1; /* - LINE IS UNDER ON-LINE TEST OPERATION */ + unsigned char iobrsv19; /* - RESERVED */ + } iobincam; /* - QSAM, BSAM, EXCP ACCESS METHOD -- NORMAL */ + }; + struct { + unsigned char _filler13[28]; + unsigned int iobovr : 1, /* - OVERRUN ERROR (3890) (MDC026) @G30HP9A */ + iobrej : 1, /* - COMMAND REJECT ERROR (3890) (MDC027) @G30HP9A */ + iobdck : 1, /* - DATA CHECK ERROR (3890) (MDC028) @G30HP9A */ + iobbus : 1, /* - BUS-OUT ERROR (3890) (MDC029) @G30HP9A */ + iobeqp : 1, /* - EQUIPMENT CHECK ERROR (3890) (MDC030) @G30HP9A */ + iobent : 1, /* - FIRST TIME ENTRY SWITCH (3890) */ + iobrsv47 : 1, /* - RESERVED FOR 3890 MDC044 */ + iobrsv46 : 1; /* - RESERVED FOR 3890 MDC033 */ + unsigned char _filler14; + }; + struct { + unsigned char _filler15[28]; + unsigned char iobcrdcc; /* - DATA CHECK ERROR COUNT (OPTICAL READER) */ + unsigned char iobcrilc; /* - INCORRECT LENGTH ERROR COUNT (OPTICAL READER) */ + }; + struct { + unsigned char _filler16[28]; + unsigned char iobamaf; /* SMS DIAGNOSTICS BYTE TO DESCRIBE @L1A */ + unsigned char _filler17; + short int ioberrct; /* - USED BY I/O SUPERVISOR ERROR ROUTINES TO COUNT */ + }; + struct { + unsigned char _filler18[32]; + struct { + struct { + unsigned char iobm; /* - THE NUMBER OF THE DEB EXTENT TO BE USED FOR */ + struct { + unsigned char iobbb1; + unsigned char iobbb2; + } iobbb; /* - BIN NUMBER(DATA CELL) */ + struct { + unsigned char iobcc1; + unsigned char iobcc2; + } iobcc; /* - CYLINDER NUMBER */ + struct { + unsigned char iobhh1; + unsigned char iobhh2; + } iobhh; /* - TRACK NUMBER */ + unsigned char iobr; /* - RECORD NUMBER */ + } iobseek; /* - A SEEK ADDRESS (IN THE FORMAT MBBCCHHR) USED */ + } iobexten; + }; + struct { + unsigned char _filler19[32]; + struct { + struct { + unsigned char iobrtype; /* - RECORD TYPE FOR OBR MDC002 */ + } iobucbxv; /* - UCB INDEX MDC050 */ + unsigned int iobercta : 24; /* - POINTER TO COUNTERS FOR SIO AND TEMPORARY */ + } ioberct; /* - POINTER TO COUNTERS FOR SIO AND TEMPORARY */ + struct { + char iobnamsz; /* - SIZE OF TERMINAL NAME MDC005 */ + unsigned int iobnamea : 24; /* - POINTER TO TERMINAL NAME MDC006 */ + } iobname; /* - POINTER TO TERMINAL NAME MDC004 */ + }; + struct { + unsigned char _filler20[32]; + struct { + unsigned char iobskrv; /* - RESERVED (MDC301) @Z30OP9A */ + unsigned char iobsktt; /* - TRACK NUMBER (MDC302) @Z30OP9A */ + unsigned char iobsk0; /* - MUST BE ZERO (MDC303) @Z30OP9A */ + unsigned char iobskss; /* - SECTOR NUMBER (MDC304) @Z30OP9A */ + } iobskadr; /* - 3540 SEEK ADDRESS (MDC300) @Z30OP9A */ + unsigned char _filler21[4]; + }; + struct { + unsigned char _filler22[32]; + unsigned char iobucbx; /* - UCB INDEX. THE LINE NUMBER IS USED AS AN */ + unsigned char iobwork[5]; /* - WORK AREA USED BY ERROR ROUTINES AND ON-LINE */ + unsigned char iobrcvpt; /* - RECEIVED ACK (ACK-0 OR ACK-1) */ + unsigned char iobsndpt; /* - SENT ACK (ACK-0 OR ACK-1) */ + }; + struct { + unsigned char _filler23[32]; + unsigned char iobucbxg; /* - UCB INDEX */ + unsigned char iobrsv37[3]; /* - RESERVED */ + struct { + unsigned int iobavlfl : 1, /* - IF 0, IOB IS AVAILABLE. */ + iobrsv20 : 1, /* RESERVED */ + iobrsv21 : 1, /* RESERVED */ + iobrsv22 : 1, /* RESERVED */ + iobrsv23 : 1, /* RESERVED */ + iobrsv24 : 1, /* RESERVED */ + iobrsv25 : 1, /* RESERVED */ + iobrsv26 : 1; /* RESERVED */ + unsigned int iobnxtpb : 24; /* - ADDRESS OF NEXT AVAILABLE IOB. SET TO ZERO */ + } iobnxtpt; /* - ADDRESS OF NEXT AVAILABLE IOB. SET TO ZERO */ + }; + struct { + unsigned char _filler24[42]; + struct { + unsigned char w1oexten[2]; /* - SAME AS W1IEXTEN ABOVE */ + } w1iexten; /* - APPENDAGE CODES FOR BOTH NORMAL AND ABNORMAL */ + }; + struct { + unsigned char _filler25[42]; + struct { + unsigned char iobsk2m; /* - EXTENT NUMBER ICB435 */ + unsigned char iobsk2bb[2]; /* - BIN NUMBER ICB435 */ + unsigned char iobsk2cc[2]; /* - CYLINDER NUMBER ICB435 */ + unsigned char iobsk2hh[2]; /* - HEAD NUMBER ICB435 */ + unsigned char iobsk2r; /* - RECORD NUMBER ICB435 */ + } iobseek2; /* - SEEK FIELD 2 ICB435 */ + }; + struct { + unsigned char _filler26[42]; + unsigned char ioberccw[8]; /* - CCW AREA USED BY THE BTAM ERROR RECOVERY */ + }; + struct { + unsigned char _filler27[42]; + void * PTR32 iobccwad; /* - FOR FIXED LENGTH RECORDS, ADDRESS OF FIRST */ + unsigned int iobdeqcp : 1, /* - DEQUEUE CHANNEL PROGRAM FROM QUEUE */ + iobunsch : 1, /* - UNSCHEDULED QUEUE */ + iobovptr : 1, /* - IF 0, DECBAREA + 6 POINTS TO OVERFLOW RECORD */ + iobkeyad : 1, /* - IF 0, DECBKEY POINTS TO OVERFLOW RECORD KEY. */ + iobrsv27 : 1, /* RESERVED */ + iobrsv28 : 1, /* RESERVED */ + iobrsv29 : 1, /* RESERVED */ + iobchnnl : 1; /* - IF 0, NORMAL CHANNEL END HAS OCCURRED. */ + unsigned int iobcpbsy : 1, /* - CHANNEL PROGRAM CP1 OR CP2 BUSY */ + iobntav1 : 1, /* - NO CP4, CP5 OR CP6 AVAILABLE */ + iobntav2 : 1, /* - NO CP7 AVAILABLE */ + iobknwr : 1, /* - WRITE KN IS IN EFFECT (UNSCHEDULED IOB IS FOR */ + iobknrwr : 1, /* - WRITE KN IS IN EFFECT (UNSCHEDULED IOB IS FOR */ + iobrsv30 : 1, /* RESERVED */ + iobrsv31 : 1, /* RESERVED */ + iobrsv32 : 1; /* RESERVED */ + unsigned char iobapp; /* - APPENDAGE CODE */ + unsigned char iobasyn; /* - ASYNCHRONOUS ROUTINE CODE */ + struct { + unsigned char iobcount; /* - WRITE CHECK COUNTER */ + unsigned int iobfchnb : 24; /* - FORWARD CHAIN ADDRESS */ + } iobfchad; /* - FORWARD CHAIN ADDRESS */ + }; + struct { + unsigned char _filler28[42]; + unsigned char iobccw[32]; /* - LIST OF CHANNEL COMMAND WORDS TO TRANSFER DATA */ + }; + struct { + unsigned char _filler29[42]; + short int iobdbytr; /* - NUMBER OF UNUSED BYTES REMAINING ON THE TRACK */ + unsigned char iobdcap0; /* LAST BYTE OF CAPACITY RECORD - MUST REMAIN */ + unsigned char iobdiobs; /* OVERALL SIZE OF THE IOB IN WORDS @04C */ + struct { + unsigned char iobdayli; /* - ALL BITS SET TO ZERO INDICATE THE AVAILABILITY */ + unsigned int iobdplb : 24; /* - ADDRESS OF THE NEXT IOB IN THE POOL OF IOB'S */ + } iobdplad; /* - ADDRESS OF THE NEXT IOB IN THE POOL OF IOB'S */ + unsigned int iobverfy : 1, /* - VERIFY */ + iobovflo : 1, /* - OVERFLOW */ + iobextsc : 1, /* - EXTENDED SEARCH */ + iobfdbck : 1, /* - FEEDBACK */ + iobactad : 1, /* - ACTUAL ADDRESSING */ + iobdynbf : 1, /* - DYNAMIC BUFFERING */ + iobrdexc : 1, /* - READ EXCLUSIVE */ + iobrelbl : 1; /* - RELATIVE BLOCK ADDRESSING */ + unsigned int iobskey : 1, /* - KEY ADDRESS CODED AS 'S' */ + iobsblkl : 1, /* - BLOCK LENGTH CODED AS 'S' */ + iobsuffx : 2, /* - IF BITS 2 AND 3 ARE ONE, RU IS SUFFIXED TO THE */ + iobrqust : 1, /* - IF 1, READ REQUEST. IF 0, WRITE REQUEST. */ + iobtype : 1, /* - IF 1, KEY TYPE. IF 0, ID TYPE. */ + iobaddty : 1, /* - ADD TYPE */ + iobrelex : 1; /* - RELEX MACRO ISSUED */ + struct { + unsigned int iobabnrm : 1, /* - ABNORMAL COMPLETION */ + iobnewvl : 1, /* - ON EXTENDED SEARCH, THE NEXT EXTENT IS ON A */ + iobsynch : 1, /* - MODULE WAS ENTERED VIA SYNCH MDC037 */ + iobpass2 : 1, /* - ON EXTENDED SEARCH, INDICATES TO THE RELATIVE */ + iobenque : 1, /* - FOR EXCLUSIVE CONTROL REQUEST, INDICATES THAT */ + iobbuff : 1, /* - A BUFFER HAS BEEN ASSIGNED TO THIS IOB */ + iobaddvu : 1, /* - IOB BEING USED TO ADD A VARIABLE (V) OR */ + iobsiort : 1; /* - INDICATES TO THE DYNAMIC BUFFERING ROUTINE */ + unsigned char iobstat2; /* - ERROR CODE FOR ABNORMAL COMPLETION USED AS */ + } iobdstat; /* - STATUS OF THE I/O REQUEST */ + void * PTR32 iobdcpnd; /* - ADDRESS OF LOCATION WHERE CHANNEL END PROGRAM */ + short int iobdbytn; /* - NUMBER OF BYTES NEEDED ON A TRACK TO WRITE A */ + unsigned int iobrec31 : 1, /* - BLOCK REFERENCE ADDR (DECRECPT) IS A @03A */ + iobkey31 : 1, /* - KEY ADDR (DECKYADR) IS A 31 BIT ADDR @03A */ + iobdat31 : 1, /* - DATA ADDR (DECAREA) IS A 31 BIT ADDR @03A */ + : 5; + unsigned char iobrsv34; /* - RESERVED @03C */ + void * PTR32 iobdqptr; /* - ADDRESS OF IOB FOR NEXT I/O OPERATION TO BE */ + unsigned char iobrsv35[8]; /* - RESERVED */ + }; + struct { + unsigned char _filler30[42]; + void * PTR32 iobmdrec; /* - POINTER TO RECORD BEING PASSED TO */ + void * PTR32 iobrcd; /* - POINTER TO QUEUE OF OBR RECORDS PASSED FROM */ + unsigned char iobsensv; /* - SENSE BYTE SAVE AREA MDC009 */ + unsigned char iobcswsv[7]; /* - SAVE AREA FOR LAST 7 BYTES OF CSW MDC010 */ + unsigned char _filler31[16]; + }; + struct { + unsigned char _filler32[48]; + unsigned char ioberinf[16]; /* - ERROR INFORMATION FIELD USED BY THE BTAM ERROR */ + struct { + unsigned char _filler33[8]; + } iobcpa; /* - CHANNEL PROGRAMS AREA. THE LENGTH DEPENDS ON */ + }; + struct { + unsigned char _filler34[48]; + void * PTR32 iobbufc; /* - ADDRESS OF ASSOCIATED BUFFER CONTROL BLOCK */ + void * PTR32 iobreada; /* - ADDRESS OF FIRST READ CHANNEL PROGRAM SEGMENT */ + void * PTR32 iobnexta; /* - ADDRESS OF NEXT ACTIVE IOB ICB435 */ + void * PTR32 iobrdchp; /* - ADDRESS OF READ CHANNEL PROGRAM ICB435 */ + unsigned char _filler35[8]; + }; + struct { + unsigned char _filler36[52]; + void * PTR32 iobbchad; /* - BACKWARD CHAIN ADDRESS */ + unsigned char _filler37[16]; + unsigned char iobdncrf[8]; /* - COUNT FIELD FOR NEW BLOCK */ + }; + struct { + unsigned char _filler38[72]; + __extension__ double iobchnpr[0]; /* - CHANNEL PROGRAM USED TO TRANSFER DATA AS */ + }; + }; + }; + +/* Values for field "iobnflg1" */ +#define iobprtov 0x80 /* - PRTOV HAS OCCURRED (PRINTER DEVICES) */ +#define iobsegmt 0x80 /* - SEGMENTING OF A SPANNED RECORD IS IN PROCESS */ +#define iobwrite 0x40 /* - A WRITE OPERATION IS IN PROCESS */ +#define iobread 0x20 /* - A READ OPERATION IS IN PROCESS */ +#define iobupdat 0x10 /* - UPDATE FLAG. SET ON TOGETHER WITH BIT 1 OF */ +#define iobbkspc 0x08 /* - IOB BEING USED FOR BACKSPACE, CONTROL OR */ +#define iobspan 0x04 /* - THE RECORD CURRENTLY BEING PROCESSED HAS MORE */ +#define iobuperr 0x02 /* - UPDATE CHANNEL PROGRAM HAS BEEN SPLIT INTO */ +#define iobfirst 0x01 /* - THIS IS THE FIRST IOB ON CHAIN */ + +/* Values for field "iobflag1" */ +#define iobdatch 0x80 /* - DATA CHAINING USED IN CHANNEL PROGRAM */ +#define iobcmdch 0x40 /* - COMMAND CHAINING USED IN CHANNEL PROGRAM */ +#define ioberrtn 0x20 /* - ERROR ROUTINE IS IN CONTROL */ +#define iobrpstn 0x10 /* - DEVICE IS TO BE REPOSITIONED */ +#define iobcycck 0x08 /* - CYCLIC REDUNDANCY CHECK (CRC) NEEDED (TAPE) */ +#define iobfcrex 0x08 /* - FETCH COMMAND RETRY EXIT (DIRECT ACCESS) */ +#define iobioerr 0x04 /* - EXCEPTIONAL CONDITION. AFTER THE ERROR */ +#define iobunrel 0x02 /* - IOB UNRELATED FLAG (I.E., NONSEQUENTIAL) */ +#define iobrstrt 0x01 /* - IF 1, RESTART ADDRESS IN IOB TO BE USED. */ +#define iobspsvc 0x01 /* - FOR SAM/PAM, SET BY SVC IF I/O APPENDAGE */ + +/* Values for field "iobflag2" */ +#define iobhalt 0x80 /* - HALT I/O HAS BEEN ISSUED BY SVC PURGE ROUTINE */ +#define iobsense 0x40 /* - SENSE WILL NOT BE PERFORMED UNTIL THE DEVICE */ +#define iobpurge 0x20 /* - IOB HAS BEEN PURGED TO ALLOW I/O ACTIVITY TO */ +#define iobrrt3 0x20 /* - TYPE 3 RELATED REQUEST (OS/VS2) MDC048 */ +#define iobrdha0 0x10 /* - HOME ADDRESS (R0) RECORD IS TO BE READ. SEEK */ +#define iobrrt2 0x10 /* - TYPE 2 RELATED REQUEST (OS/VS2) MDC049 */ +#define iobalttr 0x08 /* - NO TEST FOR OUT-OF-EXTENT. AN ALTERNATE TRACK */ +#define iobskupd 0x04 /* - SEEK ADDRESS IS BEING UPDATED. CYLINDER END */ +#define iobstato 0x02 /* - DEVICE END STATUS HAS BEEN OR'ED WITH CHANNEL */ +#define iobpnch 0x01 /* - ERROR RECOVERY IN CONTROL FOR A 2540 CARD */ + +/* Values for field "iobsens0" */ +#define iobs0b0 0x80 /* - BIT 0 (DEVICE DEPENDENT) */ +#define iobs0b1 0x40 /* - BIT 1 (DEVICE DEPENDENT) */ +#define iobs0b2 0x20 /* - BIT 2 (DEVICE DEPENDENT) */ +#define iobs0b3 0x10 /* - BIT 3 (DEVICE DEPENDENT) */ +#define iobs0b4 0x08 /* - BIT 4 (DEVICE DEPENDENT) */ +#define iobs0b5 0x04 /* - BIT 5 (DEVICE DEPENDENT) */ +#define iobs0b6 0x02 /* - BIT 6 (DEVICE DEPENDENT) */ +#define iobs0b7 0x01 /* - BIT 7 (DEVICE DEPENDENT) */ +#define iobsnsc9 0x01 /* - CHANNEL 9 SENSED IN CARRIAGE TAPE */ + +/* Values for field "iobfl3" */ +#define iobccc 0x80 /* - CHANNEL CONTROL CHECK ERROR COUNT (3890) */ +#define iobicc 0x40 /* - INTERFACE CONTROL CHECK ERROR COUNT (3890) */ +#define iobcdc 0x20 /* - CHANNEL DATA CHECK ERROR (3890) MDC040 */ +#define iobacu 0x10 /* - ATTENTION/CONTROL UNIT ERROR (3890) MDC041 */ +#define iobcnc 0x08 /* - CHAIN CHECK ERROR (3890) MDC042 */ +#define iobsdr 0x08 /* - STATISTICS ONLY FLAG (3800) (MDC306) @X50AD9A */ +#define iobmsg 0x04 /* - MESSAGE FLAG (3890 OR 3800) (MDC308) @X50AD9A */ +#define iobicl 0x02 /* - INCORRECT LENGTH ERROR (3890) MDC020 */ +#define iobjam 0x02 /* - SET ON WHEN JES SUBSYSTEM HAS DETECTED A */ +#define ioblog 0x01 /* - LOG OUT FLAG (3890 OR 3800) (MDC309) @X50AD9A */ + +/* Values for field "iobamaf" */ +#define iobbdfpl 0x01 /* - BAD FPL PASSED TO ASYNC COMP RTN @L1A */ +#define iobpgmck 0x02 /* - PROGRAM CHECK ENCOUNTERED IN IGG019SY @L1A */ +#define iobbadrc 0x03 /* - BAD RETURN CODE ENCOUNTERED FROM SMS - @L1A */ +#define iobbadlt 0x04 /* - INVALID LOCATOR TOKEN DETECTED BY POINT @L1A */ +#define iobncrlt 0x05 /* - RLT WAS INPUT BUT NO MEMBER WAS CONNECTED @L1A */ +#define iobpout 0x06 /* - DCB OPEN FOR OUTPUT & AN MLT FOR OTHER @L1A */ +#define ioboutio 0x07 /* - OUTSTANDING I/O IN PROGRESS DETECTED @L1A */ +#define iobrlttb 0x08 /* - RLT TOO BIG (>= HWM) DETECTED BY POINT @L1A */ +#define iobflock 0x09 /* - CONNECT OR RECONNECT UNABLE TO GET FILE @01A */ +#define iobnfile 0x0A /* - MLT INPUT TO POINT BUT NO SUCH FILE @01A */ +#define iobpad 0x0B /* - PADDING ERROR DETECTED BY MEDIA MANAGER @L2A */ +#define iobmmerr 0x0C /* - I/O ERROR DETECTED BY MEDIA MANAGER FOR @L2A */ +#define iobshdw 0x0D /* - AN I/O ERROR ENCOUNTERED IN A SHADOW IOB. @L4A */ +#define iobrbnnp 0x0E /* - READ/WRITE REQUEST IS FOR A USER RBN WHICH@L4A */ + +#define iobgam 0x0C +#define iobqisam 0x0C + +#pragma pack(pop) + +#endif diff --git a/include/ispf.h b/include/ispf.h new file mode 100644 index 0000000..53a12b2 --- /dev/null +++ b/include/ispf.h @@ -0,0 +1,50 @@ +#ifndef __ISPF__ + #define __ISPF__ + + #include + + #pragma pack(1) + struct ispf_disk_stats { + unsigned char ver_num; + unsigned char mod_num; + int sclm:1; + int reserve_a:1; + int extended:1; + int reserve_b:5; + unsigned char pd_mod_seconds; + + unsigned char create_century; + char pd_create_julian[3]; + + unsigned char mod_century; + char pd_mod_julian[3]; + + unsigned char pd_mod_hours; + unsigned char pd_mod_minutes; + unsigned short curr_num_lines; + + unsigned short init_num_lines; + unsigned short mod_num_lines; + + char userid[8]; + + /* following is available only in extended format */ + unsigned int full_curr_num_lines; + unsigned int full_init_num_lines; + unsigned int full_mod_num_lines; + }; + #pragma pack(pop) + + struct ispf_stats { + struct tm create_time; + struct tm mod_time; + unsigned int curr_num_lines; + unsigned int init_num_lines; + unsigned int mod_num_lines; + unsigned char userid[8+1]; + unsigned char ver_num; + unsigned char mod_num; + unsigned char sclm; + }; + +#endif diff --git a/include/mem.h b/include/mem.h new file mode 100644 index 0000000..7796447 --- /dev/null +++ b/include/mem.h @@ -0,0 +1,15 @@ +#ifndef __MEM_H__ +#define __MEM_H__ 1 + + #include + #include "diocommon.h" + + void* PTR32 MALLOC24(unsigned int len); + int FREE24(void* PTR32 addr, unsigned int len); + void* PTR32 MALLOC31(unsigned int len); + void FREE31(void* PTR32 addr); + + void dumpstg(FILE* stream, void* p, size_t len); + + +#endif diff --git a/include/opencb.h b/include/opencb.h new file mode 100644 index 0000000..47652c4 --- /dev/null +++ b/include/opencb.h @@ -0,0 +1,19 @@ +#ifndef __OPENCB__ +#define __OPENCB__ 1 + +#include "diocommon.h" + +#pragma pack(1) +struct opencb { + int last_entry:1; + int disp:3; + int mode:4; + int reserved:24; + void* PTR32 dcb24; +}; + +#define OPEN_INPUT (0) +#define OPEN_OUTPUT (0xF) +#pragma pack(pop) + +#endif diff --git a/include/smde.h b/include/smde.h new file mode 100644 index 0000000..d355bd0 --- /dev/null +++ b/include/smde.h @@ -0,0 +1,411 @@ +#ifndef __SMDE_H__ +#define __SMDE_H__ 1 + +#include "diocommon.h" + +#pragma pack(1) + +struct smde { + union { + unsigned char smde_basic[44]; /* START OF BASIC SECTION */ + unsigned char smde_hdr[16]; /* HEADER */ + struct { + unsigned char smde_id[8]; /* EYECATCHER IGWSMDE */ + int smde_len; /* LENGTH OF CONTROL BLOCK. THIS */ + unsigned int : 7, + smde_lvl_val : 1; /* LEVEL CONSTANT */ + unsigned char _filler1[3]; /* RESERVED */ + unsigned char smde_libtype; /* SOURCE LIBRARY TYPE. POSSIBLE */ + unsigned int smde_flag_alias : 1, /* ENTRY IS AN ALIAS. */ + smde_flag_lmod : 1, /* MEMBER IS A PROGRAM. */ + smde_system_dcb : 1, /* DCB IS A SYSTEM DCB, THEREFORE */ + : 5; + unsigned char _filler2[2]; /* RESERVED. MUST BE ZERO. */ + unsigned char _filler3; /* RESERVED. MUST BE ZERO. */ + struct { + unsigned char smde_mlt[3]; /* MLT OF MEMBER (ZERO IF HFS) */ + unsigned char smde_cnct; /* CONCATENATION NUMBER */ + } smde_mltk; /* MLT AND CONCAT # */ + unsigned char smde_libf; /* LIBRARY FLAG (Z-BYTE) */ + short int smde_name_off; /* NAME OFFSET */ + struct { + short int smde_pmar_len; /* SUM OF LENGTHS OF PROGRAM */ + } smde_usrd_len; /* USER DATA LENGTH */ + struct { + short int smde_pmar_off; /* PROGRAM MANAGEMENT */ + } smde_usrd_off; /* USER DATA OFFSET */ + struct { + short int smde_gene_len; /* GENERATION SECTION LENGTH @L4A */ + } smde_token_len; /* TOKEN SECTION LENGTH @L4C */ + struct { + short int smde_gene_off; /* GENERATION SECTION OFFSET @L4A */ + } smde_token_off; /* TOKEN DATA OFFSET @L4C */ + short int smde_pname_off; /* PRIMARY NAME OFFSET. */ + short int smde_nlst_cnt; /* NUMBER OF NOTE LIST */ + short int smde_c370_attr_off; /* OFFSET TO C370LIB ATTRIBUTE @02A */ + short int smde_ext_attr_off; /* OFFSET TO EXTENDED ATTRIBUTES @L3A */ + __extension__ unsigned char smde_sections[0]; /* START OF ENTRY SECTIONS */ + }; + }; + }; + +/* Values for field "smde_libtype" */ +#define smde_libtype_c370lib 0x03 /* C370LIB LIBRARY TYPE @L2A */ +#define smde_libtype_hfs 0x02 /* HFS FILE TYPE */ +#define smde_libtype_pdse 0x01 /* PDSE LIBRARY TYPE */ +#define smde_libtype_pds 0x00 /* PDS LIBRARY TYPE */ + +/* Values for field "smde_libf" */ +#define smde_libf_tasklib 0x02 /* LIBRARY FOUND FLAG - TASKLIB */ +#define smde_libf_linklib 0x01 /* LIBRARY FOUND FLAG - LNKLST */ +#define smde_libf_private 0x00 /* LIBRARY FOUND FLAG - PRIVATE */ + +struct smde_name { + short int smde_name_len; /* LENGTH OF ENTRY NAME */ + __extension__ unsigned char smde_name_val[0]; /* ENTRY NAME */ + }; + +struct smde_nlst { + union { + unsigned char smde_nlst_entry[4]; /* NOTE LIST ENTRIES */ + struct { + unsigned char smde_nlst_rlt[3]; /* NOTE LIST RECORD LOCATION */ + unsigned char smde_nlst_num; /* NUMBER OF RLT DESCRIBED BY */ + }; + }; + }; + +struct smde_token { + union { + struct { + int smde_token_connid; /* CONNECT_IDENTIFIER */ + int smde_token_itemno; /* ITEM NUMBER */ + unsigned char smde_token_ft[24]; /* FILE TOKEN */ + }; + struct { + unsigned char _filler1[16]; /* RESERVED @L2A */ + unsigned char smde_token_bmf_ct[8]; /* BMF CONNECT TOKEN @L2A */ + unsigned char smde_token_cdm_ct[8]; /* JCDM CONNECT TOKEN @L2A */ + __extension__ unsigned char smde_token_end[0]; + }; + }; + }; + +struct smde_fd { + int smde_fd_token; /* FILE DESCRIPTOR */ + __extension__ unsigned char smde_fd_end[0]; + }; + +struct smde_pname { + short int smde_pname_len; /* LENGTH OF PRIMARY NAME */ + __extension__ unsigned char smde_pname_val[0]; /* PRIMARY NAME */ + }; + +struct smde_gene { + unsigned char smde_gene_name[8]; /* Generation Name */ + unsigned int smde_is_dummy : 1, /* Entry is dummy */ + : 7; + unsigned char smde_gene_flgs2; /* Flags */ + unsigned char smde_gene_flgs3; /* Flags */ + unsigned char smde_gene_flgs4; /* Flags */ + int smde_gene_number; /* Absolute Generation number */ + union { + unsigned char smde_gene_mltk[4]; /* MLT AND CONCAT # */ + struct { + unsigned char smde_gene_mlt[3]; /* MLT OF MEMBER */ + unsigned char smde_gene_cnct; /* CONCATENATION NUMBER */ + }; + }; + short int smde_gene_ccsid; /* CCSID or '0000'x if not */ + unsigned char _filler1[2]; /* Reserved */ + unsigned char smde_gene_userid[8]; /* Userid of creator or last */ + unsigned char smde_gene_timestamp[8]; /* Last member update or create */ + unsigned char smde_gene_gentimestamp[8]; /* Last generation update */ + __extension__ unsigned char smde_gene_end[0]; /* @03A */ + }; + +/* Values for field "smde_gene_end" */ +#define smde_po1_name_maxlen 63 /* Maximum length of names in a */ +#define smde_hfs_name_maxlen 256 /* Maximum length of names in a */ +#define smde_po2_name_maxlen 1024 /* Maximum length of names in a */ +#define smde_name_maxlen 1024 /* Maximum length of names @L1A */ +#define smde_pname_maxlen 8 /* Maximum length of primary */ +#define smde_maxlen 0x11F +#define smde_hfs_maxlen 0x4BA +#define smde_po2_maxlen 0x4E0 +#define smde_all_maxlen 0x4E0 /* Maximum length of SMDE for all */ +#define smde_pds_maxlen 0x42 + +struct smde_ext_attr { + short int smde_ext_attr_len; /* length of this section @L3a */ + unsigned char smde_ccsid[2]; /* CCSID, or x'0000' if CCSID was */ + unsigned char smde_type_descriptor[16]; /* type descriptor @L3a */ + unsigned char smde_userid_last_change[8]; /* userid of creator or last updater */ + unsigned char smde_change_timestamp[8]; /* last member update or creation@L3a */ + }; + +struct pmar { + union { + unsigned char pmar_entry[30]; /* Alternative name for the PMAR section */ + struct { + short int pmar_slen; /* Section length. */ + unsigned char pmar_lvl; /* PMAR format level */ + unsigned char pmar_plvl; /* Bind processor creating object */ + struct { + unsigned int pmar_rent : 1, /* Reenterable */ + pmar_reus : 1, /* Reusable */ + pmar_ovly : 1, /* Overlay structure */ + pmar_test : 1, /* Module to be tested - TESTRAN */ + pmar_load : 1, /* Only loadable */ + pmar_sctr : 1, /* Scatter format */ + pmar_exec : 1, /* Executable */ + pmar_1blk : 1; /* Load module contains only one */ + unsigned int pmar_flvl : 1, /* If on, the program cannot be */ + pmar_org0 : 1, /* Linkage editor assigned origin */ + : 1, + pmar_nrld : 1, /* Program contains no RLD items */ + pmar_nrep : 1, /* Module cannot be reprocessed */ + pmar_tstn : 1, /* Module contains TESTRAN symbol */ + : 1, + pmar_refr : 1; /* Refreshable program */ + struct { + unsigned int : 1, + pmar_big : 1, /* This program requires 16M bytes */ + pmar_paga : 1, /* Page alignment is required */ + pmar_xssi : 1, /* SSI information present */ + pmar_xapf : 1, /* APF information present */ + pmar_lfmt : 1, /* PMARL follows PMAR. */ + pmar_signed : 1, /* Program is signed. Verified on */ + : 1; + } pmar_atr3; /* Third attribute byte. */ + struct { + unsigned char pmar_ftb2; /* Alternative name for flags byte */ + } pmar_atr4; /* Fourth attribute byte */ + } pmar_atr; /* Attribute bytes. */ + unsigned int : 7, + pmar_longparm : 1; /* Parm >100 chars allowed @LFA */ + unsigned char pmar_ac; /* APF authorization code */ + unsigned char pmar_stor[4]; /* Virtual storage required */ + unsigned char pmar_epm[4]; /* Main entry point offset */ + unsigned char pmar_epa[4]; /* This entry point offset */ + struct { + unsigned char pmar_chlv; /* Change level of member */ + unsigned char pmar_ssfb; /* SSI flag byte */ + unsigned char pmar_mser[2]; /* Member serial number */ + } pmar_ssi; /* SSI information */ + unsigned int pmar_system_le : 1, /* @L7A */ + pmar_lightweight_le : 1, /* @L7A */ + : 14; + unsigned char _filler1[2]; /* Reserved @L7A */ + __extension__ unsigned char pmar_end[0]; /* END OF BASIC SECTION */ + }; + }; + }; + +/* Values for field "pmar_lvl" */ +#define pmar_pm1_val 0x01 /* level constant for PO1 @L2A */ +#define pmar_pm2_val 0x02 /* level constant for PO2 @L2A */ +#define pmar_pm3_val 0x03 /* level constant for PO3 @L3A */ +#define pmar_pm4_val 0x04 /* level constant for PO4 @L7A */ +#define pmar_pm5_val 0x05 /* level constant for PO5 @LAA */ +#define pmar_lvl_val 0x05 /* level constant @LAC */ + +/* Values for field "pmar_plvl" */ +#define pmar_plvl_e_val 0x01 /* E-level constant */ +#define pmar_plvl_f_val 0x02 /* F-level constant */ +#define pmar_plvl_aos_val 0x03 /* AOS-level constant */ +#define pmar_plvl_xa_val 0x04 /* XA-level constant */ +#define pmar_plvl_b1_val 0x05 /* Binder version 1 */ +#define pmar_plvl_b2_val 0x06 /* Binder version 2 @L2A */ +#define pmar_plvl_b3_val 0x07 /* Binder version 3 @L3A */ +#define pmar_plvl_b4_val 0x08 /* Binder version 4 @L7A */ +#define pmar_plvl_b5_val 0x09 /* Binder version 5 @L8A */ + +/* Values for field "pmar_ftb2" */ +#define pmar_altp 0x80 /* Alternate primary flag. If on */ +#define pmar_rmode64 0x20 /* RMODE 64 @LGC */ +#define pmar_rmod 0x10 /* RMODE is 31 or 64 */ +#define pmar_aamd 0x0C /* Alias entry point addressing */ +#define pmar_aamd_maskoff 0xF3 /* Mask for AMODE flags */ +#define pmar_mamd 0x03 /* Main entry point addressing */ + +struct pmarl { + short int pmarl_slen; /* Section length */ + union { + unsigned char pmarl_data[48]; /* Section Data */ + unsigned char pmarl_atr[4]; /* Attribute bytes */ + struct { + unsigned char pmarl_atr1; /* 6th attribute byte */ + unsigned int pmarl_cmpr : 1, /* Compressed format module */ + pmarl_1rmod : 1, /* 1st segment is RMODE 31, @L2A */ + pmarl_2rmod : 1, /* 2nd segment is RMODE 31, @L2A */ + : 1, + pmarl_1alin : 1, /* 1st segment is page-aligned,@L2A */ + pmarl_2alin : 1, /* 2nd segment is page-aligned,@L2A */ + pmarl_fill : 1, /* FILL option specified @L2A */ + : 1; + unsigned char pmarl_fillval; /* FILL character value @L2A */ + unsigned char pmarl_po_sublvl; /* Program object sublevel @L7A */ + unsigned char pmarl_mpgs[4]; /* Total length of program on */ + struct { + unsigned char pmarl_txtl[4]; /* Length of initial load text on */ + void * PTR32 pmarl_txto; /* Offset to text */ + unsigned char pmarl_bdrl[4]; /* Length of Binder index */ + void * PTR32 pmarl_bdro; /* Offset to Binder index */ + unsigned char pmarl_rdtl[4]; /* Length of PRDT */ + void * PTR32 pmarl_rdto; /* Offset to PRDT */ + unsigned char pmarl_ratl[4]; /* Length of PRAT */ + void * PTR32 pmarl_rato; /* Offset to PRAT */ + struct { + unsigned char pmarl_lmdl[4]; /* Length of LSLoader data, */ + } pmarl_nvspgs; /* Number of virtual storage @L2A */ + void * PTR32 pmarl_lmdo; /* Offset to LSLoader data */ + } pmarl_mdat; /* DASD program descriptors */ + }; + struct { + unsigned char _filler1[48]; + struct { + unsigned char pmarl_nseg[2]; /* Number of loadable segments @L2A */ + unsigned char pmarl_ngas[2]; /* Count of entries in Gas @L2A */ + unsigned char pmarl_1stor[4]; /* Virtual storage required @L2A */ + unsigned char pmarl_2stor[4]; /* Virtual storage required @L2A */ + unsigned char pmarl_2txto[4]; /* Offset to second txt segment@L2A */ + unsigned char _filler2[8]; + } pmarl_pm2; /* New fields for PM2-Level @L2A */ + }; + struct { + unsigned char _filler3[64]; + struct { + unsigned char pmarl_date[4]; /* Date saved @L2A */ + unsigned char pmarl_time[4]; /* Time saved @L2A */ + unsigned char pmarl_user[8]; /* User or job identification @L2A */ + } pmarl_trace; /* Audit trace data @L2A */ + }; + struct { + unsigned char _filler4[80]; + struct { + unsigned int pmarl_hide : 1, /* Name is an alias that can @L3A */ + pmarl_dllena : 1, /* PO is DLL-enabled @L3A */ + pmarl_mustdelet : 1, /* If on and directed LOAD @L3A */ + pmarl_iewblitp : 1, /* If on, PMARL_IEWBLITO is @L3A */ + pmarl_mangled : 1, /* If on, name is mangled. @L3A */ + : 3; + unsigned int pmarl_cms_system : 1, /* SYSTEM module bit @L6A */ + pmarl_cms_noclean : 1, /* Do not cleanup at end of service @L6A */ + pmarl_cms_strinit : 1, /* STRINIT bit @L6A */ + pmarl_cms_moddos : 1, /* Gen'd with DOS @L6A */ + pmarl_cms_modall : 1, /* Gen'd with ALL @L6A */ + pmarl_cms_invalxa : 1, /* XA-mode invalid @L6A */ + pmarl_cms_invalxc : 1, /* XC-mode invalid @L6A */ + : 1; + unsigned char pmarl_ndefer[2]; /* Number of deferred classes @L3A */ + unsigned char pmarl_dtempl[4]; /* Total length of deferred @L3A */ + unsigned char pmarl_1dtxto[4]; /* Offset of 1st deferred @L3A */ + unsigned char pmarl_iewblito[4]; /* Byte offset of IEWBLIT @L3A */ + } pmarl_pm3; /* New fields for PM3-Level @L3A */ + }; + struct { + unsigned char _filler5[96]; + union { + unsigned char pmarl_pm4[8]; /* New fields for PM4-Level @L7A */ + struct { + unsigned int pmarl_1rmod64 : 1, /* 1st segment is RMODE 64 @L8A */ + pmarl_2rmod64 : 1, /* 2nd segment is RMODE 64 @L8A */ + : 6; + unsigned char _filler6[7]; /* Reserved @L7A */ + __extension__ unsigned char pmarl_pm5[0]; /* New fields for PM5-Level @LAA */ + __extension__ unsigned char pmarl_end[0]; /* END OF LSLOADER SECTION */ + }; + }; + }; + }; + }; + +/* Values for field "pmarl_atr1" */ +#define pmarl_nmig 0x80 /* This program object cannot be */ +#define pmarl_prim 0x40 /* FETCHOPT PRIME option */ +#define pmarl_pack 0x20 /* FETCHOPT PACK option */ +#define pmarl_xpl 0x10 /* Module requires XPLINK @L4A */ +#define pmarl_hpl 0x10 /* Module requires XPLINK @L4A */ + +/* Values for field "pmarl_po_sublvl" */ +#define pmarl_po_sublvl_zosv1r3 1 /* Value for z/OS V1 R3 / PO4 @L7A */ +#define pmarl_po_sublvl_zosv1r5 2 /* Value for z/OS V1 R5 / PO4 @L8A */ +#define pmarl_po_sublvl_zosv1r7 3 /* Value for z/OS V1 R7 / PO4 @L9A */ +#define pmarl_po_sublvl_zosv1r8 1 /* Value for z/OS V1 R8 / PO5 @LAA */ +#define pmarl_po_sublvl_zosv1r10 2 /* Value for z/OS V1 R10 / PO5 @LBA */ +#define pmarl_po_sublvl_zosv1r13 3 /* Value for z/OS V1 R13 / PO5 @LDA */ +#define pmarl_po_sublvl_zosv2r1 4 /* Value for z/OS V2 R1 / PO5 @LEA */ + +struct pmarr { + short int pmarr_slen; /* Section length */ + union { + unsigned char pmarr_data[21]; /* Section data */ + unsigned char pmarr_ttrs[8]; /* TTR fields */ + struct { + unsigned char pmarr_ttrt[3]; /* TTR of first block of text */ + unsigned char pmarr_zero; /* Zero */ + unsigned char pmarr_ttrn[3]; /* TTR of note list or scatter */ + unsigned char pmarr_nl; /* Number of entries in note list */ + unsigned char pmarr_ftbl[2]; /* Length of first block of text. */ + struct { + unsigned char _filler1[2]; /* Reserved */ + unsigned char pmarr_rlds; /* Number of RLD/CTL records which */ + } pmarr_org; /* Load module origin if ^0 */ + union { + unsigned char pmarr_scat[8]; /* Scatter load information */ + struct { + unsigned char pmarr_slsz[2]; /* Scatter list length */ + unsigned char pmarr_ttsz[2]; /* Translation table length */ + unsigned char pmarr_esdt[2]; /* ESDID of first text block */ + unsigned char pmarr_esdc[2]; /* ESDID of EP control section */ + __extension__ unsigned char pmarr_end[0]; /* END OF LOAD MODULE ATTRIBUTES */ + }; + }; + }; + }; + }; + +struct pmara { + short int pmara_len; /* Section length */ + union { + unsigned char pmara_data; /* Section data */ + unsigned char pmara_epa[4]; /* Entry point offset */ + struct { + unsigned char _filler1[4]; + union { + unsigned char pmara_atr; /* Attribute bytes */ + unsigned char pmara_atr1; /* First attribute byte */ + struct { + unsigned int pmara_altp : 1, /* Alternate Primary flag. */ + pmara_hide : 1, /* Alias name can be hidden @L3A */ + pmara_nexec : 1, /* Entry point is non-executable */ + pmara_mangled : 1, /* Alias is a mangled name @L3A */ + pmara_amd : 2, /* Alias entry addressing mode */ + : 2; + __extension__ unsigned char pmara_end[0]; /* END OF ALIAS ENTRY SECTION */ + }; + }; + }; + }; + }; + +/* Values for field "pmara_end" */ +#define pmar_maxlen 0x88 +#define pmar_maxlen_progobj 0x88 +#define pmar_maxlen_po1 0x50 +#define pmar_maxlen_po2 0x70 /* @L3C */ +#define pmar_maxlen_po3 0x80 /* @L7C */ +#define pmar_maxlen_po4 0x88 /* @LAC */ +#define pmar_maxlen_po5 0x88 /* @LAA */ +#define pmar_maxlen_loadmod 0x35 +#define pmarl_lvl1len 0x32 /* @L2A */ +#define pmarl_lvl2len 0x52 /* @L3A */ +#define pmarl_lvl3len 0x62 /* @L7A */ +#define pmarl_lvl4len 0x6A /* @LAA */ +#define pmarl_lvl5len 0x6A /* @LAA */ + +#pragma pack(pop) + +#endif // __SMDE_H__ + diff --git a/intinclude/dioint.h b/intinclude/dioint.h index 6ca6eb1..36161a0 100644 --- a/intinclude/dioint.h +++ b/intinclude/dioint.h @@ -2,6 +2,7 @@ #define __DIOINT__ 1 #include + #include enum DSTATE { D_CLOSED=1, @@ -46,11 +47,12 @@ char ddname[DD_MAX+1]; char unix_extension[EXTENSION_MAX+1]; FILE* fp; + FM_BPAMHandle* bpamhandle; + struct mstat* memstat; enum DSTATE dstate; size_t read_buffer_size; size_t cur_read_offset; }; - void errmsg(struct DFILE* dfile, const char* format, ...); int initialize_configuration(char* in_dsname, char* in_llq, char* out_extension, int* out_txtflag, int* out_ccsid); #endif diff --git a/intinclude/s99.h b/intinclude/s99.h index 00c3478..0d9dbee 100644 --- a/intinclude/s99.h +++ b/intinclude/s99.h @@ -111,16 +111,21 @@ }; }; - #define DALDDNAM 0x01 - #define DALDSNAM 0x02 - #define DALSTATS 0x04 - #define DALNDISP 0x05 - #define DALEROPT 0x3D - #define DALRTDDN 0x55 - #define DALBRTKN 0x6E - #define DALSSREQ 0x5C - - #define DUNDDNAM 0x01 +#define DALDDNAM 0x01 +#define DALDSNAM 0x02 +#define DALSTATS 0x04 +#define DALNDISP 0x05 +#define DALEROPT 0x3D +#define DALRTDDN 0x55 +#define DALBRTKN 0x6E +#define DALSSREQ 0x5C + +#define DUNDDNAM 0x01 + +#define DALSTATS_OLD 0x1 +#define DALSTATS_MOD 0x2 +#define DALSTATS_NEW 0x4 +#define DALSTATS_SHR 0x8 struct s99_eopts { int s99eimsg:1; diff --git a/src/.dio.c.swm b/src/.dio.c.swm new file mode 100644 index 0000000..8d49713 Binary files /dev/null and b/src/.dio.c.swm differ diff --git a/src/.dio.c.swn b/src/.dio.c.swn new file mode 100644 index 0000000..d31454b Binary files /dev/null and b/src/.dio.c.swn differ diff --git a/src/Makefile b/src/Makefile index ff2a9cd..ea5d7ad 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,12 +1,13 @@ -IINCDIR=../intinclude INCDIR=../include +IINCDIR=../intinclude MACDIR=../maclib AR=ar ARFLAGS=rcs ARCHIVE=libdio.a -OBJ_FILES=dio.o call31.o call31a.o s99.o s99a.o defaults.o json_parser.o +OBJ_FILES=libdio.o call31.o call31a.o s99.o s99a.o defaults.o json_parser.o \ + ztime.o all: $(ARCHIVE) @@ -19,10 +20,13 @@ call31.o: call31.c $(IINCDIR)/wrappers.h call31a.o: call31a.s $(AS) $(ASFLAGS) -I$(MACDIR) $< >$*.lst +mema.o: mema.s + $(AS) $(ASFLAGS) -I$(MACDIR) $< >$*.lst + s99a.o: s99a.s $(AS) $(ASFLAGS) -I$(MACDIR) $< >$*.lst -dio.o: dio.c $(IINCDIR)/dioint.h $(IINCDIR)/wrappers.h $(INCDIR)/*.h +libdio.o: libdio.c $(IINCDIR)/dioint.h $(IINCDIR)/wrappers.h $(INCDIR)/*.h $(CC) $(CFLAGS) $(CPPFLAGS) -I$(INCDIR) -I$(IINCDIR) -c $< s99.o: s99.c $(IINCDIR)/dioint.h $(IINCDIR)/wrappers.h $(IINCDIR)/s99.h diff --git a/src/basicread.c b/src/basicread.c new file mode 100644 index 0000000..e69de29 diff --git a/src/call31.c b/src/call31.c index 61fef90..f005828 100644 --- a/src/call31.c +++ b/src/call31.c @@ -1,6 +1,7 @@ #include #include #include +#include "diocommon.h" #include "wrappers.h" #if AMODE == 64 @@ -12,9 +13,9 @@ //#define DEBUG_CALL31ASM 1 - int call31asm(const char* fn_name, int* fn, size_t num_parms, ...) { + int call31asm(const char* fn_name, int* fn, unsigned int num_parms, ...) { va_list args; - size_t i; + unsigned int i; int rc; unsigned int* r1_31bit_parms = __malloc31(num_parms*sizeof(unsigned int)); char* r13_31bit_dsa = __malloc31(MAX_DSA_SIZE); diff --git a/src/dio.c b/src/libdio.c similarity index 58% rename from src/dio.c rename to src/libdio.c index 9323021..c7f17ca 100644 --- a/src/dio.c +++ b/src/libdio.c @@ -8,12 +8,16 @@ #include #include #include "s99.h" +#include "bpamio.h" #include "dio.h" #include "dioint.h" +#include "memdir.h" #include "wrappers.h" +#include "dbgopts.h" #include <_Nascii.h> #include #include +#include <_Ccsid.h> #define _OPEN_SYS_EXT #include @@ -25,94 +29,39 @@ const struct s99_rbx s99rbxtemplate = {"S99RBX",S99RBXVR,{0,1,0,0,0,0,0},0,0,0}; -void errmsg(struct DFILE* dfile, const char* format, ...) -{ - va_list arg_ptr; - va_start(arg_ptr, format); - vsnprintf(dfile->msgbuff, dfile->msgbufflen, format, arg_ptr); - if (__isASCII()) { - size_t msglen = strlen(dfile->msgbuff); - if (msglen > 0) { - __e2a_l(dfile->msgbuff, msglen); - } - } - va_end(arg_ptr); -} - -static enum DIOERR dsdd_alloc(struct DFILE* dfile, struct s99_common_text_unit* dsn, struct s99_common_text_unit* dd, struct s99_common_text_unit* disp) -{ - struct s99rb* __ptr32 parms; - enum s99_verb verb = S99VRBAL; - struct s99_flag1 s99flag1 = {0}; - struct s99_flag2 s99flag2 = {0}; - size_t num_text_units = 3; - int rc; - struct s99_rbx s99rbx = s99rbxtemplate; - - parms = s99_init(verb, s99flag1, s99flag2, &s99rbx, num_text_units, dsn, dd, disp ); - if (!parms) { - errmsg(dfile, "Unable to initialize SVC99 (DYNALLOC) control blocks."); - return DIOERR_SVC99INIT_ALLOC_FAILURE; +static int get_space_char(int ccsid) { + if (ccsid == 0) { + return 0x40; // Default to EBCDIC for untagged datasets } - rc = S99(parms); - if (rc) { - errmsg(dfile, "SVC99 failed. See error log for details."); -#ifdef DEBUG - s99_fmt_dmp(dfile->logstream, parms); -#endif - s99_prt_msg(dfile, dfile->logstream, parms, rc); - return DIOERR_SVC99_ALLOC_FAILURE; + if (ccsid > 0) { + __csType cs = __CcsidType(ccsid); + if (cs == _CSTYPE_ASCII || cs == _CSTYPE_UTF8) { + return 0x20; // ASCII space + } + if (cs == _CSTYPE_EBCDIC) { + return 0x40; // EBCDIC space + } } - - struct s99_common_text_unit* ddout = (struct s99_common_text_unit*) parms->s99txtpp[1]; - dd->s99tulng = ddout->s99tulng; - memcpy(dd->s99tupar, ddout->s99tupar, dd->s99tulng); - - s99_free(parms); - return DIOERR_NOERROR; + return -1; // Default to disable trimming for unknown/multi-byte encodings } -enum DIOERR ddfree(struct DFILE* dfile, struct s99_common_text_unit* dd) +void dbgmsg(struct DFILE* dfile, const char* format, ...) { - struct s99rb* __ptr32 parms; - enum s99_verb verb = S99VRBUN; - struct s99_flag1 s99flag1 = {0}; - struct s99_flag2 s99flag2 = {0}; - size_t num_text_units = 1; - int rc; - struct s99_rbx s99rbx = s99rbxtemplate; - - parms = s99_init(verb, s99flag1, s99flag2, &s99rbx, num_text_units, dd ); - if (!parms) { - errmsg(dfile, "Unable to initialize SVC99 (DYNFREE) control blocks."); - return DIOERR_SVC99INIT_FREE_FAILURE; - } - rc = S99(parms); - if (rc) { -#ifdef DEBUG - s99_fmt_dmp(dfile->logstream, parms); -#endif - s99_prt_msg(dfile, dfile->logstream, parms, rc); - return DIOERR_SVC99_ALLOC_FAILURE; + if (!dfile->debug) { + return; } - s99_free(parms); - return DIOERR_NOERROR; -} + va_list args; + va_start(args, format); -enum DIOERR init_dsnam_text_unit(struct DFILE* dfile, const char* dsname, struct s99_common_text_unit* dsn) -{ - size_t dsname_len = (dsname == NULL) ? 0 : strlen(dsname); - if (dsname == NULL || dsname_len == 0 || dsname_len > DS_MAX) { - errmsg(dfile, "Dataset Name <%.*s> is invalid.", dsname_len, dsname); - return DIOERR_INVALID_DATASET_NAME; - } + fprintf(stderr, "[DEBUG] "); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); - dsn->s99tulng = dsname_len; - memcpy(dsn->s99tupar, dsname, dsname_len); - return DIOERR_NOERROR; + va_end(args); } + void strupper(char* str) { for (int i=0; i' or // */ if ((dataset_name_len > DS_MAX+MEM_MAX+2+2+2) || (dataset_name_len < 2+2)) { - errmsg(dfile, "Dataset name %s is not a valid dataset name of format: // or //''.", dataset_name); + errmsg(dfile->opts, "Dataset name %s is not a valid dataset name of format: // or //''.", dataset_name); return DIOERR_LE_DATASET_NAME_TOO_LONG_OR_TOO_SHORT; } if (memcmp(dataset_name, "//", 2)) { - errmsg(dfile, "Dataset name %s does not start with // and therefore is not a valid dataset name.", dataset_name); + errmsg(dfile->opts, "Dataset name %s does not start with // and therefore is not a valid dataset name.", dataset_name); return DIOERR_INVALID_LE_DATASET_NAME; } if (!memcmp(dataset_name, "//'", 3)) { if (dataset_name[dataset_name_len-1] != '\'') { - errmsg(dfile, "Dataset name %s does not have balanced single quotes.", dataset_name); + errmsg(dfile->opts, "Dataset name %s does not have balanced single quotes.", dataset_name); return DIOERR_LE_DATASET_NAME_QUOTE_MISMATCH; } dsi->is_relative = 0; @@ -197,7 +146,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, if (dsi->open_paren && dsi->close_paren) { size_t memlen = dsi->close_paren - dsi->open_paren - 1; if (memlen > MEM_MAX) { - errmsg(dfile, "Member name of %s is more than %d characters.", dataset_name, MEM_MAX); + errmsg(dfile->opts, "Member name of %s is more than %d characters.", dataset_name, MEM_MAX); return DIOERR_MEMBER_NAME_TOO_LONG; } /* dataset member - valid */ @@ -209,7 +158,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, dsi->ds_end = dsi->name_end; } else { /* mis-matched parens - invalid */ - errmsg(dfile, "Dataset %s is not a valid dataset name or dataset member name.", dataset_name); + errmsg(dfile->opts, "Dataset %s is not a valid dataset name or dataset member name.", dataset_name); return DIOERR_LE_DATASET_NAME_PAREN_MISMATCH; } @@ -227,7 +176,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, if (dsi->first_dot && dsi->last_dot) { /* Note first_dot and last_dot can be the same: consider SYS1.MACLIB */ } else { - errmsg(dfile, "Dataset %s should have at least 1 qualifiers.", dataset_name); + errmsg(dfile->opts, "Dataset %s should have at least 1 qualifiers.", dataset_name); return DIOERR_NOT_ENOUGH_QUALIFIERS; } @@ -235,7 +184,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, dsi->hlq = dsi->ds_start; size_t hlq_len = dsi->first_dot - dsi->hlq - 1; if (hlq_len > HLQ_MAX) { - errmsg(dfile, "Dataset %s high level qualifier is too long.", dataset_name); + errmsg(dfile->opts, "Dataset %s high level qualifier is too long.", dataset_name); return DIOERR_HLQ_TOO_LONG; } if (dsi->first_dot == dsi->last_dot) { @@ -255,7 +204,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, if (dsi->mlqs) { size_t mlqslen = dsi->last_dot - dsi->mlqs - 1; if (mlqslen > MLQS_MAX) { - errmsg(dfile, "Dataset %s mid level qualifiers are too long.", dataset_name); + errmsg(dfile->opts, "Dataset %s mid level qualifiers are too long.", dataset_name); return DIOERR_MLQS_TOO_LONG; } } @@ -263,7 +212,7 @@ static enum DIOERR check_dataset(struct DFILE* dfile, const char* dataset_name, dsi->llq = dsi->last_dot + 1; size_t llqlen = dsi->ds_end - dsi->llq - 1; if (llqlen > LLQ_MAX) { - errmsg(dfile, "Dataset %s low level qualifier is too long.", dataset_name); + errmsg(dfile->opts, "Dataset %s low level qualifier is too long.", dataset_name); return DIOERR_LLQ_TOO_LONG; } @@ -442,11 +391,23 @@ static FILE* opendd(struct DFILE* dfile, struct DIFILE* difile, const char* open } FILE* fp = fopen(copendd, openfmt); if (fp == NULL) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); } return fp; } +void init_opts(DBG_Opts* opts, struct DFILE* dfile) +{ + opts->debug = dfile->debug; + opts->error_buffer = (DBG_MsgBuffer*)malloc(sizeof(DBG_MsgBuffer)); + opts->error_buffer->buffer = dfile->msgbuff; // ✅ + opts->error_buffer->size = dfile->msgbufflen; + opts->info_buffer = 0; + opts->verbose = 0; +} + + + struct DFILE* open_dataset(const char* dataset_name, FILE* logstream) { enum DIOERR rc; @@ -471,6 +432,7 @@ struct DFILE* open_dataset(const char* dataset_name, FILE* logstream) } dfile->msgbufflen = DIO_MSG_BUFF_LEN; dfile->logstream = logstream; + dfile->opts = calloc(1, sizeof(DBG_Opts)); struct DIFILE* difile = calloc(1, sizeof(struct DIFILE)); if (!difile) { @@ -478,6 +440,14 @@ struct DFILE* open_dataset(const char* dataset_name, FILE* logstream) return dfile; } + // Check if LIBDIO_DEBUG environment variable is set + if (!dfile->debug) { + const char* debug_env = getenv("LIBDIO_DEBUG"); + if (debug_env && strcmp(debug_env, "1") == 0) { + dfile->debug = 1; + } + } + dfile->internal = difile; char* dataset_name_copy = strdup(dataset_name); @@ -493,14 +463,16 @@ struct DFILE* open_dataset(const char* dataset_name, FILE* logstream) struct s99_common_text_unit dsn = { DALDSNAM, 1, 0, 0 }; struct s99_common_text_unit dd = { DALRTDDN, 1, sizeof(DD_SYSTEM)-1, DD_SYSTEM }; - struct s99_common_text_unit stats = { DALSTATS, 1, 1, {0x8} }; + struct s99_common_text_unit stats = { DALSTATS, 1, 1, { DALSTATS_SHR } }; - rc = init_dsnam_text_unit(dfile, difile->dataset_name, &dsn); + init_opts(dfile->opts, dfile); + rc = init_dsnam_text_unit(difile->dataset_name, &dsn, dfile->opts); if (rc) { dfile->err = rc; + return dfile; } - rc = dsdd_alloc(dfile, &dsn, &dd, &stats); + rc = dsdd_alloc(&dsn, &dd, &stats, dfile->opts); if (rc) { dfile->err = rc; return dfile; @@ -512,99 +484,152 @@ struct DFILE* open_dataset(const char* dataset_name, FILE* logstream) difile->dstate = D_CLOSED; #ifdef DEBUG + printf("datasetname:%s\n", difile->dataset_name); printf("allocated ddname:%s\n", difile->ddname); #endif + + int use_bpam_services = 0; + if (has_member(dfile)) { + use_bpam_services = 1; + } - /* - * Note - there is a timing window here and it is not efficient to - * open the dataset twice (once to get the dataset characteristics and once to read or write) - * but this is 'good enough' for now since the C I/O services don't let us do better - */ - - difile->fp = opendd(dfile, difile, "rb+,type=record"); - if (difile->fp) { - difile->dstate = D_READWRITE_BINARY; - } else { - if ((errno == ERRNO_NONEXISTANT_FILE) && has_member(dfile)) { - /* - * This is a PDS or PDSE member, and the member does not exist yet. - * We need to open the member in write to get the attributes of the actual - * PDS(E) member, otherwise if we only specify the PDS(E), we will get - * the attributes for working with the PDS(E) directly, which is wrong (unformatted) - * This is 'ok' because if we don't have write access to the PDS(E) to create a - * member, we should know this now now rather than later. - */ - - difile->fp = opendd(dfile, difile, "wb,type=record"); - if (!difile->fp) { - return dfile; + if (use_bpam_services) { + //bh->ddname = difile->ddname; TODO: do we close it? + FM_BPAMHandle* bh = open_pds_for_read(difile->dataset_name, dfile->opts); + if (rc) { + if (rc == 1) { // soft error, likely not a pdse + if (!record_format(bh, dfile->opts)) { + use_bpam_services = 0; + close_pds(bh, dfile->opts); + } } - difile->dstate = D_WRITE_BINARY; - } else { - /* - * Try to open 'rb' (perhaps file is write protected) - */ - difile->fp = opendd(dfile, difile, "rb,type=record"); - if (difile->fp) { - dfile->readonly = 1; - difile->dstate = D_READ_BINARY; - } else { - errmsg(dfile, "Unable to obtain dataset %s for READ.", dataset_name_copy); - dfile->err = DIOERR_FOPEN_FOR_READ_FAILED; + else { // critical error, exit + dfile->err = rc; return dfile; } } - } +/* + struct mstat read_mstat; + if (readmemdir_entry(bh, difile->member_name, &read_mstat, dfile->opts)) { + use_bpam_services = 0; + close_pds(bh, dfile->opts); + } +*/ + + if (use_bpam_services) { + record_format_t rf = record_format(bh, dfile->opts); + switch (rf) { + case RECORD_FORMAT_F: + case RECORD_FORMAT_FB: + dfile->recfm = D_F; + break; + case RECORD_FORMAT_V: + case RECORD_FORMAT_VB: + dfile->recfm = D_V; + break; + case RECORD_FORMAT_U: + dfile->recfm = D_U; + break; + default: + errmsg(dfile->opts, + "Dataset %s is not F, V, or U format. open_dataset not supported at this time.", + dataset_name_copy); + dfile->err = DIOERR_UNSUPPORTED_RECFM; + return dfile; + } + dfile->reclen = record_length(bh, dfile->opts); + difile->bpamhandle = bh; - fldata_t info; - rc = __fldata(difile->fp, NULL, &info); - if (rc) { - errmsg(dfile, "Unable to obtain file information for %s.", dataset_name_copy); - close_dataset(dfile); - dfile->err = DIOERR_FLDATA_FAILED; - return dfile; + } } - if (info.__recfmF) { - if (info.__recfmASA) { - dfile->recfm = D_FA; + if (!use_bpam_services) { + /* + * Note - there is a timing window here and it is not efficient to + * open the dataset twice (once to get the dataset characteristics and once to read or write) + * but this is 'good enough' for now since the C I/O services don't let us do better + */ + difile->fp = opendd(dfile, difile, "rb+,type=record"); + if (difile->fp) { + difile->dstate = D_READWRITE_BINARY; } else { - dfile->recfm = D_F; + if ((errno == ERRNO_NONEXISTANT_FILE) && has_member(dfile)) { + /* + * This is a PDS or PDSE member, and the member does not exist yet. + * We need to open the member in write to get the attributes of the actual + * PDS(E) member, otherwise if we only specify the PDS(E), we will get + * the attributes for working with the PDS(E) directly, which is wrong (unformatted) + * This is 'ok' because if we don't have write access to the PDS(E) to create a + * member, we should know this now now rather than later. + */ + + difile->fp = opendd(dfile, difile, "wb,type=record"); + if (!difile->fp) { + return dfile; + } + difile->dstate = D_WRITE_BINARY; + } else { + /* + * Try to open 'rb' (perhaps file is write protected) + */ + difile->fp = opendd(dfile, difile, "rb,type=record"); + if (difile->fp) { + dfile->readonly = 1; + difile->dstate = D_READ_BINARY; + } else { + errmsg(dfile->opts, "Unable to obtain dataset %s for READ.", dataset_name_copy); + dfile->err = DIOERR_FOPEN_FOR_READ_FAILED; + return dfile; + } + } + } + + fldata_t info; + rc = __fldata(difile->fp, NULL, &info); + if (rc) { + errmsg(dfile->opts, "Unable to obtain file information for %s.", dataset_name_copy); + close_dataset(dfile); + dfile->err = DIOERR_FLDATA_FAILED; + return dfile; } - } else if (info.__recfmV) { - if (info.__recfmASA) { - dfile->recfm = D_VA; + + if (info.__recfmF) { + if (info.__recfmASA) { + dfile->recfm = D_FA; + } else { + dfile->recfm = D_F; + } + } else if (info.__recfmV) { + if (info.__recfmASA) { + dfile->recfm = D_VA; + } else { + dfile->recfm = D_V; + } + } else if (info.__recfmU) { + dfile->recfm = D_U; } else { - dfile->recfm = D_V; + errmsg(dfile->opts, "Dataset %s is not F, V, or U format. open_dataset not supported at this time.", dataset_name_copy); + dfile->err = DIOERR_UNSUPPORTED_RECFM; + return dfile; } - } else if (info.__recfmU) { - dfile->recfm = D_U; - } else { - errmsg(dfile, "Dataset %s is not F, V, or U format. open_dataset not supported at this time.", dataset_name_copy); - dfile->err = DIOERR_UNSUPPORTED_RECFM; - return dfile; - } - if (info.__dsorgPDSE) { - dfile->dsorg = D_PDSE; - } else if (info.__dsorgPO) { - dfile->dsorg = D_PDS; - } else if (info.__dsorgPS) { - dfile->dsorg = D_SEQ; - } else { - errmsg(dfile, "Dataset %s is not PDS, PDSE, or SEQ organization. open_dataset not supported at this time.", dataset_name_copy); - dfile->err = DIOERR_UNSUPPORTED_RECFM; - return dfile; + if (info.__dsorgPS) { + dfile->dsorg = D_SEQ; + } else { + errmsg(dfile->opts, "Dataset %s is not PDS, PDSE, or SEQ organization. open_dataset not supported at this time.", dataset_name_copy); + dfile->err = DIOERR_UNSUPPORTED_RECFM; + return dfile; + } + dfile->reclen = info.__maxreclen; } - dfile->reclen = info.__maxreclen; dfile->dccsid = DCCSID_NOTSET; #ifdef DEBUG char ccsidstr[DCCSID_MAX]; printf("Dataset attributes: dsorg:%s recfm:%s lrecl:%d dstate:%s ccsid:%s\n", dsorgs_internal(dfile->dsorg), recfms_internal(dfile->recfm), dfile->reclen, dstates(difile->dstate), dccsids(dfile->dccsid, ccsidstr)); -#endif +#endif // 0 return dfile; } @@ -637,7 +662,7 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) if (difile->dstate == D_WRITE_BINARY) { rc=fclose(difile->fp); if (rc) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FCLOSE_FAILED_ON_READ; } difile->dstate = D_CLOSED; @@ -659,7 +684,7 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) difile->read_buffer_size = INIT_READ_BUFFER_SIZE; dfile->buffer = malloc(difile->read_buffer_size); if (!dfile->buffer) { - errmsg(dfile, "Unable to acquire storage to read dataset %s.", difile->dataset_name); + errmsg(dfile->opts, "Unable to acquire storage to read dataset %s.", difile->dataset_name); return DIOERR_READ_BUFFER_ALLOC_FAILED; } } @@ -676,7 +701,7 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) while (1) { rc = fread(record, size, count, difile->fp); if (errno) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FREAD_FAILED; } if (feof(difile->fp)) { @@ -687,7 +712,7 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) bytes_to_copy += sizeof(uint16_t); } if (difile->cur_read_offset + bytes_to_copy > difile->read_buffer_size) { - errmsg(dfile, "To be implemented - need to write code to grow buffer for reading in file."); + errmsg(dfile->opts, "To be implemented - need to write code to grow buffer for reading in file."); return DIOERR_LARGE_READ_BUFFER_NOT_IMPLEMENTED_YET; } reclen = rc; @@ -695,9 +720,9 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) memcpy(&dfile->buffer[difile->cur_read_offset], &reclen, sizeof(reclen)); difile->cur_read_offset += sizeof(reclen); } - memcpy(&dfile->buffer[difile->cur_read_offset], record, bytes_to_copy); - if (!is_binary) - isbinary = is_binary(&dfile->buffer[difile->cur_read_offset], bytes_to_copy); + memcpy(&dfile->buffer[difile->cur_read_offset], record, rc); + if (!isbinary) + isbinary = is_binary(&dfile->buffer[difile->cur_read_offset], rc); #ifdef DEBUG printf("%5.5u <%*.*s>\n", reclen, reclen, reclen, record); #endif @@ -708,9 +733,181 @@ static enum DIOERR read_dataset_internal(struct DFILE* dfile) return DIOERR_NOERROR; } +static ssize_t read_member(FM_BPAMHandle* bh, const char* ds, const char* mem_name, char* buffer, size_t buffer_len, DBG_Opts* opts, struct DFILE* dfile) +{ + int rc = find_member(bh, mem_name, opts); + if (rc) { + info(opts, "Unable to find %s(%s) for read. rc:%d\n", ds, mem_name, rc); + return 0; + } + + int length_prefix = has_length_prefix(dfile->recfm); + + size_t remaining_buffer_len = buffer_len; + char* cur = buffer; + ssize_t bytes_read; + ssize_t tot_bytes_written_to_buffer = 0; + int num_lines = 0; + + while (1) { + char* read_target; + size_t max_bytes_to_read_this_iteration; + + if (length_prefix) { + if (remaining_buffer_len < sizeof(uint16_t)) { + break; + } + read_target = cur + sizeof(uint16_t); + max_bytes_to_read_this_iteration = remaining_buffer_len - sizeof(uint16_t); + } else { + read_target = cur; + max_bytes_to_read_this_iteration = remaining_buffer_len; + } + + if (max_bytes_to_read_this_iteration == 0) { + break; + } + + bytes_read = read_record(bh, max_bytes_to_read_this_iteration, read_target, opts); + + if (bytes_read < 0) { + break; + } + + size_t bytes_to_add_to_buffer; + if (length_prefix) { + uint16_t reclen = (uint16_t)bytes_read; + memcpy(cur, &reclen, sizeof(uint16_t)); + bytes_to_add_to_buffer = sizeof(uint16_t) + bytes_read; + } else { + bytes_to_add_to_buffer = bytes_read; + } + + cur += bytes_to_add_to_buffer; + tot_bytes_written_to_buffer += bytes_to_add_to_buffer; + remaining_buffer_len -= bytes_to_add_to_buffer; + ++num_lines; + } + + dbgmsg(dfile, "Read %d lines (%d bytes) for member %s(%s)\n", num_lines, tot_bytes_written_to_buffer, ds, mem_name); + + return tot_bytes_written_to_buffer; +} + +static int write_member(FM_BPAMHandle* bh, const char* ds, const char* mem_name, const char* buffer, DBG_Opts* opts, struct DFILE* dfile) +{ + const char* cur = buffer; + const char* next; + int num_lines = 0; + + int length_prefix = has_length_prefix(dfile->recfm); + + size_t size = 1; + size_t buffer_offset = 0; + + if (length_prefix) { + uint16_t reclen; + while (buffer_offset < dfile->bufflen) { + reclen = *((uint16_t*)(&dfile->buffer[buffer_offset])); + buffer_offset += sizeof(uint16_t); + ssize_t rc = write_record(bh, reclen, &dfile->buffer[buffer_offset], opts); + if (rc < 0) { + errmsg(opts, "Unable to write record for member %s(%s)\n", ds, mem_name); + return -1; + } + buffer_offset += reclen; + ++num_lines; + } + } else { + while (buffer_offset < dfile->bufflen) { + ssize_t rc = write_record(bh, dfile->reclen, &dfile->buffer[buffer_offset], opts); + if (rc < 0) { + errmsg(opts, "Unable to write record for member %s(%s)\n", ds, mem_name); + return -1; + } + ++num_lines; + buffer_offset += dfile->reclen; + } + } + + int rc = flush(bh, opts); /* flush any remaining records */ + if (rc < 0) { + errmsg(opts, "Unable to write final block for member %s(%s)\n", ds, mem_name); + return -1; + } + + struct mstat mstat; + char userid[USERID_LEN+1]; + char* alias_name = NULL; + void* ttr = NULL; /* msf - perhaps the TTR should not be part of the mstat? */ + + int ccsid = 1047; + if (!create_mstat(&mstat, userid, alias_name, mem_name, ttr, num_lines, ccsid, opts)) { + errmsg(opts, "Unable to create member statistics for PDS member %s(%s). Member not written\n", ds, mem_name); + return 8; + } + + if (enq_dataset_member(ds, mem_name, opts)) { + errmsg(opts,"Unable to obtain ENQ for PDS member %s(%s). Member not written\n", ds, mem_name); + return 8; + } + if (dfile->debug) { + fprintf(stdout, "MSTAT information for %s(%s) at time of creation.\n"); + print_member(&mstat, 1); + } + if (writememdir_entry(bh, &mstat, opts)) { + errmsg(opts, "Unable to write directory entry for member %s(%s)\n", ds, mem_name); + return 8; + } + if (deq_dataset_member(ds, mem_name, opts)) { + errmsg(opts, "Unable to obtain ENQ for PDS member %s(%s). Member not written\n", ds, mem_name); + return 8; + } + return 0; +} + +static enum DIOERR read_dataset_internal_bpam(struct DFILE* dfile) +{ + struct DIFILE* difile = (struct DIFILE*) (dfile->internal); + int rc; + errno = 0; + + if ((difile->read_buffer_size == 0) || (dfile->buffer == NULL)) { + difile->read_buffer_size = INIT_READ_BUFFER_SIZE; + dfile->buffer = malloc(difile->read_buffer_size); + if (!dfile->buffer) { + errmsg(dfile->opts, "Unable to acquire storage to read dataset %s.", difile->dataset_name); + return DIOERR_READ_BUFFER_ALLOC_FAILED; + } + } + + ssize_t bytes_read; + if ((bytes_read = read_member(difile->bpamhandle, difile->dataset_name, difile->member_name, dfile->buffer, INIT_READ_BUFFER_SIZE, dfile->opts, dfile)) < 0 ) { + info(dfile->opts, "Unable to read back dataset %s. rc:%d", difile->dataset_full_name, rc); + } +#if 0 + if (bytes_read != first_file_len || !memcmp(buffer, ascii_data, first_file_len)) { + fprintf(stderr, "Expected to read %d bytes with value:\n%s but got %d bytes of value:\n%s", + first_file_len, ascii_data, bytes_read, buffer); + } +#endif + + + dfile->bufflen = bytes_read; + dfile->is_binary = 0; + return DIOERR_NOERROR; +} + enum DIOERR read_dataset(struct DFILE* dfile) { - enum DIOERR rc = read_dataset_internal(dfile); + struct DIFILE* difile = (struct DIFILE*) dfile->internal; + enum DIOERR rc; + if (difile->bpamhandle) { + rc = read_dataset_internal_bpam(dfile); + } + else { + rc = read_dataset_internal(dfile); + } dfile->err = rc; return rc; } @@ -724,14 +921,14 @@ static enum DIOERR write_dataset_internal(struct DFILE* dfile) errno = 0; if ((dfile->bufflen < 0) || (dfile->buffer == NULL)) { - errmsg(dfile, "No buffer and/or buffer length not positive - no action performed."); + errmsg(dfile->opts, "No buffer and/or buffer length not positive - no action performed."); return DIOERR_INVALID_BUFFER_PASSED_TO_WRITE; } if (difile->dstate == D_READ_BINARY) { rc=fclose(difile->fp); if (rc) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FCLOSE_FAILED_ON_WRITE; } difile->dstate = D_CLOSED; @@ -740,7 +937,7 @@ static enum DIOERR write_dataset_internal(struct DFILE* dfile) if (difile->dstate == D_READWRITE_BINARY) { rc=fclose(difile->fp); if (rc) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FCLOSE_FAILED_ON_WRITE; } difile->dstate = D_CLOSED; @@ -790,16 +987,47 @@ static enum DIOERR write_dataset_internal(struct DFILE* dfile) } if (err) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FWRITE_FAILED; } else { return DIOERR_NOERROR; } } +/** + * @brief Writes data from dfile->buffer to a PDS/E member using block-oriented BPAM I/O. + * Uses adapted helper functions for block/record creation. + */ +static enum DIOERR write_dataset_internal_bpam(struct DFILE* dfile) +{ + struct DIFILE* difile = (struct DIFILE*)dfile->internal; + int rc_bpam_io; // Return code from BPAM I/O operations like write_block + enum DIOERR overall_rc = DIOERR_NOERROR; + if ((dfile->bufflen < 0) || (dfile->buffer == NULL)) { + errmsg(dfile->opts, "No buffer and/or buffer length not positive - no action performed."); + return DIOERR_INVALID_BUFFER_PASSED_TO_WRITE; + } + close_pds(difile->bpamhandle, dfile->opts); + difile->bpamhandle = open_pds_for_write(difile->dataset_name, dfile->opts); + if (write_member(difile->bpamhandle, difile->dataset_name, difile->member_name, dfile->buffer, dfile->opts, dfile)) { + return 8; + } + + return overall_rc; +} + + + enum DIOERR write_dataset(struct DFILE* dfile) { - enum DIOERR rc = write_dataset_internal(dfile); + struct DIFILE* difile = (struct DIFILE*) dfile->internal; + enum DIOERR rc; + if (difile->bpamhandle) { + rc = write_dataset_internal_bpam(dfile); + } + else { + rc = write_dataset_internal(dfile); + } dfile->err = rc; return rc; } @@ -809,9 +1037,14 @@ static enum DIOERR close_dataset_internal(struct DFILE* dfile) int rc = 0; struct DIFILE* difile = (struct DIFILE*) dfile->internal; - rc = fclose(difile->fp); + if (difile->bpamhandle) { + rc = close_pds(difile->bpamhandle, dfile->opts); + } else { + rc = fclose(difile->fp); + } + if (rc) { - errmsg(dfile, strerror(errno)); + errmsg(dfile->opts, strerror(errno)); return DIOERR_FCLOSE_FAILED_ON_CLOSE; } @@ -928,15 +1161,32 @@ int write_dataset_to_temp_file(struct DFILE *dfile, char *tempname, struct f_cnvrt req = {SETCVTOFF, 0, 0}; fcntl(temp_fd, F_CONTROL_CVT, &req); + int space_char = get_space_char(dfile->ccsid); int length_prefix = has_length_prefix(dfile->recfm); int i = 0; char *data = dfile->buffer; if (length_prefix) { uint16_t reclen; while (i < dfile->bufflen) { + if (i + sizeof(reclen) > dfile->bufflen) { + close_dataset(dfile); + close(temp_fd); + return 1; // Corrupt buffer: header truncated + } memcpy(&reclen, &data[i], sizeof(reclen)); i += sizeof(reclen); - if (write(temp_fd, &data[i], reclen) != reclen) { + int actual_len = reclen; + if (i + actual_len > dfile->bufflen) { + close_dataset(dfile); + close(temp_fd); + return 1; // Corrupt buffer: record truncated + } + if (!force_binary && space_char != -1) { + while (actual_len > 0 && data[i + actual_len - 1] == space_char) { + actual_len--; + } + } + if (write(temp_fd, &data[i], actual_len) != actual_len) { close_dataset(dfile); close(temp_fd); return 1; @@ -951,7 +1201,16 @@ int write_dataset_to_temp_file(struct DFILE *dfile, char *tempname, } } else { while (i < dfile->bufflen) { - if (write(temp_fd, &data[i], dfile->reclen) != dfile->reclen) { + int actual_len = dfile->reclen; + if (i + actual_len > dfile->bufflen) { + actual_len = dfile->bufflen - i; // Clamp to remaining buffer + } + if (!force_binary && space_char != -1) { + while (actual_len > 0 && data[i + actual_len - 1] == space_char) { + actual_len--; + } + } + if (write(temp_fd, &data[i], actual_len) != actual_len) { close_dataset(dfile); close(temp_fd); return 1; @@ -986,12 +1245,12 @@ char *read_temp_file_to_buffer(char *tempname, struct DFILE *dfile) { } FILE *fp; if ((fp = fopen(tempname, "r")) == NULL) { - errmsg(dfile, "Cannot open temporary file: %s", tempname); + errmsg(dfile->opts, "Cannot open temporary file: %s", tempname); return NULL; } if (!fp) { - errmsg(dfile, "Error: Invalid file pointer"); + errmsg(dfile->opts, "Error: Invalid file pointer"); return NULL; } @@ -1010,13 +1269,13 @@ char *read_temp_file_to_buffer(char *tempname, struct DFILE *dfile) { char *buffer = malloc(buffer_size); if (!buffer) { - errmsg(dfile, "Error: Failed to allocate memory for buffer"); + errmsg(dfile->opts, "Error: Failed to allocate memory for buffer"); fclose(fp); return NULL; } if (!line) { - errmsg(dfile, "Error: Failed to allocate memory for line buffer"); + errmsg(dfile->opts, "Error: Failed to allocate memory for line buffer"); free(buffer); fclose(fp); return NULL; @@ -1036,7 +1295,7 @@ char *read_temp_file_to_buffer(char *tempname, struct DFILE *dfile) { record_length = strlen(line) - 1; // Ignore newline character if (record_length > dfile->reclen) { - errmsg(dfile, "Error: Line %d exceeds record length of %d", line_num, + errmsg(dfile->opts, "Error: Line %d exceeds record length of %d", line_num, dfile->reclen); free(line); free(buffer); @@ -1047,7 +1306,7 @@ char *read_temp_file_to_buffer(char *tempname, struct DFILE *dfile) { // Add the length prefix if needed if (length_prefix) { if ((tot_size + sizeof(uint16_t) + record_length) > buffer_size) { - errmsg(dfile, "Error: Exceeded buffer size at line %d", line_num); + errmsg(dfile->opts, "Error: Exceeded buffer size at line %d", line_num); free(line); free(buffer); fclose(fp); @@ -1059,7 +1318,7 @@ char *read_temp_file_to_buffer(char *tempname, struct DFILE *dfile) { tot_size += record_length; } else { if ((tot_size + dfile->reclen) > buffer_size) { - errmsg(dfile, "Error: Exceeded buffer size at line %d", line_num); + errmsg(dfile->opts, "Error: Exceeded buffer size at line %d", line_num); free(line); free(buffer); fclose(fp); diff --git a/src/mem.c b/src/mem.c new file mode 100644 index 0000000..aa9703e --- /dev/null +++ b/src/mem.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include "mem.h" +#include "wrappers.h" + +//#define DEBUG 1 + +void* PTR32 MALLOC24(unsigned int bytes) +{ + int ptr24; + ptr24 = MALOC24A(bytes); + void* PTR32 ptr = (void* PTR32) ptr24; + if (ptr24 == 0) { + fprintf(stderr, "Internal Error: Unable to allocate %d bytes below the bar\n", bytes); + } else { +#ifdef DEBUG + memset(ptr, 0xFE, bytes); +#else + memset(ptr, 0x00, bytes); +#endif + } + return ptr; +} + +int FREE24(void* PTR32 addr, unsigned int len) +{ + return FREE24A(addr, len); +} + +void* PTR32 MALLOC31(unsigned int bytes) +{ + void* PTR32 p = __malloc31(bytes); + if (p == 0) { + fprintf(stderr, "Internal Error: Unable to allocate %d bytes below the line\n", bytes); + } else { +#ifdef DEBUG + memset(p, 0xFE, bytes); +#else + memset(p, 0x00, bytes); +#endif + } + return p; +} +void FREE31(void* PTR32 addr) +{ + return free(addr); +} + +void dumpstg(FILE* stream, void* p, size_t len) +{ + char* buff = p; + size_t i; + for (i=0; i Pointer to fullword allocation length +**| R15 -> Pointer to allocated storage or 0 if failure + +MEMA CSECT + ENTRY MALOC24A +MALOC24A ASDPRO BASE_REG=3,USR_DSAL=MALOC24A_DSAL + LR R7,R1 + USING MALOC24A_PARMS,R7 + L R8,MALOC24A_LEN +* Get 24-bit storage + + STORAGE OBTAIN,LENGTH=(8),LOC=24,COND=YES + CHI R15,0 + BZ MALOC24A_SUCCESS +MALOC24A_FAILURE DS 0H + LA R15,0 + B MALOC24A_EXIT +MALOC24A_SUCCESS DS 0H + LR R15,R1 +MALOC24A_EXIT DS 0H + ASDEPI + + DROP + LTORG + +MALOC24A_PARMS DSECT +MALOC24A_LEN DS F +MALOC24A_DSAL EQU 0 + +**| FREE24A.... free storage below the line +**| https://tech.mikefulton.ca/STORAGE-RELEASEMacro +**| R1 -> Fullword pointer and Fullword allocation length +**| R15 -> 0 if successful, non-zero otherwise + +MEMA CSECT + ENTRY FREE24A +FREE24A ASDPRO BASE_REG=3,USR_DSAL=FREE24A_DSAL + LR R7,R1 + USING FREE24A_PARMS,R7 + L R8,FREE24A_PTR + L R9,FREE24A_LEN + +* Get 24-bit storage + + STORAGE RELEASE,ADDR=(8),LENGTH=(9) +FREE24A_EXIT DS 0H + ASDEPI + + DROP + LTORG + +FREE24A_PARMS DSECT +FREE24A_PTR DS AL4 +FREE24A_LEN DS F +FREE24A_DSAL EQU 0 + +**| Finish off the CSECT + +MEMA CSECT + DC C'Open Source' + END diff --git a/src/ztime.c b/src/ztime.c new file mode 100644 index 0000000..1734756 --- /dev/null +++ b/src/ztime.c @@ -0,0 +1,193 @@ +#include +#include "ztime.h" + +/* + * ztime: functions for converting to/from various types of Z ISA and z/OS time + * formats + * + * Reference: + * Packed Decimal Format: https://tech.mikefulton.ca/PackedDecimalFormat + * ISPF Stats Layout on disk: https://tech.mikefulton.ca/ISPFStatsLayout + */ + +static const int days[] = { + /* Jan */ 31, + /* Feb */ 28, + /* Mar */ 31, + /* Apr */ 30, + /* May */ 31, + /* Jun */ 30, + /* Jul */ 31, + /* Aug */ 31, + /* Sep */ 30, + /* Oct */ 31, + /* Nov */ 30, + /* Dec */ 31 +}; + +/* + * convert julian (ordinal) day to month/day, where month starts from 0 + */ +static void j_to_mmdd(int year, int ordinal, int* month, int* day) +{ + *month = 0; + *day = 0; + int i; + int leap; + + int remainder = ordinal; + if ((year % 4 == 0)) { + if ((year % 100 != 0) || (year % 400 == 0)) { + leap = 1; + } else { + leap = 0; + } + } else { + leap = 0; + } + for (i = 0; i<12; ++i) { + int days_in_month = days[i]; + if (i == 1 && leap) { + days_in_month++; + } + if (remainder < days_in_month) { + *month = i; + *day = remainder; + break; + } + remainder -= days_in_month; + } + return; +} + +/* + * convert month/day to julian (ordinal), where month starts from 0 + */ + +static void mmdd_to_j(int year, int month, int day, int* ordinal) +{ + int i; + int leap; + + *ordinal = 0; + if ((year % 4 == 0)) { + if ((year % 100 != 0) || (year % 400 == 0)) { + leap = 1; + } else { + leap = 0; + } + } else { + leap = 0; + } + for (i = 0; i> 4U); + } else { + return (((pd & 0xF0U) >> 4U)*10U) + (pd & 0x0FU); + } +} + +/* + * convert a decimal value to packed decimal. + * If 'set_positive_sign' is specified, then the + * value is expected to only be from 0 to 9 and the low + * order nibble has the positive sign set. + */ +unsigned char d_to_pd(unsigned int val, int set_positive_sign) +{ + unsigned char pd; + if (set_positive_sign) { + pd = 0x0F; + pd |= (val << 4); + } else { + pd = (val % 10); + pd |= (val / 10) << 4; + } + return pd; +} + +/* + * convert a 3 byte Julian Date that is relative to a start century of + * 0 (20th century) or 1 (21st century), adjusted for subsequent + * use in a 'struct tm' format, where 0th month is January, 0th year is 1900, + * and 1st day is the 1st day of the month. + */ +int pdjd_to_tm(const char* pdjd, int start_century, struct tm* ltime) +{ + int year = pd_to_d(pdjd[0]); + int tens = pd_to_d(pdjd[1]); + int ones = pd_to_d(pdjd[2]); + int ordinal = tens*10 + ones; + + year += (1900 + (start_century*100)); + j_to_mmdd(year, ordinal, <ime->tm_mon, <ime->tm_mday); + + ltime->tm_year = (year - 1900); + + return 0; +} + +/* + * given a 'struct tm' structure containing the + * year, month, and day, set a 3 byte Julian date in packed + * decimal format, relative to the closest century. + * Valid century settings are 0 for the 20th century (1900->1999) and + * 1 for the 21st century (2000->2099). + */ +void tm_to_pdjd(unsigned char* century, char* pdjd, struct tm* ltime) +{ + int year,month,day; + int ordinal; + + *century = (ltime->tm_year / 100); + + year = ltime->tm_year + 1900; + month = ltime->tm_mon; + day = ltime->tm_mday; + + mmdd_to_j(year, month, day, &ordinal); + + int tens = ordinal / 10; + int ones = ordinal % 10; + + pdjd[0] = d_to_pd(year%100, 0); + pdjd[1] = d_to_pd(tens, 0); + pdjd[2] = d_to_pd(ones, 1); +} + +time_t tod_to_time(unsigned long long tod) +{ + /* + * Note that this conversion does not factor in leap seconds. + * This is 'on purpose' so that it is consistent with other time + * stamps such as the time of a zFS file, the time returned from time() + * and other places that a C user would get the time on z/OS. + * + * Having consistent relative time for zFS files and PDS members being + * reported seems more important than providing an 'accurate' time + * for a PDS member update which is inconsistent with a time a developer + * would get from a zFS file. + */ + unsigned long long rawtime = tod; + unsigned long long raw1970time = rawtime - 9048018124800000000ULL; + double doubletime = (raw1970time >> 32); + double doublesecs = doubletime * 1.048576; + unsigned long rawseconds = (unsigned long) doublesecs; + time_t ltime = (time_t) rawseconds; + + return ltime; +} diff --git a/src/ztime.h b/src/ztime.h new file mode 100644 index 0000000..cfb667b --- /dev/null +++ b/src/ztime.h @@ -0,0 +1,11 @@ +#ifndef __Z_TIME__ + #define __Z_TIME__ 1 + + #include + + int pdjd_to_tm(const char* pdjd, int start_century, struct tm* ltime); + void tm_to_pdjd(unsigned char* century, char* pdjd, struct tm* ltime); + time_t tod_to_time(unsigned long long tod); + unsigned int pd_to_d(unsigned char pd); + unsigned char d_to_pd(unsigned int val, int set_positive_sign); +#endif diff --git a/test/basicread.c b/test/basicread.c index 6b70c6c..f0c43b4 100644 --- a/test/basicread.c +++ b/test/basicread.c @@ -1,4 +1,5 @@ #include "dio.h" +#include "dio_utils.h" #include #include @@ -63,6 +64,8 @@ int main(int argc, char* argv[]) { printf("Read %d bytes from dataset %s\n", dfile->bufflen, relds); + printf("Buffer: %.*s", dfile->bufflen, dfile->buffer); + rc = close_dataset(dfile); if (rc) { fprintf(stderr, "%s\n", dfile->msgbuff); diff --git a/test/basicwrite.c b/test/basicwrite.c index 43f723b..50fbd51 100644 --- a/test/basicwrite.c +++ b/test/basicwrite.c @@ -1,4 +1,5 @@ #include "dio.h" +#include "dio_utils.h" #include #include @@ -81,7 +82,7 @@ int main(int argc, char* argv[]) { printf("Dataset attributes for dataset %s: dsorg:%s recfm:%s lrecl:%d ccsid:%s\n", relds, dsorgs(dfile->dsorg, dsorgbuff), recfms(dfile->recfm, recfmbuff), dfile->reclen, dccsids(dfile->dccsid, ccsidbuff)); - int length_prefix = has_length_prefix(dfile->recfm); + int length_prefix = 0; has_length_prefix(dfile->recfm); dfile->bufflen = calc_size(data, length_prefix, dfile->reclen); dfile->buffer = malloc(dfile->bufflen); diff --git a/test/file.txt b/test/file.txt new file mode 100644 index 0000000..20d1aa1 --- /dev/null +++ b/test/file.txt @@ -0,0 +1,3 @@ +ds://'ITODORO.SOURCE.COBOL(HELLO)' +֙@Laa}KKM]}n@@LKKM]n@@LKKn@@Ln@@Ln@@Ln@@Ln@@Ln@@Ln@@LnzKK@zDataset attributes for dataset SOURCE.COBOL(HELLO): mem:HELLO hlq:ITODORO mlqs:SOURCE llq:COBOL dsorg:PDSE recfm:F lrecl:80 ccsid:? +Unix file: ITODORO.SOURCE.HELLO.cbl diff --git a/test/less-497368162.json.gz b/test/less-497368162.json.gz new file mode 100644 index 0000000..c4995e0 Binary files /dev/null and b/test/less-497368162.json.gz differ diff --git a/test/run.sh b/test/run.sh new file mode 100755 index 0000000..cc9caa1 --- /dev/null +++ b/test/run.sh @@ -0,0 +1 @@ +xlc -Wc,lp64 -Wl,edit=no -L/home/itodoro/zopen/usr/local/zopen/cjson/cjson-heads.v1.7.18.20240826_024755.zos/lib -L/home/itodoro/zopen/usr/local/zopen/curl/curl-8.9.1.20240828_125453.zos/lib -L/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses-6.5.20240507_195319.zos/lib -o basicread basicread.o ../src/*.o -lcjson -lcurl -lncurses /home/itodoro/projects/libdioport/libdio/.zoslib_hooks/zoslib_env_hook.c.o /home/itodoro/zopen/usr/local/zopen/cjson/cjson-heads.v1.7.18.20240826_024755.zos/lib/libcjson.a