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