forked from enlightenment/efl
464 lines
13 KiB
C
464 lines
13 KiB
C
#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__)
|
|
|
|
#ifndef O_BINARY
|
|
# define O_BINARY 0
|
|
#endif
|
|
|
|
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 EINA_UNUSED, int type EINA_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 EINA_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 EINA_UNUSED, size_t size EINA_UNUSED, void *user_data EINA_UNUSED)
|
|
{
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
static Eina_Bool
|
|
cl_add(void *data EINA_UNUSED, int type EINA_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_add(clients, &ev->client, ec);
|
|
cl_setup(ev->client, ec);
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
cl_del(void *data EINA_UNUSED, int type EINA_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)
|
|
{
|
|
eina_hash_del_by_data(clients, &ec);
|
|
eet_connection_close(ec, &d);
|
|
}
|
|
|
|
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 | O_BINARY);
|
|
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 EINA_UNUSED, Eeze_Udev_Watch *watch EINA_UNUSED)
|
|
{
|
|
Eina_List *l;
|
|
Eeze_Scanner_Device *dev;
|
|
|
|
DBG("device='%s'", device);
|
|
|
|
if (ev == EEZE_UDEV_EVENT_ONLINE) ev = EEZE_UDEV_EVENT_ADD;
|
|
else if (ev == EEZE_UDEV_EVENT_OFFLINE) ev = EEZE_UDEV_EVENT_REMOVE;
|
|
|
|
event_send(device, (Eeze_Scanner_Event_Type)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 EINA_UNUSED, Eeze_Udev_Watch *watch EINA_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, (Eeze_Scanner_Event_Type)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));
|
|
if (!dev) return;
|
|
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, (Eeze_Scanner_Event_Type)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;
|
|
|
|
memset(&s, 0, sizeof(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)
|
|
{
|
|
int ret;
|
|
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);
|
|
ret = 1;
|
|
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);
|
|
ret = 2;
|
|
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(ret);
|
|
}
|