fix VIDIOC_DQEVENT (v4l2) ioctl fallback for pre-5.6 kernels
authorRich Felker <dalias@aerifal.cx>
Mon, 14 Dec 2020 16:10:30 +0000 (11:10 -0500)
committerRich Felker <dalias@aerifal.cx>
Tue, 15 Dec 2020 01:36:13 +0000 (20:36 -0500)
commit 2412638bb39eb799b2600393bbd71cca8ae96bb2 got the size of struct
v4l2_event wrong and failed to account for the fact that the old
struct might be either 120 bytes with time misaligned mod 8, or 128
bytes with time aligned mod 8, due to the contained union having
64-bit members whose alignment is arch-dependent.

rather than adding new logic to handle the differences, use an actual
stripped-down version of the structure in question to derive the ioctl
number, size, and offsets.

src/misc/ioctl.c

index 26481c6..4928281 100644 (file)
@@ -4,6 +4,7 @@
 #include <time.h>
 #include <sys/time.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <string.h>
 #include "syscall.h"
 
@@ -28,6 +29,12 @@ struct ioctl_compat_map {
  * number producing macros; only size of result is meaningful. */
 #define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; }
 
+struct v4l2_event {
+       uint32_t a;
+       uint64_t b[8];
+       uint32_t c[2], ts[2], d[9];
+};
+
 static const struct ioctl_compat_map compat_map[] = {
        { SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) },
        { SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) },
@@ -55,7 +62,8 @@ static const struct ioctl_compat_map compat_map[] = {
        { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) },
 
        /* VIDIOC_DQEVENT */
-       { _IOR('V', 89, new_misaligned(96)), _IOR('V', 89, char[96]), 96, R, 0, OFFS(76,80) },
+       { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event),
+         R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) },
 
        /* VIDIOC_OMAP3ISP_STAT_REQ */
        { _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) },