Mercurial > emacs
changeset 94823:7f11d589b5ad
Include sys/types.h, sys/stat.h, and errno.h.
(IS_DIRECTORY_SEP): New macro.
(convert_time, is_exec, stat): New functions.
author | Eli Zaretskii <eliz@gnu.org> |
---|---|
date | Fri, 09 May 2008 20:37:04 +0000 |
parents | e93f071bc17a |
children | 049f8debb0ac |
files | lib-src/ntlib.c |
diffstat | 1 files changed, 147 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/lib-src/ntlib.c Fri May 09 20:28:54 2008 +0000 +++ b/lib-src/ntlib.c Fri May 09 20:37:04 2008 +0000 @@ -27,6 +27,9 @@ #include <stdio.h> #include <time.h> #include <direct.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> #include "ntlib.h" @@ -210,5 +213,149 @@ return _chdir (path); } +static FILETIME utc_base_ft; +static long double utc_base; +static int init = 0; + +static time_t +convert_time (FILETIME ft) +{ + long double ret; + + if (CompareFileTime (&ft, &utc_base_ft) < 0) + return 0; + + ret = (long double) ft.dwHighDateTime + * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime; + ret -= utc_base; + return (time_t) (ret * 1e-7L); +} + +static int +is_exec (const char * name) +{ + char * p = strrchr (name, '.'); + return + (p != NULL + && (stricmp (p, ".exe") == 0 || + stricmp (p, ".com") == 0 || + stricmp (p, ".bat") == 0 || + stricmp (p, ".cmd") == 0)); +} + +#define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\') + +/* We need this because nt/inc/sys/stat.h defines struct stat that is + incompatible with the MS run-time libraries. */ +int +stat (const char * path, struct stat * buf) +{ + WIN32_FIND_DATA wfd; + HANDLE fh; + int permission; + int len; + int rootdir = FALSE; + char *name = alloca (FILENAME_MAX); + + if (!init) + { + /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ + SYSTEMTIME st; + + st.wYear = 1970; + st.wMonth = 1; + st.wDay = 1; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + + SystemTimeToFileTime (&st, &utc_base_ft); + utc_base = (long double) utc_base_ft.dwHighDateTime + * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime; + init = 1; + } + + if (path == NULL || buf == NULL || *path == '\0') + { + errno = EFAULT; + return -1; + } + if (_mbspbrk (path, "*?|<>\"")) + { + errno = ENOENT; + return -1; + } + + strcpy (name, path); + /* Remove trailing directory separator, unless name is the root + directory of a drive in which case ensure there is a trailing + separator. */ + len = strlen (name); + rootdir = IS_DIRECTORY_SEP (name[0]) + || (len == 3 && name[1] == ':' && IS_DIRECTORY_SEP (name[2])); + if (rootdir) + { + if (GetDriveType (name) < 2) + { + errno = ENOENT; + return -1; + } + memset (&wfd, 0, sizeof (wfd)); + wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + wfd.ftCreationTime = utc_base_ft; + wfd.ftLastAccessTime = utc_base_ft; + wfd.ftLastWriteTime = utc_base_ft; + strcpy (wfd.cFileName, name); + } + else + { + if (IS_DIRECTORY_SEP (name[len-1])) + name[len - 1] = 0; + + fh = FindFirstFile (name, &wfd); + if (fh == INVALID_HANDLE_VALUE) + { + errno = ENOENT; + return -1; + } + FindClose (fh); + } + buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? + S_IFDIR : S_IFREG; + buf->st_nlink = 1; + buf->st_ino = 0; + + if (name[0] && name[1] == ':') + buf->st_dev = tolower (name[0]) - 'a' + 1; + else + buf->st_dev = _getdrive (); + buf->st_rdev = buf->st_dev; + + buf->st_size = wfd.nFileSizeLow; + + /* Convert timestamps to Unix format. */ + buf->st_mtime = convert_time (wfd.ftLastWriteTime); + buf->st_atime = convert_time (wfd.ftLastAccessTime); + if (buf->st_atime == 0) buf->st_atime = buf->st_mtime; + buf->st_ctime = convert_time (wfd.ftCreationTime); + if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime; + + /* determine rwx permissions */ + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + permission = S_IREAD; + else + permission = S_IREAD | S_IWRITE; + + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + permission |= S_IEXEC; + else if (is_exec (name)) + permission |= S_IEXEC; + + buf->st_mode |= permission | (permission >> 3) | (permission >> 6); + + return 0; +} + /* arch-tag: 7b63fb83-70ee-4124-8822-54e53e5d0773 (do not change this comment) */