wrowe 01/01/28 22:21:42
Modified: . STATUS CHANGES
include/arch/win32 fileio.h
file_io/win32 filestat.c dir.c
Log:
Refactor out the 'extras' [not returned by the atomic get info call]
and implement protections. The only bit missing, according to testfile.c
are the dir_read/stat inode/dev/nlink fields [these are in getfileinfo]
Revision Changes Path
1.33 +22 -5 apr/STATUS
Index: STATUS
===================================================================
RCS file: /home/cvs/apr/STATUS,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- STATUS 2001/01/28 17:23:22 1.32
+++ STATUS 2001/01/29 06:21:36 1.33
@@ -1,5 +1,5 @@
APACHE PORTABLE RUNTIME (APR) LIBRARY STATUS:
-*-text-*-
-Last modified at [$Date: 2001/01/28 17:23:22 $]
+Last modified at [$Date: 2001/01/29 06:21:36 $]
Release:
@@ -15,11 +15,18 @@
RELEASE SHOWSTOPPERS:
+ * Unix apr_stat/lstat/getfileinfo were very fast hacks, needs review.
+ Will suggests: Unix is looking pretty good. Ignore APR_FINFO_NAME
+ issues for b1, I've noted that issue below.
+ * OS2 apr_stat/lstat/getfileinfo/dir_read were very fast hacks, need
+ cleanup, toggle messy (APR_INCOMPLETE) result when appropriate.
+
RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:
- * Unix, OS2 apr_stat/lstat/getfileinfo were very fast hacks. These
- need to be fleshed out.
+ * Solve Win32 APR_CHR, APR_BLK, etc for Win32 apr_stat without
+ GetFileType? How about inode/dev/nlink?
+ Status: Will's WIP
* SysV semaphore support isn't usable by Apache when started as
root because we don't have a way to allow the semaphore to be
@@ -30,9 +37,9 @@
* Build scripts do not recognise AIX 4.2.1 pthreads
- * Win32: Implement ap_shm_ functions
+ * Win32: Implement apr_shm_ functions
- * Bill says we need a new procattr, APR_CREATE_SUSPENDED (or
+ * FirstBill says we need a new procattr, APR_CREATE_SUSPENDED (or
something similar) to direct ap_create_process to create the
process suspended. We also need a call to wake up the suspended
process This may not be able to be implemented everywhere though.
@@ -111,3 +118,13 @@
Stuff waiting for code thawing after Beta 1:
+ * Implement APR_FINFO_ICASE/APR_FINFO_NAME for stat'ish calls.
+ Can wait till after b1, will be required to eliminate canonical
+ and add that functionallity in-line with directory_walk, which
+ is _not_ planned for 2.0b1, but immediately afterwards. It's
+ required to complete Apache/WinNT's Unicode schema as well.
+ Note: Will doesn't like his original APR_FINFO_ICASE definition.
+
+ * Identify and implement those protection bits that have general
+ usefulness, perhaps hidden, generic read-only [immutable],
+ effective current user permissions, etc.
1.53 +2 -0 apr/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr/CHANGES,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- CHANGES 2001/01/28 23:52:47 1.52
+++ CHANGES 2001/01/29 06:21:37 1.53
@@ -1,5 +1,7 @@
Changes with APR b1
+ *) Implement WinNT Unix'ish permissions. [William Rowe]
+
*) Corrected an OS2'ism of apr_get_home_directory. OS2 now returns the
proper directory, including the user's name.
1.44 +12 -0 apr/include/arch/win32/fileio.h
Index: fileio.h
===================================================================
RCS file: /home/cvs/apr/include/arch/win32/fileio.h,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -r1.43 -r1.44
--- fileio.h 2001/01/27 22:25:11 1.43
+++ fileio.h 2001/01/29 06:21:39 1.44
@@ -140,6 +140,18 @@
| APR_FINFO_CTIME | APR_FINFO_ATIME \
| APR_FINFO_MTIME | APR_FINFO_SIZE)
+/* Sneak the Readonly bit through finfo->protection for internal use _only_
*/
+#define APR_FREADONLY 0x10000000
+
+/* Private function that extends apr_stat/lstat/getfileinfo/dir_read */
+apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile,
+ apr_int32_t wanted, int whatfile,
+ apr_oslevel_e os_level);
+
+/* whatfile types for the ufile arg */
+#define MORE_OF_HANDLE 0
+#define MORE_OF_FSPEC 1
+#define MORE_OF_WFSPEC 2
/* quick run-down of fields in windows' apr_file_t structure that may have
* obvious uses.
1.43 +226 -177 apr/file_io/win32/filestat.c
Index: filestat.c
===================================================================
RCS file: /home/cvs/apr/file_io/win32/filestat.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -r1.42 -r1.43
--- filestat.c 2001/01/28 22:33:26 1.42
+++ filestat.c 2001/01/29 06:21:40 1.43
@@ -69,14 +69,216 @@
return APR_SUCCESS;
}
+static apr_gid_t worldid = NULL;
+
+static void free_world(void)
+{
+ if (worldid) {
+ FreeSid(worldid);
+ worldid = NULL;
+ }
+}
+
+/* Left bit shifts from World scope to given scope */
+typedef enum prot_scope_e {
+ prot_scope_world = 0,
+ prot_scope_group = 4,
+ prot_scope_user = 8
+} prot_scope_e;
+
+static apr_fileperms_t convert_prot(ACCESS_MASK acc, prot_scope_e scope)
+{
+ /* These choices are based on the single filesystem bit that controls
+ * the given behavior. They are -not- recommended for any set protection
+ * function, such a function should -set- use GENERIC_READ/WRITE/EXECUTE
+ */
+ apr_fileperms_t prot;
+ if (acc & FILE_EXECUTE)
+ prot |= APR_WEXECUTE;
+ if (acc & FILE_WRITE_DATA)
+ prot |= APR_WWRITE;
+ if (acc & FILE_READ_DATA)
+ prot |= APR_WREAD;
+ return (prot << scope);
+}
+
+static void resolve_prot(apr_finfo_t *finfo, apr_int32_t wanted, PACL dacl)
+{
+ TRUSTEE ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
+ ACCESS_MASK acc;
+ if ((wanted & APR_FINFO_WPROT) && !worldid) {
+ SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_WORLD_SID_AUTHORITY;
+ if (AllocateAndInitializeSid(&SIDAuth, 1, SECURITY_WORLD_RID,
+ 0, 0, 0, 0, 0, 0, 0, &worldid))
+ atexit(free_world);
+ else
+ worldid = NULL;
+ }
+ if ((wanted & APR_FINFO_UPROT) && (finfo->valid & APR_FINFO_USER)) {
+ ident.TrusteeType = TRUSTEE_IS_USER;
+ ident.ptstrName = finfo->user;
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
+ finfo->protection |= convert_prot(acc, prot_scope_user);
+ finfo->valid |= APR_FINFO_UPROT;
+ }
+ }
+ if ((wanted & APR_FINFO_GPROT) && (finfo->valid & APR_FINFO_GROUP)) {
+ ident.TrusteeType = TRUSTEE_IS_GROUP;
+ ident.ptstrName = finfo->group;
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
+ finfo->protection |= convert_prot(acc, prot_scope_group);
+ finfo->valid |= APR_FINFO_GPROT;
+ }
+ }
+ if ((wanted & APR_FINFO_WPROT) && (worldid)) {
+ ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+ ident.ptstrName = worldid;
+ if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
+ finfo->protection |= convert_prot(acc, prot_scope_world);
+ finfo->valid |= APR_FINFO_WPROT;
+ }
+ }
+}
+
+static int resolve_ident(apr_finfo_t *finfo, const char *fname,
+ apr_int32_t wanted, apr_pool_t *cont)
+{
+ apr_file_t *thefile = NULL;
+ apr_status_t rv;
+ /*
+ * NT5 (W2K) only supports symlinks in the same manner as mount points.
+ * This code should eventually take that into account, for now treat
+ * every reparse point as a symlink...
+ *
+ * We must open the file with READ_CONTROL if we plan to retrieve the
+ * user, group or permissions.
+ */
+
+ if ((rv = apr_open(&thefile, fname,
+ ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0)
+ | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
+ ? APR_READCONTROL : 0),
+ APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
+ rv = apr_getfileinfo(finfo, wanted, thefile);
+ finfo->filehand = NULL;
+ apr_close(thefile);
+ }
+ else if (APR_STATUS_IS_EACCES(rv) && (wanted & (APR_FINFO_PROT
+ | APR_FINFO_OWNER))) {
+ /* We have a backup plan. Perhaps we couldn't grab READ_CONTROL?
+ * proceed without asking for that permission...
+ */
+ if ((rv = apr_open(&thefile, fname,
+ ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0),
+ APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
+ rv = apr_getfileinfo(finfo, wanted & ~(APR_FINFO_PROT
+ | APR_FINFO_OWNER),
+ thefile);
+ finfo->filehand = NULL;
+ apr_close(thefile);
+ }
+ }
+ if (rv != APR_SUCCESS && rv != APR_INCOMPLETE)
+ return (rv);
+ /* We picked up this case above and had opened the link's properties */
+ if (wanted & APR_FINFO_LINK)
+ finfo->valid |= APR_FINFO_LINK;
+ finfo->fname = thefile->fname;
+
+ return rv;
+}
+
+apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, apr_int32_t
wanted,
+ int whatfile, apr_oslevel_e os_level)
+{
+ PSID user = NULL, grp = NULL;
+ PACL dacl = NULL;
+ apr_status_t rv;
+
+ if (whatfile == MORE_OF_WFSPEC)
+ (apr_wchar_t*)ufile;
+ else if (whatfile == MORE_OF_FSPEC)
+ (char*)ufile;
+ else if (whatfile == MORE_OF_HANDLE)
+ (HANDLE)ufile;
+
+ if ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
+ && os_level >= APR_WIN_NT)
+ {
+ SECURITY_INFORMATION sinf = 0;
+ PSECURITY_DESCRIPTOR pdesc = NULL;
+ if (wanted & (APR_FINFO_USER | APR_FINFO_UPROT))
+ sinf |= OWNER_SECURITY_INFORMATION;
+ if (wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT))
+ sinf |= GROUP_SECURITY_INFORMATION;
+ if (wanted & APR_FINFO_PROT)
+ sinf |= DACL_SECURITY_INFORMATION;
+ if (whatfile == MORE_OF_WFSPEC)
+ rv = GetNamedSecurityInfoW((apr_wchar_t*)ufile,
+ SE_FILE_OBJECT, sinf,
+ ((wanted & APR_FINFO_USER) ? &user : NULL),
+ ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
+ ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
+ NULL, &pdesc);
+ 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_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_PROT) ? &dacl : NULL),
+ NULL, &pdesc);
+ if (rv == ERROR_SUCCESS)
+ apr_register_cleanup(finfo->cntxt, pdesc, free_localheap,
+ apr_null_cleanup);
+ else
+ user = grp = dacl = NULL;
+
+ if (user) {
+ finfo->user = user;
+ finfo->valid |= APR_FINFO_USER;
+ }
+
+ if (grp) {
+ finfo->group = grp;
+ finfo->valid |= APR_FINFO_GROUP;
+ }
+
+ if (dacl) {
+ /* Retrieved the discresionary access list */
+ resolve_prot(finfo, wanted, dacl);
+ }
+ }
+
+ if (!(finfo->valid & APR_FINFO_UPROT)) {
+ /* Read, write execute for owner. In the Win32 environment,
+ * anything readable is executable (well, not entirely 100% true,
+ * but I'm looking for some obvious logic that would help us here.)
+ */
+ if (finfo->protection & APR_FREADONLY) {
+ finfo->protection |= S_IREAD | S_IEXEC;
+ }
+ else {
+ finfo->protection |= S_IREAD | S_IWRITE | S_IEXEC;
+ }
+ finfo->valid |= APR_FINFO_UPROT;
+ }
+
+ return ((wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS);
+}
+
+
APR_DECLARE(apr_status_t) apr_getfileinfo(apr_finfo_t *finfo, apr_int32_t
wanted,
apr_file_t *thefile)
{
BY_HANDLE_FILE_INFORMATION FileInformation;
apr_oslevel_e os_level;
- PSID user = NULL, grp = NULL;
- PACL dacl = NULL;
- apr_status_t rv;
if (!GetFileInformationByHandle(thefile->filehand, &FileInformation)) {
return apr_get_os_error();
@@ -134,60 +336,12 @@
}
}
+ if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ finfo->protection = APR_FREADONLY;
- if ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
- && !apr_get_oslevel(thefile->cntxt, &os_level)
- && os_level >= APR_WIN_NT) {
- SECURITY_INFORMATION sinf = 0;
- PSECURITY_DESCRIPTOR pdesc = NULL;
- if (wanted & (APR_FINFO_USER | APR_FINFO_UPROT))
- sinf |= OWNER_SECURITY_INFORMATION;
- if (wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT))
- sinf |= GROUP_SECURITY_INFORMATION;
- if (wanted & APR_FINFO_PROT)
- sinf |= DACL_SECURITY_INFORMATION;
- rv = GetSecurityInfo(thefile->filehand, SE_FILE_OBJECT, sinf,
- ((wanted & APR_FINFO_USER) ? &user : NULL),
- ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
- ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
- NULL, &pdesc);
- if (rv == ERROR_SUCCESS)
- apr_register_cleanup(thefile->cntxt, pdesc, free_localheap,
- apr_null_cleanup);
- }
+ if (wanted &= ~finfo->valid)
+ return more_finfo(finfo, thefile->filehand, wanted, MORE_OF_HANDLE,
os_level);
- if (user) {
- finfo->user = user;
- finfo->valid |= APR_FINFO_USER;
- }
-
- if (grp) {
- finfo->group = grp;
- finfo->valid |= APR_FINFO_GROUP;
- }
-
- if (dacl) {
- /* Retrieved the discresionary access list */
-
- }
- else {
- /* Read, write execute for owner. In the Win32 environment,
- * anything readable is executable (well, not entirely 100% true,
- * but I'm looking for some obvious logic that would help us here.)
- * TODO: The real permissions come from the DACL
- */
- if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
- finfo->protection |= S_IREAD | S_IEXEC;
- }
- else {
- finfo->protection |= S_IREAD | S_IWRITE | S_IEXEC;
- }
- finfo->valid |= APR_FINFO_UPROT;
- }
-
- if (wanted & ~finfo->valid)
- return APR_INCOMPLETE;
-
return APR_SUCCESS;
}
@@ -197,63 +351,17 @@
return APR_ENOTIMPL;
}
-static int stat_with_handle(apr_finfo_t *finfo, const char *fname,
- apr_int32_t wanted, apr_pool_t *cont)
-{
- apr_file_t *thefile = NULL;
- apr_status_t rv;
- /*
- * NT5 (W2K) only supports symlinks in the same manner as mount points.
- * This code should eventually take that into account, for now treat
- * every reparse point as a symlink...
- *
- * We must open the file with READ_CONTROL if we plan to retrieve the
- * user, group or permissions.
- */
-
- if ((rv = apr_open(&thefile, fname,
- ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0)
- | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
- ? APR_READCONTROL : 0),
- APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
- rv = apr_getfileinfo(finfo, wanted, thefile);
- finfo->filehand = NULL;
- apr_close(thefile);
- }
- else if (APR_STATUS_IS_EACCES(rv) && (wanted & (APR_FINFO_PROT
- | APR_FINFO_OWNER))) {
- /* We have a backup plan. Perhaps we couldn't grab READ_CONTROL?
- * proceed without asking for that permission...
- */
- if ((rv = apr_open(&thefile, fname,
- ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0),
- APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
- rv = apr_getfileinfo(finfo, wanted & ~(APR_FINFO_PROT
- | APR_FINFO_OWNER),
- thefile);
- finfo->filehand = NULL;
- apr_close(thefile);
- }
- }
- if (rv != APR_SUCCESS && rv != APR_INCOMPLETE)
- return (rv);
- /* We picked up this case above and had opened the link's properties */
- if (wanted & APR_FINFO_LINK)
- finfo->valid |= APR_FINFO_LINK;
- finfo->fname = thefile->fname;
-
- return rv;
-}
-
APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname,
apr_int32_t wanted, apr_pool_t *cont)
{
- /* The WIN32_FILE_ATTRIBUTE_DATA is a subset of this structure
+#ifdef APR_HAS_UNICODE_FS
+ apr_wchar_t wfname[APR_PATH_MAX];
+#endif
+ /*
+ * The WIN32_FILE_ATTRIBUTE_DATA is a subset of this structure
*/
WIN32_FIND_DATA FileInformation;
apr_oslevel_e os_level;
- PSID user = NULL, grp = NULL;
- PACL dacl = NULL;
if (apr_get_oslevel(cont, &os_level))
os_level = APR_WIN_95;
@@ -265,9 +373,9 @@
if (strlen(fname) >= APR_PATH_MAX) {
return APR_ENAMETOOLONG;
}
+
#ifdef APR_HAS_UNICODE_FS
- else if (os_level >= APR_WIN_NT) {
- apr_wchar_t wfname[APR_PATH_MAX];
+ if (os_level >= APR_WIN_NT) {
apr_status_t rv;
if (rv = utf8_to_unicode_path(wfname, sizeof(wfname)
/ sizeof(apr_wchar_t), fname))
@@ -276,27 +384,10 @@
&FileInformation)) {
return apr_get_os_error();
}
- if (wanted & (APR_FINFO_PROT | APR_FINFO_OWNER)) {
- SECURITY_INFORMATION sinf = 0;
- PSECURITY_DESCRIPTOR pdesc = NULL;
- if (wanted & (APR_FINFO_USER | APR_FINFO_UPROT))
- sinf |= OWNER_SECURITY_INFORMATION;
- if (wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT))
- sinf |= GROUP_SECURITY_INFORMATION;
- if (wanted & APR_FINFO_PROT)
- sinf |= DACL_SECURITY_INFORMATION;
- rv = GetNamedSecurityInfoW(wfname, SE_FILE_OBJECT, sinf,
- ((wanted & APR_FINFO_USER) ? &user : NULL),
- ((wanted & APR_FINFO_GROUP) ? &grp : NULL),
- ((wanted & APR_FINFO_PROT) ? &dacl : NULL),
- NULL, &pdesc);
- if (rv == ERROR_SUCCESS)
- apr_register_cleanup(cont, pdesc, free_localheap,
- apr_null_cleanup);
- }
}
+ else
#endif
- else if (os_level >= APR_WIN_98) {
+ if (os_level >= APR_WIN_98) {
if (!GetFileAttributesExA(fname, GetFileExInfoStandard,
&FileInformation)) {
return apr_get_os_error();
@@ -353,40 +444,18 @@
*/
finfo->filetype = APR_REG;
}
-
- if (user) {
- finfo->user = user;
- finfo->valid |= APR_FINFO_USER;
- }
- if (grp) {
- finfo->group = grp;
- finfo->valid |= APR_FINFO_GROUP;
- }
+ if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ finfo->protection = APR_FREADONLY;
- if (dacl) {
- /* Retrieved the discresionary access list, provide some real answers
- */
-
- }
- else {
- /* Read, write execute for owner
- * In the Win32 environment, anything readable is executable
- * (not entirely 100% true, but the dacl is -expensive-!)
- */
- if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
- finfo->protection |= S_IREAD | S_IEXEC;
- }
- else {
- finfo->protection |= S_IREAD | S_IWRITE | S_IEXEC;
- }
- /* Lying through our teeth */
- finfo->valid |= APR_FINFO_UPROT;
+ if (wanted &= ~finfo->valid) {
+#ifdef APR_HAS_UNICODE_FS
+ if (os_level >= APR_WIN_NT)
+ return more_finfo(finfo, wfname, wanted, MORE_OF_WFSPEC,
os_level);
+#endif
+ return more_finfo(finfo, fname, wanted, MORE_OF_FSPEC, os_level);
}
- if (wanted & ~finfo->valid)
- return APR_INCOMPLETE;
-
return APR_SUCCESS;
}
@@ -395,23 +464,3 @@
{
return apr_stat(finfo, fname, wanted & APR_FINFO_LINK, cont);
}
-
-#if 0
- apr_oslevel_e os_level;
- if (!apr_get_oslevel(cont, &os_level) && os_level >= APR_WIN_NT)
- {
- WIN32_FIND_DATAW FileInformation;
- HANDLE hFind;
- apr_wchar_t *wname;
- if (strchr(fspec, '*') || strchr(fspec, '?'))
- return APR_ENOENT;
- wname = utf8_to_unicode_path(fspec, cont);
- if (!wname)
- return APR_ENAMETOOLONG;
- hFind = FindFirstFileW(wname, &FileInformation);
- if (hFind == INVALID_HANDLE_VALUE)
- return apr_get_os_error();
- else
- FindClose(hFind);
- *fname = unicode_to_utf8_path(FileInformation.cFileName, cont);
-#endif
\ No newline at end of file
1.50 +36 -23 apr/file_io/win32/dir.c
Index: dir.c
===================================================================
RCS file: /home/cvs/apr/file_io/win32/dir.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- dir.c 2001/01/28 04:03:11 1.49
+++ dir.c 2001/01/29 06:21:40 1.50
@@ -152,11 +152,11 @@
*/
#if APR_HAS_UNICODE_FS
apr_oslevel_e os_level;
+ apr_wchar_t *eos, wdirname[APR_PATH_MAX];
if (!apr_get_oslevel(thedir->cntxt, &os_level) && os_level >= APR_WIN_NT)
{
if (thedir->dirhand == INVALID_HANDLE_VALUE)
{
- apr_wchar_t *eos, wdirname[APR_PATH_MAX];
apr_status_t rv;
if (rv = utf8_to_unicode_path(wdirname, sizeof(wdirname)
/ sizeof(apr_wchar_t),
@@ -170,6 +170,7 @@
if (thedir->dirhand == INVALID_HANDLE_VALUE) {
return apr_get_os_error();
}
+ eos[0] = '\0';
}
else if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) {
return apr_get_os_error();
@@ -211,22 +212,6 @@
}
fname = thedir->n.entry->cFileName;
}
- if (wanted & ~APR_FINFO_WIN32_DIR) {
- char fspec[APR_PATH_MAX];
- int dirlen = strlen(thedir->dirname);
- if (dirlen >= sizeof(fspec))
- dirlen = sizeof(fspec) - 1;
- apr_cpystrn(fspec, thedir->dirname, sizeof(fspec));
- apr_cpystrn(fspec + dirlen, fname, sizeof(fspec) - dirlen);
- rv = apr_stat(finfo, fspec, wanted, thedir->cntxt);
- if (rv == APR_SUCCESS || rv == APR_INCOMPLETE) {
- finfo->valid |= APR_FINFO_NAME;
- finfo->name = fname;
- finfo->fname = fspec;
- rv = (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
- }
- return rv;
- }
memset(finfo, '\0', sizeof(*finfo));
finfo->name = fname;
@@ -261,8 +246,41 @@
finfo->size = (apr_off_t)thedir->n.entry->nFileSizeLow;
if (finfo->size < 0 || FileInformation.nFileSizeHigh)
finfo->size = 0x7fffffff;
+#endif
+
+ if (thedir->n.entry->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ finfo->protection = APR_FREADONLY;
+
+ if (wanted &= ~finfo->valid) {
+ /* Go back and get more_info if we can't answer the whole inquiry
+ */
+#if APR_HAS_UNICODE_FS
+ if (os_level >= APR_WIN_NT) {
+ /* Almost all our work is done. Tack on the wide file name
+ * to the end of the wdirname (already / delimited)
+ */
+ wcscpy(eos, thedir->w.entry->cFileName);
+ return more_finfo(finfo, wdirname, wanted, MORE_OF_WFSPEC,
os_level);
+ }
+ else {
+ /* Don't waste stack space on a second buffer, the one we set
+ * aside for the wide directory name is twice what we need.
+ */
+ char *fspec = (char*)wdirname;
+#else /* !APR_HAS_UNICODE_FS */
+ {
+ char fspec[APR_PATH_MAX];
#endif
- return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
+ int dirlen = strlen(thedir->dirname);
+ if (dirlen >= sizeof(fspec))
+ dirlen = sizeof(fspec) - 1;
+ apr_cpystrn(fspec, thedir->dirname, sizeof(fspec));
+ apr_cpystrn(fspec + dirlen, fname, sizeof(fspec) - dirlen);
+ return more_finfo(finfo, fspec, wanted, MORE_OF_FSPEC, os_level);
+ }
+ }
+
+ return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *dir)
@@ -323,11 +341,6 @@
}
return APR_SUCCESS;
}
-
-
-
-
-
APR_DECLARE(apr_status_t) apr_get_os_dir(apr_os_dir_t **thedir,
apr_dir_t *dir)