/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/_readdir_pyx.pyx

  • Committer: Martin Pool
  • Date: 2009-07-27 06:28:35 UTC
  • mto: This revision was merged to the branch mainline in revision 4587.
  • Revision ID: mbp@sourcefrog.net-20090727062835-o66p8it658tq1sma
Add CountedLock.get_physical_lock_status

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006, 2008, 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2006, 2008, 2009 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
16
16
 
17
17
"""Wrapper for readdir which returns files ordered by inode."""
18
18
 
19
 
from __future__ import absolute_import
20
 
 
21
19
 
22
20
import os
23
21
import sys
24
22
 
 
23
#python2.4 support
25
24
cdef extern from "python-compat.h":
26
25
    pass
27
26
 
79
78
 
80
79
 
81
80
cdef extern from 'Python.h':
82
 
    int PyErr_CheckSignals() except -1
83
 
    char * PyBytes_AS_STRING(object)
 
81
    char * PyString_AS_STRING(object)
 
82
    ctypedef int Py_ssize_t # Required for older pyrex versions
84
83
    ctypedef struct PyObject:
85
84
        pass
86
 
    Py_ssize_t PyBytes_Size(object s)
 
85
    Py_ssize_t PyString_Size(object s)
87
86
    object PyList_GetItem(object lst, Py_ssize_t index)
88
87
    void *PyList_GetItem_object_void "PyList_GET_ITEM" (object lst, int index)
89
88
    int PyList_Append(object lst, object item) except -1
92
91
    int PyTuple_SetItem_obj "PyTuple_SetItem" (void *, Py_ssize_t pos, PyObject * item) except -1
93
92
    void Py_INCREF(object o)
94
93
    void Py_DECREF(object o)
95
 
    void PyBytes_Concat(PyObject **string, object newpart)
 
94
    void PyString_Concat(PyObject **string, object newpart)
96
95
 
97
96
 
98
97
cdef extern from 'dirent.h':
106
105
    int closedir(DIR * dir)
107
106
    dirent *readdir(DIR *dir)
108
107
 
109
 
cdef object _directory
110
108
_directory = 'directory'
111
 
cdef object _chardev
112
109
_chardev = 'chardev'
113
 
cdef object _block
114
110
_block = 'block'
115
 
cdef object _file
116
111
_file = 'file'
117
 
cdef object _fifo
118
112
_fifo = 'fifo'
119
 
cdef object _symlink
120
113
_symlink = 'symlink'
121
 
cdef object _socket
122
114
_socket = 'socket'
123
 
cdef object _unknown
124
115
_unknown = 'unknown'
 
116
_missing = 'missing'
125
117
 
126
118
# add a typedef struct dirent dirent to workaround pyrex
127
119
cdef extern from 'readdir.h':
163
155
        (mode, ino, dev, nlink, uid, gid, size, None(atime), mtime, ctime)
164
156
        """
165
157
        return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, None,
166
 
                     self.st_mtime, self.st_ctime))
167
 
 
168
 
 
169
 
from . import osutils
170
 
 
171
 
cdef object _safe_utf8
172
 
_safe_utf8 = osutils.safe_utf8
 
158
                     self._mtime, self._ctime))
 
159
 
 
160
 
 
161
from bzrlib import osutils
 
162
 
173
163
 
174
164
cdef class UTF8DirReader:
175
165
    """A dir reader for utf8 file systems."""
176
166
 
 
167
    cdef readonly object _safe_utf8
 
168
    cdef _directory, _chardev, _block, _file, _fifo, _symlink
 
169
    cdef _socket, _unknown
 
170
 
 
171
    def __init__(self):
 
172
        self._safe_utf8 = osutils.safe_utf8
 
173
        self._directory = _directory
 
174
        self._chardev = _chardev
 
175
        self._block = _block
 
176
        self._file = _file
 
177
        self._fifo = _fifo
 
178
        self._symlink = _symlink
 
179
        self._socket = _socket
 
180
        self._unknown = _unknown
 
181
 
177
182
    def kind_from_mode(self, int mode):
178
183
        """Get the kind of a path from a mode status."""
179
184
        return self._kind_from_mode(mode)
181
186
    cdef _kind_from_mode(self, int mode):
182
187
        # Files and directories are the most common - check them first.
183
188
        if S_ISREG(mode):
184
 
            return _file
 
189
            return self._file
185
190
        if S_ISDIR(mode):
186
 
            return _directory
 
191
            return self._directory
187
192
        if S_ISCHR(mode):
188
 
            return _chardev
 
193
            return self._chardev
189
194
        if S_ISBLK(mode):
190
 
            return _block
 
195
            return self._block
191
196
        if S_ISLNK(mode):
192
 
            return _symlink
 
197
            return self._symlink
193
198
        if S_ISFIFO(mode):
194
 
            return _fifo
 
199
            return self._fifo
195
200
        if S_ISSOCK(mode):
196
 
            return _socket
197
 
        return _unknown
 
201
            return self._socket
 
202
        return self._unknown
198
203
 
199
204
    def top_prefix_to_starting_dir(self, top, prefix=""):
200
205
        """See DirReader.top_prefix_to_starting_dir."""
201
 
        return (_safe_utf8(prefix), None, None, None, _safe_utf8(top))
 
206
        return (self._safe_utf8(prefix), None, None, None,
 
207
            self._safe_utf8(top))
202
208
 
203
209
    def read_dir(self, prefix, top):
204
210
        """Read a single directory from a utf8 file system.
220
226
        cdef object name
221
227
        cdef PyObject * new_val_obj
222
228
 
223
 
        if PyBytes_Size(prefix):
224
 
            relprefix = prefix + b'/'
 
