mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-20 16:36:46 +00:00
fix os.read_dir closing the given file descriptor
This commit is contained in:
@@ -5,10 +5,12 @@ import "core:strings"
|
|||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) {
|
||||||
dirp := _fdopendir(fd) or_return
|
dupfd := _dup(fd) or_return
|
||||||
|
|
||||||
|
dirp := _fdopendir(dupfd) or_return
|
||||||
defer _closedir(dirp)
|
defer _closedir(dirp)
|
||||||
|
|
||||||
dirpath := absolute_path_from_handle(fd) or_return
|
dirpath := absolute_path_from_handle(dupfd) or_return
|
||||||
defer delete(dirpath)
|
defer delete(dirpath)
|
||||||
|
|
||||||
n := n
|
n := n
|
||||||
|
|||||||
+11
-1
@@ -598,7 +598,8 @@ foreign libc {
|
|||||||
@(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
@(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
||||||
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
||||||
@(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
|
@(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
|
||||||
@(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int ---
|
@(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int ---
|
||||||
|
@(link_name="dup") _unix_dup :: proc(handle: Handle) -> Handle ---
|
||||||
|
|
||||||
@(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir ---
|
@(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir ---
|
||||||
@(link_name="readdir_r$INODE64") _unix_readdir_r_amd64 :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
@(link_name="readdir_r$INODE64") _unix_readdir_r_amd64 :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||||
@@ -1009,6 +1010,15 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private, require_results)
|
||||||
|
_dup :: proc(fd: Handle) -> (Handle, Error) {
|
||||||
|
dup := _unix_dup(fd)
|
||||||
|
if dup == -1 {
|
||||||
|
return INVALID_HANDLE, get_last_error()
|
||||||
|
}
|
||||||
|
return dup, nil
|
||||||
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||||
buf: [DARWIN_MAXPATHLEN]byte
|
buf: [DARWIN_MAXPATHLEN]byte
|
||||||
|
|||||||
@@ -389,6 +389,7 @@ foreign libc {
|
|||||||
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
||||||
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
||||||
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
|
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
|
||||||
|
@(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle ---
|
||||||
|
|
||||||
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
||||||
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
||||||
@@ -739,6 +740,15 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|||||||
return "", Error{}
|
return "", Error{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private, require_results)
|
||||||
|
_dup :: proc(fd: Handle) -> (Handle, Error) {
|
||||||
|
dup := _unix_dup(fd)
|
||||||
|
if dup == -1 {
|
||||||
|
return INVALID_HANDLE, get_last_error()
|
||||||
|
}
|
||||||
|
return dup, nil
|
||||||
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||||
// NOTE(Feoramund): The situation isn't ideal, but this was the best way I
|
// NOTE(Feoramund): The situation isn't ideal, but this was the best way I
|
||||||
|
|||||||
@@ -886,6 +886,12 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private, require_results)
|
||||||
|
_dup :: proc(fd: Handle) -> (Handle, Error) {
|
||||||
|
dup, err := linux.dup(linux.Fd(fd))
|
||||||
|
return Handle(dup), err
|
||||||
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||||
buf : [256]byte
|
buf : [256]byte
|
||||||
|
|||||||
@@ -441,6 +441,7 @@ foreign libc {
|
|||||||
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
||||||
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
||||||
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
|
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, arg: uintptr) -> c.int ---
|
||||||
|
@(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle ---
|
||||||
|
|
||||||
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
||||||
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
||||||
@@ -801,6 +802,15 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|||||||
return "", Error{}
|
return "", Error{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private, require_results)
|
||||||
|
_dup :: proc(fd: Handle) -> (Handle, Error) {
|
||||||
|
dup := _unix_dup(fd)
|
||||||
|
if dup == -1 {
|
||||||
|
return INVALID_HANDLE, get_last_error()
|
||||||
|
}
|
||||||
|
return dup, nil
|
||||||
|
}
|
||||||
|
|
||||||
@(require_results)
|
@(require_results)
|
||||||
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) {
|
||||||
buf: [MAX_PATH]byte
|
buf: [MAX_PATH]byte
|
||||||
|
|||||||
@@ -364,6 +364,7 @@ foreign libc {
|
|||||||
@(link_name="unlink") _unix_unlink :: proc(path: cstring) -> c.int ---
|
@(link_name="unlink") _unix_unlink :: proc(path: cstring) -> c.int ---
|
||||||
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
@(link_name="rmdir") _unix_rmdir :: proc(path: cstring) -> c.int ---
|
||||||
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
@(link_name="mkdir") _unix_mkdir :: proc(path: cstring, mode: mode_t) -> c.int ---
|
||||||
|
@(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle ---
|
||||||
|
|
||||||
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
|
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
|
||||||
@(link_name="sysconf") _sysconf :: proc(name: c.int) -> c.long ---
|
@(link_name="sysconf") _sysconf :: proc(name: c.int) -> c.long ---
|
||||||
@@ -716,6 +717,15 @@ _readlink :: proc(path: string) -> (string, Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private, require_results)
|
||||||
|
_dup :: proc(fd: Handle) -> (Handle, Error) {
|
||||||
|
dup := _unix_dup(fd)
|
||||||
|
if dup == -1 {
|
||||||
|
return INVALID_HANDLE, get_last_error()
|
||||||
|
}
|
||||||
|
return dup, nil
|
||||||
|
}
|
||||||
|
|
||||||
// XXX OpenBSD
|
// XXX OpenBSD
|
||||||
@(require_results)
|
@(require_results)
|
||||||
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) {
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ read_dir :: proc(t: ^testing.T) {
|
|||||||
|
|
||||||
fd, err := os.open(#directory + "/dir")
|
fd, err := os.open(#directory + "/dir")
|
||||||
testing.expect_value(t, err, nil)
|
testing.expect_value(t, err, nil)
|
||||||
defer os.close(fd)
|
defer {
|
||||||
|
testing.expect_value(t, os.close(fd), nil)
|
||||||
|
}
|
||||||
|
|
||||||
dir, err2 := os.read_dir(fd, -1)
|
dir, err2 := os.read_dir(fd, -1)
|
||||||
testing.expect_value(t, err2, nil)
|
testing.expect_value(t, err2, nil)
|
||||||
@@ -58,4 +60,4 @@ read_dir :: proc(t: ^testing.T) {
|
|||||||
testing.expect_value(t, dir[2].name, "sub")
|
testing.expect_value(t, dir[2].name, "sub")
|
||||||
testing.expect(t, dir[2].is_dir, "is not a directory")
|
testing.expect(t, dir[2].is_dir, "is not a directory")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user