/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 Arbash Meinel
  • Date: 2008-10-08 21:56:12 UTC
  • mto: This revision was merged to the branch mainline in revision 3773.
  • Revision ID: john@arbash-meinel.com-20081008215612-y9v94tqxreqoangx
Simplify the --raw mode.

I didn't realize, but the only node that is special cased is the 'root' node,
and to read it, you actually have to parse it directly, because the
compressed bytes start immediately after the end of the header, rather than
having any padding before the zlib bytes.

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 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
12
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
"""Wrapper for readdir which returns files ordered by inode."""
18
18
 
36
36
 
37
37
cdef extern from 'unistd.h':
38
38
    int chdir(char *path)
39
 
    int close(int fd)
40
 
    int fchdir(int fd)
41
39
    char *getcwd(char *, int size)
42
40
 
43
41
cdef extern from 'stdlib.h':
51
49
    ctypedef long time_t
52
50
    ctypedef unsigned long ino_t
53
51
    ctypedef unsigned long long off_t
54
 
    ctypedef int mode_t
55
52
 
56
53
 
57
54
cdef extern from 'sys/stat.h':
72
69
    int S_ISSOCK(int mode)
73
70
 
74
71
 
75
 
cdef extern from 'fcntl.h':
76
 
    int O_RDONLY
77
 
    int open(char *pathname, int flags, mode_t mode)
78
 
 
79
 
 
80
72
cdef extern from 'Python.h':
81
 
    int PyErr_CheckSignals() except -1
82
73
    char * PyString_AS_STRING(object)
83
74
    ctypedef int Py_ssize_t # Required for older pyrex versions
84
75
    ctypedef struct PyObject:
156
147
        (mode, ino, dev, nlink, uid, gid, size, None(atime), mtime, ctime)
157
148
        """
158
149
        return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, None,
159
 
                     self.st_mtime, self.st_ctime))
 
150
                     self._mtime, self._ctime))
160
151
 
161
152
 
162
153
from bzrlib import osutils
272
263
        return result
273
264
 
274
265
 
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
 
 
281
266
cdef _read_dir(path):
282
267
    """Like os.listdir, this reads the contents of a directory.
283
268
 
294
279
    cdef char *name
295
280
    cdef int stat_result
296
281
    cdef _Stat statvalue
 
282
    cdef char *cwd
297
283
    global errno
298
 
    cdef int orig_dir_fd
299
 
 
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:
308
 
            raise_os_error(errno, "open: ", ".")
309
 
        if -1 == chdir(path):
310
 
            raise_os_error(errno, "chdir: ", path)
311
 
    else:
312
 
        orig_dir_fd = -1
313
 
 
 
284
 
 
285
    cwd = getcwd(NULL, 0)
 
286
    if -1 == chdir(path):
 
287
        raise OSError(errno, strerror(errno))
 
288
    the_dir = opendir(".")
 
289
    if NULL == the_dir:
 
290
        raise OSError(errno, strerror(errno))
 
291
    result = []
314
292
    try:
315
 
        the_dir = opendir(".")
316
 
        if NULL == the_dir:
317
 
            raise_os_error(errno, "opendir: ", path)
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:
326
 
                    errno = 0
327
 
                    entry = readdir(the_dir)
328
 
                    if entry == NULL and (errno == EAGAIN or errno == EINTR):
329
 
                        if errno == EINTR:
330
 
                            PyErr_CheckSignals()
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:
342
 
                        raise_os_error(errno, "readdir: ", path)
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:
352
 
                            raise_os_error(errno, "lstat: ",
353
 
                                path + "/" + entry.d_name)
354
 
                        else:
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
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):
370
 
                raise_os_error(errno, "closedir: ", path)
 
293
        entry = &sentinel
 
294
        while entry != NULL:
 
295
            # Unlike most libc functions, readdir needs errno set to 0
 
296
            # beforehand so that eof can be distinguished from errors.  See
 
297
            # <https://bugs.launchpad.net/bzr/+bug/279381>
 
298
            while True:
 
299
                errno = 0;
 
300
                entry = readdir(the_dir)
 
301
                if entry == NULL and (errno == EAGAIN or errno == EINTR):
 
302
                    # try again
 
303
                    continue
 
304
                else:
 
305
                    break
 
306
            if entry == NULL:
 
307
                if errno == ENOTDIR or errno == 0:
 
308
                    # We see ENOTDIR at the end of a normal directory.
 
309
                    # As ENOTDIR for read_dir(file) is triggered on opendir,
 
310
                    # we consider ENOTDIR to be 'no error'.
 
311
                    continue
 
312
                else:
 
313
                    raise OSError(errno, strerror(errno))
 
314
            name = entry.d_name
 
315
            if not (name[0] == c"." and (
 
316
                (name[1] == 0) or 
 
317
                (name[1] == c"." and name[2] == 0))
 
318
                ):
 
319
                statvalue = _Stat()
 
320
                stat_result = lstat(entry.d_name, &statvalue._st)
 
321
                if stat_result != 0:
 
322
                    if errno != ENOENT:
 
323
                        raise OSError(errno, strerror(errno))
 
324
                    else:
 
325
                        kind = _missing
 
326
                        statvalue = None
 
327
                # We append a 5-tuple that can be modified in-place by the C
 
328
                # api:
 
329
                # inode to sort on (to replace with top_path)
 
330
                # name (to keep)
 
331
                # kind (None, to set)
 
332
                # statvalue (to keep)
 
333
                # abspath (None, to set)
 
334
                PyList_Append(result, (entry.d_ino, entry.d_name, None,
 
335
                    statvalue, None))
371
336
    finally:
372
 
        if -1 != orig_dir_fd:
373
 
            failed = False
374
 
            if -1 == fchdir(orig_dir_fd):
375
 
                # try to close the original directory anyhow
376
 
                failed = True
377
 
            if -1 == close(orig_dir_fd) or failed:
378
 
                raise_os_error(errno, "return to orig_dir: ", "")
379
 
 
 
337
        if -1 == chdir(cwd):
 
338
            free(cwd)
 
339
            raise OSError(errno, strerror(errno))
 
340
        free(cwd)
 
341
        if -1 == closedir(the_dir):
 
342
            raise OSError(errno, strerror(errno))
380
343
    return result
381
344
 
382
345