diff --git a/c/datasetjson.c b/c/datasetjson.c index 97fb7f093..479bbdecd 100644 --- a/c/datasetjson.c +++ b/c/datasetjson.c @@ -24,6 +24,7 @@ #include "json.h" #include "bpxnet.h" #include "unixfile.h" +#include "errno.h" #ifdef __ZOWE_OS_ZOS #include "zos.h" #endif @@ -53,6 +54,10 @@ static int defaultVSAMCSIFieldCount = 4; static char getRecordLengthType(char *dscb); static int getMaxRecordLength(char *dscb); +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 void respondWithNonVSAMDataset(HttpResponse* response, char* absolutePath, int jsonMode); static void respondWithVSAMDataset(HttpResponse* response, char* absolutePath, hashtable *acbTable, int jsonMode); static void updateNonVSAMDataset(HttpResponse* response, char* absolutePath, int jsonMode); @@ -1719,6 +1724,354 @@ void respondWithHLQNames(HttpResponse *response, MetadataQueryCache *metadataQue #endif /* __ZOWE_OS_ZOS */ } +static int updateInputParmsProperty(JsonObject *object, int *configsCount, DynallocNewTextUnit *textUnit) { + Json* value = jsonObjectGetPropertyValue(object, "dsorg"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "PS")) { + setTextUnitCharOrInt(sizeof(short), DALDSORG_PS, configsCount, DALDSORG, textUnit); + } + else if (!strcmp(value->data.string, "PO")) { + setTextUnitCharOrInt(sizeof(short), DALDSORG_PO, configsCount, DALDSORG, textUnit); + } + } + + errno = 0; + value = jsonObjectGetPropertyValue(object, "blksz"); + if (jsonIsString(value)){ + long toi = strtol(value->data.string, 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); + } + } + } + + errno = 0; + value = jsonObjectGetPropertyValue(object, "lrecl"); + if (jsonIsString(value)){ + long toi = strtol(value->data.string, 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); + } + } + } + value = jsonObjectGetPropertyValue(object, "volser"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= VOLSER_SIZE){ + setTextUnitString(VOLSER_SIZE, &(value->data.string)[0], configsCount, DALVLSER, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "recfm"); + if (jsonIsString(value)){ + int setRECFM = 0; + if (indexOf(value->data.string, strlen(value->data.string), 'A', 0) != -1){ + setRECFM = setRECFM | DALRECFM_A; + } + if (indexOf(value->data.string, strlen(value->data.string), 'B', 0) != -1){ + setRECFM = setRECFM | DALRECFM_B; + } + if (indexOf(value->data.string, strlen(value->data.string), 'V', 0) != -1){ + setRECFM = setRECFM | DALRECFM_V; + } + if (indexOf(value->data.string, strlen(value->data.string), 'F', 0) != -1){ + setRECFM = setRECFM | DALRECFM_F; + } + if (indexOf(value->data.string, strlen(value->data.string), 'U', 0) != -1){ + setRECFM = setRECFM | DALRECFM_U; + } + setTextUnitCharOrInt(sizeof(char), setRECFM, configsCount, DALRECFM, textUnit); + } + + errno = 0; + value = jsonObjectGetPropertyValue(object, "prime"); + if (jsonIsString(value)){ + long toi = strtol(value->data.string, NULL, 0); + if (toi <= 0xFFFFFF || toi >= 0) { + if (errno != ERANGE){ + setTextUnitCharOrInt(INT24_SIZE, toi, configsCount, DALPRIME, textUnit); + } + } + } + + errno = 0; + value = jsonObjectGetPropertyValue(object, "second"); + if (jsonIsString(value)){ + long toi = strtol(value->data.string, NULL, 0); + if (toi <= 0xFFFFFF || toi >= 0) { + if (errno != ERANGE){ + setTextUnitCharOrInt(INT24_SIZE, toi, configsCount, DALSECND, textUnit); + } + } + } + + value = jsonObjectGetPropertyValue(object, "space"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "cyl")){ + setTextUnitBool(configsCount, DALCYL, textUnit); + } + if (!strcmp(value->data.string, "trk")){ + setTextUnitBool(configsCount, DALCYL, textUnit); + } + } + + errno = 0; + value = jsonObjectGetPropertyValue(object, "blkln"); + if (jsonIsString(value)){ + long toi = strtol(value->data.string, NULL, 0); + if (toi <= 0xFFFF || toi >= 0) { + if (errno != ERANGE){ + setTextUnitCharOrInt(INT24_SIZE, toi, configsCount, DALBLKLN, textUnit); + } + } + } + + value = jsonObjectGetPropertyValue(object, "status"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "OLD")){ + setTextUnitCharOrInt(sizeof(char), DISP_OLD, configsCount, DALSTATS, textUnit); + } + else if (!strcmp(value->data.string, "MOD")){ + setTextUnitCharOrInt(sizeof(char), DISP_MOD, configsCount, DALSTATS, textUnit); + } + else if (!strcmp(value->data.string, "SHARE")){ + setTextUnitCharOrInt(sizeof(char), DISP_SHARE, configsCount, DALSTATS, textUnit); + } + else { + setTextUnitCharOrInt(sizeof(char), DISP_NEW, configsCount, DALSTATS, textUnit); + } + } + else { + setTextUnitCharOrInt(sizeof(char), DISP_NEW, configsCount, DALSTATS, textUnit); + } + + value = jsonObjectGetPropertyValue(object, "ndisp"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "UNCATLG")){ + setTextUnitCharOrInt(sizeof(char), DISP_UNCATLG, configsCount, DALNDISP, textUnit); + } + else if (!strcmp(value->data.string, "DELETE")){ + setTextUnitCharOrInt(sizeof(char), DISP_DELETE, configsCount, DALNDISP, textUnit); + } + else if (!strcmp(value->data.string, "KEEP")){ + setTextUnitCharOrInt(sizeof(char), DISP_KEEP, configsCount, DALNDISP, textUnit); + } + else { + setTextUnitCharOrInt(sizeof(char), DISP_CATLG, configsCount, DALNDISP, textUnit); + } + } + else { + setTextUnitCharOrInt(sizeof(char), DISP_CATLG, configsCount, DALNDISP, textUnit); + } + + value = jsonObjectGetPropertyValue(object, "unit"); + if (jsonIsString(value)){ + setTextUnitString(strlen(value->data.string), &(value->data.string)[0], configsCount, DALUNIT, textUnit); + } + + value = jsonObjectGetPropertyValue(object, "sysout"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "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(value->data.string[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, value->data.string[0], configsCount, DALSYSOU, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "spgnm"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= CLASS_WRITER_SIZE){ + setTextUnitString(strlen(value->data.string), &(value->data.string)[0], configsCount, DALSPGNM, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "close"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "true")){ + setTextUnitBool(configsCount, DALCLOSE, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "dummy"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "true")){ + setTextUnitBool(configsCount, DALDUMMY, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "dcbdd"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= DD_NAME_LEN){ + setTextUnitString(DD_NAME_LEN, &(value->data.string)[0], configsCount, DALDCBDD, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "retdd"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= DD_NAME_LEN){ + setTextUnitString(DD_NAME_LEN, &(value->data.string)[0], configsCount, DALRTDDN, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "spin"); + if (jsonIsString(value)){ + if (!strcmp(value->data.string, "UNALLOC")){ + setTextUnitCharOrInt(1, SPIN_UNALLOC, configsCount, DALSPIN, textUnit); + } + else if (!strcmp(value->data.string, "ENDJOB")){ + setTextUnitCharOrInt(1, SPIN_ENDJOB, configsCount, DALSPIN, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "strcls"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= CLASS_WRITER_SIZE){ + setTextUnitString(8, &(value->data.string)[0], configsCount, DALSTCL, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "mngcls"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= CLASS_WRITER_SIZE){ + setTextUnitString(CLASS_WRITER_SIZE, &(value->data.string)[0], configsCount, DALMGCL, textUnit); + } + } + + value = jsonObjectGetPropertyValue(object, "datacls"); + if (jsonIsString(value)){ + if (strlen(value->data.string) <= CLASS_WRITER_SIZE){ + setTextUnitString(CLASS_WRITER_SIZE, &(value->data.string)[0], configsCount, DALDACL, textUnit); + } + } +} + +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)++; +} + +void newDataset(HttpResponse* response, char* datasetName, int jsonMode){ + #ifdef __ZOWE_OS_ZOS + + DatasetName dsn = {0}; + memset(dsn.value, ' ', DATASET_NAME_LEN); + + int lParenIndex = indexOf(datasetName, strlen(datasetName),'(',0); + + //String parsing operation, gets rid of of 3 initial unnecessary characters-> //' + if (lParenIndex > 0){ + memcpy(dsn.value,datasetName+3,lParenIndex-3); + } + //String parsing operation, gets rid of of 3 initial unnecessary characters-> //' + else{ + memcpy(dsn.value,datasetName+3,strlen(datasetName)-4); + } + + int configsCount = 0; + DynallocNewTextUnit textUnits[TOTAL_TEXT_UNITS]; + setTextUnitString(DATASET_NAME_LEN, &dsn.value[0], &configsCount, DALDSNAM, &textUnits[0]); + setTextUnitString(DD_NAME_LEN, "MVD00000", &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; + } + + HttpRequest *request = response->request; + + FileInfo info; + + 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]); + } + } + } + + returnCode = dynallocNewDataset(&reasonCode, &textUnits[0], configsCount); + int ddNumber = 1; + char buffer[DD_NAME_LEN + 1]; + while (reasonCode==0x4100000 && ddNumber < 100000) { + sprintf(buffer, "MVD%05d", ddNumber); + int ddconfig = 1; + setTextUnitString(DD_NAME_LEN, buffer, &ddconfig, DALDDNAM, &textUnits[0]); + returnCode = dynallocNewDataset(&reasonCode, &textUnits[0], configsCount); + ddNumber++; + } + if (returnCode) { + printf("Dynalloc RC = %d, reasonCode = %x\n", returnCode, reasonCode); + respondWithError(response, HTTP_STATUS_INTERNAL_SERVER_ERROR, "Unable to allocate a DD for ACB"); + return; + } + else { + printf("Dynalloc RC = %d, reasonCode = %x\n", returnCode, reasonCode); + response200WithMessage(response, "Successfully created dataset"); + } + #endif +} #endif /* not METTLE - the whole module */ diff --git a/c/dynalloc.c b/c/dynalloc.c index c75fd0eb7..ea06fe483 100644 --- a/c/dynalloc.c +++ b/c/dynalloc.c @@ -56,6 +56,10 @@ TextUnit *createSimpleTextUnit(int key, char *value) { return createSimpleTextUnit2(key, value, firstParameterLength); } +TextUnit *createIntTextUnitLength(int key, int value, int length) { + return createSimpleTextUnit2(key, (char*)&value, length); +} + TextUnit *createIntTextUnit(int key, int 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; @@ -831,6 +851,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 **)safeMalloc(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); + safeFree((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 bcf5de66d..61da6ef5c 100644 --- a/h/datasetjson.h +++ b/h/datasetjson.h @@ -63,6 +63,7 @@ void respondWithDatasetMetadata(HttpResponse *response); void respondWithHLQNames(HttpResponse *response, MetadataQueryCache *metadataQueryCache); void respondWithDataset(HttpResponse* response, char* fullPath, int jsonMode, HttpService* service); void updateDataset(HttpResponse* response, char* fullPath, int jsonMode, HttpService* service); +void newDataset(HttpResponse* response, char* absolutePath, int jsonMode); #endif diff --git a/h/dynalloc.h b/h/dynalloc.h index 06edd67ca..ff7ca5d5c 100644 --- a/h/dynalloc.h +++ b/h/dynalloc.h @@ -209,6 +209,7 @@ X'40' Data set available for printing at the end of the job. #define DALVSER 0x0010 #define DALVSEQ 0x0012 #define DALDSORG 0x003C +#define DALDSORG_PO 0x0200 #define DALDSORG_PS 0x4000 #define DALBLKSZ 0x0030 #define DALLRECL 0x0042 @@ -250,10 +251,13 @@ typedef struct _text_unit { TextUnit *createSimpleTextUnit(int key, char *value); TextUnit *createSimpleTextUnit2(int key, char *value, int firstParameterLength); TextUnit *createCharTextUnit(int key, char value); +TextUnit *createCharTextUnit2(int key, short value); TextUnit *createCompoundTextUnit(int key, char **values, int valueCount); TextUnit *createIntTextUnit(int key, int value); +TextUnit *createIntTextUnitLength(int key, int value, int length); TextUnit *createInt8TextUnit(int key, int8_t value); 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 */ @@ -680,8 +684,28 @@ int DeallocDDName(char *ddname); // Values for disposition field #define DISP_OLD 0x01 #define DISP_MOD 0x02 +#define DISP_NEW 0x04 #define DISP_SHARE 0x08 +// 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 { @@ -694,11 +718,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);