Commit d88e6e9b by Vicent Marti

mkdir-ext: Retry lstat on EEXIST race

parent 2c4e90f3
...@@ -399,6 +399,7 @@ int git_futils_mkdir_ext( ...@@ -399,6 +399,7 @@ int git_futils_mkdir_ext(
/* walk down tail of path making each directory */ /* walk down tail of path making each directory */
for (tail = &make_path.ptr[root]; *tail; *tail = lastch) { for (tail = &make_path.ptr[root]; *tail; *tail = lastch) {
bool mkdir_attempted = false;
/* advance tail to include next path component */ /* advance tail to include next path component */
while (*tail == '/') while (*tail == '/')
...@@ -417,16 +418,24 @@ int git_futils_mkdir_ext( ...@@ -417,16 +418,24 @@ int git_futils_mkdir_ext(
/* See what's going on with this path component */ /* See what's going on with this path component */
opts->perfdata.stat_calls++; opts->perfdata.stat_calls++;
retry_lstat:
if (p_lstat(make_path.ptr, &st) < 0) { if (p_lstat(make_path.ptr, &st) < 0) {
opts->perfdata.mkdir_calls++; if (mkdir_attempted || errno != ENOENT) {
giterr_set(GITERR_OS, "Cannot access component in path '%s'", make_path.ptr);
if (errno != ENOENT || p_mkdir(make_path.ptr, mode) < 0) { error = -1;
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
error = GIT_EEXISTS;
goto done; goto done;
} }
giterr_clear(); giterr_clear();
opts->perfdata.mkdir_calls++;
mkdir_attempted = true;
if (p_mkdir(make_path.ptr, mode) < 0) {
if (errno == EEXIST)
goto retry_lstat;
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
error = -1;
goto done;
}
} else { } else {
/* with exclusive create, existing dir is an error */ /* with exclusive create, existing dir is an error */
if ((flags & GIT_MKDIR_EXCL) != 0) { if ((flags & GIT_MKDIR_EXCL) != 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment