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