diff options
author | Clay Sweetser <clay.sweetser@gmail.com> | 2014-02-01 20:56:34 -0500 |
---|---|---|
committer | Clay Sweetser <clay.sweetser@gmail.com> | 2014-02-01 20:56:34 -0500 |
commit | 7cd5e79464c13b6a8047bdc3d58f0ddc4069431b (patch) | |
tree | 37b056a24ac9201b09d253b36416b368a0da2dc4 /lib/pure | |
parent | 69bc0779378bf3684d2138d2b6c0a423ae56f2c6 (diff) | |
download | Nim-7cd5e79464c13b6a8047bdc3d58f0ddc4069431b.tar.gz |
Added symlink procs
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/os.nim | 74 |
1 files changed, 72 insertions, 2 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 8cb3919a7..4bdb0e7e7 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -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; |