changes FileHandle type on Windows (#24910)

On windows, `HANDLE` type values are converted to `syncio.FileHandle` in
`lib/std/syncio.nim`, `lib/pure/memfiles.nim` and `lib/pure/osproc.nim`.
`HANDLE` type is `void *` on Windows and its size is larger then `cint`.

https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types

This PR change `syncio.FileHandle` type so that converting `HANDLE` type
to `syncio.FileHandle` doesn't lose bits.

We can keep `FileHandle` unchanged and change some of parameter/return
type from `FileHandle` to an type same size to `HANDLE`, but it is
breaking change.
This commit is contained in:
Tomohiro
2025-04-28 17:43:53 +09:00
committed by GitHub
parent 8c9a645bdf
commit eea4ce0e2c
6 changed files with 38 additions and 29 deletions

View File

@@ -40,9 +40,6 @@ type
## at the end. If the file does not exist, it
## will be created.
FileHandle* = cint ## The type that represents an OS file handle; this is
## useful for low-level file access.
FileSeekPos* = enum ## Position relative to which seek should happen.
# The values are ordered so that they match with stdio
# SEEK_SET, SEEK_CUR and SEEK_END respectively.
@@ -50,6 +47,13 @@ type
fspCur ## Seek relative to current position
fspEnd ## Seek relative to end
when defined(windows):
type FileHandle* = int
## Windows `HANDLE` type, convertible to `winlean.Handle`.
else:
type FileHandle* = cint ## The type that represents an OS file handle; this is
## useful for low-level file access.
# text file handling:
when not defined(nimscript) and not defined(js):
# duplicated between io and ansi_c
@@ -310,12 +314,7 @@ elif defined(windows):
proc getOsfhandle(fd: cint): int {.
importc: "_get_osfhandle", header: "<io.h>".}
type
IoHandle = distinct pointer
## Windows' HANDLE type. Defined as an untyped pointer but is **not**
## one. Named like this to avoid collision with other `system` modules.
proc setHandleInformation(hObject: IoHandle, dwMask, dwFlags: WinDWORD):
proc setHandleInformation(hObject: FileHandle, dwMask, dwFlags: WinDWORD):
WinBOOL {.stdcall, dynlib: "kernel32",
importc: "SetHandleInformation".}
@@ -361,7 +360,7 @@ proc getFileHandle*(f: File): FileHandle =
## Note that on Windows this doesn't return the Windows-specific handle,
## but the C library's notion of a handle, whatever that means.
## Use `getOsFileHandle` instead.
c_fileno(f)
FileHandle c_fileno(f)
proc getOsFileHandle*(f: File): FileHandle =
## Returns the OS file handle of the file `f`. This is only useful for
@@ -390,7 +389,7 @@ when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(w
flags = if inheritable: flags and not FD_CLOEXEC else: flags or FD_CLOEXEC
result = c_fcntl(f, F_SETFD, flags) != -1
else:
result = setHandleInformation(cast[IoHandle](f), HANDLE_FLAG_INHERIT,
result = setHandleInformation(f, HANDLE_FLAG_INHERIT,
inheritable.WinDWORD) != 0
proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
@@ -423,12 +422,18 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
importc: "LocalFree", stdcall, dynlib: "kernel32".}
proc isatty(f: File): bool =
# terminal module also has isatty
when defined(posix):
proc isatty(fildes: FileHandle): cint {.
importc: "isatty", header: "<unistd.h>".}
else:
proc isatty(fildes: FileHandle): cint {.
elif defined(windows):
proc c_isatty(fildes: cint): cint {.
importc: "_isatty", header: "<io.h>".}
proc isatty(fildes: FileHandle): cint =
c_isatty(cint(fildes))
else:
{.error: "isatty is not supported on your operating system!".}
result = isatty(getFileHandle(f)) != 0'i32
# this implies the file is open
@@ -769,10 +774,10 @@ proc open*(f: var File, filehandle: FileHandle,
## The passed file handle will no longer be inheritable.
when not defined(nimInheritHandles) and declared(setInheritable):
let oshandle = when defined(windows): FileHandle getOsfhandle(
filehandle) else: filehandle
cint filehandle) else: filehandle
if not setInheritable(oshandle, false):
return false
f = c_fdopen(filehandle, RawFormatOpen[mode])
f = c_fdopen(cint filehandle, RawFormatOpen[mode])
result = f != nil
proc open*(filename: string,