summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/memfiles.nim26
1 files changed, 21 insertions, 5 deletions
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 810223d72..d1a006eee 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -42,9 +42,10 @@ type
       wasOpened*: bool     ## **Caution**: Windows specific public field.
     else:
       handle*: cint        ## **Caution**: Posix specific public field.
+      flags: cint          ## **Caution**: Platform specific private field.
 
 proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
-             mappedSize = -1, offset = 0): pointer =
+             mappedSize = -1, offset = 0, mapFlags = cint(-1)): pointer =
   ## returns a pointer to a mapped portion of MemFile `m`
   ##
   ## ``mappedSize`` of ``-1`` maps to the whole file, and
@@ -65,11 +66,17 @@ proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
       raiseOSError(osLastError())
   else:
     assert mappedSize > 0
+
+    m.flags = if mapFlags == cint(-1): MAP_SHARED else: mapFlags
+    #Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set
+    if int(m.flags and MAP_PRIVATE) == 0:
+      m.flags = m.flags or MAP_SHARED
+
     result = mmap(
       nil,
       mappedSize,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
+      m.flags,
       m.handle, offset)
     if result == cast[pointer](MAP_FAILED):
       raiseOSError(osLastError())
@@ -90,7 +97,7 @@ proc unmapMem*(f: var MemFile, p: pointer, size: int) =
 
 proc open*(filename: string, mode: FileMode = fmRead,
            mappedSize = -1, offset = 0, newFileSize = -1,
-           allowRemap = false): MemFile =
+           allowRemap = false, mapFlags = cint(-1)): MemFile =
   ## opens a memory mapped file. If this fails, ``OSError`` is raised.
   ##
   ## ``newFileSize`` can only be set if the file does not exist and is opened
@@ -105,6 +112,10 @@ proc open*(filename: string, mode: FileMode = fmRead,
   ## ``allowRemap`` only needs to be true if you want to call ``mapMem`` on
   ## the resulting MemFile; else file handles are not kept open.
   ##
+  ## ``mapFlags`` allows callers to override default choices for memory mapping
+  ## flags with a bitwise mask of a variety of likely platform-specific flags
+  ## which may be ignored or even cause `open` to fail if misspecified.
+  ##
   ## Example:
   ##
   ## .. code-block:: nim
@@ -245,11 +256,16 @@ proc open*(filename: string, mode: FileMode = fmRead,
       else:
         fail(osLastError(), "error getting file size")
 
+    result.flags = if mapFlags == cint(-1): MAP_SHARED else: mapFlags
+    #Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set
+    if int(result.flags and MAP_PRIVATE) == 0:
+      result.flags = result.flags or MAP_SHARED
+
     result.mem = mmap(
       nil,
       result.size,
       if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      if readonly: (MAP_PRIVATE or MAP_POPULATE) else: (MAP_SHARED or MAP_POPULATE),
+      result.flags,
       result.handle,
       offset)
 
@@ -305,7 +321,7 @@ when defined(posix) or defined(nimdoc):
         if munmap(f.mem, f.size) != 0:
           raiseOSError(osLastError())
         let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE,
-                            MAP_SHARED or MAP_POPULATE, f.handle, 0)
+                           f.flags, f.handle, 0)
         if newAddr == cast[pointer](MAP_FAILED):
           raiseOSError(osLastError())
       f.mem = newAddr