| ... | @@ -2343,25 +2343,26 @@ pub const NamespacePrefix = enum { | ... | @@ -2343,25 +2343,26 @@ pub const NamespacePrefix = enum { |
| 2343 | nt, | 2343 | nt, |
| 2344 | }; | 2344 | }; |
| 2345 | | 2345 | |
| | 2346 | /// If `T` is `u16`, then `path` should be encoded as UTF-16LE. |
| 2346 | pub fn getNamespacePrefix(comptime T: type, path: []const T) NamespacePrefix { | 2347 | pub fn getNamespacePrefix(comptime T: type, path: []const T) NamespacePrefix { |
| 2347 | if (path.len < 4) return .none; | 2348 | if (path.len < 4) return .none; |
| 2348 | var all_backslash = switch (path[0]) { | 2349 | var all_backslash = switch (mem.littleToNative(T, path[0])) { |
| 2349 | '\\' => true, | 2350 | '\\' => true, |
| 2350 | '/' => false, | 2351 | '/' => false, |
| 2351 | else => return .none, | 2352 | else => return .none, |
| 2352 | }; | 2353 | }; |
| 2353 | all_backslash = all_backslash and switch (path[3]) { | 2354 | all_backslash = all_backslash and switch (mem.littleToNative(T, path[3])) { |
| 2354 | '\\' => true, | 2355 | '\\' => true, |
| 2355 | '/' => false, | 2356 | '/' => false, |
| 2356 | else => return .none, | 2357 | else => return .none, |
| 2357 | }; | 2358 | }; |
| 2358 | switch (path[1]) { | 2359 | switch (mem.littleToNative(T, path[1])) { |
| 2359 | '?' => if (path[2] == '?' and all_backslash) return .nt else return .none, | 2360 | '?' => if (mem.littleToNative(T, path[2]) == '?' and all_backslash) return .nt else return .none, |
| 2360 | '\\' => {}, | 2361 | '\\' => {}, |
| 2361 | '/' => all_backslash = false, | 2362 | '/' => all_backslash = false, |
| 2362 | else => return .none, | 2363 | else => return .none, |
| 2363 | } | 2364 | } |
| 2364 | return switch (path[2]) { | 2365 | return switch (mem.littleToNative(T, path[2])) { |
| 2365 | '?' => if (all_backslash) .verbatim else .fake_verbatim, | 2366 | '?' => if (all_backslash) .verbatim else .fake_verbatim, |
| 2366 | '.' => .local_device, | 2367 | '.' => .local_device, |
| 2367 | else => .none, | 2368 | else => .none, |
| ... | @@ -2396,6 +2397,7 @@ pub const UnprefixedPathType = enum { | ... | @@ -2396,6 +2397,7 @@ pub const UnprefixedPathType = enum { |
| 2396 | | 2397 | |
| 2397 | /// Get the path type of a path that is known to not have any namespace prefixes | 2398 | /// Get the path type of a path that is known to not have any namespace prefixes |
| 2398 | /// (`\\?\`, `\\.\`, `\??\`). | 2399 | /// (`\\?\`, `\\.\`, `\??\`). |
| | 2400 | /// If `T` is `u16`, then `path` should be encoded as UTF-16LE. |
| 2399 | pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathType { | 2401 | pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathType { |
| 2400 | if (path.len < 1) return .relative; | 2402 | if (path.len < 1) return .relative; |
| 2401 | | 2403 | |
| ... | @@ -2404,18 +2406,18 @@ pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathTy | ... | @@ -2404,18 +2406,18 @@ pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathTy |
| 2404 | } | 2406 | } |
| 2405 | | 2407 | |
| 2406 | const windows_path = std.fs.path.PathType.windows; | 2408 | const windows_path = std.fs.path.PathType.windows; |
| 2407 | if (windows_path.isSep(T, path[0])) { | 2409 | if (windows_path.isSep(T, mem.littleToNative(T, path[0]))) { |
| 2408 | // \x | 2410 | // \x |
| 2409 | if (path.len < 2 or !windows_path.isSep(T, path[1])) return .rooted; | 2411 | if (path.len < 2 or !windows_path.isSep(T, mem.littleToNative(T, path[1]))) return .rooted; |
| 2410 | // exactly \\. or \\? with nothing trailing | 2412 | // exactly \\. or \\? with nothing trailing |
| 2411 | if (path.len == 3 and (path[2] == '.' or path[2] == '?')) return .root_local_device; | 2413 | if (path.len == 3 and (mem.littleToNative(T, path[2]) == '.' or mem.littleToNative(T, path[2]) == '?')) return .root_local_device; |
| 2412 | // \\x | 2414 | // \\x |
| 2413 | return .unc_absolute; | 2415 | return .unc_absolute; |
| 2414 | } else { | 2416 | } else { |
| 2415 | // x | 2417 | // x |
| 2416 | if (path.len < 2 or path[1] != ':') return .relative; | 2418 | if (path.len < 2 or mem.littleToNative(T, path[1]) != ':') return .relative; |
| 2417 | // x:\ | 2419 | // x:\ |
| 2418 | if (path.len > 2 and windows_path.isSep(T, path[2])) return .drive_absolute; | 2420 | if (path.len > 2 and windows_path.isSep(T, mem.littleToNative(T, path[2]))) return .drive_absolute; |
| 2419 | // x: | 2421 | // x: |
| 2420 | return .drive_relative; | 2422 | return .drive_relative; |
| 2421 | } | 2423 | } |
| ... | @@ -2448,6 +2450,8 @@ test getUnprefixedPathType { | ... | @@ -2448,6 +2450,8 @@ test getUnprefixedPathType { |
| 2448 | /// | 2450 | /// |
| 2449 | /// Functionality is based on the ReactOS test cases found here: | 2451 | /// Functionality is based on the ReactOS test cases found here: |
| 2450 | /// https://github.com/reactos/reactos/blob/master/modules/rostests/apitests/ntdll/RtlNtPathNameToDosPathName.c | 2452 | /// https://github.com/reactos/reactos/blob/master/modules/rostests/apitests/ntdll/RtlNtPathNameToDosPathName.c |
| | 2453 | /// |
| | 2454 | /// `path` should be encoded as UTF-16LE. |
| 2451 | pub fn ntToWin32Namespace(path: []const u16) !PathSpace { | 2455 | pub fn ntToWin32Namespace(path: []const u16) !PathSpace { |
| 2452 | if (path.len > PATH_MAX_WIDE) return error.NameTooLong; | 2456 | if (path.len > PATH_MAX_WIDE) return error.NameTooLong; |
| 2453 | | 2457 | |
| ... | @@ -2463,9 +2467,11 @@ pub fn ntToWin32Namespace(path: []const u16) !PathSpace { | ... | @@ -2463,9 +2467,11 @@ pub fn ntToWin32Namespace(path: []const u16) !PathSpace { |
| 2463 | // it's unlikely to matter since most/all paths passed into this | 2467 | // it's unlikely to matter since most/all paths passed into this |
| 2464 | // function will have come from the OS meaning it should have | 2468 | // function will have come from the OS meaning it should have |
| 2465 | // the 'canonical' uppercase UNC. | 2469 | // the 'canonical' uppercase UNC. |
| 2466 | const is_unc = after_prefix.len >= 4 and std.mem.eql(u16, after_prefix[0..3], std.unicode.utf8ToUtf16LeStringLiteral("UNC")) and std.fs.path.PathType.windows.isSep(u16, after_prefix[3]); | 2470 | const is_unc = after_prefix.len >= 4 and |
| | 2471 | std.mem.eql(u16, after_prefix[0..3], std.unicode.utf8ToUtf16LeStringLiteral("UNC")) and |
| | 2472 | std.fs.path.PathType.windows.isSep(u16, std.mem.littleToNative(u16, after_prefix[3])); |
| 2467 | if (is_unc) { | 2473 | if (is_unc) { |
| 2468 | path_space.data[0] = '\\'; | 2474 | path_space.data[0] = comptime std.mem.nativeToLittle(u16, '\\'); |
| 2469 | dest_index += 1; | 2475 | dest_index += 1; |
| 2470 | // We want to include the last `\` of `\??\UNC\` | 2476 | // We want to include the last `\` of `\??\UNC\` |
| 2471 | after_prefix = path[7..]; | 2477 | after_prefix = path[7..]; |