I make an ioctl call from C ++ to a driver that I donβt own / don't support, and I'm trying to figure out if there is a clean, "safe" mechanism for working with some of which requires an ugly distribution of the structure.
Broken version of some involved structures
// IOCTL expects an instance of this structure "first" typedef struct { int param1; int param2; } s_ioctl_request; //... followed by an instance of this. If attr_length // is > sizeof(s_attr_header), more data is allowed to follow. typedef struct { uint32_t attr_length; uint32_t attr_type; } s_attr_header; // Example that uses more data than just the header. typedef struct { s_attr_header hdr; uint32_t attr_param; } s_attr_type1; // Another example. typedef struct { s_attr_header hdr; uint32_t attr_param1; uint32_t attr_param2; } s_attr_type2;
s_ioctl_request immediately followed by s_attr_header or another structure containing it, where attr_length is the size of the external structure in bytes.
In C , to write a wrapper for ioctl , this will be done through something in these lines:
int do_ugly_ioctl(int fd, int p1, int p2, s_attr_header * attr) { int res;
A couple of options that I think of are as follows:
Throw modern C ++ - is being swept out of the window and do what I showed above.
Allocate storage with std :: vector, then do ugly throws with the resulting pointer std :: vector :: data (), at least I don't do new[] / delete[] or malloc / free .
Create a unique wrapper method for each s_attr_type* , which uses its own "special" structure. This seems to be the βsafest,β that is, the least likely for the user to wrap the method to ruin it. And bonus points, allows you to skip the link.
Example of method No. 3:
int do_ugly_ioctl(fd, int param1, int param2, s_attr_type2& attr){ struct RequestData { s_ioctl_request ioreq; s_attr_type2 attr; }; RequestData r; r.ioreq.param1 = param1; r.ioreq.param2 = param2; r.attr = attr; r.attr.hdr.attr_length = sizeof(attr);
So, I think some questions are here:
Is it "worth it" for C ++ to solve the problem? (as opposed to relying on a more error-prone C impl).
If I go with method # 3 or similar, is there anything I can do with <type_traits> to create a template for this function and only accept structs with s_attr_header as the first member?
Any other brilliant ideas?
source share