mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Remove returned bool from access and faccessat in sys/linux.
Switch to using AT_EMPTY_PATH to execve with file descriptors.
This commit is contained in:
@@ -386,8 +386,7 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
|||||||
_exists :: proc(name: string) -> bool {
|
_exists :: proc(name: string) -> bool {
|
||||||
TEMP_ALLOCATOR_GUARD()
|
TEMP_ALLOCATOR_GUARD()
|
||||||
name_cstr, _ := temp_cstring(name)
|
name_cstr, _ := temp_cstring(name)
|
||||||
res, errno := linux.access(name_cstr, linux.F_OK)
|
return linux.access(name_cstr, linux.F_OK) == .NONE
|
||||||
return !res && errno == .NONE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For reading Linux system files that stat to size 0 */
|
/* For reading Linux system files that stat to size 0 */
|
||||||
|
|||||||
@@ -300,6 +300,12 @@ _Sys_Process_Attributes :: struct {}
|
|||||||
|
|
||||||
@(private="package")
|
@(private="package")
|
||||||
_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
_process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
||||||
|
_has_executable_permissions :: proc(fd: linux.Fd) -> bool {
|
||||||
|
backing: [48]u8
|
||||||
|
_ = fmt.bprintf(backing[:], "/proc/self/fd/%d", fd)
|
||||||
|
return linux.access(cstring(&backing[0]), linux.X_OK) == .NONE
|
||||||
|
}
|
||||||
|
|
||||||
TEMP_ALLOCATOR_GUARD()
|
TEMP_ALLOCATOR_GUARD()
|
||||||
|
|
||||||
if len(desc.command) == 0 {
|
if len(desc.command) == 0 {
|
||||||
@@ -314,38 +320,54 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
return process, _get_platform_error(errno)
|
return process, _get_platform_error(errno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
defer if desc.working_dir != "" {
|
||||||
|
linux.close(dir_fd)
|
||||||
|
}
|
||||||
|
|
||||||
// search PATH if just a plain name is provided
|
// search PATH if just a plain name is provided
|
||||||
|
exe_fd: linux.Fd
|
||||||
executable_name := desc.command[0]
|
executable_name := desc.command[0]
|
||||||
executable_path: cstring
|
|
||||||
if strings.index_byte(executable_name, '/') == -1 {
|
if strings.index_byte(executable_name, '/') == -1 {
|
||||||
path_env := get_env("PATH", temp_allocator())
|
path_env := get_env("PATH", temp_allocator())
|
||||||
path_dirs := filepath.split_list(path_env, temp_allocator())
|
path_dirs := filepath.split_list(path_env, temp_allocator())
|
||||||
|
|
||||||
found: bool
|
found: bool
|
||||||
for dir in path_dirs {
|
for dir in path_dirs {
|
||||||
executable_path = fmt.caprintf("%s/%s", dir, executable_name, temp_allocator())
|
exe_path := fmt.caprintf("%s/%s", dir, executable_name, allocator=temp_allocator())
|
||||||
fail: bool
|
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||||
if fail, errno = linux.faccessat(dir_fd, executable_path, linux.F_OK); errno == .NONE && !fail {
|
continue
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
if !_has_executable_permissions(exe_fd) {
|
||||||
|
linux.close(exe_fd)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
// check in cwd to match windows behavior
|
// check in cwd to match windows behavior
|
||||||
executable_path = fmt.caprintf("./%s", name, temp_allocator())
|
exe_path := fmt.caprintf("./%s", executable_name, allocator=temp_allocator())
|
||||||
fail: bool
|
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||||
if fail, errno = linux.faccessat(dir_fd, executable_path, linux.F_OK); errno != .NONE || fail {
|
|
||||||
return process, .Not_Exist
|
return process, .Not_Exist
|
||||||
}
|
}
|
||||||
|
if !_has_executable_permissions(exe_fd) {
|
||||||
|
linux.close(exe_fd)
|
||||||
|
return process, .Permission_Denied
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
executable_path = temp_cstring(executable_name) or_return
|
exe_path := temp_cstring(executable_name) or_return
|
||||||
|
if exe_fd, errno = linux.openat(dir_fd, exe_path, {.PATH, .CLOEXEC}); errno != .NONE {
|
||||||
|
return process, _get_platform_error(errno)
|
||||||
|
}
|
||||||
|
if !_has_executable_permissions(exe_fd) {
|
||||||
|
linux.close(exe_fd)
|
||||||
|
return process, .Permission_Denied
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
not_exec: bool
|
// At this point, we have an executable.
|
||||||
if not_exec, errno = linux.faccessat(dir_fd, executable_path, linux.F_OK | linux.X_OK); errno != .NONE || not_exec {
|
defer linux.close(exe_fd)
|
||||||
return process, errno == .NONE ? .Permission_Denied : _get_platform_error(errno)
|
|
||||||
}
|
|
||||||
|
|
||||||
// args and environment need to be a list of cstrings
|
// args and environment need to be a list of cstrings
|
||||||
// that are terminated by a nil pointer.
|
// that are terminated by a nil pointer.
|
||||||
@@ -409,7 +431,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if errno = linux.execveat(dir_fd, executable_path, &cargs[0], env); errno != .NONE {
|
if errno = linux.execveat(exe_fd, "", &cargs[0], env, {.AT_EMPTY_PATH}); errno != .NONE {
|
||||||
intrinsics.trap()
|
intrinsics.trap()
|
||||||
}
|
}
|
||||||
unreachable()
|
unreachable()
|
||||||
|
|||||||
@@ -279,13 +279,13 @@ writev :: proc "contextless" (fd: Fd, iov: []IO_Vec) -> (int, Errno) {
|
|||||||
Available since Linux 1.0.
|
Available since Linux 1.0.
|
||||||
For ARM64 available since Linux 2.6.16.
|
For ARM64 available since Linux 2.6.16.
|
||||||
*/
|
*/
|
||||||
access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (bool, Errno) {
|
access :: proc "contextless" (name: cstring, mode: Mode = F_OK) -> (Errno) {
|
||||||
when ODIN_ARCH == .arm64 {
|
when ODIN_ARCH == .arm64 {
|
||||||
ret := syscall(SYS_faccessat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
|
ret := syscall(SYS_faccessat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
|
||||||
return errno_unwrap(ret, bool)
|
return Errno(-ret)
|
||||||
} else {
|
} else {
|
||||||
ret := syscall(SYS_access, cast(rawptr) name, transmute(u32) mode)
|
ret := syscall(SYS_access, cast(rawptr) name, transmute(u32) mode)
|
||||||
return errno_unwrap(ret, bool)
|
return Errno(-ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2616,9 +2616,9 @@ fchmodat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode, flags: FD_
|
|||||||
Checks the user permissions for a file at specified dirfd.
|
Checks the user permissions for a file at specified dirfd.
|
||||||
Available since Linux 2.6.16.
|
Available since Linux 2.6.16.
|
||||||
*/
|
*/
|
||||||
faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) -> (bool, Errno) {
|
faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) -> (Errno) {
|
||||||
ret := syscall(SYS_faccessat, dirfd, cast(rawptr) name, transmute(u32) mode)
|
ret := syscall(SYS_faccessat, dirfd, cast(rawptr) name, transmute(u32) mode)
|
||||||
return errno_unwrap(ret, bool)
|
return Errno(-ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2916,9 +2916,9 @@ pidfd_getfd :: proc "contextless" (pidfd: Pid_FD, fd: Fd, flags: i32 = 0) -> (Fd
|
|||||||
Checks the user permissions for a file at specified dirfd (with flags).
|
Checks the user permissions for a file at specified dirfd (with flags).
|
||||||
Available since Linux 5.8.
|
Available since Linux 5.8.
|
||||||
*/
|
*/
|
||||||
faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, flags: FD_Flags = FD_Flags{}) -> (bool, Errno) {
|
faccessat2 :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK, flags: FD_Flags = FD_Flags{}) -> (Errno) {
|
||||||
ret := syscall(SYS_faccessat2, dirfd, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags)
|
ret := syscall(SYS_faccessat2, dirfd, cast(rawptr) name, transmute(u32) mode, transmute(i32) flags)
|
||||||
return errno_unwrap(ret, bool)
|
return Errno(-ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(flysand): process_madvise
|
// TODO(flysand): process_madvise
|
||||||
|
|||||||
Reference in New Issue
Block a user