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.
This commit is contained in:
Josef Söntgen 2020-09-11 11:52:37 +02:00 committed by Christian Helmuth
parent 1a54ee895e
commit f3268cade6
2 changed files with 64 additions and 12 deletions

View File

@ -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'
*

View File

@ -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);
}