Index: sys/compat/cloudabi/cloudabi_fd.c =================================================================== --- sys/compat/cloudabi/cloudabi_fd.c +++ sys/compat/cloudabi/cloudabi_fd.c @@ -26,6 +26,13 @@ #include __FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include +#include + #include int @@ -32,8 +39,7 @@ 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,9 +64,12 @@ 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 @@ -67,8 +76,7 @@ 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 @@ -75,17 +83,48 @@ 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 @@ 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)); } Index: sys/kern/kern_descrip.c =================================================================== --- sys/kern/kern_descrip.c +++ sys/kern/kern_descrip.c @@ -102,7 +102,6 @@ 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 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 @@ /* * 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; @@ -808,6 +802,8 @@ fdp = p->p_fd; MPASS((flags & ~(FDDUP_FIXED | FDDUP_FCNTL | FDDUP_CLOEXEC)) == 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 +824,7 @@ 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 +839,16 @@ * 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. Index: sys/sys/filedesc.h =================================================================== --- sys/sys/filedesc.h +++ sys/sys/filedesc.h @@ -134,6 +134,12 @@ 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); Index: sys/sys/syscallsubr.h =================================================================== --- sys/sys/syscallsubr.h +++ sys/sys/syscallsubr.h @@ -85,6 +85,7 @@ 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,