Skip to content

Commit

Permalink
apply: check D/F conflicts more carefully.
Browse files Browse the repository at this point in the history
When creating a new file where a directory used to be (or the user had
an empty directory) the code did not check the result from lstat() closely
enough, and mistakenly thought the path already existed in the working tree.

This does not fix the problem where you have a patch that creates a file
at "foo" and removes a file at "foo/bar" (which presumably is the last file
in "foo/" directory in the original).  For that, we would need to restructure
write_out_results() loop.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Jul 17, 2006
1 parent 8641fb2 commit c28c571
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions builtin-apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,9 +1732,14 @@ static int check_patch(struct patch *patch)
if (check_index && cache_name_pos(new_name, strlen(new_name)) >= 0)
return error("%s: already exists in index", new_name);
if (!cached) {
if (!lstat(new_name, &st))
return error("%s: already exists in working directory", new_name);
if (errno != ENOENT)
struct stat nst;
if (!lstat(new_name, &nst)) {
if (S_ISDIR(nst.st_mode))
; /* ok */
else
return error("%s: already exists in working directory", new_name);
}
else if ((errno != ENOENT) && (errno != ENOTDIR))
return error("%s: %s", new_name, strerror(errno));
}
if (!patch->new_mode) {
Expand Down Expand Up @@ -2010,6 +2015,16 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
return;
}

if (errno == EEXIST) {
/* We may be trying to create a file where a directory
* used to be.
*/
struct stat st;
errno = 0;
if (!lstat(path, &st) && S_ISDIR(st.st_mode) && !rmdir(path))
errno = EEXIST;
}

if (errno == EEXIST) {
unsigned int nr = getpid();

Expand Down

0 comments on commit c28c571

Please sign in to comment.