aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Rostovtsev <tetromino@gentoo.org>2012-02-05 01:43:59 -0500
committerAlexandre Rostovtsev <tetromino@gentoo.org>2012-02-05 01:43:59 -0500
commit66ab55afd15550e937972bf980336d1c51246165 (patch)
treee7353259056e99678ab3868cb886837870f383d0
parentGStaticMutex is deprecated in glib-2.31 (diff)
downloadopenrc-settingsd-66ab55afd15550e937972bf980336d1c51246165.tar.gz
openrc-settingsd-66ab55afd15550e937972bf980336d1c51246165.tar.bz2
openrc-settingsd-66ab55afd15550e937972bf980336d1c51246165.zip
Port to GFile, and add shell_utils_trivial_set_and_save() to simplify on_handle_set_* callbacks
-rw-r--r--TODO4
-rw-r--r--src/hostnamed.c57
-rw-r--r--src/shell-utils.c201
-rw-r--r--src/shell-utils.h13
4 files changed, 145 insertions, 130 deletions
diff --git a/TODO b/TODO
index 530ec81..62ec523 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,3 @@
-Use GFile for file I/O to take advantage of built-in temporary handling.
-
-Refactor on_handle_set_* callbacks (lots of code duplication currently).
-
Source /etc/rc.conf after /etc/conf.d/$service; do something intelligent
if the relevant variable is set in /etc/rc.conf (go to read-only mode?)
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