summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2021-04-29 04:42:56 -0700
committerGitHub <noreply@github.com>2021-04-29 13:42:56 +0200
commite4db733d80d0b70192ac7eb4094a46269fe7cd5b (patch)
treeb60bdb281a29ac34be393c38a00ebbe3e53c9402
parent5edddd68d04648553bc02d52cd53d3a1a14102f3 (diff)
downloadNim-e4db733d80d0b70192ac7eb4094a46269fe7cd5b.tar.gz
fix #17888: remove undefined behavior for posix.open; fix tempfiles.createTempFile (#17889)
* fix #17888: remove undefined behavior for posix.open; fix tempfiles.createTempFile

* fix for tests/async/tasyncfile.nim

* hide mode for now

* add notice regarding stability
-rw-r--r--lib/posix/posix.nim6
-rw-r--r--lib/pure/streams.nim1
-rw-r--r--lib/std/tempfiles.nim13
3 files changed, 16 insertions, 4 deletions
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index 035b4e8fb..45fe00d5d 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -183,7 +183,11 @@ proc dlsym*(a1: pointer, a2: cstring): pointer {.importc, header: "<dlfcn.h>", s
 
 proc creat*(a1: cstring, a2: Mode): cint {.importc, header: "<fcntl.h>", sideEffect.}
 proc fcntl*(a1: cint | SocketHandle, a2: cint): cint {.varargs, importc, header: "<fcntl.h>", sideEffect.}
-proc open*(a1: cstring, a2: cint): cint {.varargs, importc, header: "<fcntl.h>", sideEffect.}
+proc openImpl(a1: cstring, a2: cint): cint {.varargs, importc: "open", header: "<fcntl.h>", sideEffect.}
+proc open*(a1: cstring, a2: cint, mode: Mode | cint = 0.Mode): cint {.inline.} =
+  # prevents bug #17888
+  openImpl(a1, a2, mode)
+
 proc posix_fadvise*(a1: cint, a2, a3: Off, a4: cint): cint {.
   importc, header: "<fcntl.h>".}
 proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index eb1c9cc14..3cc5ea038 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -1503,6 +1503,7 @@ when false:
       of fmReadWrite: flags = O_RDWR or int(O_CREAT)
       of fmReadWriteExisting: flags = O_RDWR
       of fmAppend: flags = O_WRONLY or int(O_CREAT) or O_APPEND
+      static: doAssert false # handle bug #17888
       var handle = open(filename, flags)
       if handle < 0: raise newEOS("posix.open() call failed")
     result = newFileHandleStream(handle)
diff --git a/lib/std/tempfiles.nim b/lib/std/tempfiles.nim
index 1e1bbd403..2a6fe7d83 100644
--- a/lib/std/tempfiles.nim
+++ b/lib/std/tempfiles.nim
@@ -8,6 +8,8 @@
 #
 
 ## This module creates temporary files and directories.
+##
+## Experimental API, subject to change.
 
 import os, random
 
@@ -44,6 +46,8 @@ else:
 
 proc safeOpen(filename: string): File =
   ## Open files exclusively.
+  # xxx this should be clarified; it doesn't in particular prevent other processes
+  # from opening the file, at least currently.
   when defined(windows):
     let dwShareMode = FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE
     let dwCreation = CREATE_NEW
@@ -64,9 +68,13 @@ proc safeOpen(filename: string): File =
       discard close_osfandle(fileHandle)
       raiseOSError(osLastError(), filename)
   else:
+    # xxx we need a `proc toMode(a: FilePermission): Mode`, possibly by
+    # exposing fusion/filepermissions.fromFilePermissions to stdlib; then we need
+    # to expose a `perm` param so users can customize this (e.g. the temp file may
+    # need execute permissions), and figure out how to make the API cross platform.
+    let mode = Mode(S_IRUSR or S_IWUSR)
     let flags = posix.O_RDWR or posix.O_CREAT or posix.O_EXCL
-
-    let fileHandle = posix.open(filename, flags)
+    let fileHandle = posix.open(filename, flags, mode)
     if fileHandle == -1:
       raiseOSError(osLastError(), filename)
 
@@ -93,7 +101,6 @@ proc createTempFile*(prefix, suffix: string, dir = ""): tuple[fd: File, path: st
   ## If failing to create a temporary file, `IOError` will be raised.
   ##
   ## .. note:: It is the caller's responsibility to remove the file when no longer needed.
-  ##
   var dir = dir
   if dir.len == 0:
     dir = getTempDir()