10 staticforward PyTypeObject ACL_Type;
11 static PyObject* ACL_applyto(PyObject* obj, PyObject* args);
12 static PyObject* ACL_valid(PyObject* obj, PyObject* args);
15 static PyObject* ACL_get_state(PyObject *obj, PyObject* args);
16 static PyObject* ACL_set_state(PyObject *obj, PyObject* args);
18 staticforward PyTypeObject Entry_Type;
19 staticforward PyTypeObject Permset_Type;
20 static PyObject* Permset_new(PyTypeObject* type, PyObject* args, PyObject *keywds);
23 static acl_perm_t holder_ACL_EXECUTE = ACL_EXECUTE;
24 static acl_perm_t holder_ACL_READ = ACL_READ;
25 static acl_perm_t holder_ACL_WRITE = ACL_WRITE;
39 PyObject *parent_acl; /* The parent acl, so it won't run out on us */
45 PyObject *parent_entry; /* The parent entry, so it won't run out on us */
46 acl_permset_t permset;
51 /* Creation of a new ACL instance */
52 static PyObject* ACL_new(PyTypeObject* type, PyObject* args, PyObject *keywds) {
55 newacl = type->tp_alloc(type, 0);
58 ((ACL_Object*)newacl)->acl = NULL;
60 ((ACL_Object*)newacl)->entry_id = ACL_FIRST_ENTRY;
67 /* Initialization of a new ACL instance */
68 static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) {
69 ACL_Object* self = (ACL_Object*) obj;
70 static char *kwlist[] = { "file", "fd", "text", "acl", "filedef", NULL };
75 ACL_Object* thesrc = NULL;
77 if(!PyTuple_Check(args) || PyTuple_Size(args) != 0 ||
78 (keywds != NULL && PyDict_Check(keywds) && PyDict_Size(keywds) > 1)) {
79 PyErr_SetString(PyExc_ValueError, "a max of one keyword argument must be passed");
82 if(!PyArg_ParseTupleAndKeywords(args, keywds, "|sisO!s", kwlist,
83 &file, &fd, &text, &ACL_Type, &thesrc, &filedef))
86 /* Free the old acl_t without checking for error, we don't
92 self->acl = acl_get_file(file, ACL_TYPE_ACCESS);
94 self->acl = acl_from_text(text);
96 self->acl = acl_get_fd(fd);
97 else if(thesrc != NULL)
98 self->acl = acl_dup(thesrc->acl);
99 else if(filedef != NULL)
100 self->acl = acl_get_file(filedef, ACL_TYPE_DEFAULT);
102 self->acl = acl_init(0);
104 if(self->acl == NULL) {
105 PyErr_SetFromErrno(PyExc_IOError);
112 /* Standard type functions */
113 static void ACL_dealloc(PyObject* obj) {
114 ACL_Object *self = (ACL_Object*) obj;
115 PyObject *err_type, *err_value, *err_traceback;
116 int have_error = PyErr_Occurred() ? 1 : 0;
119 PyErr_Fetch(&err_type, &err_value, &err_traceback);
120 if(self->acl != NULL && acl_free(self->acl) != 0)
121 PyErr_WriteUnraisable(obj);
123 PyErr_Restore(err_type, err_value, err_traceback);
127 /* Converts the acl to a text format */
128 static PyObject* ACL_str(PyObject *obj) {
130 ACL_Object *self = (ACL_Object*) obj;
133 text = acl_to_text(self->acl, NULL);
135 return PyErr_SetFromErrno(PyExc_IOError);
137 ret = PyString_FromString(text);
138 if(acl_free(text) != 0) {
140 return PyErr_SetFromErrno(PyExc_IOError);
146 static char __applyto_doc__[] = \
147 "Apply the ACL to a file or filehandle.\n" \
150 " - either a filename or a file-like object or an integer; this\n" \
151 " represents the filesystem object on which to act\n" \
152 " - optional flag representing the type of ACL to set, either\n" \
153 " ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT\n" \
156 /* Applyes the ACL to a file */
157 static PyObject* ACL_applyto(PyObject* obj, PyObject* args) {
158 ACL_Object *self = (ACL_Object*) obj;
160 acl_type_t type = ACL_TYPE_ACCESS;
164 if (!PyArg_ParseTuple(args, "O|i", &myarg, &type))
167 if(PyString_Check(myarg)) {
168 char *filename = PyString_AS_STRING(myarg);
169 nret = acl_set_file(filename, type, self->acl);
170 } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) {
171 nret = acl_set_fd(fd, self->acl);
173 PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int, or file-like object");
177 return PyErr_SetFromErrno(PyExc_IOError);
180 /* Return the result */
185 static char __valid_doc__[] = \
186 "Test the ACL for validity.\n" \
188 "This method tests the ACL to see if it is a valid ACL\n" \
189 "in terms of the filesystem. More precisely, it checks:\n" \
190 "A valid ACL contains exactly one entry with each of the ACL_USER_OBJ,\n" \
191 "ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and\n" \
192 "ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that\n" \
193 "contains entries of ACL_USER or ACL_GROUP tag types must contain exactly\n" \
194 "one entry of the ACL_MASK tag type. If an ACL contains no entries of\n" \
195 "ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.\n" \
197 "All user ID qualifiers must be unique among all entries of ACL_USER tag\n" \
198 "type, and all group IDs must be unique among all entries of ACL_GROUP tag\n" \
201 "The method will return 1 for a valid ACL and 0 for an invalid one.\n" \
202 "This has been chosen because the specification for acl_valid in POSIX.1e\n" \
203 "documents only one possible value for errno in case of an invalid ACL, \n" \
204 "so we can't differentiate between classes of errors. Other suggestions \n" \
208 /* Checks the ACL for validity */
209 static PyObject* ACL_valid(PyObject* obj, PyObject* args) {
210 ACL_Object *self = (ACL_Object*) obj;
212 if(acl_valid(self->acl) == -1) {
223 static PyObject* ACL_get_state(PyObject *obj, PyObject* args) {
224 ACL_Object *self = (ACL_Object*) obj;
229 size = acl_size(self->acl);
231 return PyErr_SetFromErrno(PyExc_IOError);
233 if((ret = PyString_FromStringAndSize(NULL, size)) == NULL)
235 buf = PyString_AsString(ret);
237 if((nsize = acl_copy_ext(buf, self->acl, size)) == -1) {
239 return PyErr_SetFromErrno(PyExc_IOError);
245 static PyObject* ACL_set_state(PyObject *obj, PyObject* args) {
246 ACL_Object *self = (ACL_Object*) obj;
251 /* Parse the argument */
252 if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize))
255 /* Try to import the external representation */
256 if((ptr = acl_copy_int(buf)) == NULL)
257 return PyErr_SetFromErrno(PyExc_IOError);
259 /* Free the old acl. Should we ignore errors here? */
260 if(self->acl != NULL) {
261 if(acl_free(self->acl) == -1)
262 return PyErr_SetFromErrno(PyExc_IOError);
267 /* Return the result */
272 /* tp_iter for the ACL type; since it can be iterated only
273 * destructively, the type is its iterator
275 static PyObject* ACL_iter(PyObject *obj) {
276 ACL_Object *self = (ACL_Object*)obj;
277 self->entry_id = ACL_FIRST_ENTRY;
282 /* the tp_iternext function for the ACL type */
283 static PyObject* ACL_iternext(PyObject *obj) {
284 ACL_Object *self = (ACL_Object*)obj;
285 acl_entry_t the_entry_t;
286 Entry_Object *the_entry_obj;
289 nerr = acl_get_entry(self->acl, self->entry_id, &the_entry_t);
290 self->entry_id = ACL_NEXT_ENTRY;
292 return PyErr_SetFromErrno(PyExc_IOError);
294 /* Docs says this is not needed */
295 /*PyErr_SetObject(PyExc_StopIteration, Py_None);*/
299 the_entry_obj = (Entry_Object*) PyType_GenericNew(&Entry_Type, NULL, NULL);
300 if(the_entry_obj == NULL)
303 the_entry_obj->entry = the_entry_t;
305 the_entry_obj->parent_acl = obj;
306 Py_INCREF(obj); /* For the reference we have in entry->parent */
308 return (PyObject*)the_entry_obj;
311 static char __ACL_delete_entry_doc__[] = \
312 "Deletes an entry from the ACL.\n" \
314 "Note: Only with level 2\n" \
316 " - the Entry object which should be deleted; note that after\n" \
317 " this function is called, that object is unusable any longer\n" \
318 " and should be deleted\n" \
321 /* Deletes an entry from the ACL */
322 static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) {
323 ACL_Object *self = (ACL_Object*)obj;
326 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &e))
329 if(acl_delete_entry(self->acl, e->entry) == -1)
330 return PyErr_SetFromErrno(PyExc_IOError);
332 /* Return the result */
337 static char __ACL_calc_mask_doc__[] = \
338 "Compute the file group class mask.\n" \
340 "The calc_mask() method calculates and sets the permissions \n" \
341 "associated with the ACL_MASK Entry of the ACL.\n" \
342 "The value of the new permissions is the union of the permissions \n" \
343 "granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or \n" \
344 "ACL_USER. If the ACL already contains an ACL_MASK entry, its \n" \
345 "permissions are overwritten; if it does not contain an ACL_MASK \n" \
346 "Entry, one is added.\n" \
348 "The order of existing entries in the ACL is undefined after this \n" \
352 /* Updates the mask entry in the ACL */
353 static PyObject* ACL_calc_mask(PyObject *obj, PyObject *args) {
354 ACL_Object *self = (ACL_Object*)obj;
356 if(acl_calc_mask(&self->acl) == -1)
357 return PyErr_SetFromErrno(PyExc_IOError);
359 /* Return the result */
364 static char __ACL_append_doc__[] = \
365 "Append a new Entry to the ACL and return it.\n" \
367 "This is a convenience function to create a new Entry \n" \
368 "and append it to the ACL.\n" \
369 "If a parameter of type Entry instance is given, the \n" \
370 "entry will be a copy of that one (as if copied with \n" \
371 "Entry.copy()), otherwise, the new entry will be empty.\n" \
374 /* Convenience method to create a new Entry */
375 static PyObject* ACL_append(PyObject *obj, PyObject *args) {
376 ACL_Object* self = (ACL_Object*) obj;
377 Entry_Object* newentry;
378 Entry_Object* oldentry = NULL;
381 newentry = (Entry_Object*)PyType_GenericNew(&Entry_Type, NULL, NULL);
382 if(newentry == NULL) {
386 if (!PyArg_ParseTuple(args, "|O!", &Entry_Type, &oldentry))
389 nret = acl_create_entry(&self->acl, &newentry->entry);
392 return PyErr_SetFromErrno(PyExc_IOError);
395 if(oldentry != NULL) {
396 nret = acl_copy_entry(newentry->entry, oldentry->entry);
399 return PyErr_SetFromErrno(PyExc_IOError);
403 newentry->parent_acl = obj;
406 return (PyObject*)newentry;
409 /***** Entry type *****/
411 /* Creation of a new Entry instance */
412 static PyObject* Entry_new(PyTypeObject* type, PyObject* args, PyObject *keywds) {
415 newentry = PyType_GenericNew(type, args, keywds);
417 if(newentry != NULL) {
418 ((Entry_Object*)newentry)->entry = NULL;
419 ((Entry_Object*)newentry)->parent_acl = NULL;
425 /* Initialization of a new Entry instance */
426 static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) {
427 Entry_Object* self = (Entry_Object*) obj;
428 ACL_Object* parent = NULL;
430 if (!PyArg_ParseTuple(args, "O!", &ACL_Type, &parent))
433 if(acl_create_entry(&parent->acl, &self->entry) == -1) {
434 PyErr_SetFromErrno(PyExc_IOError);
438 self->parent_acl = (PyObject*)parent;
444 /* Free the Entry instance */
445 static void Entry_dealloc(PyObject* obj) {
446 Entry_Object *self = (Entry_Object*) obj;
447 PyObject *err_type, *err_value, *err_traceback;
448 int have_error = PyErr_Occurred() ? 1 : 0;
451 PyErr_Fetch(&err_type, &err_value, &err_traceback);
452 if(self->parent_acl != NULL) {
453 Py_DECREF(self->parent_acl);
454 self->parent_acl = NULL;
457 PyErr_Restore(err_type, err_value, err_traceback);
461 /* Converts the entry to a text format */
462 static PyObject* Entry_str(PyObject *obj) {
467 PyObject *format, *list;
468 Entry_Object *self = (Entry_Object*) obj;
470 if(acl_get_tag_type(self->entry, &tag) == -1) {
471 PyErr_SetFromErrno(PyExc_IOError);
474 if(tag == ACL_USER || tag == ACL_GROUP) {
475 if((p = acl_get_qualifier(self->entry)) == NULL) {
476 PyErr_SetFromErrno(PyExc_IOError);
479 qualifier = *(uid_t*)p;
485 format = PyString_FromString("ACL entry for %s");
488 list = PyTuple_New(1);
489 if(tag == ACL_UNDEFINED_TAG) {
490 PyTuple_SetItem(list, 0, PyString_FromString("undefined type"));
491 } else if(tag == ACL_USER_OBJ) {
492 PyTuple_SetItem(list, 0, PyString_FromString("the owner"));
493 } else if(tag == ACL_GROUP_OBJ) {
494 PyTuple_SetItem(list, 0, PyString_FromString("the group"));
495 } else if(tag == ACL_OTHER) {
496 PyTuple_SetItem(list, 0, PyString_FromString("the others"));
497 } else if(tag == ACL_USER) {
498 PyTuple_SetItem(list, 0, PyString_FromFormat("user with uid %d", qualifier));
499 } else if(tag == ACL_GROUP) {
500 PyTuple_SetItem(list, 0, PyString_FromFormat("group with gid %d", qualifier));
501 } else if(tag == ACL_MASK) {
502 PyTuple_SetItem(list, 0, PyString_FromString("the mask"));
504 PyTuple_SetItem(list, 0, PyString_FromString("UNKNOWN_TAG_TYPE!"));
506 ret = PyString_Format(format, list);
512 /* Sets the tag type of the entry */
513 static int Entry_set_tag_type(PyObject* obj, PyObject* value, void* arg) {
514 Entry_Object *self = (Entry_Object*) obj;
517 PyErr_SetString(PyExc_TypeError,
518 "tag type deletion is not supported");
522 if(!PyInt_Check(value)) {
523 PyErr_SetString(PyExc_TypeError,
524 "tag type must be integer");
527 if(acl_set_tag_type(self->entry, (acl_tag_t)PyInt_AsLong(value)) == -1) {
528 PyErr_SetFromErrno(PyExc_IOError);
535 /* Returns the tag type of the entry */
536 static PyObject* Entry_get_tag_type(PyObject *obj, void* arg) {
537 Entry_Object *self = (Entry_Object*) obj;
540 if (self->entry == NULL) {
541 PyErr_SetString(PyExc_AttributeError, "entry attribute");
544 if(acl_get_tag_type(self->entry, &value) == -1) {
545 PyErr_SetFromErrno(PyExc_IOError);
549 return PyInt_FromLong(value);
552 /* Sets the qualifier (either uid_t or gid_t) for the entry,
553 * usable only if the tag type if ACL_USER or ACL_GROUP
555 static int Entry_set_qualifier(PyObject* obj, PyObject* value, void* arg) {
556 Entry_Object *self = (Entry_Object*) obj;
560 PyErr_SetString(PyExc_TypeError,
561 "qualifier deletion is not supported");
565 if(!PyInt_Check(value)) {
566 PyErr_SetString(PyExc_TypeError,
567 "tag type must be integer");
570 uidgid = PyInt_AsLong(value);
571 if(acl_set_qualifier(self->entry, (void*)&uidgid) == -1) {
572 PyErr_SetFromErrno(PyExc_IOError);
579 /* Returns the qualifier of the entry */
580 static PyObject* Entry_get_qualifier(PyObject *obj, void* arg) {
581 Entry_Object *self = (Entry_Object*) obj;
585 if (self->entry == NULL) {
586 PyErr_SetString(PyExc_AttributeError, "entry attribute");
589 if((p = acl_get_qualifier(self->entry)) == NULL) {
590 PyErr_SetFromErrno(PyExc_IOError);
596 return PyInt_FromLong(value);
599 /* Returns the parent ACL of the entry */
600 static PyObject* Entry_get_parent(PyObject *obj, void* arg) {
601 Entry_Object *self = (Entry_Object*) obj;
603 Py_INCREF(self->parent_acl);
604 return self->parent_acl;
607 /* Returns the a new Permset representing the permset of the entry
608 * FIXME: Should return a new reference to the same object, which
609 * should be created at init time!
611 static PyObject* Entry_get_permset(PyObject *obj, void* arg) {
612 Entry_Object *self = (Entry_Object*)obj;
616 p = Permset_new(&Permset_Type, NULL, NULL);
619 ps = (Permset_Object*)p;
620 if(acl_get_permset(self->entry, &ps->permset) == -1) {
621 PyErr_SetFromErrno(PyExc_IOError);
624 ps->parent_entry = obj;
630 /* Sets the permset of the entry to the passed Permset */
631 static int Entry_set_permset(PyObject* obj, PyObject* value, void* arg) {
632 Entry_Object *self = (Entry_Object*)obj;
635 if(!PyObject_IsInstance(value, (PyObject*)&Permset_Type)) {
636 PyErr_SetString(PyExc_TypeError, "argument 1 must be posix1e.Permset");
639 p = (Permset_Object*)value;
640 if(acl_set_permset(self->entry, p->permset) == -1) {
641 PyErr_SetFromErrno(PyExc_IOError);
647 static char __Entry_copy_doc__[] = \
648 "Copy an ACL entry.\n" \
650 "This method sets all the parameters to those of another\n" \
651 "entry, even one of another's ACL\n" \
653 " - src, instance of type Entry\n" \
656 /* Sets all the entry parameters to another's entry */
657 static PyObject* Entry_copy(PyObject *obj, PyObject *args) {
658 Entry_Object *self = (Entry_Object*)obj;
661 if(!PyArg_ParseTuple(args, "O!", &Entry_Type, &other))
664 if(acl_copy_entry(self->entry, other->entry) == -1)
665 return PyErr_SetFromErrno(PyExc_IOError);
671 /**** Permset type *****/
673 /* Creation of a new Permset instance */
674 static PyObject* Permset_new(PyTypeObject* type, PyObject* args, PyObject *keywds) {
675 PyObject* newpermset;
677 newpermset = PyType_GenericNew(type, args, keywds);
679 if(newpermset != NULL) {
680 ((Permset_Object*)newpermset)->permset = NULL;
681 ((Permset_Object*)newpermset)->parent_entry = NULL;
687 /* Initialization of a new Permset instance */
688 static int Permset_init(PyObject* obj, PyObject* args, PyObject *keywds) {
689 Permset_Object* self = (Permset_Object*) obj;
690 Entry_Object* parent = NULL;
692 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &parent))
695 if(acl_get_permset(parent->entry, &self->permset) == -1) {
696 PyErr_SetFromErrno(PyExc_IOError);
700 self->parent_entry = (PyObject*)parent;
706 /* Free the Permset instance */
707 static void Permset_dealloc(PyObject* obj) {
708 Permset_Object *self = (Permset_Object*) obj;
709 PyObject *err_type, *err_value, *err_traceback;
710 int have_error = PyErr_Occurred() ? 1 : 0;
713 PyErr_Fetch(&err_type, &err_value, &err_traceback);
714 if(self->parent_entry != NULL) {
715 Py_DECREF(self->parent_entry);
716 self->parent_entry = NULL;
719 PyErr_Restore(err_type, err_value, err_traceback);
723 /* Permset string representation */
724 static PyObject* Permset_str(PyObject *obj) {
725 Permset_Object *self = (Permset_Object*) obj;
728 pstr[0] = get_perm(self->permset, ACL_READ) ? 'r' : '-';
729 pstr[1] = get_perm(self->permset, ACL_WRITE) ? 'w' : '-';
730 pstr[2] = get_perm(self->permset, ACL_EXECUTE) ? 'x' : '-';
731 return PyString_FromStringAndSize(pstr, 3);
734 static char __Permset_clear_doc__[] = \
735 "Clear all permissions from the permission set.\n" \
738 /* Clears all permissions from the permset */
739 static PyObject* Permset_clear(PyObject* obj, PyObject* args) {
740 Permset_Object *self = (Permset_Object*) obj;
742 if(acl_clear_perms(self->permset) == -1)
743 return PyErr_SetFromErrno(PyExc_IOError);
745 /* Return the result */
750 static PyObject* Permset_get_right(PyObject *obj, void* arg) {
751 Permset_Object *self = (Permset_Object*) obj;
753 if(get_perm(self->permset, *(acl_perm_t*)arg)) {
762 static int Permset_set_right(PyObject* obj, PyObject* value, void* arg) {
763 Permset_Object *self = (Permset_Object*) obj;
767 if(!PyInt_Check(value)) {
768 PyErr_SetString(PyExc_ValueError, "a maximum of one argument must be passed");
771 on = PyInt_AsLong(value);
773 nerr = acl_add_perm(self->permset, *(acl_perm_t*)arg);
775 nerr = acl_delete_perm(self->permset, *(acl_perm_t*)arg);
777 PyErr_SetFromErrno(PyExc_IOError);
783 static char __Permset_add_doc__[] = \
784 "Add a permission to the permission set.\n" \
786 "The add() function adds the permission contained in \n" \
787 "the argument perm to the permission set. An attempt \n" \
788 "to add a permission that is already contained in the \n" \
789 "permission set is not considered an error.\n" \
791 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
794 "Can raise: IOError\n" \
797 static PyObject* Permset_add(PyObject* obj, PyObject* args) {
798 Permset_Object *self = (Permset_Object*) obj;
801 if (!PyArg_ParseTuple(args, "i", &right))
804 if(acl_add_perm(self->permset, (acl_perm_t) right) == -1)
805 return PyErr_SetFromErrno(PyExc_IOError);
807 /* Return the result */
812 static char __Permset_delete_doc__[] = \
813 "Delete a permission from the permission set.\n" \
815 "The delete() function deletes the permission contained in \n" \
816 "the argument perm from the permission set. An attempt \n" \
817 "to delete a permission that is not contained in the \n" \
818 "permission set is not considered an error.\n" \
820 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
823 "Can raise: IOError\n" \
826 static PyObject* Permset_delete(PyObject* obj, PyObject* args) {
827 Permset_Object *self = (Permset_Object*) obj;
830 if (!PyArg_ParseTuple(args, "i", &right))
833 if(acl_delete_perm(self->permset, (acl_perm_t) right) == -1)
834 return PyErr_SetFromErrno(PyExc_IOError);
836 /* Return the result */
841 static char __Permset_test_doc__[] = \
842 "Test if a permission exists in the permission set.\n" \
844 "The test() function tests if the permission contained in \n" \
845 "the argument perm exits the permission set.\n" \
847 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
850 "Can raise: IOError\n" \
853 static PyObject* Permset_test(PyObject* obj, PyObject* args) {
854 Permset_Object *self = (Permset_Object*) obj;
858 if (!PyArg_ParseTuple(args, "i", &right))
861 ret = get_perm(self->permset, (acl_perm_t) right);
863 return PyErr_SetFromErrno(PyExc_IOError);
876 static char __ACL_Type_doc__[] = \
877 "Type which represents a POSIX ACL\n" \
880 " Only one keword parameter should be provided:\n"
881 " - file=\"...\", meaning create ACL representing\n"
882 " the access ACL of that file\n" \
883 " - filedef=\"...\", meaning create ACL representing\n"
884 " the default ACL of that directory\n" \
885 " - fd=<int>, meaning create ACL representing\n" \
886 " the access ACL of that file descriptor\n" \
887 " - text=\"...\", meaning create ACL from a \n" \
888 " textual description\n" \
889 " - acl=<ACL instance>, meaning create a copy\n" \
890 " of an existing ACL instance\n" \
891 "If no parameters are passed, create an empty ACL; this\n" \
892 "makes sense only when your OS supports ACL modification\n" \
893 " (i.e. it implements full POSIX.1e support)\n" \
896 /* ACL type methods */
897 static PyMethodDef ACL_methods[] = {
898 {"applyto", ACL_applyto, METH_VARARGS, __applyto_doc__},
899 {"valid", ACL_valid, METH_NOARGS, __valid_doc__},
901 {"__getstate__", ACL_get_state, METH_NOARGS, "Dumps the ACL to an external format."},
902 {"__setstate__", ACL_set_state, METH_VARARGS, "Loads the ACL from an external format."},
903 {"delete_entry", ACL_delete_entry, METH_VARARGS, __ACL_delete_entry_doc__},
904 {"calc_mask", ACL_calc_mask, METH_NOARGS, __ACL_calc_mask_doc__},
905 {"append", ACL_append, METH_VARARGS, __ACL_append_doc__},
907 {NULL, NULL, 0, NULL}
911 /* The definition of the ACL Type */
912 static PyTypeObject ACL_Type = {
913 PyObject_HEAD_INIT(NULL)
918 ACL_dealloc, /* tp_dealloc */
924 0, /* tp_as_number */
925 0, /* tp_as_sequence */
926 0, /* tp_as_mapping */
929 ACL_str, /* tp_str */
932 0, /* tp_as_buffer */
933 Py_TPFLAGS_DEFAULT, /* tp_flags */
934 __ACL_Type_doc__, /* tp_doc */
937 0, /* tp_richcompare */
938 0, /* tp_weaklistoffset */
946 ACL_methods, /* tp_methods */
951 0, /* tp_descr_get */
952 0, /* tp_descr_set */
953 0, /* tp_dictoffset */
954 ACL_init, /* tp_init */
956 ACL_new, /* tp_new */
961 /* Entry type methods */
962 static PyMethodDef Entry_methods[] = {
963 {"copy", Entry_copy, METH_VARARGS, __Entry_copy_doc__},
964 {NULL, NULL, 0, NULL}
967 static char __Entry_tagtype_doc__[] = \
968 "The tag type of the current entry\n" \
970 "This is one of:\n" \
971 " - ACL_UNDEFINED_TAG\n" \
972 " - ACL_USER_OBJ\n" \
974 " - ACL_GROUP_OBJ\n" \
980 static char __Entry_qualifier_doc__[] = \
981 "The qualifier of the current entry\n" \
983 "If the tag type is ACL_USER, this should be a user id.\n" \
984 "If the tag type if ACL_GROUP, this should be a group id.\n" \
985 "Else, it doesn't matter.\n" \
988 static char __Entry_parent_doc__[] = \
989 "The parent ACL of this entry\n" \
992 static char __Entry_permset_doc__[] = \
993 "The permission set of this ACL entry\n" \
997 static PyGetSetDef Entry_getsets[] = {
998 {"tag_type", Entry_get_tag_type, Entry_set_tag_type, __Entry_tagtype_doc__},
999 {"qualifier", Entry_get_qualifier, Entry_set_qualifier, __Entry_qualifier_doc__},
1000 {"parent", Entry_get_parent, NULL, __Entry_parent_doc__},
1001 {"permset", Entry_get_permset, Entry_set_permset, __Entry_permset_doc__},
1005 static char __Entry_Type_doc__[] = \
1006 "Type which represents an entry in an ACL.\n" \
1008 "The type exists only if the OS has full support for POSIX.1e\n" \
1009 "Can be created either by:\n" \
1010 " e = posix1e.Entry(myACL) # this creates a new entry in the ACL\n" \
1012 " for entry in myACL:\n" \
1015 "Note that the Entry keeps a reference to its ACL, so even if \n" \
1016 "you delete the ACL, it won't be cleaned up and will continue to \n" \
1017 "exist until its Entry(ies) will be deleted.\n" \
1019 /* The definition of the Entry Type */
1020 static PyTypeObject Entry_Type = {
1021 PyObject_HEAD_INIT(NULL)
1024 sizeof(Entry_Object),
1026 Entry_dealloc, /* tp_dealloc */
1032 0, /* tp_as_number */
1033 0, /* tp_as_sequence */
1034 0, /* tp_as_mapping */
1037 Entry_str, /* tp_str */
1038 0, /* tp_getattro */
1039 0, /* tp_setattro */
1040 0, /* tp_as_buffer */
1041 Py_TPFLAGS_DEFAULT, /* tp_flags */
1042 __Entry_Type_doc__, /* tp_doc */
1043 0, /* tp_traverse */
1045 0, /* tp_richcompare */
1046 0, /* tp_weaklistoffset */
1048 0, /* tp_iternext */
1049 Entry_methods, /* tp_methods */
1051 Entry_getsets, /* tp_getset */
1054 0, /* tp_descr_get */
1055 0, /* tp_descr_set */
1056 0, /* tp_dictoffset */
1057 Entry_init, /* tp_init */
1059 Entry_new, /* tp_new */
1062 /* Permset type methods */
1063 static PyMethodDef Permset_methods[] = {
1064 {"clear", Permset_clear, METH_NOARGS, __Permset_clear_doc__, },
1065 {"add", Permset_add, METH_VARARGS, __Permset_add_doc__, },
1066 {"delete", Permset_delete, METH_VARARGS, __Permset_delete_doc__, },
1067 {"test", Permset_test, METH_VARARGS, __Permset_test_doc__, },
1068 {NULL, NULL, 0, NULL}
1071 static char __Permset_execute_doc__[] = \
1072 "Execute permsission\n" \
1074 "This is a convenience method of access; the \n" \
1075 "same effect can be achieved using the functions\n" \
1076 "add(), test(), delete(), and those can take any \n" \
1077 "permission defined by your platform.\n" \
1080 static char __Permset_read_doc__[] = \
1081 "Read permsission\n" \
1083 "This is a convenience method of access; the \n" \
1084 "same effect can be achieved using the functions\n" \
1085 "add(), test(), delete(), and those can take any \n" \
1086 "permission defined by your platform.\n" \
1089 static char __Permset_write_doc__[] = \
1090 "Write permsission\n" \
1092 "This is a convenience method of access; the \n" \
1093 "same effect can be achieved using the functions\n" \
1094 "add(), test(), delete(), and those can take any \n" \
1095 "permission defined by your platform.\n" \
1098 /* Permset getset */
1099 static PyGetSetDef Permset_getsets[] = {
1100 {"execute", Permset_get_right, Permset_set_right, \
1101 __Permset_execute_doc__, &holder_ACL_EXECUTE},
1102 {"read", Permset_get_right, Permset_set_right, \
1103 __Permset_read_doc__, &holder_ACL_READ},
1104 {"write", Permset_get_right, Permset_set_right, \
1105 __Permset_write_doc__, &holder_ACL_WRITE},
1109 static char __Permset_Type_doc__[] = \
1110 "Type which represents the permission set in an ACL entry\n" \
1112 "The type exists only if the OS has full support for POSIX.1e\n" \
1113 "Can be created either by:\n" \
1114 " perms = myEntry.permset\n" \
1116 " perms = posix1e.Permset(myEntry)\n" \
1118 "Note that the Permset keeps a reference to its Entry, so even if \n" \
1119 "you delete the entry, it won't be cleaned up and will continue to \n" \
1120 "exist until its Permset will be deleted.\n" \
1123 /* The definition of the Permset Type */
1124 static PyTypeObject Permset_Type = {
1125 PyObject_HEAD_INIT(NULL)
1128 sizeof(Permset_Object),
1130 Permset_dealloc, /* tp_dealloc */
1136 0, /* tp_as_number */
1137 0, /* tp_as_sequence */
1138 0, /* tp_as_mapping */
1141 Permset_str, /* tp_str */
1142 0, /* tp_getattro */
1143 0, /* tp_setattro */
1144 0, /* tp_as_buffer */
1145 Py_TPFLAGS_DEFAULT, /* tp_flags */
1146 __Permset_Type_doc__,/* tp_doc */
1147 0, /* tp_traverse */
1149 0, /* tp_richcompare */
1150 0, /* tp_weaklistoffset */
1152 0, /* tp_iternext */
1153 Permset_methods, /* tp_methods */
1155 Permset_getsets, /* tp_getset */
1158 0, /* tp_descr_get */
1159 0, /* tp_descr_set */
1160 0, /* tp_dictoffset */
1161 Permset_init, /* tp_init */
1163 Permset_new, /* tp_new */
1168 /* Module methods */
1170 static char __deletedef_doc__[] = \
1171 "Delete the default ACL from a directory.\n" \
1173 "This function deletes the default ACL associated with \n" \
1174 "a directory (the ACL which will be ANDed with the mode\n" \
1175 "parameter to the open, creat functions).\n" \
1177 " - a string representing the directory whose default ACL\n" \
1178 " should be deleted\n" \
1181 /* Deletes the default ACL from a directory */
1182 static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) {
1185 /* Parse the arguments */
1186 if (!PyArg_ParseTuple(args, "s", &filename))
1189 if(acl_delete_def_file(filename) == -1) {
1190 return PyErr_SetFromErrno(PyExc_IOError);
1193 /* Return the result */
1198 /* The module methods */
1199 static PyMethodDef aclmodule_methods[] = {
1200 {"delete_default", aclmodule_delete_default, METH_VARARGS, __deletedef_doc__},
1201 {NULL, NULL, 0, NULL}
1204 static char __posix1e_doc__[] = \
1205 "POSIX.1e ACLs manipulation\n" \
1207 "This module provides support for manipulating POSIX.1e ACLS\n" \
1209 "Depending on the operating system support for POSIX.1e, \n" \
1210 "the ACL type will have more or less capabilities:\n" \
1211 " - level 1, only basic support, you can create\n" \
1212 " ACLs from files and text descriptions;\n" \
1213 " once created, the type is immutable\n" \
1214 " - level 2, complete support, you can alter\n"\
1215 " the ACL once it is created\n" \
1217 "Also, in level 2, more types are available, corresponding\n" \
1218 "to acl_entry_t (Entry type), acl_permset_t (Permset type).\n" \
1221 ">>> import posix1e\n" \
1222 ">>> acl1 = posix1e.ACL(file=\"file.txt\") \n" \
1223 ">>> print acl1\n" \
1228 ">>> b = posix1e.ACL(text=\"u::rx,g::-,o::-\")\n" \
1234 ">>> b.applyto(\"file.txt\")\n" \
1235 ">>> print posix1e.ACL(file=\"file.txt\")\n" \
1243 void initposix1e(void) {
1246 ACL_Type.ob_type = &PyType_Type;
1247 if(PyType_Ready(&ACL_Type) < 0)
1251 Entry_Type.ob_type = &PyType_Type;
1252 if(PyType_Ready(&Entry_Type) < 0)
1255 Permset_Type.ob_type = &PyType_Type;
1256 if(PyType_Ready(&Permset_Type) < 0)
1260 m = Py_InitModule3("posix1e", aclmodule_methods, __posix1e_doc__);
1262 d = PyModule_GetDict(m);
1266 Py_INCREF(&ACL_Type);
1267 if (PyDict_SetItemString(d, "ACL",
1268 (PyObject *) &ACL_Type) < 0)
1271 /* 23.3.6 acl_type_t values */
1272 PyModule_AddIntConstant(m, "ACL_TYPE_ACCESS", ACL_TYPE_ACCESS);
1273 PyModule_AddIntConstant(m, "ACL_TYPE_DEFAULT", ACL_TYPE_DEFAULT);
1277 Py_INCREF(&Entry_Type);
1278 if (PyDict_SetItemString(d, "Entry",
1279 (PyObject *) &Entry_Type) < 0)
1282 Py_INCREF(&Permset_Type);
1283 if (PyDict_SetItemString(d, "Permset",
1284 (PyObject *) &Permset_Type) < 0)
1287 /* 23.2.2 acl_perm_t values */
1288 PyModule_AddIntConstant(m, "ACL_READ", ACL_READ);
1289 PyModule_AddIntConstant(m, "ACL_WRITE", ACL_WRITE);
1290 PyModule_AddIntConstant(m, "ACL_EXECUTE", ACL_EXECUTE);
1292 /* 23.2.5 acl_tag_t values */
1293 PyModule_AddIntConstant(m, "ACL_UNDEFINED_TAG", ACL_UNDEFINED_TAG);
1294 PyModule_AddIntConstant(m, "ACL_USER_OBJ", ACL_USER_OBJ);
1295 PyModule_AddIntConstant(m, "ACL_USER", ACL_USER);
1296 PyModule_AddIntConstant(m, "ACL_GROUP_OBJ", ACL_GROUP_OBJ);
1297 PyModule_AddIntConstant(m, "ACL_GROUP", ACL_GROUP);
1298 PyModule_AddIntConstant(m, "ACL_MASK", ACL_MASK);
1299 PyModule_AddIntConstant(m, "ACL_OTHER", ACL_OTHER);