]> granicus.if.org Git - php/commitdiff
Fixed bug #72885 flatfile: dba_fetch() fails to read replaced entry
authorAnatol Belski <ab@php.net>
Sat, 27 May 2017 20:23:02 +0000 (22:23 +0200)
committerAnatol Belski <ab@php.net>
Sat, 27 May 2017 20:23:02 +0000 (22:23 +0200)
With append mode it is only possible to write to the end of the file. It
is not suitable for drivers like flatfile. Thus, if the file is created,
the stream is closed and is reopened with r+b, otherwise r+ mode is used
right away.

ext/dba/dba.c
ext/dba/tests/bug72885.phpt [new file with mode: 0644]

index 60060a5f10545fc430c6cfda2be2862e7a5c9e49..754ae10a8aabb7c63119727713feaa6b5cbefeb0 100644 (file)
@@ -644,6 +644,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
        int persistent_flag = persistent ? STREAM_OPEN_PERSISTENT : 0;
        zend_string *opened_path = NULL;
        char *lock_name;
+#ifdef PHP_WIN32
+       zend_bool restarted = 0;
+#endif
 
        if (ac < 2) {
                WRONG_PARAM_COUNT;
@@ -762,7 +765,15 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                        lock_mode = (lock_flag & DBA_LOCK_WRITER) ? LOCK_EX : 0;
                        file_mode = "r+b";
                        break;
-               case 'c':
+               case 'c': {
+#ifdef PHP_WIN32
+                       php_stream_statbuf ssb;
+                       zend_bool need_creation = 0;
+
+                       if (hptr->flags & (DBA_NO_APPEND|DBA_CAST_AS_FD)) {
+                               need_creation = (SUCCESS != php_stream_stat_path(Z_STRVAL(args[0]), &ssb));
+                       }
+#endif
                        modenr = DBA_CREAT;
                        lock_mode = (lock_flag & DBA_LOCK_CREAT) ? LOCK_EX : 0;
                        if (lock_mode) {
@@ -771,18 +782,34 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                                         * when the lib opens the file it is already created
                                         */
                                        file_mode = "r+b";       /* read & write, seek 0 */
+#ifdef PHP_WIN32
+                                       if (!need_creation) {
+                                               lock_file_mode = "r+b";
+                                       } else
+#endif
                                        lock_file_mode = "a+b";  /* append */
                                } else {
+#ifdef PHP_WIN32
+                                       if (!need_creation) {
+                                               file_mode = "r+b";
+                                       } else
+#endif
                                        file_mode = "a+b";       /* append */
                                        lock_file_mode = "w+b";  /* create/truncate */
                                }
                        } else {
+#ifdef PHP_WIN32
+                               if (!need_creation) {
+                                       file_mode = "r+b";
+                               } else
+#endif
                                file_mode = "a+b";
                        }
                        /* In case of the 'a+b' append mode, the handler is responsible
                         * to handle any rewind problems (see flatfile handler).
                         */
                        break;
+               }
                case 'n':
                        modenr = DBA_TRUNC;
                        lock_mode = (lock_flag & DBA_LOCK_TRUNC) ? LOCK_EX : 0;
@@ -849,6 +876,9 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                }
        }
 
+#ifdef PHP_WIN32
+restart:
+#endif
        if (!error && lock_mode) {
                if (lock_dbf) {
                        lock_name = Z_STRVAL(args[0]);
@@ -926,6 +956,25 @@ static void php_dba_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
                        } else if (modenr == DBA_CREAT) {
                                int flags = fcntl(info->fd, F_GETFL);
                                fcntl(info->fd, F_SETFL, flags & ~O_APPEND);
+#elif defined(PHP_WIN32)
+       } else if (modenr == DBA_CREAT && !restarted) {
+               zend_bool close_both;
+
+               close_both = (info->fp != info->lock.fp);
+               php_stream_close(info->lock.fp);
+               if (close_both) {
+                       php_stream_close(info->fp);
+               }
+               info->fp = NULL;
+               info->lock.fp = NULL;
+               info->fd = -1;
+
+               pefree(info->lock.name, persistent);
+
+               lock_file_mode = "r+b";
+
+               restarted = 1;
+               goto restart;
 #endif
                        }
 
diff --git a/ext/dba/tests/bug72885.phpt b/ext/dba/tests/bug72885.phpt
new file mode 100644 (file)
index 0000000..eb67778
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+Bug #72885 flatfile: dba_fetch() fails to read replaced entry
+--SKIPIF--
+<?php 
+$handler = "flatfile";
+require_once(dirname(__FILE__) .'/skipif.inc');
+?>
+--FILE--
+<?php
+
+require_once(dirname(__FILE__) .'/test.inc');
+
+$db = dba_open($db_filename, 'c', 'flatfile');
+dba_insert('foo', 'bar', $db);
+var_dump(dba_replace('foo', 'baz', $db));
+var_dump(dba_fetch('foo', $db));
+dba_close($db);
+
+?>
+===DONE===
+--CLEAN--
+<?php
+require_once(dirname(__FILE__) .'/clean.inc');
+?>
+--EXPECT--
+bool(true)
+string(3) "baz"
+===DONE===