From 10fea9c4d210182a5bb60f0a537e7c8d5fcb9a9a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 9 May 2008 20:37:32 +0000 Subject: [PATCH] Include sys/types.h, sys/stat.h, and errno.h. (IS_DIRECTORY_SEP): New macro. (convert_time, is_exec, stat): New functions. --- lib-src/ChangeLog | 6 ++ lib-src/ntlib.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+) diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 1b64f54cbd..d044149647 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,9 @@ +2008-05-09 Eli Zaretskii + + * ntlib.c: Include sys/types.h, sys/stat.h, and errno.h. + (IS_DIRECTORY_SEP): New macro. + (convert_time, is_exec, stat): New functions. + 2008-05-08 Eli Zaretskii * makefile.w32-in (lisp2): Rename epa-file-hook.elc to epa-hook.elc. diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 67533894ac..4cfb7ad062 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -27,6 +27,9 @@ Boston, MA 02110-1301, USA. #include #include #include +#include +#include +#include #include "ntlib.h" @@ -210,5 +213,149 @@ sys_chdir (const char * path) 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) */ -- 2.20.1