From a5f57ccec46dae2f5f539cbd87c0950688f49ada Mon Sep 17 00:00:00 2001 From: Iustin Pop Date: Tue, 26 Feb 2008 20:48:11 +0100 Subject: [PATCH 1/1] Imported upstream version 0.2.2 --- BENCHMARK | 20 + ChangeLog | 108 ++++ IMPLEMENTATION | 36 ++ MANIFEST | 12 + PKG-INFO | 12 + PLATFORMS | 23 + README | 6 + acl.c | 1302 ++++++++++++++++++++++++++++++++++++++++++++++++ os_linux.c | 6 + posix1e.html | 414 +++++++++++++++ posix1e.txt | 443 ++++++++++++++++ setup.cfg | 4 + setup.py | 44 ++ 13 files changed, 2430 insertions(+) create mode 100644 BENCHMARK create mode 100644 ChangeLog create mode 100644 IMPLEMENTATION create mode 100644 MANIFEST create mode 100644 PKG-INFO create mode 100644 PLATFORMS create mode 100644 README create mode 100644 acl.c create mode 100644 os_linux.c create mode 100644 posix1e.html create mode 100644 posix1e.txt create mode 100644 setup.cfg create mode 100755 setup.py diff --git a/BENCHMARK b/BENCHMARK new file mode 100644 index 0000000..3c9cea1 --- /dev/null +++ b/BENCHMARK @@ -0,0 +1,20 @@ +On my Duron 1000, Linux 2.4, creating 1.000.000 ACLs and discarding them: + +empty ACL: 4.48user 0.03system 0:04.50elapsed 100%CPU +from text: 13.87user 0.09system 0:13.97elapsed 99%CPU +XFS, file: 14.17user 14.95system 0:29.13elapsed 99%CPU + +creating a list from the entries of an ACL: +no entries: 3.86user 0.01system 0:03.86elapsed 100%CPU +6 entries: 16.39user 0.00system 0:16.38elapsed 100%CPU + +As you can see, creating from file is the longest (as expected). More than +half time when creating from file was in kernel mode. + + +In freebsd 4.6, UNDER VMWARE!!!!, same machine: +empty ACL: 3.409u 0.432s 0:03.85 99.4% 516+15695k 0+0io 0pf+0w +from text: 10.672u 1.016s 0:11.71 99.7% 508+24230k 0+0io 0pf+0w + +Interesting results, it seems from text is faster here - but here +the library doens't support editing, so maybe that's why. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..35f2eb4 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,108 @@ +2006-12-03 11:15 Iustin Pop + + * setup.py: Add support for building on GNU/kFreeBSD + +2004-04-27 20:27 Iustin Pop + + * MANIFEST.in: Added ChangeLog to distribution + +2002-12-29 20:41 Iustin Pop + + * BENCHMARK, MANIFEST.in, setup.py: Release 0.2.1 + +2002-12-29 06:48 Iustin Pop + + * acl.c: Fixed compilation on LEVEL1 platform (broke since after + 0.1) + +2002-12-29 06:36 Iustin Pop + + * BENCHMARK, acl.c: Added missing functionality (acl_calc_mask) and + some convenience functions. + +2002-12-27 21:55 Iustin Pop + + * MANIFEST.in, setup.py: Small changes + +2002-12-27 19:47 Iustin Pop + + * IMPLEMENTATION, acl.c: Prepare for release 0.2 + +2002-12-27 19:43 Iustin Pop + + * Makefile: Small makefile + +2002-12-27 19:42 Iustin Pop + + * MANIFEST.in: Distutils file + +2002-12-27 19:42 Iustin Pop + + * os_linux.c: Linux-specific file + +2002-12-27 11:35 Iustin Pop + + * PORTING: Informations for porting to other platforms. + +2002-12-26 09:21 Iustin Pop + + * acl.c: Added the Permset type/object and some other naming + changes + +2002-12-26 06:48 Iustin Pop + + * acl.c: Renamed type & object names from ACLType to ACL_Type and + so on. Also ACLEntry is now jus Entry. + +2002-12-26 06:43 Iustin Pop + + * acl.c: Renamed some fields from ob_x to x, as per other modules + in python + +2002-12-26 06:41 Iustin Pop + + * IMPLEMENTATION, acl.c: Added acl_entry_t type (named + ACLEntryType, respectively ACLEntryObject) + +2002-12-26 03:24 Iustin Pop + + * acl.c: Documentation typo + +2002-12-24 15:35 Iustin Pop + + * setup.cfg: Added setup.cfg, mainly for bdist_rpm + +2002-12-24 15:29 Iustin Pop + + * setup.py: Don't call python2, only python + +2002-12-24 15:19 Iustin Pop + + * acl.c, setup.py: Prepare for first public release + +2002-12-24 03:35 Iustin Pop + + * PLATFORMS, acl.c, setup.py: Moved to real instance creation via + type() + +2002-12-23 21:05 Iustin Pop + + * IMPLEMENTATION, PLATFORMS, README, acl.c, setup.py: Addedd + __setstate__ and some docs + +2002-12-23 16:55 Iustin Pop + + * README, setup.py: Initial revision + +2002-12-23 16:55 Iustin Pop + + * acl.c: Many functions added, started working on level 2 support + +2002-12-21 21:55 Iustin Pop + + * acl.c: Initial revision + +2002-12-21 21:55 + + * branches, tags, .: New repository initialized by cvs2svn. + diff --git a/IMPLEMENTATION b/IMPLEMENTATION new file mode 100644 index 0000000..64ad4a5 --- /dev/null +++ b/IMPLEMENTATION @@ -0,0 +1,36 @@ +The IEEE 1003.1e draft 17 ("POSIX.1e") describes a set of 28 +functions. These are grouped into three groups, based on their +portability: + - first group, the most portable one. All systems which claim to + support POSIX.1e should implement these: + acl_delete_def_file(3), acl_dup(3), acl_free(3), acl_from_text(3), + acl_get_fd(3), acl_get_file(3), acl_init(3), acl_set_fd(3), + acl_set_file(3), acl_to_text(3), acl_valid(3) + + - second group, containing the rest of the POSIX ACL functions. Systems + which claim to fully implement POSIX.1e should implement these: + acl_add_perm(3), acl_calc_mask(3), acl_clear_perms(3), acl_copy_entry(3), + acl_copy_ext(3), acl_copy_int(3), acl_create_entry(3), + acl_delete_entry(3), acl_delete_perm(3), acl_get_entry(3), + acl_get_permset(3), acl_get_qualifier(3), acl_get_tag_type(3), + acl_set_permset(3), acl_set_qualifier(3), acl_set_tag_type(3), + acl_size(3) + + - third group, containing extra functions implemented by each OS. These + are non-portable version. Both Linux and FreeBSD implement some extra + function. + +Thus we have the level of compliance. Depending on whether the system +library support the second group, you get some extra methods for the +ACL object. + +Internal structure + The POSIX draft has the following stuff (correct me if I'm wrong): + - an ACL is denoted by acl_t + - an ACL contains many acl_entry_t, these are the individual entries + in the list; they always! belong to an acl_t + - each entry_t has a qualifier (think uid_t or gid_t), whose type is + denoted by the acl_tag_t type, and an acl_permset_t + - the acl_permset_t can contain acl_perm_t value (ACL_READ, ACL_WRITE, + ACL_EXECUTE, ACL_ADD, ACL_DELETE, ...) + - function to manipulate all these, and functions to manipulate files diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..6d339f4 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,12 @@ +BENCHMARK +ChangeLog +IMPLEMENTATION +MANIFEST +PLATFORMS +README +acl.c +os_linux.c +posix1e.html +posix1e.txt +setup.cfg +setup.py diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..1752799 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 1.0 +Name: pylibacl +Version: 0.2.2 +Summary: POSIX.1e ACLs for python +Home-page: http://pylibacl.sourceforge.net +Author: Iustin Pop +Author-email: iusty@k1024.org +License: GPL +Description: This is a C extension module for Python which + implements POSIX ACLs manipulation. It is a wrapper on top + of the systems's acl C library - see acl(5). +Platform: UNKNOWN diff --git a/PLATFORMS b/PLATFORMS new file mode 100644 index 0000000..ab2d28b --- /dev/null +++ b/PLATFORMS @@ -0,0 +1,23 @@ +The current supported platforms: + +Linux + + It needs kernel 2.4 or higher and the libacl library installed (with + development headers, if installing from rpm). The url is + http://acl.bestbits.at if using for ext2/ext3 and JFS, and + http://oss.sgi.com/projects/xfs/ if using for XFS. + + The level of compliance is level 2 (see IMPLEMENTATION). + + +FreeBSD + + The current tested version is 4.6. I hope to be able to test 5.0 after + it's released. + + The level of compliance is level 1. I hope that in FreeBSD 5 they will + improve. + + +For any other platform, volunteers are welcome. To add support, look +into setup.py at first and then into acl.c diff --git a/README b/README new file mode 100644 index 0000000..e17837d --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +This is an extension for Python which implements POSIX ACLs (POSIX.1e). + +To see the supported platforms, look at PLATFORMS. +To see internal details, look at IMPLEMENTATION. + +Iustin Pop, diff --git a/acl.c b/acl.c new file mode 100644 index 0000000..e4248a6 --- /dev/null +++ b/acl.c @@ -0,0 +1,1302 @@ +#include + +#include +#include + +#ifdef HAVE_LINUX +#include "os_linux.c" +#endif + +staticforward PyTypeObject ACL_Type; +static PyObject* ACL_applyto(PyObject* obj, PyObject* args); +static PyObject* ACL_valid(PyObject* obj, PyObject* args); + +#ifdef HAVE_LEVEL2 +static PyObject* ACL_get_state(PyObject *obj, PyObject* args); +static PyObject* ACL_set_state(PyObject *obj, PyObject* args); + +staticforward PyTypeObject Entry_Type; +staticforward PyTypeObject Permset_Type; +static PyObject* Permset_new(PyTypeObject* type, PyObject* args, PyObject *keywds); +#endif + +static acl_perm_t holder_ACL_EXECUTE = ACL_EXECUTE; +static acl_perm_t holder_ACL_READ = ACL_READ; +static acl_perm_t holder_ACL_WRITE = ACL_WRITE; + +typedef struct { + PyObject_HEAD + acl_t acl; +#ifdef HAVE_LEVEL2 + int entry_id; +#endif +} ACL_Object; + +#ifdef HAVE_LEVEL2 + +typedef struct { + PyObject_HEAD + PyObject *parent_acl; /* The parent acl, so it won't run out on us */ + acl_entry_t entry; +} Entry_Object; + +typedef struct { + PyObject_HEAD + PyObject *parent_entry; /* The parent entry, so it won't run out on us */ + acl_permset_t permset; +} Permset_Object; + +#endif + +/* Creation of a new ACL instance */ +static PyObject* ACL_new(PyTypeObject* type, PyObject* args, PyObject *keywds) { + PyObject* newacl; + + newacl = type->tp_alloc(type, 0); + + if(newacl != NULL) { + ((ACL_Object*)newacl)->acl = NULL; +#ifdef HAVEL_LEVEL2 + ((ACL_Object*)newacl)->entry_id = ACL_FIRST_ENTRY; +#endif + } + + return newacl; +} + +/* Initialization of a new ACL instance */ +static int ACL_init(PyObject* obj, PyObject* args, PyObject *keywds) { + ACL_Object* self = (ACL_Object*) obj; + static char *kwlist[] = { "file", "fd", "text", "acl", "filedef", NULL }; + char *file = NULL; + char *filedef = NULL; + char *text = NULL; + int fd = -1; + ACL_Object* thesrc = NULL; + + if(!PyTuple_Check(args) || PyTuple_Size(args) != 0 || + (keywds != NULL && PyDict_Check(keywds) && PyDict_Size(keywds) > 1)) { + PyErr_SetString(PyExc_ValueError, "a max of one keyword argument must be passed"); + return -1; + } + if(!PyArg_ParseTupleAndKeywords(args, keywds, "|sisO!s", kwlist, + &file, &fd, &text, &ACL_Type, &thesrc, &filedef)) + return -1; + + /* Free the old acl_t without checking for error, we don't + * care right now */ + if(self->acl != NULL) + acl_free(self->acl); + + if(file != NULL) + self->acl = acl_get_file(file, ACL_TYPE_ACCESS); + else if(text != NULL) + self->acl = acl_from_text(text); + else if(fd != -1) + self->acl = acl_get_fd(fd); + else if(thesrc != NULL) + self->acl = acl_dup(thesrc->acl); + else if(filedef != NULL) + self->acl = acl_get_file(filedef, ACL_TYPE_DEFAULT); + else + self->acl = acl_init(0); + + if(self->acl == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + return 0; +} + +/* Standard type functions */ +static void ACL_dealloc(PyObject* obj) { + ACL_Object *self = (ACL_Object*) obj; + PyObject *err_type, *err_value, *err_traceback; + int have_error = PyErr_Occurred() ? 1 : 0; + + if (have_error) + PyErr_Fetch(&err_type, &err_value, &err_traceback); + if(self->acl != NULL && acl_free(self->acl) != 0) + PyErr_WriteUnraisable(obj); + if (have_error) + PyErr_Restore(err_type, err_value, err_traceback); + PyObject_DEL(self); +} + +/* Converts the acl to a text format */ +static PyObject* ACL_str(PyObject *obj) { + char *text; + ACL_Object *self = (ACL_Object*) obj; + PyObject *ret; + + text = acl_to_text(self->acl, NULL); + if(text == NULL) { + return PyErr_SetFromErrno(PyExc_IOError); + } + ret = PyString_FromString(text); + if(acl_free(text) != 0) { + Py_DECREF(ret); + return PyErr_SetFromErrno(PyExc_IOError); + } + return ret; +} + +/* Custom methods */ +static char __applyto_doc__[] = \ +"Apply the ACL to a file or filehandle.\n" \ +"\n" \ +"Parameters:\n" \ +" - either a filename or a file-like object or an integer; this\n" \ +" represents the filesystem object on which to act\n" \ +" - optional flag representing the type of ACL to set, either\n" \ +" ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT\n" \ +; + +/* Applyes the ACL to a file */ +static PyObject* ACL_applyto(PyObject* obj, PyObject* args) { + ACL_Object *self = (ACL_Object*) obj; + PyObject *myarg; + acl_type_t type = ACL_TYPE_ACCESS; + int nret; + int fd; + + if (!PyArg_ParseTuple(args, "O|i", &myarg, &type)) + return NULL; + + if(PyString_Check(myarg)) { + char *filename = PyString_AS_STRING(myarg); + nret = acl_set_file(filename, type, self->acl); + } else if((fd = PyObject_AsFileDescriptor(myarg)) != -1) { + nret = acl_set_fd(fd, self->acl); + } else { + PyErr_SetString(PyExc_TypeError, "argument 1 must be string, int, or file-like object"); + return 0; + } + if(nret == -1) { + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __valid_doc__[] = \ +"Test the ACL for validity.\n" \ +"\n" \ +"This method tests the ACL to see if it is a valid ACL\n" \ +"in terms of the filesystem. More precisely, it checks:\n" \ +"A valid ACL contains exactly one entry with each of the ACL_USER_OBJ,\n" \ +"ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and\n" \ +"ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that\n" \ +"contains entries of ACL_USER or ACL_GROUP tag types must contain exactly\n" \ +"one entry of the ACL_MASK tag type. If an ACL contains no entries of\n" \ +"ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.\n" \ +"\n" \ +"All user ID qualifiers must be unique among all entries of ACL_USER tag\n" \ +"type, and all group IDs must be unique among all entries of ACL_GROUP tag\n" \ +"type.\n" \ +"\n" \ +"The method will return 1 for a valid ACL and 0 for an invalid one.\n" \ +"This has been chosen because the specification for acl_valid in POSIX.1e\n" \ +"documents only one possible value for errno in case of an invalid ACL, \n" \ +"so we can't differentiate between classes of errors. Other suggestions \n" \ +"are welcome.\n" \ +; + +/* Checks the ACL for validity */ +static PyObject* ACL_valid(PyObject* obj, PyObject* args) { + ACL_Object *self = (ACL_Object*) obj; + + if(acl_valid(self->acl) == -1) { + Py_INCREF(Py_False); + return Py_False; + } else { + Py_INCREF(Py_True); + return Py_True; + } +} + +#ifdef HAVE_LEVEL2 + +static PyObject* ACL_get_state(PyObject *obj, PyObject* args) { + ACL_Object *self = (ACL_Object*) obj; + PyObject *ret; + ssize_t size, nsize; + char *buf; + + size = acl_size(self->acl); + if(size == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + if((ret = PyString_FromStringAndSize(NULL, size)) == NULL) + return NULL; + buf = PyString_AsString(ret); + + if((nsize = acl_copy_ext(buf, self->acl, size)) == -1) { + Py_DECREF(ret); + return PyErr_SetFromErrno(PyExc_IOError); + } + + return ret; +} + +static PyObject* ACL_set_state(PyObject *obj, PyObject* args) { + ACL_Object *self = (ACL_Object*) obj; + const void *buf; + int bufsize; + acl_t ptr; + + /* Parse the argument */ + if (!PyArg_ParseTuple(args, "s#", &buf, &bufsize)) + return NULL; + + /* Try to import the external representation */ + if((ptr = acl_copy_int(buf)) == NULL) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Free the old acl. Should we ignore errors here? */ + if(self->acl != NULL) { + if(acl_free(self->acl) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + } + + self->acl = ptr; + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +/* tp_iter for the ACL type; since it can be iterated only + * destructively, the type is its iterator + */ +static PyObject* ACL_iter(PyObject *obj) { + ACL_Object *self = (ACL_Object*)obj; + self->entry_id = ACL_FIRST_ENTRY; + Py_INCREF(obj); + return obj; +} + +/* the tp_iternext function for the ACL type */ +static PyObject* ACL_iternext(PyObject *obj) { + ACL_Object *self = (ACL_Object*)obj; + acl_entry_t the_entry_t; + Entry_Object *the_entry_obj; + int nerr; + + nerr = acl_get_entry(self->acl, self->entry_id, &the_entry_t); + self->entry_id = ACL_NEXT_ENTRY; + if(nerr == -1) + return PyErr_SetFromErrno(PyExc_IOError); + else if(nerr == 0) { + /* Docs says this is not needed */ + /*PyErr_SetObject(PyExc_StopIteration, Py_None);*/ + return NULL; + } + + the_entry_obj = (Entry_Object*) PyType_GenericNew(&Entry_Type, NULL, NULL); + if(the_entry_obj == NULL) + return NULL; + + the_entry_obj->entry = the_entry_t; + + the_entry_obj->parent_acl = obj; + Py_INCREF(obj); /* For the reference we have in entry->parent */ + + return (PyObject*)the_entry_obj; +} + +static char __ACL_delete_entry_doc__[] = \ +"Deletes an entry from the ACL.\n" \ +"\n" \ +"Note: Only with level 2\n" \ +"Parameters:\n" \ +" - the Entry object which should be deleted; note that after\n" \ +" this function is called, that object is unusable any longer\n" \ +" and should be deleted\n" \ +; + +/* Deletes an entry from the ACL */ +static PyObject* ACL_delete_entry(PyObject *obj, PyObject *args) { + ACL_Object *self = (ACL_Object*)obj; + Entry_Object *e; + + if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &e)) + return NULL; + + if(acl_delete_entry(self->acl, e->entry) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __ACL_calc_mask_doc__[] = \ +"Compute the file group class mask.\n" \ +"\n" \ +"The calc_mask() method calculates and sets the permissions \n" \ +"associated with the ACL_MASK Entry of the ACL.\n" \ +"The value of the new permissions is the union of the permissions \n" \ +"granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or \n" \ +"ACL_USER. If the ACL already contains an ACL_MASK entry, its \n" \ +"permissions are overwritten; if it does not contain an ACL_MASK \n" \ +"Entry, one is added.\n" \ +"\n" \ +"The order of existing entries in the ACL is undefined after this \n" \ +"function.\n" \ +; + +/* Updates the mask entry in the ACL */ +static PyObject* ACL_calc_mask(PyObject *obj, PyObject *args) { + ACL_Object *self = (ACL_Object*)obj; + + if(acl_calc_mask(&self->acl) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __ACL_append_doc__[] = \ +"Append a new Entry to the ACL and return it.\n" \ +"\n" \ +"This is a convenience function to create a new Entry \n" \ +"and append it to the ACL.\n" \ +"If a parameter of type Entry instance is given, the \n" \ +"entry will be a copy of that one (as if copied with \n" \ +"Entry.copy()), otherwise, the new entry will be empty.\n" \ +; + +/* Convenience method to create a new Entry */ +static PyObject* ACL_append(PyObject *obj, PyObject *args) { + ACL_Object* self = (ACL_Object*) obj; + Entry_Object* newentry; + Entry_Object* oldentry = NULL; + int nret; + + newentry = (Entry_Object*)PyType_GenericNew(&Entry_Type, NULL, NULL); + if(newentry == NULL) { + return NULL; + } + + if (!PyArg_ParseTuple(args, "|O!", &Entry_Type, &oldentry)) + return NULL; + + nret = acl_create_entry(&self->acl, &newentry->entry); + if(nret == -1) { + Py_DECREF(newentry); + return PyErr_SetFromErrno(PyExc_IOError); + } + + if(oldentry != NULL) { + nret = acl_copy_entry(newentry->entry, oldentry->entry); + if(nret == -1) { + Py_DECREF(newentry); + return PyErr_SetFromErrno(PyExc_IOError); + } + } + + newentry->parent_acl = obj; + Py_INCREF(obj); + + return (PyObject*)newentry; +} + +/***** Entry type *****/ + +/* Creation of a new Entry instance */ +static PyObject* Entry_new(PyTypeObject* type, PyObject* args, PyObject *keywds) { + PyObject* newentry; + + newentry = PyType_GenericNew(type, args, keywds); + + if(newentry != NULL) { + ((Entry_Object*)newentry)->entry = NULL; + ((Entry_Object*)newentry)->parent_acl = NULL; + } + + return newentry; +} + +/* Initialization of a new Entry instance */ +static int Entry_init(PyObject* obj, PyObject* args, PyObject *keywds) { + Entry_Object* self = (Entry_Object*) obj; + ACL_Object* parent = NULL; + + if (!PyArg_ParseTuple(args, "O!", &ACL_Type, &parent)) + return -1; + + if(acl_create_entry(&parent->acl, &self->entry) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + self->parent_acl = (PyObject*)parent; + Py_INCREF(parent); + + return 0; +} + +/* Free the Entry instance */ +static void Entry_dealloc(PyObject* obj) { + Entry_Object *self = (Entry_Object*) obj; + PyObject *err_type, *err_value, *err_traceback; + int have_error = PyErr_Occurred() ? 1 : 0; + + if (have_error) + PyErr_Fetch(&err_type, &err_value, &err_traceback); + if(self->parent_acl != NULL) { + Py_DECREF(self->parent_acl); + self->parent_acl = NULL; + } + if (have_error) + PyErr_Restore(err_type, err_value, err_traceback); + PyObject_DEL(self); +} + +/* Converts the entry to a text format */ +static PyObject* Entry_str(PyObject *obj) { + acl_tag_t tag; + uid_t qualifier; + void *p; + PyObject *ret; + PyObject *format, *list; + Entry_Object *self = (Entry_Object*) obj; + + if(acl_get_tag_type(self->entry, &tag) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + if(tag == ACL_USER || tag == ACL_GROUP) { + if((p = acl_get_qualifier(self->entry)) == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + qualifier = *(uid_t*)p; + acl_free(p); + } else { + qualifier = 0; + } + + format = PyString_FromString("ACL entry for %s"); + if(format == NULL) + return NULL; + list = PyTuple_New(1); + if(tag == ACL_UNDEFINED_TAG) { + PyTuple_SetItem(list, 0, PyString_FromString("undefined type")); + } else if(tag == ACL_USER_OBJ) { + PyTuple_SetItem(list, 0, PyString_FromString("the owner")); + } else if(tag == ACL_GROUP_OBJ) { + PyTuple_SetItem(list, 0, PyString_FromString("the group")); + } else if(tag == ACL_OTHER) { + PyTuple_SetItem(list, 0, PyString_FromString("the others")); + } else if(tag == ACL_USER) { + PyTuple_SetItem(list, 0, PyString_FromFormat("user with uid %d", qualifier)); + } else if(tag == ACL_GROUP) { + PyTuple_SetItem(list, 0, PyString_FromFormat("group with gid %d", qualifier)); + } else if(tag == ACL_MASK) { + PyTuple_SetItem(list, 0, PyString_FromString("the mask")); + } else { + PyTuple_SetItem(list, 0, PyString_FromString("UNKNOWN_TAG_TYPE!")); + } + ret = PyString_Format(format, list); + Py_DECREF(format); + Py_DECREF(list); + return ret; +} + +/* Sets the tag type of the entry */ +static int Entry_set_tag_type(PyObject* obj, PyObject* value, void* arg) { + Entry_Object *self = (Entry_Object*) obj; + + if(value == NULL) { + PyErr_SetString(PyExc_TypeError, + "tag type deletion is not supported"); + return -1; + } + + if(!PyInt_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "tag type must be integer"); + return -1; + } + if(acl_set_tag_type(self->entry, (acl_tag_t)PyInt_AsLong(value)) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + return 0; +} + +/* Returns the tag type of the entry */ +static PyObject* Entry_get_tag_type(PyObject *obj, void* arg) { + Entry_Object *self = (Entry_Object*) obj; + acl_tag_t value; + + if (self->entry == NULL) { + PyErr_SetString(PyExc_AttributeError, "entry attribute"); + return NULL; + } + if(acl_get_tag_type(self->entry, &value) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + + return PyInt_FromLong(value); +} + +/* Sets the qualifier (either uid_t or gid_t) for the entry, + * usable only if the tag type if ACL_USER or ACL_GROUP + */ +static int Entry_set_qualifier(PyObject* obj, PyObject* value, void* arg) { + Entry_Object *self = (Entry_Object*) obj; + int uidgid; + + if(value == NULL) { + PyErr_SetString(PyExc_TypeError, + "qualifier deletion is not supported"); + return -1; + } + + if(!PyInt_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "tag type must be integer"); + return -1; + } + uidgid = PyInt_AsLong(value); + if(acl_set_qualifier(self->entry, (void*)&uidgid) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + return 0; +} + +/* Returns the qualifier of the entry */ +static PyObject* Entry_get_qualifier(PyObject *obj, void* arg) { + Entry_Object *self = (Entry_Object*) obj; + void *p; + int value; + + if (self->entry == NULL) { + PyErr_SetString(PyExc_AttributeError, "entry attribute"); + return NULL; + } + if((p = acl_get_qualifier(self->entry)) == NULL) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + value = *(uid_t*)p; + acl_free(p); + + return PyInt_FromLong(value); +} + +/* Returns the parent ACL of the entry */ +static PyObject* Entry_get_parent(PyObject *obj, void* arg) { + Entry_Object *self = (Entry_Object*) obj; + + Py_INCREF(self->parent_acl); + return self->parent_acl; +} + +/* Returns the a new Permset representing the permset of the entry + * FIXME: Should return a new reference to the same object, which + * should be created at init time! +*/ +static PyObject* Entry_get_permset(PyObject *obj, void* arg) { + Entry_Object *self = (Entry_Object*)obj; + PyObject *p; + Permset_Object *ps; + + p = Permset_new(&Permset_Type, NULL, NULL); + if(p == NULL) + return NULL; + ps = (Permset_Object*)p; + if(acl_get_permset(self->entry, &ps->permset) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return NULL; + } + ps->parent_entry = obj; + Py_INCREF(obj); + + return (PyObject*)p; +} + +/* Sets the permset of the entry to the passed Permset */ +static int Entry_set_permset(PyObject* obj, PyObject* value, void* arg) { + Entry_Object *self = (Entry_Object*)obj; + Permset_Object *p; + + if(!PyObject_IsInstance(value, (PyObject*)&Permset_Type)) { + PyErr_SetString(PyExc_TypeError, "argument 1 must be posix1e.Permset"); + return -1; + } + p = (Permset_Object*)value; + if(acl_set_permset(self->entry, p->permset) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + return 0; +} + +static char __Entry_copy_doc__[] = \ +"Copy an ACL entry.\n" \ +"\n" \ +"This method sets all the parameters to those of another\n" \ +"entry, even one of another's ACL\n" \ +"Parameters:\n" \ +" - src, instance of type Entry\n" \ +; + +/* Sets all the entry parameters to another's entry */ +static PyObject* Entry_copy(PyObject *obj, PyObject *args) { + Entry_Object *self = (Entry_Object*)obj; + Entry_Object *other; + + if(!PyArg_ParseTuple(args, "O!", &Entry_Type, &other)) + return NULL; + + if(acl_copy_entry(self->entry, other->entry) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + Py_INCREF(Py_None); + return Py_None; +} + +/**** Permset type *****/ + +/* Creation of a new Permset instance */ +static PyObject* Permset_new(PyTypeObject* type, PyObject* args, PyObject *keywds) { + PyObject* newpermset; + + newpermset = PyType_GenericNew(type, args, keywds); + + if(newpermset != NULL) { + ((Permset_Object*)newpermset)->permset = NULL; + ((Permset_Object*)newpermset)->parent_entry = NULL; + } + + return newpermset; +} + +/* Initialization of a new Permset instance */ +static int Permset_init(PyObject* obj, PyObject* args, PyObject *keywds) { + Permset_Object* self = (Permset_Object*) obj; + Entry_Object* parent = NULL; + + if (!PyArg_ParseTuple(args, "O!", &Entry_Type, &parent)) + return -1; + + if(acl_get_permset(parent->entry, &self->permset) == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + + self->parent_entry = (PyObject*)parent; + Py_INCREF(parent); + + return 0; +} + +/* Free the Permset instance */ +static void Permset_dealloc(PyObject* obj) { + Permset_Object *self = (Permset_Object*) obj; + PyObject *err_type, *err_value, *err_traceback; + int have_error = PyErr_Occurred() ? 1 : 0; + + if (have_error) + PyErr_Fetch(&err_type, &err_value, &err_traceback); + if(self->parent_entry != NULL) { + Py_DECREF(self->parent_entry); + self->parent_entry = NULL; + } + if (have_error) + PyErr_Restore(err_type, err_value, err_traceback); + PyObject_DEL(self); +} + +/* Permset string representation */ +static PyObject* Permset_str(PyObject *obj) { + Permset_Object *self = (Permset_Object*) obj; + char pstr[3]; + + pstr[0] = get_perm(self->permset, ACL_READ) ? 'r' : '-'; + pstr[1] = get_perm(self->permset, ACL_WRITE) ? 'w' : '-'; + pstr[2] = get_perm(self->permset, ACL_EXECUTE) ? 'x' : '-'; + return PyString_FromStringAndSize(pstr, 3); +} + +static char __Permset_clear_doc__[] = \ +"Clear all permissions from the permission set.\n" \ +; + +/* Clears all permissions from the permset */ +static PyObject* Permset_clear(PyObject* obj, PyObject* args) { + Permset_Object *self = (Permset_Object*) obj; + + if(acl_clear_perms(self->permset) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject* Permset_get_right(PyObject *obj, void* arg) { + Permset_Object *self = (Permset_Object*) obj; + + if(get_perm(self->permset, *(acl_perm_t*)arg)) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +static int Permset_set_right(PyObject* obj, PyObject* value, void* arg) { + Permset_Object *self = (Permset_Object*) obj; + int on; + int nerr; + + if(!PyInt_Check(value)) { + PyErr_SetString(PyExc_ValueError, "a maximum of one argument must be passed"); + return -1; + } + on = PyInt_AsLong(value); + if(on) + nerr = acl_add_perm(self->permset, *(acl_perm_t*)arg); + else + nerr = acl_delete_perm(self->permset, *(acl_perm_t*)arg); + if(nerr == -1) { + PyErr_SetFromErrno(PyExc_IOError); + return -1; + } + return 0; +} + +static char __Permset_add_doc__[] = \ +"Add a permission to the permission set.\n" \ +"\n" \ +"The add() function adds the permission contained in \n" \ +"the argument perm to the permission set. An attempt \n" \ +"to add a permission that is already contained in the \n" \ +"permission set is not considered an error.\n" \ +"Parameters:\n" \ +" - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \ +"Return value:\n" \ +" None\n" \ +"Can raise: IOError\n" \ +; + +static PyObject* Permset_add(PyObject* obj, PyObject* args) { + Permset_Object *self = (Permset_Object*) obj; + int right; + + if (!PyArg_ParseTuple(args, "i", &right)) + return NULL; + + if(acl_add_perm(self->permset, (acl_perm_t) right) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __Permset_delete_doc__[] = \ +"Delete a permission from the permission set.\n" \ +"\n" \ +"The delete() function deletes the permission contained in \n" \ +"the argument perm from the permission set. An attempt \n" \ +"to delete a permission that is not contained in the \n" \ +"permission set is not considered an error.\n" \ +"Parameters:\n" \ +" - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \ +"Return value:\n" \ +" None\n" \ +"Can raise: IOError\n" \ +; + +static PyObject* Permset_delete(PyObject* obj, PyObject* args) { + Permset_Object *self = (Permset_Object*) obj; + int right; + + if (!PyArg_ParseTuple(args, "i", &right)) + return NULL; + + if(acl_delete_perm(self->permset, (acl_perm_t) right) == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +static char __Permset_test_doc__[] = \ +"Test if a permission exists in the permission set.\n" \ +"\n" \ +"The test() function tests if the permission contained in \n" \ +"the argument perm exits the permission set.\n" \ +"Parameters:\n" \ +" - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...\n" \ +"Return value:\n" \ +" Bool\n" \ +"Can raise: IOError\n" \ +; + +static PyObject* Permset_test(PyObject* obj, PyObject* args) { + Permset_Object *self = (Permset_Object*) obj; + int right; + int ret; + + if (!PyArg_ParseTuple(args, "i", &right)) + return NULL; + + ret = get_perm(self->permset, (acl_perm_t) right); + if(ret == -1) + return PyErr_SetFromErrno(PyExc_IOError); + + if(ret) { + Py_INCREF(Py_True); + return Py_True; + } else { + Py_INCREF(Py_False); + return Py_False; + } +} + +#endif + +static char __ACL_Type_doc__[] = \ +"Type which represents a POSIX ACL\n" \ +"\n" \ +"Parameters:\n" \ +" Only one keword parameter should be provided:\n" +" - file=\"...\", meaning create ACL representing\n" +" the access ACL of that file\n" \ +" - filedef=\"...\", meaning create ACL representing\n" +" the default ACL of that directory\n" \ +" - fd=, meaning create ACL representing\n" \ +" the access ACL of that file descriptor\n" \ +" - text=\"...\", meaning create ACL from a \n" \ +" textual description\n" \ +" - acl=, meaning create a copy\n" \ +" of an existing ACL instance\n" \ +"If no parameters are passed, create an empty ACL; this\n" \ +"makes sense only when your OS supports ACL modification\n" \ +" (i.e. it implements full POSIX.1e support)\n" \ +; + +/* ACL type methods */ +static PyMethodDef ACL_methods[] = { + {"applyto", ACL_applyto, METH_VARARGS, __applyto_doc__}, + {"valid", ACL_valid, METH_NOARGS, __valid_doc__}, +#ifdef HAVE_LEVEL2 + {"__getstate__", ACL_get_state, METH_NOARGS, "Dumps the ACL to an external format."}, + {"__setstate__", ACL_set_state, METH_VARARGS, "Loads the ACL from an external format."}, + {"delete_entry", ACL_delete_entry, METH_VARARGS, __ACL_delete_entry_doc__}, + {"calc_mask", ACL_calc_mask, METH_NOARGS, __ACL_calc_mask_doc__}, + {"append", ACL_append, METH_VARARGS, __ACL_append_doc__}, +#endif + {NULL, NULL, 0, NULL} +}; + + +/* The definition of the ACL Type */ +static PyTypeObject ACL_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "posix1e.ACL", + sizeof(ACL_Object), + 0, + ACL_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + ACL_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + __ACL_Type_doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ +#ifdef HAVE_LEVEL2 + ACL_iter, + ACL_iternext, +#else + 0, /* tp_iter */ + 0, /* tp_iternext */ +#endif + ACL_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + ACL_init, /* tp_init */ + 0, /* tp_alloc */ + ACL_new, /* tp_new */ +}; + +#ifdef HAVE_LEVEL2 + +/* Entry type methods */ +static PyMethodDef Entry_methods[] = { + {"copy", Entry_copy, METH_VARARGS, __Entry_copy_doc__}, + {NULL, NULL, 0, NULL} +}; + +static char __Entry_tagtype_doc__[] = \ +"The tag type of the current entry\n" \ +"\n" \ +"This is one of:\n" \ +" - ACL_UNDEFINED_TAG\n" \ +" - ACL_USER_OBJ\n" \ +" - ACL_USER\n" \ +" - ACL_GROUP_OBJ\n" \ +" - ACL_GROUP\n" \ +" - ACL_MASK\n" \ +" - ACL_OTHER\n" \ +; + +static char __Entry_qualifier_doc__[] = \ +"The qualifier of the current entry\n" \ +"\n" \ +"If the tag type is ACL_USER, this should be a user id.\n" \ +"If the tag type if ACL_GROUP, this should be a group id.\n" \ +"Else, it doesn't matter.\n" \ +; + +static char __Entry_parent_doc__[] = \ +"The parent ACL of this entry\n" \ +; + +static char __Entry_permset_doc__[] = \ +"The permission set of this ACL entry\n" \ +; + +/* Entry getset */ +static PyGetSetDef Entry_getsets[] = { + {"tag_type", Entry_get_tag_type, Entry_set_tag_type, __Entry_tagtype_doc__}, + {"qualifier", Entry_get_qualifier, Entry_set_qualifier, __Entry_qualifier_doc__}, + {"parent", Entry_get_parent, NULL, __Entry_parent_doc__}, + {"permset", Entry_get_permset, Entry_set_permset, __Entry_permset_doc__}, + {NULL} +}; + +static char __Entry_Type_doc__[] = \ +"Type which represents an entry in an ACL.\n" \ +"\n" \ +"The type exists only if the OS has full support for POSIX.1e\n" \ +"Can be created either by:\n" \ +" e = posix1e.Entry(myACL) # this creates a new entry in the ACL\n" \ +"or by:\n" \ +" for entry in myACL:\n" \ +" print entry\n" \ +"\n" \ +"Note that the Entry keeps a reference to its ACL, so even if \n" \ +"you delete the ACL, it won't be cleaned up and will continue to \n" \ +"exist until its Entry(ies) will be deleted.\n" \ +; +/* The definition of the Entry Type */ +static PyTypeObject Entry_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "posix1e.Entry", + sizeof(Entry_Object), + 0, + Entry_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + Entry_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + __Entry_Type_doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Entry_methods, /* tp_methods */ + 0, /* tp_members */ + Entry_getsets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + Entry_init, /* tp_init */ + 0, /* tp_alloc */ + Entry_new, /* tp_new */ +}; + +/* Permset type methods */ +static PyMethodDef Permset_methods[] = { + {"clear", Permset_clear, METH_NOARGS, __Permset_clear_doc__, }, + {"add", Permset_add, METH_VARARGS, __Permset_add_doc__, }, + {"delete", Permset_delete, METH_VARARGS, __Permset_delete_doc__, }, + {"test", Permset_test, METH_VARARGS, __Permset_test_doc__, }, + {NULL, NULL, 0, NULL} +}; + +static char __Permset_execute_doc__[] = \ +"Execute permsission\n" \ +"\n" \ +"This is a convenience method of access; the \n" \ +"same effect can be achieved using the functions\n" \ +"add(), test(), delete(), and those can take any \n" \ +"permission defined by your platform.\n" \ +; + +static char __Permset_read_doc__[] = \ +"Read permsission\n" \ +"\n" \ +"This is a convenience method of access; the \n" \ +"same effect can be achieved using the functions\n" \ +"add(), test(), delete(), and those can take any \n" \ +"permission defined by your platform.\n" \ +; + +static char __Permset_write_doc__[] = \ +"Write permsission\n" \ +"\n" \ +"This is a convenience method of access; the \n" \ +"same effect can be achieved using the functions\n" \ +"add(), test(), delete(), and those can take any \n" \ +"permission defined by your platform.\n" \ +; + +/* Permset getset */ +static PyGetSetDef Permset_getsets[] = { + {"execute", Permset_get_right, Permset_set_right, \ + __Permset_execute_doc__, &holder_ACL_EXECUTE}, + {"read", Permset_get_right, Permset_set_right, \ + __Permset_read_doc__, &holder_ACL_READ}, + {"write", Permset_get_right, Permset_set_right, \ + __Permset_write_doc__, &holder_ACL_WRITE}, + {NULL} +}; + +static char __Permset_Type_doc__[] = \ +"Type which represents the permission set in an ACL entry\n" \ +"\n" \ +"The type exists only if the OS has full support for POSIX.1e\n" \ +"Can be created either by:\n" \ +" perms = myEntry.permset\n" \ +"or by:\n" \ +" perms = posix1e.Permset(myEntry)\n" \ +"\n" \ +"Note that the Permset keeps a reference to its Entry, so even if \n" \ +"you delete the entry, it won't be cleaned up and will continue to \n" \ +"exist until its Permset will be deleted.\n" \ +; + +/* The definition of the Permset Type */ +static PyTypeObject Permset_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "posix1e.Permset", + sizeof(Permset_Object), + 0, + Permset_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + Permset_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + __Permset_Type_doc__,/* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + Permset_methods, /* tp_methods */ + 0, /* tp_members */ + Permset_getsets, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + Permset_init, /* tp_init */ + 0, /* tp_alloc */ + Permset_new, /* tp_new */ +}; + +#endif + +/* Module methods */ + +static char __deletedef_doc__[] = \ +"Delete the default ACL from a directory.\n" \ +"\n" \ +"This function deletes the default ACL associated with \n" \ +"a directory (the ACL which will be ANDed with the mode\n" \ +"parameter to the open, creat functions).\n" \ +"Parameters:\n" \ +" - a string representing the directory whose default ACL\n" \ +" should be deleted\n" \ +; + +/* Deletes the default ACL from a directory */ +static PyObject* aclmodule_delete_default(PyObject* obj, PyObject* args) { + char *filename; + + /* Parse the arguments */ + if (!PyArg_ParseTuple(args, "s", &filename)) + return NULL; + + if(acl_delete_def_file(filename) == -1) { + return PyErr_SetFromErrno(PyExc_IOError); + } + + /* Return the result */ + Py_INCREF(Py_None); + return Py_None; +} + +/* The module methods */ +static PyMethodDef aclmodule_methods[] = { + {"delete_default", aclmodule_delete_default, METH_VARARGS, __deletedef_doc__}, + {NULL, NULL, 0, NULL} +}; + +static char __posix1e_doc__[] = \ +"POSIX.1e ACLs manipulation\n" \ +"\n" \ +"This module provides support for manipulating POSIX.1e ACLS\n" \ +"\n" \ +"Depending on the operating system support for POSIX.1e, \n" \ +"the ACL type will have more or less capabilities:\n" \ +" - level 1, only basic support, you can create\n" \ +" ACLs from files and text descriptions;\n" \ +" once created, the type is immutable\n" \ +" - level 2, complete support, you can alter\n"\ +" the ACL once it is created\n" \ +"\n" \ +"Also, in level 2, more types are available, corresponding\n" \ +"to acl_entry_t (Entry type), acl_permset_t (Permset type).\n" \ +"\n" \ +"Example:\n" \ +">>> import posix1e\n" \ +">>> acl1 = posix1e.ACL(file=\"file.txt\") \n" \ +">>> print acl1\n" \ +"user::rw-\n" \ +"group::rw-\n" \ +"other::r--\n" \ +"\n" \ +">>> b = posix1e.ACL(text=\"u::rx,g::-,o::-\")\n" \ +">>> print b\n" \ +"user::r-x\n" \ +"group::---\n" \ +"other::---\n" \ +"\n" \ +">>> b.applyto(\"file.txt\")\n" \ +">>> print posix1e.ACL(file=\"file.txt\")\n" \ +"user::r-x\n" \ +"group::---\n" \ +"other::---\n" \ +"\n" \ +">>>\n" \ +; + +void initposix1e(void) { + PyObject *m, *d; + + ACL_Type.ob_type = &PyType_Type; + if(PyType_Ready(&ACL_Type) < 0) + return; + +#ifdef HAVE_LEVEL2 + Entry_Type.ob_type = &PyType_Type; + if(PyType_Ready(&Entry_Type) < 0) + return; + + Permset_Type.ob_type = &PyType_Type; + if(PyType_Ready(&Permset_Type) < 0) + return; +#endif + + m = Py_InitModule3("posix1e", aclmodule_methods, __posix1e_doc__); + + d = PyModule_GetDict(m); + if (d == NULL) + return; + + Py_INCREF(&ACL_Type); + if (PyDict_SetItemString(d, "ACL", + (PyObject *) &ACL_Type) < 0) + return; + + /* 23.3.6 acl_type_t values */ + PyModule_AddIntConstant(m, "ACL_TYPE_ACCESS", ACL_TYPE_ACCESS); + PyModule_AddIntConstant(m, "ACL_TYPE_DEFAULT", ACL_TYPE_DEFAULT); + + +#ifdef HAVE_LEVEL2 + Py_INCREF(&Entry_Type); + if (PyDict_SetItemString(d, "Entry", + (PyObject *) &Entry_Type) < 0) + return; + + Py_INCREF(&Permset_Type); + if (PyDict_SetItemString(d, "Permset", + (PyObject *) &Permset_Type) < 0) + return; + + /* 23.2.2 acl_perm_t values */ + PyModule_AddIntConstant(m, "ACL_READ", ACL_READ); + PyModule_AddIntConstant(m, "ACL_WRITE", ACL_WRITE); + PyModule_AddIntConstant(m, "ACL_EXECUTE", ACL_EXECUTE); + + /* 23.2.5 acl_tag_t values */ + PyModule_AddIntConstant(m, "ACL_UNDEFINED_TAG", ACL_UNDEFINED_TAG); + PyModule_AddIntConstant(m, "ACL_USER_OBJ", ACL_USER_OBJ); + PyModule_AddIntConstant(m, "ACL_USER", ACL_USER); + PyModule_AddIntConstant(m, "ACL_GROUP_OBJ", ACL_GROUP_OBJ); + PyModule_AddIntConstant(m, "ACL_GROUP", ACL_GROUP); + PyModule_AddIntConstant(m, "ACL_MASK", ACL_MASK); + PyModule_AddIntConstant(m, "ACL_OTHER", ACL_OTHER); + +#endif +} diff --git a/os_linux.c b/os_linux.c new file mode 100644 index 0000000..1fb7203 --- /dev/null +++ b/os_linux.c @@ -0,0 +1,6 @@ +#include + +int get_perm(acl_permset_t permset, acl_perm_t perm) +{ + return acl_get_perm(permset, perm); +} diff --git a/posix1e.html b/posix1e.html new file mode 100644 index 0000000..9b488ff --- /dev/null +++ b/posix1e.html @@ -0,0 +1,414 @@ + + +Python: module posix1e + + + + +
 
