From b3c2f5cb123200767cbdffabf797764f3080ea1f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 15 Nov 2024 20:47:34 +0100 Subject: [PATCH 1/5] os2: fix leak in dir_windows --- core/os/os2/dir_windows.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin index 09990aeecee..7b53e476ec3 100644 --- a/core/os/os2/dir_windows.odin +++ b/core/os/os2/dir_windows.odin @@ -137,5 +137,6 @@ _read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { return } file_info_delete(it.impl.prev_fi, file_allocator()) + delete(it.impl.path, file_allocator()) win32.FindClose(it.impl.find_handle) } From 71020d764205bb3eb658eb04fe17beaab92c2af3 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 15 Nov 2024 20:47:51 +0100 Subject: [PATCH 2/5] os2: add read dir test --- tests/core/os/os2/dir.odin | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/core/os/os2/dir.odin diff --git a/tests/core/os/os2/dir.odin b/tests/core/os/os2/dir.odin new file mode 100644 index 00000000000..e716b5a972b --- /dev/null +++ b/tests/core/os/os2/dir.odin @@ -0,0 +1,26 @@ +package tests_core_os_os2 + +import os "core:os/os2" +import "core:path/filepath" +import "core:slice" +import "core:testing" + +@(test) +test_read_dir :: proc(t: ^testing.T) { + path := filepath.join({#directory, "../dir"}) + defer delete(path) + + fis, err := os.read_all_directory_by_path(path, context.allocator) + defer os.file_info_slice_delete(fis, context.allocator) + + slice.sort_by_key(fis, proc(fi: os.File_Info) -> string { return fi.name }) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(fis), 2) + + testing.expect_value(t, fis[0].name, "b.txt") + testing.expect_value(t, fis[0].type, os.File_Type.Regular) + + testing.expect_value(t, fis[1].name, "sub") + testing.expect_value(t, fis[1].type, os.File_Type.Directory) +} From de9d0134e489b5962a84438a4aa845113b0b433f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 15 Nov 2024 21:01:24 +0100 Subject: [PATCH 3/5] os2: fix file type detection in dir_windows --- core/os/os2/dir_windows.odin | 9 +++------ core/os/os2/stat_windows.odin | 15 +++++++-------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin index 7b53e476ec3..f71e7e763bb 100644 --- a/core/os/os2/dir_windows.odin +++ b/core/os/os2/dir_windows.odin @@ -16,28 +16,25 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al } path := concatenate({base_path, `\`, win32_utf16_to_utf8(d.cFileName[:], temp_allocator()) or_else ""}, allocator) or_return + handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0) + defer win32.CloseHandle(handle) fi.fullpath = path fi.name = basename(path) fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) - fi.type, fi.mode = _file_type_mode_from_file_attributes(d.dwFileAttributes, nil, d.dwReserved0) + fi.type, fi.mode = _file_type_mode_from_file_attributes(d.dwFileAttributes, handle, d.dwReserved0) fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime)) fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime)) fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) - - handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0) - defer win32.CloseHandle(handle) - if file_id_info: win32.FILE_ID_INFO; handle != nil && win32.GetFileInformationByHandleEx(handle, .FileIdInfo, &file_id_info, size_of(file_id_info)) { #assert(size_of(fi.inode) == size_of(file_id_info.FileId)) #assert(size_of(fi.inode) == 16) runtime.mem_copy_non_overlapping(&fi.inode, &file_id_info.FileId, 16) } - return } diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 8ed2a6fed8e..0a019e9daa3 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -200,22 +200,21 @@ _file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: wi } else { mode |= 0o666 } + is_sym := false if file_attributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 { is_sym = false } else { is_sym = ReparseTag == win32.IO_REPARSE_TAG_SYMLINK || ReparseTag == win32.IO_REPARSE_TAG_MOUNT_POINT } + if is_sym { type = .Symlink - } else { - if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { - type = .Directory - mode |= 0o111 - } - if h != nil { - type = file_type(h) - } + } else if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 { + type = .Directory + mode |= 0o111 + } else if h != nil { + type = file_type(h) } return } From ce74325673bde36837e58c8e46753e5ab51d4065 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 15 Nov 2024 21:22:23 +0100 Subject: [PATCH 4/5] sys/posix: fix dirfd on netbsd --- core/sys/posix/dirent.odin | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/core/sys/posix/dirent.odin b/core/sys/posix/dirent.odin index 73351b29dc7..bf32be8cf53 100644 --- a/core/sys/posix/dirent.odin +++ b/core/sys/posix/dirent.odin @@ -54,15 +54,6 @@ foreign lib { */ closedir :: proc(dirp: DIR) -> result --- - /* - Return a file descriptor referring to the same directory as the dirp argument. - - // TODO: this is a macro on NetBSD? - - [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/dirfd.html ]] - */ - dirfd :: proc(dirp: DIR) -> FD --- - /* Equivalent to the opendir() function except that the directory is specified by a file descriptor rather than by a name. @@ -161,11 +152,36 @@ when ODIN_OS == .NetBSD { @(private) LSCANDIR :: "__scandir30" @(private) LOPENDIR :: "__opendir30" @(private) LREADDIR :: "__readdir30" + + /* + Return a file descriptor referring to the same directory as the dirp argument. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/dirfd.html ]] + */ + dirfd :: proc "c" (dirp: DIR) -> FD { + _dirdesc :: struct { + dd_fd: FD, + + // more stuff... + } + + return (^_dirdesc)(dirp).dd_fd + } + } else { @(private) LALPHASORT :: "alphasort" + INODE_SUFFIX @(private) LSCANDIR :: "scandir" + INODE_SUFFIX @(private) LOPENDIR :: "opendir" + INODE_SUFFIX @(private) LREADDIR :: "readdir" + INODE_SUFFIX + + foreign lib { + /* + Return a file descriptor referring to the same directory as the dirp argument. + + [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/dirfd.html ]] + */ + dirfd :: proc(dirp: DIR) -> FD --- + } } when ODIN_OS == .Darwin { From 282d956aa7c9e0a59a94b6e5091c369f491d38f7 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 15 Nov 2024 21:26:48 +0100 Subject: [PATCH 5/5] os2: skip dir test when unsupported --- core/os/os2/dir_linux.odin | 2 +- tests/core/os/os2/dir.odin | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/os/os2/dir_linux.odin b/core/os/os2/dir_linux.odin index 6a097e1922d..f26b4fc79fa 100644 --- a/core/os/os2/dir_linux.odin +++ b/core/os/os2/dir_linux.odin @@ -13,7 +13,7 @@ _read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info @(require_results) _read_directory_iterator_create :: proc(f: ^File) -> (Read_Directory_Iterator, Error) { - return {}, nil + return {}, .Unsupported } _read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) { diff --git a/tests/core/os/os2/dir.odin b/tests/core/os/os2/dir.odin index e716b5a972b..5bb5c9820bb 100644 --- a/tests/core/os/os2/dir.odin +++ b/tests/core/os/os2/dir.odin @@ -1,6 +1,7 @@ package tests_core_os_os2 import os "core:os/os2" +import "core:log" import "core:path/filepath" import "core:slice" import "core:testing" @@ -15,6 +16,11 @@ test_read_dir :: proc(t: ^testing.T) { slice.sort_by_key(fis, proc(fi: os.File_Info) -> string { return fi.name }) + if err == .Unsupported { + log.warn("os2 directory functionality is unsupported, skipping test") + return + } + testing.expect_value(t, err, nil) testing.expect_value(t, len(fis), 2)