svn: /php/php-src/trunk/ UPGRADING ext/standard/tests/file/userstreams_005.phpt main/streams/userspace.c
| From: | Gustavo André dos Santos Lopes | Date: | Thu, 17 Feb 2011 00:25:32 +0000 |
| Subject: | svn: /php/php-src/trunk/ UPGRADING ext/standard/tests/file/userstreams_005.phpt main/streams/userspace.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-64565@lists.php.net to get a copy of this message | ||
cataphract Thu, 17 Feb 2011 00:25:32 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=308410
Log:
- Classes that implement stream wrappers can define a method called
stream_truncate that will respond to truncation, e.g. through ftruncate.
Closes feature request #53888.
Bug: http://bugs.php.net/53888 (Assigned) ftruncate() does
not work with user-defined stream wrappers
Changed paths:
U php/php-src/trunk/UPGRADING
A php/php-src/trunk/ext/standard/tests/file/userstreams_005.phpt
U php/php-src/trunk/main/streams/userspace.c
Modified: php/php-src/trunk/UPGRADING
===================================================================
--- php/php-src/trunk/UPGRADING 2011-02-17 00:10:15 UTC (rev 308409)
+++ php/php-src/trunk/UPGRADING 2011-02-17 00:25:32 UTC (rev 308410)
@@ -176,7 +176,10 @@
6. Changes made to existing classes
===================================
--
+- Classes that implement stream wrappers can define a method called
+ stream_truncate that will respond to truncation, e.g. through ftruncate.
+ Strictly speaking, this is an addition to the user-space stream wrapper
+ template, not a change to an actual class.
=============
7. Deprecated
Added: php/php-src/trunk/ext/standard/tests/file/userstreams_005.phpt
===================================================================
--- php/php-src/trunk/ext/standard/tests/file/userstreams_005.phpt (rev 0)
+++ php/php-src/trunk/ext/standard/tests/file/userstreams_005.phpt 2011-02-17 00:25:32 UTC (rev
308410)
@@ -0,0 +1,63 @@
+--TEST--
+User-space streams: stream_truncate()
+--FILE--
+<?php
+class test_wrapper_base {
+ public $mode;
+ function stream_open($path, $mode, $openedpath) {
+ return true;
+ }
+ function stream_eof() {
+ return false;
+ }
+}
+class test_wrapper extends test_wrapper_base {
+ function stream_truncate($new_size) {
+ echo "truncation with new_size=$new_size\n";
+ return true;
+ }
+}
+class test_wrapper_bad extends test_wrapper_base {
+ function stream_truncate($new_size) {
+ echo "truncation with new_size=$new_size\n";
+ return "kkk";
+ }
+}
+function test($name, $fd, $dest_size) {
+ echo "------ $name: -------\n";
+ var_dump(ftruncate($fd, $dest_size));
+}
+var_dump(stream_wrapper_register('test', 'test_wrapper'));
+var_dump(stream_wrapper_register('test2', 'test_wrapper_base'));
+var_dump(stream_wrapper_register('test3', 'test_wrapper_bad'));
+
+$fd = fopen("test://foo","r");
+$fd2 = fopen("test2://foo","r");
+$fd3 = fopen("test3://foo","r");
+
+test("stream_truncate not implemented", $fd2, 0);
+test("stream_truncate size 0", $fd, 0);
+test("stream_truncate size 10", $fd, 10);
+test("stream_truncate negative size", $fd, -1);
+test("stream_truncate bad return", $fd3, 0);
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+------ stream_truncate not implemented: -------
+
+Warning: ftruncate(): Can't truncate this stream! in %s on line %d
+bool(false)
+------ stream_truncate size 0: -------
+truncation with new_size=0
+bool(true)
+------ stream_truncate size 10: -------
+truncation with new_size=10
+bool(true)
+------ stream_truncate negative size: -------
+bool(false)
+------ stream_truncate bad return: -------
+truncation with new_size=0
+
+Warning: ftruncate(): test_wrapper_bad::stream_truncate did not return a boolean! in %s on line %d
+bool(false)
Modified: php/php-src/trunk/main/streams/userspace.c
===================================================================
--- php/php-src/trunk/main/streams/userspace.c 2011-02-17 00:10:15 UTC (rev 308409)
+++ php/php-src/trunk/main/streams/userspace.c 2011-02-17 00:25:32 UTC (rev 308410)
@@ -26,6 +26,7 @@
#ifdef HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
+#include <stddef.h>
static int le_protocols;
@@ -129,6 +130,7 @@
#define USERSTREAM_LOCK "stream_lock"
#define USERSTREAM_CAST "stream_cast"
#define USERSTREAM_SET_OPTION "stream_set_option"
+#define USERSTREAM_TRUNCATE "stream_truncate"
/* {{{ class should have methods like these:
@@ -254,6 +256,11 @@
{
return true / false;
}
+
+ function stream_truncate($new_size)
+ {
+ return true / false;
+ }
}}} **/
@@ -992,6 +999,51 @@
}
break;
+
+ case PHP_STREAM_OPTION_TRUNCATE_API:
+ ZVAL_STRINGL(&func_name, USERSTREAM_TRUNCATE, sizeof(USERSTREAM_TRUNCATE)-1, 0);
+
+ switch (value) {
+ case PHP_STREAM_TRUNCATE_SUPPORTED:
+ if (zend_is_callable_ex(&func_name, us->object, IS_CALLABLE_CHECK_SILENT,
+ NULL, NULL, NULL, NULL TSRMLS_CC))
+ ret = PHP_STREAM_OPTION_RETURN_OK;
+ else
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ break;
+
+ case PHP_STREAM_TRUNCATE_SET_SIZE: {
+ ptrdiff_t new_size = *(ptrdiff_t*) ptrparam;
+ if (new_size >= 0 && new_size <= (ptrdiff_t)LONG_MAX) {
+ MAKE_STD_ZVAL(zvalue);
+ ZVAL_LONG(zvalue, (long)new_size);
+ args[0] = &zvalue;
+ call_result = call_user_function_ex(NULL,
+ &us->object,
+ &func_name,
+ &retval,
+ 1, args, 0, NULL TSRMLS_CC);
+ if (call_result == SUCCESS && retval != NULL) {
+ if (Z_TYPE_P(retval) == IS_BOOL) {
+ ret = Z_LVAL_P(retval) ? PHP_STREAM_OPTION_RETURN_OK :
+ PHP_STREAM_OPTION_RETURN_ERR;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "%s::" USERSTREAM_TRUNCATE " did not return a boolean!",
+ us->wrapper->classname);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "%s::" USERSTREAM_TRUNCATE " is not implemented!",
+ us->wrapper->classname);
+ }
+ } else { /* bad new size */
+ ret = PHP_STREAM_OPTION_RETURN_ERR;
+ }
+ break;
+ }
+ }
+ break;
case PHP_STREAM_OPTION_READ_BUFFER:
case PHP_STREAM_OPTION_WRITE_BUFFER: