/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: John Ferlito
  • Date: 2009-09-02 04:31:45 UTC
  • mto: (4665.7.1 serve-init)
  • mto: This revision was merged to the branch mainline in revision 4913.
  • Revision ID: johnf@inodes.org-20090902043145-gxdsfw03ilcwbyn5
Add a debian init script for bzr --serve

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