2011-01-28 20:21:53 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-05-15 17:06:41 -07:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2011-01-28 20:21:53 -08:00
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Eeze.h>
|
|
|
|
#include <Eeze_Disk.h>
|
|
|
|
|
|
|
|
#include "eeze_udev_private.h"
|
|
|
|
#include "eeze_disk_private.h"
|
|
|
|
|
2011-02-09 13:31:11 -08:00
|
|
|
#define EEZE_MOUNT_DEFAULT_OPTS "noexec,nosuid,utf8"
|
2011-01-28 20:21:53 -08:00
|
|
|
|
|
|
|
EAPI int EEZE_EVENT_DISK_MOUNT = 0;
|
|
|
|
EAPI int EEZE_EVENT_DISK_UNMOUNT = 0;
|
|
|
|
EAPI int EEZE_EVENT_DISK_ERROR = 0;
|
|
|
|
static Ecore_Event_Handler *_mount_handler = NULL;
|
2011-02-13 17:47:37 -08:00
|
|
|
static Eina_List *eeze_events = NULL;
|
2011-01-28 20:21:53 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* PRIVATE
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eeze_disk_mount_error_free(void *data __UNUSED__, Eeze_Event_Disk_Error *de)
|
|
|
|
{
|
|
|
|
if (!de)
|
|
|
|
return;
|
|
|
|
|
|
|
|
eina_stringshare_del(de->message);
|
|
|
|
free(de);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eeze_disk_mount_error_handler(Eeze_Disk *disk, const char *error)
|
|
|
|
{
|
|
|
|
Eeze_Event_Disk_Error *de;
|
2011-03-12 10:41:03 -08:00
|
|
|
|
2011-01-28 20:21:53 -08:00
|
|
|
ERR("%s", error);
|
|
|
|
if (!(de = calloc(1, sizeof(Eeze_Event_Disk_Error))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
de->disk = disk;
|
|
|
|
de->message = eina_stringshare_add(error);
|
|
|
|
/* FIXME: this is a placeholder since currently there are only mount-type errors */
|
|
|
|
de->type.mount = EINA_TRUE;
|
|
|
|
ecore_event_add(EEZE_EVENT_DISK_ERROR, de, (Ecore_End_Cb)_eeze_disk_mount_error_free, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2011-02-13 17:32:40 -08:00
|
|
|
_eeze_disk_mount_result_handler(void *data __UNUSED__, int type __UNUSED__, Ecore_Exe_Event_Del *ev)
|
2011-01-28 20:21:53 -08:00
|
|
|
{
|
|
|
|
Eeze_Disk *disk;
|
2011-02-13 17:47:37 -08:00
|
|
|
Eina_List *l;
|
2011-01-28 20:21:53 -08:00
|
|
|
Eeze_Event_Disk_Mount *e;
|
|
|
|
|
|
|
|
if ((!ev) || (!ev->exe))
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
2011-02-13 17:47:37 -08:00
|
|
|
disk = ecore_exe_data_get(ev->exe);
|
|
|
|
|
|
|
|
if ((!disk) || (!eeze_events) || (!(l = eina_list_data_find(eeze_events, disk))))
|
2011-01-28 20:21:53 -08:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2011-03-12 10:41:03 -08:00
|
|
|
|
2011-02-13 17:47:37 -08:00
|
|
|
eeze_events = eina_list_remove_list(eeze_events, l);
|
2011-01-28 20:21:53 -08:00
|
|
|
if (disk->mount_status == EEZE_DISK_MOUNTING)
|
2011-05-15 15:32:17 -07:00
|
|
|
{
|
2011-05-15 15:34:03 -07:00
|
|
|
if (!ev->exit_code)
|
|
|
|
{
|
|
|
|
e = malloc(sizeof(Eeze_Event_Disk_Mount));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW);
|
|
|
|
e->disk = disk;
|
|
|
|
ecore_event_add(EEZE_EVENT_DISK_MOUNT, e, NULL, NULL);
|
|
|
|
}
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 2)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "system error (out of memory, cannot fork, no more loop devices)");
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 4)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "internal mount bug");
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 8)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "user interrupt");
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 16)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "problems writing or locking /etc/mtab");
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 32)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "mount failure");
|
2011-05-15 15:32:17 -07:00
|
|
|
else if (ev->exit_code & 64)
|
2011-01-28 20:21:53 -08:00
|
|
|
_eeze_disk_mount_error_handler(disk, "some mount succeeded");
|
2011-05-15 15:34:03 -07:00
|
|
|
else
|
|
|
|
_eeze_disk_mount_error_handler(disk, "incorrect invocation or permissions");
|
2011-05-15 15:32:17 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
switch (ev->exit_code)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
e = malloc(sizeof(Eeze_Event_Disk_Unmount));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW);
|
|
|
|
e->disk = disk;
|
|
|
|
ecore_event_add(EEZE_EVENT_DISK_UNMOUNT, e, NULL, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
INF("Could not unmount disk, retrying");
|
|
|
|
disk->mounter = ecore_exe_pipe_run(eina_strbuf_string_get(disk->unmount_cmd), 0, disk);
|
|
|
|
eeze_events = eina_list_append(eeze_events, disk);
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
2011-03-12 10:41:03 -08:00
|
|
|
|
2011-01-28 20:21:53 -08:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* INVISIBLE
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
eeze_mount_init(void)
|
|
|
|
{
|
|
|
|
EEZE_EVENT_DISK_MOUNT = ecore_event_type_new();
|
|
|
|
EEZE_EVENT_DISK_UNMOUNT = ecore_event_type_new();
|
|
|
|
EEZE_EVENT_DISK_ERROR = ecore_event_type_new();
|
|
|
|
_mount_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
|
2011-02-13 17:32:40 -08:00
|
|
|
(Ecore_Event_Handler_Cb)_eeze_disk_mount_result_handler, NULL);
|
2011-01-28 20:21:53 -08:00
|
|
|
return eeze_libmount_init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
eeze_mount_shutdown(void)
|
|
|
|
{
|
|
|
|
eeze_libmount_shutdown();
|
|
|
|
ecore_event_handler_del(_mount_handler);
|
|
|
|
_mount_handler = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
* API
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
eeze_disk_mounted_get(Eeze_Disk *disk)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
|
|
|
|
return eeze_disk_libmount_mounted_get(disk);
|
|
|
|
}
|
|
|
|
|
2011-02-09 13:31:11 -08:00
|
|
|
EAPI Eina_Bool
|
2011-02-10 19:14:00 -08:00
|
|
|
eeze_disk_mountopts_set(Eeze_Disk *disk, unsigned long opts)
|
2011-02-09 13:31:11 -08:00
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
if (opts != disk->mount_opts)
|
|
|
|
disk->mount_cmd_changed = EINA_TRUE;
|
|
|
|
disk->mount_opts = opts;
|
2011-05-15 17:06:41 -07:00
|
|
|
if (opts & EEZE_DISK_MOUNTOPT_UID)
|
|
|
|
disk->uid = getuid();
|
2011-02-09 13:31:11 -08:00
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-02-10 19:14:00 -08:00
|
|
|
EAPI unsigned long
|
2011-02-09 13:31:11 -08:00
|
|
|
eeze_disk_mountopts_get(Eeze_Disk *disk)
|
|
|
|
{
|
2011-02-10 19:14:00 -08:00
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, 0);
|
|
|
|
#ifndef OLD_LIBMOUNT
|
|
|
|
if (!disk->mount_opts)
|
|
|
|
disk->mount_opts = eeze_disk_libmount_opts_get(disk);
|
|
|
|
#endif
|
2011-02-09 13:31:11 -08:00
|
|
|
return disk->mount_opts;
|
|
|
|
}
|
|
|
|
|
2011-05-15 15:56:14 -07:00
|
|
|
EAPI Eina_Bool
|
|
|
|
eeze_disk_mount_wrapper_set(Eeze_Disk *disk, const char *wrapper)
|
|
|
|
{
|
|
|
|
struct stat s;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
if (wrapper) EINA_SAFETY_ON_TRUE_RETURN_VAL(!*wrapper, EINA_FALSE);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eina_stringshare_del(disk->mount_wrapper);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
if ((!stat(wrapper, &s)) && S_ISREG(s.st_mode))
|
|
|
|
{
|
|
|
|
eina_stringshare_replace(&disk->mount_wrapper, wrapper);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
ERR("%s does not exist!", wrapper);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const char *
|
|
|
|
eeze_disk_mount_wrapper_get(Eeze_Disk *disk)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
|
|
|
|
return disk->mount_wrapper;
|
|
|
|
}
|
|
|
|
|
2011-01-28 20:21:53 -08:00
|
|
|
EAPI Eina_Bool
|
|
|
|
eeze_disk_mount(Eeze_Disk *disk)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
|
|
|
|
if ((!disk->mount_point) && eeze_disk_libmount_mounted_get(disk))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
if (!disk->mount_cmd)
|
|
|
|
disk->mount_cmd = eina_strbuf_new();
|
|
|
|
|
|
|
|
if (disk->mount_cmd_changed)
|
|
|
|
{
|
|
|
|
eina_strbuf_string_free(disk->mount_cmd);
|
|
|
|
if (!disk->cache.uuid)
|
|
|
|
disk->cache.uuid = udev_device_get_property_value(disk->device, "ID_FS_UUID");
|
|
|
|
|
|
|
|
if (!disk->mount_point)
|
|
|
|
{
|
|
|
|
const char *mp;
|
|
|
|
/* here we attempt to guess the mount point using libmount */
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_uuid(disk->cache.uuid);
|
|
|
|
if (!mp)
|
|
|
|
{
|
|
|
|
const char *label;
|
|
|
|
|
|
|
|
label = eeze_disk_label_get(disk);
|
|
|
|
if (label)
|
|
|
|
{
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_label(label);
|
|
|
|
eina_stringshare_del(label);
|
|
|
|
}
|
|
|
|
if (!mp)
|
|
|
|
{
|
|
|
|
const char *devpath;
|
|
|
|
|
|
|
|
devpath = eeze_disk_devpath_get(disk);
|
|
|
|
if (devpath)
|
|
|
|
{
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_devpath(devpath);
|
|
|
|
eina_stringshare_del(devpath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!eeze_disk_mount_point_set(disk, mp))
|
|
|
|
/* sometimes we fail */
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2011-02-09 12:38:09 -08:00
|
|
|
if ((!disk->mount_point) || (!disk->mount_point[0])) return EINA_FALSE;
|
2011-05-15 15:56:14 -07:00
|
|
|
if (disk->mount_wrapper)
|
|
|
|
eina_strbuf_append_printf(disk->mount_cmd, "%s ", disk->mount_wrapper);
|
2011-02-10 19:14:00 -08:00
|
|
|
if (disk->mount_opts == EEZE_DISK_MOUNTOPT_DEFAULTS)
|
2011-05-15 15:50:22 -07:00
|
|
|
eina_strbuf_append_printf(disk->mount_cmd, EEZE_MOUNT_BIN" -o "EEZE_MOUNT_DEFAULT_OPTS" UUID=%s %s", disk->cache.uuid, disk->mount_point);
|
2011-02-10 19:14:00 -08:00
|
|
|
else if (!disk->mount_opts)
|
2011-05-15 15:50:22 -07:00
|
|
|
eina_strbuf_append_printf(disk->mount_cmd, EEZE_MOUNT_BIN" UUID=%s %s", disk->cache.uuid, disk->mount_point);
|
2011-02-09 13:31:11 -08:00
|
|
|
else
|
|
|
|
{
|
2011-05-15 15:50:22 -07:00
|
|
|
eina_strbuf_append(disk->mount_cmd, EEZE_MOUNT_BIN" -o ");
|
2011-02-09 13:31:11 -08:00
|
|
|
/* trailing commas are okay */
|
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_LOOP)
|
|
|
|
eina_strbuf_append(disk->mount_cmd, "loop,");
|
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_UTF8)
|
|
|
|
eina_strbuf_append(disk->mount_cmd, "utf8,");
|
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_NOEXEC)
|
|
|
|
eina_strbuf_append(disk->mount_cmd, "noexec,");
|
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_NOSUID)
|
|
|
|
eina_strbuf_append(disk->mount_cmd, "nosuid,");
|
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_REMOUNT)
|
|
|
|
eina_strbuf_append(disk->mount_cmd, "remount,");
|
2011-05-15 17:06:41 -07:00
|
|
|
if (disk->mount_opts & EEZE_DISK_MOUNTOPT_UID)
|
|
|
|
eina_strbuf_append_printf(disk->mount_cmd, "uid=%i,", (int)disk->uid);
|
2011-02-09 13:31:11 -08:00
|
|
|
eina_strbuf_append_printf(disk->mount_cmd, " UUID=%s %s", disk->cache.uuid, disk->mount_point);
|
|
|
|
}
|
2011-01-28 20:21:53 -08:00
|
|
|
disk->mount_cmd_changed = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
INF("Mounting: %s", eina_strbuf_string_get(disk->mount_cmd));
|
2011-05-15 16:50:06 -07:00
|
|
|
disk->mounter = ecore_exe_run(eina_strbuf_string_get(disk->mount_cmd), disk);
|
2011-01-28 20:21:53 -08:00
|
|
|
if (!disk->mounter)
|
|
|
|
return EINA_FALSE;
|
2011-02-13 17:47:37 -08:00
|
|
|
eeze_events = eina_list_append(eeze_events, disk);
|
2011-01-28 20:21:53 -08:00
|
|
|
disk->mount_status = EEZE_DISK_MOUNTING;
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
eeze_disk_unmount(Eeze_Disk *disk)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
|
|
|
|
if (!eeze_disk_libmount_mounted_get(disk))
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
if (!disk->unmount_cmd)
|
|
|
|
disk->unmount_cmd = eina_strbuf_new();
|
|
|
|
|
|
|
|
if (disk->unmount_cmd_changed)
|
|
|
|
{
|
|
|
|
eina_strbuf_string_free(disk->unmount_cmd);
|
2011-05-15 16:54:30 -07:00
|
|
|
if (disk->mount_wrapper)
|
|
|
|
eina_strbuf_append_printf(disk->unmount_cmd, "%s ", disk->mount_wrapper);
|
|
|
|
eina_strbuf_append_printf(disk->unmount_cmd, EEZE_UNMOUNT_BIN" %s", disk->mount_point);
|
2011-01-28 20:21:53 -08:00
|
|
|
disk->unmount_cmd_changed = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
INF("Unmounting: %s", eina_strbuf_string_get(disk->unmount_cmd));
|
2011-05-15 16:54:30 -07:00
|
|
|
disk->mounter = ecore_exe_run(eina_strbuf_string_get(disk->unmount_cmd), disk);
|
2011-01-28 20:21:53 -08:00
|
|
|
if (!disk->mounter)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
2011-02-13 17:47:37 -08:00
|
|
|
eeze_events = eina_list_append(eeze_events, disk);
|
2011-01-28 20:21:53 -08:00
|
|
|
disk->mount_status = EEZE_DISK_UNMOUNTING;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI const char *
|
|
|
|
eeze_disk_mount_point_get(Eeze_Disk *disk)
|
|
|
|
{
|
|
|
|
const char *mp;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, NULL);
|
|
|
|
|
|
|
|
if (disk->mount_point)
|
|
|
|
return disk->mount_point;
|
|
|
|
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_devpath(eeze_disk_devpath_get(disk));
|
|
|
|
if (mp)
|
|
|
|
{
|
|
|
|
disk->mount_point = eina_stringshare_add(mp);
|
|
|
|
return disk->mount_point;
|
|
|
|
}
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_uuid(eeze_disk_uuid_get(disk));
|
|
|
|
if (mp)
|
|
|
|
{
|
|
|
|
disk->mount_point = eina_stringshare_add(mp);
|
|
|
|
return disk->mount_point;
|
|
|
|
}
|
|
|
|
mp = eeze_disk_libmount_mp_lookup_by_label(eeze_disk_label_get(disk));
|
|
|
|
if (mp)
|
|
|
|
{
|
|
|
|
disk->mount_point = eina_stringshare_add(mp);
|
|
|
|
return disk->mount_point;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI Eina_Bool
|
|
|
|
eeze_disk_mount_point_set(Eeze_Disk *disk, const char *mount_point)
|
|
|
|
{
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN_VAL(disk, EINA_FALSE);
|
|
|
|
|
2011-02-10 19:14:00 -08:00
|
|
|
eina_stringshare_replace(&disk->mount_point, mount_point);
|
2011-01-28 20:21:53 -08:00
|
|
|
disk->mount_cmd_changed = EINA_TRUE;
|
|
|
|
disk->unmount_cmd_changed = EINA_TRUE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|