| ... | ... | @@ -2343,25 +2343,26 @@ pub const NamespacePrefix = enum { |
| 2343 | 2343 | nt, |
| 2344 | 2344 | }; |
| 2345 | 2345 | |
| 2346 | /// If `T` is `u16`, then `path` should be encoded as UTF-16LE. |
| 2346 | 2347 | pub fn getNamespacePrefix(comptime T: type, path: []const T) NamespacePrefix { |
| 2347 | 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 | 2350 | '\\' => true, |
| 2350 | 2351 | '/' => false, |
| 2351 | 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 | 2355 | '\\' => true, |
| 2355 | 2356 | '/' => false, |
| 2356 | 2357 | else => return .none, |
| 2357 | 2358 | }; |
| 2358 | | switch (path[1]) { |
| 2359 | | '?' => if (path[2] == '?' and all_backslash) return .nt else return .none, |
| 2359 | switch (mem.littleToNative(T, path[1])) { |
| 2360 | '?' => if (mem.littleToNative(T, path[2]) == '?' and all_backslash) return .nt else return .none, |
| 2360 | 2361 | '\\' => {}, |
| 2361 | 2362 | '/' => all_backslash = false, |
| 2362 | 2363 | else => return .none, |
| 2363 | 2364 | } |
| 2364 | | return switch (path[2]) { |
| 2365 | return switch (mem.littleToNative(T, path[2])) { |
| 2365 | 2366 | '?' => if (all_backslash) .verbatim else .fake_verbatim, |
| 2366 | 2367 | '.' => .local_device, |
| 2367 | 2368 | else => .none, |
| ... | ... | @@ -2396,6 +2397,7 @@ pub const UnprefixedPathType = enum { |
| 2396 | 2397 | |
| 2397 | 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 | 2401 | pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathType { |
| 2400 | 2402 | if (path.len < 1) return .relative; |
| 2401 | 2403 | |
| ... | ... | @@ -2404,18 +2406,18 @@ pub fn getUnprefixedPathType(comptime T: type, path: []const T) UnprefixedPathTy |
| 2404 | 2406 | } |
| 2405 | 2407 | |
| 2406 | 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 | 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 | 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 | 2414 | // \\x |
| 2413 | 2415 | return .unc_absolute; |
| 2414 | 2416 | } else { |
| 2415 | 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 | 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 | 2421 | // x: |
| 2420 | 2422 | return .drive_relative; |
| 2421 | 2423 | } |
| ... | ... | @@ -2448,6 +2450,8 @@ test getUnprefixedPathType { |
| 2448 | 2450 | /// |
| 2449 | 2451 | /// Functionality is based on the ReactOS test cases found here: |
| 2450 | 2452 | /// https://github.com/reactos/reactos/blob/master/modules/rostests/apitests/ntdll/RtlNtPathNameToDosPathName.c |
| 2453 | /// |
| 2454 | /// `path` should be encoded as UTF-16LE. |
| 2451 | 2455 | pub fn ntToWin32Namespace(path: []const u16) !PathSpace { |
| 2452 | 2456 | if (path.len > PATH_MAX_WIDE) return error.NameTooLong; |
| 2453 | 2457 | |
| ... | ... | @@ -2463,9 +2467,11 @@ pub fn ntToWin32Namespace(path: []const u16) !PathSpace { |
| 2463 | 2467 | // it's unlikely to matter since most/all paths passed into this |
| 2464 | 2468 | // function will have come from the OS meaning it should have |
| 2465 | 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 | 2473 | if (is_unc) { |
| 2468 | | path_space.data[0] = '\\'; |
| 2474 | path_space.data[0] = comptime std.mem.nativeToLittle(u16, '\\'); |
| 2469 | 2475 | dest_index += 1; |
| 2470 | 2476 | // We want to include the last `\` of `\??\UNC\` |
| 2471 | 2477 | after_prefix = path[7..]; |