Examining compatibility and behavior of the PHP chmod() and is_writable() functions on Windows
Compatibility of the PHP "is_writable()" function on the Windows platform is greatly improved, when compared to earlier versions of PHP. This article demonstrates that the PHP "is_writable()" function now works as expected on Windows. I will also demonstrate using the PHP chmod() function on Windows, to set and remove the read-only bit for a file.

Nearly every PHP application (except for Gallery) runs just fine on Windows with IIS and PHP. This has been true for quite a while now. PHP ran just fine on IIS, even before Microsoft released their fastcgi handler. Prior to the release of the fastcgi handler, I regularly configured PHP4 and PHP5 sites to run on IIS6. There were almost never any problems running the PHP applications on Windows and IIS. But where I would regularly see problems, was on the installation of PHP applications on IIS.

The is_writable() function on Windows
Until fairly recently, the PHP is_writable() function did not work as expected on Windows platforms. This situation was a constant headache for website administrators, PHP developers, and system admins alike. On Windows platforms, is_writable() would always return true, unless the file had the read-only attribute set. File ACL's were not checked by PHP. The file ACL's could be set in such a way as the web user could not write to the file, but is_writable() would still return true.

This problem could rear its head when an application such as Joomla or any other advanced PHP application is installed. Some applications may try to make sure that the site admin has properly secured the PHP app. The app might check to make sure that the "setup" directories have been deleted from the publicly accessible portion of the site. The app might also run is_writable() against the config file for the PHP app. The problem is, is_writable() would always return "true" on Windows.

The problem would not be corrected, even if the website admin used a control panel to change the file ACL, or asked the system administrator to fix the file ACL. The only solution was to set the file to read-only. Unfortunately, PHP application readme files rarely mentioned this behavior, and few Windows system admins knew about it.

This led many PHP users, developers, and even Windows system admins to think that many PHP apps were unreliable on Windows.

PHP is_writable() finally works
Tested on IIS 7.5 and the latest version of PHP 5.
Tested on this site.
This site is configured with an anon user name of "victorrweba".

Test 1, directory.
Check if the directory "D:/wwwsites/victor-ratajczykcom/www/examples/php/dir1/" can be written to.
Directory ACL for "victorrweba": Read, Write, Modify.
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/dir1/');
Result: True.

Test 2, directory.
Check if the directory "D:/wwwsites/victor-ratajczykcom/www/examples/php/dir2/" can be written to.
Directory ACL for "victorrweba": Read. (Write, Modify have been removed)
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/dir2/');
Result: False.

Test 3, files.
Check if the file "D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file1.txt" can be written to.
File ACL for "victorrweba": Read, Write, Modify.
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file1.txt');
Result: True.

Test 4, files.
Check if the file "D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file2.txt" can be written to.
File ACL for "victorrweba": Read, Write. (Modify has been removed)
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file2.txt');
Result: True.

Test 5, files.
Check if the file "D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file3.txt" can be written to.
File ACL for "victorrweba": Read. (Write and Modify have been removed)
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file3.txt');
Result: False.

Test 6, files, read-only files.
Check if the file "D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file4.txt" can be written to.
In this test we leave the file ACLs at read, write, modify. But we set the read-only bit on the file. Here we see that even if the anon user has ACL permissions, the read-only bit locks the file down.

File ACL for "victorrweba": Read, Write, Modify.
Read-only bit: On
Command: is_writable('D:/wwwsites/victor-ratajczykcom/www/examples/php/files1/file4.txt');
Result: False.


So now you may be thinking to yourself "good for you Victor, PHP is_writable() works for you". But my host is on an older version of PHP. The only option I have, is to set the read-only bit on the file, and the only way to set the read-only bit on a file is to ask the host to do it for me, and it's a big hassle to do this every time I need to make a change to the config.php file.

 

The PHP chmod() function to the rescue
It is widely reported that the PHP chmod() command does not work on Windows. This is (partially) false.

The PHP chmod() function will not change the file ACLs on Windows.
The PHP chmod() function can not grant or revoke Read, Write, Execute privileges  to the anon user on Windows.
The PHP chmod() function on Windows does not work anything like the PHP chmod() funtion on Linux.

But the PHP chmod() function can do one important thing on Windows. The PHP chmod() function can turn the read-only bit on and off, for Windows files.
The web anon user does not need "modify" permissions to set the read-only bit. The web anon user only need "write' permissions to set or remove the read-only bit.

Set the read-only bit on a Windows file, via the PHP chmod() function
<?php
      chmod( "D:/wwwsites/examplecom/www/config/config.php", 0444 );
?>

Remove the read-only bit on a Windows file, via the PHP chmod() function
<?php
      chmod( "D:/wwwsites/examplecom/www/config/config.php", 0777 );
?>

 

Notes
Once you set the read-only bit on a file, you must try to remember that you have done so.
When the read-only bit is set, you will not be able to write to, delete or overwrite the file via FTP or the web app, until you remove the read-only bit.