/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
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
cdef extern from "python-compat.h":
24
    pass
25
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.
26
27
cdef extern from 'errno.h':
28
    int ENOENT
1739.2.6 by Robert Collins
Merge bzr.dev
29
    int ENOTDIR
30
    int EAGAIN
3766.1.5 by Martin Pool
add missing pyrex import
31
    int EINTR
3766.1.6 by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments
32
    char *strerror(int errno)
33
    # 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.
34
    int errno
35
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)
36
cdef extern from 'unistd.h':
37
    int chdir(char *path)
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
38
    int close(int fd)
39
    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)
40
    char *getcwd(char *, int size)
41
42
cdef extern from 'stdlib.h':
43
    void *malloc(int)
44
    void free(void *)
45
3696.3.10 by Robert Collins
Review feedback.
46
47
cdef extern from 'sys/types.h':
48
    ctypedef long ssize_t
49
    ctypedef unsigned long size_t
50
    ctypedef long time_t
51
    ctypedef unsigned long ino_t
52
    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
53
    ctypedef int mode_t
3696.3.10 by Robert Collins
Review feedback.
54
55
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)
56
cdef extern from 'sys/stat.h':
57
    cdef struct stat:
58
        int st_mode
3696.3.10 by Robert Collins
Review feedback.
59
        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)
60
        int st_dev
3696.3.10 by Robert Collins
Review feedback.
61
        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)
62
        int st_mtime
63
        int st_ctime
64
    int lstat(char *path, stat *buf)
65
    int S_ISDIR(int mode)
66
    int S_ISCHR(int mode)
67
    int S_ISBLK(int mode)
68
    int S_ISREG(int mode)
69
    int S_ISFIFO(int mode)
70
    int S_ISLNK(int mode)
71
    int S_ISSOCK(int mode)
72
73
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
74
cdef extern from 'fcntl.h':
75
    int O_RDONLY
76
    int open(char *pathname, int flags, mode_t mode)
77
78
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)
79
cdef extern from 'Python.h':
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
80
    int PyErr_CheckSignals() except -1
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
81
    char * PyBytes_AS_STRING(object)
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
82
    ctypedef struct PyObject:
83
        pass
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
84
    Py_ssize_t PyBytes_Size(object s)
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)
85
    object PyList_GetItem(object lst, Py_ssize_t index)
86
    void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index)
87
    int PyList_Append(object lst, object item) except -1
88
    void *PyTuple_GetItem_void_void "PyTuple_GET_ITEM" (void* tpl, int index)
89
    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.
90
    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)
91
    void Py_INCREF(object o)
92
    void Py_DECREF(object o)
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
93
    void PyBytes_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)
94
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.
95
96
cdef extern from 'dirent.h':
97
    ctypedef struct dirent:
98
        char d_name[256]
3696.3.6 by Robert Collins
Partial review feedback fixups.
99
        ino_t d_ino
3766.1.6 by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments
100
    # 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.
101
    ctypedef struct DIR
102
    # should be DIR *, pyrex barfs.
1739.2.6 by Robert Collins
Merge bzr.dev
103
    DIR * opendir(char * name)
104
    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.
105
    dirent *readdir(DIR *dir)
106
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
107
cdef object _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.
108
_directory = 'directory'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
109
cdef object _chardev
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.
110
_chardev = 'chardev'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
111
cdef object _block
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.
112
_block = 'block'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
113
cdef object _file
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.
114
_file = 'file'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
115
cdef object _fifo
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.
116
_fifo = 'fifo'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
117
cdef object _symlink
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
_symlink = 'symlink'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
119
cdef object _socket
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.
120
_socket = 'socket'
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
121
cdef object _unknown
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.
122
_unknown = 'unknown'
123
124
# add a typedef struct dirent dirent to workaround pyrex
125
cdef extern from 'readdir.h':
126
    pass
127
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)
128
129
cdef class _Stat:
130
    """Represent a 'stat' result."""
131
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.
132
    cdef stat _st
133
134
    property st_dev:
135
        def __get__(self):
136
            return self._st.st_dev
137
138
    property st_ino:
139
        def __get__(self):
140
            return self._st.st_ino
141
142
    property st_mode:
143
        def __get__(self):
144
            return self._st.st_mode
145
146
    property st_ctime:
147
        def __get__(self):
148
            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)
149
150
    property st_mtime:
151
        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.
152
            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)
153
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.
154
    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)
155
        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.
156
            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)
157
158
    def __repr__(self):
159
        """Repr is the same as a Stat object.
160
3696.3.6 by Robert Collins
Partial review feedback fixups.
161
        (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)
162
        """
163
        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.
164
                     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)
165
166
6656.2.2 by Jelmer Vernooij
Use absolute_import.
167
from . import osutils
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)
168
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
169
cdef object _safe_utf8
170
_safe_utf8 = osutils.safe_utf8
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)
171
172
cdef class UTF8DirReader:
173
    """A dir reader for utf8 file systems."""
