]> git.k1024.org Git - pyxattr.git/blob - xattr.c
Fixed names again, and switched parsing of int and files to PyObject_AsFileDescriptor
[pyxattr.git] / xattr.c
1 #include <Python.h>
2 #include <attr/xattr.h>
3
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)) {
7         *ishandle = 0;
8         *filename = PyString_AS_STRING(myobj);
9     } else if((*filehandle = PyObject_AsFileDescriptor(myobj)) != -1) {
10         *ishandle = 1;
11     } else {
12         PyErr_SetString(PyExc_TypeError, "argument 1 must be string or int");
13         return 0;
14     }
15     return 1;
16 }
17
18 /* Wrapper for getxattr */
19 static PyObject *
20 pygetxattr(PyObject *self, PyObject *args)
21 {
22     PyObject *myarg;
23     char *file;
24     int filedes, ishandle;
25     char *attrname;
26     char *buf;
27     int nalloc, nret;
28     PyObject *res;
29     
30     /* Parse the arguments */
31     if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
32         return NULL;
33     if(!convertObj(myarg, &ishandle, &filedes, &file))
34         return NULL;
35
36     /* Find out the needed size of the buffer */
37     nalloc = ishandle ? 
38         fgetxattr(filedes, attrname, NULL, 0) : 
39         getxattr(file, attrname, NULL, 0);
40     if(nalloc == -1) {
41         return PyErr_SetFromErrno(PyExc_IOError);
42     }
43
44     /* Try to allocate the memory, using Python's allocator */
45     if((buf = PyMem_Malloc(nalloc)) == NULL) {
46         PyErr_NoMemory();
47         return NULL;
48     }
49
50     /* Now retrieve the attribute value */
51     nret = ishandle ? 
52         fgetxattr(filedes, attrname, buf, nalloc) :
53         getxattr(file, attrname, buf, nalloc);
54     if(nret == -1) {
55         return PyErr_SetFromErrno(PyExc_IOError);
56     }
57
58     /* Create the string which will hold the result */
59     res = PyString_FromStringAndSize(buf, nret);
60
61     /* Free the buffer, now it is no longer needed */
62     PyMem_Free(buf);
63
64     /* Return the result */
65     return res;
66 }
67
68 /* Wrapper for setxattr */
69 static PyObject *
70 pysetxattr(PyObject *self, PyObject *args)
71 {
72     PyObject *myarg;
73     char *file;
74     int ishandle, filedes;
75     char *attrname;
76     char *buf;
77     char mode = 0;
78     int bufsize, nret;
79     int flags;
80     
81     /* Parse the arguments */
82     if (!PyArg_ParseTuple(args, "Oss#|b", &myarg, &attrname, &buf, &bufsize, &mode))
83         return NULL;
84     if(!convertObj(myarg, &ishandle, &filedes, &file))
85         return NULL;
86
87     /* Check the flags and convert them to libattr values */
88     flags = mode == 1 ? XATTR_CREATE : mode == 2 ? XATTR_REPLACE : 0;
89
90     /* Set the attribute's value */
91     nret = ishandle ?
92         fsetxattr(filedes, attrname, buf, bufsize, flags) :
93         setxattr(file, attrname, buf, bufsize, flags);
94
95     if(nret == -1) {
96         return PyErr_SetFromErrno(PyExc_IOError);
97     }
98
99     /* Return the result */
100     Py_INCREF(Py_None);
101     return Py_None;
102 }
103
104 /* Wrapper for removexattr */
105 static PyObject *
106 pyremovexattr(PyObject *self, PyObject *args)
107 {
108     PyObject *myarg;
109     char *file;
110     int ishandle, filedes;
111     char *attrname;
112     int nret;
113     
114     /* Parse the arguments */
115     if (!PyArg_ParseTuple(args, "Os", &myarg, &attrname))
116         return NULL;
117
118     if(!convertObj(myarg, &ishandle, &filedes, &file))
119         return NULL;
120
121     /* Remove the attribute */
122     nret = ishandle ?
123         fremovexattr(filedes, attrname) :
124         removexattr(file, attrname);
125
126     if(nret == -1)
127         return PyErr_SetFromErrno(PyExc_IOError);
128
129     /* Return the result */
130     Py_INCREF(Py_None);
131     return Py_None;
132 }
133
134 /* Wrapper for listxattr */
135 static PyObject *
136 pylistxattr(PyObject *self, PyObject *args)
137 {
138     char *file = NULL;
139     int filedes = -1;
140     char *buf;
141     int ishandle;
142     int nalloc, nret;
143     PyObject *myarg;
144     PyObject *mytuple;
145     int nattrs;
146     char *s;
147     
148     /* Parse the arguments */
149     if (!PyArg_ParseTuple(args, "O", &myarg))
150         return NULL;
151     if(!convertObj(myarg, &ishandle, &filedes, &file))
152         return NULL;
153
154     /* Find out the needed size of the buffer */
155     nalloc = ishandle ?
156         flistxattr(filedes, NULL, 0) :
157         listxattr(file, NULL, 0);
158
159     if(nalloc == -1) {
160         return PyErr_SetFromErrno(PyExc_IOError);
161     }
162
163     /* Try to allocate the memory, using Python's allocator */
164     if((buf = PyMem_Malloc(nalloc)) == NULL) {
165         PyErr_NoMemory();
166         return NULL;
167     }
168
169     /* Now retrieve the list of attributes */
170     nret = ishandle ? 
171         flistxattr(filedes, buf, nalloc) : 
172         listxattr(file, buf, nalloc);
173     if(nret == -1) {
174         return PyErr_SetFromErrno(PyExc_IOError);
175     }
176
177     /* Compute the number of attributes in the list */
178     for(s = buf, nattrs = 0; (s - buf) < nret; s += strlen(s) + 1) {
179         nattrs++;
180     }
181
182     /* Create the tuple which will hold the result */
183     mytuple = PyTuple_New(nattrs);
184
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));
188         nattrs++;
189     }
190
191     /* Free the buffer, now it is no longer needed */
192     PyMem_Free(buf);
193
194     /* Return the result */
195     return mytuple;
196 }
197
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 */
208 };
209
210 void
211 initxattr(void)
212 {
213     (void) Py_InitModule3("xattr", xattr_methods, "Wrapper module for libattr");
214 }