Skip to content

Commit

Permalink
Add FD_CLOEXEC and related code
Browse files Browse the repository at this point in the history
  • Loading branch information
Arshia001 committed Feb 11, 2025
1 parent b2ee794 commit 1ce83b0
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 13 deletions.
36 changes: 30 additions & 6 deletions libc-bottom-half/cloudlibc/src/libc/fcntl/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,30 @@

int fcntl(int fildes, int cmd, ...) {
switch (cmd) {
case F_GETFD:
// Act as if the close-on-exec flag is always set.
return FD_CLOEXEC;
case F_SETFD:
// The close-on-exec flag is ignored.
case F_GETFD: {
__wasi_fdflagsext_t flags;
__wasi_errno_t error = __wasi_fd_fdflags_get(fildes, &flags);
if (error != 0) {
errno = error;
return -1;
}
return flags & __WASI_FDFLAGSEXT_CLOEXEC ? FD_CLOEXEC : 0;
}
case F_SETFD: {
va_list ap;
va_start(ap, cmd);
int flags = va_arg(ap, int);
va_end(ap);

__wasi_fdflagsext_t fd_flags = flags | FD_CLOEXEC ? __WASI_FDFLAGSEXT_CLOEXEC : 0;
__wasi_errno_t error =
__wasi_fd_fdflags_set(fildes, fd_flags);
if (error != 0) {
errno = error;
return -1;
}
return 0;
}
case F_GETFL: {
// Obtain the flags and the rights of the descriptor.
__wasi_fdstat_t fds;
Expand Down Expand Up @@ -57,8 +75,14 @@ int fcntl(int fildes, int cmd, ...) {
}
case F_DUPFD:
case F_DUPFD_CLOEXEC: {
va_list ap;
va_start(ap, cmd);
int min_res_fd = va_arg(ap, int);
va_end(ap);

int fd;
__wasi_errno_t error = __wasi_fd_dup(fildes, &fd);
__wasi_bool_t cloexec = cmd == F_DUPFD_CLOEXEC;
__wasi_errno_t error = __wasi_fd_dup2(fildes, min_res_fd, cloexec, &fd);
if (error != 0) {
errno = error;
return -1;
Expand Down
7 changes: 5 additions & 2 deletions libc-bottom-half/cloudlibc/src/libc/fcntl/openat.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ static_assert(O_DIRECTORY >> 12 == __WASI_OFLAGS_DIRECTORY, "Value mismatch");
static_assert(O_EXCL >> 12 == __WASI_OFLAGS_EXCL, "Value mismatch");
static_assert(O_TRUNC >> 12 == __WASI_OFLAGS_TRUNC, "Value mismatch");

static_assert(O_CLOEXEC >> 24 == __WASI_FDFLAGSEXT_CLOEXEC, "Value mismatch");

int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) {
// Compute rights corresponding with the access modes provided.
// Attempt to obtain all rights, except the ones that contradict the
Expand Down Expand Up @@ -65,13 +67,14 @@ int __wasilibc_nocwd_openat_nomode(int fd, const char *path, int oflag) {

// Open file with appropriate rights.
__wasi_fdflags_t fs_flags = oflag & 0xfff;
__wasi_fdflagsext_t fd_flags = oflag >> 24 & 0xff;
__wasi_rights_t fs_rights_base = max & fsb_cur.fs_rights_inheriting;
__wasi_rights_t fs_rights_inheriting = fsb_cur.fs_rights_inheriting;
__wasi_fd_t newfd;
error = __wasi_path_open(fd, lookup_flags, path,
error = __wasi_path_open2(fd, lookup_flags, path,
(oflag >> 12) & 0xfff,
fs_rights_base, fs_rights_inheriting, fs_flags,
&newfd);
fd_flags, &newfd);
if (error != 0) {
errno = error;
return -1;
Expand Down
5 changes: 1 addition & 4 deletions libc-bottom-half/headers/public/__header_fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
#define O_SEARCH (0x08000000)
#define O_WRONLY (0x10000000)

/*
* O_CLOEXEC is defined to be zero, as WASI has no exec-style functions.
*/
#define O_CLOEXEC (0)
#define O_CLOEXEC (__WASI_FDFLAGSEXT_CLOEXEC << 24)

/*
* O_TTY_INIT is defined to be zero, meaning that WASI implementations are
Expand Down
85 changes: 85 additions & 0 deletions libc-bottom-half/headers/public/wasi/api_wasix.h
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,18 @@ typedef uint16_t __wasi_eventfdflags_t;
*/
#define __WASI_EVENTFDFLAGS_SEMAPHORE ((__wasi_eventfdflags_t)(1 << 0))

/**
* Actual file descriptor flags. The fdflags type from WASI corresponds to
* file status flags, which is why we had to come up with a weird name for
* this type.
*/
typedef uint16_t __wasi_fdflagsext_t;

/**
* Close this file in the child process when spawning one.
*/
#define __WASI_FDFLAGSEXT_CLOEXEC ((__wasi_fdflagsext_t)(1 << 0))

/**
* Rect that represents the TTY.
*/
Expand Down Expand Up @@ -3631,6 +3643,15 @@ __wasi_errno_t __wasi_fd_dup(
__wasi_fd_t fd,
__wasi_fd_t *retptr0
) __attribute__((__warn_unused_result__));
/**
* Atomically duplicate a file handle.
*/
__wasi_errno_t __wasi_fd_dup2(
__wasi_fd_t fd,
__wasi_fd_t min_result_fd,
__wasi_bool_t cloexec,
__wasi_fd_t *retptr0
) __attribute__((__warn_unused_result__));
/**
* Creates a file handle for event notifications
*
Expand Down Expand Up @@ -3849,6 +3870,70 @@ _Noreturn void __wasi_stack_restore(
*/
__wasi_longsize_t val
);
/**
* Open a file or directory.
* The returned file descriptor is not guaranteed to be the lowest-numbered
* file descriptor not currently open; it is randomized to prevent
* applications from depending on making assumptions about indexes, since this
* is error-prone in multi-threaded contexts. The returned file descriptor is
* guaranteed to be less than 2**31.
* Note: This is similar to `openat` in POSIX.
* Recreated in WASIX from the original WASI function to add support for
* fdflagsext.
* @return
* The file descriptor of the file that has been opened.
*/
__wasi_errno_t __wasi_path_open2(
__wasi_fd_t fd,
/**
* Flags determining the method of how the path is resolved.
*/
__wasi_lookupflags_t dirflags,
/**
* The relative path of the file or directory to open, relative to the
* `path_open::fd` directory.
*/
const char *path,
/**
* The method by which to open the file.
*/
__wasi_oflags_t oflags,
/**
* The initial rights of the newly created file descriptor. The
* implementation is allowed to return a file descriptor with fewer rights
* than specified, if and only if those rights do not apply to the type of
* file being opened.
* The *base* rights are rights that will apply to operations using the file
* descriptor itself, while the *inheriting* rights are rights that apply to
* file descriptors derived from it.
*/
__wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting,
__wasi_fdflags_t fdflags,
__wasi_fdflagsext_t fdflagsext,
__wasi_fd_t *retptr0
) __attribute__((__warn_unused_result__));
/**
* Get the FD flags of a file descriptor (fdflagsext).
* Note: This returns similar flags to `fsync(fd, F_GETFD)` in POSIX.
* @return
* The buffer where the file descriptor's attributes are stored.
*/
__wasi_errno_t __wasi_fd_fdflags_get(
__wasi_fd_t fd,
__wasi_fdflagsext_t *retptr0
) __attribute__((__warn_unused_result__));
/**
* Adjust the FD flags associated with a file descriptor.
* Note: This is similar to `fcntl(fd, F_SETFD, flags)` in POSIX.
*/
__wasi_errno_t __wasi_fd_fdflags_set(
__wasi_fd_t fd,
/**
* The desired values of the file descriptor flags.
*/
__wasi_fdflagsext_t flags
) __attribute__((__warn_unused_result__));
/**
* Send a signal to the process of the calling thread on a regular basis
* Note: This is similar to `setitimer` in POSIX.
Expand Down
62 changes: 62 additions & 0 deletions libc-bottom-half/sources/__wasixlibc_real.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@ __wasi_errno_t __wasi_fd_dup(
return (uint16_t) ret;
}

int32_t __imported_wasix_32v1_fd_dup2(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("fd_dup2")
));

__wasi_errno_t __wasi_fd_dup2(
__wasi_fd_t fd,
__wasi_fd_t min_result_fd,
__wasi_bool_t cloexec,
__wasi_fd_t *retptr0
){
int32_t ret = __imported_wasix_32v1_fd_dup2((int32_t) fd, (int32_t) min_result_fd, (int32_t) cloexec, (intptr_t) retptr0);
return (uint16_t) ret;
}

int32_t __imported_wasix_32v1_fd_event(int64_t arg0, int32_t arg1, int32_t arg2) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("fd_event")
Expand Down Expand Up @@ -279,6 +294,53 @@ _Noreturn void __wasi_stack_restore(
__imported_wasix_32v1_stack_restore((int32_t) snapshot, (int64_t) val);
}

int32_t __imported_wasix_32v1_path_open2(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int64_t arg5, int64_t arg6, int32_t arg7, int32_t arg8, int32_t arg9) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("path_open2")
));

__wasi_errno_t __wasi_path_open2(
__wasi_fd_t fd,
__wasi_lookupflags_t dirflags,
const char *path,
__wasi_oflags_t oflags,
__wasi_rights_t fs_rights_base,
__wasi_rights_t fs_rights_inheriting,
__wasi_fdflags_t fdflags,
__wasi_fdflagsext_t fdflagsext,
__wasi_fd_t *retptr0
){
size_t path_len = strlen(path);
int32_t ret = __imported_wasix_32v1_path_open2((int32_t) fd, dirflags, (intptr_t) path, (intptr_t) path_len, oflags, fs_rights_base, fs_rights_inheriting, fdflags, fdflagsext, (intptr_t) retptr0);
return (uint16_t) ret;
}

int32_t __imported_wasix_32v1_fd_fdflags_get(int32_t arg0, int32_t arg1) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("fd_fdflags_get")
));

__wasi_errno_t __wasi_fd_fdflags_get(
__wasi_fd_t fd,
__wasi_fdflagsext_t *retptr0
){
int32_t ret = __imported_wasix_32v1_fd_fdflags_get((int32_t) fd, (intptr_t) retptr0);
return (uint16_t) ret;
}

int32_t __imported_wasix_32v1_fd_fdflags_set(int32_t arg0, int32_t arg1) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("fd_fdflags_set")
));

__wasi_errno_t __wasi_fd_fdflags_set(
__wasi_fd_t fd,
__wasi_fdflagsext_t flags
){
int32_t ret = __imported_wasix_32v1_fd_fdflags_set((int32_t) fd, flags);
return (uint16_t) ret;
}

int32_t __imported_wasix_32v1_proc_raise_interval(int32_t arg0, int64_t arg1, int32_t arg2) __attribute__((
__import_module__("wasix_32v1"),
__import_name__("proc_raise_interval")
Expand Down
2 changes: 1 addition & 1 deletion libc-top-half/musl/src/thread/thrd_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
{
int ret = __pthread_create(thr, __ATTRP_C11_THREAD, (void *(*)(void *))func, arg);
int ret = __pthread_create(thr, __ATTRP_C11_THREAD, (void *(*)(void *))(void *)func, arg);
switch (ret) {
case 0: return thrd_success;
case EAGAIN: return thrd_nomem;
Expand Down

0 comments on commit 1ce83b0

Please sign in to comment.