aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2012-07-28 22:37:24 +0200
committerKim Alvefur <zash@zash.se>2012-07-28 22:37:24 +0200
commit72f5f1529ccee122ba59710efec30c07eb27f209 (patch)
tree572134513556c9dca116bf6470cd34167ec00f3d
parent5d4399e9a5fe825170c766178059015a2ee0bd6a (diff)
downloadprosody-72f5f1529ccee122ba59710efec30c07eb27f209.tar.gz
prosody-72f5f1529ccee122ba59710efec30c07eb27f209.zip
util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
-rw-r--r--util/datamanager.lua31
1 files changed, 27 insertions, 4 deletions
diff --git a/util/datamanager.lua b/util/datamanager.lua
index 23a2d74f..29a5b994 100644
--- a/util/datamanager.lua
+++ b/util/datamanager.lua
@@ -21,17 +21,33 @@ local next = next;
local t_insert = table.insert;
local append = require "util.serialization".append;
local envloadfile = require"util.envload".envloadfile;
+local serialize = require "util.serialization".serialize;
local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) -- Extract directory seperator from package.config (an undocumented string that comes with lua)
local lfs = require "lfs";
local prosody = prosody;
local raw_mkdir;
+local fallocate;
if prosody.platform == "posix" then
raw_mkdir = require "util.pposix".mkdir; -- Doesn't trample on umask
+ fallocate = require "util.pposix".fallocate;
else
raw_mkdir = lfs.mkdir;
end
+if not fallocate then -- Fallback
+ 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(offset);
+ return true;
+ end
+end
+
module "datamanager"
---- utils -----
@@ -165,14 +181,21 @@ function list_append(username, host, datastore, data)
if not data then return; end
if callback(username, host, datastore) == false then return true; end
-- save the datastore
- local f, msg = io_open(getpath(username, host, datastore, "list", true), "a+");
+ local f, msg = io_open(getpath(username, host, datastore, "list", true), "a");
if not f then
log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
return;
end
- f:write("item(");
- append(f, data);
- f:write(");\n");
+ local data = "item(" .. serialize(data) .. ");\n";
+ local pos = f:seek("end");
+ local ok, msg = fallocate(f, pos, #data);
+ f:seek("set", pos);
+ if ok then
+ f:write(data);
+ else
+ log("error", "Unable to write to %s storage ('%s') for user: %s@%s", datastore, msg, username or "nil", host or "nil");
+ return ok, msg;
+ end
f:close();
return true;
end