aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorEli Zaretskii <[email protected]>2008-05-09 20:37:32 +0000
committerEli Zaretskii <[email protected]>2008-05-09 20:37:32 +0000
commit10fea9c4d210182a5bb60f0a537e7c8d5fcb9a9a (patch)
tree138a0b0b693b8d725e64e5b9f34cb26fa1e13265 /lib-src
parent6877092ed693b50f487b4b6f4f14e631f4f7045c (diff)
Include sys/types.h, sys/stat.h, and errno.h.
(IS_DIRECTORY_SEP): New macro. (convert_time, is_exec, stat): New functions.
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/ChangeLog6
-rw-r--r--lib-src/ntlib.c147
2 files changed, 153 insertions, 0 deletions
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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <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 @@ 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) */