From 97d26201966f8478a7e19770f0b48856370e1bbb Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Tue, 26 Feb 2008 22:26:49 +0100 Subject: [PATCH] Imported upstream version 0.2.2 --- ChangeLog | 92 ++++++++++++++++ MANIFEST | 9 ++ NEWS | 7 ++ PKG-INFO | 12 ++ README | 7 ++ setup.cfg | 4 + setup.py | 20 ++++ xattr.c | 317 +++++++++++++++++++++++++++++++++++++++++++++++++++++ xattr.html | 104 ++++++++++++++++++ xattr.txt | 98 +++++++++++++++++ 10 files changed, 670 insertions(+) create mode 100644 ChangeLog create mode 100644 MANIFEST create mode 100644 NEWS create mode 100644 PKG-INFO create mode 100644 README create mode 100644 setup.cfg create mode 100755 setup.py create mode 100644 xattr.c create mode 100644 xattr.html create mode 100644 xattr.txt diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..d6eb215 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,92 @@ +2007-07-01 Iustin Pop + + Fix a bug when listing xattrs of symlinks (report and fix by cscott@cscott.net) + +2006-02-11 Iustin Pop + + * Fixed bug in dealing with symlinks (didn't work at all) + * Fixed possible memory leak if reading of EA failed but buffer + calculation didn't fail + * Added and fixed Makefile after switched to subversion + +2006-02-11 Iustin Pop + + * Added MANIFEST file in MANIFEST.in (old change from 2003) + +2003-07-07 Iustin Pop + + Increase version number + +2003-07-07 Iustin Pop + + Added support for manipulating attributes of symbolic links (by request of + an actual user!) + +2002-12-24 Iustin Pop + + Removed build_requires + +2002-12-24 Iustin Pop + + Don't call python2, only python + +2002-12-24 Iustin Pop + + Prepare for first public release + +2002-12-24 Iustin Pop + + Added README + +2002-12-24 Iustin Pop + + Build changes + +2002-12-24 Iustin Pop + + Added new files, some example in the docstrings + +2002-12-24 Iustin Pop + + Improved documentation and added some constants (XATTR_*) + +2002-12-24 Iustin Pop + + Added url and license to setup.py + +2002-12-22 Iustin Pop + + Fixed names again, and switched parsing of int and files to PyObject_AsFileDescriptor + +2002-12-21 Iustin Pop + + Typos + +2002-12-21 Iustin Pop + + Renaming files + +2002-12-21 Iustin Pop + + Initial revision + +2002-12-21 Iustin Pop + + Documentation/comments + +2002-12-21 Iustin Pop + + Added support for variable type parameters, in order to wrap + both forms like get... and fget... in the same call. + +2002-12-21 Iustin Pop + + Initial revision + +2002-12-21 Iustin Pop + + New repository initialized by cvs2svn. + +;; Local Variables: +;; coding: utf-8 +;; End: diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..77381a0 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,9 @@ +ChangeLog +MANIFEST +NEWS +README +setup.cfg +setup.py +xattr.c +xattr.html +xattr.txt diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..a04869c --- /dev/null +++ b/NEWS @@ -0,0 +1,7 @@ +News in 0.2.1 +------------- + + * fixed a bug when reading symlink EAs (you weren't able to + do it, actually) + * fix a possible memory leak when the actual read of the EA + failed but the call to get the length of the EA didn't diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..c0f5565 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 1.0 +Name: pyxattr +Version: 0.2.2 +Summary: Extended attributes for python +Home-page: http://pyxattr.sourceforge.net +Author: Iustin Pop +Author-email: iusty@k1024.org +License: GPL +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/README b/README new file mode 100644 index 0000000..33f49a4 --- /dev/null +++ b/README @@ -0,0 +1,7 @@ +This is the pyxattr module, a Python extension module which gives +access to the extended attributes available in some operating systems. + +For usage details, see xattr.txt or xattr.html. +The project web page is http://pyxattr.sourceforge.net + +Author: Iustin Pop, diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..256aa5f --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[bdist_rpm] +release = 1 +requires = libattr +;build_requires = libattr libattr-devel diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..9e468b4 --- /dev/null +++ b/setup.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import distutils +from distutils.core 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.2.2" + +setup(name="pyxattr", + version=version, + description="Extended attributes for python", + long_description=long_desc, + author="Iustin Pop", + author_email="iusty@k1024.org", + url="http://pyxattr.sourceforge.net", + license="GPL", + ext_modules=[Extension("xattr", ["xattr.c"], libraries=["attr"])], + ) diff --git a/xattr.c b/xattr.c new file mode 100644 index 0000000..8fd55a5 --- /dev/null +++ b/xattr.c @@ -0,0 +1,317 @@ +#include +#include + +/** Converts from a string, file or int argument to what we need. */ +static int convertObj(PyObject *myobj, int *ishandle, int *filehandle, char **filename) { + if(PyString_Check(myobj)) { + *ishandle = 0; + *filename = PyString_AS_STRING(myobj); + } else if((*filehandle = PyObject_AsFileDescriptor(myobj)) != -1) { + *ishandle = 1; + } else { + PyErr_SetString(PyExc_TypeError, "argument 1 must be string or int"); + return 0; + } + return 1; +} + +/* Wrapper for getxattr */ +static char __pygetxattr_doc__[] = \ +"Get the value of a given extended attribute.\n" \ +"\n" \ +"Parameters:\n" \ +"\t- a string representing filename, or a file-like object,\n" \ +"\t or a file descriptor; this represents the file on \n" \ +"\t which to act\n" \ +"\t- a string, representing the attribute whose value to retrieve;\n" \ +"\t usually in form of system.posix_acl or user.mime_type\n" \ +"\t- (optional) a boolean value (defaults to false), which, if\n" \ +"\t the file name given is a symbolic link, makes the\n" \ +"\t function operate on the symbolic link itself instead\n" \ +"\t of its target;" \ +; + +static PyObject * +pygetxattr(PyObject *self, PyObject *args) +{ + PyObject *myarg; + char *file = NULL; + int filedes = -1, ishandle, dolink=0; + char *attrname; + char *buf; + int nalloc, nret; + PyObject *res; + + /* Parse the arguments */ + if (!PyArg_ParseTuple(args, "Os|i", &myarg, &attrname, &dolink)) + return NULL; + if(!convertObj(myarg, &ishandle, &filedes, &file)) + return NULL; + + /* Find out the needed size of the buffer */ + nalloc = ishandle ? + fgetxattr(filedes, attrname, NULL, 0) : + dolink ? + lgetxattr(file, attrname, NULL, 0) : + getxattr(file, attrname, NULL, 0); + if(nalloc == -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 attribute value */ + nret = ishandle ? + fgetxattr(filedes, attrname, buf, nalloc) : + dolink ? + lgetxattr(file, attrname, buf, nalloc) : + getxattr(file, attrname, buf, nalloc); + if(nret == -1) { + PyMem_Free(buf); + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Create the string which will hold the result */ + res = PyString_FromStringAndSize(buf, nret); + + /* Free the buffer, now it is no longer needed */ + PyMem_Free(buf); + + /* Return the result */ + return res; +} + +static char __pysetxattr_doc__[] = \ +"Set the value of a given extended attribute.\n" \ +"Be carefull in case you want to set attributes on symbolic\n" \ +"links, you have to use all the 5 parameters; use 0 for the \n" \ +"flags value if you want the default behavior (create or " \ +"replace)\n" \ +"\n" \ +"Parameters:\n" \ +"\t- a string representing filename, or a file-like object,\n" \ +"\t or a file descriptor; this represents the file on \n" \ +"\t which to act\n" \ +"\t- a string, representing the attribute whose value to set;\n" \ +"\t usually in form of system.posix_acl or user.mime_type\n" \ +"\t- a string, possibly with embedded NULLs; note that there\n" \ +"\t are restrictions regarding the size of the value, for\n" \ +"\t example, for ext2/ext3, maximum size is the block size\n" \ +"\t- (optional) flags; if 0 or ommited the attribute will be \n" \ +"\t created or replaced; if XATTR_CREATE, the attribute \n" \ +"\t will be created, giving an error if it already exists;\n" \ +"\t of XATTR_REPLACE, the attribute will be replaced,\n" \ +"\t giving an error if it doesn't exists;\n" \ +"\t- (optional) a boolean value (defaults to false), which, if\n" \ +"\t the file name given is a symbolic link, makes the\n" \ +"\t function operate on the symbolic link itself instead\n" \ +"\t of its target;" \ +; + +/* Wrapper for setxattr */ +static PyObject * +pysetxattr(PyObject *self, PyObject *args) +{ + PyObject *myarg; + char *file; + int ishandle, filedes, dolink=0; + char *attrname; + char *buf; + int bufsize, nret; + int flags = 0; + + /* Parse the arguments */ + if (!PyArg_ParseTuple(args, "Oss#|bi", &myarg, &attrname, &buf, &bufsize, &flags, &dolink)) + return NULL; + if(!convertObj(myarg, &ishandle, &filedes, &file)) + return NULL; + + /* Set the attribute's value */ + nret = ishandle ? + fsetxattr(filedes, attrname, buf, bufsize, flags) : + dolink ? + lsetxattr(file, attrname, buf, bufsize, flags) : + setxattr(file, attrname, buf, bufsize, flags); + + if(nret == -1) { + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __pyremovexattr_doc__[] = \ +"Remove an attribute from a file\n" \ +"\n" \ +"Parameters:\n" \ +"\t- a string representing filename, or a file-like object,\n" \ +"\t or a file descriptor; this represents the file on \n" \ +"\t which to act\n" \ +"\t- a string, representing the attribute to be removed;\n" \ +"\t usually in form of system.posix_acl or user.mime_type\n" \ +"\t- (optional) a boolean value (defaults to false), which, if\n" \ +"\t the file name given is a symbolic link, makes the\n" \ +"\t function operate on the symbolic link itself instead\n" \ +"\t of its target;" \ +; + +/* Wrapper for removexattr */ +static PyObject * +pyremovexattr(PyObject *self, PyObject *args) +{ + PyObject *myarg; + char *file; + int ishandle, filedes, dolink=0; + char *attrname; + int nret; + + /* Parse the arguments */ + if (!PyArg_ParseTuple(args, "Os|i", &myarg, &attrname, &dolink)) + return NULL; + + if(!convertObj(myarg, &ishandle, &filedes, &file)) + return NULL; + + /* Remove the attribute */ + nret = ishandle ? + fremovexattr(filedes, attrname) : + dolink ? + lremovexattr(file, attrname) : + removexattr(file, attrname); + + if(nret == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __pylistxattr_doc__[] = \ +"Return the tuple of attribute names from a file\n" \ +"\n" \ +"Parameters:\n" \ +"\t- a string representing filename, or a file-like object,\n" \ +"\t or a file descriptor; this represents the file to \n" \ +"\t be queried\n" \ +"\t- (optional) a boolean value (defaults to false), which, if\n" \ +"\t the file name given is a symbolic link, makes the\n" \ +"\t function operate on the symbolic link itself instead\n" \ +"\t of its target;" \ +; + +/* Wrapper for listxattr */ +static PyObject * +pylistxattr(PyObject *self, PyObject *args) +{ + char *file = NULL; + int filedes = -1; + char *buf; + int ishandle, dolink=0; + int nalloc, nret; + PyObject *myarg; + PyObject *mytuple; + int nattrs; + char *s; + + /* Parse the arguments */ + if (!PyArg_ParseTuple(args, "O|i", &myarg, &dolink)) + return NULL; + if(!convertObj(myarg, &ishandle, &filedes, &file)) + return NULL; + + /* Find out the needed size of the buffer */ + nalloc = ishandle ? + flistxattr(filedes, NULL, 0) : + dolink ? + llistxattr(file, NULL, 0) : + listxattr(file, NULL, 0); + + if(nalloc == -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 */ + nret = ishandle ? + flistxattr(filedes, buf, nalloc) : + dolink ? + llistxattr(file, buf, nalloc) : + listxattr(file, buf, nalloc); + + if(nret == -1) { + 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) { + nattrs++; + } + + /* Create the tuple which will hold the result */ + mytuple = PyTuple_New(nattrs); + + /* Create and insert the attributes as strings in the tuple */ + for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) { + PyTuple_SET_ITEM(mytuple, nattrs, PyString_FromString(s)); + nattrs++; + } + + /* Free the buffer, now it is no longer needed */ + PyMem_Free(buf); + + /* Return the result */ + return mytuple; +} + +static PyMethodDef xattr_methods[] = { + {"getxattr", pygetxattr, METH_VARARGS, __pygetxattr_doc__ }, + {"setxattr", pysetxattr, METH_VARARGS, __pysetxattr_doc__ }, + {"removexattr", pyremovexattr, METH_VARARGS, __pyremovexattr_doc__ }, + {"listxattr", pylistxattr, METH_VARARGS, __pylistxattr_doc__ }, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static char __xattr_doc__[] = \ +"Access extended filesystem attributes\n" \ +"\n" \ +"This module gives access to the extended attributes present\n" \ +"in some operating systems/filesystems. You can list attributes,\n"\ +"get, set and remove them.\n"\ +"The last and optional parameter for all functions is a boolean \n"\ +"value which enables the 'l-' version of the functions - acting\n"\ +"on symbolic links and not their destination.\n"\ +"\n" \ +"Example: \n" \ +">>> import xattr\n" \ +">>> xattr.listxattr(\"file.txt\")\n" \ +"('user.mime_type',)\n" \ +">>> xattr.getxattr(\"file.txt\", \"user.mime_type\")\n" \ +"'text/plain'\n" \ +">>> xattr.setxattr(\"file.txt\", \"user.comment\", \"Simple text file\")\n"\ +">>> xattr.listxattr(\"file.txt\")\n" \ +"('user.mime_type', 'user.comment')\n" \ +">>> xattr.removexattr (\"file.txt\", \"user.comment\")\n" \ +"" \ +; + +void +initxattr(void) +{ + PyObject *m = Py_InitModule3("xattr", xattr_methods, __xattr_doc__); + + PyModule_AddIntConstant(m, "XATTR_CREATE", XATTR_CREATE); + PyModule_AddIntConstant(m, "XATTR_REPLACE", XATTR_REPLACE); + +} diff --git a/xattr.html b/xattr.html new file mode 100644 index 0000000..94d9606 --- /dev/null +++ b/xattr.html @@ -0,0 +1,104 @@ + + +Python: module xattr + + + + +
 