+ 
posix1e
index
/home/iusty/work/pylibacl/build/lib.linux-i686-2.2/posix1e.so
+

POSIX.1e ACLs manipulation

+This module provides support for manipulating POSIX.1e ACLS

+Depending on the operating system support for POSIX.1e, 
+the ACL type will have more or less capabilities:
+  - level 1, only basic support, you can create
+    ACLs from files and text descriptions;
+    once created, the type is immutable
+  - level 2, complete support, you can alter
+    the ACL once it is created

+Also, in level 2, more types are available, corresponding
+to acl_entry_t (Entry type), acl_permset_t (Permset type).

+Example:
+>>> import posix1e
+>>> acl1 = posix1e.ACL(file="file.txt") 
+>>> print acl1
+user::rw-
+group::rw-
+other::r--

+>>> b = posix1e.ACL(text="u::rx,g::-,o::-")
+>>> print b
+user::r-x
+group::---
+other::---

+>>> b.applyto("file.txt")
+>>> print posix1e.ACL(file="file.txt")
+user::r-x
+group::---
+other::---

+>>>

+ + + + + + +
 
+Classes
            
+
__builtin__.object +
+
+
ACL +
Entry +
Permset +
+
+
+ + + + + + + + +
 
+class ACL(__builtin__.object)
     Type which represents a POSIX ACL

