Skip to content

Commit d88e6e9

Browse files
author
Vicent Marti
committed
mkdir-ext: Retry lstat on EEXIST race
1 parent 2c4e90f commit d88e6e9

File tree

1 file changed

+14
-5
lines changed

1 file changed

+14
-5
lines changed

src/fileops.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ int git_futils_mkdir_ext(
399399

400400
/* walk down tail of path making each directory */
401401
for (tail = &make_path.ptr[root]; *tail; *tail = lastch) {
402+
bool mkdir_attempted = false;
402403

403404
/* advance tail to include next path component */
404405
while (*tail == '/')
@@ -417,16 +418,24 @@ int git_futils_mkdir_ext(
417418
/* See what's going on with this path component */
418419
opts->perfdata.stat_calls++;
419420

421+
retry_lstat:
420422
if (p_lstat(make_path.ptr, &st) < 0) {
421-
opts->perfdata.mkdir_calls++;
422-
423-
if (errno != ENOENT || p_mkdir(make_path.ptr, mode) < 0) {
424-
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
425-
error = GIT_EEXISTS;
423+
if (mkdir_attempted || errno != ENOENT) {
424+
giterr_set(GITERR_OS, "Cannot access component in path '%s'", make_path.ptr);
425+
error = -1;
426426
goto done;
427427
}
428428

429429
giterr_clear();
430+
opts->perfdata.mkdir_calls++;
431+
mkdir_attempted = true;
432+
if (p_mkdir(make_path.ptr, mode) < 0) {
433+
if (errno == EEXIST)
434+
goto retry_lstat;
435+
giterr_set(GITERR_OS, "Failed to make directory '%s'", make_path.ptr);
436+
error = -1;
437+
goto done;
438+
}
430439
} else {
431440
/* with exclusive create, existing dir is an error */
432441
if ((flags & GIT_MKDIR_EXCL) != 0) {

0 commit comments

Comments
 (0)