| ... | @@ -208,6 +208,7 @@ pub fn io(t: *Threaded) Io { | ... | @@ -208,6 +208,7 @@ pub fn io(t: *Threaded) Io { |
| 208 | .dirOpenDir = switch (builtin.os.tag) { | 208 | .dirOpenDir = switch (builtin.os.tag) { |
| 209 | .windows => dirOpenDirWindows, | 209 | .windows => dirOpenDirWindows, |
| 210 | .wasi => dirOpenDirWasi, | 210 | .wasi => dirOpenDirWasi, |
| | 211 | .haiku => dirOpenDirHaiku, |
| 211 | else => dirOpenDirPosix, | 212 | else => dirOpenDirPosix, |
| 212 | }, | 213 | }, |
| 213 | .dirClose = dirClose, | 214 | .dirClose = dirClose, |
| ... | @@ -1784,22 +1785,20 @@ fn dirOpenFilePosix( | ... | @@ -1784,22 +1785,20 @@ fn dirOpenFilePosix( |
| 1784 | if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; | 1785 | if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; |
| 1785 | | 1786 | |
| 1786 | // Use the O locking flags if the os supports them to acquire the lock | 1787 | // Use the O locking flags if the os supports them to acquire the lock |
| 1787 | // atomically. | 1788 | // atomically. Note that the NONBLOCK flag is removed after the openat() |
| 1788 | if (have_flock_open_flags) { | 1789 | // call is successful. |
| 1789 | // Note that the NONBLOCK flag is removed after the openat() call | 1790 | if (have_flock_open_flags) switch (flags.lock) { |
| 1790 | // is successful. | 1791 | .none => {}, |
| 1791 | switch (flags.lock) { | 1792 | .shared => { |
| 1792 | .none => {}, | 1793 | os_flags.SHLOCK = true; |
| 1793 | .shared => { | 1794 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1794 | os_flags.SHLOCK = true; | 1795 | }, |
| 1795 | os_flags.NONBLOCK = flags.lock_nonblocking; | 1796 | .exclusive => { |
| 1796 | }, | 1797 | os_flags.EXLOCK = true; |
| 1797 | .exclusive => { | 1798 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1798 | os_flags.EXLOCK = true; | 1799 | }, |
| 1799 | os_flags.NONBLOCK = flags.lock_nonblocking; | 1800 | }; |
| 1800 | }, | 1801 | |
| 1801 | } | | |
| 1802 | } | | |
| 1803 | const fd: posix.fd_t = while (true) { | 1802 | const fd: posix.fd_t = while (true) { |
| 1804 | try t.checkCancel(); | 1803 | try t.checkCancel(); |
| 1805 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0)); | 1804 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0)); |
| ... | @@ -2008,11 +2007,92 @@ fn dirOpenDirPosix( | ... | @@ -2008,11 +2007,92 @@ fn dirOpenDirPosix( |
| 2008 | ) Io.Dir.OpenError!Io.Dir { | 2007 | ) Io.Dir.OpenError!Io.Dir { |
| 2009 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 2008 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2010 | | 2009 | |
| 2011 | _ = t; | 2010 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 2012 | _ = dir; | 2011 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| 2013 | _ = sub_path; | 2012 | |
| | 2013 | var flags: posix.O = switch (native_os) { |
| | 2014 | .wasi => .{ |
| | 2015 | .read = true, |
| | 2016 | .NOFOLLOW = !options.follow_symlinks, |
| | 2017 | .DIRECTORY = true, |
| | 2018 | }, |
| | 2019 | else => .{ |
| | 2020 | .ACCMODE = .RDONLY, |
| | 2021 | .NOFOLLOW = !options.follow_symlinks, |
| | 2022 | .DIRECTORY = true, |
| | 2023 | .CLOEXEC = true, |
| | 2024 | }, |
| | 2025 | }; |
| | 2026 | |
| | 2027 | if (@hasField(posix.O, "PATH") and !options.iterate) |
| | 2028 | flags.PATH = true; |
| | 2029 | |
| | 2030 | while (true) { |
| | 2031 | try t.checkCancel(); |
| | 2032 | const rc = openat_sym(dir.handle, sub_path_posix, flags, @as(usize, 0)); |
| | 2033 | switch (posix.errno(rc)) { |
| | 2034 | .SUCCESS => return .{ .handle = @intCast(rc) }, |
| | 2035 | .INTR => continue, |
| | 2036 | .CANCELED => return error.Canceled, |
| | 2037 | |
| | 2038 | .FAULT => |err| return errnoBug(err), |
| | 2039 | .INVAL => return error.BadPathName, |
| | 2040 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| | 2041 | .ACCES => return error.AccessDenied, |
| | 2042 | .LOOP => return error.SymLinkLoop, |
| | 2043 | .MFILE => return error.ProcessFdQuotaExceeded, |
| | 2044 | .NAMETOOLONG => return error.NameTooLong, |
| | 2045 | .NFILE => return error.SystemFdQuotaExceeded, |
| | 2046 | .NODEV => return error.NoDevice, |
| | 2047 | .NOENT => return error.FileNotFound, |
| | 2048 | .NOMEM => return error.SystemResources, |
| | 2049 | .NOTDIR => return error.NotDir, |
| | 2050 | .PERM => return error.PermissionDenied, |
| | 2051 | .BUSY => return error.DeviceBusy, |
| | 2052 | .NXIO => return error.NoDevice, |
| | 2053 | .ILSEQ => return error.BadPathName, |
| | 2054 | else => |err| return posix.unexpectedErrno(err), |
| | 2055 | } |
| | 2056 | } |
| | 2057 | } |
| | 2058 | |
| | 2059 | fn dirOpenDirHaiku( |
| | 2060 | userdata: ?*anyopaque, |
| | 2061 | dir: Io.Dir, |
| | 2062 | sub_path: []const u8, |
| | 2063 | options: Io.Dir.OpenOptions, |
| | 2064 | ) Io.Dir.OpenError!Io.Dir { |
| | 2065 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| | 2066 | |
| | 2067 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| | 2068 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| | 2069 | |
| 2014 | _ = options; | 2070 | _ = options; |
| 2015 | @panic("TODO"); | 2071 | |
| | 2072 | while (true) { |
| | 2073 | try t.checkCancel(); |
| | 2074 | const rc = posix.system._kern_open_dir(dir.handle, sub_path_posix); |
| | 2075 | if (rc >= 0) return .{ .handle = rc }; |
| | 2076 | switch (@as(posix.E, @enumFromInt(rc))) { |
| | 2077 | .INTR => continue, |
| | 2078 | .CANCELED => return error.Canceled, |
| | 2079 | .FAULT => |err| return errnoBug(err), |
| | 2080 | .INVAL => |err| return errnoBug(err), |
| | 2081 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| | 2082 | .ACCES => return error.AccessDenied, |
| | 2083 | .LOOP => return error.SymLinkLoop, |
| | 2084 | .MFILE => return error.ProcessFdQuotaExceeded, |
| | 2085 | .NAMETOOLONG => return error.NameTooLong, |
| | 2086 | .NFILE => return error.SystemFdQuotaExceeded, |
| | 2087 | .NODEV => return error.NoDevice, |
| | 2088 | .NOENT => return error.FileNotFound, |
| | 2089 | .NOMEM => return error.SystemResources, |
| | 2090 | .NOTDIR => return error.NotDir, |
| | 2091 | .PERM => return error.PermissionDenied, |
| | 2092 | .BUSY => return error.DeviceBusy, |
| | 2093 | else => |err| return posix.unexpectedErrno(err), |
| | 2094 | } |
| | 2095 | } |
| 2016 | } | 2096 | } |
| 2017 | | 2097 | |
| 2018 | fn dirOpenDirWindows( | 2098 | fn dirOpenDirWindows( |