v4l2: v4l2_compat: Handle __ioctl_time64
diff mbox series

Message ID 20260122121015.3842322-1-paul.elder@ideasonboard.com
State New
Headers show
Series
  • v4l2: v4l2_compat: Handle __ioctl_time64
Related show

Commit Message

Paul Elder Jan. 22, 2026, 12:10 p.m. UTC
On 32-bit systems, ioctl is redirected to __ioctl_time64, so the latter
needs to be intercepted and handled as well. Add support for this.

Bug: https://gitlab.freedesktop.org/camera/libcamera/-/issues/290
Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
---
 src/v4l2/v4l2_compat.cpp         | 21 +++++++++++++++++++++
 src/v4l2/v4l2_compat_manager.cpp | 10 ++++++++++
 src/v4l2/v4l2_compat_manager.h   |  2 ++
 3 files changed, 33 insertions(+)

Comments

Kieran Bingham Jan. 22, 2026, 12:58 p.m. UTC | #1
Quoting Paul Elder (2026-01-22 12:10:15)
> On 32-bit systems, ioctl is redirected to __ioctl_time64, so the latter
> needs to be intercepted and handled as well. Add support for this.
> 
> Bug: https://gitlab.freedesktop.org/camera/libcamera/-/issues/290

I think we've switched to Closes: now ?

But best I can tell this all looks reasonable and fixes and issue so:

Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>

> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
>  src/v4l2/v4l2_compat.cpp         | 21 +++++++++++++++++++++
>  src/v4l2/v4l2_compat_manager.cpp | 10 ++++++++++
>  src/v4l2/v4l2_compat_manager.h   |  2 ++
>  3 files changed, 33 insertions(+)
> 
> diff --git a/src/v4l2/v4l2_compat.cpp b/src/v4l2/v4l2_compat.cpp
> index ff833f571bde..10421cef76f4 100644
> --- a/src/v4l2/v4l2_compat.cpp
> +++ b/src/v4l2/v4l2_compat.cpp
> @@ -165,4 +165,25 @@ LIBCAMERA_PUBLIC int ioctl(int fd, unsigned long request, ...)
>         return V4L2CompatManager::instance()->ioctl(fd, request, arg);
>  }
>  
> +/*
> + * __USE_TIME64_REDIRECTS redirects ioctl to __ioctl_time64. Disable the
> + * -Wmissing-declarations warnings, as the functions won't be declared if
> + *  __USE_TIME64_REDIRECTS is not in use.
> + */
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wmissing-declarations"
> +
> +#if HAVE_POSIX_IOCTL
> +LIBCAMERA_PUBLIC int __ioctl_time64(int fd, int request, ...)
> +#else
> +LIBCAMERA_PUBLIC int __ioctl_time64(int fd, unsigned long request, ...)
> +#endif
> +{
> +       void *arg;
> +       extract_va_arg(void *, arg, request);
> +
> +       return V4L2CompatManager::instance()->ioctl_time64(fd, request, arg);
> +}
> +
> +#pragma GCC diagnostic pop
>  }
> diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
> index f53fb300dde8..4303883712d6 100644
> --- a/src/v4l2/v4l2_compat_manager.cpp
> +++ b/src/v4l2/v4l2_compat_manager.cpp
> @@ -46,6 +46,7 @@ V4L2CompatManager::V4L2CompatManager()
>         get_symbol(fops_.dup, "dup");
>         get_symbol(fops_.close, "close");
>         get_symbol(fops_.ioctl, "ioctl");
> +       get_symbol(fops_.ioctl_time64, "__ioctl_time64");
>         get_symbol(fops_.mmap, "mmap64");
>         get_symbol(fops_.munmap, "munmap");
>  }
> @@ -249,3 +250,12 @@ int V4L2CompatManager::ioctl(int fd, unsigned long request, void *arg)
>  
>         return file->proxy()->ioctl(file.get(), request, arg);
>  }
> +
> +int V4L2CompatManager::ioctl_time64(int fd, unsigned long request, void *arg)
> +{
> +       std::shared_ptr<V4L2CameraFile> file = cameraFile(fd);
> +       if (!file)
> +               return fops_.ioctl_time64(fd, request, arg);
> +
> +       return file->proxy()->ioctl(file.get(), request, arg);
> +}
> diff --git a/src/v4l2/v4l2_compat_manager.h b/src/v4l2/v4l2_compat_manager.h
> index f7c6f1228282..f713f2333500 100644
> --- a/src/v4l2/v4l2_compat_manager.h
> +++ b/src/v4l2/v4l2_compat_manager.h
> @@ -34,6 +34,7 @@ public:
>                 dup_func_t dup;
>                 close_func_t close;
>                 ioctl_func_t ioctl;
> +               ioctl_func_t ioctl_time64;
>                 mmap_func_t mmap;
>                 munmap_func_t munmap;
>         };
> @@ -50,6 +51,7 @@ public:
>                    int fd, off64_t offset);
>         int munmap(void *addr, size_t length);
>         int ioctl(int fd, unsigned long request, void *arg);
> +       int ioctl_time64(int fd, unsigned long request, void *arg);
>  
>  private:
>         V4L2CompatManager();
> -- 
> 2.47.2
>

