##// END OF EJS Templates
osutil: implementation for Win32...
Petr Kodl -
r7056:2c1f18b8 default
parent child Browse files
Show More
@@ -9,17 +9,41 b''
9
9
10 #define _ATFILE_SOURCE
10 #define _ATFILE_SOURCE
11 #include <Python.h>
11 #include <Python.h>
12 #ifdef _WIN32
13 #include <windows.h>
14 #else
12 #include <dirent.h>
15 #include <dirent.h>
13 #include <fcntl.h>
16 #include <fcntl.h>
14 #include <string.h>
17 #include <string.h>
15 #include <sys/stat.h>
18 #include <sys/stat.h>
16 #include <sys/types.h>
19 #include <sys/types.h>
17 #include <unistd.h>
20 #include <unistd.h>
21 #endif
18
22
23 #ifdef _WIN32
24 /*
25 stat struct compatible with hg expectations
26 Mercurial only uses st_mode, st_size and st_mtime
27 the rest is kept to minimize changes between implementations
28 */
29 struct hg_stat {
30 int st_dev;
31 int st_mode;
32 int st_nlink;
33 __int64 st_size;
34 int st_mtime;
35 int st_ctime;
36 };
37 struct listdir_stat {
38 PyObject_HEAD
39 struct hg_stat st;
40 };
41 #else
19 struct listdir_stat {
42 struct listdir_stat {
20 PyObject_HEAD
43 PyObject_HEAD
21 struct stat st;
44 struct stat st;
22 };
45 };
46 #endif
23
47
24 #define listdir_slot(name) \
48 #define listdir_slot(name) \
25 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
@@ -30,7 +54,15 b' struct listdir_stat {'
30 listdir_slot(st_dev)
54 listdir_slot(st_dev)
31 listdir_slot(st_mode)
55 listdir_slot(st_mode)
32 listdir_slot(st_nlink)
56 listdir_slot(st_nlink)
57 #ifdef _WIN32
58 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
59 {
60 return PyLong_FromLongLong(
61 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
62 }
63 #else
33 listdir_slot(st_size)
64 listdir_slot(st_size)
65 #endif
34 listdir_slot(st_mtime)
66 listdir_slot(st_mtime)
35 listdir_slot(st_ctime)
67 listdir_slot(st_ctime)
36
68
@@ -96,6 +128,142 b' static PyTypeObject listdir_stat_type = '
96 listdir_stat_new, /* tp_new */
128 listdir_stat_new, /* tp_new */
97 };
129 };
98
130
131 #ifdef _WIN32
132
133 static int to_python_time(const FILETIME *tm)
134 {
135 /* number of seconds between epoch and January 1 1601 */
136 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
137 /* conversion factor from 100ns to 1s */
138 const __int64 a1 = 10000000;
139 /* explicit (int) cast to suspend compiler warnings */
140 return (int)((((__int64)tm->dwHighDateTime << 32)
141 + tm->dwLowDateTime) / a1 - a0);
142 }
143
144 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
145 {
146 PyObject *py_st;
147 struct hg_stat *stp;
148
149 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
150 ? _S_IFDIR : _S_IFREG;
151
152 if (!wantstat)
153 return Py_BuildValue("si", fd->cFileName, kind);
154
155 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
156 if (!py_st)
157 return NULL;
158
159 stp = &((struct listdir_stat *)py_st)->st;
160 /*
161 use kind as st_mode
162 rwx bits on Win32 are meaningless
163 and Hg does not use them anyway
164 */
165 stp->st_mode = kind;
166 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
167 stp->st_ctime = to_python_time(&fd->ftCreationTime);
168 if (kind == _S_IFREG)
169 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
170 + fd->nFileSizeLow;
171 return Py_BuildValue("siN", fd->cFileName,
172 kind, py_st);
173 }
174
175 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
176 {
177 PyObject *rval = NULL; /* initialize - return value */
178 PyObject *statobj = NULL; /* initialize - optional arg */
179 PyObject *list;
180 HANDLE fh;
181 WIN32_FIND_DATAA fd;
182 char *path, *pattern, *skip = NULL;
183 int plen, wantstat;
184
185 static char *kwlist[] = {"path", "stat", "skip", NULL};
186
187 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir",
188 kwlist, &path, &plen, &statobj, &skip))
189 goto error_parse;
190
191 wantstat = statobj && PyObject_IsTrue(statobj);
192
193 /* build the path + \* pattern string */
194 pattern = malloc(plen+3); /* path + \* + \0 */
195 if (!pattern) {
196 PyErr_NoMemory();
197 goto error_parse;
198 }
199 strcpy(pattern, path);
200
201 if (plen > 0) {
202 char c = path[plen-1];
203 if (c != ':' && c != '/' && c != '\\')
204 pattern[plen++] = '\\';
205 }
206 strcpy(pattern + plen, "*");
207
208 fh = FindFirstFileA(pattern, &fd);
209 if (fh == INVALID_HANDLE_VALUE) {
210 PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,
211 GetLastError(),
212 path);
213 goto error_file;
214 }
215
216 list = PyList_New(0);
217 if (!list)
218 goto error_list;
219
220 do {
221 PyObject *item;
222
223 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
224 if (!strcmp(fd.cFileName, ".")
225 || !strcmp(fd.cFileName, ".."))
226 continue;
227
228 if (skip && !strcmp(fd.cFileName, skip)) {
229 rval = PyList_New(0);
230 goto error;
231 }
232 }
233
234 item = make_item(&fd, wantstat);
235 if (!item)
236 goto error;
237
238 if (PyList_Append(list, item)) {
239 Py_XDECREF(item);
240 goto error;
241 }
242
243 Py_XDECREF(item);
244 } while (FindNextFileA(fh, &fd));
245
246 if (GetLastError() != ERROR_NO_MORE_FILES) {
247 PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,
248 GetLastError(),
249 path);
250 goto error;
251 }
252
253 rval = list;
254 Py_XINCREF(rval);
255 error:
256 Py_XDECREF(list);
257 error_list:
258 FindClose(fh);
259 error_file:
260 free(pattern);
261 error_parse:
262 return rval;
263 }
264
265 #else
266
99 int entkind(struct dirent *ent)
267 int entkind(struct dirent *ent)
100 {
268 {
101 #ifdef DT_REG
269 #ifdef DT_REG
@@ -214,6 +382,8 b' error_parse:'
214 return ret;
382 return ret;
215 }
383 }
216
384
385 #endif /* ndef _WIN32 */
386
217 static char osutil_doc[] = "Native operating system services.";
387 static char osutil_doc[] = "Native operating system services.";
218
388
219 static PyMethodDef methods[] = {
389 static PyMethodDef methods[] = {
@@ -102,6 +102,12 b" packages = ['mercurial', 'mercurial.hgwe"
102 'hgext.highlight']
102 'hgext.highlight']
103
103
104 try:
104 try:
105 import msvcrt
106 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
107 except ImportError:
108 pass
109
110 try:
105 import posix
111 import posix
106 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
112 ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
107
113
General Comments 0
You need to be logged in to leave comments. Login now