[PATCH] osutil.c: minimal Win32 implementation - no unicode and fancy exe flags
Petr Kodl
petrkodl at gmail.com
Tue Sep 9 03:01:12 UTC 2008
# HG changeset patch
# User Petr Kodl <petrkodl at gmail.com>
# Date 1220929179 14400
# Node ID 5d3d651b86c02a0b8b4fbfd022ebf9b71b6b5ec0
# Parent 9141bebefe3ed0498ff07271214bfca8b4eb0d27
osutil: implementation for Win32
diff -r 9141bebefe3e -r 5d3d651b86c0 mercurial/osutil.c
--- a/mercurial/osutil.c Mon Sep 08 14:22:14 2008 +0200
+++ b/mercurial/osutil.c Mon Sep 08 22:59:39 2008 -0400
@@ -9,16 +9,37 @@
#define _ATFILE_SOURCE
#include <Python.h>
+#include <string.h>
+#ifdef _WIN32
+#include <windows.h>
+#include <malloc.h> /* for _alloca */
+#else
#include <dirent.h>
#include <fcntl.h>
-#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+/*
+minimal stat struct compatible with hg expectations
+supporting large files (64 bit size)
+*/
+struct non_posix_stat
+{
+ int st_mode;
+ __int64 st_size;
+ int st_mtime;
+};
+typedef struct non_posix_stat hg_stat;
+#else
+typedef struct stat hg_stat;
+#endif
struct listdir_stat {
PyObject_HEAD
- struct stat st;
+ hg_stat st;
};
#define listdir_slot(name) \
@@ -27,20 +48,32 @@
return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
}
+#ifndef _WIN32
listdir_slot(st_dev)
+listdir_slot(st_nlink)
+listdir_slot(st_ctime)
+#endif
+listdir_slot(st_mtime)
listdir_slot(st_mode)
-listdir_slot(st_nlink)
+#ifdef _WIN32
+static PyObject *listdir_stat_st_size(PyObject *self, void *x)
+{
+ return PyLong_FromLongLong(
+ (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
+}
+#else
listdir_slot(st_size)
-listdir_slot(st_mtime)
-listdir_slot(st_ctime)
+#endif
static struct PyGetSetDef listdir_stat_getsets[] = {
- {"st_dev", listdir_stat_st_dev, 0, 0, 0},
- {"st_mode", listdir_stat_st_mode, 0, 0, 0},
+#ifndef _WIN32
+ {"st_dev", listdir_stat_st_dev, 0, 0, 0},
{"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
+ {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
+#endif
+ {"st_mode", listdir_stat_st_mode, 0, 0, 0},
{"st_size", listdir_stat_st_size, 0, 0, 0},
{"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
- {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
{0, 0, 0, 0, 0}
};
@@ -95,6 +128,120 @@
0, /* tp_alloc */
listdir_stat_new, /* tp_new */
};
+
+#ifdef _WIN32
+
+static int to_python_time(FILETIME* ms_time)
+{
+ /* this is number of 100-nanoseconds between epoch and January 1 1601 */
+ static __int64 a0 = (__int64)134774L * (__int64)24L
+ *(__int64)3600L * (__int64)1000L
+ *(__int64)1000L * (__int64)10L;
+ /* conversion factor back to 1s resolution required by Python ctime */
+ static __int64 a1 = 1000 * 1000 * 10;
+ __int64 tmp;
+ memcpy(&tmp, ms_time, sizeof(__int64));
+ return (int)((tmp - a0) / a1);
+}
+
+static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyObject *statobj = NULL,
+ *list = NULL,
+ *items = NULL,
+ *ctor_args = NULL,
+ *item0 = NULL,
+ *item1 = NULL,
+ *py_st = NULL;
+ HANDLE fh = INVALID_HANDLE_VALUE;
+ WIN32_FIND_DATAA fd;
+ hg_stat* stp=NULL;
+ char path[_MAX_PATH + 1];
+ char *buffer=path;
+ int plen = _MAX_PATH-2;
+ int keepstat = 0;
+
+ static char *kwlist[] = { "path", "stat", NULL };
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "et#|O:listdir",
+ kwlist, Py_FileSystemDefaultEncoding, &buffer, &plen, &statobj))
+ goto error;
+ keepstat= statobj && PyObject_IsTrue(statobj);
+ if (plen > 0 && path[plen - 1] != ':'
+ && path[plen - 1] != '/' && path[plen - 1] != '\\')
+ path[plen++] = '\\';
+ strcpy(path + plen, "*");
+ fh = FindFirstFileA(path, &fd);
+ if (INVALID_HANDLE_VALUE == fh) {
+ PyErr_SetExcFromWindowsErr(PyExc_OSError, GetLastError());
+ goto error;
+ }
+ list = PyList_New(0);
+ ctor_args = PyTuple_New(0);
+ if (!list || !ctor_args) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ do {
+ int isdir = fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ int isro = fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY;
+
+ if (isdir && (!strcmp(fd.cFileName, ".") || !strcmp(fd.cFileName, "..")))
+ continue;
+ items = PyTuple_New(keepstat ? 3 : 2);
+ item0 = PyString_FromString(fd.cFileName);
+ item1 = PyInt_FromLong(isdir ? _S_IFDIR : _S_IFREG);
+ if (!items || !item0 || !item1) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ PyTuple_SetItem(items, 0, item0);
+ PyTuple_SetItem(items, 1, item1);
+ item0 = item1 = NULL;
+ if (keepstat) {
+ py_st = PyObject_CallObject(
+ (PyObject *)&listdir_stat_type,
+ ctor_args);
+ if (!py_st) {
+ PyErr_NoMemory();
+ goto error;
+ }
+ stp = &((struct listdir_stat *)py_st)->st;
+ stp->st_mtime = to_python_time(&fd.ftLastWriteTime);
+ stp->st_size = isdir ? 0
+ : (((__int64)fd.nFileSizeHigh) << 32)
+ + fd.nFileSizeLow;
+ stp->st_mode = (isdir ? (S_IFDIR | 0111) : S_IFREG)
+ | (isro ? 0444 : 0666);
+ PyTuple_SET_ITEM(items, 2, py_st);
+ py_st = NULL;
+ }
+ if (PyList_Append(list, items))
+ goto error;
+ Py_XDECREF(items);
+ items = NULL;
+ }
+ while (FindNextFileA(fh, &fd));
+ if (GetLastError()!=ERROR_NO_MORE_FILES || !FindClose(fh)) {
+ PyErr_SetExcFromWindowsErr(PyExc_OSError, GetLastError());
+ goto error;
+ }
+ fh = INVALID_HANDLE_VALUE;
+ if (PyList_Sort(list))
+ goto error;
+ goto ok;
+error:
+ Py_XDECREF(list);
+ list = NULL;
+ Py_XDECREF(items);
+ Py_XDECREF(item0);
+ Py_XDECREF(item1);
+ if (fh!=INVALID_HANDLE_VALUE) FindClose(fh);
+ok:
+ Py_XDECREF(ctor_args);
+ return list;
+}
+
+#else
static PyObject *listfiles(PyObject *list, DIR *dir,
int keep_stat, int *need_stat)
@@ -295,7 +442,7 @@
closedir(dir);
return err ? err : list;
}
-
+#endif
static char osutil_doc[] = "Native operating system services.";
diff -r 9141bebefe3e -r 5d3d651b86c0 setup.py
--- a/setup.py Mon Sep 08 14:22:14 2008 +0200
+++ b/setup.py Mon Sep 08 22:59:39 2008 -0400
@@ -102,6 +102,12 @@
'hgext.highlight']
try:
+ import msvcrt
+ ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
+except ImportError:
+ pass
+
+try:
import posix
ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
More information about the Mercurial-devel
mailing list