aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--core/os/os2/path_windows.odin6
-rw-r--r--core/os/os2/stat_windows.odin80
-rw-r--r--tests/core/os/os2/path.odin85
-rw-r--r--tests/core/os/os2/process.odin1
5 files changed, 108 insertions, 65 deletions
diff --git a/.gitignore b/.gitignore
index 254731c96..1187596de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -294,4 +294,5 @@ build.sh
# RAD debugger project file
*.raddbg
*.rdi
+tests/issues/build/*
misc/featuregen/featuregen
diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin
index 9c0fec9b9..c2e51040f 100644
--- a/core/os/os2/path_windows.odin
+++ b/core/os/os2/path_windows.odin
@@ -187,7 +187,6 @@ init_long_path_support :: proc() {
if value == 1 {
can_use_long_paths = true
}
-
}
@(require_results)
@@ -271,6 +270,11 @@ _clean_path_handle_start :: proc(path: string, buffer: []u8) -> (rooted: bool, s
start += 1
}
copy(buffer, path[:start])
+ for n in 0..<start {
+ if _is_path_separator(buffer[n]) {
+ buffer[n] = _Path_Separator
+ }
+ }
}
return
}
diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin
index 918c86f76..af84e1443 100644
--- a/core/os/os2/stat_windows.odin
+++ b/core/os/os2/stat_windows.odin
@@ -329,42 +329,68 @@ _is_reserved_name :: proc(path: string) -> bool {
return false
}
-_is_UNC :: proc(path: string) -> bool {
- return _volume_name_len(path) > 2
-}
-
-_volume_name_len :: proc(path: string) -> int {
+_volume_name_len :: proc(path: string) -> (length: int) {
if len(path) < 2 {
return 0
}
- c := path[0]
+
if path[1] == ':' {
- switch c {
+ switch path[0] {
case 'a'..='z', 'A'..='Z':
return 2
}
}
- // URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
- if l := len(path); l >= 5 && _is_path_separator(path[0]) && _is_path_separator(path[1]) &&
- !_is_path_separator(path[2]) && path[2] != '.' {
- for n := 3; n < l-1; n += 1 {
- if _is_path_separator(path[n]) {
- n += 1
- if !_is_path_separator(path[n]) {
- if path[n] == '.' {
- break
- }
- }
- for ; n < l; n += 1 {
- if _is_path_separator(path[n]) {
- break
- }
- }
- return n
+ /*
+ See: URL: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
+ Further allowed paths can be of the form of:
+ - \\server\share or \\server\share\more\path
+ - \\?\C:\...
+ - \\.\PhysicalDriveX
+ */
+ // Any remaining kind of path has to start with two slashes.
+ if !_is_path_separator(path[0]) || !_is_path_separator(path[1]) {
+ return 0
+ }
+
+ // Device path. The volume name is the whole string
+ if len(path) >= 5 && path[2] == '.' && _is_path_separator(path[3]) {
+ return len(path)
+ }
+
+ // We're a UNC share `\\host\share`, file namespace `\\?\C:` or UNC in file namespace `\\?\\host\share`
+ prefix := 2
+
+ // File namespace.
+ if len(path) >= 5 && path[2] == '?' && _is_path_separator(path[3]) {
+ if _is_path_separator(path[4]) {
+ // `\\?\\` UNC path in file namespace
+ prefix = 5
+ }
+
+ if len(path) >= 6 && path[5] == ':' {
+ switch path[4] {
+ case 'a'..='z', 'A'..='Z':
+ return 6
+ case:
+ return 0
}
- break
}
}
- return 0
-}
+
+ // UNC path, minimum version of the volume is `\\h\s` for host, share.
+ // Can also contain an IP address in the host position.
+ slash_count := 0
+ for i in prefix..<len(path) {
+ // Host needs to be at least 1 character
+ if _is_path_separator(path[i]) && i > 0 {
+ slash_count += 1
+
+ if slash_count == 2 {
+ return i
+ }
+ }
+ }
+
+ return len(path)
+} \ No newline at end of file
diff --git a/tests/core/os/os2/path.odin b/tests/core/os/os2/path.odin
index 2cf1f1f1c..7b1cb0146 100644
--- a/tests/core/os/os2/path.odin
+++ b/tests/core/os/os2/path.odin
@@ -36,47 +36,58 @@ posix_to_dos_path :: proc(path: string) -> string {
@(test)
test_clean_path :: proc(t: ^testing.T) {
Test_Case :: struct{
- path: string,
+ path: string,
expected: string,
}
- test_cases := [?]Test_Case {
- {`../../foo/../../`, `../../..`},
- {`../../foo/..`, `../..`},
- {`../../foo`, `../../foo`},
- {`../..`, `../..`},
- {`.././foo`, `../foo`},
- {`..`, `..`},
- {`.`, `.`},
- {`.foo`, `.foo`},
- {`/../../foo/../../`, `/`},
- {`/../`, `/`},
- {`/..`, `/`},
- {`/`, `/`},
- {`//home/foo/bar/../../`, `/home`},
- {`/a/../..`, `/`},
- {`/a/../`, `/`},
- {`/a/あ`, `/a/あ`},
- {`/a/あ/..`, `/a`},
- {`/あ/a/..`, `/あ`},
- {`/あ/a/../あ`, `/あ/あ`},
- {`/home/../`, `/`},
- {`/home/..`, `/`},
- {`/home/foo/../../usr`, `/usr`},
- {`/home/foo/../..`, `/`},
- {`/home/foo/../`, `/home`},
- {``, `.`},
- {`a/..`, `.`},
- {`a`, `a`},
- {`abc//.//../foo`, `foo`},
- {`foo`, `foo`},
- {`home/foo/bar/../../`, `home`},
- }
-
when ODIN_OS == .Windows {
- for &tc in test_cases {
- tc.path = posix_to_dos_path(tc.path)
- tc.expected = posix_to_dos_path(tc.expected)
+ test_cases := [?]Test_Case {
+ {`W:/odin\examples\demo/demo.odin`, `W:\odin\examples\demo\demo.odin`},
+ {`\\server\share\path\file.ext`, `\\server\share\path\file.ext`},
+ {`//server\share/path\file.ext`, `\\server\share\path\file.ext`},
+ {`/\192.168.0.10\share/path\file.ext`, `\\192.168.0.10\share\path\file.ext`},
+ {`\\?\C:/Users/Foo/path\file.ext`, `\\?\C:\Users\Foo\path\file.ext`},
+ {`\\?\\localhost\share\file.ext`, `\\?\\localhost\share\file.ext`},
+ {`//?\/192.168.0.10\share\file.ext`, `\\?\\192.168.0.10\share\file.ext`},
+ {`\\.\PhysicalDrive3`, `\\.\PhysicalDrive3`},
+ {`/\./PhysicalDrive3`, `\\.\PhysicalDrive3`},
+ {`C:\a\..\..`, `C:\`},
+ {`C:\a\..`, `C:\`},
+ {`C:\あ/a/..`, `C:\あ`},
+ {`C:\あ/a/../あ`, `C:\あ\あ`},
+ }
+ } else {
+ test_cases := [?]Test_Case {
+ {`../../foo/../../`, `../../..`},
+ {`../../foo/..`, `../..`},
+ {`../../foo`, `../../foo`},
+ {`../..`, `../..`},
+ {`.././foo`, `../foo`},
+ {`..`, `..`},
+ {`.`, `.`},
+ {`.foo`, `.foo`},
+ {`/../../foo/../../`, `/`},
+ {`/../`, `/`},
+ {`/..`, `/`},
+ {`/`, `/`},
+ {`//home/foo/bar/../../`, `/home`},
+ {`/a/../..`, `/`},
+ {`/a/../`, `/`},
+ {`/a/あ`, `/a/あ`},
+ {`/a/あ/..`, `/a`},
+ {`/あ/a/..`, `/あ`},
+ {`/あ/a/../あ`, `/あ/あ`},
+ {`/home/../`, `/`},
+ {`/home/..`, `/`},
+ {`/home/foo/../../usr`, `/usr`},
+ {`/home/foo/../..`, `/`},
+ {`/home/foo/../`, `/home`},
+ {``, `.`},
+ {`a/..`, `.`},
+ {`a`, `a`},
+ {`abc//.//../foo`, `foo`},
+ {`foo`, `foo`},
+ {`home/foo/bar/../../`, `home`},
}
}
diff --git a/tests/core/os/os2/process.odin b/tests/core/os/os2/process.odin
index d7700d201..c530b4c79 100644
--- a/tests/core/os/os2/process.odin
+++ b/tests/core/os/os2/process.odin
@@ -1,3 +1,4 @@
+#+build !windows
package tests_core_os_os2
import os "core:os/os2"