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 */
20 pygetxattr(PyObject *self, PyObject *args)
24 int filedes, ishandle;
30 /* Parse the arguments */
31 if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
33 if(!convertObj(myarg, &ishandle, &filedes, &file))
36 /* Find out the needed size of the buffer */
38 fgetxattr(filedes, attrname, NULL, 0) :
39 getxattr(file, attrname, NULL, 0);
41 return PyErr_SetFromErrno(PyExc_IOError);
44 /* Try to allocate the memory, using Python's allocator */
45 if((buf = PyMem_Malloc(nalloc)) == NULL) {
50 /* Now retrieve the attribute value */
52 fgetxattr(filedes, attrname, buf, nalloc) :
53 getxattr(file, attrname, buf, nalloc);
55 return PyErr_SetFromErrno(PyExc_IOError);
58 /* Create the string which will hold the result */
59 res = PyString_FromStringAndSize(buf, nret);
61 /* Free the buffer, now it is no longer needed */
64 /* Return the result */
68 /* Wrapper for setxattr */
70 pysetxattr(PyObject *self, PyObject *args)
74 int ishandle, filedes;
81 /* Parse the arguments */
82 if (!PyArg_ParseTuple(args, "Oss#|b", &myarg, &attrname, &buf, &bufsize, &mode))
84 if(!convertObj(myarg, &ishandle, &filedes, &file))
87 /* Check the flags and convert them to libattr values */
88 flags = mode == 1 ? XATTR_CREATE : mode == 2 ? XATTR_REPLACE : 0;
90 /* Set the attribute's value */
92 fsetxattr(filedes, attrname, buf, bufsize, flags) :
93 setxattr(file, attrname, buf, bufsize, flags);
96 return PyErr_SetFromErrno(PyExc_IOError);
99 /* Return the result */
104 /* Wrapper for removexattr */
106 pyremovexattr(PyObject *self, PyObject *args)
110 int ishandle, filedes;
114 /* Parse the arguments */
115 if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
118 if(!convertObj(myarg, &ishandle, &filedes, &file))
121 /* Remove the attribute */
123 fremovexattr(filedes, attrname) :
124 removexattr(file, attrname);
127 return PyErr_SetFromErrno(PyExc_IOError);
129 /* Return the result */
134 /* Wrapper for listxattr */
136 pylistxattr(PyObject *self, PyObject *args)
148 /* Parse the arguments */
149 if (!PyArg_ParseTuple(args, "O", &myarg))
151 if(!convertObj(myarg, &ishandle, &filedes, &file))
154 /* Find out the needed size of the buffer */
156 flistxattr(filedes, NULL, 0) :
157 listxattr(file, NULL, 0);
160 return PyErr_SetFromErrno(PyExc_IOError);
163 /* Try to allocate the memory, using Python's allocator */
164 if((buf = PyMem_Malloc(nalloc)) == NULL) {
169 /* Now retrieve the list of attributes */
171 flistxattr(filedes, buf, nalloc) :
172 listxattr(file, buf, nalloc);
174 return PyErr_SetFromErrno(PyExc_IOError);
177 /* Compute the number of attributes in the list */
178 for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) {
182 /* Create the tuple which will hold the result */
183 mytuple = PyTuple_New(nattrs);
185 /* Create and insert the attributes as strings in the tuple */
186 for(s = buf, nattrs = 0; s - buf < nret; s += strlen(s) + 1) {
187 PyTuple_SET_ITEM(mytuple, nattrs, PyString_FromString(s));
191 /* Free the buffer, now it is no longer needed */
194 /* Return the result */
198 static PyMethodDef xattr_methods[] = {
199 {"getxattr", pygetxattr, METH_VARARGS,
200 "Get the value of a given extended attribute."},
201 {"setxattr", pysetxattr, METH_VARARGS,
202 "Set the value of a given extended attribute."},
203 {"removexattr", pyremovexattr, METH_VARARGS,
204 "Remove the a given extended attribute."},
205 {"listxattr", pylistxattr, METH_VARARGS,
206 "Retrieve the list of extened attributes."},
207 {NULL, NULL, 0, NULL} /* Sentinel */
213 (void) Py_InitModule3("xattr", xattr_methods, "Wrapper module for libattr");