Browse Source

fix `open` bindings

`open` specifies the `mode` argument as vararg (presumably to make it
optional). varargs actually have rules about casting, in this case the
rule that any integer arg of size <= 4 has to be casted to `i32` before
passing it.

Not doing that implicit cast makes the permissions wrong or not apply at
all.
Laytan Laats 1 year ago
parent
commit
f7d7d65bc0

+ 1 - 13
core/os/os_darwin.odin

@@ -584,7 +584,7 @@ F_GETPATH :: 50 // return the full path of the fd
 foreign libc {
 foreign libc {
 	@(link_name="__error") __error :: proc() -> ^c.int ---
 	@(link_name="__error") __error :: proc() -> ^c.int ---
 
 
-	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: i32, mode: u16) -> Handle ---
+	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: i32, #c_vararg mode: ..u16) -> Handle ---
 	@(link_name="close")            _unix_close         :: proc(handle: Handle) -> c.int ---
 	@(link_name="close")            _unix_close         :: proc(handle: Handle) -> c.int ---
 	@(link_name="read")             _unix_read          :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
 	@(link_name="read")             _unix_read          :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
 	@(link_name="write")            _unix_write         :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
 	@(link_name="write")            _unix_write         :: proc(handle: Handle, buffer: rawptr, count: c.size_t) -> int ---
@@ -698,18 +698,6 @@ open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handl
 		return
 		return
 	}
 	}
 
 
-	/*
-		@INFO(Platin): this is only done because O_CREATE for some reason fails to apply mode
-		               should not happen if the handle is a directory
-	*/
-	if flags & O_CREATE != 0 && mode != 0 && !isDir {
-		err = fchmod(handle, cast(u16)mode)
-		if err != nil {
-			_unix_close(handle)
-			handle = INVALID_HANDLE
-		}
-	}
-
 	return
 	return
 }
 }
 
 

+ 1 - 1
core/os/os_freebsd.odin

@@ -371,7 +371,7 @@ F_KINFO :: 22
 foreign libc {
 foreign libc {
 	@(link_name="__error")		__Error_location :: proc() -> ^c.int ---
 	@(link_name="__error")		__Error_location :: proc() -> ^c.int ---
 
 
-	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: c.int, mode: c.uint16_t) -> Handle ---
+	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: c.int, #c_vararg mode: ..u16) -> Handle ---
 	@(link_name="close")            _unix_close         :: proc(fd: Handle) -> c.int ---
 	@(link_name="close")            _unix_close         :: proc(fd: Handle) -> c.int ---
 	@(link_name="read")             _unix_read          :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="read")             _unix_read          :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")            _unix_write         :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")            _unix_write         :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---

+ 2 - 2
core/os/os_haiku.odin

