15 local log = require "util.logger".init("datamanager"); |
15 local log = require "util.logger".init("datamanager"); |
16 local io_open = io.open; |
16 local io_open = io.open; |
17 local os_remove = os.remove; |
17 local os_remove = os.remove; |
18 local os_rename = os.rename; |
18 local os_rename = os.rename; |
19 local tonumber = tonumber; |
19 local tonumber = tonumber; |
20 local tostring = tostring; |
|
21 local next = next; |
20 local next = next; |
22 local type = type; |
21 local type = type; |
23 local t_insert = table.insert; |
22 local t_insert = table.insert; |
24 local t_concat = table.concat; |
23 local t_concat = table.concat; |
25 local envloadfile = require"util.envload".envloadfile; |
24 local envloadfile = require"util.envload".envloadfile; |
29 local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) |
28 local path_separator = assert ( package.config:match ( "^([^\n]+)" ) , "package.config not in standard form" ) |
30 |
29 |
31 local prosody = prosody; |
30 local prosody = prosody; |
32 |
31 |
33 local raw_mkdir = lfs.mkdir; |
32 local raw_mkdir = lfs.mkdir; |
34 local function fallocate(f, offset, len) |
33 local atomic_append; |
35 -- This assumes that current position == offset |
|
36 local fake_data = (" "):rep(len); |
|
37 local ok, msg = f:write(fake_data); |
|
38 if not ok then |
|
39 return ok, msg; |
|
40 end |
|
41 f:seek("set", offset); |
|
42 return true; |
|
43 end; |
|
44 local ENOENT = 2; |
34 local ENOENT = 2; |
45 pcall(function() |
35 pcall(function() |
46 local pposix = require "util.pposix"; |
36 local pposix = require "util.pposix"; |
47 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask |
37 raw_mkdir = pposix.mkdir or raw_mkdir; -- Doesn't trample on umask |
48 fallocate = pposix.fallocate or fallocate; |
38 atomic_append = pposix.atomic_append; |
49 ENOENT = pposix.ENOENT or ENOENT; |
39 ENOENT = pposix.ENOENT or ENOENT; |
50 end); |
40 end); |
51 |
41 |
52 local _ENV = nil; |
42 local _ENV = nil; |
53 |
43 |
60 return s and (s:gsub("%%(%x%x)", urlcodes)); |
50 return s and (s:gsub("%%(%x%x)", urlcodes)); |
61 end |
51 end |
62 |
52 |
63 encode = function (s) |
53 encode = function (s) |
64 return s and (s:gsub("%W", function (c) return format("%%%02x", c:byte()); end)); |
54 return s and (s:gsub("%W", function (c) return format("%%%02x", c:byte()); end)); |
|
55 end |
|
56 end |
|
57 |
|
58 if not atomic_append then |
|
59 function atomic_append(f, data) |
|
60 local pos = f:seek(); |
|
61 if not f:write(data) or not f:flush() then |
|
62 f:seek("set", pos); |
|
63 f:write((" "):rep(#data)); |
|
64 f:flush(); |
|
65 return nil, "write-failed"; |
|
66 end |
|
67 return true; |
65 end |
68 end |
66 end |
69 end |
67 |
70 |
68 local _mkdir = {}; |
71 local _mkdir = {}; |
69 local function mkdir(path) |
72 local function mkdir(path) |
219 local function append(username, host, datastore, ext, data) |
222 local function append(username, host, datastore, ext, data) |
220 if type(data) ~= "string" then return; end |
223 if type(data) ~= "string" then return; end |
221 local filename = getpath(username, host, datastore, ext, true); |
224 local filename = getpath(username, host, datastore, ext, true); |
222 |
225 |
223 local ok; |
226 local ok; |
224 local f, msg = io_open(filename, "r+"); |
227 local f, msg, errno = io_open(filename, "r+"); |
225 if not f then |
228 if not f then |
226 return atomic_store(filename, data); |
229 return atomic_store(filename, data); |
227 -- File did probably not exist, let's create it |
230 -- File did probably not exist, let's create it |
228 end |
231 end |
229 |
232 |
230 local pos = f:seek("end"); |
233 local pos = f:seek("end"); |
231 ok, msg = fallocate(f, pos, #data); |
234 |
232 if not ok then |
235 ok, msg = atomic_append(f, data); |
233 log("warn", "fallocate() failed: %s", tostring(msg)); |
236 |
234 -- This doesn't work on every file system |
|
235 end |
|
236 |
|
237 if f:seek() ~= pos then |
|
238 log("debug", "fallocate() changed file position"); |
|
239 f:seek("set", pos); |
|
240 end |
|
241 |
|
242 ok, msg = f:write(data); |
|
243 if not ok then |
237 if not ok then |
244 f:close(); |
238 f:close(); |
245 return ok, msg, "write"; |
239 return ok, msg, "write"; |
246 end |
240 end |
247 |
241 |