From bba0de15760e43cd75795e9105e504ae5ee5efed Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Tue, 9 Aug 2011 15:16:04 -0400 Subject: [PATCH] Add missing files Signed-off-by: David Zeuthen --- src/udisksfstabentry.c | 252 +++++++++++++++++++++++++++++ src/udisksfstabentry.h | 44 +++++ src/udisksfstabmonitor.c | 414 +++++++++++++++++++++++++++++++++++++++++++++++ src/udisksfstabmonitor.h | 38 +++++ 4 files changed, 748 insertions(+) create mode 100644 src/udisksfstabentry.c create mode 100644 src/udisksfstabentry.h create mode 100644 src/udisksfstabmonitor.c create mode 100644 src/udisksfstabmonitor.h diff --git a/src/udisksfstabentry.c b/src/udisksfstabentry.c new file mode 100644 index 0000000..6ec9eaf --- /dev/null +++ b/src/udisksfstabentry.c @@ -0,0 +1,252 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "udisksfstabentry.h" +#include "udisksprivate.h" + +/** + * SECTION:udisksfstabentry + * @title: UDisksFstabEntry + * @short_description: Object corresponding to an entry in the fstab file + * + * Object corresponding to an entry in the + * /etc/fstab file. You cannot instantiate this + * type yourself – use #UDisksFstabMonitor. + */ + +/** + * UDisksFstabEntry: + * + * The #UDisksFstabEntry structure contains only private data and should + * only be accessed using the provided API. + */ +struct _UDisksFstabEntry +{ + GObject parent_instance; + + gchar *fsname; + gchar *dir; + gchar *type; + gchar *opts; + gint freq; + gint passno; +}; + +typedef struct _UDisksFstabEntryClass UDisksFstabEntryClass; + +struct _UDisksFstabEntryClass +{ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE (UDisksFstabEntry, udisks_fstab_entry, G_TYPE_OBJECT); + +static void +udisks_fstab_entry_finalize (GObject *object) +{ + UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (object); + + g_free (entry->fsname); + g_free (entry->dir); + g_free (entry->type); + g_free (entry->opts); + + if (G_OBJECT_CLASS (udisks_fstab_entry_parent_class)->finalize) + G_OBJECT_CLASS (udisks_fstab_entry_parent_class)->finalize (object); +} + +static void +udisks_fstab_entry_init (UDisksFstabEntry *fstab_entry) +{ +} + +static void +udisks_fstab_entry_class_init (UDisksFstabEntryClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = udisks_fstab_entry_finalize; +} + +UDisksFstabEntry * +_udisks_fstab_entry_new (const struct mntent *mntent) +{ + UDisksFstabEntry *entry; + + entry = UDISKS_FSTAB_ENTRY (g_object_new (UDISKS_TYPE_FSTAB_ENTRY, NULL)); + entry->fsname = g_strdup (mntent->mnt_fsname); + entry->dir = g_strdup (mntent->mnt_dir); + entry->type = g_strdup (mntent->mnt_type); + entry->opts = g_strdup (mntent->mnt_opts); + entry->freq = mntent->mnt_freq; + entry->passno = mntent->mnt_passno; + + return entry; +} + +/** + * udisks_fstab_entry_compare: + * @entry: A #UDisksFstabEntry + * @other_entry: Another #UDisksFstabEntry. + * + * Comparison function for comparing two #UDisksFstabEntry objects. + * + * Returns: Negative value if @entry < @other_entry; zero if @entry = @other_entry; positive value if @entry > @other_entry. + */ +gint +udisks_fstab_entry_compare (UDisksFstabEntry *entry, + UDisksFstabEntry *other_entry) +{ + gint ret; + + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), 0); + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (other_entry), 0); + + ret = g_strcmp0 (other_entry->fsname, entry->fsname); + if (ret != 0) + goto out; + + ret = g_strcmp0 (other_entry->dir, entry->dir); + if (ret != 0) + goto out; + + ret = g_strcmp0 (other_entry->type, entry->type); + if (ret != 0) + goto out; + + ret = g_strcmp0 (other_entry->opts, entry->opts); + if (ret != 0) + goto out; + + ret = entry->freq - other_entry->freq; + if (ret != 0) + goto out; + + ret = entry->passno - other_entry->passno; + + out: + return ret; +} + +/** + * udisks_fstab_entry_get_fsname: + * @entry: A #UDisksFstabEntry. + * + * Gets the fsname field of @entry. + * + * Returns: The fsname field. + */ +const gchar * +udisks_fstab_entry_get_fsname (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), NULL); + return entry->fsname; +} + +/** + * udisks_fstab_entry_get_dir: + * @entry: A #UDisksFstabEntry. + * + * Gets the dir field of @entry. + * + * Returns: The dir field. + */ +const gchar * +udisks_fstab_entry_get_dir (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), NULL); + return entry->dir; +} + +/** + * udisks_fstab_entry_get_fstype: + * @entry: A #UDisksFstabEntry. + * + * Gets the type field of @entry. + * + * Returns: The type field. + */ +const gchar * +udisks_fstab_entry_get_fstype (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), NULL); + return entry->type; +} + +/** + * udisks_fstab_entry_get_opts: + * @entry: A #UDisksFstabEntry. + * + * Gets the opts field of @entry. + * + * Returns: The opts field. + */ +const gchar * +udisks_fstab_entry_get_opts (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), NULL); + return entry->opts; +} + +/** + * udisks_fstab_entry_get_freq: + * @entry: A #UDisksFstabEntry. + * + * Gets the freq field of @entry. + * + * Returns: The freq field. + */ +gint +udisks_fstab_entry_get_freq (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), 0); + return entry->freq; +} + +/** + * udisks_fstab_entry_get_passno: + * @entry: A #UDisksFstabEntry. + * + * Gets the passno field of @entry. + * + * Returns: The passno field. + */ +gint +udisks_fstab_entry_get_passno (UDisksFstabEntry *entry) +{ + g_return_val_if_fail (UDISKS_IS_FSTAB_ENTRY (entry), 0); + return entry->passno; +} diff --git a/src/udisksfstabentry.h b/src/udisksfstabentry.h new file mode 100644 index 0000000..14fc7c0 --- /dev/null +++ b/src/udisksfstabentry.h @@ -0,0 +1,44 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008-2010 David Zeuthen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __UDISKS_FSTAB_ENTRY_H__ +#define __UDISKS_FSTAB_ENTRY_H__ + +#include "udisksdaemontypes.h" + +G_BEGIN_DECLS + +#define UDISKS_TYPE_FSTAB_ENTRY (udisks_fstab_entry_get_type ()) +#define UDISKS_FSTAB_ENTRY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_FSTAB_ENTRY, UDisksFstabEntry)) +#define UDISKS_IS_FSTAB_ENTRY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_FSTAB_ENTRY)) + +GType udisks_fstab_entry_get_type (void) G_GNUC_CONST; +const gchar *udisks_fstab_entry_get_fsname (UDisksFstabEntry *entry); +const gchar *udisks_fstab_entry_get_dir (UDisksFstabEntry *entry); +const gchar *udisks_fstab_entry_get_fstype (UDisksFstabEntry *entry); +const gchar *udisks_fstab_entry_get_opts (UDisksFstabEntry *entry); +gint udisks_fstab_entry_get_freq (UDisksFstabEntry *entry); +gint udisks_fstab_entry_get_passno (UDisksFstabEntry *entry); +gint udisks_fstab_entry_compare (UDisksFstabEntry *entry, + UDisksFstabEntry *other_entry); + +G_END_DECLS + +#endif /* __UDISKS_FSTAB_ENTRY_H__ */ diff --git a/src/udisksfstabmonitor.c b/src/udisksfstabmonitor.c new file mode 100644 index 0000000..2b5788a --- /dev/null +++ b/src/udisksfstabmonitor.c @@ -0,0 +1,414 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008 David Zeuthen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "udisksfstabmonitor.h" +#include "udisksfstabentry.h" +#include "udisksprivate.h" +#include "udiskslogging.h" + +/** + * SECTION:udisksfstabmonitor + * @title: UDisksFstabMonitor + * @short_description: Monitors entries in the fstab file + * + * This type is used for monitoring entries in the + * /etc/fstab file. + */ + +/** + * UDisksFstabMonitor: + * + * The #UDisksFstabMonitor structure contains only private data and + * should only be accessed using the provided API. + */ +struct _UDisksFstabMonitor +{ + GObject parent_instance; + + gboolean have_data; + GList *fstab_entries; + + GFileMonitor *file_monitor; +}; + +typedef struct _UDisksFstabMonitorClass UDisksFstabMonitorClass; + +struct _UDisksFstabMonitorClass +{ + GObjectClass parent_class; + + void (*entry_added) (UDisksFstabMonitor *monitor, + UDisksFstabEntry *entry); + void (*entry_removed) (UDisksFstabMonitor *monitor, + UDisksFstabEntry *entry); +}; + +/*--------------------------------------------------------------------------------------------------------------*/ + +enum + { + ENTRY_ADDED_SIGNAL, + ENTRY_REMOVED_SIGNAL, + LAST_SIGNAL, + }; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (UDisksFstabMonitor, udisks_fstab_monitor, G_TYPE_OBJECT) + +static void udisks_fstab_monitor_ensure (UDisksFstabMonitor *monitor); +static void udisks_fstab_monitor_invalidate (UDisksFstabMonitor *monitor); +static void udisks_fstab_monitor_constructed (GObject *object); + +static void +udisks_fstab_monitor_finalize (GObject *object) +{ + UDisksFstabMonitor *monitor = UDISKS_FSTAB_MONITOR (object); + + g_object_unref (monitor->file_monitor); + + g_list_foreach (monitor->fstab_entries, (GFunc) g_object_unref, NULL); + g_list_free (monitor->fstab_entries); + + if (G_OBJECT_CLASS (udisks_fstab_monitor_parent_class)->finalize != NULL) + G_OBJECT_CLASS (udisks_fstab_monitor_parent_class)->finalize (object); +} + +static void +udisks_fstab_monitor_init (UDisksFstabMonitor *monitor) +{ + monitor->fstab_entries = NULL; +} + +static void +udisks_fstab_monitor_class_init (UDisksFstabMonitorClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = udisks_fstab_monitor_finalize; + gobject_class->constructed = udisks_fstab_monitor_constructed; + + /** + * UDisksFstabMonitor::entry-added + * @monitor: A #UDisksFstabMonitor. + * @entry: The #UDisksFstabEntry that was added. + * + * Emitted when a fstab entry is added. + * + * This signal is emitted in the + * thread-default main loop + * that @monitor was created in. + */ + signals[ENTRY_ADDED_SIGNAL] = g_signal_new ("entry-added", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (UDisksFstabMonitorClass, entry_added), + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + UDISKS_TYPE_FSTAB_ENTRY); + + /** + * UDisksFstabMonitor::entry-removed + * @monitor: A #UDisksFstabMonitor. + * @entry: The #UDisksFstabEntry that was removed. + * + * Emitted when a fstab entry is removed. + * + * This signal is emitted in the + * thread-default main loop + * that @monitor was created in. + */ + signals[ENTRY_REMOVED_SIGNAL] = g_signal_new ("entry-removed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, + G_STRUCT_OFFSET (UDisksFstabMonitorClass, entry_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, + 1, + UDISKS_TYPE_FSTAB_ENTRY); +} + +static void +diff_sorted_lists (GList *list1, + GList *list2, + GCompareFunc compare, + GList **added, + GList **removed) +{ + int order; + + *added = *removed = NULL; + + while (list1 != NULL && list2 != NULL) + { + order = (*compare) (list1->data, list2->data); + if (order < 0) + { + *removed = g_list_prepend (*removed, list1->data); + list1 = list1->next; + } + else if (order > 0) + { + *added = g_list_prepend (*added, list2->data); + list2 = list2->next; + } + else + { /* same item */ + list1 = list1->next; + list2 = list2->next; + } + } + + while (list1 != NULL) + { + *removed = g_list_prepend (*removed, list1->data); + list1 = list1->next; + } + while (list2 != NULL) + { + *added = g_list_prepend (*added, list2->data); + list2 = list2->next; + } +} + +static void +reload_fstab_entries (UDisksFstabMonitor *monitor) +{ + GList *old_fstab_entries; + GList *cur_fstab_entries; + GList *added; + GList *removed; + GList *l; + + udisks_fstab_monitor_ensure (monitor); + + old_fstab_entries = g_list_copy (monitor->fstab_entries); + g_list_foreach (old_fstab_entries, (GFunc) g_object_ref, NULL); + + udisks_fstab_monitor_invalidate (monitor); + udisks_fstab_monitor_ensure (monitor); + + cur_fstab_entries = g_list_copy (monitor->fstab_entries); + + old_fstab_entries = g_list_sort (old_fstab_entries, (GCompareFunc) udisks_fstab_entry_compare); + cur_fstab_entries = g_list_sort (cur_fstab_entries, (GCompareFunc) udisks_fstab_entry_compare); + diff_sorted_lists (old_fstab_entries, cur_fstab_entries, (GCompareFunc) udisks_fstab_entry_compare, &added, &removed); + + for (l = removed; l != NULL; l = l->next) + { + UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); + g_signal_emit (monitor, signals[ENTRY_REMOVED_SIGNAL], 0, entry); + } + + for (l = added; l != NULL; l = l->next) + { + UDisksFstabEntry *entry = UDISKS_FSTAB_ENTRY (l->data); + g_signal_emit (monitor, signals[ENTRY_ADDED_SIGNAL], 0, entry); + } + + g_list_foreach (old_fstab_entries, (GFunc) g_object_unref, NULL); + g_list_free (old_fstab_entries); + g_list_free (cur_fstab_entries); + g_list_free (removed); + g_list_free (added); +} + +static void +on_file_monitor_changed (GFileMonitor *file_monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + UDisksFstabMonitor *monitor = UDISKS_FSTAB_MONITOR (user_data); + if (event_type == G_FILE_MONITOR_EVENT_CHANGED || + event_type == G_FILE_MONITOR_EVENT_CREATED) + { + udisks_debug ("/etc/fstab changed!"); + reload_fstab_entries (monitor); + } +} + +static void +udisks_fstab_monitor_constructed (GObject *object) +{ + UDisksFstabMonitor *monitor = UDISKS_FSTAB_MONITOR (object); + GError *error; + GFile *file; + + file = g_file_new_for_path ("/etc/fstab"); + error = NULL; + monitor->file_monitor = g_file_monitor_file (file, + G_FILE_MONITOR_NONE, + NULL, /* cancellable */ + &error); + if (monitor->file_monitor == NULL) + { + udisks_error ("Error monitoring /etc/fstab: %s (%s, %d)", + error->message, g_quark_to_string (error->domain), error->code); + g_error_free (error); + } + else + { + g_signal_connect (monitor->file_monitor, + "changed", + G_CALLBACK (on_file_monitor_changed), + monitor); + } + g_object_unref (file); + + if (G_OBJECT_CLASS (udisks_fstab_monitor_parent_class)->constructed != NULL) + (*G_OBJECT_CLASS (udisks_fstab_monitor_parent_class)->constructed) (object); +} + +/** + * udisks_fstab_monitor_new: + * + * Creates a new #UDisksFstabMonitor object. + * + * Signals are emitted in the thread-default main + * loop that this function is called from. + * + * Returns: A #UDisksFstabMonitor. Free with g_object_unref(). + */ +UDisksFstabMonitor * +udisks_fstab_monitor_new (void) +{ + return UDISKS_FSTAB_MONITOR (g_object_new (UDISKS_TYPE_FSTAB_MONITOR, NULL)); +} + +static void +udisks_fstab_monitor_invalidate (UDisksFstabMonitor *monitor) +{ + monitor->have_data = FALSE; + + g_list_foreach (monitor->fstab_entries, (GFunc) g_object_unref, NULL); + g_list_free (monitor->fstab_entries); + monitor->fstab_entries = NULL; +} + + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +have_entry (UDisksFstabMonitor *monitor, + UDisksFstabEntry *entry) +{ + GList *l; + gboolean ret; + + ret = FALSE; + for (l = monitor->fstab_entries; l != NULL; l = l->next) + { + UDisksFstabEntry *other_entry = UDISKS_FSTAB_ENTRY (l->data); + if (udisks_fstab_entry_compare (entry, other_entry) == 0) + { + ret = TRUE; + goto out; + } + } + out: + return ret; +} + +static void +udisks_fstab_monitor_ensure (UDisksFstabMonitor *monitor) +{ + FILE *f; + char buf[8192]; + struct mntent mbuf; + struct mntent *m; + + f = NULL; + + if (monitor->have_data) + goto out; + + f = fopen ("/etc/fstab", "r"); + if (f == NULL) + { + udisks_warning ("Error opening /etc/fstab file: %m"); + goto out; + } + + while ((m = getmntent_r (f, &mbuf, buf, sizeof (buf))) != NULL) + { + UDisksFstabEntry *entry; + entry = _udisks_fstab_entry_new (m); + if (!have_entry (monitor, entry)) + { + monitor->fstab_entries = g_list_prepend (monitor->fstab_entries, entry); + } + else + { + g_object_unref (entry); + } + } + + monitor->have_data = TRUE; + + out: + if (f != NULL) + fclose (f); +} + +/** + * udisks_fstab_monitor_get_entries: + * @monitor: A #UDisksFstabMonitor. + * + * Gets all /etc/fstab entries + * + * Returns: (transfer full) (element-type UDisksFstabEntry): A list of #UDisksFstabEntry objects that must be freed with g_list_free() after each element has been freed with g_object_unref(). + */ +GList * +udisks_fstab_monitor_get_entries (UDisksFstabMonitor *monitor) +{ + GList *ret; + + g_return_val_if_fail (UDISKS_IS_FSTAB_MONITOR (monitor), NULL); + + udisks_fstab_monitor_ensure (monitor); + + ret = g_list_copy (monitor->fstab_entries); + g_list_foreach (ret, (GFunc) g_object_ref, NULL); + return ret; +} + diff --git a/src/udisksfstabmonitor.h b/src/udisksfstabmonitor.h new file mode 100644 index 0000000..7062791 --- /dev/null +++ b/src/udisksfstabmonitor.h @@ -0,0 +1,38 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2008-2010 David Zeuthen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __UDISKS_FSTAB_MONITOR_H__ +#define __UDISKS_FSTAB_MONITOR_H__ + +#include "udisksdaemontypes.h" + +G_BEGIN_DECLS + +#define UDISKS_TYPE_FSTAB_MONITOR (udisks_fstab_monitor_get_type ()) +#define UDISKS_FSTAB_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_FSTAB_MONITOR, UDisksFstabMonitor)) +#define UDISKS_IS_FSTAB_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_FSTAB_MONITOR)) + +GType udisks_fstab_monitor_get_type (void) G_GNUC_CONST; +UDisksFstabMonitor *udisks_fstab_monitor_new (void); +GList *udisks_fstab_monitor_get_entries (UDisksFstabMonitor *monitor); + +G_END_DECLS + +#endif /* __UDISKS_FSTAB_MONITOR_H__ */ -- 2.7.4