aboutsummaryrefslogtreecommitdiffstats
path: root/util/datamanager.lua
diff options
context:
space:
mode:
Diffstat (limited to 'util/datamanager.lua')
-rw-r--r--util/datamanager.lua48
1 files changed, 21 insertions, 27 deletions
diff --git a/util/datamanager.lua b/util/datamanager.lua
index b825cb33..6edf7ac0 100644
--- a/util/datamanager.lua
+++ b/util/datamanager.lua
@@ -17,7 +17,6 @@ local io_open = io.open;
local os_remove = os.remove;
local os_rename = os.rename;
local tonumber = tonumber;
-local tostring = tostring;
local next = next;
local type = type;
local t_insert = table.insert;
@@ -31,21 +30,12 @@ local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.
local prosody = prosody;
local raw_mkdir = lfs.mkdir;
-local function fallocate(f, offset, len)
- -- This assumes that current position == offset
- local fake_data = (" "):rep(len);
- local ok, msg = f:write(fake_data);
- if not ok then
- return ok, msg;
- end
- f:seek("set", offset);
- return true;
-end;
+local atomic_append;
local ENOENT = 2;
pcall(function()
local pposix = require "util.pposix";
raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask
- fallocate = pposix.fallocate or fallocate;
+ atomic_append = pposix.atomic_append;
ENOENT = pposix.ENOENT or ENOENT;
end);
@@ -65,6 +55,19 @@ do
end
end
+if not atomic_append then
+ function atomic_append(f, data)
+ local pos = f:seek();
+ if not f:write(data) or not f:flush() then
+ f:seek("set", pos);
+ f:write((" "):rep(#data));
+ f:flush();
+ return nil, "write-failed";
+ end
+ return true;
+ end
+end
+
local _mkdir = {};
local function mkdir(path)
path = path:gsub("/", path_separator); -- TODO as an optimization, do this during path creation rather than here
@@ -220,26 +223,16 @@ local function append(username, host, datastore, ext, data)
if type(data) ~= "string" then return; end
local filename = getpath(username, host, datastore, ext, true);
- local ok;
- local f, msg = io_open(filename, "r+");
+ local f = io_open(filename, "r+");
if not f then
return atomic_store(filename, data);
-- File did probably not exist, let's create it
end
local pos = f:seek("end");
- ok, msg = fallocate(f, pos, #data);
- if not ok then
- log("warn", "fallocate() failed: %s", tostring(msg));
- -- This doesn't work on every file system
- end
- if f:seek() ~= pos then
- log("debug", "fallocate() changed file position");
- f:seek("set", pos);
- end
+ local ok, msg = atomic_append(f, data);
- ok, msg = f:write(data);
if not ok then
f:close();
return ok, msg, "write";
@@ -247,7 +240,7 @@ local function append(username, host, datastore, ext, data)
ok, msg = f:close();
if not ok then
- return ok, msg;
+ return ok, msg, "close";
end
return true, pos;
@@ -259,9 +252,10 @@ local function list_append(username, host, datastore, data)
-- save the datastore
data = "item(" .. serialize(data) .. ");\n";
- local ok, msg = append(username, host, datastore, "list", data);
+ local ok, msg, where = append(username, host, datastore, "list", data);
if not ok then
- log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
+ log("error", "Unable to write to %s storage ('%s' in %s) for user: %s@%s",
+ datastore, msg, where, username or "nil", host or "nil");
return ok, msg;
end
return true;