+Parameters:
+  Only one keword parameter should be provided:
+  - file="...", meaning create ACL representing
+    the access ACL of that file
+  - filedef="...", meaning create ACL representing
+    the default ACL of that directory
+  - fd=<int>, meaning create ACL representing
+    the access ACL of that file descriptor
+  - text="...", meaning create ACL from a 
+    textual description
+  - acl=<ACL instance>, meaning create a copy
+    of an existing ACL instance
+If no parameters are passed, create an empty ACL; this
+makes sense only when your OS supports ACL modification
+ (i.e. it implements full POSIX.1e support)
 
  Methods defined here:
+
__getstate__(...)
Dumps the ACL to an external format.
+ +
__init__(...)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
+ +
__iter__(...)
x.__iter__() <==> iter(x)
+ +
__setstate__(...)
Loads the ACL from an external format.
+ +
__str__(...)
x.__str__() <==> str(x)
+ +
append(...)
Append a new Entry to the ACL and return it.

+This is a convenience function to create a new Entry 
+and append it to the ACL.
+If a parameter of type Entry instance is given, the 
+entry will be a copy of that one (as if copied with 
+Entry.copy()), otherwise, the new entry will be empty.
+ +
applyto(...)
Apply the ACL to a file or filehandle.

+Parameters:
+  - either a filename or a file-like object or an integer; this
+    represents the filesystem object on which to act
+  - optional flag representing the type of ACL to set, either
+    ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT
+ +
calc_mask(...)
Compute the file group class mask.

+The calc_mask() method calculates and sets the permissions 
+associated with the ACL_MASK Entry of the ACL.
+The value of the new permissions is the union of the permissions 
+granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or 
+ACL_USER.  If the ACL already contains an ACL_MASK entry, its 
+permissions are overwritten; if it does not contain an ACL_MASK 
+Entry, one is added.

+The order of existing entries in the ACL is undefined after this 
+function.
+ +
delete_entry(...)
Deletes an entry from the ACL.

+Note: Only with level 2
+Parameters:
+ - the Entry object which should be deleted; note that after
+   this function is called, that object is unusable any longer
+   and should be deleted
+ +
next(...)
x.next() -> the next value, or raise StopIteration
+ +
valid(...)
Test the ACL for validity.

+This method tests the ACL to see if it is a valid ACL
+in terms of the filesystem. More precisely, it checks:
+A valid ACL contains exactly one entry with each of the ACL_USER_OBJ,
+ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and
+ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that
+contains entries of ACL_USER or ACL_GROUP tag types must contain exactly
+one entry of the ACL_MASK tag type. If an ACL contains no entries of
+ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional.

+All user ID qualifiers must be unique among all entries of ACL_USER tag
+type, and all group IDs must be unique among all entries of ACL_GROUP tag
+type.

+The method will return 1 for a valid ACL and 0 for an invalid one.
+This has been chosen because the specification for acl_valid in POSIX.1e
+documents only one possible value for errno in case of an invalid ACL
+so we can't differentiate between classes of errors. Other suggestions 
+are welcome.
+ +
+Data and non-method functions defined here:
+
__doc__ = 'Type which represents a POSIX ACL\n\nParameters:\n ...tion\n (i.e. it implements full POSIX.1e support)\n'
str(object) -> string

