| ... | @@ -160,7 +160,11 @@ pub fn io(pool: *Pool) Io { | ... | @@ -160,7 +160,11 @@ pub fn io(pool: *Pool) Io { |
| 160 | .conditionWait = conditionWait, | 160 | .conditionWait = conditionWait, |
| 161 | .conditionWake = conditionWake, | 161 | .conditionWake = conditionWake, |
| 162 | | 162 | |
| 163 | .dirMake = dirMake, | 163 | .dirMake = switch (builtin.os.tag) { |
| | 164 | .windows => @panic("TODO"), |
| | 165 | .wasi => @panic("TODO"), |
| | 166 | else => dirMakePosix, |
| | 167 | }, |
| 164 | .dirStat = dirStat, | 168 | .dirStat = dirStat, |
| 165 | .dirStatPath = dirStatPath, | 169 | .dirStatPath = dirStatPath, |
| 166 | .fileStat = switch (builtin.os.tag) { | 170 | .fileStat = switch (builtin.os.tag) { |
| ... | @@ -759,14 +763,35 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. | ... | @@ -759,14 +763,35 @@ fn conditionWake(userdata: ?*anyopaque, cond: *Io.Condition, wake: Io.Condition. |
| 759 | } | 763 | } |
| 760 | } | 764 | } |
| 761 | | 765 | |
| 762 | fn dirMake(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { | 766 | fn dirMakePosix(userdata: ?*anyopaque, dir: Io.Dir, sub_path: []const u8, mode: Io.Dir.Mode) Io.Dir.MakeError!void { |
| 763 | const pool: *Pool = @ptrCast(@alignCast(userdata)); | 767 | const pool: *Pool = @ptrCast(@alignCast(userdata)); |
| 764 | try pool.checkCancel(); | 768 | var path_buffer: [posix.PATH_MAX]u8 = undefined; |
| 765 | | 769 | const sub_path_posix = try toPosixPath(sub_path, &path_buffer); |
| 766 | _ = dir; | 770 | while (true) { |
| 767 | _ = sub_path; | 771 | try pool.checkCancel(); |
| 768 | _ = mode; | 772 | switch (posix.errno(posix.system.mkdirat(dir.handle, sub_path_posix, mode))) { |
| 769 | @panic("TODO"); | 773 | .SUCCESS => return, |
| | 774 | .INTR => continue, |
| | 775 | .ACCES => return error.AccessDenied, |
| | 776 | .BADF => |err| return errnoBug(err), |
| | 777 | .PERM => return error.PermissionDenied, |
| | 778 | .DQUOT => return error.DiskQuota, |
| | 779 | .EXIST => return error.PathAlreadyExists, |
| | 780 | .FAULT => |err| return errnoBug(err), |
| | 781 | .LOOP => return error.SymLinkLoop, |
| | 782 | .MLINK => return error.LinkQuotaExceeded, |
| | 783 | .NAMETOOLONG => return error.NameTooLong, |
| | 784 | .NOENT => return error.FileNotFound, |
| | 785 | .NOMEM => return error.SystemResources, |
| | 786 | .NOSPC => return error.NoSpaceLeft, |
| | 787 | .NOTDIR => return error.NotDir, |
| | 788 | .ROFS => return error.ReadOnlyFileSystem, |
| | 789 | // dragonfly: when dir_fd is unlinked from filesystem |
| | 790 | .NOTCONN => return error.FileNotFound, |
| | 791 | .ILSEQ => return error.InvalidFileName, |
| | 792 | else => |err| return posix.unexpectedErrno(err), |
| | 793 | } |
| | 794 | } |
| 770 | } | 795 | } |
| 771 | | 796 | |
| 772 | fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { | 797 | fn dirStat(userdata: ?*anyopaque, dir: Io.Dir) Io.Dir.StatError!Io.Dir.Stat { |
| ... | @@ -2267,3 +2292,12 @@ fn timestampToPosix(nanoseconds: i96) std.posix.timespec { | ... | @@ -2267,3 +2292,12 @@ fn timestampToPosix(nanoseconds: i96) std.posix.timespec { |
| 2267 | .nsec = @intCast(@mod(nanoseconds, std.time.ns_per_s)), | 2292 | .nsec = @intCast(@mod(nanoseconds, std.time.ns_per_s)), |
| 2268 | }; | 2293 | }; |
| 2269 | } | 2294 | } |
| | 2295 | |
| | 2296 | fn toPosixPath(file_path: []const u8, buffer: *[posix.PATH_MAX]u8) error{ NameTooLong, InvalidFileName }![:0]u8 { |
| | 2297 | if (std.mem.containsAtLeastScalar2(u8, file_path, 0, 1)) return error.InvalidFileName; |
| | 2298 | // >= rather than > to make room for the null byte |
| | 2299 | if (file_path.len >= buffer.len) return error.NameTooLong; |
| | 2300 | @memcpy(buffer[0..file_path.len], file_path); |
| | 2301 | buffer[file_path.len] = 0; |
| | 2302 | return buffer[0..file_path.len :0]; |
| | 2303 | } |