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,
24 static acl_perm_t holder_ACL_EXECUTE = ACL_EXECUTE;
25 static acl_perm_t holder_ACL_READ = ACL_READ;
26 static acl_perm_t holder_ACL_WRITE = ACL_WRITE;
40 PyObject *parent_acl; /* The parent acl, so it won't run out on us */
46 PyObject *parent_entry; /* The parent entry, so it won't run out on us */
47 acl_permset_t permset;
52 /* Creation of a new ACL instance */
53 static PyObject* ACL_new(PyTypeObject* type, PyObject* args,
57 newacl = type->tp_alloc(type, 0);
60 ((ACL_Object*)newacl)->acl = NULL;
62 ((ACL_Object*)newacl)->entry_id = ACL_FIRST_ENTRY;
69 /* Initialization of a new ACL instance */
70 static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) {
71 ACL_Object* self = (ACL_Object*) obj;
73 static char *kwlist[] = { "file", "fd", "text", "acl", "filedef",
75 char *format = "|sisO!sH";
78 static char *kwlist[] = { "file", "fd", "text", "acl", "filedef", NULL };
79 char *format = "|sisO!s";
85 ACL_Object* thesrc = NULL;
87 if(!PyTuple_Check(args) || PyTuple_Size(args) != 0 ||
88 (keywds != NULL && PyDict_Check(keywds) && PyDict_Size(keywds) > 1)) {
89 PyErr_SetString(PyExc_ValueError, "a max of one keyword argument"
93 if(!PyArg_ParseTupleAndKeywords(args, keywds, format, kwlist,
94 &file, &fd, &text, &ACL_Type,
102 /* Free the old acl_t without checking for error, we don't
104 if(self->acl != NULL)
108 self->acl = acl_get_file(file, ACL_TYPE_ACCESS);
109 else if(text != NULL)
110 self->acl = acl_from_text(text);
112 self->acl = acl_get_fd(fd);
113 else if(thesrc != NULL)
114 self->acl = acl_dup(thesrc->acl);
115 else if(filedef != NULL)
116 self->acl = acl_get_file(filedef, ACL_TYPE_DEFAULT);
118 else if(PyMapping_HasKeyString(keywds, kwlist[5]))
119 self->acl = acl_from_mode(mode);
122 self->acl = acl_init(0);
124 if(self->acl == NULL) {
125 PyErr_SetFromErrno(PyExc_IOError);
132 /* Standard type functions */
133 static void ACL_dealloc(PyObject* obj) {
134 ACL_Object *self = (ACL_Object*) obj;
135 PyObject *err_type, *err_value, *err_traceback;
136 int have_error = PyErr_Occurred() ? 1 : 0;
139 PyErr_Fetch(&err_type, &err_value, &err_traceback);
140 if(self->acl != NULL && acl_free(self->acl) != 0)
141 PyErr_WriteUnraisable(obj);
143 PyErr_Restore(err_type, err_value, err_traceback);
147 /* Converts the acl to a text format */
148 static PyObject* ACL_str(PyObject *obj) {
150 ACL_Object *self = (ACL_Object*) obj;
153 text = acl_to_text(self->acl, NULL);
155 return PyErr_SetFromErrno(PyExc_IOError);
157 ret = PyString_FromString(text);
158 if(acl_free(text) != 0) {
160 return PyErr_SetFromErrno(PyExc_IOError);
166 static char __to_any_text_doc__[] =
167 "Convert the ACL to a custom text format.\n"
169 "This method encapsulates the acl_to_any_text function. It allows a \n"
170 "customized text format to be generated for the ACL. See\n"
171 "acl_to_any_text(3) for more details.\n"
174 " - prefix: if given, this string will be prepended to all lines\n"
175 " - separator: a single character (defaults to '\\n'); this will be\n"
176 " user to separate the entries in the ACL\n"
177 " - options: a bitwise combination of:\n"
178 " TEXT_ABBREVIATE: use 'u' instead of 'user', 'g' instead of \n"
180 " TEXT_NUMERIC_IDS: User and group IDs are included as decimal\n"
181 " numbers instead of names\n"
182 " TEXT_SOME_EFFECTIVE: Include comments denoting the effective\n"
183 " permissions when some are masked\n"
184 " TEXT_ALL_EFFECTIVE: Include comments after all ACL entries\n"
185 " affected by an ACL_MASK entry\n"
186 " TEXT_SMART_INDENT: Used in combination with the _EFFECTIVE\n"
187 " options, this will ensure that comments \n"
188 " are alligned to the fourth tab position\n"
189 " (assuming one tab equal eight spaces\n"
192 /* Converts the acl to a custom text format */
193 static PyObject* ACL_to_any_text(PyObject *obj, PyObject *args,
196 ACL_Object *self = (ACL_Object*) obj;
198 char *arg_prefix = NULL;
199 char arg_separator = '\n';
201 static char *kwlist[] = {"prefix", "separator", "options", NULL};
203 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sci", kwlist, &arg_prefix,
204 &arg_separator, &arg_options))
207 text = acl_to_any_text(self->acl, arg_prefix, arg_separator, arg_options);
209 return PyErr_SetFromErrno(PyExc_IOError);
211 ret = PyString_FromString(text);
212 if(acl_free(text) != 0) {
214 return PyErr_SetFromErrno(PyExc_IOError);
222 static char __applyto_doc__[] =
223 "Apply the ACL to a file or filehandle.\n"
226 " - either a filename or a file-like object or an integer; this\n"
227 " represents the filesystem object on which to act\n"
228 " - optional flag representing the type of ACL to set, either\n"
229 " ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT\n"
232 /* Applyes the ACL to a file */
233 static PyObject* ACL_applyto(PyObject* obj, PyObject* args) {
234 ACL_Object *self = (ACL_Object*) obj;
236 acl_type_t type = ACL_TYPE_ACCESS;
240 if (!PyArg_ParseTuple(args, "O|i", &myarg, &type))
243 if(PyString_Check(myarg)) {
244 char *filename = PyString_AS_STRING(myarg);
245 nret = acl_set_file(filename, type, self->acl);
246 } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) {
247 nret = acl_set_fd(fd, self->acl);
249 PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int,"
250 " or file-like object");
254 return PyErr_SetFromErrno(PyExc_IOError);
257 /* Return the result */
262 static char __valid_doc__[] =
263 "Test the ACL for validity.\n"
265 "This method tests the ACL to see if it is a valid ACL\n"
266 "in terms of the filesystem. More precisely, it checks that:\n"
268 "The ACL contains exactly one entry with each of the\n"
269 "ACL_USER_OBJ, ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries\n"
270 "with ACL_USER and ACL_GROUP tag types may appear zero or more\n"
271 "times in an ACL. An ACL that contains entries of ACL_USER or\n"
272 "ACL_GROUP tag types must contain exactly one entry of the \n"
273 "ACL_MASK tag type. If an ACL contains no entries of\n"
274 "ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.\n"
276 "All user ID qualifiers must be unique among all entries of\n"
277 "the ACL_USER tag type, and all group IDs must be unique among all\n"
278 "entries of ACL_GROUP tag type.\n"
280 "The method will return 1 for a valid ACL and 0 for an invalid one.\n"
281 "This has been chosen because the specification for acl_valid in\n"
282 "the POSIX.1e standard documents only one possible value for errno\n"
283 "in case of an invalid ACL, so we can't differentiate between\n"
284 "classes of errors. Other suggestions are welcome.\n"
287 /* Checks the ACL for validity */
288 static PyObject* ACL_valid(PyObject* obj, PyObject* args) {
289 ACL_Object *self = (ACL_Object*) obj;
291 if(acl_valid(self->acl) == -1) {
302 static PyObject* ACL_get_state(PyObject *obj, PyObject* args) {
303 ACL_Object *self = (ACL_Object*) obj;
308 size = acl_size(self->acl);
310 return PyErr_SetFromErrno(PyExc_IOError);
312 if((ret = PyString_FromStringAndSize(NULL, size)) == NULL)
314 buf = PyString_AsString(ret);
316 if((nsize = acl_copy_ext(buf, self->acl, size)) == -1) {
318 return PyErr_SetFromErrno(PyExc_IOError);
324 static PyObject* ACL_set_state(PyObject *obj, PyObject* args) {
325 ACL_Object *self = (ACL_Object*) obj;
330 /* Parse the argument */
331 if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize))
334 /* Try to import the external representation */
335 if((ptr = acl_copy_int(buf)) == NULL)
336 return PyErr_SetFromErrno(PyExc_IOError);
338 /* Free the old acl. Should we ignore errors here? */
339 if(self->acl != NULL) {
340 if(acl_free(self->acl) == -1)
341 return PyErr_SetFromErrno(PyExc_IOError);
346 /* Return the result */
351 /* tp_iter for the ACL type; since it can be iterated only
352 * destructively, the type is its iterator
354 static PyObject* ACL_iter(PyObject *obj) {
355 ACL_Object *self = (ACL_Object*)obj;
356 self->entry_id = ACL_FIRST_ENTRY;
361 /* the tp_iternext function for the ACL type */
362 static PyObject* ACL_iternext(PyObject *obj) {
363 ACL_Object *self = (ACL_Object*)obj;
364 acl_entry_t the_entry_t;
365 Entry_Object *the_entry_obj;
368 nerr = acl_get_entry(self->acl, self->entry_id, &the_entry_t);
369 self->entry_id = ACL_NEXT_ENTRY;
371 return PyErr_SetFromErrno(PyExc_IOError);
373 /* Docs says this is not needed */
374 /*PyErr_SetObject(PyExc_StopIteration, Py_None);*/
378 the_entry_obj = (Entry_Object*) PyType_GenericNew(&Entry_Type, NULL, NULL);
379 if(the_entry_obj == NULL)
382 the_entry_obj->entry = the_entry_t;
384 the_entry_obj->parent_acl = obj;
385 Py_INCREF(obj); /* For the reference we have in entry->parent */
387 return (PyObject*)the_entry_obj;
390 static char __ACL_delete_entry_doc__[] =
391 "Deletes an entry from the ACL.\n"
393 "Note: Only with level 2\n"
395 " - the Entry object which should be deleted; note that after\n"
396 " this function is called, that object is unusable any longer\n"
397 " and should be deleted\n"
400 /* Deletes an entry from the ACL */
401 static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) {
402 ACL_Object *self = (ACL_Object*)obj;
405 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &e))
408 if(acl_delete_entry(self->acl, e->entry) == -1)
409 return PyErr_SetFromErrno(PyExc_IOError);
411 /* Return the result */
416 static char __ACL_calc_mask_doc__[] =
417 "Compute the file group class mask.\n"
419 "The calc_mask() method calculates and sets the permissions \n"
420 "associated with the ACL_MASK Entry of the ACL.\n"
421 "The value of the new permissions is the union of the permissions \n"
422 "granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or \n"
423 "ACL_USER. If the ACL already contains an ACL_MASK entry, its \n"
424 "permissions are overwritten; if it does not contain an ACL_MASK \n"
425 "Entry, one is added.\n"
427 "The order of existing entries in the ACL is undefined after this \n"
431 /* Updates the mask entry in the ACL */
432 static PyObject* ACL_calc_mask(PyObject *obj, PyObject *args) {
433 ACL_Object *self = (ACL_Object*)obj;
435 if(acl_calc_mask(&self->acl) == -1)
436 return PyErr_SetFromErrno(PyExc_IOError);
438 /* Return the result */
443 static char __ACL_append_doc__[] =
444 "Append a new Entry to the ACL and return it.\n"
446 "This is a convenience function to create a new Entry \n"
447 "and append it to the ACL.\n"
448 "If a parameter of type Entry instance is given, the \n"
449 "entry will be a copy of that one (as if copied with \n"
450 "Entry.copy()), otherwise, the new entry will be empty.\n"
453 /* Convenience method to create a new Entry */
454 static PyObject* ACL_append(PyObject *obj, PyObject *args) {
455 ACL_Object* self = (ACL_Object*) obj;
456 Entry_Object* newentry;
457 Entry_Object* oldentry = NULL;
460 newentry = (Entry_Object*)PyType_GenericNew(&Entry_Type, NULL, NULL);
461 if(newentry == NULL) {
465 if (!PyArg_ParseTuple(args, "|O!", &Entry_Type, &oldentry))
468 nret = acl_create_entry(&self->acl, &newentry->entry);
471 return PyErr_SetFromErrno(PyExc_IOError);
474 if(oldentry != NULL) {
475 nret = acl_copy_entry(newentry->entry, oldentry->entry);
478 return PyErr_SetFromErrno(PyExc_IOError);
482 newentry->parent_acl = obj;
485 return (PyObject*)newentry;
488 /***** Entry type *****/
490 /* Creation of a new Entry instance */
491 static PyObject* Entry_new(PyTypeObject* type, PyObject* args,
495 newentry = PyType_GenericNew(type, args, keywds);
497 if(newentry != NULL) {
498 ((Entry_Object*)newentry)->entry = NULL;
499 ((Entry_Object*)newentry)->parent_acl = NULL;
505 /* Initialization of a new Entry instance */
506 static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) {
507 Entry_Object* self = (Entry_Object*) obj;
508 ACL_Object* parent = NULL;
510 if (!PyArg_ParseTuple(args, "O!", &ACL_Type, &parent))
513 if(acl_create_entry(&parent->acl, &self->entry) == -1) {
514 PyErr_SetFromErrno(PyExc_IOError);
518 self->parent_acl = (PyObject*)parent;
524 /* Free the Entry instance */
525 static void Entry_dealloc(PyObject* obj) {
526 Entry_Object *self = (Entry_Object*) obj;
527 PyObject *err_type, *err_value, *err_traceback;
528 int have_error = PyErr_Occurred() ? 1 : 0;
531 PyErr_Fetch(&err_type, &err_value, &err_traceback);
532 if(self->parent_acl != NULL) {
533 Py_DECREF(self->parent_acl);
534 self->parent_acl = NULL;
537 PyErr_Restore(err_type, err_value, err_traceback);
541 /* Converts the entry to a text format */
542 static PyObject* Entry_str(PyObject *obj) {
547 PyObject *format, *list;
548 Entry_Object *self = (Entry_Object*) obj;
550 if(acl_get_tag_type(self->entry, &tag) == -1) {
551 PyErr_SetFromErrno(PyExc_IOError);
554 if(tag == ACL_USER || tag == ACL_GROUP) {
555 if((p = acl_get_qualifier(self->entry)) == NULL) {
556 PyErr_SetFromErrno(PyExc_IOError);
559 qualifier = *(uid_t*)p;
565 format = PyString_FromString("ACL entry for %s");
568 list = PyTuple_New(1);
569 if(tag == ACL_UNDEFINED_TAG) {
570 PyTuple_SetItem(list, 0, PyString_FromString("undefined type"));
571 } else if(tag == ACL_USER_OBJ) {
572 PyTuple_SetItem(list, 0, PyString_FromString("the owner"));
573 } else if(tag == ACL_GROUP_OBJ) {
574 PyTuple_SetItem(list, 0, PyString_FromString("the group"));
575 } else if(tag == ACL_OTHER) {
576 PyTuple_SetItem(list, 0, PyString_FromString("the others"));
577 } else if(tag == ACL_USER) {
578 PyTuple_SetItem(list, 0, PyString_FromFormat("user with uid %d",
580 } else if(tag == ACL_GROUP) {
581 PyTuple_SetItem(list, 0, PyString_FromFormat("group with gid %d",
583 } else if(tag == ACL_MASK) {
584 PyTuple_SetItem(list, 0, PyString_FromString("the mask"));
586 PyTuple_SetItem(list, 0, PyString_FromString("UNKNOWN_TAG_TYPE!"));
588 ret = PyString_Format(format, list);
594 /* Sets the tag type of the entry */
595 static int Entry_set_tag_type(PyObject* obj, PyObject* value, void* arg) {
596 Entry_Object *self = (Entry_Object*) obj;
599 PyErr_SetString(PyExc_TypeError,
600 "tag type deletion is not supported");
604 if(!PyInt_Check(value)) {
605 PyErr_SetString(PyExc_TypeError,
606 "tag type must be integer");
609 if(acl_set_tag_type(self->entry, (acl_tag_t)PyInt_AsLong(value)) == -1) {
610 PyErr_SetFromErrno(PyExc_IOError);
617 /* Returns the tag type of the entry */
618 static PyObject* Entry_get_tag_type(PyObject *obj, void* arg) {
619 Entry_Object *self = (Entry_Object*) obj;
622 if (self->entry == NULL) {
623 PyErr_SetString(PyExc_AttributeError, "entry attribute");
626 if(acl_get_tag_type(self->entry, &value) == -1) {
627 PyErr_SetFromErrno(PyExc_IOError);
631 return PyInt_FromLong(value);
634 /* Sets the qualifier (either uid_t or gid_t) for the entry,
635 * usable only if the tag type if ACL_USER or ACL_GROUP
637 static int Entry_set_qualifier(PyObject* obj, PyObject* value, void* arg) {
638 Entry_Object *self = (Entry_Object*) obj;
642 PyErr_SetString(PyExc_TypeError,
643 "qualifier deletion is not supported");
647 if(!PyInt_Check(value)) {
648 PyErr_SetString(PyExc_TypeError,
649 "tag type must be integer");
652 uidgid = PyInt_AsLong(value);
653 if(acl_set_qualifier(self->entry, (void*)&uidgid) == -1) {
654 PyErr_SetFromErrno(PyExc_IOError);
661 /* Returns the qualifier of the entry */
662 static PyObject* Entry_get_qualifier(PyObject *obj, void* arg) {
663 Entry_Object *self = (Entry_Object*) obj;
667 if (self->entry == NULL) {
668 PyErr_SetString(PyExc_AttributeError, "entry attribute");
671 if((p = acl_get_qualifier(self->entry)) == NULL) {
672 PyErr_SetFromErrno(PyExc_IOError);
678 return PyInt_FromLong(value);
681 /* Returns the parent ACL of the entry */
682 static PyObject* Entry_get_parent(PyObject *obj, void* arg) {
683 Entry_Object *self = (Entry_Object*) obj;
685 Py_INCREF(self->parent_acl);
686 return self->parent_acl;
689 /* Returns the a new Permset representing the permset of the entry
690 * FIXME: Should return a new reference to the same object, which
691 * should be created at init time!
693 static PyObject* Entry_get_permset(PyObject *obj, void* arg) {
694 Entry_Object *self = (Entry_Object*)obj;
698 p = Permset_new(&Permset_Type, NULL, NULL);
701 ps = (Permset_Object*)p;
702 if(acl_get_permset(self->entry, &ps->permset) == -1) {
703 PyErr_SetFromErrno(PyExc_IOError);
706 ps->parent_entry = obj;
712 /* Sets the permset of the entry to the passed Permset */
713 static int Entry_set_permset(PyObject* obj, PyObject* value, void* arg) {
714 Entry_Object *self = (Entry_Object*)obj;
717 if(!PyObject_IsInstance(value, (PyObject*)&Permset_Type)) {
718 PyErr_SetString(PyExc_TypeError, "argument 1 must be posix1e.Permset");
721 p = (Permset_Object*)value;
722 if(acl_set_permset(self->entry, p->permset) == -1) {
723 PyErr_SetFromErrno(PyExc_IOError);
729 static char __Entry_copy_doc__[] =
730 "Copy an ACL entry.\n"
732 "This method sets all the parameters to those of another\n"
733 "entry, even one of another's ACL\n"
735 " - src, instance of type Entry\n"
738 /* Sets all the entry parameters to another's entry */
739 static PyObject* Entry_copy(PyObject *obj, PyObject *args) {
740 Entry_Object *self = (Entry_Object*)obj;
743 if(!PyArg_ParseTuple(args, "O!", &Entry_Type, &other))
746 if(acl_copy_entry(self->entry, other->entry) == -1)
747 return PyErr_SetFromErrno(PyExc_IOError);
753 /**** Permset type *****/
755 /* Creation of a new Permset instance */
756 static PyObject* Permset_new(PyTypeObject* type, PyObject* args,
758 PyObject* newpermset;
760 newpermset = PyType_GenericNew(type, args, keywds);
762 if(newpermset != NULL) {
763 ((Permset_Object*)newpermset)->permset = NULL;
764 ((Permset_Object*)newpermset)->parent_entry = NULL;
770 /* Initialization of a new Permset instance */
771 static int Permset_init(PyObject* obj, PyObject* args, PyObject *keywds) {
772 Permset_Object* self = (Permset_Object*) obj;
773 Entry_Object* parent = NULL;
775 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &parent))
778 if(acl_get_permset(parent->entry, &self->permset) == -1) {
779 PyErr_SetFromErrno(PyExc_IOError);
783 self->parent_entry = (PyObject*)parent;
789 /* Free the Permset instance */
790 static void Permset_dealloc(PyObject* obj) {
791 Permset_Object *self = (Permset_Object*) obj;
792 PyObject *err_type, *err_value, *err_traceback;
793 int have_error = PyErr_Occurred() ? 1 : 0;
796 PyErr_Fetch(&err_type, &err_value, &err_traceback);
797 if(self->parent_entry != NULL) {
798 Py_DECREF(self->parent_entry);
799 self->parent_entry = NULL;
802 PyErr_Restore(err_type, err_value, err_traceback);
806 /* Permset string representation */
807 static PyObject* Permset_str(PyObject *obj) {
808 Permset_Object *self = (Permset_Object*) obj;
811 pstr[0] = get_perm(self->permset, ACL_READ) ? 'r' : '-';
812 pstr[1] = get_perm(self->permset, ACL_WRITE) ? 'w' : '-';
813 pstr[2] = get_perm(self->permset, ACL_EXECUTE) ? 'x' : '-';
814 return PyString_FromStringAndSize(pstr, 3);
817 static char __Permset_clear_doc__[] =
818 "Clear all permissions from the permission set.\n"
821 /* Clears all permissions from the permset */
822 static PyObject* Permset_clear(PyObject* obj, PyObject* args) {
823 Permset_Object *self = (Permset_Object*) obj;
825 if(acl_clear_perms(self->permset) == -1)
826 return PyErr_SetFromErrno(PyExc_IOError);
828 /* Return the result */
833 static PyObject* Permset_get_right(PyObject *obj, void* arg) {
834 Permset_Object *self = (Permset_Object*) obj;
836 if(get_perm(self->permset, *(acl_perm_t*)arg)) {
845 static int Permset_set_right(PyObject* obj, PyObject* value, void* arg) {
846 Permset_Object *self = (Permset_Object*) obj;
850 if(!PyInt_Check(value)) {
851 PyErr_SetString(PyExc_ValueError, "a maximum of one argument must"
855 on = PyInt_AsLong(value);
857 nerr = acl_add_perm(self->permset, *(acl_perm_t*)arg);
859 nerr = acl_delete_perm(self->permset, *(acl_perm_t*)arg);
861 PyErr_SetFromErrno(PyExc_IOError);
867 static char __Permset_add_doc__[] =
868 "Add a permission to the permission set.\n"
870 "The add() function adds the permission contained in \n"
871 "the argument perm to the permission set. An attempt \n"
872 "to add a permission that is already contained in the \n"
873 "permission set is not considered an error.\n"
875 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n"
878 "Can raise: IOError\n"
881 static PyObject* Permset_add(PyObject* obj, PyObject* args) {
882 Permset_Object *self = (Permset_Object*) obj;
885 if (!PyArg_ParseTuple(args, "i", &right))
888 if(acl_add_perm(self->permset, (acl_perm_t) right) == -1)
889 return PyErr_SetFromErrno(PyExc_IOError);
891 /* Return the result */
896 static char __Permset_delete_doc__[] =
897 "Delete a permission from the permission set.\n"
899 "The delete() function deletes the permission contained in \n"
900 "the argument perm from the permission set. An attempt \n"
901 "to delete a permission that is not contained in the \n"
902 "permission set is not considered an error.\n"
904 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n"
907 "Can raise: IOError\n"
910 static PyObject* Permset_delete(PyObject* obj, PyObject* args) {
911 Permset_Object *self = (Permset_Object*) obj;
914 if (!PyArg_ParseTuple(args, "i", &right))
917 if(acl_delete_perm(self->permset, (acl_perm_t) right) == -1)
918 return PyErr_SetFromErrno(PyExc_IOError);
920 /* Return the result */
925 static char __Permset_test_doc__[] =
926 "Test if a permission exists in the permission set.\n"
928 "The test() function tests if the permission contained in \n"
929 "the argument perm exits the permission set.\n"
931 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n"
934 "Can raise: IOError\n"
937 static PyObject* Permset_test(PyObject* obj, PyObject* args) {
938 Permset_Object *self = (Permset_Object*) obj;
942 if (!PyArg_ParseTuple(args, "i", &right))
945 ret = get_perm(self->permset, (acl_perm_t) right);
947 return PyErr_SetFromErrno(PyExc_IOError);
960 static char __ACL_Type_doc__[] =
961 "Type which represents a POSIX ACL\n"
964 " Only one keword parameter should be provided:\n"
965 " - file=\"...\", meaning create ACL representing\n"
966 " the access ACL of that file\n"
967 " - filedef=\"...\", meaning create ACL representing\n"
968 " the default ACL of that directory\n"
969 " - fd=<int>, meaning create ACL representing\n"
970 " the access ACL of that file descriptor\n"
971 " - text=\"...\", meaning create ACL from a \n"
972 " textual description\n"
973 " - acl=<ACL instance>, meaning create a copy\n"
974 " of an existing ACL instance\n"
975 " - mode=<int>, meaning create an ACL from a numeric mode\n"
976 " (e.g. mode=0644) (this is valid only when the C library\n"
977 " provides the acl_from_mode call)\n"
978 "If no parameters are passed, create an empty ACL; this\n"
979 "makes sense only when your OS supports ACL modification\n"
980 " (i.e. it implements full POSIX.1e support)\n"
983 /* ACL type methods */
984 static PyMethodDef ACL_methods[] = {
985 {"applyto", ACL_applyto, METH_VARARGS, __applyto_doc__},
986 {"valid", ACL_valid, METH_NOARGS, __valid_doc__},
988 {"to_any_text", (PyCFunction)ACL_to_any_text, METH_VARARGS | METH_KEYWORDS,
989 __to_any_text_doc__},
992 {"__getstate__", ACL_get_state, METH_NOARGS,
993 "Dumps the ACL to an external format."},
994 {"__setstate__", ACL_set_state, METH_VARARGS,
995 "Loads the ACL from an external format."},
996 {"delete_entry", ACL_delete_entry, METH_VARARGS, __ACL_delete_entry_doc__},
997 {"calc_mask", ACL_calc_mask, METH_NOARGS, __ACL_calc_mask_doc__},
998 {"append", ACL_append, METH_VARARGS, __ACL_append_doc__},
1000 {NULL, NULL, 0, NULL}
1004 /* The definition of the ACL Type */
1005 static PyTypeObject ACL_Type = {
1006 PyObject_HEAD_INIT(NULL)
1011 ACL_dealloc, /* tp_dealloc */
1017 0, /* tp_as_number */
1018 0, /* tp_as_sequence */
1019 0, /* tp_as_mapping */
1022 ACL_str, /* tp_str */
1023 0, /* tp_getattro */
1024 0, /* tp_setattro */
1025 0, /* tp_as_buffer */
1026 Py_TPFLAGS_DEFAULT, /* tp_flags */
1027 __ACL_Type_doc__, /* tp_doc */
1028 0, /* tp_traverse */
1030 0, /* tp_richcompare */
1031 0, /* tp_weaklistoffset */
1037 0, /* tp_iternext */
1039 ACL_methods, /* tp_methods */
1044 0, /* tp_descr_get */
1045 0, /* tp_descr_set */
1046 0, /* tp_dictoffset */
1047 ACL_init, /* tp_init */
1049 ACL_new, /* tp_new */
1054 /* Entry type methods */
1055 static PyMethodDef Entry_methods[] = {
1056 {"copy", Entry_copy, METH_VARARGS, __Entry_copy_doc__},
1057 {NULL, NULL, 0, NULL}
1060 static char __Entry_tagtype_doc__[] =
1061 "The tag type of the current entry\n"
1064 " - ACL_UNDEFINED_TAG\n"
1067 " - ACL_GROUP_OBJ\n"
1073 static char __Entry_qualifier_doc__[] =
1074 "The qualifier of the current entry\n"
1076 "If the tag type is ACL_USER, this should be a user id.\n"
1077 "If the tag type if ACL_GROUP, this should be a group id.\n"
1078 "Else, it doesn't matter.\n"
1081 static char __Entry_parent_doc__[] =
1082 "The parent ACL of this entry\n"
1085 static char __Entry_permset_doc__[] =
1086 "The permission set of this ACL entry\n"
1090 static PyGetSetDef Entry_getsets[] = {
1091 {"tag_type", Entry_get_tag_type, Entry_set_tag_type,
1092 __Entry_tagtype_doc__},
1093 {"qualifier", Entry_get_qualifier, Entry_set_qualifier,
1094 __Entry_qualifier_doc__},
1095 {"parent", Entry_get_parent, NULL, __Entry_parent_doc__},
1096 {"permset", Entry_get_permset, Entry_set_permset, __Entry_permset_doc__},
1100 static char __Entry_Type_doc__[] =
1101 "Type which represents an entry in an ACL.\n"
1103 "The type exists only if the OS has full support for POSIX.1e\n"
1104 "Can be created either by:\n"
1105 " e = posix1e.Entry(myACL) # this creates a new entry in the ACL\n"
1107 " for entry in myACL:\n"
1110 "Note that the Entry keeps a reference to its ACL, so even if \n"
1111 "you delete the ACL, it won't be cleaned up and will continue to \n"
1112 "exist until its Entry(ies) will be deleted.\n"
1114 /* The definition of the Entry Type */
1115 static PyTypeObject Entry_Type = {
1116 PyObject_HEAD_INIT(NULL)
1119 sizeof(Entry_Object),
1121 Entry_dealloc, /* tp_dealloc */
1127 0, /* tp_as_number */
1128 0, /* tp_as_sequence */
1129 0, /* tp_as_mapping */
1132 Entry_str, /* tp_str */
1133 0, /* tp_getattro */
1134 0, /* tp_setattro */
1135 0, /* tp_as_buffer */
1136 Py_TPFLAGS_DEFAULT, /* tp_flags */
1137 __Entry_Type_doc__, /* tp_doc */
1138 0, /* tp_traverse */
1140 0, /* tp_richcompare */
1141 0, /* tp_weaklistoffset */
1143 0, /* tp_iternext */
1144 Entry_methods, /* tp_methods */
1146 Entry_getsets, /* tp_getset */
1149 0, /* tp_descr_get */
1150 0, /* tp_descr_set */
1151 0, /* tp_dictoffset */
1152 Entry_init, /* tp_init */
1154 Entry_new, /* tp_new */
1157 /* Permset type methods */
1158 static PyMethodDef Permset_methods[] = {
1159 {"clear", Permset_clear, METH_NOARGS, __Permset_clear_doc__, },
1160 {"add", Permset_add, METH_VARARGS, __Permset_add_doc__, },
1161 {"delete", Permset_delete, METH_VARARGS, __Permset_delete_doc__, },
1162 {"test", Permset_test, METH_VARARGS, __Permset_test_doc__, },
1163 {NULL, NULL, 0, NULL}
1166 static char __Permset_execute_doc__[] =
1167 "Execute permsission\n"
1169 "This is a convenience method of access; the \n"
1170 "same effect can be achieved using the functions\n"
1171 "add(), test(), delete(), and those can take any \n"
1172 "permission defined by your platform.\n"
1175 static char __Permset_read_doc__[] =
1176 "Read permsission\n"
1178 "This is a convenience method of access; the \n"
1179 "same effect can be achieved using the functions\n"
1180 "add(), test(), delete(), and those can take any \n"
1181 "permission defined by your platform.\n"
1184 static char __Permset_write_doc__[] =
1185 "Write permsission\n"
1187 "This is a convenience method of access; the \n"
1188 "same effect can be achieved using the functions\n"
1189 "add(), test(), delete(), and those can take any \n"
1190 "permission defined by your platform.\n"
1193 /* Permset getset */
1194 static PyGetSetDef Permset_getsets[] = {
1195 {"execute", Permset_get_right, Permset_set_right,
1196 __Permset_execute_doc__, &holder_ACL_EXECUTE},
1197 {"read", Permset_get_right, Permset_set_right,
1198 __Permset_read_doc__, &holder_ACL_READ},
1199 {"write", Permset_get_right, Permset_set_right,
1200 __Permset_write_doc__, &holder_ACL_WRITE},
1204 static char __Permset_Type_doc__[] =
1205 "Type which represents the permission set in an ACL entry\n"
1207 "The type exists only if the OS has full support for POSIX.1e\n"
1208 "Can be created either by:\n"
1209 " perms = myEntry.permset\n"
1211 " perms = posix1e.Permset(myEntry)\n"
1213 "Note that the Permset keeps a reference to its Entry, so even if \n"
1214 "you delete the entry, it won't be cleaned up and will continue to \n"
1215 "exist until its Permset will be deleted.\n"
1218 /* The definition of the Permset Type */
1219 static PyTypeObject Permset_Type = {
1220 PyObject_HEAD_INIT(NULL)
1223 sizeof(Permset_Object),
1225 Permset_dealloc, /* tp_dealloc */
1231 0, /* tp_as_number */
1232 0, /* tp_as_sequence */
1233 0, /* tp_as_mapping */
1236 Permset_str, /* tp_str */
1237 0, /* tp_getattro */
1238 0, /* tp_setattro */
1239 0, /* tp_as_buffer */
1240 Py_TPFLAGS_DEFAULT, /* tp_flags */
1241 __Permset_Type_doc__,/* tp_doc */
1242 0, /* tp_traverse */
1244 0, /* tp_richcompare */
1245 0, /* tp_weaklistoffset */
1247 0, /* tp_iternext */
1248 Permset_methods, /* tp_methods */
1250 Permset_getsets, /* tp_getset */
1253 0, /* tp_descr_get */
1254 0, /* tp_descr_set */
1255 0, /* tp_dictoffset */
1256 Permset_init, /* tp_init */
1258 Permset_new, /* tp_new */
1263 /* Module methods */
1265 static char __deletedef_doc__[] =
1266 "Delete the default ACL from a directory.\n"
1268 "This function deletes the default ACL associated with \n"
1269 "a directory (the ACL which will be ANDed with the mode\n"
1270 "parameter to the open, creat functions).\n"
1272 " - a string representing the directory whose default ACL\n"
1273 " should be deleted\n"
1276 /* Deletes the default ACL from a directory */
1277 static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) {
1280 /* Parse the arguments */
1281 if (!PyArg_ParseTuple(args, "s", &filename))
1284 if(acl_delete_def_file(filename) == -1) {
1285 return PyErr_SetFromErrno(PyExc_IOError);
1288 /* Return the result */
1293 /* The module methods */
1294 static PyMethodDef aclmodule_methods[] = {
1295 {"delete_default", aclmodule_delete_default, METH_VARARGS,
1297 {NULL, NULL, 0, NULL}
1300 static char __posix1e_doc__[] =
1301 "POSIX.1e ACLs manipulation\n"
1303 "This module provides support for manipulating POSIX.1e ACLS\n"
1305 "Depending on the operating system support for POSIX.1e, \n"
1306 "the ACL type will have more or less capabilities:\n"
1307 " - level 1, only basic support, you can create\n"
1308 " ACLs from files and text descriptions;\n"
1309 " once created, the type is immutable\n"
1310 " - level 2, complete support, you can alter\n"
1311 " the ACL once it is created\n"
1313 "Also, in level 2, more types are available, corresponding\n"
1314 "to acl_entry_t (Entry type), acl_permset_t (Permset type).\n"
1317 ">>> import posix1e\n"
1318 ">>> acl1 = posix1e.ACL(file=\"file.txt\") \n"
1324 ">>> b = posix1e.ACL(text=\"u::rx,g::-,o::-\")\n"
1330 ">>> b.applyto(\"file.txt\")\n"
1331 ">>> print posix1e.ACL(file=\"file.txt\")\n"
1339 void initposix1e(void) {
1342 ACL_Type.ob_type = &PyType_Type;
1343 if(PyType_Ready(&ACL_Type) < 0)
1347 Entry_Type.ob_type = &PyType_Type;
1348 if(PyType_Ready(&Entry_Type) < 0)
1351 Permset_Type.ob_type = &PyType_Type;
1352 if(PyType_Ready(&Permset_Type) < 0)
1356 m = Py_InitModule3("posix1e", aclmodule_methods, __posix1e_doc__);
1358 d = PyModule_GetDict(m);
1362 Py_INCREF(&ACL_Type);
1363 if (PyDict_SetItemString(d, "ACL",
1364 (PyObject *) &ACL_Type) < 0)
1367 /* 23.3.6 acl_type_t values */
1368 PyModule_AddIntConstant(m, "ACL_TYPE_ACCESS", ACL_TYPE_ACCESS);
1369 PyModule_AddIntConstant(m, "ACL_TYPE_DEFAULT", ACL_TYPE_DEFAULT);
1373 Py_INCREF(&Entry_Type);
1374 if (PyDict_SetItemString(d, "Entry",
1375 (PyObject *) &Entry_Type) < 0)
1378 Py_INCREF(&Permset_Type);
1379 if (PyDict_SetItemString(d, "Permset",
1380 (PyObject *) &Permset_Type) < 0)
1383 /* 23.2.2 acl_perm_t values */
1384 PyModule_AddIntConstant(m, "ACL_READ", ACL_READ);
1385 PyModule_AddIntConstant(m, "ACL_WRITE", ACL_WRITE);
1386 PyModule_AddIntConstant(m, "ACL_EXECUTE", ACL_EXECUTE);
1388 /* 23.2.5 acl_tag_t values */
1389 PyModule_AddIntConstant(m, "ACL_UNDEFINED_TAG", ACL_UNDEFINED_TAG);
1390 PyModule_AddIntConstant(m, "ACL_USER_OBJ", ACL_USER_OBJ);
1391 PyModule_AddIntConstant(m, "ACL_USER", ACL_USER);
1392 PyModule_AddIntConstant(m, "ACL_GROUP_OBJ", ACL_GROUP_OBJ);
1393 PyModule_AddIntConstant(m, "ACL_GROUP", ACL_GROUP);
1394 PyModule_AddIntConstant(m, "ACL_MASK", ACL_MASK);
1395 PyModule_AddIntConstant(m, "ACL_OTHER", ACL_OTHER);
1400 /* Linux libacl specific acl_to_any_text constants */
1401 PyModule_AddIntConstant(m, "TEXT_ABBREVIATE", TEXT_ABBREVIATE);
1402 PyModule_AddIntConstant(m, "TEXT_NUMERIC_IDS", TEXT_NUMERIC_IDS);
1403 PyModule_AddIntConstant(m, "TEXT_SOME_EFFECTIVE", TEXT_SOME_EFFECTIVE);
1404 PyModule_AddIntConstant(m, "TEXT_ALL_EFFECTIVE", TEXT_ALL_EFFECTIVE);
1405 PyModule_AddIntConstant(m, "TEXT_SMART_INDENT", TEXT_SMART_INDENT);
1407 /* Linux libacl specific acl_check constants */
1408 PyModule_AddIntConstant(m, "ACL_MULTI_ERROR", ACL_MULTI_ERROR);
1409 PyModule_AddIntConstant(m, "ACL_DUPLICATE_ERROR", ACL_DUPLICATE_ERROR);
1410 PyModule_AddIntConstant(m, "ACL_MISS_ERROR", ACL_MISS_ERROR);
1411 PyModule_AddIntConstant(m, "ACL_ENTRY_ERROR", ACL_ENTRY_ERROR);