6 staticforward PyTypeObject ACLType;
7 static PyObject* ACL_applyto(PyObject* obj, PyObject* args);
8 static PyObject* ACL_valid(PyObject* obj, PyObject* args);
10 static PyObject* ACL_get_state(PyObject *obj, PyObject* args);
11 static PyObject* ACL_set_state(PyObject *obj, PyObject* args);
19 /* Creation of a new ACL instance */
20 static PyObject* ACL_new(PyTypeObject* type, PyObject* args, PyObject *keywds) {
23 newacl = type->tp_alloc(type, 0);
26 ((ACLObject*)newacl)->ob_acl = NULL;
31 /* Initialization of a new ACL instance */
32 static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) {
33 ACLObject* self = (ACLObject*) obj;
34 static char *kwlist[] = { "file", "fd", "text", "acl", NULL };
38 ACLObject* thesrc = NULL;
41 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|sisO!", kwlist,
42 &file, &fd, &text, &ACLType, &thesrc))
54 PyErr_SetString(PyExc_ValueError, "a maximum of one argument must be passed");
58 /* Free the old acl_t without checking for error, we don't
60 if(self->ob_acl != NULL)
61 acl_free(self->ob_acl);
64 self->ob_acl = acl_get_file(file, ACL_TYPE_ACCESS);
66 self->ob_acl = acl_from_text(text);
68 self->ob_acl = acl_get_fd(fd);
69 else if(thesrc != NULL)
70 self->ob_acl = acl_dup(thesrc->ob_acl);
72 self->ob_acl = acl_init(0);
74 if(self->ob_acl == NULL) {
75 PyErr_SetFromErrno(PyExc_IOError);
82 /* Standard type functions */
83 static void ACL_dealloc(PyObject* obj) {
84 ACLObject *self = (ACLObject*) obj;
85 PyObject *err_type, *err_value, *err_traceback;
86 int have_error = PyErr_Occurred() ? 1 : 0;
89 PyErr_Fetch(&err_type, &err_value, &err_traceback);
90 if(acl_free(self->ob_acl) != 0)
91 PyErr_WriteUnraisable(obj);
93 PyErr_Restore(err_type, err_value, err_traceback);
97 /* Converts the acl to a text format */
98 static PyObject* ACL_repr(PyObject *obj) {
100 ACLObject *self = (ACLObject*) obj;
103 text = acl_to_text(self->ob_acl, NULL);
105 return PyErr_SetFromErrno(PyExc_IOError);
107 ret = PyString_FromString(text);
108 if(acl_free(text) != 0) {
110 return PyErr_SetFromErrno(PyExc_IOError);
116 static char __applyto_doc__[] = \
117 "Apply the ACL to a file or filehandle.\n" \
120 " - either a filename or a file-like object or an integer; this\n" \
121 " represents the filesystem object on which to act\n" \
124 /* Applyes the ACL to a file */
125 static PyObject* ACL_applyto(PyObject* obj, PyObject* args) {
126 ACLObject *self = (ACLObject*) obj;
128 int type_default = 0;
129 acl_type_t type = ACL_TYPE_ACCESS;
133 if (!PyArg_ParseTuple(args, "O|i", &myarg, &type_default))
136 type = ACL_TYPE_DEFAULT;
138 if(PyString_Check(myarg)) {
139 char *filename = PyString_AS_STRING(myarg);
140 nret = acl_set_file(filename, type, self->ob_acl);
141 } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) {
142 nret = acl_set_fd(fd, self->ob_acl);
144 PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int, or file-like object");
148 return PyErr_SetFromErrno(PyExc_IOError);
151 /* Return the result */
156 static char __valid_doc__[] = \
157 "Test the ACL for validity.\n" \
159 "This method tests the ACL to see if it is a valid ACL\n" \
160 "in terms of the filesystem. More precisely, it checks:\n" \
161 "A valid ACL contains exactly one entry with each of the ACL_USER_OBJ,\n" \
162 "ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and\n" \
163 "ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that\n" \
164 "contains entries of ACL_USER or ACL_GROUP tag types must contain exactly\n" \
165 "one entry of the ACL_MASK tag type. If an ACL contains no entries of\n" \
166 "ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.\n" \
168 "All user ID qualifiers must be unique among all entries of ACL_USER tag\n" \
169 "type, and all group IDs must be unique among all entries of ACL_GROUP tag\n" \
172 /* Checks the ACL for validity */
173 static PyObject* ACL_valid(PyObject* obj, PyObject* args) {
174 ACLObject *self = (ACLObject*) obj;
176 if(acl_valid(self->ob_acl) == -1) {
177 return PyErr_SetFromErrno(PyExc_IOError);
180 /* Return the result */
187 static PyObject* ACL_get_state(PyObject *obj, PyObject* args) {
188 ACLObject *self = (ACLObject*) obj;
193 size = acl_size(self->ob_acl);
195 return PyErr_SetFromErrno(PyExc_IOError);
197 if((ret = PyString_FromStringAndSize(NULL, size)) == NULL)
199 buf = PyString_AsString(ret);
201 if((nsize = acl_copy_ext(buf, self->ob_acl, size)) == -1) {
203 return PyErr_SetFromErrno(PyExc_IOError);
209 static PyObject* ACL_set_state(PyObject *obj, PyObject* args) {
210 ACLObject *self = (ACLObject*) obj;
215 /* Parse the argument */
216 if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize))
219 /* Try to import the external representation */
220 if((ptr = acl_copy_int(buf)) == NULL)
221 return PyErr_SetFromErrno(PyExc_IOError);
223 /* Free the old acl. Should we ignore errors here? */
224 if(self->ob_acl != NULL) {
225 if(acl_free(self->ob_acl) == -1)
226 return PyErr_SetFromErrno(PyExc_IOError);
231 /* Return the result */
238 static char __acltype_doc__[] = \
239 "Type which represents a POSIX ACL\n" \
242 " Only one keword parameter should be provided:\n"
243 " - file=\"...\", meaning create ACL representing\n"
244 " the ACL of that file\n" \
245 " - fd=<int>, meaning create ACL representing\n" \
246 " the ACL of that file descriptor\n" \
247 " - text=\"...\", meaning create ACL from a \n" \
248 " textual description\n" \
249 " - acl=<ACL instance>, meaning create a copy\n" \
250 " of an existing ACL instance\n" \
253 /* ACL type methods */
254 static PyMethodDef ACL_methods[] = {
255 {"applyto", ACL_applyto, METH_VARARGS, __applyto_doc__},
256 {"valid", ACL_valid, METH_NOARGS, __valid_doc__},
258 {"__getstate__", ACL_get_state, METH_NOARGS, "Dumps the ACL to an external format."},
259 {"__setstate__", ACL_set_state, METH_VARARGS, "Loads the ACL from an external format."},
261 {NULL, NULL, 0, NULL}
265 /* The definition of the ACL Type */
266 static PyTypeObject ACLType = {
267 PyObject_HEAD_INIT(NULL)
272 ACL_dealloc, /* tp_dealloc */
277 ACL_repr, /* tp_repr */
278 0, /* tp_as_number */
279 0, /* tp_as_sequence */
280 0, /* tp_as_mapping */
286 0, /* tp_as_buffer */
287 Py_TPFLAGS_DEFAULT, /* tp_flags */
288 __acltype_doc__, /* tp_doc */
291 0, /* tp_richcompare */
292 0, /* tp_weaklistoffset */
295 ACL_methods, /* tp_methods */
300 0, /* tp_descr_get */
301 0, /* tp_descr_set */
302 0, /* tp_dictoffset */
303 ACL_init, /* tp_init */
305 ACL_new, /* tp_new */
310 static char __deletedef_doc__[] = \
311 "Delete the default ACL from a directory.\n" \
313 "This function deletes the default ACL associated with \n" \
314 "a directory (the ACL which will be ANDed with the mode\n" \
315 "parameter to the open, creat functions).\n" \
317 " - a string representing the directory whose default ACL\n" \
318 " should be deleted\n" \
321 /* Deletes the default ACL from a directory */
322 static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) {
325 /* Parse the arguments */
326 if (!PyArg_ParseTuple(args, "s", &filename))
329 if(acl_delete_def_file(filename) == -1) {
330 return PyErr_SetFromErrno(PyExc_IOError);
333 /* Return the result */
338 /* The module methods */
339 static PyMethodDef aclmodule_methods[] = {
340 {"delete_default", aclmodule_delete_default, METH_VARARGS, __deletedef_doc__},
341 {NULL, NULL, 0, NULL}
344 static char __posix1e_doc__[] = \
345 "POSIX.1e ACLs manipulation\n" \
347 "This module provides support for manipulating POSIX.1e ACLS\n" \
349 "Depending on the operating system support for POSIX.1e, \n" \
350 "the ACL type will have more or less capabilities:\n" \
351 " - level 1, only basic support, you can create\n" \
352 " ACLs from files and text descriptions;\n" \
353 " once created, the type is immutable\n" \
354 " - level 2, complete support, you can alter\n"\
355 " the ACL once it is created\n" \
357 "Also, in level 2, more types will be available, corresponding\n" \
358 "to acl_entry_t, acl_permset_t, etc.\n" \
361 ">>> import posix1e\n" \
362 ">>> acl1 = posix1e.ACL(file=\"file.txt\") \n" \
368 ">>> b = posix1e.ACL(text=\"u::rx,g::-,o::-\")\n" \
374 ">>> b.applyto(\"file.txt\")\n" \
375 ">>> print posix1e.ACL(file=\"file.txt\")\n" \
383 DL_EXPORT(void) initposix1e(void) {
386 ACLType.ob_type = &PyType_Type;
388 if(PyType_Ready(&ACLType) < 0)
391 m = Py_InitModule3("posix1e", aclmodule_methods, __posix1e_doc__);
393 d = PyModule_GetDict(m);
398 if (PyDict_SetItemString(d, "ACL",
399 (PyObject *) &ACLType) < 0)