]> git.k1024.org Git - pylibacl.git/blob - acl.c
Addedd __setstate__ and some docs
[pylibacl.git] / acl.c
1 #include <sys/types.h>
2 #include <sys/acl.h>
3
4 #include <Python.h>
5
6 staticforward PyTypeObject ACLType;
7 static PyObject* ACL_applyto(PyObject* obj, PyObject* args);
8 static PyObject* ACL_valid(PyObject* obj, PyObject* args);
9 #ifdef HAVE_LEVEL2
10 static PyObject* ACL_get_state(PyObject *obj, PyObject* args);
11 static PyObject* ACL_set_state(PyObject *obj, PyObject* args);
12 #endif
13
14 typedef struct {
15     PyObject_HEAD
16     acl_t ob_acl;
17 } ACLObject;
18
19 /* ACL type methods */
20 static PyMethodDef ACL_methods[] = {
21     {"applyto", ACL_applyto, METH_VARARGS, "Apply the ACL to a file or filehandle."},
22     {"valid", ACL_valid, METH_NOARGS, "Test the ACL for validity."},
23 #ifdef HAVE_LEVEL2
24     {"__getstate__", ACL_get_state, METH_NOARGS, "Dumps the ACL to an external format."},
25     {"__setstate__", ACL_set_state, METH_VARARGS, "Loads the ACL from an external format."},
26 #endif
27     {NULL, NULL, 0, NULL}
28 };
29
30 /* Creation of a new ACL instance */
31 static PyObject* ACL_new(PyObject* self, PyObject* args, PyObject *keywds) {
32     ACLObject* theacl;
33     static char *kwlist[] = { "file", "fd", "text", "acl", NULL };
34     char *file = NULL;
35     char *text = NULL;
36     int fd = -1;
37     ACLObject* thesrc = NULL;
38     int tmp;
39
40     if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sisO!", kwlist,
41                                      &file, &fd, &text, &ACLType, &thesrc))
42         return NULL;
43     tmp = 0;
44     if(file != NULL)
45         tmp++;
46     if(text != NULL)
47         tmp++;
48     if(fd != -1)
49         tmp++;
50     if(thesrc != NULL)
51         tmp++;
52     if(tmp > 1) {
53         PyErr_SetString(PyExc_ValueError, "a maximum of one argument must be passed");
54         return NULL;
55     }
56
57     theacl = PyObject_New(ACLObject, &ACLType);
58     if(file != NULL)
59         theacl->ob_acl = acl_get_file(file, ACL_TYPE_ACCESS);
60     else if(text != NULL)
61         theacl->ob_acl = acl_from_text(text);
62     else if(fd != -1)
63         theacl->ob_acl = acl_get_fd(fd);
64     else if(thesrc != NULL)
65         theacl->ob_acl = acl_dup(thesrc->ob_acl);
66     else
67         theacl->ob_acl = acl_init(0);
68     if(theacl->ob_acl == NULL) {
69         Py_DECREF(theacl);
70         return PyErr_SetFromErrno(PyExc_IOError);
71     }
72
73     return (PyObject*)theacl;
74 }
75
76 /* Standard type functions */
77 static void ACL_dealloc(PyObject* obj) {
78     ACLObject *self = (ACLObject*) obj;
79     PyObject *err_type, *err_value, *err_traceback;
80     int have_error = PyErr_Occurred() ? 1 : 0;
81
82     if (have_error)
83         PyErr_Fetch(&err_type, &err_value, &err_traceback);
84     if(acl_free(self->ob_acl) != 0)
85         PyErr_WriteUnraisable(obj);
86     if (have_error)
87         PyErr_Restore(err_type, err_value, err_traceback);
88     PyObject_DEL(self);
89 }
90
91 /* Converts the acl to a text format */
92 static PyObject* ACL_repr(PyObject *obj) {
93     char *text;
94     ACLObject *self = (ACLObject*) obj;
95     PyObject *ret;
96
97     text = acl_to_text(self->ob_acl, NULL);
98     if(text == NULL) {
99         return PyErr_SetFromErrno(PyExc_IOError);
100     }
101     ret = PyString_FromString(text);
102     if(acl_free(text) != 0) {
103         Py_DECREF(ret);
104         return PyErr_SetFromErrno(PyExc_IOError);
105     }
106     return ret;
107 }
108
109 /* Custom methods */
110 /* Applyes the ACL to a file */
111 static PyObject* ACL_applyto(PyObject* obj, PyObject* args) {
112     ACLObject *self = (ACLObject*) obj;
113     PyObject *myarg;
114     int type_default = 0;
115     acl_type_t type = ACL_TYPE_ACCESS;
116     int nret;
117     int fd;
118
119     if (!PyArg_ParseTuple(args, "O|i", &myarg, &type_default))
120         return NULL;
121     if(type_default)
122         type = ACL_TYPE_DEFAULT;
123
124     if(PyString_Check(myarg)) {
125         char *filename = PyString_AS_STRING(myarg);
126         nret = acl_set_file(filename, type, self->ob_acl);
127     } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) {
128         nret = acl_set_fd(fd, self->ob_acl);
129     } else {
130         PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int, or file-like object");
131         return 0;
132     }
133     if(nret == -1) {
134         return PyErr_SetFromErrno(PyExc_IOError);
135     }
136
137     /* Return the result */
138     Py_INCREF(Py_None);
139     return Py_None;
140 }
141
142 /* Checks the ACL for validity */
143 static PyObject* ACL_valid(PyObject* obj, PyObject* args) {
144     ACLObject *self = (ACLObject*) obj;
145
146     if(acl_valid(self->ob_acl) == -1) {
147         return PyErr_SetFromErrno(PyExc_IOError);
148     }
149
150     /* Return the result */
151     Py_INCREF(Py_None);
152     return Py_None;
153 }
154
155 #ifdef HAVE_LEVEL2
156
157 static PyObject* ACL_get_state(PyObject *obj, PyObject* args) {
158     ACLObject *self = (ACLObject*) obj;
159     PyObject *ret;
160     ssize_t size, nsize;
161     char *buf;
162
163     size = acl_size(self->ob_acl);
164     if(size == -1)
165         return PyErr_SetFromErrno(PyExc_IOError);
166
167     if((ret = PyString_FromStringAndSize(NULL, size)) == NULL)
168         return NULL;
169     buf = PyString_AsString(ret);
170     
171     if((nsize = acl_copy_ext(buf, self->ob_acl, size)) == -1) {
172         Py_DECREF(ret);
173         return PyErr_SetFromErrno(PyExc_IOError);
174     }
175     
176     return ret;
177 }
178
179 static PyObject* ACL_set_state(PyObject *obj, PyObject* args) {
180     ACLObject *self = (ACLObject*) obj;
181     const void *buf;
182     int bufsize;
183     acl_t ptr;
184
185     /* Parse the argument */
186     if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize))
187         return NULL;
188
189     /* Try to import the external representation */
190     if((ptr = acl_copy_int(buf)) == NULL)
191         return PyErr_SetFromErrno(PyExc_IOError);
192         
193     /* Free the old acl. Should we ignore errors here? */
194     if(self->ob_acl != NULL) {
195         if(acl_free(self->ob_acl) == -1)
196             return PyErr_SetFromErrno(PyExc_IOError);
197     }
198
199     self->ob_acl = ptr;
200
201     /* Return the result */
202     Py_INCREF(Py_None);
203     return Py_None;
204 }
205
206 #endif
207
208 /* The definition of the ACL Type */
209 static PyTypeObject ACLType = {
210     PyObject_HEAD_INIT(NULL)
211     0,
212     "ACL",
213     sizeof(ACLObject),
214     0,
215     ACL_dealloc,/*tp_dealloc*/
216     0,          /*tp_print*/
217     0,          /*tp_getattr*/
218     0,          /*tp_setattr*/
219     0,          /*tp_compare*/
220     ACL_repr,   /*tp_repr*/
221     0,          /*tp_as_number*/
222     0,          /*tp_as_sequence*/
223     0,          /*tp_as_mapping*/
224     0,          /*tp_hash*/
225     0,          /*tp_call*/
226     0,          /*tp_str*/
227     0,          /*tp_getattro*/
228     0,          /*tp_setattro*/
229     0,          /*tp_as_buffer*/
230     0,          /*tp_flags*/
231     "Type which represents a POSIX ACL", /*tp_doc*/
232     0,          /*tp_traverse*/
233     0,          /*tp_clear*/
234     0,          /*tp_richcompare*/
235     0,          /*tp_weaklistoffset*/
236     0,          /*tp_iter*/
237     0,          /*tp_iternext*/
238     ACL_methods, /*tp_methods*/
239 };
240
241 /* Module methods */
242
243 /* Deletes the default ACL from a directory */
244 static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) {
245     char *filename;
246
247     /* Parse the arguments */
248     if (!PyArg_ParseTuple(args, "s", &filename))
249         return NULL;
250
251     if(acl_delete_def_file(filename) == -1) {
252         return PyErr_SetFromErrno(PyExc_IOError);
253     }
254
255     /* Return the result */
256     Py_INCREF(Py_None);
257     return Py_None;
258 }
259
260 /* The module methods */
261 static PyMethodDef aclmodule_methods[] = {
262     {"ACL", (PyCFunction)ACL_new, METH_VARARGS|METH_KEYWORDS, "Create a new ACL object."},
263     {"delete_default", aclmodule_delete_default, 
264      METH_VARARGS, "Delete the default ACL from a directory."},
265     {NULL, NULL, 0, NULL}
266 };
267
268 DL_EXPORT(void) initposixacl(void) {
269     ACLType.ob_type = &PyType_Type;
270
271     if(PyType_Ready(&ACLType) < 0)
272         return;
273     Py_InitModule("posixacl", aclmodule_methods);
274 }