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