summary refs log tree commit diff stats
path: root/lib/std/private/ospaths2.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/private/ospaths2.nim')
-rw-r--r--lib/std/private/ospaths2.nim74
1 files changed, 48 insertions, 26 deletions
diff --git a/lib/std/private/ospaths2.nim b/lib/std/private/ospaths2.nim
index 8092549d8..75c34ecf5 100644
--- a/lib/std/private/ospaths2.nim
+++ b/lib/std/private/ospaths2.nim
@@ -4,6 +4,9 @@ import std/private/since
 import strutils, pathnorm
 import std/oserrors
 
+import oscommon
+export ReadDirEffect, WriteDirEffect
+
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions, widestrs]
 
@@ -34,13 +37,6 @@ else:
 
 proc normalizePathAux(path: var string){.inline, raises: [], noSideEffect.}
 
-type
-  ReadDirEffect* = object of ReadIOEffect   ## Effect that denotes a read
-                                            ## operation from the directory
-                                            ## structure.
-  WriteDirEffect* = object of WriteIOEffect ## Effect that denotes a write
-                                            ## operation to
-                                            ## the directory structure.
 
 import std/private/osseps
 export osseps
@@ -891,25 +887,6 @@ when not defined(nimscript):
           else:
             raiseOSError(osLastError())
 
-proc setCurrentDir*(newDir: string) {.inline, tags: [], noWeirdTarget.} =
-  ## Sets the `current working directory`:idx:; `OSError`
-  ## is raised if `newDir` cannot been set.
-  ##
-  ## See also:
-  ## * `getHomeDir proc`_
-  ## * `getConfigDir proc`_
-  ## * `getTempDir proc`_
-  ## * `getCurrentDir proc`_
-  when defined(windows):
-    when useWinUnicode:
-      if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
-        raiseOSError(osLastError(), newDir)
-    else:
-      if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError(), newDir)
-  else:
-    if chdir(newDir) != 0'i32: raiseOSError(osLastError(), newDir)
-
-
 proc absolutePath*(path: string, root = getCurrentDir()): string =
   ## Returns the absolute path of `path`, rooted at `root` (which must be absolute;
   ## default: current directory).
@@ -1004,3 +981,48 @@ proc normalizeExe*(file: var string) {.since: (1, 3, 5).} =
   when defined(posix):
     if file.len > 0 and DirSep notin file and file != "." and file != "..":
       file = "./" & file
+
+proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
+  tags: [ReadDirEffect], noWeirdTarget.} =
+  ## Returns true if both pathname arguments refer to the same physical
+  ## file or directory.
+  ##
+  ## Raises `OSError` if any of the files does not
+  ## exist or information about it can not be obtained.
+  ##
+  ## This proc will return true if given two alternative hard-linked or
+  ## sym-linked paths to the same file or directory.
+  ##
+  ## See also:
+  ## * `sameFileContent proc`_
+  when defined(windows):
+    var success = true
+    var f1 = openHandle(path1)
+    var f2 = openHandle(path2)
+
+    var lastErr: OSErrorCode
+    if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE:
+      var fi1, fi2: BY_HANDLE_FILE_INFORMATION
+
+      if getFileInformationByHandle(f1, addr(fi1)) != 0 and
+         getFileInformationByHandle(f2, addr(fi2)) != 0:
+        result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and
+                 fi1.nFileIndexHigh == fi2.nFileIndexHigh and
+                 fi1.nFileIndexLow == fi2.nFileIndexLow
+      else:
+        lastErr = osLastError()
+        success = false
+    else:
+      lastErr = osLastError()
+      success = false
+
+    discard closeHandle(f1)
+    discard closeHandle(f2)
+
+    if not success: raiseOSError(lastErr, $(path1, path2))
+  else:
+    var a, b: Stat
+    if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
+      raiseOSError(osLastError(), $(path1, path2))
+    else:
+      result = a.st_dev == b.st_dev and a.st_ino == b.st_ino