POSIX: ioctl(fd, op, arg) equals ioctl(fd, op, arg, 0)

The ioctl call cannot know the expected number of arguments
because it depends on the specific ioctl being used, and the
same value could be used to do different things by different
devices. Without knowing that, it is not safe to use va_arg
(at best a random value will be read from the stack, at worst,
it will just crash).

This changes the implementation of ioctl in two ways:
- For C++ code: a 4 argument function with default values
  for arguments 3 and 4.
- For C code: wrap arguments 3 and 4 in a struct with the
  help of a macro, providing something that behaves like the
  C++ version.

So, with this new code:
- Calling ioctl with only 3 arguments sets the 4th one to 0
- Calling ioctl with only 2 arguments sets the 3rd and 4th to 0
- Calling with 1 or 5+ arguments is a compile time error

The existing ioctl symbol is preserved for ABI compatibility.

Change-Id: I6d4d1d38fccd8cc9bd94203d3e11aeac6da8efc3
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3360
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Jérôme Duval
2021-05-04 19:21:48 +00:00
committed by Adrien Destugues
parent 3349a731ef
commit 7065a89fc6
2 changed files with 24 additions and 0 deletions
+16
View File
@@ -190,7 +190,23 @@ extern int symlinkat(const char *toPath, int fd, const char *symlinkPath);
extern int ftruncate(int fd, off_t newSize);
extern int truncate(const char *path, off_t newSize);
struct ioctl_args {
void* argument;
size_t size;
};
int __ioctl(int fd, ulong cmd, struct ioctl_args args);
#ifndef __cplusplus
extern int ioctl(int fd, unsigned long op, ...);
#ifndef _KERNEL_MODE
#define ioctl(a, b, c...) __ioctl(a, b, (struct ioctl_args){ c })
#endif
#else
inline int
ioctl(int fd, unsigned long op, void* argument = NULL, size_t size = 0)
{
return __ioctl(fd, op, (struct ioctl_args){ argument, size });
}
#endif
extern ssize_t read(int fd, void *buffer, size_t count);
extern ssize_t read_pos(int fd, off_t pos, void *buffer, size_t count);
+8
View File
@@ -13,6 +13,14 @@
#include <syscall_utils.h>
int
__ioctl(int fd, ulong cmd, struct ioctl_args args)
{
RETURN_AND_SET_ERRNO(_kern_ioctl(fd, cmd, args.argument, args.size));
}
#undef ioctl
int
ioctl(int fd, ulong cmd, ...)
{