From 55ffebe37768b2b839f5501f76e77e89d9f91882 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sat, 5 Mar 2011 14:34:32 +0200 Subject: [PATCH] Fix creation of deeply-rooted references Use a new `gitfo_creat_force` that will create the full path to a file before creating it. Signed-off-by: Vicent Marti --- src/filebuf.c | 7 ++++++- src/fileops.c | 50 +++++++++++++++++++++++++++++++++----------------- src/fileops.h | 1 + src/refs.c | 2 +- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/filebuf.c b/src/filebuf.c index 73f0a70f4..4fc4f1486 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -39,7 +39,12 @@ static int lock_file(git_filebuf *file, int flags) return GIT_EOSERR; } - file->fd = gitfo_creat(file->path_lock, 0644); + /* create path to the file buffer is required */ + if (flags & GIT_FILEBUF_FORCE) { + file->fd = gitfo_creat_force(file->path_lock, 0644); + } else { + file->fd = gitfo_creat(file->path_lock, 0644); + } if (file->fd < 0) return GIT_EOSERR; diff --git a/src/fileops.c b/src/fileops.c index 7691129f6..76e689e8a 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -2,6 +2,29 @@ #include "fileops.h" #include +static int force_path(const char *to) +{ + const int mode = 0755; /* or 0777 ? */ + int error = GIT_SUCCESS; + char target_folder_path[GIT_PATH_MAX]; + + error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to); + if (error < GIT_SUCCESS) + return error; + + /* Does the containing folder exist? */ + if (gitfo_isdir(target_folder_path)) { + git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */ + + /* Let's create the tree structure */ + error = gitfo_mkdir_recurs(target_folder_path, mode); + if (error < GIT_SUCCESS) + return error; + } + + return GIT_SUCCESS; +} + int gitfo_open(const char *path, int flags) { int fd = open(path, flags | O_BINARY); @@ -14,6 +37,14 @@ int gitfo_creat(const char *path, int mode) return fd >= 0 ? fd : GIT_EOSERR; } +int gitfo_creat_force(const char *path, int mode) +{ + if (force_path(path) < GIT_SUCCESS) + return GIT_EOSERR; + + return gitfo_creat(path, mode); +} + int gitfo_read(git_file fd, void *buf, size_t cnt) { char *b = buf; @@ -167,23 +198,8 @@ int gitfo_mv(const char *from, const char *to) int gitfo_mv_force(const char *from, const char *to) { - const int mode = 0755; /* or 0777 ? */ - int error = GIT_SUCCESS; - char target_folder_path[GIT_PATH_MAX]; - - error = git__dirname_r(target_folder_path, sizeof(target_folder_path), to); - if (error < GIT_SUCCESS) - return error; - - /* Does the containing folder exist? */ - if (gitfo_isdir(target_folder_path)) { - git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */ - - /* Let's create the tree structure */ - error = gitfo_mkdir_recurs(target_folder_path, mode); - if (error < GIT_SUCCESS) - return error; - } + if (force_path(to) < GIT_SUCCESS) + return GIT_EOSERR; return gitfo_mv(from, to); } diff --git a/src/fileops.h b/src/fileops.h index fd150df5e..5aa302b54 100644 --- a/src/fileops.h +++ b/src/fileops.h @@ -57,6 +57,7 @@ typedef struct { /* file io buffer */ extern int gitfo_exists(const char *path); extern int gitfo_open(const char *path, int flags); extern int gitfo_creat(const char *path, int mode); +extern int gitfo_creat_force(const char *path, int mode); extern int gitfo_isdir(const char *path); extern int gitfo_mkdir_recurs(const char *path, int mode); #define gitfo_close(fd) close(fd) diff --git a/src/refs.c b/src/refs.c index 10df8e0c4..2fc383e22 100644 --- a/src/refs.c +++ b/src/refs.c @@ -291,7 +291,7 @@ static int loose_write(git_reference *ref) git__joinpath(ref_path, ref->owner->path_repository, ref->name); - if ((error = git_filebuf_open(&file, ref_path, 0)) < GIT_SUCCESS) + if ((error = git_filebuf_open(&file, ref_path, GIT_FILEBUF_FORCE)) < GIT_SUCCESS) return error; if (ref->type & GIT_REF_OID) {