Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 18d37e8

Browse files
mhaggergitster
authored andcommitted
safe_create_leading_directories(): add new error value SCLD_VANISHED
Add a new possible error result that can be returned by safe_create_leading_directories() and safe_create_leading_directories_const(): SCLD_VANISHED. This value indicates that a file or directory on the path existed at one point (either it already existed or the function created it), but then it disappeared. This probably indicates that another process deleted the directory while we were working. If SCLD_VANISHED is returned, the caller might want to retry the function call, as there is a chance that a new attempt will succeed. Why doesn't safe_create_leading_directories() do the retrying internally? Because an empty directory isn't really ever safe until it holds a file. So even if safe_create_leading_directories() were absolutely sure that the directory existed before it returned, there would be no guarantee that the directory still existed when the caller tried to write something in it. Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f3565c0 commit 18d37e8

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

cache.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,12 +741,20 @@ int adjust_shared_perm(const char *path);
741741
* Create the directory containing the named path, using care to be
742742
* somewhat safe against races. Return one of the scld_error values
743743
* to indicate success/failure.
744+
*
745+
* SCLD_VANISHED indicates that one of the ancestor directories of the
746+
* path existed at one point during the function call and then
747+
* suddenly vanished, probably because another process pruned the
748+
* directory while we were working. To be robust against this kind of
749+
* race, callers might want to try invoking the function again when it
750+
* returns SCLD_VANISHED.
744751
*/
745752
enum scld_error {
746753
SCLD_OK = 0,
747754
SCLD_FAILED = -1,
748755
SCLD_PERMS = -2,
749-
SCLD_EXISTS = -3
756+
SCLD_EXISTS = -3,
757+
SCLD_VANISHED = -4
750758
};
751759
enum scld_error safe_create_leading_directories(char *path);
752760
enum scld_error safe_create_leading_directories_const(const char *path);

sha1_file.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ enum scld_error safe_create_leading_directories(char *path)
132132
if (errno == EEXIST &&
133133
!stat(path, &st) && S_ISDIR(st.st_mode))
134134
; /* somebody created it since we checked */
135+
else if (errno == ENOENT)
136+
/*
137+
* Either mkdir() failed because
138+
* somebody just pruned the containing
139+
* directory, or stat() failed because
140+
* the file that was in our way was
141+
* just removed. Either way, inform
142+
* the caller that it might be worth
143+
* trying again:
144+
*/
145+
ret = SCLD_VANISHED;
135146
else
136147
ret = SCLD_FAILED;
137148
} else if (adjust_shared_perm(path)) {

0 commit comments

Comments
 (0)