4763.2.4
by John Arbash Meinel
merge bzr.2.1 in preparation for NEWS entry. |
1 |
# Copyright (C) 2006, 2008, 2009, 2010 Canonical Ltd
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
2 |
#
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
4183.7.1
by Sabin Iacob
update FSF mailing address |
15 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
16 |
|
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
17 |
"""Wrapper for readdir which returns files ordered by inode."""
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
18 |
|
19 |
||
20 |
import os |
|
21 |
import sys |
|
22 |
||
3731.1.1
by Robert Collins
* The C extensions now build on python 2.4 (Robert Collins, #271939) |
23 |
#python2.4 support
|
24 |
cdef extern from "python-compat.h": |
|
25 |
pass
|
|
26 |
||
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
27 |
|
28 |
cdef extern from 'errno.h': |
|
29 |
int ENOENT |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
30 |
int ENOTDIR |
31 |
int EAGAIN |
|
3766.1.5
by Martin Pool
add missing pyrex import |
32 |
int EINTR |
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
33 |
char *strerror(int errno) |
34 |
# not necessarily a real variable, but this should be close enough
|
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
35 |
int errno |
36 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
37 |
cdef extern from 'unistd.h': |
38 |
int chdir(char *path) |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
39 |
int close(int fd) |
40 |
int fchdir(int fd) |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
41 |
char *getcwd(char *, int size) |
42 |
||
43 |
cdef extern from 'stdlib.h': |
|
44 |
void *malloc(int) |
|
45 |
void free(void *) |
|
46 |
||
3696.3.10
by Robert Collins
Review feedback. |
47 |
|
48 |
cdef extern from 'sys/types.h': |
|
49 |
ctypedef long ssize_t |
|
50 |
ctypedef unsigned long size_t |
|
51 |
ctypedef long time_t |
|
52 |
ctypedef unsigned long ino_t |
|
53 |
ctypedef unsigned long long off_t |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
54 |
ctypedef int mode_t |
3696.3.10
by Robert Collins
Review feedback. |
55 |
|
56 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
57 |
cdef extern from 'sys/stat.h': |
58 |
cdef struct stat: |
|
59 |
int st_mode |
|
3696.3.10
by Robert Collins
Review feedback. |
60 |
off_t st_size |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
61 |
int st_dev |
3696.3.10
by Robert Collins
Review feedback. |
62 |
ino_t st_ino |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
63 |
int st_mtime |
64 |
int st_ctime |
|
65 |
int lstat(char *path, stat *buf) |
|
66 |
int S_ISDIR(int mode) |
|
67 |
int S_ISCHR(int mode) |
|
68 |
int S_ISBLK(int mode) |
|
69 |
int S_ISREG(int mode) |
|
70 |
int S_ISFIFO(int mode) |
|
71 |
int S_ISLNK(int mode) |
|
72 |
int S_ISSOCK(int mode) |
|
73 |
||
74 |
||
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
75 |
cdef extern from 'fcntl.h': |
76 |
int O_RDONLY |
|
77 |
int open(char *pathname, int flags, mode_t mode) |
|
78 |
||
79 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
80 |
cdef extern from 'Python.h': |
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
81 |
int PyErr_CheckSignals() except -1 |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
82 |
char * PyString_AS_STRING(object) |
83 |
ctypedef int Py_ssize_t # Required for older pyrex versions |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
84 |
ctypedef struct PyObject: |
85 |
pass
|
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
86 |
Py_ssize_t PyString_Size(object s) |
87 |
object PyList_GetItem(object lst, Py_ssize_t index) |
|
88 |
void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index) |
|
89 |
int PyList_Append(object lst, object item) except -1 |
|
90 |
void *PyTuple_GetItem_void_void "PyTuple_GET_ITEM" (void* tpl, int index) |
|
91 |
int PyTuple_SetItem(void *, Py_ssize_t pos, object item) except -1 |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
92 |
int PyTuple_SetItem_obj "PyTuple_SetItem" (void *, Py_ssize_t pos, PyObject * item) except -1 |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
93 |
void Py_INCREF(object o) |
94 |
void Py_DECREF(object o) |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
95 |
void PyString_Concat(PyObject **string, object newpart) |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
96 |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
97 |
|
98 |
cdef extern from 'dirent.h': |
|
99 |
ctypedef struct dirent: |
|
100 |
char d_name[256] |
|
3696.3.6
by Robert Collins
Partial review feedback fixups. |
101 |
ino_t d_ino |
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
102 |
# the opaque C library DIR type.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
103 |
ctypedef struct DIR |
104 |
# should be DIR *, pyrex barfs.
|
|
1739.2.6
by Robert Collins
Merge bzr.dev |
105 |
DIR * opendir(char * name) |
106 |
int closedir(DIR * dir) |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
107 |
dirent *readdir(DIR *dir) |
108 |
||
109 |
_directory = 'directory' |
|
110 |
_chardev = 'chardev' |
|
111 |
_block = 'block' |
|
112 |
_file = 'file' |
|
113 |
_fifo = 'fifo' |
|
114 |
_symlink = 'symlink' |
|
115 |
_socket = 'socket' |
|
116 |
_unknown = 'unknown' |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
117 |
_missing = 'missing' |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
118 |
|
119 |
# add a typedef struct dirent dirent to workaround pyrex
|
|
120 |
cdef extern from 'readdir.h': |
|
121 |
pass
|
|
122 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
123 |
|
124 |
cdef class _Stat: |
|
125 |
"""Represent a 'stat' result."""
|
|
126 |
||
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
127 |
cdef stat _st |
128 |
||
129 |
property st_dev: |
|
130 |
def __get__(self): |
|
131 |
return self._st.st_dev |
|
132 |
||
133 |
property st_ino: |
|
134 |
def __get__(self): |
|
135 |
return self._st.st_ino |
|
136 |
||
137 |
property st_mode: |
|
138 |
def __get__(self): |
|
139 |
return self._st.st_mode |
|
140 |
||
141 |
property st_ctime: |
|
142 |
def __get__(self): |
|
143 |
return self._st.st_ctime |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
144 |
|
145 |
property st_mtime: |
|
146 |
def __get__(self): |
|
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
147 |
return self._st.st_mtime |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
148 |
|
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
149 |
property st_size: |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
150 |
def __get__(self): |
3696.3.8
by Robert Collins
Just embed a struct st in the python result object, avoids converting things we don't need converted, and copying values around always. |
151 |
return self._st.st_size |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
152 |
|
153 |
def __repr__(self): |
|
154 |
"""Repr is the same as a Stat object.
|
|
155 |
||
3696.3.6
by Robert Collins
Partial review feedback fixups. |
156 |
(mode, ino, dev, nlink, uid, gid, size, None(atime), mtime, ctime)
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
157 |
"""
|
158 |
return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, None, |
|
4570.1.1
by Robert Collins
Fix repr() on Stat objects from the readdir C extension. |
159 |
self.st_mtime, self.st_ctime)) |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
160 |
|
161 |
||
162 |
from bzrlib import osutils |
|
163 |
||
164 |
||
165 |
cdef class UTF8DirReader: |
|
166 |
"""A dir reader for utf8 file systems."""
|
|
167 |
||
168 |
cdef readonly object _safe_utf8 |
|
169 |
cdef _directory, _chardev, _block, _file, _fifo, _symlink |
|
170 |
cdef _socket, _unknown |
|
171 |
||
172 |
def __init__(self): |
|
173 |
self._safe_utf8 = osutils.safe_utf8 |
|
174 |
self._directory = _directory |
|
175 |
self._chardev = _chardev |
|
176 |
self._block = _block |
|
177 |
self._file = _file |
|
178 |
self._fifo = _fifo |
|
179 |
self._symlink = _symlink |
|
180 |
self._socket = _socket |
|
181 |
self._unknown = _unknown |
|
182 |
||
183 |
def kind_from_mode(self, int mode): |
|
184 |
"""Get the kind of a path from a mode status."""
|
|
185 |
return self._kind_from_mode(mode) |
|
186 |
||
187 |
cdef _kind_from_mode(self, int mode): |
|
3696.3.10
by Robert Collins
Review feedback. |
188 |
# Files and directories are the most common - check them first.
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
189 |
if S_ISREG(mode): |
190 |
return self._file |
|
191 |
if S_ISDIR(mode): |
|
192 |
return self._directory |
|
193 |
if S_ISCHR(mode): |
|
194 |
return self._chardev |
|
195 |
if S_ISBLK(mode): |
|
196 |
return self._block |
|
197 |
if S_ISLNK(mode): |
|
198 |
return self._symlink |
|
199 |
if S_ISFIFO(mode): |
|
200 |
return self._fifo |
|
201 |
if S_ISSOCK(mode): |
|
202 |
return self._socket |
|
203 |
return self._unknown |
|
204 |
||
205 |
def top_prefix_to_starting_dir(self, top, prefix=""): |
|
206 |
"""See DirReader.top_prefix_to_starting_dir."""
|
|
207 |
return (self._safe_utf8(prefix), None, None, None, |
|
208 |
self._safe_utf8(top)) |
|
209 |
||
210 |
def read_dir(self, prefix, top): |
|
211 |
"""Read a single directory from a utf8 file system.
|
|
212 |
||
213 |
All paths in and out are utf8.
|
|
214 |
||
215 |
This sub-function is called when we know the filesystem is already in utf8
|
|
216 |
encoding. So we don't need to transcode filenames.
|
|
217 |
||
218 |
See DirReader.read_dir for details.
|
|
219 |
"""
|
|
220 |
#cdef char *_prefix = prefix
|
|
221 |
#cdef char *_top = top
|
|
222 |
# Use C accelerated directory listing.
|
|
223 |
cdef object newval |
|
224 |
cdef int index |
|
225 |
cdef int length |
|
226 |
cdef void * atuple |
|
227 |
cdef object name |
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
228 |
cdef PyObject * new_val_obj |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
229 |
|
230 |
if PyString_Size(prefix): |
|
231 |
relprefix = prefix + '/' |
|
232 |
else: |
|
233 |
relprefix = '' |
|
234 |
top_slash = top + '/' |
|
235 |
||
236 |
# read_dir supplies in should-stat order.
|
|
237 |
# for _, name in sorted(_listdir(top)):
|
|
238 |
result = _read_dir(top) |
|
239 |
length = len(result) |
|
240 |
# result.sort()
|
|
241 |
for index from 0 <= index < length: |
|
242 |
atuple = PyList_GetItem_object_void(result, index) |
|
243 |
name = <object>PyTuple_GetItem_void_void(atuple, 1) |
|
3696.3.10
by Robert Collins
Review feedback. |
244 |
# We have a tuple with (inode, name, None, statvalue, None)
|
245 |
# Now edit it:
|
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
246 |
# inode -> path_from_top
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
247 |
# direct concat - faster than operator +.
|
248 |
new_val_obj = <PyObject *>relprefix |
|
249 |
Py_INCREF(relprefix) |
|
250 |
PyString_Concat(&new_val_obj, name) |
|
251 |
if NULL == new_val_obj: |
|
252 |
# PyString_Concat will have setup an exception, but how to get
|
|
253 |
# at it?
|
|
254 |
raise Exception("failed to strcat") |
|
255 |
PyTuple_SetItem_obj(atuple, 0, new_val_obj) |
|
3696.3.10
by Robert Collins
Review feedback. |
256 |
# 1st None -> kind
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
257 |
newval = self._kind_from_mode( |
258 |
(<_Stat>PyTuple_GetItem_void_void(atuple, 3)).st_mode) |
|
259 |
Py_INCREF(newval) |
|
260 |
PyTuple_SetItem(atuple, 2, newval) |
|
3696.3.10
by Robert Collins
Review feedback. |
261 |
# 2nd None -> abspath # for all - the caller may need to stat files
|
262 |
# etc.
|
|
3696.3.7
by Robert Collins
Use PyString_Concat directly for another small boost. |
263 |
# direct concat - faster than operator +.
|
264 |
new_val_obj = <PyObject *>top_slash |
|
265 |
Py_INCREF(top_slash) |
|
266 |
PyString_Concat(&new_val_obj, name) |
|
267 |
if NULL == new_val_obj: |
|
268 |
# PyString_Concat will have setup an exception, but how to get
|
|
269 |
# at it?
|
|
270 |
raise Exception("failed to strcat") |
|
271 |
PyTuple_SetItem_obj(atuple, 4, new_val_obj) |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
272 |
return result |
273 |
||
274 |
||
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
275 |
cdef raise_os_error(int errnum, char *msg_prefix, path): |
276 |
if errnum == EINTR: |
|
277 |
PyErr_CheckSignals() |
|
278 |
raise OSError(errnum, msg_prefix + strerror(errnum), path) |
|
279 |
||
280 |
||
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
281 |
cdef _read_dir(path): |
1739.2.11
by Robert Collins
Docstring and copyright header update per Martin's review. |
282 |
"""Like os.listdir, this reads the contents of a directory.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
283 |
|
284 |
:param path: the directory to list.
|
|
3696.3.10
by Robert Collins
Review feedback. |
285 |
:return: a list of single-owner (the list) tuples ready for editing into
|
286 |
the result tuples walkdirs needs to yield. They contain (inode, name,
|
|
287 |
None, statvalue, None).
|
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
288 |
"""
|
289 |
cdef DIR *the_dir |
|
290 |
# currently this needs a fixup - the C code says 'dirent' but should say
|
|
291 |
# 'struct dirent'
|
|
292 |
cdef dirent * entry |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
293 |
cdef dirent sentinel |
294 |
cdef char *name |
|
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
295 |
cdef int stat_result |
296 |
cdef _Stat statvalue |
|
3766.1.6
by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments |
297 |
global errno |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
298 |
cdef int orig_dir_fd |
3696.3.5
by Robert Collins
Streamline _walkdirs_utf8 for utf8 file systems, reducing time to traverse a mozilla tree from 1s to .6 seconds. (Robert Collins) |
299 |
|
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
300 |
# Avoid chdir('') because it causes problems on Sun OS, and avoid this if
|
301 |
# staying in .
|
|
302 |
if path != "" and path != '.': |
|
303 |
# we change into the requested directory before reading, and back at the
|
|
304 |
# end, because that turns out to make the stat calls measurably faster than
|
|
305 |
# passing full paths every time.
|
|
306 |
orig_dir_fd = open(".", O_RDONLY, 0) |
|
307 |
if orig_dir_fd == -1: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
308 |
raise_os_error(errno, "open: ", ".") |
3841.1.2
by Martin Pool
Don't call chdir('') |
309 |
if -1 == chdir(path): |
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
310 |
raise_os_error(errno, "chdir: ", path) |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
311 |
else: |
312 |
orig_dir_fd = -1 |
|
313 |
||
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
314 |
try: |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
315 |
the_dir = opendir(".") |
316 |
if NULL == the_dir: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
317 |
raise_os_error(errno, "opendir: ", path) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
318 |
try: |
319 |
result = [] |
|
320 |
entry = &sentinel |
|
321 |
while entry != NULL: |
|
322 |
# Unlike most libc functions, readdir needs errno set to 0
|
|
323 |
# beforehand so that eof can be distinguished from errors. See
|
|
324 |
# <https://bugs.launchpad.net/bzr/+bug/279381>
|
|
325 |
while True: |
|
3841.1.5
by Martin Pool
Review cleanups on readdir |
326 |
errno = 0 |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
327 |
entry = readdir(the_dir) |
328 |
if entry == NULL and (errno == EAGAIN or errno == EINTR): |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
329 |
if errno == EINTR: |
330 |
PyErr_CheckSignals() |
|
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
331 |
# try again
|
332 |
continue
|
|
333 |
else: |
|
334 |
break
|
|
335 |
if entry == NULL: |
|
336 |
if errno == ENOTDIR or errno == 0: |
|
337 |
# We see ENOTDIR at the end of a normal directory.
|
|
338 |
# As ENOTDIR for read_dir(file) is triggered on opendir,
|
|
339 |
# we consider ENOTDIR to be 'no error'.
|
|
340 |
continue
|
|
341 |
else: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
342 |
raise_os_error(errno, "readdir: ", path) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
343 |
name = entry.d_name |
344 |
if not (name[0] == c"." and ( |
|
345 |
(name[1] == 0) or |
|
346 |
(name[1] == c"." and name[2] == 0)) |
|
347 |
):
|
|
348 |
statvalue = _Stat() |
|
349 |
stat_result = lstat(entry.d_name, &statvalue._st) |
|
350 |
if stat_result != 0: |
|
351 |
if errno != ENOENT: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
352 |
raise_os_error(errno, "lstat: ", |
4095.1.3
by Martin Pool
Add test for failures inside pyrex readdir |
353 |
path + "/" + entry.d_name) |
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
354 |
else: |
4634.75.1
by Martin Pool
Cope with files disappearing between readdir and stat |
355 |
# the file seems to have disappeared after being
|
356 |
# seen by readdir - perhaps a transient temporary
|
|
357 |
# file. there's no point returning it.
|
|
358 |
continue
|
|
3841.1.1
by Martin Pool
Fix try/finally block after chdir in readdir_pyx |
359 |
# We append a 5-tuple that can be modified in-place by the C
|
360 |
# api:
|
|
361 |
# inode to sort on (to replace with top_path)
|
|
362 |
# name (to keep)
|
|
363 |
# kind (None, to set)
|
|
364 |
# statvalue (to keep)
|
|
365 |
# abspath (None, to set)
|
|
366 |
PyList_Append(result, (entry.d_ino, entry.d_name, None, |
|
367 |
statvalue, None)) |
|
368 |
finally: |
|
369 |
if -1 == closedir(the_dir): |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
370 |
raise_os_error(errno, "closedir: ", path) |
1739.2.6
by Robert Collins
Merge bzr.dev |
371 |
finally: |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
372 |
if -1 != orig_dir_fd: |
3841.1.5
by Martin Pool
Review cleanups on readdir |
373 |
failed = False |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
374 |
if -1 == fchdir(orig_dir_fd): |
3841.1.5
by Martin Pool
Review cleanups on readdir |
375 |
# try to close the original directory anyhow
|
376 |
failed = True |
|
377 |
if -1 == close(orig_dir_fd) or failed: |
|
4634.115.1
by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx. |
378 |
raise_os_error(errno, "return to orig_dir: ", "") |
3841.1.4
by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location |
379 |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
380 |
return result |
1739.2.6
by Robert Collins
Merge bzr.dev |
381 |
|
382 |
||
383 |
# vim: tw=79 ai expandtab sw=4 sts=4
|