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:
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php