This bug has been open for a while:
http://bugs.php.net/bug.php?id=27792

Having run into this issue recently, here's a patch (hopefully attached, mail.app and list filters willing) against PHP 5.3 to address it. This patch will promote to double the file sizes that overflow LONG_MAX, which works transparently for my script. Note that this only touches the obvious functions in the core; there may be other extensions that need to behave similarly.

The defines that I jam into CFLAGS are known to work in our other projects on Linux, Solaris, FreeBSD and OSX. The other (weirder) platforms might need some other adjustments to work correctly.

--Wez.

Index: configure.in
===================================================================
RCS file: /repository/php-src/configure.in,v
retrieving revision 1.579.2.52.2.77.2.5
diff -u -p -r1.579.2.52.2.77.2.5 configure.in
--- configure.in        5 Oct 2007 15:00:05 -0000       1.579.2.52.2.77.2.5
+++ configure.in        14 Oct 2007 21:54:34 -0000
@@ -154,6 +154,8 @@ PHP_PROG_LEX
 dnl Platform-specific compile settings.
 dnl -------------------------------------------------------------------------
 
+CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 
-D_LARGEFILE64_SOURCE"
+
 dnl See bug #28605
 case $host_cpu in
 alpha*)
Index: ext/standard/file.c
===================================================================
RCS file: /repository/php-src/ext/standard/file.c,v
retrieving revision 1.409.2.6.2.28.2.1
diff -u -p -r1.409.2.6.2.28.2.1 file.c
--- ext/standard/file.c 3 Oct 2007 10:44:32 -0000       1.409.2.6.2.28.2.1
+++ ext/standard/file.c 14 Oct 2007 21:54:36 -0000
@@ -1348,7 +1348,7 @@ PHPAPI PHP_FUNCTION(rewind)
 PHPAPI PHP_FUNCTION(ftell)
 {
        zval **arg1;
-       long ret;
+       off_t ret;
        php_stream *stream;
 
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == 
FAILURE) {
@@ -1361,7 +1361,11 @@ PHPAPI PHP_FUNCTION(ftell)
        if (ret == -1)  {
                RETURN_FALSE;
        }
-       RETURN_LONG(ret);
+       if (ret > LONG_MAX) {
+               RETURN_DOUBLE((double)ret);
+       } else {
+               RETURN_LONG((long)ret);
+       }
 }
 /* }}} */
 
@@ -1460,7 +1464,7 @@ PHP_FUNCTION(rmdir)
 PHP_FUNCTION(readfile)
 {
        char *filename;
-       int size = 0;
+       size_t size = 0;
        int filename_len;
        zend_bool use_include_path = 0;
        zval *zcontext = NULL;
@@ -1477,7 +1481,11 @@ PHP_FUNCTION(readfile)
        if (stream) {
                size = php_stream_passthru(stream);
                php_stream_close(stream);
-               RETURN_LONG(size);
+               if (size > LONG_MAX) {
+                       RETURN_DOUBLE((double)size);
+               } else {
+                       RETURN_LONG((long)size);
+               }
        }
        RETURN_FALSE;
 }
@@ -1517,7 +1525,7 @@ PHP_FUNCTION(umask)
 PHPAPI PHP_FUNCTION(fpassthru)
 {
        zval **arg1;
-       int size;
+       size_t size;
        php_stream *stream;
 
        if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg1) == 
FAILURE) {
@@ -1527,7 +1535,11 @@ PHPAPI PHP_FUNCTION(fpassthru)
        PHP_STREAM_TO_ZVAL(stream, arg1);
 
        size = php_stream_passthru(stream);
-       RETURN_LONG(size);
+       if (size > LONG_MAX) {
+               RETURN_DOUBLE((double)size);
+       } else {
+               RETURN_LONG((long)size);
+       }
 }
 /* }}} */
 
@@ -1659,7 +1671,11 @@ PHP_NAMED_FUNCTION(php_if_fstat)
 #else
        MAKE_LONG_ZVAL_INCREF(stat_rdev, -1); 
 #endif
-       MAKE_LONG_ZVAL_INCREF(stat_size, stat_ssb.sb.st_size);
+       if (stat_ssb.sb.st_size > LONG_MAX) {
+               MAKE_DOUBLE_ZVAL_INCREF(stat_size, (double)stat_ssb.sb.st_size);
+       } else {
+               MAKE_LONG_ZVAL_INCREF(stat_size, (long)stat_ssb.sb.st_size);
+       }
 #ifdef NETWARE
        MAKE_LONG_ZVAL_INCREF(stat_atime, stat_ssb.sb.st_atime.tv_sec);
        MAKE_LONG_ZVAL_INCREF(stat_mtime, stat_ssb.sb.st_mtime.tv_sec);
