#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_hal.h" #ifdef HAVE_UDISKS_MOUNT # include "e_fm_main_udisks.h" #endif #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 *_hal_poll = NULL; static E_DBus_Connection *_e_fm_main_hal_conn = NULL; static Eina_List *_e_stores = NULL; static void _e_fm_main_hal_cb_dev_all(void *user_data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_dev_store(void *user_data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_dev_vol(void *user_data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_store_is(void *user_data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_vol_is(void *user_data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_dev_add(void *data, DBusMessage *msg); static void _e_fm_main_hal_cb_dev_del(void *data, DBusMessage *msg); static void _e_fm_main_hal_cb_cap_add(void *data, DBusMessage *msg); static void _e_fm_main_hal_cb_prop_modified(void *data, DBusMessage *msg); static void _e_fm_main_hal_cb_store_prop(void *data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_vol_prop(void *data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error); static void _e_fm_main_hal_cb_vol_mounted(void *user_data, void *method_return, DBusError *error); static void _e_fm_main_hal_cb_vol_unmounted(void *user_data, void *method_return, DBusError *error); static void _e_fm_main_hal_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error); static Eina_Bool _e_fm_main_hal_vb_vol_ejecting_after_unmount(void *data); static void _e_fm_main_hal_cb_vol_ejected(void *user_data, void *method_return, DBusError *error); static int _e_fm_main_hal_format_error_msg(char **buf, E_Volume *v, DBusError *error); static void _e_fm_main_hal_test(void *data, DBusMessage *msg, DBusError *error); static void _e_fm_main_hal_poll(void *data, DBusMessage *msg); static Eina_Bool _e_fm_main_hal_vol_mount_timeout(void *data); static Eina_Bool _e_fm_main_hal_vol_unmount_timeout(void *data); static Eina_Bool _e_fm_main_hal_vol_eject_timeout(void *data); static void _e_fm_main_hal_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_HAL_SENDER)) _e_fm_main_hal_test(NULL, NULL, NULL); } static void _e_fm_main_hal_test(void *data __UNUSED__, DBusMessage *msg __UNUSED__, DBusError *error) { if ((error) && (dbus_error_is_set(error))) { dbus_error_free(error); if (!_hal_poll) _hal_poll = e_dbus_signal_handler_add(_e_fm_main_hal_conn, E_DBUS_FDO_BUS, E_DBUS_FDO_PATH, E_DBUS_FDO_INTERFACE, "NameOwnerChanged", _e_fm_main_hal_poll, NULL); #ifdef HAVE_UDISKS_MOUNT _e_fm_main_udisks_init(); /* check for udisks while listening for hal */ #else # ifdef HAVE_EEZE_MOUNT _e_fm_main_eeze_init(); /* check for eeze while listening for hal */ # endif #endif return; } if (_hal_poll) e_dbus_signal_handler_del(_e_fm_main_hal_conn, _hal_poll); e_hal_manager_get_all_devices(_e_fm_main_hal_conn, _e_fm_main_hal_cb_dev_all, NULL); e_hal_manager_find_device_by_capability(_e_fm_main_hal_conn, "storage", _e_fm_main_hal_cb_dev_store, NULL); e_hal_manager_find_device_by_capability(_e_fm_main_hal_conn, "volume", _e_fm_main_hal_cb_dev_vol, NULL); e_dbus_signal_handler_add(_e_fm_main_hal_conn, E_HAL_SENDER, E_HAL_MANAGER_PATH, E_HAL_MANAGER_INTERFACE, "DeviceAdded", _e_fm_main_hal_cb_dev_add, NULL); e_dbus_signal_handler_add(_e_fm_main_hal_conn, E_HAL_SENDER, E_HAL_MANAGER_PATH, E_HAL_MANAGER_INTERFACE, "DeviceRemoved", _e_fm_main_hal_cb_dev_del, NULL); e_dbus_signal_handler_add(_e_fm_main_hal_conn, E_HAL_SENDER, E_HAL_MANAGER_PATH, E_HAL_MANAGER_INTERFACE, "NewCapability", _e_fm_main_hal_cb_cap_add, NULL); _e_fm_main_hal_catch(EINA_TRUE); /* signal usage of HAL for mounting */ } static void _e_fm_main_hal_cb_dev_all(void *user_data __UNUSED__, void *reply_data, DBusError *error) { E_Hal_Manager_Get_All_Devices_Return *ret = reply_data; Eina_List *l; 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_hal_device_query_capability(_e_fm_main_hal_conn, udi, "storage", _e_fm_main_hal_cb_store_is, (void *)eina_stringshare_add(udi)); e_hal_device_query_capability(_e_fm_main_hal_conn, udi, "volume", _e_fm_main_hal_cb_vol_is, (void *)eina_stringshare_add(udi)); } } static void _e_fm_main_hal_cb_dev_store(void *user_data __UNUSED__, void *reply_data, DBusError *error) { E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply_data; Eina_List *l; char *device; if (!ret || !ret->strings) return; if (dbus_error_is_set(error)) { dbus_error_free(error); return; } EINA_LIST_FOREACH(ret->strings, l, device) { // printf("DB STORE+: %s\n", device); _e_fm_main_hal_storage_add(device); } } static void _e_fm_main_hal_cb_dev_vol(void *user_data __UNUSED__, void *reply_data, DBusError *error) { E_Hal_Manager_Find_Device_By_Capability_Return *ret = reply_data; Eina_List *l; char *device; if (!ret || !ret->strings) return; if (dbus_error_is_set(error)) { dbus_error_free(error); return; } EINA_LIST_FOREACH(ret->strings, l, device) { // printf("DB VOL+: %s\n", device); _e_fm_main_hal_volume_add(device, 1); } } static void _e_fm_main_hal_cb_store_is(void *user_data, void *reply_data, DBusError *error) { char *udi = user_data; E_Hal_Device_Query_Capability_Return *ret = reply_data; if (dbus_error_is_set(error)) { dbus_error_free(error); goto error; } if (ret && ret->boolean) { // printf("DB STORE IS+: %s\n", udi); _e_fm_main_hal_storage_add(udi); } error: eina_stringshare_del(udi); } static void _e_fm_main_hal_cb_vol_is(void *user_data, void *reply_data, DBusError *error) { char *udi = user_data; E_Hal_Device_Query_Capability_Return *ret = reply_data; if (dbus_error_is_set(error)) { dbus_error_free(error); goto error; } if (ret && ret->boolean) { // printf("DB VOL IS+: %s\n", udi); _e_fm_main_hal_volume_add(udi, 0); } error: eina_stringshare_del(udi); } static void _e_fm_main_hal_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_hal_device_query_capability(_e_fm_main_hal_conn, udi, "storage", _e_fm_main_hal_cb_store_is, (void *)eina_stringshare_add(udi)); e_hal_device_query_capability(_e_fm_main_hal_conn, udi, "volume", _e_fm_main_hal_cb_vol_is, (void *)eina_stringshare_add(udi)); } static void _e_fm_main_hal_cb_dev_del(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 DEV-: %s\n", udi); _e_fm_main_hal_storage_del(udi); _e_fm_main_hal_volume_del(udi); } static void _e_fm_main_hal_cb_cap_add(void *data __UNUSED__, DBusMessage *msg) { DBusError err; char *udi, *capability; dbus_error_init(&err); dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &udi, DBUS_TYPE_STRING, &capability, DBUS_TYPE_INVALID); if (!strcmp(capability, "storage")) { // printf("DB STORE CAP+: %s\n", udi); _e_fm_main_hal_storage_add(udi); } } static void _e_fm_main_hal_cb_prop_modified(void *data, DBusMessage *msg) { E_Volume *v; DBusMessageIter iter, sub, subsub; struct { const char *name; int added; int removed; } prop; int num_changes = 0, i; if (!(v = data)) return; if (dbus_message_get_error_name(msg)) { printf("DBUS ERROR: %s\n", dbus_message_get_error_name(msg)); return; } if (!dbus_message_iter_init(msg, &iter)) return; if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) return; dbus_message_iter_get_basic(&iter, &num_changes); if (num_changes == 0) return; dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) return; dbus_message_iter_recurse(&iter, &sub); for (i = 0; i < num_changes; i++, dbus_message_iter_next(&sub)) { dbus_message_iter_recurse(&sub, &subsub); if (dbus_message_iter_get_arg_type(&subsub) != DBUS_TYPE_STRING) break; dbus_message_iter_get_basic(&subsub, &(prop.name)); if (!strcmp(prop.name, "volume.mount_point")) { e_hal_device_get_all_properties(_e_fm_main_hal_conn, v->udi, _e_fm_main_hal_cb_vol_prop_mount_modified, v); return; } dbus_message_iter_next(&subsub); dbus_message_iter_next(&subsub); } } static void _e_fm_main_hal_cb_store_prop(void *data, void *reply_data, DBusError *error) { E_Storage *s = data; E_Hal_Properties *ret = reply_data; int err = 0; if (!ret) goto error; if (dbus_error_is_set(error)) { dbus_error_free(error); goto error; } s->bus = e_hal_property_string_get(ret, "storage.bus", &err); if (err) goto error; s->bus = eina_stringshare_add(s->bus); s->drive_type = e_hal_property_string_get(ret, "storage.drive_type", &err); if (err) goto error; s->drive_type = eina_stringshare_add(s->drive_type); s->model = e_hal_property_string_get(ret, "storage.model", &err); if (err) goto error; s->model = eina_stringshare_add(s->model); s->vendor = e_hal_property_string_get(ret, "storage.vendor", &err); if (err) goto error; s->vendor = eina_stringshare_add(s->vendor); s->serial = e_hal_property_string_get(ret, "storage.serial", &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_hal_property_bool_get(ret, "storage.removable", &err); if (s->removable) { s->media_available = e_hal_property_bool_get(ret, "storage.removable.media_available", &err); s->media_size = e_hal_property_uint64_get(ret, "storage.removable.media_size", &err); } s->requires_eject = e_hal_property_bool_get(ret, "storage.requires_eject", &err); s->hotpluggable = e_hal_property_bool_get(ret, "storage.hotpluggable", &err); s->media_check_enabled = e_hal_property_bool_get(ret, "storage.media_check_enabled", &err); s->icon.drive = e_hal_property_string_get(ret, "storage.icon.drive", &err); s->icon.drive = eina_stringshare_add(s->icon.drive); s->icon.volume = e_hal_property_string_get(ret, "storage.icon.volume", &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_hal_storage_del(s->udi); } static void _e_fm_main_hal_cb_vol_prop(void *data, void *reply_data, DBusError *error) { E_Volume *v = data; E_Storage *s = NULL; E_Hal_Device_Get_All_Properties_Return *ret = reply_data; int err = 0; const char *str = NULL; if (!ret) goto error; if (dbus_error_is_set(error)) { dbus_error_free(error); goto error; } /* skip volumes with volume.ignore set */ if (e_hal_property_bool_get(ret, "volume.ignore", &err) || err) goto error; /* skip volumes that aren't filesystems */ str = e_hal_property_string_get(ret, "volume.fsusage", &err); if (err || !str) goto error; if (strcmp(str, "filesystem")) goto error; str = NULL; v->uuid = e_hal_property_string_get(ret, "volume.uuid", &err); if (err) goto error; v->uuid = eina_stringshare_add(v->uuid); v->label = e_hal_property_string_get(ret, "volume.label", &err); // if (err) goto error; v->label = eina_stringshare_add(v->label); v->fstype = e_hal_property_string_get(ret, "volume.fstype", &err); // if (err) goto error; v->fstype = eina_stringshare_add(v->fstype); v->size = e_hal_property_uint64_get(ret, "volume.size", &err); v->mounted = e_hal_property_bool_get(ret, "volume.is_mounted", &err); if (err) goto error; v->partition = e_hal_property_bool_get(ret, "volume.is_partition", &err); if (err) goto error; v->mount_point = e_hal_property_string_get(ret, "volume.mount_point", &err); if (err) goto error; v->mount_point = eina_stringshare_add(v->mount_point); if (v->partition) { v->partition_number = e_hal_property_int_get(ret, "volume.partition.number", NULL); v->partition_label = e_hal_property_string_get(ret, "volume.partition.label", NULL); v->partition_label = eina_stringshare_add(v->partition_label); } v->parent = e_hal_property_string_get(ret, "info.parent", &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_hal_volume_del(v->udi); return; } static int _e_fm_main_hal_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 void _e_fm_main_hal_cb_vol_prop_mount_modified(void *data, void *reply_data, DBusError *error) { E_Volume *v = data; E_Hal_Device_Get_All_Properties_Return *ret = reply_data; int err = 0; if (!ret) return; if (dbus_error_is_set(error)) { char *buf; int size; size = _e_fm_main_hal_format_error_msg(&buf, v, error); if (v->mounted) ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR, 0, 0, 0, buf, size); else 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 = e_hal_property_bool_get(ret, "volume.is_mounted", &err); if (err) printf("HAL Error : can't get volume.is_mounted property"); if (v->mount_point) eina_stringshare_del(v->mount_point); v->mount_point = e_hal_property_string_get(ret, "volume.mount_point", &err); if (err) printf("HAL Error : can't get volume.is_mount_point property"); v->mount_point = eina_stringshare_add(v->mount_point); // printf("**VOL udi: %s mount_point: %s mounted: %d\n", v->udi, v->mount_point, v->mounted); { char *buf; int size; 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); if (v->mounted) ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_DONE, 0, 0, 0, buf, size); else ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_DONE, 0, 0, 0, buf, size); } return; } static Eina_Bool _e_fm_main_hal_vol_mount_timeout(void *data) { E_Volume *v = data; 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_hal_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_hal_cb_vol_mounted(void *user_data, void *method_return __UNUSED__, DBusError *error) { E_Volume *v = user_data; char *buf; int size; if (v->guard) { ecore_timer_del(v->guard); v->guard = NULL; } if (dbus_error_is_set(error)) { size = _e_fm_main_hal_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; } #if 0 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); #endif } static Eina_Bool _e_fm_main_hal_vol_unmount_timeout(void *data) { E_Volume *v = data; 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_hal_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_hal_cb_vol_unmounted(void *user_data, void *method_return __UNUSED__, DBusError *error) { E_Volume *v = user_data; char *buf; int size; if (v->guard) { ecore_timer_del(v->guard); v->guard = NULL; } if (dbus_error_is_set(error)) { size = _e_fm_main_hal_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; } #if 0 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); #endif } static Eina_Bool _e_fm_main_hal_vol_eject_timeout(void *data) { E_Volume *v = data; 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_hal_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_hal_vb_vol_ejecting_after_unmount(void *data) { E_Volume *v = data; v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_fm_main_hal_vol_eject_timeout, v); v->op = e_hal_device_volume_eject(_e_fm_main_hal_conn, v->udi, NULL, _e_fm_main_hal_cb_vol_ejected, v); return ECORE_CALLBACK_CANCEL; } static void _e_fm_main_hal_cb_vol_unmounted_before_eject(void *user_data, void *method_return, DBusError *error) { E_Volume *v = user_data; char err; err = dbus_error_is_set(error) ? 1 : 0; _e_fm_main_hal_cb_vol_unmounted(user_data, method_return, error); // delay is required for all message handlers were executed after unmount if (!err) ecore_timer_add(1.0, _e_fm_main_hal_vb_vol_ejecting_after_unmount, v); } static void _e_fm_main_hal_cb_vol_ejected(void *user_data, void *method_return __UNUSED__, DBusError *error) { E_Volume *v = user_data; char *buf; int size; if (v->guard) { ecore_timer_del(v->guard); v->guard = NULL; } if (dbus_error_is_set(error)) { size = _e_fm_main_hal_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); } static Eina_List *_e_vols = NULL; E_Volume * _e_fm_main_hal_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->efm_mode = EFM_MODE_USING_HAL_MOUNT; v->icon = NULL; v->first_time = first_time; _e_vols = eina_list_append(_e_vols, v); e_hal_device_get_all_properties(_e_fm_main_hal_conn, v->udi, _e_fm_main_hal_cb_vol_prop, v); v->prop_handler = e_dbus_signal_handler_add(_e_fm_main_hal_conn, E_HAL_SENDER, udi, E_HAL_DEVICE_INTERFACE, "PropertyModified", _e_fm_main_hal_cb_prop_modified, v); v->guard = NULL; return v; } void _e_fm_main_hal_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_hal_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_hal_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_hal_volume_eject(E_Volume *v) { if (!v || v->guard) return; if (v->mounted) { v->guard = ecore_timer_add(E_FM_UNMOUNT_TIMEOUT, _e_fm_main_hal_vol_unmount_timeout, v); v->op = e_hal_device_volume_unmount(_e_fm_main_hal_conn, v->udi, NULL, _e_fm_main_hal_cb_vol_unmounted_before_eject, v); } else { v->guard = ecore_timer_add(E_FM_EJECT_TIMEOUT, _e_fm_main_hal_vol_eject_timeout, v); v->op = e_hal_device_volume_eject(_e_fm_main_hal_conn, v->udi, NULL, _e_fm_main_hal_cb_vol_ejected, v); } } void _e_fm_main_hal_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, _e_fm_main_hal_vol_unmount_timeout, v); v->op = e_hal_device_volume_unmount(_e_fm_main_hal_conn, v->udi, NULL, _e_fm_main_hal_cb_vol_unmounted, v); } void _e_fm_main_hal_volume_mount(E_Volume *v) { char buf[256]; char buf2[256]; const char *mount_point; Eina_List *opt = NULL; if ((!v) || (v->guard) || (!v->mount_point) || (strncmp(v->mount_point, "/media/", 7))) return; mount_point = v->mount_point + 7; // 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, _e_fm_main_hal_vol_mount_timeout, v); v->op = e_hal_device_volume_mount(_e_fm_main_hal_conn, v->udi, mount_point, v->fstype, opt, _e_fm_main_hal_cb_vol_mounted, v); eina_list_free(opt); } void _e_fm_main_hal_init(void) { e_dbus_init(); e_hal_init(); _e_fm_main_hal_conn = e_dbus_bus_get(DBUS_BUS_SYSTEM); /* previously, this assumed that if dbus was running, hal was running. */ if (_e_fm_main_hal_conn) e_dbus_get_name_owner(_e_fm_main_hal_conn, E_HAL_SENDER, _e_fm_main_hal_test, NULL); } void _e_fm_main_hal_shutdown(void) { if (_e_fm_main_hal_conn) e_dbus_connection_close(_e_fm_main_hal_conn); e_hal_shutdown(); e_dbus_shutdown(); } E_Storage * _e_fm_main_hal_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_hal_device_get_all_properties(_e_fm_main_hal_conn, s->udi, _e_fm_main_hal_cb_store_prop, s); return s; } void _e_fm_main_hal_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_hal_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; }