Commit f966acd13366d21e0b9beeecf021c0114596c716

Edward Thomson 2013-11-04T15:46:32

Take umask into account in filebuf_commit

diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h
index d3dd733..4d772ca 100644
--- a/include/git2/odb_backend.h
+++ b/include/git2/odb_backend.h
@@ -50,8 +50,8 @@ GIT_EXTERN(int) git_odb_backend_loose(
 	const char *objects_dir,
 	int compression_level,
 	int do_fsync,
-	mode_t dir_mode,
-	mode_t file_mode);
+	unsigned int dir_mode,
+	unsigned int file_mode);
 
 /**
  * Create a backend out of a single packfile
diff --git a/src/filebuf.c b/src/filebuf.c
index 714a323..de2944b 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -320,9 +320,13 @@ int git_filebuf_commit_at(git_filebuf *file, const char *path, mode_t mode)
 
 int git_filebuf_commit(git_filebuf *file, mode_t mode)
 {
+	mode_t mask;
+
 	/* temporary files cannot be committed */
 	assert(file && file->path_original);
 
+	p_umask(mask = p_umask(0));
+
 	file->flush_mode = Z_FINISH;
 	flush_buffer(file);
 
@@ -338,7 +342,7 @@ int git_filebuf_commit(git_filebuf *file, mode_t mode)
 
 	file->fd = -1;
 
-	if (p_chmod(file->path_lock, mode)) {
+	if (p_chmod(file->path_lock, (mode & ~mask))) {
 		giterr_set(GITERR_OS, "Failed to set attributes for file at '%s'", file->path_lock);
 		goto on_error;
 	}
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 0dfd78a..3e52edf 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -902,8 +902,8 @@ int git_odb_backend_loose(
 	const char *objects_dir,
 	int compression_level,
 	int do_fsync,
-	mode_t dir_mode,
-	mode_t file_mode)
+	unsigned int dir_mode,
+	unsigned int file_mode)
 {
 	loose_backend *backend;
 	size_t objects_dirlen;
diff --git a/tests-clar/core/filebuf.c b/tests-clar/core/filebuf.c
index bf21670..646d42c 100644
--- a/tests-clar/core/filebuf.c
+++ b/tests-clar/core/filebuf.c
@@ -90,3 +90,37 @@ void test_core_filebuf__5(void)
 
 	cl_must_pass(p_unlink(test));
 }
+
+
+/* make sure git_filebuf_commit takes umask into account */
+void test_core_filebuf__umask(void)
+{
+	git_filebuf file = GIT_FILEBUF_INIT;
+	char test[] = "test";
+	struct stat statbuf;
+	mode_t mask, os_mask;
+
+#ifdef GIT_WIN32
+	os_mask = 0600;
+#else
+	os_mask = 0777;
+#endif
+
+	p_umask(mask = p_umask(0));
+
+	cl_assert(file.buffer == NULL);
+
+	cl_git_pass(git_filebuf_open(&file, test, 0));
+	cl_assert(file.buffer != NULL);
+	cl_git_pass(git_filebuf_printf(&file, "%s\n", "libgit2 rocks"));
+	cl_assert(file.buffer != NULL);
+
+	cl_git_pass(git_filebuf_commit(&file, 0666));
+	cl_assert(file.buffer == NULL);
+
+	cl_must_pass(p_stat("test", &statbuf));
+	cl_assert_equal_i(statbuf.st_mode & os_mask, (0666 & ~mask) & os_mask);
+
+	cl_must_pass(p_unlink(test));
+}
+