Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refs #8391 std/os now shows runtime context for raiseOSError exceptions #13294

Merged
merged 3 commits into from
Jan 30, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 51 additions & 52 deletions lib/pure/os.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ proc findExe*(exe: string, followSymlinks: bool = true;
var r = newString(256)
var len = readlink(x, r, 256)
if len < 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), exe)
if len > 256:
r = newString(len+1)
len = readlink(x, r, len)
Expand All @@ -1196,12 +1196,12 @@ proc getLastModificationTime*(file: string): times.Time {.rtl, extern: "nos$1",
## * `fileNewer proc <#fileNewer,string,string>`_
when defined(posix):
var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError())
if stat(file, res) < 0'i32: raiseOSError(osLastError(), file)
result = res.st_mtim.toTime
else:
var f: WIN32_FIND_DATA
var h = findFirstFile(file, f)
if h == -1'i32: raiseOSError(osLastError())
if h == -1'i32: raiseOSError(osLastError(), file)
result = fromWinTime(rdFileTime(f.ftLastWriteTime))
findClose(h)

Expand All @@ -1214,12 +1214,12 @@ proc getLastAccessTime*(file: string): times.Time {.rtl, extern: "nos$1", noNimS
## * `fileNewer proc <#fileNewer,string,string>`_
when defined(posix):
var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError())
if stat(file, res) < 0'i32: raiseOSError(osLastError(), file)
result = res.st_atim.toTime
else:
var f: WIN32_FIND_DATA
var h = findFirstFile(file, f)
if h == -1'i32: raiseOSError(osLastError())
if h == -1'i32: raiseOSError(osLastError(), file)
result = fromWinTime(rdFileTime(f.ftLastAccessTime))
findClose(h)

Expand All @@ -1236,12 +1236,12 @@ proc getCreationTime*(file: string): times.Time {.rtl, extern: "nos$1", noNimScr
## * `fileNewer proc <#fileNewer,string,string>`_
when defined(posix):
var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError())
if stat(file, res) < 0'i32: raiseOSError(osLastError(), file)
result = res.st_ctim.toTime
else:
var f: WIN32_FIND_DATA
var h = findFirstFile(file, f)
if h == -1'i32: raiseOSError(osLastError())
if h == -1'i32: raiseOSError(osLastError(), file)
result = fromWinTime(rdFileTime(f.ftCreationTime))
findClose(h)

Expand Down Expand Up @@ -1329,11 +1329,11 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [], noNimScript.} =
when defined(Windows):
when useWinUnicode:
if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), newDir)
else:
if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError())
if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError(), newDir)
else:
if chdir(newDir) != 0'i32: raiseOSError(osLastError())
if chdir(newDir) != 0'i32: raiseOSError(osLastError(), newDir)

when not weirdTarget:
proc absolutePath*(path: string, root = getCurrentDir()): string {.noNimScript.} =
Expand Down Expand Up @@ -1470,11 +1470,11 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
discard closeHandle(f1)
discard closeHandle(f2)

if not success: raiseOSError(lastErr)
if not success: raiseOSError(lastErr, $(path1, path2))
else:
var a, b: Stat
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(path1, path2))
else:
result = a.st_dev == b.st_dev and a.st_ino == b.st_ino

