I’m confused about a) how the Linux ioctl command seems to be overloaded with either pointers or longs, and how b) rust gets away with just passing raw
*mut u8 pointers on, no matter what.
I am trying to understand how rust-i2cdev makes
ioctl calls like this one here: https://github.com/rust-embedded/rust-i2cdev/blob/master/src/ffi.rs#L182
As you can see, the last argument is a raw
*mut u8, which is the
data argument in the macro definition here: https://github.com/nix-rust/nix/blob/60370990485092b4d7cbe625b964001e912dea9a/src/sys/ioctl/platform/linux.rs#L93
I don’t really understand how and why this works. On the one hand,
ioctl(2) says that:
The third argument is an untyped pointer to memory. It’s traditionally char *argp (from the days before void * was valid C), and will be so named for this discussion.
On the other hand, this and some other sources talk about one being able to pass either an
unsigned long or a pointer, and this being some kind of hack.
Stranger still, the Linux i2c-dev docs mention that the particular ioctl call above takes a long: https://www.kernel.org/doc/Documentation/i2c/dev-interface
So what is it? Does it take a pointer or a long? And if it takes on or the other, how does rust get away with passing it a raw pointer, no matter what, even if in this case it should get a long?