You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
6.4 KiB
317 lines
6.4 KiB
/*
|
|
* Copyright © 2006 Novell, Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
* and its documentation for any purpose is hereby granted without
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
* and that both that copyright notice and this permission notice
|
|
* appear in supporting documentation, and that the name of
|
|
* Novell, Inc. not be used in advertising or publicity pertaining to
|
|
* distribution of the software without specific, written prior permission.
|
|
* Novell, Inc. makes no representations about the suitability of this
|
|
* software for any purpose. It is provided "as is" without express or
|
|
* implied warranty.
|
|
*
|
|
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
|
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
|
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: David Reveman <davidr@novell.com>
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <poll.h>
|
|
#include <sys/inotify.h>
|
|
|
|
#include <compiz-core.h>
|
|
|
|
static CompMetadata inotifyMetadata;
|
|
|
|
static int corePrivateIndex;
|
|
|
|
typedef struct _CompInotifyWatch {
|
|
struct _CompInotifyWatch *next;
|
|
CompFileWatchHandle handle;
|
|
int wd;
|
|
} CompInotifyWatch;
|
|
|
|
typedef struct _InotifyCore {
|
|
int fd;
|
|
CompInotifyWatch *watch;
|
|
CompWatchFdHandle watchFdHandle;
|
|
|
|
FileWatchAddedProc fileWatchAdded;
|
|
FileWatchRemovedProc fileWatchRemoved;
|
|
} InotifyCore;
|
|
|
|
#define GET_INOTIFY_CORE(c) \
|
|
((InotifyCore *) (c)->base.privates[corePrivateIndex].ptr)
|
|
|
|
#define INOTIFY_CORE(c) \
|
|
InotifyCore *ic = GET_INOTIFY_CORE (c)
|
|
|
|
|
|
static Bool
|
|
inotifyProcessEvents (void *data)
|
|
{
|
|
char buf[256 * (sizeof (struct inotify_event) + 16)];
|
|
int len;
|
|
|
|
INOTIFY_CORE (&core);
|
|
|
|
len = read (ic->fd, buf, sizeof (buf));
|
|
if (len < 0)
|
|
{
|
|
perror ("read");
|
|
}
|
|
else
|
|
{
|
|
struct inotify_event *event;
|
|
CompInotifyWatch *iw;
|
|
CompFileWatch *fw;
|
|
int i = 0;
|
|
|
|
while (i < len)
|
|
{
|
|
event = (struct inotify_event *) &buf[i];
|
|
|
|
for (iw = ic->watch; iw; iw = iw->next)
|
|
if (iw->wd == event->wd)
|
|
break;
|
|
|
|
if (iw)
|
|
{
|
|
for (fw = core.fileWatch; fw; fw = fw->next)
|
|
if (fw->handle == iw->handle)
|
|
break;
|
|
|
|
if (fw)
|
|
{
|
|
if (event->len)
|
|
(*fw->callBack) (event->name, fw->closure);
|
|
else
|
|
(*fw->callBack) (NULL, fw->closure);
|
|
}
|
|
}
|
|
|
|
i += sizeof (*event) + event->len;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int
|
|
inotifyMask (CompFileWatch *fileWatch)
|
|
{
|
|
int mask = 0;
|
|
|
|
if (fileWatch->mask & NOTIFY_CREATE_MASK)
|
|
mask |= IN_CREATE;
|
|
|
|
if (fileWatch->mask & NOTIFY_DELETE_MASK)
|
|
mask |= IN_DELETE;
|
|
|
|
if (fileWatch->mask & NOTIFY_MOVE_MASK)
|
|
mask |= IN_MOVE;
|
|
|
|
if (fileWatch->mask & NOTIFY_MODIFY_MASK)
|
|
mask |= IN_MODIFY;
|
|
|
|
return mask;
|
|
}
|
|
|
|
static void
|
|
inotifyFileWatchAdded (CompCore *c,
|
|
CompFileWatch *fileWatch)
|
|
{
|
|
CompInotifyWatch *iw;
|
|
|
|
INOTIFY_CORE (c);
|
|
|
|
iw = malloc (sizeof (CompInotifyWatch));
|
|
if (!iw)
|
|
return;
|
|
|
|
iw->handle = fileWatch->handle;
|
|
iw->wd = inotify_add_watch (ic->fd,
|
|
fileWatch->path,
|
|
inotifyMask (fileWatch));
|
|
if (iw->wd < 0)
|
|
{
|
|
perror ("inotify_add_watch");
|
|
free (iw);
|
|
return;
|
|
}
|
|
|
|
iw->next = ic->watch;
|
|
ic->watch = iw;
|
|
}
|
|
|
|
static void
|
|
inotifyFileWatchRemoved (CompCore *c,
|
|
CompFileWatch *fileWatch)
|
|
{
|
|
CompInotifyWatch *p = 0, *iw;
|
|
|
|
INOTIFY_CORE (c);
|
|
|
|
for (iw = ic->watch; iw; iw = iw->next)
|
|
{
|
|
if (iw->handle == fileWatch->handle)
|
|
break;
|
|
|
|
p = iw;
|
|
}
|
|
|
|
if (iw)
|
|
{
|
|
if (p)
|
|
p->next = iw->next;
|
|
else
|
|
ic->watch = iw->next;
|
|
|
|
if (inotify_rm_watch (ic->fd, iw->wd))
|
|
perror ("inotify_rm_watch");
|
|
|
|
free (iw);
|
|
}
|
|
}
|
|
|
|
static Bool
|
|
inotifyInitCore (CompPlugin *p,
|
|
CompCore *c)
|
|
{
|
|
InotifyCore *ic;
|
|
CompFileWatch *fw;
|
|
|
|
if (!checkPluginABI ("core", CORE_ABIVERSION))
|
|
return FALSE;
|
|
|
|
ic = malloc (sizeof (InotifyCore));
|
|
if (!ic)
|
|
return FALSE;
|
|
|
|
ic->fd = inotify_init ();
|
|
if (ic->fd < 0)
|
|
{
|
|
perror ("inotify_init");
|
|
free (ic);
|
|
return FALSE;
|
|
}
|
|
|
|
ic->watch = NULL;
|
|
|
|
ic->watchFdHandle = compAddWatchFd (ic->fd,
|
|
POLLIN | POLLPRI | POLLHUP | POLLERR,
|
|
inotifyProcessEvents,
|
|
NULL);
|
|
|
|
WRAP (ic, c, fileWatchAdded, inotifyFileWatchAdded);
|
|
WRAP (ic, c, fileWatchRemoved, inotifyFileWatchRemoved);
|
|
|
|
c->base.privates[corePrivateIndex].ptr = ic;
|
|
|
|
for (fw = c->fileWatch; fw; fw = fw->next)
|
|
inotifyFileWatchAdded (c, fw);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
inotifyFiniCore (CompPlugin *p,
|
|
CompCore *c)
|
|
{
|
|
CompFileWatch *fw;
|
|
|
|
INOTIFY_CORE (c);
|
|
|
|
compRemoveWatchFd (ic->watchFdHandle);
|
|
|
|
for (fw = c->fileWatch; fw; fw = fw->next)
|
|
inotifyFileWatchRemoved (c, fw);
|
|
|
|
close (ic->fd);
|
|
|
|
UNWRAP (ic, c, fileWatchAdded);
|
|
UNWRAP (ic, c, fileWatchRemoved);
|
|
|
|
free (ic);
|
|
}
|
|
|
|
static CompBool
|
|
inotifyInitObject (CompPlugin *p,
|
|
CompObject *o)
|
|
{
|
|
static InitPluginObjectProc dispTab[] = {
|
|
(InitPluginObjectProc) inotifyInitCore
|
|
};
|
|
|
|
RETURN_DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), TRUE, (p, o));
|
|
}
|
|
|
|
static void
|
|
inotifyFiniObject (CompPlugin *p,
|
|
CompObject *o)
|
|
{
|
|
static FiniPluginObjectProc dispTab[] = {
|
|
(FiniPluginObjectProc) inotifyFiniCore
|
|
};
|
|
|
|
DISPATCH (o, dispTab, ARRAY_SIZE (dispTab), (p, o));
|
|
}
|
|
|
|
static Bool
|
|
inotifyInit (CompPlugin *p)
|
|
{
|
|
if (!compInitPluginMetadataFromInfo (&inotifyMetadata, p->vTable->name,
|
|
0, 0, 0, 0))
|
|
return FALSE;
|
|
|
|
corePrivateIndex = allocateCorePrivateIndex ();
|
|
if (corePrivateIndex < 0)
|
|
{
|
|
compFiniMetadata (&inotifyMetadata);
|
|
return FALSE;
|
|
}
|
|
|
|
compAddMetadataFromFile (&inotifyMetadata, p->vTable->name);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
inotifyFini (CompPlugin *p)
|
|
{
|
|
freeCorePrivateIndex (corePrivateIndex);
|
|
compFiniMetadata (&inotifyMetadata);
|
|
}
|
|
|
|
static CompMetadata *
|
|
inotifyGetMetadata (CompPlugin *plugin)
|
|
{
|
|
return &inotifyMetadata;
|
|
}
|
|
|
|
CompPluginVTable inotifyVTable = {
|
|
"inotify",
|
|
inotifyGetMetadata,
|
|
inotifyInit,
|
|
inotifyFini,
|
|
inotifyInitObject,
|
|
inotifyFiniObject,
|
|
0, /* GetObjectOptions */
|
|
0 /* SetObjectOption */
|
|
};
|
|
|
|
CompPluginVTable *
|
|
getCompPluginInfo20070830 (void)
|
|
{
|
|
return &inotifyVTable;
|
|
}
|