1 #include "config.h"
2
3 #include "e_fm_shared_device.h"
4 #include "e_fm_shared_codec.h"
5 #include "e_fm_ipc.h"
6
7 #include "e_macros.h"
8 #include "e_fm_main_udisks2.h"
9 #include "e_fm_main.h"
10
11 #define E_TYPEDEFS
12 #include "e_fm_op.h"
13
14 #define UDISKS2_BUS "org.freedesktop.UDisks2"
15 #define UDISKS2_PATH "/org/freedesktop/UDisks2"
16 #define UDISKS2_INTERFACE "org.freedesktop.UDisks2"
17 #define UDISKS2_INTERFACE_BLOCK "org.freedesktop.UDisks2.Block"
18 #define UDISKS2_INTERFACE_DRIVE "org.freedesktop.UDisks2.Drive"
19 #define UDISKS2_INTERFACE_FILESYSTEM "org.freedesktop.UDisks2.Filesystem"
20
21 typedef struct U2_Block
22 {
23 size_t Size;
24 Eina_Stringshare *Device;
25 Eina_Stringshare *parent;
26 Eina_Bool volume;
27 Eina_Stringshare *IdType;
28 Eina_Stringshare *IdLabel;
29 Eina_Stringshare *IdUUID;
30 Eina_Bool HintIgnore;
31 Eina_Bool HintSystem;
32 Eina_Stringshare *HintName;
33 Eina_Stringshare *HintIconName;
34 } U2_Block;
35
36 static Eldbus_Connection *_e_fm_main_udisks2_conn = NULL;
37 static Eldbus_Proxy *_e_fm_main_udisks2_proxy = NULL;
38 static Eina_List *_e_stores = NULL;
39 static Eina_List *_e_vols = NULL;
40
41 static void _e_fm_main_udisks2_cb_dev_all(void *data, const Eldbus_Message *msg,
42 Eldbus_Pending *pending);
43 static void _e_fm_main_udisks2_cb_dev_add(void *data, const Eldbus_Message *msg);
44 static void _e_fm_main_udisks2_cb_dev_del(void *data, const Eldbus_Message *msg);
45 static void _e_fm_main_udisks2_cb_vol_mounted(E_Volume *v);
46 static void _e_fm_main_udisks2_cb_vol_unmounted(E_Volume *v);
47
48 static void _e_fm_main_udisks2_cb_vol_ejected(E_Volume *v);
49 static int _e_fm_main_udisks2_format_error_msg(char **buf,
50 E_Volume *v,
51 const char *name,
52 const char *message);
53 static void _e_fm_main_udisks2_cb_storage_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p);
54 static void _e_fm_main_udisks2_volume_mounts_update(E_Volume *v, Eldbus_Message_Iter *arr3, Eina_Bool first);
55 static Eina_Bool _e_fm_main_udisks2_vol_mount_timeout(E_Volume *v);
56 static Eina_Bool _e_fm_main_udisks2_vol_unmount_timeout(E_Volume *v);
57 static Eina_Bool _e_fm_main_udisks2_vol_eject_timeout(E_Volume *v);
58 static E_Storage *_storage_find_by_dbus_path(const char *path);
59 static E_Volume *_volume_find_by_dbus_path(const char *path);
60 static void _volume_del(E_Volume *v);
61 static Eina_Bool _storage_del(void *data);
62 static void _e_fm_main_udisks2_cb_storage_prop_modified_cb(void *data, const Eldbus_Message *msg);
63 static E_Storage * _e_fm_main_udisks2_storage_drive_add(const char *udi, E_Storage *s, Eldbus_Message_Iter *arr3);
64
65 static Eina_List *vols_ejecting = NULL;
66
67 static Eina_List *stores_registered = NULL;
68
69 static Eina_Stringshare *
_util_fuckyouglib_convert(Eldbus_Message_Iter * fuckyouglib)70 _util_fuckyouglib_convert(Eldbus_Message_Iter *fuckyouglib)
71 {
72 Eldbus_Message_Iter *no_really;
73 unsigned char c, buf[PATH_MAX] = {0};
74 unsigned int x = 0;
75
76 if (!eldbus_message_iter_arguments_get(fuckyouglib, "ay", &no_really)) return NULL;
77 while (eldbus_message_iter_get_and_next(no_really, 'y', &c))
78 {
79 buf[x] = c;
80 x++;
81 }
82 if (!buf[0]) return NULL;
83 return eina_stringshare_add((char*)buf);
84 }
85
86 static void
_e_fm_main_udisks2_name_start(void * data EINA_UNUSED,const Eldbus_Message * msg,Eldbus_Pending * pending EINA_UNUSED)87 _e_fm_main_udisks2_name_start(void *data EINA_UNUSED, const Eldbus_Message *msg,
88 Eldbus_Pending *pending EINA_UNUSED)
89 {
90 unsigned flag = 0;
91 Eldbus_Object *obj;
92
93 if (!eldbus_message_arguments_get(msg, "u", &flag) || !flag)
94 {
95 _e_fm_main_udisks2_catch(EINA_FALSE);
96 return;
97 }
98 obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, UDISKS2_PATH);
99 eldbus_object_managed_objects_get(obj, _e_fm_main_udisks2_cb_dev_all, NULL);
100
101 _e_fm_main_udisks2_proxy = eldbus_proxy_get(obj, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER);
102 eldbus_proxy_signal_handler_add(_e_fm_main_udisks2_proxy, "InterfacesAdded",
103 _e_fm_main_udisks2_cb_dev_add, NULL);
104 eldbus_proxy_signal_handler_add(_e_fm_main_udisks2_proxy, "InterfacesRemoved",
105 _e_fm_main_udisks2_cb_dev_del, NULL);
106 //eldbus_signal_handler_add(_e_fm_main_udisks2_conn, NULL,
107 //NULL, ELDBUS_FDO_INTERFACE_PROPERTIES, "PropertiesChanged",
108 //_e_fm_main_udisks2_cb_dev_add, NULL);
109 _e_fm_main_udisks2_catch(EINA_TRUE); /* signal usage of udisks2 for mounting */
110 }
111
112 static void
_e_fm_main_udisks2_block_clear(U2_Block * u2)113 _e_fm_main_udisks2_block_clear(U2_Block *u2)
114 {
115 eina_stringshare_del(u2->Device);
116 eina_stringshare_del(u2->parent);
117 eina_stringshare_del(u2->IdType);
118 eina_stringshare_del(u2->IdLabel);
119 eina_stringshare_del(u2->IdUUID);
120 eina_stringshare_del(u2->HintIconName);
121 eina_stringshare_del(u2->HintName);
122
123 }
124
125 static void
_e_fm_main_udisks2_storage_block_add(E_Storage * s,U2_Block * u2)126 _e_fm_main_udisks2_storage_block_add(E_Storage *s, U2_Block *u2)
127 {
128 s->media_size = u2->Size;
129 eina_stringshare_replace(&s->icon.drive, u2->HintIconName);
130 s->system_internal = u2->HintIgnore;
131 }
132
133 static void
_e_fm_main_udisks2_volume_block_add(E_Volume * v,U2_Block * u2)134 _e_fm_main_udisks2_volume_block_add(E_Volume *v, U2_Block *u2)
135 {
136 v->validated = u2->volume && u2->Device && u2->parent && (!u2->HintSystem);
137 if (!v->validated) return;
138 v->size = u2->Size;
139 eina_stringshare_replace(&v->udi, u2->Device);
140 eina_stringshare_replace(&v->parent, u2->parent);
141 eina_stringshare_replace(&v->icon, u2->HintIconName);
142 eina_stringshare_replace(&v->uuid, u2->IdUUID);
143 eina_stringshare_replace(&v->fstype, u2->IdType);
144 eina_stringshare_replace(&v->label, u2->IdLabel);
145 if (!v->label) v->label = eina_stringshare_ref(u2->HintName);
146
147 }
148
149 static void
_e_fm_main_udisks2_storage_add_send(E_Storage * s)150 _e_fm_main_udisks2_storage_add_send(E_Storage *s)
151 {
152 void *msg_data;
153 int msg_size;
154
155 if (!s->validated) return;
156 if (eina_list_data_find(stores_registered, s)) return;
157 if ((!s->removable) && (!s->hotpluggable) && (!s->requires_eject))
158 {
159 DBG("removing likely internal storage %s", s->dbus_path);
160 s->validated = 0;
161 ecore_idler_add(_storage_del, s->dbus_path);
162 return;
163 }
164 stores_registered = eina_list_append(stores_registered, s);
165 msg_data = _e_fm_shared_codec_storage_encode(s, &msg_size);
166 if (msg_data)
167 {
168 ecore_ipc_server_send(_e_fm_ipc_server,
169 6 /*E_IPC_DOMAIN_FM*/,
170 E_FM_OP_STORAGE_ADD,
171 0, 0, 0, msg_data, msg_size);
172 free(msg_data);
173 }
174 }
175
176 static int
_e_fm_main_udisks2_block_handle(Eldbus_Message_Iter * arr3,U2_Block * u2)177 _e_fm_main_udisks2_block_handle(Eldbus_Message_Iter *arr3, U2_Block *u2)
178 {
179 Eldbus_Message_Iter *dict3;
180 int block = 0;
181
182 while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3))
183 {
184 Eldbus_Message_Iter *var;
185 char *key2, *val, *type;
186 uint64_t u;
187 Eina_Bool b;
188
189 if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var))
190 continue;
191
192 type = eldbus_message_iter_signature_get(var);
193 switch (type[0])
194 {
195 case 's':
196 case 'o':
197 eldbus_message_iter_arguments_get(var, type, &val);
198 if ((!val) || (!val[0])) continue;
199 break;
200 case 't':
201 eldbus_message_iter_arguments_get(var, type, &u);
202 break;
203 case 'b':
204 eldbus_message_iter_arguments_get(var, type, &b);
205 break;
206 default: break;
207 }
208 if (!strcmp(key2, "Device"))
209 {
210 u2->Device = _util_fuckyouglib_convert(var);
211 if (!strncmp(u2->Device, "/dev/ram", 8)) return -1;
212 }
213 else if (!strcmp(key2, "Size"))
214 u2->Size = u;
215 else if (!strcmp(key2, "Drive"))
216 u2->parent = eina_stringshare_add(val);
217 else if (!strcmp(key2, "IdUsage"))
218 {
219 if (!strcmp(val, "other")) return -1;
220 u2->volume = !strcmp(val, "filesystem");
221 }
222 else if (!strcmp(key2, "IdType"))
223 u2->IdType = eina_stringshare_add(val);
224 else if (!strcmp(key2, "IdLabel"))
225 u2->IdLabel = eina_stringshare_add(val);
226 else if (!strcmp(key2, "IdUUID"))
227 u2->IdUUID = eina_stringshare_add(val);
228 else if (!strcmp(key2, "HintIgnore"))
229 u2->HintIgnore = !!b;
230 else if (!strcmp(key2, "HintSystem"))
231 u2->HintSystem = !!b;
232 else if (!strcmp(key2, "HintName"))
233 u2->HintName = eina_stringshare_add(val);
234 else if (!strcmp(key2, "HintIconName"))
235 u2->HintIconName = eina_stringshare_add(val);
236 block = 1;
237 }
238 return block;
239 }
240
241 static void
_e_fm_main_udisks2_handle_device(Eldbus_Message_Iter * dict)242 _e_fm_main_udisks2_handle_device(Eldbus_Message_Iter *dict)
243 {
244 const char *udi;
245 Eldbus_Message_Iter *arr2, *dict2;
246 E_Volume *v = NULL;
247 E_Storage *s = NULL;
248 U2_Block u2;
249 int block = 0;
250 unsigned int pnum = UINT_MAX;
251 Eina_Stringshare *pname = NULL;
252
253 if (!eldbus_message_iter_arguments_get(dict, "oa{sa{sv}}", &udi, &arr2))
254 return;
255 memset(&u2, 0, sizeof(U2_Block));
256 while (eldbus_message_iter_get_and_next(arr2, 'e', &dict2))
257 {
258 Eldbus_Message_Iter *arr3, *dict3;
259 char *interface;
260
261 if (!eldbus_message_iter_arguments_get(dict2, "sa{sv}", &interface, &arr3))
262 continue;
263 interface += sizeof(UDISKS2_INTERFACE);
264 if (!strcmp(interface, "Partition"))
265 {
266 while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3))
267 {
268 Eldbus_Message_Iter *var;
269 char *key2, *val, *type;
270
271 if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var))
272 continue;
273
274 type = eldbus_message_iter_signature_get(var);
275 switch (type[0])
276 {
277 case 's':
278 if (strcmp(key2, "Name")) continue;
279 if (!eldbus_message_iter_arguments_get(var, type, &val)) continue;
280 if (val && val[0]) pname = eina_stringshare_add(val);
281 break;
282 case 'u':
283 if (strcmp(key2, "Number")) continue;
284 eldbus_message_iter_arguments_get(var, type, &pnum);
285 break;
286 default: break;
287 }
288 }
289 if (v)
290 {
291 v->partition_label = pname;
292 pname = NULL;
293 v->partition_number = pnum;
294 v->partition = (v->partition_label || (pnum != UINT_MAX));
295 }
296 }
297 else if (!strcmp(interface, "Filesystem"))
298 {
299 if (!v) v = _volume_find_by_dbus_path(udi);
300 if (!v) v = _e_fm_main_udisks2_volume_add(udi, EINA_TRUE);
301 _e_fm_main_udisks2_volume_mounts_update(v, arr3, 1);
302 v->partition_label = pname;
303 pname = NULL;
304 if (pnum != UINT_MAX)
305 {
306 v->partition_number = pnum;
307 v->partition = 1;
308 }
309 if (block)
310 {
311 _e_fm_main_udisks2_volume_block_add(v, &u2);
312 if (!v->validated) E_FREE_FUNC(v, _volume_del);
313 }
314 }
315 else if (!strcmp(interface, "Block"))
316 {
317 block = _e_fm_main_udisks2_block_handle(arr3, &u2);
318 switch (block)
319 {
320 case -1: goto out;
321 case 0: continue;
322 default: break;
323 }
324 if ((!s) && (!v))
325 {
326 v = _volume_find_by_dbus_path(udi);
327 s = _e_fm_main_udisks2_storage_find(u2.parent);
328 }
329 if (s)
330 _e_fm_main_udisks2_storage_block_add(s, &u2);
331 if (v)
332 {
333 _e_fm_main_udisks2_volume_block_add(v, &u2);
334 if (!v->validated) E_FREE_FUNC(v, _volume_del);
335 }
336 }
337 else if (!strcmp(interface, "Drive"))
338 {
339 s = _e_fm_main_udisks2_storage_drive_add(udi, s, arr3);
340 if (block) _e_fm_main_udisks2_storage_block_add(s, &u2);
341 }
342 }
343 out:
344 _e_fm_main_udisks2_block_clear(&u2);
345 eina_stringshare_del(pname);
346 if (v && v->validated) e_fm_ipc_volume_add(v);
347 if (s)
348 {
349 Eina_List *l;
350
351 if (!block) //cdrom :/
352 s->udi = eina_stringshare_add(udi);
353 EINA_LIST_FOREACH(_e_vols, l, v)
354 {
355 if ((v->parent == s->udi) || (v->parent == s->dbus_path))
356 {
357 if (!v->storage)
358 {
359 v->storage = s;
360 s->volumes = eina_list_append(s->volumes, v);
361 }
362 }
363 }
364 _e_fm_main_udisks2_storage_add_send(s);
365 }
366 }
367
368 static void
_e_fm_main_udisks2_cb_dev_all(void * data EINA_UNUSED,const Eldbus_Message * msg,Eldbus_Pending * pending EINA_UNUSED)369 _e_fm_main_udisks2_cb_dev_all(void *data EINA_UNUSED, const Eldbus_Message *msg,
370 Eldbus_Pending *pending EINA_UNUSED)
371 {
372 const char *name, *txt;
373 Eldbus_Message_Iter *arr1, *dict1;
374
375 if (eldbus_message_error_get(msg, &name, &txt))
376 {
377 ERR("Error %s %s.", name, txt);
378 return;
379 }
380
381 if (!eldbus_message_arguments_get(msg, "a{oa{sa{sv}}}", &arr1))
382 {
383 ERR("Error getting arguments.");
384 return;
385 }
386
387 while (eldbus_message_iter_get_and_next(arr1, 'e', &dict1))
388 _e_fm_main_udisks2_handle_device(dict1);
389 }
390
391 static void
_e_fm_main_udisks2_cb_vol_props(void * data,const Eldbus_Message * msg,Eldbus_Pending * p EINA_UNUSED)392 _e_fm_main_udisks2_cb_vol_props(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
393 {
394 U2_Block u2;
395 int block;
396 E_Volume *v = data;
397 Eldbus_Message_Iter *arr;
398
399 memset(&u2, 0, sizeof(U2_Block));
400 if (!eldbus_message_arguments_get(msg, "a{sv}", &arr))
401 {
402 ERR("WTF");
403 return;
404 }
405 block = _e_fm_main_udisks2_block_handle(arr, &u2);
406 if (block == 1)
407 {
408 Eina_Bool valid = v->validated;
409
410 _e_fm_main_udisks2_volume_block_add(v, &u2);
411 if (v->validated && (valid != v->validated))
412 e_fm_ipc_volume_add(v);
413 else if (!v->validated)
414 _volume_del(v);
415 }
416 _e_fm_main_udisks2_block_clear(&u2);
417 }
418
419 static void
_e_fm_main_udisks2_cb_dev_add(void * data EINA_UNUSED,const Eldbus_Message * msg)420 _e_fm_main_udisks2_cb_dev_add(void *data EINA_UNUSED, const Eldbus_Message *msg)
421 {
422 const char *interface;
423
424 interface = eldbus_message_interface_get(msg);
425 //path = eldbus_message_path_get(msg);
426 //if (!strncmp(path, "/org/freedesktop/UDisks2/drives", sizeof("/org/freedesktop/UDisks2/drives") - 1))
427 //{
428 //E_Storage *s;
429 //
430 //if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2))
431 //return;
432 //interface += sizeof(UDISKS2_INTERFACE);
433 //if (strcmp(interface, "Drive")) return;
434 //s = _storage_find_by_dbus_path(path);
435 //if (!s) return;
436 //valid = s->validated;
437 //_e_fm_main_udisks2_storage_drive_add(s->udi, s, arr);
438 //if (valid != s->validated)
439 //_e_fm_main_udisks2_storage_add_send(s);
440 //}
441 //else if (!strncmp(path, "/org/freedesktop/UDisks2/block_devices", sizeof("/org/freedesktop/UDisks2/block_devices") - 1))
442 //{
443 //E_Volume *v;
444 //
445 //if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2))
446 //return;
447 //v = _volume_find_by_dbus_path(path);
448 //if (!v) v = _e_fm_main_udisks2_volume_add(path, 1);
449 //
450 //interface += sizeof(UDISKS2_INTERFACE);
451 //if (!strcmp(interface, "Filesystem"))
452 //_e_fm_main_udisks2_volume_mounts_update(v, arr, 0);
453 //else if (!strcmp(interface, "Block"))
454 //{
455 //U2_Block u2;
456 //int block;
457 //
458 //memset(&u2, 0, sizeof(U2_Block));
459 //block = _e_fm_main_udisks2_block_handle(arr, &u2);
460 //if (block == 1)
461 //{
462 //valid = v->validated;
463 //
464 //_e_fm_main_udisks2_volume_block_add(v, &u2);
465 //if (v->validated && (valid != v->validated))
466 //e_fm_ipc_volume_add(v);
467 //else if (!v->validated)
468 //_volume_del(v);
469 //}
470 //_e_fm_main_udisks2_block_clear(&u2);
471 //}
472 //}
473 //else
474 E_Storage *s = eina_list_last_data_get(_e_stores);
475 E_Volume *v = eina_list_last_data_get(_e_vols);
476 if (!strcmp(interface, ELDBUS_FDO_INTERFACE_OBJECT_MANAGER))
477 _e_fm_main_udisks2_handle_device(eldbus_message_iter_get(msg));
478 if (_e_stores && (s != eina_list_last_data_get(_e_stores)))
479 {
480 s = eina_list_last_data_get(_e_stores);
481 if (s->proxy)
482 eldbus_proxy_property_get_all(s->proxy, _e_fm_main_udisks2_cb_storage_prop_modified, s);
483 }
484 if (_e_vols && (v != eina_list_last_data_get(_e_vols)))
485 {
486 Eldbus_Message *m;
487 Eldbus_Object *obj;
488
489 v = eina_list_last_data_get(_e_vols);
490 m = eldbus_message_method_call_new(UDISKS2_BUS, v->dbus_path, ELDBUS_FDO_INTERFACE_PROPERTIES, "GetAll");
491 eldbus_message_arguments_append(m, "s", UDISKS2_INTERFACE_BLOCK);
492 obj = eldbus_proxy_object_get(v->proxy);
493 eldbus_object_send(obj, m, _e_fm_main_udisks2_cb_vol_props, v, -1);
494 }
495 }
496
497 static void
_e_fm_main_udisks2_cb_dev_del(void * data EINA_UNUSED,const Eldbus_Message * msg)498 _e_fm_main_udisks2_cb_dev_del(void *data EINA_UNUSED, const Eldbus_Message *msg)
499 {
500 char *path, *interface;
501 Eldbus_Message_Iter *arr;
502 E_Volume *v;
503 Eina_Bool vol = EINA_FALSE, sto = EINA_FALSE;
504
505 if (!eldbus_message_arguments_get(msg, "oas", &path, &arr))
506 return;
507 DBG("DB DEV-: %s", path);
508
509 while (eldbus_message_iter_get_and_next(arr, 's', &interface))
510 {
511 interface += sizeof(UDISKS2_INTERFACE);
512 if (!strcmp(interface, "Filesystem"))
513 vol = EINA_TRUE;
514 else if (!strcmp(interface, "Drive"))
515 sto = EINA_TRUE;
516 }
517 if (vol)
518 {
519 v = _volume_find_by_dbus_path(path);
520 if (v)
521 {
522 if (v->mounted)
523 {
524 v->optype = E_VOLUME_OP_TYPE_EJECT;
525 _e_fm_main_udisks2_cb_vol_unmounted(v);
526 }
527 if (v->optype == E_VOLUME_OP_TYPE_EJECT)
528 _e_fm_main_udisks2_cb_vol_ejected(v);
529 _volume_del(v);
530 }
531 }
532 if (sto) _e_fm_main_udisks2_storage_del(path);
533 }
534
535 static void
_e_fm_main_udisks2_cb_storage_prop_modified(void * data,const Eldbus_Message * msg,Eldbus_Pending * p EINA_UNUSED)536 _e_fm_main_udisks2_cb_storage_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
537 {
538 Eldbus_Message_Iter *arr;
539 E_Storage *s = data;
540 Eina_Bool valid;
541
542 {
543 const char *type = eldbus_message_signature_get(msg);
544 if (type[0] == 's')
545 {
546 char *txt;
547
548 if (eldbus_message_arguments_get(msg, type, &txt))
549 {
550 ERR("%s", txt);
551 }
552 }
553 }
554 if (!eldbus_message_arguments_get(msg, "a{sv}", &arr))
555 return;
556 valid = s->validated;
557 _e_fm_main_udisks2_storage_drive_add(s->udi, s, arr);
558 if (valid != s->validated)
559 _e_fm_main_udisks2_storage_add_send(s);
560 }
561
562 static void
_e_fm_main_udisks2_cb_storage_prop_modified_cb(void * data,const Eldbus_Message * msg)563 _e_fm_main_udisks2_cb_storage_prop_modified_cb(void *data, const Eldbus_Message *msg)
564 {
565 const char *interface;
566 Eldbus_Message_Iter *arr, *arr2;
567 E_Storage *s = data;
568 Eina_Bool valid;
569
570 if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2))
571 return;
572 valid = s->validated;
573 _e_fm_main_udisks2_storage_drive_add(s->udi, s, arr);
574 if (valid != s->validated)
575 _e_fm_main_udisks2_storage_add_send(s);
576 }
577
578 static void
_e_fm_main_udisks2_cb_vol_prop_modified(void * data,const Eldbus_Message * msg,Eldbus_Pending * p EINA_UNUSED)579 _e_fm_main_udisks2_cb_vol_prop_modified(void *data, const Eldbus_Message *msg, Eldbus_Pending *p EINA_UNUSED)
580 {
581 const char *interface;
582 Eldbus_Message_Iter *arr, *arr2;
583 E_Volume *v = data;
584
585 if (!eldbus_message_arguments_get(msg, "sa{sv}as", &interface, &arr, &arr2))
586 return;
587 interface += sizeof(UDISKS2_INTERFACE);
588 if (!strcmp(interface, "Filesystem"))
589 _e_fm_main_udisks2_volume_mounts_update(v, arr, 0);
590 else if (!strcmp(interface, "Block"))
591 {
592 U2_Block u2;
593 int block;
594
595 memset(&u2, 0, sizeof(U2_Block));
596 block = _e_fm_main_udisks2_block_handle(arr, &u2);
597 if (block == 1)
598 {
599 Eina_Bool valid = v->validated;
600
601 _e_fm_main_udisks2_volume_block_add(v, &u2);
602 if (v->validated && (valid != v->validated))
603 e_fm_ipc_volume_add(v);
604 else if (!v->validated)
605 _volume_del(v);
606 }
607 _e_fm_main_udisks2_block_clear(&u2);
608 }
609 }
610
611 static void
_e_fm_main_udisks2_cb_vol_prop_modified_cb(void * data,const Eldbus_Message * msg)612 _e_fm_main_udisks2_cb_vol_prop_modified_cb(void *data, const Eldbus_Message *msg)
613 {
614 _e_fm_main_udisks2_cb_vol_prop_modified(data, msg, NULL);
615 }
616
617 static Eina_Bool
_storage_del(void * data)618 _storage_del(void *data)
619 {
620 const char *path = data;
621 _e_fm_main_udisks2_storage_del(path);
622 return ECORE_CALLBACK_CANCEL;
623 }
624
625 static E_Storage *
_e_fm_main_udisks2_storage_drive_add(const char * udi,E_Storage * s,Eldbus_Message_Iter * arr3)626 _e_fm_main_udisks2_storage_drive_add(const char *udi, E_Storage *s, Eldbus_Message_Iter *arr3)
627 {
628 Eldbus_Message_Iter *dict3;
629
630 if (!s)
631 {
632 if (!s) s = _e_fm_main_udisks2_storage_find(udi);
633 if (!s) s = _e_fm_main_udisks2_storage_add(udi);
634 if (!s) return NULL;
635 }
636 if (s->system_internal)
637 {
638 DBG("removing storage internal %s", s->dbus_path);
639 s->validated = 0;
640 ecore_idler_add(_storage_del, s->dbus_path);
641 return NULL;
642 }
643 while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3))
644 {
645 Eldbus_Message_Iter *var;
646 char *key2, *val, *type;
647 Eina_Bool b;
648 uint64_t t;
649
650 if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var))
651 continue;
652
653 type = eldbus_message_iter_signature_get(var);
654 switch (type[0])
655 {
656 case 's':
657 case 'o':
658 eldbus_message_iter_arguments_get(var, type, &val);
659 break;
660 case 'b':
661 eldbus_message_iter_arguments_get(var, type, &b);
662 break;
663 case 't':
664 eldbus_message_iter_arguments_get(var, type, &t);
665 break;
666 default: break;
667 }
668
669 if (!strcmp(key2, "ConnectionBus"))
670 eina_stringshare_replace(&s->bus, val);
671 else if (!strcmp(key2, "MediaCompatibility"))
672 {
673 Eldbus_Message_Iter *inner_array;
674 const char *media;
675
676 if (!eldbus_message_iter_arguments_get(var, "as", &inner_array))
677 continue;
678
679 if (eldbus_message_iter_get_and_next(inner_array, 's', &media))
680 eina_stringshare_replace(&s->drive_type, media);
681 }
682 else if (!strcmp(key2, "Model"))
683 eina_stringshare_replace(&s->model, (val && val[0]) ? val : NULL);
684 else if (!strcmp(key2, "Vendor"))
685 eina_stringshare_replace(&s->vendor, (val && val[0]) ? val : NULL);
686 else if (!strcmp(key2, "Serial"))
687 eina_stringshare_replace(&s->serial, (val && val[0]) ? val : NULL);
688 else if (!strcmp(key2, "MediaAvailable"))
689 s->media_available = !!b;
690 else if (!strcmp(key2, "Size"))
691 s->media_size = t;
692 else if (!strcmp(key2, "Ejectable"))
693 s->requires_eject = !!b;
694 else if (!strcmp(key2, "Removable"))
695 s->hotpluggable = !!b;
696 else if (!strcmp(key2, "MediaRemovable"))
697 s->removable = !!b;
698 }
699
700 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);
701 s->validated = EINA_TRUE;
702
703 if (!s->proxy)
704 {
705 Eldbus_Object *obj;
706
707 obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, s->udi);
708 s->proxy = eldbus_proxy_get(obj, UDISKS2_INTERFACE_DRIVE);
709 eldbus_proxy_properties_monitor(s->proxy, 1);
710 eldbus_proxy_properties_changed_callback_add(s->proxy, _e_fm_main_udisks2_cb_storage_prop_modified_cb, s);
711 }
712 return s;
713 }
714
715 static int
_e_fm_main_udisks2_format_error_msg(char ** buf,E_Volume * v,const char * name,const char * message)716 _e_fm_main_udisks2_format_error_msg(char **buf,
717 E_Volume *v,
718 const char *name,
719 const char *message)
720 {
721 int size, vu, vm = 1, en;
722 char *tmp;
723
724 vu = strlen(v->udi) + 1;
725 if (v->mount_point) vm = strlen(v->mount_point) + 1;
726 en = strlen(name) + 1;
727 size = vu + vm + en + strlen(message) + 1;
728 tmp = *buf = malloc(size);
729
730 strcpy(tmp, v->udi);
731 tmp += vu;
732 if (v->mount_point)
733 {
734 strcpy(tmp, v->mount_point);
735 tmp += vm;
736 }
737 else
738 {
739 *tmp = 0;
740 tmp += vm;
741 }
742 strcpy(tmp, name);
743 tmp += en;
744 strcpy(tmp, message);
745
746 return size;
747 }
748
749 static Eina_Bool
_e_fm_main_udisks2_vol_mount_timeout(E_Volume * v)750 _e_fm_main_udisks2_vol_mount_timeout(E_Volume *v)
751 {
752 char *buf;
753 int size;
754
755 v->guard = NULL;
756
757 E_FREE_FUNC(v->op, eldbus_pending_cancel);
758 v->optype = E_VOLUME_OP_TYPE_NONE;
759 size = _e_fm_main_udisks2_format_error_msg(&buf, v,
760 "org.enlightenment.fm2.MountTimeout",
761 "Unable to mount the volume with specified time-out.");
762 ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_MOUNT_ERROR,
763 0, 0, 0, buf, size);
764 free(buf);
765
766 return ECORE_CALLBACK_CANCEL;
767 }
768
769 static void
_e_fm_main_udisks2_cb_vol_mounted(E_Volume * v)770 _e_fm_main_udisks2_cb_vol_mounted(E_Volume *v)
771 {
772 char *buf;
773 int size;
774
775 E_FREE_FUNC(v->guard, ecore_timer_del);
776 if (!v->mount_point) return; /* come back later */
777
778 v->optype = E_VOLUME_OP_TYPE_NONE;
779 v->op = NULL;
780 v->mounted = EINA_TRUE;
781 INF("MOUNT: %s from %s", v->udi, v->mount_point);
782 size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1;
783 buf = alloca(size);
784 strcpy(buf, v->udi);
785 strcpy(buf + strlen(buf) + 1, v->mount_point);
786 ecore_ipc_server_send(_e_fm_ipc_server,
787 6 /*E_IPC_DOMAIN_FM*/,
788 E_FM_OP_MOUNT_DONE,
789 0, 0, 0, buf, size);
790 }
791
792 static Eina_Bool
_e_fm_main_udisks2_vol_unmount_timeout(E_Volume * v)793 _e_fm_main_udisks2_vol_unmount_timeout(E_Volume *v)
794 {
795 char *buf;
796 int size;
797
798 v->guard = NULL;
799 if (v->op)
800 eldbus_pending_cancel(v->op);
801 v->op = NULL;
802 v->optype = E_VOLUME_OP_TYPE_NONE;
803 size = _e_fm_main_udisks2_format_error_msg(&buf, v,
804 "org.enlightenment.fm2.UnmountTimeout",
805 "Unable to unmount the volume with specified time-out.");
806 ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_UNMOUNT_ERROR,
807 0, 0, 0, buf, size);
808 free(buf);
809
810 return ECORE_CALLBACK_CANCEL;
811 }
812
813 static void
_e_fm_main_udisks2_cb_vol_unmounted(E_Volume * v)814 _e_fm_main_udisks2_cb_vol_unmounted(E_Volume *v)
815 {
816 char *buf;
817 int size;
818
819 E_FREE_FUNC(v->guard, ecore_timer_del);
820
821 if (v->optype != E_VOLUME_OP_TYPE_EJECT)
822 {
823 v->optype = E_VOLUME_OP_TYPE_NONE;
824 v->op = NULL;
825 }
826
827 v->mounted = EINA_FALSE;
828 INF("UNMOUNT: %s from %s", v->udi, v->mount_point);
829 size = strlen(v->udi) + 1 + strlen(v->mount_point) + 1;
830 buf = alloca(size);
831 strcpy(buf, v->udi);
832 strcpy(buf + strlen(buf) + 1, v->mount_point);
833 ecore_ipc_server_send(_e_fm_ipc_server,
834 6 /*E_IPC_DOMAIN_FM*/,
835 E_FM_OP_UNMOUNT_DONE,
836 0, 0, 0, buf, size);
837 }
838
839 static Eina_Bool
_e_fm_main_udisks2_vol_eject_timeout(E_Volume * v)840 _e_fm_main_udisks2_vol_eject_timeout(E_Volume *v)
841 {
842 char *buf;
843 int size;
844
845 v->guard = NULL;
846 if (v->op)
847 eldbus_pending_cancel(v->op);
848 v->op = NULL;
849 v->optype = E_VOLUME_OP_TYPE_NONE;
850 size = _e_fm_main_udisks2_format_error_msg(&buf, v,
851 "org.enlightenment.fm2.EjectTimeout",
852 "Unable to eject the media with specified time-out.");
853 ecore_ipc_server_send(_e_fm_ipc_server, 6 /*E_IPC_DOMAIN_FM*/, E_FM_OP_EJECT_ERROR,
854 0, 0, 0, buf, size);
855 free(buf);
856
857 return ECORE_CALLBACK_CANCEL;
858 }
859
860 static Eldbus_Pending *
_volume_eject(Eldbus_Proxy * proxy)861 _volume_eject(Eldbus_Proxy *proxy)
862 {
863 Eldbus_Message *msg;
864 Eldbus_Message_Iter *array, *main_iter;
865
866 msg = eldbus_proxy_method_call_new(proxy, "Eject");
867 main_iter = eldbus_message_iter_get(msg);
868 eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array);
869 eldbus_message_iter_container_close(main_iter, array);
870
871 return eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
872 }
873
874 static void
_volume_eject_umount_cb(void * data,const Eldbus_Message * msg,Eldbus_Pending * pending EINA_UNUSED)875 _volume_eject_umount_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
876 {
877 const char *name, *txt;
878 E_Volume *v = data;
879
880 if (eldbus_message_error_get(msg, &name, &txt))
881 {
882 ERR("%s: %s", name, txt);
883 }
884 else if (v->optype == E_VOLUME_OP_TYPE_EJECT)
885 {
886 vols_ejecting = eina_list_remove(vols_ejecting, v);
887 _volume_eject(v->storage->proxy);
888 }
889
890 }
891
892 static Eldbus_Pending *
_volume_umount(E_Volume * v)893 _volume_umount(E_Volume *v)
894 {
895 Eldbus_Message *msg;
896 Eldbus_Message_Iter *array, *main_iter;
897
898 msg = eldbus_proxy_method_call_new(v->proxy, "Unmount");
899 main_iter = eldbus_message_iter_get(msg);
900 eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array);
901 eldbus_message_iter_container_close(main_iter, array);
902
903 return eldbus_proxy_send(v->proxy, msg, _volume_eject_umount_cb, v, -1);
904 }
905
906 static Eldbus_Pending *
_volume_mount(Eldbus_Proxy * proxy,const char * fstype,const char * buf)907 _volume_mount(Eldbus_Proxy *proxy, const char *fstype, const char *buf)
908 {
909 Eldbus_Message *msg;
910 Eldbus_Message_Iter *array, *main_iter, *dict, *var;
911 char opt_txt[] = "options";
912 char fs_txt[] = "fstype";
913
914 msg = eldbus_proxy_method_call_new(proxy, "Mount");
915 main_iter = eldbus_message_iter_get(msg);
916 if (!eldbus_message_iter_arguments_append(main_iter, "a{sv}", &array))
917 ERR("E");
918 if (fstype)
919 {
920 if (!eldbus_message_iter_arguments_append(array, "{sv}", &dict))
921 {
922 ERR("E");
923 }
924 eldbus_message_iter_basic_append(dict, 's', fs_txt);
925
926 var = eldbus_message_iter_container_new(dict, 'v', "s");
927 eldbus_message_iter_basic_append(var, 's', fstype);
928 eldbus_message_iter_container_close(dict, var);
929 eldbus_message_iter_container_close(array, dict);
930
931 }
932 if (buf[0])
933 {
934 if (!eldbus_message_iter_arguments_append(array, "{sv}", &dict))
935 {
936 ERR("E");
937 }
938 eldbus_message_iter_basic_append(dict, 's', opt_txt);
939
940 var = eldbus_message_iter_container_new(dict, 'v', "s");
941 eldbus_message_iter_basic_append(var, 's', buf);
942 eldbus_message_iter_container_close(dict, var);
943 eldbus_message_iter_container_close(array, dict);
944 }
945 eldbus_message_iter_container_close(main_iter, array);
946
947 return eldbus_proxy_send(proxy, msg, NULL, NULL, -1);
948 }
949
950 static void
_e_fm_main_udisks2_cb_vol_ejected(E_Volume * v)951 _e_fm_main_udisks2_cb_vol_ejected(E_Volume *v)
952 {
953 char *buf;
954 int size;
955
956 E_FREE_FUNC(v->guard, ecore_timer_del);
957 v->optype = E_VOLUME_OP_TYPE_NONE;
958
959 size = strlen(v->udi) + 1;
960 buf = alloca(size);
961 strcpy(buf, v->udi);
962 ecore_ipc_server_send(_e_fm_ipc_server,
963 6 /*E_IPC_DOMAIN_FM*/,
964 E_FM_OP_EJECT_DONE,
965 0, 0, 0, buf, size);
966 }
967
968 static void
_e_fm_main_udisks2_volume_mounts_update(E_Volume * v,Eldbus_Message_Iter * arr3,Eina_Bool first)969 _e_fm_main_udisks2_volume_mounts_update(E_Volume *v, Eldbus_Message_Iter *arr3, Eina_Bool first)
970 {
971 Eldbus_Message_Iter *dict3;
972 Eina_List *mounts = NULL;
973
974 while (eldbus_message_iter_get_and_next(arr3, 'e', &dict3))
975 {
976 Eldbus_Message_Iter *var;
977 char *key2, *type;
978
979 if (!eldbus_message_iter_arguments_get(dict3, "sv", &key2, &var))
980 continue;
981
982 type = eldbus_message_iter_signature_get(var);
983 switch (type[0])
984 {
985 Eldbus_Message_Iter *fuckyouglib;
986
987 case 'a':
988 if (strcmp(key2, "MountPoints")) continue;
989 /* glib developers are assholes, so this is "aay" instead of just "as" */
990 if (!eldbus_message_iter_arguments_get(var, type, &fuckyouglib))
991 {
992 ERR("fucked by glib I guess");
993 continue;
994 }
995 do
996 {
997 Eina_Stringshare *m;
998
999 m = _util_fuckyouglib_convert(fuckyouglib);
1000 if (m) mounts = eina_list_append(mounts, m);
1001 }
1002 while (eldbus_message_iter_next(fuckyouglib));
1003 EINA_FALLTHROUGH;
1004 /* no break */
1005
1006 default: continue;
1007 }
1008 }
1009 if (first)
1010 {
1011 eina_stringshare_replace(&v->mount_point, eina_list_last_data_get(mounts));
1012 v->mounted = !!v->mount_point;
1013 if (v->storage)
1014 v->storage->media_available = v->mounted;
1015 }
1016 else if ((!v->mounted) || (!eina_list_data_find(mounts, v->mount_point)))
1017 {
1018 if (mounts)
1019 eina_stringshare_replace(&v->mount_point, eina_list_last_data_get(mounts));
1020 v->mounted = !!mounts;
1021 if (v->storage)
1022 v->storage->media_available = v->mounted;
1023 switch (v->optype)
1024 {
1025 case E_VOLUME_OP_TYPE_MOUNT:
1026 _e_fm_main_udisks2_cb_vol_mounted(v);
1027 break;
1028 case E_VOLUME_OP_TYPE_UNMOUNT:
1029 _e_fm_main_udisks2_cb_vol_unmounted(v);
1030 break;
1031 case E_VOLUME_OP_TYPE_EJECT:
1032 if (vols_ejecting && eina_list_data_find(vols_ejecting, v))
1033 _e_fm_main_udisks2_cb_vol_unmounted(v);
1034 else
1035 _e_fm_main_udisks2_cb_vol_ejected(v);
1036 break;
1037 default: break;
1038 }
1039 }
1040 E_FREE_LIST(mounts, eina_stringshare_del);
1041 }
1042
1043 E_Volume *
_e_fm_main_udisks2_volume_add(const char * path,Eina_Bool first_time)1044 _e_fm_main_udisks2_volume_add(const char *path, Eina_Bool first_time)
1045 {
1046 E_Volume *v;
1047 Eldbus_Object *obj;
1048
1049 if (!path) return NULL;
1050 if (_volume_find_by_dbus_path(path)) return NULL;
1051 v = calloc(1, sizeof(E_Volume));
1052 if (!v) return NULL;
1053 v->dbus_path = eina_stringshare_add(path);
1054 INF("VOL+ %s", path);
1055 v->efm_mode = EFM_MODE_USING_UDISKS2_MOUNT;
1056 v->first_time = first_time;
1057 _e_vols = eina_list_append(_e_vols, v);
1058 obj = eldbus_object_get(_e_fm_main_udisks2_conn, UDISKS2_BUS, path);
1059 v->proxy = eldbus_proxy_get(obj, UDISKS2_INTERFACE_FILESYSTEM);
1060 eldbus_proxy_properties_monitor(v->proxy, 1);
1061 eldbus_proxy_properties_changed_callback_add(v->proxy, _e_fm_main_udisks2_cb_vol_prop_modified_cb, v);
1062
1063 return v;
1064 }
1065
1066 void
_e_fm_main_udisks2_volume_del(const char * path)1067 _e_fm_main_udisks2_volume_del(const char *path)
1068 {
1069 E_Volume *v;
1070
1071 v = _volume_find_by_dbus_path(path);
1072 if (!v) return;
1073 _volume_del(v);
1074 }
1075
1076 static void
_volume_del(E_Volume * v)1077 _volume_del(E_Volume *v)
1078 {
1079 E_FREE_FUNC(v->guard, ecore_timer_del);
1080 if (v->validated)
1081 {
1082 INF("--VOL %s", v->udi);
1083 /* FIXME: send event of storage volume (disk) removed */
1084 ecore_ipc_server_send(_e_fm_ipc_server,
1085 6 /*E_IPC_DOMAIN_FM*/,
1086 E_FM_OP_VOLUME_DEL,
1087 0, 0, 0, v->udi, eina_stringshare_strlen(v->udi) + 1);
1088 }
1089 v->optype = E_VOLUME_OP_TYPE_NONE;
1090 if (v->proxy)
1091 {
1092 Eldbus_Object *obj = eldbus_proxy_object_get(v->proxy);
1093 eldbus_proxy_unref(v->proxy);
1094 eldbus_object_unref(obj);
1095 }
1096 _e_vols = eina_list_remove(_e_vols, v);
1097 _e_fm_shared_device_volume_free(v);
1098 }
1099
1100 E_Volume *
_e_fm_main_udisks2_volume_find(const char * udi)1101 _e_fm_main_udisks2_volume_find(const char *udi)
1102 {
1103 Eina_List *l;
1104 E_Volume *v;
1105
1106 if (!udi) return NULL;
1107 EINA_LIST_FOREACH(_e_vols, l, v)
1108 {
1109 if (!v->udi) continue;
1110 if (!strcmp(udi, v->udi)) return v;
1111 }
1112 return NULL;
1113 }
1114
1115 static E_Volume *
_volume_find_by_dbus_path(const char * path)1116 _volume_find_by_dbus_path(const char *path)
1117 {
1118 Eina_List *l;
1119 E_Volume *v;
1120
1121 if (!path) return NULL;
1122 EINA_LIST_FOREACH(_e_vols, l, v)
1123 if (!strcmp(path, v->dbus_path)) return v;
1124 return NULL;
1125 }
1126
1127 void
_e_fm_main_udisks2_volume_eject(E_Volume * v)1128 _e_fm_main_udisks2_volume_eject(E_Volume *v)
1129 {
1130 if (!v || v->guard) return;
1131 if (!v->storage) v->storage = _e_fm_main_udisks2_storage_find(v->parent);
1132 if (!v->storage)
1133 {
1134 ERR("COULD NOT FIND DISK STORAGE!!!");
1135 return;
1136 }
1137 if (v->mounted)
1138 {
1139 v->guard = ecore_timer_loop_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_unmount_timeout, v);
1140 v->op = _volume_umount(v);
1141 vols_ejecting = eina_list_append(vols_ejecting, v);
1142 }
1143 else
1144 {
1145 v->guard = ecore_timer_loop_add(E_FM_EJECT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_eject_timeout, v);
1146 v->op = _volume_eject(v->storage->proxy);
1147 }
1148 v->optype = E_VOLUME_OP_TYPE_EJECT;
1149 }
1150
1151 void
_e_fm_main_udisks2_volume_unmount(E_Volume * v)1152 _e_fm_main_udisks2_volume_unmount(E_Volume *v)
1153 {
1154 if (!v || v->guard) return;
1155 INF("unmount %s %s", v->udi, v->mount_point);
1156
1157 v->guard = ecore_timer_loop_add(E_FM_UNMOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_unmount_timeout, v);
1158 v->op = _volume_umount(v);
1159 v->optype = E_VOLUME_OP_TYPE_UNMOUNT;
1160 }
1161
1162 void
_e_fm_main_udisks2_volume_mount(E_Volume * v)1163 _e_fm_main_udisks2_volume_mount(E_Volume *v)
1164 {
1165 char buf[256] = {0};
1166
1167 if ((!v) || (v->guard))
1168 return;
1169
1170 INF("mount %s %s [fs type = %s]", v->udi, v->mount_point, v->fstype);
1171
1172 // Map uid to current user if possible
1173 // Possible filesystems found in udisks2 source (src/udisks2linuxfilesystem.c) as of 2012-07-11
1174 if (!strcmp(v->fstype, "vfat"))
1175 snprintf(buf, sizeof(buf), "uid=%i,utf8=1", (int)getuid());
1176 else if ((!strcmp(v->fstype, "iso9660")) || (!strcmp(v->fstype, "udf")))
1177 // force utf8 as the encoding - e only likes/handles utf8. its the
1178 // pseudo-standard these days anyway for "linux" for intl text to work
1179 // everywhere. problem is some fs's use differing options and udisks2
1180 // doesn't allow some options with certain filesystems.
1181 // Valid options found in udisks2 (src/udisks2linuxfilesystem.c) as of 2012-07-11
1182 // Note that these options are default with the latest udisks2, kept here to
1183 // avoid breakage in the future (hopefully).
1184 snprintf(buf, sizeof(buf), "uid=%i,iocharset=utf8", (int)getuid());
1185 else if (!strcmp(v->fstype, "ntfs"))
1186 snprintf(buf, sizeof(buf), "uid=%i", (int)getuid());
1187
1188 v->guard = ecore_timer_loop_add(E_FM_MOUNT_TIMEOUT, (Ecore_Task_Cb)_e_fm_main_udisks2_vol_mount_timeout, v);
1189
1190 // It was previously noted here that ubuntu 10.04 failed to mount if opt was passed to
1191 // e_udisks2_volume_mount. The reason at the time was unknown and apparently never found.
1192 // I theorize that this was due to improper mount options being passed (namely the utf8 options).
1193 // If this still fails on Ubuntu 10.04 then an actual fix should be found.
1194 v->op = _volume_mount(v->proxy, v->fstype, buf);
1195
1196 v->optype = E_VOLUME_OP_TYPE_MOUNT;
1197 }
1198
1199 void
_e_fm_main_udisks2_init(void)1200 _e_fm_main_udisks2_init(void)
1201 {
1202 eldbus_init();
1203 _e_fm_main_udisks2_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
1204 if (!_e_fm_main_udisks2_conn) return;
1205
1206 eldbus_name_start(_e_fm_main_udisks2_conn, UDISKS2_BUS, 0,
1207 _e_fm_main_udisks2_name_start, NULL);
1208 }
1209
1210 void
_e_fm_main_udisks2_shutdown(void)1211 _e_fm_main_udisks2_shutdown(void)
1212 {
1213 if (_e_fm_main_udisks2_proxy)
1214 {
1215 Eldbus_Object *obj;
1216 obj = eldbus_proxy_object_get(_e_fm_main_udisks2_proxy);
1217 eldbus_proxy_unref(_e_fm_main_udisks2_proxy);
1218 eldbus_object_unref(obj);
1219 }
1220 if (_e_fm_main_udisks2_conn)
1221 {
1222 eldbus_connection_unref(_e_fm_main_udisks2_conn);
1223 eldbus_shutdown();
1224 }
1225 }
1226
1227 E_Storage *
_e_fm_main_udisks2_storage_add(const char * path)1228 _e_fm_main_udisks2_storage_add(const char *path)
1229 {
1230 E_Storage *s;
1231
1232 if (!path) return NULL;
1233 if (_storage_find_by_dbus_path(path)) return NULL;
1234 s = calloc(1, sizeof(E_Storage));
1235 if (!s) return NULL;
1236
1237 DBG("STORAGE+=%s", path);
1238 s->dbus_path = eina_stringshare_add(path);
1239 s->udi = eina_stringshare_ref(s->dbus_path);
1240 _e_stores = eina_list_append(_e_stores, s);
1241 return s;
1242 }
1243
1244 void
_e_fm_main_udisks2_storage_del(const char * path)1245 _e_fm_main_udisks2_storage_del(const char *path)
1246 {
1247 E_Storage *s;
1248
1249 s = _storage_find_by_dbus_path(path);
1250 if (!s) return;
1251 if (s->validated)
1252 {
1253 stores_registered = eina_list_remove(stores_registered, s);
1254 INF("--STO %s", s->udi);
1255 ecore_ipc_server_send(_e_fm_ipc_server,
1256 6 /*E_IPC_DOMAIN_FM*/,
1257 E_FM_OP_STORAGE_DEL,
1258 0, 0, 0, s->udi, strlen(s->udi) + 1);
1259 }
1260 _e_stores = eina_list_remove(_e_stores, s);
1261 if (s->proxy)
1262 {
1263 Eldbus_Object *obj = eldbus_proxy_object_get(s->proxy);
1264 eldbus_proxy_unref(s->proxy);
1265 eldbus_object_unref(obj);
1266 }
1267 while (s->volumes)
1268 _volume_del(eina_list_data_get(s->volumes));
1269 _e_fm_shared_device_storage_free(s);
1270 }
1271
1272 static E_Storage *
_storage_find_by_dbus_path(const char * path)1273 _storage_find_by_dbus_path(const char *path)
1274 {
1275 Eina_List *l;
1276 E_Storage *s;
1277
1278 EINA_LIST_FOREACH(_e_stores, l, s)
1279 if (!strcmp(path, s->dbus_path)) return s;
1280 return NULL;
1281 }
1282
1283 E_Storage *
_e_fm_main_udisks2_storage_find(const char * udi)1284 _e_fm_main_udisks2_storage_find(const char *udi)
1285 {
1286 Eina_List *l;
1287 E_Storage *s;
1288
1289 EINA_LIST_FOREACH(_e_stores, l, s)
1290 {
1291 if (!s->udi) continue;
1292 if (!strcmp(udi, s->udi)) return s;
1293 }
1294 return NULL;
1295 }
1296