1

We have the following setup for a webserver: Windows Server 2008 R2 Standard, IIS 7.5.7600.16385, PHP 5.3.28, the HMVC framework we use is Kohana.

Kohana needs a cache directory to be writable in D:\inetpub\www\application\cache (D:\inetpub\www\ is our webroot). We removed the cache dir at this location and created a symbolic link to a directory outside of the webroot: D:\cache, which is writable.

It looks like the first user that is visiting the website gets the error "cache directory is not writeable", which is an error Kohana triggers, surprisingly, when it does not have permission to write in the directory. The second, third and so forth users do not get this error. The strange thing is that only this first user is keep getting this error, while the others never see it.

The solution for us was to use a directory junction.

I read a lot of documentation about the differences between a symbolic link and a directory junction, but I can't relate any to it to the error we got. The only thing I can think of is the fact that a symbolic link is processed on the client side, while a junction is processed on the server side.

The comment of Harry Johnston in this post points to two new links, but there we couldn't find a good explanation for our problem.

@Daan the fact that symbolic links cross SMB is documented in What's new in SMB?. I don't know of any documentation that explicitly states that junction points don't, but it is inherent in the way they are implemented and I did find Create the SYSVOL Root and Staging Areas Junction Point which otherwise wouldn't work. (Mostly though, it's just experience.)

Update:

I monitored the directories in process monitor and got the following result:

User: Test2, first user (here I got the error)

10:21:52.7311891 AM php-cgi.exe QueryOpen           D:\inetpub\www\application\cache    SUCCESS             CreationTime: 8/28/2015 5:12:56 PM, LastAccessTime: 8/28/2015 5:12:56 PM, LastWriteTime: 8/28/2015 5:12:56 PM, ChangeTime: 8/28/2015 5:12:56 PM, AllocationSize: 0, EndOfFile: 0, FileAttributes: DRP
10:21:52.7313164 AM php-cgi.exe CreateFile          D:\inetpub\www\application\cache    SUCCESS             Desired Access: Read Control, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test2, OpenResult: Opened
10:21:52.7313552 AM php-cgi.exe QuerySecurityFile   D:\inetpub\www\application\cache    BUFFER OVERFLOW     Information: Owner, Group, DACL
10:21:52.7313725 AM php-cgi.exe CloseFile           D:\inetpub\www\application\cache    SUCCESS 
10:21:52.7314490 AM php-cgi.exe CreateFile          D:\inetpub\www\application\cache    SUCCESS             Desired Access: Read Control, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test2, OpenResult: Opened
10:21:52.7314729 AM php-cgi.exe QuerySecurityFile   D:\inetpub\www\application\cache    SUCCESS             Information: Owner, Group, DACL
10:21:52.7314867 AM php-cgi.exe CloseFile           D:\inetpub\www\application\cache    SUCCESS 

User: Test3, second user (here i don't got the error)

10:28:01.7973266 AM php-cgi.exe 5220    QueryOpen           D:\inetpub\www\application\cache    SUCCESS CreationTime: 8/28/2015 5:12:56 PM, LastAccessTime: 8/28/2015 5:12:56 PM, LastWriteTime: 8/28/2015 5:12:56 PM, ChangeTime: 8/28/2015 5:12:56 PM, AllocationSize: 0, EndOfFile: 0, FileAttributes: DRP
10:28:01.7974467 AM php-cgi.exe 5220    CreateFile          D:\inetpub\www\application          SUCCESS Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test3, OpenResult: Opened
10:28:01.7974702 AM php-cgi.exe 5220    QueryDirectory      D:\inetpub\www\application\cache    SUCCESS Filter: cache, 1: cache
10:28:01.7974943 AM php-cgi.exe 5220    CloseFile           D:\inetpub\www\application          SUCCESS 
10:28:01.7975657 AM php-cgi.exe 5220    CreateFile          D:\inetpub\www\application\cache    SUCCESS Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: None, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test3, OpenResult: Opened
10:28:01.7976098 AM php-cgi.exe 5220    FileSystemControl   D:\inetpub\www\application\cache    SUCCESS Control: FSCTL_GET_REPARSE_POINT
10:28:01.7976285 AM php-cgi.exe 5220    CloseFile           D:\inetpub\www\application\cache    SUCCESS 
10:28:01.7977090 AM php-cgi.exe 5220    CreateFile          D:\cache                SUCCESS Desired Access: Read Control, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test3, OpenResult: Opened
10:28:01.7977524 AM php-cgi.exe 5220    QuerySecurityFile   D:\cache                BUFFER OVERFLOW Information: Owner, Group, DACL
10:28:01.7977657 AM php-cgi.exe 5220    CloseFile           D:\cache                SUCCESS 
10:28:01.7978337 AM php-cgi.exe 5220    CreateFile          D:\cache                SUCCESS Desired Access: Read Control, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: NL-COMPUTER1\Test3, OpenResult: Opened
10:28:01.7978573 AM php-cgi.exe 5220    QuerySecurityFile   D:\cache                SUCCESS Information: Owner, Group, DACL
10:28:01.7978703 AM php-cgi.exe 5220    CloseFile           D:\cache                SUCCESS 

Does anyone know why the first user can't write in the directory when we use a symbolic link instead of a directory junction?

Daan
  • 113
  • 7
  • That's client-side vs. server-side *for SMB*, I'm not sure it applies to a web server scenario. But in more general terms I think junction points are more robust, i.e., they look more like real directories than symbolic links do to software that encounters them unexpectedly. (Also, they've existed for longer, so software is more likely to explicitly support them.) – Harry Johnston Sep 15 '15 at 08:39
  • If you're wanting to figure out exactly what is happening, the best troubleshooting tool would probably be Process Monitor (available from the MS web site). But I'm not sure whether you're likely to discover anything useful, particularly since you already know how to fix the problem. – Harry Johnston Sep 15 '15 at 08:41
  • I updated the answer with the process monitor results – Daan Sep 16 '15 at 09:14
  • 1
    Looks like PHP is calling GetFileSecurity or an equivalent function on the `cache` directory. That returns the security information for the symbolic link, not the security information for the target directory. Since PHP doesn't have access to write to the symbolic link, it thinks it can't write to the directory. As to why it behaves differently the second time around, I don't know. Perhaps PHP is doing something weird, perhaps Windows is. The only way to tell would be to inspect the PHP code very carefully, or run it in a debugger. – Harry Johnston Sep 16 '15 at 21:45

0 Answers0