On Tue, May 6, 2008 at 2:07 PM, David Rees <[EMAIL PROTECTED]> wrote:
> Ah, missed that. I did see a few other places where it appears that
> config.xml is written besides through the write_config routine...
> Modifying write_config to update the config file atomically will be
> straight forward and should cover most of the cases where the file is
> commonly written.
OK, attached is a patch to /etc/config.inc that makes sure that the
config.xml and config.cache is updated atomically. The patch adds a
function function "write_safe_file" with 3 arguments: $file, $content,
$force_binary.
Tested on my local pfSense 1.2 box here, seems to work OK.
Let me know what you think!
If the patches I submitted look OK, do you think they'll make it into 1.2.1?
-Dave
--- config.inc.orig 2008-02-14 10:41:55.000000000 -0800
+++ config.inc 2008-05-06 14:23:24.000000000 -0700
@@ -1061,11 +1061,9 @@
conf_mount_rw();
/* write new configuration */
- $fd = fopen("{$g['cf_conf_path']}/config.xml", "w");
- if (!$fd)
+ if (!write_safe_file("{$g['cf_conf_path']}/config.xml", $xmlconfig, false)) {
die("Unable to open {$g['cf_conf_path']}/config.xml for writing in write_config()\n");
- fwrite($fd, $xmlconfig);
- fclose($fd);
+ }
if($g['platform'] == "embedded") {
cleanup_backupcache(5);
@@ -1082,11 +1080,7 @@
$config = parse_xml_config("{$g['conf_path']}/config.xml", $g['xml_rootobj']);
/* write config cache */
- $fd = @fopen("{$g['tmp_path']}/config.cache", "wb");
- if ($fd) {
- fwrite($fd, serialize($config));
- fclose($fd);
- }
+ write_safe_file("{$g['tmp_path']}/config.cache", serialize($config), true);
/* tell kernel to sync fs data */
mwexec("/bin/sync");
@@ -1096,6 +1090,45 @@
return $config;
}
+/****f* config/write_safe_file
+ * NAME
+ * write_safe_file - Write a file out atomically
+ * DESCRIPTION
+ * write_safe_file() Writes a file out atomically by first writing to a
+ * temporary file of the same name but ending with the pid of the current
+ * process, them renaming the temporary file over the original.
+ * INPUTS
+ * $filename - string containing the filename of the file to write
+ * $content - string containing the file content to write to file
+ * $force_binary - boolean denoting whether we should force binary
+ * mode writing.
+ * RESULT
+ * boolean - true if successful, false if not
+ ******/
+function write_safe_file($file, $content, $force_binary) {
+ $tmp_file = $file . "." . getmypid();
+ $write_mode = $force_binary ? "wb" : "w";
+
+ $fd = fopen($tmp_file, $write_mode);
+ if (!$fd) {
+ // Unable to open temporary file for writing
+ return false;
+ }
+ if (!fwrite($fd, $content)) {
+ // Unable to write to temporary file
+ fclose($fd);
+ return false;
+ }
+ fclose($fd);
+
+ if (!rename($tmp_file, $file)) {
+ // Unable to move temporary file to original
+ unlink($tmp_file);
+ return false;
+ }
+ return true;
+}
+
/****f* config/reset_factory_defaults
* NAME
* reset_factory_defaults - Reset the system to its default configuration.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]