From f3268cade61d8c6da567e71d32b3a773c7808bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 11 Sep 2020 11:52:37 +0200 Subject: [PATCH] libc: split ioctl method Use one ioctl method for each type of I/O control because by now the general method will become increasingly long. Fixes #3890. --- .../src/lib/libc/internal/vfs_plugin.h | 16 +++++ repos/libports/src/lib/libc/vfs_plugin.cc | 60 +++++++++++++++---- 2 files changed, 64 insertions(+), 12 deletions(-) diff --git a/repos/libports/src/lib/libc/internal/vfs_plugin.h b/repos/libports/src/lib/libc/internal/vfs_plugin.h index 9dbce47704..11d8a24e0a 100644 --- a/repos/libports/src/lib/libc/internal/vfs_plugin.h +++ b/repos/libports/src/lib/libc/internal/vfs_plugin.h @@ -93,6 +93,22 @@ class Libc::Vfs_plugin : public Plugin int _legacy_ioctl(File_descriptor *, unsigned long, char *); + struct Ioctl_result + { + bool handled; + int error; + }; + + /** + * Terminal related I/O controls + */ + Ioctl_result _ioctl_tio(File_descriptor *, unsigned long, char *); + + /** + * Block related I/O controls + */ + Ioctl_result _ioctl_dio(File_descriptor *, unsigned long, char *); + /** * Call functor 'fn' with ioctl info for the given file descriptor 'fd' * diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index 308f3503e9..f3fbd03df4 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -1061,15 +1061,16 @@ ssize_t Libc::Vfs_plugin::getdirentries(File_descriptor *fd, char *buf, } -int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *argp) +Libc::Vfs_plugin::Ioctl_result +Libc::Vfs_plugin::_ioctl_tio(File_descriptor *fd, unsigned long request, char *argp) { + if (!argp) + return { true, EINVAL }; + bool handled = false; if (request == TIOCGWINSZ) { - if (!argp) - return Errno(EINVAL); - monitor().monitor([&] { _with_info(*fd, [&] (Xml_node info) { if (info.type() == "terminal") { @@ -1098,12 +1099,25 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar ::memset(termios->c_cc, _POSIX_VDISABLE, sizeof(termios->c_cc)); termios->c_ispeed = 0; termios->c_ospeed = 0; + handled = true; + } - } else if (request == DIOCGMEDIASIZE) { + return { handled, 0 }; +} - if (!argp) - return Errno(EINVAL); + +Libc::Vfs_plugin::Ioctl_result +Libc::Vfs_plugin::_ioctl_dio(File_descriptor *fd, unsigned long request, char *argp) +{ + if (!argp) + return { true, EINVAL }; + + bool handled = false; + + using ::off_t; + + if (request == DIOCGMEDIASIZE) { monitor().monitor([&] { _with_info(*fd, [&] (Xml_node info) { @@ -1121,9 +1135,6 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar warning("block count is 0"); } - /* we need libc's off_t which is int64_t */ - using ::off_t; - off_t disk_size = (off_t) count * size; if (disk_size < 0) { warning("disk size overflow - returning 0"); @@ -1137,10 +1148,35 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar return Fn::COMPLETE; }); + } - if (handled) - return 0; + return { handled, 0 }; +} + + +int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *argp) +{ + Ioctl_result result { false, 0 }; + + /* we need libc's off_t which is int64_t */ + using ::off_t; + + switch (request) { + case TIOCGWINSZ: + case TIOCGETA: + result = _ioctl_tio(fd, request, argp); + break; + case DIOCGMEDIASIZE: + result = _ioctl_dio(fd, request, argp); + break; + default: + break; + } + + if (result.handled) { + return result.error ? Errno(result.error) : 0; + } return _legacy_ioctl(fd, request, argp); }