+Return a nice string representation of the object.
+If the argument is a string, the return value is the same object.
+ +
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
+ +
+Methods inherited from __builtin__.object:
+
__delattr__(...)
x.__delattr__('name') <==> del x.name
+ +
__getattribute__(...)
x.__getattribute__('name') <==> x.name
+ +
__hash__(...)
x.__hash__() <==> hash(x)
+ +
__reduce__(...)
helper for pickle
+ +
__repr__(...)
x.__repr__() <==> repr(x)
+ +
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
+ +
+Data and non-method functions inherited from __builtin__.object:
+
__class__ = <type 'type'>
the object's class
+ +
+ + + + + + + +
 
+class Entry(__builtin__.object)
     Type which represents an entry in an ACL.

+The type exists only if the OS has full support for POSIX.1e
+Can be created either by:
+  e = posix1e.Entry(myACL) # this creates a new entry in the ACL
+or by:
+  for entry in myACL:
+      print entry

+Note that the Entry keeps a reference to its ACL, so even if 
+you delete the ACL, it won't be cleaned up and will continue to 
+exist until its Entry(ies) will be deleted.
 
  Methods defined here:
+
__init__(...)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
+ +
__str__(...)
x.__str__() <==> str(x)
+ +
copy(...)
Copy an ACL entry.

