From 9a3adeea6ef0eb30e75e732148e0a2b93d0d0c99 Mon Sep 17 00:00:00 2001 From: Ryan Liptak Date: Wed, 26 Jul 2023 14:41:53 -0700 Subject: [PATCH] windows.OpenFile/DeleteFile: Add NetworkNotFound as a possible error When calling NtCreateFile with a UNC path, if either `\\server` or `\\server\share` are not found, then the statuses `BAD_NETWORK_PATH` or `BAD_NETWORK_NAME` are returned (respectively). These statuses are not translated into `error.FileNotFound` because they convey more information than the typical FileNotFound error. For example, if you were trying to call `Dir.makePath` with an absolute UNC path like `\\MyServer\MyShare\a\b\c\d`, then knowing that `\\MyServer\MyShare` was not found allows for returning after trying to create the first directory instead of then trying to create `a\b\c`, `a\b`, etc. when it's already known that they will all fail in the same way. --- lib/std/child_process.zig | 2 ++ lib/std/fs.zig | 15 +++++++++++++++ lib/std/fs/file.zig | 2 ++ lib/std/os.zig | 15 +++++++++++++++ lib/std/os/windows.zig | 11 +++++++++++ lib/std/zig/system/NativeTargetInfo.zig | 3 +++ 6 files changed, 48 insertions(+) diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index baa1c0f58b..36288d7bb3 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -508,6 +508,7 @@ pub const ChildProcess = struct { error.BadPathName => unreachable, // Windows-only error.InvalidHandle => unreachable, // WASI-only error.WouldBlock => unreachable, + error.NetworkNotFound => unreachable, // Windows-only else => |e| return e, } else @@ -659,6 +660,7 @@ pub const ChildProcess = struct { 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" else => |e| return e, } else diff --git a/lib/std/fs.zig b/lib/std/fs.zig index cb6ce2032e..28a7472ccc 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -1099,6 +1099,8 @@ pub const Dir = struct { InvalidUtf8, BadPathName, DeviceBusy, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || os.UnexpectedError; pub fn close(self: *Dir) void { @@ -1890,6 +1892,8 @@ pub const Dir = struct { ReadOnlyFileSystem, InvalidUtf8, BadPathName, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, Unexpected, }; @@ -2112,6 +2116,9 @@ pub const Dir = struct { /// On Windows, file paths cannot contain these characters: /// '/', '*', '?', '"', '<', '>', '|' BadPathName, + + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || os.UnexpectedError; /// Whether `full_path` describes a symlink, file, or directory, this function @@ -2168,6 +2175,7 @@ pub const Dir = struct { error.Unexpected, error.InvalidUtf8, error.BadPathName, + error.NetworkNotFound, error.DeviceBusy, => |e| return e, }; @@ -2204,6 +2212,7 @@ pub const Dir = struct { error.FileSystem, error.FileBusy, error.BadPathName, + error.NetworkNotFound, error.Unexpected, => |e| return e, } @@ -2257,6 +2266,7 @@ pub const Dir = struct { error.Unexpected, error.InvalidUtf8, error.BadPathName, + error.NetworkNotFound, error.DeviceBusy, => |e| return e, }; @@ -2283,6 +2293,7 @@ pub const Dir = struct { error.FileSystem, error.FileBusy, error.BadPathName, + error.NetworkNotFound, error.Unexpected, => |e| return e, } @@ -2353,6 +2364,7 @@ pub const Dir = struct { error.Unexpected, error.InvalidUtf8, error.BadPathName, + error.NetworkNotFound, error.DeviceBusy, => |e| return e, }; @@ -2386,6 +2398,7 @@ pub const Dir = struct { error.FileSystem, error.FileBusy, error.BadPathName, + error.NetworkNotFound, error.Unexpected, => |e| return e, } @@ -2446,6 +2459,7 @@ pub const Dir = struct { error.InvalidUtf8, error.BadPathName, error.DeviceBusy, + error.NetworkNotFound, => |e| return e, }; } else { @@ -2469,6 +2483,7 @@ pub const Dir = struct { error.FileSystem, error.FileBusy, error.BadPathName, + error.NetworkNotFound, error.Unexpected, => |e| return e, } diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index e9448aa5d3..99946f2fae 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -73,6 +73,8 @@ pub const File = struct { /// '/', '*', '?', '"', '<', '>', '|' BadPathName, Unexpected, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || os.OpenError || os.FlockError; pub const OpenMode = enum { diff --git a/lib/std/os.zig b/lib/std/os.zig index db07614ce9..d569a466cb 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1463,6 +1463,9 @@ pub const OpenError = error{ BadPathName, InvalidUtf8, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + /// One of these three things: /// * pathname refers to an executable image which is currently being /// executed and write access was requested. @@ -2307,6 +2310,9 @@ pub const UnlinkError = error{ /// On Windows, file paths cannot contain these characters: /// '/', '*', '?', '"', '<', '>', '|' BadPathName, + + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || UnexpectedError; /// Delete a name and possibly the file it refers to. @@ -2472,6 +2478,8 @@ pub const RenameError = error{ NoDevice, SharingViolation, PipeBusy, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || UnexpectedError; /// Change the name or location of a file. @@ -2777,6 +2785,8 @@ pub const MakeDirError = error{ InvalidUtf8, BadPathName, NoDevice, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || UnexpectedError; /// Create a directory. @@ -2850,6 +2860,8 @@ pub const DeleteDirError = error{ ReadOnlyFileSystem, InvalidUtf8, BadPathName, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, } || UnexpectedError; /// Deletes an empty directory. @@ -5067,6 +5079,9 @@ pub const RealPathError = error{ /// On Windows, file paths must be valid Unicode. InvalidUtf8, + /// On Windows, `\\server` or `\\server\share` was not found. + NetworkNotFound, + PathAlreadyExists, } || UnexpectedError; diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index dccae6852b..1e52337538 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -46,6 +46,7 @@ pub const OpenError = error{ Unexpected, NameTooLong, WouldBlock, + NetworkNotFound, }; pub const OpenFileOptions = struct { @@ -130,6 +131,8 @@ pub fn OpenFile(sub_path_w: []const u16, options: OpenFileOptions) OpenError!HAN .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found + .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't .NO_MEDIA_IN_DEVICE => return error.NoDevice, .INVALID_PARAMETER => unreachable, .SHARING_VIOLATION => return error.AccessDenied, @@ -700,6 +703,7 @@ pub const CreateSymbolicLinkError = error{ FileNotFound, NameTooLong, NoDevice, + NetworkNotFound, Unexpected, }; @@ -812,6 +816,9 @@ pub fn ReadLink(dir: ?HANDLE, sub_path_w: []const u16, out_buffer: []u8) ReadLin .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, .NO_MEDIA_IN_DEVICE => return error.FileNotFound, + // TODO: Should BAD_NETWORK_* be translated to a different error? + .BAD_NETWORK_PATH => return error.FileNotFound, // \\server was not found + .BAD_NETWORK_NAME => return error.FileNotFound, // \\server was found but \\server\share wasn't .INVALID_PARAMETER => unreachable, .SHARING_VIOLATION => return error.AccessDenied, .ACCESS_DENIED => return error.AccessDenied, @@ -873,6 +880,7 @@ pub const DeleteFileError = error{ NotDir, IsDir, DirNotEmpty, + NetworkNotFound, }; pub const DeleteFileOptions = struct { @@ -931,6 +939,8 @@ pub fn DeleteFile(sub_path_w: []const u16, options: DeleteFileOptions) DeleteFil .OBJECT_NAME_INVALID => unreachable, .OBJECT_NAME_NOT_FOUND => return error.FileNotFound, .OBJECT_PATH_NOT_FOUND => return error.FileNotFound, + .BAD_NETWORK_PATH => return error.NetworkNotFound, // \\server was not found + .BAD_NETWORK_NAME => return error.NetworkNotFound, // \\server was found but \\server\share wasn't .INVALID_PARAMETER => unreachable, .FILE_IS_A_DIRECTORY => return error.IsDir, .NOT_A_DIRECTORY => return error.NotDir, @@ -1207,6 +1217,7 @@ pub fn GetFinalPathNameByHandle( error.PipeBusy => unreachable, error.PathAlreadyExists => unreachable, error.WouldBlock => unreachable, + error.NetworkNotFound => unreachable, else => |e| return e, }; defer CloseHandle(mgmt_handle); diff --git a/lib/std/zig/system/NativeTargetInfo.zig b/lib/std/zig/system/NativeTargetInfo.zig index f69f1e1b1e..99a1a8f2ef 100644 --- a/lib/std/zig/system/NativeTargetInfo.zig +++ b/lib/std/zig/system/NativeTargetInfo.zig @@ -338,6 +338,7 @@ fn detectAbiAndDynamicLinker( error.AccessDenied, error.NoDevice, error.FileNotFound, + error.NetworkNotFound, error.FileTooBig, error.Unexpected, => |e| { @@ -401,6 +402,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { error.InvalidUtf8 => unreachable, error.BadPathName => unreachable, error.DeviceBusy => unreachable, + error.NetworkNotFound => unreachable, // Windows-only error.FileNotFound, error.NotDir, @@ -432,6 +434,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { error.BadPathName => unreachable, // Windows only error.PipeBusy => unreachable, // Windows-only error.SharingViolation => unreachable, // Windows-only + error.NetworkNotFound => unreachable, // Windows-only error.FileLocksNotSupported => unreachable, // No lock requested. error.NoSpaceLeft => unreachable, // read-only error.PathAlreadyExists => unreachable, // read-only