Skip to content

Commit

Permalink
git-apply: create subdirectories leading up to a new file
Browse files Browse the repository at this point in the history
Applying Andrew's latest patch-bomb showed us failing miserably if a new
subdirectory needed to be created..  That said, it's uncommon enough
that it's worth optimistically assuming it won't be needed, and then
creating the subdirectories only on failure.
  • Loading branch information
Linus Torvalds committed Jun 22, 2005
1 parent fa3e065 commit 5c8af18
Showing 1 changed file with 47 additions and 2 deletions.
49 changes: 47 additions & 2 deletions apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,51 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
die("unable to add cache entry for %s", path);
}

static void create_subdirectories(const char *path)
{
int len = strlen(path);
char *buf = xmalloc(len + 1);
const char *slash = path;

while ((slash = strchr(slash+1, '/')) != NULL) {
len = slash - path;
memcpy(buf, path, len);
buf[len] = 0;
if (mkdir(buf, 0755) < 0) {
if (errno != EEXIST)
break;
}
}
free(buf);
}

/*
* We optimistically assume that the directories exist,
* which is true 99% of the time anyway. If they don't,
* we create them and try again.
*/
static int create_regular_file(const char *path, unsigned int mode)
{
int ret = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);

if (ret < 0 && errno == ENOENT) {
create_subdirectories(path);
ret = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
}
return ret;
}

static int create_symlink(const char *buf, const char *path)
{
int ret = symlink(buf, path);

if (ret < 0 && errno == ENOENT) {
create_subdirectories(path);
ret = symlink(buf, path);
}
return ret;
}

static void create_file(struct patch *patch)
{
const char *path = patch->new_name;
Expand All @@ -1156,7 +1201,7 @@ static void create_file(struct patch *patch)
if (S_ISREG(mode)) {
int fd;
mode = (mode & 0100) ? 0777 : 0666;
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
fd = create_regular_file(path, mode);
if (fd < 0)
die("unable to create file %s (%s)", path, strerror(errno));
if (write(fd, buf, size) != size)
Expand All @@ -1169,7 +1214,7 @@ static void create_file(struct patch *patch)
if (size && buf[size-1] == '\n')
size--;
buf[size] = 0;
if (symlink(buf, path) < 0)
if (create_symlink(buf, path) < 0)
die("unable to write symlink %s", path);
add_index_file(path, mode, buf, size);
return;
Expand Down

0 comments on commit 5c8af18

Please sign in to comment.