+This method sets all the parameters to those of another
+entry, even one of another's ACL
+Parameters:
+ - src, instance of type Entry
+ +
+Data and non-method functions defined here:
+
__doc__ = 'Type which represents an entry in an ACL.\n\nThe t... to \nexist until its Entry(ies) will be deleted.\n'
str(object) -> string

+Return a nice string representation of the object.
+If the argument is a string, the return value is the same object.
+ +
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
+ +
parent = <attribute 'parent' of 'posix1e.Entry' objects>
The parent ACL of this entry
+ +
permset = <attribute 'permset' of 'posix1e.Entry' objects>
The permission set of this ACL entry
+ +
qualifier = <attribute 'qualifier' of 'posix1e.Entry' objects>
The qualifier of the current entry

+If the tag type is ACL_USER, this should be a user id.
+If the tag type if ACL_GROUP, this should be a group id.
+Else, it doesn't matter.
+ +
tag_type = <attribute 'tag_type' of 'posix1e.Entry' objects>
The tag type of the current entry

+This is one of:
+ - ACL_UNDEFINED_TAG
+ - ACL_USER_OBJ
+ - ACL_USER
+ - ACL_GROUP_OBJ
+ - ACL_GROUP
+ - ACL_MASK
+ - ACL_OTHER
+ +
+Methods inherited from __builtin__.object:
+
__delattr__(...)
x.__delattr__('name') <==> del x.name
+ +
__getattribute__(...)
x.__getattribute__('name') <==> x.name
+ +
__hash__(...)
x.__hash__() <==> hash(x)
+ +
__reduce__(...)
helper for pickle
+ +
__repr__(...)
x.__repr__() <==> repr(x)
+ +
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
+ +
+Data and non-method functions inherited from __builtin__.object:
+
__class__ = <type 'type'>
the object's class
+ +
+ + + + + + + +
 
