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

Add support for longer cross-memory server parms (Zowe v3) #480

Closed
wants to merge 2 commits into from
Closed
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## `3.1.0`
- Feature: added javascript `zos.getStatvfs(path)` function to obtain file system information (#482).
- Bugfix: SLH should not ABEND when MEMLIMIT is reached (additional NULL check)
- Bugfix: support cross-memory server parameters longer than 128 characters
(zowe/zss#684)

## `3.0.0`
- Add support for LE 64-bit in isgenq.c (#422).
Expand Down
193 changes: 176 additions & 17 deletions c/crossmemory.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#include "utils.h"
#include "zvt.h"

#define CMS_STATIC_ASSERT($expr) typedef char p[($expr) ? 1 : -1]

#define CROSS_MEMORY_SERVER_MIN_NAME_LENGTH 4
#define CROSS_MEMORY_SERVER_MAX_NAME_LENGTH 16

Expand Down Expand Up @@ -598,12 +600,32 @@ typedef struct CrossMemoryServerConfigServiceParm_tag {
char eyecatcher[8];
#define CMS_CONFIG_SERVICE_PARM_EYECATCHER "RSCMSCSY"
char nameNullTerm[CMS_CONFIG_PARM_MAX_NAME_LENGTH + 1];
char padding[7];
CrossMemoryServerConfigParm result;
uint8_t version;
#define CMS_CONFIG_SERVICE_PARM_VERSION_0 0
#define CMS_CONFIG_SERVICE_PARM_VERSION_2 2
#define CMS_CONFIG_SERVICE_PARM_SIZE_V0 227
#define CMS_CONFIG_SERVICE_PARM_SIZE_V2 227
#define CMS_CONFIG_SERVICE_PARM_VERSION CMS_CONFIG_SERVICE_PARM_VERSION_2
char padding[6];
union {
CrossMemoryServerConfigParm result;
struct { // only for versions >= 2
int32_t nameLength;
int32_t valueBufferLength;
PAD_LONG(0, const char *name);
PAD_LONG(1, void *valueBuffer);
CrossMemoryServerConfigParmExt result;
} ext;
};
} CrossMemoryServerConfigServiceParm;

ZOWE_PRAGMA_PACK_RESET

CMS_STATIC_ASSERT(CMS_CONFIG_SERVICE_PARM_SIZE_V0 ==
sizeof(CrossMemoryServerConfigServiceParm));
CMS_STATIC_ASSERT(CMS_CONFIG_SERVICE_PARM_SIZE_V2 ==
sizeof(CrossMemoryServerConfigServiceParm));

static void initLogMessagePrefix(LogMessagePrefix *prefix) {
LogTimestamp currentTime;
getCurrentLogTimestamp(&currentTime);
Expand Down Expand Up @@ -984,7 +1006,7 @@ int cmsAddConfigParm(CrossMemoryServer *server,
ShortLivedHeap *slh = server->slh;

size_t keyLength = strlen(name);
if (keyLength > CMS_CONFIG_PARM_MAX_NAME_LENGTH) {
if (keyLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

Expand All @@ -995,28 +1017,33 @@ int cmsAddConfigParm(CrossMemoryServer *server,

strcpy(keyNullTerm, name);

CrossMemoryServerConfigParm *parm =
(CrossMemoryServerConfigParm *)SLHAlloc(
CrossMemoryServerConfigParmExt *parm =
(CrossMemoryServerConfigParmExt *)SLHAlloc(
slh,
sizeof(CrossMemoryServerConfigParm)
sizeof(CrossMemoryServerConfigParmExt)
);
if (parm == NULL) {
return RC_CMS_SLH_ALLOC_FAILED;
}

memcpy(parm->eyecatcher, CMS_PARM_EYECATCHER, sizeof(parm->eyecatcher));
memcpy(parm->eyecatcher, CMS_CONFIG_PARM_EXT_EYECATCHER,
sizeof(parm->eyecatcher));
parm->type = type;

switch (type) {
case CMS_CONFIG_PARM_TYPE_CHAR:
{
const char *charValueNullTerm = value;
size_t valueLength = strlen(charValueNullTerm);
if (valueLength > sizeof(parm->charValueNullTerm) - 1) {
if (valueLength > CMS_CONFIG_PARM_EXT_MAX_VALUE_SIZE) {
return RC_CMS_CHAR_PARM_TOO_LONG;
}
parm->valueLength = valueLength;
strcpy(parm->charValueNullTerm, charValueNullTerm);
parm->value = SLHAlloc(slh, valueLength + 1);
if (parm->value == NULL) {
return RC_CMS_SLH_ALLOC_FAILED;
}
strcpy(parm->value, charValueNullTerm);
}
break;
default:
Expand Down Expand Up @@ -1784,6 +1811,9 @@ static int handleConfigService(CrossMemoryServer *server,
return RC_CMS_STDSVC_PARM_NULL;
}

// Copying different versions using the same size is fine because both v0 and
// v2 have the same size, but, if this changes in the future, more complicated
// logic would need to be implemented.
CrossMemoryServerConfigServiceParm localParm;
cmCopyFromSecondaryWithCallerKey(&localParm, callerParm,
sizeof(CrossMemoryServerConfigServiceParm));
Expand All @@ -1793,16 +1823,58 @@ static int handleConfigService(CrossMemoryServer *server,
return RC_CMS_STDSVC_PARM_BAD_EYECATCHER;
}

localParm.nameNullTerm[sizeof(localParm.nameNullTerm) - 1] = '\0';

CrossMemoryServerConfigParm *configParm =
htGet(server->configParms, localParm.nameNullTerm);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
if (localParm.version != CMS_CONFIG_SERVICE_PARM_VERSION_0 &&
localParm.version != CMS_CONFIG_SERVICE_PARM_VERSION_2) {
return RC_CMS_STDSVC_PARM_BAD_VERSION;
}

cmCopyToSecondaryWithCallerKey(&callerParm->result, configParm,
sizeof(callerParm->result));
if (localParm.version == CMS_CONFIG_SERVICE_PARM_VERSION_0) {
localParm.nameNullTerm[sizeof(localParm.nameNullTerm) - 1] = '\0';
CrossMemoryServerConfigParmExt *configParm = htGet(server->configParms,
localParm.nameNullTerm);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
}
size_t valueCopyLength = configParm->type == CMS_CONFIG_PARM_TYPE_CHAR ?
configParm->valueLength + 1 : configParm->valueLength;
if (valueCopyLength > sizeof(localParm.result.charValueNullTerm)) {
return RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL;
}
localParm.result = (CrossMemoryServerConfigParm) {
.eyecatcher = CMS_PARM_EYECATCHER,
.valueLength = configParm->valueLength,
.type = configParm->type,
};
memcpy(localParm.result.charValueNullTerm, configParm->value,
valueCopyLength);
cmCopyToSecondaryWithCallerKey(callerParm, &localParm,
CMS_CONFIG_SERVICE_PARM_SIZE_V0);
} else {
char nameLocalBuffer[CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH + 1];
if (localParm.ext.nameLength > sizeof(nameLocalBuffer) - 1) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}
cmCopyFromSecondaryWithCallerKey(nameLocalBuffer, localParm.ext.name,
localParm.ext.nameLength);
nameLocalBuffer[localParm.ext.nameLength] = '\0';
CrossMemoryServerConfigParmExt *configParm = htGet(server->configParms,
nameLocalBuffer);
if (configParm == NULL) {
return RC_CMS_CONFIG_PARM_NOT_FOUND;
}
size_t valueCopyLength = configParm->type == CMS_CONFIG_PARM_TYPE_CHAR ?
configParm->valueLength + 1 : configParm->valueLength;
localParm.ext.result = *configParm;
localParm.ext.result.value = localParm.ext.valueBuffer;
cmCopyToSecondaryWithCallerKey(callerParm, &localParm,
CMS_CONFIG_SERVICE_PARM_SIZE_V2);
if (valueCopyLength > localParm.ext.valueBufferLength) {
return RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL;
}
cmCopyToSecondaryWithCallerKey(localParm.ext.valueBuffer,
configParm->value,
valueCopyLength);
}

return RC_CMS_OK;
}
Expand Down Expand Up @@ -5335,6 +5407,7 @@ int cmsGetConfigParm(const CrossMemoryServerName *serverName, const char *name,
memcpy(parmList.eyecatcher, CMS_CONFIG_SERVICE_PARM_EYECATCHER,
sizeof(parmList.eyecatcher));
memcpy(parmList.nameNullTerm, name, nameLength);
parmList.version = CMS_CONFIG_SERVICE_PARM_VERSION_0;

int serviceRC = cmsCallService(
serverName,
Expand Down Expand Up @@ -5364,6 +5437,7 @@ int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
memcpy(parmList.eyecatcher, CMS_CONFIG_SERVICE_PARM_EYECATCHER,
sizeof(parmList.eyecatcher));
memcpy(parmList.nameNullTerm, name, nameLength);
parmList.version = CMS_CONFIG_SERVICE_PARM_VERSION_0;

CrossMemoryServerGlobalArea *cmsGA = NULL;
int getGlobalAreaRC = cmsGetGlobalArea(serverName, &cmsGA);
Expand All @@ -5387,6 +5461,91 @@ int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
return RC_CMS_OK;
}

int cmsGetConfigParmExt(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn) {

size_t nameLength = strlen(name);
if (nameLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

CrossMemoryServerConfigServiceParm parmList = {
.eyecatcher = CMS_CONFIG_SERVICE_PARM_EYECATCHER,
.version = CMS_CONFIG_SERVICE_PARM_VERSION,
.ext.nameLength = nameLength,
.ext.name = name,
.ext.valueBufferLength = valueBufferSize,
.ext.valueBuffer = valueBuffer,
};

int serviceRC = cmsCallService(
serverName,
CROSS_MEMORY_SERVER_CONFIG_SERVICE_ID,
&parmList,
rsn
);
if (serviceRC != RC_CMS_OK) {
if (serviceRC == RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL) {
*parm = parmList.ext.result;
}
return serviceRC;
}

*parm = parmList.ext.result;

return RC_CMS_OK;
}

int cmsGetConfigParmExtUnchecked(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn) {

size_t nameLength = strlen(name);
if (nameLength > CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH) {
return RC_CMS_CONFIG_PARM_NAME_TOO_LONG;
}

CrossMemoryServerConfigServiceParm parmList = {
.eyecatcher = CMS_CONFIG_SERVICE_PARM_EYECATCHER,
.version = CMS_CONFIG_SERVICE_PARM_VERSION,
.ext.nameLength = nameLength,
.ext.name = name,
.ext.valueBufferLength = valueBufferSize,
.ext.valueBuffer = valueBuffer,
};

CrossMemoryServerGlobalArea *cmsGA = NULL;
int getGlobalAreaRC = cmsGetGlobalArea(serverName, &cmsGA);
if (getGlobalAreaRC != RC_CMS_OK) {
return getGlobalAreaRC;
}

int serviceRC = cmsCallService3(
cmsGA,
CROSS_MEMORY_SERVER_CONFIG_SERVICE_ID,
&parmList,
CMS_CALL_FLAG_NO_SAF_CHECK,
rsn
);
if (serviceRC != RC_CMS_OK) {
if (serviceRC == RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL) {
*parm = parmList.ext.result;
}
return serviceRC;
}

*parm = parmList.ext.result;

return RC_CMS_OK;
}

int cmsGetPCLogLevel(const CrossMemoryServerName *serverName) {

int logLevel = ZOWE_LOG_NA;
Expand Down
2 changes: 2 additions & 0 deletions c/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,7 @@ char *SLHAlloc(ShortLivedHeap *slh, int size){
safeMalloc31(size+4,"SLH Oversize Extend"));
if (bigBlock == NULL){
reportSLHFailure(slh,size);
return NULL;
}
int *sizePtr = (int*)bigBlock;
*sizePtr = size;
Expand All @@ -1528,6 +1529,7 @@ char *SLHAlloc(ShortLivedHeap *slh, int size){
safeMalloc31(slh->blockSize+4,"SLH Extend") );
if (data == NULL){
reportSLHFailure(slh,size);
return NULL;
}
int *sizePtr = (int*)data;
*sizePtr = slh->blockSize;
Expand Down
58 changes: 57 additions & 1 deletion h/crossmemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@
#define RC_CMS_NO_ROOM_FOR_CMS_GETTER 91
#define RC_CMS_LANC_NOT_LOCKED 92
#define RC_CMS_LANC_NOT_RELEASED 93
#define RC_CMS_MAX_RC 93
#define RC_CMS_STDSVC_PARM_BAD_VERSION 94
#define RC_CMS_CONFIG_VALUE_BUF_TOO_SMALL 95
#define RC_CMS_MAX_RC 95

extern const char *CMS_RC_DESCRIPTION[];

Expand Down Expand Up @@ -377,9 +379,11 @@ typedef struct CrossMemoryServerParmList_tag {
PAD_LONG(1, void *callerData);
} CrossMemoryServerParmList;

#pragma enum(1)
typedef enum CrossMemoryServerParmType_tag {
CMS_CONFIG_PARM_TYPE_CHAR
} CrossMemoryServerParmType;
#pragma enum(reset)

#define CMS_CONFIG_PARM_MAX_NAME_LENGTH 72
#define CMS_CONFIG_PARM_MAX_VALUE_SIZE 128
Expand All @@ -394,6 +398,19 @@ typedef struct CrossMemoryServerConfigParm_tag {
};
} CrossMemoryServerConfigParm;

typedef struct CrossMemoryServerConfigParmExt_tag {
char eyecatcher[8];
#define CMS_CONFIG_PARM_EXT_EYECATCHER "RSCMSCFX"
uint8_t version;
#define CMS_CONFIG_PARM_EXT_VERSION 1
CrossMemoryServerParmType type;
char padding0[2];
#define CMS_CONFIG_PARM_EXT_MAX_NAME_LENGTH 1024
#define CMS_CONFIG_PARM_EXT_MAX_VALUE_SIZE INT32_MAX
int32_t valueLength;
PAD_LONG(0, void *value);
} CrossMemoryServerConfigParmExt;

typedef struct CrossMemoryServerStatus_tag {
int cmsRC;
char descriptionNullTerm[64];
Expand Down Expand Up @@ -424,6 +441,8 @@ ZOWE_PRAGMA_PACK_RESET
#define cmsHexDump CMHEXDMP
#define cmsGetConfigParm CMGETPRM
#define cmsGetConfigParmUnchecked CMGETPRU
#define cmsGetConfigParmExt CMGETPRX
#define cmsGetConfigParmExtUnchecked CMGETPUX
#define cmsGetPCLogLevel CMGETLOG
#define cmsGetStatus CMGETSTS
#define cmsMakeServerName CMMKSNAM
Expand Down Expand Up @@ -559,6 +578,43 @@ int cmsGetConfigParm(const CrossMemoryServerName *serverName, const char *name,
int cmsGetConfigParmUnchecked(const CrossMemoryServerName *serverName,
const char *name,
CrossMemoryServerConfigParm *parm);
/**
* @brief Get a parameter from the cross-memory server's PARMLIB
* @param[in] serverName Cross-memory server whose parameter is to be read
* @param[in] name Name of the parameter
* @param[out] valueBuffer Buffer for the result value
* @param[out] valueBufferSize Size of the value buffer
* @param[out] parm Result parameter entry
* @param[out] rsn Reason code provided by the service in case of a failure
* @return RC_CMS_OK in case of success, and one of the RC_CMS_nn values in
* case of failure
*/
int cmsGetConfigParmExt(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn);


/**
* @brief Get a parameter from the cross-memory server's PARMLIB without the
* authorization check (the caller must be SUP or system key)
* @param[in] serverName Cross-memory server whose parameter is to be read
* @param[in] name Name of the parameter
* @param[out] valueBuffer Buffer for the result value
* @param[out] valueBufferSize Size of the value buffer
* @param[out] parm Result parameter entry
* @param[out] rsn Reason code provided by the service in case of a failure
* @return RC_CMS_OK in case of success, and one of the RC_CMS_nn values in
* case of failure
*/
int cmsGetConfigParmExtUnchecked(const CrossMemoryServerName *serverName,
const char *name,
void *valueBuffer,
int valueBufferSize,
CrossMemoryServerConfigParmExt *parm,
int *rsn);

int cmsGetPCLogLevel(const CrossMemoryServerName *serverName);
CrossMemoryServerStatus cmsGetStatus(const CrossMemoryServerName *serverName);
Expand Down
Loading