about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/file.lua24
-rw-r--r--src/liolib.c3
2 files changed, 26 insertions, 1 deletions
diff --git a/src/file.lua b/src/file.lua
index cd71f50..17e543c 100644
--- a/src/file.lua
+++ b/src/file.lua
@@ -23,8 +23,11 @@ end
 -- indicate you're done writing by calling :close()
 -- file will not be externally visible until :close()
 function start_writing(fs, filename)
+  if filename == nil then
+    error('start_writing requires two arguments: a file-system (nil for real disk) and a filename')
+  end
   local result = task.Channel:new()
-  local initial_filename = os.tmpname()
+  local initial_filename = temporary_filename_in_same_volume(filename)
   local outfile = io.open(initial_filename, 'w')
   if outfile == nil then return nil end
   result.close = function()
@@ -36,6 +39,25 @@ function start_writing(fs, filename)
   return result
 end
 
+function temporary_filename_in_same_volume(filename)
+  -- opening in same directory will hopefully keep it on the same volume,
+  -- so that a future rename works
+  local i = 1
+  while true do
+    temporary_filename = 'teliva_temp_'..filename..'_'..i
+    if io.open(temporary_filename) == nil then
+      -- file doesn't exist yet; create a placeholder and return it
+      local handle = io.open(temporary_filename, 'w')
+      if handle == nil then
+        error("this is unexpected; I can't create temporary files..")
+      end
+      handle:close()
+      return temporary_filename
+    end
+    i = i+1
+  end
+end
+
 function writing_task(outfile, chanin)
   while true do
     local line = chanin:recv()
diff --git a/src/liolib.c b/src/liolib.c
index a1a5b35..a53d8e6 100644
--- a/src/liolib.c
+++ b/src/liolib.c
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ncurses.h>
 
 #define liolib_c
 #define LUA_LIB
@@ -139,6 +140,8 @@ static int io_open (lua_State *L) {
   const char *caller = get_caller(L);
   if (file_operation_permitted(caller, filename, mode))
     *pf = fopen(filename, mode);
+  else if (is_equal(caller, "temporary_filename_in_same_volume"))
+    *pf = fopen(filename, mode);
   else if (is_equal(caller, "start_writing") || is_equal(caller, "start_reading")) {
     caller = get_caller_of_caller(L);
     if (file_operation_permitted(caller, filename, mode))