Python 3.3 comes with os.getxattr
. If not, yeah... one way would be using ctypes
, at least to get the raw stuff, or maybe use pyxattr
For pyxattr
:
>>> import xattr
>>> xattr.listxattr("/bin/ping")
(u'security.capability',)
>>> xattr.getxattr("/bin/ping", "security.capability")
'\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
For Python 3.3's version, it's essentially the same, just importing os
, instead of xattr
. ctypes
is a bit more involved, though.
Now, we're getting the raw result, meaning that those two are most useful only retrieving textual attributes. But... we can use the same approach of getcap
, through libcap
itself [warning, this will work as-is only on Python 2, as written originally - read the note at the end for details]:
import ctypes
libcap = ctypes.cdll.LoadLibrary("libcap.so")
cap_t = libcap.cap_get_file('/bin/ping')
libcap.cap_to_text.restype = ctypes.c_char_p
libcap.cap_to_text(cap_t, None)
which gives me:
'= cap_net_raw+p'
probably more useful for you.
PS: note that cap_to_text
returns a malloc
ed string. It's your job to deallocate it using cap_free
Hint about the "binary gibberish":
>>> import struct
>>> caps = '\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> struct.unpack("<IIIII", caps)
(33554432, 8192, 0, 0, 0)
In that 8192
, the only active bit is the 13th. If you go to linux/capability.h
, you'll see that CAP_NET_RAW
is defined at 13
.
Now, if you want to write a module with all those constants, you can decode the info. But I'd say it's much more laborious than just using ctypes
+ libcap
.
PS2: I notice another answer mentioning that there are problems with my invocation on the ctype
solution. That's because I likely wrote that using Python 2.x back then in 2014 (as Python 3 offered os.getxattr
).
The key here is reminding that back in Python 2.x there were no bytes
objects, and str
and unicode
where separate entities. Python 3.x merged those two so that str
is now basically unicode
, and that may mess up with the C interface.
So, if using Python 3 (likely the case at this point), make sure to turn your strings into bytes
(e.g., foo_bar.encode('utf-8')
) before passing them to libcap
, and the reverse operation with the results.
/bin/ping
? – Oldtime