mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
std.os.windows.OpenFile: add missing error
Encountered in a recent CI run on an aarch64-windows dev kit. Pretty sure I disabled the virus scanner but it looks like it turned itself back on with a Windows Update. Rather than marking the new error code as unreachable in the places where it is unexpected, this commit makes it return `error.Unexpected`.
This commit is contained in:
parent
a23ab331a2
commit
07c1dd3d1d
6 changed files with 88 additions and 48 deletions
|
|
@ -668,13 +668,14 @@ pub const ChildProcess = struct {
|
|||
.sa = &saAttr,
|
||||
.creation = windows.OPEN_EXISTING,
|
||||
}) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => unreachable, // not possible for "NUL"
|
||||
error.PipeBusy => unreachable, // not possible for "NUL"
|
||||
error.FileNotFound => unreachable, // not possible for "NUL"
|
||||
error.AccessDenied => unreachable, // not possible for "NUL"
|
||||
error.NameTooLong => unreachable, // not possible for "NUL"
|
||||
error.WouldBlock => unreachable, // not possible for "NUL"
|
||||
error.NetworkNotFound => unreachable, // not possible for "NUL"
|
||||
error.PathAlreadyExists => return error.Unexpected, // not possible for "NUL"
|
||||
error.PipeBusy => return error.Unexpected, // not possible for "NUL"
|
||||
error.FileNotFound => return error.Unexpected, // not possible for "NUL"
|
||||
error.AccessDenied => return error.Unexpected, // not possible for "NUL"
|
||||
error.NameTooLong => return error.Unexpected, // not possible for "NUL"
|
||||
error.WouldBlock => return error.Unexpected, // not possible for "NUL"
|
||||
error.NetworkNotFound => return error.Unexpected, // not possible for "NUL"
|
||||
error.AntivirusInterference => return error.Unexpected, // not possible for "NUL"
|
||||
else => |e| return e,
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,8 @@ pub fn makeOpenPath(self: Dir, sub_path: []const u8, open_dir_options: OpenDirOp
|
|||
};
|
||||
}
|
||||
|
||||
pub const RealPathError = posix.RealPathError;
|
||||
|
||||
/// This function returns the canonicalized absolute pathname of
|
||||
/// `pathname` relative to this `Dir`. If `pathname` is absolute, ignores this
|
||||
/// `Dir` handle and returns the canonicalized absolute pathname of `pathname`
|
||||
|
|
@ -1186,7 +1188,7 @@ pub fn makeOpenPath(self: Dir, sub_path: []const u8, open_dir_options: OpenDirOp
|
|||
/// This function is not universally supported by all platforms.
|
||||
/// Currently supported hosts are: Linux, macOS, and Windows.
|
||||
/// See also `Dir.realpathZ`, `Dir.realpathW`, and `Dir.realpathAlloc`.
|
||||
pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) ![]u8 {
|
||||
pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) RealPathError![]u8 {
|
||||
if (builtin.os.tag == .wasi) {
|
||||
@compileError("realpath is not available on WASI");
|
||||
}
|
||||
|
|
@ -1200,7 +1202,7 @@ pub fn realpath(self: Dir, pathname: []const u8, out_buffer: []u8) ![]u8 {
|
|||
|
||||
/// Same as `Dir.realpath` except `pathname` is null-terminated.
|
||||
/// See also `Dir.realpath`, `realpathZ`.
|
||||
pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 {
|
||||
pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) RealPathError![]u8 {
|
||||
if (builtin.os.tag == .windows) {
|
||||
const pathname_w = try posix.windows.cStrToPrefixedFileW(self.fd, pathname);
|
||||
return self.realpathW(pathname_w.span(), out_buffer);
|
||||
|
|
@ -1219,7 +1221,9 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 {
|
|||
};
|
||||
|
||||
const fd = posix.openatZ(self.fd, pathname, flags, 0) catch |err| switch (err) {
|
||||
error.FileLocksNotSupported => unreachable,
|
||||
error.FileLocksNotSupported => return error.Unexpected,
|
||||
error.FileBusy => return error.Unexpected,
|
||||
error.WouldBlock => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer posix.close(fd);
|
||||
|
|
@ -1244,7 +1248,7 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 {
|
|||
|
||||
/// Windows-only. Same as `Dir.realpath` except `pathname` is WTF16 encoded.
|
||||
/// See also `Dir.realpath`, `realpathW`.
|
||||
pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) ![]u8 {
|
||||
pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) RealPathError![]u8 {
|
||||
const w = std.os.windows;
|
||||
|
||||
const access_mask = w.GENERIC_READ | w.SYNCHRONIZE;
|
||||
|
|
@ -1265,27 +1269,31 @@ pub fn realpathW(self: Dir, pathname: []const u16, out_buffer: []u8) ![]u8 {
|
|||
};
|
||||
defer w.CloseHandle(h_file);
|
||||
|
||||
// Use of MAX_PATH_BYTES here is valid as the realpath function does not
|
||||
// have a variant that takes an arbitrary-size buffer.
|
||||
// TODO(#4812): Consider reimplementing realpath or using the POSIX.1-2008
|
||||
// NULL out parameter (GNU's canonicalize_file_name) to handle overelong
|
||||
// paths. musl supports passing NULL but restricts the output to PATH_MAX
|
||||
// anyway.
|
||||
var buffer: [fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const out_path = try posix.getFdPath(h_file, &buffer);
|
||||
|
||||
if (out_path.len > out_buffer.len) {
|
||||
var wide_buf: [w.PATH_MAX_WIDE]u16 = undefined;
|
||||
const wide_slice = try w.GetFinalPathNameByHandle(h_file, .{}, &wide_buf);
|
||||
var big_out_buf: [fs.MAX_PATH_BYTES]u8 = undefined;
|
||||
const end_index = std.unicode.utf16leToUtf8(&big_out_buf, wide_slice) catch |e| switch (e) {
|
||||
// TODO: Windows file paths can be arbitrary arrays of u16 values and
|
||||
// must not fail with InvalidUtf8.
|
||||
error.DanglingSurrogateHalf,
|
||||
error.ExpectedSecondSurrogateHalf,
|
||||
error.UnexpectedSecondSurrogateHalf,
|
||||
error.CodepointTooLarge,
|
||||
error.Utf8CannotEncodeSurrogateHalf,
|
||||
=> return error.InvalidUtf8,
|
||||
};
|
||||
if (end_index > out_buffer.len)
|
||||
return error.NameTooLong;
|
||||
}
|
||||
|
||||
const result = out_buffer[0..out_path.len];
|
||||
@memcpy(result, out_path);
|
||||
const result = out_buffer[0..end_index];
|
||||
@memcpy(result, big_out_buf[0..end_index]);
|
||||
return result;
|
||||
}
|
||||
|
||||
pub const RealPathAllocError = RealPathError || Allocator.Error;
|
||||
|
||||
/// Same as `Dir.realpath` except caller must free the returned memory.
|
||||
/// See also `Dir.realpath`.
|
||||
pub fn realpathAlloc(self: Dir, allocator: Allocator, pathname: []const u8) ![]u8 {
|
||||
pub fn realpathAlloc(self: Dir, allocator: Allocator, pathname: []const u8) RealPathAllocError![]u8 {
|
||||
// Use of MAX_PATH_BYTES here is valid as the realpath function does not
|
||||
// have a variant that takes an arbitrary-size buffer.
|
||||
// TODO(#4812): Consider reimplementing realpath or using the POSIX.1-2008
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ pub const OpenError = error{
|
|||
Unexpected,
|
||||
/// On Windows, `\\server` or `\\server\share` was not found.
|
||||
NetworkNotFound,
|
||||
/// On Windows, antivirus software is enabled by default. It can be
|
||||
/// disabled, but Windows Update sometimes ignores the user's preference
|
||||
/// and re-enables it. When enabled, antivirus software on Windows
|
||||
/// intercepts file system operations and makes them significantly slower
|
||||
/// in addition to possibly failing with this error code.
|
||||
AntivirusInterference,
|
||||
} || posix.OpenError || posix.FlockError;
|
||||
|
||||
pub const OpenMode = enum {
|
||||
|
|
|
|||
|
|
@ -2602,6 +2602,12 @@ pub const RenameError = error{
|
|||
PipeBusy,
|
||||
/// On Windows, `\\server` or `\\server\share` was not found.
|
||||
NetworkNotFound,
|
||||
/// On Windows, antivirus software is enabled by default. It can be
|
||||
/// disabled, but Windows Update sometimes ignores the user's preference
|
||||
/// and re-enables it. When enabled, antivirus software on Windows
|
||||
/// intercepts file system operations and makes them significantly slower
|
||||
/// in addition to possibly failing with this error code.
|
||||
AntivirusInterference,
|
||||
} || UnexpectedError;
|
||||
|
||||
/// Change the name or location of a file.
|
||||
|
|
@ -2927,9 +2933,10 @@ pub fn mkdiratW(dir_fd: fd_t, sub_path_w: []const u16, mode: u32) MakeDirError!v
|
|||
.creation = windows.FILE_CREATE,
|
||||
.filter = .dir_only,
|
||||
}) catch |err| switch (err) {
|
||||
error.IsDir => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.IsDir => return error.Unexpected,
|
||||
error.PipeBusy => return error.Unexpected,
|
||||
error.WouldBlock => return error.Unexpected,
|
||||
error.AntivirusInterference => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
windows.CloseHandle(sub_dir_handle);
|
||||
|
|
@ -3006,9 +3013,10 @@ pub fn mkdirW(dir_path_w: []const u16, mode: u32) MakeDirError!void {
|
|||
.creation = windows.FILE_CREATE,
|
||||
.filter = .dir_only,
|
||||
}) catch |err| switch (err) {
|
||||
error.IsDir => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.IsDir => return error.Unexpected,
|
||||
error.PipeBusy => return error.Unexpected,
|
||||
error.WouldBlock => return error.Unexpected,
|
||||
error.AntivirusInterference => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
windows.CloseHandle(sub_dir_handle);
|
||||
|
|
@ -5347,6 +5355,13 @@ pub const RealPathError = error{
|
|||
NetworkNotFound,
|
||||
|
||||
PathAlreadyExists,
|
||||
|
||||
/// On Windows, antivirus software is enabled by default. It can be
|
||||
/// disabled, but Windows Update sometimes ignores the user's preference
|
||||
/// and re-enables it. When enabled, antivirus software on Windows
|
||||
/// intercepts file system operations and makes them significantly slower
|
||||
/// in addition to possibly failing with this error code.
|
||||
AntivirusInterference,
|
||||
} || UnexpectedError;
|
||||
|
||||
/// Return the canonicalized absolute pathname.
|
||||
|
|
@ -5441,15 +5456,17 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
|
|||
|
||||
pub fn isGetFdPathSupportedOnTarget(os: std.Target.Os) bool {
|
||||
return switch (os.tag) {
|
||||
// zig fmt: off
|
||||
.windows,
|
||||
.macos, .ios, .watchos, .tvos,
|
||||
.macos,
|
||||
.ios,
|
||||
.watchos,
|
||||
.tvos,
|
||||
.linux,
|
||||
.solaris,
|
||||
.illumos,
|
||||
.freebsd,
|
||||
=> true,
|
||||
// zig fmt: on
|
||||
|
||||
.dragonfly => os.version_range.semver.max.order(.{ .major = 6, .minor = 0, .patch = 0 }) != .lt,
|
||||
.netbsd => os.version_range.semver.max.order(.{ .major = 10, .minor = 0, .patch = 0 }) != .lt,
|
||||
else => false,
|
||||
|
|
@ -5469,8 +5486,10 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
|
|||
var wide_buf: [windows.PATH_MAX_WIDE]u16 = undefined;
|
||||
const wide_slice = try windows.GetFinalPathNameByHandle(fd, .{}, wide_buf[0..]);
|
||||
|
||||
// Trust that Windows gives us valid UTF-16LE.
|
||||
const end_index = std.unicode.utf16leToUtf8(out_buffer, wide_slice) catch unreachable;
|
||||
// TODO: Windows file paths can be arbitrary arrays of u16 values
|
||||
// and must not fail with InvalidUtf8.
|
||||
const end_index = std.unicode.utf16leToUtf8(out_buffer, wide_slice) catch
|
||||
return error.InvalidUtf8;
|
||||
return out_buffer[0..end_index];
|
||||
},
|
||||
.macos, .ios, .watchos, .tvos => {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ pub const OpenError = error{
|
|||
NameTooLong,
|
||||
WouldBlock,
|
||||
NetworkNotFound,
|
||||
AntivirusInterference,
|
||||
};
|
||||
|
||||
pub const OpenFileOptions = struct {
|
||||
|
|
@ -145,6 +146,7 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN
|
|||
std.time.sleep(std.time.ns_per_ms);
|
||||
continue;
|
||||
},
|
||||
.VIRUS_INFECTED, .VIRUS_DELETED => return error.AntivirusInterference,
|
||||
else => return unexpectedStatus(rc),
|
||||
}
|
||||
}
|
||||
|
|
@ -637,9 +639,10 @@ pub fn CreateSymbolicLink(
|
|||
.filter = if (is_directory) .dir_only else .file_only,
|
||||
}) catch |err| switch (err) {
|
||||
error.IsDir => return error.PathAlreadyExists,
|
||||
error.NotDir => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.NotDir => return error.Unexpected,
|
||||
error.WouldBlock => return error.Unexpected,
|
||||
error.PipeBusy => return error.Unexpected,
|
||||
error.AntivirusInterference => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer CloseHandle(symlink_handle);
|
||||
|
|
@ -1158,14 +1161,15 @@ pub fn GetFinalPathNameByHandle(
|
|||
.share_access = FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
.creation = FILE_OPEN,
|
||||
}) catch |err| switch (err) {
|
||||
error.IsDir => unreachable,
|
||||
error.NotDir => unreachable,
|
||||
error.NoDevice => unreachable,
|
||||
error.AccessDenied => unreachable,
|
||||
error.PipeBusy => unreachable,
|
||||
error.PathAlreadyExists => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.NetworkNotFound => unreachable,
|
||||
error.IsDir => return error.Unexpected,
|
||||
error.NotDir => return error.Unexpected,
|
||||
error.NoDevice => return error.Unexpected,
|
||||
error.AccessDenied => return error.Unexpected,
|
||||
error.PipeBusy => return error.Unexpected,
|
||||
error.PathAlreadyExists => return error.Unexpected,
|
||||
error.WouldBlock => return error.Unexpected,
|
||||
error.NetworkNotFound => return error.Unexpected,
|
||||
error.AntivirusInterference => return error.Unexpected,
|
||||
else => |e| return e,
|
||||
};
|
||||
defer CloseHandle(mgmt_handle);
|
||||
|
|
|
|||
|
|
@ -766,6 +766,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion {
|
|||
error.PipeBusy => unreachable, // Windows-only
|
||||
error.SharingViolation => unreachable, // Windows-only
|
||||
error.NetworkNotFound => unreachable, // Windows-only
|
||||
error.AntivirusInterference => unreachable, // Windows-only
|
||||
error.FileLocksNotSupported => unreachable, // No lock requested.
|
||||
error.NoSpaceLeft => unreachable, // read-only
|
||||
error.PathAlreadyExists => unreachable, // read-only
|
||||
|
|
@ -1003,6 +1004,7 @@ fn detectAbiAndDynamicLinker(
|
|||
error.FileLocksNotSupported => unreachable,
|
||||
error.WouldBlock => unreachable,
|
||||
error.FileBusy => unreachable, // opened without write permissions
|
||||
error.AntivirusInterference => unreachable, // Windows-only error
|
||||
|
||||
error.IsDir,
|
||||
error.NotDir,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue