1739.2.6
by Robert Collins
Merge bzr.dev |
1 |
# Copyright (C) 2006, 2008 Canonical Ltd
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
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 |
||
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
17 |
"""Wrapper for readdir which returns files ordered by inode."""
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
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 |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
27 |
int ENOTDIR |
28 |
int EAGAIN |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
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 |
|
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
49 |
int d_ino |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
50 |
ctypedef struct DIR |
51 |
# should be DIR *, pyrex barfs.
|
|
1739.2.6
by Robert Collins
Merge bzr.dev |
52 |
DIR * opendir(char * name) |
53 |
int closedir(DIR * dir) |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
54 |
dirent *readdir(DIR *dir) |
55 |
||
56 |
_directory = 'directory' |
|
57 |
_chardev = 'chardev' |
|
58 |
_block = 'block' |
|
59 |
_file = 'file' |
|
60 |
_fifo = 'fifo' |
|
61 |
_symlink = 'symlink' |
|
62 |
_socket = 'socket' |
|
63 |
_unknown = 'unknown' |
|
64 |
||
65 |
dot = ord('.') |
|
66 |
||
67 |
# add a typedef struct dirent dirent to workaround pyrex
|
|
68 |
cdef extern from 'readdir.h': |
|
69 |
pass
|
|
70 |
||
71 |
def read_dir(path): |
|
1739.2.11
by Robert Collins
Docstring and copyright header update per Martin's review. |
72 |
"""Like os.listdir, this reads the contents of a directory.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
73 |
|
74 |
:param path: the directory to list.
|
|
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
75 |
:return: a list of (sort_key, basename) tuples.
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
76 |
"""
|
77 |
cdef DIR *the_dir |
|
78 |
# currently this needs a fixup - the C code says 'dirent' but should say
|
|
79 |
# 'struct dirent'
|
|
80 |
cdef dirent * entry |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
81 |
cdef dirent sentinel |
82 |
cdef char *name |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
83 |
the_dir = opendir(path) |
1739.2.6
by Robert Collins
Merge bzr.dev |
84 |
if NULL == the_dir: |
85 |
raise OSError(errno, strerror(errno)) |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
86 |
result = [] |
87 |
try: |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
88 |
entry = &sentinel |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
89 |
while entry != NULL: |
1739.2.6
by Robert Collins
Merge bzr.dev |
90 |
entry = readdir(the_dir) |
91 |
if entry == NULL: |
|
92 |
if errno == EAGAIN: |
|
93 |
# try again
|
|
94 |
continue
|
|
95 |
elif errno != ENOTDIR and errno != ENOENT and errno != 0: |
|
96 |
# We see ENOTDIR at the end of a normal directory.
|
|
97 |
# As ENOTDIR for read_dir(file) is triggered on opendir,
|
|
98 |
# we consider ENOTDIR to be 'no error'.
|
|
99 |
# ENOENT is listed as 'invalid position in the dir stream' for
|
|
100 |
# readdir. We swallow this for now and just keep reading.
|
|
101 |
raise OSError(errno, strerror(errno)) |
|
102 |
else: |
|
103 |
# done
|
|
104 |
continue
|
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
105 |
name = entry.d_name |
106 |
if not (name[0] == dot and ( |
|
107 |
(name[1] == 0) or |
|
1739.2.9
by Robert Collins
Review feedback. |
108 |
(name[1] == dot and name[2] == 0)) |
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
109 |
):
|
1739.2.7
by Robert Collins
Update readdir pyrex source files and usage in line with current practice. |
110 |
result.append((entry.d_ino, entry.d_name)) |
1739.2.6
by Robert Collins
Merge bzr.dev |
111 |
finally: |
112 |
if -1 == closedir(the_dir): |
|
1739.2.3
by Robert Collins
Add a replacement for os.listdir which returns file kind information from readdir when it is available. This drops our osutils.walkdirs time further, down to 77ms. |
113 |
raise OSError(errno, strerror(errno)) |
114 |
return result |
|
1739.2.6
by Robert Collins
Merge bzr.dev |
115 |
|
116 |
||
117 |
# vim: tw=79 ai expandtab sw=4 sts=4
|