Commit 9a3adeea6e

Ryan Liptak <squeek502@hotmail.com>
2023-07-26 23:41:53
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.
1 parent 0f21d3d
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 {
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);
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
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
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,
                     }
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;