diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2025-11-27 09:06:36 +0000 |
|---|---|---|
| committer | gingerBill <gingerBill@users.noreply.github.com> | 2025-11-27 09:06:36 +0000 |
| commit | 49634246c5853dceb770161bea3742b9171b7a0f (patch) | |
| tree | 68aa1e102b327404d41bc008666afbb388bc25a5 /core | |
| parent | 5380cf8b90132e5a1a638d9e90d0e3b6b1ed0d64 (diff) | |
| parent | f48e87d77d1376f03cf53afbc51b695698d6e5a7 (diff) | |
Merge branch 'master' of https://github.com/odin-lang/Odin
Diffstat (limited to 'core')
| -rw-r--r-- | core/encoding/base64/base64.odin | 54 | ||||
| -rw-r--r-- | core/fmt/fmt.odin | 2 | ||||
| -rw-r--r-- | core/math/math.odin | 29 | ||||
| -rw-r--r-- | core/os/os2/file.odin | 61 | ||||
| -rw-r--r-- | core/os/os2/file_linux.odin | 65 | ||||
| -rw-r--r-- | core/os/os2/file_posix.odin | 13 | ||||
| -rw-r--r-- | core/os/os2/file_stream.odin | 65 | ||||
| -rw-r--r-- | core/os/os2/file_windows.odin | 32 | ||||
| -rw-r--r-- | core/os/os2/stat.odin | 7 | ||||
| -rw-r--r-- | core/sys/linux/bits.odin | 43 | ||||
| -rw-r--r-- | core/sys/linux/constants.odin | 5 | ||||
| -rw-r--r-- | core/sys/linux/sys.odin | 298 | ||||
| -rw-r--r-- | core/sys/linux/types.odin | 57 | ||||
| -rw-r--r-- | core/sys/windows/ws2_32.odin | 10 |
14 files changed, 604 insertions, 137 deletions
diff --git a/core/encoding/base64/base64.odin b/core/encoding/base64/base64.odin index 2cd7227b5..032716bde 100644 --- a/core/encoding/base64/base64.odin +++ b/core/encoding/base64/base64.odin @@ -26,23 +26,39 @@ ENC_TABLE := [64]byte { PADDING :: '=' -DEC_TABLE := [128]int { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 62, -1, -1, -1, 63, +DEC_TABLE := [256]u8 { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, + 60, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, -1, -1, -1, -1, -1, - -1, 26, 27, 28, 29, 30, 31, 32, + 23, 24, 25, 0, 0, 0, 0, 0, + 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, -1, -1, -1, -1, -1, + 49, 50, 51, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } encode :: proc(data: []byte, ENC_TBL := ENC_TABLE, allocator := context.allocator) -> (encoded: string, err: mem.Allocator_Error) #optional_allocator_error { @@ -120,10 +136,10 @@ decode_into :: proc(w: io.Writer, data: string, DEC_TBL := DEC_TABLE) -> io.Erro i, j: int for ; j + 3 <= length; i, j = i + 4, j + 3 { #no_bounds_check { - c0 = DEC_TBL[data[i]] - c1 = DEC_TBL[data[i + 1]] - c2 = DEC_TBL[data[i + 2]] - c3 = DEC_TBL[data[i + 3]] + c0 = int(DEC_TBL[data[i]]) + c1 = int(DEC_TBL[data[i + 1]]) + c2 = int(DEC_TBL[data[i + 2]]) + c3 = int(DEC_TBL[data[i + 3]]) b0 = (c0 << 2) | (c1 >> 4) b1 = (c1 << 4) | (c2 >> 2) @@ -140,9 +156,9 @@ decode_into :: proc(w: io.Writer, data: string, DEC_TBL := DEC_TABLE) -> io.Erro rest := length - j if rest > 0 { #no_bounds_check { - c0 = DEC_TBL[data[i]] - c1 = DEC_TBL[data[i + 1]] - c2 = DEC_TBL[data[i + 2]] + c0 = int(DEC_TBL[data[i]]) + c1 = int(DEC_TBL[data[i + 1]]) + c2 = int(DEC_TBL[data[i + 2]]) b0 = (c0 << 2) | (c1 >> 4) b1 = (c1 << 4) | (c2 >> 2) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index dec4e90fa..7ec3062e1 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1067,7 +1067,7 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d } } - buf: [256]byte + buf: [BUF_SIZE]byte start := 0 if fi.hash && !is_signed { diff --git a/core/math/math.odin b/core/math/math.odin index 34642049c..7afb32db6 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -457,7 +457,6 @@ gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_float(T) { return bias(t*2 - 1, 1 - g) * 0.5 + 0.5 } - @(require_results) sign_f16 :: proc "contextless" (x: f16) -> f16 { return f16(int(0 < x) - int(x < 0)) } @(require_results) sign_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(int(0 < x) - int(x < 0)) } @(require_results) sign_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(int(0 < x) - int(x < 0)) } @@ -467,10 +466,24 @@ gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_float(T) { @(require_results) sign_f64 :: proc "contextless" (x: f64) -> f64 { return f64(int(0 < x) - int(x < 0)) } @(require_results) sign_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(int(0 < x) - int(x < 0)) } @(require_results) sign_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(int(0 < x) - int(x < 0)) } +@(require_results) sign_int :: proc "contextless" (x: int) -> int { return int(0 < x) - int(x < 0) } +@(require_results) sign_i16 :: proc "contextless" (x: i16) -> i16 { return i16(int(0 < x) - int(x < 0)) } +@(require_results) sign_i16le :: proc "contextless" (x: i16le) -> i16le { return i16le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i16be :: proc "contextless" (x: i16be) -> i16be { return i16be(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32 :: proc "contextless" (x: i32) -> i32 { return i32(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32le :: proc "contextless" (x: i32le) -> i32le { return i32le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i32be :: proc "contextless" (x: i32be) -> i32be { return i32be(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64 :: proc "contextless" (x: i64) -> i64 { return i64(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64le :: proc "contextless" (x: i64le) -> i64le { return i64le(int(0 < x) - int(x < 0)) } +@(require_results) sign_i64be :: proc "contextless" (x: i64be) -> i64be { return i64be(int(0 < x) - int(x < 0)) } sign :: proc{ sign_f16, sign_f16le, sign_f16be, sign_f32, sign_f32le, sign_f32be, sign_f64, sign_f64le, sign_f64be, + sign_int, + sign_i16, sign_i16le, sign_i16be, + sign_i32, sign_i32le, sign_i32be, + sign_i64, sign_i64le, sign_i64be, } @(require_results) sign_bit_f16 :: proc "contextless" (x: f16) -> bool { return (transmute(u16)x) & (1<<15) != 0 } @@ -482,10 +495,24 @@ sign :: proc{ @(require_results) sign_bit_f64 :: proc "contextless" (x: f64) -> bool { return (transmute(u64)x) & (1<<63) != 0 } @(require_results) sign_bit_f64le :: proc "contextless" (x: f64le) -> bool { return #force_inline sign_bit_f64(f64(x)) } @(require_results) sign_bit_f64be :: proc "contextless" (x: f64be) -> bool { return #force_inline sign_bit_f64(f64(x)) } +@(require_results) sign_bit_int :: proc "contextless" (x: int) -> bool { return uint(x) & (1<<(size_of(int)*8 - 1)) != 0 } +@(require_results) sign_bit_i16 :: proc "contextless" (x: i16) -> bool { return u16(x) & (1<<15) != 0 } +@(require_results) sign_bit_i16le :: proc "contextless" (x: i16le) -> bool { return #force_inline sign_bit_i16(i16(x)) } +@(require_results) sign_bit_i16be :: proc "contextless" (x: i16be) -> bool { return #force_inline sign_bit_i16(i16(x)) } +@(require_results) sign_bit_i32 :: proc "contextless" (x: i32) -> bool { return u32(x) & (1<<31) != 0 } +@(require_results) sign_bit_i32le :: proc "contextless" (x: i32le) -> bool { return #force_inline sign_bit_i32(i32(x)) } +@(require_results) sign_bit_i32be :: proc "contextless" (x: i32be) -> bool { return #force_inline sign_bit_i32(i32(x)) } +@(require_results) sign_bit_i64 :: proc "contextless" (x: i64) -> bool { return u64(x) & (1<<63) != 0 } +@(require_results) sign_bit_i64le :: proc "contextless" (x: i64le) -> bool { return #force_inline sign_bit_i64(i64(x)) } +@(require_results) sign_bit_i64be :: proc "contextless" (x: i64be) -> bool { return #force_inline sign_bit_i64(i64(x)) } sign_bit :: proc{ sign_bit_f16, sign_bit_f16le, sign_bit_f16be, sign_bit_f32, sign_bit_f32le, sign_bit_f32be, sign_bit_f64, sign_bit_f64le, sign_bit_f64be, + sign_bit_int, + sign_bit_i16, sign_bit_i16le, sign_bit_i16be, + sign_bit_i32, sign_bit_i32le, sign_bit_i32be, + sign_bit_i64, sign_bit_i64le, sign_bit_i64be, } @(require_results) diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index 85ebfcece..9e7788c31 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -22,8 +22,7 @@ import "base:runtime" */ File :: struct { impl: rawptr, - stream: io.Stream, - fstat: Fstat_Callback, + stream: File_Stream, } /* @@ -218,7 +217,11 @@ name :: proc(f: ^File) -> string { */ close :: proc(f: ^File) -> Error { if f != nil { - return io.close(f.stream) + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Close, nil, 0, nil, runtime.nil_allocator()) + return err } return nil } @@ -235,7 +238,10 @@ close :: proc(f: ^File) -> Error { */ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { if f != nil { - return io.seek(f.stream, offset, whence) + if f.stream.procedure == nil { + return 0, .Unsupported + } + return f.stream.procedure(f, .Seek, nil, offset, whence, runtime.nil_allocator()) } return 0, .Invalid_File } @@ -247,7 +253,12 @@ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Err */ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.read(f.stream, p) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read, p, 0, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -260,7 +271,12 @@ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { */ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.read_at(f.stream, p, offset) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -272,7 +288,12 @@ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { */ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.write(f.stream, p) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write, p, 0, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -284,7 +305,12 @@ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { */ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.write_at(f.stream, p, offset) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -294,7 +320,18 @@ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { */ file_size :: proc(f: ^File) -> (n: i64, err: Error) { if f != nil { - return io.size(f.stream) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n, err = f.stream.procedure(f, .Size, nil, 0, nil, runtime.nil_allocator()) + if err == .Unsupported { + n = 0 + curr := seek(f, 0, .Current) or_return + end := seek(f, 0, .End) or_return + seek(f, curr, .Start) or_return + n = end + } + return } return 0, .Invalid_File } @@ -304,7 +341,11 @@ file_size :: proc(f: ^File) -> (n: i64, err: Error) { */ flush :: proc(f: ^File) -> Error { if f != nil { - return io.flush(f.stream) + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Flush, nil, 0, nil, runtime.nil_allocator()) + return err } return nil } diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index 6d66ffd75..fb25ca411 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -29,19 +29,16 @@ _stdin := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stdout := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stderr := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } @init @@ -55,7 +52,6 @@ _standard_stream_init :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -109,7 +105,6 @@ _new_file :: proc(fd: uintptr, _: string, allocator: runtime.Allocator) -> (f: ^ data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -476,88 +471,76 @@ _read_entire_pseudo_file_cstring :: proc(name: cstring, allocator: runtime.Alloc } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } @(private="package") -_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } diff --git a/core/os/os2/file_posix.odin b/core/os/os2/file_posix.odin index f445cb5f4..874ec7c7d 100644 --- a/core/os/os2/file_posix.odin +++ b/core/os/os2/file_posix.odin @@ -36,7 +36,6 @@ init_std_files :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -110,7 +109,6 @@ __new_file :: proc(handle: posix.FD, allocator: runtime.Allocator) -> ^File { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -371,7 +369,7 @@ _exists :: proc(path: string) -> bool { return posix.access(cpath) == .OK } -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) fd := f.fd @@ -489,18 +487,19 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, return case .Flush: - ferr := _sync(&f.file) - err = error_to_io_error(ferr) + err = _sync(&f.file) return case .Close, .Destroy: - ferr := _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return case: return 0, .Unsupported } diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index e1c29a792..af6e50921 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -1,12 +1,50 @@ package os2 +import "base:intrinsics" +import "base:runtime" import "core:io" +// A subset of the io.Stream_Mode with added File specific modes +File_Stream_Mode :: enum { + Close, + Flush, + Read, + Read_At, + Write, + Write_At, + Seek, + Size, + Destroy, + Query, // query what modes are available on `io.Stream` + + Fstat, // File specific (not available on io.Stream) +} +#assert(intrinsics.type_is_superset_of(File_Stream_Mode, io.Stream_Mode)) + +// Superset interface of io.Stream_Proc with the added `runtime.Allocator` parameter needed for the Fstat mode +File_Stream_Proc :: #type proc( + stream_data: rawptr, + mode: File_Stream_Mode, + p: []byte, + offset: i64, + whence: io.Seek_From, + allocator: runtime.Allocator, +) -> (n: i64, err: Error) + +File_Stream :: struct { + procedure: File_Stream_Proc, + data: rawptr, +} + + // Converts a file `f` into an `io.Stream` to_stream :: proc(f: ^File) -> (s: io.Stream) { if f != nil { assert(f.stream.procedure != nil) - s = f.stream + s = { + file_io_stream_proc, + f, + } } return } @@ -24,3 +62,28 @@ to_writer :: to_stream even if it has no logical difference. */ to_reader :: to_stream + + +@(private="package") +file_io_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { + f := (^File)(stream_data) + + file_stream_mode := transmute(File_Stream_Mode)mode + + ferr: Error + n, ferr = f.stream.procedure(f, file_stream_mode, p, offset, whence, runtime.nil_allocator()) + err = error_to_io_error(ferr) + return +} + +@(private="package") +file_stream_fstat_utility :: proc(f: ^File_Impl, p: []byte, allocator: runtime.Allocator) -> (err: Error) { + fi: File_Info + if len(p) >= size_of(fi) { + fi, err = _fstat(&f.file, allocator) + runtime.mem_copy_non_overlapping(raw_data(p), &fi, size_of(fi)) + } else { + err = .Short_Buffer + } + return +}
\ No newline at end of file diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 03fbc596e..0d2f28642 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -65,7 +65,6 @@ init_std_files :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -185,7 +184,6 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) - data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -827,44 +825,38 @@ _exists :: proc(path: string) -> bool { } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin index f87afc4c9..58df45754 100644 --- a/core/os/os2/stat.odin +++ b/core/os/os2/stat.odin @@ -46,8 +46,11 @@ file_info_delete :: proc(fi: File_Info, allocator: runtime.Allocator) { fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { if f == nil { return {}, nil - } else if f.fstat != nil { - return f->fstat(allocator) + } else if f.stream.procedure != nil { + fi: File_Info + data := ([^]byte)(&fi)[:size_of(fi)] + _, err := f.stream.procedure(f, .Fstat, data, 0, nil, allocator) + return fi, err } return {}, .Invalid_Callback } diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 12ae949ef..213d6c26f 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -2226,3 +2226,46 @@ IO_Uring_Submission_Queue_Flags_Bits :: enum { CQ_OVERFLOW, TASKRUN, } + +Mount_Flags_Bits :: enum { + RDONLY = log2(1), + NOSUID = log2(2), + NODEV = log2(4), + NOEXEC = log2(8), + SYNCHRONOUS = log2(16), + REMOUNT = log2(32), + MANDLOCK = log2(64), + DIRSYNC = log2(128), + NOATIME = log2(1024), + NODIRATIME = log2(2048), + BIND = log2(4096), + MOVE = log2(8192), + REC = log2(16384), + SILENT = log2(32768), + POSIXACL = log2(1<<16), + UNBINDABLE = log2(1<<17), + PRIVATE = log2(1<<18), + SLAVE = log2(1<<19), + SHARED = log2(1<<20), + RELATIME = log2(1<<21), + KERNMOUNT = log2(1<<22), + I_VERSION = log2(1<<23), + STRICTATIME = log2(1<<24), + LAZYTIME = log2(1<<25), + ACTIVE = log2(1<<30), + NOUSER = log2(1<<31), + NOSYMFOLLOW = log2(256), +} + +Umount2_Flags_Bits :: enum { + MNT_FORCE = log2(0x00000001), + MNT_DETACH = log2(0x00000002), + MNT_EXPIRE = log2(0x00000004), + UMOUNT_NOFOLLOW = log2(0x00000008), + UMOUNT_UNUSED = log2(0x80000000), +} + +Swap_Flags_Bits :: enum { + PREFER = log2(0x8000), + DISCARD = log2(0x10000), +} diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index c80777025..71a16312e 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -54,6 +54,8 @@ PRIO_MIN :: -20 SIGRTMIN :: Signal(32) SIGRTMAX :: Signal(64) +_NSIG :: 65 + S_IFMT :: Mode{.IFREG, .IFDIR, .IFCHR, .IFIFO} S_IFSOCK :: Mode{.IFREG, .IFDIR} S_IFLNK :: Mode{.IFREG, .IFCHR} @@ -405,3 +407,6 @@ IORING_OFF_SQES :: 0x10000000 IORING_OFF_PBUF_RING :: 0x80000000 IORING_OFF_PBUF_SHIFT :: 16 IORING_OFF_MMAP_MASK :: 0xf8000000 + +SWAP_FLAG_PRIO_SHIFT :: u32(0) +SWAP_FLAG_PRIO_MASK :: u32(0x7fff) diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index cfd586a66..04305ece1 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -2100,19 +2100,67 @@ munlockall :: proc "contextless" () -> (Errno) { return Errno(-ret) } -// TODO(flysand): vhangup +/* + Virtually hangup the current terminal + Available since Linux 1.0. +*/ +vhangup :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_vhangup) + return Errno(-ret) +} -// TODO(flysand): modify_ldt +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Get or set local descriptor table + Available since Linux 2.1 + */ + modify_ldt :: proc "contextless" (func: i32, ptr: rawptr, bytecount: uint) -> (int, Errno) { + ret := syscall(SYS_modify_ldt, func, ptr, bytecount) + return errno_unwrap(ret, int) + } +} -// TODO(flysand): pivot_root +/* + Change the root mount + Available since Linux 2.3.41 +*/ +pivot_root :: proc "contextless" (new_root: cstring, old_root: cstring) -> (Errno) { + ret := syscall(SYS_pivot_root, cast(rawptr) new_root, cast(rawptr) old_root) + return Errno(-ret) +} // TODO(flysand): _sysctl +// Deprecated and discouraged -// TODO(flysand): prctl +/* + Operations on a process or thread + Available since Linux 2.1.57 +*/ +prctl :: proc "contextless" (op: i32, args: ..uint) -> (Errno) { + assert_contextless(len(args) <= 4) + ret := syscall(SYS_prctl, op, args[0], args[1], args[2], args[3]) + return Errno(-ret) +} -// TODO(flysand): arch_prctl +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Set architecture-specific thread state + Available since Linux 2.6.19 + */ + arch_prctl :: proc "contextless" (op: i32, addr: uint) -> (Errno) { + ret := syscall(SYS_arch_prctl, op, addr) + return Errno(-ret) + } +} -// TODO(flysand): adj_timex +/* + Display or set the kernel time variables + Available since Linux 1.0. +*/ +adjtimex :: proc "contextless" (buf: ^Timex) -> (Clock_State, Errno) { + ret := syscall(SYS_adjtimex) + return errno_unwrap(ret, Clock_State) +} /* Set limits on resources. @@ -2123,21 +2171,86 @@ setrlimit :: proc "contextless" (kind: RLimit_Kind, resource: ^RLimit) -> (Errno return Errno(-ret) } -// TODO(flysand): sync +/* + Change root directory + Available since Linux 1.0. +*/ +chroot :: proc "contextless" (pathname: cstring) -> (Errno) { + ret := syscall(SYS_chroot, cast(rawptr) pathname) + return Errno(-ret) +} + +/* + Commit filesystem caches to disk + Available since Linux 1.0. +*/ +sync :: proc "contextless" () -> (Errno) { + ret := syscall(SYS_sync) + return Errno(-ret) +} -// TODO(flysand): acct +/* + Switch process accounting on or off + Available since Linux 2.3.23 +*/ +acct :: proc "contextless" (filename: cstring) -> (Errno) { + ret := syscall(SYS_acct, cast(rawptr) filename) + return Errno(-ret) +} -// TODO(flysand): settimeofday +/* + Set Time + Available since Linux 1.0 +*/ +settimeofday :: proc "contextless" (tv: ^Time_Val) -> (Errno) { + ret := syscall(SYS_settimeofday, tv, rawptr(nil)) + return Errno(-ret) +} -// TODO(flysand): mount +/* + Mount filesystem + Available since Linux 1.0 +*/ +mount :: proc "contextless" (source: cstring, target: cstring, filesystemtype: cstring, mountflags: Mount_Flags, data: rawptr) -> (Errno) { + ret := syscall(SYS_mount, cast(rawptr) source, cast(rawptr) target, cast(rawptr) filesystemtype, transmute(uint) mountflags, data) + return Errno(-ret) +} -// TODO(flysand): umount2 +/* + Unmount filesystem + Available since Linux 2.1 +*/ +umount2 :: proc "contextless" (target: cstring, flags: Umount2_Flags) -> (Errno) { + ret := syscall(SYS_umount2, cast(rawptr) target, transmute(u32) flags) + return Errno(-ret) +} -// TODO(flysand): swapon +/* + Start swapping to file/device + Available since Linux 2.0 +*/ +swapon :: proc "contextless" (path: cstring, swapflags: Swap_Flags) -> (Errno) { + ret := syscall(SYS_swapon, cast(rawptr) path, transmute(u32) swapflags) + return Errno(-ret) +} -// TODO(flysand): swapoff +/* + Stop swapping to file/device + Available since Linux 2.0 +*/ +swapoff :: proc "contextless" (path: cstring) -> (Errno) { + ret := syscall(SYS_swapoff, cast(rawptr) path) + return Errno(-ret) +} -// TODO(flysand): reboot +/* + Reboot or enable/disable Ctrl-Alt-Del + Available since Linux 1.0 +*/ +reboot :: proc "contextless" (magic: Reboot_Magic, magic2: Reboot_Magic, op: Reboot_Operation, arg: rawptr) -> (Errno) { + ret := syscall(SYS_reboot, cast(i32)magic, cast(i32)magic2, cast(i32)op, arg) + return Errno(-ret) +} /* Set hostname. @@ -2160,16 +2273,48 @@ setdomainname :: proc "contextless" (name: string) -> (Errno) { } // TODO(flysand): iopl +// deprecated -// TODO(flysand): ioperm +when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 { + /* + Set port input/output permissions + Available since Linux 1.0 + */ + ioperm :: proc "contextless" (form: u32, num: u32, turn_on: i32) -> (Errno) { + ret := syscall(SYS_ioperm, form, num, turn_on) + return Errno(-ret) + } +} -// TODO(flysand): init_module +/* + Load a kernel module + Available since Linux 2.2 +*/ +init_module :: proc "contextless" (module_image: rawptr, size: u32, param_values: cstring) -> (Errno) { + ret := syscall(SYS_init_module, module_image, size, cast(rawptr) param_values) + return Errno(-ret) +} -// TODO(flysand): delete_module +/* + Unload a kernel module + Available since Linux 2.2 +*/ +delete_module :: proc "contextless" (name: cstring, flags: u32) -> (Errno) { + ret := syscall(SYS_delete_module, cast(rawptr) name, flags) + return Errno(-ret) +} -// TODO(flysand): quotactl +/* + Manipulate disk quotas + Available since Linux 2.0 +*/ +quotactl :: proc "contextless" (op: i32, special: cstring, id: i32, addr: rawptr) -> (Errno) { + ret := syscall(SYS_quotactl, op, cast(rawptr) special, id, addr) + return Errno(-ret) +} // TODO(flysand): nfsservctl +/// No longer present after 3.1 // TODO(flysand): getpmsg @@ -2193,31 +2338,122 @@ gettid :: proc "contextless" () -> Pid { return cast(Pid) syscall(SYS_gettid) } -// TODO(flysand): readahead +/* + Initiate a file readahead into page cache + Available since Linux 2.1 +*/ +readahead :: proc "contextless" (fd: Fd, offset: int, count: uint) -> (Errno) { + ret := syscall(SYS_readahead, fd, offset, count) + return Errno(-ret) +} -// TODO(flysand): setxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +setxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_setxattr, cast(rawptr) path, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): lsetxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +lsetxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_lsetxattr, cast(rawptr) path, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): fsetxattr +/* + Set an extended attribute value + Available since Linux 2.6.25 +*/ +fsetxattr :: proc "contextless" (fd: Fd, name: cstring, value: rawptr, size: uint, flags: i32) -> (Errno) { + ret := syscall(SYS_fsetxattr, fd, cast(rawptr) name, value, size, flags) + return Errno(-ret) +} -// TODO(flysand): getxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +getxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_getxattr, cast(rawptr) path, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): lgetxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +lgetxattr :: proc "contextless" (path: cstring, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_lgetxattr, cast(rawptr) path, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): fgetxattr +/* + Retrieve an extended attribute + Available since Linux 2.6.25 +*/ +fgetxattr :: proc "contextless" (fd: Fd, name: cstring, value: rawptr, size: uint) -> (Errno) { + ret := syscall(SYS_fgetxattr, fd, cast(rawptr) name, value, size) + return Errno(-ret) +} -// TODO(flysand): listxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +listxattr :: proc "contextless" (path: cstring, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_listxattr, cast(rawptr) path, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): llistxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +llistxattr :: proc "contextless" (path: cstring, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_llistxattr, cast(rawptr) path, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): flistxattr +/* + List extended attribute names + Available since Linux 2.6.25 +*/ +flistxattr :: proc "contextless" (fd: Fd, list: cstring, size: uint) -> (Errno) { + ret := syscall(SYS_flistxattr, fd, cast(rawptr) list, size) + return Errno(-ret) +} -// TODO(flysand): removexattr +/* + Remove an extended attribute + Available since Linux 2.6.25 +*/ +removexattr :: proc "contextless" (path: cstring, name: cstring) -> (Errno) { + ret := syscall(SYS_removexattr, cast(rawptr) path, cast(rawptr) name) + return Errno(-ret) +} -// TODO(flysand): lremovexattr +/* + Remove an extended attribute + Available since Linux 2.6 +*/ +lremovexattr :: proc "contextless" (path: cstring, name: cstring) -> (Errno) { + ret := syscall(SYS_lremovexattr, cast(rawptr) path, cast(rawptr) name) + return Errno(-ret) +} -// TODO(flysand): fremovexattr +/* + Remove an extended attribute + Available since Linux 2.6.25 +*/ +fremovexattr :: proc "contextless" (fd: Fd, name: cstring) -> (Errno) { + ret := syscall(SYS_fremovexattr, fd, cast(rawptr) name) + return Errno(-ret) +} /* Get current time in seconds. diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index a2819803c..6a2f7cbca 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -1691,3 +1691,60 @@ IO_Uring_Accept_Flags :: bit_set[IO_Uring_Accept_Flags_Bits; u16] IO_Uring_Send_Recv_Flags :: bit_set[IO_Uring_Send_Recv_Flags_Bits; u16] IO_Uring_Submission_Queue_Flags :: bit_set[IO_Uring_Submission_Queue_Flags_Bits; u32] + +Clock_State :: enum i32 { + TIME_OK = 0, + TIME_INS = 1, + TIME_DEL = 2, + TIME_OOP = 3, + TIME_WAIT = 4, + TIME_ERROR = 5, +} + +Timex :: struct { + modes: u32, + offset: int, + freq: int, + maxerror: int, + esterror: int, + status: i32, + constant: int, + precision: int, + tolerance: int, + time: Time_Val, + tick: int, + ppsfreq: int, + jitter: int, + shift: i32, + stabil: int, + jitcnt: int, + calcnt: int, + errcnt: int, + stbcnt: int, + tai: i32, +} + +Reboot_Magic :: enum u64 { + RB_MAGIC_1 = 0xfee1dead, + RB_MAGIC_2 = 672274793, + RB_MAGIC_2A = 85072278, // Since Linux 2.1.17 + RB_MAGIC_2B = 369367448, // Since Linux 2.1.97 + RB_MAGIC_2C = 537993216, // Since Linux 2.5.71 +} + +Reboot_Operation :: enum u64 { + RB_DISABLE_CAD = 0, + RB_ENABLE_CAD = 0x89abcdef, + RB_HALT_SYSTEM = 0xcdef0123, + RB_KEXEC = 0x45584543, + RB_POWER_OFF = 0x4321fedc, + RB_AUTOBOOT = 0x01234567, + RB_AUTOBOOT_2 = 0xa1b2c3d4, + RB_SW_SUSPEND = 0xd000fce2, +} + +Mount_Flags :: bit_set[Mount_Flags_Bits; uint] + +Umount2_Flags :: bit_set[Umount2_Flags_Bits; u32] + +Swap_Flags :: bit_set[Swap_Flags_Bits; u32] diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index 66054dd98..ed2ad5e24 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -42,11 +42,13 @@ WSAID_GETACCEPTEXSOCKADDRS :: GUID{0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00 WSAID_CONNECTX :: GUID{0x25a207b9, 0xddf3, 0x4660, {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} SIO_GET_EXTENSION_FUNCTION_POINTER :: IOC_INOUT | IOC_WS2 | 6 +SIO_UDP_CONNRESET :: IOC_IN | IOC_VENDOR | 12 -IOC_OUT :: 0x40000000 -IOC_IN :: 0x80000000 -IOC_INOUT :: (IOC_IN | IOC_OUT) -IOC_WS2 :: 0x08000000 +IOC_OUT :: 0x40000000 +IOC_IN :: 0x80000000 +IOC_INOUT :: (IOC_IN | IOC_OUT) +IOC_WS2 :: 0x08000000 +IOC_VENDOR :: 0x18000000 SO_UPDATE_ACCEPT_CONTEXT :: 28683 |