mirror of
https://github.com/Unidata/netcdf-c.git
synced 2025-02-17 16:50:18 +08:00
Fix shell handling of escapes
re: https://github.com/Unidata/netcdf-c/issues/1988 There was an issue with certain shell programs (bash notably). For certain platforms and when given a url that had an escaped '#' character (e.g. \\#) bash would not remove the backslash. So I had to add a hack for this. Unfortunately I overdid it and it removed all '' characters. This is ok for non-windows platforms, but obviously fails for windows. The fix is this. 1. In a utility program (ncgen, ncdump, nccopy, etc) there is probably a call (or calls) to NC_backslashUnescape(xxx) where xxx is a path argument from the command line. 2. Replace each such call with NC_shellUnescape(xxx). The NC_shellUnescape function was added and searched only for occurrences of "\#" and replaces them with "#".
This commit is contained in:
parent
67c640f1b8
commit
efd1be5d62
@ -168,5 +168,6 @@ EXTERNL void printutf8hex(const char* s, char* sx);
|
||||
/* From dutil.c */
|
||||
EXTERNL char* NC_backslashEscape(const char* s);
|
||||
EXTERNL char* NC_backslashUnescape(const char* esc);
|
||||
EXTERNL char* NC_shellUnescape(const char* esc);
|
||||
|
||||
#endif /* _NCPATHMGR_H_ */
|
||||
|
@ -164,6 +164,37 @@ NC_entityescape(const char* s)
|
||||
return escaped;
|
||||
}
|
||||
|
||||
char*
|
||||
/*
|
||||
Depending on the platform, the shell will sometimes
|
||||
pass an escaped octotherpe character without removing
|
||||
the backslash. So this function is appropriate to be called
|
||||
on possible url paths to unescape such cases. See e.g. ncgen.
|
||||
*/
|
||||
NC_shellUnescape(const char* esc)
|
||||
{
|
||||
size_t len;
|
||||
char* s;
|
||||
const char* p;
|
||||
char* q;
|
||||
|
||||
if(esc == NULL) return NULL;
|
||||
len = strlen(esc);
|
||||
s = (char*)malloc(len+1);
|
||||
if(s == NULL) return NULL;
|
||||
for(p=esc,q=s;*p;) {
|
||||
switch (*p) {
|
||||
case '\\':
|
||||
if(p[1] == '#')
|
||||
p++;
|
||||
/* fall thru */
|
||||
default: *q++ = *p++; break;
|
||||
}
|
||||
}
|
||||
*q = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
Wrap mktmp and return the generated path,
|
||||
or null if failed.
|
||||
@ -371,3 +402,4 @@ int isnan(double x)
|
||||
}
|
||||
|
||||
#endif /*APPLE*/
|
||||
|
||||
|
@ -2412,8 +2412,8 @@ main(int argc, char**argv)
|
||||
error("one input file and one output file required");
|
||||
}
|
||||
/* Canonicalize the input and output files names */
|
||||
inputfile = NC_backslashUnescape(argv[0]); /* Remove shell added escapes */
|
||||
outputfile = NC_backslashUnescape(argv[1]);
|
||||
inputfile = NC_shellUnescape(argv[0]); /* Remove shell added escapes */
|
||||
outputfile = NC_shellUnescape(argv[1]);
|
||||
if(strcmp(inputfile, outputfile) == 0) {
|
||||
error("output would overwrite input");
|
||||
}
|
||||
|
@ -2335,7 +2335,7 @@ main(int argc, char *argv[])
|
||||
|
||||
/* We need to look for escape characters because the argument
|
||||
may have come in via a shell script */
|
||||
path = NC_backslashUnescape(argv[i]);
|
||||
path = NC_shellUnescape(argv[i]);
|
||||
if(path == NULL) {
|
||||
snprintf(errmsg,sizeof(errmsg),"out of memory un-escaping argument %s", argv[i]);
|
||||
goto fail;
|
||||
|
@ -351,7 +351,7 @@ main(
|
||||
break;
|
||||
case 'o': /* to explicitly specify output name */
|
||||
if(netcdf_name) efree(netcdf_name);
|
||||
netcdf_name = NC_backslashUnescape(optarg);
|
||||
netcdf_name = NC_shellUnescape(optarg);
|
||||
break;
|
||||
case 'P': /* diskless with persistence */
|
||||
diskless = 1;
|
||||
@ -460,7 +460,7 @@ main(
|
||||
}
|
||||
}
|
||||
|
||||
cdlname = NC_backslashUnescape(argv[0]);
|
||||
cdlname = NC_shellUnescape(argv[0]);
|
||||
if(cdlname != NULL) {
|
||||
if(strlen(cdlname) > NC_MAX_NAME)
|
||||
cdlname[NC_MAX_NAME] = '\0';
|
||||
|
@ -485,7 +485,7 @@ main(int argc, char** argv)
|
||||
}
|
||||
|
||||
{
|
||||
char* s = NC_backslashUnescape(argv[0]);
|
||||
char* s = NC_shellUnescape(argv[0]);
|
||||
strcpy(format.file_name,filenamefor(s));
|
||||
nullfree(s);
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ main(int argc, char** argv)
|
||||
dumpoptions.nctype = typefor(optarg);
|
||||
break;
|
||||
case 'u': {
|
||||
char* p = NC_backslashUnescape(optarg);
|
||||
char* p = NC_shellUnescape(optarg);
|
||||
ncuriparse(p,&dumpoptions.url);
|
||||
nullfree(p);
|
||||
if(dumpoptions.url == NULL) {
|
||||
|
@ -129,7 +129,7 @@ getoptions(int* argcp, char*** argvp)
|
||||
*argvp += optind;
|
||||
|
||||
if(*argcp > 0) {
|
||||
char* p = NC_backslashUnescape((*argvp)[0]);
|
||||
char* p = NC_shellUnescape((*argvp)[0]);
|
||||
strcpy(options->file,filenamefor(p));
|
||||
nullfree(p);
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ main(int argc, char** argv)
|
||||
}
|
||||
|
||||
{
|
||||
char* p = NC_backslashUnescape(argv[0]);
|
||||
char* p = NC_shellUnescape(argv[0]);
|
||||
strcpy(dumpoptions.infile,filenamefor(p));
|
||||
if(p) free(p);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ typedef struct Test {
|
||||
static Test PATHTESTS[] = {
|
||||
{"/xxx/a/b",{"/xxx/a/b", "/c/xxx/a/b", "/cygdrive/c/xxx/a/b", "c:\\xxx\\a\\b"}},
|
||||
{"d:/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
|
||||
{"d:\\x\\y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
|
||||
{"/cygdrive/d/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
|
||||
{"/d/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
|
||||
{"/cygdrive/d",{ "/d", "/d", "/cygdrive/d", "d:"}},
|
||||
@ -38,6 +39,7 @@ static Test PATHTESTS[] = {
|
||||
"d:\\git\\netcdf-c\\dap4_test\\test_anon_dim.2.syn"}},
|
||||
/* Test relative path */
|
||||
{"x/y",{ "x/y", "x/y", "x/y", "x\\y"}},
|
||||
{"x\\y",{ "x/y", "x/y", "x/y", "x\\y"}},
|
||||
#ifndef _WIN32
|
||||
/* Test utf8 path */
|
||||
{"/海/海",{ "/海/海", "/c/海/海", "/cygdrive/c/海/海", "c:\\海\\海"}},
|
||||
@ -54,6 +56,7 @@ main(int argc, char** argv)
|
||||
Test* test;
|
||||
int failcount = 0;
|
||||
char* cvt = NULL;
|
||||
char* unescaped = NULL;
|
||||
int k;
|
||||
int drive = 'c';
|
||||
|
||||
@ -71,7 +74,9 @@ main(int argc, char** argv)
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
cvt = NCpathcvt_test(test->test,kind,drive);
|
||||
/* ensure that NC_shellUnescape does not affect result */
|
||||
unescaped = NC_shellUnescape(test->test);
|
||||
cvt = NCpathcvt_test(unescaped,kind,drive);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"TEST local=%s: input: |%s| expected=|%s| actual=|%s|: ",
|
||||
kind2string(kind),test->test,test->expected[k],cvt);
|
||||
@ -95,10 +100,11 @@ main(int argc, char** argv)
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"\n");
|
||||
#endif
|
||||
nullfree(unescaped); unescaped = NULL;
|
||||
nullfree( cvt); cvt = NULL;
|
||||
}
|
||||
}
|
||||
nullfree(cvt);
|
||||
nullfree(cvt); nullfree(unescaped);
|
||||
fprintf(stderr,"%s test_pathcvt\n",failcount > 0 ? "***FAIL":"***PASS");
|
||||
nc_finalize();
|
||||
return (failcount > 0 ? 1 : 0);
|
||||
|
Loading…
Reference in New Issue
Block a user