# include <fcntl.h> /* _use_lfn(f) prototype */
#endif
-#ifndef UNITTESTS
+#ifdef MSDOS
+/* only used by msdosify() */
static SANITIZEcode truncate_dryrun(const char *path,
const size_t truncate_pos);
-#ifdef MSDOS
static SANITIZEcode msdosify(char **const sanitized, const char *file_name,
int flags);
#endif
-static SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
- const char *file_name,
- int flags);
-#endif /* !UNITTESTS (static declarations used if no unit tests) */
+static SANITIZEcode rename_if_reserved_dos(char **const sanitized,
+ const char *file_name,
+ int flags);
/*
Flags
-----
-SANITIZE_ALLOW_COLONS: Allow colons.
-Without this flag colons are sanitized.
-
SANITIZE_ALLOW_PATH: Allow path separators and colons.
Without this flag path separators and colons are sanitized.
Without this flag a reserved device name is renamed (COM1 => _COM1) unless it
is in a UNC prefixed path.
-SANITIZE_ALLOW_TRUNCATE: Allow truncating a long filename.
-Without this flag if the sanitized filename or path will be too long an error
-occurs. With this flag the filename --and not any other parts of the path-- may
-be truncated to at least a single character. A filename followed by an
-alternate data stream (ADS) cannot be truncated in any case.
-
Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
*/
if(!file_name)
return SANITIZE_ERR_BAD_ARGUMENT;
- if((flags & SANITIZE_ALLOW_PATH)) {
+ if(flags & SANITIZE_ALLOW_PATH) {
#ifndef MSDOS
if(file_name[0] == '\\' && file_name[1] == '\\')
/* UNC prefixed path \\ (eg \\?\C:\foo) */
max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1;
len = strlen(file_name);
- if(len > max_sanitized_len) {
- if(!(flags & SANITIZE_ALLOW_TRUNCATE) ||
- truncate_dryrun(file_name, max_sanitized_len))
- return SANITIZE_ERR_INVALID_PATH;
-
- len = max_sanitized_len;
- }
+ if(len > max_sanitized_len)
+ return SANITIZE_ERR_INVALID_PATH;
- target = malloc(len + 1);
+ target = strdup(file_name);
if(!target)
return SANITIZE_ERR_OUT_OF_MEMORY;
- strncpy(target, file_name, len);
- target[len] = '\0';
-
#ifndef MSDOS
if((flags & SANITIZE_ALLOW_PATH) && !strncmp(target, "\\\\?\\", 4))
/* Skip the literal path prefix \\?\ */
const char *banned;
if((1 <= *p && *p <= 31) ||
- (!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *p == ':') ||
+ (!(flags & SANITIZE_ALLOW_PATH) && *p == ':') ||
(!(flags & SANITIZE_ALLOW_PATH) && (*p == '/' || *p == '\\'))) {
*p = '_';
continue;
#endif
if(!(flags & SANITIZE_ALLOW_RESERVED)) {
- sc = rename_if_reserved_dos_device_name(&p, target, flags);
+ sc = rename_if_reserved_dos(&p, target, flags);
free(target);
if(sc)
return sc;
return SANITIZE_ERR_OK;
}
-
+#if defined(MSDOS)
/*
Test if truncating a path to a file will leave at least a single character in
the filename. Filenames suffixed by an alternate data stream cannot be
Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
*/
-#if defined(MSDOS) || defined(UNITTESTS)
SANITIZEcode msdosify(char **const sanitized, const char *file_name,
int flags)
{
if(!file_name)
return SANITIZE_ERR_BAD_ARGUMENT;
- if(strlen(file_name) > PATH_MAX-1 &&
- (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
- truncate_dryrun(file_name, PATH_MAX-1)))
+ if(strlen(file_name) > PATH_MAX-1)
return SANITIZE_ERR_INVALID_PATH;
/* Support for Windows 9X VFAT systems, when available. */
/* Get past the drive letter, if any. */
if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') {
*d++ = *s++;
- *d = ((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) ? ':' : '_';
+ *d = ((flags & SANITIZE_ALLOW_PATH)) ? ':' : '_';
++d; ++s;
}
for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) {
if(memchr(illegal_aliens, *s, len)) {
- if((flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH)) && *s == ':')
+ if((flags & SANITIZE_ALLOW_PATH) && *s == ':')
*d = ':';
else if((flags & SANITIZE_ALLOW_PATH) && (*s == '/' || *s == '\\'))
*d = *s;
/* dos_name is truncated, check that truncation requirements are met,
specifically truncating a filename suffixed by an alternate data stream
or truncating the entire filename is not allowed. */
- if(!(flags & SANITIZE_ALLOW_TRUNCATE) || strpbrk(s, "\\/:") ||
- truncate_dryrun(dos_name, d - dos_name))
+ if(strpbrk(s, "\\/:") || truncate_dryrun(dos_name, d - dos_name))
return SANITIZE_ERR_INVALID_PATH;
}
*sanitized = strdup(dos_name);
return (*sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY);
}
-#endif /* MSDOS || UNITTESTS */
+#endif /* MSDOS */
/*
Rename file_name if it is a reserved dos device name.
Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name.
Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL.
*/
-SANITIZEcode rename_if_reserved_dos_device_name(char **const sanitized,
- const char *file_name,
- int flags)
+static SANITIZEcode rename_if_reserved_dos(char **const sanitized,
+ const char *file_name,
+ int flags)
{
/* We could have a file whose name is a device on MS-DOS. Trying to
* retrieve such a file would fail at best and wedge us at worst. We need
#ifdef MSDOS
struct_stat st_buf;
#endif
+ size_t len;
- if(!sanitized)
+ if(!sanitized || !file_name)
return SANITIZE_ERR_BAD_ARGUMENT;
*sanitized = NULL;
-
- if(!file_name)
- return SANITIZE_ERR_BAD_ARGUMENT;
+ len = strlen(file_name);
/* Ignore UNC prefixed paths, they are allowed to contain a reserved name. */
#ifndef MSDOS
if((flags & SANITIZE_ALLOW_PATH) &&
file_name[0] == '\\' && file_name[1] == '\\') {
- size_t len = strlen(file_name);
- *sanitized = malloc(len + 1);
+ *sanitized = strdup(file_name);
if(!*sanitized)
return SANITIZE_ERR_OUT_OF_MEMORY;
- strncpy(*sanitized, file_name, len + 1);
return SANITIZE_ERR_OK;
}
#endif
- if(strlen(file_name) > PATH_MAX-1 &&
- (!(flags & SANITIZE_ALLOW_TRUNCATE) ||
- truncate_dryrun(file_name, PATH_MAX-1)))
+ if(len > PATH_MAX-1)
return SANITIZE_ERR_INVALID_PATH;
- strncpy(fname, file_name, PATH_MAX-1);
- fname[PATH_MAX-1] = '\0';
+ memcpy(fname, file_name, len);
+ fname[len] = '\0';
base = basename(fname);
/* Rename reserved device names that are known to be accessible without \\.\
continue;
}
else if(p[x] == ':') {
- if(!(flags & (SANITIZE_ALLOW_COLONS|SANITIZE_ALLOW_PATH))) {
+ if(!(flags & SANITIZE_ALLOW_PATH)) {
p[x] = '_';
continue;
}
p_len = strlen(p);
/* Prepend a '_' */
- if(strlen(fname) == PATH_MAX-1) {
- --p_len;
- if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(p, p_len))
- return SANITIZE_ERR_INVALID_PATH;
- p[p_len] = '\0';
- }
+ if(strlen(fname) == PATH_MAX-1)
+ return SANITIZE_ERR_INVALID_PATH;
memmove(p + 1, p, p_len + 1);
p[0] = '_';
++p_len;
/* Prepend a '_' */
size_t blen = strlen(base);
if(blen) {
- if(strlen(fname) == PATH_MAX-1) {
- --blen;
- if(!(flags & SANITIZE_ALLOW_TRUNCATE) || truncate_dryrun(base, blen))
- return SANITIZE_ERR_INVALID_PATH;
- base[blen] = '\0';
- }
+ if(strlen(fname) >= PATH_MAX-1)
+ return SANITIZE_ERR_INVALID_PATH;
memmove(base + 1, base, blen + 1);
base[0] = '_';
}
{
char *buf = malloc(256);
if(buf) {
- msnprintf(buf, 256, "%s,%s,%s,%s",
- ((flags & SANITIZE_ALLOW_COLONS) ?
- "SANITIZE_ALLOW_COLONS" : ""),
+ msnprintf(buf, 256, "%s,%s",
((flags & SANITIZE_ALLOW_PATH) ?
"SANITIZE_ALLOW_PATH" : ""),
((flags & SANITIZE_ALLOW_RESERVED) ?
- "SANITIZE_ALLOW_RESERVED" : ""),
- ((flags & SANITIZE_ALLOW_TRUNCATE) ?
- "SANITIZE_ALLOW_TRUNCATE" : ""));
+ "SANITIZE_ALLOW_RESERVED" : ""));
}
return buf;
}
{ "f:foo", 0,
"f_foo", SANITIZE_ERR_OK
},
- { "f:foo", SANITIZE_ALLOW_COLONS,
- "f:foo", SANITIZE_ERR_OK
- },
{ "f:foo", SANITIZE_ALLOW_PATH,
"f:foo", SANITIZE_ERR_OK
},
{ "f:\\com1", SANITIZE_ALLOW_RESERVED,
"f__com1", SANITIZE_ERR_OK
},
- { "f:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_COLONS,
- "f:_com1", SANITIZE_ERR_OK
- },
{ "f:\\com1", SANITIZE_ALLOW_RESERVED | SANITIZE_ALLOW_PATH,
"f:\\com1", SANITIZE_ERR_OK
},
/* At the moment we expect a maximum path length of 259. I assume MS-DOS
has variable max path lengths depending on compiler that are shorter
so currently these "good" truncate tests will not run on MS-DOS */
-#ifndef MSDOS
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE,
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFFFF", SANITIZE_ERR_OK
- },
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFF\\FFFFF", SANITIZE_ERR_OK
- },
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE,
- "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFF_F", SANITIZE_ERR_OK
- },
-#endif /* !MSDOS */
{ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
0,
NULL, SANITIZE_ERR_INVALID_PATH
},
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFFF\\FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE,
- NULL, SANITIZE_ERR_INVALID_PATH
- },
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFFFFFFFFFFFFFFFFFFFFFFFF\\FFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
- NULL, SANITIZE_ERR_INVALID_PATH
- },
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FFF\\FFFFFFFFFFFFFFFFFFFFF:FFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
- NULL, SANITIZE_ERR_INVALID_PATH
- },
- { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
- "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
- "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
- "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD"
- "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
- "FF\\F:FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- SANITIZE_ALLOW_TRUNCATE | SANITIZE_ALLOW_PATH,
- NULL, SANITIZE_ERR_INVALID_PATH
- },
{ NULL, 0,
NULL, SANITIZE_ERR_BAD_ARGUMENT
},