From 4086b915ebf7bc1a4ad4cec202ffb63682d1bfd0 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Thu, 11 Aug 2011 17:17:50 -0400 Subject: [PATCH] Preserve mode_t of /etc/fstab and /etc/crypttab when updating Signed-off-by: David Zeuthen --- src/udiskslinuxblock.c | 140 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 126 insertions(+), 14 deletions(-) diff --git a/src/udiskslinuxblock.c b/src/udiskslinuxblock.c index cd9dc21..abc3a48 100644 --- a/src/udiskslinuxblock.c +++ b/src/udiskslinuxblock.c @@ -22,6 +22,10 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -485,6 +489,113 @@ out: return dest; } +/* ---------------------------------------------------------------------------------------------------- */ + +/* TODO: maybe move to GLib */ +static gboolean +_g_file_set_contents_full (const gchar *filename, + const gchar *contents, + gssize contents_len, + gint mode_for_new_file, + GError **error) +{ + gboolean ret; + struct stat statbuf; + gint mode; + gchar *tmpl; + gint fd; + FILE *f; + + ret = FALSE; + tmpl = NULL; + + if (stat (filename, &statbuf) != 0) + { + if (errno == ENOENT) + { + mode = mode_for_new_file; + } + else + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error stat(2)'ing %s: %m", + filename); + goto out; + } + } + else + { + mode = statbuf.st_mode; + } + + tmpl = g_strdup_printf ("%s.XXXXXX", filename); + fd = g_mkstemp_full (tmpl, O_RDWR, mode); + if (fd == -1) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error creating temporary file: %m"); + goto out; + } + + f = fdopen (fd, "w"); + if (f == NULL) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error calling fdopen: %m"); + g_unlink (tmpl); + goto out; + } + + if (contents_len < 0 ) + contents_len = strlen (contents); + if (fwrite (contents, 1, contents_len, f) != contents_len) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error calling fwrite on temp file: %m"); + fclose (f); + g_unlink (tmpl); + goto out; + } + + if (fsync (fileno (f)) != 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error calling fsync on temp file: %m"); + fclose (f); + g_unlink (tmpl); + goto out; + } + fclose (f); + + if (rename (tmpl, filename) != 0) + { + g_set_error (error, + G_IO_ERROR, + g_io_error_from_errno (errno), + "Error renaming temp file to final file: %m"); + g_unlink (tmpl); + goto out; + } + + ret = TRUE; + + out: + g_free (tmpl); + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + static gboolean add_remove_fstab_entry (GVariant *remove, GVariant *add, @@ -626,10 +737,11 @@ add_remove_fstab_entry (GVariant *remove, g_free (escaped_opts); } - if (!g_file_set_contents ("/etc/fstab", - str->str, - -1, - error) != 0) + if (!_g_file_set_contents_full ("/etc/fstab", + str->str, + -1, + 0644, /* mode to use if non-existant */ + error) != 0) goto out; ret = TRUE; @@ -851,11 +963,11 @@ add_remove_crypttab_entry (GVariant *remove, goto out; } - /* TODO: XXX: would like to use mode 0600 here - umask(3) at start-up? */ - if (!g_file_set_contents (filename, - add_passphrase_contents, - -1, - error)) + if (!_g_file_set_contents_full (filename, + add_passphrase_contents, + -1, + 0600, /* mode to use if non-existant */ + error)) { g_free (filename); goto out; @@ -869,11 +981,11 @@ add_remove_crypttab_entry (GVariant *remove, add_options); } - /* TODO: XXX: ugh, the mode is wrong.. umask(3) at start-up? */ - if (!g_file_set_contents ("/etc/crypttab", - str->str, - -1, - error) != 0) + if (!_g_file_set_contents_full ("/etc/crypttab", + str->str, + -1, + 0600, /* mode to use if non-existant */ + error) != 0) goto out; ret = TRUE; -- 2.7.4