mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Add os.read_at and for Windows; fix mem.clone_slice; fix current directory locking code
This commit is contained in:
+1
-1
@@ -290,6 +290,6 @@ calc_padding_with_header :: proc(ptr: uintptr, align: uintptr, header_size: int)
|
|||||||
|
|
||||||
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> T {
|
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> T {
|
||||||
new_slice := make(T, len(slice), allocator, loc);
|
new_slice := make(T, len(slice), allocator, loc);
|
||||||
copy(new_slice, slice);
|
runtime.copy(new_slice, slice);
|
||||||
return new_slice;
|
return new_slice;
|
||||||
}
|
}
|
||||||
|
|||||||
+107
-15
@@ -77,8 +77,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|||||||
|
|
||||||
for total_write < length {
|
for total_write < length {
|
||||||
remaining := length - total_write;
|
remaining := length - total_write;
|
||||||
MAX :: 1<<31-1;
|
to_write := win32.DWORD(min(i32(remaining), MAX_RW));
|
||||||
to_write := win32.DWORD(min(i32(remaining), MAX));
|
|
||||||
|
|
||||||
e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil);
|
e := win32.WriteFile(win32.HANDLE(fd), &data[total_write], to_write, &single_write_length, nil);
|
||||||
if single_write_length <= 0 || !e {
|
if single_write_length <= 0 || !e {
|
||||||
@@ -101,8 +100,7 @@ read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
|||||||
|
|
||||||
for total_read < length {
|
for total_read < length {
|
||||||
remaining := length - total_read;
|
remaining := length - total_read;
|
||||||
MAX :: 1<<32-1;
|
to_read := win32.DWORD(min(u32(remaining), MAX_RW));
|
||||||
to_read := win32.DWORD(min(u32(remaining), MAX));
|
|
||||||
|
|
||||||
e := win32.ReadFile(win32.HANDLE(fd), &data[total_read], to_read, &single_read_length, nil);
|
e := win32.ReadFile(win32.HANDLE(fd), &data[total_read], to_read, &single_read_length, nil);
|
||||||
if single_read_length <= 0 || !e {
|
if single_read_length <= 0 || !e {
|
||||||
@@ -146,6 +144,101 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
MAX_RW :: 1<<30;
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||||
|
buf := data;
|
||||||
|
if len(buf) > MAX_RW {
|
||||||
|
buf = buf[:MAX_RW];
|
||||||
|
|
||||||
|
}
|
||||||
|
curr_offset, e := seek(fd, offset, 1);
|
||||||
|
if e != 0 {
|
||||||
|
return 0, e;
|
||||||
|
}
|
||||||
|
defer seek(fd, curr_offset, 0);
|
||||||
|
|
||||||
|
o := win32.OVERLAPPED{
|
||||||
|
OffsetHigh = u32(offset>>32),
|
||||||
|
Offset = u32(offset),
|
||||||
|
};
|
||||||
|
|
||||||
|
h := win32.HANDLE(fd);
|
||||||
|
done: win32.DWORD;
|
||||||
|
if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
|
||||||
|
e = Errno(win32.GetLastError());
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
return int(done), e;
|
||||||
|
}
|
||||||
|
@(private)
|
||||||
|
pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
|
||||||
|
buf := data;
|
||||||
|
if len(buf) > MAX_RW {
|
||||||
|
buf = buf[:MAX_RW];
|
||||||
|
|
||||||
|
}
|
||||||
|
curr_offset, e := seek(fd, offset, 1);
|
||||||
|
if e != 0 {
|
||||||
|
return 0, e;
|
||||||
|
}
|
||||||
|
defer seek(fd, curr_offset, 0);
|
||||||
|
|
||||||
|
o := win32.OVERLAPPED{
|
||||||
|
OffsetHigh = u32(offset>>32),
|
||||||
|
Offset = u32(offset),
|
||||||
|
};
|
||||||
|
|
||||||
|
h := win32.HANDLE(fd);
|
||||||
|
done: win32.DWORD;
|
||||||
|
if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
|
||||||
|
e = Errno(win32.GetLastError());
|
||||||
|
done = 0;
|
||||||
|
}
|
||||||
|
return int(done), e;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
|
||||||
|
if offset < 0 {
|
||||||
|
return 0, ERROR_NEGATIVE_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
b, offset := data, offset;
|
||||||
|
for len(b) > 0 {
|
||||||
|
m, e := pread(fd, b, offset);
|
||||||
|
if e != 0 {
|
||||||
|
err = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n += m;
|
||||||
|
b = b[m:];
|
||||||
|
offset += i64(m);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
|
||||||
|
if offset < 0 {
|
||||||
|
return 0, ERROR_NEGATIVE_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
b, offset := data, offset;
|
||||||
|
for len(b) > 0 {
|
||||||
|
m, e := pwrite(fd, b, offset);
|
||||||
|
if e != 0 {
|
||||||
|
err = e;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n += m;
|
||||||
|
b = b[m:];
|
||||||
|
offset += i64(m);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
stdin := get_std_handle(uint(win32.STD_INPUT_HANDLE));
|
stdin := get_std_handle(uint(win32.STD_INPUT_HANDLE));
|
||||||
stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE));
|
stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE));
|
||||||
@@ -188,20 +281,19 @@ is_dir :: proc(path: string) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName;
|
// NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName
|
||||||
// The current directory is stored as a global variable in the process.
|
@private cwd_lock := win32.SRWLOCK{}; // zero is initialized
|
||||||
@private cwd_gate := false;
|
|
||||||
|
|
||||||
get_current_directory :: proc(allocator := context.allocator) -> string {
|
get_current_directory :: proc(allocator := context.allocator) -> string {
|
||||||
for intrinsics.atomic_xchg(&cwd_gate, true) {}
|
win32.AcquireSRWLockExclusive(&cwd_lock);
|
||||||
|
|
||||||
sz_utf16 := win32.GetCurrentDirectoryW(0, nil);
|
sz_utf16 := win32.GetCurrentDirectoryW(0, nil);
|
||||||
dir_buf_wstr := make([]u16, sz_utf16, context.temp_allocator); // the first time, it _includes_ the NUL.
|
dir_buf_wstr := make([]u16, sz_utf16, context.temp_allocator); // the first time, it _includes_ the NUL.
|
||||||
|
|
||||||
sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), auto_cast &dir_buf_wstr[0]);
|
sz_utf16 = win32.GetCurrentDirectoryW(win32.DWORD(len(dir_buf_wstr)), raw_data(dir_buf_wstr));
|
||||||
assert(int(sz_utf16)+1 == len(dir_buf_wstr)); // the second time, it _excludes_ the NUL.
|
assert(int(sz_utf16)+1 == len(dir_buf_wstr)); // the second time, it _excludes_ the NUL.
|
||||||
|
|
||||||
intrinsics.atomic_store(&cwd_gate, false);
|
win32.ReleaseSRWLockExclusive(&cwd_lock);
|
||||||
|
|
||||||
return win32.utf16_to_utf8(dir_buf_wstr, allocator);
|
return win32.utf16_to_utf8(dir_buf_wstr, allocator);
|
||||||
}
|
}
|
||||||
@@ -209,14 +301,14 @@ get_current_directory :: proc(allocator := context.allocator) -> string {
|
|||||||
set_current_directory :: proc(path: string) -> (err: Errno) {
|
set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||||
wstr := win32.utf8_to_wstring(path);
|
wstr := win32.utf8_to_wstring(path);
|
||||||
|
|
||||||
for intrinsics.atomic_xchg(&cwd_gate, true) {}
|
win32.AcquireSRWLockExclusive(&cwd_lock);
|
||||||
defer intrinsics.atomic_store(&cwd_gate, false);
|
|
||||||
|
|
||||||
res := win32.SetCurrentDirectoryW(auto_cast wstr);
|
if !win32.SetCurrentDirectoryW(wstr) {
|
||||||
if !res {
|
err = Errno(win32.GetLastError());
|
||||||
return Errno(win32.GetLastError());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
win32.ReleaseSRWLockExclusive(&cwd_lock);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ WSAECONNRESET: Errno : 10054;
|
|||||||
// Windows reserves errors >= 1<<29 for application use
|
// Windows reserves errors >= 1<<29 for application use
|
||||||
ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0;
|
ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0;
|
||||||
ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1;
|
ERROR_FILE_IS_NOT_DIR: Errno : 1<<29 + 1;
|
||||||
|
ERROR_NEGATIVE_OFFSET: Errno : 1<<29 + 2;
|
||||||
|
|
||||||
// "Argv" arguments converted to Odin strings
|
// "Argv" arguments converted to Odin strings
|
||||||
args := _alloc_command_line_arguments();
|
args := _alloc_command_line_arguments();
|
||||||
|
|||||||
Reference in New Issue
Block a user