Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Qsam data set #109

Open
wants to merge 2 commits into
base: v1.x/staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions c/datasetjson.c
Original file line number Diff line number Diff line change
Expand Up @@ -2251,10 +2251,8 @@ void respondWithHLQNames(HttpResponse *response, MetadataQueryCache *metadataQue
#endif /* __ZOWE_OS_ZOS */
}


#endif /* not METTLE - the whole module */


/*
This program and the accompanying materials are
made available under the terms of the Eclipse Public License v2.0 which accompanies
Expand Down
269 changes: 269 additions & 0 deletions c/dynalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "zowetypes.h"
#include "alloc.h"
#include "dynalloc.h"
#include "logging.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're introducing a new dependency. Can we work out a different way of returning debug info? Perhaps return and reason codes.


#define TEXT_UNIT_ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))

Expand Down Expand Up @@ -1164,6 +1165,274 @@ int dynallocUnallocDatasetByDDName(const DynallocDDName *ddName,
return dynallocUnallocDatasetByDDNameInternal(ddName, flags, sysRC, sysRSN, FALSE);
}

/*************************/
#define FIELD_MAX_LENGTH 1024
#define REQUEST_MAX_LENGTH 2048
typedef int EXTF();
#pragma linkage(EXTF,OS_UPSTACK)