Patch
diff mbox series

diff --git a/src/v4l2/v4l2_compat.cpp b/src/v4l2/v4l2_compat.cpp
index ff833f571bde..10421cef76f4 100644
--- a/src/v4l2/v4l2_compat.cpp
+++ b/src/v4l2/v4l2_compat.cpp
@@ -165,4 +165,25 @@  LIBCAMERA_PUBLIC int ioctl(int fd, unsigned long request, ...)
 	return V4L2CompatManager::instance()->ioctl(fd, request, arg);
 }
 
+/*
+ * __USE_TIME64_REDIRECTS redirects ioctl to __ioctl_time64. Disable the
+ * -Wmissing-declarations warnings, as the functions won't be declared if
+ *  __USE_TIME64_REDIRECTS is not in use.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+
+#if HAVE_POSIX_IOCTL
+LIBCAMERA_PUBLIC int __ioctl_time64(int fd, int request, ...)
+#else
+LIBCAMERA_PUBLIC int __ioctl_time64(int fd, unsigned long request, ...)
+#endif
+{
+	void *arg;
+	extract_va_arg(void *, arg, request);
+
+	return V4L2CompatManager::instance()->ioctl_time64(fd, request, arg);
+}
+
+#pragma GCC diagnostic pop
 }
diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
index f53fb300dde8..4303883712d6 100644
--- a/src/v4l2/v4l2_compat_manager.cpp
+++ b/src/v4l2/v4l2_compat_manager.cpp
@@ -46,6 +46,7 @@  V4L2CompatManager::V4L2CompatManager()
 	get_symbol(fops_.dup, "dup");
 	get_symbol(fops_.close, "close");
 	get_symbol(fops_.ioctl, "ioctl");
+	get_symbol(fops_.ioctl_time64, "__ioctl_time64");
 	get_symbol(fops_.mmap, "mmap64");
 	get_symbol(fops_.munmap, "munmap");
 }
@@ -249,3 +250,12 @@  int V4L2CompatManager::ioctl(int fd, unsigned long request, void *arg)
 
 	return file->proxy()->ioctl(file.get(), request, arg);
 }
+
+int V4L2CompatManager::ioctl_time64(int fd, unsigned long request, void *arg)
+{
+	std::shared_ptr<V4L2CameraFile> file = cameraFile(fd);
+	if (!file)
+		return fops_.ioctl_time64(fd, request, arg);
+
+	return file->proxy()->ioctl(file.get(), request, arg);
+}
diff --git a/src/v4l2/v4l2_compat_manager.h b/src/v4l2/v4l2_compat_manager.h
index f7c6f1228282..f713f2333500 100644
--- a/src/v4l2/v4l2_compat_manager.h
+++ b/src/v4l2/v4l2_compat_manager.h
@@ -34,6 +34,7 @@  public:
 		dup_func_t dup;
 		close_func_t close;
 		ioctl_func_t ioctl;
+		ioctl_func_t ioctl_time64;
 		mmap_func_t mmap;
 		munmap_func_t munmap;
 	};
@@ -50,6 +51,7 @@  public:
 		   int fd, off64_t offset);
 	int munmap(void *addr, size_t length);
 	int ioctl(int fd, unsigned long request, void *arg);
+	int ioctl_time64(int fd, unsigned long request, void *arg);
 
 private:
 	V4L2CompatManager();