174
175
    def kind_from_mode(self, int mode):
176
        """Get the kind of a path from a mode status."""
177
        return self._kind_from_mode(mode)
178
179
    cdef _kind_from_mode(self, int mode):
3696.3.10 by Robert Collins
Review feedback.
180
        # 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)
181
        if S_ISREG(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
182
            return _file
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)
183
        if S_ISDIR(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
184
            return _directory
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)
185
        if S_ISCHR(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
186
            return _chardev
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)
187
        if S_ISBLK(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
188
            return _block
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_ISLNK(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
190
            return _symlink
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)
191
        if S_ISFIFO(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
192
            return _fifo
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)
193
        if S_ISSOCK(mode):
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
194
            return _socket
195
        return _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)
196
197
    def top_prefix_to_starting_dir(self, top, prefix=""):
198
        """See DirReader.top_prefix_to_starting_dir."""
5243.2.1 by John Arbash Meinel
Change the object-level functions into module-level functions.
199
        return (_safe_utf8(prefix), None, None, None, _safe_utf8(top))
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)
200
201
    def read_dir(self, prefix, top):
202
        """Read a single directory from a utf8 file system.
203
204
        All paths in and out are utf8.
205
206
        This sub-function is called when we know the filesystem is already in utf8
207
        encoding. So we don't need to transcode filenames.
208
209
        See DirReader.read_dir for details.
210
        """
211
        #cdef char *_prefix = prefix
212
        #cdef char *_top = top
213
        # Use C accelerated directory listing.
214
        cdef object newval
215
        cdef int index
216
        cdef int length
217
        cdef void * atuple
218
        cdef object name
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
219
        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)
220
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
221
        if PyBytes_Size(prefix):
222
            relprefix = prefix + b'/'
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)
223
        else:
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
224
            relprefix = b''
225
        top_slash = top + b'/'
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)
226
227
        # read_dir supplies in should-stat order.
228
        # for _, name in sorted(_listdir(top)):
229
        result = _read_dir(top)
230
        length = len(result)
231
        # result.sort()
232
        for index from 0 <= index < length:
233
            atuple = PyList_GetItem_object_void(result, index)
234
            name = <object>PyTuple_GetItem_void_void(atuple, 1)
3696.3.10 by Robert Collins
Review feedback.
235
            # We have a tuple with (inode, name, None, statvalue, None)
236
            # 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)
237
            # inode -> path_from_top
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
238
            # direct concat - faster than operator +.
239
            new_val_obj = <PyObject *>relprefix
240
            Py_INCREF(relprefix)
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
241
            PyBytes_Concat(&new_val_obj, name)
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
242
            if NULL == new_val_obj:
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
243
                # PyBytes_Concat will have setup an exception, but how to get
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
244
                # at it?
245
                raise Exception("failed to strcat")
246
            PyTuple_SetItem_obj(atuple, 0, new_val_obj)
3696.3.10 by Robert Collins
Review feedback.
247
            # 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)
248
            newval = self._kind_from_mode(
249
                (<_Stat>PyTuple_GetItem_void_void(atuple, 3)).st_mode)
250
            Py_INCREF(newval)
251
            PyTuple_SetItem(atuple, 2, newval)
3696.3.10 by Robert Collins
Review feedback.
252
            # 2nd None -> abspath # for all - the caller may need to stat files
253
            # etc.
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
254
            # direct concat - faster than operator +.
255
            new_val_obj = <PyObject *>top_slash
256
            Py_INCREF(top_slash)
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
257
            PyBytes_Concat(&new_val_obj, name)
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
258
            if NULL == new_val_obj:
7067.16.1 by Jelmer Vernooij
Fix some C extensions.
259
                # PyBytes_Concat will have setup an exception, but how to get
3696.3.7 by Robert Collins
Use PyString_Concat directly for another small boost.
260
                # at it?
261
                raise Exception("failed to strcat")
262
            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)
263
        return result
264
265
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
266
cdef raise_os_error(int errnum, char *msg_prefix, path):
267
    if errnum == EINTR:
268
        PyErr_CheckSignals()
269
    raise OSError(errnum, msg_prefix + strerror(errnum), path)
270
271
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
cdef _read_dir(path):
1739.2.11 by Robert Collins
Docstring and copyright header update per Martin's review.
273
    """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.
274
275
    :param path: the directory to list.
3696.3.10 by Robert Collins
Review feedback.
276
    :return: a list of single-owner (the list) tuples ready for editing into
277
        the result tuples walkdirs needs to yield. They contain (inode, name,
278
        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.
279
    """
280
    cdef DIR *the_dir
281
    # currently this needs a fixup - the C code says 'dirent' but should say
