diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..f870fed90 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,45 @@ +--- +name: Bug report +about: Create a report to help us improve. +title: '' +labels: bug, new +--- + + + +**Describe the bug** + +**Steps to Reproduce** + +1. +2. + +**Expected behavior** + +**Screenshots (if needed)** + +**Logs** + + + + + + + + + + +**Describe your environment** + + +- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder): +- Install method (pax, smpe, kubernetes, github clone): +- Operating system (z/OS, kubernetes, etc) and OS version: +- Node.js version number (Shown in logs, or via `node --version`): +- Java version number (Shown in logs, or via `java -version`): +- z/OSMF version: +- What is the output of log message ZWES1014I: +- Environment variables in use: + + +**Additional context** diff --git a/.github/ISSUE_TEMPLATE/bug_report_high.md b/.github/ISSUE_TEMPLATE/bug_report_high.md new file mode 100644 index 000000000..2a055864e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_high.md @@ -0,0 +1,45 @@ +--- +name: High-severity bug report +about: Create a report on a high-severity bug. High severity is when there is an issue that has a major impact on usage of Zowe. +title: '' +labels: bug, new, severity-high +--- + + + +**Describe the bug** + +**Steps to Reproduce** + +1. +2. + +**Expected behavior** + +**Screenshots (if needed)** + +**Logs** + + + + + + + + + + +**Describe your environment** + + +- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder): +- Install method (pax, smpe, kubernetes, github clone): +- Operating system (z/OS, kubernetes, etc) and OS version: +- Node.js version number (Shown in logs, or via `node --version`): +- Java version number (Shown in logs, or via `java -version`): +- z/OSMF version: +- What is the output of log message ZWES1014I: +- Environment variables in use: + + +**Additional context** diff --git a/.github/ISSUE_TEMPLATE/bug_report_low.md b/.github/ISSUE_TEMPLATE/bug_report_low.md new file mode 100644 index 000000000..e47807673 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_low.md @@ -0,0 +1,45 @@ +--- +name: Low-severity bug report +about: Create a report on a low-severity bug. Low severity is when there is an issue that is inconvenient but doesn't impact key use cases. +title: '' +labels: bug, new, severity-low +--- + + + +**Describe the bug** + +**Steps to Reproduce** + +1. +2. + +**Expected behavior** + +**Screenshots (if needed)** + +**Logs** + + + + + + + + + + +**Describe your environment** + + +- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder): +- Install method (pax, smpe, kubernetes, github clone): +- Operating system (z/OS, kubernetes, etc) and OS version: +- Node.js version number (Shown in logs, or via `node --version`): +- Java version number (Shown in logs, or via `java -version`): +- z/OSMF version: +- What is the output of log message ZWES1014I: +- Environment variables in use: + + +**Additional context** diff --git a/.github/ISSUE_TEMPLATE/bug_report_medium.md b/.github/ISSUE_TEMPLATE/bug_report_medium.md new file mode 100644 index 000000000..86e45dc95 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report_medium.md @@ -0,0 +1,45 @@ +--- +name: Medium-severity bug report +about: Create a report on a medium-severity bug. Medium severity is when there is an issue that makes the use of Zowe difficult, but has a workaround or doesn't prevent the use of Zowe. +title: '' +labels: bug, new, severity-medium +--- + + + +**Describe the bug** + +**Steps to Reproduce** + +1. +2. + +**Expected behavior** + +**Screenshots (if needed)** + +**Logs** + + + + + + + + + + +**Describe your environment** + + +- Zowe version number (Check the Desktop login screen, or manifest.json in the Zowe install folder): +- Install method (pax, smpe, kubernetes, github clone): +- Operating system (z/OS, kubernetes, etc) and OS version: +- Node.js version number (Shown in logs, or via `node --version`): +- Java version number (Shown in logs, or via `java -version`): +- z/OSMF version: +- What is the output of log message ZWES1014I: +- Environment variables in use: + + +**Additional context** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..842a135fa --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,25 @@ +--- +name: Feature request +about: Suggest an idea for ZSS +labels: enhancement, new +--- + + + +**Is your feature or enhancement request related to a problem or limitation? Please describe** + + + +**Describe your enhancement idea** + + + + +**Describe alternatives you've considered** + + + +**Provide any additional context** + + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..062dec064 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,35 @@ + + +## Proposed changes + + +This PR addresses Issue: [*Link to Github issue within https://github.com/zowe/zowe-common-c/issues* if any] + +This PR depends upon the following PRs: + +## Type of change +Please delete options that are not relevant. +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Change in a documentation +- [ ] Refactor the code +- [ ] Chore, repository cleanup, updates the dependencies. +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) + +## PR Checklist +Please delete options that are not relevant. +- [ ] If the changes in this PR are meant for the next release / mainline, this PR targets the "staging" branch. +- [ ] My code follows the style guidelines of this project (see: [Contributing guideline](https://github.com/zowe/zss/blob/v2.x/master/CONTRIBUTING.md)) +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] New and existing unit tests pass locally with my changes +- [ ] video or image is included if visual changes are made +- [ ] Relevant update to CHANGELOG.md +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works, or describe a test method below + +## Testing + + +## Further comments + diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..bb9de01ab --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,30 @@ +name: 'Close stale issues and PRs' +on: + schedule: + - cron: '0 */6 * * *' + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v5 + with: + close-issue-message: > + This issue has been automatically closed due to lack of activity. + If this issue is still valid and important to you, it can be reopened. + days-before-close: 90 + days-before-stale: 180 + exempt-all-assignees: true + exempt-all-milestones: true + exempt-issue-labels: "community-upvoted, dependency, for-review, keep, security, high-severity, critical-severity, help-wanted, good-first-issue" + stale-issue-label: "stale-reopen-if-needed" + stale-issue-message: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs, + but can be reopened if needed. Thank you for your contributions. + stale-pr-label: "stale-reopen-if-needed" + start-date: "2022-05-30T00:00:00Z" diff --git a/CHANGELOG.md b/CHANGELOG.md index d57e3a675..1be845d1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Zowe Common C Changelog +## `2.5.0` + +- Added embeddedjs command "xplatform.appendFileUTF8" for appending to files rather than writing whole files. +- Bugfix that the configmgr binary would always return rc=0. Now, it has various return codes for the various internal errors or config invalid responses. + ## `2.3.0` - Bugfix for lht functions of collections.c to avoid memory issues on negative keys diff --git a/build/configmgr.proj.env b/build/configmgr.proj.env index b24079b03..b565dc288 100644 --- a/build/configmgr.proj.env +++ b/build/configmgr.proj.env @@ -1,5 +1,5 @@ PROJECT="configmgr" -VERSION=0.4.0 +VERSION=0.4.1 DEPS="QUICKJS LIBYAML" QUICKJS="quickjs" diff --git a/c/configmgr.c b/c/configmgr.c index 1bf415f74..f7adc2036 100644 --- a/c/configmgr.c +++ b/c/configmgr.c @@ -1638,7 +1638,7 @@ static int simpleMain(int argc, char **argv){ bool jqRaw = false; if (argc == 1){ showHelp(traceOut); - return 0; + return ZCFG_BAD_ARGS; } while (argx < argc){ @@ -1669,7 +1669,7 @@ static int simpleMain(int argc, char **argv){ if (strlen(nextArg) && nextArg[0] == '-'){ fprintf(traceOut,"\n *** unknown option *** '%s'\n",nextArg); showHelp(traceOut); - return 0; + return ZCFG_BAD_ARGS; } else { break; } @@ -1686,12 +1686,12 @@ static int simpleMain(int argc, char **argv){ if (schemaList == NULL){ fprintf(traceOut,"Must specify schema list with at least one schema"); showHelp(traceOut); - return 0; + return ZCFG_BAD_JSON_SCHEMA; } if (configPath == NULL){ fprintf(traceOut,"Must specify config path\n"); showHelp(traceOut); - return 0; + return ZCFG_BAD_CONFIG_PATH; } ConfigManager *mgr = makeConfigManager(); @@ -1702,7 +1702,7 @@ static int simpleMain(int argc, char **argv){ int schemaLoadStatus = cfgLoadSchemas(mgr,configName,schemaList); if (schemaLoadStatus){ fprintf(traceOut,"Failed to load schemas rsn=%d\n",schemaLoadStatus); - return 0; + return schemaLoadStatus; } if (parmlibMemberName != NULL){ cfgSetParmlibMemberName(mgr,configName,parmlibMemberName); @@ -1711,7 +1711,7 @@ static int simpleMain(int argc, char **argv){ int configPathStatus = cfgSetConfigPath(mgr,configName,configPath); if (configPathStatus){ fprintf(traceOut,"Problems with config path rsn=%d\n",configPathStatus); - return 0; + return configPathStatus; } trace(mgr,DEBUG,"ConfigMgr built at 0x%p\n",mgr); @@ -1720,7 +1720,7 @@ static int simpleMain(int argc, char **argv){ if (argx >= argc){ printf("\n *** No Command Seen ***\n\n"); showHelp(traceOut); - return 0; + return ZCFG_BAD_ARGS; } command = argv[argx++]; trace(mgr,DEBUG,"command = %s\n",command); @@ -1730,7 +1730,7 @@ static int simpleMain(int argc, char **argv){ int loadStatus = cfgLoadConfiguration(mgr,configName); if (loadStatus){ trace(mgr,INFO,"Failed to load configuration, element may be bad, or less likey a bad merge\n"); - return 0; + return loadStatus; } trace(mgr,DEBUG,"configuration parms are loaded\n"); if (!strcmp(command,"validate")){ /* just a testing mode */ @@ -1744,21 +1744,25 @@ static int simpleMain(int argc, char **argv){ switch (validateStatus){ case JSON_VALIDATOR_NO_EXCEPTIONS: trace(mgr,INFO,"No validity Exceptions\n"); + return ZCFG_SUCCESS; break; case JSON_VALIDATOR_HAS_EXCEPTIONS: { trace(mgr,INFO,"Validity Exceptions:\n"); traceValidityException(mgr,0,validator->topValidityException); } + return ZCFG_CONFIG_FAILED_VALIDATION; break; case JSON_VALIDATOR_INTERNAL_FAILURE: trace(mgr,INFO,"validation internal failure"); + return ZCFG_VALIDATION_INTERNAL_ERROR; break; } freeJsonValidator(validator); } else if (!strcmp(command,"jq")){ if (argx >= argc){ trace(mgr,INFO,"jq requires at least one filter argument"); + return ZCFG_BAD_ARGS; } else { JQTokenizer jqt; memset(&jqt,0,sizeof(JQTokenizer)); @@ -1773,20 +1777,23 @@ static int simpleMain(int argc, char **argv){ int evalStatus = evalJQ(cfgGetConfigData(mgr,configName),jqTree,stdout,flags,mgr->traceLevel); if (evalStatus != 0){ trace(mgr, INFO,"micro jq eval problem %d\n",evalStatus); + return evalStatus; } } else { trace(mgr, INFO, "Failed to parse jq expression\n"); + return ZCFG_JQ_PARSE_ERROR; } } } else if (!strcmp(command,"extract")){ if (argx >= argc){ trace(mgr,INFO,"extract command requires a json path\n"); + return ZCFG_BAD_ARGS; } else { char *path = argv[argx++]; JsonPointer *jp = parseJsonPointer(path); if (jp == NULL){ trace(mgr,INFO,"Could not parse JSON pointer '%s'\n",path); - return 0; + return ZCFG_POINTER_PARSE_ERROR; } if (mgr->traceLevel >= 1){ printJsonPointer(mgr->traceOut,jp); @@ -1799,6 +1806,7 @@ static int simpleMain(int argc, char **argv){ } else if (!strcmp(command, "env")) { if (argx >= argc){ trace(mgr, INFO, "env command requires an env file path\n"); + return ZCFG_BAD_ARGS; } else { char *outputPath = argv[argx++]; Json *config = cfgGetConfigData(mgr,configName); @@ -1808,10 +1816,11 @@ static int simpleMain(int argc, char **argv){ fclose(out); } else { trace (mgr, INFO, "failed to open output file '%s' - %s\n", outputPath, strerror(errno)); + return ZCFG_IO_ERROR; } } } - return 0; + return ZCFG_SUCCESS; } /* a diagnostic function that can be used if other logging initialization bugs come up */ diff --git a/c/embeddedjs.c b/c/embeddedjs.c index 18a22fb17..ebee05c53 100644 --- a/c/embeddedjs.c +++ b/c/embeddedjs.c @@ -660,6 +660,61 @@ static int writeFully(char *filename, const char *data, int length){ } } +static int appendToFile(char *filename, const char *data, int length) { + FILE *out = fopen(filename, "a"); + if (!out){ + return errno; + } + int res = fwrite(data, 1, length, out); + if (res != length){ + fclose(out); + return -1; + } else { + fclose(out); + return 0; + } +} + +/* (filename, ccsid) ccsid -1 implies guess best for platform, 0 implies don't translate */ +static JSValue xplatformAppendFileUTF8(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv){ + size_t size; + size_t length; + + NATIVE_STR(filename,nativeFilename,0); + if (!filename){ + return JS_EXCEPTION; + } + + int targetCCSID; + JS_ToInt32(ctx, &targetCCSID, argv[1]); + + size_t cLen; + const char *content = JS_ToCStringLen(ctx, &cLen, argv[2]); + if (!content){ + return JS_EXCEPTION; + } + + if (targetCCSID < 0){ + char *nativeContent = safeMalloc(cLen+1,"xplatformAppendFileUtf8"); + memcpy(nativeContent,content,cLen); + nativeContent[cLen] = 0; + convertToNative(nativeContent,cLen); + int status = appendToFile(nativeFilename,(const char *)nativeContent,cLen); + JS_FreeCString(ctx, filename); + safeFree(nativeContent,cLen+1); + return JS_NewInt64(ctx,(int64_t)status); + } else if (targetCCSID == 0) { + int status = appendToFile(nativeFilename,content,cLen); + JS_FreeCString(ctx, filename); + return JS_NewInt64(ctx,(int64_t)status); + } else { + printf("string from specific encoding not yet implemented\n"); + return JS_EXCEPTION; + } + +} + /* (filename, ccsid) ccsid -1 implies guess best for platform, 0 implies don't translate */ static JSValue xplatformStoreFileUTF8(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ @@ -724,6 +779,7 @@ static char AUTO_DETECT_ASCII[12] = {0x41, 0x55, 0x54, 0x4f, 0x5f, 0x44, 0x45, 0 static char NO_CONVERT_ASCII[11] = {0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x56, 0x45, 0x52, 0x54, 0x00 }; static char loadFileUTF8ASCII[13] = {0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x55, 0x54, 0x46, 0x38, 0x00 }; static char storeFileUTF8ASCII[14] = {0x73, 0x74, 0x6f, 0x72, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x55, 0x54, 0x46, 0x38, 0x00 }; +static char appendFileUTF8ASCII[15] = {0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x55, 0x54, 0x46, 0x38, 0x00 }; static char tcpPingASCII[8] ={0x74, 0x63, 0x70, 0x50, 0x69, 0x6e, 0x67, 0x00}; static const JSCFunctionListEntry xplatformFunctions[] = { @@ -733,6 +789,7 @@ static const JSCFunctionListEntry xplatformFunctions[] = { JS_CFUNC_DEF(stringFromBytesASCII, 4, xplatformStringFromBytes), JS_CFUNC_DEF(loadFileUTF8ASCII, 2, xplatformLoadFileUTF8), JS_CFUNC_DEF(storeFileUTF8ASCII, 3, xplatformStoreFileUTF8), + JS_CFUNC_DEF(appendFileUTF8ASCII, 3, xplatformAppendFileUTF8), JS_CFUNC_DEF(getpidASCII, 0, xplatformGetpid), JS_PROP_INT32_DEF(AUTO_DETECT_ASCII, -1, JS_PROP_CONFIGURABLE ), JS_PROP_INT32_DEF(NO_CONVERT_ASCII, -1, JS_PROP_CONFIGURABLE ), diff --git a/h/configmgr.h b/h/configmgr.h index 008233302..303c4ffaa 100644 --- a/h/configmgr.h +++ b/h/configmgr.h @@ -31,6 +31,7 @@ typedef struct ConfigManager_tag{ #define JSON_POINTER_TOO_DEEP 101 #define JSON_POINTER_ARRAY_INDEX_NOT_INTEGER 102 #define JSON_POINTER_ARRAY_INDEX_OUT_OF_BOUNDS 103 +#define JSON_POINTER_PARSE_ERROR 104 /* These eventually need ZWE unique messages */ #define ZCFG_SUCCESS 0 @@ -45,9 +46,17 @@ typedef struct ConfigManager_tag{ #define ZCFG_BAD_TRACE_LEVEL 9 #define ZCFG_UNKNOWN_REXX_FUNCTION 10 #define ZCFG_NO_CONFIG_DATA 11 +#define ZCFG_BAD_ARGS 12 +#define ZCFG_IO_ERROR 13 +#define ZCFG_VALIDATION_INTERNAL_ERROR 14 +#define ZCFG_JQ_PARSE_ERROR 15 +/* Normal way to tell people the program succeded but their config is bad */ +#define ZCFG_CONFIG_FAILED_VALIDATION 99 + #define ZCFG_POINTER_TOO_DEEP JSON_POINTER_TOO_DEEP #define ZCFG_POINTER_ARRAY_INDEX_NOT_INTEGER JSON_POINTER_ARRAY_INDEX_NOT_INTEGER #define ZCFG_POINTER_ARRAY_INDEX_OUT_OF_BOUNDS JSON_POINTER_ARRAY_INDEX_OUT_OF_BOUNDS +#define ZCFG_POINTER_PARSE_ERROR JSON_POINTER_PARSE_ERROR ConfigManager *makeConfigManager(void);