Fix FreeBSD implementations of read_at and write_at

These procedures must not modify the underlying file pointer.
This commit is contained in:
Feoramund
2024-08-19 17:19:00 -04:00
committed by Laytan
parent 1ced76cdd1
commit 5c8c63ae04
2 changed files with 93 additions and 12 deletions

View File

@@ -6,6 +6,7 @@ foreign import libc "system:c"
import "base:runtime"
import "core:strings"
import "core:c"
import "core:sys/freebsd"
Handle :: distinct i32
File_Time :: distinct u64
@@ -481,23 +482,27 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) {
}
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
curr := seek(fd, offset, SEEK_CUR) or_return
n, err = read(fd, data)
_, err1 := seek(fd, curr, SEEK_SET)
if err1 != nil && err == nil {
err = err1
if len(data) == 0 {
return 0, nil
}
return
to_read := min(uint(len(data)), MAX_RW)
bytes_read, errno := freebsd.pread(cast(freebsd.Fd)fd, data[:to_read], cast(freebsd.off_t)offset)
return bytes_read, cast(_Platform_Error)errno
}
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) {
curr := seek(fd, offset, SEEK_CUR) or_return
n, err = write(fd, data)
_, err1 := seek(fd, curr, SEEK_SET)
if err1 != nil && err == nil {
err = err1
if len(data) == 0 {
return 0, nil
}
return
to_write := min(uint(len(data)), MAX_RW)
bytes_written, errno := freebsd.pwrite(cast(freebsd.Fd)fd, data[:to_write], cast(freebsd.off_t)offset)
return bytes_written, cast(_Platform_Error)errno
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {

View File

@@ -14,6 +14,8 @@ import "core:c"
// FreeBSD 15 syscall numbers
// See: https://alfonsosiciliano.gitlab.io/posts/2023-08-28-freebsd-15-system-calls.html
SYS_read : uintptr : 3
SYS_write : uintptr : 4
SYS_open : uintptr : 5
SYS_close : uintptr : 6
SYS_getpid : uintptr : 20
@@ -29,12 +31,46 @@ SYS_shutdown : uintptr : 134
SYS_setsockopt : uintptr : 105
SYS_sysctl : uintptr : 202
SYS__umtx_op : uintptr : 454
SYS_pread : uintptr : 475
SYS_pwrite : uintptr : 476
SYS_accept4 : uintptr : 541
//
// Odin syscall wrappers
//
// Read input.
//
// The read() function appeared in Version 1 AT&T UNIX.
read :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_read,
cast(uintptr)fd,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf))
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Write output.
//
// The write() function appeared in Version 1 AT&T UNIX.
write :: proc "contextless" (fd: Fd, buf: []u8) -> (int, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_pwrite,
cast(uintptr)fd,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf))
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Open or create a file for reading, writing or executing.
//
// The open() function appeared in Version 1 AT&T UNIX.
@@ -469,6 +505,46 @@ _umtx_op :: proc "contextless" (obj: rawptr, op: Userland_Mutex_Operation, val:
return cast(Errno)result
}
// Read input without modifying the file pointer.
//
// The pread() function appeared in AT&T System V Release 4 UNIX.
pread :: proc "contextless" (fd: Fd, buf: []u8, offset: off_t) -> (int, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_pread,
cast(uintptr)fd,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf),
cast(uintptr)offset)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Write output without modifying the file pointer.
//
// The pwrite() function appeared in AT&T System V Release 4 UNIX.
//
// BUGS
//
// The pwrite() system call appends the file without changing the file
// offset if O_APPEND is set, contrary to IEEE Std 1003.1-2008 (“POSIX.1”)
// where pwrite() writes into offset regardless of whether O_APPEND is set.
pwrite :: proc "contextless" (fd: Fd, buf: []u8, offset: off_t) -> (int, Errno) {
result, ok := intrinsics.syscall_bsd(SYS_pwrite,
cast(uintptr)fd,
cast(uintptr)raw_data(buf),
cast(uintptr)len(buf),
cast(uintptr)offset)
if !ok {
return 0, cast(Errno)result
}
return cast(int)result, nil
}
// Accept a connection on a socket.
//
// The accept4() system call appeared in FreeBSD 10.0.