Commit 6d42a047 authored by David Zeuthen's avatar David Zeuthen

refine file monitoring interface and implement policy reload

parent 01b261ee
......@@ -56,49 +56,98 @@
struct PolKitContext
{
int refcount;
PolKitContextConfigChangedCB config_changed_cb;
gpointer config_changed_user_data;
PolKitContextFileMonitorAddWatch file_monitor_add_watch_func;
PolKitContextFileMonitorRemoveWatch file_monitor_remove_watch_func;
char *priv_dir;
PolKitPrivilegeCache *priv_cache;
};
/**
* libpolkit_context_new:
* @error: return location for error
*
* Create a new context; loads PolicyKit files from
* /etc/PolicyKit/privileges unless the environment variable
* $POLKIT_PRIVILEGE_DIR points to a location.
*
* If the environment $POLKIT_DEBUG is set, libpolkit will spew lots
* of debug.
* Create a new context
*
* Returns: #NULL if @error was set, otherwise the #PolKitPrivilegeCache object
* Returns: the #PolKitPrivilegeCache object
**/
PolKitContext *
libpolkit_context_new (GError **error)
libpolkit_context_new (void)
{
const char *dirname;
PolKitContext *pk_context;
pk_context = g_new0 (PolKitContext, 1);
pk_context->refcount = 1;
return pk_context;
}
static void
_privilege_dir_events (PolKitContext *pk_context,
PolKitContextFileMonitorEvent event_mask,
const char *path,
gpointer user_data)
{
/* mark cache of privilege files as stale.. (will be populated on-demand, see _get_cache()) */
if (pk_context->priv_cache != NULL) {
_pk_debug ("Something happened in %s - invalidating cache", pk_context->priv_dir);
libpolkit_privilege_cache_unref (pk_context->priv_cache);
pk_context->priv_cache = NULL;
}
/* signal that our configuration (may have) changed */
if (pk_context->config_changed_cb) {
pk_context->config_changed_cb (pk_context, pk_context->config_changed_user_data);
}
}
/**
* libpolkit_context_init:
* @pk_context: the context object
* @error: return location for error
*
* Initializes a new context; loads PolicyKit files from
* /etc/PolicyKit/privileges unless the environment variable
* $POLKIT_PRIVILEGE_DIR points to a location.
*
* Returns: #FALSE if @error was set, otherwise #TRUE
**/
gboolean
libpolkit_context_init (PolKitContext *pk_context, GError **error)
{
gboolean ret;
const char *dirname;
ret = FALSE;
dirname = getenv ("POLKIT_PRIVILEGE_DIR");
if (dirname != NULL) {
_pk_debug ("Using directory %s", dirname);
pk_context->priv_dir = g_strdup (dirname);
} else {
dirname = PACKAGE_SYSCONF_DIR "/PolicyKit/privileges";
pk_context->priv_dir = g_strdup (PACKAGE_SYSCONF_DIR "/PolicyKit/privileges");
}
_pk_debug ("Using privilege files from directory %s", pk_context->priv_dir);
pk_context->priv_cache = libpolkit_privilege_cache_new (dirname, error);
if (pk_context->priv_cache == NULL)
goto error;
libpolkit_privilege_cache_debug (pk_context->priv_cache);
/* don't populate the cache until it's needed.. */
return pk_context;
error:
libpolkit_context_unref (pk_context);
return NULL;
if (pk_context->file_monitor_add_watch_func == NULL) {
_pk_debug ("No file monitor; cannot monitor '%s' for .priv file changes", dirname);
} else {
pk_context->file_monitor_add_watch_func (pk_context,
dirname,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE,
_privilege_dir_events,
NULL);
}
/* right now we can't fail - but in the future modules we load may */
ret = TRUE;
return ret;
}
/**
......@@ -144,7 +193,15 @@ libpolkit_context_unref (PolKitContext *pk_context)
* Register the callback function for when configuration changes.
* Mechanisms should use this callback to e.g. reconfigure all
* permissions / acl's they have set in response to policy decisions
* made from information provided by PolicyKit.
* made from information provided by PolicyKit.
*
* Note that this function may be called many times within a short
* interval due to how file monitoring works if e.g. the user is
* editing a configuration file (editors typically create back-up
* files). Mechanisms should use a "cool-off" timer (of, say, one
* second) to avoid doing many expensive operations (such as
* reconfiguring all ACL's for all devices) within a very short
* timeframe.
**/
void
libpolkit_context_set_config_changed (PolKitContext *pk_context,
......@@ -156,6 +213,25 @@ libpolkit_context_set_config_changed (PolKitContext *pk_context,
pk_context->config_changed_user_data = user_data;
}
/**
* libpolkit_context_set_file_monitor:
* @pk_context: the context object
* @add_watch_func: the function that the PolicyKit library can invoke to start watching a file
* @remove_watch_func: the function that the PolicyKit library can invoke to stop watching a file
*
* Register a functions that PolicyKit can use for watching files.
**/
void
libpolkit_context_set_file_monitor (PolKitContext *pk_context,
PolKitContextFileMonitorAddWatch add_watch_func,
PolKitContextFileMonitorRemoveWatch remove_watch_func)
{
g_return_if_fail (pk_context != NULL);
pk_context->file_monitor_add_watch_func = add_watch_func;
pk_context->file_monitor_remove_watch_func = remove_watch_func;
}
/**
* libpolkit_context_get_privilege_cache:
* @pk_context: the context
......@@ -168,5 +244,22 @@ PolKitPrivilegeCache *
libpolkit_context_get_privilege_cache (PolKitContext *pk_context)
{
g_return_val_if_fail (pk_context != NULL, NULL);
if (pk_context->priv_cache == NULL) {
GError *error;
_pk_debug ("Populating cache from directory %s", pk_context->priv_dir);
error = NULL;
pk_context->priv_cache = libpolkit_privilege_cache_new (pk_context->priv_dir, &error);
if (pk_context->priv_cache == NULL) {
g_warning ("Error loading privilege files from %s: %s",
pk_context->priv_dir, error->message);
g_error_free (error);
} else {
libpolkit_privilege_cache_debug (pk_context->priv_cache);
}
}
return pk_context->priv_cache;
}
......@@ -41,17 +41,101 @@ typedef struct PolKitContext PolKitContext;
* @pk_context: PolicyKit context
* @user_data: user data
*
* See libpolkit_context_set_config_changed() for details.
* The type of the callback function for when configuration changes.
* Mechanisms should use this callback to e.g. reconfigure all
* permissions / acl's they have set in response to policy decisions
* made from information provided by PolicyKit.
*
* Note that this function may be called many times within a short
* interval due to how file monitoring works if e.g. the user is
* editing a configuration file (editors typically create back-up
* files). Mechanisms should use a "cool-off" timer (of, say, one
* second) to avoid doing many expensive operations (such as
* reconfiguring all ACL's for all devices) within a very short
* timeframe.
*/
typedef void (*PolKitContextConfigChangedCB) (PolKitContext *pk_context,
gpointer user_data);
PolKitContext *libpolkit_context_new (GError **error);
PolKitContext *libpolkit_context_ref (PolKitContext *pk_context);
void libpolkit_context_set_config_changed (PolKitContext *pk_context,
PolKitContextConfigChangedCB cb,
gpointer user_data);
void libpolkit_context_unref (PolKitContext *pk_context);
/**
* PolKitContextFileMonitorEvent:
* @POLKIT_CONTEXT_FILE_MONITOR_EVENT_NONE: TODO
* @POLKIT_CONTEXT_FILE_MONITOR_EVENT_ACCESS: watch when a file is accessed
* @POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE: watch when a file is created
* @POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE: watch when a file is deleted
* @POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE: watch when a file changes
*
* File monitoring events.
**/
typedef enum
{
POLKIT_CONTEXT_FILE_MONITOR_EVENT_NONE = 1 << 0,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_ACCESS = 1 << 1,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE = 1 << 2,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE = 1 << 3,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE = 1 << 4,
} PolKitContextFileMonitorEvent;
/**
* PolKitContextFileMonitorNotifyFunc:
* @pk_context: PolicyKit context
* @event_mask: event that happened
* @path: the path to the monitored file
* @user_data: the user data supplied to the function of type #PolKitContextFileMonitorAddWatch
*
* Callback when an event happens on a file that is monitored.
**/
typedef void (*PolKitContextFileMonitorNotifyFunc) (PolKitContext *pk_context,
PolKitContextFileMonitorEvent event_mask,
const char *path,
gpointer user_data);
/**
* PolKitContextFileMonitorAddWatch:
* @pk_context: PolicyKit context
* @path: path to file/directory to monitor for events
* @event_mask: events to look for
* @notify_cb: function to call on events
* @user_data: user data
*
* The type of a function that PolicyKit can use to watch file
* events. This function must call the supplied @notify_cb function
* (and pass @path and @user_data) on events
*
* Returns: A handle for the watch. If zero it means the file cannot
* be watched. Caller can remove the watch using the supplied function
* of type #PolKitContextFileMonitorRemoveWatch and the handle.
*/
typedef guint (*PolKitContextFileMonitorAddWatch) (PolKitContext *pk_context,
const char *path,
PolKitContextFileMonitorEvent event_mask,
PolKitContextFileMonitorNotifyFunc notify_cb,
gpointer user_data);
/**
* PolKitContextFileMonitorRemoveWatch:
* @pk_context: PolicyKit context
* @watch_id: the watch id
*
* The type of a function that PolicyKit can use to stop monitoring
* file events. Pass the handle obtained from the supplied function of
* type #PolKitContextFileMonitorAddWatch.
*/
typedef void (*PolKitContextFileMonitorRemoveWatch) (PolKitContext *pk_context,
guint watch_id);
PolKitContext *libpolkit_context_new (void);
gboolean libpolkit_context_init (PolKitContext *pk_context,
GError **error);
PolKitContext *libpolkit_context_ref (PolKitContext *pk_context);
void libpolkit_context_unref (PolKitContext *pk_context);
void libpolkit_context_set_config_changed (PolKitContext *pk_context,
PolKitContextConfigChangedCB cb,
gpointer user_data);
void libpolkit_context_set_file_monitor (PolKitContext *pk_context,
PolKitContextFileMonitorAddWatch add_watch_func,
PolKitContextFileMonitorRemoveWatch remove_watch_func);
PolKitPrivilegeCache *libpolkit_context_get_privilege_cache (PolKitContext *pk_context);
......
......@@ -111,6 +111,9 @@ libpolkit_privilege_cache_new (const char *dirname, GError **error)
if (!g_str_has_suffix (file, ".priv"))
continue;
if (g_str_has_suffix (file, "."))
continue;
path = g_strdup_printf ("%s/%s", dirname, file);
_pk_debug ("Loading %s", path);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment