Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ the claim can be checked rather than repeated.

```toml
[dependencies]
openkal-musl = "0.22.8"
openkal-musl = "0.22.9"
```

> **Engine floor (mcpp 2026.9.18.3):** this version of this package declares
Expand Down
6 changes: 6 additions & 0 deletions examples/posix/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ int main(int argc, char **argv, char **envp) {
check(lseek(fd, 3, SEEK_SET) == 3, "the position is set");
char rb[8] = {0};
check(read(fd, rb, 4) == 4 && memcmp(rb, "3456", 4) == 0, "four bytes are read from the position");
/* At an offset, and the position stays where the read above left it. */
memset(rb, 0, sizeof rb);
check(pread(fd, rb, 3, 1) == 3 && memcmp(rb, "123", 3) == 0, "three bytes are read at an offset");
check(pwrite(fd, "x", 1, 0) == 1, "a byte is written at an offset");
check(lseek(fd, 0, SEEK_CUR) == 7, "neither moves the position");
check(pread(fd, rb, 2, 0) == 2 && memcmp(rb, "x1", 2) == 0, "the byte written at an offset is read back");
struct stat st;
check(fstat(fd, &st) == 0 && st.st_size == 10, "the open file reports its length");
check(ftruncate(fd, 4) == 0, "the length is set");
Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-musl"
version = "0.22.8"
version = "0.22.9"
description = "musl 1.2.5 redirected onto openkal: one C library, ported once, above every implementation of the specification rather than above one kernel."
license = "Apache-2.0"

Expand Down
15 changes: 15 additions & 0 deletions musl/PATCHES.md
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,21 @@ to a directory's time at all. A file still asks for exactly what is required,
and an implementation that cannot open a directory returns an error that is
passed on unchanged. Asked of the specification.

## A transfer at an offset, made of the position (0.22.9)

`pread`, `pwrite`, `preadv` and `pwritev` are a seek to the offset, the
transfer, and a seek back to the descriptor's position, under the descriptor
table's lock (`do_transfer_at` in `port/src/okm_syscall.c`). openkal reads and
writes a file at its position and has no transfer at an offset. Before 0.22.9
the four answered `ENOSYS`, which a configure check cannot see because the
functions link; LLVM reads every file through `pread`.

A caller can tell one difference. Two positional transfers on one descriptor do
not interleave, but a plain `read` or `write` on the same descriptor in another
thread, made between the two seeks, moves from the positional offset; POSIX
leaves the position of such a call unaffected. A descriptor that is not a file
answers `ESPIPE`, as POSIX states.

## What the architecture does not decide alone

`long double`.
Expand Down
56 changes: 56 additions & 0 deletions port/src/okm_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,47 @@ static syscall_arg_t do_read(int fd, void* buf, size_t len)
return r;
}

/* A TRANSFER AT AN OFFSET, MADE OF THE POSITION.
*
* openkal reads and writes a file at its position and offers no transfer at
* an offset, so `pread' and `pwrite' are a seek, the transfer, and a seek back
* to the position the descriptor had. Until 0.22.9 they were answered ENOSYS,
* which no configure check can see: the functions link. LLVM reads every file
* through `pread', and clangd built as an ok image could open none (measured
* 2026-10-29).
*
* The three steps hold the descriptor table's lock, so two positional transfers
* do not interleave. What the lock does not give is POSIX's other promise: a
* plain `read' or `write' on the same descriptor, in another thread, between
* the two seeks, moves from the positional offset. Recorded in musl/PATCHES.md. */
static syscall_arg_t do_transfer_at(int fd, const struct iovec* v, int count,
int64_t at, int writing)
{
struct okm_desc* d = okm_desc_of(fd);
if (!d) return -EBADF;
if (d->kind != OKM_FILE) return -ESPIPE;
if (at < 0 || count < 0) return -EINVAL;

okm_lock();
kal_u64 keep = 0, now = 0;
int e = okm_fs_seek(d->file, 0, SEEK_CUR, &keep);
if (e == kal_ok) e = okm_fs_seek(d->file, at, SEEK_SET, &now);
if (e != kal_ok) { okm_unlock(); return -okm_errno(e); }

syscall_arg_t total = 0;
for (int i = 0; i < count; i++) {
if (v[i].iov_len == 0) continue;
const syscall_arg_t r = writing ? do_write(fd, v[i].iov_base, v[i].iov_len)
: do_read(fd, v[i].iov_base, v[i].iov_len);
if (r < 0) { if (!total) total = r; break; }
total += r;
if ((size_t)r < v[i].iov_len) break;
}
okm_fs_seek(d->file, (int64_t)keep, SEEK_SET, &now);
okm_unlock();
return total;
}

/* --- opening --------------------------------------------------------------- */

static syscall_arg_t do_openat(int dirfd, const char* path, int flags, int mode)
Expand Down Expand Up @@ -1348,6 +1389,21 @@ syscall_arg_t __okm_syscall(syscall_arg_t n, syscall_arg_t a1, syscall_arg_t a2,
return total;
}

/* The offset is one argument on every target this library builds (LP64);
* see do_transfer_at for how the transfer is made. */
case SYS_pread64: {
struct iovec one = { (void*)a2, (size_t)a3 };
return do_transfer_at((int)a1, &one, 1, (int64_t)a4, 0);
}
case SYS_pwrite64: {
struct iovec one = { (void*)a2, (size_t)a3 };
return do_transfer_at((int)a1, &one, 1, (int64_t)a4, 1);
}
case SYS_preadv:
return do_transfer_at((int)a1, (const struct iovec*)a2, (int)a3, (int64_t)a4, 0);
case SYS_pwritev:
return do_transfer_at((int)a1, (const struct iovec*)a2, (int)a3, (int64_t)a4, 1);

/* --- naming ----------------------------------------------------------- */
case SYS_openat: return do_openat((int)a1, (const char*)a2, (int)a3, (int)a4);
#ifdef SYS_open
Expand Down
Loading