stoddard 00/01/31 16:15:13
Modified: src/lib/apr/file_io/win32 filestat.c Log: Reimplement ap_stat using native Windows calls. This is good for a 10% performance boost serving a 500 byte static file. Revision Changes Path 1.6 +66 -7 apache-2.0/src/lib/apr/file_io/win32/filestat.c Index: filestat.c =================================================================== RCS file: /home/cvs/apache-2.0/src/lib/apr/file_io/win32/filestat.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- filestat.c 2000/01/17 23:34:38 1.5 +++ filestat.c 2000/02/01 00:15:11 1.6 @@ -58,15 +58,12 @@ #include "apr_file_io.h" #include "apr_general.h" #include "apr_errno.h" +#include "apr_time.h" #include <sys/stat.h> -#define S_ISLNK(m) (0) -#ifndef S_ISREG -#define S_ISREG(m) (((m)&(S_IFMT)) == (S_IFREG)) -#endif -#ifndef S_ISDIR -#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) -#endif +#define S_ISLNK(m) (0) +#define S_ISREG(m) (((m) & (S_IFMT)) == S_IFREG) +#define S_ISDIR(m) (((m) & (S_IFDIR)) == S_IFDIR) static ap_filetype_e filetype_from_mode(int mode) { @@ -81,6 +78,27 @@ return type; } +BOOLEAN is_exe(const char* fname, ap_context_t *cont) { + const char* exename; + const char* ext; + exename = strrchr(fname, '/'); + if (!exename) { + exename = strrchr(fname, '\\'); + } + if (!exename) { + exename = fname; + } + else { + exename++; + } + ext = strrchr(exename, '.'); + + if (ext && (!strcasecmp(ext,".exe") || !strcasecmp(ext,".com") || + !strcasecmp(ext,".bat") || !strcasecmp(ext,".cmd"))) { + return TRUE; + } + return FALSE; +} ap_status_t ap_getfileinfo(ap_finfo_t *finfo, struct file_t *thefile) { @@ -110,6 +128,46 @@ } ap_status_t ap_stat(ap_finfo_t *finfo, const char *fname, ap_context_t *cont) { + WIN32_FILE_ATTRIBUTE_DATA FileInformation; + + memset(finfo,'\0', sizeof(*finfo)); + + if (!GetFileAttributesEx(fname, GetFileExInfoStandard, &FileInformation)) { + return GetLastError(); + } + /* Filetype - Directory or file? */ + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + finfo->protection |= S_IFDIR; + finfo->filetype = APR_DIR; + } + else { + finfo->protection |= S_IFREG; + finfo->filetype = APR_REG; + } + /* Read, write execute for owner */ + if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + finfo->protection |= S_IREAD; + } + else { + finfo->protection |= S_IREAD; + finfo->protection |= S_IWRITE; + } + /* Is this an executable? Guess based on the file extension. */ + if (is_exe(fname, cont)) { + finfo->protection |= S_IEXEC; + } + /* File times */ + FileTimeToAprTime(&finfo->atime, &FileInformation.ftLastAccessTime); + FileTimeToAprTime(&finfo->ctime, &FileInformation.ftCreationTime); + FileTimeToAprTime(&finfo->mtime, &FileInformation.ftLastWriteTime); + + /* File size + * Note: This cannot handle files greater than can be held by an int */ + finfo->size = FileInformation.nFileSizeLow; + + return APR_SUCCESS; +#if 0 + /* ap_stat implemented using stat() */ struct stat info; int rv = stat(fname, &info); if (rv == 0) { @@ -127,5 +185,6 @@ else { return errno; } +#endif }