Index: sys/compat/cloudabi/cloudabi_fd.c =================================================================== --- sys/compat/cloudabi/cloudabi_fd.c +++ sys/compat/cloudabi/cloudabi_fd.c @@ -26,6 +26,12 @@ #include __FBSDID("$FreeBSD$"); +#include +#include +#include +#include +#include + #include int @@ -32,8 +38,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 +63,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 +75,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 +82,47 @@ 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 DUP_REPLACE, 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, DUP_FIXED | DUP_REPLACE, 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 +146,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 do_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 do_dup() */ -#define DUP_FIXED 0x1 /* Force fixed allocation. */ -#define DUP_FCNTL 0x2 /* fcntl()-style errors. */ -#define DUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */ - /* * Each process has: * @@ -361,7 +355,7 @@ sys_dup2(struct thread *td, struct dup2_args *uap) { - return (do_dup(td, DUP_FIXED, (int)uap->from, (int)uap->to)); + return (kern_dup(td, DUP_FIXED, (int)uap->from, (int)uap->to)); } /* @@ -377,7 +371,7 @@ sys_dup(struct thread *td, struct dup_args *uap) { - return (do_dup(td, 0, (int)uap->fd, 0)); + return (kern_dup(td, 0, (int)uap->fd, 0)); } /* @@ -487,22 +481,22 @@ switch (cmd) { case F_DUPFD: tmp = arg; - error = do_dup(td, DUP_FCNTL, fd, tmp); + error = kern_dup(td, DUP_FCNTL, fd, tmp); break; case F_DUPFD_CLOEXEC: tmp = arg; - error = do_dup(td, DUP_FCNTL | DUP_CLOEXEC, fd, tmp); + error = kern_dup(td, DUP_FCNTL | DUP_CLOEXEC, fd, tmp); break; case F_DUP2FD: tmp = arg; - error = do_dup(td, DUP_FIXED, fd, tmp); + error = kern_dup(td, DUP_FIXED, fd, tmp); break; case F_DUP2FD_CLOEXEC: tmp = arg; - error = do_dup(td, DUP_FIXED | DUP_CLOEXEC, fd, tmp); + error = kern_dup(td, DUP_FIXED | DUP_CLOEXEC, fd, tmp); break; case F_GETFD: @@ -794,8 +788,8 @@ /* * Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD). */ -static int -do_dup(struct thread *td, int flags, int old, int new) +int +kern_dup(struct thread *td, int flags, int old, int new) { struct filedesc *fdp; struct filedescent *oldfde, *newfde; @@ -841,7 +835,16 @@ * table is large enough to hold it, and grab it. Otherwise, just * allocate a new descriptor the usual way. */ - if (flags & DUP_FIXED) { + if (flags & DUP_REPLACE) { + /* 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 & DUP_FIXED) { if (new >= fdp->fd_nfiles) { /* * The resource limits are here instead of e.g. @@ -1988,7 +1991,7 @@ if (fdp->fd_holdleaderscount > 0 && (p->p_leader->p_flag & P_ADVLOCK) != 0) { /* - * close() or do_dup() has cleared a reference + * close() or kern_dup() has cleared a reference * in a shared file descriptor table. */ fdp->fd_holdleaderswakeup = 1; @@ -2215,7 +2218,7 @@ save = td->td_retval[0]; if (devnull != -1) { - error = do_dup(td, DUP_FIXED, devnull, i); + error = kern_dup(td, DUP_FIXED, devnull, i); } else { error = kern_openat(td, AT_FDCWD, "/dev/null", UIO_SYSSPACE, O_RDWR, 0); 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, @@ -250,8 +251,14 @@ int kern_socketpair(struct thread *td, int domain, int type, int protocol, int *rsv); -/* flags for kern_sigaction */ -#define KSA_OSIGSET 0x0001 /* uses osigact_t */ -#define KSA_FREEBSD4 0x0002 /* uses ucontext4 */ +/* Flags for kern_sigaction. */ +#define KSA_OSIGSET 0x0001 /* Uses osigact_t. */ +#define KSA_FREEBSD4 0x0002 /* Uses ucontext4. */ +/* Flags for kern_dup(). */ +#define DUP_FIXED 0x1 /* Force fixed allocation. */ +#define DUP_FCNTL 0x2 /* fcntl()-style errors. */ +#define DUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */ +#define DUP_REPLACE 0x8 /* Target must exist. */ + #endif /* !_SYS_SYSCALLSUBR_H_ */