os: add non blocking open flag

This commit is contained in:
Laytan Laats
2026-01-11 20:11:07 +01:00
parent fa97aa4dc9
commit bc70402093
7 changed files with 31 additions and 14 deletions

View File

@@ -67,7 +67,7 @@ File_Flag :: enum {
Trunc,
Sparse,
Inheritable,
Non_Blocking,
Unbuffered_IO,
}

View File

@@ -82,6 +82,7 @@ _open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File,
if .Excl in flags { sys_flags += {.EXCL} }
if .Sync in flags { sys_flags += {.DSYNC} }
if .Trunc in flags { sys_flags += {.TRUNC} }
if .Non_Blocking in flags { sys_flags += {.NONBLOCK} }
if .Inheritable in flags { sys_flags -= {.CLOEXEC} }
fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)transmute(u32)perm)

View File

@@ -61,12 +61,13 @@ _open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File,
}
}
if .Append in flags { sys_flags += {.APPEND} }
if .Create in flags { sys_flags += {.CREAT} }
if .Excl in flags { sys_flags += {.EXCL} }
if .Sync in flags { sys_flags += {.DSYNC} }
if .Trunc in flags { sys_flags += {.TRUNC} }
if .Inheritable in flags { sys_flags -= {.CLOEXEC} }
if .Append in flags { sys_flags += {.APPEND} }
if .Create in flags { sys_flags += {.CREAT} }
if .Excl in flags { sys_flags += {.EXCL} }
if .Sync in flags { sys_flags += {.DSYNC} }
if .Trunc in flags { sys_flags += {.TRUNC} }
if .Non_Blocking in flags { sys_flags += {.NONBLOCK} }
if .Inheritable in flags { sys_flags -= {.CLOEXEC} }
temp_allocator := TEMP_ALLOCATOR_GUARD({})
cname := clone_to_cstring(name, temp_allocator) or_return

View File

@@ -185,8 +185,9 @@ _open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File,
if .Trunc in flags { oflags += {.TRUNC} }
fdflags: wasi.fdflags_t
if .Append in flags { fdflags += {.APPEND} }
if .Sync in flags { fdflags += {.SYNC} }
if .Append in flags { fdflags += {.APPEND} }
if .Sync in flags { fdflags += {.SYNC} }
if .Non_Blocking in flags { fdflags += {.NONBLOCK} }
// NOTE: rights are adjusted to what this package's functions might want to call.
rights: wasi.rights_t

View File

@@ -126,7 +126,11 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: Permissions) -> (h
// NOTE(bill): Open has just asked to create a file in read-only mode.
// If the file already exists, to make it akin to a *nix open call,
// the call preserves the existing permissions.
h := win32.CreateFileW(path, access, share_mode, &sa, win32.TRUNCATE_EXISTING, win32.FILE_ATTRIBUTE_NORMAL, nil)
nix_attrs := win32.FILE_ATTRIBUTE_NORMAL
if .Non_Blocking in flags {
nix_attrs |= win32.FILE_FLAG_OVERLAPPED
}
h := win32.CreateFileW(path, access, share_mode, &sa, win32.TRUNCATE_EXISTING, nix_attrs, nil)
if h == win32.INVALID_HANDLE {
switch e := win32.GetLastError(); e {
case win32.ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, win32.ERROR_PATH_NOT_FOUND:
@@ -140,6 +144,10 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: Permissions) -> (h
}
}
if .Non_Blocking in flags {
attrs |= win32.FILE_FLAG_OVERLAPPED
}
h := win32.CreateFileW(path, access, share_mode, &sa, create_mode, attrs, nil)
if h == win32.INVALID_HANDLE {
return 0, _get_platform_error()

View File

@@ -14,7 +14,7 @@ MAX_ATTEMPTS :: 1<<13 // Should be enough for everyone, right?
//
// The caller must `close` the file once finished with.
@(require_results)
create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) {
create_temp_file :: proc(dir, pattern: string, additional_flags: File_Flags = {}) -> (f: ^File, err: Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
dir := dir if dir != "" else temp_directory(temp_allocator) or_return
prefix, suffix := _prefix_and_suffix(pattern) or_return
@@ -26,7 +26,7 @@ create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) {
attempts := 0
for {
name := concatenate_strings_from_buffer(name_buf[:], prefix, random_string(rand_buf[:]), suffix)
f, err = open(name, {.Read, .Write, .Create, .Excl}, Permissions_Read_Write_All)
f, err = open(name, {.Read, .Write, .Create, .Excl} + additional_flags, Permissions_Read_Write_All)
if err == .Exist {
close(f)
attempts += 1

View File

@@ -333,8 +333,14 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Erro
case:
create_mode = win32.OPEN_EXISTING
}
attrs := win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS
if mode & (O_NONBLOCK) == O_NONBLOCK {
attrs |= win32.FILE_FLAG_OVERLAPPED
}
wide_path := win32.utf8_to_wstring(path)
handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS, nil))
handle := Handle(win32.CreateFileW(wide_path, access, share_mode, sa, create_mode, attrs, nil))
if handle != INVALID_HANDLE {
return handle, nil
}
@@ -862,4 +868,4 @@ pipe :: proc() -> (r, w: Handle, err: Error) {
err = get_last_error()
}
return
}
}