+ 
xattr
index
/home/iusty/work/pyxattr/build/lib.linux-i686-2.3/xattr.so
+

Access extended filesystem attributes

+This module gives access to the extended attributes present
+in some operating systems/filesystems. You can list attributes,
+get, set and remove them.
+The last and optional parameter for all functions is a boolean 
+value which enables the 'l-' version of the functions - acting
+on symbolic links and not their destination.

+Example: 
+>>> import xattr
+>>> xattr.listxattr("file.txt")
+('user.mime_type',)
+>>> xattr.getxattr("file.txt", "user.mime_type")
+'text/plain'
+>>> xattr.setxattr("file.txt", "user.comment", "Simple text file")
+>>> xattr.listxattr("file.txt")
+('user.mime_type', 'user.comment')
+>>> xattr.removexattr ("file.txt", "user.comment")

+

+ + + + + +
 
+Functions
       
getxattr(...)
Get the value of a given extended attribute.

+Parameters:
+        - a string representing filename, or a file-like object,
+              or a file descriptor; this represents the file on 
+              which to act
+        - a string, representing the attribute whose value to retrieve;
+              usually in form of system.posix_acl or user.mime_type
+        - (optional) a boolean value (defaults to false), which, if
+              the file name given is a symbolic link, makes the
+              function operate on the symbolic link itself instead
+              of its target;
+
listxattr(...)
Return the tuple of attribute names from a file

