ossymlinks.nim 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. include system/inclrtl
  2. import std/oserrors
  3. import oscommon
  4. export symlinkExists
  5. when defined(nimPreviewSlimSystem):
  6. import std/[syncio, assertions, widestrs]
  7. when weirdTarget:
  8. discard
  9. elif defined(windows):
  10. import winlean, times
  11. elif defined(posix):
  12. import posix
  13. else:
  14. {.error: "OS module not ported to your operating system!".}
  15. when weirdTarget:
  16. {.pragma: noWeirdTarget, error: "this proc is not available on the NimScript/js target".}
  17. else:
  18. {.pragma: noWeirdTarget.}
  19. when defined(nimscript):
  20. # for procs already defined in scriptconfig.nim
  21. template noNimJs(body): untyped = discard
  22. elif defined(js):
  23. {.pragma: noNimJs, error: "this proc is not available on the js target".}
  24. else:
  25. {.pragma: noNimJs.}
  26. proc createSymlink*(src, dest: string) {.noWeirdTarget.} =
  27. ## Create a symbolic link at `dest` which points to the item specified
  28. ## by `src`. On most operating systems, will fail if a link already exists.
  29. ##
  30. ## .. warning:: Some OS's (such as Microsoft Windows) restrict the creation
  31. ## of symlinks to root users (administrators) or users with developer mode enabled.
  32. ##
  33. ## See also:
  34. ## * `createHardlink proc`_
  35. ## * `expandSymlink proc`_
  36. when defined(windows):
  37. const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 2
  38. # allows anyone with developer mode on to create a link
  39. let flag = dirExists(src).int32 or SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
  40. when useWinUnicode:
  41. var wSrc = newWideCString(src)
  42. var wDst = newWideCString(dest)
  43. if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
  44. raiseOSError(osLastError(), $(src, dest))
  45. else:
  46. if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
  47. raiseOSError(osLastError(), $(src, dest))
  48. else:
  49. if symlink(src, dest) != 0:
  50. raiseOSError(osLastError(), $(src, dest))
  51. proc expandSymlink*(symlinkPath: string): string {.noWeirdTarget.} =
  52. ## Returns a string representing the path to which the symbolic link points.
  53. ##
  54. ## On Windows this is a noop, `symlinkPath` is simply returned.
  55. ##
  56. ## See also:
  57. ## * `createSymlink proc`_
  58. when defined(windows):
  59. result = symlinkPath
  60. else:
  61. result = newString(maxSymlinkLen)
  62. var len = readlink(symlinkPath, result.cstring, maxSymlinkLen)
  63. if len < 0:
  64. raiseOSError(osLastError(), symlinkPath)
  65. if len > maxSymlinkLen:
  66. result = newString(len+1)
  67. len = readlink(symlinkPath, result.cstring, len)
  68. setLen(result, len)