commit 3c45a30aebce27db2fb0f5b453695260456bacc9 from: joshua stein date: Sun May 12 18:58:51 2019 UTC checkout: if worktree path exists and is empty, suppress mkdir failure commit - 00ba99a7be48f532c0673f3e2ada13d7c299b2a0 commit + 3c45a30aebce27db2fb0f5b453695260456bacc9 blob - bc14b937b2e2688bef36d04f7659e90265482817 blob + 3d3ea43dcf4295a664e1352ecbafb88f28096f6a --- got/got.c +++ got/got.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -197,10 +198,25 @@ apply_unveil(const char *repo_path, int repo_read_only const char *worktree_path, int create_worktree) { const struct got_error *error; + static char err_msg[MAXPATHLEN + 36]; if (create_worktree) { /* Pre-create work tree path to avoid unveiling its parents. */ error = got_path_mkdir(worktree_path); + + if (errno == EEXIST) { + if (got_dir_is_empty(worktree_path)) { + errno = 0; + error = NULL; + } else { + snprintf(err_msg, sizeof(err_msg), + "%s: directory exists but is not empty", + worktree_path); + error = got_error_msg(GOT_ERR_BAD_PATH, + err_msg); + } + } + if (error && (error->code != GOT_ERR_ERRNO || errno != EISDIR)) return error; } blob - e4dc262d9f534be828275a226b7a4592b85d5a03 blob + b80b464ead9ddd50e8e97e06b4d5fc92a1268f4a --- include/got_path.h +++ include/got_path.h @@ -90,6 +90,9 @@ void got_pathlist_free(struct got_pathlist_head *); /* Attempt to create a directory at a given path. */ const struct got_error *got_path_mkdir(const char *); +/* Determine whether a directory has no files or directories in it. */ +int got_dir_is_empty(const char *); + /* dirname(3) with error handling and dynamically allocated result. */ const struct got_error *got_path_dirname(char **, const char *); blob - 3cbf1e571016182b989eabf6e95c60e0879b0314 blob + abd5d7f4e126836f6242180512c1307ef26963cd --- lib/path.c +++ lib/path.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "got_error.h" #include "got_path.h" @@ -323,6 +324,29 @@ got_path_mkdir(const char *abspath) done: return err; +} + +int +got_dir_is_empty(const char *dir) +{ + DIR *d; + struct dirent *dent; + int empty = 1; + + d = opendir(dir); + if (d == NULL) + return 1; + + while ((dent = readdir(d)) != NULL) { + if (strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0) + continue; + + empty = 0; + break; + } + + return empty; } const struct got_error *