Expand Down Expand Up @@ -1542,7 +1542,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {.
## * `FilePermission enum <#FilePermission>`_
when defined(posix):
var a: Stat
if stat(filename, a) < 0'i32: raiseOSError(osLastError())
if stat(filename, a) < 0'i32: raiseOSError(osLastError(), filename)
result = {}
if (a.st_mode and S_IRUSR.Mode) != 0.Mode: result.incl(fpUserRead)
if (a.st_mode and S_IWUSR.Mode) != 0.Mode: result.incl(fpUserWrite)
Expand All @@ -1560,7 +1560,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {.
wrapUnary(res, getFileAttributesW, filename)
else:
var res = getFileAttributesA(filename)
if res == -1'i32: raiseOSError(osLastError())
if res == -1'i32: raiseOSError(osLastError(), filename)
if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead,
fpOthersExec, fpOthersRead}
Expand Down Expand Up @@ -1592,13 +1592,13 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {.
if fpOthersWrite in permissions: p = p or S_IWOTH.Mode
if fpOthersExec in permissions: p = p or S_IXOTH.Mode

if chmod(filename, cast[Mode](p)) != 0: raiseOSError(osLastError())
if chmod(filename, cast[Mode](p)) != 0: raiseOSError(osLastError(), $(filename, permissions))
else:
when useWinUnicode:
wrapUnary(res, getFileAttributesW, filename)
else:
var res = getFileAttributesA(filename)
if res == -1'i32: raiseOSError(osLastError())
if res == -1'i32: raiseOSError(osLastError(), filename)
if fpUserWrite in permissions:
res = res and not FILE_ATTRIBUTE_READONLY
else:
Expand All @@ -1607,7 +1607,7 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission]) {.
wrapBinary(res2, setFileAttributesW, filename, res)
else:
var res2 = setFileAttributesA(filename, res)
if res2 == - 1'i32: raiseOSError(osLastError())
if res2 == - 1'i32: raiseOSError(osLastError(), $(filename, permissions))

proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
tags: [ReadIOEffect, WriteIOEffect], noNimScript.} =
Expand Down Expand Up @@ -1640,17 +1640,17 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
when useWinUnicode:
let s = newWideCString(source)
let d = newWideCString(dest)
if copyFileW(s, d, 0'i32) == 0'i32: raiseOSError(osLastError())
if copyFileW(s, d, 0'i32) == 0'i32: raiseOSError(osLastError(), $(source, dest))
else:
if copyFileA(source, dest, 0'i32) == 0'i32: raiseOSError(osLastError())
if copyFileA(source, dest, 0'i32) == 0'i32: raiseOSError(osLastError(), $(source, dest))
else:
# generic version of copyFile which works for any platform:
const bufSize = 8000 # better for memory manager
var d, s: File
if not open(s, source): raiseOSError(osLastError())
if not open(s, source): raiseOSError(osLastError(), source)
if not open(d, dest, fmWrite):
close(s)
raiseOSError(osLastError())
raiseOSError(osLastError(), dest)
var buf = alloc(bufSize)
while true:
var bytesread = readBuffer(s, buf, bufSize)
Expand All @@ -1660,7 +1660,7 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1",
dealloc(buf)
close(s)
close(d)
raiseOSError(osLastError())
raiseOSError(osLastError(), dest)
if bytesread != bufSize: break
dealloc(buf)
close(s)
Expand Down Expand Up @@ -1733,10 +1733,7 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect], n
## * `tryRemoveFile proc <#tryRemoveFile,string>`_
## * `moveFile proc <#moveFile,string,string>`_
if not tryRemoveFile(file):
when defined(Windows):
raiseOSError(osLastError())
else:
raiseOSError(osLastError(), $strerror(errno))
raiseOSError(osLastError(), file)

proc tryMoveFSObject(source, dest: string): bool {.noNimScript.} =
## Moves a file or directory from `source` to `dest`.
Expand All @@ -1748,16 +1745,17 @@ proc tryMoveFSObject(source, dest: string): bool {.noNimScript.} =
when useWinUnicode:
let s = newWideCString(source)
let d = newWideCString(dest)
if moveFileExW(s, d, MOVEFILE_COPY_ALLOWED) == 0'i32: raiseOSError(osLastError())
if moveFileExW(s, d, MOVEFILE_COPY_ALLOWED) == 0'i32: raiseOSError(osLastError(), $(source, dest))
else:
if moveFileExA(source, dest, MOVEFILE_COPY_ALLOWED) == 0'i32: raiseOSError(osLastError())
if moveFileExA(source, dest, MOVEFILE_COPY_ALLOWED) == 0'i32: raiseOSError(osLastError(), $(source, dest))
else:
if c_rename(source, dest) != 0'i32:
let err = osLastError()
if err == EXDEV.OSErrorCode:
return false
else:
raiseOSError(err, $strerror(errno))
# see whether `strerror(errno)` is redundant with what raiseOSError already shows
raiseOSError(err, $(source, dest, strerror(errno)))
return true

proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
Expand Down Expand Up @@ -1927,7 +1925,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
while true:
var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused)
if L == 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), filename)
elif L > bufsize:
res = newWideCString("", L)
bufsize = L
Expand All @@ -1940,7 +1938,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
while true:
var L = getFullPathNameA(filename, bufsize, result, unused)
if L == 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), filename)
elif L > bufsize:
result = newString(L)
bufsize = L
Expand All @@ -1952,13 +1950,14 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
for x in walkFiles(result):
result = x
if not existsFile(result) and not existsDir(result):
# consider using: `raiseOSError(osLastError(), result)`
raise newException(OSError, "file '" & result & "' does not exist")
else:
# according to Posix we don't need to allocate space for result pathname.
# But we need to free return value with free(3).
var r = realpath(filename, nil)
if r.isNil:
raiseOSError(osLastError())
raiseOSError(osLastError(), filename)
else:
result = $r
c_free(cast[pointer](r))
Expand Down Expand Up @@ -2145,9 +2144,9 @@ proc rawRemoveDir(dir: string) {.noNimScript.} =
let lastError = osLastError()
if res == 0'i32 and lastError.int32 != 3'i32 and
lastError.int32 != 18'i32 and lastError.int32 != 2'i32:
raiseOSError(lastError)
raiseOSError(lastError, dir)
else:
if rmdir(dir) != 0'i32 and errno != ENOENT: raiseOSError(osLastError())
if rmdir(dir) != 0'i32 and errno != ENOENT: raiseOSError(osLastError(), dir)

proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [
WriteDirEffect, ReadDirEffect], benign, noNimScript.} =
Expand Down Expand Up @@ -2336,13 +2335,13 @@ proc createSymlink*(src, dest: string) {.noNimScript.} =
var wSrc = newWideCString(src)
var wDst = newWideCString(dest)
if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))
else:
if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))
else:
if symlink(src, dest) != 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))

proc createHardlink*(src, dest: string) {.noNimScript.} =
## Create a hard link at `dest` which points to the item specified
Expand All @@ -2358,13 +2357,13 @@ proc createHardlink*(src, dest: string) {.noNimScript.} =
var wSrc = newWideCString(src)
var wDst = newWideCString(dest)
if createHardLinkW(wDst, wSrc, nil) == 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))
else:
if createHardLinkA(dest, src, nil) == 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))
else:
if link(src, dest) != 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $(src, dest))

proc copyFileWithPermissions*(source, dest: string,
ignorePermissionErrors = true) {.noNimScript.} =
Expand Down Expand Up @@ -2473,7 +2472,7 @@ proc expandSymlink*(symlinkPath: string): string {.noNimScript.} =
result = newString(256)
var len = readlink(symlinkPath, result, 256)
if len < 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), symlinkPath)
if len > 256:
result = newString(len+1)
len = readlink(symlinkPath, result, len)
Expand Down Expand Up @@ -2942,15 +2941,15 @@ proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1",
when defined(windows):
var a: WIN32_FIND_DATA
var resA = findFirstFile(file, a)
if resA == -1: raiseOSError(osLastError())
if resA == -1: raiseOSError(osLastError(), file)
result = rdFileSize(a)
findClose(resA)
else:
var f: File
if open(f, file):
result = getFileSize(f)
close(f)
else: raiseOSError(osLastError())
else: raiseOSError(osLastError(), file)

when defined(Windows) or weirdTarget:
type
Expand Down Expand Up @@ -3061,12 +3060,12 @@ proc getFileInfo*(handle: FileHandle): FileInfo {.noNimScript.} =
# To transform the C file descriptor to a native file handle.
var realHandle = get_osfhandle(handle)
if getFileInformationByHandle(realHandle, addr rawInfo) == 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), $handle)
rawToFormalFileInfo(rawInfo, "", result)
else:
var rawInfo: Stat
if fstat(handle, rawInfo) < 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), $handle)
rawToFormalFileInfo(rawInfo, "", result)

proc getFileInfo*(file: File): FileInfo {.noNimScript.} =
Expand Down Expand Up @@ -3102,19 +3101,19 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo {.noNimScript.}
handle = openHandle(path, followSymlink)
rawInfo: BY_HANDLE_FILE_INFORMATION
if handle == INVALID_HANDLE_VALUE:
raiseOSError(osLastError())
raiseOSError(osLastError(), path)
if getFileInformationByHandle(handle, addr rawInfo) == 0:
raiseOSError(osLastError())
raiseOSError(osLastError(), path)
rawToFormalFileInfo(rawInfo, path, result)
discard closeHandle(handle)
else:
var rawInfo: Stat
if followSymlink:
if stat(path, rawInfo) < 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), path)
else:
if lstat(path, rawInfo) < 0'i32:
raiseOSError(osLastError())
raiseOSError(osLastError(), path)
rawToFormalFileInfo(rawInfo, path, result)

proc isHidden*(path: string): bool {.noNimScript.} =
Expand Down Expand Up @@ -3167,14 +3166,14 @@ proc setLastModificationTime*(file: string, t: times.Time) {.noNimScript.} =
let micro = convert(Nanoseconds, Microseconds, t.nanosecond)
var timevals = [Timeval(tv_sec: unixt, tv_usec: micro),
Timeval(tv_sec: unixt, tv_usec: micro)] # [last access, last modification]
if utimes(file, timevals.addr) != 0: raiseOSError(osLastError())
if utimes(file, timevals.addr) != 0: raiseOSError(osLastError(), file)
else:
let h = openHandle(path = file, writeAccess = true)
if h == INVALID_HANDLE_VALUE: raiseOSError(osLastError())
if h == INVALID_HANDLE_VALUE: raiseOSError(osLastError(), file)
var ft = t.toWinTime.toFILETIME
let res = setFileTime(h, nil, nil, ft.addr)
discard h.closeHandle
if res == 0'i32: raiseOSError(osLastError())
if res == 0'i32: raiseOSError(osLastError(), file)


when isMainModule:
Expand Down