+class Permset(__builtin__.object)
     Type which represents the permission set in an ACL entry

+The type exists only if the OS has full support for POSIX.1e
+Can be created either by:
+  perms = myEntry.permset
+or by:
+  perms = posix1e.Permset(myEntry)

+Note that the Permset keeps a reference to its Entry, so even if 
+you delete the entry, it won't be cleaned up and will continue to 
+exist until its Permset will be deleted.
 
  Methods defined here:
+
__init__(...)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
+ +
__str__(...)
x.__str__() <==> str(x)
+ +
add(...)
Add a permission to the permission set.

+The add() function adds the permission contained in 
+the argument perm to the permission set.  An attempt 
+to add a permission that is already contained in the 
+permission set is not considered an error.
+Parameters:
+  - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...
+Return value:
+  None
+Can raise: IOError
+ +
clear(...)
Clear all permissions from the permission set.
+ +
delete(...)
Delete a permission from the permission set.

+The delete() function deletes the permission contained in 
+the argument perm from the permission set.  An attempt 
+to delete a permission that is not contained in the 
+permission set is not considered an error.
+Parameters:
+  - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...
+Return value:
+  None
+Can raise: IOError
+ +
test(...)
Test if a permission exists in the permission set.

+The test() function tests if the permission contained in 
+the argument perm exits the permission set.
+Parameters:
+  - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ...
+Return value:
+  Bool
+Can raise: IOError
+ +
+Data and non-method functions defined here:
+
__doc__ = 'Type which represents the permission set in an A...nue to \nexist until its Permset will be deleted.\n'
str(object) -> string

+Return a nice string representation of the object.
+If the argument is a string, the return value is the same object.
+ +
__new__ = <built-in method __new__ of type object>
T.__new__(S, ...) -> a new object with type S, a subtype of T
+ +
execute = <attribute 'execute' of 'posix1e.Permset' objects>
Execute permsission

+This is a convenience method of access; the 
+same effect can be achieved using the functions
+add(), test(), delete(), and those can take any 
+permission defined by your platform.
+ +
read = <attribute 'read' of 'posix1e.Permset' objects>
Read permsission

+This is a convenience method of access; the 
+same effect can be achieved using the functions
+add(), test(), delete(), and those can take any 
+permission defined by your platform.
+ +
write = <attribute 'write' of 'posix1e.Permset' objects>
Write permsission

+This is a convenience method of access; the 
+same effect can be achieved using the functions
+add(), test(), delete(), and those can take any 
+permission defined by your platform.
+ +
+Methods inherited from __builtin__.object:
+
__delattr__(...)
x.__delattr__('name') <==> del x.name
+ +
__getattribute__(...)
x.__getattribute__('name') <==> x.name
+ +
__hash__(...)
x.__hash__() <==> hash(x)
+ +
__reduce__(...)
helper for pickle
+ +
__repr__(...)
x.__repr__() <==> repr(x)
+ +
__setattr__(...)
x.__setattr__('name', value) <==> x.name = value
+ +
+Data and non-method functions inherited from __builtin__.object:
+
__class__ = <type 'type'>
the object's class
+ +
+ + + + + +
 
+Functions
            
delete_default(...)
Delete the default ACL from a directory.

+This function deletes the default ACL associated with 
+a directory (the ACL which will be ANDed with the mode
+parameter to the open, creat functions).
+Parameters:
+  - a string representing the directory whose default ACL
+    should be deleted
+
+ + + + + +
 
+Data
            ACL_EXECUTE = 1
