[SOLVED] Working with Flags in libc


#1

Hi! I’m working on a wrapper type for ifaddrs, and I’ve created a struct of bools to represent the flags in ifa_flags. However, ifa_flags is of type c_uint a.k.a. u32 while the flags in libc (like libc::IFF_UP, et cetera) are i32. Both mem::transmuteing them and casting them causes an “off by one” issue:

Interface { name: "lo", flags: InterfaceFlags { up: false, broadcast: true, debug: true, loopback: false, point_to_point: true, running: false, noarp: true, promisc: true, notrailers: true, allmulti: true, master: true, slave: true, multicast: true, portsel: true, automedia: true, dynamic: true } }

Obviously this is not right; lo is a loopback interface, it is up, and it’s not point to point, et cetera. How do I correctly type my input flags to that I can to bitwise AND comparisons right?


#2

bool in struct in Rust will not translate to a bit. It will be a byte, and fields may even be randomly reordered unless you use #[repr(C)] on it. In any case, it can’t be transmuted to binary flags in an int.

If you want the struct this way, you’ll have to make the int the “hard way” with if ifa_flags.up {c_flags |= 1<<up_bit;}

There’s a bitflags crate that provides convenient access to such flags:

https://crates.io/crates/bitflags


#3

bool in struct in Rust will not translate to a bit. It will be a byte, and fields may even be randomly reordered unless you use #[repr©] on it. In any case, it can’t be transmuted to binary flags in an int.

I’m aware, the translation is one-way; that is, I want to turn bitflags into some bools. The code I’m using is like this:

let i = flag_int as i32; // I also tried mem::transmute()

return InterfaceFlags {
    ip: i & libc::IFF_UP == 0,
    broadcast: i & libc::IFF_BROADCAST == 0,
    // et cetera
}

#4

In this case, you need to compare the result of AND against 0 to get a bool out of it.


#5

Yes, I’m doing that; I just forgot to type it in, sorry. The code compiles, it just doesn’t produce the right result.

I guess the question I’m asking is: how do I compare the bits of an i32 to the bits of a u32, without casting moving them around? I thought that mem::transmute() would do that, but it seems like it doesn’t.


#6

You need to compare != 0 in your example code. Or is that a typo?


#7

Nope, that’s my problem. Thanks.

:man_facepalming: