##// END OF EJS Templates
osutil: fix some braindamage...
Matt Mackall -
r7033:892d27fb default
parent child Browse files
Show More
@@ -1,226 +1,225
1 1 /*
2 2 osutil.c - native operating system services
3 3
4 4 Copyright 2007 Matt Mackall and others
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 #define _ATFILE_SOURCE
11 11 #include <Python.h>
12 12 #include <dirent.h>
13 13 #include <fcntl.h>
14 14 #include <string.h>
15 15 #include <sys/stat.h>
16 16 #include <sys/types.h>
17 17 #include <unistd.h>
18 18
19 19 struct listdir_stat {
20 20 PyObject_HEAD
21 21 struct stat st;
22 22 };
23 23
24 24 #define listdir_slot(name) \
25 25 static PyObject *listdir_stat_##name(PyObject *self, void *x) \
26 26 { \
27 27 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
28 28 }
29 29
30 30 listdir_slot(st_dev)
31 31 listdir_slot(st_mode)
32 32 listdir_slot(st_nlink)
33 33 listdir_slot(st_size)
34 34 listdir_slot(st_mtime)
35 35 listdir_slot(st_ctime)
36 36
37 37 static struct PyGetSetDef listdir_stat_getsets[] = {
38 38 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
39 39 {"st_mode", listdir_stat_st_mode, 0, 0, 0},
40 40 {"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
41 41 {"st_size", listdir_stat_st_size, 0, 0, 0},
42 42 {"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
43 43 {"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
44 44 {0, 0, 0, 0, 0}
45 45 };
46 46
47 47 static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
48 48 {
49 49 return t->tp_alloc(t, 0);
50 50 }
51 51
52 52 static void listdir_stat_dealloc(PyObject *o)
53 53 {
54 54 o->ob_type->tp_free(o);
55 55 }
56 56
57 57 static PyTypeObject listdir_stat_type = {
58 58 PyObject_HEAD_INIT(NULL)
59 59 0, /*ob_size*/
60 60 "osutil.stat", /*tp_name*/
61 61 sizeof(struct listdir_stat), /*tp_basicsize*/
62 62 0, /*tp_itemsize*/
63 63 (destructor)listdir_stat_dealloc, /*tp_dealloc*/
64 64 0, /*tp_print*/
65 65 0, /*tp_getattr*/
66 66 0, /*tp_setattr*/
67 67 0, /*tp_compare*/
68 68 0, /*tp_repr*/
69 69 0, /*tp_as_number*/
70 70 0, /*tp_as_sequence*/
71 71 0, /*tp_as_mapping*/
72 72 0, /*tp_hash */
73 73 0, /*tp_call*/
74 74 0, /*tp_str*/
75 75 0, /*tp_getattro*/
76 76 0, /*tp_setattro*/
77 77 0, /*tp_as_buffer*/
78 78 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
79 79 "stat objects", /* tp_doc */
80 80 0, /* tp_traverse */
81 81 0, /* tp_clear */
82 82 0, /* tp_richcompare */
83 83 0, /* tp_weaklistoffset */
84 84 0, /* tp_iter */
85 85 0, /* tp_iternext */
86 86 0, /* tp_methods */
87 87 0, /* tp_members */
88 88 listdir_stat_getsets, /* tp_getset */
89 89 0, /* tp_base */
90 90 0, /* tp_dict */
91 91 0, /* tp_descr_get */
92 92 0, /* tp_descr_set */
93 93 0, /* tp_dictoffset */
94 94 0, /* tp_init */
95 95 0, /* tp_alloc */
96 96 listdir_stat_new, /* tp_new */
97 97 };
98 98
99 #ifdef AT_SYMLINK_NOFOLLOW
100 #define USEFDOPEN 1
101 #else
102 #define USEFDOPEN 0
103 #endif
104
105 99 int entkind(struct dirent *ent)
106 100 {
107 101 #ifdef DT_REG
108 102 switch (ent->d_type) {
109 103 case DT_REG: return S_IFREG;
110 104 case DT_DIR: return S_IFDIR;
111 105 case DT_LNK: return S_IFLNK;
112 106 case DT_BLK: return S_IFBLK;
113 107 case DT_CHR: return S_IFCHR;
114 108 case DT_FIFO: return S_IFIFO;
115 109 case DT_SOCK: return S_IFSOCK;
116 110 }
117 111 #endif
112 return -1;
118 113 }
119 114
120 115 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
121 116 {
122 117 static char *kwlist[] = { "path", "stat", NULL };
123 118 PyObject *statflag = NULL, *list, *elem, *stat, *ret = NULL;
124 119 char fullpath[PATH_MAX + 10], *path;
125 int pathlen, keepstat, kind, dfd, err;
120 int pathlen, keepstat, kind, dfd = -1, err;
126 121 struct stat st;
127 122 struct dirent *ent;
128 123 DIR *dir;
129 124
130 125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist,
131 126 &path, &pathlen, &statflag))
132 127 goto error_parse;
128 if (pathlen >= PATH_MAX)
129 goto error_parse;
133 130
134 131 strncpy(fullpath, path, PATH_MAX);
135 132 fullpath[pathlen] = '/';
136 133 keepstat = statflag && PyObject_IsTrue(statflag);
137 134
138 if (USEFDOPEN) {
135 #ifdef AT_SYMLINK_NOFOLLOW
139 136 dfd = open(path, O_RDONLY);
140 137 if (dfd == -1) {
141 138 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
142 139 goto error_parse;
143 140 }
144 141 dir = fdopendir(dfd);
145 } else
142 #else
146 143 dir = opendir(path);
144 #endif
147 145 if (!dir) {
148 146 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
149 147 goto error_dir;
150 148 }
151 149
152 150 list = PyList_New(0);
153 151 if (!list)
154 152 goto error_list;
155 153
156 154 while ((ent = readdir(dir))) {
157 155 if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
158 156 continue;
159 157
160 158 kind = entkind(ent);
161 159 if (kind == -1 || keepstat) {
162 if (USEFDOPEN)
160 #ifdef AT_SYMLINK_NOFOLLOW
163 161 err = fstatat(dfd, ent->d_name, &st,
164 162 AT_SYMLINK_NOFOLLOW);
165 else {
163 #else
166 164 strncpy(fullpath + pathlen + 1, ent->d_name,
167 165 PATH_MAX - pathlen);
168 166 fullpath[PATH_MAX] = 0;
169 167 err = lstat(fullpath, &st);
170 }
168 #endif
171 169 if (err == -1) {
172 170 strncpy(fullpath + pathlen + 1, ent->d_name,
173 171 PATH_MAX - pathlen);
174 172 fullpath[PATH_MAX] = 0;
175 173 PyErr_SetFromErrnoWithFilename(PyExc_OSError,
176 174 fullpath);
177 175 goto error;
178 176 }
179 177 kind = st.st_mode & S_IFMT;
180 178 }
181 179
182 180 if (keepstat) {
183 181 stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
184 182 if (!stat)
185 183 goto error;
186 184 memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
187 185 elem = Py_BuildValue("siN", ent->d_name, kind, stat);
188 186 } else
189 187 elem = Py_BuildValue("si", ent->d_name, kind);
190 188 if (!elem)
191 189 goto error;
192 190
193 191 PyList_Append(list, elem);
194 192 Py_DECREF(elem);
195 193 }
196 194
197 195 PyList_Sort(list);
198 196 ret = list;
199 197 Py_INCREF(ret);
200 198
201 199 error:
202 200 Py_DECREF(list);
203 201 error_list:
204 202 closedir(dir);
205 203 error_dir:
206 if (USEFDOPEN)
204 #ifdef AT_SYMLINK_NOFOLLOW
207 205 close(dfd);
206 #endif
208 207 error_parse:
209 208 return ret;
210 209 }
211 210
212 211 static char osutil_doc[] = "Native operating system services.";
213 212
214 213 static PyMethodDef methods[] = {
215 214 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
216 215 "list a directory\n"},
217 216 {NULL, NULL}
218 217 };
219 218
220 219 PyMODINIT_FUNC initosutil(void)
221 220 {
222 221 if (PyType_Ready(&listdir_stat_type) == -1)
223 222 return;
224 223
225 224 Py_InitModule3("osutil", methods, osutil_doc);
226 225 }
General Comments 0
You need to be logged in to leave comments. Login now