Refactor fcntl(2) ABI.

This is an incompatible ABI change.
This commit is contained in:
Jonas 'Sortie' Termansen 2013-09-24 12:39:48 +02:00
parent 4e520c8c36
commit 8c0e0235d6
3 changed files with 68 additions and 30 deletions

View File

@ -24,16 +24,26 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h>
DEFN_SYSCALL3(int, sys_fcntl, SYSCALL_FCNTL, int, int, unsigned long); DEFN_SYSCALL3(int, sys_fcntl, SYSCALL_FCNTL, int, int, uintptr_t);
extern "C" int fcntl(int fd, int cmd, ...) extern "C" int fcntl(int fd, int cmd, ...)
{ {
uintptr_t arg;
va_list ap; va_list ap;
va_start(ap, cmd); va_start(ap, cmd);
unsigned long arg = va_arg(ap, unsigned long); switch ( F_DECODE_CMD_TYPE(cmd) )
{
case F_TYPE_VOID: arg = 0; break;
case F_TYPE_INT: arg = (uintptr_t) va_arg(ap, int); break;
case F_TYPE_LONG: arg = (uintptr_t) va_arg(ap, long); break;
case F_TYPE_PTR: arg = (uintptr_t) va_arg(ap, void*); break;
default: return errno = EINVAL, -1;
}
va_end(ap); va_end(ap);
return sys_fcntl(fd, cmd, arg); return sys_fcntl(fd, cmd, arg);
} }

View File

@ -50,10 +50,43 @@ __BEGIN_DECLS
#define __FD_ALLOWED_FLAGS (FD_CLOEXEC | FD_CLOFORK) #define __FD_ALLOWED_FLAGS (FD_CLOEXEC | FD_CLOFORK)
#define F_SETFD 0 /* Encode type information about arguments into fcntl commands. Unfortunately
#define F_GETFD 1 the fcntl function declaration doesn't include type information, which means
#define F_SETFL 2 that the fcntl implementation either needs a list of command type information
#define F_GETFL 3 to use va_list correctly - or we can simply embed the information into the
commands. */
#define F_TYPE_EXP 3 /* 2^3 kinds of argument types supported.*/
#define F_TYPE_VOID 0
#define F_TYPE_INT 1
#define F_TYPE_LONG 2
#define F_TYPE_PTR 3
/* 5-7 is unused in case of future expansion. */
#define F_ENCODE_CMD(cmd_val, arg_type) ((cmd_val) << F_TYPE_EXP | (arg_type))
#define F_DECODE_CMD_RAW(cmd) (cmd >> F_TYPE_EXP)
#define F_DECODE_CMD_TYPE(cmd) ((cmd) & ((1 << F_TYPE_EXP)-1))
/* Encode small parameters into fcntl commands. This allows adding some flags
and other modifiers to fcntl commands without declaring a heap of new fcntl
commands variants. */
#define F_ENCODE(cmd, small_param) (((cmd) & 0xFFFF) | ((small_param) << 16))
#define F_DECODE_CMD(val) (val & 0xFFFF)
#define F_DECODE_FLAGS(val) ((val & ~0xFFFF) >> 16)
/* Set file descriptor status. */
#define F_SETFD_NUM 0
#define F_SETFD F_ENCODE_CMD(F_SETFD_NUM, F_TYPE_INT)
/* Get file descriptor status. */
#define F_GETFD_NUM 1
#define F_GETFD F_ENCODE_CMD(F_GETFD_NUM, F_TYPE_VOID)
/* Set descriptor table entry flags. */
#define F_SETFL_NUM 3
#define F_SETFL F_ENCODE_CMD(F_SETFL_NUM, F_TYPE_INT)
/* Get descriptor table entry flags. */
#define F_GETFL_NUM 3
#define F_GETFL F_ENCODE_CMD(F_GETFL_NUM, F_TYPE_VOID)
#define AT_FDCWD (-100) #define AT_FDCWD (-100)
#define AT_REMOVEDIR (1<<0) #define AT_REMOVEDIR (1<<0)

View File

@ -316,32 +316,27 @@ static int sys_fstat(int fd, struct stat* st)
return desc->stat(&ctx, st); return desc->stat(&ctx, st);
} }
static int sys_fcntl(int fd, int cmd, unsigned long arg) static int sys_fcntl(int fd, int cmd, uintptr_t arg)
{ {
// Operations on the descriptor table.
Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable(); Ref<DescriptorTable> dtable = CurrentProcess()->GetDTable();
Ref<Descriptor> desc;
int ret = -1; // Operations on the file descriptior.
switch ( cmd ) if ( cmd == F_SETFD )
{ return dtable->SetFlags(fd, (int) arg) ? 0 : -1;;
case F_SETFD: if ( cmd == F_GETFD )
ret = dtable->SetFlags(fd, (int) arg) ? 0 : -1; return dtable->GetFlags(fd);
break;
case F_GETFD: // Operations on the file description.
ret = dtable->GetFlags(fd); Ref<Descriptor> desc = dtable->Get(fd);
break; if ( !desc )
case F_SETFL: return -1;
if ( (desc = dtable->Get(fd)) ) if ( cmd == F_SETFL )
ret = desc->SetFlags((int) arg) ? 0 : -1; return desc->SetFlags((int) arg);
break; if ( cmd == F_GETFL )
case F_GETFL: return desc->GetFlags();
if ( (desc = dtable->Get(fd)) )
ret = desc->GetFlags(); return errno = EINVAL, -1;
break;
default:
errno = EINVAL;
break;
}
return ret;
} }
static int sys_ioctl(int fd, int cmd, void* /*ptr*/) static int sys_ioctl(int fd, int cmd, void* /*ptr*/)