##// END OF EJS Templates
util: set_flags shouldn't know about repo flag formats
util: set_flags shouldn't know about repo flag formats

File last commit:

r5463:3b204881 default
r6877:1d38f360 default
Show More
osutil.c
314 lines | 7.5 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: more tidying...
r5428 static PyObject *listfiles(PyObject *list, DIR *dir,
int keep_stat, int *need_stat)
Matt Mackall
osutil: move file list loop to its own function
r5427 {
struct dirent *ent;
PyObject *name, *py_kind, *val;
Matt Mackall
osutil: more tidying...
r5428 #ifdef DT_REG
*need_stat = 0;
#else
*need_stat = 1;
#endif
Matt Mackall
osutil: move file list loop to its own function
r5427 for (ent = readdir(dir); ent; ent = readdir(dir)) {
int kind = -1;
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
#ifdef DT_REG
Matt Mackall
osutil: more tidying...
r5428 if (!keep_stat)
Matt Mackall
osutil: move file list loop to its own function
r5427 switch (ent->d_type) {
case DT_REG: kind = S_IFREG; break;
case DT_DIR: kind = S_IFDIR; break;
case DT_LNK: kind = S_IFLNK; break;
case DT_BLK: kind = S_IFBLK; break;
case DT_CHR: kind = S_IFCHR; break;
case DT_FIFO: kind = S_IFIFO; break;
case DT_SOCK: kind = S_IFSOCK; break;
default:
Matt Mackall
osutil: more tidying...
r5428 *need_stat = 0;
Matt Mackall
osutil: move file list loop to its own function
r5427 break;
}
#endif
if (kind != -1)
py_kind = PyInt_FromLong(kind);
else {
py_kind = Py_None;
Py_INCREF(Py_None);
}
Matt Mackall
osutil: more tidying...
r5428 val = PyTuple_New(keep_stat ? 3 : 2);
Matt Mackall
osutil: move file list loop to its own function
r5427 name = PyString_FromString(ent->d_name);
if (!name || !py_kind || !val) {
Py_XDECREF(name);
Py_XDECREF(py_kind);
Py_XDECREF(val);
return PyErr_NoMemory();
}
PyTuple_SET_ITEM(val, 0, name);
PyTuple_SET_ITEM(val, 1, py_kind);
Matt Mackall
osutil: more tidying...
r5428 if (keep_stat) {
Matt Mackall
osutil: move file list loop to its own function
r5427 PyTuple_SET_ITEM(val, 2, Py_None);
Py_INCREF(Py_None);
}
PyList_Append(list, val);
Py_DECREF(val);
}
return 0;
}
Matt Mackall
osutils: pull file stat loop into its own function
r5425 static PyObject *statfiles(PyObject *list, PyObject *ctor_args, int keep,
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 char *path, int len, int dfd)
Matt Mackall
osutils: pull file stat loop into its own function
r5425 {
struct stat buf;
struct stat *stp = &buf;
int kind;
int ret;
ssize_t i;
ssize_t size = PyList_Size(list);
for (i = 0; i < size; i++) {
PyObject *elt = PyList_GetItem(list, i);
char *name = PyString_AsString(PyTuple_GET_ITEM(elt, 0));
PyObject *py_st = NULL;
PyObject *py_kind = PyTuple_GET_ITEM(elt, 1);
kind = py_kind == Py_None ? -1 : PyInt_AsLong(py_kind);
if (kind != -1 && !keep)
continue;
Alexis S. L. Carvalho
osutil.c: use strncpy instead of strncat
r5430 strncpy(path + len + 1, name, PATH_MAX - len);
Matt Mackall
osutils: pull file stat loop into its own function
r5425 path[PATH_MAX] = 0;
if (keep) {
py_st = PyObject_CallObject(
(PyObject *)&listdir_stat_type, ctor_args);
if (!py_st)
return PyErr_NoMemory();
stp = &((struct listdir_stat *)py_st)->st;
PyTuple_SET_ITEM(elt, 2, py_st);
}
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 #ifdef AT_SYMLINK_NOFOLLOW
ret = fstatat(dfd, name, stp, AT_SYMLINK_NOFOLLOW);
#else
Matt Mackall
osutils: pull file stat loop into its own function
r5425 ret = lstat(path, stp);
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 #endif
Matt Mackall
osutils: pull file stat loop into its own function
r5425 if (ret == -1)
return PyErr_SetFromErrnoWithFilename(PyExc_OSError,
path);
Matt Mackall
osutil: improve portability...
r5457 if (kind == -1) {
if (S_ISREG(stp->st_mode))
kind = S_IFREG;
else if (S_ISDIR(stp->st_mode))
kind = S_IFDIR;
else if (S_ISLNK(stp->st_mode))
kind = S_IFLNK;
else if (S_ISBLK(stp->st_mode))
kind = S_IFBLK;
else if (S_ISCHR(stp->st_mode))
kind = S_IFCHR;
else if (S_ISFIFO(stp->st_mode))
kind = S_IFIFO;
else if (S_ISSOCK(stp->st_mode))
kind = S_IFSOCK;
else
kind = stp->st_mode;
}
Matt Mackall
osutils: pull file stat loop into its own function
r5425
if (py_kind == Py_None && kind != -1) {
py_kind = PyInt_FromLong(kind);
if (!py_kind)
return PyErr_NoMemory();
Py_XDECREF(Py_None);
PyTuple_SET_ITEM(elt, 1, py_kind);
}
}
return 0;
}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
{
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416 static char *kwlist[] = { "path", "stat", NULL };
Matt Mackall
osutil: more tidying...
r5428 DIR *dir = NULL;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 PyObject *statobj = NULL;
Matt Mackall
osutil: cleanups...
r5421 PyObject *list = NULL;
Matt Mackall
osutils: pull file stat loop into its own function
r5425 PyObject *err = NULL;
Matt Mackall
osutil: cleanups...
r5421 PyObject *ctor_args = NULL;
Matt Mackall
osutil: more tidying...
r5428 char *path;
Matt Mackall
osutil: eliminate alloca call...
r5422 char full_path[PATH_MAX + 10];
Matt Mackall
osutil: cleanups...
r5421 int path_len;
Matt Mackall
osutil: more tidying...
r5428 int need_stat, keep_stat;
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 int dfd;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist,
&path, &path_len, &statobj))
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more tidying...
r5428 keep_stat = statobj && PyObject_IsTrue(statobj);
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 #ifdef AT_SYMLINK_NOFOLLOW
dfd = open(path, O_RDONLY);
dir = fdopendir(dfd);
#else
Matt Mackall
osutil: cleanups...
r5421 dir = opendir(path);
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 dfd = -1;
#endif
Matt Mackall
osutil: cleanups...
r5421 if (!dir) {
Matt Mackall
osutil: more tidying...
r5428 err = PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
Matt Mackall
osutil: cleanups...
r5421 list = PyList_New(0);
Matt Mackall
osutil: more tidying...
r5428 ctor_args = PyTuple_New(0);
if (!list || !ctor_args)
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416
Matt Mackall
osutil: eliminate alloca call...
r5422 strncpy(full_path, path, PATH_MAX);
Matt Mackall
osutil: cleanups...
r5421 full_path[path_len] = '/';
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more tidying...
r5428 err = listfiles(list, dir, keep_stat, &need_stat);
Matt Mackall
osutil: move file list loop to its own function
r5427 if (err)
goto bail;
Matt Mackall
osutil: cleanups...
r5421
PyList_Sort(list);
Matt Mackall
osutil: more tidying...
r5428 if (!keep_stat && !need_stat)
goto done;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Bryan O'Sullivan
osutil: use fdopendir instead of dirfd
r5463 err = statfiles(list, ctor_args, keep_stat, full_path, path_len, dfd);
Matt Mackall
osutil: more tidying...
r5428 if (!err)
goto done;
Matt Mackall
osutil: cleanups...
r5421
Matt Mackall
osutil: more cleanups...
r5423 bail:
Py_XDECREF(list);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more cleanups...
r5423 done:
Py_XDECREF(ctor_args);
if (dir)
closedir(dir);
Matt Mackall
osutils: pull file stat loop into its own function
r5425 return err ? err : list;
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 }