summaryrefslogtreecommitdiff
path: root/src/win32
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@microsoft.com>2014-11-25 18:13:00 -0500
committerEdward Thomson <ethomson@microsoft.com>2014-12-17 14:58:58 -0600
commit9db49cce076229f5dbd0470a419888bb7b7a5511 (patch)
tree58d74cba5a9c19dd9b299b936c3071e927900b76 /src/win32
parenta4bb75aabb6bc440785e0af273ff255bc4b77336 (diff)
downloadlibgit2-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.c36
-rw-r--r--src/win32/path_w32.h15
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