Index: udisks-2.1.5/src/udiskslinuxfilesystem.c =================================================================== --- udisks-2.1.5.orig/src/udiskslinuxfilesystem.c +++ udisks-2.1.5/src/udiskslinuxfilesystem.c @@ -85,6 +85,8 @@ G_DEFINE_TYPE_WITH_CODE (UDisksLinuxFile # define MOUNT_BASE "/run/media" #endif +#define MOUNT_CONF "udisks2-mount.conf" + /* ---------------------------------------------------------------------------------------------------- */ static void @@ -532,10 +534,145 @@ is_mount_option_allowed (const FSMountOp return allowed; } +/* There can be 3 results: + * no key match (return FALSE, match = FALSE) + * id match (return TRUE, match = TRUE) + * no id match (return TRUE, match = FALSE) */ +static inline gboolean +check_mount_conf_condition (GKeyFile *keyfile, + const gchar *group, const gchar *key, gboolean *match, + const gchar *key_to_match, const gchar *id_to_match) +{ + if (!strcmp (key, key_to_match)) + { + if (id_to_match) + { + gchar **strarray, **value; + /* group/key is expected to exist! */ + strarray = g_key_file_get_string_list (keyfile, + group, + key_to_match, NULL, NULL); + for (value = strarray; *value; value++) + if (!strcmp (*value, id_to_match)) + *match = TRUE; + g_strfreev(strarray); + } + return TRUE; + } else + return FALSE; +} + +static void +get_mount_conf_dir_options (const gchar *config_dir, + GPtrArray *options, + const gchar *fs_type, + UDisksBlock *block, + GError **error) +{ + GError *parse_error; // TODO: merge parse_error with error, ignore file not found + GKeyFile *keyfile; + + gchar *conf_filename; + conf_filename = g_build_filename (config_dir, PACKAGE, MOUNT_CONF, NULL); + + parse_error = NULL; + keyfile = g_key_file_new (); + + if (g_key_file_load_from_file (keyfile, conf_filename, + G_KEY_FILE_NONE, &parse_error)) + + { + gchar **groups, **group; + + udisks_info ("Loading %s", conf_filename); + // TODO: use error where appropriate + groups = g_key_file_get_groups (keyfile, NULL); + + group = groups; + while (*group) + { + gchar **keys, **key; + gboolean options_seen = FALSE; + gboolean match_all = TRUE; + gchar **options_add = NULL; + + keys = g_key_file_get_keys (keyfile, *group, NULL, NULL); + key = keys; + + while (*key) + { + if (!strcmp (*key, "Options")) + { + options_seen = TRUE; + options_add = g_key_file_get_string_list (keyfile, + *group, + "Options", NULL, NULL); + } else { + gboolean match = FALSE; + // TODO: If fs_type is passed, use fs_type instead of udisks_block_get_id_type (block)) + check_mount_conf_condition (keyfile, *group, *key, &match, "Type", udisks_block_get_id_type (block)) || + check_mount_conf_condition (keyfile, *group, *key, &match, "UUID", udisks_block_get_id_uuid (block)) || + check_mount_conf_condition (keyfile, *group, *key, &match, "Label", udisks_block_get_id_label (block)) || + check_mount_conf_condition (keyfile, *group, *key, &match, "Usage", udisks_block_get_id_usage (block)) || + check_mount_conf_condition (keyfile, *group, *key, &match, "Version", udisks_block_get_id_version (block)); + /* TODO: g_set_error if unknown key is not found (above is FALSE). */ + if (!match) + match_all = FALSE; + } + /* TODO: g_set_error if options_seen is FALSE. */ + key++; + } + + g_strfreev (keys); + + if (match_all) + { + udisks_debug ("Mount options rule \"%s\" matches", *group); + for (key = options_add; *key; key++) + g_ptr_array_add (options, *key); + } + + /* Free just the array, keep elements alocated to save g_strdup() */ + g_free (options_add); + + group++; + } + g_strfreev (groups); + g_key_file_free (keyfile); + /* + if (parse_error != NULL) + g_propagate_error (error, parse_error); + */ + } else { + // TODO: merge parse_error with error, ignore file not found error->code != G_FILE_ERROR_NOENT + } + g_free (conf_filename); // FIXME: may be needed for errors. Check whether it is OK. +} + +static void +get_mount_conf_options (GPtrArray *options, + const gchar *fs_type, + UDisksBlock *block, + GError **error) +{ + const gchar **config_dir; + + // TODO: Process error + for (config_dir = g_get_system_config_dirs (); *config_dir; config_dir++) + get_mount_conf_dir_options (*config_dir, options, fs_type, block, error); + + config_dir = g_get_user_config_dir (); + get_mount_conf_dir_options (config_dir, options, fs_type, block, error); + +} + static gchar ** prepend_default_mount_options (const FSMountOptions *fsmo, uid_t caller_uid, - GVariant *given_options) + GVariant *given_options, + const gchar *fs_type, + UDisksBlock *block, + GError **error) { GPtrArray *options; gint n; @@ -573,6 +710,8 @@ prepend_default_mount_options (const FSM } } + get_mount_conf_options (options, fs_type, block, error); + if (g_variant_lookup (given_options, "options", "&s", &option_string)) @@ -730,7 +869,7 @@ calculate_mount_options (UDisksDaemon /* always prepend some reasonable default mount options; these are * chosen here; the user can override them if he wants to */ - options_to_use = prepend_default_mount_options (fsmo, caller_uid, options); + options_to_use = prepend_default_mount_options (fsmo, caller_uid, options, fs_type, block, error); /* validate mount options */ str = g_string_new ("uhelper=udisks2,nodev,nosuid"); @@ -772,6 +911,7 @@ calculate_mount_options (UDisksDaemon g_assert (options_to_use_str == NULL || g_utf8_validate (options_to_use_str, -1, NULL)); + udisks_info ("Calculated mount options: %s", options_to_use_str); return options_to_use_str; }