diff options
author | Kim Alvefur <zash@zash.se> | 2012-07-28 22:37:24 +0200 |
---|---|---|
committer | Kim Alvefur <zash@zash.se> | 2012-07-28 22:37:24 +0200 |
commit | 72f5f1529ccee122ba59710efec30c07eb27f209 (patch) | |
tree | 572134513556c9dca116bf6470cd34167ec00f3d /util/datamanager.lua | |
parent | 5d4399e9a5fe825170c766178059015a2ee0bd6a (diff) | |
download | prosody-72f5f1529ccee122ba59710efec30c07eb27f209.tar.gz prosody-72f5f1529ccee122ba59710efec30c07eb27f209.zip |
util.datamanager: Use pposix.fallocate() to make sure appends succeed. Also add a fallback fallocate()
Diffstat (limited to 'util/datamanager.lua')
-rw-r--r-- | util/datamanager.lua | 31 |
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 |