229
        if PyString_Size(prefix):
 
230
            relprefix = prefix + '/'
225
231
        else:
226
 
            relprefix = b''
227
 
        top_slash = top + b'/'
 
232
            relprefix = ''
 
233
        top_slash = top + '/'
228
234
 
229
235
        # read_dir supplies in should-stat order.
230
236
        # for _, name in sorted(_listdir(top)):
240
246
            # direct concat - faster than operator +.
241
247
            new_val_obj = <PyObject *>relprefix
242
248
            Py_INCREF(relprefix)
243
 
            PyBytes_Concat(&new_val_obj, name)
 
249
            PyString_Concat(&new_val_obj, name)
244
250
            if NULL == new_val_obj:
245
 
                # PyBytes_Concat will have setup an exception, but how to get
 
251
                # PyString_Concat will have setup an exception, but how to get
246
252
                # at it?
247
253
                raise Exception("failed to strcat")
248
254
            PyTuple_SetItem_obj(atuple, 0, new_val_obj)
256
262
            # direct concat - faster than operator +.
257
263
            new_val_obj = <PyObject *>top_slash
258
264
            Py_INCREF(top_slash)
259
 
            PyBytes_Concat(&new_val_obj, name)
 
265
            PyString_Concat(&new_val_obj, name)
260
266
            if NULL == new_val_obj:
261
 
                # PyBytes_Concat will have setup an exception, but how to get
 
267
                # PyString_Concat will have setup an exception, but how to get
262
268
                # at it?
263
269
                raise Exception("failed to strcat")
264
270
            PyTuple_SetItem_obj(atuple, 4, new_val_obj)
265
271
        return result
266
272
 
267
273
 
268
 
cdef raise_os_error(int errnum, char *msg_prefix, path):
269
 
    if errnum == EINTR:
270
 
        PyErr_CheckSignals()
271
 
    raise OSError(errnum, msg_prefix + strerror(errnum), path)
272
 
 
273
 
 
274
274
cdef _read_dir(path):
275
275
    """Like os.listdir, this reads the contents of a directory.
276
276
 
292
292
 
293
293
    # Avoid chdir('') because it causes problems on Sun OS, and avoid this if
294
294
    # staying in .
295
 
    if path != b"" and path != b'.':
 
295
    if path != "" and path != '.':
296
296
        # we change into the requested directory before reading, and back at the
297
297
        # end, because that turns out to make the stat calls measurably faster than
298
298
        # passing full paths every time.
299
299
        orig_dir_fd = open(".", O_RDONLY, 0)
300
300
        if orig_dir_fd == -1:
301
 
            raise_os_error(errno, "open: ", ".")
 
301
            raise OSError(errno, "open: " + strerror(errno), ".")
302
302
        if -1 == chdir(path):
303
 
            # Ignore the return value, because we are already raising an
304
 
            # exception
305
 
            close(orig_dir_fd)
306
 
            raise_os_error(errno, "chdir: ", path)
 
303
            raise OSError(errno, "chdir: " + strerror(errno), path)
307
304
    else:
308
305
        orig_dir_fd = -1
309
306
 
310
307
    try:
311
 
        the_dir = opendir(b".")
 
308
        the_dir = opendir(".")
312
309
        if NULL == the_dir:
313
 
            raise_os_error(errno, "opendir: ", path)
 
310
            raise OSError(errno, "opendir: " + strerror(errno), path)
314
311
        try:
315
312
            result = []
316
313
            entry = &sentinel
322
319
                    errno = 0
323
320
                    entry = readdir(the_dir)
324
321
                    if entry == NULL and (errno == EAGAIN or errno == EINTR):
325
 
                        if errno == EINTR:
326
 
                            PyErr_CheckSignals()
327
322
                        # try again
328
323
                        continue
329
324
                    else:
335
330
                        # we consider ENOTDIR to be 'no error'.
336
331
                        continue
337
332
                    else:
338
 
                        raise_os_error(errno, "readdir: ", path)
 
333
                        raise OSError(errno, "readdir: " + strerror(errno), path)
339
334
                name = entry.d_name
340
335
                if not (name[0] == c"." and (
341
336
                    (name[1] == 0) or 
345
340
                    stat_result = lstat(entry.d_name, &statvalue._st)
346
341
                    if stat_result != 0:
347
342
                        if errno != ENOENT:
348
 
                            raise_os_error(errno, "lstat: ",
349
 
                                path + b"/" + entry.d_name)
 
343
                            raise OSError(errno, "lstat: " + strerror(errno),
 
344
                                path + "/" + entry.d_name)
350
345
                        else:
351
 
                            # the file seems to have disappeared after being
352
 
                            # seen by readdir - perhaps a transient temporary
353
 
                            # file.  there's no point returning it.
354
 
                            continue
 
346
                            kind = _missing
 
347
                            statvalue = None
355
348
                    # We append a 5-tuple that can be modified in-place by the C
356
349
                    # api:
357
350
                    # inode to sort on (to replace with top_path)
363
356
                        statvalue, None))
364
357
        finally:
365
358
            if -1 == closedir(the_dir):
366
 
                raise_os_error(errno, "closedir: ", path)
 
359
                raise OSError(errno, "closedir: " + strerror(errno), path)
367
360
    finally:
368
361
        if -1 != orig_dir_fd:
369
362
            failed = False
371
364
                # try to close the original directory anyhow
372
365
                failed = True
373
366
            if -1 == close(orig_dir_fd) or failed:
374
 
                raise_os_error(errno, "return to orig_dir: ", "")
 
367
                raise OSError(errno, "return to orig_dir: " + strerror(errno))
375
368
 
376
369
    return result
377
370