mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
Merge pull request #861 from Varriount/os/add-linkprocs-prettyplease
Added symlink procs
This commit is contained in:
@@ -287,12 +287,18 @@ proc osLastError*(): TOSErrorCode =
|
||||
result = TOSErrorCode(errno)
|
||||
{.pop.}
|
||||
|
||||
proc unixToNativePath*(path: string): string {.
|
||||
proc unixToNativePath*(path: string, drive=""): string {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Converts an UNIX-like path to a native one.
|
||||
##
|
||||
## On an UNIX system this does nothing. Else it converts
|
||||
## '/', '.', '..' 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):
|
||||
result = path
|
||||
else:
|
||||
@@ -300,7 +306,10 @@ proc unixToNativePath*(path: string): string {.
|
||||
if path[0] == '/':
|
||||
# an absolute path
|
||||
when doslike:
|
||||
result = r"C:\"
|
||||
if drive != "":
|
||||
result = drive & ":" & DirSep
|
||||
else:
|
||||
result = $DirSep
|
||||
elif defined(macos):
|
||||
result = "" # must not start with ':'
|
||||
else:
|
||||
@@ -387,6 +396,21 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} =
|
||||
var res: TStat
|
||||
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.} =
|
||||
## Synonym for existsFile
|
||||
existsFile(filename)
|
||||
@@ -1221,6 +1245,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {.
|
||||
if not skipFindData(f):
|
||||
if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32:
|
||||
k = pcDir
|
||||
if (f.dwFileAttributes and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32:
|
||||
k = succ(k)
|
||||
yield (k, dir / extractFilename(getFilename(f)))
|
||||
if findNextFile(h, f) == 0'i32: break
|
||||
findClose(h)
|
||||
@@ -1245,6 +1271,10 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
|
||||
tags: [FReadDir].} =
|
||||
## walks over the directory `dir` and yields for each file in `dir`. The
|
||||
## 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:
|
||||
##
|
||||
## --------------------- ---------------------------------------------
|
||||
@@ -1336,6 +1366,46 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
|
||||
copyDir(path, dest / noSource)
|
||||
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] {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Splits a command line into several components;
|
||||
|
||||
@@ -204,7 +204,22 @@ else:
|
||||
|
||||
proc getModuleFileNameA*(handle: THandle, buf: CString, size: int32): int32 {.
|
||||
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
|
||||
FILE_ATTRIBUTE_ARCHIVE* = 32'i32
|
||||
FILE_ATTRIBUTE_COMPRESSED* = 2048'i32
|
||||
@@ -212,6 +227,7 @@ const
|
||||
FILE_ATTRIBUTE_DIRECTORY* = 16'i32
|
||||
FILE_ATTRIBUTE_HIDDEN* = 2'i32
|
||||
FILE_ATTRIBUTE_READONLY* = 1'i32
|
||||
FILE_ATTRIBUTE_REPARSE_POINT* = 1024'i32
|
||||
FILE_ATTRIBUTE_SYSTEM* = 4'i32
|
||||
FILE_ATTRIBUTE_TEMPORARY* = 256'i32
|
||||
|
||||
|
||||
Reference in New Issue
Block a user