summaryrefslogtreecommitdiff
path: root/src/path.c
diff options
context:
space:
mode:
authorCarlos Martín Nieto <carlosmn@github.com>2018-05-16 14:47:04 +0200
committerCarlos Martín Nieto <carlosmn@github.com>2018-05-18 14:49:08 +0200
commit22973e099e85211470b6bc26c55d7cf9f7934079 (patch)
treeb84df1ba2c22333c11b055cb14ebcbca42e55959 /src/path.c
parent0283fc4697988d1067946e781066da5fc1397175 (diff)
downloadlibgit2-22973e099e85211470b6bc26c55d7cf9f7934079.tar.gz
path: provide a generic function for checking dogit files on NTFS
It checks against the 8.3 shortname variants, including the one which includes the checksum as part of its name.
Diffstat (limited to 'src/path.c')
-rw-r--r--src/path.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/path.c b/src/path.c
index e770e530b..8c548746e 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1621,6 +1621,59 @@ GIT_INLINE(bool) verify_dotgit_ntfs(git_repository *repo, const char *path, size
return false;
}
+GIT_INLINE(bool) only_spaces_and_dots(const char *path)
+{
+ const char *c = path;
+
+ for (;; c++) {
+ if (*c == '\0')
+ return true;
+ if (*c != ' ' && *c != '.')
+ return false;
+ }
+
+ return true;
+}
+
+GIT_INLINE(bool) verify_dotgit_ntfs_generic(const char *name, const char *dotgit_name, const char *shortname_pfix)
+{
+ size_t len = strlen(name);
+ size_t dotgit_len = strlen(dotgit_name);
+ int i, saw_tilde;
+
+ if (name[0] == '.' && len >= dotgit_len &&
+ !strncasecmp(name + 1, dotgit_name, dotgit_len)) {
+ return !only_spaces_and_dots(name + dotgit_len + 1);
+ }
+
+ /* Detect the basic NTFS shortname with the first six chars */
+ if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
+ name[7] >= '1' && name[7] <= '4')
+ return !only_spaces_and_dots(name + 8);
+
+ /* Catch fallback names */
+ for (i = 0, saw_tilde = 0; i < 8; i++) {
+ if (name[i] == '\0') {
+ return true;
+ } else if (saw_tilde) {
+ if (name[i] < '0' || name[i] > '9')
+ return true;
+ } else if (name[i] == '~') {
+ if (name[i+1] < '1' || name[i+1] > '9')
+ return true;
+ saw_tilde = 1;
+ } else if (i >= 6) {
+ return true;
+ } else if (name[i] < 0) {
+ return true;
+ } else if (git__tolower(name[i]) != shortname_pfix[i]) {
+ return true;
+ }
+ }
+
+ return !only_spaces_and_dots(name + i);
+}
+
GIT_INLINE(bool) verify_char(unsigned char c, unsigned int flags)
{
if ((flags & GIT_PATH_REJECT_BACKSLASH) && c == '\\')