@@ -124,7 +124,7 @@ foreign libc {
 	@(link_name="fork")	_unix_fork	:: proc() -> pid_t ---
 	@(link_name="fork")	_unix_fork	:: proc() -> pid_t ---
 	@(link_name="getthrid")	_unix_getthrid	:: proc() -> int ---
 	@(link_name="getthrid")	_unix_getthrid	:: proc() -> int ---
 
 
-	@(link_name="open")	_unix_open	:: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
+	@(link_name="open")	_unix_open	:: proc(path: cstring, flags: c.int, #c_vararg mode: ..u16) -> Handle ---
 	@(link_name="close")	_unix_close	:: proc(fd: Handle) -> c.int ---
 	@(link_name="close")	_unix_close	:: proc(fd: Handle) -> c.int ---
 	@(link_name="read")	_unix_read	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="read")	_unix_read	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")	_unix_write	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")	_unix_write	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@@ -200,7 +200,7 @@ fork :: proc() -> (Pid, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
-	handle := _unix_open(cstr, c.int(flags), c.int(mode))
+	handle := _unix_open(cstr, c.int(flags), u16(mode))
 	if handle == -1 {
 	if handle == -1 {
 		return INVALID_HANDLE, get_last_error()
 		return INVALID_HANDLE, get_last_error()
 	}
 	}

+ 2 - 2
core/os/os_netbsd.odin

@@ -423,7 +423,7 @@ R_OK :: 4 // Test for read permission
 foreign libc {
 foreign libc {
 	@(link_name="__errno")          __errno_location    :: proc() -> ^c.int ---
 	@(link_name="__errno")          __errno_location    :: proc() -> ^c.int ---
 
 
-	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
+	@(link_name="open")             _unix_open          :: proc(path: cstring, flags: c.int, #c_vararg mode: ..u32) -> Handle ---
 	@(link_name="close")            _unix_close         :: proc(fd: Handle) -> c.int ---
 	@(link_name="close")            _unix_close         :: proc(fd: Handle) -> c.int ---
 	@(link_name="read")             _unix_read          :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="read")             _unix_read          :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")            _unix_write         :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")            _unix_write         :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@@ -488,7 +488,7 @@ get_last_error :: proc "contextless" () -> Error {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
-	handle := _unix_open(cstr, c.int(flags), c.int(mode))
+	handle := _unix_open(cstr, c.int(flags), c.uint(mode))
 	if handle == -1 {
 	if handle == -1 {
 		return INVALID_HANDLE, get_last_error()
 		return INVALID_HANDLE, get_last_error()
 	}
 	}

+ 2 - 2
core/os/os_openbsd.odin

@@ -348,7 +348,7 @@ foreign libc {
 	@(link_name="fork")	_unix_fork	:: proc() -> pid_t ---
 	@(link_name="fork")	_unix_fork	:: proc() -> pid_t ---
 	@(link_name="getthrid")	_unix_getthrid	:: proc() -> int ---
 	@(link_name="getthrid")	_unix_getthrid	:: proc() -> int ---
 
 
-	@(link_name="open")	_unix_open	:: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
+	@(link_name="open")	_unix_open	:: proc(path: cstring, flags: c.int, #c_vararg mode: ..u32) -> Handle ---
 	@(link_name="close")	_unix_close	:: proc(fd: Handle) -> c.int ---
 	@(link_name="close")	_unix_close	:: proc(fd: Handle) -> c.int ---
 	@(link_name="read")	_unix_read	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="read")	_unix_read	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")	_unix_write	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
 	@(link_name="write")	_unix_write	:: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
@@ -412,7 +412,7 @@ fork :: proc() -> (Pid, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
 	cstr := strings.clone_to_cstring(path, context.temp_allocator)
-	handle := _unix_open(cstr, c.int(flags), c.int(mode))
+	handle := _unix_open(cstr, c.int(flags), c.uint(mode))
 	if handle == -1 {
 	if handle == -1 {
 		return INVALID_HANDLE, get_last_error()
 		return INVALID_HANDLE, get_last_error()
 	}
 	}

+ 1 - 1
core/sys/posix/fcntl.odin

@@ -58,7 +58,7 @@ foreign lib {
 
 
 	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
 	[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html ]]
 	*/
 	*/
-	open :: proc(path: cstring, flags: O_Flags, mode: mode_t = {}) -> FD ---
+	open :: proc(path: cstring, flags: O_Flags, #c_vararg mode: ..mode_t) -> FD ---
 
 
 	/*
 	/*
 	Equivalent to the open() function except in the case where path specifies a relative path.
 	Equivalent to the open() function except in the case where path specifies a relative path.

+ 15 - 0
src/check_decl.cpp

@@ -691,6 +691,13 @@ gb_internal bool sig_compare(TypeCheckSig *a, TypeCheckSig *b, Type *x, Type *y)
 }
 }
 
 
 gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) {
 gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) {
+	if (is_type_bit_set(x)) {
+		x = bit_set_to_int(x);
+	}
+	if (is_type_bit_set(y)) {
+		y = bit_set_to_int(y);
+	}
+
 	if (sig_compare(is_type_pointer, x, y)) {
 	if (sig_compare(is_type_pointer, x, y)) {
 		return true;
 		return true;
 	}
 	}
@@ -737,6 +744,14 @@ gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) {
 		return true;
 		return true;
 	}
 	}
 
 
+	if (sig_compare(is_type_slice, x, y)) {
+		Type *s1 = core_type(x);
+		Type *s2 = core_type(y);
+		if (signature_parameter_similar_enough(s1->Slice.elem, s2->Slice.elem)) {
+			return true;
+		}
+	}
+
 	return are_types_identical(x, y);
 	return are_types_identical(x, y);
 }
 }
 
 

+ 21 - 0
tests/core/sys/posix/posix.odin

@@ -287,3 +287,24 @@ test_pthreads :: proc(t: ^testing.T) {
 		return nil
 		return nil
 	}
 	}
 }
 }
+
+@(test)
+open_permissions :: proc(t: ^testing.T) {
+	in_mode := posix.mode_t{.IRUSR, .IWUSR, .IROTH, .IRGRP}
+	fd := posix.open("test_posix_permissions.txt", {.CREAT, .RDWR}, in_mode)
+	testing.expectf(t, fd != -1, "failed to open: %v", posix.strerror())
+
+	defer {
+		ret := posix.close(fd)
+		testing.expectf(t, ret == .OK, "failed to close: %v", posix.strerror())
+		ret2 := posix.remove("test_posix_permissions.txt")
+		testing.expectf(t, ret2 == 0, "failed to remove: %v", posix.strerror())
+	}
+
+	stat: posix.stat_t
+	res := posix.fstat(fd, &stat)
+	testing.expectf(t, res == .OK, "failed to stat: %v", posix.strerror())
+
+	stat.st_mode -= posix.S_IFMT
+	testing.expect_value(t, stat.st_mode, in_mode)
+}