/*
Copyright (C) 2016 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <talloc.h>
#include <errno.h>
#include <libgen.h>
#include <limits.h>
/* For parent directories, we want to know if a file was moved there or
* created there
*/
* directory
*/
struct snotify_watch_ctx {
/* In case we're also watching the parent directory, otherwise -1.
* We keep the variable here and not in snctx so that we're able
* to catch even changes to the parent directory
*/
int dir_wd;
/* The file watch */
int file_wd;
};
/* This is what we call when an event we're interested in arrives */
struct snotify_cb_ctx {
const char *fn_name;
void *pvt;
};
/* One instance of a callback. We hoard the inotify notifications
* until timer fires in caught_flags
*/
struct snotify_dispatcher {
};
struct snotify_ctx {
/* The full path of the file we're watching,
* its file and directory components */
const char *filename;
const char *dir_name;
const char *base_name;
/* Private pointer passed to the callback */
/* A singleton callback dispatcher */
/* Internal snotify flags */
/* The caller might decide to batch the updates and receive
* them all together with a delay
*/
/* We keep the structure that actually does the work
* separately to be able to reinitialize it when the
* file is recreated or moved to the directory
*/
};
struct flg2str {
const char *str;
} flg_table[] = {
{ 0x00000001, "IN_ACCESS" },
{ 0x00000002, "IN_MODIFY" },
{ 0x00000004, "IN_ATTRIB" },
{ 0x00000008, "IN_CLOSE_WRITE" },
{ 0x00000010, "IN_CLOSE_NOWRITE" },
{ 0x00000020, "IN_OPEN" },
{ 0x00000040, "IN_MOVED_FROM" },
{ 0x00000080, "IN_MOVED_TO" },
{ 0x00000100, "IN_CREATE" },
{ 0x00000200, "IN_DELETE" },
{ 0x00000400, "IN_DELETE_SELF" },
{ 0x00000800, "IN_MOVE_SELF" },
{ 0x00002000, "IN_UNMOUNT" },
{ 0x00004000, "IN_Q_OVERFLOW" },
{ 0x00008000, "IN_IGNORED" },
{ 0x01000000, "IN_ONLYDIR" },
{ 0x02000000, "IN_DONT_FOLLOW" },
{ 0x04000000, "IN_EXCL_UNLINK" },
{ 0x20000000, "IN_MASK_ADD" },
{ 0x40000000, "IN_ISDIR" },
{ 0x80000000, "IN_ONESHOT" },
{ 0, NULL },
};
#if 0
{
char msgbuf[1024];
if (!DEBUG_IS_SET(SSSDBG_TRACE_LIBS)) {
return;
}
}
}
if (total == 0) {
}
}
#endif
struct tevent_timer *te,
struct timeval t,
void *ptr)
{
return;
}
}
{
return NULL;
}
"Running a timer with delay %ld.%ld\n",
snctx);
return NULL;
}
return disp;
}
{
}
return create_dispatcher(snctx);
}
{
return EOK;
}
return ENOMEM;
}
"Dispatched an event with combined flags 0x%X\n",
disp->caught_flags);
return EOK;
}
const struct inotify_event *in_event)
{
return EOK;
}
"received notification for watched file [%s] under %s\n",
/* file the event for the file to see if the caller is interested in it */
/* Tells the outer loop to re-initialize flags once the loop is finished.
* However, finish reading all the events first to make sure we don't
* miss any
*/
return EAGAIN;
}
return ret;
}
const struct inotify_event *in_event)
{
/* Notify caller of the event, don't quit */
return EAGAIN;
}
}
void *data)
{
const char *ptr;
bool rewatch;
return;
}
while (1) {
if (len == -1) {
"Cannot read inotify_event [%d]: %s\n",
} else {
}
return;
}
/* Did not even read the required amount of data, move on.. */
continue;
}
//debug_flags(in_event->mask, in_event->name);
rewatch = true;
/* Continue with the loop and read all the events from
* this descriptor first, then rewatch when done
*/
"Failed to process inotify event\n");
continue;
}
"Failed to process inotify event\n");
continue;
}
} else {
}
}
}
if (rewatch) {
}
}
}
{
return 1;
}
/* We don't need to close the watches explicitly. man 7 inotify says:
* When all file descriptors referring to an inotify instance
* have been closed (using close(2)), the underlying object
* and its resources are freed for reuse by the kernel; all
* associated watches are automatically freed.
*/
}
return 0;
}
const char *filename)
{
char *p;
if (p == NULL) {
return EIO;
}
return ENOMEM;
}
if (p == NULL) {
return EIO;
}
return ENOMEM;
}
return ENOMEM;
}
return EOK;
}
{
return NULL;
}
goto fail;
}
snctx);
"Cannot add tevent fd watch for %s\n",
goto fail;
}
"inotify_add_watch failed [%d]: %s\n",
goto fail;
}
}
/* Create a watch for the parent directory. This is useful for cases
* where we start watching a file before it's created, but still want
* a notification when the file is moved in
*/
"inotify_add_watch failed [%d]: %s\n",
goto fail;
}
}
return wctx;
fail:
return NULL;
}
{
return ENOMEM;
}
return EOK;
}
struct tevent_context *ev,
const char *filename,
const char *fn_name,
void *pvt)
{
return NULL;
}
if (delay) {
}
return NULL;
}
return NULL;
}
"Added a watch for %s with inotify flags 0x%X "
"internal flags 0x%X "
"using function %s after delay %ld.%ld\n",
mask,
return snctx;
}