diff options
-rw-r--r-- | include/git2/odb_backend.h | 10 | ||||
-rw-r--r-- | src/odb.c | 2 | ||||
-rw-r--r-- | src/odb_loose.c | 20 | ||||
-rw-r--r-- | tests-clar/odb/loose.c | 52 |
4 files changed, 78 insertions, 6 deletions
diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 1b3e2fd12..d3dd733a8 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -40,10 +40,18 @@ GIT_EXTERN(int) git_odb_backend_pack(git_odb_backend **out, const char *objects_ * @param objects_dir the Git repository's objects directory * @param compression_level zlib compression level to use * @param do_fsync whether to do an fsync() after writing (currently ignored) + * @param dir_mode permissions to use creating a directory or 0 for defaults + * @param file_mode permissions to use creating a file or 0 for defaults * * @return 0 or an error code */ -GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects_dir, int compression_level, int do_fsync); +GIT_EXTERN(int) git_odb_backend_loose( + git_odb_backend **out, + const char *objects_dir, + int compression_level, + int do_fsync, + mode_t dir_mode, + mode_t file_mode); /** * Create a backend out of a single packfile @@ -492,7 +492,7 @@ static int add_default_backends( #endif /* add the loose object backend */ - if (git_odb_backend_loose(&loose, objects_dir, -1, 0) < 0 || + if (git_odb_backend_loose(&loose, objects_dir, -1, 0, 0, 0) < 0 || add_backend_internal(db, loose, GIT_LOOSE_PRIORITY, as_alternates, inode) < 0) return -1; diff --git a/src/odb_loose.c b/src/odb_loose.c index 07dfae539..0dfd78aee 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -33,6 +33,8 @@ typedef struct loose_backend { int object_zlib_level; /** loose object zlib compression level. */ int fsync_object_files; /** loose object file fsync flag. */ + mode_t object_file_mode; + mode_t object_dir_mode; size_t objects_dirlen; char objects_dir[GIT_FLEX_ARRAY]; @@ -79,7 +81,7 @@ static int object_file_name( static int object_mkdir(const git_buf *name, const loose_backend *be) { return git_futils_mkdir( - name->ptr + be->objects_dirlen, be->objects_dir, GIT_OBJECT_DIR_MODE, + name->ptr + be->objects_dirlen, be->objects_dir, be->object_dir_mode, GIT_MKDIR_PATH | GIT_MKDIR_SKIP_LAST | GIT_MKDIR_VERIFY_DIR); } @@ -787,7 +789,7 @@ static int loose_backend__stream_fwrite(git_odb_stream *_stream, const git_oid * error = -1; else error = git_filebuf_commit_at( - &stream->fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE); + &stream->fbuf, final_path.ptr, backend->object_file_mode); git_buf_free(&final_path); @@ -876,7 +878,7 @@ static int loose_backend__write(git_odb_backend *_backend, const git_oid *oid, c if (object_file_name(&final_path, backend, oid) < 0 || object_mkdir(&final_path, backend) < 0 || - git_filebuf_commit_at(&fbuf, final_path.ptr, GIT_OBJECT_FILE_MODE) < 0) + git_filebuf_commit_at(&fbuf, final_path.ptr, backend->object_file_mode) < 0) error = -1; cleanup: @@ -899,7 +901,9 @@ int git_odb_backend_loose( git_odb_backend **backend_out, const char *objects_dir, int compression_level, - int do_fsync) + int do_fsync, + mode_t dir_mode, + mode_t file_mode) { loose_backend *backend; size_t objects_dirlen; @@ -920,8 +924,16 @@ int git_odb_backend_loose( if (compression_level < 0) compression_level = Z_BEST_SPEED; + if (dir_mode == 0) + dir_mode = GIT_OBJECT_DIR_MODE; + + if (file_mode == 0) + file_mode = GIT_OBJECT_FILE_MODE; + backend->object_zlib_level = compression_level; backend->fsync_object_files = do_fsync; + backend->object_dir_mode = dir_mode; + backend->object_file_mode = file_mode; backend->parent.read = &loose_backend__read; backend->parent.write = &loose_backend__write; diff --git a/tests-clar/odb/loose.c b/tests-clar/odb/loose.c index eb6b788b7..a85f1430d 100644 --- a/tests-clar/odb/loose.c +++ b/tests-clar/odb/loose.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "odb.h" +#include "git2/odb_backend.h" #include "posix.h" #include "loose_data.h" @@ -92,3 +93,54 @@ void test_odb_loose__simple_reads(void) test_read_object(&two); test_read_object(&some); } + +void test_write_object_permission( + mode_t dir_mode, mode_t file_mode, + mode_t expected_dir_mode, mode_t expected_file_mode) +{ + git_odb *odb; + git_odb_backend *backend; + git_oid oid; + struct stat statbuf; + mode_t mask, os_mask; + + /* Windows does not return group/user bits from stat, + * files are never executable. + */ +#ifdef GIT_WIN32 + os_mask = 0600; +#else + os_mask = 0777; +#endif + + mask = p_umask(0); + p_umask(mask); + + cl_git_pass(git_odb_new(&odb)); + cl_git_pass(git_odb_backend_loose(&backend, "test-objects", -1, 0, dir_mode, file_mode)); + cl_git_pass(git_odb_add_backend(odb, backend, 1)); + cl_git_pass(git_odb_write(&oid, odb, "Test data\n", 10, GIT_OBJ_BLOB)); + + cl_git_pass(p_stat("test-objects/67", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_dir_mode & ~mask) & os_mask); + + cl_git_pass(p_stat("test-objects/67/b808feb36201507a77f85e6d898f0a2836e4a5", &statbuf)); + cl_assert_equal_i(statbuf.st_mode & os_mask, (expected_file_mode & ~mask) & os_mask); + + git_odb_free(odb); +} + +void test_odb_loose__permissions_standard(void) +{ + test_write_object_permission(0, 0, GIT_OBJECT_DIR_MODE, GIT_OBJECT_FILE_MODE); +} + +void test_odb_loose_permissions_readonly(void) +{ + test_write_object_permission(0777, 0444, 0777, 0444); +} + +void test_odb_loose__permissions_readwrite(void) +{ + test_write_object_permission(0777, 0666, 0777, 0666); +} |