282
    # 'struct dirent'
283
    cdef dirent * entry
1739.2.6 by Robert Collins
Merge bzr.dev
284
    cdef dirent sentinel
285
    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)
286
    cdef int stat_result
287
    cdef _Stat statvalue
3766.1.6 by Martin Pool
We need a 'global' declaration to assign to errno; and fix comments
288
    global errno
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
289
    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)
290
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
291
    # Avoid chdir('') because it causes problems on Sun OS, and avoid this if
292
    # staying in .
7067.16.3 by Jelmer Vernooij
Some more walkdir fixes.
293
    if path != b"" and path != b'.':
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
294
        # we change into the requested directory before reading, and back at the
295
        # end, because that turns out to make the stat calls measurably faster than
296
        # passing full paths every time.
297
        orig_dir_fd = open(".", O_RDONLY, 0)
298
        if orig_dir_fd == -1:
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
299
            raise_os_error(errno, "open: ", ".")
3841.1.2 by Martin Pool
Don't call chdir('')
300
        if -1 == chdir(path):
4634.154.1 by John Arbash Meinel
Bug #583486, close the current-dir file descriptor
301
            # Ignore the return value, because we are already raising an
302
            # exception
303
            close(orig_dir_fd)
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
304
            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
305
    else:
306
        orig_dir_fd = -1
307
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.
308
    try:
7067.16.3 by Jelmer Vernooij
Some more walkdir fixes.
309
        the_dir = opendir(b".")
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
310
        if NULL == the_dir:
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
311
            raise_os_error(errno, "opendir: ", path)
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
312
        try:
313
            result = []
314
            entry = &sentinel
315
            while entry != NULL:
316
                # Unlike most libc functions, readdir needs errno set to 0
317
                # beforehand so that eof can be distinguished from errors.  See
318
                # <https://bugs.launchpad.net/bzr/+bug/279381>
319
                while True:
3841.1.5 by Martin Pool
Review cleanups on readdir
320
                    errno = 0
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
321
                    entry = readdir(the_dir)
322
                    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.
323
                        if errno == EINTR:
324
                            PyErr_CheckSignals()
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
325
                        # try again
326
                        continue
327
                    else:
328
                        break
329
                if entry == NULL:
330
                    if errno == ENOTDIR or errno == 0:
331
                        # We see ENOTDIR at the end of a normal directory.
332
                        # As ENOTDIR for read_dir(file) is triggered on opendir,
333
                        # we consider ENOTDIR to be 'no error'.
334
                        continue
335
                    else:
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
336
                        raise_os_error(errno, "readdir: ", path)
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
337
                name = entry.d_name
338
                if not (name[0] == c"." and (
339
                    (name[1] == 0) or 
340
                    (name[1] == c"." and name[2] == 0))
341
                    ):
342
                    statvalue = _Stat()
343
                    stat_result = lstat(entry.d_name, &statvalue._st)
344
                    if stat_result != 0:
345
                        if errno != ENOENT:
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
346
                            raise_os_error(errno, "lstat: ",
7067.16.3 by Jelmer Vernooij
Some more walkdir fixes.
347
                                path + b"/" + entry.d_name)
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
348
                        else:
4634.75.1 by Martin Pool
Cope with files disappearing between readdir and stat
349
                            # the file seems to have disappeared after being
350
                            # seen by readdir - perhaps a transient temporary
351
                            # file.  there's no point returning it.
352
                            continue
3841.1.1 by Martin Pool
Fix try/finally block after chdir in readdir_pyx
353
                    # We append a 5-tuple that can be modified in-place by the C
354
                    # api:
355
                    # inode to sort on (to replace with top_path)
356
                    # name (to keep)
357
                    # kind (None, to set)
358
                    # statvalue (to keep)
359
                    # abspath (None, to set)
360
                    PyList_Append(result, (entry.d_ino, entry.d_name, None,
361
                        statvalue, None))
362
        finally:
363
            if -1 == closedir(the_dir):
4634.115.1 by Andrew Bennetts
Check for signals whenever an EINTR might have occurred in _readdir_pyx.
364
                raise_os_error(errno, "closedir: ", path)
1739.2.6 by Robert Collins
Merge bzr.dev
365
    finally:
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
366
        if -1 != orig_dir_fd:
3841.1.5 by Martin Pool
Review cleanups on readdir
367
            failed = False
3841.1.4 by Martin Pool
Use open/fchdir rather than getcwd/chdir to save and restore directory location
368
            if -1 == fchdir(orig_dir_fd):
3841.1.5 by Martin Pool
Review cleanups on readdir
369
                # try to close the original directory anyhow
370
                failed = True
371
            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.
372
                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
373
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.
374
    return result
1739.2.6 by Robert Collins
Merge bzr.dev
375
376
377
# vim: tw=79 ai expandtab sw=4 sts=4