Merge pull request #861 from Varriount/os/add-linkprocs-prettyplease
Added symlink procs
This commit is contained in:
commit
20cf73669d
2 changed files with 89 additions and 3 deletions
|
|
@ -287,12 +287,18 @@ proc osLastError*(): TOSErrorCode =
|
||||||
result = TOSErrorCode(errno)
|
result = TOSErrorCode(errno)
|
||||||
{.pop.}
|
{.pop.}
|
||||||
|
|
||||||
proc unixToNativePath*(path: string): string {.
|
proc unixToNativePath*(path: string, drive=""): string {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Converts an UNIX-like path to a native one.
|
## Converts an UNIX-like path to a native one.
|
||||||
##
|
##
|
||||||
## On an UNIX system this does nothing. Else it converts
|
## On an UNIX system this does nothing. Else it converts
|
||||||
## '/', '.', '..' to the appropriate things.
|
## '/', '.', '..' to the appropriate things.
|
||||||
|
##
|
||||||
|
## On systems with a concept of "drives", `drive` is used to determine
|
||||||
|
## which drive label to use during absolute path conversion.
|
||||||
|
## `drive` defaults to the drive of the current working directory, and is
|
||||||
|
## ignored on systems that do not have a concept of "drives".
|
||||||
|
|
||||||
when defined(unix):
|
when defined(unix):
|
||||||
result = path
|
result = path
|
||||||
else:
|
else:
|
||||||
|
|
@ -300,7 +306,10 @@ proc unixToNativePath*(path: string): string {.
|
||||||
if path[0] == '/':
|
if path[0] == '/':
|
||||||
# an absolute path
|
# an absolute path
|
||||||
when doslike:
|
when doslike:
|
||||||
result = r"C:\"
|
if drive != "":
|
||||||
|
result = drive & ":" & DirSep
|
||||||
|
else:
|
||||||
|
result = $DirSep
|
||||||
elif defined(macos):
|
elif defined(macos):
|
||||||
result = "" # must not start with ':'
|
result = "" # must not start with ':'
|
||||||
else:
|
else:
|
||||||
|
|
@ -387,6 +396,21 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
|
||||||
var res: TStat
|
var res: TStat
|
||||||
return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
|
return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
|
||||||
|
|
||||||
|
proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
|
||||||
|
tags: [FReadDir].} =
|
||||||
|
## Returns true iff the symlink `link` exists. Will return true
|
||||||
|
## regardless of whether the link points to a directory or file.
|
||||||
|
when defined(windows):
|
||||||
|
when useWinUnicode:
|
||||||
|
wrapUnary(a, GetFileAttributesW, link)
|
||||||
|
else:
|
||||||
|
var a = GetFileAttributesA(link)
|
||||||
|
if a != -1'i32:
|
||||||
|
result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
|
||||||
|
else:
|
||||||
|
var res: TStat
|
||||||
|
return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
|
||||||
|
|
||||||
proc fileExists*(filename: string): bool {.inline.} =
|
proc fileExists*(filename: string): bool {.inline.} =
|
||||||
## Synonym for existsFile
|
## Synonym for existsFile
|
||||||
existsFile(filename)
|
existsFile(filename)
|
||||||
|
|
@ -1221,6 +1245,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
|
||||||
if not skipFindData(f):
|
if not skipFindData(f):
|
||||||
if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
|
if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
|
||||||
k = pcDir
|
k = pcDir
|
||||||
|
if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||||
|
k = succ(k)
|
||||||
yield (k, dir / extractFilename(getFilename(f)))
|
yield (k, dir / extractFilename(getFilename(f)))
|
||||||
if findNextFile(h, f) == 0'i32: break
|
if findNextFile(h, f) == 0'i32: break
|
||||||
findClose(h)
|
findClose(h)
|
||||||
|
|
@ -1245,6 +1271,10 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
|
||||||
tags: [FReadDir].} =
|
tags: [FReadDir].} =
|
||||||
## walks over the directory `dir` and yields for each file in `dir`. The
|
## walks over the directory `dir` and yields for each file in `dir`. The
|
||||||
## full path for each file is returned.
|
## full path for each file is returned.
|
||||||
|
## **Warning**:
|
||||||
|
## Modifying the directory structure while the iterator
|
||||||
|
## is traversing may result in undefined behavior!
|
||||||
|
##
|
||||||
## Walking is recursive. `filter` controls the behaviour of the iterator:
|
## Walking is recursive. `filter` controls the behaviour of the iterator:
|
||||||
##
|
##
|
||||||
## --------------------- ---------------------------------------------
|
## --------------------- ---------------------------------------------
|
||||||
|
|
@ -1336,6 +1366,46 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
|
||||||
copyDir(path, dest / noSource)
|
copyDir(path, dest / noSource)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
proc createSymlink*(src, dest: string) =
|
||||||
|
## Create a symbolic link at `dest` which points to the item specified
|
||||||
|
## by `src`. On most operating systems, will fail if a lonk
|
||||||
|
##
|
||||||
|
## **Warning**:
|
||||||
|
## Some OS's (such as Microsoft Windows) restrict the creation
|
||||||
|
## of symlinks to root users (administrators).
|
||||||
|
when defined(Windows):
|
||||||
|
let flag = dirExists(src).int32
|
||||||
|
when useWinUnicode:
|
||||||
|
var wSrc = newWideCString(src)
|
||||||
|
var wDst = newWideCString(dest)
|
||||||
|
if CreateSymbolicLinkW(wDst, wSrc, flag) == 0 or GetLastError() != 0:
|
||||||
|
osError(osLastError())
|
||||||
|
else:
|
||||||
|
if CreateSymbolicLinkA(dest, src, flag) == 0 or GetLastError() != 0:
|
||||||
|
osError(osLastError())
|
||||||
|
else:
|
||||||
|
if symlink(src, dest) != 0:
|
||||||
|
OSError(OSLastError())
|
||||||
|
|
||||||
|
proc createHardlink*(src, dest: string) =
|
||||||
|
## Create a hard link at `dest` which points to the item specified
|
||||||
|
## by `src`.
|
||||||
|
##
|
||||||
|
## **Warning**: Most OS's restrict the creation of hard links to
|
||||||
|
## root users (administrators) .
|
||||||
|
when defined(Windows):
|
||||||
|
when useWinUnicode:
|
||||||
|
var wSrc = newWideCString(src)
|
||||||
|
var wDst = newWideCString(dest)
|
||||||
|
if createHardLinkW(wDst, wSrc, nil) == 0:
|
||||||
|
OSError(OSLastError())
|
||||||
|
else:
|
||||||
|
if createHardLinkA(dest, src, nil) == 0:
|
||||||
|
OSError(OSLastError())
|
||||||
|
else:
|
||||||
|
if link(src, dest) != 0:
|
||||||
|
OSError(OSLastError())
|
||||||
|
|
||||||
proc parseCmdLine*(c: string): seq[string] {.
|
proc parseCmdLine*(c: string): seq[string] {.
|
||||||
noSideEffect, rtl, extern: "nos$1".} =
|
noSideEffect, rtl, extern: "nos$1".} =
|
||||||
## Splits a command line into several components;
|
## Splits a command line into several components;
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,22 @@ else:
|
||||||
|
|
||||||
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
||||||
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
|
importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
|
||||||
|
|
||||||
|
when useWinUnicode:
|
||||||
|
proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: wideCString,
|
||||||
|
flags: DWORD): int32 {.
|
||||||
|
importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall.}
|
||||||
|
proc createHardLinkW*(lpFileName, lpExistingFileName: wideCString,
|
||||||
|
security: Pointer=nil): int32 {.
|
||||||
|
importc:"CreateHardLinkW", dynlib: "kernel32", stdcall.}
|
||||||
|
else:
|
||||||
|
proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring,
|
||||||
|
flags: DWORD): int32 {.
|
||||||
|
importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall.}
|
||||||
|
proc createHardLinkA*(lpFileName, lpExistingFileName: cstring,
|
||||||
|
security: Pointer=nil): int32 {.
|
||||||
|
importc:"CreateHardLinkA", dynlib: "kernel32", stdcall.}
|
||||||
|
|
||||||
const
|
const
|
||||||
FILE_ATTRIBUTE_ARCHIVE* = 32'i32
|
FILE_ATTRIBUTE_ARCHIVE* = 32'i32
|
||||||
FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
|
FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
|
||||||
|
|
@ -212,6 +227,7 @@ const
|
||||||
FILE_ATTRIBUTE_DIRECTORY* = 16'i32
|
FILE_ATTRIBUTE_DIRECTORY* = 16'i32
|
||||||
FILE_ATTRIBUTE_HIDDEN* = 2'i32
|
FILE_ATTRIBUTE_HIDDEN* = 2'i32
|
||||||
FILE_ATTRIBUTE_READONLY* = 1'i32
|
FILE_ATTRIBUTE_READONLY* = 1'i32
|
||||||
|
FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32
|
||||||
FILE_ATTRIBUTE_SYSTEM* = 4'i32
|
FILE_ATTRIBUTE_SYSTEM* = 4'i32
|
||||||
FILE_ATTRIBUTE_TEMPORARY* = 256'i32
|
FILE_ATTRIBUTE_TEMPORARY* = 256'i32
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue