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