Changeset

5050:2ad43c183d00

Merge with Zash
author Matthew Wild <mwild1@gmail.com>
date Sun, 29 Jul 2012 02:28:25 +0100
parents 5047:aab64739022e (current diff) 5049:5d685f123332 (diff)
children 5051:71253db26fda
files
diffstat 2 files changed, 35 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/configure	Sun Jul 29 02:27:07 2012 +0100
+++ b/configure	Sun Jul 29 02:28:25 2012 +0100
@@ -96,6 +96,7 @@
 	LUA_SUFFIX_SET=yes
 	LUA_INCDIR=/usr/include/lua5.1;
 	LUA_INCDIR_SET=yes
+	CFLAGS="$CFLAGS -D_GNU_SOURCE"
 	fi
 	if [ "$OSTYPE" = "macosx" ]
 	then LUA_INCDIR=/usr/local/include;
@@ -110,6 +111,7 @@
         LUA_LIBDIR=/usr/local/lib
         LUA_LIBDIR_SET=yes
         CFLAGS="-Wall -fPIC"
+        CFLAGS="$CFLAGS -D_GNU_SOURCE"
         LDFLAGS="-shared"
         fi
         if [ "$OSTYPE" = "freebsd" -o "$OSTYPE" = "openbsd" ]
--- a/util/datamanager.lua	Sun Jul 29 02:27:07 2012 +0100
+++ b/util/datamanager.lua	Sun Jul 29 02:28:25 2012 +0100
@@ -15,11 +15,12 @@
 local log = require "util.logger".init("datamanager");
 local io_open = io.open;
 local os_remove = os.remove;
+local os_rename = os.rename;
 local tostring, tonumber = tostring, tonumber;
 local error = error;
 local next = next;
 local t_insert = table.insert;
-local append = require "util.serialization".append;
+local t_concat = table.concat;
 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)
@@ -149,6 +150,28 @@
 	return ret;
 end
 
+local function atomic_store(filename, data)
+	local scratch = filename.."~";
+	local f, ok, msg;
+	repeat
+		f, msg = io_open(scratch, "w");
+		if not f then break end
+
+		ok, msg = f:write(data);
+		if not ok then break end
+
+		ok, msg = f:close();
+		if not ok then break end
+
+		return os_rename(scratch, filename);
+	until false;
+
+	-- Cleanup
+	if f then f:close(); end
+	os_remove(scratch);
+	return nil, msg;
+end
+
 function store(username, host, datastore, data)
 	if not data then
 		data = {};
@@ -160,14 +183,12 @@
 	end
 
 	-- save the datastore
-	local f, msg = io_open(getpath(username, host, datastore, nil, true), "w+");
-	if not f then
+	local d = "return " .. serialize(data) .. ";\n";
+	local ok, msg = atomic_store(getpath(username, host, datastore, nil, true), d);
+	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");
 		return nil, "Error saving to storage";
 	end
-	f:write("return ");
-	append(f, data);
-	f:close();
 	if next(data) == nil then -- try to delete empty datastore
 		log("debug", "Removing empty %s datastore for user %s@%s", datastore, username or "nil", host or "nil");
 		os_remove(getpath(username, host, datastore));
@@ -206,17 +227,15 @@
 	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), "w+");
-	if not f then
+	local d = {};
+	for _, item in ipairs(data) do
+		d[#d+1] = "item(" .. serialize(item) .. ");\n";
+	end
+	local ok, msg = atomic_store(getpath(username, host, datastore, "list", true), t_concat(d));
+	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");
 		return;
 	end
-	for _, d in ipairs(data) do
-		f:write("item(");
-		append(f, d);
-		f:write(");\n");
-	end
-	f:close();
 	if next(data) == nil then -- try to delete empty datastore
 		log("debug", "Removing empty %s datastore for user %s@%s", datastore, username or "nil", host or "nil");
 		os_remove(getpath(username, host, datastore, "list"));