~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/_readdir_pyx.pyx

  • Committer: Andrew Bennetts
  • Date: 2009-11-25 07:27:43 UTC
  • mto: This revision was merged to the branch mainline in revision 4825.
  • Revision ID: andrew.bennetts@canonical.com-20091125072743-v6sv4m2mkt9iyslp
Terminate SSHSubprocesses when no refs to them are left, in case .close is never called.

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
78
78
 
79
79
 
80
80
cdef extern from 'Python.h':
81
 
    int PyErr_CheckSignals() except -1
82
81
    char * PyString_AS_STRING(object)
83
82
    ctypedef int Py_ssize_t # Required for older pyrex versions
84
83
    ctypedef struct PyObject:
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':
168
160
 
169
161
from bzrlib import osutils
170
162
 
171
 
cdef object _safe_utf8
172
 
_safe_utf8 = osutils.safe_utf8
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.
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
 
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
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: ",
 
343
                            raise OSError(errno, "lstat: " + strerror(errno),
349
344
                                path + "/" + entry.d_name)
350
345
                        else:
351
346
                            # the file seems to have disappeared after being
363
358
                        statvalue, None))
364
359
        finally:
365
360
            if -1 == closedir(the_dir):
366
 
                raise_os_error(errno, "closedir: ", path)
 
361
                raise OSError(errno, "closedir: " + strerror(errno), path)
367
362
    finally:
368
363
        if -1 != orig_dir_fd:
369
364
            failed = False
371
366
                # try to close the original directory anyhow
372
367
                failed = True
373
368
            if -1 == close(orig_dir_fd) or failed:
374
 
                raise_os_error(errno, "return to orig_dir: ", "")
 
369
                raise OSError(errno, "return to orig_dir: " + strerror(errno))
375
370
 
376
371
    return result
377
372