clean up std/os related modules (#20651)
* clean up `std/os` related modules * use `cmpPaths` * reset * cleanup
This commit is contained in:
parent
daf35c6d1b
commit
69eaa4f14c
6 changed files with 140 additions and 157 deletions
|
|
@ -350,70 +350,6 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1", noWeirdTarget.} =
|
||||||
else:
|
else:
|
||||||
result = getLastModificationTime(a) > getLastModificationTime(b)
|
result = getLastModificationTime(a) > getLastModificationTime(b)
|
||||||
|
|
||||||
when defined(windows) and not weirdTarget:
|
|
||||||
proc openHandle(path: string, followSymlink=true, writeAccess=false): Handle =
|
|
||||||
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
|
|
||||||
if not followSymlink:
|
|
||||||
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
|
|
||||||
let access = if writeAccess: GENERIC_WRITE else: 0'i32
|
|
||||||
|
|
||||||
when useWinUnicode:
|
|
||||||
result = createFileW(
|
|
||||||
newWideCString(path), access,
|
|
||||||
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
|
||||||
nil, OPEN_EXISTING, flags, 0
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
result = createFileA(
|
|
||||||
path, access,
|
|
||||||
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
|
||||||
nil, OPEN_EXISTING, flags, 0
|
|
||||||
)
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
proc isAdmin*: bool {.noWeirdTarget.} =
|
proc isAdmin*: bool {.noWeirdTarget.} =
|
||||||
## Returns whether the caller's process is a member of the Administrators local
|
## Returns whether the caller's process is a member of the Administrators local
|
||||||
|
|
@ -447,7 +383,6 @@ proc isAdmin*: bool {.noWeirdTarget.} =
|
||||||
result = geteuid() == 0
|
result = geteuid() == 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc exitStatusLikeShell*(status: cint): cint =
|
proc exitStatusLikeShell*(status: cint): cint =
|
||||||
## Converts exit code from `c_system` into a shell exit code.
|
## Converts exit code from `c_system` into a shell exit code.
|
||||||
when defined(posix) and not weirdTarget:
|
when defined(posix) and not weirdTarget:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from paths import Path, ReadDirEffect, WriteDirEffect
|
from paths import Path, ReadDirEffect, WriteDirEffect
|
||||||
|
|
||||||
from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir,
|
from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir,
|
||||||
moveDir, walkPattern, walkFiles, walkDirs, walkDir,
|
moveDir, walkDir, setCurrentDir,
|
||||||
walkDirRec, PathComponent
|
walkDirRec, PathComponent
|
||||||
|
|
||||||
export PathComponent
|
export PathComponent
|
||||||
|
|
@ -76,51 +76,6 @@ proc moveDir*(source, dest: Path) {.inline, tags: [ReadIOEffect, WriteIOEffect].
|
||||||
## * `createDir proc`_
|
## * `createDir proc`_
|
||||||
moveDir(source.string, dest.string)
|
moveDir(source.string, dest.string)
|
||||||
|
|
||||||
iterator walkPattern*(pattern: Path): Path {.tags: [ReadDirEffect].} =
|
|
||||||
## Iterate over all the files and directories that match the `pattern`.
|
|
||||||
##
|
|
||||||
## On POSIX this uses the `glob`:idx: call.
|
|
||||||
## `pattern` is OS dependent, but at least the `"*.ext"`
|
|
||||||
## notation is supported.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `walkFiles iterator`_
|
|
||||||
## * `walkDirs iterator`_
|
|
||||||
## * `walkDir iterator`_
|
|
||||||
## * `walkDirRec iterator`_
|
|
||||||
for p in walkPattern(pattern.string):
|
|
||||||
yield Path(p)
|
|
||||||
|
|
||||||
iterator walkFiles*(pattern: Path): Path {.tags: [ReadDirEffect].} =
|
|
||||||
## Iterate over all the files that match the `pattern`.
|
|
||||||
##
|
|
||||||
## On POSIX this uses the `glob`:idx: call.
|
|
||||||
## `pattern` is OS dependent, but at least the `"*.ext"`
|
|
||||||
## notation is supported.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `walkPattern iterator`_
|
|
||||||
## * `walkDirs iterator`_
|
|
||||||
## * `walkDir iterator`_
|
|
||||||
## * `walkDirRec iterator`_
|
|
||||||
for p in walkFiles(pattern.string):
|
|
||||||
yield Path(p)
|
|
||||||
|
|
||||||
iterator walkDirs*(pattern: Path): Path {.tags: [ReadDirEffect].} =
|
|
||||||
## Iterate over all the directories that match the `pattern`.
|
|
||||||
##
|
|
||||||
## On POSIX this uses the `glob`:idx: call.
|
|
||||||
## `pattern` is OS dependent, but at least the `"*.ext"`
|
|
||||||
## notation is supported.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `walkPattern iterator`_
|
|
||||||
## * `walkFiles iterator`_
|
|
||||||
## * `walkDir iterator`_
|
|
||||||
## * `walkDirRec iterator`_
|
|
||||||
for p in walkDirs(pattern.string):
|
|
||||||
yield Path(p)
|
|
||||||
|
|
||||||
iterator walkDir*(dir: Path; relative = false, checkDir = false,
|
iterator walkDir*(dir: Path; relative = false, checkDir = false,
|
||||||
onlyRegular = false):
|
onlyRegular = false):
|
||||||
tuple[kind: PathComponent, path: Path] {.tags: [ReadDirEffect].} =
|
tuple[kind: PathComponent, path: Path] {.tags: [ReadDirEffect].} =
|
||||||
|
|
@ -179,3 +134,11 @@ iterator walkDirRec*(dir: Path,
|
||||||
for p in walkDirRec(dir.string, yieldFilter, followFilter, relative,
|
for p in walkDirRec(dir.string, yieldFilter, followFilter, relative,
|
||||||
checkDir, onlyRegular):
|
checkDir, onlyRegular):
|
||||||
yield Path(p)
|
yield Path(p)
|
||||||
|
|
||||||
|
proc setCurrentDir*(newDir: Path) {.inline, tags: [].} =
|
||||||
|
## Sets the `current working directory`:idx:; `OSError`
|
||||||
|
## is raised if `newDir` cannot been set.
|
||||||
|
##
|
||||||
|
## See also:
|
||||||
|
## * `getCurrentDir proc`_
|
||||||
|
osdirs.setCurrentDir(newDir.string)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import std/private/osseps
|
import std/private/osseps
|
||||||
export osseps
|
export osseps
|
||||||
|
|
||||||
|
import std/envvars
|
||||||
|
import std/private/osappdirs
|
||||||
|
|
||||||
import pathnorm
|
import pathnorm
|
||||||
|
|
||||||
from std/private/ospaths2 import joinPath, splitPath,
|
from std/private/ospaths2 import joinPath, splitPath,
|
||||||
|
|
@ -17,6 +20,13 @@ export ReadDirEffect, WriteDirEffect
|
||||||
type
|
type
|
||||||
Path* = distinct string
|
Path* = distinct string
|
||||||
|
|
||||||
|
func `==`*(x, y: Path): bool {.inline.} =
|
||||||
|
## Compares two paths.
|
||||||
|
##
|
||||||
|
## On a case-sensitive filesystem this is done
|
||||||
|
## case-sensitively otherwise case-insensitively.
|
||||||
|
result = cmpPaths(x.string, y.string) == 0
|
||||||
|
|
||||||
template endsWith(a: string, b: set[char]): bool =
|
template endsWith(a: string, b: set[char]): bool =
|
||||||
a.len > 0 and a[^1] in b
|
a.len > 0 and a[^1] in b
|
||||||
|
|
||||||
|
|
@ -208,17 +218,6 @@ func addFileExt*(filename: Path, ext: string): Path {.inline.} =
|
||||||
## * `changeFileExt proc`_
|
## * `changeFileExt proc`_
|
||||||
result = Path(addFileExt(filename.string, ext))
|
result = Path(addFileExt(filename.string, ext))
|
||||||
|
|
||||||
func cmpPaths*(pathA, pathB: Path): int {.inline.} =
|
|
||||||
## Compares two paths.
|
|
||||||
##
|
|
||||||
## On a case-sensitive filesystem this is done
|
|
||||||
## case-sensitively otherwise case-insensitively. Returns:
|
|
||||||
##
|
|
||||||
## | 0 if pathA == pathB
|
|
||||||
## | < 0 if pathA < pathB
|
|
||||||
## | > 0 if pathA > pathB
|
|
||||||
result = cmpPaths(pathA.string, pathB.string)
|
|
||||||
|
|
||||||
func unixToNativePath*(path: Path, drive=Path("")): Path {.inline.} =
|
func unixToNativePath*(path: Path, drive=Path("")): Path {.inline.} =
|
||||||
## Converts an UNIX-like path to a native one.
|
## Converts an UNIX-like path to a native one.
|
||||||
##
|
##
|
||||||
|
|
@ -246,14 +245,6 @@ proc getCurrentDir*(): Path {.inline, tags: [].} =
|
||||||
## * `getProjectPath proc <macros.html#getProjectPath>`_
|
## * `getProjectPath proc <macros.html#getProjectPath>`_
|
||||||
result = Path(ospaths2.getCurrentDir())
|
result = Path(ospaths2.getCurrentDir())
|
||||||
|
|
||||||
proc setCurrentDir*(newDir: Path) {.inline, tags: [].} =
|
|
||||||
## Sets the `current working directory`:idx:; `OSError`
|
|
||||||
## is raised if `newDir` cannot been set.
|
|
||||||
##
|
|
||||||
## See also:
|
|
||||||
## * `getCurrentDir proc`_
|
|
||||||
ospaths2.setCurrentDir(newDir.string)
|
|
||||||
|
|
||||||
proc normalizeExe*(file: var Path) {.borrow.}
|
proc normalizeExe*(file: var Path) {.borrow.}
|
||||||
|
|
||||||
proc normalizePath*(path: var Path) {.borrow.}
|
proc normalizePath*(path: var Path) {.borrow.}
|
||||||
|
|
@ -268,3 +259,29 @@ proc absolutePath*(path: Path, root = getCurrentDir()): Path =
|
||||||
## See also:
|
## See also:
|
||||||
## * `normalizePath proc`_
|
## * `normalizePath proc`_
|
||||||
result = Path(absolutePath(path.string, root.string))
|
result = Path(absolutePath(path.string, root.string))
|
||||||
|
|
||||||
|
proc expandTildeImpl(path: string): string {.
|
||||||
|
tags: [ReadEnvEffect, ReadIOEffect].} =
|
||||||
|
if len(path) == 0 or path[0] != '~':
|
||||||
|
result = path
|
||||||
|
elif len(path) == 1:
|
||||||
|
result = getHomeDir()
|
||||||
|
elif (path[1] in {DirSep, AltSep}):
|
||||||
|
result = joinPath(getHomeDir(), path.substr(2))
|
||||||
|
else:
|
||||||
|
# TODO: handle `~bob` and `~bob/` which means home of bob
|
||||||
|
result = path
|
||||||
|
|
||||||
|
proc expandTilde*(path: Path): Path {.inline,
|
||||||
|
tags: [ReadEnvEffect, ReadIOEffect].} =
|
||||||
|
## Expands ``~`` or a path starting with ``~/`` to a full path, replacing
|
||||||
|
## ``~`` with `getHomeDir()`_ (otherwise returns ``path`` unmodified).
|
||||||
|
##
|
||||||
|
## Windows: this is still supported despite the Windows platform not having this
|
||||||
|
## convention; also, both ``~/`` and ``~\`` are handled.
|
||||||
|
runnableExamples:
|
||||||
|
import std/appdirs
|
||||||
|
assert expandTilde(Path("~") / Path("appname.cfg")) == getHomeDir() / Path("appname.cfg")
|
||||||
|
assert expandTilde(Path("~/foo/bar")) == getHomeDir() / Path("foo/bar")
|
||||||
|
assert expandTilde(Path("/foo/bar")) == Path("/foo/bar")
|
||||||
|
result = Path(expandTildeImpl(path.string))
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
include system/inclrtl
|
include system/inclrtl
|
||||||
|
|
||||||
import ospaths2
|
|
||||||
import std/[oserrors]
|
import std/[oserrors]
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
|
|
@ -9,6 +8,15 @@ when defined(nimPreviewSlimSystem):
|
||||||
const weirdTarget* = defined(nimscript) or defined(js)
|
const weirdTarget* = defined(nimscript) or defined(js)
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
when weirdTarget:
|
when weirdTarget:
|
||||||
discard
|
discard
|
||||||
elif defined(windows):
|
elif defined(windows):
|
||||||
|
|
@ -181,3 +189,23 @@ proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
|
||||||
else:
|
else:
|
||||||
var res: Stat
|
var res: Stat
|
||||||
result = lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
|
result = lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
|
||||||
|
|
||||||
|
when defined(windows) and not weirdTarget:
|
||||||
|
proc openHandle*(path: string, followSymlink=true, writeAccess=false): Handle =
|
||||||
|
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
|
||||||
|
if not followSymlink:
|
||||||
|
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
|
||||||
|
let access = if writeAccess: GENERIC_WRITE else: 0'i32
|
||||||
|
|
||||||
|
when useWinUnicode:
|
||||||
|
result = createFileW(
|
||||||
|
newWideCString(path), access,
|
||||||
|
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
||||||
|
nil, OPEN_EXISTING, flags, 0
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
result = createFileA(
|
||||||
|
path, access,
|
||||||
|
FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
|
||||||
|
nil, OPEN_EXISTING, flags, 0
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -548,3 +548,21 @@ proc moveDir*(source, dest: string) {.tags: [ReadIOEffect, WriteIOEffect], noWei
|
||||||
# Fallback to copy & del
|
# Fallback to copy & del
|
||||||
copyDir(source, dest)
|
copyDir(source, dest)
|
||||||
removeDir(source)
|
removeDir(source)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ import std/private/since
|
||||||
import strutils, pathnorm
|
import strutils, pathnorm
|
||||||
import std/oserrors
|
import std/oserrors
|
||||||
|
|
||||||
|
import oscommon
|
||||||
|
export ReadDirEffect, WriteDirEffect
|
||||||
|
|
||||||
when defined(nimPreviewSlimSystem):
|
when defined(nimPreviewSlimSystem):
|
||||||
import std/[syncio, assertions, widestrs]
|
import std/[syncio, assertions, widestrs]
|
||||||
|
|
||||||
|
|
@ -34,13 +37,6 @@ else:
|
||||||
|
|
||||||
proc normalizePathAux(path: var string){.inline, raises: [], noSideEffect.}
|
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
|
import std/private/osseps
|
||||||
export osseps
|
export osseps
|
||||||
|
|
@ -891,25 +887,6 @@ when not defined(nimscript):
|
||||||
else:
|
else:
|
||||||
raiseOSError(osLastError())
|
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 =
|
proc absolutePath*(path: string, root = getCurrentDir()): string =
|
||||||
## Returns the absolute path of `path`, rooted at `root` (which must be absolute;
|
## Returns the absolute path of `path`, rooted at `root` (which must be absolute;
|
||||||
## default: current directory).
|
## default: current directory).
|
||||||
|
|
@ -1004,3 +981,48 @@ proc normalizeExe*(file: var string) {.since: (1, 3, 5).} =
|
||||||
when defined(posix):
|
when defined(posix):
|
||||||
if file.len > 0 and DirSep notin file and file != "." and file != "..":
|
if file.len > 0 and DirSep notin file and file != "." and file != "..":
|
||||||
file = "./" & 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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue