SVN revision: 74326devs/devilhorns/wayland_egl
parent
a32308d4e8
commit
7914a063ea
6 changed files with 532 additions and 5 deletions
@ -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 <Ecore.h> |
||||
#include <Eeze.h> |
||||
#include <Eeze_Disk.h> |
||||
#include <libmount.h> |
||||
#include <unistd.h> |
||||
|
||||
#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; |
||||
} |
Loading…
Reference in new issue