static int allocDataSetOpenString(dataSetRequest *request, char *buffer,
int bufferSize ) {
char * ptr;
char field[FIELD_MAX_LENGTH];
int status = 0, value;
char *baseRequest = "alloc new catalog msg(2) ";
char tempString[20] = {0};

/* setup initial request string */
strncpy(buffer, baseRequest, bufferSize);

/* Initialize the DD/FI field */
ptr = (request->ddName == NULL ? DATASET_DEFAULT_DDNAME: request->ddName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take a look at the existing functions in this file, they use a programmatic way to pass this information.

snprintf(field, sizeof(field)-1, "FI(%s) ", ptr);
strncat(buffer, field, bufferSize - strlen(buffer));

/* Initialize daName */
snprintf(field, sizeof(field)-1, "DA(%s) ", request->daName);
strncat(buffer, field, bufferSize - strlen(buffer));

/* Initialize data set type */
if ((ptr = request->dsnType) != NULL) {
snprintf(field, sizeof(field)-1, "DSNTYPE(%s) ", ptr);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize organization */
if (request->organization != NULL) {
snprintf(field, sizeof(field)-1, "DSORG(%s) ", request->organization);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • snprintf may fail
  • snprintf limit doesn't require a -1

strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize record format */
if (request->recordFormat != NULL) {
snprintf(field, sizeof(field)-1, "RECFM(%s) ", request->recordFormat);
strncat(buffer, field, bufferSize - strlen(buffer));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if strlen(buffer) is greater than bufferSize, the result will wrap around, you'll get a huge positive number and a buffer overflow.

}

/* Initialize record length */
if (request->recordLength != 0) {
snprintf(field, sizeof(field)-1, "LRECL(%d) ", request->recordLength);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize block size*/
if (request->blkSize != 0) {
snprintf(field, sizeof(field)-1, "BLKSIZE(%d) ", request->blkSize);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize storage type */
if (request->storageClass != NULL) {
snprintf(field, sizeof(field)-1, "STORCLAS(%s) ", request->storageClass);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize data type */
if (request->fileData != NULL) {
snprintf(field, sizeof(field)-1, "FILEDATA(%s) ", request->fileData);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize extended attribute */
if (request->eattr != NULL) {
strncpy(tempString, request->eattr, sizeof (tempString) -1);
strupcase(tempString);
if (strncmp(tempString, "TRUE", 5)) {
snprintf(field, sizeof(field)-1, "EATTR(OPT) ");
strncat(buffer, field, bufferSize - strlen(buffer));
}
}

/* Initialize number of generations */
if (request->numGenerations != 0) {
snprintf(field, sizeof(field)-1, "MAXGENS(%d) ", request->numGenerations);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize volumn if defined */
if (request->volume != NULL) {
snprintf(field, sizeof(field)-1, "VOL(%s) ", request->volume);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize dataClass if defined */
if (request->dataClass != NULL) {
snprintf(field, sizeof(field)-1, "DATACLAS(%s) ", request->dataClass);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize management class if defined */
if (request->manageClass != NULL) {
snprintf(field, sizeof(field)-1, "MGMTCLAS(%s) ", request->manageClass);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize management class if defined */
if (request->averageRecord != NULL) {
snprintf(field, sizeof(field)-1, "AVGREC(%s) ", request->averageRecord);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize expiration data */
if (request->expiration != NULL) {
snprintf(field, sizeof(field)-1, "EXPDL(%s) ", request->expiration);
strncat(buffer, field, bufferSize - strlen(buffer));
}

/* Initialize expiration data */
if (request->spaceUnit != NULL) {
snprintf(field, sizeof(field)-1, "SPACE(%s) ", request->spaceUnit);
strncat(buffer, field, bufferSize - strlen(buffer));
}
return status;
}

static void allocDataSetCloseString(dataSetRequest *request, char *buffer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about reusing dynallocUnallocDatasetByDDName and the other unalloc functions?

int bufferSize ) {
char * ptr;
char *freeRequest = "free ";
char field[FIELD_MAX_LENGTH];
char tempString[20] = {0};

strncpy( buffer, freeRequest, bufferSize);

/* Initialize the DD/FI field */
ptr = (request->ddName == NULL ? DATASET_DEFAULT_DDNAME: request->ddName);
snprintf(field, sizeof(field)-1, "fi(%s) ", ptr);
strncat(buffer, field, bufferSize - strlen(buffer));

/* Initialize daName */
snprintf(field, sizeof(field)-1, "da(%s) ", request->daName);
strncat(buffer, field, bufferSize - strlen(buffer));
}

static void allocDataSetInterpretError(char *requestBuffer,
int errorStatus, char *outBuffer, int bufferSize){

char field[FIELD_MAX_LENGTH];
int cause = 0, reasonIndex;
char *reason;

/* errorStatus between -20 and -9999 represents Key errors. */
/* The key index is (-errorStatus -20) */
/* errorStatus below -10000 has the IEFDB476 return code in */
/* lower 2 digits (decimal) of the errorStatus. */
/* Status code between -1610612737 and -2147483648 */
/* contains the S99ERROR code. */
# define KEY_ERROR_BEGIN 20
# define KEY_ERROR_END 9999
# define KEY_ERROR_MOD 100
# define IEF_ERROR_BEGIN (-32*1024)
# define IEF_ERROR_END (-10000)
# define IEF_ERROR_MOD 100
# define S99_ERROR_BEGIN (-1610612737)
# define S99_ERROR_END (-2147483648)
reason = strtok(requestBuffer, " ");
sprintf(field,"", "");
if ((errorStatus <= -KEY_ERROR_BEGIN) &&
(errorStatus >= -KEY_ERROR_END)) {
cause = (-errorStatus - KEY_ERROR_BEGIN) % KEY_ERROR_MOD;
for (int i=0; i < cause -1; i ++) {
reason = strtok(NULL, " ");
if (reason == NULL) {
break;
}
}
if (reason != NULL) {
int reasondIndex = -errorStatus / KEY_ERROR_MOD;
snprintf(field, sizeof(field)-1, " Field %s Error: Code %d",
reason, reasondIndex);
}
}
if ((IEF_ERROR_BEGIN <= errorStatus) && (errorStatus < IEF_ERROR_END)) {
cause = (-errorStatus - 20) %IEF_ERROR_MOD;
snprintf(field, sizeof(field)-1, "IEFDB476 Error Code %d", cause);
}
if ((errorStatus <= S99_ERROR_BEGIN) && (errorStatus >= S99_ERROR_END)) {
snprintf(field, sizeof(field)-1, "S99INFO Error Code %08x", errorStatus);
}

/* Write error message if one found */
if ((outBuffer != NULL) && strlen(field)) {
strncpy(outBuffer, field, bufferSize);
}
}

int allocDataSet( dataSetRequest *request, char* message, int messageLength){
#ifdef __ZOWE_OS_ZOS
char *baseRequest = "alloc new catalog msg(2) ";
char tempString[20] = {0};
char field[FIELD_MAX_LENGTH];
int status, value;
char *ptr;

/* Must supply daName */
if (request->daName == NULL) {
return -1;
}

/* Allocate structure in A31 space */
EXTF *bpxwdyn=(EXTF *)fetch("BPXWDYN");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not going to work in Metal C. Why not use the invokeSVC99 function?

if (bpxwdyn == NULL) {
strncpy(message, "Unable to fetch system function", messageLength);
return -1;
}

ALLOC_STRUCT31(
STRUCT31_NAME(below2G),
STRUCT31_FIELDS(
char request[REQUEST_MAX_LENGTH];
)
);

status = allocDataSetOpenString(request, below2G->request,
sizeof(below2G->request));
if (status < 0) {

/* Write error message if one found */
if ((message != NULL) && strlen(field)) {
strncpy(message, "Bad input value", messageLength);
}
goto freeStruct;
}

/****************************/
/* Create the data set */
/****************************/
//printf (" REQUEST: %s\n", below2G->request);
status = bpxwdyn(below2G->request);

/* If error, don't try to free, decipher error code */
if (status != 0) {
allocDataSetInterpretError(below2G->request, status, message,
messageLength);
zowelog(NULL, LOG_COMP_ALLOC, ZOWE_LOG_SEVERE,
"Create File %s Failed:: %s\n", request->daName, message);
goto freeStruct;
}

zowelog(NULL, LOG_COMP_ALLOC, ZOWE_LOG_INFO,
"Create File:: Request: %s\n",below2G->request);

/* If created the data set, then free/close it up */
allocDataSetCloseString(request, below2G->request,
sizeof (below2G->request));
status = bpxwdyn(below2G->request);

/* free the structure */
freeStruct:
release ((void (*)())bpxwdyn);
FREE_STRUCT31(
STRUCT31_NAME(below2G)
);

return status;
#endif /* __ZOWE_OS_ZOS */
}
#undef FIELD_MAX_LENGTH
#undef REQUEST_MAX_LENGTH



/*
This program and the accompanying materials are
Expand Down
1 change: 1 addition & 0 deletions h/datasetjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "json.h"
#include "xml.h"
#include "jcsi.h"
#include "qsam.h"

#define DATA_STREAM_BUFFER_SIZE 4096

Expand Down
31 changes: 31 additions & 0 deletions h/dynalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,37 @@ int dynallocUnallocDatasetByDDName(const DynallocDDName *ddName,
#define RC_DYNALLOC_TU_ALLOC_FAILED 8
#define RC_DYNALLOC_SVC99_FAILED 9

/*
The following definitions are used to create a qsam file using BPXWDYN.
*/
#define DATASET_DEFAULT_DDNAME "DUMMY"

typedef struct dataSetRequest_tag {
char *ddName;
char *daName; /* Name of file */
char *manageClass;
char *storageClass;
char *fileData; /* Data type: TEXT or BINARY ??? */
char *volume;
char *dsnType; /* LIBRARY,LIBRAY1,PDS,HFS,EXTREQ,EXTPREF,BASIC,LARGE*/
char *eattr; /* extended attribute: true/false */

char *organization; /* PS, PO, DA */
char *recordFormat; /* F - fixed, */
int recordLength;
int blkSize;
int primary;
int secondary;
int fileSize; /* Size of file*/
int numGenerations;
int avrBlockLength;
char *dataClass;
char *averageRecord; /* M, K or U */
char *expiration;
char *spaceUnit; /* BLKS, TRKS, CYCLS, KB, MB, BYTES */
int dirBlk;
} dataSetRequest;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We start our own types with a capital letter.

int allocDataSet( dataSetRequest *request, char* message, int messageLength);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Please remove the blank char between allocDataSet( and dataSetRequest *request,.
  • Is the content of message changed inside allocDataSet? If not, please use const.
  • Please use the dynalloc prefix for new functions.
  • I believe size_t would be more appropriate to represent a size.

#endif


Expand Down
2 changes: 1 addition & 1 deletion h/qsam.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ int bpamFind(char * __ptr32 dcb, char * __ptr32 memberName, int *reasonCode);
int bpamRead(void * __ptr32 dcb, void * __ptr32 buffer);
int bpamRead2(void * __ptr32 dcb, void * __ptr32 buffer, int *lengthRead);

#endif
#endif /* End __QSAM__ */


/*
Expand Down