diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2022-03-07 19:14:02 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2022-03-07 19:14:02 -0800 |
commit | a0674f7b85430201ab40b73d775781d9eeeed065 (patch) | |
tree | ab520d62f8bf89ae1f0b79e49986bde7f92bb6b5 /src/file.lua | |
parent | 88827db20d7a2d1acde328f0b77351475d516d4a (diff) | |
download | teliva-a0674f7b85430201ab40b73d775781d9eeeed065.tar.gz |
hokey primitive to create temporary file
The trouble with os.tmpname() is that it always creates in /tmp. If /tmp is in a different volume from our real filename, os.rename() will fail. This new primitive doesn't support primitive paths yet. I'm also again nervous about the security implications of my whole approach. What if we create an inner function called start_writing? Would we be able to do anything inside it? I'm starting to suspect this whole approach of going by caller name is broken. An app could also create inner functions called 'main'..
Diffstat (limited to 'src/file.lua')
-rw-r--r-- | src/file.lua | 24 |
1 files changed, 23 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() |