1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4 
5 #include <Ecore.h>
6 #include <Eeze.h>
7 #include <Eeze_Disk.h>
8 #include <unistd.h>
9 
10 #include "eeze_udev_private.h"
11 #include "eeze_disk_private.h"
12 
13 int _eeze_disk_log_dom = -1;
14 Eina_List *_eeze_disks = NULL;
15 
16 static Eeze_Disk_Type
_eeze_disk_type_find(Eeze_Disk * disk)17 _eeze_disk_type_find(Eeze_Disk *disk)
18 {
19    const char *test;
20    Eeze_Disk_Type ret;
21    Eina_Bool filesystem = EINA_FALSE; /* this will have no children */
22 
23    if (udev_device_get_property_value(disk->device, "ID_CDROM"))
24      return EEZE_DISK_TYPE_CDROM;
25    test = udev_device_get_property_value(disk->device, "ID_FS_USAGE");
26    if ((!test) || strcmp(test, "filesystem"))
27      {
28         test = _walk_children_get_attr(disk->syspath, "ID_CDROM", "block", EINA_TRUE);
29         if (test)
30           {
31              eina_stringshare_del(test);
32              return EEZE_DISK_TYPE_CDROM;
33           }
34      }
35    else
36      filesystem = EINA_TRUE;
37    if (udev_device_get_property_value(disk->device, "ID_ATA"))
38      return EEZE_DISK_TYPE_INTERNAL;
39    if (!filesystem)
40      {
41         test = _walk_children_get_attr(disk->syspath, "ID_ATA", "block", EINA_TRUE);
42         if (test)
43           {
44              eina_stringshare_del(test);
45              return EEZE_DISK_TYPE_INTERNAL;
46           }
47      }
48    test = udev_device_get_property_value(disk->device, "ID_BUS");
49    if (test)
50      {
51         if (!strcmp(test, "ata")) return EEZE_DISK_TYPE_INTERNAL;
52         if (!strcmp(test, "usb")) return EEZE_DISK_TYPE_USB;
53         return EEZE_DISK_TYPE_UNKNOWN; /* FIXME */
54      }
55    if (!filesystem)
56      test = _walk_children_get_attr(disk->syspath, "ID_BUS", "block", EINA_TRUE);
57    if (!test)
58      {
59         _udev_device *dev;
60 
61         for (dev = udev_device_get_parent(disk->device); dev; dev = udev_device_get_parent(dev))
62           {
63              test = udev_device_get_subsystem(dev);
64              if (!test) return EEZE_DISK_TYPE_UNKNOWN;
65              if (!strcmp(test, "block")) continue;
66              if (!strcmp(test, "mmc")) return EEZE_DISK_TYPE_FLASH;
67              break;
68           }
69         return EEZE_DISK_TYPE_UNKNOWN;  /* FIXME */
70      }
71 
72    if (!strcmp(test, "ata")) ret = EEZE_DISK_TYPE_INTERNAL;
73    else if (!strcmp(test, "usb")) ret = EEZE_DISK_TYPE_USB;
74    else ret = EEZE_DISK_TYPE_UNKNOWN; /* FIXME */
75 
76    eina_stringshare_del(test);
77 
78    return ret;
79 }
80 
81 static _udev_device *
_eeze_disk_device_from_property(const char * prop,Eina_Bool uuid)82 _eeze_disk_device_from_property(const char *prop, Eina_Bool uuid)
83 {
84    _udev_enumerate *en;
85    _udev_list_entry *devs, *cur;
86    _udev_device *device = NULL;
87    const char *devname;
88 
89    en = udev_enumerate_new(udev);
90 
91    if (!en)
92      return NULL;
93 
94    if (uuid)
95      udev_enumerate_add_match_property(en, "ID_FS_UUID", prop);
96    else
97      udev_enumerate_add_match_property(en, "ID_FS_LABEL", prop);
98    udev_enumerate_scan_devices(en);
99    devs = udev_enumerate_get_list_entry(en);
100    udev_list_entry_foreach(cur, devs)
101      {
102         devname = udev_list_entry_get_name(cur);
103         device = udev_device_new_from_syspath(udev, devname);
104         break;
105      }
106    udev_enumerate_unref(en);
107    return device;
108 
109 }
110 
111 void
eeze_disk_shutdown(void)112 eeze_disk_shutdown(void)
113 {
114    eeze_mount_shutdown();
115    ecore_file_shutdown();
116    eina_log_domain_unregister(_eeze_disk_log_dom);
117    _eeze_disk_log_dom = -1;
118 }
119 
120 Eina_Bool
eeze_disk_init(void)121 eeze_disk_init(void)
122 {
123    _eeze_disk_log_dom = eina_log_domain_register("eeze_disk", EINA_COLOR_LIGHTBLUE);
124 
125    if (_eeze_disk_log_dom < 0)
126      {
127         EINA_LOG_ERR("Could not register 'eeze_disk' log domain.");
128         goto disk_fail;
129      }
130 
131    if (!ecore_file_init())
132      goto disk_fail;
133    if  (!eeze_mount_init())
134      goto ecore_file_fail;
135 
136    return EINA_TRUE;
137 
138 ecore_file_fail:
139    ecore_file_shutdown();
140 disk_fail:
141    eina_log_domain_unregister(_eeze_disk_log_dom);
142    _eeze_disk_log_dom = -1;
143    return EINA_FALSE;
144 }
145 
146 EAPI void
eeze_disk_function(void)147 eeze_disk_function(void)
148 {
149 }
150 
151 EAPI Eeze_Disk *
eeze_disk_new(const char * path)152 eeze_disk_new(const char *path)
153 {
154    Eeze_Disk *disk;
155    _udev_device *dev;
156    const char *syspath = NULL;
157    Eina_Bool is_dev = EINA_FALSE;
158 
159    EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
160 
161    if (!strncmp(path, "/dev/", 5))
162      {
163         is_dev = EINA_TRUE;
164         syspath = eeze_udev_devpath_get_syspath(path);
165         if (!syspath)
166           return NULL;
167 
168         if (!(dev = _new_device(syspath)))
169           {
170              eina_stringshare_del(syspath);
171              return NULL;
172           }
173      }
174    else if (!(dev = _new_device(path)))
175      return NULL;
176 
177 
178    if (!(disk = calloc(1, sizeof(Eeze_Disk))))
179      return NULL;
180 
181 
182    if (is_dev)
183      {
184         disk->devpath = eina_stringshare_add(path);
185         disk->syspath = syspath;
186      }
187    else
188      disk->syspath = eina_stringshare_add(udev_device_get_syspath(dev));
189 
190 
191    disk->device = dev;
192    disk->mount_opts = EEZE_DISK_MOUNTOPT_DEFAULTS;
193    disk->mount_cmd_changed = EINA_TRUE;
194    disk->unmount_cmd_changed = EINA_TRUE;
195 
196    _eeze_disks = eina_list_append(_eeze_disks, disk);
197 
198    return disk;
199 }
200 
201 EAPI Eeze_Disk *
eeze_disk_new_from_mount(const char * mount_point)202 eeze_disk_new_from_mount(const char *mount_point)
203 {
204    Eeze_Disk *disk = NULL;
205    _udev_device *dev = NULL;
206    const char *source, *uuid = NULL, *label = NULL, *devpath = NULL;
207 
208    EINA_SAFETY_ON_NULL_RETURN_VAL(mount_point, NULL);
209 
210    if (!(source = eeze_disk_libmount_mp_find_source(mount_point)))
211      return NULL;
212 
213    if (source[4] == '=')
214      {
215         source += 5;
216         uuid = eina_stringshare_add(source);
217         dev = _eeze_disk_device_from_property(uuid, EINA_TRUE);
218      }
219    else if (source[5] == '=')
220      {
221         source += 6;
222         label = eina_stringshare_add(source);
223         dev = _eeze_disk_device_from_property(label, EINA_FALSE);
224      }
225    else
226      {
227         const char *spath;
228 
229         devpath = eina_stringshare_add(source);
230         spath = eeze_udev_devpath_get_syspath(devpath);
231         dev = _new_device(spath);
232         eina_stringshare_del(spath);
233      }
234 
235    if (!dev)
236      goto error;
237 
238    if (!(disk = calloc(1, sizeof(Eeze_Disk))))
239      goto error;
240 
241    disk->syspath = udev_device_get_syspath(dev);
242 
243    disk->device = dev;
244    disk->mount_cmd_changed = EINA_TRUE;
245    disk->unmount_cmd_changed = EINA_TRUE;
246    if (uuid)
247      disk->cache.uuid = uuid;
248    else if (label)
249      disk->cache.label = label;
250    else
251      disk->devpath = devpath;
252    disk->mount_point = eina_stringshare_add(mount_point);
253 
254    _eeze_disks = eina_list_append(_eeze_disks, disk);
255 
256    return disk;
257 error:
258    if (uuid)
259      eina_stringshare_del(uuid);
260    else if (label)
261      eina_stringshare_del(label);
262    else if (devpath)
263      eina_stringshare_del(devpath);
264    if (dev)
265      udev_device_unref(dev);
266    return NULL;
267 }
268 
269 EAPI void
eeze_disk_free(Eeze_Disk * disk)270 eeze_disk_free(Eeze_Disk *disk)
271 {
272    extern Eina_List *eeze_events;
273    EINA_SAFETY_ON_NULL_RETURN(disk);
274 
275    udev_device_unref(disk->device);
276    if (disk->mount_cmd)
277      eina_strbuf_free(disk->mount_cmd);
278    if (disk->unmount_cmd)
279      eina_strbuf_free(disk->unmount_cmd);
280    if (disk->eject_cmd)
281      eina_strbuf_free(disk->eject_cmd);
282    if (disk->mounter) ecore_exe_kill(disk->mounter);
283    _eeze_disks = eina_list_remove(_eeze_disks, disk);
284    eeze_events = eina_list_remove(eeze_events, disk);
285    free(disk);
286 }
287 
288 EAPI void
eeze_disk_scan(Eeze_Disk * disk)289 eeze_disk_scan(Eeze_Disk *disk)
290 {
291    const char *test;
292    EINA_SAFETY_ON_NULL_RETURN(disk);
293    /* never rescan; if these values change then something is seriously wrong */
294    if (disk->cache.filled) return;
295 
296    if (!disk->cache.vendor)
297      disk->cache.vendor = udev_device_get_property_value(disk->device, "ID_VENDOR");
298    if (!disk->cache.vendor)
299      disk->cache.vendor = udev_device_get_sysattr_value(disk->device, "vendor");
300    if (!disk->cache.model)
301      disk->cache.model = udev_device_get_property_value(disk->device, "ID_MODEL");
302    if (!disk->cache.model)
303      disk->cache.model = udev_device_get_sysattr_value(disk->device, "model");
304    if (!disk->cache.serial)
305      disk->cache.serial = udev_device_get_property_value(disk->device, "ID_SERIAL_SHORT");
306    if (!disk->cache.uuid)
307      disk->cache.uuid = udev_device_get_property_value(disk->device, "ID_FS_UUID");
308    if (!disk->cache.type)
309      disk->cache.type = _eeze_disk_type_find(disk);
310    if (!disk->cache.label)
311      disk->cache.label = udev_device_get_property_value(disk->device, "ID_FS_LABEL");
312    test = udev_device_get_sysattr_value(disk->device, "removable");
313    if (test) disk->cache.removable = !!strtol(test, NULL, 10);
314    else
315      test = _walk_children_get_attr(disk->syspath, "removable", "block", EINA_FALSE);
316    if (test)
317      {
318         disk->cache.removable = !!strtol(test, NULL, 10);
319         eina_stringshare_del(test);
320      }
321 
322    disk->cache.filled = EINA_TRUE;
323 }
324 
325 EAPI void
eeze_disk_data_set(Eeze_Disk * disk,void * data)326 eeze_disk_data_set(Eeze_Disk *disk, void *data)
327 {
328    EINA_SAFETY_ON_NULL_RETURN(disk);
329 
330    disk->data = data;
331 }
332 
333 EAPI void *
eeze_disk_data_get(Eeze_Disk * disk)334 eeze_disk_data_get(Eeze_Disk *disk)
335 {
336    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
337 
338    return disk->data;
339 }
340 
341 EAPI const char *
eeze_disk_syspath_get(Eeze_Disk * disk)342 eeze_disk_syspath_get(Eeze_Disk *disk)
343 {
344    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
345 
346    return disk->syspath;
347 }
348 
349 EAPI const char *
eeze_disk_devpath_get(Eeze_Disk * disk)350 eeze_disk_devpath_get(Eeze_Disk *disk)
351 {
352    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
353 
354    if (disk->devpath)
355      return disk->devpath;
356    disk->devpath = udev_device_get_devnode(disk->device);
357    return disk->devpath;
358 }
359 
360 EAPI const char *
eeze_disk_fstype_get(Eeze_Disk * disk)361 eeze_disk_fstype_get(Eeze_Disk *disk)
362 {
363    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
364 
365    return disk->fstype;
366 }
367 
368 EAPI const char *
eeze_disk_vendor_get(Eeze_Disk * disk)369 eeze_disk_vendor_get(Eeze_Disk *disk)
370 {
371    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
372 
373    if (disk->cache.vendor)
374      return disk->cache.vendor;
375 
376    disk->cache.vendor = udev_device_get_property_value(disk->device, "ID_VENDOR");
377    if (!disk->cache.vendor) disk->cache.vendor = udev_device_get_sysattr_value(disk->device, "vendor");
378    return disk->cache.vendor;
379 }
380 
381 EAPI const char *
eeze_disk_model_get(Eeze_Disk * disk)382 eeze_disk_model_get(Eeze_Disk *disk)
383 {
384    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
385 
386    if (disk->cache.model)
387      return disk->cache.model;
388 
389    disk->cache.model = udev_device_get_property_value(disk->device, "ID_MODEL");
390    if (!disk->cache.model) disk->cache.model = udev_device_get_sysattr_value(disk->device, "model");
391    return disk->cache.model;
392 }
393 
394 EAPI const char *
eeze_disk_serial_get(Eeze_Disk * disk)395 eeze_disk_serial_get(Eeze_Disk *disk)
396 {
397    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
398 
399    if (disk->cache.serial)
400      return disk->cache.serial;
401    disk->cache.serial = udev_device_get_property_value(disk->device, "ID_SERIAL_SHORT");
402    return disk->cache.serial;
403 }
404 
405 EAPI const char *
eeze_disk_uuid_get(Eeze_Disk * disk)406 eeze_disk_uuid_get(Eeze_Disk *disk)
407 {
408    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
409 
410    if (disk->cache.uuid)
411      return disk->cache.uuid;
412    disk->cache.uuid = udev_device_get_property_value(disk->device, "ID_FS_UUID");
413    return disk->cache.uuid;
414 }
415 
416 EAPI const char *
eeze_disk_label_get(Eeze_Disk * disk)417 eeze_disk_label_get(Eeze_Disk *disk)
418 {
419    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
420 
421    if (disk->cache.label)
422      return disk->cache.label;
423    disk->cache.label = udev_device_get_property_value(disk->device, "ID_FS_LABEL");
424    return disk->cache.label;
425 }
426 
427 EAPI Eeze_Disk_Type
eeze_disk_type_get(Eeze_Disk * disk)428 eeze_disk_type_get(Eeze_Disk *disk)
429 {
430    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EEZE_DISK_TYPE_UNKNOWN);
431 
432    if (disk->cache.type)
433      return disk->cache.type;
434    disk->cache.type = _eeze_disk_type_find(disk);
435    return disk->cache.type;
436 }
437 
438 EAPI Eina_Bool
eeze_disk_removable_get(Eeze_Disk * disk)439 eeze_disk_removable_get(Eeze_Disk *disk)
440 {
441    const char *test;
442    EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
443 
444    if (disk->cache.filled)
445      return disk->cache.removable;
446 
447    test = udev_device_get_sysattr_value(disk->device, "removable");
448    if (test) disk->cache.removable = !!strtol(test, NULL, 10);
449    else
450      test = _walk_children_get_attr(disk->syspath, "removable", "block", EINA_FALSE);
451    if (test)
452      {
453         disk->cache.removable = !!strtol(test, NULL, 10);
454         eina_stringshare_del(test);
455      }
456    return disk->cache.removable;
457 }
458 
459 EAPI Eina_Bool
eeze_disk_can_mount(void)460 eeze_disk_can_mount(void)
461 {
462    if (sizeof(EEZE_MOUNT_BIN) == sizeof(""))
463      return EINA_FALSE;
464    return access(EEZE_MOUNT_BIN, X_OK | R_OK) == 0;
465 }
466 
467 EAPI Eina_Bool
eeze_disk_can_unmount(void)468 eeze_disk_can_unmount(void)
469 {
470    if (sizeof(EEZE_UNMOUNT_BIN) == sizeof(""))
471      return EINA_FALSE;
472    return access(EEZE_UNMOUNT_BIN, X_OK | R_OK) == 0;
473 }
474 
475 EAPI Eina_Bool
eeze_disk_can_eject(void)476 eeze_disk_can_eject(void)
477 {
478    if (sizeof(EEZE_EJECT_BIN) == sizeof(""))
479      return EINA_FALSE;
480    return access(EEZE_EJECT_BIN, X_OK | R_OK) == 0;
481 }
482