diff --git a/configure.ac b/configure.ac index 4f255559f..0e6fed75d 100644 --- a/configure.ac +++ b/configure.ac @@ -350,11 +350,10 @@ fi AC_SUBST([EEZE_MOUNT_CONFIG]) AC_SUBST([DBUS_MOUNT_CONFIG]) AM_CONDITIONAL([HAVE_HAL_MOUNT], [test -n "$hal_mount"]) -AM_CONDITIONAL([HAVE_UDISKS_MOUNT], [false]) AM_CONDITIONAL([HAVE_EEZE_MOUNT], [false]) test -n "$hal_mount" && AC_DEFINE_UNQUOTED([HAVE_HAL_MOUNT], [1], [enable HAL mounting]) -##test -n "$udisks_mount" && AC_DEFINE_UNQUOTED([HAVE_UDISKS_MOUNT], [1], [enable Udisks mounting]) -##AM_CONDITIONAL([HAVE_UDISKS_MOUNT], [test -n "$udisks_mount"]) +test -n "$udisks_mount" && AC_DEFINE_UNQUOTED([HAVE_UDISKS_MOUNT], [1], [enable Udisks mounting]) +AM_CONDITIONAL([HAVE_UDISKS_MOUNT], [test -n "$udisks_mount"]) ##AM_CONDITIONAL([HAVE_EEZE_MOUNT], [test -n "$eeze_mount"]) # doxygen program for documentation building diff --git a/src/bin/e_fm/Makefile.am b/src/bin/e_fm/Makefile.am index 0bde05add..6eb107713 100644 --- a/src/bin/e_fm/Makefile.am +++ b/src/bin/e_fm/Makefile.am @@ -28,12 +28,21 @@ else hal_s = endif +if HAVE_UDISKS_MOUNT +udisks_s = \ +e_fm_main_udisks.h \ +e_fm_main_udisks.c +else +udisks_s = +endif + enlightenment_fm_SOURCES = \ e_fm_main.h \ e_fm_ipc.h \ e_fm_main.c \ e_fm_ipc.c \ $(hal_s) \ +$(udisks_s) \ ../e_fm_shared_codec.c \ ../e_fm_shared_device.c \ ../e_user.c \ diff --git a/src/bin/e_fm/e_fm_main_udisks.c b/src/bin/e_fm/e_fm_main_udisks.c new file mode 100644 index 000000000..862855594 --- /dev/null +++ b/src/bin/e_fm/e_fm_main_udisks.c @@ -0,0 +1,929 @@ +#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 + +#include "e_fm_main.h" +#include "e_fm_main_udisks.h" +#ifdef HAVE_EEZE_MOUNT +# include "e_fm_main_eeze.h" +#endif + +#include "e_fm_shared_codec.h" +#include "e_fm_shared_device.h" +#include "e_fm_ipc.h" +#include "e_fm_device.h" + +static E_DBus_Signal_Handler *_udisks_poll = NULL; +static E_DBus_Connection *_e_fm_main_udisks_conn = NULL; +static Eina_List *_e_stores = NULL; +static Eina_List *_e_vols = NULL; + +static void _e_fm_main_udisks_cb_dev_all(void *user_data __UNUSED__, + E_Ukit_String_List_Return *ret, + DBusError *error); +static void _e_fm_main_udisks_cb_dev_verify(const char *udi, + E_Ukit_Property *ret, + DBusError *error); +static void _e_fm_main_udisks_cb_dev_add_verify(const char *udi, + E_Ukit_Property *ret, + DBusError *error); +static void _e_fm_main_udisks_cb_dev_add(void *data, + DBusMessage *msg); +static void _e_fm_main_udisks_cb_dev_del(void *data, + DBusMessage *msg); +static void _e_fm_main_udisks_cb_dev_chg(void *data, + DBusMessage *msg); +static void _e_fm_main_udisks_cb_prop_modified(E_Volume *v, + DBusMessage *msg); +static void _e_fm_main_udisks_cb_store_prop(E_Storage *s, + E_Ukit_Properties *ret, + DBusError *error); +static void _e_fm_main_udisks_cb_vol_prop(E_Volume *v, + E_Ukit_Properties *ret, + DBusError *error); +static void _e_fm_main_udisks_cb_vol_mounted(E_Volume *v, + DBusError *error); +static void _e_fm_main_udisks_cb_vol_unmounted(E_Volume *v, + DBusError *error); +static void _e_fm_main_udisks_cb_vol_unmounted_before_eject(E_Volume *v, + void *method_return __UNUSED__, + DBusError *error); + +static Eina_Bool _e_fm_main_udisks_cb_vol_ejecting_after_unmount(E_Volume *v); +static void _e_fm_main_udisks_cb_vol_ejected(E_Volume *v, + void *method_return __UNUSED__, + DBusError *error); +static int _e_fm_main_udisks_format_error_msg(char **buf, + E_Volume *v, + DBusError *error); +static void _e_fm_main_udisks_test(void *data, + DBusMessage *msg, + DBusError *error); +static void _e_fm_main_udisks_poll(void *data, + DBusMessage *msg); + +static Eina_Bool _e_fm_main_udisks_vol_mount_timeout(E_Volume *v); +static Eina_Bool _e_fm_main_udisks_vol_unmount_timeout(E_Volume *v); +static Eina_Bool _e_fm_main_udisks_vol_eject_timeout(E_Volume *v); + +static void +_e_fm_main_udisks_poll(void *data __UNUSED__, + DBusMessage *msg) +{ + DBusError err; + const char *name, *from, *to; + + dbus_error_init(&err); + if (!dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &from, + DBUS_TYPE_STRING, &to, + DBUS_TYPE_INVALID)) + dbus_error_free(&err); + + printf("name: %s\nfrom: %s\nto: %s\n", name, from, to); + if ((name) && !strcmp(name, E_UDISKS_BUS)) + _e_fm_main_udisks_test(NULL, NULL, NULL); +} + +static void +_e_fm_main_udisks_test(void *data __UNUSED__, + DBusMessage *msg __UNUSED__, + DBusError *error) +{ + if ((error) && (dbus_error_is_set(error))) + { + dbus_error_free(error); + if (!_udisks_poll) + _udisks_poll = e_dbus_signal_handler_add(_e_fm_main_udisks_conn, + E_DBUS_FDO_BUS, E_DBUS_FDO_PATH, + E_DBUS_FDO_INTERFACE, + "NameOwnerChanged", _e_fm_main_udisks_poll, NULL); +#ifdef HAVE_EEZE_MOUNT + _e_fm_main_eeze_init(); /* check for eeze while listening for udisks */ +#endif + return; + } + if (_udisks_poll) + e_dbus_signal_handler_del(_e_fm_main_udisks_conn, _udisks_poll); + + e_udisks_get_all_devices(_e_fm_main_udisks_conn, (E_DBus_Callback_Func)_e_fm_main_udisks_cb_dev_all, NULL); + + e_dbus_signal_handler_add(_e_fm_main_udisks_conn, E_UDISKS_BUS, + E_UDISKS_PATH, + E_UDISKS_INTERFACE, + "DeviceAdded", (E_DBus_Signal_Cb)_e_fm_main_udisks_cb_dev_add, NULL); + e_dbus_signal_handler_add(_e_fm_main_udisks_conn, E_UDISKS_BUS, + E_UDISKS_PATH, + E_UDISKS_INTERFACE, + "DeviceRemoved", (E_DBus_Signal_Cb)_e_fm_main_udisks_cb_dev_del, NULL); + e_dbus_signal_handler_add(_e_fm_main_udisks_conn, E_UDISKS_BUS, + E_UDISKS_PATH, + E_UDISKS_INTERFACE, + "DeviceChanged", (E_DBus_Signal_Cb)_e_fm_main_udisks_cb_dev_chg, NULL); + _e_fm_main_udisks_catch(EINA_TRUE); /* signal usage of udisks for mounting */ +} + +static void +_e_fm_main_udisks_cb_dev_all(void *user_data __UNUSED__, + E_Ukit_String_List_Return *ret, + DBusError *error) +{ + Eina_List *l; + const char *udi; + + if (!ret || !ret->strings) return; + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + return; + } + + EINA_LIST_FOREACH(ret->strings, l, udi) + { +// printf("DB INIT DEV+: %s\n", udi); + e_udisks_get_property(_e_fm_main_udisks_conn, udi, "IdUsage", + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_dev_verify, (void*)eina_stringshare_add(udi)); + } +} + + +static void +_e_fm_main_udisks_cb_dev_verify(const char *udi, + E_Ukit_Property *ret, + DBusError *error) +{ + if (!ret) return; + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + return; + } + + if ((!ret->val.s) || (!ret->val.s[0])) /* storage */ + _e_fm_main_udisks_storage_add(udi); + else if (!strcmp(ret->val.s, "filesystem")) + { +// printf("DB VOL+: %s\n", udi); + _e_fm_main_udisks_volume_add(udi, EINA_TRUE); + } + eina_stringshare_del(udi); +} + +static void +_e_fm_main_udisks_cb_dev_add_verify(const char *udi, + E_Ukit_Property *ret, + DBusError *error) +{ + if (!ret) return; + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + return; + } + + if ((!ret->val.s) || (!ret->val.s[0])) /* storage */ + _e_fm_main_udisks_storage_add(udi); + else if (!strcmp(ret->val.s, "filesystem")) + { +// printf("DB VOL+: %s\n", udi); + _e_fm_main_udisks_volume_add(udi, EINA_FALSE); + } + eina_stringshare_del(udi); +} + +static void +_e_fm_main_udisks_cb_dev_add(void *data __UNUSED__, + DBusMessage *msg) +{ + DBusError err; + char *udi = NULL; + + dbus_error_init(&err); + dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_INVALID); + if (!udi) return; + e_udisks_get_property(_e_fm_main_udisks_conn, udi, "IdUsage", + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_dev_add_verify, (void*)eina_stringshare_add(udi)); +} + +static void +_e_fm_main_udisks_cb_dev_del(void *data __UNUSED__, + DBusMessage *msg) +{ + DBusError err; + char *udi; + E_Volume *v; + + dbus_error_init(&err); + + dbus_message_get_args(msg, + &err, DBUS_TYPE_STRING, + &udi, DBUS_TYPE_INVALID); +// printf("DB DEV-: %s\n", udi); + if ((v = _e_fm_main_udisks_volume_find(udi))) + { + if (v->optype == E_VOLUME_OP_TYPE_EJECT) + _e_fm_main_udisks_cb_vol_ejected(v, msg, &err); + } + _e_fm_main_udisks_storage_del(udi); + _e_fm_main_udisks_volume_del(udi); +} + +static void +_e_fm_main_udisks_cb_dev_chg(void *data __UNUSED__, + DBusMessage *msg) +{ + DBusError err; + char *udi; + + dbus_error_init(&err); + + dbus_message_get_args(msg, &err, + DBUS_TYPE_STRING, &udi, + DBUS_TYPE_INVALID); + +// printf("DB STORE CAP+: %s\n", udi); + e_udisks_get_property(_e_fm_main_udisks_conn, udi, "IdUsage", + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_dev_add_verify, (void*)eina_stringshare_add(udi)); +} + +static void +_e_fm_main_udisks_cb_prop_modified(E_Volume *v, + DBusMessage *msg) +{ + if (!v) return; + + if (dbus_message_get_error_name(msg)) + { + printf("DBUS ERROR: %s\n", dbus_message_get_error_name(msg)); + return; + } + e_udisks_get_all_properties(_e_fm_main_udisks_conn, v->udi, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_prop, v); +} + +static void +_e_fm_main_udisks_cb_store_prop(E_Storage *s, + E_Ukit_Properties *ret, + DBusError *error) +{ + int err = 0; + + if (!ret) goto error; + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + goto error; + } + + s->bus = e_ukit_property_string_get(ret, "DriveConnectionInterface", &err); + if (err) goto error; + s->bus = eina_stringshare_add(s->bus); + s->drive_type = e_ukit_property_string_get(ret, "DriveMediaCompatibility", &err); + if (err) goto error; + s->drive_type = eina_stringshare_add(s->drive_type); + s->model = e_ukit_property_string_get(ret, "DriveModel", &err); + if (err) goto error; + s->model = eina_stringshare_add(s->model); + s->vendor = e_ukit_property_string_get(ret, "DriveVendor", &err); + if (err) goto error; + s->vendor = eina_stringshare_add(s->vendor); + s->serial = e_ukit_property_string_get(ret, "DriveSerial", &err); +// if (err) goto error; + if (err) printf("Error getting serial for %s\n", s->udi); + s->serial = eina_stringshare_add(s->serial); + + s->removable = e_ukit_property_bool_get(ret, "DeviceIsRemovable", &err); + + if (s->removable) + { + s->media_available = e_ukit_property_bool_get(ret, "DeviceIsMediaAvailable", &err); + s->media_size = e_ukit_property_uint64_get(ret, "DeviceSize", &err); + } + + s->requires_eject = e_ukit_property_bool_get(ret, "DriveIsMediaEjectable", &err); + s->hotpluggable = e_ukit_property_bool_get(ret, "DriveCanDetach", &err); + s->media_check_enabled = !e_ukit_property_bool_get(ret, "DeviceIsMediaChangeDetectionInhibited", &err); + + s->icon.drive = e_ukit_property_string_get(ret, "DevicePresentationIconName", &err); + s->icon.drive = eina_stringshare_add(s->icon.drive); + s->icon.volume = e_ukit_property_string_get(ret, "DevicePresentationIconName", &err); + s->icon.volume = eina_stringshare_add(s->icon.volume); + +// printf("++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\n", s->udi, s->bus, s->drive_type, s->model, s->vendor, s->serial, s->icon.drive, s->icon.volume); + s->validated = EINA_TRUE; + { + void *msg_data; + int msg_size; + + 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); + } + } + return; + +error: +// printf("ERR %s\n", s->udi); + _e_fm_main_udisks_storage_del(s->udi); +} + +static void +_e_fm_main_udisks_cb_vol_prop(E_Volume *v, + E_Ukit_Properties *ret, + DBusError *error) +{ + E_Storage *s = NULL; + int err = 0; + const char *str = NULL; + + if ((!v) || (!ret)) goto error; + + switch (v->optype) + { + case E_VOLUME_OP_TYPE_MOUNT: + _e_fm_main_udisks_cb_vol_mounted(v, error); + return; + case E_VOLUME_OP_TYPE_UNMOUNT: + _e_fm_main_udisks_cb_vol_unmounted(v, error); + return; + case E_VOLUME_OP_TYPE_EJECT: + _e_fm_main_udisks_cb_vol_unmounted_before_eject(v, NULL, error); + return; + default: + break; + } + + if (dbus_error_is_set(error)) + { + dbus_error_free(error); + goto error; + } + + /* skip volumes with volume.ignore set */ + if (e_ukit_property_bool_get(ret, "DeviceIsMediaChangeDetectionInhibited", &err) || err) + goto error; + + /* skip volumes that aren't filesystems */ + str = e_ukit_property_string_get(ret, "IdUsage", &err); + if (err || !str) goto error; + if (strcmp(str, "filesystem")) goto error; + str = NULL; + + v->uuid = e_ukit_property_string_get(ret, "IdUuid", &err); + if (err) goto error; + v->uuid = eina_stringshare_add(v->uuid); + + v->label = e_ukit_property_string_get(ret, "IdLabel", &err); +// if (err) goto error; + v->label = eina_stringshare_add(v->label); + + v->fstype = e_ukit_property_string_get(ret, "IdType", &err); +// if (err) goto error; + v->fstype = eina_stringshare_add(v->fstype); + + v->size = e_ukit_property_uint64_get(ret, "DeviceSize", &err); + + v->mounted = e_ukit_property_bool_get(ret, "DeviceIsMounted", &err); + if (err) goto error; + + v->partition = e_ukit_property_bool_get(ret, "DeviceIsPartition", &err); + if (err) goto error; + + { + const Eina_List *l; + l = e_ukit_property_strlist_get(ret, "DeviceMountPaths", &err); + if (err || (!l)) goto error; + v->mount_point = eina_stringshare_add(l->data); + } + + if (v->partition) + { + v->partition_number = e_ukit_property_int_get(ret, "PartitionNumber", NULL); + v->partition_label = e_ukit_property_string_get(ret, "PartitionLabel", NULL); + v->partition_label = eina_stringshare_add(v->partition_label); + } + + v->parent = e_ukit_property_string_get(ret, "PartitionSlave", &err); + if ((!err) && (v->parent)) + { + s = e_storage_find(v->parent); + if (s) + { + v->storage = s; + s->volumes = eina_list_append(s->volumes, v); + } + } + v->parent = eina_stringshare_add(v->parent); + +// printf("++VOL:\n udi: %s\n uuid: %s\n fstype: %s\n size: %llu\n label: %s\n partition: %d\n partition_number: %d\n partition_label: %s\n mounted: %d\n mount_point: %s\n", v->udi, v->uuid, v->fstype, v->size, v->label, v->partition, v->partition_number, v->partition ? v->partition_label : "(not a partition)", v->mounted, v->mount_point); +// if (s) printf(" for storage: %s\n", s->udi); +// else printf(" storage unknown\n"); + v->validated = EINA_TRUE; + { + void *msg_data; + int msg_size; + + msg_data = _e_fm_shared_codec_volume_encode(v, &msg_size); + if (msg_data) + { + ecore_ipc_server_send(_e_fm_ipc_server, + 6 /*E_IPC_DOMAIN_FM*/, + E_FM_OP_VOLUME_ADD, + 0, 0, 0, msg_data, msg_size); + free(msg_data); + } + } + return; + +error: + _e_fm_main_udisks_volume_del(v->udi); + return; +} + +static int +_e_fm_main_udisks_format_error_msg(char **buf, + E_Volume *v, + DBusError *error) +{ + int size, vu, vm, en; + char *tmp; + + vu = strlen(v->udi) + 1; + vm = strlen(v->mount_point) + 1; + en = strlen(error->name) + 1; + size = vu + vm + en + strlen(error->message) + 1; + tmp = *buf = malloc(size); + + strcpy(tmp, v->udi); + tmp += vu; + strcpy(tmp, v->mount_point); + tmp += vm; + strcpy(tmp, error->name); + tmp += en; + strcpy(tmp, error->message); + + return size; +} + +static Eina_Bool +_e_fm_main_udisks_vol_mount_timeout(E_Volume *v) +{ + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.MountTimeout"; + error.message = "Unable to mount the volume with specified time-out."; + size = _e_fm_main_udisks_format_error_msg(&buf, v, &error); + 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_udisks_cb_vol_mounted(E_Volume *v, + DBusError *error) +{ + char *buf; + int size; + + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + + v->optype = E_VOLUME_OP_TYPE_NONE; + if (dbus_error_is_set(error)) + { + size = _e_fm_main_udisks_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; + } + + v->mounted = EINA_TRUE; +// printf("MOUNT: %s from %s\n", 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_udisks_vol_unmount_timeout(E_Volume *v) +{ + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.UnmountTimeout"; + error.message = "Unable to unmount the volume with specified time-out."; + size = _e_fm_main_udisks_format_error_msg(&buf, v, &error); + 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_udisks_cb_vol_unmounted(E_Volume *v, + DBusError *error) +{ + char *buf; + int size; + + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + + if (v->optype != E_VOLUME_OP_TYPE_EJECT) v->optype = E_VOLUME_OP_TYPE_NONE; + if (dbus_error_is_set(error)) + { + size = _e_fm_main_udisks_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; + } + + v->mounted = EINA_FALSE; +// printf("UNMOUNT: %s from %s\n", 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_udisks_vol_eject_timeout(E_Volume *v) +{ + DBusError error; + char *buf; + int size; + + v->guard = NULL; + dbus_pending_call_cancel(v->op); + error.name = "org.enlightenment.fm2.EjectTimeout"; + error.message = "Unable to eject the media with specified time-out."; + size = _e_fm_main_udisks_format_error_msg(&buf, v, &error); + 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 Eina_Bool +_e_fm_main_udisks_cb_vol_ejecting_after_unmount(E_Volume *v) +{ + v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks_vol_eject_timeout, v); + v->op = e_udisks_volume_eject(_e_fm_main_udisks_conn, v->udi, NULL, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_ejected, v); + + return ECORE_CALLBACK_CANCEL; +} + +static void +_e_fm_main_udisks_cb_vol_unmounted_before_eject(E_Volume *v, + void *method_return __UNUSED__, + DBusError *error) +{ + Eina_Bool err; + + err = !!dbus_error_is_set(error); + _e_fm_main_udisks_cb_vol_unmounted(v, error); + + // delay is required for all message handlers were executed after unmount + if (!err) + ecore_timer_add(1.0, (Ecore_Task_Cb)_e_fm_main_udisks_cb_vol_ejecting_after_unmount, v); +} + +static void +_e_fm_main_udisks_cb_vol_ejected(E_Volume *v, + void *method_return __UNUSED__, + DBusError *error) +{ + char *buf; + int size; + + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + + v->optype = E_VOLUME_OP_TYPE_NONE; + if (dbus_error_is_set(error)) + { + size = _e_fm_main_udisks_format_error_msg(&buf, v, error); + ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR, + 0, 0, 0, buf, size); + dbus_error_free(error); + free(buf); + return; + } + + 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); +} + +E_Volume * +_e_fm_main_udisks_volume_add(const char *udi, + Eina_Bool first_time) +{ + E_Volume *v; + + if (!udi) return NULL; + if (e_volume_find(udi)) return NULL; + v = calloc(1, sizeof(E_Volume)); + if (!v) return NULL; +// printf("VOL+ %s\n", udi); + v->udi = eina_stringshare_add(udi); + v->icon = NULL; + v->first_time = first_time; + _e_vols = eina_list_append(_e_vols, v); + e_udisks_get_all_properties(_e_fm_main_udisks_conn, v->udi, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_prop, v); + v->prop_handler = e_dbus_signal_handler_add(_e_fm_main_udisks_conn, + E_UDISKS_BUS, + udi, + E_UDISKS_INTERFACE, + "Changed", + (E_DBus_Signal_Cb)_e_fm_main_udisks_cb_prop_modified, v); + v->guard = NULL; + + return v; +} + +void +_e_fm_main_udisks_volume_del(const char *udi) +{ + E_Volume *v; + + v = e_volume_find(udi); + if (!v) return; + if (v->guard) + { + ecore_timer_del(v->guard); + v->guard = NULL; + } + if (v->prop_handler) e_dbus_signal_handler_del(_e_fm_main_udisks_conn, v->prop_handler); + if (v->validated) + { + // printf("--VOL %s\n", 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); + } + _e_vols = eina_list_remove(_e_vols, v); + _e_fm_shared_device_volume_free(v); +} + +E_Volume * +_e_fm_main_udisks_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; +} + +void +_e_fm_main_udisks_volume_eject(E_Volume *v) +{ + if (!v || v->guard) return; + if (v->mounted) + { + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks_vol_unmount_timeout, v); + v->op = e_udisks_volume_unmount(_e_fm_main_udisks_conn, v->udi, NULL, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_unmounted_before_eject, v); + } + else + { + v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks_vol_eject_timeout, v); + v->op = e_udisks_volume_eject(_e_fm_main_udisks_conn, v->udi, NULL, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_ejected, v); + } + v->optype = E_VOLUME_OP_TYPE_EJECT; +} + +void +_e_fm_main_udisks_volume_unmount(E_Volume *v) +{ +// printf("unmount %s %s\n", v->udi, v->mount_point); + if (!v || v->guard) return; + + v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks_vol_unmount_timeout, v); + v->op = e_udisks_volume_unmount(_e_fm_main_udisks_conn, v->udi, NULL, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_unmounted, v); + v->optype = E_VOLUME_OP_TYPE_UNMOUNT; +} + +void +_e_fm_main_udisks_volume_mount(E_Volume *v) +{ + char buf[256]; + char buf2[256]; + Eina_List *opt = NULL; + + if ((!v) || (v->guard) || (!v->mount_point) || + (strncmp(v->mount_point, "/media/", 7))) + return; + +// printf("mount %s %s [fs type = %s]\n", v->udi, v->mount_point, v->fstype); + + // for vfat and ntfs we want the uid mapped to the user mounting, if we can + if ((!strcmp(v->fstype, "vfat")) || + (!strcmp(v->fstype, "ntfs")) + ) + { + snprintf(buf, sizeof(buf), "uid=%i", (int)getuid()); + opt = eina_list_append(opt, buf); + } + + // 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 + if ((!strcmp(v->fstype, "vfat")) || + (!strcmp(v->fstype, "ntfs")) || + (!strcmp(v->fstype, "iso9660")) + ) + { + snprintf(buf2, sizeof(buf2), "utf8"); + opt = eina_list_append(opt, buf2); + } + else if ((!strcmp(v->fstype, "fat")) || + (!strcmp(v->fstype, "jfs")) || + (!strcmp(v->fstype, "udf")) + ) + { + snprintf(buf2, sizeof(buf2), "iocharset=utf8"); + opt = eina_list_append(opt, buf2); + } + + v->guard = ecore_timer_add(E_FM_MOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks_vol_mount_timeout, v); + v->op = e_udisks_volume_mount(_e_fm_main_udisks_conn, v->udi, + v->fstype, opt, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_vol_mounted, v); + eina_list_free(opt); + v->optype = E_VOLUME_OP_TYPE_MOUNT; +} + +void +_e_fm_main_udisks_init(void) +{ + e_dbus_init(); + e_ukit_init(); + _e_fm_main_udisks_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); + /* previously, this assumed that if dbus was running, udisks was running. */ + if (_e_fm_main_udisks_conn) + e_dbus_get_name_owner(_e_fm_main_udisks_conn, E_UDISKS_BUS, _e_fm_main_udisks_test, NULL); +} + +void +_e_fm_main_udisks_shutdown(void) +{ + if (_e_fm_main_udisks_conn) + e_dbus_connection_close(_e_fm_main_udisks_conn); + e_ukit_shutdown(); + e_dbus_shutdown(); +} + +E_Storage * +_e_fm_main_udisks_storage_add(const char *udi) +{ + E_Storage *s; + + if (!udi) return NULL; + if (e_storage_find(udi)) return NULL; + s = calloc(1, sizeof(E_Storage)); + if (!s) return NULL; + s->udi = eina_stringshare_add(udi); + _e_stores = eina_list_append(_e_stores, s); + e_udisks_get_all_properties(_e_fm_main_udisks_conn, s->udi, + (E_DBus_Callback_Func)_e_fm_main_udisks_cb_store_prop, s); + return s; +} + +void +_e_fm_main_udisks_storage_del(const char *udi) +{ + E_Storage *s; + + s = e_storage_find(udi); + if (!s) return; + if (s->validated) + { + // printf("--STO %s\n", 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); + _e_fm_shared_device_storage_free(s); +} + +E_Storage * +_e_fm_main_udisks_storage_find(const char *udi) +{ + Eina_List *l; + E_Storage *s; + + EINA_LIST_FOREACH(_e_stores, l, s) + { + if (!strcmp(udi, s->udi)) return s; + } + return NULL; +} + diff --git a/src/bin/e_fm/e_fm_main_udisks.h b/src/bin/e_fm/e_fm_main_udisks.h new file mode 100644 index 000000000..f9bc659eb --- /dev/null +++ b/src/bin/e_fm/e_fm_main_udisks.h @@ -0,0 +1,26 @@ +#ifndef E_FM_MAIN_UDISKS_H +#define E_FM_MAIN_UDISKS_H + +#include +#include + +#include "e_fm_shared_types.h" + +E_Volume *_e_fm_main_udisks_volume_add(const char *udi, Eina_Bool first_time); +void _e_fm_main_udisks_volume_del(const char *udi); +E_Volume *_e_fm_main_udisks_volume_find(const char *udi); + +void _e_fm_main_udisks_volume_eject(E_Volume *v); +void _e_fm_main_udisks_volume_unmount(E_Volume *v); +void _e_fm_main_udisks_volume_mount(E_Volume *v); + +E_Storage *_e_fm_main_udisks_storage_add(const char *udi); +void _e_fm_main_udisks_storage_del(const char *udi); +E_Storage *_e_fm_main_udisks_storage_find(const char *udi); + + +void _e_fm_main_udisks_init(void); +void _e_fm_main_udisks_shutdown(void); +void _e_fm_main_udisks_catch(Eina_Bool usable); + +#endif