diff --git a/legacy/eeze/ChangeLog b/legacy/eeze/ChangeLog index 6166e07746..029dbef1e4 100644 --- a/legacy/eeze/ChangeLog +++ b/legacy/eeze/ChangeLog @@ -105,3 +105,8 @@ * Add a check in event monitoring for disks which ensures that device changes for loopback devices are picked up + +2012-07-23 Mike Blumenkrantz + + * Add yet another libmount backend for eeze_disk to handle current + setups which do not have mtab and instead use /proc/self/mountinfo diff --git a/legacy/eeze/NEWS b/legacy/eeze/NEWS index 23d7195335..b953461a7c 100644 --- a/legacy/eeze/NEWS +++ b/legacy/eeze/NEWS @@ -1,11 +1,12 @@ -Eeze 1.3.0 +Eeze 1.7.0 -Changes since Eeze 1.1.0: +Changes since Eeze 1.2.0: ------------------------- Additions: * Joystick support + * Support for mtab-less systems Changes since Eeze 1.1.0: ------------------------- diff --git a/legacy/eeze/configure.ac b/legacy/eeze/configure.ac index 1056f36d95..ae3fe69887 100644 --- a/legacy/eeze/configure.ac +++ b/legacy/eeze/configure.ac @@ -147,12 +147,13 @@ if test "x$eeze_mount" = "xyes";then fi if test -n "$mount_v";then AM_CONDITIONAL([OLD_LIBMOUNT], [test "$(echo $mount_v | cut -d'.' -f2)" -lt 19]) + AM_CONDITIONAL([NEW_LIBMOUNT], [test "$(echo $mount_v | cut -d'.' -f2)" -gt 19]) else AM_CONDITIONAL([OLD_LIBMOUNT], [false]) fi -if test -z "$OLD_LIBMOUNT_TRUE" ; then - AC_DEFINE_UNQUOTED([OLD_LIBMOUNT], [1], [using first version of libmount]) -fi +AM_COND_IF([OLD_LIBMOUNT], [ + AC_DEFINE_UNQUOTED([OLD_LIBMOUNT], [1], [using first version of libmount]) + ],[]) AC_CHECK_HEADERS([netinet/in.h]) want_ipv6="yes" diff --git a/legacy/eeze/src/lib/Makefile.am b/legacy/eeze/src/lib/Makefile.am index eb3a18fac3..b14e44d401 100644 --- a/legacy/eeze/src/lib/Makefile.am +++ b/legacy/eeze/src/lib/Makefile.am @@ -20,8 +20,12 @@ if HAVE_EEZE_MOUNT libeeze_la_SOURCES += eeze_disk.c eeze_disk_udev.c eeze_disk_mount.c eeze_disk_private.h if OLD_LIBMOUNT libeeze_la_SOURCES += eeze_disk_libmount_old.c +else +if NEW_LIBMOUNT + libeeze_la_SOURCES += eeze_disk_libmount_new.c else libeeze_la_SOURCES += eeze_disk_libmount.c +endif endif includes_HEADERS += Eeze_Disk.h else diff --git a/legacy/eeze/src/lib/eeze_disk_libmount_new.c b/legacy/eeze/src/lib/eeze_disk_libmount_new.c new file mode 100644 index 0000000000..f9c7e229eb --- /dev/null +++ b/legacy/eeze/src/lib/eeze_disk_libmount_new.c @@ -0,0 +1,515 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef USE_UNSTABLE_LIBMOUNT_API +# define USE_UNSTABLE_LIBMOUNT_API 1 +#endif + +#include +#include +#include +#include +#include + +#include "eeze_udev_private.h" +#include "eeze_disk_private.h" + +/* + * + * PRIVATE + * + */ + +static struct libmnt_optmap eeze_optmap[] = +{ + { "loop[=]", EEZE_DISK_MOUNTOPT_LOOP, 0 }, + { "utf8", EEZE_DISK_MOUNTOPT_UTF8, 0 }, + { "noexec", EEZE_DISK_MOUNTOPT_NOEXEC, 0 }, + { "nosuid", EEZE_DISK_MOUNTOPT_NOSUID, 0 }, + { "remount", EEZE_DISK_MOUNTOPT_REMOUNT, 0 }, + { "uid[=]", EEZE_DISK_MOUNTOPT_UID, 0 }, + { NULL, 0, 0 } +}; +typedef struct libmnt_table libmnt_table; +typedef struct libmnt_fs libmnt_fs; +typedef struct libmnt_cache libmnt_cache; +static Ecore_File_Monitor *_fstab_mon = NULL; +static Eina_Bool _watching = EINA_FALSE; +static Eina_Bool _fstab_scan_active = EINA_FALSE; +static libmnt_cache *_eeze_mount_mtab_cache = NULL; +static libmnt_cache *_eeze_mount_fstab_cache = NULL; +static libmnt_table *_eeze_mount_mtab = NULL; +static libmnt_table *_eeze_mount_fstab = NULL; +extern Eina_List *_eeze_disks; + +static Ecore_Fd_Handler *_mountinfo_fdh = NULL; +static FILE *_mountinfo = NULL; + +static libmnt_table *_eeze_mount_tab_parse(const char *filename); +static void _eeze_mount_tab_watcher(void *data, Ecore_File_Monitor *mon __UNUSED__, Ecore_File_Event event __UNUSED__, const char *path); + +static int +_eeze_mount_tab_parse_errcb(libmnt_table *tab __UNUSED__, const char *filename, int line) +{ + ERR("%s:%d: could not parse line!", filename, line); /* most worthless error reporting ever. */ + return -1; +} + +/* + * I could use mnt_new_table_from_file() but this way gives much more detailed output + * on failure so why not + */ +static libmnt_table * +_eeze_mount_tab_parse(const char *filename) +{ + libmnt_table *tab; + + if (!(tab = mnt_new_table())) return NULL; + if (mnt_table_set_parser_errcb(tab, _eeze_mount_tab_parse_errcb)) + { + ERR("Alloc!"); + mnt_free_table(tab); + return NULL; + } + + if (!mnt_table_parse_file(tab, filename)) + return tab; + + mnt_free_table(tab); + return NULL; +} + +static void +_eeze_mount_tab_watcher(void *data, Ecore_File_Monitor *mon __UNUSED__, Ecore_File_Event event __UNUSED__, const char *path) +{ + libmnt_table *bak; + + if (_fstab_scan_active) + /* prevent scans from triggering a scan */ + return; + + bak = _eeze_mount_mtab; + _eeze_mount_mtab = _eeze_mount_tab_parse(path); + if (!_eeze_mount_mtab) + { + ERR("Could not parse %s! keeping old tab...", path); + goto error; + } + + mnt_free_table(bak); + if (data) + { + mnt_free_cache(_eeze_mount_mtab_cache); + _eeze_mount_mtab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_mtab, _eeze_mount_mtab_cache); + } + else + { + mnt_free_cache(_eeze_mount_fstab_cache); + _eeze_mount_fstab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_fstab, _eeze_mount_fstab_cache); + } + return; + +error: + mnt_free_table(_eeze_mount_mtab); + _eeze_mount_mtab = bak; +} + +/* on tab change, check differences + * based on code from findmnt + */ +static Eina_Bool +_eeze_mount_fdh(void *d __UNUSED__, Ecore_Fd_Handler *fdh __UNUSED__) +{ + libmnt_table *tb_new; + libmnt_fs *old, *new; + int change; + struct libmnt_iter *itr = NULL; + struct libmnt_tabdiff *diff = NULL; + + tb_new = mnt_new_table(); + EINA_SAFETY_ON_NULL_RETURN_VAL(tb_new, ECORE_CALLBACK_RENEW); + EINA_SAFETY_ON_TRUE_GOTO(mnt_table_set_parser_errcb(tb_new, _eeze_mount_tab_parse_errcb), err); + itr = mnt_new_iter(MNT_ITER_BACKWARD); + EINA_SAFETY_ON_NULL_GOTO(itr, err); + diff = mnt_new_tabdiff(); + EINA_SAFETY_ON_NULL_GOTO(diff, err); + rewind(_mountinfo); + if (mnt_table_parse_stream(tb_new, _mountinfo, "/proc/self/mountinfo")) + { + ERR("PARSING FAILED FOR /proc/self/mountinfo! THIS IS WEIRD!"); + goto err; + } + change = mnt_diff_tables(diff, _eeze_mount_mtab, tb_new); + if (change < 0) + { + ERR("DIFFING FAILED FOR /proc/self/mountinfo! THIS IS ALSO WEIRD!"); + goto err; + } + if (!change) goto err; + while (!mnt_tabdiff_next_change(diff, itr, &old, &new, &change)) + { + const char *src; + Eeze_Disk *disk; + Eina_Bool found = EINA_FALSE; + Eeze_Event_Disk_Mount *e; + Eina_List *l; + + src = mnt_fs_get_source(new); + if (!src) continue; + EINA_LIST_FOREACH(_eeze_disks, l, disk) + { + if (!strcmp(src, eeze_disk_devpath_get(disk))) + { + found = EINA_TRUE; + break; + } + } + if (!found) continue; + switch (change) + { + case MNT_TABDIFF_MOUNT: + disk->mounted = EINA_TRUE; + eina_stringshare_replace(&disk->mount_point, mnt_fs_get_target(new)); + e = malloc(sizeof(Eeze_Event_Disk_Mount)); + if (e) + { + e->disk = disk; + ecore_event_add(EEZE_EVENT_DISK_MOUNT, e, NULL, NULL); + } + break; + case MNT_TABDIFF_UMOUNT: + if (!mnt_fs_get_target(new)) + disk->mounted = EINA_FALSE; + eina_stringshare_replace(&disk->mount_point, NULL); + e = malloc(sizeof(Eeze_Event_Disk_Mount)); + if (e) + { + e->disk = disk; + ecore_event_add(EEZE_EVENT_DISK_UNMOUNT, e, NULL, NULL); + } + break; + /* anything could have happened here, send both events to flush */ + case MNT_TABDIFF_REMOUNT: + case MNT_TABDIFF_MOVE: + if (!mnt_fs_get_target(new)) + disk->mounted = EINA_FALSE; + eina_stringshare_replace(&disk->mount_point, mnt_fs_get_target(new)); + e = malloc(sizeof(Eeze_Event_Disk_Mount)); + if (e) + { + e->disk = disk; + ecore_event_add(EEZE_EVENT_DISK_UNMOUNT, e, NULL, NULL); + } + e = malloc(sizeof(Eeze_Event_Disk_Mount)); + if (e) + { + e->disk = disk; + ecore_event_add(EEZE_EVENT_DISK_MOUNT, e, NULL, NULL); + } + default: + break; + } + } + + mnt_free_cache(_eeze_mount_mtab_cache); + _eeze_mount_mtab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_mtab, _eeze_mount_mtab_cache); + mnt_free_table(_eeze_mount_mtab); + _eeze_mount_mtab = tb_new; + return ECORE_CALLBACK_RENEW; +err: + if (tb_new) mnt_free_table(tb_new); + if (itr) mnt_free_iter(itr); + if (diff) mnt_free_tabdiff(diff); + return ECORE_CALLBACK_RENEW; +} + +/* + * + * INVISIBLE + * + */ + +Eina_Bool +eeze_libmount_init(void) +{ + /* placeholder */ + return EINA_TRUE; +} + +void +eeze_libmount_shutdown(void) +{ + if (_eeze_mount_fstab) + { + mnt_free_table(_eeze_mount_fstab); + mnt_free_cache(_eeze_mount_fstab_cache); + } + if (_eeze_mount_mtab) + { + mnt_free_table(_eeze_mount_mtab); + mnt_free_cache(_eeze_mount_mtab_cache); + } + eeze_mount_tabs_unwatch(); +} + +unsigned long +eeze_disk_libmount_opts_get(Eeze_Disk *disk) +{ + libmnt_fs *mnt; + const char *opts; + unsigned long f = 0; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return 0; + + mnt = mnt_table_find_tag(_eeze_mount_mtab, "UUID", eeze_disk_uuid_get(disk), MNT_ITER_BACKWARD); + if (!mnt) + mnt = mnt_table_find_tag(_eeze_mount_fstab, "UUID", eeze_disk_uuid_get(disk), MNT_ITER_BACKWARD); + + if (!mnt) return 0; + + opts = mnt_fs_get_fs_options(mnt); + if (!opts) return 0; + if (!mnt_optstr_get_flags(opts, &f, eeze_optmap)) return 0; + return f; +} + +/* + * helper function to return whether a disk is mounted + */ +Eina_Bool +eeze_disk_libmount_mounted_get(Eeze_Disk *disk) +{ + libmnt_fs *mnt; + + if (!disk) + return EINA_FALSE; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return EINA_FALSE; + + mnt = mnt_table_find_source(_eeze_mount_mtab, eeze_disk_devpath_get(disk), MNT_ITER_BACKWARD); + if (!mnt) + { + disk->mounted = EINA_FALSE; + return EINA_FALSE; + } + + eina_stringshare_replace(&disk->mount_point, mnt_fs_get_target(mnt)); + disk->mounted = EINA_TRUE; + return EINA_TRUE; +} + + +/* + * helper function to return the device that is mounted at a mount point + */ +const char * +eeze_disk_libmount_mp_find_source(const char *mount_point) +{ + libmnt_fs *mnt; + + if (!mount_point) + return NULL; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return NULL; + + mnt = mnt_table_find_target(_eeze_mount_mtab, mount_point, MNT_ITER_BACKWARD); + if (!mnt) + mnt = mnt_table_find_target(_eeze_mount_fstab, mount_point, MNT_ITER_BACKWARD); + + if (!mnt) + return NULL; + + return mnt_fs_get_source(mnt); +} + +/* + * helper function to return a mount point from a uuid + */ +const char * +eeze_disk_libmount_mp_lookup_by_uuid(const char *uuid) +{ + libmnt_fs *mnt; + + if (!uuid) + return NULL; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return NULL; + + mnt = mnt_table_find_tag(_eeze_mount_fstab, "UUID", uuid, MNT_ITER_BACKWARD); + + if (!mnt) + return NULL; + + return mnt_fs_get_target(mnt); +} + +/* + * helper function to return a mount point from a label + */ +const char * +eeze_disk_libmount_mp_lookup_by_label(const char *label) +{ + libmnt_fs *mnt; + + if (!label) + return NULL; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return NULL; + + mnt = mnt_table_find_tag(_eeze_mount_fstab, "LABEL", label, MNT_ITER_BACKWARD); + + if (!mnt) + return NULL; + + return mnt_fs_get_target(mnt); +} + +/* + * helper function to return a mount point from a /dev/ path + */ +const char * +eeze_disk_libmount_mp_lookup_by_devpath(const char *devpath) +{ + libmnt_fs *mnt; + + if (!devpath) + return NULL; + + if (!eeze_mount_mtab_scan() || !eeze_mount_fstab_scan()) + return NULL; + + mnt = mnt_table_find_srcpath(_eeze_mount_mtab, devpath, MNT_ITER_BACKWARD); + if (!mnt) + mnt = mnt_table_find_srcpath(_eeze_mount_fstab, devpath, MNT_ITER_BACKWARD); + + if (!mnt) + return NULL; + + return mnt_fs_get_target(mnt); +} + +/* + * + * API + * + */ + +EAPI Eina_Bool +eeze_mount_tabs_watch(void) +{ + libmnt_table *bak; + + if (_watching) + return EINA_TRUE; + + bak = _eeze_mount_tab_parse("/proc/self/mountinfo"); + EINA_SAFETY_ON_NULL_GOTO(bak, error); + + mnt_free_table(_eeze_mount_mtab); + _eeze_mount_mtab = bak; + bak = _eeze_mount_tab_parse("/etc/fstab"); + EINA_SAFETY_ON_NULL_GOTO(bak, error); + + mnt_free_table(_eeze_mount_fstab); + _eeze_mount_fstab = bak; + + _eeze_mount_mtab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_mtab, _eeze_mount_mtab_cache); + + _eeze_mount_fstab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_fstab, _eeze_mount_fstab_cache); + + _mountinfo = fopen("/proc/self/mountinfo", "r"); + if (!_mountinfo) goto error; + _mountinfo_fdh = ecore_main_fd_handler_add(fileno(_mountinfo), ECORE_FD_ERROR, _eeze_mount_fdh, NULL, NULL, NULL); + if (!_mountinfo_fdh) goto error; + _fstab_mon = ecore_file_monitor_add("/etc/fstab", _eeze_mount_tab_watcher, NULL); + _watching = EINA_TRUE; + + return EINA_TRUE; + +error: + if (_mountinfo) fclose(_mountinfo); + _mountinfo = NULL; + if (!_eeze_mount_mtab) + ERR("Could not parse /proc/self/mountinfo!"); + else + { + ERR("Could not parse /etc/fstab!"); + mnt_free_table(_eeze_mount_mtab); + } + _eeze_mount_mtab = _eeze_mount_fstab = NULL; + return EINA_FALSE; +} + +EAPI void +eeze_mount_tabs_unwatch(void) +{ + if (!_watching) + return; + + _mountinfo_fdh = ecore_main_fd_handler_del(_mountinfo_fdh); + ecore_file_monitor_del(_fstab_mon); + _fstab_mon = NULL; + _watching = EINA_FALSE; +} + +EAPI Eina_Bool +eeze_mount_mtab_scan(void) +{ + libmnt_table *bak; + + if (_watching) + return EINA_TRUE; + + bak = _eeze_mount_tab_parse("/proc/self/mountinfo"); + if (!bak) + goto error; + if (_eeze_mount_mtab) + { + mnt_free_table(_eeze_mount_mtab); + mnt_free_cache(_eeze_mount_mtab_cache); + } + _eeze_mount_mtab = bak; + _eeze_mount_mtab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_mtab, _eeze_mount_mtab_cache); + + return EINA_TRUE; + +error: + return EINA_FALSE; +} + +EAPI Eina_Bool +eeze_mount_fstab_scan(void) +{ + libmnt_table *bak; + if (_watching) + return EINA_TRUE; + + bak = _eeze_mount_tab_parse("/etc/fstab"); + if (!bak) + goto error; + if (_eeze_mount_fstab) + { + mnt_free_table(_eeze_mount_fstab); + mnt_free_cache(_eeze_mount_fstab_cache); + } + _eeze_mount_fstab = bak; + _eeze_mount_fstab_cache = mnt_new_cache(); + mnt_table_set_cache(_eeze_mount_fstab, _eeze_mount_fstab_cache); + + return EINA_TRUE; + +error: + return EINA_FALSE; +} diff --git a/legacy/eeze/src/lib/eeze_disk_mount.c b/legacy/eeze/src/lib/eeze_disk_mount.c index 5de67fb0f1..cbb57aed7c 100644 --- a/legacy/eeze/src/lib/eeze_disk_mount.c +++ b/legacy/eeze/src/lib/eeze_disk_mount.c @@ -79,6 +79,7 @@ _eeze_disk_mount_result_handler(void *data __UNUSED__, int type __UNUSED__, Ecor disk->mounter = NULL; if (!ev->exit_code) { + disk->mounted = EINA_TRUE; e = malloc(sizeof(Eeze_Event_Disk_Mount)); EINA_SAFETY_ON_NULL_RETURN_VAL(e, ECORE_CALLBACK_RENEW); e->disk = disk;