diff options
| author | Edward Thomson <ethomson@microsoft.com> | 2014-11-25 18:13:00 -0500 |
|---|---|---|
| committer | Edward Thomson <ethomson@microsoft.com> | 2014-12-17 14:58:58 -0600 |
| commit | 9db49cce076229f5dbd0470a419888bb7b7a5511 (patch) | |
| tree | 58d74cba5a9c19dd9b299b936c3071e927900b76 /src/win32 | |
| parent | a4bb75aabb6bc440785e0af273ff255bc4b77336 (diff) | |
| download | libgit2-9db49cce076229f5dbd0470a419888bb7b7a5511.tar.gz | |
checkout: disallow bad paths on win32
Disallow:
1. paths with trailing dot
2. paths with trailing space
3. paths with trailing colon
4. paths that are 8.3 short names of .git folders ("GIT~1")
5. paths that are reserved path names (COM1, LPT1, etc).
6. paths with reserved DOS characters (colons, asterisks, etc)
These paths would (without \\?\ syntax) be elided to other paths - for
example, ".git." would be written as ".git". As a result, writing these
paths literally (using \\?\ syntax) makes them hard to operate with from
the shell, Windows Explorer or other tools. Disallow these.
Diffstat (limited to 'src/win32')
| -rw-r--r-- | src/win32/path_w32.c | 36 | ||||
| -rw-r--r-- | src/win32/path_w32.h | 15 |
2 files changed, 51 insertions, 0 deletions
diff --git a/src/win32/path_w32.c b/src/win32/path_w32.c index f0eacaa63..d66969c4d 100644 --- a/src/win32/path_w32.c +++ b/src/win32/path_w32.c @@ -267,3 +267,39 @@ int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src) return len; } + +char *git_win32_path_8dot3_name(const char *path) +{ + git_win32_path longpath, shortpath; + wchar_t *start; + char *shortname; + int len, namelen = 1; + + if (git_win32_path_from_utf8(longpath, path) < 0) + return NULL; + + len = GetShortPathNameW(longpath, shortpath, GIT_WIN_PATH_UTF16); + + while (len && shortpath[len-1] == L'\\') + shortpath[--len] = L'\0'; + + if (len == 0 || len >= GIT_WIN_PATH_UTF16) + return NULL; + + for (start = shortpath + (len - 1); + start > shortpath && *(start-1) != '/' && *(start-1) != '\\'; + start--) + namelen++; + + /* We may not have actually been given a short name. But if we have, + * it will be in the ASCII byte range, so we don't need to worry about + * multi-byte sequences and can allocate naively. + */ + if (namelen > 12 || (shortname = git__malloc(namelen + 1)) == NULL) + return NULL; + + if ((len = git__utf16_to_8(shortname, namelen + 1, start)) < 0) + return NULL; + + return shortname; +} diff --git a/src/win32/path_w32.h b/src/win32/path_w32.h index dc7a68e59..1d10166e8 100644 --- a/src/win32/path_w32.h +++ b/src/win32/path_w32.h @@ -26,6 +26,11 @@ */ #define GIT_WIN_PATH_UTF8 (259 * 3 + 1) +/* + * The length of a Windows "shortname", for 8.3 compatibility. + */ +#define GIT_WIN_PATH_SHORTNAME 13 + /* Win32 path types */ typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; typedef char git_win32_utf8_path[GIT_WIN_PATH_UTF8]; @@ -62,4 +67,14 @@ extern int git_win32_path_canonicalize(git_win32_path path); */ extern int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src); +/** + * Get the short name for the terminal path component in the given path. + * For example, given "C:\Foo\Bar\Asdf.txt", this will return the short name + * for the file "Asdf.txt". + * + * @param path The given path in UTF-8 + * @return The name of the shortname for the given path + */ +extern char *git_win32_path_8dot3_name(const char *path); + #endif |
