| ... | @@ -2033,7 +2033,7 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { | ... | @@ -2033,7 +2033,7 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { |
| 2033 | // TODO call NtQueryInformationFile and ask for only the size instead of "all" | 2033 | // TODO call NtQueryInformationFile and ask for only the size instead of "all" |
| 2034 | } | 2034 | } |
| 2035 | | 2035 | |
| 2036 | const stat = try fileStat(ioBasic(t), file); | 2036 | const stat = try fileStat(t, file); |
| 2037 | return stat.size; | 2037 | return stat.size; |
| 2038 | } | 2038 | } |
| 2039 | | 2039 | |
| ... | @@ -3429,7 +3429,7 @@ fn dirReadDarwin(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Di | ... | @@ -3429,7 +3429,7 @@ fn dirReadDarwin(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Di |
| 3429 | const dents_buffer = dr.buffer[header_end..]; | 3429 | const dents_buffer = dr.buffer[header_end..]; |
| 3430 | try current_thread.beginSyscall(); | 3430 | try current_thread.beginSyscall(); |
| 3431 | const n: usize = while (true) { | 3431 | const n: usize = while (true) { |
| 3432 | const rc = posix.system.getdirentries(dr.dir.fd, dents_buffer.ptr, dents_buffer.len, &header.seek); | 3432 | const rc = posix.system.getdirentries(dr.dir.handle, dents_buffer.ptr, dents_buffer.len, &header.seek); |
| 3433 | switch (posix.errno(rc)) { | 3433 | switch (posix.errno(rc)) { |
| 3434 | .SUCCESS => { | 3434 | .SUCCESS => { |
| 3435 | current_thread.endSyscall(); | 3435 | current_thread.endSyscall(); |
| ... | @@ -3735,9 +3735,11 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b | ... | @@ -3735,9 +3735,11 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b |
| 3735 | if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; | 3735 | if (@hasField(posix.O, "CLOEXEC")) flags.CLOEXEC = true; |
| 3736 | if (@hasField(posix.O, "PATH")) flags.PATH = true; | 3736 | if (@hasField(posix.O, "PATH")) flags.PATH = true; |
| 3737 | | 3737 | |
| | 3738 | const mode: posix.mode_t = 0; |
| | 3739 | |
| 3738 | try current_thread.beginSyscall(); | 3740 | try current_thread.beginSyscall(); |
| 3739 | const fd: posix.fd_t = while (true) { | 3741 | const fd: posix.fd_t = while (true) { |
| 3740 | const rc = openat_sym(dir.handle, sub_path_posix, flags, 0); | 3742 | const rc = openat_sym(dir.handle, sub_path_posix, flags, mode); |
| 3741 | switch (posix.errno(rc)) { | 3743 | switch (posix.errno(rc)) { |
| 3742 | .SUCCESS => { | 3744 | .SUCCESS => { |
| 3743 | current_thread.endSyscall(); | 3745 | current_thread.endSyscall(); |
| ... | @@ -3784,10 +3786,11 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b | ... | @@ -3784,10 +3786,11 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b |
| 3784 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { | 3786 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { |
| 3785 | // On macOS, we can use F.GETPATH fcntl command to query the OS for | 3787 | // On macOS, we can use F.GETPATH fcntl command to query the OS for |
| 3786 | // the path to the file descriptor. | 3788 | // the path to the file descriptor. |
| 3787 | @memset(out_buffer, 0); | 3789 | var sufficient_buffer: [posix.PATH_MAX]u8 = undefined; |
| | 3790 | @memset(&sufficient_buffer, 0); |
| 3788 | try current_thread.beginSyscall(); | 3791 | try current_thread.beginSyscall(); |
| 3789 | while (true) { | 3792 | while (true) { |
| 3790 | switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, out_buffer))) { | 3793 | switch (posix.errno(posix.system.fcntl(fd, posix.F.GETPATH, &sufficient_buffer))) { |
| 3791 | .SUCCESS => { | 3794 | .SUCCESS => { |
| 3792 | current_thread.endSyscall(); | 3795 | current_thread.endSyscall(); |
| 3793 | break; | 3796 | break; |
| ... | @@ -3803,14 +3806,15 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b | ... | @@ -3803,14 +3806,15 @@ fn dirRealPathPosix(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8, out_b |
| 3803 | .BADF => return error.FileNotFound, | 3806 | .BADF => return error.FileNotFound, |
| 3804 | .NOSPC => return error.NameTooLong, | 3807 | .NOSPC => return error.NameTooLong, |
| 3805 | .NOENT => return error.FileNotFound, | 3808 | .NOENT => return error.FileNotFound, |
| 3806 | // TODO man pages for fcntl on macOS don't really tell you what | | |
| 3807 | // errno values to expect when command is F.GETPATH... | | |
| 3808 | else => |err| return posix.unexpectedErrno(err), | 3809 | else => |err| return posix.unexpectedErrno(err), |
| 3809 | } | 3810 | } |
| 3810 | }, | 3811 | }, |
| 3811 | } | 3812 | } |
| 3812 | } | 3813 | } |
| 3813 | return std.mem.indexOfScalar(u8, &out_buffer, 0) orelse out_buffer.len; | 3814 | const n = std.mem.indexOfScalar(u8, &sufficient_buffer, 0) orelse sufficient_buffer.len; |
| | 3815 | if (n > out_buffer.len) return error.NameTooLong; |
| | 3816 | @memcpy(out_buffer[0..n], sufficient_buffer[0..n]); |
| | 3817 | return n; |
| 3814 | }, | 3818 | }, |
| 3815 | .linux, .serenity, .illumos => { | 3819 | .linux, .serenity, .illumos => { |
| 3816 | var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined; | 3820 | var procfs_buf: ["/proc/self/path/-2147483648\x00".len]u8 = undefined; |
| ... | @@ -6578,7 +6582,6 @@ fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) std.proce | ... | @@ -6578,7 +6582,6 @@ fn processExecutableOpen(userdata: ?*anyopaque, flags: File.OpenFlags) std.proce |
| 6578 | | 6582 | |
| 6579 | fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.ExecutablePathError!usize { | 6583 | fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.ExecutablePathError!usize { |
| 6580 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | 6584 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 6581 | const max_path_bytes = std.fs.max_path_bytes; | | |
| 6582 | | 6585 | |
| 6583 | switch (native_os) { | 6586 | switch (native_os) { |
| 6584 | .driverkit, | 6587 | .driverkit, |
| ... | @@ -6591,20 +6594,19 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex | ... | @@ -6591,20 +6594,19 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex |
| 6591 | => { | 6594 | => { |
| 6592 | // Note that _NSGetExecutablePath() will return "a path" to | 6595 | // Note that _NSGetExecutablePath() will return "a path" to |
| 6593 | // the executable not a "real path" to the executable. | 6596 | // the executable not a "real path" to the executable. |
| 6594 | var symlink_path_buf: [max_path_bytes:0]u8 = undefined; | 6597 | var symlink_path_buf: [posix.PATH_MAX:0]u8 = undefined; |
| 6595 | var u32_len: u32 = max_path_bytes + 1; // include the sentinel | 6598 | var u32_len: u32 = posix.PATH_MAX + 1; // include the sentinel |
| 6596 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len); | 6599 | const rc = std.c._NSGetExecutablePath(&symlink_path_buf, &u32_len); |
| 6597 | if (rc != 0) return error.NameTooLong; | 6600 | if (rc != 0) return error.NameTooLong; |
| 6598 | | 6601 | |
| 6599 | var real_path_buf: [max_path_bytes]u8 = undefined; | 6602 | var real_path_buf: [posix.PATH_MAX]u8 = undefined; |
| 6600 | const real_path = Io.Dir.realPathAbsolute(ioBasic(t), &symlink_path_buf, &real_path_buf) catch |err| switch (err) { | 6603 | const n = Io.Dir.realPathAbsolute(ioBasic(t), &symlink_path_buf, &real_path_buf) catch |err| switch (err) { |
| 6601 | error.NetworkNotFound => unreachable, // Windows-only | 6604 | error.NetworkNotFound => unreachable, // Windows-only |
| 6602 | else => |e| return e, | 6605 | else => |e| return e, |
| 6603 | }; | 6606 | }; |
| 6604 | if (real_path.len > out_buffer.len) return error.NameTooLong; | 6607 | if (n > out_buffer.len) return error.NameTooLong; |
| 6605 | const result = out_buffer[0..real_path.len]; | 6608 | @memcpy(out_buffer[0..n], real_path_buf[0..n]); |
| 6606 | @memcpy(result, real_path); | 6609 | return n; |
| 6607 | return result.len; | | |
| 6608 | }, | 6610 | }, |
| 6609 | .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { | 6611 | .linux, .serenity => return Io.Dir.readLinkAbsolute(ioBasic(t), "/proc/self/exe", out_buffer) catch |err| switch (err) { |
| 6610 | error.UnsupportedReparsePointType => unreachable, // Windows-only | 6612 | error.UnsupportedReparsePointType => unreachable, // Windows-only |
| ... | @@ -6640,7 +6642,7 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex | ... | @@ -6640,7 +6642,7 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex |
| 6640 | const argv0 = std.mem.span(std.os.argv[0]); | 6642 | const argv0 = std.mem.span(std.os.argv[0]); |
| 6641 | if (std.mem.indexOf(u8, argv0, "/") != null) { | 6643 | if (std.mem.indexOf(u8, argv0, "/") != null) { |
| 6642 | // argv[0] is a path (relative or absolute): use realpath(3) directly | 6644 | // argv[0] is a path (relative or absolute): use realpath(3) directly |
| 6643 | var real_path_buf: [max_path_bytes]u8 = undefined; | 6645 | var real_path_buf: [posix.PATH_MAX]u8 = undefined; |
| 6644 | const real_path = Io.Dir.realPathAbsolute(ioBasic(t), std.os.argv[0], &real_path_buf) catch |err| switch (err) { | 6646 | const real_path = Io.Dir.realPathAbsolute(ioBasic(t), std.os.argv[0], &real_path_buf) catch |err| switch (err) { |
| 6645 | error.NetworkNotFound => unreachable, // Windows-only | 6647 | error.NetworkNotFound => unreachable, // Windows-only |
| 6646 | else => |e| return e, | 6648 | else => |e| return e, |
| ... | @@ -6655,12 +6657,12 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex | ... | @@ -6655,12 +6657,12 @@ fn processExecutablePath(userdata: ?*anyopaque, out_buffer: []u8) std.process.Ex |
| 6655 | const PATH = posix.getenvZ("PATH") orelse return error.FileNotFound; | 6657 | const PATH = posix.getenvZ("PATH") orelse return error.FileNotFound; |
| 6656 | var path_it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter); | 6658 | var path_it = std.mem.tokenizeScalar(u8, PATH, std.fs.path.delimiter); |
| 6657 | while (path_it.next()) |a_path| { | 6659 | while (path_it.next()) |a_path| { |
| 6658 | var resolved_path_buf: [max_path_bytes - 1:0]u8 = undefined; | 6660 | var resolved_path_buf: [posix.PATH_MAX - 1:0]u8 = undefined; |
| 6659 | const resolved_path = std.fmt.bufPrintSentinel(&resolved_path_buf, "{s}/{s}", .{ | 6661 | const resolved_path = std.fmt.bufPrintSentinel(&resolved_path_buf, "{s}/{s}", .{ |
| 6660 | a_path, std.os.argv[0], | 6662 | a_path, std.os.argv[0], |
| 6661 | }, 0) catch continue; | 6663 | }, 0) catch continue; |
| 6662 | | 6664 | |
| 6663 | var real_path_buf: [max_path_bytes]u8 = undefined; | 6665 | var real_path_buf: [posix.PATH_MAX]u8 = undefined; |
| 6664 | if (Io.Dir.realPathAbsolute(ioBasic(t), resolved_path, &real_path_buf)) |real_path| { | 6666 | if (Io.Dir.realPathAbsolute(ioBasic(t), resolved_path, &real_path_buf)) |real_path| { |
| 6665 | // found a file, and hope it is the right file | 6667 | // found a file, and hope it is the right file |
| 6666 | if (real_path.len > out_buffer.len) | 6668 | if (real_path.len > out_buffer.len) |
| ... | @@ -7566,7 +7568,7 @@ fn fileWriteFilePositional( | ... | @@ -7566,7 +7568,7 @@ fn fileWriteFilePositional( |
| 7566 | current_thread.endSyscall(); | 7568 | current_thread.endSyscall(); |
| 7567 | assert(error.Unexpected == switch (e) { | 7569 | assert(error.Unexpected == switch (e) { |
| 7568 | .NOMEM => return error.SystemResources, | 7570 | .NOMEM => return error.SystemResources, |
| 7569 | .INVAL => |err| posix.errnoBug(err), | 7571 | .INVAL => |err| errnoBug(err), |
| 7570 | else => |err| posix.unexpectedErrno(err), | 7572 | else => |err| posix.unexpectedErrno(err), |
| 7571 | }); | 7573 | }); |
| 7572 | return 0; | 7574 | return 0; |