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