Git init
[platform/core/uifw/e17.git] / src / bin / e_fm_device.c
1 #include "e_fm_device.h"
2 #include "e_fm_shared_codec.h"
3 #include "e_fm_shared_device.h"
4
5 #define TEBIBYTE_SIZE 1099511627776LL
6 #define GIBIBYTE_SIZE 1073741824
7 #define MEBIBYTE_SIZE 1048576
8 #define KIBIBYTE_SIZE 1024
9
10 static void _e_fm2_volume_write(E_Volume *v) EINA_ARG_NONNULL(1);
11 static void _e_fm2_volume_erase(E_Volume *v) EINA_ARG_NONNULL(1);
12 static void _e_fm2_device_mount_free(E_Fm2_Mount *m); EINA_ARG_NONNULL(1);
13 static void _e_fm2_device_mount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
14 static void _e_fm2_device_mount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
15 static void _e_fm2_device_unmount_ok(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
16 static void _e_fm2_device_unmount_fail(E_Fm2_Mount *m) EINA_ARG_NONNULL(1);
17
18 static Eina_List *_e_stores = NULL;
19 static Eina_List *_e_vols = NULL;
20
21 static void
22 _e_fm2_device_volume_setup(E_Volume *v)
23 {
24    char label[1024] = {0};
25    char size[256] = {0};
26    const char *icon = NULL;
27    unsigned long long sz;
28
29    /* Compute the size in a readable form */
30    if (v->size)
31      {
32         if ((sz = (v->size / TEBIBYTE_SIZE)) > 0)
33           snprintf(size, sizeof(size) - 1, _("%llu TiB"), sz);
34         else if ((sz = (v->size / GIBIBYTE_SIZE)) > 0)
35           snprintf(size, sizeof(size) - 1, _("%llu GiB"), sz);
36         else if ((sz = (v->size / MEBIBYTE_SIZE)) > 0)
37           snprintf(size, sizeof(size) - 1, _("%llu MiB"), sz);
38         else if ((sz = (v->size / KIBIBYTE_SIZE)) > 0)
39           snprintf(size, sizeof(size) - 1, _("%llu KiB"), sz);
40         else
41           snprintf(size, sizeof(size) - 1, _("%llu B"), v->size);
42      }
43
44    /* Choose the label */
45    if ((v->label) && (v->label[0]))
46      {}
47    else if ((v->partition_label) && (v->partition_label[0]))
48      snprintf(label, sizeof(label) - 1, "%s", v->partition_label);
49    else if (((v->storage->vendor) && (v->storage->vendor[0])) &&
50             ((v->storage->model) && (v->storage->model[0])))
51      {
52         if (size[0] != '\0')
53           snprintf(label, sizeof(label) - 1, "%s %s - %s", v->storage->vendor, v->storage->model, size);
54         else
55           snprintf(label, sizeof(label) - 1, "%s %s", v->storage->vendor, v->storage->model);
56      }
57    else if ((v->storage->model) && (v->storage->model[0]))
58      {
59         if (size[0] != '\0')
60           snprintf(label, sizeof(label) - 1, "%s - %s", v->storage->model, size);
61         else
62           snprintf(label, sizeof(label) - 1, "%s", v->storage->model);
63      }
64    else if ((v->storage->vendor) && (v->storage->vendor[0]))
65      {
66         if (size[0] != '\0')
67           snprintf(label, sizeof(label) - 1, "%s - %s", v->storage->vendor, size);
68         else
69           snprintf(label, sizeof(label) - 1, "%s", v->storage->vendor);
70      }
71    else
72      snprintf(label, sizeof(label), _("Unknown Volume"));
73
74    if (label[0]) eina_stringshare_replace(&v->label, label);
75
76    /* Choose the icon */
77    /* http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html */
78    if (v->storage->icon.volume)
79      icon = v->storage->icon.volume;
80    else
81      {
82         if ((!v->storage->drive_type) || (!strcmp(v->storage->drive_type, "disk")))
83           {
84              if (v->storage->removable == 0)
85                icon = "drive-harddisk";
86              else
87                icon = "drive-removable-media";
88           }
89         else if ((!strcmp(v->storage->drive_type, "cdrom")) || (!strncmp(v->storage->drive_type, "optical", 7)))
90           icon = "drive-optical";
91         else if (!strncmp(v->storage->drive_type, "floppy", 6))
92           icon = "media-floppy";
93         else if (!strcmp(v->storage->drive_type, "tape"))
94           icon = "media-tape";
95         else if (!strcmp(v->storage->drive_type, "compact_flash")
96                  || !strcmp(v->storage->drive_type, "memory_stick")
97                  || !strcmp(v->storage->drive_type, "smart_media")
98                  || !strcmp(v->storage->drive_type, "sd_mmc")
99                  || !strncmp(v->storage->drive_type, "flash", 5))
100           icon = "media-flash";
101      }
102    if (icon) eina_stringshare_replace(&v->icon, icon);
103
104    if ((!v->mount_point) ||
105        (strcmp(v->mount_point, "/") &&
106         strcmp(v->mount_point, "/home") &&
107         strcmp(v->mount_point, "/tmp")))
108      _e_fm2_volume_write(v);
109 }
110      
111 EAPI void
112 e_fm2_device_storage_add(E_Storage *s)
113 {
114    Eina_List *l;
115    E_Volume *v;
116    
117    if (e_fm2_device_storage_find(s->udi)) return;
118
119    s->validated = EINA_TRUE;
120    _e_stores = eina_list_append(_e_stores, s);
121 /*
122    printf("STO+\n"
123           "  udi: %s\n"
124           "  bus: %s\n"
125           "  drive_type: %s\n"
126           "  model: %s\n"
127           "  vendor: %s\n"
128           "  serial: %s\n"
129           "  removable: %i\n"
130           "  media_available: %i\n"
131           "  media_size: %lli\n"
132           "  requires_eject: %i\n"
133           "  hotpluggable: %i\n"
134           "  media_check_enabled: %i\n"
135           "  icon.drive: %s\n"
136           "  icon.volume: %s\n\n"
137           ,
138           s->udi,
139           s->bus,
140           s->drive_type,
141           s->model,
142           s->vendor,
143           s->serial,
144           s->removable,
145           s->media_available,
146           s->media_size,
147           s->requires_eject,
148           s->hotpluggable,
149           s->media_check_enabled,
150           s->icon.drive,
151           s->icon.volume);
152  */
153    if ((s->removable == 0) &&
154        (s->media_available == 0) &&
155        (s->media_size == 0) &&
156        (s->requires_eject == 0) &&
157        (s->hotpluggable == 0) &&
158        (s->media_check_enabled == 0))
159      {
160 //      printf("      Ignore this storage\n");
161      }
162    else
163      {
164         s->trackable = EINA_TRUE;
165      }
166      
167    EINA_LIST_FOREACH(_e_vols, l, v) /* catch volumes which were added before their storage */
168      {
169         if ((!v->storage) && (s->udi == v->parent))
170           {
171              v->storage = s;
172              _e_fm2_device_volume_setup(v);
173           }
174      }
175 }
176
177 EAPI void
178 e_fm2_device_storage_del(E_Storage *s)
179 {
180 //   printf("STO- %s\n", s->udi);
181      _e_stores = eina_list_remove(_e_stores, s);
182      _e_fm_shared_device_storage_free(s);
183 }
184
185 EAPI E_Storage *
186 e_fm2_device_storage_find(const char *udi)
187 {
188    Eina_List *l;
189    E_Storage *s;
190
191    if (!udi) return NULL;
192    EINA_LIST_FOREACH(_e_stores, l, s)
193      {
194         if (!strcmp(udi, s->udi)) return s;
195      }
196    return NULL;
197 }
198
199
200 EAPI void
201 e_fm2_device_volume_add(E_Volume *v)
202 {
203    E_Storage *s;
204
205    if (e_fm2_device_volume_find(v->udi)) return;
206
207    v->validated = EINA_TRUE;
208    _e_vols = eina_list_append(_e_vols, v);
209 /*
210    printf("VOL+\n"
211           "  udi: %s\n"
212           "  uuid: %s\n"
213           "  fstype: %s\n"
214           "  size: %llu\n"
215           "  label: %s\n"
216           "  partition: %d\n"
217           "  partition_number: %d\n"
218           "  partition_label: %s\n"
219           "  mounted: %d\n"
220           "  mount_point: %s\n"
221           "  parent: %s\n"
222           ,
223           v->udi,
224           v->uuid,
225           v->fstype,
226           v->size,
227           v->label,
228           v->partition,
229           v->partition_number,
230           v->partition ? v->partition_label : "(not a partition)",
231           v->mounted,
232           v->mount_point,
233           v->parent);
234  */
235 /* Check mount point */
236    if ((v->efm_mode == EFM_MODE_USING_HAL_MOUNT) &&
237        ((!v->mount_point) || (!v->mount_point[0])))
238      {
239         if (v->mount_point) eina_stringshare_del(v->mount_point);
240         v->mount_point = NULL;
241         v->mount_point = e_fm2_device_volume_mountpoint_get(v);
242         if ((!v->mount_point) || (!v->mount_point[0]))
243           {
244              char buf[PATH_MAX];
245              const char *id;
246
247              if (v->mount_point) eina_stringshare_del(v->mount_point);
248              v->mount_point = NULL;
249              id = "disk";
250              if ((v->uuid) && (v->uuid[0])) id = v->uuid;
251              if (ecore_file_is_dir("/media"))
252                snprintf(buf, sizeof(buf), "/media/%s", id);
253              else if (ecore_file_is_dir("/mnt"))
254                snprintf(buf, sizeof(buf), "/mnt/%s", id);
255              else if (ecore_file_is_dir("/tmp"))
256                snprintf(buf, sizeof(buf), "/tmp/%s", id);
257              else
258                buf[0] = 0;
259              v->mount_point = eina_stringshare_add(buf);
260           }
261      }
262
263    /* Search parent storage */
264    if ((s = e_fm2_device_storage_find(v->parent)))
265      {
266         v->storage = s;
267         s->volumes = eina_list_append(s->volumes, v);
268      }
269
270    if (v->storage) _e_fm2_device_volume_setup(v);
271      
272 }
273
274 EAPI void
275 e_fm2_device_volume_del(E_Volume *v)
276 {
277    E_Fm2_Mount *m;
278
279 //   printf("VOL- %s\n", v->udi);
280    _e_vols = eina_list_remove(_e_vols, v);
281    _e_fm2_volume_erase(v);
282    if (v->storage)
283      {
284         v->storage->volumes = eina_list_remove(v->storage->volumes, v);
285         v->storage = NULL;
286      }
287    EINA_LIST_FREE(v->mounts, m)
288      {
289         _e_fm2_device_unmount_ok(m);
290         _e_fm2_device_mount_free(m);
291      }
292    _e_fm_shared_device_volume_free(v);
293 }
294
295 static void
296 _e_fm2_volume_write(E_Volume *v)
297 {
298    char buf[PATH_MAX], buf2[PATH_MAX];
299    FILE *f;
300    const char *id;
301
302    if (!v->storage) return;
303    id = ecore_file_file_get(v->storage->udi);
304 //   printf("vol write %s\n", id);
305    e_user_dir_snprintf(buf, sizeof(buf), "fileman/favorites/|%s_%d.desktop",
306                        id, v->partition_number);
307
308    f = fopen(buf, "w");
309    if (f)
310      {
311         fprintf(f,
312                 "[Desktop Entry]\n"
313                 "Encoding=UTF-8\n"
314                 "Type=Link\n"
315                 "X-Enlightenment-Type=Removable\n"
316                 "X-Enlightenment-Removable-State=Full\n"
317                 "Name=%s\n"
318                 "Icon=%s\n"
319                 "Comment=%s\n"
320                 "URL=file:/%s\n"
321                 ,
322                 v->label,
323                 v->icon,
324                 _("Removable Device"),
325                 v->udi);
326         fclose(f);
327
328         if (e_config->device_desktop)
329           {
330              e_user_homedir_snprintf(buf2, sizeof(buf2),
331                                      "%s/|%s_%d.desktop",
332                                      _("Desktop"), id, v->partition_number);
333              ecore_file_symlink(buf, buf2);
334           }
335
336         /* FIXME: manipulate icon directly */
337         _e_fm2_file_force_update(buf);
338         //_e_fm2_file_force_update(buf2);
339      }
340 }
341
342 #undef TEBIBYTE_SIZE
343 #undef GIBIBYTE_SIZE
344 #undef MEBIBYTE_SIZE
345 #undef KIBIBYTE_SIZE
346
347 static void
348 _e_fm2_volume_erase(E_Volume *v)
349 {
350    char buf[PATH_MAX] = {0};
351    const char *id;
352
353    if (!v->storage) return;
354    id = ecore_file_file_get(v->storage->udi);
355    e_user_homedir_snprintf(buf, sizeof(buf), "%s/|%s_%d.desktop",
356                            _("Desktop"), id, v->partition_number);
357    ecore_file_unlink(buf);
358    _e_fm2_file_force_update(buf);
359
360    if (e_config->device_desktop)
361      {
362         e_user_dir_snprintf(buf, sizeof(buf),
363                             "fileman/favorites/|%s_%d.desktop",
364                             id, v->partition_number);
365         ecore_file_unlink(buf);
366         _e_fm2_file_force_update(buf);
367      }
368 }
369
370 EAPI E_Volume *
371 e_fm2_device_volume_find(const char *udi)
372 {
373    Eina_List *l;
374    E_Volume *v;
375
376    if (!udi) return NULL;
377
378    EINA_LIST_FOREACH(_e_vols, l, v)
379      {
380         if (!v->udi) continue;
381         if (!strcmp(udi, v->udi)) return v;
382      }
383
384    return NULL;
385 }
386
387 EAPI const char *
388 e_fm2_device_volume_mountpoint_get(E_Volume *v)
389 {
390    char buf[PATH_MAX] = {0};
391
392    if (!v) return NULL;
393    if (v->mount_point)
394      {
395         //      printf("GET MOUNTPOINT = %s\n", v->mount_point);
396           return eina_stringshare_add(v->mount_point);
397      }
398    else if (v->efm_mode != EFM_MODE_USING_HAL_MOUNT)
399      return NULL;
400
401    if (v->label && v->label[0] != '\0')
402      snprintf(buf, sizeof(buf) - 1, "/media/%s", v->label);
403    else if (v->uuid && v->uuid[0] != '\0')
404      snprintf(buf, sizeof(buf) - 1, "/media/%s", v->uuid);
405    else if ((v->storage) && (v->storage->serial) && v->storage->serial[0] != '\0')
406      snprintf(buf, sizeof(buf) - 1, "/media/%s", v->storage->serial);
407    else
408      {
409         static int mount_count = 1;
410         snprintf(buf, sizeof(buf) - 1, "/media/unknown-%i", mount_count++);
411      }
412 //   printf("GET MOUNTPOINT = %s\n", buf);
413    return eina_stringshare_add(buf);
414 }
415
416 EAPI void
417 e_fm2_device_mount_add(E_Volume   *v,
418                        const char *mountpoint)
419 {
420    Eina_List *l;
421    E_Fm2_Mount *m;
422
423    v->mounted = EINA_TRUE;
424    if (mountpoint && (mountpoint[0]))
425      eina_stringshare_replace(&v->mount_point, mountpoint);
426
427    EINA_LIST_FOREACH(v->mounts, l, m)
428      _e_fm2_device_mount_ok(m);
429
430 //   printf("MOUNT %s %s\n", v->udi, v->mount_point);
431 }
432
433 EAPI void
434 e_fm2_device_mount_del(E_Volume *v)
435 {
436    E_Fm2_Mount *m;
437
438    v->mounted = EINA_FALSE;
439    if (v->mount_point)
440      {
441         eina_stringshare_del(v->mount_point);
442         v->mount_point = NULL;
443      }
444
445    EINA_LIST_FREE(v->mounts, m)
446      {
447         _e_fm2_device_unmount_ok(m);
448         _e_fm2_device_mount_free(m);
449      }
450 }
451
452 EAPI void
453 _e_fm2_device_mount_free(E_Fm2_Mount *m)
454 {
455    if (!m) return;
456
457    if (m->udi) eina_stringshare_del(m->udi);
458    if (m->mount_point) eina_stringshare_del(m->mount_point);
459
460    free(m);
461 }
462
463 EAPI E_Fm2_Mount *
464 e_fm2_device_mount_find(const char *path)
465 {
466    Eina_List *l;
467    E_Volume *v;
468
469    EINA_LIST_FOREACH(_e_vols, l, v)
470      {
471         if (v->mounted
472             && v->mount_point
473             && !strncmp(path, v->mount_point, strlen(v->mount_point))
474             && v->mounts)
475           return eina_list_data_get(v->mounts);
476      }
477    return NULL;
478 }
479
480 EAPI E_Fm2_Mount *
481 e_fm2_device_mount(E_Volume *v,
482                    Ecore_Cb  mount_ok,
483                    Ecore_Cb  mount_fail,
484                    Ecore_Cb  unmount_ok,
485                    Ecore_Cb  unmount_fail,
486                    void     *data)
487 {
488    E_Fm2_Mount *m;
489
490    if (!v) return NULL;
491
492    m = calloc(1, sizeof(E_Fm2_Mount));
493    if (!m) return NULL;
494    m->udi = eina_stringshare_add(v->udi);
495    m->mount_ok = mount_ok;
496    m->mount_fail = mount_fail;
497    m->unmount_ok = unmount_ok;
498    m->unmount_fail = unmount_fail;
499    m->data = data;
500    m->volume = v;
501    m->mounted = v->mounted;
502
503    v->mounts = eina_list_prepend(v->mounts, m);
504
505 //   printf("BEGIN MOUNT %p '%s'\n", m, v->mount_point);
506
507    if (!v->mounted)
508      {
509         v->auto_unmount = EINA_TRUE;
510         _e_fm2_client_mount(v->udi, v->mount_point);
511      }
512    else
513      {
514         v->auto_unmount = EINA_FALSE;
515         m->mount_point = eina_stringshare_add(v->mount_point);
516      }
517
518    return m;
519 }
520
521 EAPI void
522 e_fm2_device_mount_fail(E_Volume *v)
523 {
524    E_Fm2_Mount *m;
525
526    v->mounted = EINA_FALSE;
527    if (v->mount_point)
528      {
529         eina_stringshare_del(v->mount_point);
530         v->mount_point = NULL;
531      }
532
533    EINA_LIST_FREE(v->mounts, m)
534      {
535         _e_fm2_device_mount_fail(m);
536         _e_fm2_device_mount_free(m);
537      }
538 }
539
540 EAPI void
541 e_fm2_device_unmount(E_Fm2_Mount *m)
542 {
543    E_Volume *v;
544
545    if (!(v = m->volume)) return;
546    v->mounts = eina_list_remove(v->mounts, m);
547    _e_fm2_device_mount_free(m);
548
549    if (v->auto_unmount && v->mounted && !eina_list_count(v->mounts))
550      _e_fm2_client_unmount(v->udi);
551 }
552
553 EAPI void
554 e_fm2_device_unmount_fail(E_Volume *v)
555 {
556    Eina_List *l;
557    E_Fm2_Mount *m;
558
559    v->mounted = EINA_TRUE;
560
561    EINA_LIST_FOREACH(v->mounts, l, m)
562      _e_fm2_device_unmount_fail(m);
563 }
564
565 static void
566 _e_fm2_device_mount_ok(E_Fm2_Mount *m)
567 {
568    if (m->mounted) return;
569    m->mounted = EINA_TRUE;
570    if (m->volume)
571      m->mount_point = eina_stringshare_add(m->volume->mount_point);
572    if (m->mount_ok)
573      m->mount_ok(m->data);
574 //   printf("MOUNT OK '%s'\n", m->mount_point);
575 }
576
577 static void
578 _e_fm2_device_mount_fail(E_Fm2_Mount *m)
579 {
580    m->mounted = EINA_FALSE;
581    if (m->mount_point)
582      {
583         eina_stringshare_del(m->mount_point);
584         m->mount_point = NULL;
585      }
586    if (m->mount_fail)
587      m->mount_fail(m->data);
588 }
589
590 static void
591 _e_fm2_device_unmount_ok(E_Fm2_Mount *m)
592 {
593    if (!m->mounted) return;
594    m->mounted = EINA_FALSE;
595    if (m->mount_point)
596      {
597         eina_stringshare_del(m->mount_point);
598         m->mount_point = NULL;
599      }
600    if (m->unmount_ok)
601      m->unmount_ok(m->data);
602 }
603
604 static void
605 _e_fm2_device_unmount_fail(E_Fm2_Mount *m)
606 {
607    if (m->mounted) return;
608    m->mounted = EINA_TRUE;
609    if (m->unmount_fail)
610      m->unmount_fail(m->data);
611 }
612
613 EAPI void
614 e_fm2_device_show_desktop_icons(void)
615 {
616    Eina_List *l;
617    E_Volume *v;
618    char buf[PATH_MAX] = {0};
619    char buf2[PATH_MAX] = {0};
620    const char *id;
621
622    EINA_LIST_FOREACH(_e_vols, l, v)
623      {
624         if (!v) continue;
625         if (!v->storage) continue;
626
627         id = ecore_file_file_get(v->storage->udi);
628
629         e_user_dir_snprintf(buf, sizeof(buf),
630                             "fileman/favorites/|%s_%d.desktop",
631                             id, v->partition_number);
632
633         e_user_homedir_snprintf(buf2, sizeof(buf2),
634                                 "%s/|%s_%d.desktop",
635                                 _("Desktop"), id, v->partition_number);
636
637         if (ecore_file_exists(buf) && !ecore_file_exists(buf2))
638           {
639              ecore_file_symlink(buf, buf2);
640              _e_fm2_file_force_update(buf2);
641           }
642      }
643 }
644
645 EAPI void
646 e_fm2_device_hide_desktop_icons(void)
647 {
648    Eina_List *l;
649    E_Volume *v;
650    char buf[PATH_MAX] = {0};
651    const char *id;
652
653    EINA_LIST_FOREACH(_e_vols, l, v)
654      {
655         if (!v) continue;
656         if (!v->storage) continue;
657
658         id = ecore_file_file_get(v->storage->udi);
659
660         e_user_homedir_snprintf(buf, sizeof(buf),
661                                 "%s/|%s_%d.desktop",
662                                 _("Desktop"), id, v->partition_number);
663
664         if (ecore_file_exists(buf))
665           {
666              ecore_file_unlink(buf);
667              _e_fm2_file_force_update(buf);
668           }
669      }
670 }
671
672 EAPI Eina_List *
673 e_fm2_device_volume_list_get(void)
674 {
675    return _e_vols;
676 }
677