1 """!Manipulates Access Control Lists (ACL)
3 This module is a wrapper around the C libacl library, which provides
4 support for POSIX Access Control Lists, as defined by the abandoned
5 draft standard "IEEE 1003.1e draft 17". Only the widely-supported
6 features are implemented. It is intended to be used with the Linux
7 libacl, but might be portable to other versions if the module-scope
8 acl_library variable is changed to the name of your "dll" or "so" file
9 for libacl and values of ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT are
10 changed. In addition, one must change the means by which errno is
11 accessed if switching from glibc to another C library."""
13 import ctypes, os, stat
16 """!Superclass of any ACL errors"""
18 """!ACLError constructor
19 @param message the description of the error
20 @param errno the system errno from the error"""
21 super(ACLError,self).
__init__(message)
27 """!Raised when the libacl library could not be loaded."""
28 class ACLMissingError(ACLError):
29 """!Raised when a function that requires an ACL object received
30 None, or an invalid ACL."""
32 """!Raised when libacl cannot convert an ACL to text."""
34 """!Raised when the libacl library could not get a file's ACL."""
36 """!Raised when the libacl library could not set a file's ACL."""
54 ACL_TYPE_DEFAULT=16384
60 acl_library=
'libacl.so.1'
77 """!Loads the libc library.
79 Loads the standard C library, which is needed to test the value of
80 errno in order to report errors. This function is called
81 automatically when needed; you should never need to call it
85 libc=ctypes.cdll.LoadLibrary(c_library)
86 get_errno_loc = libc.__errno_location
87 get_errno_loc.restype = ctypes.POINTER(ctypes.c_int)
88 except EnvironmentError
as e:
92 'Cannot find libc. The ctypes.cdll.LoadLibrary(%s) returned None.'
95 get_errno=
lambda: get_errno_loc()[0]
98 """!Loads the libacl library.
100 Loads the libacl library whose name is specified in the module
101 scope acl_library variable. This function is called automatically
102 when needed; you should never need to call it directly."""
108 libacl=ctypes.cdll.LoadLibrary(acl_library)
109 except EnvironmentError
as e:
112 raise ACLLibraryError(
'Cannot find libacl. The ctypes.cdll.LoadLibrary(%s) returned None.'%(repr(acl_library),))
115 libacl.acl_get_fd.argtypes=[ ctypes.c_int ]
116 libacl.acl_get_fd.restype=ctypes.c_void_p
118 libacl.acl_get_file.argtypes=[ ctypes.c_char_p, ctypes.c_int ]
119 libacl.acl_get_file.restype=ctypes.c_void_p
121 libacl.acl_from_text.argtypes=[ ctypes.c_char_p ]
122 libacl.acl_from_text.restype=ctypes.c_void_p
124 libacl.acl_to_text.argtypes=[ ctypes.c_int, ctypes.c_void_p ]
125 libacl.acl_to_text.restype=ctypes.c_char_p
127 libacl.acl_set_fd.argtypes=[ ctypes.c_int, ctypes.c_void_p ]
128 libacl.acl_set_fd.restype=ctypes.c_int
130 libacl.acl_set_file.argtypes=[ ctypes.c_char_p, ctypes.c_int, ctypes.c_void_p ]
131 libacl.acl_set_file.restype=ctypes.c_int
133 libacl.acl_free.argtypes=[ ctypes.c_void_p ]
134 libacl.acl_free.restype=ctypes.c_int
140 """!Inquire and manipulate access control lists (ACLs).
142 Represents a POSIX Access Control List (ACL). This is a wrapper
143 around the libacl library, and implements only widely-supported
144 ACL features. Data is stored internally in C structures, which
145 are allocated and freed automatically as needed."""
147 """!Create a blank, invalid, ACL. You should use the various
148 from_* routines to fill it with valid data."""
153 """!Free the memory used by the ACL in libacl."""
156 """!Frees resources used by the libacl library to store this
157 ACL's underlying C structures."""
161 self.__libacl.acl_free(self.
__acl)
165 """!Returns True if this ACL has data, and False otherwise."""
166 return self.
__acl is not None and self.
__acl!=0
168 """!Attempts to convert the given string to an ACL, storing the
169 result in this object. Any prior ACL information in this
170 object will be freed.
171 @param acl the access control list description"""
174 cacl=ctypes.c_char_p(sacl)
175 self.
__acl=self.__libacl.acl_from_text(cacl)
181 shortacl=sacl[0:17]+
'...'
182 raise ACLCannotGet(
'Cannot convert to acl: %s. String: %s'
183 %(os.strerror(errno),repr(shortacl)),errno)
186 """!Copies the files's ACL into this object.
188 Specify which type of access control list via the second
189 argument: ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT. Any prior ACL
190 information in this object will be freed.
191 @param filename the name of the file whose ACL is desired
192 @param which which access control list is desired;
193 ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT.
196 sfilename=str(filename)
197 cfilename=ctypes.c_char_p(sfilename)
198 self.
__acl=self.__libacl.acl_get_file(filename,which)
203 %(sfilename,os.strerror(errno)),errno)
206 """!Get an access control list from a file descriptor.
208 Obtains an Access Control List from the specified file object
209 or file descriptor number. You can also pass any object that
210 has a "fileno()" member function. Any prior ACL information
211 in this object will be freed.
212 @param fd an integer file descriptor or a file object.
214 if hasattr(fd,
'fileno'): fd=fd.fileno()
216 cfd=ctypes.c_int(ifd)
217 self.
__acl=self.__libacl.acl_get_fd(cfd)
221 raise ACLCannotGet(
'file descriptor %d: cannot get acl: %s'
222 %(ifd,os.strerror(errno)),errno)
225 """!Updates a file's file descriptor.
227 Sets the ACL for the specified file descriptor to the ACL
228 stored in this object. Raises ACLMissingError if this object
229 has no ACL information.
230 @param fd an integer file descriptor or open file object"""
233 "to_fd: caller tried to set a file descriptor's ACL to an invalid ACL: %s"
234 %(os.strerror(errno),),errno)
235 if hasattr(fd,
'fileno'):
238 cfd=ctypes.c_int(ifd)
239 r=self.__libacl.acl_set_fd(cfd,self.
__acl)
241 if r
is not None and r!=0:
242 raise ACLCannotSet(
'file descriptor %d: cannot set acl: %s'
243 %(ifd,os.strerror(errno)),errno)
245 def to_file(self,filename,access=ACL_TYPE_ACCESS):
246 """!Updates a file's access control list.
248 Sets the ACL for the specified file to the ACL stored in this
249 object. Specify access=ACL_TYPE_DEFAULT to obtain the default
250 access control list (Default ACL) or ACL_TYPE_ACCESS for the
251 access control list. Raises ACLMissingError if this object
252 has no ACL information.
254 @param filename the name of the file whose ACL is to be updated
255 @param access ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT"""
258 "Tried to set a file's ACL, while providing an invalid ACL.",
261 cfn=ctypes.c_char_p(sfn)
262 r=self.__libacl.acl_set_file(cfn,access,self.
__acl)
264 if r
is not None and r!=0:
266 %(sfn,os.strerror(errno)),errno)
269 """!Converts an ACL to text.
271 Returns a string representation of this ACL from acl_to_text.
272 Returns the empty string ('') if this ACL has no data."""
273 if self.
__acl is None or self.
__acl==0:
return ''
274 size=ctypes.c_ulonglong(0)
275 textified=self.__libacl.acl_to_text(self.
__acl,ctypes.byref(size))
277 if textified==0
or textified
is None:
279 'Cannot convert ACL to a string: acl_to_text returned NULL: %s'
280 %(os.strerror(errno),), errno)
283 (
'Cannot convert ACL to a string: acl_to_text size was %d'
284 ' (but return value was non-NULL): %s')
285 %(int(size),os.strerror(errno)), errno)
286 retstr=ctypes.string_at(textified)
287 self.__libacl.acl_free(textified)
291 """! => self.to_text() """
298 """!Returns a string representation of the given access control
300 @param acl an ACL object
301 @returns the string equivalent"""
305 """!Returns an object that represents the access control list for
307 @param filename the name of the file of interest
308 @param access ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT
310 return ACL().from_file(filename,access)
313 """!Returns an object that represents the access control list for
314 an open file descriptor.
315 @param fd the integer file descriptor or open file object
316 @returns a new ACL object"""
317 return ACL().from_fd(fd)
320 """!Sets the named file's access control list.
321 @param filename the name of the file of interest
322 @param acl the destination ACL object
323 @param access ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT
325 return acl.to_file(filename)
328 """!Given an open file descriptor, sets the corresponding file's
330 @param fd the file descriptor or file object
331 @param acl the ACL object to change
336 """!Converts text to an access control list.
337 @param txt a text access control list
338 @returns a new ACL object"""
339 return ACL().from_text(txt)
345 """!Copy an access control list from one object to another
347 Copies a POSIX Access Control List (ACL) from one open file to
348 another. The arguments should be either UNIX file descriptors, or
349 the return values from open(). This routine is quicker than using
350 the ACL() object due to avoidance of creating unnecessary Python
351 objects. However, the access control list information is
352 discarded in this routine, so it can only be used when the sole
353 need is to copy the information from one file to another.
354 @param fromfd the source file descriptor
355 @param tofd the target file descriptor"""
356 if hasattr(fromfd,
'fileno'): fromfd=fromfd.fileno()
357 if hasattr(tofd,
'fileno'): tofd=tofd.fileno()
361 cfrom=ctypes.c_int(int(fromfd))
362 cdto=ctypes.c_int(int(tofd))
363 acl=libacl.acl_get_fd(cfrom)
365 if acl
is None or acl==0:
367 'Cannot read acl from descriptor %s: acl_get_fd returned NULL: %s'
368 %(repr(fromfd),os.strerror(errno)), errno)
369 res=libacl.acl_set_fd(cto,acl)
371 if res
is None or res!=0:
372 raise ACLCannotSet(
'Cannot set acl to descriptor %s: %s'
373 %(repr(getfd),os.strerror(errno)), errno)
375 if acl
is not None and acl!=0:
Superclass of any ACL errors.
def acl_set_file
Sets the named file's access control list.
def acl_set_fd(fd, acl)
Given an open file descriptor, sets the corresponding file's access control list. ...
def to_fd(self, fd)
Updates a file's file descriptor.
def __init__(self, message, errno)
ACLError constructor.
def acl_to_text(acl)
Returns a string representation of the given access control list object.
def have_acl(self)
Returns True if this ACL has data, and False otherwise.
def load_libc()
Library loading routine:
def __del__(self)
Free the memory used by the ACL in libacl.
Raised when the libacl library could not get a file's ACL.
Raised when the libacl library could not set a file's ACL.
def from_file
Copies the files's ACL into this object.
Raised when a function that requires an ACL object received None, or an invalid ACL.
def copy_acl_fd(fromfd, tofd)
Simplified wrappers that perform common tasks:
Raised when the libacl library could not be loaded.
def to_file
Updates a file's access control list.
def from_fd(self, fd)
Get an access control list from a file descriptor.
errno
The errno value when the error happened.
def __str__(self)
=> self.to_text()
def acl_get_fd(fd)
Returns an object that represents the access control list for an open file descriptor.
get_errno
Function that returns the value of errno.
def to_text(self)
Converts an ACL to text.
def __init__(self)
Create a blank, invalid, ACL.
def from_text(self, acl)
Attempts to convert the given string to an ACL, storing the result in this object.
def free(self)
Frees resources used by the libacl library to store this ACL's underlying C structures.
def acl_get_file
Returns an object that represents the access control list for the specified file. ...
def load_libacl()
Loads the libacl library.
def acl_from_text(txt)
Converts text to an access control list.
ACL class wrapped around the libacl library:
Raised when libacl cannot convert an ACL to text.