oserr.nim 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. ## Include file that implements 'osErrorMsg' and friends. Do not import it!
  2. when not declared(ospaths):
  3. {.error: "This is an include file for ospaths.nim!".}
  4. when not defined(nimscript):
  5. var errno {.importc, header: "<errno.h>".}: cint
  6. proc c_strerror(errnum: cint): cstring {.
  7. importc: "strerror", header: "<string.h>".}
  8. when defined(windows):
  9. import winlean
  10. proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} =
  11. ## Retrieves the operating system's error flag, ``errno``.
  12. ## On Windows ``GetLastError`` is checked before ``errno``.
  13. ## Returns "" if no error occurred.
  14. ##
  15. ## **Deprecated since version 0.9.4**: use the other ``osErrorMsg`` proc.
  16. result = ""
  17. when defined(Windows) and not defined(nimscript):
  18. var err = getLastError()
  19. if err != 0'i32:
  20. when useWinUnicode:
  21. var msgbuf: WideCString
  22. if formatMessageW(0x00000100 or 0x00001000 or 0x00000200 or 0x000000FF,
  23. nil, err, 0, addr(msgbuf), 0, nil) != 0'i32:
  24. result = $msgbuf
  25. if msgbuf != nil: localFree(cast[pointer](msgbuf))
  26. else:
  27. var msgbuf: cstring
  28. if formatMessageA(0x00000100 or 0x00001000 or 0x00000200 or 0x000000FF,
  29. nil, err, 0, addr(msgbuf), 0, nil) != 0'i32:
  30. result = $msgbuf
  31. if msgbuf != nil: localFree(msgbuf)
  32. when not defined(nimscript):
  33. if errno != 0'i32:
  34. result = $c_strerror(errno)
  35. {.push warning[deprecated]: off.}
  36. proc raiseOSError*(msg: string = "") {.noinline, rtl, extern: "nos$1",
  37. deprecated.} =
  38. ## raises an OSError exception with the given message ``msg``.
  39. ## If ``msg == ""``, the operating system's error flag
  40. ## (``errno``) is converted to a readable error message. On Windows
  41. ## ``GetLastError`` is checked before ``errno``.
  42. ## If no error flag is set, the message ``unknown OS error`` is used.
  43. ##
  44. ## **Deprecated since version 0.9.4**: use the other ``raiseOSError`` proc.
  45. if len(msg) == 0:
  46. var m = osErrorMsg()
  47. raise newException(OSError, if m.len > 0: m else: "unknown OS error")
  48. else:
  49. raise newException(OSError, msg)
  50. {.pop.}
  51. when not defined(nimfix):
  52. {.deprecated: [osError: raiseOSError].}
  53. proc `==`*(err1, err2: OSErrorCode): bool {.borrow.}
  54. proc `$`*(err: OSErrorCode): string {.borrow.}
  55. proc osErrorMsg*(errorCode: OSErrorCode): string =
  56. ## Converts an OS error code into a human readable string.
  57. ##
  58. ## The error code can be retrieved using the ``osLastError`` proc.
  59. ##
  60. ## If conversion fails, or ``errorCode`` is ``0`` then ``""`` will be
  61. ## returned.
  62. ##
  63. ## On Windows, the ``-d:useWinAnsi`` compilation flag can be used to
  64. ## make this procedure use the non-unicode Win API calls to retrieve the
  65. ## message.
  66. result = ""
  67. when defined(nimscript):
  68. discard
  69. elif defined(Windows):
  70. if errorCode != OSErrorCode(0'i32):
  71. when useWinUnicode:
  72. var msgbuf: WideCString
  73. if formatMessageW(0x00000100 or 0x00001000 or 0x00000200,
  74. nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32:
  75. result = $msgbuf
  76. if msgbuf != nil: localFree(cast[pointer](msgbuf))
  77. else:
  78. var msgbuf: cstring
  79. if formatMessageA(0x00000100 or 0x00001000 or 0x00000200,
  80. nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32:
  81. result = $msgbuf
  82. if msgbuf != nil: localFree(msgbuf)
  83. else:
  84. if errorCode != OSErrorCode(0'i32):
  85. result = $c_strerror(errorCode.int32)
  86. proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} =
  87. ## Raises an ``OSError`` exception. The ``errorCode`` will determine the
  88. ## message, ``osErrorMsg`` will be used to get this message.
  89. ##
  90. ## The error code can be retrieved using the ``osLastError`` proc.
  91. ##
  92. ## If the error code is ``0`` or an error message could not be retrieved,
  93. ## the message ``unknown OS error`` will be used.
  94. var e: ref OSError; new(e)
  95. e.errorCode = errorCode.int32
  96. if additionalInfo.len == 0:
  97. e.msg = osErrorMsg(errorCode)
  98. else:
  99. e.msg = osErrorMsg(errorCode) & "\nAdditional info: " & additionalInfo
  100. if e.msg == "":
  101. e.msg = "unknown OS error"
  102. raise e
  103. {.push stackTrace:off.}
  104. proc osLastError*(): OSErrorCode =
  105. ## Retrieves the last operating system error code.
  106. ##
  107. ## This procedure is useful in the event when an OS call fails. In that case
  108. ## this procedure will return the error code describing the reason why the
  109. ## OS call failed. The ``OSErrorMsg`` procedure can then be used to convert
  110. ## this code into a string.
  111. ##
  112. ## **Warning**:
  113. ## The behaviour of this procedure varies between Windows and POSIX systems.
  114. ## On Windows some OS calls can reset the error code to ``0`` causing this
  115. ## procedure to return ``0``. It is therefore advised to call this procedure
  116. ## immediately after an OS call fails. On POSIX systems this is not a problem.
  117. when defined(nimscript):
  118. discard
  119. elif defined(windows):
  120. result = OSErrorCode(getLastError())
  121. else:
  122. result = OSErrorCode(errno)
  123. {.pop.}