G_CALLBACK (device_event_signal_handler), daemon);
daemon->priv->mount_monitor = devkit_disks_mount_monitor_new ();
- g_signal_connect (daemon->priv->mount_monitor, "mounted", (GCallback) mount_added, daemon);
- g_signal_connect (daemon->priv->mount_monitor, "unmounted", (GCallback) mount_removed, daemon);
+ g_signal_connect (daemon->priv->mount_monitor, "mount-added", (GCallback) mount_added, daemon);
+ g_signal_connect (daemon->priv->mount_monitor, "mount-removed", (GCallback) mount_removed, daemon);
return TRUE;
error:
if (a->len == 0 && b == NULL)
return TRUE;
- b_len = g_strv_length (b);
+ b_len = (b != NULL ? g_strv_length (b) : 0);
if (a->len != b_len)
return FALSE;
}
void
-devkit_disks_device_set_device_mount_path (DevkitDisksDevice *device, const gchar *value)
+devkit_disks_device_set_device_mount_paths (DevkitDisksDevice *device, GStrv value)
{
- if (G_UNLIKELY (g_strcmp0 (device->priv->device_mount_path, value) != 0))
+ if (G_UNLIKELY (!ptr_str_array_equals_strv (device->priv->device_mount_paths, value)))
{
- g_free (device->priv->device_mount_path);
- device->priv->device_mount_path = g_strdup (value);
- emit_changed (device, "device_mount_path");
+ ptr_str_array_free (device->priv->device_mount_paths);
+ device->priv->device_mount_paths = ptr_str_array_from_strv (value);
+ emit_changed (device, "device_mount_paths");
}
}
guint64 device_size;
guint64 device_block_size;
gboolean device_is_mounted;
- char *device_mount_path;
+ GPtrArray *device_mount_paths;
uid_t device_mounted_by_uid;
char *device_presentation_name;
char *device_presentation_icon_name;
void devkit_disks_device_set_device_size (DevkitDisksDevice *device, guint64 value);
void devkit_disks_device_set_device_block_size (DevkitDisksDevice *device, guint64 value);
void devkit_disks_device_set_device_is_mounted (DevkitDisksDevice *device, gboolean value);
-void devkit_disks_device_set_device_mount_path (DevkitDisksDevice *device, const gchar *value);
+void devkit_disks_device_set_device_mount_paths (DevkitDisksDevice *device, GStrv value);
void devkit_disks_device_set_device_mounted_by_uid (DevkitDisksDevice *device, guint value);
void devkit_disks_device_set_device_presentation_name (DevkitDisksDevice *device, const gchar *value);
void devkit_disks_device_set_device_presentation_icon_name (DevkitDisksDevice *device, const gchar *value);
PROP_DEVICE_BLOCK_SIZE,
PROP_DEVICE_IS_MOUNTED,
PROP_DEVICE_IS_BUSY,
- PROP_DEVICE_MOUNT_PATH,
+ PROP_DEVICE_MOUNT_PATHS,
PROP_DEVICE_MOUNTED_BY_UID,
PROP_DEVICE_PRESENTATION_NAME,
PROP_DEVICE_PRESENTATION_ICON_NAME,
/* this property is special; it's value is computed on demand */
g_value_set_boolean (value, devkit_disks_device_local_is_busy (device));
break;
- case PROP_DEVICE_MOUNT_PATH:
- g_value_set_string (value, device->priv->device_mount_path);
+ case PROP_DEVICE_MOUNT_PATHS:
+ g_value_set_boxed (value, device->priv->device_mount_paths);
break;
case PROP_DEVICE_MOUNTED_BY_UID:
g_value_set_uint (value, device->priv->device_mounted_by_uid);
g_param_spec_boolean ("device-is-busy", NULL, NULL, FALSE, G_PARAM_READABLE));
g_object_class_install_property (
object_class,
- PROP_DEVICE_MOUNT_PATH,
- g_param_spec_string ("device-mount-path", NULL, NULL, NULL, G_PARAM_READABLE));
+ PROP_DEVICE_MOUNT_PATHS,
+ g_param_spec_boxed ("device-mount-paths", NULL, NULL,
+ dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING),
+ G_PARAM_READABLE));
g_object_class_install_property (
object_class,
PROP_DEVICE_MOUNTED_BY_UID,
device->priv->device_file_by_id = g_ptr_array_new ();
device->priv->device_file_by_path = g_ptr_array_new ();
+ device->priv->device_mount_paths = g_ptr_array_new ();
device->priv->partition_flags = g_ptr_array_new ();
device->priv->drive_media_compatibility = g_ptr_array_new ();
device->priv->linux_md_component_state = g_ptr_array_new ();
g_ptr_array_foreach (device->priv->device_file_by_path, (GFunc) g_free, NULL);
g_ptr_array_free (device->priv->device_file_by_id, TRUE);
g_ptr_array_free (device->priv->device_file_by_path, TRUE);
- g_free (device->priv->device_mount_path);
+ g_ptr_array_free (device->priv->device_mount_paths, TRUE);
g_free (device->priv->device_presentation_name);
g_free (device->priv->device_presentation_icon_name);
{
DevkitDisksMountMonitor *monitor;
DevkitDisksMount *mount;
+ GList *mounts;
gboolean was_mounted;
- gchar *old_mount_path;
- old_mount_path = NULL;
+ mounts = NULL;
/* defer setting the mount point until FilesystemMount returns and
* the mounts file is written
goto out;
monitor = devkit_disks_daemon_local_get_mount_monitor (device->priv->daemon);
- mount = devkit_disks_mount_monitor_get_mount_for_dev (monitor, device->priv->dev);
+
+ mounts = devkit_disks_mount_monitor_get_mounts_for_dev (monitor, device->priv->dev);
was_mounted = device->priv->device_is_mounted;
- old_mount_path = g_strdup (device->priv->device_mount_path);
- if (mount != NULL) {
+ if (mounts != NULL) {
+ GList *l;
+ guint n;
+ gchar **mount_paths;
+
+ mount = g_object_ref (mounts->data);
+ mount_paths = g_new0 (gchar *, g_list_length (mounts) + 1);
+ for (l = mounts, n = 0; l != NULL; l = l->next, n++) {
+ mount_paths[n] = g_strdup (devkit_disks_mount_get_mount_path (DEVKIT_DISKS_MOUNT (l->data)));
+ }
+
devkit_disks_device_set_device_is_mounted (device, TRUE);
- devkit_disks_device_set_device_mount_path (device, devkit_disks_mount_get_mount_path (mount));
+ devkit_disks_device_set_device_mount_paths (device, mount_paths);
if (!was_mounted) {
uid_t mounted_by_uid;
mounted_by_uid = 0;
devkit_disks_device_set_device_mounted_by_uid (device, mounted_by_uid);
}
+
+ g_strfreev (mount_paths);
+
} else {
gboolean remove_dir_on_unmount;
+ gchar *old_mount_path;
+
+ old_mount_path = NULL;
+ if (device->priv->device_mount_paths->len > 0)
+ old_mount_path = g_strdup (((gchar **) device->priv->device_mount_paths->pdata)[0]);
devkit_disks_device_set_device_is_mounted (device, FALSE);
- devkit_disks_device_set_device_mount_path (device, NULL);
+ devkit_disks_device_set_device_mount_paths (device, NULL);
devkit_disks_device_set_device_mounted_by_uid (device, 0);
/* clean up stale mount directory */
remove_dir_on_unmount = FALSE;
- if (was_mounted && devkit_disks_mount_file_has_device (device->priv->device_file, NULL, &remove_dir_on_unmount)) {
+ if (was_mounted && devkit_disks_mount_file_has_device (device->priv->device_file,
+ NULL,
+ &remove_dir_on_unmount)) {
devkit_disks_mount_file_remove (device->priv->device_file, old_mount_path);
if (remove_dir_on_unmount) {
if (g_rmdir (old_mount_path) != 0) {
}
}
+ g_free (old_mount_path);
+
}
out:
- g_free (old_mount_path);
+ g_list_foreach (mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (mounts);
return TRUE;
}
return device->priv->device_file;
}
-const char *
-devkit_disks_device_local_get_mount_path (DevkitDisksDevice *device)
-{
- return device->priv->device_mount_path;
-}
-
/*--------------------------------------------------------------------------------------------------------------*/
static gboolean
typedef struct {
char *mount_point;
gboolean remove_dir_on_unmount;
- gboolean is_remount;
} MountData;
static MountData *
-filesystem_mount_data_new (const char *mount_point, gboolean remove_dir_on_unmount, gboolean is_remount)
+filesystem_mount_data_new (const char *mount_point, gboolean remove_dir_on_unmount)
{
MountData *data;
data = g_new0 (MountData, 1);
data->mount_point = g_strdup (mount_point);
data->remove_dir_on_unmount = remove_dir_on_unmount;
- data->is_remount = is_remount;
return data;
}
"atime",
"noatime",
"nodiratime",
- "remount",
"ro",
"rw",
"sync",
dbus_g_method_return (context, data->mount_point);
} else {
- if (!data->is_remount) {
- devkit_disks_mount_file_remove (device->priv->device_file, data->mount_point);
+ devkit_disks_mount_file_remove (device->priv->device_file, data->mount_point);
- if (data->remove_dir_on_unmount) {
- if (g_rmdir (data->mount_point) != 0) {
- g_warning ("Error removing dir in late mount error path: %m");
- }
+ if (data->remove_dir_on_unmount) {
+ if (g_rmdir (data->mount_point) != 0) {
+ g_warning ("Error removing dir in late mount error path: %m");
}
}
gboolean remove_dir_on_unmount;
const FSMountOptions *fsmo;
char **options;
- gboolean is_remount;
char uid_buf[32];
fstype = NULL;
options = NULL;
mount_options = NULL;
mount_point = NULL;
- is_remount = FALSE;
if ((pk_caller = devkit_disks_damon_local_get_caller_for_context (device->priv->daemon, context)) == NULL)
goto out;
goto out;
}
- if (strcmp (option, "remount") == 0)
- is_remount = TRUE;
-
g_string_append_c (s, ',');
g_string_append (s, option);
}
g_print ("**** USING MOUNT OPTIONS '%s' FOR DEVICE %s\n", mount_options, device->priv->device_file);
if (device->priv->device_is_mounted) {
- if (!is_remount) {
- throw_error (context, DEVKIT_DISKS_ERROR_ALREADY_MOUNTED,
- "Device is already mounted");
- goto out;
- }
+ throw_error (context, DEVKIT_DISKS_ERROR_ALREADY_MOUNTED,
+ "Device is already mounted");
+ goto out;
}
- /* TODO: check for auth if user tries to remount something mounted by another user */
-
- /* handle some constraints required by remount */
- if (is_remount) {
- if (!device->priv->device_is_mounted ||
- device->priv->device_mount_path == NULL) {
- throw_error (context,
- DEVKIT_DISKS_ERROR_NOT_MOUNTED,
- "Can't remount a device that is not mounted");
- goto out;
- }
-
- if (strlen (filesystem_type) > 0) {
- throw_error (context,
- DEVKIT_DISKS_ERROR_FAILED,
- "Can't remount a device with a different file system type");
- goto out;
- }
+ /* Determine the mount point to use.
+ *
+ * TODO: use characteristics of the drive such as the name, connection etc.
+ * to get better names (/media/disk is kinda lame).
+ */
+ if (device->priv->id_label != NULL && strlen (device->priv->id_label) > 0 ) {
+ mount_point = g_build_filename ("/media", device->priv->id_label, NULL);
+ } else if (device->priv->id_uuid != NULL && strlen (device->priv->id_uuid) > 0) {
+ mount_point = g_build_filename ("/media", device->priv->id_uuid, NULL);
+ } else {
+ mount_point = g_strdup ("/media/disk");
}
- if (!is_remount) {
- /* Determine the mount point to use.
- *
- * TODO: use characteristics of the drive such as the name, connection etc.
- * to get better names (/media/disk is kinda lame).
- */
- if (device->priv->id_label != NULL && strlen (device->priv->id_label) > 0 ) {
- mount_point = g_build_filename ("/media", device->priv->id_label, NULL);
- } else if (device->priv->id_uuid != NULL && strlen (device->priv->id_uuid) > 0) {
- mount_point = g_build_filename ("/media", device->priv->id_uuid, NULL);
- } else {
- mount_point = g_strdup ("/media/disk");
- }
-
try_another_mount_point:
- /* ... then uniqify the mount point and mkdir it */
- if (g_file_test (mount_point, G_FILE_TEST_EXISTS)) {
- char *s = mount_point;
- /* TODO: append numbers instead of _, __ and so on */
- mount_point = g_strdup_printf ("%s_", mount_point);
- g_free (s);
- goto try_another_mount_point;
- }
+ /* ... then uniqify the mount point and mkdir it */
+ if (g_file_test (mount_point, G_FILE_TEST_EXISTS)) {
+ char *s = mount_point;
+ /* TODO: append numbers instead of _, __ and so on */
+ mount_point = g_strdup_printf ("%s_", mount_point);
+ g_free (s);
+ goto try_another_mount_point;
+ }
- remove_dir_on_unmount = TRUE;
+ remove_dir_on_unmount = TRUE;
- if (g_mkdir (mount_point, 0700) != 0) {
- throw_error (context, DEVKIT_DISKS_ERROR_FAILED, "Error creating moint point: %m");
- goto out;
- }
-
- n = 0;
- argv[n++] = "mount";
- argv[n++] = "-t";
- argv[n++] = fstype;
- argv[n++] = "-o";
- argv[n++] = mount_options;
- argv[n++] = device->priv->device_file;
- argv[n++] = mount_point;
- argv[n++] = NULL;
- } else {
- /* we recycle the mount point on remount */
- mount_point = g_strdup (device->priv->device_mount_path);
- n = 0;
- argv[n++] = "mount";
- argv[n++] = "-o";
- argv[n++] = mount_options;
- argv[n++] = mount_point;
- argv[n++] = NULL;
+ if (g_mkdir (mount_point, 0700) != 0) {
+ throw_error (context, DEVKIT_DISKS_ERROR_FAILED, "Error creating moint point: %m");
+ goto out;
}
+ n = 0;
+ argv[n++] = "mount";
+ argv[n++] = "-t";
+ argv[n++] = fstype;
+ argv[n++] = "-o";
+ argv[n++] = mount_options;
+ argv[n++] = device->priv->device_file;
+ argv[n++] = mount_point;
+ argv[n++] = NULL;
+
run_job:
- if (!is_remount) {
- /* now that we have a mount point, immediately add it to the
- * /var/lib/DeviceKit-disks/mtab file
- */
- devkit_disks_mount_file_add (device->priv->device_file,
- mount_point,
- caller_uid,
- remove_dir_on_unmount);
- }
+ /* now that we have a mount point, immediately add it to the
+ * /var/lib/DeviceKit-disks/mtab file
+ */
+ devkit_disks_mount_file_add (device->priv->device_file,
+ mount_point,
+ caller_uid,
+ remove_dir_on_unmount);
error = NULL;
if (!job_new (context,
argv,
NULL,
filesystem_mount_completed_cb,
- filesystem_mount_data_new (mount_point, remove_dir_on_unmount, is_remount),
+ filesystem_mount_data_new (mount_point, remove_dir_on_unmount),
(GDestroyNotify) filesystem_mount_data_free)) {
- if (!is_remount) {
- devkit_disks_mount_file_remove (device->priv->device_file, mount_point);
- if (remove_dir_on_unmount) {
- if (g_rmdir (mount_point) != 0) {
- g_warning ("Error removing dir in early mount error path: %m");
- }
+ devkit_disks_mount_file_remove (device->priv->device_file, mount_point);
+ if (remove_dir_on_unmount) {
+ if (g_rmdir (mount_point) != 0) {
+ g_warning ("Error removing dir in early mount error path: %m");
}
}
goto out;
polkit_caller_get_uid (pk_caller, &uid);
if (!device->priv->device_is_mounted ||
- device->priv->device_mount_path == NULL) {
+ device->priv->device_mount_paths->len == 0) {
throw_error (context,
DEVKIT_DISKS_ERROR_NOT_MOUNTED,
"Device is not mounted");
goto out;
}
+ mount_path = g_strdup (((gchar **) device->priv->device_mount_paths->pdata)[0]);
+
n = 0;
argv[n++] = "umount";
if (force_unmount) {
/* on Linux we currently only have lazy unmount to emulate this */
argv[n++] = "-l";
}
- argv[n++] = device->priv->device_mount_path;
+ argv[n++] = mount_path;
argv[n++] = NULL;
- mount_path = g_strdup (device->priv->device_mount_path);
-
run_job:
error = NULL;
if (!job_new (context,
goto out;
if (!device->priv->device_is_mounted ||
- device->priv->device_mount_path == NULL) {
+ device->priv->device_mount_paths->len == 0) {
throw_error (context,
DEVKIT_DISKS_ERROR_NOT_MOUNTED,
"Device is not mounted");
n = 0;
argv[n++] = "lsof";
argv[n++] = "-t";
- argv[n++] = device->priv->device_mount_path;
+ argv[n++] = ((gchar **) device->priv->device_mount_paths->pdata)[0];
argv[n++] = NULL;
error = NULL;
} ForceUnmountData;
static ForceUnmountData *
-force_unmount_data_new (char *mount_path,
+force_unmount_data_new (const gchar *mount_path,
ForceRemovalCompleteFunc fr_callback,
gpointer fr_user_data)
{
int n;
char *argv[16];
GError *error;
+ const gchar *mount_path;
+
+ mount_path = ((gchar **) device->priv->device_mount_paths->pdata)[0];
n = 0;
argv[n++] = "umount";
/* on Linux, we only have lazy unmount for now */
argv[n++] = "-l";
- argv[n++] = device->priv->device_mount_path;
+ argv[n++] = (gchar *) mount_path;
argv[n++] = NULL;
error = NULL;
argv,
NULL,
force_unmount_completed_cb,
- force_unmount_data_new (device->priv->device_mount_path, callback, user_data),
+ force_unmount_data_new (mount_path, callback, user_data),
(GDestroyNotify) force_unmount_data_unref)) {
g_warning ("Couldn't spawn unmount for force unmounting: %s", error->message);
g_error_free (error);
* companion. If so, tear it down if it was setup by us.
*
*/
- if (device->priv->device_is_mounted && device->priv->device_mount_path != NULL) {
+ if (device->priv->device_is_mounted && device->priv->device_mount_paths->len > 0) {
gboolean remove_dir_on_unmount;
if (devkit_disks_mount_file_has_device (device->priv->device_file, NULL, &remove_dir_on_unmount)) {
dev_t devkit_disks_device_local_get_dev (DevkitDisksDevice *device);
const char *devkit_disks_device_local_get_device_file (DevkitDisksDevice *device);
-const char *devkit_disks_device_local_get_mount_path (DevkitDisksDevice *device);
/* exported methods */
char *mount_path_escaped;
if (!device->priv->device_is_mounted ||
- device->priv->device_mount_path == NULL)
+ device->priv->device_mount_paths == NULL)
continue;
- mount_path_escaped =
- g_uri_escape_string (device->priv->device_mount_path, NULL, TRUE);
+ mount_path_escaped = g_uri_escape_string (((gchar **) device->priv->device_mount_paths->pdata)[0], NULL, TRUE);
if (strcmp (line_mount_path, mount_path_escaped) == 0) {
entry_is_valid = TRUE;
enum
{
- MOUNTED_SIGNAL,
- UNMOUNTED_SIGNAL,
+ MOUNT_ADDED_SIGNAL,
+ MOUNT_REMOVED_SIGNAL,
LAST_SIGNAL,
};
struct DevkitDisksMountMonitorPrivate
{
GIOChannel *mounts_channel;
- GHashTable *mounts;
gboolean have_data;
+ GList *mounts;
};
G_DEFINE_TYPE (DevkitDisksMountMonitor, devkit_disks_mount_monitor, G_TYPE_OBJECT)
if (monitor->priv->mounts_channel != NULL)
g_io_channel_unref (monitor->priv->mounts_channel);
- g_hash_table_unref (monitor->priv->mounts);
+ g_list_foreach (monitor->priv->mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (monitor->priv->mounts);
if (G_OBJECT_CLASS (devkit_disks_mount_monitor_parent_class)->finalize != NULL)
(* G_OBJECT_CLASS (devkit_disks_mount_monitor_parent_class)->finalize) (object);
DEVKIT_DISKS_TYPE_MOUNT_MONITOR,
DevkitDisksMountMonitorPrivate);
- monitor->priv->mounts = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- g_object_unref);
+ monitor->priv->mounts = NULL;
}
static void
g_type_class_add_private (klass, sizeof (DevkitDisksMountMonitorPrivate));
/**
- * DevkitDisksMountMonitor::mounted
+ * DevkitDisksMountMonitor::mount-added
* @monitor: A #DevkitDisksMountMonitor.
- * @mount: The #DevkitDisksMount that was mounted.
+ * @mount: The #DevkitDisksMount that was added.
*
- * Emitted when a filesystem is mounted.
+ * Emitted when a mount is added.
*/
- signals[MOUNTED_SIGNAL] =
- g_signal_new ("mounted",
+ signals[MOUNT_ADDED_SIGNAL] =
+ g_signal_new ("mount-added",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
+ G_STRUCT_OFFSET (DevkitDisksMountMonitorClass, mount_added),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
DEVKIT_DISKS_TYPE_MOUNT);
/**
- * DevkitDisksMountMonitor::unmounted
+ * DevkitDisksMountMonitor::mount-removed
* @monitor: A #DevkitDisksMountMonitor.
- * @mount: The #DevkitDisksMount that was unmounted.
+ * @mount: The #DevkitDisksMount that was removed.
*
- * Emitted when a filesystem is unmounted.
+ * Emitted when a mount is removed.
*/
- signals[UNMOUNTED_SIGNAL] =
- g_signal_new ("unmounted",
+ signals[MOUNT_REMOVED_SIGNAL] =
+ g_signal_new ("mount-removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
- 0,
+ G_STRUCT_OFFSET (DevkitDisksMountMonitorClass, mount_removed),
NULL,
NULL,
g_cclosure_marshal_VOID__OBJECT,
if (cond & ~G_IO_ERR)
goto out;
+ g_debug ("/proc/self/mountinfo changed");
+
devkit_disks_mount_monitor_ensure (monitor);
- old_mounts = g_hash_table_get_values (monitor->priv->mounts);
+
+ old_mounts = g_list_copy (monitor->priv->mounts);
g_list_foreach (old_mounts, (GFunc) g_object_ref, NULL);
devkit_disks_mount_monitor_invalidate (monitor);
devkit_disks_mount_monitor_ensure (monitor);
- cur_mounts = g_hash_table_get_values (monitor->priv->mounts);
+ cur_mounts = g_list_copy (monitor->priv->mounts);
old_mounts = g_list_sort (old_mounts, (GCompareFunc) devkit_disks_mount_compare);
cur_mounts = g_list_sort (cur_mounts, (GCompareFunc) devkit_disks_mount_compare);
for (l = removed; l != NULL; l = l->next) {
DevkitDisksMount *mount = DEVKIT_DISKS_MOUNT (l->data);
g_signal_emit (monitor,
- signals[UNMOUNTED_SIGNAL],
+ signals[MOUNT_REMOVED_SIGNAL],
0,
mount);
}
for (l = added; l != NULL; l = l->next) {
DevkitDisksMount *mount = DEVKIT_DISKS_MOUNT (l->data);
g_signal_emit (monitor,
- signals[MOUNTED_SIGNAL],
+ signals[MOUNT_ADDED_SIGNAL],
0,
mount);
}
mount_monitor = DEVKIT_DISKS_MOUNT_MONITOR (g_object_new (DEVKIT_DISKS_TYPE_MOUNT_MONITOR, NULL));
error = NULL;
- mount_monitor->priv->mounts_channel = g_io_channel_new_file ("/proc/mounts", "r", &error);
+ mount_monitor->priv->mounts_channel = g_io_channel_new_file ("/proc/self/mountinfo", "r", &error);
if (mount_monitor->priv->mounts_channel != NULL) {
g_io_add_watch (mount_monitor->priv->mounts_channel, G_IO_ERR, mounts_changed_event, mount_monitor);
} else {
- g_warning ("No /proc/mounts file: %s", error->message);
+ g_warning ("No /proc/self/mountinfo file: %s", error->message);
g_error_free (error);
g_object_unref (mount_monitor);
mount_monitor = NULL;
devkit_disks_mount_monitor_invalidate (DevkitDisksMountMonitor *monitor)
{
monitor->priv->have_data = FALSE;
- g_hash_table_remove_all (monitor->priv->mounts);
+
+ g_list_foreach (monitor->priv->mounts, (GFunc) g_object_unref, NULL);
+ g_list_free (monitor->priv->mounts);
+ monitor->priv->mounts = NULL;
+}
+
+static gboolean
+have_mount (DevkitDisksMountMonitor *monitor,
+ dev_t dev,
+ const gchar *mount_point)
+{
+ GList *l;
+ gboolean ret;
+
+ ret = FALSE;
+
+ for (l = monitor->priv->mounts; l != NULL; l = l->next) {
+ DevkitDisksMount *mount = DEVKIT_DISKS_MOUNT (l->data);
+ if (devkit_disks_mount_get_dev (mount) == dev &&
+ g_strcmp0 (devkit_disks_mount_get_mount_path (mount), mount_point) == 0) {
+ ret = TRUE;
+ break;
+ }
+ }
+
+ return ret;
}
static void
devkit_disks_mount_monitor_ensure (DevkitDisksMountMonitor *monitor)
{
- struct mntent *m;
- FILE *f;
+ gchar *contents;
+ gchar **lines;
+ GError *error;
+ guint n;
+
+ contents = NULL;
+ lines = NULL;
if (monitor->priv->have_data)
goto out;
- f = fopen ("/proc/mounts", "r");
- if (f == NULL) {
- g_warning ("error opening /proc/mounts: %m");
+ error = NULL;
+ if (!g_file_get_contents ("/proc/self/mountinfo", &contents, NULL, &error)) {
+ g_warning ("Error reading /proc/self/mountinfo: %s", error->message);
+ g_error_free (error);
goto out;
}
- while ((m = getmntent (f)) != NULL) {
- DevkitDisksMount *mount;
- struct stat statbuf;
- /* ignore if not an absolute patch */
- if (m->mnt_fsname[0] != '/')
+ /* See Documentation/filesystems/proc.txt for the format of /proc/self/mountinfo
+ *
+ * Note that things like space are encoded as \020.
+ */
+
+ lines = g_strsplit (contents, "\n", 0);
+ for (n = 0; lines[n] != NULL; n++) {
+ guint mount_id;
+ guint parent_id;
+ guint major, minor;
+ gchar encoded_root[PATH_MAX];
+ gchar encoded_mount_point[PATH_MAX];
+ gchar *mount_point;
+ dev_t dev;
+
+ if (strlen (lines[n]) == 0)
+ continue;
+
+ if (sscanf (lines[n], "%d %d %d:%d %s %s",
+ &mount_id,
+ &parent_id,
+ &major,
+ &minor,
+ encoded_root,
+ encoded_mount_point) != 6) {
+ g_warning ("Error parsing line '%s'", lines[n]);
+ continue;
+ }
+
+ /* ignore mounts where only a subtree of a filesystem is mounted */
+ if (g_strcmp0 (encoded_root, "/") != 0)
continue;
- if (stat (m->mnt_fsname, &statbuf) != 0) {
- g_warning ("Cannot stat %s: %m", m->mnt_fsname);
- } else if (statbuf.st_rdev != 0) {
+ mount_point = g_strcompress (encoded_mount_point);
- mount = _devkit_disks_mount_new (statbuf.st_rdev, m->mnt_dir);
+ dev = makedev (major, minor);
- g_hash_table_insert (monitor->priv->mounts,
- GINT_TO_POINTER (statbuf.st_rdev),
- mount);
+ /* TODO: we can probably use a hash table or something if this turns out to be slow */
+ if (!have_mount (monitor, dev, mount_point)) {
+ DevkitDisksMount *mount;
+ mount = _devkit_disks_mount_new (dev, mount_point);
+ monitor->priv->mounts = g_list_prepend (monitor->priv->mounts, mount);
+ g_debug ("SUP ADDING %d:%d on %s", major, minor, mount_point);
}
+
+ g_free (mount_point);
}
- fclose (f);
monitor->priv->have_data = TRUE;
out:
- ;
+ g_free (contents);
+ g_strfreev (lines);
}
-DevkitDisksMount *
-devkit_disks_mount_monitor_get_mount_for_dev (DevkitDisksMountMonitor *monitor,
- dev_t dev)
+GList *
+devkit_disks_mount_monitor_get_mounts_for_dev (DevkitDisksMountMonitor *monitor,
+ dev_t dev)
{
- DevkitDisksMount *ret;
+ GList *ret;
+ GList *l;
+
+ ret = NULL;
devkit_disks_mount_monitor_ensure (monitor);
- ret = g_hash_table_lookup (monitor->priv->mounts, GINT_TO_POINTER (dev));
+ for (l = monitor->priv->mounts; l != NULL; l = l->next) {
+ DevkitDisksMount *mount = DEVKIT_DISKS_MOUNT (l->data);
+
+ if (devkit_disks_mount_get_dev (mount) == dev) {
+ ret = g_list_prepend (ret, g_object_ref (mount));
+ }
+ }
+
+ /* Sort the list to ensure that shortest mount paths appear first */
+ ret = g_list_sort (ret, (GCompareFunc) devkit_disks_mount_compare);
return ret;
}
struct DevkitDisksMountMonitor
{
GObject parent;
+
+ /*< private >*/
DevkitDisksMountMonitorPrivate *priv;
};
struct DevkitDisksMountMonitorClass
{
GObjectClass parent_class;
+
+ /*< public >*/
+ /* signals */
+ void (*mount_added) (DevkitDisksMountMonitor *monitor,
+ DevkitDisksMount *mount);
+ void (*mount_removed) (DevkitDisksMountMonitor *monitor,
+ DevkitDisksMount *mount);
};
GType devkit_disks_mount_monitor_get_type (void) G_GNUC_CONST;
DevkitDisksMountMonitor *devkit_disks_mount_monitor_new (void);
-DevkitDisksMount *devkit_disks_mount_monitor_get_mount_for_dev (DevkitDisksMountMonitor *monitor,
+GList *devkit_disks_mount_monitor_get_mounts_for_dev (DevkitDisksMountMonitor *monitor,
dev_t dev);
void devkit_disks_mount_monitor_invalidate (DevkitDisksMountMonitor *monitor);
{
gint ret;
- ret = g_strcmp0 (a->priv->mount_path, b->priv->mount_path);
+ ret = g_strcmp0 (b->priv->mount_path, a->priv->mount_path);
if (ret != 0)
goto out;
goto out;
cursor += num;
-
percent = 100 * cursor / size;
+
if (percent > old_percent) {
g_print ("progress: %d %d %d zeroing\n", cur_task, num_tasks, percent);
old_percent = percent;
Most methods on this interface take an array of strings
for options that can affect what the method does. Some of
these options are literal strings (such
- as <doc:tt>remount</doc:tt>) while some are encoded in the
+ as <doc:tt>noatime</doc:tt>) while some are encoded in the
form of a key/value pair (such
as <doc:tt>label=</doc:tt>). While the documentation for
each method will specify exactly what set of options are
<doc:doc><doc:summary>File system type to use.</doc:summary></doc:doc>
</arg>
<arg name="options" direction="in" type="as">
- <doc:doc><doc:summary>Mount Options. Valid mount options include 'remount' and other mount options accepted by the native mount program.</doc:summary></doc:doc>
+ <doc:doc><doc:summary>Mount Options. Valid mount options include mount options accepted by the native mount program.</doc:summary></doc:doc>
</arg>
<arg name="mount_path" direction="out" type="s">
<doc:doc><doc:summary>Where the device was mounted.</doc:summary></doc:doc>
<doc:error name="&ERROR_NOT_FILESYSTEM;">if the device is not a mountable file system</doc:error>
<doc:error name="&ERROR_INVALID_OPTION;">if an invalid or malformed mount option was given</doc:error>
<doc:error name="&ERROR_ALREADY_MOUNTED;">if the device is already mounted</doc:error>
- <doc:error name="&ERROR_NOT_MOUNTED;">if the remount option was given and the device wasn't mounted</doc:error>
</doc:errors>
</doc:doc>
</method>
TRUE if the device is mounted.
</doc:para></doc:description></doc:doc>
</property>
- <property name="device-mount-path" type="s" access="read">
+ <property name="device-mount-paths" type="as" access="read">
<doc:doc><doc:description><doc:para>
- Where the device is mounted.
+ A list of paths in the root namespace where the root of the device is mounted.
This property is only valid if
<doc:ref type="property" to="Device:device-is-mounted">device-is-mounted</doc:ref>
is TRUE.
gboolean device_is_busy;
gboolean device_is_linux_md_component;
gboolean device_is_linux_md;
- char *device_mount_path;
+ char **device_mount_paths;
uid_t device_mounted_by_uid;
char *device_presentation_name;
char *device_presentation_icon_name;
props->device_is_mounted = g_value_get_boolean (value);
else if (strcmp (key, "device-is-busy") == 0)
props->device_is_busy = g_value_get_boolean (value);
- else if (strcmp (key, "device-mount-path") == 0)
- props->device_mount_path = g_strdup (g_value_get_string (value));
+ else if (strcmp (key, "device-mount-paths") == 0)
+ props->device_mount_paths = g_strdupv (g_value_get_boxed (value));
else if (strcmp (key, "device-mounted-by-uid") == 0)
props->device_mounted_by_uid = g_value_get_uint (value);
else if (strcmp (key, "device-presentation-name") == 0)
g_free (props->device_file);
g_strfreev (props->device_file_by_id);
g_strfreev (props->device_file_by_path);
- g_free (props->device_mount_path);
+ g_strfreev (props->device_mount_paths);
g_free (props->device_presentation_name);
g_free (props->device_presentation_icon_name);
g_free (props->job_id);
g_print (" is read only: %d\n", props->device_is_read_only);
g_print (" is mounted: %d\n", props->device_is_mounted);
g_print (" is busy: %d\n", props->device_is_busy);
- g_print (" mount path: %s\n", props->device_mount_path);
+ g_print (" mount paths: ");
+ for (n = 0; props->device_mount_paths != NULL && props->device_mount_paths[n] != NULL; n++) {
+ if (n != 0)
+ g_print (", ");
+ g_print ("%s", props->device_mount_paths[n]);
+ }
+ g_print ("\n");
g_print (" mounted by uid: %d\n", props->device_mounted_by_uid);
g_print (" presentation name: %s\n", props->device_presentation_name);
g_print (" presentation icon: %s\n", props->device_presentation_icon_name);
val = props->drive_ata_smart_power_on_seconds;
if (val > 60 * 60 * 24) {
- power_on_text = g_strdup_printf (_("%.3g days"), val / 60.0 / 60.0 / 24.0);
+ power_on_text = g_strdup_printf ("%.3g days", val / 60.0 / 60.0 / 24.0);
} else {
- power_on_text = g_strdup_printf (_("%.3g hours"), val / 60.0 / 60.0);
+ power_on_text = g_strdup_printf ("%.3g hours", val / 60.0 / 60.0);
}
g_print (" powered on: %s\n", power_on_text);