+Parameters:
+        - a string representing filename, or a file-like object,
+              or a file descriptor; this represents the file to 
+              be queried
+        - (optional) a boolean value (defaults to false), which, if
+              the file name given is a symbolic link, makes the
+              function operate on the symbolic link itself instead
+              of its target;
+
removexattr(...)
Remove an attribute from a file

+Parameters:
+        - a string representing filename, or a file-like object,
+              or a file descriptor; this represents the file on 
+              which to act
+        - a string, representing the attribute to be removed;
+              usually in form of system.posix_acl or user.mime_type
+        - (optional) a boolean value (defaults to false), which, if
+              the file name given is a symbolic link, makes the
+              function operate on the symbolic link itself instead
+              of its target;
+
setxattr(...)
Set the value of a given extended attribute.
+Be carefull in case you want to set attributes on symbolic
+links, you have to use all the 5 parameters; use 0 for the 
+flags value if you want the default behavior (create or replace)

+Parameters:
+        - a string representing filename, or a file-like object,
+              or a file descriptor; this represents the file on 
+              which to act
+        - a string, representing the attribute whose value to set;
+              usually in form of system.posix_acl or user.mime_type
+        - a string, possibly with embedded NULLs; note that there
+              are restrictions regarding the size of the value, for
+              example, for ext2/ext3, maximum size is the block size
+        - (optional) flags; if 0 or ommited the attribute will be 
+              created or replaced; if XATTR_CREATE, the attribute 
+              will be created, giving an error if it already exists;
+              of XATTR_REPLACE, the attribute will be replaced,
+              giving an error if it doesn't exists;
+        - (optional) a boolean value (defaults to false), which, if
+              the file name given is a symbolic link, makes the
+              function operate on the symbolic link itself instead
+              of its target;
+

