summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/standard/tests/file/ftruncate_bug76422.phpt36
-rw-r--r--ext/standard/tests/file/ftruncate_variation2-win32.phpt12
-rw-r--r--main/streams/plain_wrapper.c22
3 files changed, 64 insertions, 6 deletions
diff --git a/ext/standard/tests/file/ftruncate_bug76422.phpt b/ext/standard/tests/file/ftruncate_bug76422.phpt
new file mode 100644
index 0000000000..46f52aace9
--- /dev/null
+++ b/ext/standard/tests/file/ftruncate_bug76422.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #76422 ftruncate fails on files > 2GB
+--SKIPIF--
+<?php
+if (PHP_INT_SIZE < 8) {
+ die('skip.. only valid for 64-bit');
+}
+?>
+--FILE--
+<?php
+
+$fn = dirname(__FILE__) . DIRECTORY_SEPARATOR . "test76422";
+
+$file_handle = fopen($fn,'cb');
+
+if (false === $file_handle) {
+ die('Cannot open test file :/');
+}
+
+$truncate_offset = 4 * 1024 * 1024 * 1024 + 1;
+$ftruncate_result = ftruncate($file_handle, $truncate_offset);
+
+if (false === $ftruncate_result) {
+ die('Truncate has failed :/');
+}
+
+fclose($file_handle);
+var_dump(filesize($fn) >= $truncate_offset);
+?>
+--CLEAN--
+<?php
+$fn = dirname(__FILE__) . "/test76422";
+unlink($fn);
+?>
+--EXPECT--
+bool(true)
diff --git a/ext/standard/tests/file/ftruncate_variation2-win32.phpt b/ext/standard/tests/file/ftruncate_variation2-win32.phpt
index 535881206a..6d62f75f1a 100644
--- a/ext/standard/tests/file/ftruncate_variation2-win32.phpt
+++ b/ext/standard/tests/file/ftruncate_variation2-win32.phpt
@@ -77,7 +77,7 @@ echo "Done\n";
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
@@ -85,7 +85,7 @@ int(1024)
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
@@ -93,7 +93,7 @@ int(1024)
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
@@ -271,7 +271,7 @@ int(1024)
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
@@ -279,7 +279,7 @@ int(1024)
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
@@ -287,7 +287,7 @@ int(1024)
-- Testing ftruncate(): truncate file to size = current size --
int(1024)
int(0)
-bool(true)
+bool(false)
int(0)
bool(false)
int(1024)
diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c
index 7657b35faf..285b12b052 100644
--- a/main/streams/plain_wrapper.c
+++ b/main/streams/plain_wrapper.c
@@ -854,7 +854,29 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void
if (new_size < 0) {
return PHP_STREAM_OPTION_RETURN_ERR;
}
+#ifdef PHP_WIN32
+ HANDLE h = (HANDLE) _get_osfhandle(fd);
+ if (INVALID_HANDLE_VALUE == h) {
+ return PHP_STREAM_OPTION_RETURN_ERR;
+ }
+ LARGE_INTEGER sz;
+#if defined(_WIN64)
+ sz.HighPart = (new_size >> 32);
+ sz.LowPart = (new_size & 0xffffffff);
+#else
+ sz.HighPart = 0;
+ sz.LowPart = new_size;
+#endif
+ if (INVALID_SET_FILE_POINTER == SetFilePointerEx(h, sz, NULL, FILE_BEGIN) && NO_ERROR != GetLastError()) {
+ return PHP_STREAM_OPTION_RETURN_ERR;
+ }
+ if (0 == SetEndOfFile(h)) {
+ return PHP_STREAM_OPTION_RETURN_ERR;
+ }
+ return PHP_STREAM_OPTION_RETURN_OK;
+#else
return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR;
+#endif
}
}