diff --git a/ChangeLog b/ChangeLog index e04ba3f07..ce5f52e5f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-06-20 Mike Blumenkrantz + + * udisks2 support + 2013-06-19 Mike Blumenkrantz * added check changed to shelf config dialog diff --git a/NEWS b/NEWS index 523ecdc81..8e51d7e98 100644 --- a/NEWS +++ b/NEWS @@ -147,6 +147,7 @@ Improvements: * added dnd support for text/x-moz-url * filemanager dnd operations now show all files when dragging * added check changed to shelf config dialog + * udisks2 support Fixes: * IBar menu didn't allow to configure different icon sources, show contents menu even on empty IBar. diff --git a/src/bin/e_fm/Makefile.am b/src/bin/e_fm/Makefile.am index 55e2d089f..083839c73 100644 --- a/src/bin/e_fm/Makefile.am +++ b/src/bin/e_fm/Makefile.am @@ -22,7 +22,9 @@ enlightenment_fm if HAVE_UDISKS_MOUNT udisks_s = \ e_fm_main_udisks.h \ -e_fm_main_udisks.c +e_fm_main_udisks.c \ +e_fm_main_udisks2.h \ +e_fm_main_udisks2.c else udisks_s = endif diff --git a/src/bin/e_fm/e_fm_main.c b/src/bin/e_fm/e_fm_main.c index 3d45b063c..b78f8252a 100644 --- a/src/bin/e_fm/e_fm_main.c +++ b/src/bin/e_fm/e_fm_main.c @@ -56,6 +56,7 @@ void *alloca (size_t); #include "e_fm_shared_device.h" #ifdef HAVE_UDISKS_MOUNT # include "e_fm_main_udisks.h" +# include "e_fm_main_udisks2.h" #endif #ifdef HAVE_EEZE_MOUNT # include "e_fm_main_eeze.h" @@ -91,7 +92,7 @@ static void _e_fm_init(void) { # ifdef HAVE_UDISKS_MOUNT - _e_fm_main_udisks_init(); + _e_fm_main_udisks2_init(); # else # ifdef HAVE_EEZE_MOUNT _e_fm_main_eeze_init(); @@ -104,6 +105,7 @@ static void _e_fm_shutdown(void) { # ifdef HAVE_UDISKS_MOUNT + _e_fm_main_udisks2_shutdown(); _e_fm_main_udisks_shutdown(); # else # ifdef HAVE_EEZE_MOUNT @@ -172,6 +174,18 @@ _e_fm_main_udisks_catch(Eina_Bool usable) mode = EFM_MODE_USING_EEZE_MOUNT; # endif } + +void +_e_fm_main_udisks2_catch(Eina_Bool usable) +{ + if (usable) + { + mode = EFM_MODE_USING_UDISKS2_MOUNT; + return; + } + _e_fm_main_udisks_init(); + mode = EFM_MODE_USING_UDISKS_MOUNT; +} #endif void @@ -197,6 +211,9 @@ e_volume_mount(E_Volume *v) case EFM_MODE_USING_UDISKS_MOUNT: _e_fm_main_udisks_volume_mount(v); break; + case EFM_MODE_USING_UDISKS2_MOUNT: + _e_fm_main_udisks2_volume_mount(v); + break; #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: @@ -219,6 +236,9 @@ e_volume_unmount(E_Volume *v) case EFM_MODE_USING_UDISKS_MOUNT: _e_fm_main_udisks_volume_unmount(v); break; + case EFM_MODE_USING_UDISKS2_MOUNT: + _e_fm_main_udisks2_volume_unmount(v); + break; #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: @@ -240,6 +260,9 @@ e_volume_eject(E_Volume *v) case EFM_MODE_USING_UDISKS_MOUNT: _e_fm_main_udisks_volume_eject(v); break; + case EFM_MODE_USING_UDISKS2_MOUNT: + _e_fm_main_udisks2_volume_eject(v); + break; #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: @@ -260,6 +283,8 @@ e_volume_find(const char *udi) #ifdef HAVE_UDISKS_MOUNT case EFM_MODE_USING_UDISKS_MOUNT: return _e_fm_main_udisks_volume_find(udi); + case EFM_MODE_USING_UDISKS2_MOUNT: + return _e_fm_main_udisks2_volume_find(udi); #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: @@ -281,6 +306,9 @@ e_storage_del(const char *udi) case EFM_MODE_USING_UDISKS_MOUNT: _e_fm_main_udisks_storage_del(udi); break; + case EFM_MODE_USING_UDISKS2_MOUNT: + _e_fm_main_udisks2_storage_del(udi); + break; #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: @@ -301,6 +329,8 @@ e_storage_find(const char *udi) #ifdef HAVE_UDISKS_MOUNT case EFM_MODE_USING_UDISKS_MOUNT: return _e_fm_main_udisks_storage_find(udi); + case EFM_MODE_USING_UDISKS2_MOUNT: + return _e_fm_main_udisks2_storage_find(udi); #endif #ifdef HAVE_EEZE_MOUNT case EFM_MODE_USING_EEZE_MOUNT: diff --git a/src/bin/e_fm/e_fm_main_udisks.c b/src/bin/e_fm/e_fm_main_udisks.c index f65515efc..804041307 100644 --- a/src/bin/e_fm/e_fm_main_udisks.c +++ b/src/bin/e_fm/e_fm_main_udisks.c @@ -663,15 +663,18 @@ _e_fm_main_udisks_format_error_msg(char **buf, char *tmp; vu = strlen(v->udi) + 1; - vm = strlen(v->mount_point) + 1; + if (v->mount_point) vm = strlen(v->mount_point) + 1; en = strlen(name) + 1; size = vu + vm + en + strlen(message) + 1; tmp = *buf = malloc(size); strcpy(tmp, v->udi); tmp += vu; - strcpy(tmp, v->mount_point); - tmp += vm; + if (v->mount_point) + { + strcpy(tmp, v->mount_point); + tmp += vm; + } strcpy(tmp, name); tmp += en; strcpy(tmp, message); diff --git a/src/bin/e_fm/e_fm_main_udisks2.c b/src/bin/e_fm/e_fm_main_udisks2.c new file mode 100644 index 000000000..4b7cb3282 --- /dev/null +++ b/src/bin/e_fm/e_fm_main_udisks2.c @@ -0,0 +1,1297 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_ALLOCA_H +# include +#elif defined __GNUC__ +# define alloca __builtin_alloca +#elif defined _AIX +# define alloca __alloca +#elif defined _MSC_VER +# include +# define alloca _alloca +#else +# include +# ifdef __cplusplus +extern "C" +# endif +void *alloca(size_t); +#endif + +#ifdef __linux__ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "e_fm_shared_device.h" +#include "e_fm_shared_codec.h" +#include "e_fm_ipc.h" +#include "e_fm_device.h" + +#include "e_fm_main_udisks2.h" +#include "e_fm_main.h" + +#define UDISKS2_BUS "org.freedesktop.UDisks2" +#define UDISKS2_PATH "/org/freedesktop/UDisks2" +#define UDISKS2_INTERFACE "org.freedesktop.UDisks2" +#define UDISKS2_INTERFACE_BLOCK "org.freedesktop.UDisks2.Block" +#define UDISKS2_INTERFACE_DRIVE "org.freedesktop.UDisks2.Drive" +#define UDISKS2_INTERFACE_FILESYSTEM "org.freedesktop.UDisks2.Filesystem" + +typedef struct U2_Block +{ + size_t Size; + Eina_Stringshare *Device; + Eina_Stringshare *parent; + Eina_Bool volume; + Eina_Stringshare *IdType; + Eina_Stringshare *IdLabel; + Eina_Stringshare *IdUUID; + Eina_Bool HintIgnore; + Eina_Stringshare *HintName; + Eina_Stringshare *HintIconName; +} U2_Block; + +static Eldbus_Connection *_e_fm_main_udisks2_conn = NULL; +static Eldbus_Proxy *_e_fm_main_udisks2_proxy = NULL; +static Eina_List *_e_stores = NULL; +static Eina_List *_e_vols = NULL; + +static void _e_fm_main_udisks2_cb_dev_all(void *data, const Eldbus_Message *msg, + Eldbus_Pending *pending); +static void _e_fm_main_udisks2_cb_dev_add(void *data, const Eldbus_Message *msg); +static void _e_fm_main_udisks2_cb_dev_del(void *data, const Eldbus_Message *msg); +static void _e_fm_main_udisks2_cb_vol_mounted(E_Volume *v); +static void _e_fm_main_udisks2_cb_vol_unmounted(E_Volume *v); + +static void _e_fm_main_udisks2_cb_vol_ejected(E_Volume *v); +static int _e_fm_main_udisks2_format_error_msg(char **buf, + E_Volume *v, + const char *name, + const char *message); +static void _e_fm_main_udisks2_cb_storage_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p); +static void _e_fm_main_udisks2_volume_mounts_update(E_Volume *v, Eldbus_Message_Iter *arr3, Eina_Bool first); +static Eina_Bool _e_fm_main_udisks2_vol_mount_timeout(E_Volume *v); +static Eina_Bool _e_fm_main_udisks2_vol_unmount_timeout(E_Volume *v); +static Eina_Bool _e_fm_main_udisks2_vol_eject_timeout(E_Volume *v); +static E_Storage *_storage_find_by_dbus_path(const char *path); +static E_Volume *_volume_find_by_dbus_path(const char *path); +static void _volume_del(E_Volume *v); +static Eina_Bool _storage_del(void *data); +static void _e_fm_main_udisks2_cb_storage_prop_modified_cb(void *data, const Eldbus_Message *msg); +static E_Storage * _e_fm_main_udisks2_storage_drive_add(const char *udi, E_Storage *s, Eldbus_Message_Iter *arr3); + +static Eina_List *vols_ejecting = NULL; + +static Eina_List *stores_registered = NULL; + +static Eina_Stringshare * +_util_fuckyouglib_convert(Eldbus_Message_Iter *fuckyouglib) +{ + Eldbus_Message_Iter *no_really; + unsigned char c, buf[PATH_MAX] = {0}; + unsigned int x = 0; + + if (!eldbus_message_iter_arguments_get(fuckyouglib, "ay", &no_really)) return NULL; + while (eldbus_message_iter_get_and_next(no_really, 'y', &c)) + { + buf[x] = c; + x++; + } + if (!buf[0]) return NULL; + return eina_stringshare_add((char*)buf); +} + +static void +_e_fm_main_udisks2_name_start(void *data __UNUSED__, const Eldbus_Message *msg, + Eldbus_Pending *pending __UNUSED__) +{ + unsigned flag = 0; + Eldbus_Object *obj; + + if (!eldbus_message_arguments_get(msg, "u", &flag) || !flag) + { + _e_fm_main_udisks2_catch(EINA_FALSE); + return; + } + obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, UDISKS2_PATH); + eldbus_object_managed_objects_get(obj, _e_fm_main_udisks2_cb_dev_all, NULL); + + _e_fm_main_udisks2_proxy = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER); + eldbus_proxy_signal_handler_add(_e_fm_main_udisks2_proxy, "InterfacesAdded", + _e_fm_main_udisks2_cb_dev_add, NULL); + eldbus_proxy_signal_handler_add(_e_fm_main_udisks2_proxy, "InterfacesRemoved", + _e_fm_main_udisks2_cb_dev_del, NULL); + //eldbus_signal_handler_add(_e_fm_main_udisks2_conn, NULL, + //NULL, ELDBUS_FDO_INTERFACE_PROPERTIES, "PropertiesChanged", + //_e_fm_main_udisks2_cb_dev_add, NULL); + _e_fm_main_udisks2_catch(EINA_TRUE); /* signal usage of udisks2 for mounting */ +} + +static void +_e_fm_main_udisks2_block_clear(U2_Block *u2) +{ + eina_stringshare_del(u2->Device); + eina_stringshare_del(u2->parent); + eina_stringshare_del(u2->IdType); + eina_stringshare_del(u2->IdLabel); + eina_stringshare_del(u2->IdUUID); + eina_stringshare_del(u2->HintIconName); + eina_stringshare_del(u2->HintName); + +} + +static void +_e_fm_main_udisks2_storage_block_add(E_Storage *s, U2_Block *u2) +{ + s->media_size = u2->Size; + eina_stringshare_replace(&s->icon.drive, u2->HintIconName); + s->system_internal = u2->HintIgnore; +} + +static void +_e_fm_main_udisks2_volume_block_add(E_Volume *v, U2_Block *u2) +{ + v->validated = u2->volume && u2->Device && u2->parent; + if (!v->validated) return; + v->size = u2->Size; + eina_stringshare_replace(&v->udi, u2->Device); + eina_stringshare_replace(&v->parent, u2->parent); + eina_stringshare_replace(&v->icon, u2->HintIconName); + eina_stringshare_replace(&v->uuid, u2->IdUUID); + eina_stringshare_replace(&v->fstype, u2->IdType); + eina_stringshare_replace(&v->label, u2->IdLabel); + if (!v->label) v->label = eina_stringshare_ref(u2->HintName); + +} + +static void +_e_fm_main_udisks2_storage_add_send(E_Storage *s) +{ + void *msg_data; + int msg_size; + + if (!s->validated) return; + if (eina_list_data_find(stores_registered, s)) return; + if ((!s->removable) && (!s->hotpluggable) && (!s->requires_eject)) + { + DBG("removing likely internal storage %s", s->dbus_path); + s->validated = 0; + ecore_idler_add(_storage_del, s->dbus_path); + return; + } + stores_registered = eina_list_append(stores_registered, s); + msg_data = _e_fm_shared_codec_storage_encode(s, &msg_size); + if (msg_data) + { + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_STORAGE_ADD, + 0, 0, 0, msg_data, msg_size); + free(msg_data); + } +} + +static int +_e_fm_main_udisks2_block_handle(Eldbus_Message_Iter *arr3, U2_Block *u2) +{ + Eldbus_Message_Iter *dict3; + int block = 0; + + while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3)) + { + Eldbus_Message_Iter *var; + char *key2, *val, *type; + uint64_t u; + Eina_Bool b; + + if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var)) + continue; + + type = eldbus_message_iter_signature_get(var); + switch (type[0]) + { + case 's': + case 'o': + eldbus_message_iter_arguments_get(var, type, &val); + if ((!val) || (!val[0])) continue; + break; + case 't': + eldbus_message_iter_arguments_get(var, type, &u); + break; + case 'b': + eldbus_message_iter_arguments_get(var, type, &b); + break; + default: break; + } + if (!strcmp(key2, "Device")) + { + u2->Device = _util_fuckyouglib_convert(var); + if (!strncmp(u2->Device, "/dev/ram", 8)) return -1; + } + else if (!strcmp(key2, "Size")) + u2->Size = u; + else if (!strcmp(key2, "Drive")) + u2->parent = eina_stringshare_add(val); + else if (!strcmp(key2, "IdUsage")) + { + if (!strcmp(val, "other")) return -1; + u2->volume = !strcmp(val, "filesystem"); + } + else if (!strcmp(key2, "IdType")) + u2->IdType = eina_stringshare_add(val); + else if (!strcmp(key2, "IdLabel")) + u2->IdLabel = eina_stringshare_add(val); + else if (!strcmp(key2, "IdUUID")) + u2->IdUUID = eina_stringshare_add(val); + else if (!strcmp(key2, "HintIgnore")) + u2->HintIgnore = !!b; + else if (!strcmp(key2, "HintName")) + u2->HintName = eina_stringshare_add(val); + else if (!strcmp(key2, "HintIconName")) + u2->HintIconName = eina_stringshare_add(val); + block = 1; + } + return block; +} + +static void +_e_fm_main_udisks2_handle_device(Eldbus_Message_Iter *dict) +{ + const char *udi; + Eldbus_Message_Iter *arr2, *dict2; + E_Volume *v = NULL; + E_Storage *s = NULL; + U2_Block u2; + int block = 0; + unsigned int pnum = UINT_MAX; + Eina_Stringshare *pname = NULL; + + if (!eldbus_message_iter_arguments_get(dict, "oa{sa{sv}}", &udi, &arr2)) + return; + memset(&u2, 0, sizeof(U2_Block)); + while (eldbus_message_iter_get_and_next(arr2, 'e', &dict2)) + { + Eldbus_Message_Iter *arr3, *dict3; + char *interface; + + if (!eldbus_message_iter_arguments_get(dict2, "sa{sv}", &interface, &arr3)) + continue; + interface += sizeof(UDISKS2_INTERFACE); + if (!strcmp(interface, "Partition")) + { + while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3)) + { + Eldbus_Message_Iter *var; + char *key2, *val, *type; + + if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var)) + continue; + + type = eldbus_message_iter_signature_get(var); + switch (type[0]) + { + case 's': + if (strcmp(key2, "Name")) continue; + if (!eldbus_message_iter_arguments_get(var, type, &val)) continue; + if (val && val[0]) pname = eina_stringshare_add(val); + break; + case 'u': + if (strcmp(key2, "Number")) continue; + eldbus_message_iter_arguments_get(var, type, &pnum); + break; + default: break; + } + } + if (v) + { + v->partition_label = pname; + pname = NULL; + v->partition_number = pnum; + v->partition = (v->partition_label || (pnum != UINT_MAX)); + } + } + else if (!strcmp(interface, "Filesystem")) + { + if (!v) v = _volume_find_by_dbus_path(udi); + if (!v) v = _e_fm_main_udisks2_volume_add(udi, EINA_TRUE); + _e_fm_main_udisks2_volume_mounts_update(v, arr3, 1); + v->partition_label = pname; + pname = NULL; + if (pnum != UINT_MAX) + { + v->partition_number = pnum; + v->partition = 1; + } + if (block) + { + _e_fm_main_udisks2_volume_block_add(v, &u2); + if (!v->validated) E_FREE_FUNC(v, _volume_del); + } + } + else if (!strcmp(interface, "Block")) + { + block = _e_fm_main_udisks2_block_handle(arr3, &u2); + switch (block) + { + case -1: goto out; + case 0: continue; + default: break; + } + if ((!s) && (!v)) + { + v = _volume_find_by_dbus_path(udi); + s = _e_fm_main_udisks2_storage_find(u2.parent); + } + if (s) + _e_fm_main_udisks2_storage_block_add(s, &u2); + if (v) + { + _e_fm_main_udisks2_volume_block_add(v, &u2); + if (!v->validated) E_FREE_FUNC(v, _volume_del); + } + } + else if (!strcmp(interface, "Drive")) + { + s = _e_fm_main_udisks2_storage_drive_add(udi, s, arr3); + if (block) _e_fm_main_udisks2_storage_block_add(s, &u2); + } + } +out: + _e_fm_main_udisks2_block_clear(&u2); + eina_stringshare_del(pname); + if (v && v->validated) e_fm_ipc_volume_add(v); + if (s) + { + if (!block) //cdrom :/ + s->udi = eina_stringshare_add(udi); + _e_fm_main_udisks2_storage_add_send(s); + } +} + +static void +_e_fm_main_udisks2_cb_dev_all(void *data __UNUSED__, const Eldbus_Message *msg, + Eldbus_Pending *pending __UNUSED__) +{ + const char *name, *txt; + Eldbus_Message_Iter *arr1, *dict1; + + if (eldbus_message_error_get(msg, &name, &txt)) + { + ERR("Error %s %s.", name, txt); + return; + } + + if (!eldbus_message_arguments_get(msg, "a{oa{sa{sv}}}", &arr1)) + { + ERR("Error getting arguments."); + return; + } + + while (eldbus_message_iter_get_and_next(arr1, 'e', &dict1)) + _e_fm_main_udisks2_handle_device(dict1); +} + +static void +_e_fm_main_udisks2_cb_vol_props(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED) +{ + U2_Block u2; + int block; + E_Volume *v = data; + Eldbus_Message_Iter *arr; + + memset(&u2, 0, sizeof(U2_Block)); + if (!eldbus_message_arguments_get(msg, "a{sv}", &arr)) + { + ERR("WTF"); + return; + } + block = _e_fm_main_udisks2_block_handle(arr, &u2); + if (block == 1) + { + Eina_Bool valid = v->validated; + + _e_fm_main_udisks2_volume_block_add(v, &u2); + if (v->validated && (valid != v->validated)) + e_fm_ipc_volume_add(v); + else if (!v->validated) + _volume_del(v); + } + _e_fm_main_udisks2_block_clear(&u2); +} + +static void +_e_fm_main_udisks2_cb_dev_add(void *data __UNUSED__, const Eldbus_Message *msg) +{ + const char *interface; + + interface = eldbus_message_interface_get(msg); + //path = eldbus_message_path_get(msg); + //if (!strncmp(path, "/org/freedesktop/UDisks2/drives", sizeof("/org/freedesktop/UDisks2/drives") - 1)) + //{ + //E_Storage *s; +// + //if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2)) + //return; + //interface += sizeof(UDISKS2_INTERFACE); + //if (strcmp(interface, "Drive")) return; + //s = _storage_find_by_dbus_path(path); + //if (!s) return; + //valid = s->validated; + //_e_fm_main_udisks2_storage_drive_add(s->udi, s, arr); + //if (valid != s->validated) + //_e_fm_main_udisks2_storage_add_send(s); + //} + //else if (!strncmp(path, "/org/freedesktop/UDisks2/block_devices", sizeof("/org/freedesktop/UDisks2/block_devices") - 1)) + //{ + //E_Volume *v; +// + //if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2)) + //return; + //v = _volume_find_by_dbus_path(path); + //if (!v) v = _e_fm_main_udisks2_volume_add(path, 1); +// + //interface += sizeof(UDISKS2_INTERFACE); + //if (!strcmp(interface, "Filesystem")) + //_e_fm_main_udisks2_volume_mounts_update(v, arr, 0); + //else if (!strcmp(interface, "Block")) + //{ + //U2_Block u2; + //int block; +// + //memset(&u2, 0, sizeof(U2_Block)); + //block = _e_fm_main_udisks2_block_handle(arr, &u2); + //if (block == 1) + //{ + //valid = v->validated; +// + //_e_fm_main_udisks2_volume_block_add(v, &u2); + //if (v->validated && (valid != v->validated)) + //e_fm_ipc_volume_add(v); + //else if (!v->validated) + //_volume_del(v); + //} + //_e_fm_main_udisks2_block_clear(&u2); + //} + //} + //else + E_Storage *s = eina_list_last_data_get(_e_stores); + E_Volume *v = eina_list_last_data_get(_e_vols); + if (!strcmp(interface, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER)) + _e_fm_main_udisks2_handle_device(eldbus_message_iter_get(msg)); + if (_e_stores && (s != eina_list_last_data_get(_e_stores))) + { + s = eina_list_last_data_get(_e_stores); + if (s->proxy) + eldbus_proxy_property_get_all(s->proxy, _e_fm_main_udisks2_cb_storage_prop_modified, s); + } + if (_e_vols && (v != eina_list_last_data_get(_e_vols))) + { + Eldbus_Message *m; + Eldbus_Object *obj; + + v = eina_list_last_data_get(_e_vols); + m = eldbus_message_method_call_new(UDISKS2_BUS, v->dbus_path, ELDBUS_FDO_INTERFACE_PROPERTIES, "GetAll"); + eldbus_message_arguments_append(m, "s", UDISKS2_INTERFACE_BLOCK); + obj = eldbus_proxy_object_get(v->proxy); + eldbus_object_send(obj, m, _e_fm_main_udisks2_cb_vol_props, v, -1); + } +} + +static void +_e_fm_main_udisks2_cb_dev_del(void *data __UNUSED__, const Eldbus_Message *msg) +{ + char *path, *interface; + Eldbus_Message_Iter *arr; + E_Volume *v; + Eina_Bool vol = EINA_FALSE, sto = EINA_FALSE; + + if (!eldbus_message_arguments_get(msg, "oas", &path, &arr)) + return; + DBG("DB DEV-: %s", path); + + while (eldbus_message_iter_get_and_next(arr, 's', &interface)) + { + interface += sizeof(UDISKS2_INTERFACE); + if (!strcmp(interface, "Filesystem")) + vol = EINA_TRUE; + else if (!strcmp(interface, "Drive")) + sto = EINA_TRUE; + } + if (vol) + { + v = _volume_find_by_dbus_path(path); + if (v && (!v->mounted)) + { + if (v->optype == E_VOLUME_OP_TYPE_EJECT) + _e_fm_main_udisks2_cb_vol_ejected(v); + _volume_del(v); + } + } + if (sto) _e_fm_main_udisks2_storage_del(path); +} + +static void +_e_fm_main_udisks2_cb_storage_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED) +{ + Eldbus_Message_Iter *arr; + E_Storage *s = data; + Eina_Bool valid; + + { + const char *type = eldbus_message_signature_get(msg); + if (type[0] == 's') + { + char *txt; + if (eldbus_message_arguments_get(msg, type, &txt)) + ERR("%s", txt); + } + } + if (!eldbus_message_arguments_get(msg, "a{sv}", &arr)) + return; + valid = s->validated; + _e_fm_main_udisks2_storage_drive_add(s->udi, s, arr); + if (valid != s->validated) + _e_fm_main_udisks2_storage_add_send(s); +} + +static void +_e_fm_main_udisks2_cb_storage_prop_modified_cb(void *data, const Eldbus_Message *msg) +{ + const char *interface; + Eldbus_Message_Iter *arr, *arr2; + E_Storage *s = data; + Eina_Bool valid; + + if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2)) + return; + valid = s->validated; + _e_fm_main_udisks2_storage_drive_add(s->udi, s, arr); + if (valid != s->validated) + _e_fm_main_udisks2_storage_add_send(s); +} + +static void +_e_fm_main_udisks2_cb_vol_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED) +{ + const char *interface; + Eldbus_Message_Iter *arr, *arr2; + E_Volume *v = data; + + if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2)) + return; + interface += sizeof(UDISKS2_INTERFACE); + if (!strcmp(interface, "Filesystem")) + _e_fm_main_udisks2_volume_mounts_update(v, arr, 0); + else if (!strcmp(interface, "Block")) + { + U2_Block u2; + int block; + + memset(&u2, 0, sizeof(U2_Block)); + block = _e_fm_main_udisks2_block_handle(arr, &u2); + if (block == 1) + { + Eina_Bool valid = v->validated; + + _e_fm_main_udisks2_volume_block_add(v, &u2); + if (v->validated && (valid != v->validated)) + e_fm_ipc_volume_add(v); + else if (!v->validated) + _volume_del(v); + } + _e_fm_main_udisks2_block_clear(&u2); + } +} + +static void +_e_fm_main_udisks2_cb_vol_prop_modified_cb(void *data, const Eldbus_Message *msg) +{ + _e_fm_main_udisks2_cb_vol_prop_modified(data, msg, NULL); +} + +static Eina_Bool +_storage_del(void *data) +{ + const char *path = data; + _e_fm_main_udisks2_storage_del(path); + return ECORE_CALLBACK_CANCEL; +} + +static E_Storage * +_e_fm_main_udisks2_storage_drive_add(const char *udi, E_Storage *s, Eldbus_Message_Iter *arr3) +{ + Eldbus_Message_Iter *dict3; + + if (!s) + { + if (!s) s = _e_fm_main_udisks2_storage_find(udi); + if (!s) s = _e_fm_main_udisks2_storage_add(udi); + if (!s) return NULL; + } + if (s->system_internal) + { + DBG("removing storage internal %s", s->dbus_path); + s->validated = 0; + ecore_idler_add(_storage_del, s->dbus_path); + return NULL; + } + while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3)) + { + Eldbus_Message_Iter *var; + char *key2, *val, *type; + Eina_Bool b; + uint64_t t; + + if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var)) + continue; + + type = eldbus_message_iter_signature_get(var); + switch (type[0]) + { + case 's': + case 'o': + eldbus_message_iter_arguments_get(var, type, &val); + break; + case 'b': + eldbus_message_iter_arguments_get(var, type, &b); + break; + case 't': + eldbus_message_iter_arguments_get(var, type, &t); + break; + default: break; + } + + if (!strcmp(key2, "ConnectionBus")) + eina_stringshare_replace(&s->bus, val); + else if (!strcmp(key2, "MediaCompatibility")) + { + Eldbus_Message_Iter *inner_array; + const char *media; + + if (!eldbus_message_iter_arguments_get(var, "as", &inner_array)) + continue; + + if (eldbus_message_iter_get_and_next(inner_array, 's', &media)) + eina_stringshare_replace(&s->drive_type, media); + } + else if (!strcmp(key2, "Model")) + eina_stringshare_replace(&s->model, val); + else if (!strcmp(key2, "Vendor")) + eina_stringshare_replace(&s->vendor, val); + else if (!strcmp(key2, "Serial")) + eina_stringshare_replace(&s->serial, val); + else if (!strcmp(key2, "MediaAvailable")) + s->media_available = !!b; + else if (!strcmp(key2, "Size")) + s->media_size = t; + else if (!strcmp(key2, "Ejectable")) + s->requires_eject = !!b; + else if (!strcmp(key2, "Removable")) + s->hotpluggable = !!b; + else if (!strcmp(key2, "MediaRemovable")) + s->removable = !!b; + } + + INF("++STO:\n udi: %s\n bus: %s\n drive_type: %s\n model: %s\n vendor: %s\n serial: %s\n icon.drive: %s\n icon.volume: %s\n", s->udi, s->bus, s->drive_type, s->model, s->vendor, s->serial, s->icon.drive, s->icon.volume); + s->validated = EINA_TRUE; + + if (!s->proxy) + { + Eldbus_Object *obj; + + obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, s->udi); + s->proxy = eldbus_proxy_get(obj, UDISKS2_INTERFACE_DRIVE); + eldbus_proxy_properties_monitor(s->proxy, 1); + eldbus_proxy_properties_changed_callback_add(s->proxy, _e_fm_main_udisks2_cb_storage_prop_modified_cb, s); + } + return s; +} + +static int +_e_fm_main_udisks2_format_error_msg(char **buf, + E_Volume *v, + const char *name, + const char *message) +{ + int size, vu, vm, en; + char *tmp; + + vu = strlen(v->udi) + 1; + if (v->mount_point) vm = strlen(v->mount_point) + 1; + en = strlen(name) + 1; + size = vu + vm + en + strlen(message) + 1; + tmp = *buf = malloc(size); + + strcpy(tmp, v->udi); + tmp += vu; + if (v->mount_point) + { + strcpy(tmp, v->mount_point); + tmp += vm; + } + strcpy(tmp, name); + tmp += en; + strcpy(tmp, message); + + return size; +} + +static Eina_Bool +_e_fm_main_udisks2_vol_mount_timeout(E_Volume *v) +{ + char *buf; + int size; + + v->guard = NULL; + + E_FREE_FUNC(v->op, eldbus_pending_cancel); + v->optype = E_VOLUME_OP_TYPE_NONE; + size = _e_fm_main_udisks2_format_error_msg(&buf, v, + "org.enlightenment.fm2.MountTimeout", + "Unable to mount the volume with specified time-out."); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return ECORE_CALLBACK_CANCEL; +} + +static void +_e_fm_main_udisks2_cb_vol_mounted(E_Volume *v) +{ + char *buf; + int size; + + E_FREE_FUNC(v->guard, ecore_timer_del); + if (!v->mount_point) return; /* come back later */ + + v->optype = E_VOLUME_OP_TYPE_NONE; + v->op = NULL; + v->mounted = EINA_TRUE; + INF("MOUNT: %s from %s", v->udi, v->mount_point); + size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1; + buf = alloca(size); + strcpy(buf, v->udi); + strcpy(buf + strlen(buf) + 1, v->mount_point); + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_MOUNT_DONE, + 0, 0, 0, buf, size); +} + +static Eina_Bool +_e_fm_main_udisks2_vol_unmount_timeout(E_Volume *v) +{ + char *buf; + int size; + + v->guard = NULL; + if (v->op) + eldbus_pending_cancel(v->op); + v->op = NULL; + v->optype = E_VOLUME_OP_TYPE_NONE; + size = _e_fm_main_udisks2_format_error_msg(&buf, v, + "org.enlightenment.fm2.UnmountTimeout", + "Unable to unmount the volume with specified time-out."); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return ECORE_CALLBACK_CANCEL; +} + +static void +_e_fm_main_udisks2_cb_vol_unmounted(E_Volume *v) +{ + char *buf; + int size; + + E_FREE_FUNC(v->guard, ecore_timer_del); + + if (v->optype != E_VOLUME_OP_TYPE_EJECT) + { + v->optype = E_VOLUME_OP_TYPE_NONE; + v->op = NULL; + } + + v->mounted = EINA_FALSE; + INF("UNMOUNT: %s from %s", v->udi, v->mount_point); + size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1; + buf = alloca(size); + strcpy(buf, v->udi); + strcpy(buf + strlen(buf) + 1, v->mount_point); + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_UNMOUNT_DONE, + 0, 0, 0, buf, size); +} + +static Eina_Bool +_e_fm_main_udisks2_vol_eject_timeout(E_Volume *v) +{ + char *buf; + int size; + + v->guard = NULL; + if (v->op) + eldbus_pending_cancel(v->op); + v->op = NULL; + v->optype = E_VOLUME_OP_TYPE_NONE; + size = _e_fm_main_udisks2_format_error_msg(&buf, v, + "org.enlightenment.fm2.EjectTimeout", + "Unable to eject the media with specified time-out."); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR, + 0, 0, 0, buf, size); + free(buf); + + return ECORE_CALLBACK_CANCEL; +} + +static Eldbus_Pending * +_volume_eject(Eldbus_Proxy *proxy) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *array, *main_iter; + + msg = eldbus_proxy_method_call_new(proxy, "Eject"); + main_iter = eldbus_message_iter_get(msg); + eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array); + eldbus_message_iter_container_close(main_iter, array); + + return eldbus_proxy_send(proxy, msg, NULL, NULL, -1); +} + +static void +_volume_eject_umount_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED) +{ + const char *name, *txt; + E_Volume *v = data; + + if (eldbus_message_error_get(msg, &name, &txt)) + ERR("%s: %s", name, txt); + else if (v->optype == E_VOLUME_OP_TYPE_EJECT) + { + vols_ejecting = eina_list_remove(vols_ejecting, v); + _volume_eject(v->storage->proxy); + } + +} + +static Eldbus_Pending * +_volume_umount(E_Volume *v) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *array, *main_iter; + + msg = eldbus_proxy_method_call_new(v->proxy, "Unmount"); + main_iter = eldbus_message_iter_get(msg); + eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array); + eldbus_message_iter_container_close(main_iter, array); + + return eldbus_proxy_send(v->proxy, msg, _volume_eject_umount_cb, v, -1); +} + +static Eldbus_Pending * +_volume_mount(Eldbus_Proxy *proxy, const char *fstype, const char *buf) +{ + Eldbus_Message *msg; + Eldbus_Message_Iter *array, *main_iter, *dict, *var; + char opt_txt[] = "options"; + char fs_txt[] = "fstype"; + + msg = eldbus_proxy_method_call_new(proxy, "Mount"); + main_iter = eldbus_message_iter_get(msg); + if (!eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array)) + ERR("E"); + if (fstype) + { + if (!eldbus_message_iter_arguments_append(array, "{sv}", &dict)) + ERR("E"); + eldbus_message_iter_basic_append(dict, 's', fs_txt); + + var = eldbus_message_iter_container_new(dict, 'v', "s"); + eldbus_message_iter_basic_append(var, 's', fstype); + eldbus_message_iter_container_close(dict, var); + eldbus_message_iter_container_close(array, dict); + + } + if (buf[0]) + { + if (!eldbus_message_iter_arguments_append(array, "{sv}", &dict)) + ERR("E"); + eldbus_message_iter_basic_append(dict, 's', opt_txt); + + var = eldbus_message_iter_container_new(dict, 'v', "s"); + eldbus_message_iter_basic_append(var, 's', buf); + eldbus_message_iter_container_close(dict, var); + eldbus_message_iter_container_close(array, dict); + } + eldbus_message_iter_container_close(main_iter, array); + + return eldbus_proxy_send(proxy, msg, NULL, NULL, -1); +} + +static void +_e_fm_main_udisks2_cb_vol_ejected(E_Volume *v) +{ + char *buf; + int size; + + E_FREE_FUNC(v->guard, ecore_timer_del); + v->optype = E_VOLUME_OP_TYPE_NONE; + + size = strlen(v->udi) + 1; + buf = alloca(size); + strcpy(buf, v->udi); + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_EJECT_DONE, + 0, 0, 0, buf, size); +} + +static void +_e_fm_main_udisks2_volume_mounts_update(E_Volume *v, Eldbus_Message_Iter *arr3, Eina_Bool first) +{ + Eldbus_Message_Iter *dict3; + Eina_List *mounts = NULL; + + while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3)) + { + Eldbus_Message_Iter *var; + char *key2, *type; + + if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var)) + continue; + + type = eldbus_message_iter_signature_get(var); + switch (type[0]) + { + Eldbus_Message_Iter *fuckyouglib; + + case 'a': + if (strcmp(key2, "MountPoints")) continue; + /* glib developers are assholes, so this is "aay" instead of just "as" */ + if (!eldbus_message_iter_arguments_get(var, type, &fuckyouglib)) + { + ERR("fucked by glib I guess"); + continue; + } + do + { + Eina_Stringshare *m; + + m = _util_fuckyouglib_convert(fuckyouglib); + if (m) mounts = eina_list_append(mounts, m); + } + while (eldbus_message_iter_next(fuckyouglib)); + default: continue; + } + } + if (first) + { + eina_stringshare_replace(&v->mount_point, eina_list_last_data_get(mounts)); + v->mounted = !!v->mount_point; + if (v->storage) + v->storage->media_available = v->mounted; + } + else if ((!v->mounted) || (!eina_list_data_find(mounts, v->mount_point))) + { + if (mounts) + eina_stringshare_replace(&v->mount_point, eina_list_last_data_get(mounts)); + v->mounted = !!mounts; + if (v->storage) + v->storage->media_available = v->mounted; + switch (v->optype) + { + case E_VOLUME_OP_TYPE_MOUNT: + _e_fm_main_udisks2_cb_vol_mounted(v); + break; + case E_VOLUME_OP_TYPE_UNMOUNT: + _e_fm_main_udisks2_cb_vol_unmounted(v); + break; + case E_VOLUME_OP_TYPE_EJECT: + if (vols_ejecting && eina_list_data_find(vols_ejecting, v)) + _e_fm_main_udisks2_cb_vol_unmounted(v); + else + _e_fm_main_udisks2_cb_vol_ejected(v); + break; + default: break; + } + } + E_FREE_LIST(mounts, eina_stringshare_del); +} + +E_Volume * +_e_fm_main_udisks2_volume_add(const char *path, Eina_Bool first_time) +{ + E_Volume *v; + Eldbus_Object *obj; + + if (!path) return NULL; + if (_volume_find_by_dbus_path(path)) return NULL; + v = calloc(1, sizeof(E_Volume)); + if (!v) return NULL; + v->dbus_path = eina_stringshare_add(path); + INF("VOL+ %s", path); + v->efm_mode = EFM_MODE_USING_UDISKS2_MOUNT; + v->first_time = first_time; + _e_vols = eina_list_append(_e_vols, v); + obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, path); + v->proxy = eldbus_proxy_get(obj, UDISKS2_INTERFACE_FILESYSTEM); + eldbus_proxy_properties_monitor(v->proxy, 1); + eldbus_proxy_properties_changed_callback_add(v->proxy, _e_fm_main_udisks2_cb_vol_prop_modified_cb, v); + + return v; +} + +void +_e_fm_main_udisks2_volume_del(const char *path) +{ + E_Volume *v; + + v = _volume_find_by_dbus_path(path); + if (!v) return; + _volume_del(v); +} + +static void +_volume_del(E_Volume *v) +{ + E_FREE_FUNC(v->guard, ecore_timer_del); + if (v->validated) + { + INF("--VOL %s", v->udi); + /* FIXME: send event of storage volume (disk) removed */ + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_VOLUME_DEL, + 0, 0, 0, v->udi, eina_stringshare_strlen(v->udi) + 1); + } + v->optype = E_VOLUME_OP_TYPE_NONE; + if (v->proxy) + { + Eldbus_Object *obj = eldbus_proxy_object_get(v->proxy); + eldbus_proxy_unref(v->proxy); + eldbus_object_unref(obj); + } + _e_vols = eina_list_remove(_e_vols, v); + _e_fm_shared_device_volume_free(v); +} + +E_Volume * +_e_fm_main_udisks2_volume_find(const char *udi) +{ + Eina_List *l; + E_Volume *v; + + if (!udi) return NULL; + EINA_LIST_FOREACH(_e_vols, l, v) + { + if (!v->udi) continue; + if (!strcmp(udi, v->udi)) return v; + } + return NULL; +} + +static E_Volume * +_volume_find_by_dbus_path(const char *path) +{ + Eina_List *l; + E_Volume *v; + + if (!path) return NULL; + EINA_LIST_FOREACH(_e_vols, l, v) + if (!strcmp(path, v->dbus_path)) return v; + return NULL; +} + +void +_e_fm_main_udisks2_volume_eject(E_Volume *v) +{ + if (!v || v->guard) return; + if (!v->storage) v->storage = _e_fm_main_udisks2_storage_find(v->parent); + if (!v->storage) + { + ERR("COULD NOT FIND DISK STORAGE!!!"); + return; + } + if (v->mounted) + { + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_unmount_timeout, v); + v->op = _volume_umount(v); + vols_ejecting = eina_list_append(vols_ejecting, v); + } + else + { + v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_eject_timeout, v); + v->op = _volume_eject(v->storage->proxy); + } + v->optype = E_VOLUME_OP_TYPE_EJECT; +} + +void +_e_fm_main_udisks2_volume_unmount(E_Volume *v) +{ + if (!v || v->guard) return; + INF("unmount %s %s", v->udi, v->mount_point); + + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_unmount_timeout, v); + v->op = _volume_umount(v); + v->optype = E_VOLUME_OP_TYPE_UNMOUNT; +} + +void +_e_fm_main_udisks2_volume_mount(E_Volume *v) +{ + char buf[256] = {0}; + + if ((!v) || (v->guard)) + return; + + INF("mount %s %s [fs type = %s]", v->udi, v->mount_point, v->fstype); + + // Map uid to current user if possible + // Possible filesystems found in udisks2 source (src/udisks2linuxfilesystem.c) as of 2012-07-11 + if (!strcmp(v->fstype, "vfat")) + snprintf(buf, sizeof(buf), "uid=%i,utf8=1", (int)getuid()); + else if ((!strcmp(v->fstype, "iso9660")) || (!strcmp(v->fstype, "udf"))) + // force utf8 as the encoding - e only likes/handles utf8. its the + // pseudo-standard these days anyway for "linux" for intl text to work + // everywhere. problem is some fs's use differing options and udisks2 + // doesn't allow some options with certain filesystems. + // Valid options found in udisks2 (src/udisks2linuxfilesystem.c) as of 2012-07-11 + // Note that these options are default with the latest udisks2, kept here to + // avoid breakage in the future (hopefully). + snprintf(buf, sizeof(buf), "uid=%i,iocharset=utf8", (int)getuid()); + else if (!strcmp(v->fstype, "ntfs")) + snprintf(buf, sizeof(buf), "uid=%i", (int)getuid()); + + v->guard = ecore_timer_add(E_FM_MOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_mount_timeout, v); + + // It was previously noted here that ubuntu 10.04 failed to mount if opt was passed to + // e_udisks2_volume_mount. The reason at the time was unknown and apparently never found. + // I theorize that this was due to improper mount options being passed (namely the utf8 options). + // If this still fails on Ubuntu 10.04 then an actual fix should be found. + v->op = _volume_mount(v->proxy, v->fstype, buf); + + v->optype = E_VOLUME_OP_TYPE_MOUNT; +} + +void +_e_fm_main_udisks2_init(void) +{ + eldbus_init(); + _e_fm_main_udisks2_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM); + if (!_e_fm_main_udisks2_conn) return; + + eldbus_name_start(_e_fm_main_udisks2_conn, UDISKS2_BUS, 0, + _e_fm_main_udisks2_name_start, NULL); +} + +void +_e_fm_main_udisks2_shutdown(void) +{ + if (_e_fm_main_udisks2_proxy) + { + Eldbus_Object *obj; + obj = eldbus_proxy_object_get(_e_fm_main_udisks2_proxy); + eldbus_proxy_unref(_e_fm_main_udisks2_proxy); + eldbus_object_unref(obj); + } + if (_e_fm_main_udisks2_conn) + eldbus_connection_unref(_e_fm_main_udisks2_conn); + eldbus_shutdown(); +} + +E_Storage * +_e_fm_main_udisks2_storage_add(const char *path) +{ + E_Storage *s; + + if (!path) return NULL; + if (_storage_find_by_dbus_path(path)) return NULL; + s = calloc(1, sizeof(E_Storage)); + if (!s) return NULL; + + DBG("STORAGE+=%s", path); + s->dbus_path = eina_stringshare_add(path); + s->udi = eina_stringshare_ref(s->dbus_path); + _e_stores = eina_list_append(_e_stores, s); + return s; +} + +void +_e_fm_main_udisks2_storage_del(const char *path) +{ + E_Storage *s; + + s = _storage_find_by_dbus_path(path); + if (!s) return; + if (s->validated) + { + stores_registered = eina_list_remove(stores_registered, s); + INF("--STO %s", s->udi); + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_STORAGE_DEL, + 0, 0, 0, s->udi, strlen(s->udi) + 1); + } + _e_stores = eina_list_remove(_e_stores, s); + if (s->proxy) + { + Eldbus_Object *obj = eldbus_proxy_object_get(s->proxy); + eldbus_proxy_unref(s->proxy); + eldbus_object_unref(obj); + } + _e_fm_shared_device_storage_free(s); +} + +static E_Storage * +_storage_find_by_dbus_path(const char *path) +{ + Eina_List *l; + E_Storage *s; + + EINA_LIST_FOREACH(_e_stores, l, s) + if (!strcmp(path, s->dbus_path)) return s; + return NULL; +} + +E_Storage * +_e_fm_main_udisks2_storage_find(const char *udi) +{ + Eina_List *l; + E_Storage *s; + + EINA_LIST_FOREACH(_e_stores, l, s) + { + if (!s->udi) continue; + if (!strcmp(udi, s->udi)) return s; + } + return NULL; +} diff --git a/src/bin/e_fm/e_fm_main_udisks2.h b/src/bin/e_fm/e_fm_main_udisks2.h new file mode 100644 index 000000000..c22fb2eb6 --- /dev/null +++ b/src/bin/e_fm/e_fm_main_udisks2.h @@ -0,0 +1,21 @@ +#ifndef E_FM_MAIN_UDISKS2_H +#define E_FM_MAIN_UDISKS2_H + +E_Volume *_e_fm_main_udisks2_volume_add(const char *udi, Eina_Bool first_time); +void _e_fm_main_udisks2_volume_del(const char *udi); +E_Volume *_e_fm_main_udisks2_volume_find(const char *udi); + +void _e_fm_main_udisks2_volume_eject(E_Volume *v); +void _e_fm_main_udisks2_volume_unmount(E_Volume *v); +void _e_fm_main_udisks2_volume_mount(E_Volume *v); + +E_Storage *_e_fm_main_udisks2_storage_add(const char *udi); +void _e_fm_main_udisks2_storage_del(const char *udi); +E_Storage *_e_fm_main_udisks2_storage_find(const char *udi); + + +void _e_fm_main_udisks2_init(void); +void _e_fm_main_udisks2_shutdown(void); +void _e_fm_main_udisks2_catch(Eina_Bool usable); + +#endif diff --git a/src/bin/e_fm_shared_types.h.in b/src/bin/e_fm_shared_types.h.in index d041b9ad7..06e0de29e 100644 --- a/src/bin/e_fm_shared_types.h.in +++ b/src/bin/e_fm_shared_types.h.in @@ -23,6 +23,7 @@ typedef enum EFM_MODE_USING_RASTER_MOUNT, EFM_MODE_USING_HAL_MOUNT, EFM_MODE_USING_UDISKS_MOUNT, + EFM_MODE_USING_UDISKS2_MOUNT, EFM_MODE_USING_EEZE_MOUNT } Efm_Mode; diff --git a/src/modules/fileman/e_mod_config.c b/src/modules/fileman/e_mod_config.c index c84da1d2f..bce0193c8 100644 --- a/src/modules/fileman/e_mod_config.c +++ b/src/modules/fileman/e_mod_config.c @@ -429,6 +429,9 @@ _basic_create(E_Config_Dialog *cfd __UNUSED__, case EFM_MODE_USING_UDISKS_MOUNT: snprintf(buf, sizeof(buf), "%s: UDISKS", _("Mode")); break; + case EFM_MODE_USING_UDISKS2_MOUNT: + snprintf(buf, sizeof(buf), "%s: UDISKS2", _("Mode")); + break; case EFM_MODE_USING_EEZE_MOUNT: snprintf(buf, sizeof(buf), "%s: EEZE", _("Mode")); break;