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

Reply via email to