From d8b26529700b77b8327194172805a0eb1e995720 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Tue, 6 Feb 2024 09:23:49 -0500 Subject: [PATCH 01/10] Treat special chars Signed-off-by: Martin Zeithaml --- bin/libs/configmgr.ts | 3 ++- bin/libs/string.ts | 13 +++++++++++++ bin/libs/zos-dataset.ts | 16 ++++++++-------- bin/libs/zos.ts | 2 +- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/bin/libs/configmgr.ts b/bin/libs/configmgr.ts index ba16685f1e..e9a4112d38 100644 --- a/bin/libs/configmgr.ts +++ b/bin/libs/configmgr.ts @@ -14,6 +14,7 @@ import * as os from 'cm_os'; import * as xplatform from 'xplatform'; import { ConfigManager } from 'Configuration'; import * as fs from './fs'; +import * as stringlib from './string'; import * as objUtils from '../utils/ObjUtils'; @@ -415,7 +416,7 @@ function getMemberNameFromConfigPath(configPath: string): string|undefined { function stripMemberName(configPath: string, memberName: string): string { //Turn PARMLIB(my.zowe(yaml)):PARMLIB(my.other.zowe(yaml)) //Into PARMLIB(my.zowe):FILE(/some/path.yaml):PARMLIB(my.other.zowe) - const replacer = new RegExp('\\('+memberName+'\\)\\)', 'gi'); + const replacer = new RegExp('\\('+stringlib.escapeRegExp(memberName)+'\\)\\)', 'gi'); return configPath.replace(replacer, ")"); } diff --git a/bin/libs/string.ts b/bin/libs/string.ts index 7fa5c6020f..20acafbf6d 100644 --- a/bin/libs/string.ts +++ b/bin/libs/string.ts @@ -344,3 +344,16 @@ export function itemInList(stringList: string, stringToFind?: string, separator: } return stringList.split(separator).includes(stringToFind); } + +export function escapeDollar(str: string): string | undefined { + if (str === null || str === undefined) + return undefined; + return str.replace(/[$]/g, '\\$&'); +} + +export function escapeRegExp(str: string): string | undefined { + if (str === null || str === undefined) + return undefined; + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + diff --git a/bin/libs/zos-dataset.ts b/bin/libs/zos-dataset.ts index c1960ec929..295afc8d05 100644 --- a/bin/libs/zos-dataset.ts +++ b/bin/libs/zos-dataset.ts @@ -18,7 +18,7 @@ import * as shell from './shell'; import * as zoslib from './zos'; export function isDatasetExists(datasetName: string): boolean { - const result = shell.execSync('sh', '-c', `cat "//'${datasetName}'" 1>/dev/null 2>&1`); + const result = shell.execSync('sh', '-c', `cat "//'${stringlib.escapeDollar(datasetName)}'" 1>/dev/null 2>&1`); return result.rc === 0; } @@ -27,7 +27,7 @@ export function isDatasetExists(datasetName: string): boolean { // 1: data set is not in catalog // 2: data set member doesn't exist export function tsoIsDatasetExists(datasetName: string): number { - const result = zoslib.tsoCommand(`listds '${datasetName}' label`); + const result = zoslib.tsoCommand(`listds '${stringlib.escapeDollar(datasetName)}' label`); if (result.rc != 0) { if (result.out.includes('NOT IN CATALOG')) { return 1; @@ -44,7 +44,7 @@ export function tsoIsDatasetExists(datasetName: string): number { } export function createDataSet(dsName: string, dsOptions: string): number { - const result=zoslib.tsoCommand(`ALLOCATE NEW DA('${dsName}') ${dsOptions}`); + const result=zoslib.tsoCommand(`ALLOCATE NEW DA('${stringlib.escapeDollar(dsName)}') ${dsOptions}`); return result.rc; } @@ -55,7 +55,7 @@ export function copyToDataset(filePath: string, dsName: string, cpOptions: strin } } - const cpCommand=`cp ${cpOptions} -v "${filePath}" "//'${dsName}'"`; + const cpCommand=`cp ${cpOptions} -v "${filePath}" "//'${stringlib.escapeDollar(dsName)}'"`; common.printDebug('- '+cpCommand); const result=shell.execOutSync('sh', '-c', `${cpCommand} 2>&1`); if (result.rc == 0) { @@ -79,7 +79,7 @@ export function datasetCopyToDataset(prefix: string, datasetFrom: string, datase } } - const cmd=`exec '${prefix}.${std.getenv('ZWE_PRIVATE_DS_SZWEEXEC')}(ZWEMCOPY)' '${datasetFrom} ${datasetTo}'`; + const cmd=`exec '${prefix}.${std.getenv('ZWE_PRIVATE_DS_SZWEEXEC')}(ZWEMCOPY)' '${stringlib.escapeDollar(datasetFrom)} ${stringlib.escapeDollar(datasetTo)}'`; const result = zoslib.tsoCommand(cmd); return result.rc; } @@ -128,7 +128,7 @@ export function listDatasetUser(datasetName: string): number { // 3: data set is in use // @output tso listds label output export function deleteDataset(dataset: string): number { - const cmd=`delete '${dataset}'`; + const cmd=`delete '${stringlib.escapeDollar(dataset)}'`; const result=zoslib.tsoCommand(cmd); if (result.rc != 0) { if (result.out.includes('NOT IN CATALOG')) { @@ -170,7 +170,7 @@ export function isDatasetSmsManaged(dataset: string): { rc: number, smsManaged?: // SMS flag is in `FORMAT 1 DSCB` section second line, after 780037 common.printTrace(`- Check if ${dataset} is SMS managed`); - const labelResult = zoslib.tsoCommand(`listds '${dataset}' label`); + const labelResult = zoslib.tsoCommand(`listds '${stringlib.escapeDollar(dataset)}' label`); const datasetLabel=labelResult.out; if (labelResult.rc == 0) { let formatIndex = datasetLabel.indexOf('--FORMAT 1 DSCB--'); @@ -212,7 +212,7 @@ export function isDatasetSmsManaged(dataset: string): { rc: number, smsManaged?: export function getDatasetVolume(dataset: string): { rc: number, volume?: string } { common.printTrace(`- Find volume of data set ${dataset}`); - const result = zoslib.tsoCommand(`listds '${dataset}'`); + const result = zoslib.tsoCommand(`listds '${stringlib.escapeDollar(dataset)}'`); if (result.rc == 0) { let volumesIndex = result.out.indexOf('--VOLUMES--'); let volume: string; diff --git a/bin/libs/zos.ts b/bin/libs/zos.ts index b49e81451b..8cc5dea000 100644 --- a/bin/libs/zos.ts +++ b/bin/libs/zos.ts @@ -16,7 +16,7 @@ import * as shell from './shell'; import * as stringlib from './string'; export function tsoCommand(...args:string[]): { rc: number, out: string } { - let message="tsocmd "+args.join(' '); + let message = "tsocmd " + '"' + args.join(' ') + '"'; common.printDebug('- '+message); //we echo at the end to avoid a configmgr quirk where trying to read stdout when empty can hang waiting for bytes const result = shell.execOutSync('sh', '-c', `${message} 2>&1 && echo '.'`); From 4bec72ec877ffd5065b278108e5e10c798139dd5 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Tue, 6 Feb 2024 10:08:58 -0500 Subject: [PATCH 02/10] Too many slashes Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/libs/zos-dataset.sh b/bin/libs/zos-dataset.sh index 16154681f5..18ebc5fade 100644 --- a/bin/libs/zos-dataset.sh +++ b/bin/libs/zos-dataset.sh @@ -75,7 +75,7 @@ copy_to_data_set() { allow_overwrite="${4}" if [ "${allow_overwrite}" != "true" ]; then - if [ "$(is_data_set_exists "//'${ds_name}'")" = "true" ]; then + if [ "$(is_data_set_exists "${ds_name}")" = "true" ]; then print_error_and_exit "Error ZWEL0133E: Data set ${ds_name} already exists" "" 133 fi fi @@ -105,7 +105,7 @@ data_set_copy_to_data_set() { allow_overwrite="${4}" if [ "${allow_overwrite}" != "true" ]; then - if [ "$(is_data_set_exists "//'${ds_to}'")" = "true" ]; then + if [ "$(is_data_set_exists "${ds_to}")" = "true" ]; then print_error_and_exit "Error ZWEL0133E: Data set ${ds_to} already exists" "" 133 fi fi From 686cd7967258f6d28692e2d7e214d9eb18baff9c Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Tue, 6 Feb 2024 10:30:58 -0500 Subject: [PATCH 03/10] Minor fixes Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.ts | 6 +++--- bin/libs/zwecli.sh | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/bin/libs/zos-dataset.ts b/bin/libs/zos-dataset.ts index 295afc8d05..912c35eb07 100644 --- a/bin/libs/zos-dataset.ts +++ b/bin/libs/zos-dataset.ts @@ -235,7 +235,7 @@ export function getDatasetVolume(dataset: string): { rc: number, volume?: string export function apfAuthorizeDataset(dataset: string): number { const result = isDatasetSmsManaged(dataset); if (result.rc) { - common.printError("Error ZWEL0134E: Failed to find SMS status of data set ${dataset}."); + common.printError(`Error ZWEL0134E: Failed to find SMS status of data set ${dataset}.`); return 134; } @@ -256,7 +256,7 @@ export function apfAuthorizeDataset(dataset: string): number { } } - const apfCmd="SETPROG APF,ADD,DSNAME=${dataset},${apfVolumeParam}" + const apfCmd=`SETPROG APF,ADD,DSNAME=${dataset},${apfVolumeParam}`; if (std.getenv('ZWE_CLI_PARAMETER_SECURITY_DRY_RUN') == "true") { common.printMessage("- Dry-run mode, security setup is NOT performed on the system."); common.printMessage(" Please apply this operator command manually:"); @@ -277,7 +277,7 @@ export function apfAuthorizeDataset(dataset: string): number { } export function createDatasetTmpMember(dataset: string, prefix: string='ZW'): string | null { - common.printTrace(` > create_data_set_tmp_member in ${dataset}`); + common.printTrace(` > createDatasetTmpMember in ${dataset}`); for (var i = 0; i < 100; i++) { let rnd=Math.floor(Math.random()*10000); diff --git a/bin/libs/zwecli.sh b/bin/libs/zwecli.sh index eb0e249a3c..0131c5ff5b 100755 --- a/bin/libs/zwecli.sh +++ b/bin/libs/zwecli.sh @@ -376,6 +376,9 @@ zwecli_inline_execute_command() { export ZWE_PRIVATE_CLI_IS_TOP_LEVEL_COMMAND=false + print_trace "- zwecli_inline_execute_command" + print_trace " * ${*}" + # process new command . "${ZWE_zowe_runtimeDirectory}/bin/zwe" From af0e6a000f73ecc123ac50023a849103bd21481e Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Wed, 7 Feb 2024 02:56:26 -0500 Subject: [PATCH 04/10] Switch ChangeTag to sh Signed-off-by: Martin Zeithaml --- bin/libs/zos-fs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/libs/zos-fs.ts b/bin/libs/zos-fs.ts index 99305bc4b9..d0c868cb8d 100644 --- a/bin/libs/zos-fs.ts +++ b/bin/libs/zos-fs.ts @@ -109,7 +109,7 @@ export function ensureFileEncoding(file: string, expectedSample: string, expecte } } common.printTrace(`- Remove encoding tag of ${file}.`); - zos.changeTag(file, 0); + shell.execSync('sh', '-c', `chtag -r "${file}"`); } else { common.printTrace(`- Failed to detect encoding of ${file}.`); } From dc66beb2d5578419de2f981dea90ad8796162151 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Thu, 8 Feb 2024 03:48:15 -0500 Subject: [PATCH 05/10] Regex update Signed-off-by: Martin Zeithaml --- bin/libs/configmgr.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/libs/configmgr.ts b/bin/libs/configmgr.ts index e9a4112d38..26c16fa89a 100644 --- a/bin/libs/configmgr.ts +++ b/bin/libs/configmgr.ts @@ -416,7 +416,7 @@ function getMemberNameFromConfigPath(configPath: string): string|undefined { function stripMemberName(configPath: string, memberName: string): string { //Turn PARMLIB(my.zowe(yaml)):PARMLIB(my.other.zowe(yaml)) //Into PARMLIB(my.zowe):FILE(/some/path.yaml):PARMLIB(my.other.zowe) - const replacer = new RegExp('\\('+stringlib.escapeRegExp(memberName)+'\\)\\)', 'gi'); + const replacer = new RegExp('\\('+stringlib.escapeDollar(memberName)+'\\)\\)', 'gi'); return configPath.replace(replacer, ")"); } From d1abd3e79a8204abd538d79aead5fc56997e21a5 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Thu, 8 Feb 2024 10:20:23 -0500 Subject: [PATCH 06/10] Revert changes Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/libs/zos-dataset.sh b/bin/libs/zos-dataset.sh index 18ebc5fade..16154681f5 100644 --- a/bin/libs/zos-dataset.sh +++ b/bin/libs/zos-dataset.sh @@ -75,7 +75,7 @@ copy_to_data_set() { allow_overwrite="${4}" if [ "${allow_overwrite}" != "true" ]; then - if [ "$(is_data_set_exists "${ds_name}")" = "true" ]; then + if [ "$(is_data_set_exists "//'${ds_name}'")" = "true" ]; then print_error_and_exit "Error ZWEL0133E: Data set ${ds_name} already exists" "" 133 fi fi @@ -105,7 +105,7 @@ data_set_copy_to_data_set() { allow_overwrite="${4}" if [ "${allow_overwrite}" != "true" ]; then - if [ "$(is_data_set_exists "${ds_to}")" = "true" ]; then + if [ "$(is_data_set_exists "//'${ds_to}'")" = "true" ]; then print_error_and_exit "Error ZWEL0133E: Data set ${ds_to} already exists" "" 133 fi fi From 0d461b6f8f35048e47e67ffef3fbe5f707727b41 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Fri, 9 Feb 2024 08:53:18 -0500 Subject: [PATCH 07/10] Get volume Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/libs/zos-dataset.ts b/bin/libs/zos-dataset.ts index 912c35eb07..f18fcde5ac 100644 --- a/bin/libs/zos-dataset.ts +++ b/bin/libs/zos-dataset.ts @@ -218,8 +218,7 @@ export function getDatasetVolume(dataset: string): { rc: number, volume?: string let volume: string; if (volumesIndex != -1) { let startIndex = volumesIndex + '--VOLUMES--'.length; - let endIndex = result.out.indexOf('--',startIndex); - volume = result.out.substring(startIndex, endIndex).trim(); + volume = result.out.substring(startIndex).trim(); } if (!volume) { common.printError(" * Failed to find volume information of the data set."); From f77aba55055821efd872d10b3d475ebc7a0358af Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Fri, 9 Feb 2024 10:41:43 -0500 Subject: [PATCH 08/10] Support '$' and '-' in ds name Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/libs/zos-dataset.ts b/bin/libs/zos-dataset.ts index f18fcde5ac..4e4528b5c2 100644 --- a/bin/libs/zos-dataset.ts +++ b/bin/libs/zos-dataset.ts @@ -91,7 +91,7 @@ export function datasetCopyToDataset(prefix: string, datasetFrom: string, datase // 1: there are some users // @output output of operator command "d grs" export function listDatasetUser(datasetName: string): number { - const cmd=`D GRS,RES=(*,${datasetName})`; + const cmd = `D GRS,RES=(*,'${stringlib.escapeDollar(datasetName)}')`; const result=zoslib.operatorCommand(cmd); return result.out.includes('NO REQUESTORS FOR RESOURCE') ? 0 : 1; // example outputs: From 406e1bc773a7c96b451f83a191e6eea40123f403 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Mon, 12 Feb 2024 05:28:41 -0500 Subject: [PATCH 09/10] Escape prefix Signed-off-by: Martin Zeithaml --- bin/libs/zos-dataset.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/libs/zos-dataset.ts b/bin/libs/zos-dataset.ts index 4e4528b5c2..74d10aed9e 100644 --- a/bin/libs/zos-dataset.ts +++ b/bin/libs/zos-dataset.ts @@ -79,7 +79,7 @@ export function datasetCopyToDataset(prefix: string, datasetFrom: string, datase } } - const cmd=`exec '${prefix}.${std.getenv('ZWE_PRIVATE_DS_SZWEEXEC')}(ZWEMCOPY)' '${stringlib.escapeDollar(datasetFrom)} ${stringlib.escapeDollar(datasetTo)}'`; + const cmd = `exec '${stringlib.escapeDollar(prefix)}.${std.getenv('ZWE_PRIVATE_DS_SZWEEXEC')}(ZWEMCOPY)' '${stringlib.escapeDollar(datasetFrom)} ${stringlib.escapeDollar(datasetTo)}'`; const result = zoslib.tsoCommand(cmd); return result.rc; } From e23727250b30f29973caa8d582041208ee3db187 Mon Sep 17 00:00:00 2001 From: Martin Zeithaml Date: Thu, 15 Feb 2024 10:07:20 -0500 Subject: [PATCH 10/10] Escape dataset in copyMvsToUss Signed-off-by: Martin Zeithaml --- bin/libs/zos-fs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/libs/zos-fs.ts b/bin/libs/zos-fs.ts index ec29d37c69..e0023a449f 100644 --- a/bin/libs/zos-fs.ts +++ b/bin/libs/zos-fs.ts @@ -87,7 +87,7 @@ export function detectFileEncoding(fileName: string, expectedSample: string, exp export function copyMvsToUss(dataset: string, file: string): number { common.printDebug(`copyMvsToUss dataset=${dataset}, file=${file}`); - const result = shell.execSync('sh', '-c', `cp "//'${dataset}'" "${file}"`); + const result = shell.execSync('sh', '-c', `cp "//'${stringlib.escapeDollar(dataset)}'" '${file}'`); return result.rc; }