From afc34c5e8e5c0cd189d35824b53cc04cf62f0383 Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Mon, 1 Mar 2010 21:03:06 +0100 Subject: [PATCH] Imported Upstream version 0.5.0 --- MANIFEST.in | 7 - NEWS | 6 + PKG-INFO | 2 +- pyxattr.egg-info/PKG-INFO | 12 - pyxattr.egg-info/SOURCES.txt | 13 - pyxattr.egg-info/dependency_links.txt | 1 - pyxattr.egg-info/top_level.txt | 1 - setup.cfg | 7 +- setup.py | 10 +- test/test_xattr.py | 26 +- xattr.c | 402 ++++++++++++++++++-------- 11 files changed, 323 insertions(+), 164 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 pyxattr.egg-info/PKG-INFO delete mode 100644 pyxattr.egg-info/SOURCES.txt delete mode 100644 pyxattr.egg-info/dependency_links.txt delete mode 100644 pyxattr.egg-info/top_level.txt diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index efa600a..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,7 +0,0 @@ -include COPYING -include NEWS -include README -include epydoc.conf -include setup.cfg -include test/test_xattr.py -include xattr.c diff --git a/NEWS b/NEWS index 6c9ffbb..1b933d7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +Version 0.5 +=========== + +Implemented support for python 3. This required a significant change to +the C module, hence the new version number. + Version 0.4 =========== diff --git a/PKG-INFO b/PKG-INFO index 22d8588..85223fe 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: pyxattr -Version: 0.4.0 +Version: 0.5.0 Summary: Filesystem extended attributes for python Home-page: http://pyxattr.sourceforge.net/ Author: Iustin Pop diff --git a/pyxattr.egg-info/PKG-INFO b/pyxattr.egg-info/PKG-INFO deleted file mode 100644 index 22d8588..0000000 --- a/pyxattr.egg-info/PKG-INFO +++ /dev/null @@ -1,12 +0,0 @@ -Metadata-Version: 1.0 -Name: pyxattr -Version: 0.4.0 -Summary: Filesystem extended attributes for python -Home-page: http://pyxattr.sourceforge.net/ -Author: Iustin Pop -Author-email: iusty@k1024.org -License: LGPL -Description: This is a C extension module for Python which - implements extended attributes manipulation. It is a wrapper on top - of the attr C library - see attr(5). -Platform: UNKNOWN diff --git a/pyxattr.egg-info/SOURCES.txt b/pyxattr.egg-info/SOURCES.txt deleted file mode 100644 index 31a43a3..0000000 --- a/pyxattr.egg-info/SOURCES.txt +++ /dev/null @@ -1,13 +0,0 @@ -COPYING -MANIFEST.in -NEWS -README -epydoc.conf -setup.cfg -setup.py -xattr.c -pyxattr.egg-info/PKG-INFO -pyxattr.egg-info/SOURCES.txt -pyxattr.egg-info/dependency_links.txt -pyxattr.egg-info/top_level.txt -test/test_xattr.py \ No newline at end of file diff --git a/pyxattr.egg-info/dependency_links.txt b/pyxattr.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/pyxattr.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pyxattr.egg-info/top_level.txt b/pyxattr.egg-info/top_level.txt deleted file mode 100644 index 18c5e90..0000000 --- a/pyxattr.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -xattr diff --git a/setup.cfg b/setup.cfg index a68b051..256aa5f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,9 +1,4 @@ [bdist_rpm] release = 1 requires = libattr - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - +;build_requires = libattr libattr-devel diff --git a/setup.py b/setup.py index 02e4098..e6f77bc 100755 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ #!/usr/bin/python -#import distutils -#from distutils.core import setup, Extension -from setuptools import setup, Extension +import distutils +from distutils.core import setup, Extension +#from setuptools import setup, Extension long_desc = """This is a C extension module for Python which implements extended attributes manipulation. It is a wrapper on top of the attr C library - see attr(5).""" -version = "0.4.0" +version = "0.5.0" author = "Iustin Pop" author_email = "iusty@k1024.org" macros = [ @@ -26,5 +26,5 @@ setup(name = "pyxattr", ext_modules = [Extension("xattr", ["xattr.c"], libraries=["attr"], define_macros=macros)], - test_suite = "test/test_xattr", + #test_suite = "test/test_xattr", ) diff --git a/test/test_xattr.py b/test/test_xattr.py index 2f4abb0..cd25594 100644 --- a/test/test_xattr.py +++ b/test/test_xattr.py @@ -1,6 +1,7 @@ # # +import sys import unittest import tempfile import os @@ -9,15 +10,25 @@ import errno import xattr from xattr import NS_USER, XATTR_CREATE, XATTR_REPLACE +if sys.hexversion >= 0x03000000: + PY3K = True +else: + PY3K = False + TEST_DIR = os.environ.get("TESTDIR", ".") class xattrTest(unittest.TestCase): USER_NN = "test" - USER_ATTR = "%s.%s" % (NS_USER, USER_NN) + USER_ATTR = NS_USER.decode() + "." + USER_NN USER_VAL = "abc" MANYOPS_COUNT = 131072 + if PY3K: + USER_NN = USER_NN.encode() + USER_VAL = USER_VAL.encode() + USER_ATTR = USER_ATTR.encode() + def setUp(self): """set up function""" self.rmfiles = [] @@ -67,7 +78,8 @@ class xattrTest(unittest.TestCase): XATTR_REPLACE) try: xattr.setxattr(item, self.USER_ATTR, self.USER_VAL, 0, symlink) - except IOError, err: + except IOError: + err = sys.exc_info()[1] if err.errno == errno.EPERM and symlink: # symlinks may fail, in which case we abort the rest # of the test for this case @@ -105,7 +117,8 @@ class xattrTest(unittest.TestCase): else: xattr.set(item, self.USER_ATTR, self.USER_VAL, nofollow=symlink) - except IOError, err: + except IOError: + err = sys.exc_info()[1] if err.errno == errno.EPERM and symlink: # symlinks may fail, in which case we abort the rest # of the test for this case @@ -297,6 +310,8 @@ class xattrTest(unittest.TestCase): fh, fname = self._getfile() os.close(fh) BINVAL = "abc" + '\0' + "def" + if PY3K: + BINVAL = BINVAL.encode() xattr.setxattr(fname, self.USER_ATTR, BINVAL) self.failUnlessEqual(xattr.listxattr(fname), [self.USER_ATTR]) self.failUnlessEqual(xattr.getxattr(fname, self.USER_ATTR), BINVAL) @@ -308,6 +323,8 @@ class xattrTest(unittest.TestCase): fh, fname = self._getfile() os.close(fh) BINVAL = "abc" + '\0' + "def" + if PY3K: + BINVAL = BINVAL.encode() xattr.set(fname, self.USER_ATTR, BINVAL) self.failUnlessEqual(xattr.list(fname), [self.USER_ATTR]) self.failUnlessEqual(xattr.list(fname, namespace=NS_USER), @@ -354,3 +371,6 @@ class xattrTest(unittest.TestCase): [(self.USER_ATTR, self.USER_VAL)]) self.failUnlessEqual(xattr.get_all(fh, namespace=NS_USER), [(self.USER_NN, self.USER_VAL)]) + +if __name__ == "__main__": + unittest.main() diff --git a/xattr.c b/xattr.c index 9609fa3..370324a 100644 --- a/xattr.c +++ b/xattr.c @@ -1,3 +1,25 @@ +/* + xattr - a python module for manipulating filesystem extended attributes + + Copyright (C) 2002, 2003, 2006, 2008 Iustin Pop + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + +*/ + #define PY_SSIZE_T_CLEAN #include #include @@ -10,6 +32,15 @@ typedef int Py_ssize_t; #define PY_SSIZE_T_MIN INT_MIN #endif +#if PY_MAJOR_VERSION >= 3 +#define IS_PY3K +#else +#define PyBytes_Check PyString_Check +#define PyBytes_AS_STRING PyString_AS_STRING +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_FromString PyString_FromString +#endif + /* the estimated (startup) attribute buffer size in multi-operations */ #define ESTIMATE_ATTR_SIZE 256 @@ -22,14 +53,31 @@ typedef struct { const char *name; int fd; }; + PyObject *tmp; } target_t; +/* Cleans up a tgt structure */ +static void free_tgt(target_t *tgt) { + if (tgt->tmp != NULL) { + Py_DECREF(tgt->tmp); + } +} + /** Converts from a string, file or int argument to what we need. */ static int convertObj(PyObject *myobj, target_t *tgt, int nofollow) { int fd; - if(PyString_Check(myobj)) { + tgt->tmp = NULL; + if(PyBytes_Check(myobj)) { + tgt->type = nofollow ? T_LINK : T_PATH; + tgt->name = PyBytes_AS_STRING(myobj); + } else if(PyUnicode_Check(myobj)) { tgt->type = nofollow ? T_LINK : T_PATH; - tgt->name = PyString_AS_STRING(myobj); + tgt->tmp = \ + PyUnicode_AsEncodedString(myobj, + Py_FileSystemDefaultEncoding, "strict"); + if(tgt->tmp == NULL) + return 0; + tgt->name = PyBytes_AS_STRING(tgt->tmp); } else if((fd = PyObject_AsFileDescriptor(myobj)) != -1) { tgt->type = T_FD; tgt->fd = fd; @@ -146,40 +194,48 @@ pygetxattr(PyObject *self, PyObject *args) { PyObject *myarg; target_t tgt; - int nofollow=0; - char *attrname; + int nofollow = 0; + char *attrname = NULL; char *buf; ssize_t nalloc, nret; PyObject *res; /* Parse the arguments */ - if (!PyArg_ParseTuple(args, "Os|i", &myarg, &attrname, &nofollow)) - return NULL; - if(!convertObj(myarg, &tgt, nofollow)) + if (!PyArg_ParseTuple(args, "Oet|i", &myarg, NULL, &attrname, &nofollow)) return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } /* Find out the needed size of the buffer */ if((nalloc = _get_obj(&tgt, attrname, NULL, 0)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freetgt; } /* Try to allocate the memory, using Python's allocator */ if((buf = PyMem_Malloc(nalloc)) == NULL) { - PyErr_NoMemory(); - return NULL; + res = PyErr_NoMemory(); + goto freetgt; } /* Now retrieve the attribute value */ if((nret = _get_obj(&tgt, attrname, buf, nalloc)) == -1) { - PyMem_Free(buf); - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freebuf; } /* Create the string which will hold the result */ - res = PyString_FromStringAndSize(buf, nret); + res = PyBytes_FromStringAndSize(buf, nret); + freebuf: /* Free the buffer, now it is no longer needed */ PyMem_Free(buf); + freetgt: + free_tgt(&tgt); + freearg: + PyMem_Free(attrname); /* Return the result */ return res; @@ -219,8 +275,8 @@ xattr_get(PyObject *self, PyObject *args, PyObject *keywds) { PyObject *myarg; target_t tgt; - int nofollow=0; - char *attrname, *namebuf; + int nofollow = 0; + char *attrname = NULL, *namebuf; const char *fullname; char *buf; char *ns = NULL; @@ -229,39 +285,46 @@ xattr_get(PyObject *self, PyObject *args, PyObject *keywds) static char *kwlist[] = {"item", "name", "nofollow", "namespace", NULL}; /* Parse the arguments */ - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Os|iz", kwlist, - &myarg, &attrname, &nofollow, &ns)) - return NULL; - if(!convertObj(myarg, &tgt, nofollow)) + if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oet|iz", kwlist, + &myarg, NULL, &attrname, &nofollow, &ns)) return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } fullname = merge_ns(ns, attrname, &namebuf); /* Find out the needed size of the buffer */ if((nalloc = _get_obj(&tgt, fullname, NULL, 0)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freetgt; } /* Try to allocate the memory, using Python's allocator */ if((buf = PyMem_Malloc(nalloc)) == NULL) { - PyMem_Free(namebuf); - PyErr_NoMemory(); - return NULL; + res = PyErr_NoMemory(); + goto freenamebuf; } /* Now retrieve the attribute value */ if((nret = _get_obj(&tgt, fullname, buf, nalloc)) == -1) { - PyMem_Free(buf); - PyMem_Free(namebuf); - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freebuf; } /* Create the string which will hold the result */ - res = PyString_FromStringAndSize(buf, nret); + res = PyBytes_FromStringAndSize(buf, nret); /* Free the buffers, they are no longer needed */ - PyMem_Free(namebuf); + freebuf: PyMem_Free(buf); + freenamebuf: + PyMem_Free(namebuf); + freetgt: + free_tgt(&tgt); + freearg: + PyMem_Free(attrname); /* Return the result */ return res; @@ -308,12 +371,12 @@ static char __get_all_doc__[] = static PyObject * get_all(PyObject *self, PyObject *args, PyObject *keywds) { - PyObject *myarg; + PyObject *myarg, *res; int dolink=0; char *ns = NULL; char *buf_list, *buf_val; char *s; - size_t nalloc, nlist, nval; + ssize_t nalloc, nlist, nval; PyObject *mylist; target_t tgt; static char *kwlist[] = {"item", "nofollow", "namespace", NULL}; @@ -331,20 +394,21 @@ get_all(PyObject *self, PyObject *args, PyObject *keywds) nalloc = _list_obj(&tgt, NULL, 0); if(nalloc == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freetgt; } /* Try to allocate the memory, using Python's allocator */ if((buf_list = PyMem_Malloc(nalloc)) == NULL) { - PyErr_NoMemory(); - return NULL; + res = PyErr_NoMemory(); + goto freetgt; } /* Now retrieve the list of attributes */ nlist = _list_obj(&tgt, buf_list, nalloc); if(nlist == -1) { - PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); goto free_buf_list; } @@ -352,8 +416,9 @@ get_all(PyObject *self, PyObject *args, PyObject *keywds) mylist = PyList_New(0); nalloc = ESTIMATE_ATTR_SIZE; if((buf_val = PyMem_Malloc(nalloc)) == NULL) { - PyErr_NoMemory(); - goto free_list; + Py_DECREF(mylist); + res = PyErr_NoMemory(); + goto free_buf_list; } /* Create and insert the attributes as strings in the list */ @@ -372,8 +437,11 @@ get_all(PyObject *self, PyObject *args, PyObject *keywds) if(nval == -1) { if(errno == ERANGE) { nval = _get_obj(&tgt, s, NULL, 0); - if((buf_val = PyMem_Realloc(buf_val, nval)) == NULL) - goto free_list; + if((buf_val = PyMem_Realloc(buf_val, nval)) == NULL) { + res = NULL; + Py_DECREF(mylist); + goto free_buf_list; + } nalloc = nval; continue; } else if(errno == ENODATA || errno == ENOATTR) { @@ -382,32 +450,37 @@ get_all(PyObject *self, PyObject *args, PyObject *keywds) missing = 1; break; } - goto exit_errno; + res = PyErr_SetFromErrno(PyExc_IOError); + goto freebufval; } break; } if(missing) continue; +#ifdef IS_PY3K + my_tuple = Py_BuildValue("yy#", name, buf_val, nval); +#else my_tuple = Py_BuildValue("ss#", name, buf_val, nval); +#endif PyList_Append(mylist, my_tuple); Py_DECREF(my_tuple); } - /* Free the buffers, now they are no longer needed */ - PyMem_Free(buf_val); - PyMem_Free(buf_list); + /* Successfull exit */ + res = mylist; - /* Return the result */ - return mylist; - exit_errno: - PyErr_SetFromErrno(PyExc_IOError); + freebufval: PyMem_Free(buf_val); - free_list: - Py_DECREF(mylist); + free_buf_list: PyMem_Free(buf_list); - return NULL; + + freetgt: + free_tgt(&tgt); + + /* Return the result */ + return res; } @@ -445,29 +518,43 @@ static char __pysetxattr_doc__[] = static PyObject * pysetxattr(PyObject *self, PyObject *args) { - PyObject *myarg; - int nofollow=0; - char *attrname; - char *buf; + PyObject *myarg, *res; + int nofollow = 0; + char *attrname = NULL; + char *buf = NULL; Py_ssize_t bufsize; int nret; int flags = 0; target_t tgt; /* Parse the arguments */ - if (!PyArg_ParseTuple(args, "Oss#|bi", &myarg, &attrname, - &buf, &bufsize, &flags, &nofollow)) - return NULL; - if(!convertObj(myarg, &tgt, nofollow)) + if (!PyArg_ParseTuple(args, "Oetet#|bi", &myarg, NULL, &attrname, + NULL, &buf, &bufsize, &flags, &nofollow)) return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } /* Set the attribute's value */ - if((nret = _set_obj(&tgt, attrname, buf, bufsize, flags)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + nret = _set_obj(&tgt, attrname, buf, bufsize, flags); + + free_tgt(&tgt); + + if(nret == -1) { + res = PyErr_SetFromErrno(PyExc_IOError); + goto freearg; } + Py_INCREF(Py_None); + res = Py_None; + + freearg: + PyMem_Free(attrname); + PyMem_Free(buf); + /* Return the result */ - Py_RETURN_NONE; + return res; } static char __set_doc__[] = @@ -510,10 +597,10 @@ static char __set_doc__[] = static PyObject * xattr_set(PyObject *self, PyObject *args, PyObject *keywds) { - PyObject *myarg; - int nofollow=0; - char *attrname; - char *buf; + PyObject *myarg, *res; + int nofollow = 0; + char *attrname = NULL; + char *buf = NULL; Py_ssize_t bufsize; int nret; int flags = 0; @@ -525,24 +612,39 @@ xattr_set(PyObject *self, PyObject *args, PyObject *keywds) "nofollow", "namespace", NULL}; /* Parse the arguments */ - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oss#|iiz", kwlist, - &myarg, &attrname, + if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oetet#|iiz", kwlist, + &myarg, NULL, &attrname, NULL, &buf, &bufsize, &flags, &nofollow, &ns)) return NULL; - if(!convertObj(myarg, &tgt, nofollow)) - return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } full_name = merge_ns(ns, attrname, &newname); + /* Set the attribute's value */ nret = _set_obj(&tgt, full_name, buf, bufsize, flags); + if(newname != NULL) PyMem_Free(newname); + + free_tgt(&tgt); + if(nret == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freearg; } + Py_INCREF(Py_None); + res = Py_None; + + freearg: + PyMem_Free(attrname); + PyMem_Free(buf); + /* Return the result */ - Py_RETURN_NONE; + return res; } @@ -568,26 +670,39 @@ static char __pyremovexattr_doc__[] = static PyObject * pyremovexattr(PyObject *self, PyObject *args) { - PyObject *myarg; - int nofollow=0; - char *attrname; + PyObject *myarg, *res; + int nofollow = 0; + char *attrname = NULL; int nret; target_t tgt; /* Parse the arguments */ - if (!PyArg_ParseTuple(args, "Os|i", &myarg, &attrname, &nofollow)) + if (!PyArg_ParseTuple(args, "Oet|i", &myarg, NULL, &attrname, &nofollow)) return NULL; - if(!convertObj(myarg, &tgt, nofollow)) - return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } /* Remove the attribute */ - if((nret = _remove_obj(&tgt, attrname)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + nret = _remove_obj(&tgt, attrname); + + free_tgt(&tgt); + + if(nret == -1) { + res = PyErr_SetFromErrno(PyExc_IOError); + goto freearg; } + Py_INCREF(Py_None); + res = Py_None; + + freearg: + PyMem_Free(attrname); + /* Return the result */ - Py_RETURN_NONE; + return res; } static char __remove_doc__[] = @@ -618,9 +733,9 @@ static char __remove_doc__[] = static PyObject * xattr_remove(PyObject *self, PyObject *args, PyObject *keywds) { - PyObject *myarg; - int nofollow=0; - char *attrname, *name_buf; + PyObject *myarg, *res; + int nofollow = 0; + char *attrname = NULL, *name_buf; char *ns = NULL; const char *full_name; int nret; @@ -628,25 +743,41 @@ xattr_remove(PyObject *self, PyObject *args, PyObject *keywds) static char *kwlist[] = {"item", "name", "nofollow", "namespace", NULL}; /* Parse the arguments */ - if (!PyArg_ParseTupleAndKeywords(args, keywds, "Os|iz", kwlist, - &myarg, &attrname, &nofollow, &ns)) + if (!PyArg_ParseTupleAndKeywords(args, keywds, "Oet|iz", kwlist, + &myarg, NULL, &attrname, &nofollow, &ns)) return NULL; - if(!convertObj(myarg, &tgt, nofollow)) - return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } + full_name = merge_ns(ns, attrname, &name_buf); - if(full_name == NULL) - return NULL; + if(full_name == NULL) { + res = NULL; + goto freearg; + } /* Remove the attribute */ nret = _remove_obj(&tgt, full_name); + PyMem_Free(name_buf); + + free_tgt(&tgt); + if(nret == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freearg; } + Py_INCREF(Py_None); + res = Py_None; + + freearg: + PyMem_Free(attrname); + /* Return the result */ - Py_RETURN_NONE; + return res; } static char __pylistxattr_doc__[] = @@ -686,19 +817,20 @@ pylistxattr(PyObject *self, PyObject *args) /* Find out the needed size of the buffer */ if((nalloc = _list_obj(&tgt, NULL, 0)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + mylist = PyErr_SetFromErrno(PyExc_IOError); + goto freetgt; } /* Try to allocate the memory, using Python's allocator */ if((buf = PyMem_Malloc(nalloc)) == NULL) { - PyErr_NoMemory(); - return NULL; + mylist = PyErr_NoMemory(); + goto freetgt; } /* Now retrieve the list of attributes */ if((nret = _list_obj(&tgt, buf, nalloc)) == -1) { - PyMem_Free(buf); - return PyErr_SetFromErrno(PyExc_IOError); + mylist = PyErr_SetFromErrno(PyExc_IOError); + goto freebuf; } /* Compute the number of attributes in the list */ @@ -711,13 +843,17 @@ pylistxattr(PyObject *self, PyObject *args) /* Create and insert the attributes as strings in the list */ for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) { - PyList_SET_ITEM(mylist, nattrs, PyString_FromString(s)); + PyList_SET_ITEM(mylist, nattrs, PyBytes_FromString(s)); nattrs++; } + freebuf: /* Free the buffer, now it is no longer needed */ PyMem_Free(buf); + freetgt: + free_tgt(&tgt); + /* Return the result */ return mylist; } @@ -754,10 +890,10 @@ static PyObject * xattr_list(PyObject *self, PyObject *args, PyObject *keywds) { char *buf; - int nofollow=0; + int nofollow = 0; ssize_t nalloc, nret; PyObject *myarg; - PyObject *mylist; + PyObject *res; char *ns = NULL; Py_ssize_t nattrs; char *s; @@ -765,51 +901,60 @@ xattr_list(PyObject *self, PyObject *args, PyObject *keywds) 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)) + if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|iet", kwlist, + &myarg, &nofollow, NULL, &ns)) return NULL; + if(!convertObj(myarg, &tgt, nofollow)) { + res = NULL; + goto freearg; + } /* Find out the needed size of the buffer */ if((nalloc = _list_obj(&tgt, NULL, 0)) == -1) { - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freetgt; } /* Try to allocate the memory, using Python's allocator */ if((buf = PyMem_Malloc(nalloc)) == NULL) { - PyErr_NoMemory(); - return NULL; + res = PyErr_NoMemory(); + goto freetgt; } /* Now retrieve the list of attributes */ if((nret = _list_obj(&tgt, buf, nalloc)) == -1) { - PyMem_Free(buf); - return PyErr_SetFromErrno(PyExc_IOError); + res = PyErr_SetFromErrno(PyExc_IOError); + goto freebuf; } /* Compute the number of attributes in the list */ for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) { - if(matches_ns(ns, s)!=NULL) + if(matches_ns(ns, s) != NULL) nattrs++; } /* Create the list which will hold the result */ - mylist = PyList_New(nattrs); + res = 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) { const char *name = matches_ns(ns, s); if(name!=NULL) { - PyList_SET_ITEM(mylist, nattrs, PyString_FromString(name)); + PyList_SET_ITEM(res, nattrs, PyBytes_FromString(name)); nattrs++; } } + freebuf: /* Free the buffer, now it is no longer needed */ PyMem_Free(buf); + freetgt: + free_tgt(&tgt); + freearg: + PyMem_Free(ns); + /* Return the result */ - return mylist; + return res; } static PyMethodDef xattr_methods[] = { @@ -875,10 +1020,34 @@ static char __xattr_doc__[] = \ " removexattr\n" ; +#ifdef IS_PY3K + +static struct PyModuleDef xattrmodule = { + PyModuleDef_HEAD_INIT, + "xattr", + __xattr_doc__, + 0, + xattr_methods, +}; + +#define INITERROR return NULL + +PyMODINIT_FUNC +PyInit_xattr(void) + +#else +#define INITERROR return void initxattr(void) +#endif { +#ifdef IS_PY3K + PyObject *m = PyModule_Create(&xattrmodule); +#else PyObject *m = Py_InitModule3("xattr", xattr_methods, __xattr_doc__); +#endif + if (m==NULL) + INITERROR; PyModule_AddStringConstant(m, "__author__", _XATTR_AUTHOR); PyModule_AddStringConstant(m, "__contact__", _XATTR_EMAIL); @@ -891,9 +1060,12 @@ initxattr(void) PyModule_AddIntConstant(m, "XATTR_REPLACE", XATTR_REPLACE); /* namespace constants */ - PyModule_AddStringConstant(m, "NS_SECURITY", "security"); - PyModule_AddStringConstant(m, "NS_SYSTEM", "system"); - PyModule_AddStringConstant(m, "NS_TRUSTED", "trusted"); - PyModule_AddStringConstant(m, "NS_USER", "user"); + PyModule_AddObject(m, "NS_SECURITY", PyBytes_FromString("security")); + PyModule_AddObject(m, "NS_SYSTEM", PyBytes_FromString("system")); + PyModule_AddObject(m, "NS_TRUSTED", PyBytes_FromString("trusted")); + PyModule_AddObject(m, "NS_USER", PyBytes_FromString("user")); +#ifdef IS_PY3K + return m; +#endif } -- 2.39.5