2 #include <attr/xattr.h>
4 /** Converts from a string, file or int argument to what we need. */
5 static int convertObj(PyObject *myobj, int *ishandle, int *filehandle, char **filename) {
6 if(PyString_Check(myobj)) {
8 *filename = PyString_AS_STRING(myobj);
9 } else if((*filehandle = PyObject_AsFileDescriptor(myobj)) != -1) {
12 PyErr_SetString(PyExc_TypeError, "argument 1 must be string or int");
18 /* Wrapper for getxattr */
19 static char __pygetxattr_doc__[] = \
20 "Get the value of a given extended attribute.\n" \
23 "\t- a string representing filename, or a file-like object,\n" \
24 "\t or a file descriptor; this represents the file on \n" \
26 "\t- a string, representing the attribute whose value to retrieve;\n" \
27 "\t usually in form of system.posix_acl or user.mime_type" \
31 pygetxattr(PyObject *self, PyObject *args)
35 int filedes, ishandle;
41 /* Parse the arguments */
42 if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
44 if(!convertObj(myarg, &ishandle, &filedes, &file))
47 /* Find out the needed size of the buffer */
49 fgetxattr(filedes, attrname, NULL, 0) :
50 getxattr(file, attrname, NULL, 0);
52 return PyErr_SetFromErrno(PyExc_IOError);
55 /* Try to allocate the memory, using Python's allocator */
56 if((buf = PyMem_Malloc(nalloc)) == NULL) {
61 /* Now retrieve the attribute value */
63 fgetxattr(filedes, attrname, buf, nalloc) :
64 getxattr(file, attrname, buf, nalloc);
66 return PyErr_SetFromErrno(PyExc_IOError);
69 /* Create the string which will hold the result */
70 res = PyString_FromStringAndSize(buf, nret);
72 /* Free the buffer, now it is no longer needed */
75 /* Return the result */
79 static char __pysetxattr_doc__[] = \
80 "Set the value of a given extended attribute.\n" \
83 "\t- a string representing filename, or a file-like object,\n" \
84 "\t or a file descriptor; this represents the file on \n" \
86 "\t- a string, representing the attribute whose value to set;\n" \
87 "\t usually in form of system.posix_acl or user.mime_type\n" \
88 "\t- a string, possibly with embedded NULLs; note that there\n" \
89 "\t are restrictions regarding the size of the value, for\n" \
90 "\t example, for ext2/ext3, maximum size is the block size\n" \
91 "\t- a small integer; if ommited the attribute will be created\n" \
92 "\t or replaced; if XATTR_CREATE, the attribute will be \n" \
93 "\t created, giving an error if it already exists; if \n" \
94 "\t XATTR_REPLACE, the attribute will be replaced, giving \n" \
95 "\t an error if it doesn't exists." \
98 /* Wrapper for setxattr */
100 pysetxattr(PyObject *self, PyObject *args)
104 int ishandle, filedes;
110 /* Parse the arguments */
111 if (!PyArg_ParseTuple(args, "Oss#|b", &myarg, &attrname, &buf, &bufsize, &flags))
113 if(!convertObj(myarg, &ishandle, &filedes, &file))
116 /* Set the attribute's value */
118 fsetxattr(filedes, attrname, buf, bufsize, flags) :
119 setxattr(file, attrname, buf, bufsize, flags);
122 return PyErr_SetFromErrno(PyExc_IOError);
125 /* Return the result */
130 static char __pyremovexattr_doc__[] = \
131 "Remove an attribute from a file\n" \
134 "\t- a string representing filename, or a file-like object,\n" \
135 "\t or a file descriptor; this represents the file on \n" \
136 "\t which to act\n" \
137 "\t- a string, representing the attribute to be removed;\n" \
138 "\t usually in form of system.posix_acl or user.mime_type" \
141 /* Wrapper for removexattr */
143 pyremovexattr(PyObject *self, PyObject *args)
147 int ishandle, filedes;
151 /* Parse the arguments */
152 if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
155 if(!convertObj(myarg, &ishandle, &filedes, &file))
158 /* Remove the attribute */
160 fremovexattr(filedes, attrname) :
161 removexattr(file, attrname);
164 return PyErr_SetFromErrno(PyExc_IOError);
166 /* Return the result */
171 static char __pylistxattr_doc__[] = \
172 "Return the list of attribute names from a file\n" \
175 "\t- a string representing filename, or a file-like object,\n" \
176 "\t or a file descriptor; this represents the file to \n" \
180 /* Wrapper for listxattr */
182 pylistxattr(PyObject *self, PyObject *args)
194 /* Parse the arguments */
195 if (!PyArg_ParseTuple(args, "O", &myarg))
197 if(!convertObj(myarg, &ishandle, &filedes, &file))
200 /* Find out the needed size of the buffer */
202 flistxattr(filedes, NULL, 0) :
203 listxattr(file, NULL, 0);
206 return PyErr_SetFromErrno(PyExc_IOError);
209 /* Try to allocate the memory, using Python's allocator */
210 if((buf = PyMem_Malloc(nalloc)) == NULL) {
215 /* Now retrieve the list of attributes */
217 flistxattr(filedes, buf, nalloc) :
218 listxattr(file, buf, nalloc);
220 return PyErr_SetFromErrno(PyExc_IOError);
223 /* Compute the number of attributes in the list */
224 for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) {
228 /* Create the tuple which will hold the result */
229 mytuple = PyTuple_New(nattrs);
231 /* Create and insert the attributes as strings in the tuple */
232 for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) {
233 PyTuple_SET_ITEM(mytuple, nattrs, PyString_FromString(s));
237 /* Free the buffer, now it is no longer needed */
240 /* Return the result */
244 static PyMethodDef xattr_methods[] = {
245 {"getxattr", pygetxattr, METH_VARARGS, __pygetxattr_doc__ },
246 {"setxattr", pysetxattr, METH_VARARGS, __pysetxattr_doc__ },
247 {"removexattr", pyremovexattr, METH_VARARGS, __pyremovexattr_doc__ },
248 {"listxattr", pylistxattr, METH_VARARGS, __pylistxattr_doc__ },
249 {NULL, NULL, 0, NULL} /* Sentinel */
252 static char __xattr_doc__[] = \
253 "Access extended filesystem attributes\n" \
255 "This module gives access to the extended attributes present\n" \
256 "in some operating systems/filesystems. You can list attributes,\n"\
257 "get, set and remove them.\n"\
263 PyObject *m = Py_InitModule3("xattr", xattr_methods, __xattr_doc__);
265 PyModule_AddIntConstant(m, "XATTR_CREATE", XATTR_CREATE);
266 PyModule_AddIntConstant(m, "XATTR_REPLACE", XATTR_REPLACE);