+ACL_GROUP = 8
+ACL_GROUP_OBJ = 4
+ACL_MASK = 16
+ACL_OTHER = 32
+ACL_READ = 4
+ACL_TYPE_ACCESS = 32768
+ACL_TYPE_DEFAULT = 16384
+ACL_UNDEFINED_TAG = 0
+ACL_USER = 2
+ACL_USER_OBJ = 1
+ACL_WRITE = 2
+__file__ = '/home/iusty/work/pylibacl/build/lib.linux-i686-2.2/posix1e.so'
+__name__ = 'posix1e'
+ \ No newline at end of file diff --git a/posix1e.txt b/posix1e.txt new file mode 100644 index 0000000..7657830 --- /dev/null +++ b/posix1e.txt @@ -0,0 +1,443 @@ +Python Library Documentation: module posix1e + +NAME + posix1e - POSIX.1e ACLs manipulation + +FILE + /home/iusty/work/pylibacl/build/lib.linux-i686-2.2/posix1e.so + +DESCRIPTION + This module provides support for manipulating POSIX.1e ACLS + + Depending on the operating system support for POSIX.1e, + the ACL type will have more or less capabilities: + - level 1, only basic support, you can create + ACLs from files and text descriptions; + once created, the type is immutable + - level 2, complete support, you can alter + the ACL once it is created + + Also, in level 2, more types are available, corresponding + to acl_entry_t (Entry type), acl_permset_t (Permset type). + + Example: + >>> import posix1e + >>> acl1 = posix1e.ACL(file="file.txt") + >>> print acl1 + user::rw- + group::rw- + other::r-- + + >>> b = posix1e.ACL(text="u::rx,g::-,o::-") + >>> print b + user::r-x + group::--- + other::--- + + >>> b.applyto("file.txt") + >>> print posix1e.ACL(file="file.txt") + user::r-x + group::--- + other::--- + + >>> + +CLASSES + __builtin__.object + ACL + Entry + Permset + + class ACL(__builtin__.object) + | Type which represents a POSIX ACL + | + | Parameters: + | Only one keword parameter should be provided: + | - file="...", meaning create ACL representing + | the access ACL of that file + | - filedef="...", meaning create ACL representing + | the default ACL of that directory + | - fd=, meaning create ACL representing + | the access ACL of that file descriptor + | - text="...", meaning create ACL from a + | textual description + | - acl=, meaning create a copy + | of an existing ACL instance + | If no parameters are passed, create an empty ACL; this + | makes sense only when your OS supports ACL modification + | (i.e. it implements full POSIX.1e support) + | + | Methods defined here: + | + | __getstate__(...) + | Dumps the ACL to an external format. + | + | __init__(...) + | x.__init__(...) initializes x; see x.__class__.__doc__ for signature + | + | __iter__(...) + | x.__iter__() <==> iter(x) + | + | __setstate__(...) + | Loads the ACL from an external format. + | + | __str__(...) + | x.__str__() <==> str(x) + | + | append(...) + | Append a new Entry to the ACL and return it. + | + | This is a convenience function to create a new Entry + | and append it to the ACL. + | If a parameter of type Entry instance is given, the + | entry will be a copy of that one (as if copied with + | Entry.copy()), otherwise, the new entry will be empty. + | + | applyto(...) + | Apply the ACL to a file or filehandle. + | + | Parameters: + | - either a filename or a file-like object or an integer; this + | represents the filesystem object on which to act + | - optional flag representing the type of ACL to set, either + | ACL_TYPE_ACCESS (default) or ACL_TYPE_DEFAULT + | + | calc_mask(...) + | Compute the file group class mask. + | + | The calc_mask() method calculates and sets the permissions + | associated with the ACL_MASK Entry of the ACL. + | The value of the new permissions is the union of the permissions + | granted by all entries of tag type ACL_GROUP, ACL_GROUP_OBJ, or + | ACL_USER. If the ACL already contains an ACL_MASK entry, its + | permissions are overwritten; if it does not contain an ACL_MASK + | Entry, one is added. + | + | The order of existing entries in the ACL is undefined after this + | function. + | + | delete_entry(...) + | Deletes an entry from the ACL. + | + | Note: Only with level 2 + | Parameters: + | - the Entry object which should be deleted; note that after + | this function is called, that object is unusable any longer + | and should be deleted + | + | next(...) + | x.next() -> the next value, or raise StopIteration + | + | valid(...) + | Test the ACL for validity. + | + | This method tests the ACL to see if it is a valid ACL + | in terms of the filesystem. More precisely, it checks: + | A valid ACL contains exactly one entry with each of the ACL_USER_OBJ, + | ACL_GROUP_OBJ, and ACL_OTHER tag types. Entries with ACL_USER and + | ACL_GROUP tag types may appear zero or more times in an ACL. An ACL that + | contains entries of ACL_USER or ACL_GROUP tag types must contain exactly + | one entry of the ACL_MASK tag type. If an ACL contains no entries of + | ACL_USER or ACL_GROUP tag types, the ACL_MASK entry is optional. + | + | All user ID qualifiers must be unique among all entries of ACL_USER tag + | type, and all group IDs must be unique among all entries of ACL_GROUP tag + | type. + | + | The method will return 1 for a valid ACL and 0 for an invalid one. + | This has been chosen because the specification for acl_valid in POSIX.1e + | documents only one possible value for errno in case of an invalid ACL, + | so we can't differentiate between classes of errors. Other suggestions + | are welcome. + | + | ---------------------------------------------------------------------- + | Data and non-method functions defined here: + | + | __doc__ = 'Type which represents a POSIX ACL\n\nParameters:\n ...tion\... + | str(object) -> string + | + | Return a nice string representation of the object. + | If the argument is a string, the return value is the same object. + | + | __new__ = + | T.__new__(S, ...) -> a new object with type S, a subtype of T + | + | ---------------------------------------------------------------------- + | Methods inherited from __builtin__.object: + | + | __delattr__(...) + | x.__delattr__('name') <==> del x.name + | + | __getattribute__(...) + | x.__getattribute__('name') <==> x.name + | + | __hash__(...) + | x.__hash__() <==> hash(x) + | + | __reduce__(...) + | helper for pickle + | + | __repr__(...) + | x.__repr__() <==> repr(x) + | + | __setattr__(...) + | x.__setattr__('name', value) <==> x.name = value + | + | ---------------------------------------------------------------------- + | Data and non-method functions inherited from __builtin__.object: + | + | __class__ = + | the object's class + + class Entry(__builtin__.object) + | Type which represents an entry in an ACL. + | + | The type exists only if the OS has full support for POSIX.1e + | Can be created either by: + | e = posix1e.Entry(myACL) # this creates a new entry in the ACL + | or by: + | for entry in myACL: + | print entry + | + | Note that the Entry keeps a reference to its ACL, so even if + | you delete the ACL, it won't be cleaned up and will continue to + | exist until its Entry(ies) will be deleted. + | + | Methods defined here: + | + | __init__(...) + | x.__init__(...) initializes x; see x.__class__.__doc__ for signature + | + | __str__(...) + | x.__str__() <==> str(x) + | + | copy(...) + | Copy an ACL entry. + | + | This method sets all the parameters to those of another + | entry, even one of another's ACL + | Parameters: + | - src, instance of type Entry + | + | ---------------------------------------------------------------------- + | Data and non-method functions defined here: + | + | __doc__ = 'Type which represents an entry in an ACL.\n\nThe t... to \n... + | str(object) -> string + | + | Return a nice string representation of the object. + | If the argument is a string, the return value is the same object. + | + | __new__ = + | T.__new__(S, ...) -> a new object with type S, a subtype of T + | + | parent = + | The parent ACL of this entry + | + | + | permset = + | The permission set of this ACL entry + | + | + | qualifier = + | The qualifier of the current entry + | + | If the tag type is ACL_USER, this should be a user id. + | If the tag type if ACL_GROUP, this should be a group id. + | Else, it doesn't matter. + | + | + | tag_type = + | The tag type of the current entry + | + | This is one of: + | - ACL_UNDEFINED_TAG + | - ACL_USER_OBJ + | - ACL_USER + | - ACL_GROUP_OBJ + | - ACL_GROUP + | - ACL_MASK + | - ACL_OTHER + | + | + | ---------------------------------------------------------------------- + | Methods inherited from __builtin__.object: + | + | __delattr__(...) + | x.__delattr__('name') <==> del x.name + | + | __getattribute__(...) + | x.__getattribute__('name') <==> x.name + | + | __hash__(...) + | x.__hash__() <==> hash(x) + | + | __reduce__(...) + | helper for pickle + | + | __repr__(...) + | x.__repr__() <==> repr(x) + | + | __setattr__(...) + | x.__setattr__('name', value) <==> x.name = value + | + | ---------------------------------------------------------------------- + | Data and non-method functions inherited from __builtin__.object: + | + | __class__ = + | the object's class + + class Permset(__builtin__.object) + | Type which represents the permission set in an ACL entry + | + | The type exists only if the OS has full support for POSIX.1e + | Can be created either by: + | perms = myEntry.permset + | or by: + | perms = posix1e.Permset(myEntry) + | + | Note that the Permset keeps a reference to its Entry, so even if + | you delete the entry, it won't be cleaned up and will continue to + | exist until its Permset will be deleted. + | + | Methods defined here: + | + | __init__(...) + | x.__init__(...) initializes x; see x.__class__.__doc__ for signature + | + | __str__(...) + | x.__str__() <==> str(x) + | + | add(...) + | Add a permission to the permission set. + | + | The add() function adds the permission contained in + | the argument perm to the permission set. An attempt + | to add a permission that is already contained in the + | permission set is not considered an error. + | Parameters: + | - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ... + | Return value: + | None + | Can raise: IOError + | + | clear(...) + | Clear all permissions from the permission set. + | + | delete(...) + | Delete a permission from the permission set. + | + | The delete() function deletes the permission contained in + | the argument perm from the permission set. An attempt + | to delete a permission that is not contained in the + | permission set is not considered an error. + | Parameters: + | - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ... + | Return value: + | None + | Can raise: IOError + | + | test(...) + | Test if a permission exists in the permission set. + | + | The test() function tests if the permission contained in + | the argument perm exits the permission set. + | Parameters: + | - perm a permission (ACL_WRITE, ACL_READ, ACL_EXECUTE, ... + | Return value: + | Bool + | Can raise: IOError + | + | ---------------------------------------------------------------------- + | Data and non-method functions defined here: + | + | __doc__ = 'Type which represents the permission set in an A...nue to \... + | str(object) -> string + | + | Return a nice string representation of the object. + | If the argument is a string, the return value is the same object. + | + | __new__ = + | T.__new__(S, ...) -> a new object with type S, a subtype of T + | + | execute = + | Execute permsission + | + | This is a convenience method of access; the + | same effect can be achieved using the functions + | add(), test(), delete(), and those can take any + | permission defined by your platform. + | + | + | read = + | Read permsission + | + | This is a convenience method of access; the + | same effect can be achieved using the functions + | add(), test(), delete(), and those can take any + | permission defined by your platform. + | + | + | write = + | Write permsission + | + | This is a convenience method of access; the + | same effect can be achieved using the functions + | add(), test(), delete(), and those can take any + | permission defined by your platform. + | + | + | ---------------------------------------------------------------------- + | Methods inherited from __builtin__.object: + | + | __delattr__(...) + | x.__delattr__('name') <==> del x.name + | + | __getattribute__(...) + | x.__getattribute__('name') <==> x.name + | + | __hash__(...) + | x.__hash__() <==> hash(x) + | + | __reduce__(...) + | helper for pickle + | + | __repr__(...) + | x.__repr__() <==> repr(x) + | + | __setattr__(...) + | x.__setattr__('name', value) <==> x.name = value + | + | ---------------------------------------------------------------------- + | Data and non-method functions inherited from __builtin__.object: + | + | __class__ = + | the object's class + +FUNCTIONS + delete_default(...) + Delete the default ACL from a directory. + + This function deletes the default ACL associated with + a directory (the ACL which will be ANDed with the mode + parameter to the open, creat functions). + Parameters: + - a string representing the directory whose default ACL + should be deleted + +DATA + ACL_EXECUTE = 1 + ACL_GROUP = 8 + ACL_GROUP_OBJ = 4 + ACL_MASK = 16 + ACL_OTHER = 32 + ACL_READ = 4 + ACL_TYPE_ACCESS = 32768 + ACL_TYPE_DEFAULT = 16384 + ACL_UNDEFINED_TAG = 0 + ACL_USER = 2 + ACL_USER_OBJ = 1 + ACL_WRITE = 2 + __file__ = '/home/iusty/work/pylibacl/build/lib.linux-i686-2.2/posix1e... + __name__ = 'posix1e' + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..f8c1ed7 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[bdist_rpm] +release = 1 +requires = libacl +;build_requires = libacl libacl-devel diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..95231f8 --- /dev/null +++ b/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +import distutils, os +from distutils.core import setup, Extension + +(u_sysname, u_nodename, u_release, u_version, u_machine) = os.uname() + +macros = [] +libs = [] +if u_sysname == "Linux": + macros.append(("HAVE_LINUX", None)) + macros.append(("HAVE_LEVEL2", None)) + libs.append("acl") +elif u_sysname == "GNU/kFreeBSD": + macros.append(("HAVE_LINUX", None)) + macros.append(("HAVE_LEVEL2", None)) + libs.append("acl") +elif u_sysname == "FreeBSD": + macros.append(("HAVE_FREEBSD", None)) +else: + raise ValueError("I don't know your system '%s'." + " Please contact the author" % u_sysname) + +long_desc = """This is a C extension module for Python which +implements POSIX ACLs manipulation. It is a wrapper on top +of the systems's acl C library - see acl(5).""" +version = "0.2.2" +setup(name="pylibacl", + version=version, + description="POSIX.1e ACLs for python", + long_description=long_desc, + author="Iustin Pop", + author_email="iusty@k1024.org", + url="http://pylibacl.sourceforge.net", + license="GPL", + ext_modules=[Extension("posix1e", ["acl.c"], + libraries=libs, + define_macros=macros, + )], + data_files=[("/usr/share/doc/pylibacl-%s" % version, + ["README","IMPLEMENTATION", "PLATFORMS", + "BENCHMARK", + "posix1e.html", "posix1e.txt"])], + ) -- 2.39.2