]> granicus.if.org Git - php/commitdiff
Allow delete-sharing mode for CreateFile by default
authorAnatol Belski <ab@php.net>
Thu, 7 Dec 2017 15:52:23 +0000 (16:52 +0100)
committerAnatol Belski <ab@php.net>
Fri, 8 Dec 2017 17:14:20 +0000 (18:14 +0100)
This effectively allows a UNIX like semantics for deleting files
with an open handle. Some OS related limitations still persist,
but the Windows 95 times can be considered as definitely over.

Zend/zend_virtual_cwd.c
ext/standard/tests/file/fopen_unlink.phpt [new file with mode: 0644]
ext/standard/tests/file/unlink_variation2-win32.phpt [deleted file]
ext/standard/tests/file/unlink_variation2.phpt
win32/ftok.c
win32/ioutil.c
win32/ioutil.h

index 132b68f39c8d63cbcf0996b067338857f982da1a..32c71a6149b4eae2a450c8490d514244e4b23867 100644 (file)
@@ -187,8 +187,8 @@ CWD_API ssize_t php_sys_readlink(const char *link, char *target, size_t target_l
        }
 
        hFile = CreateFileW(linkw,            // file to open
-                                GENERIC_READ,          // open for reading
-                                FILE_SHARE_READ,       // share for reading
+                                0,  // query possible attributes
+                                PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE,
                                 NULL,                  // default security
                                 OPEN_EXISTING,         // existing file only
                                 FILE_FLAG_BACKUP_SEMANTICS, // normal file
@@ -299,7 +299,13 @@ CWD_API int php_sys_stat_ex(const char *path, zend_stat_t *buf, int lstat) /* {{
                REPARSE_DATA_BUFFER * pbuffer;
                DWORD retlength = 0;
 
-               hLink = CreateFileW(pathw, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
+               hLink = CreateFileW(pathw,
+                               FILE_READ_ATTRIBUTES,
+                               PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE,
+                               NULL,
+                               OPEN_EXISTING,
+                               FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
+                               NULL);
                if(hLink == INVALID_HANDLE_VALUE) {
                        free(pathw);
                        return -1;
@@ -879,7 +885,13 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim
                                return (size_t)-1;
                        }
 
-                       hLink = CreateFileW(pathw, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);
+                       hLink = CreateFileW(pathw,
+                                       0,
+                                       PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE,
+                                       NULL,
+                                       OPEN_EXISTING,
+                                       FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
+                                       NULL);
                        if(hLink == INVALID_HANDLE_VALUE) {
                                free_alloca(tmp, use_heap);
                                FREE_PATHW()
diff --git a/ext/standard/tests/file/fopen_unlink.phpt b/ext/standard/tests/file/fopen_unlink.phpt
new file mode 100644 (file)
index 0000000..c069ea1
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Test fopen() function : check fopen()ed descriptor is usable after the fs object is removed
+--FILE--
+<?php
+
+var_dump(
+       $p = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'tututu',
+       $f = fopen($p, 'w+'),
+       unlink($p),
+       file_exists($p),
+       fwrite($f, 'hello'),
+       fseek($f, 0),
+       fread($f, 16),
+       fwrite($f, 'world'),
+       fseek($f, 0),
+       fread($f, 16),
+       fclose($f)
+);
+
+?>
+===DONE===
+--EXPECTF--
+string(%d) "%stututu"
+resource(%s) of type (Unknown)
+bool(true)
+bool(false)
+int(5)
+int(0)
+string(5) "hello"
+int(5)
+int(0)
+string(10) "helloworld"
+bool(true)
+===DONE===
diff --git a/ext/standard/tests/file/unlink_variation2-win32.phpt b/ext/standard/tests/file/unlink_variation2-win32.phpt
deleted file mode 100644 (file)
index af7b381..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
---TEST--
-Test unlink() function : usage variations - unlink file in use
---SKIPIF--
-<?php
-if (substr(PHP_OS, 0, 3) != 'WIN') {
-    die('skip only on Windows');
-}
-?>
---FILE--
-<?php
-/* Prototype : bool unlink ( string $filename [, resource $context] );
-   Description : Deletes filename
-*/
-
-/* Try to unlink file when file handle is still in use */
-
-$file_path = dirname(__FILE__);
-
-echo "*** Testing unlink() on a file when file handle is open ***\n";
-// temp file name used here
-$filename = "$file_path/unlink_variation2-win32.tmp";
-
-// create file
-$fp = fopen($filename, "w");
-// try unlink() on $filename
-var_dump( unlink($filename) );  // expected: false as file handle is still open
-// now close file handle
-fclose($fp);
-
-// now unlink file
-var_dump( unlink($filename) );  // expected: true
-var_dump( file_exists($filename) );  // confirm file is deleted
-
-echo "Done\n";
-?>
---EXPECTF--
-*** Testing unlink() on a file when file handle is open ***
-
-Warning: unlink(%s): %s in %s on line %d
-bool(false)
-bool(true)
-bool(false)
-Done
index 071a65780cab6a11494193afc49ea86a4a1d45e8..0068dbfe1744d6a6fc0fdbd3a944e1dc86e02e04 100644 (file)
@@ -1,11 +1,5 @@
 --TEST--
 Test unlink() function : usage variations - unlink file in use
---SKIPIF--
-<?php
-if (substr(PHP_OS, 0, 3) == 'WIN') {
-    die('skip only on Linux');
-}
-?>
 --FILE--
 <?php
 /* Prototype : bool unlink ( string $filename [, resource $context] );
index b88ed009c858504f59abf86d95c68ef96fd2704f..67e95e92ee2da3b549fc6267c0fd337594814f20 100644 (file)
@@ -41,7 +41,7 @@ ftok(const char *pathname, int proj_id)
                return (key_t)-1;
        }
 
-       if ((fh = CreateFileW(pathw, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
+       if ((fh = CreateFileW(pathw, FILE_GENERIC_READ, PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
                PHP_WIN32_IOUTIL_CLEANUP_W()
                return (key_t)-1;
        }
index cb5ff363b4c0e6793260a31f548ad308bc16bfc0..68346a19bbe9365b41ca0fd004af79f6d0506031 100644 (file)
@@ -111,10 +111,7 @@ PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_iout
        * UNIX semantics. In particular, this ensures that the file can
        * be deleted even whilst it's open.
        */
-       /* opts->share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; */
-       /* XXX No UINX behavior  Good to know it's doable. 
-          Not being done as this means a behavior change. Should be evaluated properly. */
-       opts->share = FILE_SHARE_READ | FILE_SHARE_WRITE;
+       opts->share = PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE;
 
        switch (flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
                case 0:
index c470fdbb1c7f0377e09968e243415dfb3252cdbf..71737f697b4104746b041bf66c309691db3a605d 100644 (file)
@@ -121,6 +121,8 @@ typedef enum {
 #define PHP_WIN32_IOUTIL_IS_UNC(pathw, path_lenw) (path_lenw >= 2 && PHP_WIN32_IOUTIL_IS_SLASHW(pathw[0]) && PHP_WIN32_IOUTIL_IS_SLASHW(pathw[1]) \
        || path_lenw >= PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW, PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW))
 
+#define PHP_WIN32_IOUTIL_DEFAULT_SHARE_MODE (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE)
+
 #define PHP_WIN32_IOUTIL_INIT_W(path) \
        wchar_t *pathw = php_win32_ioutil_any_to_w(path); \