aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2016-01-13 00:19:20 +0100
committerPřemysl Janouch <p.janouch@gmail.com>2016-01-13 00:38:54 +0100
commit60dd23ab8f5d772bee38200395e54d640499d443 (patch)
treeaf3b16395b5ae2575da5407734109833afc73dd5
parent9e3cb2b6aa2db3ca0ea6a854fb3f89a163c84235 (diff)
downloadliberty-60dd23ab8f5d772bee38200395e54d640499d443.tar.gz
liberty-60dd23ab8f5d772bee38200395e54d640499d443.tar.xz
liberty-60dd23ab8f5d772bee38200395e54d640499d443.zip
Make writing files a bit safer
Especially configuration files.
-rw-r--r--liberty.c22
1 files changed, 19 insertions, 3 deletions
diff --git a/liberty.c b/liberty.c
index 9d5efd3..62eab4e 100644
--- a/liberty.c
+++ b/liberty.c
@@ -3379,11 +3379,11 @@ write_file (const char *filename, const struct str *data, struct error **e)
return false;
}
- errno = 0;
fwrite (data->str, data->len, 1, fp);
+ bool success = !ferror (fp) && !fflush (fp) && !fsync (fileno (fp));
fclose (fp);
- if (errno)
+ if (!success)
{
error_set (e, "writing to `%s' failed: %s", filename, strerror (errno));
return false;
@@ -3391,6 +3391,22 @@ write_file (const char *filename, const struct str *data, struct error **e)
return true;
}
+/// Wrapper for write_file() that makes sure that the new data has been written
+/// to disk in its entirety before overriding the old file
+static bool
+write_file_safe (const char *filename, const struct str *data, struct error **e)
+{
+ // XXX: ideally we would also open the directory, use *at() versions
+ // of functions and call fsync() on the directory as appropriate
+ char *temp = xstrdup_printf ("%s.new", filename);
+ bool success = write_file (temp, data, e);
+ if (success && !(success = !rename (temp, filename)))
+ error_set (e, "could not rename `%s' to `%s': %s",
+ temp, filename, strerror (errno));
+ free (temp);
+ return success;
+}
+
// --- Simple configuration ----------------------------------------------------
// The keys are stripped of surrounding whitespace, the values are not.
@@ -3482,7 +3498,7 @@ write_configuration_file (const char *path_hint, const struct str *data,
str_append (&path, "/" PROGRAM_NAME "/" PROGRAM_NAME ".conf");
}
- if (!write_file (path.str, data, e))
+ if (!write_file_safe (path.str, data, e))
{
str_free (&path);
return NULL;