diff options
author | Daniel Molkentin <daniel@molkentin.de> | 2014-10-24 23:39:21 +0400 |
---|---|---|
committer | Daniel Molkentin <daniel@molkentin.de> | 2014-10-24 23:39:21 +0400 |
commit | d0b40bab4773d29e762be70e1ab2e0da6ee4e69a (patch) | |
tree | 5f43d98b8be7e53cd401319ed31ed89c6c2c7c1b | |
parent | 0e828d802e1e37d01bd6c1d53a20181f493b540c (diff) | |
parent | d76192cce12658d08122204df75c3c29b59895a5 (diff) |
Merge pull request #2391 from owncloud/ignore_windows_reserved_charactersv1.7.0-rc1
Ignore reserved words on Windows
-rw-r--r-- | csync/src/csync_exclude.c | 41 | ||||
-rw-r--r-- | csync/src/csync_exclude.h | 8 | ||||
-rw-r--r-- | csync/src/std/c_string.c | 8 | ||||
-rw-r--r-- | csync/src/std/c_string.h | 11 | ||||
-rw-r--r-- | csync/tests/csync_tests/check_csync_exclude.c | 20 |
5 files changed, 88 insertions, 0 deletions
diff --git a/csync/src/csync_exclude.c b/csync/src/csync_exclude.c index 0855b9829..f4500b9b1 100644 --- a/csync/src/csync_exclude.c +++ b/csync/src/csync_exclude.c @@ -156,6 +156,40 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype) { return match; } +// See http://support.microsoft.com/kb/74496 +static const char *win_reserved_words[] = {"CON","PRN","AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", + "LPT1", "LPT2", "LPT3", "CLOCK$" }; + + +bool csync_is_windows_reserved_word(const char* filename) { + + size_t win_reserve_words_len = sizeof(win_reserved_words) / sizeof(char*); + size_t j; + + for (j = 0; j < win_reserve_words_len; j++) { + int len_reserved_word = strlen(win_reserved_words[j]); + int len_filename = strlen(filename); + if (len_filename == 2 && filename[1] == ':') { + if (filename[0] >= 'a' && filename[0] <= 'z') { + return true; + } + if (filename[0] >= 'A' && filename[0] <= 'Z') { + return true; + } + } + if (c_strncasecmp(filename, win_reserved_words[j], len_reserved_word) == 0) { + if (len_filename == len_reserved_word) { + return true; + } + if ((len_filename > len_reserved_word) && (filename[len_reserved_word] == '.')) { + return true; + } + } + } + return false; +} + CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype) { size_t i = 0; const char *p = NULL; @@ -214,6 +248,13 @@ CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path SAFE_FREE(dname); goto out; } + + if (csync_is_windows_reserved_word(bname)) { + match = CSYNC_FILE_EXCLUDE_INVALID_CHAR; + SAFE_FREE(bname); + SAFE_FREE(dname); + goto out; + } #endif rc = csync_fnmatch(".owncloudsync.log*", bname, 0); diff --git a/csync/src/csync_exclude.h b/csync/src/csync_exclude.h index 84a65bef7..efc809f74 100644 --- a/csync/src/csync_exclude.h +++ b/csync/src/csync_exclude.h @@ -80,4 +80,12 @@ CSYNC_EXCLUDE_TYPE csync_excluded(CSYNC *ctx, const char *path, int filetype); CSYNC_EXCLUDE_TYPE csync_excluded_no_ctx(c_strlist_t *excludes, const char *path, int filetype); #endif /* _CSYNC_EXCLUDE_H */ +/** + * @brief Checks if filename is considered reserved by Windows + * @param file_name filename + * @return true if file is reserved, false otherwise + */ +bool csync_is_windows_reserved_word(const char *file_name); + + /* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */ diff --git a/csync/src/std/c_string.c b/csync/src/std/c_string.c index 9d2c087ec..f1ca5f747 100644 --- a/csync/src/std/c_string.c +++ b/csync/src/std/c_string.c @@ -134,6 +134,14 @@ static char *c_iconv(const char* str, enum iconv_direction dir) } #endif /* defined(HAVE_ICONV) && defined(WITH_ICONV) */ +int c_strncasecmp(const char *a, const char *b, size_t n) { +#ifdef _WIN32 + return _strnicmp(a, b, n); +#else + return strncasecmp(a, b, n); +#endif +} + int c_streq(const char *a, const char *b) { register const char *s1 = a; register const char *s2 = b; diff --git a/csync/src/std/c_string.h b/csync/src/std/c_string.h index d80727a63..920266c5c 100644 --- a/csync/src/std/c_string.h +++ b/csync/src/std/c_string.h @@ -60,6 +60,17 @@ struct c_strlist_s { }; /** + * @brief Compare to strings case insensitively. + * + * @param a First string to compare. + * @param b Second string to compare. + * @param n Max comparison length. + * + * @return see strncasecmp + */ +int c_strncasecmp(const char *a, const char *b, size_t n); + +/** * @brief Compare to strings if they are equal. * * @param a First string to compare. diff --git a/csync/tests/csync_tests/check_csync_exclude.c b/csync/tests/csync_tests/check_csync_exclude.c index 1d216eba0..94430eafc 100644 --- a/csync/tests/csync_tests/check_csync_exclude.c +++ b/csync/tests/csync_tests/check_csync_exclude.c @@ -174,6 +174,25 @@ static void check_csync_pathes(void **state) assert_int_equal(rc, CSYNC_NOT_EXCLUDED); } +static void check_csync_is_windows_reserved_word() { + assert_true(csync_is_windows_reserved_word("CON")); + assert_true(csync_is_windows_reserved_word("con")); + assert_true(csync_is_windows_reserved_word("CON.")); + assert_true(csync_is_windows_reserved_word("con.")); + assert_true(csync_is_windows_reserved_word("CON.ference")); + assert_false(csync_is_windows_reserved_word("CONference")); + assert_false(csync_is_windows_reserved_word("conference")); + assert_false(csync_is_windows_reserved_word("conf.erence")); + assert_false(csync_is_windows_reserved_word("co")); + assert_true(csync_is_windows_reserved_word("A:")); + assert_true(csync_is_windows_reserved_word("a:")); + assert_true(csync_is_windows_reserved_word("z:")); + assert_true(csync_is_windows_reserved_word("Z:")); + assert_true(csync_is_windows_reserved_word("M:")); + assert_true(csync_is_windows_reserved_word("m:")); + +} + int torture_run_tests(void) { const UnitTest tests[] = { @@ -181,6 +200,7 @@ int torture_run_tests(void) unit_test_setup_teardown(check_csync_exclude_load, setup, teardown), unit_test_setup_teardown(check_csync_excluded, setup_init, teardown), unit_test_setup_teardown(check_csync_pathes, setup_init, teardown), + unit_test_setup_teardown(check_csync_is_windows_reserved_word, setup_init, teardown), }; return run_tests(tests); |