diff --git a/c/datasetjson.c b/c/datasetjson.c index b426bbb18..281840fbc 100644 --- a/c/datasetjson.c +++ b/c/datasetjson.c @@ -27,6 +27,7 @@ #include "bpxnet.h" #include "logging.h" #include "unixfile.h" +#include "errno.h" #ifdef __ZOWE_OS_ZOS #include "zos.h" #endif @@ -78,6 +79,14 @@ typedef struct Volser_tag { char value[6]; /* space-padded */ } Volser; +static char getRecordLengthType(char *dscb); +static int getMaxRecordLength(char *dscb); +static int getDSCB(DatasetName *dsName, char* dscb, int bufferSize); +static int updateInputParmsProperty(JsonObject *object, int *configsCount, DynallocNewTextUnit *textUnit); +static void setTextUnitString(int size, char* data, int *configsCount, int key, DynallocNewTextUnit *textUnit); +static void setTextUnitCharOrInt(int size, int data, int *configsCount, int key, DynallocNewTextUnit *textUnit); +static void setTextUnitBool(int *configsCount, int key, DynallocNewTextUnit *textUnit); + static int getVolserForDataset(const DatasetName *dataset, Volser *volser); static bool memberExists(char* dsName, DynallocMemberName daMemberName); @@ -2516,6 +2525,340 @@ void respondWithHLQNames(HttpResponse *response, MetadataQueryCache *metadataQue } +static int updateInputParmsProperty(JsonObject *object, int *configsCount, DynallocNewTextUnit *textUnit) { + JsonProperty *currentProp = jsonObjectGetFirstProperty(object); + //printf("Updating input parms"); + Json *value; + while(currentProp != NULL){ + value = jsonPropertyGetValue(currentProp); + char *valueString = jsonAsString(value); + + if(valueString != NULL){ + errno = 0; + int valueStrLen = strlen(valueString); + char *propString = jsonPropertyGetKey(currentProp); + + if (!strcmp(propString, "dsorg")) { + setTextUnitCharOrInt(sizeof(short), !strcmp(valueString, "PS") ? DALDSORG_PS : DALDSORG_PO, configsCount, DALDSORG, textUnit); + } else if(!strcmp(propString, "blksz")) { + long toi = strtol(valueString, NULL, 0); + if(errno != ERANGE){ + if (toi <= 0x7FF8 && toi >= 0) { //<-- If DASD, if tape, it can be 80000000 + setTextUnitCharOrInt(sizeof(short), toi, configsCount, DALBLKSZ, textUnit); + } else if (toi <= 0x80000000){ + setTextUnitCharOrInt(sizeof(long long), toi, configsCount, DALBLKSZ, textUnit); + } + } + } else if(!strcmp(propString, "lrecl")) { + long toi = strtol(valueString, NULL, 0); + if (errno != ERANGE){ + if (toi == 0x8000) { + setTextUnitCharOrInt(sizeof(short), toi, configsCount, DALLRECL, textUnit); + } + else if (toi <= 0x7FF8 && toi >= 0) { + setTextUnitCharOrInt(sizeof(short), toi, configsCount, DALLRECL, textUnit); + } + } + } else if(!strcmp(propString, "volser")) { + if (valueStrLen <= VOLSER_SIZE){ + setTextUnitString(VOLSER_SIZE, &(valueString)[0], configsCount, DALVLSER, textUnit); + } + } else if(!strcmp(propString, "recfm")) { + int setRECFM = 0; + if (indexOf(valueString, valueStrLen, 'A', 0) != -1){ + setRECFM = setRECFM | DALRECFM_A; + } + if (indexOf(valueString, valueStrLen, 'B', 0) != -1){ + setRECFM = setRECFM | DALRECFM_B; + } + if (indexOf(valueString, valueStrLen, 'V', 0) != -1){ + setRECFM = setRECFM | DALRECFM_V; + } + if (indexOf(valueString, valueStrLen, 'F', 0) != -1){ + setRECFM = setRECFM | DALRECFM_F; + } + if (indexOf(valueString, valueStrLen, 'U', 0) != -1){ + setRECFM = setRECFM | DALRECFM_U; + } + setTextUnitCharOrInt(sizeof(char), setRECFM, configsCount, DALRECFM, textUnit); + } else if(!strcmp(propString, "space")) { + setTextUnitBool(configsCount, !strcmp(valueString, "cyl") ? DALCYL : DALTRK, textUnit); + } else if(!strcmp(propString, "blkln")) { + long toi = strtol(valueString, NULL, 0); + if (toi <= 0xFFFF || toi >= 0) { + if (errno != ERANGE){ + setTextUnitCharOrInt(INT24_SIZE, toi, configsCount, DALBLKLN, textUnit); + } + } + } else if(!strcmp(propString, "status")) { + if (!strcmp(valueString, "OLD")){ + setTextUnitCharOrInt(sizeof(char), DISP_OLD, configsCount, DALSTATS, textUnit); + } else if (!strcmp(valueString, "MOD")){ + setTextUnitCharOrInt(sizeof(char), DISP_MOD, configsCount, DALSTATS, textUnit); + } else if (!strcmp(valueString, "SHARE")){ + setTextUnitCharOrInt(sizeof(char), DISP_SHARE, configsCount, DALSTATS, textUnit); + } else { + setTextUnitCharOrInt(sizeof(char), DISP_NEW, configsCount, DALSTATS, textUnit); + } + } else if (!strcmp(propString, "ndisp")) { + if (!strcmp(valueString, "UNCATLG")){ + setTextUnitCharOrInt(sizeof(char), DISP_UNCATLG, configsCount, DALNDISP, textUnit); + } else if (!strcmp(valueString, "DELETE")){ + setTextUnitCharOrInt(sizeof(char), DISP_DELETE, configsCount, DALNDISP, textUnit); + } else if (!strcmp(valueString, "KEEP")){ + setTextUnitCharOrInt(sizeof(char), DISP_KEEP, configsCount, DALNDISP, textUnit); + } else { + setTextUnitCharOrInt(sizeof(char), DISP_CATLG, configsCount, DALNDISP, textUnit); + } + } else if(!strcmp(propString, "unit")) { + setTextUnitString(valueStrLen, &(valueString)[0], configsCount, DALUNIT, textUnit); + } else if(!strcmp(propString, "sysout")) { + if (!strcmp(valueString, "default")){ + for(int i = 0; i < *configsCount; i++) { + if (textUnit[i].key == DALSTATS || textUnit[i].key == DALNDISP) { + textUnit[i].type = TEXT_UNIT_NULL; + } + } + setTextUnitBool(configsCount, DALSYSOU, textUnit); + } else if (isalnum(valueString[0])) { + for(int i = 0; i < *configsCount; i++) { + if (textUnit[i].key == DALSTATS || textUnit[i].key == DALNDISP) { + textUnit[i].type == TEXT_UNIT_NULL; + } + } + setTextUnitCharOrInt(1, valueString[0], configsCount, DALSYSOU, textUnit); + } + } else if(!strcmp(propString, "spgnm")) { + if (valueStrLen <= CLASS_WRITER_SIZE){ + setTextUnitString(valueStrLen, &(valueString)[0], configsCount, DALSPGNM, textUnit); + } + } else if(!strcmp(propString, "close") || !strcmp(propString, "dummy")) { + if (!strcmp(valueString, "true")){ + setTextUnitBool(configsCount, !strcmp(propString, "close") ? DALCLOSE : DALDUMMY, textUnit); + } + } else if(!strcmp(propString, "dcbdd") || !strcmp(propString, "retdd")) { + if (valueStrLen <= DD_NAME_LEN){ + setTextUnitString(DD_NAME_LEN, &(valueString)[0], configsCount, !strcmp(propString, "dcbdd") ? DALDCBDD : DALRTDDN, textUnit); + } + } else if(!strcmp(propString, "spin")) { + if (!strcmp(valueString, "UNALLOC")){ + setTextUnitCharOrInt(1, SPIN_UNALLOC, configsCount, DALSPIN, textUnit); + } else if (!strcmp(valueString, "ENDJOB")){ + setTextUnitCharOrInt(1, SPIN_ENDJOB, configsCount, DALSPIN, textUnit); + } + } else if(!strcmp(propString, "strcls")) { + if (valueStrLen <= CLASS_WRITER_SIZE){ + setTextUnitString(8, &(valueString)[0], configsCount, DALSTCL, textUnit); + } + } else if(!strcmp(propString, "mngcls") || !strcmp(propString, "datacls")) { + if (valueStrLen <= CLASS_WRITER_SIZE){ + setTextUnitString(CLASS_WRITER_SIZE, &(valueString)[0], configsCount, !strcmp(propString, "mngcls") ? DALMGCL : DALDACL, textUnit); + } + } + } + currentProp = jsonObjectGetNextProperty(currentProp); + } +} + +static void setTextUnitString(int size, char* data, int *configsCount, int key, DynallocNewTextUnit *textUnit) { + textUnit[*configsCount].size = size; + textUnit[*configsCount].type = TEXT_UNIT_STRING; + textUnit[*configsCount].key = key; + textUnit[*configsCount].data.string = data; + (*configsCount)++; +} + +static void setTextUnitCharOrInt(int size, int data, int *configsCount, int key, DynallocNewTextUnit *textUnit) { + textUnit[*configsCount].size = size; + textUnit[*configsCount].type = TEXT_UNIT_CHARINT; + textUnit[*configsCount].key = key; + textUnit[*configsCount].data.number = data; + (*configsCount)++; +} + +static void setTextUnitBool(int *configsCount, int key, DynallocNewTextUnit *textUnit) { + textUnit[*configsCount].type = TEXT_UNIT_BOOLEAN; + textUnit[*configsCount].key = key; + (*configsCount)++; +} + +static int getDSCB(const DatasetName* datasetName, char* dscb, int bufferSize){ + if (bufferSize < INDEXED_DSCB){ + zowelog(NULL, LOG_COMP_RESTDATASET, ZOWE_LOG_WARNING, + "DSCB of size %d is too small, must be at least %d", bufferSize, INDEXED_DSCB); + return 1; + } + Volser volser = {0}; + + int volserSuccess = getVolserForDataset(datasetName, &volser); + if(!volserSuccess){ + int rc = obtainDSCB1(datasetName->value, sizeof(datasetName->value), + volser.value, sizeof(volser.value), + dscb); + if (rc == 0){ + if (DSCB_TRACE){ + zowelog(NULL, LOG_COMP_RESTDATASET, ZOWE_LOG_WARNING, "DSCB for %.*s found\n", sizeof(&datasetName->value), datasetName->value); + dumpbuffer(dscb,INDEXED_DSCB); + } + } + return 0; + } + else { + return 1; + } +} + +void newDatasetMember(HttpResponse* response, DatasetName* datasetName, char* absolutePath) { + char dscb[INDEXED_DSCB] = {0}; + int bufferSize = sizeof(dscb); + if (getDSCB(datasetName, dscb, bufferSize) != 0) { + respondWithJsonError(response, "Error decoding dataset", 400, "Bad Request"); + } + else { + if (!isPartionedDataset(dscb)) { + respondWithJsonError(response, "Dataset must be PDS/E", 400, "Bad Request"); + } + else { + char *overwriteParam = getQueryParam(response->request,"overwrite"); + int overwrite = !strcmp(overwriteParam, "true") ? TRUE : FALSE; + FILE* memberExists = fopen(absolutePath,"r"); + if (memberExists && overwrite != TRUE) {//Member already exists and overwrite wasn't specified + if (fclose(memberExists) != 0) { + zowelog(NULL, LOG_COMP_RESTDATASET, ZOWE_LOG_WARNING, "ERROR CLOSING FILE"); + respondWithJsonError(response, "Could not close dataset", 500, "Internal Server Error"); + } + else { + respondWithJsonError(response, "Member already exists and overwrite not specified", 400, "Bad Request"); + } + } + else { // Member doesn't exist + if (memberExists) { + if (fclose(memberExists) != 0) { + zowelog(NULL, LOG_COMP_RESTDATASET, ZOWE_LOG_WARNING, "ERROR CLOSING FILE"); + respondWithJsonError(response, "Could not close dataset", 500, "Internal Server Error"); + return; + } + } + FILE* newMember = fopen(absolutePath, "w"); + if (!newMember){ + printf("full path: %s\n", absolutePath); + respondWithJsonError(response, "Bad dataset name", 400, "Bad Request"); + return; + } + if (fclose(newMember) == 0){ + response200WithMessage(response, "Successfully created member"); + } + else { + zowelog(NULL, LOG_COMP_RESTDATASET, ZOWE_LOG_WARNING, "ERROR CLOSING FILE"); + respondWithJsonError(response, "Could not close dataset", 500, "Internal Server Error"); + } + } + } + } +} + +void newDataset(HttpResponse* response, char* absolutePath, int jsonMode){ + #ifdef __ZOWE_OS_ZOS + HttpRequest *request = response->request; + if (!isDatasetPathValid(absolutePath)) { + respondWithError(response, HTTP_STATUS_BAD_REQUEST, "Invalid dataset name"); + return; + } + + DatasetName datasetName; + DatasetMemberName memberName; + extractDatasetAndMemberName(absolutePath, &datasetName, &memberName); + DynallocDatasetName daDatasetName; + DynallocMemberName daMemberName; + memcpy(daDatasetName.name, datasetName.value, sizeof(daDatasetName.name)); + memcpy(daMemberName.name, memberName.value, sizeof(daMemberName.name)); + DynallocDDName daDDName = {.name = "????????"}; + + int daRC = RC_DYNALLOC_OK, daSysReturnCode = 0, daSysReasonCode = 0; + + bool isMemberEmpty = IS_DAMEMBER_EMPTY(daMemberName); + + if(!isMemberEmpty){ + return newDatasetMember(response, &datasetName, absolutePath); + } + + int configsCount = 0; + char ddNameBuffer[DD_NAME_LEN+1] = "MVD00000"; + DynallocNewTextUnit textUnits[TOTAL_TEXT_UNITS]; + setTextUnitString(DATASET_NAME_LEN, &datasetName.value[0], &configsCount, DALDSNAM, &textUnits[0]); + setTextUnitString(DD_NAME_LEN, ddNameBuffer, &configsCount, DALDDNAM, &textUnits[0]); + + if (jsonMode != TRUE) { /*TODO add support for updating files with raw bytes instead of JSON*/ + respondWithError(response, HTTP_STATUS_BAD_REQUEST,"Cannot update file without JSON formatted record request"); + return; + } + + char *contentBody = request->contentBody; + int bodyLength = strlen(contentBody); + + char *convertedBody = safeMalloc(bodyLength*4,"writeDatasetConvert"); + int conversionBufferLength = bodyLength*4; + int translationLength; + int outCCSID = NATIVE_CODEPAGE; + int reasonCode; + + int returnCode = convertCharset(contentBody, + bodyLength, + CCSID_UTF_8, + CHARSET_OUTPUT_USE_BUFFER, + &convertedBody, + conversionBufferLength, + outCCSID, + NULL, + &translationLength, + &reasonCode); + + if(returnCode == 0) { + + ShortLivedHeap *slh = makeShortLivedHeap(0x10000,0x10); + char errorBuffer[2048]; + Json *json = jsonParseUnterminatedString(slh, + convertedBody, translationLength, + errorBuffer, sizeof(errorBuffer)); + if (json) { + if (jsonIsObject(json)){ + JsonObject * jsonObject = jsonAsObject(json); + updateInputParmsProperty(jsonObject, &configsCount, &textUnits[0]); + } + } else { + respondWithError(response, HTTP_STATUS_BAD_REQUEST, "Invalid JSON request body"); + } + } + + returnCode = dynallocNewDataset(&reasonCode, &textUnits[0], configsCount); + int ddNumber = 1; + while (reasonCode==0x4100000 && ddNumber < 100000) { + sprintf(ddNameBuffer, "MVD%05d", ddNumber); + int ddconfig = 1; + setTextUnitString(DD_NAME_LEN, ddNameBuffer, &ddconfig, DALDDNAM, &textUnits[0]); + returnCode = dynallocNewDataset(&reasonCode, &textUnits[0], configsCount); + ddNumber++; + } + if (returnCode) { + zowelog(NULL, LOG_COMP_DATASERVICE, ZOWE_LOG_DEBUG, + "error: ds alloc dsn=\'%44.44s\' dd=\'%8.8s\', sysRC=%d, sysRSN=0x%08X\n", + daDatasetName.name, ddNameBuffer, returnCode, reasonCode); + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Unable to allocate a DD for ACB"); + return; + } + memcpy(daDDName.name, ddNameBuffer, DD_NAME_LEN); + daRC = dynallocUnallocDatasetByDDName(&daDDName, DYNALLOC_UNALLOC_FLAG_NONE, &returnCode, &reasonCode); + if (daRC != RC_DYNALLOC_OK) { + zowelog(NULL, LOG_COMP_DATASERVICE, ZOWE_LOG_DEBUG, + "error: ds unalloc dsn=\'%44.44s\' dd=\'%8.8s\', rc=%d sysRC=%d, sysRSN=0x%08X\n", + daDatasetName.name, daDDName.name, daRC, returnCode, reasonCode); + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Unable to deallocate DDNAME"); + return; + } + response200WithMessage(response, "Successfully created dataset"); + #endif +} + #endif /* not METTLE - the whole module */ diff --git a/c/dynalloc.c b/c/dynalloc.c index 1d68ff3e9..6f152169a 100644 --- a/c/dynalloc.c +++ b/c/dynalloc.c @@ -60,6 +60,10 @@ TextUnit *createIntTextUnit(int key, int value) { return createSimpleTextUnit2(key, (char*)&value, sizeof(value)); } +TextUnit *createIntTextUnitLength(int key, int value, int length) { + return createSimpleTextUnit2(key, (char*)&value, length); +} + TextUnit *createInt8TextUnit(int key, int8_t value) { return createSimpleTextUnit2(key, (char*)&value, sizeof(value)); } @@ -68,6 +72,14 @@ TextUnit *createInt16TextUnit(int key, int16_t value) { return createSimpleTextUnit2(key, (char*)&value, sizeof(value)); } +TextUnit *createInt24TextUnit(int key, int value) { + return createSimpleTextUnit2(key, (char*)&value + 1, INT24_SIZE); +} + +TextUnit *createLongIntTextUnit(int key, long long value) { + return createSimpleTextUnit2(key, (char*)&value, sizeof(value)); +} + TextUnit *createCharTextUnit(int key, char value) { char valueArray[2]; valueArray[0] = value; @@ -75,6 +87,14 @@ TextUnit *createCharTextUnit(int key, char value) { return createSimpleTextUnit2(key, valueArray, 1); } +TextUnit *createCharTextUnit2(int key, short value) { + char valueArray[3]; + valueArray[0] = value >> BYTE_LENGTH & BYTE_FULL_MASK; + valueArray[1] = value & BYTE_FULL_MASK; + valueArray[2] = 0; + return createSimpleTextUnit2(key, valueArray, 2); +} + TextUnit *createCompoundTextUnit(int key, char **values, int valueCount) { TextUnit *textUnit = NULL; @@ -834,6 +854,65 @@ int dynallocDataset(DynallocInputParms *inputParms, int *reasonCode) { } +int dynallocNewDataset(int *reasonCode, DynallocNewTextUnit *setTextUnits, int TextUnitsSize) { + ALLOC_STRUCT31( + STRUCT31_NAME(below2G), + STRUCT31_FIELDS( + DynallocParms parms; + TextUnit ** __ptr32 textUnits; + ) + ); + + below2G->textUnits = (TextUnit **)safeMalloc31(sizeof(TextUnit*) * TextUnitsSize, "Text units array"); + + DynallocParms *parms = &below2G->parms; + dynallocParmsInit(parms); + + dynallocParmsSetTextUnits(parms, below2G->textUnits, TextUnitsSize); + + int rc; + + do { + rc = -1; + for (int i = 0; i < TextUnitsSize; i++) { + if (setTextUnits[i].type == TEXT_UNIT_STRING) { + below2G->textUnits[i] = createSimpleTextUnit2(setTextUnits[i].key, setTextUnits[i].data.string, setTextUnits[i].size); + } + else if (setTextUnits[i].type == TEXT_UNIT_CHARINT) { + if (setTextUnits[i].size == sizeof(char)) { + below2G->textUnits[i] = createCharTextUnit(setTextUnits[i].key, setTextUnits[i].data.number); + } + else if (setTextUnits[i].size == sizeof(short)) { + below2G->textUnits[i] = createInt16TextUnit(setTextUnits[i].key, setTextUnits[i].data.number); + } + else if (setTextUnits[i].size == INT24_SIZE) { + below2G->textUnits[i] = createInt24TextUnit(setTextUnits[i].key, setTextUnits[i].data.number); + } + else if (setTextUnits[i].size == sizeof(long long)) { + long number = setTextUnits[i].data.number; + below2G->textUnits[i] = createLongIntTextUnit(setTextUnits[i].key, (long long)setTextUnits[i].data.number); + } + } + else if (setTextUnits[i].type == TEXT_UNIT_BOOLEAN) { + below2G->textUnits[i] = createSimpleTextUnit2(setTextUnits[i].key, NULL, 0); + } + } + + turn_on_HOB(below2G->textUnits[TextUnitsSize - 1]); + rc = invokeDynalloc(parms); + *reasonCode = dynallocParmsGetInfoCode(parms) + + (dynallocParmsGetErrorCode(parms) << 16); + } while (0); + freeTextUnitArray(below2G->textUnits, TextUnitsSize); + safeFree31((char*)below2G->textUnits, sizeof(TextUnit*) * TextUnitsSize); + dynallocParmsTerm(parms); + parms = NULL; + FREE_STRUCT31( + STRUCT31_NAME(below2G) + ); + return rc; +} + int dynallocDatasetMember(DynallocInputParms *inputParms, int *reasonCode, char *member) { diff --git a/h/datasetjson.h b/h/datasetjson.h index b5ab5a60c..7c44d3e81 100644 --- a/h/datasetjson.h +++ b/h/datasetjson.h @@ -23,6 +23,9 @@ #define SAF_AUTHORIZATION_READ 0x04 #define SAF_AUTHORIZATION_UPDATE 0x08 +#define MEMBER_MAX 8 +#define DATASET_PATH_MAX 44 +#define DATASET_MEMBER_MAXLEN DATASET_PATH_MAX + MEMBER_MAX + 6 /* 6 is for extra characters in filepath -- //, '', () */ typedef struct MetadataQueryCache_tag{ EntryDataSet *cachedHLQSet; @@ -62,6 +65,7 @@ void respondWithDataset(HttpResponse* response, char* absolutePath, int jsonMode void respondWithVSAMDataset(HttpResponse* response, char* absolutePath, hashtable *acbTable, int jsonMode); void respondWithDatasetMetadata(HttpResponse *response); void respondWithHLQNames(HttpResponse *response, MetadataQueryCache *metadataQueryCache); +void newDataset(HttpResponse* response, char* absolutePath, int jsonMode); void updateDataset(HttpResponse* response, char* absolutePath, int jsonMode); void updateVSAMDataset(HttpResponse* response, char* absolutePath, hashtable *acbTable, int jsonMode); void deleteVSAMDataset(HttpResponse* response, char* absolutePath); diff --git a/h/dynalloc.h b/h/dynalloc.h index b75987233..e622efb8d 100644 --- a/h/dynalloc.h +++ b/h/dynalloc.h @@ -209,7 +209,17 @@ X'40' Data set available for printing at the end of the job. #define DALVSER 0x0010 #define DALVSEQ 0x0012 #define DALDSORG 0x003C +#define DALDSORG_VSAM 0x0008 +#define DALDSORG_GRAPHICS 0x0080 +#define DALDSORG_PO 0x0200 +#define DALDSORG_POU 0x0300 +#define DALDSORG_MQ 0x0400 +#define DALDSORG_CQ 0x0800 +#define DALDSORG_CX 0x1000 +#define DALDSORG_DA 0x2000 +#define DALDSORG_DAU 0x2100 #define DALDSORG_PS 0x4000 +#define DALDSORG_PSU 0x4100 #define DALBLKSZ 0x0030 #define DALLRECL 0x0042 #define DALBUFNO 0x0034 @@ -252,8 +262,11 @@ TextUnit *createSimpleTextUnit2(int key, char *value, int firstParameterLength); TextUnit *createCharTextUnit(int key, char value); TextUnit *createCompoundTextUnit(int key, char **values, int valueCount); TextUnit *createIntTextUnit(int key, int value); +TextUnit *createCharTextUnit2(int key, short value); TextUnit *createInt8TextUnit(int key, int8_t value); +TextUnit *createIntTextUnitLength(int key, int value, int length); TextUnit *createInt16TextUnit(int key, int16_t value); +TextUnit *createInt24TextUnit(int key, int value); void freeTextUnit(TextUnit * text_unit); /* open a stream to the internal reader */ @@ -302,7 +315,7 @@ int DeallocDDName(char *ddname); #define DOBURST 0x0001 /* BURST FieldCount: 1 FieldLength 1 - X02 for YES X04 for NO + XDc12dc2for YES Xdc104dc2 for NO Directs output to a stacker on a 3800 Printing Subsystem. */ #define DOCHARS 0x0002 @@ -347,7 +360,7 @@ int DeallocDDName(char *ddname); #define DOCONTRO 0x0008 /* CONTROL FieldCount: 1 FieldLength 1 - X80 for SINGLE X40 for DOUBLE X20 for TRIPLE X10 for PROGRAM + XDC180' for SINGLE X'40' for DOUBLE X'20' for TRIPLE X'10' for PROGRAM Specifies that all the data records begin with carriage control characters or specifies line spacing. */ #define DOCOPIE9 0x0009 @@ -362,12 +375,12 @@ int DeallocDDName(char *ddname); #define DODATACK 0x2022 /* DATACK FieldCount: 1 FieldLength 1 - X00 for BLOCK X80 for UNBLOCK X81 for BLKCHAR X82 for BLKPOS + X'00' for BLOCK X'80' for UNBLOCK X'81' for BLKCHAR X'82' for BLKPOS Specifies how errors in printers accessed through the functional subsystem Print Services Facility (PSF) are to be reported. */ #define DODEFAUL 0x000B /* DEFAULT FieldCount: 1 FieldLength 1 - X40 for YES X80 for NO + X'40' for YES X'80' for NO Specifies that this is a default output descriptor. */ #define DODEPT 0x0029 @@ -382,12 +395,12 @@ int DeallocDDName(char *ddname); #define DODPAGEL 0x0023 /* DPAGELBL FieldCount: 1 FieldLength 1 - X40 for YES X80 for NO + X'40' for YES X'80' for NO Indicates whether the system should place a security label on each output page. YES means the system should place a label on each page. NO means the system should not place a label on each page. */ #define DODUPLEX 0x003D /* DUPLEX FieldCount: 1 FieldLength 1 - X80 for NO X40 for NORMAL X20 for TUMBLE + X'80' for NO X'40' for NORMAL X'20' for TUMBLE Specifies whether the job is to be printed on one or both sides of the paper. Overrides comparable FORMDEF specification. */ #define DOFCB 0x000D @@ -552,7 +565,7 @@ int DeallocDDName(char *ddname); #define DOPIMSG 0x0021 /* PIMSG FieldCount: 2 FieldLength 1 - X80 for NO X40 for YES The second value field is a two-byte number from 0 through 999 decimal, having a length field of 2. + X'80' for NO X'40' for YES The second value field is a two-byte number from 0 through 999 decimal, having a length field of 2. Indicates that messages from a functional subsystem should or should not be printed in the listing following the SYSOUT data set. Printing terminates if the number of printing errors exceeds the second value field. */ #define DOPORTNO 0x0045 @@ -568,7 +581,7 @@ int DeallocDDName(char *ddname); #define DOPRTATT 0x0050 /* PRTATTRS FieldCount: 1 FieldLength 1-127 EBCDIC text characters - Specifies an Infoprint Server job attribute. The z/OS Infoprint Server Users Guide documents job attribute names and syntax for acceptable values. */ + Specifies an Infoprint Server job attribute. The z/OS Infoprint Server User's Guide documents job attribute names and syntax for acceptable values. */ #define DOPROPTN 0x0039 /* PRTOPTNS FieldCount: 1 FieldLength 1-16 @@ -627,7 +640,7 @@ int DeallocDDName(char *ddname); #define DOSYSARE 0x0024 /* SYSAREA FieldCount: 1 FieldLength 1 - X40 for YES X80 for NO + X'40' for YES X'80' for NO Indicates whether you want to use the system printable area of each output page. YES means you want to use the area. NO means you do not want to use the area. */ #define DOTHRESH 0x0022 @@ -642,8 +655,8 @@ int DeallocDDName(char *ddname); #define DOTRC 0x001A /* TRC FieldCount: 1 FieldLength 1 - X80 for NO X40 for YES - Specifies whether or not the SYSOUT data sets records contain table reference codes (TRC) as the second character. */ + X'80' for NO X'40' for YES + Specifies whether or not the SYSOUT data set's records contain table reference codes (TRC) as the second character. */ #define DOUCS 0x001B /* UCS FieldCount: 1 FieldLength 1-4 @@ -661,7 +674,7 @@ int DeallocDDName(char *ddname); Specifies the names of libraries containing AFP resources. */ #define DOUSERPAT 0x004F -/* USERPATH FieldCount: 8 FieldLength 1255 +/* USERPATH FieldCount: 8 FieldLength 1-255 SPECIAL text. See z/OS MVS JCL Reference. Specifies up to eight HFS or ZFS system paths containing resources to be used by PSF when processing SYSOUT data sets. */ @@ -681,9 +694,29 @@ int DeallocDDName(char *ddname); // Values for disposition field #define DISP_OLD 0x01 #define DISP_MOD 0x02 +#define DISP_NEW 0x04 #define DISP_SHARE 0x08 #define DISP_DELETE 0x04 +// Values for normal disposition field +#define DISP_UNCATLG 0x01 +#define DISP_CATLG 0x02 +#define DISP_DELETE 0x04 +#define DISP_KEEP 0x08 + +#define DALSYSOU_DEFAULT 0x08 + +#define SPIN_UNALLOC 0x80 +#define SPIN_ENDJOB 0x40 + +#define BYTE_LENGTH 8 +#define BYTE_FULL_MASK 0xff + +#define INT24_SIZE 3 +#define VOLSER_SIZE 6 +#define CLASS_WRITER_SIZE 8 +#define TOTAL_TEXT_UNITS 23 + /* Use this structure to pass parameters to DYNALLOC functions. * Dsname should be padded by spaces. */ typedef struct DynallocInputParms_tag { @@ -696,11 +729,28 @@ typedef struct DynallocInputParms_tag { char reserved[3]; } DynallocInputParms; +typedef struct DynallocNewTextUnit_tag { +#define TEXT_UNIT_STRING 1 +#define TEXT_UNIT_BOOLEAN 2 +#define TEXT_UNIT_CHARINT 3 +#define TEXT_UNIT_NULL 4 +#define JSON_TYPE_ERROR 666 + int type; + int size; + int key; + union { + int number; + char *string; + int boolean; + } data; +} DynallocNewTextUnit; + #pragma map(dynallocDataset, "DYNAUALC") #pragma map(dynallocDatasetMember, "DYNAUALM") #pragma map(unallocDataset, "DYNADALC") int dynallocDataset(DynallocInputParms *inputParms, int *reasonCode); +int dynallocNewDataset(int *reasonCode, DynallocNewTextUnit *setTextUnits, int TextUnitsSize); int dynallocDatasetMember(DynallocInputParms *inputParms, int *reasonCode, char *member); int unallocDataset(DynallocInputParms *inputParms, int *reasonCode);