summaryrefslogtreecommitdiff
path: root/vms
diff options
context:
space:
mode:
authorCraig A. Berry <craigberry@mac.com>2012-12-02 15:17:55 -0600
committerCraig A. Berry <craigberry@mac.com>2012-12-02 15:17:55 -0600
commitc1abd561a0a322ca22ba5ef8301a708c37336afb (patch)
tree00daa9b60c3aefb13ec0143b1ed50175141bd49f /vms
parenta84b1d1f981773674baedc3f054c82b3243c6136 (diff)
downloadperl-c1abd561a0a322ca22ba5ef8301a708c37336afb.tar.gz
Better escaping of dots in tovmsspec.
When converting a filename with multiple dots to native VMS syntax, it's necessary to escape all but the last dot with a caret ('^'). We've been doing this for some time, but have been doing it blindly such that multiple trips through the converter resulted in a stuttering caret problem (e.g., foo^^^.bar.pl when foo^.bar.pl was intended). So create a convenience macro that does the escaping and make it only escape unescaped instances and also make it check that the escape doesn't push us off the end of the buffer we are working on. Use the new macro in the three most obvious places that it's applicable. There may be other places that also should use it.
Diffstat (limited to 'vms')
-rw-r--r--vms/vms.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/vms/vms.c b/vms/vms.c
index 38c4ff1a23..43496efcfe 100644
--- a/vms/vms.c
+++ b/vms/vms.c
@@ -8248,7 +8248,20 @@ int utf8_flag;
return result;
}
-
+/* A convenience macro for escaping dots that haven't already been
+ * escaped, with guards to avoid checking before the start of the
+ * buffer or advancing beyond the end of it (allowing room for the
+ * NUL terminator).
+ */
+#define VMSEFS_ESCAPE_DOT(vmsefsdot,vmsefsbuf,vmsefsbufsiz) STMT_START { \
+ if ( ((vmsefsdot) > (vmsefsbuf) && *((vmsefsdot) - 1) != '^' \
+ || ((vmsefsdot) == (vmsefsbuf))) \
+ && (vmsefsdot) < (vmsefsbuf) + (vmsefsbufsiz) - 2 \
+ ) { \
+ *((vmsefsdot)++) = '^'; \
+ *((vmsefsdot)++) = '.'; \
+ } \
+} STMT_END
/*{{{ char *tovmsspec[_ts](char *path, char *buf, int * utf8_flag)*/
static char *int_tovmsspec
@@ -8536,8 +8549,7 @@ static char *int_tovmsspec
if (decc_efs_charset == 0)
*(cp1++) = '_'; /* fix up syntax - '.' in name not allowed */
else {
- *(cp1++) = '^'; /* fix up syntax - '.' in name is allowed */
- *(cp1++) = '.';
+ VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
}
}
}
@@ -8547,8 +8559,7 @@ static char *int_tovmsspec
if (decc_efs_charset == 0)
*(cp1++) = '_';
else {
- *(cp1++) = '^';
- *(cp1++) = '.';
+ VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
}
}
else *(cp1++) = *cp2;
@@ -8578,8 +8589,7 @@ static char *int_tovmsspec
case '.':
if (((cp2 < lastdot) || (cp2[1] == '\0')) &&
decc_readdir_dropdotnotype) {
- *(cp1)++ = '^';
- *(cp1)++ = '.';
+ VMSEFS_ESCAPE_DOT(cp1, rslt, VMS_MAXRSS);
cp2++;
/* trailing dot ==> '^..' on VMS */