浏览代码

Fix FreeBSD implementations of `read_at` and `write_at`

These procedures must not modify the underlying file pointer.
Feoramund 1 年之前
父节点
当前提交
5c8c63ae04
共有 2 个文件被更改,包括 93 次插入12 次删除
  1. 17 12
      core/os/os_freebsd.odin
  2. 76 0
      core/sys/freebsd/syscalls.odin

+ 17 - 12
core/os/os_freebsd.odin

@@ -6,6 +6,7 @@ foreign import libc "system:c"
 import "base:runtime"
 import "base:runtime"
 import "core:strings"
 import "core:strings"
 import "core:c"
 import "core:c"
+import "core:sys/freebsd"
 
 
 Handle :: distinct i32
 Handle :: distinct i32
 File_Time :: distinct u64
 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) {
 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) {
 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) {
 seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {

+ 76 - 0
core/sys/freebsd/syscalls.odin

@@ -14,6 +14,8 @@ import "core:c"
 // FreeBSD 15 syscall numbers
 // FreeBSD 15 syscall numbers
 // See: https://alfonsosiciliano.gitlab.io/posts/2023-08-28-freebsd-15-system-calls.html
 // 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_open       : uintptr : 5
 SYS_close      : uintptr : 6
 SYS_close      : uintptr : 6
 SYS_getpid     : uintptr : 20
 SYS_getpid     : uintptr : 20
@@ -29,12 +31,46 @@ SYS_shutdown   : uintptr : 134
 SYS_setsockopt : uintptr : 105
 SYS_setsockopt : uintptr : 105
 SYS_sysctl     : uintptr : 202
 SYS_sysctl     : uintptr : 202
 SYS__umtx_op   : uintptr : 454
 SYS__umtx_op   : uintptr : 454
+SYS_pread      : uintptr : 475
+SYS_pwrite     : uintptr : 476
 SYS_accept4    : uintptr : 541
 SYS_accept4    : uintptr : 541
 
 
 //
 //
 // Odin syscall wrappers
 // 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.
 // Open or create a file for reading, writing or executing.
 //
 //
 // The open() function appeared in Version 1 AT&T UNIX.
 // 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
 	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.
 // Accept a connection on a socket.
 //
 //
 // The accept4() system call appeared in FreeBSD 10.0.
 // The accept4() system call appeared in FreeBSD 10.0.