I was recently looking at some C code and 'translating' to Python but got stuck at a particular function called _IOR
. It is defined in sys/ioctl.h
like so:
#define _IOC(inout,group,num,len) \
(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t))
And I have seen it called in these ways:
_IOR('t', 3, int)
_IOR('keys', 1, unsigned char *)
The 'keys' call is the one I need to do. Looks like it's doing a bitwise operation on a string.
I managed to find equivalent Python code to the above but it only works for a single character.
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_DIRBITS = 2
_IOC_NRSHIFT = 0
_IOC_TYPESHIFT =(_IOC_NRSHIFT+_IOC_NRBITS)
_IOC_SIZESHIFT =(_IOC_TYPESHIFT+_IOC_TYPEBITS)
_IOC_DIRSHIFT =(_IOC_SIZESHIFT+_IOC_SIZEBITS)
_IOC_NONE = 0
_IOC_WRITE = 1
_IOC_READ = 2
def _IOC(direction,type,nr,size):
return (((direction) << _IOC_DIRSHIFT) |
((type) << _IOC_TYPESHIFT) |
((nr) << _IOC_NRSHIFT) |
((size) << _IOC_SIZESHIFT))
def _IOR(type, number, size):
return _IOC(_IOC_READ, type, number, size)
This works for single character calls.
_IOR(ord('t'), 3, 1)
But I don't know the equivalent of the second call with 'keys'. Is there a way to do this C call below in Python?
_IOR('keys', 1, unsigned char *)
The number you're getting from running on a char* isn't guaranteed to be any specific number. The macro is treating the address of the string as an integer when computing _IOR for
keys
. The result will change depending on wherekeys
lives in the stack. As a result there's really not a good replacement for this functionality in Python.From the docs for _IOR(g, n, t):
The intended use of the function is to take a byte as the first argument (via character or integer types). That being said, 'keys' was probably getting assigned to some random group. I would pick a group which you think won't be already taken (or go lookup the group it's currently be assigned to in your C code and use that number) in place of
keys
.Alternatively you could always just take the first character of the input string and treat that as the group id.
Then
_IOR('t', 3, 1)
and_IOR('keys', 1, 1)
would both still run, though the group assignments won't be identical to the C macro. But since the macro was being misused for thekeys
assignment I don't think this will be a problem.