##// END OF EJS Templates
merge with crew-stable
merge with crew-stable

File last commit:

r7034:0d513661 default
r7050:67886086 merge default
Show More
osutil.c
231 lines | 5.9 KiB | text/x-c | CLexer
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 /*
osutil.c - native operating system services
Copyright 2007 Matt Mackall and others
This software may be used and distributed according to the terms of
the GNU General Public License, incorporated herein by reference.
*/
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 #define _ATFILE_SOURCE
Alexis S. L. Carvalho
osutil.c: include Python.h before the other headers...
r5397 #include <Python.h>
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 #include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
struct listdir_stat {
Matt Mackall
osutil: cleanups...
r5421 PyObject_HEAD
struct stat st;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
#define listdir_slot(name) \
static PyObject *listdir_stat_##name(PyObject *self, void *x) \
{ \
Matt Mackall
osutil: cleanups...
r5421 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
Bryan O'Sullivan
Fix build error with Sun C compiler.
r5431 listdir_slot(st_dev)
listdir_slot(st_mode)
listdir_slot(st_nlink)
listdir_slot(st_size)
listdir_slot(st_mtime)
listdir_slot(st_ctime)
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
static struct PyGetSetDef listdir_stat_getsets[] = {
Matt Mackall
osutil: cleanups...
r5421 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
{"st_mode", listdir_stat_st_mode, 0, 0, 0},
{"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
{"st_size", listdir_stat_st_size, 0, 0, 0},
{"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
{"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
{0, 0, 0, 0, 0}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
{
Matt Mackall
osutil: cleanups...
r5421 return t->tp_alloc(t, 0);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
static void listdir_stat_dealloc(PyObject *o)
{
Matt Mackall
osutil: cleanups...
r5421 o->ob_type->tp_free(o);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
static PyTypeObject listdir_stat_type = {
Matt Mackall
osutil: cleanups...
r5421 PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"osutil.stat", /*tp_name*/
sizeof(struct listdir_stat), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)listdir_stat_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"stat objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
listdir_stat_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
listdir_stat_new, /* tp_new */
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
Matt Mackall
osutil: major listdir cleanup
r7031 int entkind(struct dirent *ent)
Matt Mackall
osutils: pull file stat loop into its own function
r5425 {
Matt Mackall
osutil: major listdir cleanup
r7031 #ifdef DT_REG
switch (ent->d_type) {
case DT_REG: return S_IFREG;
case DT_DIR: return S_IFDIR;
case DT_LNK: return S_IFLNK;
case DT_BLK: return S_IFBLK;
case DT_CHR: return S_IFCHR;
case DT_FIFO: return S_IFIFO;
case DT_SOCK: return S_IFSOCK;
}
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 #endif
Matt Mackall
osutil: fix some braindamage...
r7033 return -1;
Matt Mackall
osutils: pull file stat loop into its own function
r5425 }
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
{
Matt Mackall
listdir: add support for aborting if a certain path is found...
r7034 static char *kwlist[] = { "path", "stat", "skip", NULL };
Matt Mackall
osutil: major listdir cleanup
r7031 PyObject *statflag = NULL, *list, *elem, *stat, *ret = NULL;
Matt Mackall
listdir: add support for aborting if a certain path is found...
r7034 char fullpath[PATH_MAX + 10], *path, *skip = NULL;
Matt Mackall
osutil: fix some braindamage...
r7033 int pathlen, keepstat, kind, dfd = -1, err;
Matt Mackall
osutil: major listdir cleanup
r7031 struct stat st;
struct dirent *ent;
DIR *dir;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
listdir: add support for aborting if a certain path is found...
r7034 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|Os:listdir", kwlist,
&path, &pathlen, &statflag, &skip))
Matt Mackall
osutil: major listdir cleanup
r7031 goto error_parse;
Matt Mackall
listdir: add support for aborting if a certain path is found...
r7034
Matt Mackall
osutil: fix some braindamage...
r7033 if (pathlen >= PATH_MAX)
goto error_parse;
Matt Mackall
osutil: major listdir cleanup
r7031
strncpy(fullpath, path, PATH_MAX);
fullpath[pathlen] = '/';
keepstat = statflag && PyObject_IsTrue(statflag);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: fix some braindamage...
r7033 #ifdef AT_SYMLINK_NOFOLLOW
dfd = open(path, O_RDONLY);
if (dfd == -1) {
PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
goto error_parse;
}
dir = fdopendir(dfd);
#else
dir = opendir(path);
#endif
Matt Mackall
osutil: cleanups...
r5421 if (!dir) {
Matt Mackall
osutil: major listdir cleanup
r7031 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
goto error_dir;
}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: cleanups...
r5421 list = PyList_New(0);
Matt Mackall
osutil: major listdir cleanup
r7031 if (!list)
goto error_list;
while ((ent = readdir(dir))) {
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416
Matt Mackall
osutil: major listdir cleanup
r7031 kind = entkind(ent);
if (kind == -1 || keepstat) {
Matt Mackall
osutil: fix some braindamage...
r7033 #ifdef AT_SYMLINK_NOFOLLOW
err = fstatat(dfd, ent->d_name, &st,
AT_SYMLINK_NOFOLLOW);
#else
strncpy(fullpath + pathlen + 1, ent->d_name,
PATH_MAX - pathlen);
fullpath[PATH_MAX] = 0;
err = lstat(fullpath, &st);
#endif
Matt Mackall
osutil: major listdir cleanup
r7031 if (err == -1) {
strncpy(fullpath + pathlen + 1, ent->d_name,
PATH_MAX - pathlen);
fullpath[PATH_MAX] = 0;
PyErr_SetFromErrnoWithFilename(PyExc_OSError,
fullpath);
goto error;
}
kind = st.st_mode & S_IFMT;
}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
listdir: add support for aborting if a certain path is found...
r7034 /* quit early? */
if (skip && kind == S_IFDIR && !strcmp(ent->d_name, skip)) {
ret = PyList_New(0);
goto error;
}
Matt Mackall
osutil: major listdir cleanup
r7031 if (keepstat) {
stat = PyObject_CallObject((PyObject *)&listdir_stat_type, NULL);
if (!stat)
goto error;
memcpy(&((struct listdir_stat *)stat)->st, &st, sizeof(st));
elem = Py_BuildValue("siN", ent->d_name, kind, stat);
} else
elem = Py_BuildValue("si", ent->d_name, kind);
if (!elem)
goto error;
PyList_Append(list, elem);
Py_DECREF(elem);
}
Matt Mackall
osutil: cleanups...
r5421
Matt Mackall
osutil: major listdir cleanup
r7031 ret = list;
Py_INCREF(ret);
Matt Mackall
osutil: cleanups...
r5421
Matt Mackall
osutil: major listdir cleanup
r7031 error:
Py_DECREF(list);
error_list:
closedir(dir);
error_dir:
Matt Mackall
osutil: fix some braindamage...
r7033 #ifdef AT_SYMLINK_NOFOLLOW
close(dfd);
#endif
Matt Mackall
osutil: major listdir cleanup
r7031 error_parse:
return ret;
Matt Mackall
osutil: cleanups...
r5421 }
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
static char osutil_doc[] = "Native operating system services.";
static PyMethodDef methods[] = {
Matt Mackall
osutil: cleanups...
r5421 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
"list a directory\n"},
{NULL, NULL}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
PyMODINIT_FUNC initosutil(void)
{
Matt Mackall
osutil: cleanups...
r5421 if (PyType_Ready(&listdir_stat_type) == -1)
return;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: cleanups...
r5421 Py_InitModule3("osutil", methods, osutil_doc);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }