145
163
(mode, ino, dev, nlink, uid, gid, size, None(atime), mtime, ctime)
147
165
return repr((self.st_mode, 0, 0, 0, 0, 0, self.st_size, None,
148
self._mtime, self._ctime))
166
self.st_mtime, self.st_ctime))
151
169
from bzrlib import osutils
171
cdef object _safe_utf8
172
_safe_utf8 = osutils.safe_utf8
154
174
cdef class UTF8DirReader:
155
175
"""A dir reader for utf8 file systems."""
157
cdef readonly object _safe_utf8
158
cdef _directory, _chardev, _block, _file, _fifo, _symlink
159
cdef _socket, _unknown
162
self._safe_utf8 = osutils.safe_utf8
163
self._directory = _directory
164
self._chardev = _chardev
168
self._symlink = _symlink
169
self._socket = _socket
170
self._unknown = _unknown
172
177
def kind_from_mode(self, int mode):
173
178
"""Get the kind of a path from a mode status."""
174
179
return self._kind_from_mode(mode)
176
181
cdef _kind_from_mode(self, int mode):
177
182
# Files and directories are the most common - check them first.
178
183
if S_ISREG(mode):
180
185
if S_ISDIR(mode):
181
return self._directory
182
187
if S_ISCHR(mode):
184
189
if S_ISBLK(mode):
186
191
if S_ISLNK(mode):
188
193
if S_ISFIFO(mode):
190
195
if S_ISSOCK(mode):
194
199
def top_prefix_to_starting_dir(self, top, prefix=""):
195
200
"""See DirReader.top_prefix_to_starting_dir."""
196
return (self._safe_utf8(prefix), None, None, None,
197
self._safe_utf8(top))
201
return (_safe_utf8(prefix), None, None, None, _safe_utf8(top))
199
203
def read_dir(self, prefix, top):
200
204
"""Read a single directory from a utf8 file system.
278
288
cdef int stat_result
279
289
cdef _Stat statvalue
282
cwd = getcwd(NULL, 0)
283
if -1 == chdir(path):
284
raise OSError(errno, strerror(errno))
285
the_dir = opendir(".")
287
raise OSError(errno, strerror(errno))
293
# Avoid chdir('') because it causes problems on Sun OS, and avoid this if
295
if path != "" and path != '.':
296
# we change into the requested directory before reading, and back at the
297
# end, because that turns out to make the stat calls measurably faster than
298
# passing full paths every time.
299
orig_dir_fd = open(".", O_RDONLY, 0)
300
if orig_dir_fd == -1:
301
raise_os_error(errno, "open: ", ".")
302
if -1 == chdir(path):
303
# Ignore the return value, because we are already raising an
306
raise_os_error(errno, "chdir: ", path)
292
entry = readdir(the_dir)
297
elif errno != ENOTDIR and errno != ENOENT and errno != 0:
298
# We see ENOTDIR at the end of a normal directory.
299
# As ENOTDIR for read_dir(file) is triggered on opendir,
300
# we consider ENOTDIR to be 'no error'.
301
# ENOENT is listed as 'invalid position in the dir stream' for
302
# readdir. We swallow this for now and just keep reading.
303
raise OSError(errno, strerror(errno))
308
if not (name[0] == c"." and (
310
(name[1] == c"." and name[2] == 0))
313
stat_result = lstat(entry.d_name, &statvalue._st)
316
raise OSError(errno, strerror(errno))
320
# We append a 5-tuple that can be modified in-place by the C
322
# inode to sort on (to replace with top_path)
324
# kind (None, to set)
325
# statvalue (to keep)
326
# abspath (None, to set)
327
PyList_Append(result, (entry.d_ino, entry.d_name, None,
311
the_dir = opendir(".")
313
raise_os_error(errno, "opendir: ", path)
318
# Unlike most libc functions, readdir needs errno set to 0
319
# beforehand so that eof can be distinguished from errors. See
320
# <https://bugs.launchpad.net/bzr/+bug/279381>
323
entry = readdir(the_dir)
324
if entry == NULL and (errno == EAGAIN or errno == EINTR):
332
if errno == ENOTDIR or errno == 0:
333
# We see ENOTDIR at the end of a normal directory.
334
# As ENOTDIR for read_dir(file) is triggered on opendir,
335
# we consider ENOTDIR to be 'no error'.
338
raise_os_error(errno, "readdir: ", path)
340
if not (name[0] == c"." and (
342
(name[1] == c"." and name[2] == 0))
345
stat_result = lstat(entry.d_name, &statvalue._st)
348
raise_os_error(errno, "lstat: ",
349
path + "/" + entry.d_name)
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.
355
# We append a 5-tuple that can be modified in-place by the C
357
# inode to sort on (to replace with top_path)
359
# kind (None, to set)
360
# statvalue (to keep)
361
# abspath (None, to set)
362
PyList_Append(result, (entry.d_ino, entry.d_name, None,
365
if -1 == closedir(the_dir):
366
raise_os_error(errno, "closedir: ", path)
332
raise OSError(errno, strerror(errno))
334
if -1 == closedir(the_dir):
335
raise OSError(errno, strerror(errno))
368
if -1 != orig_dir_fd:
370
if -1 == fchdir(orig_dir_fd):
371
# try to close the original directory anyhow
373
if -1 == close(orig_dir_fd) or failed:
374
raise_os_error(errno, "return to orig_dir: ", "")