Add a new EXPERIMENTAL systemd backend

This commit is contained in:
Davide Andreoli 2021-04-22 07:58:40 +02:00
parent 0293a50c05
commit 182b9bbd82
6 changed files with 557 additions and 9 deletions

View File

@ -49,13 +49,20 @@ if get_option('mount') == true
endif
#### Experimental eeze support ####
#### EXPERIMENTAL eeze support ####
if get_option('eeze') == true
dependency('eeze', required: true)
config_h.set('PLACES_HAVE_EEZE', 1)
endif
#### EXPERIMENTAL systemd support ####
if get_option('systemd') == true
dependency('systemd', required: true,)
config_h.set('PLACES_HAVE_SYSTEMD', 1)
endif
#### i18n ####
dep_intl = []
if get_option('nls')
@ -100,6 +107,8 @@ if meson.version().version_compare('>=0.53')
summary({'udisks2': get_option('udisks2'),
'udisks1': get_option('udisks'),
'mount': get_option('mount'),
'eeze': get_option('eeze'),
}, section: 'Backends', bool_yn: true)
}, section: 'Backends', bool_yn: true)
summary({'eeze': get_option('eeze'),
'systemd': get_option('systemd'),
}, section: 'Experimental Backends', bool_yn: true)
endif

View File

@ -1,3 +1,5 @@
# Backends
option('udisks2',
type: 'boolean',
value: true,
@ -5,16 +7,24 @@ option('udisks2',
option('udisks',
type: 'boolean',
value: false,
description: 'enable udisks1 support (default=false)')
description: 'enable deprecated udisks1 support (default=false)')
option('mount',
type: 'boolean',
value: true,
description: 'enable fstab/mtab support (default=true)')
option('eeze',
type: 'boolean',
value: false,
description: 'enable experimental eeze support (default=false)')
# Localization
option('nls',
type: 'boolean',
value: true,
description: 'enable localization (default=true)')
# Experimental (NOT FULLY WORKING) backends
option('eeze',
type: 'boolean',
value: false,
description: 'enable EXPERIMENTAL eeze support (default=false)')
option('systemd',
type: 'boolean',
value: false,
description: 'enable EXPERIMENTAL systemd support (default=false)')

View File

@ -4,6 +4,11 @@
#include "e_mod_main.h"
#include "e_mod_places.h"
#ifdef PLACES_HAVE_SYSTEMD
# include "e_mod_systemd.h"
#endif
#ifdef PLACES_HAVE_EEZE
# include "e_mod_eeze.h"
#endif
@ -65,6 +70,9 @@ places_init(void)
printf("PLACES: Init\n");
#ifdef PLACES_HAVE_SYSTEMD
places_systemd_init();
#endif
#ifdef PLACES_HAVE_EEZE
places_eeze_init();
#endif
@ -119,6 +127,9 @@ places_shutdown(void)
while (volumes)
places_volume_del((Volume*)volumes->data);
#ifdef PLACES_HAVE_SYSTEMD
places_systemd_shutdown();
#endif
#ifdef PLACES_HAVE_EEZE
places_eeze_shutdown();
#endif
@ -276,7 +287,7 @@ places_volume_update(Volume *vol)
Evas_Object *obj;
Eina_List *l;
if (eina_streq(vol->fstype, "nfs") ||
if (eina_str_has_prefix(vol->fstype, "nfs") || // nfs, nfs3, nfs4, etc..
eina_streq(vol->fstype, "cifs"))
vol->remote = EINA_TRUE;
else

510
src/e_mod_systemd.c Normal file
View File

@ -0,0 +1,510 @@
#include "places_config.h"
#ifdef PLACES_HAVE_SYSTEMD
#include <e.h>
#include <Eldbus.h>
#include "e_mod_main.h"
#include "e_mod_places.h"
/*
NOTE
- I remoti li vede solo con opzione "auto" in fstab !!!!
*/
/* Systemd defines */
#define SYSTEMD_BUS "org.freedesktop.systemd1"
#define SYSTEMD_PATH "/org/freedesktop/systemd1"
#define SYSTEMD_MANAGER_IFACE "org.freedesktop.systemd1.Manager"
#define SYSTEMD_UNIT_IFACE "org.freedesktop.systemd1.Unit"
#define SYSTEMD_MOUNT_IFACE "org.freedesktop.systemd1.Mount"
/* Local backend data */
typedef struct Places_Systemd_Backend_Data
{
Eldbus_Object *unit_obj;
} Places_Systemd_Backend_Data;
/* Local Function Prototypes */
static void _places_sd_name_start(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending);
static void _places_sd_list_units_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending);
static void _places_sd_unit_new_cb(void *data, const Eldbus_Message *msg);
static void _places_sd_unit_removed_cb(void *data, const Eldbus_Message *msg);
static void _places_sd_mount_props_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending);
static void _places_sd_unit_props_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending);
static void _places_sd_mount_props_changed_cb(void *data, const Eldbus_Message *msg);
static void _places_sd_read_unit_properties(Volume *vol, const char *iface, Eldbus_Message_Iter *props);
static Volume* _places_sd_volume_add(const char *obj_path, Eina_Bool first_time);
static void _places_sd_volume_finalize(Volume *vol);
static void _places_sd_mount_func(Volume *vol, Eina_List *opts);
static void _places_sd_unmount_func(Volume *vol, Eina_List *opts);
static void _places_sd_eject_func(Volume *vol, Eina_List *opts);
static void _places_sd_volume_free_func(Volume *vol);
/* Local Variables */
static Eldbus_Connection *_places_sd_conn = NULL;
static Eldbus_Object *_places_sd_manager = NULL;
Eina_Bool
places_systemd_init(void)
{
printf("PLACES: systemd: init()\n");
EINA_SAFETY_ON_FALSE_RETURN_VAL(eldbus_init(), EINA_FALSE);
_places_sd_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
// _places_sd_conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION);
if (!_places_sd_conn)
{
printf("PLACES: systemd: Error connecting to system bus.\n");
return EINA_FALSE;
}
eldbus_name_start(_places_sd_conn, SYSTEMD_BUS, 0,
_places_sd_name_start, NULL);
return EINA_TRUE;
}
void
places_systemd_shutdown(void)
{
printf("PLACES: systemd: shutdown()\n");
E_FREE_FUNC(_places_sd_manager, eldbus_object_unref);
E_FREE_FUNC(_places_sd_conn, eldbus_connection_unref);
eldbus_shutdown();
}
/* The service is up and running, setup the Manager object */
static void
_places_sd_name_start(void *data, const Eldbus_Message *msg,
Eldbus_Pending *pending)
{
Eldbus_Proxy *proxy;
Eldbus_Message *meth;
Eldbus_Message_Iter *iter, *array;
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
printf("PLACES: systemd Up and running\n");
// get the systemd Manager object
_places_sd_manager = eldbus_object_get(_places_sd_conn, SYSTEMD_BUS, SYSTEMD_PATH);
proxy = eldbus_proxy_get(_places_sd_manager, SYSTEMD_MANAGER_IFACE);
// NOTE: proxy will be automatically deleted on obj deletion
// call the ListUnitsByPatterns(as states, as patterns) on the Manager object
meth = eldbus_proxy_method_call_new(proxy, "ListUnitsByPatterns");
iter = eldbus_message_iter_get(meth);
eldbus_message_iter_arguments_append(iter, "as", &array);
eldbus_message_iter_container_close(iter, array);
eldbus_message_iter_arguments_append(iter, "as", &array);
eldbus_message_iter_basic_append(array, 's', "*.mount");
// eldbus_message_iter_basic_append(array, 's', "*.device");
eldbus_message_iter_container_close(iter, array);
eldbus_proxy_send(proxy, meth, _places_sd_list_units_cb, NULL, -1);
// connect the Manager UnitNew / UnitRemoved signal handlers
eldbus_proxy_signal_handler_add(proxy, "UnitNew",
_places_sd_unit_new_cb, NULL);
eldbus_proxy_signal_handler_add(proxy, "UnitRemoved",
_places_sd_unit_removed_cb, NULL);
}
/* Callback for the Manager method: ListUnitsByPatterns() */
static void
_places_sd_list_units_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
{
Eldbus_Message_Iter *units, *unit;
const char *name, *label;
const char *load_state, *active_state, *sub_state;
const char *followed, *obj_path;
const char *job_type, *job_obj_path;
unsigned int job_id;
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
EINA_SAFETY_ON_FALSE_RETURN(
eldbus_message_arguments_get(msg, "a(ssssssouso)", &units)
);
printf("PLACES: ListUnits\n");
while (eldbus_message_iter_get_and_next(units, 'r', &unit))
{
if (eldbus_message_iter_arguments_get(unit, "ssssssouso",
&name, &label,
&load_state, &active_state, &sub_state,
&followed,
&obj_path,
&job_id,&job_type, &job_obj_path))
{
printf("******* %s\n", obj_path);
printf(" name: %s\n", name);
printf(" label: %s\n", label);
printf(" load_state: %s\n", load_state);
printf(" active_state: %s\n", active_state);
printf(" sub_state: %s\n", sub_state);
printf(" followed: %s\n", followed);
printf(" job_id: %d\n", job_id);
printf(" job_type: %s\n", job_type);
printf(" job_obj_path: %s\n", job_obj_path);
_places_sd_volume_add(obj_path, EINA_TRUE);
}
}
}
/* Callback for the Manager signal 'UnitNew' */
static void
_places_sd_unit_new_cb(void *data, const Eldbus_Message *msg)
{
const char *id, *obj_path;
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_arguments_get(msg, "so", &id, &obj_path));
// printf("PLACES: UnitNew(%s, %s)\n", id, obj_path);
if (eina_str_has_suffix(id, ".mount") ||
eina_str_has_suffix(id, ".device"))
{
printf("PLACES: UnitNew(%s, %s)\n", id, obj_path);
if (eina_str_has_suffix(id, ".mount"))
{
_places_sd_volume_add(obj_path, EINA_FALSE);
}
}
}
/* Callback for the Manager signal 'UnitRemoved' */
static void
_places_sd_unit_removed_cb(void *data, const Eldbus_Message *msg)
{
const char *id, *obj_path;
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
EINA_SAFETY_ON_FALSE_RETURN(eldbus_message_arguments_get(msg, "so", &id, &obj_path));
// printf("PLACES: UnitRemoved(%s, %s)\n", id, obj_path);
if (eina_str_has_suffix(id, ".mount") ||
eina_str_has_suffix(id, ".device"))
printf("PLACES: UnitRemoved(%s, %s)\n", id, obj_path);
// TODO
}
static Volume*
_places_sd_volume_add(const char *obj_path, Eina_Bool first_time)
{
Places_Systemd_Backend_Data *bdata;
Volume *vol;
// return a previously created Volume
vol = places_volume_by_id_get(obj_path);
if (vol) return vol;
// create the backend data struct
bdata = E_NEW(Places_Systemd_Backend_Data, 1);
if (!bdata) return NULL;
// create the Eldbus object for this unit
bdata->unit_obj = eldbus_object_get(_places_sd_conn, SYSTEMD_BUS, obj_path);
if (!bdata->unit_obj) return NULL;
// create the places Volume
vol = places_volume_add(obj_path, first_time);
if (!vol) return NULL;
vol->backend_data = bdata;
vol->mount_func = _places_sd_mount_func;
vol->unmount_func = _places_sd_unmount_func;
vol->eject_func = _places_sd_eject_func;
vol->free_func = _places_sd_volume_free_func;
// request all the properties for the Mount & Unit ifaces
Eldbus_Proxy *proxy;
proxy = eldbus_proxy_get(bdata->unit_obj, SYSTEMD_MOUNT_IFACE);
eldbus_proxy_property_get_all(proxy, _places_sd_mount_props_all_cb, vol);
proxy = eldbus_proxy_get(bdata->unit_obj, SYSTEMD_UNIT_IFACE);
eldbus_proxy_property_get_all(proxy, _places_sd_unit_props_all_cb, vol);
// Get notifications on object properties change
eldbus_object_signal_handler_add(bdata->unit_obj,
ELDBUS_FDO_INTERFACE_PROPERTIES,
"PropertiesChanged",
_places_sd_mount_props_changed_cb, vol);
return vol;
}
static void
_places_sd_volume_free_func(Volume *vol)
{
Places_Systemd_Backend_Data *bdata = vol->backend_data;
if (bdata)
{
E_FREE_FUNC(bdata->unit_obj, eldbus_object_unref);
E_FREE(vol->backend_data);
}
}
/* Callback for ALL properties of the Mount iface */
static void
_places_sd_mount_props_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
{
Volume *vol = data;
Eldbus_Message_Iter *props;
EINA_SAFETY_ON_NULL_RETURN(vol);
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
if (eldbus_message_arguments_get(msg, "a{sv}", &props))
{
printf("PLACES: ALL Mount props for: %s\n", vol->id);
_places_sd_read_unit_properties(vol, SYSTEMD_MOUNT_IFACE, props);
}
}
/* Callback for ALL properties of the Unit iface */
static void
_places_sd_unit_props_all_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
{
Volume *vol = data;
Eldbus_Message_Iter *props;
EINA_SAFETY_ON_NULL_RETURN(vol);
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
if (eldbus_message_arguments_get(msg, "a{sv}", &props))
{
printf("PLACES: ALL Unit props for: %s\n", vol->id);
_places_sd_read_unit_properties(vol, SYSTEMD_UNIT_IFACE, props);
}
}
/* Callback for DBUS signal "PropertiesChanged" on the unit objects */
static void
_places_sd_mount_props_changed_cb(void *data, const Eldbus_Message *msg)
{
Volume *vol = data;
Eldbus_Message_Iter *changed_props, *invalidated_props;
const char *iface;
EINA_SAFETY_ON_NULL_RETURN(vol);
EINA_SAFETY_ON_TRUE_RETURN(eldbus_message_error_get(msg, NULL, NULL));
if (eldbus_message_arguments_get(msg, "sa{sv}as", &iface,
&changed_props, &invalidated_props))
{
printf("PLACES: PropertiesChanged obj:%s - iface:%s\n", vol->id, iface);
_places_sd_read_unit_properties(vol, iface, changed_props);
}
}
/* Read the properties for a .mount object (Mount & Unit ifaces)*/
static void
_places_sd_read_unit_properties(Volume *vol, const char *iface, Eldbus_Message_Iter *props)
{
Eldbus_Message_Iter *entry, *var;
const char *key, *str_val;
unsigned int changed = 0;
Eina_Bool is_mount_iface = eina_streq(iface, SYSTEMD_MOUNT_IFACE);
Eina_Bool is_unit_iface = eina_streq(iface, SYSTEMD_UNIT_IFACE);
// NOTE props must be a{sv}
EINA_SAFETY_ON_NULL_RETURN(vol);
EINA_SAFETY_ON_NULL_RETURN(props);
printf("PLACES: Properties obj:%s - iface:%s\n", vol->id, iface);
// collect usefull props iterating over the dict
while (eldbus_message_iter_get_and_next(props, 'e', &entry))
{
if (!eldbus_message_iter_arguments_get(entry, "sv", &key, &var))
continue;
// printf(" prop: %s\n", key);
if (is_mount_iface)
{
if (eina_streq(key, "Where"))
{
eldbus_message_iter_arguments_get(var, "s", &str_val);
if (eina_stringshare_replace(&vol->mount_point, str_val))
changed++;
}
else if (eina_streq(key, "What"))
{
eldbus_message_iter_arguments_get(var, "s", &str_val);
if (eina_stringshare_replace(&vol->device, str_val))
changed++;
}
else if (eina_streq(key, "Type"))
{
eldbus_message_iter_arguments_get(var, "s", &str_val);
if (eina_stringshare_replace(&vol->fstype, str_val))
changed++;
}
// Mount.ExecMount
// Mount.ExecRemount
// Mount.ExecUnmount
}
else if (is_unit_iface)
{
if (eina_streq(key, "SubState"))
{
eldbus_message_iter_arguments_get(var, "s", &str_val);
if (eina_streq(str_val, "mounted"))
{
if (!vol->mounted)
{
vol->mounted = EINA_TRUE;
changed++;
}
}
else
{
if (vol->mounted)
{
vol->mounted = EINA_FALSE;
changed++;
}
}
}
// Unit.CanStart bool
// Unit.CanStop bool
}
}
if (changed)
_places_sd_volume_finalize(vol);
}
/* Called after all properties has been readed */
static void
_places_sd_volume_finalize(Volume *vol)
{
Eina_Bool is_valid = EINA_FALSE;
printf("PLACES: Validating %s\n", vol->id);
// TODO array of know types
if (eina_streq(vol->fstype, "ext4") ||
eina_streq(vol->fstype, "vfat") ||
eina_streq(vol->fstype, "nfs") ||
eina_streq(vol->fstype, "nfs3") ||
eina_streq(vol->fstype, "nfs4") ||
eina_streq(vol->fstype, "ntfs") ||
eina_streq(vol->fstype, "cifs"))
is_valid = EINA_TRUE;
else
is_valid = EINA_FALSE;
// choose a label
if (vol->mount_point && vol->mount_point[0])
eina_stringshare_replace(&vol->label, vol->mount_point);
else if (vol->device && vol->device[0])
eina_stringshare_replace(&vol->label, vol->device);
// the update is always needed to trigger auto_mount/auto_open
places_volume_update(vol);
if (is_valid != vol->valid)
{
// trigger a full redraw, is the only way to show/hide a new device
vol->valid = is_valid;
places_update_all_gadgets();
}
places_print_volume(vol); // TODO REMOVE ME
}
/* Callback for mount(), umont() and eject() calls */
static void
_places_sd_task_cb(void *data, const Eldbus_Message *msg, Eldbus_Pending *pending)
{
const char *str;
Eina_Bool ret;
if (eldbus_message_error_get(msg, NULL, NULL))
{
ret = eldbus_message_arguments_get(msg, "s", &str);
e_util_dialog_internal(D_("Operation failed"),
ret ? str : D_("Unknown error"));
}
}
static void
_places_sd_mount_func(Volume *vol, Eina_List *opts)
{
Places_Systemd_Backend_Data *bdata = vol->backend_data;
Eldbus_Message *msg;
EINA_SAFETY_ON_FALSE_RETURN((bdata && bdata->unit_obj));
printf("PLACES: systemd Mount %s\n", vol->id);
// Call the Start(s mode) method on the Unit iface
msg = eldbus_object_method_call_new(bdata->unit_obj,
SYSTEMD_UNIT_IFACE, "Start");
eldbus_message_arguments_append(msg, "s", "replace");
eldbus_object_send(bdata->unit_obj, msg, _places_sd_task_cb, vol, -1);
}
static void
_places_sd_unmount_func(Volume *vol, Eina_List *opts)
{
Places_Systemd_Backend_Data *bdata = vol->backend_data;
Eldbus_Message *msg;
EINA_SAFETY_ON_FALSE_RETURN((bdata && bdata->unit_obj));
printf("PLACES: systemd Unmount %s\n", vol->id);
// Call the Stop(s mode) method on the Unit iface
msg = eldbus_object_method_call_new(bdata->unit_obj,
SYSTEMD_UNIT_IFACE, "Stop");
eldbus_message_arguments_append(msg, "s", "replace");
eldbus_object_send(bdata->unit_obj, msg, _places_sd_task_cb, vol, -1);
}
static void
_places_sd_eject_func(Volume *vol, Eina_List *opts)
{
// Places_Systemd_Backend_Data *bdata = vol->backend_data;
printf("PLACES: TODO systemd Eject %s\n", vol->id);
}
#endif

7
src/e_mod_systemd.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef E_MOD_PLACES_SYSTEMD_H
#define E_MOD_PLACES_SYSTEMD_H
void places_systemd_init(void);
void places_systemd_shutdown(void);
#endif

View File

@ -9,6 +9,7 @@ module = shared_module(
'e_mod_udisks_eldbus.c',
'e_mod_mount.c',
'e_mod_eeze.c',
'e_mod_systemd.c',
dependencies : [dep_e, dep_intl],
install_dir: lib_install_dir,