| ... | ... | @@ -208,6 +208,7 @@ pub fn io(t: *Threaded) Io { |
| 208 | 208 | .dirOpenDir = switch (builtin.os.tag) { |
| 209 | 209 | .windows => dirOpenDirWindows, |
| 210 | 210 | .wasi => dirOpenDirWasi, |
| 211 | .haiku => dirOpenDirHaiku, |
| 211 | 212 | else => dirOpenDirPosix, |
| 212 | 213 | }, |
| 213 | 214 | .dirClose = dirClose, |
| ... | ... | @@ -1784,22 +1785,20 @@ fn dirOpenFilePosix( |
| 1784 | 1785 | if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; |
| 1785 | 1786 | |
| 1786 | 1787 | // Use the O locking flags if the os supports them to acquire the lock |
| 1787 | | // atomically. |
| 1788 | | if (have_flock_open_flags) { |
| 1789 | | // Note that the NONBLOCK flag is removed after the openat() call |
| 1790 | | // is successful. |
| 1791 | | switch (flags.lock) { |
| 1792 | | .none => {}, |
| 1793 | | .shared => { |
| 1794 | | os_flags.SHLOCK = true; |
| 1795 | | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1796 | | }, |
| 1797 | | .exclusive => { |
| 1798 | | os_flags.EXLOCK = true; |
| 1799 | | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1800 | | }, |
| 1801 | | } |
| 1802 | | } |
| 1788 | // atomically. Note that the NONBLOCK flag is removed after the openat() |
| 1789 | // call is successful. |
| 1790 | if (have_flock_open_flags) switch (flags.lock) { |
| 1791 | .none => {}, |
| 1792 | .shared => { |
| 1793 | os_flags.SHLOCK = true; |
| 1794 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1795 | }, |
| 1796 | .exclusive => { |
| 1797 | os_flags.EXLOCK = true; |
| 1798 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 1799 | }, |
| 1800 | }; |
| 1801 | |
| 1803 | 1802 | const fd: posix.fd_t = while (true) { |
| 1804 | 1803 | try t.checkCancel(); |
| 1805 | 1804 | const rc = openat_sym(dir.handle, sub_path_posix, os_flags, @as(posix.mode_t, 0)); |
| ... | ... | @@ -2008,11 +2007,92 @@ fn dirOpenDirPosix( |
| 2008 | 2007 | ) Io.Dir.OpenError!Io.Dir { |
| 2009 | 2008 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 2010 | 2009 | |
| 2011 | | _ = t; |
| 2012 | | _ = dir; |
| 2013 | | _ = sub_path; |
| 2010 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 2011 | const sub_path_posix = try pathToPosix(sub_path, &path_buffer); |
| 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 | 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 | 2098 | fn dirOpenDirWindows( |