posix_utils.nim 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #
  2. # Nim's Runtime Library
  3. # (c) Copyright 2019 Federico Ceratto and other Nim contributors
  4. #
  5. # See the file "copying.txt", included in this
  6. # distribution, for details about the copyright.
  7. #
  8. ## A set of helpers for the POSIX module.
  9. ## Raw interfaces are in the other ``posix*.nim`` files.
  10. # Where possible, contribute OS-independent procs in `os <os.html>`_ instead.
  11. import std/[posix, parsecfg, os]
  12. import std/private/since
  13. when defined(nimPreviewSlimSystem):
  14. import std/syncio
  15. type Uname* = object
  16. sysname*, nodename*, release*, version*, machine*: string
  17. template charArrayToString(input: typed): string =
  18. $cast[cstring](addr input)
  19. proc uname*(): Uname =
  20. ## Provides system information in a `Uname` struct with sysname, nodename,
  21. ## release, version and machine attributes.
  22. when defined(posix):
  23. runnableExamples:
  24. echo uname().nodename, uname().release, uname().version
  25. doAssert uname().sysname.len != 0
  26. var u: Utsname
  27. if uname(u) != 0:
  28. raiseOSError(OSErrorCode(errno))
  29. result.sysname = charArrayToString u.sysname
  30. result.nodename = charArrayToString u.nodename
  31. result.release = charArrayToString u.release
  32. result.version = charArrayToString u.version
  33. result.machine = charArrayToString u.machine
  34. proc fsync*(fd: int) =
  35. ## synchronize a file's buffer cache to the storage device
  36. if fsync(fd.cint) != 0:
  37. raiseOSError(OSErrorCode(errno))
  38. proc stat*(path: string): Stat =
  39. ## Returns file status in a `Stat` structure
  40. if stat(path.cstring, result) != 0:
  41. raiseOSError(OSErrorCode(errno))
  42. proc memoryLock*(a1: pointer, a2: int) =
  43. ## Locks pages starting from a1 for a1 bytes and prevent them from being swapped.
  44. if mlock(a1, a2) != 0:
  45. raiseOSError(OSErrorCode(errno))
  46. proc memoryLockAll*(flags: int) =
  47. ## Locks all memory for the running process to prevent swapping.
  48. ##
  49. ## example:
  50. ## ```nim
  51. ## memoryLockAll(MCL_CURRENT or MCL_FUTURE)
  52. ## ```
  53. if mlockall(flags.cint) != 0:
  54. raiseOSError(OSErrorCode(errno))
  55. proc memoryUnlock*(a1: pointer, a2: int) =
  56. ## Unlock pages starting from a1 for a1 bytes and allow them to be swapped.
  57. if munlock(a1, a2) != 0:
  58. raiseOSError(OSErrorCode(errno))
  59. proc memoryUnlockAll*() =
  60. ## Unlocks all memory for the running process to allow swapping.
  61. if munlockall() != 0:
  62. raiseOSError(OSErrorCode(errno))
  63. proc sendSignal*(pid: Pid, signal: int) =
  64. ## Sends a signal to a running process by calling `kill`.
  65. ## Raise exception in case of failure e.g. process not running.
  66. if kill(pid, signal.cint) != 0:
  67. raiseOSError(OSErrorCode(errno))
  68. proc mkstemp*(prefix: string, suffix=""): (string, File) =
  69. ## Creates a unique temporary file from a prefix string. A six-character string
  70. ## will be added. If suffix is provided it will be added to the string
  71. ## The file is created with perms 0600.
  72. ## Returns the filename and a file opened in r/w mode.
  73. var tmpl = cstring(prefix & "XXXXXX" & suffix)
  74. let fd =
  75. if len(suffix) == 0:
  76. when declared(mkostemp):
  77. mkostemp(tmpl, O_CLOEXEC)
  78. else:
  79. mkstemp(tmpl)
  80. else:
  81. when declared(mkostemps):
  82. mkostemps(tmpl, cint(len(suffix)), O_CLOEXEC)
  83. else:
  84. mkstemps(tmpl, cint(len(suffix)))
  85. var f: File
  86. if open(f, fd, fmReadWrite):
  87. return ($tmpl, f)
  88. raiseOSError(OSErrorCode(errno))
  89. proc mkdtemp*(prefix: string): string =
  90. ## Creates a unique temporary directory from a prefix string. Adds a six chars suffix.
  91. ## The directory is created with permissions 0700. Returns the directory name.
  92. var tmpl = cstring(prefix & "XXXXXX")
  93. if mkdtemp(tmpl) == nil:
  94. raiseOSError(OSErrorCode(errno))
  95. return $tmpl
  96. proc osReleaseFile*(): Config {.since: (1, 5).} =
  97. ## Gets system identification from `os-release` file and returns it as a `parsecfg.Config`.
  98. ## You also need to import the `parsecfg` module to gain access to this object.
  99. ## The `os-release` file is an official Freedesktop.org open standard.
  100. ## Available in Linux and BSD distributions, except Android and Android-based Linux.
  101. ## `os-release` file is not available on Windows and OS X by design.
  102. ## * https://www.freedesktop.org/software/systemd/man/os-release.html
  103. runnableExamples:
  104. import std/parsecfg
  105. when defined(linux):
  106. let data = osReleaseFile()
  107. echo "OS name: ", data.getSectionValue("", "NAME") ## the data is up to each distro.
  108. # We do not use a {.strdefine.} because Standard says it *must* be that path.
  109. for osReleaseFile in ["/etc/os-release", "/usr/lib/os-release"]:
  110. if fileExists(osReleaseFile):
  111. return loadConfig(osReleaseFile)
  112. raise newException(IOError, "File not found: /etc/os-release, /usr/lib/os-release")