diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-18 08:57:27 -0700 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2018-10-19 07:26:17 +0100 |
commit | a34f5b0db55ba2bd0080ccd8f08db157a76168a9 (patch) | |
tree | c148e881c50014ed089f7082783a4ae25578c18d | |
parent | 16fd9ba9379c0cbf0931f9486980353b5a28fda9 (diff) | |
download | libgit2-a34f5b0db55ba2bd0080ccd8f08db157a76168a9.tar.gz |
win32: refactor `git_win32_path_remove_namespace`ethomson/unc_paths
Update `git_win32_path_remove_namespace` to disambiguate the prefix
being removed versus the prefix being added. Now we remove the
"namespace", and (may) add a "prefix" in its place. Eg, we remove the
`\\?\` namespace. We remove the `\\?\UNC\` namespace, and replace it
with the `\\` prefix. This aids readability somewhat.
Additionally, use pointer arithmetic instead of offsets, which seems to
also help readability.
-rw-r--r-- | src/win32/path_w32.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/src/win32/path_w32.c b/src/win32/path_w32.c index 18dc81a33..b955b024c 100644 --- a/src/win32/path_w32.c +++ b/src/win32/path_w32.c @@ -418,46 +418,57 @@ size_t git_win32_path_trim_end(wchar_t *str, size_t len) */ size_t git_win32_path_remove_namespace(wchar_t *str, size_t len) { - static const wchar_t dosdevices_prefix[] = L"\\\?\?\\"; - static const wchar_t nt_prefix[] = L"\\\\?\\"; - static const wchar_t unc_prefix[] = L"UNC\\"; - static const wchar_t unc_canonicalized_prefix[] = L"\\\\"; + static const wchar_t dosdevices_namespace[] = L"\\\?\?\\"; + static const wchar_t nt_namespace[] = L"\\\\?\\"; + static const wchar_t unc_namespace_remainder[] = L"UNC\\"; + static const wchar_t unc_prefix[] = L"\\\\"; - size_t to_advance = 0; + const wchar_t *prefix = NULL, *remainder = NULL; + size_t prefix_len = 0, remainder_len = 0; /* "\??\" -- DOS Devices prefix */ - if (len >= CONST_STRLEN(dosdevices_prefix) && - !wcsncmp(str, dosdevices_prefix, CONST_STRLEN(dosdevices_prefix))) { - to_advance += CONST_STRLEN(dosdevices_prefix); - len -= CONST_STRLEN(dosdevices_prefix); + if (len >= CONST_STRLEN(dosdevices_namespace) && + !wcsncmp(str, dosdevices_namespace, CONST_STRLEN(dosdevices_namespace))) { + remainder = str + CONST_STRLEN(dosdevices_namespace); + remainder_len = len - CONST_STRLEN(dosdevices_namespace); } /* "\\?\" -- NT namespace prefix */ - else if (len >= CONST_STRLEN(nt_prefix) && - !wcsncmp(str, nt_prefix, CONST_STRLEN(nt_prefix))) { - to_advance += CONST_STRLEN(nt_prefix); - len -= CONST_STRLEN(nt_prefix); + else if (len >= CONST_STRLEN(nt_namespace) && + !wcsncmp(str, nt_namespace, CONST_STRLEN(nt_namespace))) { + remainder = str + CONST_STRLEN(nt_namespace); + remainder_len = len - CONST_STRLEN(nt_namespace); } /* "\??\UNC\", "\\?\UNC\" -- UNC prefix */ - if (to_advance && len >= CONST_STRLEN(unc_prefix) && - !wcsncmp(str + to_advance, unc_prefix, CONST_STRLEN(unc_prefix))) { + if (remainder_len >= CONST_STRLEN(unc_namespace_remainder) && + !wcsncmp(remainder, unc_namespace_remainder, CONST_STRLEN(unc_namespace_remainder))) { /* * The proper Win32 path for a UNC share has "\\" at beginning of it - * and looks like "\\server\share\<folderStructure>". - * So, remove the UNC prefix, but leave room for a "\\" + * and looks like "\\server\share\<folderStructure>". So remove the + * UNC namespace and add a prefix of "\\" in its place. */ - to_advance += (CONST_STRLEN(unc_prefix) - CONST_STRLEN(unc_canonicalized_prefix)); - len -= (CONST_STRLEN(unc_prefix) - CONST_STRLEN(unc_canonicalized_prefix)); + remainder += CONST_STRLEN(unc_namespace_remainder); + remainder_len -= CONST_STRLEN(unc_namespace_remainder); - /** - * Place a "\\" in the string so the result is "\\server\\share\<folderStructure>" - */ - memmove(str + to_advance, unc_canonicalized_prefix, CONST_STRLEN(unc_canonicalized_prefix) * sizeof(wchar_t)); + prefix = unc_prefix; + prefix_len = CONST_STRLEN(unc_prefix); } - if (to_advance) { - memmove(str, str + to_advance, len * sizeof(wchar_t)); + if (remainder) { + /* + * Sanity check that the new string isn't longer than the old one. + * (This could only happen due to programmer error introducing a + * prefix longer than the namespace it replaces.) + */ + assert(len >= remainder_len + prefix_len); + + if (prefix) + memmove(str, prefix, prefix_len * sizeof(wchar_t)); + + memmove(str + prefix_len, remainder, remainder_len * sizeof(wchar_t)); + + len = remainder_len + prefix_len; str[len] = L'\0'; } |