Hi,

>From the fopen(3) manual page on Solaris 2.6 (it is the same on Solaris 7 
and Solaris 8):

     When a file is opened with update mode (+ as the  second  or
     third character in the mode argument), both input and output
     may be performed on the associated stream.  However,  output
     must  not be directly followed by input without an interven-
     ing call to fflush(3S) or to  a  file  positioning  function
     (fseek(3S),  fsetpos(3S)  or rewind(3S)), and input must not
     be directly followed by output without an  intervening  call
     to  a  file positioning function, unless the input operation
     encounters end-of-file.

The nasty behaviour remains even if we disable the buffering with call to
setbuf. This imposes a significant compatibility problem with the PHP file
io functions. The decision is to call explicitly fflush() when changing
the direction of the data flow.

I prepared a fix for this (it can be optimized and improved heavily), but
before I commit it I want to hear your opinion. Please see the attachment.

Thank you:
--
Alexander Feldman
Zend Technologies Ltd.
phone: +972 3 6139665 ext. 113, fax: +972 3 6139671
http://www.zend.com
diff -u ext/standard/config.m4 ../php-4.0.4pl1.fix/ext/standard/config.m4
--- ext/standard/config.m4      Wed Jul 19 19:19:40 2000
+++ ../php-4.0.4pl1.fix/ext/standard/config.m4  Mon Feb 19 20:48:43 2001
@@ -3,6 +3,57 @@
 divert(3)dnl
 
 dnl
+dnl Check if flush should be called explicitly after buffered io
+dnl
+AC_DEFUN(AC_FLUSH_IO,[
+  AC_CACHE_CHECK([whether flush should be called explicitly after a bufferered io], 
+ac_cv_flush_io,[
+  AC_TRY_RUN( [
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv)
+{
+       char *filename = tmpnam(NULL);
+       char buffer[64];
+       int result = 0;
+       
+       FILE *fp = fopen(filename, "wb");
+       if (NULL == fp)
+               return 0;
+       fputs("line 1\n", fp);
+       fputs("line 2\n", fp);
+       fclose(fp);
+       
+       fp = fopen(filename, "rb+");
+       if (NULL == fp)
+               return 0;
+       fgets(buffer, sizeof(buffer), fp);
+       fputs("line 3\n", fp);
+       rewind(fp);
+       fgets(buffer, sizeof(buffer), fp);
+       if (0 != strcmp(buffer, "line 1\n"))
+               result = 1;
+       fgets(buffer, sizeof(buffer), fp);
+       if (0 != strcmp(buffer, "line 3\n"))
+               result = 1;
+       fclose(fp);
+       unlink(filename);
+
+       exit(result);
+}
+],[
+  ac_cv_flush_io="no"
+],[
+  ac_cv_flush_io="yes"
+],[
+  ac_cv_flush_io="no"
+])])
+  if test "$ac_cv_flush_io" = "yes"; then
+    AC_DEFINE(HAVE_FLUSHIO, 1, [Define if flush should be called explicitly after a 
+buffered io.])
+  fi
+])
+
+dnl
 dnl Check for crypt() capabilities
 dnl
 AC_DEFUN(AC_CRYPT_CAP,[
@@ -143,6 +194,7 @@
 AC_CHECK_FUNCS(getcwd getwd)
 
 AC_CRYPT_CAP
+AC_FLUSH_IO
 
 divert(5)dnl
 
diff -u ext/standard/file.c ../php-4.0.4pl1.fix/ext/standard/file.c
--- ext/standard/file.c Thu Dec 14 16:34:51 2000
+++ ../php-4.0.4pl1.fix/ext/standard/file.c     Mon Feb 19 20:55:59 2001
@@ -882,6 +882,10 @@
                efree(buf);
                RETVAL_FALSE;
        } else {
+#ifdef HAVE_FLUSHIO
+               if (!issock)
+                       fflush((FILE*)what);
+#endif
                if (PG(magic_quotes_runtime)) {
                        return_value->value.str.val = 
php_addslashes(buf,0,&return_value->value.str.len,1);
                } else {
@@ -926,6 +930,10 @@
                efree(buf);
                RETVAL_FALSE;
        } else {
+#ifdef HAVE_FLUSHIO
+               if (!issock)
+                       fflush((FILE*)what);
+#endif
                buf[0]=result;
                buf[1]='\0';
                return_value->value.str.val = buf; 
@@ -1119,6 +1127,9 @@
        if (issock){
                ret = SOCK_WRITEL((*arg2)->value.str.val,num_bytes,socketd);
        } else {
+#ifdef HAVE_FLUSHIO
+               fflush((FILE*)what);
+#endif
                ret = fwrite((*arg2)->value.str.val,1,num_bytes,(FILE*)what);
        }
        RETURN_LONG(ret);
@@ -1731,6 +1742,9 @@
        if (!issock) {
                return_value->value.str.len = fread(return_value->value.str.val, 1, 
len, (FILE*)what);
                return_value->value.str.val[return_value->value.str.len] = 0;
+#ifdef HAVE_FLUSHIO
+               fflush((FILE*)what);
+#endif
        } else {
                return_value->value.str.len = SOCK_FREAD(return_value->value.str.val, 
len, socketd);
        }
--- main/php_config.h.in        Thu Jan 11 20:39:35 2001
+++ ../php-4.0.4pl1.fix/main/php_config.h.in    Mon Feb 19 20:56:35 2001
@@ -1547,6 +1547,9 @@
 /* Whether the system supports BlowFish salt */
 #undef PHP_BLOWFISH_CRYPT
 
+/* Define if flush should be called explicitly after a buffered io. */
+#undef HAVE_FLUSHIO
+
 /* Whether to build standard as dynamic module */
 #undef COMPILE_DL_STANDARD
 
-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to