diff options
Diffstat (limited to 'lib/std/os.zig')
| -rw-r--r-- | lib/std/os.zig | 70 |
1 files changed, 46 insertions, 24 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig index 3ba810445a..b530ac94ab 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1539,12 +1539,13 @@ pub const MakeDirError = error{ ReadOnlyFileSystem, InvalidUtf8, BadPathName, + NoDevice, } || UnexpectedError; pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!void { - if (builtin.os == .windows) { + if (builtin.os.tag == .windows) { const sub_dir_path_w = try windows.sliceToPrefixedFileW(sub_dir_path); - @compileError("TODO implement mkdirat for Windows"); + return mkdiratW(dir_fd, &sub_dir_path_w, mode); } else { const sub_dir_path_c = try toPosixPath(sub_dir_path); return mkdiratC(dir_fd, &sub_dir_path_c, mode); @@ -1552,9 +1553,9 @@ pub fn mkdirat(dir_fd: fd_t, sub_dir_path: []const u8, mode: u32) MakeDirError!v } pub fn mkdiratC(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirError!void { - if (builtin.os == .windows) { + if (builtin.os.tag == .windows) { const sub_dir_path_w = try windows.cStrToPrefixedFileW(sub_dir_path); - @compileError("TODO implement mkdiratC for Windows"); + return mkdiratW(dir_fd, &sub_dir_path_w, mode); } switch (errno(system.mkdirat(dir_fd, sub_dir_path, mode))) { 0 => return, @@ -1576,23 +1577,31 @@ pub fn mkdiratC(dir_fd: fd_t, sub_dir_path: [*:0]const u8, mode: u32) MakeDirErr } } +pub fn mkdiratW(dir_fd: fd_t, sub_path_w: [*:0]const u16, mode: u32) MakeDirError!void { + const sub_dir_handle = try windows.CreateDirectoryW(dir_fd, sub_path_w, null); + windows.CloseHandle(sub_dir_handle); +} + /// Create a directory. /// `mode` is ignored on Windows. pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void { if (builtin.os.tag == .windows) { - const dir_path_w = try windows.sliceToPrefixedFileW(dir_path); - return windows.CreateDirectoryW(&dir_path_w, null); + const sub_dir_handle = try windows.CreateDirectory(null, dir_path, null); + windows.CloseHandle(sub_dir_handle); + return; } else { const dir_path_c = try toPosixPath(dir_path); - return mkdirC(&dir_path_c, mode); + return mkdirZ(&dir_path_c, mode); } } /// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string. -pub fn mkdirC(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { +pub fn mkdirZ(dir_path: [*:0]const u8, mode: u32) MakeDirError!void { if (builtin.os.tag == .windows) { const dir_path_w = try windows.cStrToPrefixedFileW(dir_path); - return windows.CreateDirectoryW(&dir_path_w, null); + const sub_dir_handle = try windows.CreateDirectoryW(null, &dir_path_w, null); + windows.CloseHandle(sub_dir_handle); + return; } switch (errno(system.mkdir(dir_path, mode))) { 0 => return, @@ -1705,7 +1714,13 @@ pub fn chdirC(dir_path: [*:0]const u8) ChangeCurDirError!void { } } -pub fn fchdir(dirfd: fd_t) ChangeCurDirError!void { +pub const FchdirError = error{ + AccessDenied, + NotDir, + FileSystem, +} || UnexpectedError; + +pub fn fchdir(dirfd: fd_t) FchdirError!void { while (true) { switch (errno(system.fchdir(dirfd))) { 0 => return, @@ -3564,12 +3579,12 @@ fn count_iovec_bytes(iovs: []const iovec_const) usize { } /// Transfer data between file descriptors, with optional headers and trailers. -/// Returns the number of bytes written. This will be zero if `in_offset` falls beyond the end of the file. +/// Returns the number of bytes written, which can be zero. /// -/// The `sendfile` call copies `count` bytes from one file descriptor to another. When possible, +/// The `sendfile` call copies `in_len` bytes from one file descriptor to another. When possible, /// this is done within the operating system kernel, which can provide better performance /// characteristics than transferring data from kernel to user space and back, such as with -/// `read` and `write` calls. When `count` is `0`, it means to copy until the end of the input file has been +/// `read` and `write` calls. When `in_len` is `0`, it means to copy until the end of the input file has been /// reached. Note, however, that partial writes are still possible in this case. /// /// `in_fd` must be a file descriptor opened for reading, and `out_fd` must be a file descriptor @@ -3578,7 +3593,8 @@ fn count_iovec_bytes(iovs: []const iovec_const) usize { /// atomicity guarantees no longer apply. /// /// Copying begins reading at `in_offset`. The input file descriptor seek position is ignored and not updated. -/// If the output file descriptor has a seek position, it is updated as bytes are written. +/// If the output file descriptor has a seek position, it is updated as bytes are written. When +/// `in_offset` is past the end of the input file, it successfully reads 0 bytes. /// /// `flags` has different meanings per operating system; refer to the respective man pages. /// @@ -3599,7 +3615,7 @@ pub fn sendfile( out_fd: fd_t, in_fd: fd_t, in_offset: u64, - count: usize, + in_len: u64, headers: []const iovec_const, trailers: []const iovec_const, flags: u32, @@ -3608,9 +3624,15 @@ pub fn sendfile( var total_written: usize = 0; // Prevents EOVERFLOW. + const size_t = @Type(std.builtin.TypeInfo{ + .Int = .{ + .is_signed = false, + .bits = @typeInfo(usize).Int.bits - 1, + }, + }); const max_count = switch (std.Target.current.os.tag) { .linux => 0x7ffff000, - else => math.maxInt(isize), + else => math.maxInt(size_t), }; switch (std.Target.current.os.tag) { @@ -3630,7 +3652,7 @@ pub fn sendfile( } // Here we match BSD behavior, making a zero count value send as many bytes as possible. - const adjusted_count = if (count == 0) max_count else math.min(count, max_count); + const adjusted_count = if (in_len == 0) max_count else math.min(in_len, @as(size_t, max_count)); while (true) { var offset: off_t = @bitCast(off_t, in_offset); @@ -3639,10 +3661,10 @@ pub fn sendfile( 0 => { const amt = @bitCast(usize, rc); total_written += amt; - if (count == 0 and amt == 0) { + if (in_len == 0 and amt == 0) { // We have detected EOF from `in_fd`. break; - } else if (amt < count) { + } else if (amt < in_len) { return total_written; } else { break; @@ -3708,7 +3730,7 @@ pub fn sendfile( hdtr = &hdtr_data; } - const adjusted_count = math.min(count, max_count); + const adjusted_count = math.min(in_len, max_count); while (true) { var sbytes: off_t = undefined; @@ -3786,7 +3808,7 @@ pub fn sendfile( hdtr = &hdtr_data; } - const adjusted_count = math.min(count, @as(u63, max_count)); + const adjusted_count = math.min(in_len, @as(u63, max_count)); while (true) { var sbytes: off_t = adjusted_count; @@ -3840,10 +3862,10 @@ pub fn sendfile( rw: { var buf: [8 * 4096]u8 = undefined; // Here we match BSD behavior, making a zero count value send as many bytes as possible. - const adjusted_count = if (count == 0) buf.len else math.min(buf.len, count); + const adjusted_count = if (in_len == 0) buf.len else math.min(buf.len, in_len); const amt_read = try pread(in_fd, buf[0..adjusted_count], in_offset); if (amt_read == 0) { - if (count == 0) { + if (in_len == 0) { // We have detected EOF from `in_fd`. break :rw; } else { @@ -3852,7 +3874,7 @@ pub fn sendfile( } const amt_written = try write(out_fd, buf[0..amt_read]); total_written += amt_written; - if (amt_written < count or count == 0) return total_written; + if (amt_written < in_len or in_len == 0) return total_written; } if (trailers.len != 0) { |
