summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-03-04 14:55:56 +0100
committerCarlos Martín Nieto <cmn@dwim.me>2015-03-04 14:55:56 +0100
commitbdf0e734506b5b18234d48a0e7c6995aeda30b9d (patch)
tree540c17e5719bf72acc6a0b19ecf54398934de33f /src
parent107958d7173ab84566c9d89b1cafa08379c849fb (diff)
parentd8be5087771db34b191b13f22a2846888a477c36 (diff)
downloadlibgit2-bdf0e734506b5b18234d48a0e7c6995aeda30b9d.tar.gz
Merge pull request #2932 from jeffhostetler/jeffhostetler/big_clone_crash
Fix crash in git_clone on extremely large repos
Diffstat (limited to 'src')
-rw-r--r--src/win32/posix.h2
-rw-r--r--src/win32/posix_w32.c24
2 files changed, 21 insertions, 5 deletions
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 104966edc..9ac78430b 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -41,7 +41,7 @@ extern int p_chdir(const char* path);
extern int p_chmod(const char* path, mode_t mode);
extern int p_rmdir(const char* path);
extern int p_access(const char* path, mode_t mode);
-extern int p_ftruncate(int fd, long size);
+extern int p_ftruncate(int fd, git_off_t size);
/* p_lstat is almost but not quite POSIX correct. Specifically, the use of
* ENOTDIR is wrong, in that it does not mean precisely that a non-directory
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index 6e005c1cd..b8b4f43f8 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -42,12 +42,28 @@
/* GetFinalPathNameByHandleW signature */
typedef DWORD(WINAPI *PFGetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD);
-int p_ftruncate(int fd, long size)
+/**
+ * Truncate or extend file.
+ *
+ * We now take a "git_off_t" rather than "long" because
+ * files may be longer than 2Gb.
+ */
+int p_ftruncate(int fd, git_off_t size)
{
-#if defined(_MSC_VER) && _MSC_VER >= 1500
- return _chsize_s(fd, size);
+ if (size < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+#if !defined(__MINGW32__)
+ return ((_chsize_s(fd, size) == 0) ? 0 : -1);
#else
- return _chsize(fd, size);
+ /* TODO MINGW32 Find a replacement for _chsize() that handles big files. */
+ if (size > INT32_MAX) {
+ errno = EFBIG;
+ return -1;
+ }
+ return _chsize(fd, (long)size);
#endif
}