]> granicus.if.org Git - php/commitdiff
stat() is reimplemented using using GetFileAttributesEx().
authorDmitry Stogov <dmitry@php.net>
Fri, 10 Nov 2006 15:04:19 +0000 (15:04 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 10 Nov 2006 15:04:19 +0000 (15:04 +0000)
The new implementation is faster then implementation in MS VC CRT, but it doesn't support Windows 95.

TSRM/tsrm_virtual_cwd.c
TSRM/tsrm_virtual_cwd.h

index 30c83f06cf9020a679cced53a235933ce56aef02..15d30d074293f9075095fb48e9dcb5b1594edf4d 100644 (file)
@@ -140,11 +140,93 @@ static int php_check_dots(const char *element, int n)
 #define CWD_STATE_FREE(s)                      \
        free((s)->cwd);
        
+#ifdef TSRM_WIN32
+CWD_API int php_sys_stat(const char *path, struct stat *buf)
+{
+       WIN32_FILE_ATTRIBUTE_DATA data;
+       __int64 t;
+
+       if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data)) {
+               return stat(path, buf);
+       }
+
+       if (path[1] == ':') {
+               if (path[0] >= 'A' && path[0] <= 'Z') {
+                       buf->st_dev = buf->st_rdev = path[0] - 'A';
+               } else {
+                       buf->st_dev = buf->st_rdev = path[0] - 'a';
+               }
+       } else {
+               char  cur_path[MAXPATHLEN+1];
+               DWORD len = sizeof(cur_path);
+               char *tmp = cur_path;
+
+               while(1) {
+                       DWORD r = GetCurrentDirectory(len, tmp);
+                       if (r < len) {
+                               if (tmp[1] == ':') {
+                                       if (path[0] >= 'A' && path[0] <= 'Z') {
+                                               buf->st_dev = buf->st_rdev = path[0] - 'A';
+                                       } else {
+                                               buf->st_dev = buf->st_rdev = path[0] - 'a';
+                                       }
+                               } else {
+                                       buf->st_dev = buf->st_rdev = -1;
+                               }
+                               break;
+                       } else if (!r) {
+                               buf->st_dev = buf->st_rdev = -1;
+                               break;
+                       } else {
+                               len = r+1;
+                               tmp = (char*)malloc(len);
+                       }
+               }
+               if (tmp != cur_path) {
+                       free(tmp);
+               }                       
+       }
+       buf->st_uid = buf->st_gid = buf->st_ino = 0;
+       buf->st_mode = (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? (S_IFDIR|S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)) : S_IFREG;
+       buf->st_mode |= (data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) : (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)|S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6));
+       if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+               int len = strlen(path);
+
+               if (path[len-4] == '.') {
+                       if (_memicmp(path+len-3, "exe", 3) == 0 ||
+                           _memicmp(path+len-3, "com", 3) == 0 ||
+                           _memicmp(path+len-3, "bat", 3) == 0 ||
+                           _memicmp(path+len-3, "cmd", 3) == 0) {
+                               buf->st_mode  |= (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
+                       }
+               }
+       }                       
+    buf->st_nlink = 1;
+       t = data.nFileSizeHigh;
+       t = t << 32;
+       t |= data.nFileSizeLow;
+       buf->st_size = t;
+       t = data.ftLastAccessTime.dwHighDateTime;
+       t = t << 32;
+       t |= data.ftLastAccessTime.dwLowDateTime;
+       buf->st_atime = (unsigned long)((t / 10000000) - 11644473600);
+       t = data.ftCreationTime.dwHighDateTime;
+       t = t << 32;
+       t |= data.ftCreationTime.dwLowDateTime;
+       buf->st_ctime = (unsigned long)((t / 10000000) - 11644473600);
+       t = data.ftLastWriteTime.dwHighDateTime;
+       t = t << 32;
+       t |= data.ftLastWriteTime.dwLowDateTime;
+       buf->st_mtime = (unsigned long)((t / 10000000) - 11644473600);
+       return 0;
+}
+#endif
+
 static int php_is_dir_ok(const cwd_state *state) 
 {
        struct stat buf;
 
-       if (stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
+       if (php_sys_stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
                return (0);
 
        return (1);
@@ -154,7 +236,7 @@ static int php_is_file_ok(const cwd_state *state)
 {
        struct stat buf;
 
-       if (stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
+       if (php_sys_stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
                return (0);
 
        return (1);
@@ -838,7 +920,7 @@ CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC)
                return -1;
        }
 
-       retval = stat(new_state.cwd, buf);
+       retval = php_sys_stat(new_state.cwd, buf);
 
        CWD_STATE_FREE(&new_state);
        return retval;
index e4f63afa7e58007fcf852aebcac0b5fb4fb67509..a6ff18c5fc012dfed805ba5b87ad3ac0b274ad6c 100644 (file)
@@ -143,6 +143,12 @@ typedef unsigned short mode_t;
 #define CWD_API
 #endif
 
+#ifdef TSRM_WIN32
+CWD_API int php_sys_stat(const char *path, struct stat *buf);
+#else
+# define php_sys_stat stat
+#endif
+
 typedef struct _cwd_state {
        char *cwd;
        int cwd_length;
@@ -280,7 +286,7 @@ extern virtual_cwd_globals cwd_globals;
 #define VCWD_CHDIR(path) chdir(path)
 #define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir)
 #define VCWD_GETWD(buf) getwd(buf)
-#define VCWD_STAT(path, buff) stat(path, buff)
+#define VCWD_STAT(path, buff) php_sys_stat(path, buff)
 #define VCWD_LSTAT(path, buff) lstat(path, buff)
 #define VCWD_UNLINK(path) unlink(path)
 #define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode)