comparison mercurial/osutil.c @ 5425:830f6e280c90

osutils: pull file stat loop into its own function
author Matt Mackall <mpm@selenic.com>
date Mon, 08 Oct 2007 18:47:16 -0500
parents 005638db9d0c
children e760cb72c02e
comparison
equal deleted inserted replaced
5424:005638db9d0c 5425:830f6e280c90
107 if (S_ISFIFO(mode)) return S_IFIFO; 107 if (S_ISFIFO(mode)) return S_IFIFO;
108 if (S_ISSOCK(mode)) return S_IFSOCK; 108 if (S_ISSOCK(mode)) return S_IFSOCK;
109 return mode; 109 return mode;
110 } 110 }
111 111
112 static PyObject *statfiles(PyObject *list, PyObject *ctor_args, int keep,
113 char *path, int len, DIR *dir)
114 {
115 struct stat buf;
116 struct stat *stp = &buf;
117 int kind;
118 int ret;
119 ssize_t i;
120 ssize_t size = PyList_Size(list);
121 #ifdef AT_SYMLINK_NOFOLLOW
122 int dfd = dirfd(dir);
123 #endif
124
125 for (i = 0; i < size; i++) {
126 PyObject *elt = PyList_GetItem(list, i);
127 char *name = PyString_AsString(PyTuple_GET_ITEM(elt, 0));
128 PyObject *py_st = NULL;
129 PyObject *py_kind = PyTuple_GET_ITEM(elt, 1);
130
131 kind = py_kind == Py_None ? -1 : PyInt_AsLong(py_kind);
132 if (kind != -1 && !keep)
133 continue;
134
135 strncat(path + len + 1, name, PATH_MAX - len);
136 path[PATH_MAX] = 0;
137
138 if (keep) {
139 py_st = PyObject_CallObject(
140 (PyObject *)&listdir_stat_type, ctor_args);
141 if (!py_st)
142 return PyErr_NoMemory();
143 stp = &((struct listdir_stat *)py_st)->st;
144 PyTuple_SET_ITEM(elt, 2, py_st);
145 }
146
147 #ifdef AT_SYMLINK_NOFOLLOW
148 ret = fstatat(dfd, name, stp, AT_SYMLINK_NOFOLLOW);
149 #else
150 ret = lstat(path, stp);
151 #endif
152 if (ret == -1)
153 return PyErr_SetFromErrnoWithFilename(PyExc_OSError,
154 path);
155
156 if (kind == -1)
157 kind = mode_to_kind(stp->st_mode);
158
159 if (py_kind == Py_None && kind != -1) {
160 py_kind = PyInt_FromLong(kind);
161 if (!py_kind)
162 return PyErr_NoMemory();
163 Py_XDECREF(Py_None);
164 PyTuple_SET_ITEM(elt, 1, py_kind);
165 }
166 }
167
168 return 0;
169 }
170
112 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) 171 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
113 { 172 {
114 static char *kwlist[] = { "path", "stat", NULL }; 173 static char *kwlist[] = { "path", "stat", NULL };
115 PyObject *statobj = NULL; 174 PyObject *statobj = NULL;
116 DIR *dir = NULL; 175 DIR *dir = NULL;
117 struct dirent *ent; 176 struct dirent *ent;
118 PyObject *list = NULL; 177 PyObject *list = NULL;
178 PyObject *err = NULL;
119 PyObject *ctor_args = NULL; 179 PyObject *ctor_args = NULL;
120 int all_kinds = 1; 180 int all_kinds = 1;
121 char full_path[PATH_MAX + 10]; 181 char full_path[PATH_MAX + 10];
122 int path_len; 182 int path_len;
123 int do_stat; 183 int do_stat;
124 char *path; 184 char *path;
125 int ret;
126 ssize_t size;
127 ssize_t i;
128 int dfd;
129 185
130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist, 186 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist,
131 &path, &path_len, &statobj)) 187 &path, &path_len, &statobj))
132 goto bail; 188 goto bail;
133 189
208 PyList_Append(list, val); 264 PyList_Append(list, val);
209 Py_DECREF(val); 265 Py_DECREF(val);
210 } 266 }
211 267
212 PyList_Sort(list); 268 PyList_Sort(list);
213 size = PyList_Size(list); 269
214 #ifdef AT_SYMLINK_NOFOLLOW 270 if (do_stat) {
215 dfd = dirfd(dir); 271 ctor_args = PyTuple_New(0);
216 #endif 272 if (!ctor_args)
217
218 if (!(do_stat || !all_kinds))
219 goto done;
220
221 for (i = 0; i < size; i++) {
222 PyObject *elt = PyList_GetItem(list, i);
223 char *name = PyString_AsString(PyTuple_GET_ITEM(elt, 0));
224 PyObject *py_st = NULL;
225 PyObject *py_kind = PyTuple_GET_ITEM(elt, 1);
226 struct listdir_stat *st;
227 struct stat buf;
228 struct stat *stp = &buf;
229 int kind;
230
231 kind = py_kind == Py_None ? -1 : PyInt_AsLong(py_kind);
232
233 if (kind != -1 && !do_stat)
234 continue;
235
236 strncat(full_path + path_len + 1, name, PATH_MAX - path_len);
237 full_path[PATH_MAX] = 0;
238
239 if (do_stat) {
240 if (!ctor_args) {
241 ctor_args = PyTuple_New(0);
242 if (!ctor_args)
243 goto bail;
244 }
245
246 py_st = PyObject_CallObject((PyObject *)&listdir_stat_type,
247 ctor_args);
248 st = (struct listdir_stat *)py_st;
249 if (!st)
250 goto bail;
251 stp = &st->st;
252 PyTuple_SET_ITEM(elt, 2, py_st);
253 }
254
255 #ifdef AT_SYMLINK_NOFOLLOW
256 ret = fstatat(dfd, name, stp, AT_SYMLINK_NOFOLLOW);
257 #else
258 ret = lstat(full_path, stp);
259 #endif
260 if (ret == -1) {
261 list = PyErr_SetFromErrnoWithFilename(PyExc_OSError,
262 full_path);
263 goto bail; 273 goto bail;
264 }
265 if (kind == -1)
266 kind = mode_to_kind(stp->st_mode);
267
268 if (py_kind == Py_None && kind != -1) {
269 py_kind = PyInt_FromLong(kind);
270 if (!py_kind)
271 goto bail;
272 Py_XDECREF(Py_None);
273 PyTuple_SET_ITEM(elt, 1, py_kind);
274 }
275 } 274 }
276 275
276 if (do_stat || !all_kinds)
277 if (statfiles(list, ctor_args, do_stat, full_path, path_len,
278 dir))
279 goto bail;
277 goto done; 280 goto done;
278 281
279 bail: 282 bail:
280 Py_XDECREF(list); 283 Py_XDECREF(list);
281 284
282 done: 285 done:
283 Py_XDECREF(ctor_args); 286 Py_XDECREF(ctor_args);
284 if (dir) 287 if (dir)
285 closedir(dir); 288 closedir(dir);
286 return list; 289 return err ? err : list;
287 } 290 }
288 291
289 292
290 static char osutil_doc[] = "Native operating system services."; 293 static char osutil_doc[] = "Native operating system services.";
291 294