summary refs log tree commit diff stats
path: root/lib/std
diff options
context:
space:
mode:
authorlit <litlighilit@foxmail.com>2024-04-03 15:32:26 +0800
committerGitHub <noreply@github.com>2024-04-03 09:32:26 +0200
commitdee55f587f4e3cfc8ffe28e4a41eba9c8ed7f2f8 (patch)
tree587368a63884e2e69dce68b472839c9b605303f5 /lib/std
parent3bdb531f90c3d804c0f8d25865955120b9598b13 (diff)
downloadNim-dee55f587f4e3cfc8ffe28e4a41eba9c8ed7f2f8.tar.gz
Update syncio.nim, fixes "open by FileHandle" doesn't work on Windows (#23456)
## Reprodution
if on Windows:
```Nim
when defined(windows):
  var file: File
  let succ = file.open(<aFileHandle>)
``` 
then `succ` will be false.

If tested, it can be found to fail with errno `22` and message: `Invalid
argument`

## Problem
After some investigations and tests,
I found it's due to the `mode` argument for `fdopen`.


Currently `NoInheritFlag`(`'N'` in Windows) is added to `mode` arg
passed to `_fdopen`, but if referring to
[Windows `_fdopen`
doc](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/fdopen-wfdopen?view=msvc-170),
you'll find there is no `'N'` describled. That's `'N'` is not accepted
by `_fdopen`.

Therefore, the demo above will fail.

## In Addition
To begin with, technologically speaking, when opening with a
`fileHandle`(or called `fd`), there is no concept of fd-inheritable as
`fd` is opened already.

In POSIX, `NoInheritFlag` is defined as `e`.

It's pointed out in [POSIX `open`
man-doc](https://www.man7.org/linux/man-pages/man3/fopen.3.html) that
`e` in mode is ignored for fdopen(),

which means `e` for `fdopen()` is not wanted, just allowed.

Therefore, better to also not pass `e` to `fdopen`

---

In all, that's this PR.
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/syncio.nim5
1 files changed, 4 insertions, 1 deletions
diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim
index 44244297f..2b39375ea 100644
--- a/lib/std/syncio.nim
+++ b/lib/std/syncio.nim
@@ -648,6 +648,9 @@ const
         ""
     else:
       ""
+  RawFormatOpen: array[FileMode, cstring] = [
+    # used for open by FileHandle, which calls `fdopen`
+    cstring("rb"), "wb", "w+b", "r+b", "ab"]
   FormatOpen: array[FileMode, cstring] = [
     cstring("rb" & NoInheritFlag), "wb" & NoInheritFlag, "w+b" & NoInheritFlag,
     "r+b" & NoInheritFlag, "ab" & NoInheritFlag
@@ -749,7 +752,7 @@ proc open*(f: var File, filehandle: FileHandle,
         filehandle) else: filehandle
     if not setInheritable(oshandle, false):
       return false
-  f = c_fdopen(filehandle, FormatOpen[mode])
+  f = c_fdopen(filehandle, RawFormatOpen[mode])
   result = f != nil
 
 proc open*(filename: string,