summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/Makefile.am49
-rw-r--r--src/bin/eeze_disk_ls.c53
-rw-r--r--src/bin/eeze_mount.c130
-rw-r--r--src/bin/eeze_scanner.c453
-rw-r--r--src/bin/eeze_scanner.h33
-rw-r--r--src/bin/eeze_udev_test.c238
-rw-r--r--src/bin/eeze_umount.c113
7 files changed, 1069 insertions, 0 deletions
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644
index 0000000..280006d
--- /dev/null
+++ b/src/bin/Makefile.am
@@ -0,0 +1,49 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+EEZE_CFLAGS = \
+-I$(top_srcdir)/src/lib \
+@EEZE_CFLAGS@
+
+noinst_PROGRAMS = @EEZE_UDEV_TEST_PRG@
+EXTRA_PROGRAMS = eeze_udev_test eeze_mount eeze_umount eeze_disk_ls eeze_scanner
+
+if HAVE_EEZE_MOUNT
+ DISK_PROGS = @EEZE_MOUNT_PRG@ @EEZE_UMOUNT_PRG@ @EEZE_DISK_LS_PRG@
+ SCAN_PROGS = @EEZE_SCANNER_PRG@
+else
+ DISK_PROGS =
+ SCAN_PROGS =
+endif
+
+bin_PROGRAMS = $(DISK_PROGS)
+util_PROGRAMS = $(SCAN_PROGS)
+utildir = $(bindir)
+
+eeze_udev_test_SOURCES = eeze_udev_test.c
+eeze_udev_test_CPPFLAGS = -I$(top_srcdir)/src/lib @EEZE_CFLAGS@
+eeze_udev_test_LDADD = $(top_builddir)/src/lib/libeeze.la @EEZE_LIBS@
+
+if HAVE_EEZE_MOUNT
+ eeze_mount_SOURCES = eeze_mount.c
+ eeze_mount_CFLAGS = -I$(top_srcdir)/src/lib $(EEZE_CFLAGS) @LIBMOUNT_CFLAGS@ @ECORE_FILE_CFLAGS@
+ eeze_mount_LDADD = $(top_builddir)/src/lib/libeeze.la @LIBMOUNT_LIBS@ @ECORE_FILE_LIBS@ @EEZE_LIBS@
+
+ eeze_umount_SOURCES = eeze_umount.c
+ eeze_umount_CFLAGS = -I$(top_srcdir)/src/lib $(EEZE_CFLAGS) @LIBMOUNT_CFLAGS@ @ECORE_FILE_CFLAGS@
+ eeze_umount_LDADD = $(top_builddir)/src/lib/libeeze.la @LIBMOUNT_LIBS@ @ECORE_FILE_LIBS@ @EEZE_LIBS@
+
+ eeze_disk_ls_SOURCES = eeze_disk_ls.c
+ eeze_disk_ls_CFLAGS = -I$(top_srcdir)/src/lib $(EEZE_CFLAGS) @LIBMOUNT_CFLAGS@ @ECORE_FILE_CFLAGS@
+ eeze_disk_ls_LDADD = $(top_builddir)/src/lib/libeeze.la @LIBMOUNT_LIBS@ @ECORE_FILE_LIBS@ @EEZE_LIBS@
+
+ eeze_scanner_SOURCES = eeze_scanner.c
+ eeze_scanner_CFLAGS = -I$(top_srcdir)/src/lib $(EEZE_CFLAGS) @LIBMOUNT_CFLAGS@ @ECORE_FILE_CFLAGS@ @ECORE_CON_CFLAGS@ @EET_CFLAGS@
+ eeze_scanner_LDADD = $(top_builddir)/src/lib/libeeze.la @LIBMOUNT_LIBS@ @ECORE_FILE_LIBS@ @ECORE_CON_LIBS@ @EET_LIBS@ @EEZE_LIBS@
+ includesdir = $(includedir)/eeze-@VMAJ@
+ includes_HEADERS = eeze_scanner.h
+
+setuid_root_mode = a=rx,u+xs
+install-data-hook:
+ @chmod $(setuid_root_mode) $(DESTDIR)$(bindir)/eeze_scanner$(EXEEXT) || true
+
+endif
diff --git a/src/bin/eeze_disk_ls.c b/src/bin/eeze_disk_ls.c
new file mode 100644
index 0000000..46c4006
--- /dev/null
+++ b/src/bin/eeze_disk_ls.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <Ecore.h>
+#include <Eeze.h>
+#include <Eeze_Disk.h>
+
+/* simple app to print disks and their mount points */
+
+int
+main(void)
+{
+ Eina_List *disks;
+ const char *syspath;
+
+ eeze_init();
+ eeze_disk_function();
+
+ disks = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, NULL);
+ printf("Found the following mountable disks:\n");
+ EINA_LIST_FREE(disks, syspath)
+ {
+ Eeze_Disk *disk;
+
+ disk = eeze_disk_new(syspath);
+ printf("\t%s - %s:%s\n", syspath, eeze_disk_devpath_get(disk), eeze_disk_mount_point_get(disk));
+ eeze_disk_free(disk);
+ eina_stringshare_del(syspath);
+ }
+
+ disks = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_REMOVABLE, NULL);
+ printf("Found the following removable drives:\n");
+ EINA_LIST_FREE(disks, syspath)
+ {
+ Eeze_Disk *disk;
+
+ disk = eeze_disk_new(syspath);
+ printf("\t%s - %s:%s\n", syspath, eeze_disk_devpath_get(disk), eeze_disk_mount_point_get(disk));
+ eeze_disk_free(disk);
+ eina_stringshare_del(syspath);
+ }
+
+ disks = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_INTERNAL, NULL);
+ printf("Found the following internal drives:\n");
+ EINA_LIST_FREE(disks, syspath)
+ {
+ Eeze_Disk *disk;
+
+ disk = eeze_disk_new(syspath);
+ printf("\t%s - %s\n", syspath, eeze_disk_devpath_get(disk));
+ eeze_disk_free(disk);
+ eina_stringshare_del(syspath);
+ }
+ return 0;
+}
diff --git a/src/bin/eeze_mount.c b/src/bin/eeze_mount.c
new file mode 100644
index 0000000..1f1c561
--- /dev/null
+++ b/src/bin/eeze_mount.c
@@ -0,0 +1,130 @@
+#include <Eeze.h>
+#include <Eeze_Disk.h>
+#include <Ecore.h>
+#include <Ecore_File.h>
+#include <Ecore_Getopt.h>
+#include <stdio.h>
+
+/** This app can be used as a "dumb" replacement for mount. Just don't try anything fancy yet! */
+static const Ecore_Getopt opts =
+{
+ "eeze_mount",
+ "eeze_mount /dev/sdb1 /media/disk",
+ "1.0",
+ "(C) 2010 Mike Blumenkrantz",
+ "LGPL",
+ "Mount a disk using either its /sys/ path or its /dev/ path\n\n",
+ 1,
+ {
+ ECORE_GETOPT_STORE_TRUE('v', "verbose", "Enable debug output"),
+ ECORE_GETOPT_VERSION('V', "version"),
+ ECORE_GETOPT_COPYRIGHT('R', "copyright"),
+ ECORE_GETOPT_LICENSE('L', "license"),
+ ECORE_GETOPT_HELP('h', "help"),
+ ECORE_GETOPT_SENTINEL
+ }
+};
+
+void
+_mount_cb(void *data, int type, Eeze_Event_Disk_Mount *e)
+{
+ (void)data;
+ (void)type;
+ printf("Success!\n");
+ eeze_disk_free(e->disk);
+ ecore_main_loop_quit();
+}
+
+void
+_error_cb(void *data, int type, Eeze_Event_Disk_Error *de)
+{
+ (void)data;
+ (void)type;
+ printf("Could not mount disk with /dev/ path: %s!\n", eeze_disk_devpath_get(de->disk));
+ eeze_disk_free(de->disk);
+ ecore_main_loop_quit();
+}
+
+int
+main(int argc, char *argv[])
+{
+ int args;
+ const char *dev, *mount_point = NULL;
+ Eina_Bool verbose = EINA_FALSE, exit_option = EINA_FALSE;
+ Eeze_Disk *disk;
+
+ Ecore_Getopt_Value values[] =
+ {
+ ECORE_GETOPT_VALUE_BOOL(verbose),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option)
+ };
+
+ if (argc < 2)
+ {
+ printf("Insufficient args specified!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+
+ ecore_init();
+ eeze_init();
+ ecore_app_args_set(argc, (const char **)argv);
+ args = ecore_getopt_parse(&opts, values, argc, argv);
+
+ if (exit_option)
+ return 0;
+
+ if (args < 0)
+ {
+ printf("No args specified!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+ if (verbose) eina_log_domain_level_set("eeze_disk", EINA_LOG_LEVEL_DBG);
+ dev = argv[args];
+ if (args + 1 < argc)
+ mount_point = argv[args + 1];
+ if ((!strncmp(dev, "/sys/", 5)) || (!strncmp(dev, "/dev/", 5)))
+ disk = eeze_disk_new(dev);
+ else if ((args == argc - 1) && (ecore_file_is_dir(dev)))
+ disk = eeze_disk_new_from_mount(dev);
+ else
+ {
+ printf("[Device] must be either a /dev/ path or a /sys/ path!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+ if (eeze_disk_mounted_get(disk))
+ {
+ printf("[%s] is already mounted!", dev);
+ exit(1);
+ }
+ if (argc - args > 1)
+ {
+ eeze_disk_mount_point_set(disk, mount_point);
+ if (eina_str_has_extension(dev, "iso"))
+ {
+ int f;
+ f = eeze_disk_mountopts_get(disk);
+ eeze_disk_mountopts_set(disk, f | EEZE_DISK_MOUNTOPT_LOOP);
+ }
+ }
+ ecore_event_handler_add(EEZE_EVENT_DISK_MOUNT, (Ecore_Event_Handler_Cb)_mount_cb, NULL);
+ ecore_event_handler_add(EEZE_EVENT_DISK_ERROR, (Ecore_Event_Handler_Cb)_error_cb, NULL);
+ eeze_disk_mountopts_get(disk);
+ if (!eeze_disk_mount(disk))
+ {
+ const char *mp;
+
+ mp = eeze_disk_mount_point_get(disk);
+ if (!mp) fprintf(stderr, "No mount point passed!\n");
+ else fprintf(stderr, "Mount operation could not be started!\n");
+ exit(1);
+ }
+ ecore_main_loop_begin();
+
+ return 0;
+}
diff --git a/src/bin/eeze_scanner.c b/src/bin/eeze_scanner.c
new file mode 100644
index 0000000..2acd736
--- /dev/null
+++ b/src/bin/eeze_scanner.c
@@ -0,0 +1,453 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Eet.h>
+#include <Eeze.h>
+#include <Ecore_Con.h>
+#include <Eeze_Disk.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "eeze_scanner.h"
+
+#define DBG(...) EINA_LOG_DOM_DBG(es_log_dom, __VA_ARGS__)
+#define INF(...) EINA_LOG_DOM_INFO(es_log_dom, __VA_ARGS__)
+#define WRN(...) EINA_LOG_DOM_WARN(es_log_dom, __VA_ARGS__)
+#define ERR(...) EINA_LOG_DOM_ERR(es_log_dom, __VA_ARGS__)
+#define CRI(...) EINA_LOG_DOM_CRIT(es_log_dom, __VA_ARGS__)
+
+static int es_log_dom = -1;
+static Ecore_Con_Server *svr = NULL;
+static Eet_Data_Descriptor *es_edd = NULL;
+static Eina_Hash *clients = NULL;
+
+static Eina_List *storage_devices = NULL;
+static Eina_List *storage_cdrom = NULL;
+
+static Eina_List *volume_cdrom = NULL;
+static Eina_List *volume_devices = NULL;
+
+static void
+event_send(const char *device, Eeze_Scanner_Event_Type type, Eina_Bool volume)
+{
+ Eeze_Scanner_Event ev;
+ const Eina_List *l;
+ Ecore_Con_Client *cl;
+
+ ev.device = device;
+ ev.type = type;
+ ev.volume = volume;
+ EINA_LIST_FOREACH(ecore_con_server_clients_get(svr), l, cl)
+ {
+ Eet_Connection *ec;
+
+ ec = eina_hash_find(clients, cl);
+ if (!ec) continue;
+ INF("Serializing event...");
+ eet_connection_send(ec, es_edd, &ev, NULL);
+ }
+}
+
+static Eina_Bool
+event_write(const void *data, size_t size, Ecore_Con_Client *cl)
+{
+ INF("Event sent!");
+ ecore_con_client_send(cl, data, size);
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+disk_mount(void *data __UNUSED__, int type __UNUSED__, Eeze_Disk *disk)
+{
+ Eina_List *l;
+ Eeze_Scanner_Device *d;
+ if (eeze_disk_type_get(disk) != EEZE_DISK_TYPE_CDROM) return ECORE_CALLBACK_RENEW;
+
+ EINA_LIST_FOREACH(storage_cdrom, l, d)
+ {
+ if (d->device == eeze_disk_syspath_get(disk))
+ {
+ d->mounted = !d->mounted;
+ break;
+ }
+ }
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+cl_setup(Ecore_Con_Client *cl __UNUSED__, Eet_Connection *ec)
+{
+ Eina_List *l;
+ Eeze_Scanner_Device *dev;
+ Eeze_Scanner_Event ev;
+ const char *sys;
+
+ INF("Sending initial events to new client");
+ EINA_LIST_FOREACH(storage_devices, l, sys)
+ {
+ ev.device = sys;
+ ev.type = EEZE_SCANNER_EVENT_TYPE_ADD;
+ ev.volume = EINA_FALSE;
+ eet_connection_send(ec, es_edd, &ev, NULL);
+ }
+ EINA_LIST_FOREACH(storage_cdrom, l, dev)
+ {
+ ev.device = dev->device;
+ ev.type = EEZE_SCANNER_EVENT_TYPE_ADD;
+ ev.volume = EINA_FALSE;
+ eet_connection_send(ec, es_edd, &ev, NULL);
+ }
+ EINA_LIST_FOREACH(volume_devices, l, sys)
+ {
+ ev.device = sys;
+ ev.type = EEZE_SCANNER_EVENT_TYPE_ADD;
+ ev.volume = EINA_TRUE;
+ eet_connection_send(ec, es_edd, &ev, NULL);
+ }
+ EINA_LIST_FOREACH(volume_cdrom, l, dev)
+ {
+ ev.device = dev->device;
+ ev.type = EEZE_SCANNER_EVENT_TYPE_ADD;
+ ev.volume = EINA_TRUE;
+ eet_connection_send(ec, es_edd, &ev, NULL);
+ }
+}
+
+static Eina_Bool
+es_read(const void *eet_data __UNUSED__, size_t size __UNUSED__, void *user_data __UNUSED__)
+{
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+cl_add(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Client_Add *ev)
+{
+ Eet_Connection *ec;
+ INF("Added client");
+
+ ec = eet_connection_new(es_read, (Eet_Write_Cb*)event_write, ev->client);
+ if (!ec)
+ {
+ ERR("Could not create eet serializer! Lost client!");
+ ecore_con_client_del(ev->client);
+ return ECORE_CALLBACK_RENEW;
+ }
+
+ eina_hash_direct_add(clients, ev->client, ec);
+ cl_setup(ev->client, ec);
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool
+cl_del(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Client_Del *ev)
+{
+ Eet_Connection *ec;
+ Eina_Bool d;
+ INF("Removed client");
+ ec = eina_hash_find(clients, ev->client);
+ if (ec)
+ {
+ eet_connection_close(ec, &d);
+ eina_hash_del_by_data(clients, ec);
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+eet_setup(void)
+{
+ Eet_Data_Descriptor_Class eddc;
+
+ if (!eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc), "eeze_scanner_event", sizeof(Eeze_Scanner_Event)))
+ {
+ CRI("Could not create eet data descriptor!");
+ exit(1);
+ }
+
+ es_edd = eet_data_descriptor_stream_new(&eddc);
+#define DAT(MEMBER, TYPE) EET_DATA_DESCRIPTOR_ADD_BASIC(es_edd, Eeze_Scanner_Event, #MEMBER, MEMBER, EET_T_##TYPE)
+ DAT(device, INLINED_STRING);
+ DAT(type, UINT);
+ DAT(volume, UCHAR);
+#undef DAT
+}
+
+static Eina_Bool
+cdrom_timer(Eeze_Scanner_Device *dev)
+{
+ const char *devpath;
+ int fd;
+
+ /* cdrom already mounted, no need to poll */
+ if (dev->mounted) return EINA_TRUE;
+ devpath = eeze_udev_syspath_get_devpath(dev->device);
+ fd = open(devpath, O_RDONLY);
+ if (fd < 0)
+ {
+ Eina_List *l;
+
+ l = eina_list_data_find_list(volume_cdrom, dev);
+ if (l)
+ {
+ /* disc removed, delete volume */
+ INF("Removed cdrom '%s'", dev->device);
+ volume_cdrom = eina_list_remove_list(volume_cdrom, l);
+ event_send(dev->device, EEZE_SCANNER_EVENT_TYPE_CHANGE, EINA_TRUE);
+ }
+ /* just in case */
+ dev->mounted = EINA_FALSE;
+ }
+ else
+ {
+ if (!eina_list_data_find(volume_cdrom, dev))
+ {
+ INF("Added cdrom '%s'", dev->device);
+ volume_cdrom = eina_list_append(volume_cdrom, dev);
+ event_send(dev->device, EEZE_SCANNER_EVENT_TYPE_CHANGE, EINA_TRUE);
+ }
+ close(fd);
+ }
+ eina_stringshare_del(devpath);
+ return EINA_TRUE;
+}
+
+static void
+storage_setup(void)
+{
+ Eina_List *l, *ll;
+ const char *sys;
+
+ storage_devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_INTERNAL, NULL);
+ if (!storage_devices)
+ {
+ ERR("No storage devices found! This is not supposed to happen!");
+ exit(1);
+ }
+ EINA_LIST_FOREACH(storage_devices, l, sys)
+ event_send(sys, EEZE_SCANNER_EVENT_TYPE_ADD, EINA_FALSE);
+
+ ll = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_REMOVABLE, NULL);
+ EINA_LIST_FREE(ll, sys)
+ {
+ event_send(sys, EEZE_SCANNER_EVENT_TYPE_ADD, EINA_FALSE);
+ storage_devices = eina_list_append(storage_devices, sys);
+ }
+
+ l = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_CDROM, NULL);
+ EINA_LIST_FREE(l, sys)
+ {
+ Eeze_Scanner_Device *dev;
+ Eeze_Disk *disk;
+
+ dev = calloc(1, sizeof(Eeze_Scanner_Device));
+ if (!dev)
+ {
+ ERR("Lost cdrom device '%s'!", sys);
+ eina_stringshare_del(sys);
+ continue;
+ }
+ disk = eeze_disk_new(sys);
+ if (!disk)
+ {
+ ERR("Lost cdrom device '%s'!", sys);
+ eina_stringshare_del(sys);
+ free(dev);
+ continue;
+ }
+ dev->device = sys;
+ dev->mounted = eeze_disk_mounted_get(disk);
+ eeze_disk_free(disk);
+ event_send(sys, EEZE_SCANNER_EVENT_TYPE_ADD, EINA_FALSE);
+ dev->poller = ecore_poller_add(ECORE_POLLER_CORE, 32, (Ecore_Task_Cb)cdrom_timer, dev);
+ storage_cdrom = eina_list_append(storage_cdrom, dev);
+ }
+ volume_devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, NULL);
+ EINA_LIST_FOREACH_SAFE(volume_devices, l, ll, sys)
+ {
+ Eina_List *c;
+ Eeze_Scanner_Device *dev;
+
+ EINA_LIST_FOREACH(storage_cdrom, c, dev)
+ if (sys == dev->device)
+ {
+ eina_stringshare_del(sys);
+ volume_devices = eina_list_remove_list(volume_devices, l);
+ volume_cdrom = eina_list_append(volume_cdrom, dev);
+ event_send(sys, EEZE_SCANNER_EVENT_TYPE_ADD, EINA_TRUE);
+ l = NULL;
+ break;
+ }
+ if (!l) continue;
+ event_send(sys, EEZE_SCANNER_EVENT_TYPE_ADD, EINA_TRUE);
+ }
+}
+
+static void
+cb_vol_chg(const char *device, Eeze_Udev_Event ev, void *data __UNUSED__, Eeze_Udev_Watch *watch __UNUSED__)
+{
+ Eina_List *l;
+ Eeze_Scanner_Device *dev;
+
+ DBG("device='%s'", device);
+
+ if (ev == EEZE_UDEV_EVENT_ONLINE) ev = EEZE_SCANNER_EVENT_TYPE_ADD;
+ else if (ev == EEZE_UDEV_EVENT_OFFLINE) ev = EEZE_SCANNER_EVENT_TYPE_REMOVE;
+
+ event_send(device, ev, EINA_TRUE);
+ switch (ev)
+ {
+ case EEZE_UDEV_EVENT_ADD:
+ case EEZE_UDEV_EVENT_ONLINE:
+ INF("Added volume '%s'", device);
+ EINA_LIST_FOREACH(storage_cdrom, l, dev)
+ if (device == dev->device)
+ {
+ volume_cdrom = eina_list_append(volume_cdrom, dev);
+ return;
+ }
+ volume_devices = eina_list_append(volume_devices, eina_stringshare_add(device));
+ break;
+ case EEZE_UDEV_EVENT_REMOVE:
+ case EEZE_UDEV_EVENT_OFFLINE:
+ INF("Removed volume '%s'", device);
+ EINA_LIST_FOREACH(volume_cdrom, l, dev)
+ if (device == dev->device)
+ {
+ volume_cdrom = eina_list_remove_list(volume_cdrom, l);
+ return;
+ }
+ volume_devices = eina_list_remove(volume_devices, device);
+ eina_stringshare_del(device);
+ break;
+ default:
+ INF("Changed volume '%s'", device);
+ break;
+ }
+}
+
+static void
+cb_stor_chg(const char *device, Eeze_Udev_Event ev, void *data __UNUSED__, Eeze_Udev_Watch *watch __UNUSED__)
+{
+ Eina_List *l;
+ Eeze_Scanner_Device *dev = NULL;
+ const char *str;
+
+
+ DBG("device='%s'", device);
+ switch (ev)
+ {
+ case EEZE_UDEV_EVENT_ADD:
+ case EEZE_UDEV_EVENT_ONLINE:
+ INF("Added device '%s'", device);
+ event_send(device, ev, EINA_FALSE);
+ str = eeze_udev_syspath_get_property(device, "ID_CDROM");
+ if (!str)
+ {
+ storage_devices = eina_list_append(storage_devices, eina_stringshare_add(device));
+ return;
+ }
+ eina_stringshare_del(str);
+ dev = calloc(1, sizeof(Eeze_Scanner_Device));
+ dev->device = eina_stringshare_add(device);
+ dev->poller = ecore_poller_add(ECORE_POLLER_CORE, 32,
+ (Ecore_Task_Cb)cdrom_timer, dev);
+ storage_cdrom = eina_list_append(storage_cdrom, dev);
+ break;
+ case EEZE_UDEV_EVENT_REMOVE:
+ case EEZE_UDEV_EVENT_OFFLINE:
+ if (!eina_list_data_find(storage_devices, device))
+ {
+ EINA_LIST_FOREACH(storage_cdrom, l, dev)
+ if (dev->device == device) break;
+ if ((!dev) || (dev->device != device)) return;
+ }
+ INF("Removed device '%s'", device);
+ event_send(device, ev, EINA_FALSE);
+ EINA_LIST_FOREACH(storage_cdrom, l, dev)
+ if (device == dev->device)
+ {
+ if (dev->poller) ecore_poller_del(dev->poller);
+ storage_cdrom = eina_list_remove_list(storage_cdrom, l);
+ eina_stringshare_del(dev->device);
+ free(dev);
+ return;
+ }
+ storage_devices = eina_list_remove(storage_devices, device);
+ eina_stringshare_del(device);
+ break;
+ default:
+ INF("Changed device '%s'", device);
+ break;
+ }
+}
+
+static void
+es_exit(int sig)
+{
+ ecore_con_server_del(svr);
+ exit(sig);
+}
+
+static void
+sigs_setup(void)
+{
+ sigset_t sigs = {{0}};
+ struct sigaction s;
+
+ sigfillset(&sigs);
+ sigdelset(&sigs, SIGSEGV);
+ sigdelset(&sigs, SIGTERM);
+ sigdelset(&sigs, SIGINT);
+ sigdelset(&sigs, SIGQUIT);
+
+ s.sa_handler = es_exit;
+ s.sa_flags = 0;
+ sigaction(SIGTERM, &s, NULL);
+ sigaction(SIGSEGV, &s, NULL);
+ sigaction(SIGINT, &s, NULL);
+}
+
+int
+main(void)
+{
+ eina_init();
+ ecore_init();
+ ecore_con_init();
+ eeze_init();
+ eeze_disk_function();
+ eeze_mount_tabs_watch();
+
+ sigs_setup();
+ es_log_dom = eina_log_domain_register("eeze_scanner", EINA_COLOR_CYAN);
+
+ eet_setup();
+ clients = eina_hash_pointer_new(NULL);
+ EINA_SAFETY_ON_NULL_GOTO(clients, error);
+
+ ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)cl_add, NULL);
+ ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb)cl_del, NULL);
+ ecore_event_handler_add(EEZE_EVENT_DISK_UNMOUNT, (Ecore_Event_Handler_Cb)disk_mount, NULL);
+ ecore_event_handler_add(EEZE_EVENT_DISK_MOUNT, (Ecore_Event_Handler_Cb)disk_mount, NULL);
+
+ eeze_udev_watch_add(EEZE_UDEV_TYPE_DRIVE_INTERNAL, EEZE_UDEV_EVENT_NONE, cb_stor_chg, NULL);
+ eeze_udev_watch_add(EEZE_UDEV_TYPE_DRIVE_REMOVABLE, EEZE_UDEV_EVENT_NONE, cb_stor_chg, NULL);
+ eeze_udev_watch_add(EEZE_UDEV_TYPE_DRIVE_CDROM, EEZE_UDEV_EVENT_NONE, cb_stor_chg, NULL);
+ eeze_udev_watch_add(EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, EEZE_UDEV_EVENT_NONE, cb_vol_chg, NULL);
+
+ svr = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM, "eeze_scanner", 0, NULL);
+ EINA_SAFETY_ON_NULL_GOTO(svr, error);
+
+ storage_setup();
+ ecore_main_loop_begin();
+
+ ecore_con_server_del(svr);
+ return 0;
+error:
+ ERR("Could not start up!");
+ exit(1);
+}
diff --git a/src/bin/eeze_scanner.h b/src/bin/eeze_scanner.h
new file mode 100644
index 0000000..a975793
--- /dev/null
+++ b/src/bin/eeze_scanner.h
@@ -0,0 +1,33 @@
+#ifndef EEZE_SCANNER_H
+#define EEZE_SCANNER_H
+
+#include <Eeze.h>
+
+#define EEZE_SCANNER_EDD_SETUP(edd) \
+ EET_DATA_DESCRIPTOR_ADD_BASIC((edd), Eeze_Scanner_Event, "device", device, EET_T_INLINED_STRING); \
+ EET_DATA_DESCRIPTOR_ADD_BASIC((edd), Eeze_Scanner_Event, "type", type, EET_T_UINT); \
+ EET_DATA_DESCRIPTOR_ADD_BASIC((edd), Eeze_Scanner_Event, "volume", volume, EET_T_UCHAR)
+
+typedef enum
+{
+ EEZE_SCANNER_EVENT_TYPE_NONE,
+ EEZE_SCANNER_EVENT_TYPE_ADD = EEZE_UDEV_EVENT_ADD,
+ EEZE_SCANNER_EVENT_TYPE_REMOVE = EEZE_UDEV_EVENT_REMOVE,
+ EEZE_SCANNER_EVENT_TYPE_CHANGE = EEZE_UDEV_EVENT_CHANGE
+} Eeze_Scanner_Event_Type;
+
+typedef struct
+{
+ const char *device;
+ Eeze_Scanner_Event_Type type;
+ Eina_Bool volume;
+} Eeze_Scanner_Event;
+
+typedef struct
+{
+ Ecore_Poller *poller;
+ const char *device;
+ Eina_Bool mounted;
+} Eeze_Scanner_Device;
+
+#endif
diff --git a/src/bin/eeze_udev_test.c b/src/bin/eeze_udev_test.c
new file mode 100644
index 0000000..130771a
--- /dev/null
+++ b/src/bin/eeze_udev_test.c
@@ -0,0 +1,238 @@
+#include <Eeze.h>
+#include <Ecore.h>
+#include <stdio.h>
+
+/**
+ * This demo program shows how to use some eeze_udev functions. It roughly
+ * 1kb as of now, TODO is to fix this but I'm too lazy now and it's only
+ * a demo.
+ */
+
+typedef struct kbdmouse
+{
+ Eina_List *kbds;
+ Eina_List *mice;
+ Eina_Hash *hash;
+} kbdmouse;
+
+static void
+/* event will always be a syspath starting with /sys */
+catch_events(const char *device,
+ Eeze_Udev_Event event,
+ void *data,
+ Eeze_Udev_Watch *watch)
+{
+ kbdmouse *akbdmouse = data;
+ Eina_List *l;
+ const char *name, *dev, *type;
+
+ /* the device that comes through will be prefixed by "/sys"
+ * but the saved name will not, so we check for the saved name
+ * inside the device name
+ */
+ EINA_LIST_FOREACH(akbdmouse->kbds, l, name)
+ if (!strncmp(device + 5, name, strlen(device + 5) - 8)) goto end;
+ EINA_LIST_FOREACH(akbdmouse->mice, l, name)
+ if (!strncmp(device + 5, name, strlen(device + 5) - 8)) goto end;
+
+ /* check to see if the device was just plugged in */
+ if (eeze_udev_syspath_is_kbd(device) || eeze_udev_syspath_is_mouse(device))
+ goto end;
+ /* if we reach here, the device is neither a keyboard nor a mouse that we saw
+ * previously, so we print a moderately amusing message and bail
+ */
+ printf("Sneaky sneaky! But %s is not a keyboard or a mouse!!\n", device);
+ return;
+
+end:
+ /* we stored the devpaths for all the syspaths previously so that
+ * we can retrieve them now even though the device has been removed and
+ * is inaccessible to udev
+ */
+ if ((event & EEZE_UDEV_EVENT_ADD) == EEZE_UDEV_EVENT_ADD)
+ {
+ dev = eeze_udev_syspath_get_devpath(device);
+ type = "plugged in";
+ }
+ else
+ {
+ dev = eina_hash_find(akbdmouse->hash, name);
+ type = "unplugged";
+ }
+ printf("You %s %s!\n", type, dev);
+ printf("All tests completed, exiting successfully!\n");
+ /* and the hash */
+ eina_hash_free(akbdmouse->hash);
+ /* now we free the lists */
+ eina_list_free(akbdmouse->kbds);
+ eina_list_free(akbdmouse->mice);
+ /* and the random storage struct */
+ free(akbdmouse);
+ /* and delete the watch */
+ eeze_udev_watch_del(watch);
+ /* and shut down eudev */
+ eeze_shutdown();
+ /* and quit the main loop */
+ ecore_main_loop_quit();
+}
+
+static void
+hash_free(void *data)
+{
+ eina_stringshare_del(data);
+}
+
+int
+main()
+{
+ Eina_List *type, *l;
+ const char *name, *check, *check2;
+ kbdmouse *akbdmouse;
+ Eina_Hash *hash;
+
+ ecore_init();
+ eeze_init();
+
+ hash = eina_hash_stringshared_new(hash_free);
+ akbdmouse = malloc(sizeof(kbdmouse));
+ akbdmouse->hash = hash;
+
+ printf("For my first trick, I will find all of your keyboards and return their syspaths.\n");
+ /* find all keyboards using type EEZE_UDEV_TYPE_KEYBOARD */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_KEYBOARD, NULL);
+ /* add all "link" devices that aren't explicitly found, but are still
+ * part of the device chain
+ */
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FOREACH(type, l, name)
+ {
+ /* add the devpath to the hash for use in the cb later */
+ if ((check = eeze_udev_syspath_get_devpath(name)))
+ eina_hash_direct_add(hash, name, check);
+ printf("Found keyboard: %s\n", name);
+ }
+ /* we save this list for later, because once a device is unplugged it can
+ * no longer be detected by udev, and any related properties are unusable unless
+ * they have been previously stored
+ */
+ akbdmouse->kbds = type;
+
+ printf("\nNext, I will find all of your mice and print the corresponding manufacturer.\n");
+ /* find all mice using type EEZE_UDEV_TYPE_MOUSE */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_MOUSE, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FOREACH(type, l, name)
+ { /* add the devpath to the hash for use in the cb later */
+ if ((check = eeze_udev_syspath_get_devpath(name)))
+ eina_hash_direct_add(hash, name, check); /* get a property using the device's syspath */
+ printf("Found mouse %s with vendor: %s\n", name, eeze_udev_walk_get_sysattr(name, "manufacturer"));
+ }
+ /* we save this list for later, because once a device is unplugged it can
+ * no longer be detected by udev, and any related properties are unusable unless
+ * they have been previously stored
+ */
+ akbdmouse->mice = type;
+
+ printf("\nNow let's try something a little more difficult. Mountable filesystems!\n");
+ /* find all mountable drives using type EEZE_UDEV_TYPE_DRIVE_MOUNTABLE */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_MOUNTABLE, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FREE(type, name)
+ {
+ printf("Found device: %s\n", name); /* get a property using the device's syspath */
+ if ((check = eeze_udev_syspath_get_property(name, "DEVNAME")))
+ {
+ printf("\tYou probably know it better as %s\n", check);
+ eina_stringshare_del(check);
+ }
+ if ((check = eeze_udev_syspath_get_property(name, "ID_FS_TYPE")))
+ {
+ printf("\tIt's formatted as %s", check);
+ eina_stringshare_del(check);
+ check = eeze_udev_syspath_get_property(name, "FSTAB_DIR");
+ if (check)
+ {
+ printf(", and gets mounted at %s", check);
+ eina_stringshare_del(check);
+ }
+ printf("!\n");
+ }
+ eina_stringshare_del(name);
+ }
+
+ printf("\nNetwork devices!\n");
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_NET, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FREE(type, name)
+ {
+ printf("Found device: %s\n", name); /* get a property using the device's syspath */
+ if ((check = eeze_udev_syspath_get_property(name, "INTERFACE")))
+ {
+ printf("\tYou probably know it better as %s\n", check);
+ eina_stringshare_del(check);
+ }
+ eina_stringshare_del(name);
+ }
+
+ printf("\nInternal drives, anyone? With serial numbers?\n");
+ /* find all internal drives using type EEZE_UDEV_TYPE_DRIVE_INTERNAL */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_INTERNAL, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FREE(type, name) /* get a property using the device's syspath */
+ {
+ if ((check = eeze_udev_syspath_get_property(name, "ID_SERIAL")))
+ {
+ printf("%s: %s\n", name, check);
+ eina_stringshare_del(check);
+ }
+ eina_stringshare_del(name);
+ }
+
+ printf("\nGot any removables? I'm gonna find em!\n");
+ /* find all removable media using type EEZE_UDEV_TYPE_DRIVE_REMOVABLE */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_DRIVE_REMOVABLE, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FREE(type, name) /* get a property using the device's syspath */
+ {
+ if ((check = eeze_udev_syspath_get_sysattr(name, "model")))
+ {
+ check2 = eeze_udev_syspath_get_subsystem(name);
+ printf("\tOoh, a %s attached to the %s subsytem!\n", check, check2);
+ eina_stringshare_del(check);
+ eina_stringshare_del(check2);
+ }
+ eina_stringshare_del(name);
+ }
+
+ printf("\nGot any v4l device ?\n");
+ /* find all V4L device, may be a webcam or anything that can get a video
+ * stream from the real worl in a numerical form */
+ type = eeze_udev_find_by_type(EEZE_UDEV_TYPE_V4L, NULL);
+ type = eeze_udev_find_unlisted_similar(type);
+ EINA_LIST_FREE(type, name) /* get a device name using the device's syspath */
+ {
+ if ((check = eeze_udev_syspath_get_property(name, "DEVNAME")))
+ {
+ if ((check2 = eeze_udev_syspath_get_sysattr(name, "name")))
+ {
+ printf("%s: '%s' [%s]\n", name, check2, check);
+ eina_stringshare_del(check2);
+ }
+ eina_stringshare_del(check);
+ }
+ eina_stringshare_del(name);
+ }
+
+ /* set a udev watch, grab all events because no EEZE_UDEV_TYPE filter is specified,
+ * set the events to be sent to callback function catch_events(), and attach
+ * kbdmouse to the watch as associated data
+ */
+ eeze_udev_watch_add(EEZE_UDEV_TYPE_NONE, (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE), catch_events, akbdmouse);
+ printf("\nAnd now for something more complicated. Plug or unplug your keyboard or mouse for me.\n");
+
+ /* main loop must be started to use ecore fd polling */
+ ecore_main_loop_begin();
+
+ return 0;
+}
+
diff --git a/src/bin/eeze_umount.c b/src/bin/eeze_umount.c
new file mode 100644
index 0000000..75d5ebb
--- /dev/null
+++ b/src/bin/eeze_umount.c
@@ -0,0 +1,113 @@
+#include <Eeze.h>
+#include <Eeze_Disk.h>
+#include <Ecore.h>
+#include <Ecore_File.h>
+#include <Ecore_Getopt.h>
+#include <stdio.h>
+
+/** This app can be used as a "dumb" replacement for unmount. Just don't try anything fancy yet! */
+static const Ecore_Getopt opts =
+{
+ "eeze_unmount",
+ "eeze_unmount /dev/sdb1 /media/disk",
+ "1.0",
+ "(C) 2010 Mike Blumenkrantz",
+ "LGPL",
+ "unmount a disk using either its /sys/ path or its /dev/ path\n\n",
+ 1,
+ {
+ ECORE_GETOPT_STORE_TRUE('v', "verbose", "Enable debug output"),
+ ECORE_GETOPT_VERSION('V', "version"),
+ ECORE_GETOPT_COPYRIGHT('R', "copyright"),
+ ECORE_GETOPT_LICENSE('L', "license"),
+ ECORE_GETOPT_HELP('h', "help"),
+ ECORE_GETOPT_SENTINEL
+ }
+};
+
+void
+_unmount_cb(void *data, int type, Eeze_Event_Disk_Unmount *e)
+{
+ (void)data;
+ (void)type;
+ printf("Success!\n");
+ eeze_disk_free(e->disk);
+ ecore_main_loop_quit();
+}
+
+void
+_error_cb(void *data, int type, Eeze_Event_Disk_Error *de)
+{
+ (void)data;
+ (void)type;
+ printf("Could not unmount disk with /dev/ path: %s!\n", eeze_disk_devpath_get(de->disk));
+ eeze_disk_free(de->disk);
+ ecore_main_loop_quit();
+}
+
+int
+main(int argc, char *argv[])
+{
+ int args;
+ const char *dev;
+ Eina_Bool verbose = EINA_FALSE, exit_option = EINA_FALSE;
+ Eeze_Disk *disk;
+
+ Ecore_Getopt_Value values[] =
+ {
+ ECORE_GETOPT_VALUE_BOOL(verbose),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option),
+ ECORE_GETOPT_VALUE_BOOL(exit_option)
+ };
+
+ if (argc < 2)
+ {
+ printf("Insufficient args specified!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+
+ ecore_init();
+ eeze_init();
+ ecore_app_args_set(argc, (const char **)argv);
+ args = ecore_getopt_parse(&opts, values, argc, argv);
+
+ if (exit_option)
+ return 0;
+
+ if (args < 0)
+ {
+ printf("No args specified!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+ if (verbose) eina_log_domain_level_set("eeze_disk", EINA_LOG_LEVEL_DBG);
+ dev = argv[args];
+ if ((!strncmp(dev, "/sys/", 5)) || (!strncmp(dev, "/dev/", 5)))
+ disk = eeze_disk_new(dev);
+ else if ((args == argc - 1) && (ecore_file_is_dir(dev)))
+ disk = eeze_disk_new_from_mount(dev);
+ else
+ {
+ printf("[Device] must be either a /dev/ path or a /sys/ path!\n");
+ ecore_getopt_help(stderr, &opts);
+ exit(1);
+ }
+ if (!eeze_disk_mounted_get(disk))
+ {
+ printf("[%s] is already unmounted!", dev);
+ exit(1);
+ }
+ ecore_event_handler_add(EEZE_EVENT_DISK_UNMOUNT, (Ecore_Event_Handler_Cb)_unmount_cb, NULL);
+ ecore_event_handler_add(EEZE_EVENT_DISK_ERROR, (Ecore_Event_Handler_Cb)_error_cb, NULL);
+ if (!eeze_disk_unmount(disk))
+ {
+ printf("unmount operation could not be started!\n");
+ exit(1);
+ }
+ ecore_main_loop_begin();
+
+ return 0;
+}