diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/hostnamed.c | 57 | ||||
-rw-r--r-- | src/shell-utils.c | 201 | ||||
-rw-r--r-- | src/shell-utils.h | 13 |
3 files changed, 145 insertions, 126 deletions
diff --git a/src/hostnamed.c b/src/hostnamed.c index d910fb0..c21d875 100644 --- a/src/hostnamed.c +++ b/src/hostnamed.c @@ -20,7 +20,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <dbus/dbus-protocol.h> #include <glib.h> @@ -45,9 +44,11 @@ static OpenrcSettingsdHostnamedHostname1 *hostname1 = NULL; static gchar hostname[HOST_NAME_MAX + 1]; G_LOCK_DEFINE_STATIC (hostname); static gchar *static_hostname = NULL; +static GFile *static_hostname_file = NULL; G_LOCK_DEFINE_STATIC (static_hostname); static gchar *pretty_hostname = NULL; static gchar *icon_name = NULL; +static GFile *machine_info_file = NULL; G_LOCK_DEFINE_STATIC (machine_info); static gboolean @@ -174,25 +175,7 @@ on_handle_set_static_hostname (OpenrcSettingsdHostnamedHostname1 *hostname1, if (!hostname_is_valid (name)) name = "localhost"; - confd_file = shell_utils_trivial_new (SYSCONFDIR "/conf.d/hostname", &err); - if (confd_file == NULL) { - g_dbus_method_invocation_return_gerror (invocation, err); - G_UNLOCK (static_hostname); - goto end; - } - - if (!shell_utils_trivial_set_variable (confd_file, "hostname", name, FALSE) && - !shell_utils_trivial_set_variable (confd_file, "HOSTNAME", name, FALSE) && - !shell_utils_trivial_set_variable (confd_file, "hostname", name, TRUE)) - { - g_dbus_method_invocation_return_dbus_error (invocation, - DBUS_ERROR_FAILED, - "Failed to set static hostname in " SYSCONFDIR "/conf.d/hostname"); - G_UNLOCK (static_hostname); - goto end; - } - - if (!shell_utils_trivial_save (confd_file, &err)) { + if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", name, NULL)) { g_dbus_method_invocation_return_gerror (invocation, err); G_UNLOCK (static_hostname); goto end; @@ -240,24 +223,10 @@ on_handle_set_machine_info (OpenrcSettingsdHostnamedHostname1 *hostname1, if (name == NULL) name = ""; - confd_file = shell_utils_trivial_new (SYSCONFDIR "/machine-info", &err); - if (confd_file == NULL) { - g_dbus_method_invocation_return_gerror (invocation, err); - G_UNLOCK (machine_info); - goto end; - } - - if ((is_pretty_hostname && !shell_utils_trivial_set_variable (confd_file, "PRETTY_HOSTNAME", name, TRUE)) || - (!is_pretty_hostname && !shell_utils_trivial_set_variable (confd_file, "ICON_NAME", name, TRUE))) - { - g_dbus_method_invocation_return_dbus_error (invocation, - DBUS_ERROR_FAILED, - "Failed to value in " SYSCONFDIR "/machine-info"); - G_UNLOCK (machine_info); - goto end; - } - - if (!shell_utils_trivial_save (confd_file, &err)) { + if ((is_pretty_hostname && + !shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, name, NULL)) || + (!is_pretty_hostname && + !shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, name, NULL))) { g_dbus_method_invocation_return_gerror (invocation, err); G_UNLOCK (machine_info); goto end; @@ -354,13 +323,16 @@ hostnamed_init (gboolean _read_only) hostname[0] = 0; } - static_hostname = shell_utils_source_var (SYSCONFDIR "/conf.d/hostname", "${hostname-${HOSTNAME-localhost}}", &err); + static_hostname_file = g_file_new_for_path (SYSCONFDIR "/conf.d/hostname"); + machine_info_file = g_file_new_for_path (SYSCONFDIR "/machine-info"); + + static_hostname = shell_utils_source_var (static_hostname_file, "${hostname-${HOSTNAME-localhost}}", &err); if (err != NULL) { g_debug ("%s", err->message); g_error_free (err); err = NULL; } - pretty_hostname = shell_utils_source_var (SYSCONFDIR "/machine-info", "${PRETTY_HOSTNAME}", &err); + pretty_hostname = shell_utils_source_var (machine_info_file, "${PRETTY_HOSTNAME}", &err); if (pretty_hostname == NULL) pretty_hostname = g_strdup (""); if (err != NULL) { @@ -368,7 +340,7 @@ hostnamed_init (gboolean _read_only) g_error_free (err); err = NULL; } - icon_name = shell_utils_source_var (SYSCONFDIR "/machine-info", "${ICON_NAME}", &err); + icon_name = shell_utils_source_var (machine_info_file, "${ICON_NAME}", &err); if (icon_name == NULL) icon_name = g_strdup (""); if (err != NULL) { @@ -402,4 +374,7 @@ hostnamed_destroy (void) g_free (static_hostname); g_free (pretty_hostname); g_free (icon_name); + + g_object_unref (static_hostname_file); + g_object_unref (machine_info_file); }
\ No newline at end of file diff --git a/src/shell-utils.c b/src/shell-utils.c index 6371ef1..4f76fee 100644 --- a/src/shell-utils.c +++ b/src/shell-utils.c @@ -16,15 +16,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> +#include <stdarg.h> #include <string.h> -#include <unistd.h> -#include <sys/stat.h> #include <glib.h> -#include <glib/gstdio.h> #include <gio/gio.h> #include "shell-utils.h" @@ -53,23 +48,53 @@ struct ShellEntry { }; gchar * -shell_utils_source_var (const gchar *filename, +shell_utils_source_var (GFile *file, const gchar *variable, GError **error) { gchar *argv[4] = { "sh", "-c", NULL, NULL }; - gchar *quoted_filename = NULL; + gchar *filename, *quoted_filename; gchar *output = NULL; + GFileInfo *info; + const GFileAttributeInfo *attribute_info; + + filename = g_file_get_path (file); + if ((info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_ACCESS_CAN_READ, G_FILE_QUERY_INFO_NONE, NULL, error)) == NULL) { + g_prefix_error (error, "Unable to source '%s': ", filename); + goto out; + } + + if (g_file_info_get_file_type (info) != G_FILE_TYPE_REGULAR && + g_file_info_get_file_type (info) != G_FILE_TYPE_SYMBOLIC_LINK) { + g_propagate_error (error, + g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, + "Unable to source '%s': not a regular file", filename)); + goto out; + } + + if (!g_file_info_get_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) { + g_propagate_error (error, + g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES, + "Unable to source '%s': permission denied", filename)); + goto out; + } quoted_filename = g_shell_quote (filename); argv[2] = g_strdup_printf (". %s; echo -n %s", quoted_filename, variable); - g_free (quoted_filename); - if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &output, NULL, NULL, error)) { - g_prefix_error (error, "Unable to source '%s': ", filename); - } - g_free (argv[2]); + if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &output, NULL, NULL, error)) { + g_prefix_error (error, "Unable to source '%s': ", filename); + } + + out: + if (filename != NULL) + g_free (filename); + if (quoted_filename != NULL) + g_free (quoted_filename); + if (info != NULL) + g_object_unref (info); + if (argv[2] != NULL) + g_free (argv[2]); return output; } @@ -92,6 +117,8 @@ shell_utils_trivial_free (ShellUtilsTrivial *trivial) if (trivial == NULL) return; + if (trivial->file != NULL) + g_object_unref (trivial->file); if (trivial->filename != NULL) g_free (trivial->filename); if (trivial->entry_list != NULL) @@ -100,7 +127,7 @@ shell_utils_trivial_free (ShellUtilsTrivial *trivial) } ShellUtilsTrivial * -shell_utils_trivial_new (const gchar *filename, +shell_utils_trivial_new (GFile *file, GError **error) { gchar *filebuf = NULL; @@ -108,20 +135,23 @@ shell_utils_trivial_new (const gchar *filename, GError *local_err; gchar *s; - g_assert (filename != NULL); + if (file == NULL) + return NULL; ret = g_new0 (ShellUtilsTrivial, 1); - ret->filename = g_strdup (filename); + g_object_ref (file); + ret->file = file; + ret->filename = g_file_get_path (file); - if (!g_file_get_contents (filename, &filebuf, NULL, &local_err)) { + if (!g_file_load_contents (file, NULL, &filebuf, NULL, NULL, &local_err)) { if (local_err != NULL) { /* Inability to parse or open is a failure; file not existing at all is *not* a failure */ - if (local_err->code == G_FILE_ERROR_NOENT) { + if (local_err->code == G_IO_ERROR_NOT_FOUND) { g_error_free (local_err); return ret; } - g_propagate_prefixed_error (error, local_err, "Unable to read '%s':", filename); + g_propagate_prefixed_error (error, local_err, "Unable to read '%s':", ret->filename); } shell_utils_trivial_free (ret); return NULL; @@ -261,7 +291,7 @@ no_match: match_info = NULL; g_propagate_error (error, g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, - "Unable to parse '%s'", filename)); + "Unable to parse '%s'", ret->filename)); shell_utils_trivial_free (ret); return NULL; } @@ -317,86 +347,91 @@ gboolean shell_utils_trivial_save (ShellUtilsTrivial *trivial, GError **error) { + gboolean ret = FALSE; GList *curr = NULL; - gchar *temp_filename = NULL; - gint fd; - gboolean retval = FALSE; - GStatBuf stat_buf; - gint mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; /* 644 by default */ + GFileOutputStream *os; - g_assert (trivial != NULL); - g_assert (trivial->filename != NULL); - - /* If the file exists, preserve its mode */ - if (!g_lstat (trivial->filename, &stat_buf)) - mode = stat_buf.st_mode; - - temp_filename = g_strdup_printf ("%s.XXXXXX", trivial->filename); - - if ((fd = g_mkstemp_full (temp_filename, O_WRONLY, mode)) < 0) { - int errsv = errno; - GFileError file_err; - file_err = g_file_error_from_errno (errsv); - g_propagate_prefixed_error (error, - g_error_copy ((GError*)&file_err), - "Unable to write '%s': Unable to create temp file: ", - trivial->filename); + g_assert (trivial != NULL && trivial->file != NULL && trivial->filename != NULL); + if ((os = g_file_replace (trivial->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error)) == NULL) { + g_prefix_error (error, "Unable to save '%s': ", trivial->filename); goto out; } for (curr = trivial->entry_list; curr != NULL; curr = curr->next) { struct ShellEntry *entry; - ssize_t written; + gsize written; entry = (struct ShellEntry *)(curr->data); - written = write (fd, entry->string, strlen (entry->string)); - int errsv = errno; - if (written < strlen (entry->string)) { - if (written < 0) { - int errsv = errno; - GFileError file_err; - file_err = g_file_error_from_errno (errsv); - g_propagate_prefixed_error (error, - g_error_copy ((GError*)&file_err), - "Unable to write temp file '%s': ", - temp_filename); - } else { - g_propagate_error (error, - g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, - "Unable to write temp file '%s'", temp_filename)); - } - close (fd); + if (!g_output_stream_write_all (G_OUTPUT_STREAM (os), entry->string, strlen (entry->string), &written, NULL, error)) { + g_prefix_error (error, "Unable to save '%s': ", trivial->filename); goto out; } } - if (fsync (fd) || close (fd)) { - int errsv = errno; - GFileError file_err; - file_err = g_file_error_from_errno (errsv); - g_propagate_prefixed_error (error, - g_error_copy ((GError*)&file_err), - "Unable to sync or close temp file '%s': ", - temp_filename); - close (fd); + + if (!g_output_stream_close (G_OUTPUT_STREAM (os), NULL, error)) { + g_prefix_error (error, "Unable to save '%s': ", trivial->filename); + g_output_stream_close (G_OUTPUT_STREAM (os), NULL, NULL); goto out; } + ret = TRUE; + + out: + if (os) + g_object_unref (os); + return ret; +} - if (g_rename (temp_filename, trivial->filename) < 0) { - int errsv = errno; - GFileError file_err; - file_err = g_file_error_from_errno (errsv); - g_propagate_prefixed_error (error, - g_error_copy ((GError*)&file_err), - "Unable to copy '%s' to '%s': ", - temp_filename, trivial->filename); +gboolean +shell_utils_trivial_set_and_save (GFile *file, + GError **error, + const gchar *first_var_name, + const gchar *first_alt_var_name, + const gchar *first_value, + ...) +{ + va_list ap; + ShellUtilsTrivial *trivial; + gboolean ret = FALSE; + const gchar *var_name, *alt_var_name, *value; + + va_start (ap, first_value); + if ((trivial = shell_utils_trivial_new (file, error)) == NULL) goto out; - } - retval = TRUE; + + var_name = first_var_name; + alt_var_name = first_alt_var_name; + value = first_value; + do { + if (alt_var_name == NULL) { + if (!shell_utils_trivial_set_variable (trivial, var_name, value, TRUE)) { + g_propagate_error (error, + g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, + "Unable to set %s in '%s'", var_name, trivial->filename)); + goto out; + } + } else { + if (!shell_utils_trivial_set_variable (trivial, var_name, value, FALSE) && + !shell_utils_trivial_set_variable (trivial, alt_var_name, value, FALSE) && + !shell_utils_trivial_set_variable (trivial, var_name, value, TRUE)) { + g_propagate_error (error, + g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, + "Unable to set %s or %s in '%s'", var_name, alt_var_name, trivial->filename)); + goto out; + } + } + } while ((var_name = va_arg (ap, const gchar*)) != NULL ? + alt_var_name = va_arg (ap, const gchar*), value = va_arg (ap, const gchar*), 1 : 0); + + if (!shell_utils_trivial_save (trivial, error)) + goto out; + + ret = TRUE; out: - g_free (temp_filename); - g_unlink (temp_filename); - return retval; + va_end (ap); + if (trivial != NULL) + shell_utils_trivial_free (trivial); + return ret; } void diff --git a/src/shell-utils.h b/src/shell-utils.h index 861cd87..5e1863d 100644 --- a/src/shell-utils.h +++ b/src/shell-utils.h @@ -20,17 +20,19 @@ #define _SHELL_UTILS_H_ #include <glib.h> +#include <gio/gio.h> typedef struct _ShellUtilsTrivial ShellUtilsTrivial; struct _ShellUtilsTrivial { + GFile *file; gchar *filename; GList *entry_list; }; gchar * -shell_utils_source_var (const gchar *filename, +shell_utils_source_var (GFile *file, const gchar *variable, GError **error); @@ -41,7 +43,7 @@ void shell_utils_destroy (void); ShellUtilsTrivial * -shell_utils_trivial_new (const gchar *filename, +shell_utils_trivial_new (GFile *file, GError **error); void @@ -57,4 +59,11 @@ gboolean shell_utils_trivial_save (ShellUtilsTrivial *trivial, GError **error); +gboolean +shell_utils_trivial_set_and_save (GFile *file, + GError **error, + const gchar *first_var_name, + const gchar *first_alt_var_name, + const gchar *first_value, + ...); #endif |