Add implementations for some of the CloudABI file descriptor system calls.

All of the CloudABI system calls that operate on file descriptors of an
arbitrary type are prefixed with fd_. This change adds wrappers for
most of these system calls around their FreeBSD equivalents.

The dup2() system call present on CloudABI deviates from POSIX, in the
sense that it can only be used to replace existing file descriptor. It
cannot be used to create new ones. The reason for this is that this is
inherently thread-unsafe. Furthermore, there is no need on CloudABI to
use fixed file descriptor numbers. File descriptors 0, 1 and 2 have no
special meaning.

This change exposes the kern_dup() through <sys/syscallsubr.h> and puts
the FDDUP_* flags in <sys/filedesc.h>. It then adds a new flag,
FDDUP_MUSTREPLACE to force that file descriptors are replaced -- not
allocated.

Differential Revision:	https://reviews.freebsd.org/D3035
Reviewed by:	mjg
This commit is contained in:
Ed Schouten 2015-07-09 16:07:01 +00:00
parent efdc25304c
commit 2491302a04
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285323
4 changed files with 76 additions and 22 deletions

View File

@ -26,14 +26,20 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/filedesc.h>
#include <sys/proc.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/unistd.h>
#include <compat/cloudabi/cloudabi_proto.h>
int
cloudabi_sys_fd_close(struct thread *td, struct cloudabi_sys_fd_close_args *uap)
{
/* Not implemented. */
return (ENOSYS);
return (kern_close(td, uap->fd));
}
int
@ -58,34 +64,67 @@ int
cloudabi_sys_fd_datasync(struct thread *td,
struct cloudabi_sys_fd_datasync_args *uap)
{
struct fsync_args fsync_args = {
.fd = uap->fd
};
/* Not implemented. */
return (ENOSYS);
/* Call into fsync(), as FreeBSD lacks fdatasync(). */
return (sys_fsync(td, &fsync_args));
}
int
cloudabi_sys_fd_dup(struct thread *td, struct cloudabi_sys_fd_dup_args *uap)
{
/* Not implemented. */
return (ENOSYS);
return (kern_dup(td, 0, uap->from, 0));
}
int
cloudabi_sys_fd_replace(struct thread *td,
struct cloudabi_sys_fd_replace_args *uap)
{
int error;
/* Not implemented. */
return (ENOSYS);
/*
* CloudABI's equivalent to dup2(). CloudABI processes should
* not depend on hardcoded file descriptor layouts, but simply
* use the file descriptor numbers that are allocated by the
* kernel. Duplicating file descriptors to arbitrary numbers
* should not be done.
*
* Invoke kern_dup() with FDDUP_MUSTREPLACE, so that we return
* EBADF when duplicating to a nonexistent file descriptor. Also
* clear the return value, as this system call yields no return
* value.
*/
error = kern_dup(td, FDDUP_MUSTREPLACE, uap->from, uap->to);
td->td_retval[0] = 0;
return (error);
}
int
cloudabi_sys_fd_seek(struct thread *td, struct cloudabi_sys_fd_seek_args *uap)
{
struct lseek_args lseek_args = {
.fd = uap->fd,
.offset = uap->offset
};
/* Not implemented. */
return (ENOSYS);
switch (uap->whence) {
case CLOUDABI_WHENCE_CUR:
lseek_args.whence = SEEK_CUR;
break;
case CLOUDABI_WHENCE_END:
lseek_args.whence = SEEK_END;
break;
case CLOUDABI_WHENCE_SET:
lseek_args.whence = SEEK_SET;
break;
default:
return (EINVAL);
}
return (sys_lseek(td, &lseek_args));
}
int
@ -109,7 +148,9 @@ cloudabi_sys_fd_stat_put(struct thread *td,
int
cloudabi_sys_fd_sync(struct thread *td, struct cloudabi_sys_fd_sync_args *uap)
{
struct fsync_args fsync_args = {
.fd = uap->fd
};
/* Not implemented. */
return (ENOSYS);
return (sys_fsync(td, &fsync_args));
}

View File

@ -102,7 +102,6 @@ static uma_zone_t filedesc0_zone;
static int closefp(struct filedesc *fdp, int fd, struct file *fp,
struct thread *td, int holdleaders);
static int kern_dup(struct thread *td, int flags, int old, int new);
static int fd_first_free(struct filedesc *fdp, int low, int size);
static int fd_last_used(struct filedesc *fdp, int size);
static void fdgrowtable(struct filedesc *fdp, int nfd);
@ -111,11 +110,6 @@ static void fdunused(struct filedesc *fdp, int fd);
static void fdused(struct filedesc *fdp, int fd);
static int getmaxfd(struct thread *td);
/* Flags for kern_dup() */
#define FDDUP_FIXED 0x1 /* Force fixed allocation. */
#define FDDUP_FCNTL 0x2 /* fcntl()-style errors. */
#define FDDUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */
/*
* Each process has:
*
@ -794,7 +788,7 @@ getmaxfd(struct thread *td)
/*
* Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD).
*/
static int
int
kern_dup(struct thread *td, int flags, int old, int new)
{
struct filedesc *fdp;
@ -807,7 +801,10 @@ kern_dup(struct thread *td, int flags, int old, int new)
p = td->td_proc;
fdp = p->p_fd;
MPASS((flags & ~(FDDUP_FIXED | FDDUP_FCNTL | FDDUP_CLOEXEC)) == 0);
MPASS((flags & ~(FDDUP_FIXED | FDDUP_FCNTL | FDDUP_CLOEXEC |
FDDUP_MUSTREPLACE)) == 0);
MPASS((flags & (FDDUP_FIXED | FDDUP_MUSTREPLACE)) !=
(FDDUP_FIXED | FDDUP_MUSTREPLACE));
/*
* Verify we have a valid descriptor to dup from and possibly to
@ -828,7 +825,7 @@ kern_dup(struct thread *td, int flags, int old, int new)
return (EBADF);
}
oldfde = &fdp->fd_ofiles[old];
if (flags & FDDUP_FIXED && old == new) {
if (flags & (FDDUP_FIXED | FDDUP_MUSTREPLACE) && old == new) {
td->td_retval[0] = new;
if (flags & FDDUP_CLOEXEC)
fdp->fd_ofiles[new].fde_flags |= UF_EXCLOSE;
@ -843,7 +840,16 @@ kern_dup(struct thread *td, int flags, int old, int new)
* table is large enough to hold it, and grab it. Otherwise, just
* allocate a new descriptor the usual way.
*/
if (flags & FDDUP_FIXED) {
if (flags & FDDUP_MUSTREPLACE) {
/* Target file descriptor must exist. */
if (new >= fdp->fd_nfiles ||
fdp->fd_ofiles[new].fde_file == NULL) {
FILEDESC_XUNLOCK(fdp);
fdrop(fp, td);
return (EBADF);
}
newfde = &fdp->fd_ofiles[new];
} else if (flags & FDDUP_FIXED) {
if (new >= fdp->fd_nfiles) {
/*
* The resource limits are here instead of e.g.

View File

@ -134,6 +134,12 @@ struct filedesc_to_leader {
SX_NOTRECURSED)
#define FILEDESC_UNLOCK_ASSERT(fdp) sx_assert(&(fdp)->fd_sx, SX_UNLOCKED)
/* Flags for kern_dup(). */
#define FDDUP_FIXED 0x1 /* Force fixed allocation. */
#define FDDUP_FCNTL 0x2 /* fcntl()-style errors. */
#define FDDUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */
#define FDDUP_MUSTREPLACE 0x8 /* Target must exist. */
struct thread;
void filecaps_init(struct filecaps *fcaps);

View File

@ -85,6 +85,7 @@ int kern_clock_settime(struct thread *td, clockid_t clock_id,
int kern_close(struct thread *td, int fd);
int kern_connectat(struct thread *td, int dirfd, int fd,
struct sockaddr *sa);
int kern_dup(struct thread *td, int flags, int old, int new);
int kern_execve(struct thread *td, struct image_args *args,
struct mac *mac_p);
int kern_fchmodat(struct thread *td, int fd, char *path,