From 1dce4107240f8169f4521bde8effc7d9ce1266b2 Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Sun, 29 Jun 2008 23:01:04 +0200 Subject: [PATCH] Add new-style list function --- test/test_xattr.py | 32 +++++++++++++------ xattr.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 10 deletions(-) diff --git a/test/test_xattr.py b/test/test_xattr.py index 35cceff..49eff07 100644 --- a/test/test_xattr.py +++ b/test/test_xattr.py @@ -78,7 +78,7 @@ class xattrTest(unittest.TestCase): def _checkListSetGet(self, item, symlink=False): """check list, set, get operations against an item""" - self.failUnlessEqual(xattr.listxattr(item, symlink), []) + self.failUnlessEqual(xattr.list(item, symlink), []) self.failUnlessRaises(EnvironmentError, xattr.set, item, self.USER_ATTR, self.USER_VAL, flags=xattr.XATTR_REPLACE) @@ -93,19 +93,19 @@ class xattrTest(unittest.TestCase): self.failUnlessRaises(EnvironmentError, xattr.set, item, self.USER_ATTR, self.USER_VAL, flags=xattr.XATTR_CREATE) - self.failUnlessEqual(xattr.listxattr(item, symlink), [self.USER_ATTR]) + self.failUnlessEqual(xattr.list(item, symlink), [self.USER_ATTR]) self.failUnlessEqual(xattr.get(item, self.USER_ATTR, nofollow=symlink), self.USER_VAL) self.failUnlessEqual(xattr.get_all(item, nofollow=symlink), [(self.USER_ATTR, self.USER_VAL)]) xattr.remove(item, self.USER_ATTR) - self.failUnlessEqual(xattr.listxattr(item, symlink), []) + self.failUnlessEqual(xattr.list(item, symlink), []) self.failUnlessEqual(xattr.get_all(item, nofollow=symlink), []) self.failUnlessRaises(EnvironmentError, xattr.remove, item, self.USER_ATTR) - def testNoXattr(self): - """test no attributes""" + def testNoXattrDeprecated(self): + """test no attributes (deprecated functions)""" fh, fname = self._getfile() self.failUnlessEqual(xattr.listxattr(fname), []) self.failUnlessEqual(xattr.get_all(fname), []) @@ -116,6 +116,18 @@ class xattrTest(unittest.TestCase): self.failUnlessEqual(xattr.listxattr(sname, True), []) self.failUnlessEqual(xattr.get_all(sname, nofollow=True), []) + def testNoXattr(self): + """test no attributes""" + fh, fname = self._getfile() + self.failUnlessEqual(xattr.list(fname), []) + self.failUnlessEqual(xattr.get_all(fname), []) + dname = self._getdir() + self.failUnlessEqual(xattr.list(dname), []) + self.failUnlessEqual(xattr.get_all(dname), []) + sname = self._getsymlink() + self.failUnlessEqual(xattr.list(sname, nofollow=True), []) + self.failUnlessEqual(xattr.get_all(sname, nofollow=True), []) + def testFileByNameDeprecated(self): """test set and retrieve one attribute by file name (deprecated)""" fh, fname = self._getfile() @@ -172,9 +184,9 @@ class xattrTest(unittest.TestCase): """test mixed access to file""" fh, fname = self._getfile() fo = os.fdopen(fh) - self.failUnlessEqual(xattr.listxattr(fname), []) + self.failUnlessEqual(xattr.list(fname), []) xattr.set(fname, self.USER_ATTR, self.USER_VAL) - self.failUnlessEqual(xattr.listxattr(fh), [self.USER_ATTR]) + self.failUnlessEqual(xattr.list(fh), [self.USER_ATTR]) self.failUnlessEqual(xattr.get(fo, self.USER_ATTR), self.USER_VAL) self.failUnlessEqual(xattr.get_all(fo), @@ -201,7 +213,7 @@ class xattrTest(unittest.TestCase): def testSymlinkOps(self): """test symlink operations""" sname = self._getsymlink() - self.failUnlessRaises(EnvironmentError, xattr.listxattr, sname) + self.failUnlessRaises(EnvironmentError, xattr.list, sname) self._checkListSetGet(sname, symlink=True) def testBinaryPayloadDeprecated(self): @@ -221,7 +233,7 @@ class xattrTest(unittest.TestCase): os.close(fh) BINVAL = "abc" + '\0' + "def" xattr.set(fname, self.USER_ATTR, BINVAL) - self.failUnlessEqual(xattr.listxattr(fname), [self.USER_ATTR]) + self.failUnlessEqual(xattr.list(fname), [self.USER_ATTR]) self.failUnlessEqual(xattr.get(fname, self.USER_ATTR), BINVAL) self.failUnlessEqual(xattr.get_all(fname), [(self.USER_ATTR, BINVAL)]) xattr.remove(fname, self.USER_ATTR) @@ -246,7 +258,7 @@ class xattrTest(unittest.TestCase): xattr.set(fh, self.USER_ATTR, self.USER_VAL) VL = [self.USER_ATTR] for i in range(self.MANYOPS_COUNT): - self.failUnlessEqual(xattr.listxattr(fh), VL) + self.failUnlessEqual(xattr.list(fh), VL) for i in range(self.MANYOPS_COUNT): self.failUnlessEqual(xattr.get(fh, self.USER_ATTR), self.USER_VAL) diff --git a/xattr.c b/xattr.c index 27b769c..4e92ec5 100644 --- a/xattr.c +++ b/xattr.c @@ -657,6 +657,83 @@ pylistxattr(PyObject *self, PyObject *args) return mylist; } +static char __list_doc__[] = + "Return the list of attribute names for a file\n" + "\n" + "@param item: the item to query; either a string representing the" + " filename, or a file-like object, or a file descriptor\n" + "@param nofollow: if given and True, and the function is passed a" + " filename that points to a symlink, the function will act on the symlink" + " itself instead of its target\n" + "@type nofollow: boolean\n" + "@param namespace: if given, the attribute must not contain the namespace" + " itself, but instead the namespace will be taken from this parameter\n" + "@type namespace: string\n" + ; + +/* Wrapper for listxattr */ +static PyObject * +xattr_list(PyObject *self, PyObject *args, PyObject *keywds) +{ + char *buf; + int nofollow=0; + int nalloc, nret; + PyObject *myarg; + PyObject *mylist; + char *ns = NULL; + int nattrs; + char *s; + target_t tgt; + static char *kwlist[] = {"item", "nofollow", "namespace", NULL}; + + /* Parse the arguments */ + if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|iz", kwlist, + &myarg, &nofollow, &ns)) + return NULL; + if(!convertObj(myarg, &tgt, nofollow)) + return NULL; + + /* Find out the needed size of the buffer */ + if((nalloc = _list_obj(&tgt, NULL, 0)) == -1) { + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Try to allocate the memory, using Python's allocator */ + if((buf = PyMem_Malloc(nalloc)) == NULL) { + PyErr_NoMemory(); + return NULL; + } + + /* Now retrieve the list of attributes */ + if((nret = _list_obj(&tgt, buf, nalloc)) == -1) { + PyMem_Free(buf); + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Compute the number of attributes in the list */ + for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) { + if(matches_ns(s, ns)) + nattrs++; + } + /* Create the list which will hold the result */ + mylist = PyList_New(nattrs); + + /* Create and insert the attributes as strings in the list */ + for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) { + if(matches_ns(s, ns)) { + char *short_form = ns == NULL ? s : s + strlen(ns) + 1; + PyList_SET_ITEM(mylist, nattrs, PyString_FromString(short_form)); + nattrs++; + } + } + + /* Free the buffer, now it is no longer needed */ + PyMem_Free(buf); + + /* Return the result */ + return mylist; +} + static PyMethodDef xattr_methods[] = { {"getxattr", pygetxattr, METH_VARARGS, __pygetxattr_doc__ }, {"get", (PyCFunction) xattr_get, METH_VARARGS | METH_KEYWORDS, @@ -670,6 +747,8 @@ static PyMethodDef xattr_methods[] = { {"remove", (PyCFunction) xattr_remove, METH_VARARGS | METH_KEYWORDS, __remove_doc__ }, {"listxattr", pylistxattr, METH_VARARGS, __pylistxattr_doc__ }, + {"list", (PyCFunction) xattr_list, METH_VARARGS | METH_KEYWORDS, + __list_doc__ }, {NULL, NULL, 0, NULL} /* Sentinel */ }; -- 2.39.5