summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/pure/memfiles.nim13
-rw-r--r--tests/stdlib/tmemfiles1.nim13
-rw-r--r--tests/stdlib/tmemfiles2.nim38
3 files changed, 60 insertions, 4 deletions
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 27b989597..b9c574944 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -32,8 +32,9 @@ type
     size*: int       ## size of the memory mapped file
 
     when defined(windows):
-      fHandle: int
-      mapHandle: int
+      fHandle: Handle
+      mapHandle: Handle
+      wasOpened: bool   ## only close if wasOpened
     else:
       handle: cint
 
@@ -115,7 +116,8 @@ proc open*(filename: string, mode: FileMode = fmRead,
     template callCreateFile(winApiProc, filename: expr): expr =
       winApiProc(
         filename,
-        if readonly: GENERIC_READ else: GENERIC_ALL,
+        # GENERIC_ALL != (GENERIC_READ or GENERIC_WRITE)
+        if readonly: GENERIC_READ else: GENERIC_READ or GENERIC_WRITE,
         FILE_SHARE_READ,
         nil,
         if newFileSize != -1: CREATE_ALWAYS else: OPEN_EXISTING,
@@ -172,6 +174,8 @@ proc open*(filename: string, mode: FileMode = fmRead,
       if mappedSize != -1: result.size = min(fileSize, mappedSize).int
       else: result.size = fileSize.int
 
+    result.wasOpened = true
+
   else:
     template fail(errCode: OSErrorCode, msg: expr) =
       rollback()
@@ -226,7 +230,7 @@ proc close*(f: var MemFile) =
   var lastErr: OSErrorCode
 
   when defined(windows):
-    if f.fHandle != INVALID_HANDLE_VALUE:
+    if f.fHandle != INVALID_HANDLE_VALUE and f.wasOpened:
       error = unmapViewOfFile(f.mem) == 0
       lastErr = osLastError()
       error = (closeHandle(f.mapHandle) == 0) or error
@@ -243,6 +247,7 @@ proc close*(f: var MemFile) =
   when defined(windows):
     f.fHandle = 0
     f.mapHandle = 0
+    f.wasOpened = false
   else:
     f.handle = 0
 
diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim
new file mode 100644
index 000000000..f7f39f5bc
--- /dev/null
+++ b/tests/stdlib/tmemfiles1.nim
@@ -0,0 +1,13 @@
+discard """
+  test that closing a closed file is ignored (no error raised)
+  file: "tmemfiles1.nim"
+"""
+import memfiles, os
+var
+  mm: MemFile
+  fn = "test.mmap"
+# Create a new file
+mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20)
+mm.close()
+mm.close()
+if fileExists(fn): removeFile(fn)
diff --git a/tests/stdlib/tmemfiles2.nim b/tests/stdlib/tmemfiles2.nim
new file mode 100644
index 000000000..04ae8429f
--- /dev/null
+++ b/tests/stdlib/tmemfiles2.nim
@@ -0,0 +1,38 @@
+discard """
+  test creating/reading/writing/changing memfiles
+  file: "tmemfiles2.nim"
+  output: '''Full read size: 20
+Half read size: 10 Data: Hello'''
+"""
+import memfiles, os
+var
+  mm, mm_full, mm_half: MemFile
+  fn = "test.mmap"
+  p: pointer
+
+if fileExists(fn): removeFile(fn)
+
+# Create a new file, data all zeros
+mm = memfiles.open(fn, mode = fmReadWrite, newFileSize = 20)
+mm.close()
+
+# read, change
+mm_full = memfiles.open(fn, mode = fmWrite, mappedSize = -1)
+echo "Full read size: ",mm_full.size
+p = mm_full.mapMem(fmReadWrite, 20, 0)
+var p2 = cast[cstring](p)
+p2[0] = 'H'
+p2[1] = 'e'
+p2[2] = 'l'
+p2[3] = 'l'
+p2[4] = 'o'
+p2[5] = '\0'
+mm_full.unmapMem(p, 20)
+mm_full.close()
+
+# read half, and verify data change
+mm_half = memfiles.open(fn, mode = fmRead, mappedSize = 10)
+echo "Half read size: ",mm_half.size, " Data: ", cast[cstring](mm_half.mem)
+mm_half.close()
+
+if fileExists(fn): removeFile(fn)