You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1299 lines
40 KiB
1299 lines
40 KiB
#ifdef HAVE_CONFIG_H |
|
#include "config.h" |
|
#endif |
|
|
|
#ifdef HAVE_ALLOCA_H |
|
# include <alloca.h> |
|
#elif defined __GNUC__ |
|
# define alloca __builtin_alloca |
|
#elif defined _AIX |
|
# define alloca __alloca |
|
#elif defined _MSC_VER |
|
# include <malloc.h> |
|
# define alloca _alloca |
|
#else |
|
# include <stddef.h> |
|
# ifdef __cplusplus |
|
extern "C" |
|
# endif |
|
void *alloca(size_t); |
|
#endif |
|
|
|
#ifdef __linux__ |
|
#include <features.h> |
|
#endif |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <unistd.h> |
|
#include <string.h> |
|
#include <sys/types.h> |
|
#include <sys/stat.h> |
|
#include <sys/time.h> |
|
#include <sys/param.h> |
|
#include <utime.h> |
|
#include <math.h> |
|
#include <fnmatch.h> |
|
#include <limits.h> |
|
#include <ctype.h> |
|
#include <time.h> |
|
#include <dirent.h> |
|
#include <pwd.h> |
|
#include <glob.h> |
|
#include <errno.h> |
|
#include <signal.h> |
|
#include <Ecore.h> |
|
#include <Ecore_Ipc.h> |
|
#include <Ecore_File.h> |
|
#include <Eet.h> |
|
#include <Eldbus.h> |
|
|
|
#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; |
|
}
|
|
|