I recently had a discussion with Garrett Rooney and William A. Rowe Jr.
about a bug in apr_file_open (on Windows in APR 0.9.7) that when
fixed created "problems" in apr_stat (for Subversion). Spurred by this
discussion, I decided to look for the root cause of the problem.
And what I found was that apr_stat(&finfo, path, APR_FINFO_PROT, &pool)
does indeed not behave (on Windows) as I imagine it would behave on
Unix/Linux.
The difference is that unpatched, the result in finfo.protection is
*only* the world rights (translated into the group "Everyone" on
Windows), and no group or user rights.
With this patch, the finfo.protection includes the rights for the
current user, and the rights for his/her primary group (plus of course
world/Everyone). Which is much more like the way I believe it works on
Unix/Linux.
In more detail, more_finfo() asks for user and group information based
on "(wanted & (APR_FINFO_USER | APR_FINFO_UPROT))" and vice versa for
groups. But when it calls GetSecurityInfo (and friends depending on
input), it only supplies the user argument if "(wanted & APR_FINFO_USER)".
Which means that when the routine later checks if "user" is valid, it
isn't, which means that when we in resolve_prot() check to see if we can
use the user information, it fails. The interesting thing is that
resolve_prot() seems to be written as if this scenario should work from
the beginning.
Note that I am by no means fluent in Unix/Linux, so if I have
misunderstood that part, please set me straight immediately.
Regards,
/Andreas
Index: file_io/win32/filestat.c
===================================================================
--- file_io/win32/filestat.c (revision 370999)
+++ file_io/win32/filestat.c (working copy)
@@ -242,8 +242,8 @@
}
rv = GetNamedSecurityInfoW(wfile + fix,
SE_FILE_OBJECT, sinf,
- ((wanted & APR_FINFO_USER) ? &user : NULL),
- ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
+ ((wanted & (APR_FINFO_USER |
APR_FINFO_UPROT)) ? &user : NULL),
+ ((wanted & (APR_FINFO_GROUP |
APR_FINFO_GPROT)) ? &grp : NULL),
((wanted & APR_FINFO_PROT) ? &dacl : NULL),
NULL, &pdesc);
if (fix == 6)
@@ -252,15 +252,15 @@
else if (whatfile == MORE_OF_FSPEC)
rv = GetNamedSecurityInfoA((char*)ufile,
SE_FILE_OBJECT, sinf,
- ((wanted & APR_FINFO_USER) ? &user : NULL),
- ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
+ ((wanted & (APR_FINFO_USER |
APR_FINFO_UPROT)) ? &user : NULL),
+ ((wanted & (APR_FINFO_GROUP |
APR_FINFO_GPROT)) ? &grp : NULL),
((wanted & APR_FINFO_PROT) ? &dacl : NULL),
NULL, &pdesc);
else if (whatfile == MORE_OF_HANDLE)
rv = GetSecurityInfo((HANDLE)ufile,
SE_FILE_OBJECT, sinf,
- ((wanted & APR_FINFO_USER) ? &user : NULL),
- ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
+ ((wanted & (APR_FINFO_USER |
APR_FINFO_UPROT)) ? &user : NULL),
+ ((wanted & (APR_FINFO_GROUP |
APR_FINFO_GPROT)) ? &grp : NULL),
((wanted & APR_FINFO_PROT) ? &dacl : NULL),
NULL, &pdesc);
else