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