| author | |
| committer | |
| log | 6d1b2c7f64fd1a1c671f357cff96b3dd39612857 |
| tree | 996e692c2b132f48827de477da5a8777bd8ee1fb |
| parent | 1c67607397be4efa962d64a1d80b7fd91fe161eb |
6 files changed, 61 insertions(+), 29 deletions(-)
lib/std/Io.zig+1| ... | ... | @@ -678,6 +678,7 @@ pub const VTable = struct { |
| 678 | 678 | fileReadPositional: *const fn (?*anyopaque, File, data: [][]u8, offset: u64) File.ReadPositionalError!usize, |
| 679 | 679 | fileSeekBy: *const fn (?*anyopaque, File, relative_offset: i64) File.SeekError!void, |
| 680 | 680 | fileSeekTo: *const fn (?*anyopaque, File, absolute_offset: u64) File.SeekError!void, |
| 681 | openSelfExe: *const fn (?*anyopaque, File.OpenFlags) File.OpenSelfExeError!File, | |
| 681 | 682 | |
| 682 | 683 | now: *const fn (?*anyopaque, Clock) Clock.Error!Timestamp, |
| 683 | 684 | sleep: *const fn (?*anyopaque, Timeout) SleepError!void, |
lib/std/Io/Dir.zig+16-1| ... | ... | @@ -1,5 +1,8 @@ |
| 1 | 1 | const Dir = @This(); |
| 2 | 2 | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const native_os = builtin.os.tag; | |
| 5 | ||
| 3 | 6 | const std = @import("../std.zig"); |
| 4 | 7 | const Io = std.Io; |
| 5 | 8 | const File = Io.File; |
| ... | ... | @@ -9,8 +12,20 @@ handle: Handle, |
| 9 | 12 | pub const Mode = Io.File.Mode; |
| 10 | 13 | pub const default_mode: Mode = 0o755; |
| 11 | 14 | |
| 15 | /// Returns a handle to the current working directory. | |
| 16 | /// | |
| 17 | /// It is not opened with iteration capability. Iterating over the result is | |
| 18 | /// illegal behavior. | |
| 19 | /// | |
| 20 | /// Closing the returned `Dir` is checked illegal behavior. | |
| 21 | /// | |
| 22 | /// On POSIX targets, this function is comptime-callable. | |
| 12 | 23 | pub fn cwd() Dir { |
| 13 | return .{ .handle = std.fs.cwd().fd }; | |
| 24 | return switch (native_os) { | |
| 25 | .windows => .{ .handle = std.os.windows.peb().ProcessParameters.CurrentDirectory.Handle }, | |
| 26 | .wasi => .{ .handle = std.options.wasiCwd() }, | |
| 27 | else => .{ .handle = std.posix.AT.FDCWD }, | |
| 28 | }; | |
| 14 | 29 | } |
| 15 | 30 | |
| 16 | 31 | pub const Handle = std.posix.fd_t; |
lib/std/Io/File.zig+6| ... | ... | @@ -207,6 +207,12 @@ pub fn close(file: File, io: Io) void { |
| 207 | 207 | return io.vtable.fileClose(io.userdata, file); |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | pub const OpenSelfExeError = OpenError || std.fs.SelfExePathError || std.posix.FlockError; | |
| 211 | ||
| 212 | pub fn openSelfExe(io: Io, flags: OpenFlags) OpenSelfExeError!File { | |
| 213 | return io.vtable.openSelfExe(io.userdata, flags); | |
| 214 | } | |
| 215 | ||
| 210 | 216 | pub const ReadStreamingError = error{ |
| 211 | 217 | InputOutput, |
| 212 | 218 | SystemResources, |
lib/std/Io/Threaded.zig+21| ... | ... | @@ -209,6 +209,7 @@ pub fn io(t: *Threaded) Io { |
| 209 | 209 | .fileReadPositional = fileReadPositional, |
| 210 | 210 | .fileSeekBy = fileSeekBy, |
| 211 | 211 | .fileSeekTo = fileSeekTo, |
| 212 | .openSelfExe = openSelfExe, | |
| 212 | 213 | |
| 213 | 214 | .now = switch (builtin.os.tag) { |
| 214 | 215 | .windows => nowWindows, |
| ... | ... | @@ -2241,6 +2242,26 @@ fn fileSeekTo(userdata: ?*anyopaque, file: Io.File, offset: u64) Io.File.SeekErr |
| 2241 | 2242 | } |
| 2242 | 2243 | } |
| 2243 | 2244 | |
| 2245 | fn openSelfExe(userdata: ?*anyopaque, flags: Io.File.OpenFlags) Io.File.OpenSelfExeError!Io.File { | |
| 2246 | const t: *Threaded = @ptrCast(@alignCast(userdata)); | |
| 2247 | if (native_os == .linux or native_os == .serenity) { | |
| 2248 | return dirOpenFilePosix(t, .{ .handle = posix.AT.FDCWD }, "/proc/self/exe", flags); | |
| 2249 | } | |
| 2250 | if (is_windows) { | |
| 2251 | // If ImagePathName is a symlink, then it will contain the path of the symlink, | |
| 2252 | // not the path that the symlink points to. However, because we are opening | |
| 2253 | // the file, we can let the openFileW call follow the symlink for us. | |
| 2254 | const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName; | |
| 2255 | const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; | |
| 2256 | const prefixed_path_w_array = try windows.wToPrefixedFileW(null, image_path_name); | |
| 2257 | const prefixed_path_w = prefixed_path_w_array.span(); | |
| 2258 | const cwd_handle = std.os.windows.peb().ProcessParameters.CurrentDirectory.Handle; | |
| 2259 | ||
| 2260 | return dirOpenFileWindows(t, .{ .handle = cwd_handle }, prefixed_path_w, flags); | |
| 2261 | } | |
| 2262 | @panic("TODO"); | |
| 2263 | } | |
| 2264 | ||
| 2244 | 2265 | fn fileWritePositional( |
| 2245 | 2266 | userdata: ?*anyopaque, |
| 2246 | 2267 | file: Io.File, |
lib/std/debug/SelfInfo/Windows.zig+10-13| ... | ... | @@ -297,17 +297,7 @@ const Module = struct { |
| 297 | 297 | // a binary is produced with -gdwarf, since the section names are longer than 8 bytes. |
| 298 | 298 | const mapped_file: ?DebugInfo.MappedFile = mapped: { |
| 299 | 299 | if (!coff_obj.strtabRequired()) break :mapped null; |
| 300 | var name_buffer: [windows.PATH_MAX_WIDE + 4:0]u16 = undefined; | |
| 301 | name_buffer[0..4].* = .{ '\\', '?', '?', '\\' }; // openFileAbsoluteW requires the prefix to be present | |
| 302 | const process_handle = windows.GetCurrentProcess(); | |
| 303 | const len = windows.kernel32.GetModuleFileNameExW( | |
| 304 | process_handle, | |
| 305 | module.handle, | |
| 306 | name_buffer[4..], | |
| 307 | windows.PATH_MAX_WIDE, | |
| 308 | ); | |
| 309 | if (len == 0) return error.MissingDebugInfo; | |
| 310 | const coff_file = fs.openFileAbsoluteW(name_buffer[0 .. len + 4 :0], .{}) catch |err| switch (err) { | |
| 300 | const coff_file = Io.File.openSelfExe(io, .{}) catch |err| switch (err) { | |
| 311 | 301 | error.Canceled => |e| return e, |
| 312 | 302 | error.Unexpected => |e| return e, |
| 313 | 303 | error.FileNotFound => return error.MissingDebugInfo, |
| ... | ... | @@ -337,9 +327,15 @@ const Module = struct { |
| 337 | 327 | error.SystemFdQuotaExceeded, |
| 338 | 328 | error.FileLocksNotSupported, |
| 339 | 329 | error.FileBusy, |
| 330 | error.InputOutput, | |
| 331 | error.NotSupported, | |
| 332 | error.FileSystem, | |
| 333 | error.NotLink, | |
| 334 | error.UnrecognizedVolume, | |
| 335 | error.UnknownName, | |
| 340 | 336 | => return error.ReadFailed, |
| 341 | 337 | }; |
| 342 | errdefer coff_file.close(); | |
| 338 | errdefer coff_file.close(io); | |
| 343 | 339 | var section_handle: windows.HANDLE = undefined; |
| 344 | 340 | const create_section_rc = windows.ntdll.NtCreateSection( |
| 345 | 341 | &section_handle, |
| ... | ... | @@ -356,6 +352,7 @@ const Module = struct { |
| 356 | 352 | errdefer windows.CloseHandle(section_handle); |
| 357 | 353 | var coff_len: usize = 0; |
| 358 | 354 | var section_view_ptr: ?[*]const u8 = null; |
| 355 | const process_handle = windows.GetCurrentProcess(); | |
| 359 | 356 | const map_section_rc = windows.ntdll.NtMapViewOfSection( |
| 360 | 357 | section_handle, |
| 361 | 358 | process_handle, |
| ... | ... | @@ -373,7 +370,7 @@ const Module = struct { |
| 373 | 370 | const section_view = section_view_ptr.?[0..coff_len]; |
| 374 | 371 | coff_obj = coff.Coff.init(section_view, false) catch return error.InvalidDebugInfo; |
| 375 | 372 | break :mapped .{ |
| 376 | .file = coff_file, | |
| 373 | .file = .adaptFromNewApi(coff_file), | |
| 377 | 374 | .section_handle = section_handle, |
| 378 | 375 | .section_view = section_view, |
| 379 | 376 | }; |
lib/std/fs.zig+7-15| ... | ... | @@ -180,9 +180,7 @@ pub fn renameZ(old_dir: Dir, old_sub_path_z: [*:0]const u8, new_dir: Dir, new_su |
| 180 | 180 | return posix.renameatZ(old_dir.fd, old_sub_path_z, new_dir.fd, new_sub_path_z); |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | /// Returns a handle to the current working directory. It is not opened with iteration capability. | |
| 184 | /// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior. | |
| 185 | /// On POSIX targets, this function is comptime-callable. | |
| 183 | /// Deprecated in favor of `Io.Dir.cwd`. | |
| 186 | 184 | pub fn cwd() Dir { |
| 187 | 185 | if (native_os == .windows) { |
| 188 | 186 | return .{ .fd = windows.peb().ProcessParameters.CurrentDirectory.Handle }; |
| ... | ... | @@ -336,20 +334,14 @@ pub fn symLinkAbsoluteW( |
| 336 | 334 | return windows.CreateSymbolicLink(null, mem.span(sym_link_path_w), mem.span(target_path_w), flags.is_directory); |
| 337 | 335 | } |
| 338 | 336 | |
| 339 | pub const OpenSelfExeError = posix.OpenError || SelfExePathError || posix.FlockError; | |
| 337 | pub const OpenSelfExeError = Io.File.OpenSelfExeError; | |
| 340 | 338 | |
| 339 | /// Deprecated in favor of `Io.File.openSelfExe`. | |
| 341 | 340 | pub fn openSelfExe(flags: File.OpenFlags) OpenSelfExeError!File { |
| 342 | if (native_os == .linux or native_os == .serenity) { | |
| 343 | return openFileAbsolute("/proc/self/exe", flags); | |
| 344 | } | |
| 345 | if (native_os == .windows) { | |
| 346 | // If ImagePathName is a symlink, then it will contain the path of the symlink, | |
| 347 | // not the path that the symlink points to. However, because we are opening | |
| 348 | // the file, we can let the openFileW call follow the symlink for us. | |
| 349 | const image_path_unicode_string = &windows.peb().ProcessParameters.ImagePathName; | |
| 350 | const image_path_name = image_path_unicode_string.Buffer.?[0 .. image_path_unicode_string.Length / 2 :0]; | |
| 351 | const prefixed_path_w = try windows.wToPrefixedFileW(null, image_path_name); | |
| 352 | return cwd().openFileW(prefixed_path_w.span(), flags); | |
| 341 | if (native_os == .linux or native_os == .serenity or native_os == .windows) { | |
| 342 | var threaded: Io.Threaded = .init_single_threaded; | |
| 343 | const io = threaded.io(); | |
| 344 | return .adaptFromNewApi(try Io.File.openSelfExe(io, flags)); | |
| 353 | 345 | } |
| 354 | 346 | // Use of max_path_bytes here is valid as the resulting path is immediately |
| 355 | 347 | // opened with no modification. |