summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-22 02:10:21 (GMT)
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-22 02:10:21 (GMT)
commit5c8af185cc547b1babdd6292b1c77bec1941922f (patch)
treeb5c34bca2e519e8f675eae30ef581464ada17687
parentfa3e0655a45f53bbc1b48edc8f931426b183cba1 (diff)
downloadgit-5c8af185cc547b1babdd6292b1c77bec1941922f.zip
git-5c8af185cc547b1babdd6292b1c77bec1941922f.tar.gz
git-5c8af185cc547b1babdd6292b1c77bec1941922f.tar.bz2
git-apply: create subdirectories leading up to a new file
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.
-rw-r--r--apply.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/apply.c b/apply.c
index 8a3ead6..af97537 100644
--- a/apply.c
+++ b/apply.c
@@ -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;
@@ -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)
@@ -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;