equal
deleted
inserted
replaced
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 #include <Python.h> |
11 #include <Python.h> |
11 #include <dirent.h> |
12 #include <dirent.h> |
12 #include <fcntl.h> |
13 #include <fcntl.h> |
13 #include <string.h> |
14 #include <string.h> |
14 #include <sys/stat.h> |
15 #include <sys/stat.h> |
15 #include <sys/types.h> |
16 #include <sys/types.h> |
16 #include <unistd.h> |
17 #include <unistd.h> |
17 |
|
18 #if defined(__sun) |
|
19 #define dirfd(dir) ((dir)->dd_fd) |
|
20 #endif |
|
21 |
18 |
22 struct listdir_stat { |
19 struct listdir_stat { |
23 PyObject_HEAD |
20 PyObject_HEAD |
24 struct stat st; |
21 struct stat st; |
25 }; |
22 }; |
163 |
160 |
164 return 0; |
161 return 0; |
165 } |
162 } |
166 |
163 |
167 static PyObject *statfiles(PyObject *list, PyObject *ctor_args, int keep, |
164 static PyObject *statfiles(PyObject *list, PyObject *ctor_args, int keep, |
168 char *path, int len, DIR *dir) |
165 char *path, int len, int dfd) |
169 { |
166 { |
170 struct stat buf; |
167 struct stat buf; |
171 struct stat *stp = &buf; |
168 struct stat *stp = &buf; |
172 int kind; |
169 int kind; |
173 int ret; |
170 int ret; |
194 return PyErr_NoMemory(); |
191 return PyErr_NoMemory(); |
195 stp = &((struct listdir_stat *)py_st)->st; |
192 stp = &((struct listdir_stat *)py_st)->st; |
196 PyTuple_SET_ITEM(elt, 2, py_st); |
193 PyTuple_SET_ITEM(elt, 2, py_st); |
197 } |
194 } |
198 |
195 |
|
196 #ifdef AT_SYMLINK_NOFOLLOW |
|
197 ret = fstatat(dfd, name, stp, AT_SYMLINK_NOFOLLOW); |
|
198 #else |
199 ret = lstat(path, stp); |
199 ret = lstat(path, stp); |
|
200 #endif |
200 if (ret == -1) |
201 if (ret == -1) |
201 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, |
202 return PyErr_SetFromErrnoWithFilename(PyExc_OSError, |
202 path); |
203 path); |
203 |
204 |
204 if (kind == -1) { |
205 if (kind == -1) { |
242 PyObject *ctor_args = NULL; |
243 PyObject *ctor_args = NULL; |
243 char *path; |
244 char *path; |
244 char full_path[PATH_MAX + 10]; |
245 char full_path[PATH_MAX + 10]; |
245 int path_len; |
246 int path_len; |
246 int need_stat, keep_stat; |
247 int need_stat, keep_stat; |
|
248 int dfd; |
247 |
249 |
248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist, |
250 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist, |
249 &path, &path_len, &statobj)) |
251 &path, &path_len, &statobj)) |
250 goto bail; |
252 goto bail; |
251 |
253 |
252 keep_stat = statobj && PyObject_IsTrue(statobj); |
254 keep_stat = statobj && PyObject_IsTrue(statobj); |
253 |
255 |
|
256 #ifdef AT_SYMLINK_NOFOLLOW |
|
257 dfd = open(path, O_RDONLY); |
|
258 dir = fdopendir(dfd); |
|
259 #else |
254 dir = opendir(path); |
260 dir = opendir(path); |
|
261 dfd = -1; |
|
262 #endif |
255 if (!dir) { |
263 if (!dir) { |
256 err = PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); |
264 err = PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); |
257 goto bail; |
265 goto bail; |
258 } |
266 } |
259 |
267 |
272 PyList_Sort(list); |
280 PyList_Sort(list); |
273 |
281 |
274 if (!keep_stat && !need_stat) |
282 if (!keep_stat && !need_stat) |
275 goto done; |
283 goto done; |
276 |
284 |
277 err = statfiles(list, ctor_args, keep_stat, full_path, path_len, dir); |
285 err = statfiles(list, ctor_args, keep_stat, full_path, path_len, dfd); |
278 if (!err) |
286 if (!err) |
279 goto done; |
287 goto done; |
280 |
288 |
281 bail: |
289 bail: |
282 Py_XDECREF(list); |
290 Py_XDECREF(list); |