Skip to content

Commit eea4ce0

Browse files
authored
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.
1 parent 8c9a645 commit eea4ce0

File tree

6 files changed

+38
-29
lines changed

6 files changed

+38
-29
lines changed

lib/pure/memfiles.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ proc setFileSize(fh: FileHandle, newFileSize = -1, oldSize = -1): OSErrorCode =
4646
when defined(windows):
4747
var sizeHigh = int32(newFileSize shr 32)
4848
let sizeLow = int32(newFileSize and 0xffffffff)
49-
let status = setFilePointer(fh, sizeLow, addr(sizeHigh), FILE_BEGIN)
49+
let status = setFilePointer(Handle fh, sizeLow, addr(sizeHigh), FILE_BEGIN)
5050
let lastErr = osLastError()
5151
if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
52-
setEndOfFile(fh) == 0:
52+
setEndOfFile(Handle fh) == 0:
5353
result = lastErr
5454
else:
5555
if newFileSize > oldSize: # grow the file

lib/pure/os.nim

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -845,11 +845,11 @@ when weirdTarget or defined(windows) or defined(posix) or defined(nintendoswitch
845845
result = default(FileInfo)
846846
when defined(windows):
847847
var rawInfo: BY_HANDLE_FILE_INFORMATION
848-
# We have to use the super special '_get_osfhandle' call (wrapped above)
848+
# We have to use the super special '_get_osfhandle' call (wrapped in winlean)
849849
# To transform the C file descriptor to a native file handle.
850-
var realHandle = get_osfhandle(handle)
850+
var realHandle = get_osfhandle(handle.cint)
851851
if getFileInformationByHandle(realHandle, addr rawInfo) == 0:
852-
raiseOSError(osLastError(), $handle)
852+
raiseOSError(osLastError(), $(int handle))
853853
rawToFormalFileInfo(rawInfo, "", result)
854854
else:
855855
var rawInfo: Stat = default(Stat)

lib/pure/osproc.nim

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,8 @@ when defined(windows) and not defined(useNimRtl):
546546
raiseOSError(osLastError())
547547

548548
proc fileClose[T: Handle | FileHandle](h: var T) {.inline.} =
549-
if h > 4:
550-
closeHandleCheck(h)
549+
if h.int > 4:
550+
closeHandleCheck(Handle h)
551551
h = INVALID_HANDLE_VALUE.T
552552
553553
proc hsClose(s: Stream) =
@@ -574,8 +574,8 @@ when defined(windows) and not defined(useNimRtl):
574574
addr bytesWritten, nil)
575575
if a == 0: raiseOSError(osLastError())
576576
577-
proc newFileHandleStream(handle: Handle): owned FileHandleStream =
578-
result = FileHandleStream(handle: handle, closeImpl: hsClose, atEndImpl: hsAtEnd,
577+
proc newFileHandleStream(handle: FileHandle): owned FileHandleStream =
578+
result = FileHandleStream(handle: Handle handle, closeImpl: hsClose, atEndImpl: hsAtEnd,
579579
readDataImpl: hsReadData, writeDataImpl: hsWriteData)
580580
581581
proc buildCommandLine(a: string, args: openArray[string]): string =
@@ -888,7 +888,7 @@ when defined(windows) and not defined(useNimRtl):
888888
assert readfds.len <= MAXIMUM_WAIT_OBJECTS
889889
var rfds: WOHandleArray
890890
for i in 0..readfds.len()-1:
891-
rfds[i] = readfds[i].outHandle #fProcessHandle
891+
rfds[i] = readfds[i].outHandle.Handle #fProcessHandle
892892
893893
var ret = waitForMultipleObjects(readfds.len.int32,
894894
addr(rfds), 0'i32, timeout.int32)
@@ -904,7 +904,7 @@ when defined(windows) and not defined(useNimRtl):
904904
905905
proc hasData*(p: Process): bool =
906906
var x: int32
907-
if peekNamedPipe(p.outHandle, lpTotalBytesAvail = addr x):
907+
if peekNamedPipe(p.outHandle.Handle, lpTotalBytesAvail = addr x):
908908
result = x > 0
909909
910910
elif not defined(useNimRtl):

lib/pure/terminal.nim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,13 @@ proc isatty*(f: File): bool =
805805
when defined(posix):
806806
proc isatty(fildes: FileHandle): cint {.
807807
importc: "isatty", header: "<unistd.h>".}
808-
else:
809-
proc isatty(fildes: FileHandle): cint {.
808+
elif defined(windows):
809+
proc c_isatty(fildes: cint): cint {.
810810
importc: "_isatty", header: "<io.h>".}
811+
proc isatty(fildes: FileHandle): cint =
812+
c_isatty(cint(fildes))
813+
else:
814+
{.error: "isatty is not supported on your operating system!".}
811815

812816
result = isatty(getFileHandle(f)) != 0'i32
813817

lib/std/syncio.nim

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,20 @@ type
4040
## at the end. If the file does not exist, it
4141
## will be created.
4242

43-
FileHandle* = cint ## The type that represents an OS file handle; this is
44-
## useful for low-level file access.
45-
4643
FileSeekPos* = enum ## Position relative to which seek should happen.
4744
# The values are ordered so that they match with stdio
4845
# SEEK_SET, SEEK_CUR and SEEK_END respectively.
4946
fspSet ## Seek to absolute value
5047
fspCur ## Seek relative to current position
5148
fspEnd ## Seek relative to end
5249

50+
when defined(windows):
51+
type FileHandle* = int
52+
## Windows `HANDLE` type, convertible to `winlean.Handle`.
53+
else:
54+
type FileHandle* = cint ## The type that represents an OS file handle; this is
55+
## useful for low-level file access.
56+
5357
# text file handling:
5458
when not defined(nimscript) and not defined(js):
5559
# duplicated between io and ansi_c
@@ -310,12 +314,7 @@ elif defined(windows):
310314
proc getOsfhandle(fd: cint): int {.
311315
importc: "_get_osfhandle", header: "<io.h>".}
312316

313-
type
314-
IoHandle = distinct pointer
315-
## Windows' HANDLE type. Defined as an untyped pointer but is **not**
316-
## one. Named like this to avoid collision with other `system` modules.
317-
318-
proc setHandleInformation(hObject: IoHandle, dwMask, dwFlags: WinDWORD):
317+
proc setHandleInformation(hObject: FileHandle, dwMask, dwFlags: WinDWORD):
319318
WinBOOL {.stdcall, dynlib: "kernel32",
320319
importc: "SetHandleInformation".}
321320

@@ -361,7 +360,7 @@ proc getFileHandle*(f: File): FileHandle =
361360
## Note that on Windows this doesn't return the Windows-specific handle,
362361
## but the C library's notion of a handle, whatever that means.
363362
## Use `getOsFileHandle` instead.
364-
c_fileno(f)
363+
FileHandle c_fileno(f)
365364

366365
proc getOsFileHandle*(f: File): FileHandle =
367366
## 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
390389
flags = if inheritable: flags and not FD_CLOEXEC else: flags or FD_CLOEXEC
391390
result = c_fcntl(f, F_SETFD, flags) != -1
392391
else:
393-
result = setHandleInformation(cast[IoHandle](f), HANDLE_FLAG_INHERIT,
392+
result = setHandleInformation(f, HANDLE_FLAG_INHERIT,
394393
inheritable.WinDWORD) != 0
395394

396395
proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
@@ -423,12 +422,18 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
423422
importc: "LocalFree", stdcall, dynlib: "kernel32".}
424423

425424
proc isatty(f: File): bool =
425+
# terminal module also has isatty
426426
when defined(posix):
427427
proc isatty(fildes: FileHandle): cint {.
428428
importc: "isatty", header: "<unistd.h>".}
429-
else:
430-
proc isatty(fildes: FileHandle): cint {.
429+
elif defined(windows):
430+
proc c_isatty(fildes: cint): cint {.
431431
importc: "_isatty", header: "<io.h>".}
432+
proc isatty(fildes: FileHandle): cint =
433+
c_isatty(cint(fildes))
434+
else:
435+
{.error: "isatty is not supported on your operating system!".}
436+
432437
result = isatty(getFileHandle(f)) != 0'i32
433438

434439
# this implies the file is open
@@ -769,10 +774,10 @@ proc open*(f: var File, filehandle: FileHandle,
769774
## The passed file handle will no longer be inheritable.
770775
when not defined(nimInheritHandles) and declared(setInheritable):
771776
let oshandle = when defined(windows): FileHandle getOsfhandle(
772-
filehandle) else: filehandle
777+
cint filehandle) else: filehandle
773778
if not setInheritable(oshandle, false):
774779
return false
775-
f = c_fdopen(filehandle, RawFormatOpen[mode])
780+
f = c_fdopen(cint filehandle, RawFormatOpen[mode])
776781
result = f != nil
777782
778783
proc open*(filename: string,

lib/windows/winlean.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ proc WSASendTo*(s: SocketHandle, buf: ptr TWSABuf, bufCount: DWORD,
815815
completionProc: POVERLAPPED_COMPLETION_ROUTINE): cint {.
816816
stdcall, importc: "WSASendTo", dynlib: "Ws2_32.dll".}
817817

818-
proc get_osfhandle*(fd:FileHandle): Handle {.
818+
proc get_osfhandle*(fd: cint): Handle {.
819819
importc: "_get_osfhandle", header:"<io.h>".}
820820

821821
proc getSystemTimes*(lpIdleTime, lpKernelTime,

0 commit comments

Comments
 (0)