##// END OF EJS Templates
osutil.c: refactor argument parsing, allow skip=None being passed
Benoit Boissinot -
r7098:8a5c88c7 default
parent child Browse files
Show More
@@ -1,398 +1,406 b''
1 /*
1 /*
2 osutil.c - native operating system services
2 osutil.c - native operating system services
3
3
4 Copyright 2007 Matt Mackall and others
4 Copyright 2007 Matt Mackall and others
5
5
6 This software may be used and distributed according to the terms of
6 This software may be used and distributed according to the terms of
7 the GNU General Public License, incorporated herein by reference.
7 the GNU General Public License, incorporated herein by reference.
8 */
8 */
9
9
10 #define _ATFILE_SOURCE
10 #define _ATFILE_SOURCE
11 #include <Python.h>
11 #include <Python.h>
12 #ifdef _WIN32
12 #ifdef _WIN32
13 #include <windows.h>
13 #include <windows.h>
14 #else
14 #else
15 #include <dirent.h>
15 #include <dirent.h>
16 #include <fcntl.h>
16 #include <fcntl.h>
17 #include <string.h>
17 #include <string.h>
18 #include <sys/stat.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
19 #include <sys/types.h>
20 #include <unistd.h>
20 #include <unistd.h>
21 #endif
21 #endif
22
22
23 #ifdef _WIN32
23 #ifdef _WIN32
24 /*
24 /*
25 stat struct compatible with hg expectations
25 stat struct compatible with hg expectations
26 Mercurial only uses st_mode, st_size and st_mtime
26 Mercurial only uses st_mode, st_size and st_mtime
27 the rest is kept to minimize changes between implementations
27 the rest is kept to minimize changes between implementations
28 */
28 */
29 struct hg_stat {
29 struct hg_stat {
30 int st_dev;
30 int st_dev;
31 int st_mode;
31 int st_mode;
32 int st_nlink;
32 int st_nlink;
33 __int64 st_size;
33 __int64 st_size;
34 int st_mtime;
34 int st_mtime;
35 int st_ctime;
35 int st_ctime;
36 };
36 };
37 struct listdir_stat {
37 struct listdir_stat {
38 PyObject_HEAD
38 PyObject_HEAD
39 struct hg_stat st;
39 struct hg_stat st;
40 };
40 };
41 #else
41 #else
42 struct listdir_stat {
42 struct listdir_stat {
43 PyObject_HEAD
43 PyObject_HEAD
44 struct stat st;
44 struct stat st;
45 };
45 };
46 #endif
46 #endif
47
47
48 #define listdir_slot(name) \
48 #define listdir_slot(name) \
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
49 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
50 { \
50 { \
51 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
51 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
52 }
52 }
53
53
54 listdir_slot(st_dev)
54 listdir_slot(st_dev)
55 listdir_slot(st_mode)
55 listdir_slot(st_mode)
56 listdir_slot(st_nlink)
56 listdir_slot(st_nlink)
57 #ifdef _WIN32
57 #ifdef _WIN32
58 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
58 static PyObject *listdir_stat_st_size(PyObject *self, void *x)
59 {
59 {
60 return PyLong_FromLongLong(
60 return PyLong_FromLongLong(
61 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
61 (PY_LONG_LONG)((struct listdir_stat *)self)->st.st_size);
62 }
62 }
63 #else
63 #else
64 listdir_slot(st_size)
64 listdir_slot(st_size)
65 #endif
65 #endif
66 listdir_slot(st_mtime)
66 listdir_slot(st_mtime)
67 listdir_slot(st_ctime)
67 listdir_slot(st_ctime)
68
68
69 static struct PyGetSetDef listdir_stat_getsets[] = {
69 static struct PyGetSetDef listdir_stat_getsets[] = {
70 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
70 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
71 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
71 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
72 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
72 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
73 {"st_size", listdir_stat_st_size, 0, 0, 0},
73 {"st_size", listdir_stat_st_size, 0, 0, 0},
74 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
74 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
75 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
75 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
76 {0, 0, 0, 0, 0}
76 {0, 0, 0, 0, 0}
77 };
77 };
78
78
79 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
79 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
80 {
80 {
81 return t->tp_alloc(t, 0);
81 return t->tp_alloc(t, 0);
82 }
82 }
83
83
84 static void listdir_stat_dealloc(PyObject *o)
84 static void listdir_stat_dealloc(PyObject *o)
85 {
85 {
86 o->ob_type->tp_free(o);
86 o->ob_type->tp_free(o);
87 }
87 }
88
88
89 static PyTypeObject listdir_stat_type = {
89 static PyTypeObject listdir_stat_type = {
90 PyObject_HEAD_INIT(NULL)
90 PyObject_HEAD_INIT(NULL)
91 0, /*ob_size*/
91 0, /*ob_size*/
92 "osutil.stat", /*tp_name*/
92 "osutil.stat", /*tp_name*/
93 sizeof(struct listdir_stat), /*tp_basicsize*/
93 sizeof(struct listdir_stat), /*tp_basicsize*/
94 0, /*tp_itemsize*/
94 0, /*tp_itemsize*/
95 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
95 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
96 0, /*tp_print*/
96 0, /*tp_print*/
97 0, /*tp_getattr*/
97 0, /*tp_getattr*/
98 0, /*tp_setattr*/
98 0, /*tp_setattr*/
99 0, /*tp_compare*/
99 0, /*tp_compare*/
100 0, /*tp_repr*/
100 0, /*tp_repr*/
101 0, /*tp_as_number*/
101 0, /*tp_as_number*/
102 0, /*tp_as_sequence*/
102 0, /*tp_as_sequence*/
103 0, /*tp_as_mapping*/
103 0, /*tp_as_mapping*/
104 0, /*tp_hash */
104 0, /*tp_hash */
105 0, /*tp_call*/
105 0, /*tp_call*/
106 0, /*tp_str*/
106 0, /*tp_str*/
107 0, /*tp_getattro*/
107 0, /*tp_getattro*/
108 0, /*tp_setattro*/
108 0, /*tp_setattro*/
109 0, /*tp_as_buffer*/
109 0, /*tp_as_buffer*/
110 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
110 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
111 "stat objects", /* tp_doc */
111 "stat objects", /* tp_doc */
112 0, /* tp_traverse */
112 0, /* tp_traverse */
113 0, /* tp_clear */
113 0, /* tp_clear */
114 0, /* tp_richcompare */
114 0, /* tp_richcompare */
115 0, /* tp_weaklistoffset */
115 0, /* tp_weaklistoffset */
116 0, /* tp_iter */
116 0, /* tp_iter */
117 0, /* tp_iternext */
117 0, /* tp_iternext */
118 0, /* tp_methods */
118 0, /* tp_methods */
119 0, /* tp_members */
119 0, /* tp_members */
120 listdir_stat_getsets, /* tp_getset */
120 listdir_stat_getsets, /* tp_getset */
121 0, /* tp_base */
121 0, /* tp_base */
122 0, /* tp_dict */
122 0, /* tp_dict */
123 0, /* tp_descr_get */
123 0, /* tp_descr_get */
124 0, /* tp_descr_set */
124 0, /* tp_descr_set */
125 0, /* tp_dictoffset */
125 0, /* tp_dictoffset */
126 0, /* tp_init */
126 0, /* tp_init */
127 0, /* tp_alloc */
127 0, /* tp_alloc */
128 listdir_stat_new, /* tp_new */
128 listdir_stat_new, /* tp_new */
129 };
129 };
130
130
131 #ifdef _WIN32
131 #ifdef _WIN32
132
132
133 static int to_python_time(const FILETIME *tm)
133 static int to_python_time(const FILETIME *tm)
134 {
134 {
135 /* number of seconds between epoch and January 1 1601 */
135 /* number of seconds between epoch and January 1 1601 */
136 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
136 const __int64 a0 = (__int64)134774L * (__int64)24L * (__int64)3600L;
137 /* conversion factor from 100ns to 1s */
137 /* conversion factor from 100ns to 1s */
138 const __int64 a1 = 10000000;
138 const __int64 a1 = 10000000;
139 /* explicit (int) cast to suspend compiler warnings */
139 /* explicit (int) cast to suspend compiler warnings */
140 return (int)((((__int64)tm->dwHighDateTime << 32)
140 return (int)((((__int64)tm->dwHighDateTime << 32)
141 + tm->dwLowDateTime) / a1 - a0);
141 + tm->dwLowDateTime) / a1 - a0);
142 }
142 }
143
143
144 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
144 static PyObject *make_item(const WIN32_FIND_DATAA *fd, int wantstat)
145 {
145 {
146 PyObject *py_st;
146 PyObject *py_st;
147 struct hg_stat *stp;
147 struct hg_stat *stp;
148
148
149 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
149 int kind = (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
150 ? _S_IFDIR : _S_IFREG;
150 ? _S_IFDIR : _S_IFREG;
151
151
152 if (!wantstat)
152 if (!wantstat)
153 return Py_BuildValue("si", fd->cFileName, kind);
153 return Py_BuildValue("si", fd->cFileName, kind);
154
154
155 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
155 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
156 if (!py_st)
156 if (!py_st)
157 return NULL;
157 return NULL;
158
158
159 stp = &((struct listdir_stat *)py_st)->st;
159 stp = &((struct listdir_stat *)py_st)->st;
160 /*
160 /*
161 use kind as st_mode
161 use kind as st_mode
162 rwx bits on Win32 are meaningless
162 rwx bits on Win32 are meaningless
163 and Hg does not use them anyway
163 and Hg does not use them anyway
164 */
164 */
165 stp->st_mode = kind;
165 stp->st_mode = kind;
166 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
166 stp->st_mtime = to_python_time(&fd->ftLastWriteTime);
167 stp->st_ctime = to_python_time(&fd->ftCreationTime);
167 stp->st_ctime = to_python_time(&fd->ftCreationTime);
168 if (kind == _S_IFREG)
168 if (kind == _S_IFREG)
169 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
169 stp->st_size = ((__int64)fd->nFileSizeHigh << 32)
170 + fd->nFileSizeLow;
170 + fd->nFileSizeLow;
171 return Py_BuildValue("siN", fd->cFileName,
171 return Py_BuildValue("siN", fd->cFileName,
172 kind, py_st);
172 kind, py_st);
173 }
173 }
174
174
175 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
175 static PyObject *_listdir(char *path, int plen, int wantstat, char *skip)
176 {
176 {
177 PyObject *rval = NULL; /* initialize - return value */
177 PyObject *rval = NULL; /* initialize - return value */
178 PyObject *statobj = NULL; /* initialize - optional arg */
179 PyObject *list;
178 PyObject *list;
180 HANDLE fh;
179 HANDLE fh;
181 WIN32_FIND_DATAA fd;
180 WIN32_FIND_DATAA fd;
182 char *path, *pattern, *skip = NULL;
181 char *pattern;
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
182
193 /* build the path + \* pattern string */
183 /* build the path + \* pattern string */
194 pattern = malloc(plen+3); /* path + \* + \0 */
184 pattern = malloc(plen+3); /* path + \* + \0 */
195 if (!pattern) {
185 if (!pattern) {
196 PyErr_NoMemory();
186 PyErr_NoMemory();
197 goto error_parse;
187 goto error_nomem;
198 }
188 }
199 strcpy(pattern, path);
189 strcpy(pattern, path);
200
190
201 if (plen > 0) {
191 if (plen > 0) {
202 char c = path[plen-1];
192 char c = path[plen-1];
203 if (c != ':' && c != '/' && c != '\\')
193 if (c != ':' && c != '/' && c != '\\')
204 pattern[plen++] = '\\';
194 pattern[plen++] = '\\';
205 }
195 }
206 strcpy(pattern + plen, "*");
196 strcpy(pattern + plen, "*");
207
197
208 fh = FindFirstFileA(pattern, &fd);
198 fh = FindFirstFileA(pattern, &fd);
209 if (fh == INVALID_HANDLE_VALUE) {
199 if (fh == INVALID_HANDLE_VALUE) {
210 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
200 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
211 goto error_file;
201 goto error_file;
212 }
202 }
213
203
214 list = PyList_New(0);
204 list = PyList_New(0);
215 if (!list)
205 if (!list)
216 goto error_list;
206 goto error_list;
217
207
218 do {
208 do {
219 PyObject *item;
209 PyObject *item;
220
210
221 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
211 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
222 if (!strcmp(fd.cFileName, ".")
212 if (!strcmp(fd.cFileName, ".")
223 || !strcmp(fd.cFileName, ".."))
213 || !strcmp(fd.cFileName, ".."))
224 continue;
214 continue;
225
215
226 if (skip && !strcmp(fd.cFileName, skip)) {
216 if (skip && !strcmp(fd.cFileName, skip)) {
227 rval = PyList_New(0);
217 rval = PyList_New(0);
228 goto error;
218 goto error;
229 }
219 }
230 }
220 }
231
221
232 item = make_item(&fd, wantstat);
222 item = make_item(&fd, wantstat);
233 if (!item)
223 if (!item)
234 goto error;
224 goto error;
235
225
236 if (PyList_Append(list, item)) {
226 if (PyList_Append(list, item)) {
237 Py_XDECREF(item);
227 Py_XDECREF(item);
238 goto error;
228 goto error;
239 }
229 }
240
230
241 Py_XDECREF(item);
231 Py_XDECREF(item);
242 } while (FindNextFileA(fh, &fd));
232 } while (FindNextFileA(fh, &fd));
243
233
244 if (GetLastError() != ERROR_NO_MORE_FILES) {
234 if (GetLastError() != ERROR_NO_MORE_FILES) {
245 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
235 PyErr_SetFromWindowsErrWithFilename(GetLastError(), path);
246 goto error;
236 goto error;
247 }
237 }
248
238
249 rval = list;
239 rval = list;
250 Py_XINCREF(rval);
240 Py_XINCREF(rval);
251 error:
241 error:
252 Py_XDECREF(list);
242 Py_XDECREF(list);
253 error_list:
243 error_list:
254 FindClose(fh);
244 FindClose(fh);
255 error_file:
245 error_file:
256 free(pattern);
246 free(pattern);
257 error_parse:
247 error_nomem:
258 return rval;
248 return rval;
259 }
249 }
260
250
261 #else
251 #else
262
252
263 int entkind(struct dirent *ent)
253 int entkind(struct dirent *ent)
264 {
254 {
265 #ifdef DT_REG
255 #ifdef DT_REG
266 switch (ent->d_type) {
256 switch (ent->d_type) {
267 case DT_REG: return S_IFREG;
257 case DT_REG: return S_IFREG;
268 case DT_DIR: return S_IFDIR;
258 case DT_DIR: return S_IFDIR;
269 case DT_LNK: return S_IFLNK;
259 case DT_LNK: return S_IFLNK;
270 case DT_BLK: return S_IFBLK;
260 case DT_BLK: return S_IFBLK;
271 case DT_CHR: return S_IFCHR;
261 case DT_CHR: return S_IFCHR;
272 case DT_FIFO: return S_IFIFO;
262 case DT_FIFO: return S_IFIFO;
273 case DT_SOCK: return S_IFSOCK;
263 case DT_SOCK: return S_IFSOCK;
274 }
264 }
275 #endif
265 #endif
276 return -1;
266 return -1;
277 }
267 }
278
268
279 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
269 static PyObject *_listdir(char *path, int pathlen, int keepstat, char *skip)
280 {
270 {
281 static char *kwlist[] = { "path", "stat", "skip", NULL };
271 PyObject *list, *elem, *stat, *ret = NULL;
282 PyObject *statflag = NULL, *list, *elem, *stat, *ret = NULL;
272 char fullpath[PATH_MAX + 10];
283 char fullpath[PATH_MAX + 10], *path, *skip = NULL;
273 int kind, dfd = -1, err;
284 int pathlen, keepstat, kind, dfd = -1, err;
285 struct stat st;
274 struct stat st;
286 struct dirent *ent;
275 struct dirent *ent;
287 DIR *dir;
276 DIR *dir;
288
277
289 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir", kwlist,
290 &path, &pathlen, &statflag, &skip))
291 goto error_parse;
292
293 if (pathlen >= PATH_MAX) {
278 if (pathlen >= PATH_MAX) {
294 PyErr_SetString(PyExc_ValueError, "path too long");
279 PyErr_SetString(PyExc_ValueError, "path too long");
295 goto error_parse;
280 goto error_value;
296 }
281 }
297 strncpy(fullpath, path, PATH_MAX);
282 strncpy(fullpath, path, PATH_MAX);
298 fullpath[pathlen] = '/';
283 fullpath[pathlen] = '/';
299 keepstat = statflag && PyObject_IsTrue(statflag);
300
284
301 #ifdef AT_SYMLINK_NOFOLLOW
285 #ifdef AT_SYMLINK_NOFOLLOW
302 dfd = open(path, O_RDONLY);
286 dfd = open(path, O_RDONLY);
303 if (dfd == -1) {
287 if (dfd == -1) {
304 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
288 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
305 goto error_parse;
289 goto error_value;
306 }
290 }
307 dir = fdopendir(dfd);
291 dir = fdopendir(dfd);
308 #else
292 #else
309 dir = opendir(path);
293 dir = opendir(path);
310 #endif
294 #endif
311 if (!dir) {
295 if (!dir) {
312 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
296 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
313 goto error_dir;
297 goto error_dir;
314 }
298 }
315
299
316 list = PyList_New(0);
300 list = PyList_New(0);
317 if (!list)
301 if (!list)
318 goto error_list;
302 goto error_list;
319
303
320 while ((ent = readdir(dir))) {
304 while ((ent = readdir(dir))) {
321 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
305 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
322 continue;
306 continue;
323
307
324 kind = entkind(ent);
308 kind = entkind(ent);
325 if (kind == -1 || keepstat) {
309 if (kind == -1 || keepstat) {
326 #ifdef AT_SYMLINK_NOFOLLOW
310 #ifdef AT_SYMLINK_NOFOLLOW
327 err = fstatat(dfd, ent->d_name, &st,
311 err = fstatat(dfd, ent->d_name, &st,
328 AT_SYMLINK_NOFOLLOW);
312 AT_SYMLINK_NOFOLLOW);
329 #else
313 #else
330 strncpy(fullpath + pathlen + 1, ent->d_name,
314 strncpy(fullpath + pathlen + 1, ent->d_name,
331 PATH_MAX - pathlen);
315 PATH_MAX - pathlen);
332 fullpath[PATH_MAX] = 0;
316 fullpath[PATH_MAX] = 0;
333 err = lstat(fullpath, &st);
317 err = lstat(fullpath, &st);
334 #endif
318 #endif
335 if (err == -1) {
319 if (err == -1) {
336 strncpy(fullpath + pathlen + 1, ent->d_name,
320 strncpy(fullpath + pathlen + 1, ent->d_name,
337 PATH_MAX - pathlen);
321 PATH_MAX - pathlen);
338 fullpath[PATH_MAX] = 0;
322 fullpath[PATH_MAX] = 0;
339 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
323 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
340 fullpath);
324 fullpath);
341 goto error;
325 goto error;
342 }
326 }
343 kind = st.st_mode & S_IFMT;
327 kind = st.st_mode & S_IFMT;
344 }
328 }
345
329
346 /* quit early? */
330 /* quit early? */
347 if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
331 if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
348 ret = PyList_New(0);
332 ret = PyList_New(0);
349 goto error;
333 goto error;
350 }
334 }
351
335
352 if (keepstat) {
336 if (keepstat) {
353 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
337 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
354 if (!stat)
338 if (!stat)
355 goto error;
339 goto error;
356 memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
340 memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
357 elem = Py_BuildValue("siN", ent->d_name, kind, stat);
341 elem = Py_BuildValue("siN", ent->d_name, kind, stat);
358 } else
342 } else
359 elem = Py_BuildValue("si", ent->d_name, kind);
343 elem = Py_BuildValue("si", ent->d_name, kind);
360 if (!elem)
344 if (!elem)
361 goto error;
345 goto error;
362
346
363 PyList_Append(list, elem);
347 PyList_Append(list, elem);
364 Py_DECREF(elem);
348 Py_DECREF(elem);
365 }
349 }
366
350
367 ret = list;
351 ret = list;
368 Py_INCREF(ret);
352 Py_INCREF(ret);
369
353
370 error:
354 error:
371 Py_DECREF(list);
355 Py_DECREF(list);
372 error_list:
356 error_list:
373 closedir(dir);
357 closedir(dir);
374 error_dir:
358 error_dir:
375 #ifdef AT_SYMLINK_NOFOLLOW
359 #ifdef AT_SYMLINK_NOFOLLOW
376 close(dfd);
360 close(dfd);
377 #endif
361 #endif
378 error_parse:
362 error_value:
379 return ret;
363 return ret;
380 }
364 }
381
365
382 #endif /* ndef _WIN32 */
366 #endif /* ndef _WIN32 */
383
367
368 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
369 {
370 PyObject *statobj = NULL; /* initialize - optional arg */
371 PyObject *skipobj = NULL; /* initialize - optional arg */
372 char *path, *skip = NULL;
373 int wantstat, plen;
374
375 static char *kwlist[] = {"path", "stat", "skip", NULL};
376
377 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|OO:listdir",
378 kwlist, &path, &plen, &statobj, &skipobj))
379 return NULL;
380
381 wantstat = statobj && PyObject_IsTrue(statobj);
382
383 if (skipobj && skipobj != Py_None) {
384 skip = PyString_AsString(skipobj);
385 if (!skip)
386 return NULL;
387 }
388
389 return _listdir(path, plen, wantstat, skip);
390 }
391
384 static char osutil_doc[] = "Native operating system services.";
392 static char osutil_doc[] = "Native operating system services.";
385
393
386 static PyMethodDef methods[] = {
394 static PyMethodDef methods[] = {
387 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
395 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
388 "list a directory\n"},
396 "list a directory\n"},
389 {NULL, NULL}
397 {NULL, NULL}
390 };
398 };
391
399
392 PyMODINIT_FUNC initosutil(void)
400 PyMODINIT_FUNC initosutil(void)
393 {
401 {
394 if (PyType_Ready(&listdir_stat_type) == -1)
402 if (PyType_Ready(&listdir_stat_type) == -1)
395 return;
403 return;
396
404
397 Py_InitModule3("osutil", methods, osutil_doc);
405 Py_InitModule3("osutil", methods, osutil_doc);
398 }
406 }
General Comments 0
You need to be logged in to leave comments. Login now