tests: test that largefiles can be read through the tree API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
diff --git a/src/posix.c b/src/posix.c
index bffe02e..ef48c60 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -216,6 +216,23 @@ int p_write(git_file fd, const void *buf, size_t cnt)
return 0;
}
+int p_fallocate(int fd, off_t offset, off_t len)
+{
+#ifdef __APPLE__
+ fstore_t prealloc;
+
+ memset(&prealloc, 0, sizeof(prealloc));
+ prealloc.fst_flags = F_ALLOCATEALL;
+ prealloc.fst_posmode = F_PEOFPOSMODE;
+ prealloc.fst_offset = offset;
+ prealloc.fst_length = len;
+
+ return fcntl(fd, F_PREALLOCATE, &prealloc);
+#else
+ return posix_fallocate(fd, offset, len);
+#endif
+}
+
#ifdef NO_MMAP
#include "map.h"
diff --git a/src/posix.h b/src/posix.h
index 2934f24..0119b6b 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -115,6 +115,7 @@ extern int p_open(const char *path, int flags, ...);
extern int p_creat(const char *path, mode_t mode);
extern int p_getcwd(char *buffer_out, size_t size);
extern int p_rename(const char *from, const char *to);
+extern int p_fallocate(int fd, off_t offset, off_t len);
extern int git__page_size(size_t *page_size);
extern int git__mmap_alignment(size_t *page_size);
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index d8bbebb..835804d 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -516,6 +516,12 @@ int p_creat(const char *path, mode_t mode)
return p_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
}
+int p_fallocate(int fd, off_t offset, off_t len)
+{
+ error = ENOSYS;
+ return -1;
+}
+
int p_utimes(const char *path, const struct p_timeval times[2])
{
git_win32_path wpath;
diff --git a/tests/object/tree/read.c b/tests/object/tree/read.c
index a0eae11..ee3dc78 100644
--- a/tests/object/tree/read.c
+++ b/tests/object/tree/read.c
@@ -73,3 +73,56 @@ void test_object_tree_read__two(void)
git_object_free(obj);
git_tree_free(tree);
}
+
+#define BIGFILE "bigfile"
+#define BIGFILE_SIZE (off_t)4 * 1024 * 1024 * 1024 /* 4 GiB */
+
+void test_object_tree_read__largefile(void)
+{
+ git_reference *ref;
+ git_commit *commit;
+ git_tree *tree;
+ git_oid oid;
+ const git_tree_entry *entry;
+ git_object *object;
+ git_buf file = GIT_BUF_INIT;
+ int fd;
+ git_index *idx;
+
+#ifdef GIT_WIN32
+ cl_skip();
+#endif
+
+ if (!cl_is_env_set("GITTEST_INVASIVE_FS_SIZE"))
+ cl_skip();
+
+ cl_git_pass(git_reference_lookup(&ref, g_repo, "refs/heads/master"));
+ cl_git_pass(git_repository_index(&idx, g_repo));
+
+ cl_git_pass(git_buf_puts(&file, git_repository_workdir(g_repo)));
+ cl_git_pass(git_buf_joinpath(&file, file.ptr, BIGFILE));
+
+ fd = p_open(git_buf_cstr(&file), O_CREAT|O_RDWR, 0644);
+ cl_assert_(fd >= 0, "invalid file descriptor");
+
+ cl_must_pass(p_fallocate(fd, 0, BIGFILE_SIZE));
+ cl_must_pass(p_close(fd));
+
+ cl_git_pass(git_index_add_bypath(idx, BIGFILE));
+ cl_repo_commit_from_index(&oid, g_repo, NULL, 0, "bigfile");
+
+ cl_git_pass(git_commit_lookup(&commit, g_repo, &oid));
+ cl_git_pass(git_commit_tree(&tree, commit));
+
+ entry = git_tree_entry_byname(tree, BIGFILE);
+ cl_assert_(entry, "entry was NULL");
+
+ cl_git_pass(git_tree_entry_to_object(&object, g_repo, entry));
+
+ git_buf_dispose(&file);
+ git_object_free(object);
+ git_tree_free(tree);
+ git_index_free(idx);
+ git_commit_free(commit);
+ git_reference_free(ref);
+}