root/masterdriverz/snakeoil-formatters/src/readdir.c @ tfkyle%2540gmail.com-20070324221905-gyh0s6ki1oadjx35

Revision tfkyle%2540gmail.com-20070324221905-gyh0s6ki1oadjx35, 10.9 kB (checked in by Kyle McFarland <tfkyle@…>, 22 months ago)

s/snakeoil.util/snakeoil/

Line 
1/*
2 * Copyright: 2006 Brian Harring <ferringb@gmail.com>
3 * Copyright: 2006-2007 Marien Zwart <marienz@gentoo.org>
4 * License: GPL2
5 *
6 * C version of some of snakeoil (for extra speed).
7 */
8
9/* This does not really do anything since we do not use the "#"
10 * specifier in a PyArg_Parse or similar call, but hey, not using it
11 * means we are Py_ssize_t-clean too!
12 */
13
14#define PY_SSIZE_T_CLEAN
15
16#include "Python.h"
17
18/* Compatibility with python < 2.5 */
19
20#if PY_VERSION_HEX < 0x02050000
21typedef int Py_ssize_t;
22#define PY_SSIZE_T_MAX INT_MAX
23#define PY_SSIZE_T_MIN INT_MIN
24#endif
25
26#include <dirent.h>
27#include <sys/stat.h>
28
29
30static PyObject *snakeoil_DIRSTR,
31    *snakeoil_CHRSTR,
32    *snakeoil_BLKSTR,
33    *snakeoil_REGSTR,
34    *snakeoil_FIFOSTR,
35    *snakeoil_LNKSTR,
36    *snakeoil_SOCKSTR,
37    *snakeoil_UNKNOWNSTR;
38
39/* This function does the actual work for listdir_files and listdir_dirs. */
40
41static PyObject*
42snakeoil_readdir_actual_listdir(const char* path, int followsyms,
43    int dkind, int skind)
44{
45    DIR *the_dir;
46    struct dirent *entry;
47
48    PyObject *string;
49
50    int pathlen = strlen(path);
51
52    PyObject *result = PyList_New(0);
53    if (!result) {
54        return NULL;
55    }
56    if (!(the_dir = opendir(path))) {
57        return PyErr_SetFromErrno(PyExc_OSError);
58    }
59    errno = 0;
60    while ((entry = readdir(the_dir))) {
61        const char *name = entry->d_name;
62        /* skip over "." and ".." */
63        if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' &&
64            name[2] == 0))) {
65            continue;
66        }
67        if (entry->d_type == DT_UNKNOWN ||
68            (followsyms && entry->d_type == DT_LNK)) {
69
70            /* both path components, the "/", the trailing null */
71
72            size_t size = pathlen + strlen(name) + 2;
73            char *buffer = (char *) malloc(size);
74            if (!buffer) {
75                Py_DECREF(result);
76                return PyErr_NoMemory();
77            }
78            snprintf(buffer, size, "%s/%s", path, name);
79
80            struct stat st;
81            int ret;
82            if (followsyms) {
83                ret = stat(buffer, &st);
84            } else {
85                ret = lstat(buffer, &st);
86            }
87            free(buffer);
88            if (ret != 0) {
89                if (followsyms && errno == ENOENT) {
90                    /* hit a dangling symlimk; skip. */
91                    errno = 0;
92                    continue;
93                }
94                Py_DECREF(result);
95                result = NULL;
96                break;
97            }
98
99            if ((st.st_mode & S_IFMT) != skind) {
100                continue;
101            }
102        } else if (entry->d_type != dkind) {
103            continue;
104        }
105        if (!(string = PyString_FromString(name))) {
106            Py_DECREF(result);
107            result = NULL;
108            break;
109        }
110        if (PyList_Append(result, string) == -1) {
111            Py_DECREF(string);
112            Py_DECREF(result);
113            result = NULL;
114            break;
115        }
116        Py_DECREF(string);
117    }
118    closedir(the_dir);
119    if (errno) {
120        return PyErr_SetFromErrno(PyExc_OSError);
121    }
122    return result;
123}
124
125static PyObject*
126snakeoil_readdir_listdir_dirs(PyObject* self, PyObject* args)
127{
128    char *path;
129    PyObject *follow_symlinks_obj = Py_True;
130
131    if (!PyArg_ParseTuple(args, "s|O", &path, &follow_symlinks_obj)) {
132        return NULL;
133    }
134
135    int follow_symlinks = PyObject_IsTrue(follow_symlinks_obj);
136    if (follow_symlinks == -1) {
137        return NULL;
138    }
139
140    return snakeoil_readdir_actual_listdir(path, follow_symlinks,
141        DT_DIR, S_IFDIR);
142}
143
144static PyObject*
145snakeoil_readdir_listdir_files(PyObject* self, PyObject* args)
146{
147    char *path;
148    PyObject *follow_symlinks_obj = Py_True;
149
150    if (!PyArg_ParseTuple(args, "s|O", &path, &follow_symlinks_obj)) {
151        return NULL;
152    }
153
154    int follow_symlinks = PyObject_IsTrue(follow_symlinks_obj);
155    if (follow_symlinks == -1) {
156        return NULL;
157    }
158
159    return snakeoil_readdir_actual_listdir(path, follow_symlinks,
160        DT_REG, S_IFREG);
161}
162
163static PyObject*
164snakeoil_readdir_listdir(PyObject* self, PyObject* args)
165{
166    char *path;
167
168    if (!PyArg_ParseTuple(args, "s", &path)) {
169        return NULL;
170    }
171
172    PyObject *result = PyList_New(0);
173    if (!result) {
174        return NULL;
175    }
176
177    DIR *the_dir = opendir(path);
178    if (!the_dir) {
179        return PyErr_SetFromErrno(PyExc_OSError);
180    }
181    errno = 0;
182    struct dirent *entry;
183    while ((entry = readdir(the_dir))) {
184        const char *name = entry->d_name;
185        /* skip over "." and ".." */
186        if (!(name[0] == '.' && (name[1] == 0 ||
187            (name[1] == '.' && name[2] == 0)))) {
188
189            PyObject *string = PyString_FromString(name);
190            if (!string) {
191                Py_DECREF(result);
192                result = NULL;
193                break;
194            }
195            int res = PyList_Append(result, string);
196            Py_DECREF(string);
197            if (res == -1) {
198                Py_DECREF(result);
199                result = NULL;
200                break;
201            }
202        }
203    }
204    closedir(the_dir);
205    if (errno) {
206        return PyErr_SetFromErrno(PyExc_OSError);
207    }
208    return result;
209}
210
211static PyObject*
212snakeoil_readdir_read_dir(PyObject* self, PyObject* args)
213{
214    char *path;
215
216    if (!PyArg_ParseTuple(args, "s", &path)) {
217        return NULL;
218    }
219    ssize_t pathlen = strlen(path);
220
221    PyObject *result = PyList_New(0);
222    if (!result) {
223        return NULL;
224    }
225
226    DIR *the_dir = opendir(path);
227    if (!the_dir) {
228        return PyErr_SetFromErrno(PyExc_OSError);
229    }
230
231    struct dirent *entry;
232    while ((entry = readdir(the_dir))) {
233        const char *name = entry->d_name;
234        /* skip over "." and ".." */
235        if (name[0] == '.' && (name[1] == 0 ||
236            (name[1] == '.' && name[2] == 0))) {
237            continue;
238        }
239
240        PyObject *typestr;
241        switch (entry->d_type) {
242            case DT_REG:
243                typestr = snakeoil_REGSTR;
244                break;
245            case DT_DIR:
246                typestr = snakeoil_DIRSTR;
247                break;
248            case DT_FIFO:
249                typestr = snakeoil_FIFOSTR;
250                break;
251            case DT_SOCK:
252                typestr = snakeoil_SOCKSTR;
253                break;
254            case DT_CHR:
255                typestr = snakeoil_CHRSTR;
256                break;
257            case DT_BLK:
258                typestr = snakeoil_BLKSTR;
259                break;
260            case DT_LNK:
261                typestr = snakeoil_LNKSTR;
262                break;
263            case DT_UNKNOWN:
264            {
265                /* both path components, the "/", the trailing null */
266                size_t size = pathlen + strlen(name) + 2;
267                char *buffer = (char *) malloc(size);
268                if (!buffer) {
269                    closedir(the_dir);
270                    return PyErr_NoMemory();
271                }
272                snprintf(buffer, size, "%s/%s", path, name);
273                struct stat st;
274                int ret = lstat(buffer, &st);
275                free(buffer);
276                if (ret == -1) {
277                    closedir(the_dir);
278                    return PyErr_SetFromErrno(PyExc_OSError);
279                }
280                switch (st.st_mode & S_IFMT) {
281                    case S_IFDIR:
282                        typestr = snakeoil_DIRSTR;
283                        break;
284                    case S_IFCHR:
285                        typestr = snakeoil_CHRSTR;
286                        break;
287                    case S_IFBLK:
288                        typestr = snakeoil_BLKSTR;
289                        break;
290                    case S_IFREG:
291                        typestr = snakeoil_REGSTR;
292                        break;
293                    case S_IFLNK:
294                        typestr = snakeoil_LNKSTR;
295                        break;
296                    case S_IFSOCK:
297                        typestr = snakeoil_SOCKSTR;
298                        break;
299                    case S_IFIFO:
300                        typestr = snakeoil_FIFOSTR;
301                        break;
302                    default:
303                        /* XXX does this make sense? probably not. */
304                        typestr = snakeoil_UNKNOWNSTR;
305                }
306            }
307            break;
308
309            default:
310                /* XXX does this make sense? probably not. */
311                typestr = snakeoil_UNKNOWNSTR;
312        }
313
314        PyObject *namestr = PyString_FromString(name);
315        if (!namestr) {
316            Py_DECREF(result);
317            result = NULL;
318            break;
319        }
320        /* Slight hack: incref typestr after our error checks. */
321        PyObject *tuple = PyTuple_Pack(2, namestr, typestr);
322        Py_DECREF(namestr);
323        if (!tuple) {
324            Py_DECREF(result);
325            result = NULL;
326            break;
327        }
328        Py_INCREF(typestr);
329
330        int res = PyList_Append(result, tuple);
331        Py_DECREF(tuple);
332        if (res == -1) {
333            Py_DECREF(result);
334            result = NULL;
335            break;
336        }
337    }
338    if (closedir(the_dir) == -1) {
339        return PyErr_SetFromErrno(PyExc_OSError);
340    }
341    return result;
342}
343
344/* Module initialization */
345
346static PyMethodDef snakeoil_readdir_methods[] = {
347    {"listdir", (PyCFunction)snakeoil_readdir_listdir, METH_VARARGS,
348     "listdir(path, followSymlinks=True, kinds=everything)"},
349    {"listdir_dirs", (PyCFunction)snakeoil_readdir_listdir_dirs, METH_VARARGS,
350     "listdir_dirs(path, followSymlinks=True)"},
351    {"listdir_files", (PyCFunction)snakeoil_readdir_listdir_files, METH_VARARGS,
352     "listdir_files(path, followSymlinks=True)"},
353    {"readdir", (PyCFunction)snakeoil_readdir_read_dir, METH_VARARGS,
354     "read_dir(path)"},
355    {NULL}
356};
357
358PyDoc_STRVAR(
359    snakeoil_module_documentation,
360    "C reimplementation of some of snakeoil.osutils");
361
362PyMODINIT_FUNC
363init_readdir()
364{
365    PyObject *m;
366
367    /* XXX we have to initialize these before we call InitModule3 because
368     * the snakeoil_readdir_methods use them, which screws up error handling.
369     */
370    snakeoil_DIRSTR = PyString_FromString("directory");
371    snakeoil_CHRSTR = PyString_FromString("chardev");
372    snakeoil_BLKSTR = PyString_FromString("block");
373    snakeoil_REGSTR = PyString_FromString("file");
374    snakeoil_FIFOSTR = PyString_FromString("fifo");
375    snakeoil_LNKSTR = PyString_FromString("symlink");
376    snakeoil_SOCKSTR = PyString_FromString("socket");
377    snakeoil_UNKNOWNSTR = PyString_FromString("unknown");
378
379    if (!(snakeoil_DIRSTR &&
380          snakeoil_CHRSTR &&
381          snakeoil_BLKSTR &&
382          snakeoil_REGSTR &&
383          snakeoil_FIFOSTR &&
384          snakeoil_LNKSTR &&
385          snakeoil_SOCKSTR &&
386          snakeoil_UNKNOWNSTR)) {
387        Py_FatalError("Can't initialize module _readdir (strings)");
388    }
389
390    /* Create the module and add the functions */
391    m = Py_InitModule3("_readdir", snakeoil_readdir_methods,
392                       snakeoil_module_documentation);
393    if (!m)
394        return;
395
396    /* Success! */
397}
Note: See TracBrowser for help on using the browser.