/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

  • Committer: Robert Collins
  • Date: 2008-08-20 02:07:36 UTC
  • mfrom: (3640 +trunk)
  • mto: This revision was merged to the branch mainline in revision 3682.
  • Revision ID: robertc@robertcollins.net-20080820020736-g2xe4921zzxtymle
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2006, 2008 Canonical Ltd
 
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
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
"""Wrapper for readdir which grabs file type from d_type."""
 
18
 
 
19
 
 
20
import os
 
21
import sys
 
22
 
 
23
 
 
24
# the opaque C library DIR type.
 
25
cdef extern from 'errno.h':
 
26
    int ENOENT
 
27
    int ENOTDIR
 
28
    int EAGAIN
 
29
    int errno
 
30
    char *strerror(int errno)
 
31
 
 
32
cdef extern from 'sys/types.h':
 
33
    ctypedef long ssize_t
 
34
    ctypedef unsigned long size_t
 
35
 
 
36
cdef extern from 'dirent.h':
 
37
    int DT_UNKNOWN
 
38
    int DT_REG
 
39
    int DT_DIR
 
40
    int DT_FIFO
 
41
    int DT_SOCK
 
42
    int DT_CHR
 
43
    int DT_BLK
 
44
    ctypedef struct dirent:
 
45
        char d_name[256]
 
46
        # this will fail to compile if d_type is not defined.
 
47
        # if this module fails to compile, use the .py version.
 
48
        unsigned char d_type
 
49
    ctypedef struct DIR
 
50
    # should be DIR *, pyrex barfs.
 
51
    DIR * opendir(char * name)
 
52
    int closedir(DIR * dir)
 
53
    dirent *readdir(DIR *dir)
 
54
 
 
55
_directory = 'directory'
 
56
_chardev = 'chardev'
 
57
_block = 'block'
 
58
_file = 'file'
 
59
_fifo = 'fifo'
 
60
_symlink = 'symlink'
 
61
_socket = 'socket'
 
62
_unknown = 'unknown'
 
63
 
 
64
dot = ord('.')
 
65
 
 
66
# add a typedef struct dirent dirent to workaround pyrex
 
67
cdef extern from 'readdir.h':
 
68
    pass
 
69
 
 
70
def read_dir(path):
 
71
    """Like os.listdir, this reads a directories contents.
 
72
 
 
73
    :param path: the directory to list.
 
74
    :return: a list of (basename, kind) tuples.
 
75
    """
 
76
    cdef DIR *the_dir
 
77
    # currently this needs a fixup - the C code says 'dirent' but should say
 
78
    # 'struct dirent'
 
79
    cdef dirent * entry
 
80
    cdef dirent sentinel
 
81
    cdef char *name
 
82
    the_dir = opendir(path)
 
83
    if NULL == the_dir:
 
84
        raise OSError(errno, strerror(errno))
 
85
    result = []
 
86
    try:
 
87
        entry = &sentinel
 
88
        while entry != NULL:
 
89
            entry = readdir(the_dir)
 
90
            if entry == NULL:
 
91
                if errno == EAGAIN:
 
92
                    # try again
 
93
                    continue
 
94
                elif errno != ENOTDIR and errno != ENOENT and errno != 0:
 
95
                    # We see ENOTDIR at the end of a normal directory.
 
96
                    # As ENOTDIR for read_dir(file) is triggered on opendir,
 
97
                    # we consider ENOTDIR to be 'no error'.
 
98
                    # ENOENT is listed as 'invalid position in the dir stream' for
 
99
                    # readdir. We swallow this for now and just keep reading.
 
100
                    raise OSError(errno, strerror(errno))
 
101
                else:
 
102
                    # done
 
103
                    continue
 
104
            name = entry.d_name
 
105
            if not (name[0] == dot and (
 
106
                (name[1] == 0) or 
 
107
                (name[1] == dot and name [2] == 0))
 
108
                ):
 
109
                if entry.d_type == DT_UNKNOWN:
 
110
                    type = _unknown
 
111
                elif entry.d_type == DT_REG:
 
112
                    type = _file
 
113
                elif entry.d_type == DT_DIR:
 
114
                    type = _directory
 
115
                elif entry.d_type == DT_FIFO:
 
116
                    type = _fifo
 
117
                elif entry.d_type == DT_SOCK:
 
118
                    type = _socket
 
119
                elif entry.d_type == DT_CHR:
 
120
                    type = _chardev
 
121
                elif entry.d_type == DT_BLK:
 
122
                    type = _block
 
123
                else:
 
124
                    type = _unknown
 
125
                # result.append((entry.d_name, type))
 
126
                result.append((entry.d_name, 'unknown'))
 
127
    finally:
 
128
        if -1 == closedir(the_dir):
 
129
            raise OSError(errno, strerror(errno))
 
130
    return result
 
131
 
 
132
 
 
133
# vim: tw=79 ai expandtab sw=4 sts=4