diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2023-02-20 20:53:28 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-20 20:53:28 +0000 |
commit | 5561070c3787385ceca01cbde6bb26573d1c6292 (patch) | |
tree | fc04ba8e49a8b4a317b1d829e857956c9fa66428 | |
parent | 96e85df607863f94b55aba088c1395095b52bba7 (diff) | |
parent | be3a78cc933169bab12dccdfcbb173cb48261103 (diff) | |
download | libgit2-5561070c3787385ceca01cbde6bb26573d1c6292.tar.gz |
Merge pull request #6493 from libgit2/ethomson/ownership
Handle Win32 shares
-rw-r--r-- | src/libgit2/repository.c | 48 | ||||
-rw-r--r-- | src/util/fs_path.c | 2 |
2 files changed, 43 insertions, 7 deletions
diff --git a/src/libgit2/repository.c b/src/libgit2/repository.c index a3e7b9e13..8c41167a1 100644 --- a/src/libgit2/repository.c +++ b/src/libgit2/repository.c @@ -496,14 +496,47 @@ static int validate_ownership_cb(const git_config_entry *entry, void *payload) { validate_ownership_data *data = payload; - if (strcmp(entry->value, "") == 0) + if (strcmp(entry->value, "") == 0) { *data->is_safe = false; - - if (strcmp(entry->value, "*") == 0) - *data->is_safe = true; - else if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 && - strcmp(data->tmp.ptr, data->repo_path) == 0) + } else if (strcmp(entry->value, "*") == 0) { *data->is_safe = true; + } else { + const char *test_path = entry->value; + +#ifdef GIT_WIN32 + /* + * Git for Windows does some truly bizarre things with + * paths that start with a forward slash; and expects you + * to escape that with `%(prefix)`. This syntax generally + * means to add the prefix that Git was installed to -- eg + * `/usr/local` -- unless it's an absolute path, in which + * case the leading `%(prefix)/` is just removed. And Git + * for Windows expects you to use this syntax for absolute + * Unix-style paths (in "Git Bash" or Windows Subsystem for + * Linux). + * + * Worse, the behavior used to be that a leading `/` was + * not absolute. It would indicate that Git for Windows + * should add the prefix. So `//` is required for absolute + * Unix-style paths. Yes, this is truly horrifying. + * + * Emulate that behavior, I guess, but only for absolute + * paths. We won't deal with the Git install prefix. Also, + * give WSL users an escape hatch where they don't have to + * think about this and can use the literal path that the + * filesystem APIs provide (`//wsl.localhost/...`). + */ + if (strncmp(test_path, "%(prefix)//", strlen("%(prefix)//")) == 0) + test_path += strlen("%(prefix)/"); + else if (strncmp(test_path, "//", 2) == 0 && + strncmp(test_path, "//wsl.localhost/", strlen("//wsl.localhost/")) != 0) + test_path++; +#endif + + if (git_fs_path_prettify_dir(&data->tmp, test_path, NULL) == 0 && + strcmp(data->tmp.ptr, data->repo_path) == 0) + *data->is_safe = true; + } return 0; } @@ -547,6 +580,9 @@ static int validate_ownership_path(bool *is_safe, const char *path) if (error == GIT_ENOTFOUND) { *is_safe = true; error = 0; + } else if (error == GIT_EINVALID) { + *is_safe = false; + error = 0; } return error; diff --git a/src/util/fs_path.c b/src/util/fs_path.c index 6c87bfd01..b52867e77 100644 --- a/src/util/fs_path.c +++ b/src/util/fs_path.c @@ -1855,7 +1855,7 @@ static int file_owner_sid(PSID *out, const char *path) PSECURITY_DESCRIPTOR descriptor = NULL; PSID owner_sid; DWORD ret; - int error = -1; + int error = GIT_EINVALID; if (git_win32_path_from_utf8(path_w32, path) < 0) return -1; |