Commit b22ebaba authored by David Zeuthen's avatar David Zeuthen
Browse files

replace configuration reload mechanism

Instead of asking the user of libpolkit to provide a huge file
monitoring abstraction we simply ask for a simple interface for
watching file descriptors and use inotify (on Linux) to watch a file,
/var/lib/PolicyKit/reload. We provide a new tool,
polkit-reload-config, that simply touches this file.
parent 608e8745
if MAN_PAGES_ENABLED
MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in polkit-policy-file-validate.1.in PolicyKit.8.in
MAN_IN_FILES = polkit-check-caller.1.in polkit-check-session.1.in polkit-policy-file-validate.1.in PolicyKit.8.in polkit-reload-config.1.in
man_MANS = $(MAN_IN_FILES:.in=)
......
.\"
.\" polkit-reload-config manual page.
.\" Copyright (C) 2007 David Zeuthen <david@fubar.dk>
.\"
.TH POLKIT-RELOAD-CONFIG 1
.SH NAME
polkit-reload-config \- reload configuration
.SH SYNOPSIS
.PP
.B polkit-reload-config
.SH DESCRIPTION
\fIpolkit-reload-config\fP can be used to signal all processes using
libpolkit to reload their configuration. For more information about
the big picture refer to the \fIPolicyKit spec\fP which can be found
in
.I "@docdir@/spec/polkit-spec.html"
depending on the distribution. Only the super user can invoke this
tool.
.SH BUGS
.PP
Please send bug reports to either the distribution or the HAL
mailing list, see
.I "http://lists.freedesktop.org/mailman/listinfo/hal"
on how to subscribe.
.SH SEE ALSO
.PP
\&\fIPolicyKit\fR\|(8)
.SH AUTHOR
Written by David Zeuthen <david@fubar.dk> with a lot of help from many
others.
......@@ -55,3 +55,10 @@ libpolkit_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
clean-local :
rm -f *~ $(BUILT_SOURCES)
# Create /var/lib/PolicyKit/reload file; this is being watched by libpolkit
# for config file changes.
install-data-local:
touch $(DESTDIR)$(localstatedir)/lib/PolicyKit/reload
-chmod 700 $(DESTDIR)$(localstatedir)/lib/PolicyKit/reload
......@@ -35,6 +35,7 @@
#include <grp.h>
#include <unistd.h>
#include <errno.h>
#include <sys/inotify.h>
#include <glib.h>
#include "polkit-debug.h"
......@@ -67,14 +68,19 @@ struct PolKitContext
PolKitContextConfigChangedCB config_changed_cb;
void *config_changed_user_data;
PolKitContextFileMonitorAddWatch file_monitor_add_watch_func;
PolKitContextFileMonitorRemoveWatch file_monitor_remove_watch_func;
PolKitContextAddIOWatch io_add_watch_func;
PolKitContextRemoveIOWatch io_remove_watch_func;
char *policy_dir;
PolKitPolicyCache *priv_cache;
polkit_bool_t load_descriptions;
int inotify_fd;
int inotify_fd_watch_id;
int inotify_reload_wd;
};
/**
......@@ -92,40 +98,6 @@ polkit_context_new (void)
pk_context->refcount = 1;
return pk_context;
}
static void
_config_file_events (PolKitContext *pk_context,
PolKitContextFileMonitorEvent event_mask,
const char *path,
void *user_data)
{
_pk_debug ("Config file changed");
/* 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);
}
}
static void
_policy_dir_events (PolKitContext *pk_context,
PolKitContextFileMonitorEvent event_mask,
const char *path,
void *user_data)
{
/* mark cache of policy 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->policy_dir);
polkit_policy_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);
}
}
/**
* polkit_context_init:
* @pk_context: the context object
......@@ -150,39 +122,41 @@ polkit_context_init (PolKitContext *pk_context, PolKitError **error)
}
_pk_debug ("Using policy files from directory %s", pk_context->policy_dir);
/* don't populate the cache until it's needed.. */
/* we don't populate the cache until it's needed.. */
if (pk_context->io_add_watch_func != NULL) {
pk_context->inotify_fd = inotify_init ();
if (pk_context->inotify_fd < 0) {
_pk_debug ("failed to initialize inotify: %s", strerror (errno));
/* TODO: set error */
goto error;
}
if (pk_context->file_monitor_add_watch_func == NULL) {
_pk_debug ("No file monitor; cannot monitor '%s' for .policy file changes", pk_context->policy_dir);
} else {
/* Watch when policy definitions file change */
pk_context->file_monitor_add_watch_func (pk_context,
pk_context->policy_dir,
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE,
_policy_dir_events,
NULL);
/* Config file changes */
pk_context->file_monitor_add_watch_func (pk_context,
PACKAGE_DATA_DIR "/PolicyKit",
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CREATE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_DELETE|
POLKIT_CONTEXT_FILE_MONITOR_EVENT_CHANGE,
_config_file_events,
NULL);
/* create a watch on /var/lib/PolicyKit/reload */
pk_context->inotify_reload_wd = inotify_add_watch (pk_context->inotify_fd,
PACKAGE_LOCALSTATEDIR "/lib/PolicyKit/reload",
IN_MODIFY | IN_CREATE | IN_ATTRIB);
if (pk_context->inotify_reload_wd < 0) {
_pk_debug ("failed to add watch on file '" PACKAGE_LOCALSTATEDIR "/lib/PolicyKit/reload': %s",
strerror (errno));
/* TODO: set error */
goto error;
}
pk_context->inotify_fd_watch_id = pk_context->io_add_watch_func (pk_context, pk_context->inotify_fd);
if (pk_context->inotify_fd_watch_id == 0) {
_pk_debug ("failed to add io watch");
/* TODO: set error */
goto error;
}
}
return TRUE;
#if 0
error:
if (pk_context != NULL)
polkit_context_unref (pk_context);
return FALSE;
#endif
}
/**
......@@ -244,8 +218,8 @@ polkit_context_unref (PolKitContext *pk_context)
**/
void
polkit_context_set_config_changed (PolKitContext *pk_context,
PolKitContextConfigChangedCB cb,
void *user_data)
PolKitContextConfigChangedCB cb,
void *user_data)
{
g_return_if_fail (pk_context != NULL);
pk_context->config_changed_cb = cb;
......@@ -253,23 +227,77 @@ polkit_context_set_config_changed (PolKitContext *pk_context,
}
/**
* polkit_context_set_file_monitor:
* polkit_context_io_func:
* @pk_context: the object
* @fd: the file descriptor passed to the supplied function of type #PolKitContextAddIOWatch.
*
* Method that the application must call when there is data to read
* from a file descriptor registered with the supplied function of
* type #PolKitContextAddIOWatch.
**/
void
polkit_context_io_func (PolKitContext *pk_context, int fd)
{
g_return_if_fail (pk_context != NULL);
_pk_debug ("polkit_context_io_func: data on fd %d", fd);
if (fd == pk_context->inotify_fd) {
/* size of the event structure, not counting name */
#define EVENT_SIZE (sizeof (struct inotify_event))
/* reasonable guess as to size of 1024 events */
#define BUF_LEN (1024 * (EVENT_SIZE + 16))
char buf[BUF_LEN];
int len;
int i = 0;
again:
len = read (fd, buf, BUF_LEN);
if (len < 0) {
if (errno == EINTR) {
goto again;
} else {
_pk_debug ("read: %s", strerror (errno));
}
} else if (len > 0) {
/* BUF_LEN too small? */
}
while (i < len) {
struct inotify_event *event;
event = (struct inotify_event *) &buf[i];
_pk_debug ("wd=%d mask=%u cookie=%u len=%u",
event->wd, event->mask, event->cookie, event->len);
if (event->wd == pk_context->inotify_reload_wd) {
_pk_debug ("config changed!");
if (pk_context->config_changed_cb != NULL) {
pk_context->config_changed_cb (pk_context,
pk_context->config_changed_user_data);
}
}
i += EVENT_SIZE + event->len;
}
}
}
/**
* polkit_context_set_io_watch_functions:
* @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
* @io_add_watch_func: the function that the PolicyKit library can invoke to start watching a file descriptor
* @io_remove_watch_func: the function that the PolicyKit library can invoke to stop watching a file descriptor
*
* Register a functions that PolicyKit can use for watching files.
* Register a functions that PolicyKit can use for watching IO descriptors.
*
* This method must be called before polkit_context_init().
**/
void
polkit_context_set_file_monitor (PolKitContext *pk_context,
PolKitContextFileMonitorAddWatch add_watch_func,
PolKitContextFileMonitorRemoveWatch remove_watch_func)
polkit_context_set_io_watch_functions (PolKitContext *pk_context,
PolKitContextAddIOWatch io_add_watch_func,
PolKitContextRemoveIOWatch io_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;
pk_context->io_add_watch_func = io_add_watch_func;
pk_context->io_remove_watch_func = io_remove_watch_func;
}
/**
......
......@@ -53,6 +53,9 @@ typedef struct PolKitContext PolKitContext;
* permissions / acl's they have set in response to policy decisions
* made from information provided by PolicyKit.
*
* The user must have set up watches using #polkit_context_set_io_watch_functions
* for this to work.
*
* 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
......@@ -65,97 +68,101 @@ typedef void (*PolKitContextConfigChangedCB) (PolKitContext *pk_context,
void *user_data);
/**
* 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
* PolKitContextAddIOWatch:
* @pk_context: the polkit context
* @fd: the file descriptor to watch
*
* Callback when an event happens on a file that is monitored.
* Type for function supplied by the application to integrate a watch
* on a file descriptor into the applications main loop. The
* application must call polkit_grant_io_func() when there is data
* to read from the file descriptor.
*
* For glib mainloop, the function will typically look like this:
*
* <programlisting>
* static gboolean
* io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
* {
* int fd;
* PolKitContext *pk_context = user_data;
* fd = g_io_channel_unix_get_fd (channel);
* polkit_context_io_func (pk_context, fd);
* return TRUE;
* }
*
* static int
* io_add_watch (PolKitContext *pk_context, int fd)
* {
* guint id = 0;
* GIOChannel *channel;
* channel = g_io_channel_unix_new (fd);
* if (channel == NULL)
* goto out;
* id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, pk_context);
* if (id == 0) {
* g_io_channel_unref (channel);
* goto out;
* }
* g_io_channel_unref (channel);
* out:
* return id;
* }
* </programlisting>
*
* Returns: 0 if the watch couldn't be set up; otherwise an unique
* identifier for the watch.
**/
typedef void (*PolKitContextFileMonitorNotifyFunc) (PolKitContext *pk_context,
PolKitContextFileMonitorEvent event_mask,
const char *path,
void *user_data);
typedef int (*PolKitContextAddIOWatch) (PolKitContext *pk_context, int fd);
/**
* 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
* PolKitContextRemoveIOWatch:
* @pk_context: the context object
* @watch_id: the id obtained from using the supplied function
* of type #PolKitContextAddIOWatch
*
* 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
* Type for function supplied by the application to remove a watch set
* up via the supplied function of type #PolKitContextAddIOWatch
*
* 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 int (*PolKitContextFileMonitorAddWatch) (PolKitContext *pk_context,
const char *path,
PolKitContextFileMonitorEvent event_mask,
PolKitContextFileMonitorNotifyFunc notify_cb,
void *user_data);
/**
* PolKitContextFileMonitorRemoveWatch:
* @pk_context: PolicyKit context
* @watch_id: the watch id
* For the glib mainloop, the function will typically look like this:
*
* 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,
int watch_id);
* <programlisting>
* static void
* io_remove_watch (PolKitContext *pk_context, int watch_id)
* {
* g_source_remove (watch_id);
* }
* </programlisting>
*
**/
typedef void (*PolKitContextRemoveIOWatch) (PolKitContext *pk_context, int watch_id);
PolKitContext *polkit_context_new (void);
void polkit_context_set_config_changed (PolKitContext *pk_context,
PolKitContextConfigChangedCB cb,
void *user_data);
void polkit_context_set_io_watch_functions (PolKitContext *pk_context,
PolKitContextAddIOWatch io_add_watch_func,
PolKitContextRemoveIOWatch io_remove_watch_func);
void polkit_context_set_load_descriptions (PolKitContext *pk_context);
polkit_bool_t polkit_context_init (PolKitContext *pk_context,
PolKitError **error);
PolKitContext *polkit_context_ref (PolKitContext *pk_context);
void polkit_context_unref (PolKitContext *pk_context);
PolKitContext *polkit_context_new (void);
void polkit_context_set_config_changed (PolKitContext *pk_context,
PolKitContextConfigChangedCB cb,
void *user_data);
void polkit_context_set_file_monitor (PolKitContext *pk_context,
PolKitContextFileMonitorAddWatch add_watch_func,
PolKitContextFileMonitorRemoveWatch remove_watch_func);
void polkit_context_set_load_descriptions (PolKitContext *pk_context);
polkit_bool_t polkit_context_init (PolKitContext *pk_context,
PolKitError **error);
PolKitContext *polkit_context_ref (PolKitContext *pk_context);
void polkit_context_unref (PolKitContext *pk_context);
void polkit_context_io_func (PolKitContext *pk_context, int fd);
PolKitPolicyCache *polkit_context_get_policy_cache (PolKitContext *pk_context);
PolKitPolicyCache *polkit_context_get_policy_cache (PolKitContext *pk_context);
PolKitResult
polkit_context_can_session_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitSession *session);
polkit_context_can_session_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitSession *session);
PolKitResult
polkit_context_can_caller_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitCaller *caller);
polkit_context_can_caller_do_action (PolKitContext *pk_context,
PolKitAction *action,
PolKitCaller *caller);
#endif /* POLKIT_CONTEXT_H */
......
......@@ -13,6 +13,8 @@ INCLUDES = \
bin_PROGRAMS = polkit-check-caller polkit-check-session polkit-policy-file-validate polkit-grant polkit-list-actions
bin_SCRIPTS = polkit-reload-config
polkit_check_caller_SOURCES = polkit-check-caller.c
polkit_check_caller_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la $(top_builddir)/polkit-dbus/libpolkit-dbus.la
......@@ -28,6 +30,16 @@ polkit_grant_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ $(top_builddir)/polkit/libpolkit.la
polkit_list_actions_SOURCES = polkit-list-actions.c
polkit_list_actions_LDADD = $(GLIB) $(top_builddir)/polkit/libpolkit.la
polkit-reload-config: polkit-reload-config.in Makefile
$(edit) $< >$@
edit = sed \
-e 's|@docdir[@]|$(docdir)|g' \
-e 's|@sbindir[@]|$(sbindir)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-e 's|@datadir[@]|$(datadir)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g'
clean-local :
rm -f *~
#!/bin/sh
touch @localstatedir@/lib/PolicyKit/reload
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