Index: ext/standard/filestat.c
===================================================================
RCS file: /repository/php-src/ext/standard/filestat.c,v
retrieving revision 1.136.2.8.2.14
diff -u -p -r1.136.2.8.2.14 filestat.c
--- ext/standard/filestat.c     21 Sep 2007 14:05:18 -0000      1.136.2.8.2.14
+++ ext/standard/filestat.c     14 Oct 2007 21:54:36 -0000
@@ -858,7 +858,11 @@ PHPAPI void php_stat(const char *filenam
        case FS_INODE:
                RETURN_LONG((long)ssb.sb.st_ino);
        case FS_SIZE:
-               RETURN_LONG((long)ssb.sb.st_size);
+               if (ssb.sb.st_size > LONG_MAX) {
+                       RETURN_DOUBLE((double)ssb.sb.st_size);
+               } else {
+                       RETURN_LONG((long)ssb.sb.st_size);
+               }
        case FS_OWNER:
                RETURN_LONG((long)ssb.sb.st_uid);
        case FS_GROUP:
@@ -927,7 +931,11 @@ PHPAPI void php_stat(const char *filenam
 #else
                MAKE_LONG_ZVAL_INCREF(stat_rdev, -1); 
 #endif
-               MAKE_LONG_ZVAL_INCREF(stat_size, stat_sb->st_size);
+               if (stat_sb->st_size > LONG_MAX) {
+                       MAKE_DOUBLE_ZVAL_INCREF(stat_size, 
(double)stat_sb->st_size);
+               } else {
+                       MAKE_LONG_ZVAL_INCREF(stat_size, 
(long)stat_sb->st_size);
+               }
 #ifdef NETWARE
                MAKE_LONG_ZVAL_INCREF(stat_atime, (stat_sb->st_atime).tv_sec);
                MAKE_LONG_ZVAL_INCREF(stat_mtime, (stat_sb->st_mtime).tv_sec);
Index: ext/standard/php_filestat.h
===================================================================
RCS file: /repository/php-src/ext/standard/php_filestat.h,v
retrieving revision 1.24.2.4.2.1.2.1
diff -u -p -r1.24.2.4.2.1.2.1 php_filestat.h
--- ext/standard/php_filestat.h 7 Oct 2007 05:22:07 -0000       1.24.2.4.2.1.2.1
+++ ext/standard/php_filestat.h 14 Oct 2007 21:54:36 -0000
@@ -64,6 +64,12 @@ PHP_FUNCTION(clearstatcache);
        ZVAL_LONG(name, val); \
        Z_ADDREF_P(name); 
 
+#define MAKE_DOUBLE_ZVAL_INCREF(name, val)\
+       MAKE_STD_ZVAL(name); \
+       ZVAL_DOUBLE(name, val); \
+       Z_ADDREF_P(name); 
+
+
 #ifdef PHP_WIN32
 #define S_IRUSR S_IREAD
 #define S_IWUSR S_IWRITE
Index: ext/standard/streamsfuncs.c
===================================================================
RCS file: /repository/php-src/ext/standard/streamsfuncs.c,v
retrieving revision 1.58.2.6.2.15.2.4
diff -u -p -r1.58.2.6.2.15.2.4 streamsfuncs.c
--- ext/standard/streamsfuncs.c 10 Oct 2007 12:58:41 -0000      
1.58.2.6.2.15.2.4
+++ ext/standard/streamsfuncs.c 14 Oct 2007 21:54:38 -0000
@@ -389,7 +389,7 @@ PHP_FUNCTION(stream_socket_recvfrom)
 }
 /* }}} */
 
-/* {{{ proto long stream_get_contents(resource source [, long maxlen [, long 
offset]])
+/* {{{ proto string stream_get_contents(resource source [, long maxlen [, long 
offset]])
    Reads all remaining bytes (or up to maxlen bytes) from a stream and returns 
them as a string. */
 PHP_FUNCTION(stream_get_contents)
 {
@@ -433,6 +433,7 @@ PHP_FUNCTION(stream_copy_to_stream)
        php_stream *src, *dest;
        zval *zsrc, *zdest;
        long maxlen = PHP_STREAM_COPY_ALL, pos = 0;
+       size_t copied;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|ll", &zsrc, 
&zdest, &maxlen, &pos) == FAILURE) {
                RETURN_FALSE;
@@ -446,7 +447,12 @@ PHP_FUNCTION(stream_copy_to_stream)
                RETURN_FALSE;
        }
 
-       RETURN_LONG(php_stream_copy_to_stream(src, dest, maxlen));
+       copied = php_stream_copy_to_stream(src, dest, maxlen);
+       if (copied > LONG_MAX) {
+               RETURN_DOUBLE((double)copied);
+       } else {
+               RETURN_LONG(copied);
+       }
 }
 /* }}} */
 

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to