+ + + + + +
 
+Data
       XATTR_CREATE = 1
+XATTR_REPLACE = 2
+ \ No newline at end of file diff --git a/xattr.txt b/xattr.txt new file mode 100644 index 0000000..cd4f8ea --- /dev/null +++ b/xattr.txt @@ -0,0 +1,98 @@ +Help on module xattr: + +NAME + xattr - Access extended filesystem attributes + +FILE + /home/iusty/work/pyxattr/build/lib.linux-i686-2.3/xattr.so + +DESCRIPTION + This module gives access to the extended attributes present + in some operating systems/filesystems. You can list attributes, + get, set and remove them. + The last and optional parameter for all functions is a boolean + value which enables the 'l-' version of the functions - acting + on symbolic links and not their destination. + + Example: + >>> import xattr + >>> xattr.listxattr("file.txt") + ('user.mime_type',) + >>> xattr.getxattr("file.txt", "user.mime_type") + 'text/plain' + >>> xattr.setxattr("file.txt", "user.comment", "Simple text file") + >>> xattr.listxattr("file.txt") + ('user.mime_type', 'user.comment') + >>> xattr.removexattr ("file.txt", "user.comment") + +FUNCTIONS + getxattr(...) + Get the value of a given extended attribute. + + Parameters: + - a string representing filename, or a file-like object, + or a file descriptor; this represents the file on + which to act + - a string, representing the attribute whose value to retrieve; + usually in form of system.posix_acl or user.mime_type + - (optional) a boolean value (defaults to false), which, if + the file name given is a symbolic link, makes the + function operate on the symbolic link itself instead + of its target; + + listxattr(...) + Return the tuple of attribute names from a file + + Parameters: + - a string representing filename, or a file-like object, + or a file descriptor; this represents the file to + be queried + - (optional) a boolean value (defaults to false), which, if + the file name given is a symbolic link, makes the + function operate on the symbolic link itself instead + of its target; + + removexattr(...) + Remove an attribute from a file + + Parameters: + - a string representing filename, or a file-like object, + or a file descriptor; this represents the file on + which to act + - a string, representing the attribute to be removed; + usually in form of system.posix_acl or user.mime_type + - (optional) a boolean value (defaults to false), which, if + the file name given is a symbolic link, makes the + function operate on the symbolic link itself instead + of its target; + + setxattr(...) + Set the value of a given extended attribute. + Be carefull in case you want to set attributes on symbolic + links, you have to use all the 5 parameters; use 0 for the + flags value if you want the default behavior (create or replace) + + Parameters: + - a string representing filename, or a file-like object, + or a file descriptor; this represents the file on + which to act + - a string, representing the attribute whose value to set; + usually in form of system.posix_acl or user.mime_type + - a string, possibly with embedded NULLs; note that there + are restrictions regarding the size of the value, for + example, for ext2/ext3, maximum size is the block size + - (optional) flags; if 0 or ommited the attribute will be + created or replaced; if XATTR_CREATE, the attribute + will be created, giving an error if it already exists; + of XATTR_REPLACE, the attribute will be replaced, + giving an error if it doesn't exists; + - (optional) a boolean value (defaults to false), which, if + the file name given is a symbolic link, makes the + function operate on the symbolic link itself instead + of its target; + +DATA + XATTR_CREATE = 1 + XATTR_REPLACE = 2 + + -- 2.39.2