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 const char *format = "|sisO!sH";
78 static char *kwlist[] = { "file", "fd", "text", "acl", "filedef", NULL };
79 const 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 __applyto_doc__[] = \
167 "Apply the ACL to a file or filehandle.\n" \
170 " - either a filename or a file-like object or an integer; this\n" \
171 " represents the filesystem object on which to act\n" \
172 " - optional flag representing the type of ACL to set, either\n" \
173 " ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT\n" \
176 /* Applyes the ACL to a file */
177 static PyObject* ACL_applyto(PyObject* obj, PyObject* args) {
178 ACL_Object *self = (ACL_Object*) obj;
180 acl_type_t type = ACL_TYPE_ACCESS;
184 if (!PyArg_ParseTuple(args, "O|i", &myarg, &type))
187 if(PyString_Check(myarg)) {
188 char *filename = PyString_AS_STRING(myarg);
189 nret = acl_set_file(filename, type, self->acl);
190 } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) {
191 nret = acl_set_fd(fd, self->acl);
193 PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int,"
194 " or file-like object");
198 return PyErr_SetFromErrno(PyExc_IOError);
201 /* Return the result */
206 static char __valid_doc__[] = \
207 "Test the ACL for validity.\n" \
209 "This method tests the ACL to see if it is a valid ACL\n" \
210 "in terms of the filesystem. More precisely, it checks:\n" \
211 "A valid ACL contains exactly one entry with each of the ACL_USER_OBJ,\n" \
212 "ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and\n" \
213 "ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that\n" \
214 "contains entries of ACL_USER or ACL_GROUP tag types must contain exactly\n" \
215 "one entry of the ACL_MASK tag type. If an ACL contains no entries of\n" \
216 "ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.\n" \
218 "All user ID qualifiers must be unique among all entries of ACL_USER tag\n" \
219 "type, and all group IDs must be unique among all entries of ACL_GROUP tag\n" \
222 "The method will return 1 for a valid ACL and 0 for an invalid one.\n" \
223 "This has been chosen because the specification for acl_valid in POSIX.1e\n" \
224 "documents only one possible value for errno in case of an invalid ACL, \n" \
225 "so we can't differentiate between classes of errors. Other suggestions \n" \
229 /* Checks the ACL for validity */
230 static PyObject* ACL_valid(PyObject* obj, PyObject* args) {
231 ACL_Object *self = (ACL_Object*) obj;
233 if(acl_valid(self->acl) == -1) {
244 static PyObject* ACL_get_state(PyObject *obj, PyObject* args) {
245 ACL_Object *self = (ACL_Object*) obj;
250 size = acl_size(self->acl);
252 return PyErr_SetFromErrno(PyExc_IOError);
254 if((ret = PyString_FromStringAndSize(NULL, size)) == NULL)
256 buf = PyString_AsString(ret);
258 if((nsize = acl_copy_ext(buf, self->acl, size)) == -1) {
260 return PyErr_SetFromErrno(PyExc_IOError);
266 static PyObject* ACL_set_state(PyObject *obj, PyObject* args) {
267 ACL_Object *self = (ACL_Object*) obj;
272 /* Parse the argument */
273 if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize))
276 /* Try to import the external representation */
277 if((ptr = acl_copy_int(buf)) == NULL)
278 return PyErr_SetFromErrno(PyExc_IOError);
280 /* Free the old acl. Should we ignore errors here? */
281 if(self->acl != NULL) {
282 if(acl_free(self->acl) == -1)
283 return PyErr_SetFromErrno(PyExc_IOError);
288 /* Return the result */
293 /* tp_iter for the ACL type; since it can be iterated only
294 * destructively, the type is its iterator
296 static PyObject* ACL_iter(PyObject *obj) {
297 ACL_Object *self = (ACL_Object*)obj;
298 self->entry_id = ACL_FIRST_ENTRY;
303 /* the tp_iternext function for the ACL type */
304 static PyObject* ACL_iternext(PyObject *obj) {
305 ACL_Object *self = (ACL_Object*)obj;
306 acl_entry_t the_entry_t;
307 Entry_Object *the_entry_obj;
310 nerr = acl_get_entry(self->acl, self->entry_id, &the_entry_t);
311 self->entry_id = ACL_NEXT_ENTRY;
313 return PyErr_SetFromErrno(PyExc_IOError);
315 /* Docs says this is not needed */
316 /*PyErr_SetObject(PyExc_StopIteration, Py_None);*/
320 the_entry_obj = (Entry_Object*) PyType_GenericNew(&Entry_Type, NULL, NULL);
321 if(the_entry_obj == NULL)
324 the_entry_obj->entry = the_entry_t;
326 the_entry_obj->parent_acl = obj;
327 Py_INCREF(obj); /* For the reference we have in entry->parent */
329 return (PyObject*)the_entry_obj;
332 static char __ACL_delete_entry_doc__[] = \
333 "Deletes an entry from the ACL.\n" \
335 "Note: Only with level 2\n" \
337 " - the Entry object which should be deleted; note that after\n" \
338 " this function is called, that object is unusable any longer\n" \
339 " and should be deleted\n" \
342 /* Deletes an entry from the ACL */
343 static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) {
344 ACL_Object *self = (ACL_Object*)obj;
347 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &e))
350 if(acl_delete_entry(self->acl, e->entry) == -1)
351 return PyErr_SetFromErrno(PyExc_IOError);
353 /* Return the result */
358 static char __ACL_calc_mask_doc__[] = \
359 "Compute the file group class mask.\n" \
361 "The calc_mask() method calculates and sets the permissions \n" \
362 "associated with the ACL_MASK Entry of the ACL.\n" \
363 "The value of the new permissions is the union of the permissions \n" \
364 "granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or \n" \
365 "ACL_USER. If the ACL already contains an ACL_MASK entry, its \n" \
366 "permissions are overwritten; if it does not contain an ACL_MASK \n" \
367 "Entry, one is added.\n" \
369 "The order of existing entries in the ACL is undefined after this \n" \
373 /* Updates the mask entry in the ACL */
374 static PyObject* ACL_calc_mask(PyObject *obj, PyObject *args) {
375 ACL_Object *self = (ACL_Object*)obj;
377 if(acl_calc_mask(&self->acl) == -1)
378 return PyErr_SetFromErrno(PyExc_IOError);
380 /* Return the result */
385 static char __ACL_append_doc__[] = \
386 "Append a new Entry to the ACL and return it.\n" \
388 "This is a convenience function to create a new Entry \n" \
389 "and append it to the ACL.\n" \
390 "If a parameter of type Entry instance is given, the \n" \
391 "entry will be a copy of that one (as if copied with \n" \
392 "Entry.copy()), otherwise, the new entry will be empty.\n" \
395 /* Convenience method to create a new Entry */
396 static PyObject* ACL_append(PyObject *obj, PyObject *args) {
397 ACL_Object* self = (ACL_Object*) obj;
398 Entry_Object* newentry;
399 Entry_Object* oldentry = NULL;
402 newentry = (Entry_Object*)PyType_GenericNew(&Entry_Type, NULL, NULL);
403 if(newentry == NULL) {
407 if (!PyArg_ParseTuple(args, "|O!", &Entry_Type, &oldentry))
410 nret = acl_create_entry(&self->acl, &newentry->entry);
413 return PyErr_SetFromErrno(PyExc_IOError);
416 if(oldentry != NULL) {
417 nret = acl_copy_entry(newentry->entry, oldentry->entry);
420 return PyErr_SetFromErrno(PyExc_IOError);
424 newentry->parent_acl = obj;
427 return (PyObject*)newentry;
430 /***** Entry type *****/
432 /* Creation of a new Entry instance */
433 static PyObject* Entry_new(PyTypeObject* type, PyObject* args,
437 newentry = PyType_GenericNew(type, args, keywds);
439 if(newentry != NULL) {
440 ((Entry_Object*)newentry)->entry = NULL;
441 ((Entry_Object*)newentry)->parent_acl = NULL;
447 /* Initialization of a new Entry instance */
448 static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) {
449 Entry_Object* self = (Entry_Object*) obj;
450 ACL_Object* parent = NULL;
452 if (!PyArg_ParseTuple(args, "O!", &ACL_Type, &parent))
455 if(acl_create_entry(&parent->acl, &self->entry) == -1) {
456 PyErr_SetFromErrno(PyExc_IOError);
460 self->parent_acl = (PyObject*)parent;
466 /* Free the Entry instance */
467 static void Entry_dealloc(PyObject* obj) {
468 Entry_Object *self = (Entry_Object*) obj;
469 PyObject *err_type, *err_value, *err_traceback;
470 int have_error = PyErr_Occurred() ? 1 : 0;
473 PyErr_Fetch(&err_type, &err_value, &err_traceback);
474 if(self->parent_acl != NULL) {
475 Py_DECREF(self->parent_acl);
476 self->parent_acl = NULL;
479 PyErr_Restore(err_type, err_value, err_traceback);
483 /* Converts the entry to a text format */
484 static PyObject* Entry_str(PyObject *obj) {
489 PyObject *format, *list;
490 Entry_Object *self = (Entry_Object*) obj;
492 if(acl_get_tag_type(self->entry, &tag) == -1) {
493 PyErr_SetFromErrno(PyExc_IOError);
496 if(tag == ACL_USER || tag == ACL_GROUP) {
497 if((p = acl_get_qualifier(self->entry)) == NULL) {
498 PyErr_SetFromErrno(PyExc_IOError);
501 qualifier = *(uid_t*)p;
507 format = PyString_FromString("ACL entry for %s");
510 list = PyTuple_New(1);
511 if(tag == ACL_UNDEFINED_TAG) {
512 PyTuple_SetItem(list, 0, PyString_FromString("undefined type"));
513 } else if(tag == ACL_USER_OBJ) {
514 PyTuple_SetItem(list, 0, PyString_FromString("the owner"));
515 } else if(tag == ACL_GROUP_OBJ) {
516 PyTuple_SetItem(list, 0, PyString_FromString("the group"));
517 } else if(tag == ACL_OTHER) {
518 PyTuple_SetItem(list, 0, PyString_FromString("the others"));
519 } else if(tag == ACL_USER) {
520 PyTuple_SetItem(list, 0, PyString_FromFormat("user with uid %d",
522 } else if(tag == ACL_GROUP) {
523 PyTuple_SetItem(list, 0, PyString_FromFormat("group with gid %d",
525 } else if(tag == ACL_MASK) {
526 PyTuple_SetItem(list, 0, PyString_FromString("the mask"));
528 PyTuple_SetItem(list, 0, PyString_FromString("UNKNOWN_TAG_TYPE!"));
530 ret = PyString_Format(format, list);
536 /* Sets the tag type of the entry */
537 static int Entry_set_tag_type(PyObject* obj, PyObject* value, void* arg) {
538 Entry_Object *self = (Entry_Object*) obj;
541 PyErr_SetString(PyExc_TypeError,
542 "tag type deletion is not supported");
546 if(!PyInt_Check(value)) {
547 PyErr_SetString(PyExc_TypeError,
548 "tag type must be integer");
551 if(acl_set_tag_type(self->entry, (acl_tag_t)PyInt_AsLong(value)) == -1) {
552 PyErr_SetFromErrno(PyExc_IOError);
559 /* Returns the tag type of the entry */
560 static PyObject* Entry_get_tag_type(PyObject *obj, void* arg) {
561 Entry_Object *self = (Entry_Object*) obj;
564 if (self->entry == NULL) {
565 PyErr_SetString(PyExc_AttributeError, "entry attribute");
568 if(acl_get_tag_type(self->entry, &value) == -1) {
569 PyErr_SetFromErrno(PyExc_IOError);
573 return PyInt_FromLong(value);
576 /* Sets the qualifier (either uid_t or gid_t) for the entry,
577 * usable only if the tag type if ACL_USER or ACL_GROUP
579 static int Entry_set_qualifier(PyObject* obj, PyObject* value, void* arg) {
580 Entry_Object *self = (Entry_Object*) obj;
584 PyErr_SetString(PyExc_TypeError,
585 "qualifier deletion is not supported");
589 if(!PyInt_Check(value)) {
590 PyErr_SetString(PyExc_TypeError,
591 "tag type must be integer");
594 uidgid = PyInt_AsLong(value);
595 if(acl_set_qualifier(self->entry, (void*)&uidgid) == -1) {
596 PyErr_SetFromErrno(PyExc_IOError);
603 /* Returns the qualifier of the entry */
604 static PyObject* Entry_get_qualifier(PyObject *obj, void* arg) {
605 Entry_Object *self = (Entry_Object*) obj;
609 if (self->entry == NULL) {
610 PyErr_SetString(PyExc_AttributeError, "entry attribute");
613 if((p = acl_get_qualifier(self->entry)) == NULL) {
614 PyErr_SetFromErrno(PyExc_IOError);
620 return PyInt_FromLong(value);
623 /* Returns the parent ACL of the entry */
624 static PyObject* Entry_get_parent(PyObject *obj, void* arg) {
625 Entry_Object *self = (Entry_Object*) obj;
627 Py_INCREF(self->parent_acl);
628 return self->parent_acl;
631 /* Returns the a new Permset representing the permset of the entry
632 * FIXME: Should return a new reference to the same object, which
633 * should be created at init time!
635 static PyObject* Entry_get_permset(PyObject *obj, void* arg) {
636 Entry_Object *self = (Entry_Object*)obj;
640 p = Permset_new(&Permset_Type, NULL, NULL);
643 ps = (Permset_Object*)p;
644 if(acl_get_permset(self->entry, &ps->permset) == -1) {
645 PyErr_SetFromErrno(PyExc_IOError);
648 ps->parent_entry = obj;
654 /* Sets the permset of the entry to the passed Permset */
655 static int Entry_set_permset(PyObject* obj, PyObject* value, void* arg) {
656 Entry_Object *self = (Entry_Object*)obj;
659 if(!PyObject_IsInstance(value, (PyObject*)&Permset_Type)) {
660 PyErr_SetString(PyExc_TypeError, "argument 1 must be posix1e.Permset");
663 p = (Permset_Object*)value;
664 if(acl_set_permset(self->entry, p->permset) == -1) {
665 PyErr_SetFromErrno(PyExc_IOError);
671 static char __Entry_copy_doc__[] = \
672 "Copy an ACL entry.\n" \
674 "This method sets all the parameters to those of another\n" \
675 "entry, even one of another's ACL\n" \
677 " - src, instance of type Entry\n" \
680 /* Sets all the entry parameters to another's entry */
681 static PyObject* Entry_copy(PyObject *obj, PyObject *args) {
682 Entry_Object *self = (Entry_Object*)obj;
685 if(!PyArg_ParseTuple(args, "O!", &Entry_Type, &other))
688 if(acl_copy_entry(self->entry, other->entry) == -1)
689 return PyErr_SetFromErrno(PyExc_IOError);
695 /**** Permset type *****/
697 /* Creation of a new Permset instance */
698 static PyObject* Permset_new(PyTypeObject* type, PyObject* args,
700 PyObject* newpermset;
702 newpermset = PyType_GenericNew(type, args, keywds);
704 if(newpermset != NULL) {
705 ((Permset_Object*)newpermset)->permset = NULL;
706 ((Permset_Object*)newpermset)->parent_entry = NULL;
712 /* Initialization of a new Permset instance */
713 static int Permset_init(PyObject* obj, PyObject* args, PyObject *keywds) {
714 Permset_Object* self = (Permset_Object*) obj;
715 Entry_Object* parent = NULL;
717 if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &parent))
720 if(acl_get_permset(parent->entry, &self->permset) == -1) {
721 PyErr_SetFromErrno(PyExc_IOError);
725 self->parent_entry = (PyObject*)parent;
731 /* Free the Permset instance */
732 static void Permset_dealloc(PyObject* obj) {
733 Permset_Object *self = (Permset_Object*) obj;
734 PyObject *err_type, *err_value, *err_traceback;
735 int have_error = PyErr_Occurred() ? 1 : 0;
738 PyErr_Fetch(&err_type, &err_value, &err_traceback);
739 if(self->parent_entry != NULL) {
740 Py_DECREF(self->parent_entry);
741 self->parent_entry = NULL;
744 PyErr_Restore(err_type, err_value, err_traceback);
748 /* Permset string representation */
749 static PyObject* Permset_str(PyObject *obj) {
750 Permset_Object *self = (Permset_Object*) obj;
753 pstr[0] = get_perm(self->permset, ACL_READ) ? 'r' : '-';
754 pstr[1] = get_perm(self->permset, ACL_WRITE) ? 'w' : '-';
755 pstr[2] = get_perm(self->permset, ACL_EXECUTE) ? 'x' : '-';
756 return PyString_FromStringAndSize(pstr, 3);
759 static char __Permset_clear_doc__[] = \
760 "Clear all permissions from the permission set.\n" \
763 /* Clears all permissions from the permset */
764 static PyObject* Permset_clear(PyObject* obj, PyObject* args) {
765 Permset_Object *self = (Permset_Object*) obj;
767 if(acl_clear_perms(self->permset) == -1)
768 return PyErr_SetFromErrno(PyExc_IOError);
770 /* Return the result */
775 static PyObject* Permset_get_right(PyObject *obj, void* arg) {
776 Permset_Object *self = (Permset_Object*) obj;
778 if(get_perm(self->permset, *(acl_perm_t*)arg)) {
787 static int Permset_set_right(PyObject* obj, PyObject* value, void* arg) {
788 Permset_Object *self = (Permset_Object*) obj;
792 if(!PyInt_Check(value)) {
793 PyErr_SetString(PyExc_ValueError, "a maximum of one argument must"
797 on = PyInt_AsLong(value);
799 nerr = acl_add_perm(self->permset, *(acl_perm_t*)arg);
801 nerr = acl_delete_perm(self->permset, *(acl_perm_t*)arg);
803 PyErr_SetFromErrno(PyExc_IOError);
809 static char __Permset_add_doc__[] = \
810 "Add a permission to the permission set.\n" \
812 "The add() function adds the permission contained in \n" \
813 "the argument perm to the permission set. An attempt \n" \
814 "to add a permission that is already contained in the \n" \
815 "permission set is not considered an error.\n" \
817 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
820 "Can raise: IOError\n" \
823 static PyObject* Permset_add(PyObject* obj, PyObject* args) {
824 Permset_Object *self = (Permset_Object*) obj;
827 if (!PyArg_ParseTuple(args, "i", &right))
830 if(acl_add_perm(self->permset, (acl_perm_t) right) == -1)
831 return PyErr_SetFromErrno(PyExc_IOError);
833 /* Return the result */
838 static char __Permset_delete_doc__[] = \
839 "Delete a permission from the permission set.\n" \
841 "The delete() function deletes the permission contained in \n" \
842 "the argument perm from the permission set. An attempt \n" \
843 "to delete a permission that is not contained in the \n" \
844 "permission set is not considered an error.\n" \
846 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
849 "Can raise: IOError\n" \
852 static PyObject* Permset_delete(PyObject* obj, PyObject* args) {
853 Permset_Object *self = (Permset_Object*) obj;
856 if (!PyArg_ParseTuple(args, "i", &right))
859 if(acl_delete_perm(self->permset, (acl_perm_t) right) == -1)
860 return PyErr_SetFromErrno(PyExc_IOError);
862 /* Return the result */
867 static char __Permset_test_doc__[] = \
868 "Test if a permission exists in the permission set.\n" \
870 "The test() function tests if the permission contained in \n" \
871 "the argument perm exits the permission set.\n" \
873 " - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \
876 "Can raise: IOError\n" \
879 static PyObject* Permset_test(PyObject* obj, PyObject* args) {
880 Permset_Object *self = (Permset_Object*) obj;
884 if (!PyArg_ParseTuple(args, "i", &right))
887 ret = get_perm(self->permset, (acl_perm_t) right);
889 return PyErr_SetFromErrno(PyExc_IOError);
902 static char __ACL_Type_doc__[] = \
903 "Type which represents a POSIX ACL\n" \
906 " Only one keword parameter should be provided:\n"
907 " - file=\"...\", meaning create ACL representing\n"
908 " the access ACL of that file\n" \
909 " - filedef=\"...\", meaning create ACL representing\n"
910 " the default ACL of that directory\n" \
911 " - fd=<int>, meaning create ACL representing\n" \
912 " the access ACL of that file descriptor\n" \
913 " - text=\"...\", meaning create ACL from a \n" \
914 " textual description\n" \
915 " - acl=<ACL instance>, meaning create a copy\n" \
916 " of an existing ACL instance\n" \
917 " - mode=<int>, meaning create an ACL from a numeric mode\n"
918 " (e.g. mode=0644) (this is valid only when the C library\n"
919 " provides the acl_from_mode call)\n"
920 "If no parameters are passed, create an empty ACL; this\n" \
921 "makes sense only when your OS supports ACL modification\n" \
922 " (i.e. it implements full POSIX.1e support)\n" \
925 /* ACL type methods */
926 static PyMethodDef ACL_methods[] = {
927 {"applyto", ACL_applyto, METH_VARARGS, __applyto_doc__},
928 {"valid", ACL_valid, METH_NOARGS, __valid_doc__},
930 {"__getstate__", ACL_get_state, METH_NOARGS,
931 "Dumps the ACL to an external format."},
932 {"__setstate__", ACL_set_state, METH_VARARGS,
933 "Loads the ACL from an external format."},
934 {"delete_entry", ACL_delete_entry, METH_VARARGS, __ACL_delete_entry_doc__},
935 {"calc_mask", ACL_calc_mask, METH_NOARGS, __ACL_calc_mask_doc__},
936 {"append", ACL_append, METH_VARARGS, __ACL_append_doc__},
938 {NULL, NULL, 0, NULL}
942 /* The definition of the ACL Type */
943 static PyTypeObject ACL_Type = {
944 PyObject_HEAD_INIT(NULL)
949 ACL_dealloc, /* tp_dealloc */
955 0, /* tp_as_number */
956 0, /* tp_as_sequence */
957 0, /* tp_as_mapping */
960 ACL_str, /* tp_str */
963 0, /* tp_as_buffer */
964 Py_TPFLAGS_DEFAULT, /* tp_flags */
965 __ACL_Type_doc__, /* tp_doc */
968 0, /* tp_richcompare */
969 0, /* tp_weaklistoffset */
977 ACL_methods, /* tp_methods */
982 0, /* tp_descr_get */
983 0, /* tp_descr_set */
984 0, /* tp_dictoffset */
985 ACL_init, /* tp_init */
987 ACL_new, /* tp_new */
992 /* Entry type methods */
993 static PyMethodDef Entry_methods[] = {
994 {"copy", Entry_copy, METH_VARARGS, __Entry_copy_doc__},
995 {NULL, NULL, 0, NULL}
998 static char __Entry_tagtype_doc__[] = \
999 "The tag type of the current entry\n" \
1001 "This is one of:\n" \
1002 " - ACL_UNDEFINED_TAG\n" \
1003 " - ACL_USER_OBJ\n" \
1005 " - ACL_GROUP_OBJ\n" \
1011 static char __Entry_qualifier_doc__[] = \
1012 "The qualifier of the current entry\n" \
1014 "If the tag type is ACL_USER, this should be a user id.\n" \
1015 "If the tag type if ACL_GROUP, this should be a group id.\n" \
1016 "Else, it doesn't matter.\n" \
1019 static char __Entry_parent_doc__[] = \
1020 "The parent ACL of this entry\n" \
1023 static char __Entry_permset_doc__[] = \
1024 "The permission set of this ACL entry\n" \
1028 static PyGetSetDef Entry_getsets[] = {
1029 {"tag_type", Entry_get_tag_type, Entry_set_tag_type,
1030 __Entry_tagtype_doc__},
1031 {"qualifier", Entry_get_qualifier, Entry_set_qualifier,
1032 __Entry_qualifier_doc__},
1033 {"parent", Entry_get_parent, NULL, __Entry_parent_doc__},
1034 {"permset", Entry_get_permset, Entry_set_permset, __Entry_permset_doc__},
1038 static char __Entry_Type_doc__[] = \
1039 "Type which represents an entry in an ACL.\n" \
1041 "The type exists only if the OS has full support for POSIX.1e\n" \
1042 "Can be created either by:\n" \
1043 " e = posix1e.Entry(myACL) # this creates a new entry in the ACL\n" \
1045 " for entry in myACL:\n" \
1048 "Note that the Entry keeps a reference to its ACL, so even if \n" \
1049 "you delete the ACL, it won't be cleaned up and will continue to \n" \
1050 "exist until its Entry(ies) will be deleted.\n" \
1052 /* The definition of the Entry Type */
1053 static PyTypeObject Entry_Type = {
1054 PyObject_HEAD_INIT(NULL)
1057 sizeof(Entry_Object),
1059 Entry_dealloc, /* tp_dealloc */
1065 0, /* tp_as_number */
1066 0, /* tp_as_sequence */
1067 0, /* tp_as_mapping */
1070 Entry_str, /* tp_str */
1071 0, /* tp_getattro */
1072 0, /* tp_setattro */
1073 0, /* tp_as_buffer */
1074 Py_TPFLAGS_DEFAULT, /* tp_flags */
1075 __Entry_Type_doc__, /* tp_doc */
1076 0, /* tp_traverse */
1078 0, /* tp_richcompare */
1079 0, /* tp_weaklistoffset */
1081 0, /* tp_iternext */
1082 Entry_methods, /* tp_methods */
1084 Entry_getsets, /* tp_getset */
1087 0, /* tp_descr_get */
1088 0, /* tp_descr_set */
1089 0, /* tp_dictoffset */
1090 Entry_init, /* tp_init */
1092 Entry_new, /* tp_new */
1095 /* Permset type methods */
1096 static PyMethodDef Permset_methods[] = {
1097 {"clear", Permset_clear, METH_NOARGS, __Permset_clear_doc__, },
1098 {"add", Permset_add, METH_VARARGS, __Permset_add_doc__, },
1099 {"delete", Permset_delete, METH_VARARGS, __Permset_delete_doc__, },
1100 {"test", Permset_test, METH_VARARGS, __Permset_test_doc__, },
1101 {NULL, NULL, 0, NULL}
1104 static char __Permset_execute_doc__[] = \
1105 "Execute permsission\n" \
1107 "This is a convenience method of access; the \n" \
1108 "same effect can be achieved using the functions\n" \
1109 "add(), test(), delete(), and those can take any \n" \
1110 "permission defined by your platform.\n" \
1113 static char __Permset_read_doc__[] = \
1114 "Read permsission\n" \
1116 "This is a convenience method of access; the \n" \
1117 "same effect can be achieved using the functions\n" \
1118 "add(), test(), delete(), and those can take any \n" \
1119 "permission defined by your platform.\n" \
1122 static char __Permset_write_doc__[] = \
1123 "Write permsission\n" \
1125 "This is a convenience method of access; the \n" \
1126 "same effect can be achieved using the functions\n" \
1127 "add(), test(), delete(), and those can take any \n" \
1128 "permission defined by your platform.\n" \
1131 /* Permset getset */
1132 static PyGetSetDef Permset_getsets[] = {
1133 {"execute", Permset_get_right, Permset_set_right, \
1134 __Permset_execute_doc__, &holder_ACL_EXECUTE},
1135 {"read", Permset_get_right, Permset_set_right, \
1136 __Permset_read_doc__, &holder_ACL_READ},
1137 {"write", Permset_get_right, Permset_set_right, \
1138 __Permset_write_doc__, &holder_ACL_WRITE},
1142 static char __Permset_Type_doc__[] = \
1143 "Type which represents the permission set in an ACL entry\n" \
1145 "The type exists only if the OS has full support for POSIX.1e\n" \
1146 "Can be created either by:\n" \
1147 " perms = myEntry.permset\n" \
1149 " perms = posix1e.Permset(myEntry)\n" \
1151 "Note that the Permset keeps a reference to its Entry, so even if \n" \
1152 "you delete the entry, it won't be cleaned up and will continue to \n" \
1153 "exist until its Permset will be deleted.\n" \
1156 /* The definition of the Permset Type */
1157 static PyTypeObject Permset_Type = {
1158 PyObject_HEAD_INIT(NULL)
1161 sizeof(Permset_Object),
1163 Permset_dealloc, /* tp_dealloc */
1169 0, /* tp_as_number */
1170 0, /* tp_as_sequence */
1171 0, /* tp_as_mapping */
1174 Permset_str, /* tp_str */
1175 0, /* tp_getattro */
1176 0, /* tp_setattro */
1177 0, /* tp_as_buffer */
1178 Py_TPFLAGS_DEFAULT, /* tp_flags */
1179 __Permset_Type_doc__,/* tp_doc */
1180 0, /* tp_traverse */
1182 0, /* tp_richcompare */
1183 0, /* tp_weaklistoffset */
1185 0, /* tp_iternext */
1186 Permset_methods, /* tp_methods */
1188 Permset_getsets, /* tp_getset */
1191 0, /* tp_descr_get */
1192 0, /* tp_descr_set */
1193 0, /* tp_dictoffset */
1194 Permset_init, /* tp_init */
1196 Permset_new, /* tp_new */
1201 /* Module methods */
1203 static char __deletedef_doc__[] = \
1204 "Delete the default ACL from a directory.\n" \
1206 "This function deletes the default ACL associated with \n" \
1207 "a directory (the ACL which will be ANDed with the mode\n" \
1208 "parameter to the open, creat functions).\n" \
1210 " - a string representing the directory whose default ACL\n" \
1211 " should be deleted\n" \
1214 /* Deletes the default ACL from a directory */
1215 static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) {
1218 /* Parse the arguments */
1219 if (!PyArg_ParseTuple(args, "s", &filename))
1222 if(acl_delete_def_file(filename) == -1) {
1223 return PyErr_SetFromErrno(PyExc_IOError);
1226 /* Return the result */
1231 /* The module methods */
1232 static PyMethodDef aclmodule_methods[] = {
1233 {"delete_default", aclmodule_delete_default, METH_VARARGS,
1235 {NULL, NULL, 0, NULL}
1238 static char __posix1e_doc__[] = \
1239 "POSIX.1e ACLs manipulation\n" \
1241 "This module provides support for manipulating POSIX.1e ACLS\n" \
1243 "Depending on the operating system support for POSIX.1e, \n" \
1244 "the ACL type will have more or less capabilities:\n" \
1245 " - level 1, only basic support, you can create\n" \
1246 " ACLs from files and text descriptions;\n" \
1247 " once created, the type is immutable\n" \
1248 " - level 2, complete support, you can alter\n"\
1249 " the ACL once it is created\n" \
1251 "Also, in level 2, more types are available, corresponding\n" \
1252 "to acl_entry_t (Entry type), acl_permset_t (Permset type).\n" \
1255 ">>> import posix1e\n" \
1256 ">>> acl1 = posix1e.ACL(file=\"file.txt\") \n" \
1257 ">>> print acl1\n" \
1262 ">>> b = posix1e.ACL(text=\"u::rx,g::-,o::-\")\n" \
1268 ">>> b.applyto(\"file.txt\")\n" \
1269 ">>> print posix1e.ACL(file=\"file.txt\")\n" \
1277 void initposix1e(void) {
1280 ACL_Type.ob_type = &PyType_Type;
1281 if(PyType_Ready(&ACL_Type) < 0)
1285 Entry_Type.ob_type = &PyType_Type;
1286 if(PyType_Ready(&Entry_Type) < 0)
1289 Permset_Type.ob_type = &PyType_Type;
1290 if(PyType_Ready(&Permset_Type) < 0)
1294 m = Py_InitModule3("posix1e", aclmodule_methods, __posix1e_doc__);
1296 d = PyModule_GetDict(m);
1300 Py_INCREF(&ACL_Type);
1301 if (PyDict_SetItemString(d, "ACL",
1302 (PyObject *) &ACL_Type) < 0)
1305 /* 23.3.6 acl_type_t values */
1306 PyModule_AddIntConstant(m, "ACL_TYPE_ACCESS", ACL_TYPE_ACCESS);
1307 PyModule_AddIntConstant(m, "ACL_TYPE_DEFAULT", ACL_TYPE_DEFAULT);
1311 Py_INCREF(&Entry_Type);
1312 if (PyDict_SetItemString(d, "Entry",
1313 (PyObject *) &Entry_Type) < 0)
1316 Py_INCREF(&Permset_Type);
1317 if (PyDict_SetItemString(d, "Permset",
1318 (PyObject *) &Permset_Type) < 0)
1321 /* 23.2.2 acl_perm_t values */
1322 PyModule_AddIntConstant(m, "ACL_READ", ACL_READ);
1323 PyModule_AddIntConstant(m, "ACL_WRITE", ACL_WRITE);
1324 PyModule_AddIntConstant(m, "ACL_EXECUTE", ACL_EXECUTE);
1326 /* 23.2.5 acl_tag_t values */
1327 PyModule_AddIntConstant(m, "ACL_UNDEFINED_TAG", ACL_UNDEFINED_TAG);
1328 PyModule_AddIntConstant(m, "ACL_USER_OBJ", ACL_USER_OBJ);
1329 PyModule_AddIntConstant(m, "ACL_USER", ACL_USER);
1330 PyModule_AddIntConstant(m, "ACL_GROUP_OBJ", ACL_GROUP_OBJ);
1331 PyModule_AddIntConstant(m, "ACL_GROUP", ACL_GROUP);
1332 PyModule_AddIntConstant(m, "ACL_MASK", ACL_MASK);
1333 PyModule_AddIntConstant(m, "ACL_OTHER", ACL_OTHER);