/brz/remove-bazaar

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