2012-10-05 07:41:46 +00:00
|
|
|
|
/*
|
|
|
|
|
| inotify.c from Lsyncd - Live (Mirror) Syncing Demon
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-27 06:54:14 +00:00
|
|
|
|
| Event interface for Lsyncd to Linux´ inotify.
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-03-27 06:54:14 +00:00
|
|
|
|
| License: GPLv2 (see COPYING) or any later version
|
|
|
|
|
|
|
|
|
|
|
| Authors: Axel Kittenberger <axkibe@gmail.com>
|
2012-10-05 07:41:46 +00:00
|
|
|
|
*/
|
2010-11-22 21:17:08 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
#include "lsyncd.h"
|
|
|
|
|
|
|
|
|
|
#include <sys/inotify.h>
|
|
|
|
|
#include <unistd.h>
|
2018-03-27 07:14:53 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
2010-11-22 20:09:52 +00:00
|
|
|
|
|
2018-03-27 07:14:53 +00:00
|
|
|
|
#define LUA_USE_APICHECK 1
|
2010-11-22 20:09:52 +00:00
|
|
|
|
#include <lua.h>
|
|
|
|
|
#include <lualib.h>
|
|
|
|
|
#include <lauxlib.h>
|
|
|
|
|
|
2018-03-27 07:09:07 +00:00
|
|
|
|
#include "mem.h"
|
2018-03-23 08:34:33 +00:00
|
|
|
|
#include "log.h"
|
2018-03-27 06:54:14 +00:00
|
|
|
|
#include "inotify.h"
|
2018-03-28 07:17:49 +00:00
|
|
|
|
#include "observe.h"
|
2018-03-30 07:40:09 +00:00
|
|
|
|
#include "time.h"
|
2018-03-27 06:54:14 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Event types.
|
|
|
|
|
*/
|
2010-11-24 21:38:48 +00:00
|
|
|
|
static const char * ATTRIB = "Attrib";
|
|
|
|
|
static const char * MODIFY = "Modify";
|
|
|
|
|
static const char * CREATE = "Create";
|
|
|
|
|
static const char * DELETE = "Delete";
|
|
|
|
|
static const char * MOVE = "Move";
|
2010-11-24 18:19:13 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2018-03-13 11:29:43 +00:00
|
|
|
|
| The inotify file descriptor.
|
|
|
|
|
*/
|
2010-11-22 21:17:08 +00:00
|
|
|
|
static int inotify_fd = -1;
|
2010-11-22 20:09:52 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Standard inotify events to listen to.
|
|
|
|
|
*/
|
2011-11-23 10:22:10 +00:00
|
|
|
|
static const uint32_t standard_event_mask =
|
2018-03-13 11:29:43 +00:00
|
|
|
|
IN_ATTRIB
|
|
|
|
|
| IN_CLOSE_WRITE
|
|
|
|
|
| IN_CREATE
|
|
|
|
|
| IN_DELETE
|
|
|
|
|
| IN_DELETE_SELF
|
|
|
|
|
| IN_MOVED_FROM
|
|
|
|
|
| IN_MOVED_TO
|
|
|
|
|
| IN_DONT_FOLLOW
|
|
|
|
|
| IN_ONLYDIR;
|
2010-11-22 20:09:52 +00:00
|
|
|
|
|
2011-06-11 16:38:47 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
/*
|
|
|
|
|
| Adds an inotify watch
|
|
|
|
|
|
|
|
|
|
|
| param dir (Lua stack) path to directory
|
|
|
|
|
| param inotifyMode (Lua stack) which inotify event to react upon
|
|
|
|
|
| "CloseWrite", "CloseWrite or Modify"
|
|
|
|
|
|
|
|
|
|
|
| returns (Lua stack) numeric watch descriptor
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static int
|
2012-10-05 07:41:46 +00:00
|
|
|
|
l_addwatch( lua_State *L )
|
2010-11-22 20:09:52 +00:00
|
|
|
|
{
|
2018-03-27 07:14:53 +00:00
|
|
|
|
char const * path = luaL_checkstring( L, 1 );
|
|
|
|
|
char const * imode = luaL_checkstring( L, 2 );
|
2011-06-11 16:38:47 +00:00
|
|
|
|
uint32_t mask = standard_event_mask;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
// checks the desired inotify reaction mode
|
|
|
|
|
if (*imode)
|
|
|
|
|
{
|
|
|
|
|
if ( !strcmp( imode, "Modify" ) )
|
|
|
|
|
{
|
|
|
|
|
// acts on modify instead of closeWrite
|
|
|
|
|
mask |= IN_MODIFY;
|
2011-06-11 16:38:47 +00:00
|
|
|
|
mask &= ~IN_CLOSE_WRITE;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if ( !strcmp( imode, "CloseWrite" ) )
|
|
|
|
|
{
|
|
|
|
|
// thats default
|
|
|
|
|
}
|
|
|
|
|
else if ( !strcmp( imode, "CloseWrite or Modify" ) )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// acts on modify and closeWrite
|
2011-06-11 16:38:47 +00:00
|
|
|
|
mask |= IN_MODIFY;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if ( ! strcmp( imode, "CloseWrite after Modify") )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// might be done in future
|
2018-03-13 11:29:43 +00:00
|
|
|
|
printlogf( L, "Error", "'CloseWrite after Modify' not implemented." );
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
printlogf( L, "Error", "'%s' not a valid inotfiyMode.", imode );
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit(-1);
|
2011-06-11 16:38:47 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
// kernel call to create the inotify watch
|
|
|
|
|
int wd = inotify_add_watch( inotify_fd, path, mask );
|
2011-06-11 16:38:47 +00:00
|
|
|
|
|
2017-02-06 16:00:39 +00:00
|
|
|
|
if( wd < 0 )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
2017-02-06 16:00:39 +00:00
|
|
|
|
if( errno == ENOSPC )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
|
|
|
|
printlogf(
|
|
|
|
|
L, "Error",
|
|
|
|
|
"%s\n%s",
|
|
|
|
|
"Terminating since out of inotify watches.",
|
|
|
|
|
"Consider increasing /proc/sys/fs/inotify/max_user_watches"
|
|
|
|
|
);
|
2011-08-17 11:28:32 +00:00
|
|
|
|
exit(-1); // ERRNO.
|
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
printlogf(
|
|
|
|
|
L, "Inotify",
|
2014-01-09 04:21:18 +00:00
|
|
|
|
"addwatch( %s )-> %d; err= %d : %s",
|
2012-10-05 07:41:46 +00:00
|
|
|
|
path, wd, errno, strerror( errno )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
printlogf( L, "Inotify", "addwatch( %s )-> %d ", path, wd );
|
2011-01-25 11:16:07 +00:00
|
|
|
|
}
|
2018-03-13 11:29:43 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
lua_pushinteger( L, wd );
|
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2017-02-06 16:00:39 +00:00
|
|
|
|
* Removes an inotify watch.
|
|
|
|
|
*
|
|
|
|
|
* param dir (Lua stack) numeric watch descriptor
|
|
|
|
|
*
|
|
|
|
|
* return nil
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static int
|
2017-02-06 16:00:39 +00:00
|
|
|
|
l_rmwatch( lua_State *L )
|
2010-11-22 20:09:52 +00:00
|
|
|
|
{
|
2018-03-27 07:14:53 +00:00
|
|
|
|
const int wd = luaL_checkinteger( L, 1 );
|
|
|
|
|
|
2017-02-06 16:00:39 +00:00
|
|
|
|
inotify_rm_watch( inotify_fd, wd );
|
|
|
|
|
printlogf( L, "Inotify", "rmwatch()<-%d", wd );
|
2018-03-27 07:14:53 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Lsyncd's core's inotify functions.
|
|
|
|
|
*/
|
2018-03-13 11:29:43 +00:00
|
|
|
|
static const luaL_Reg inotifylib[ ] =
|
2017-02-06 16:00:39 +00:00
|
|
|
|
{
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{ "addwatch", l_addwatch },
|
|
|
|
|
{ "rmwatch", l_rmwatch },
|
|
|
|
|
{ NULL, NULL}
|
2010-11-22 20:09:52 +00:00
|
|
|
|
};
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Buffer for MOVE_FROM events.
|
|
|
|
|
| Lsyncd buffers MOVE_FROM events to check if
|
|
|
|
|
| they are followed by MOVE_TO events with identical cookie
|
|
|
|
|
| then they are condensed into one move event to be sent to the
|
|
|
|
|
| runner
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static struct inotify_event * move_event_buf = NULL;
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Memory allocated for move_event_buf
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static size_t move_event_buf_size = 0;
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| True if the buffer is used.
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static bool move_event = false;
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Handles an inotify event.
|
|
|
|
|
*/
|
2011-11-23 10:22:10 +00:00
|
|
|
|
static void
|
2012-10-05 07:41:46 +00:00
|
|
|
|
handle_event(
|
|
|
|
|
lua_State *L,
|
|
|
|
|
struct inotify_event *event
|
|
|
|
|
)
|
2010-11-22 20:09:52 +00:00
|
|
|
|
{
|
2010-11-24 18:19:13 +00:00
|
|
|
|
const char *event_type = NULL;
|
2010-11-22 20:09:52 +00:00
|
|
|
|
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// used to execute two events in case of unmatched MOVE_FROM buffer
|
2010-11-22 20:09:52 +00:00
|
|
|
|
struct inotify_event *after_buf = NULL;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( event && ( IN_Q_OVERFLOW & event->mask ) )
|
|
|
|
|
{
|
|
|
|
|
// and overflow happened, tells the runner
|
2018-03-15 08:27:14 +00:00
|
|
|
|
load_mci( L, "overflow" );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
2018-03-09 14:41:16 +00:00
|
|
|
|
if( lua_pcall( L, 0, 0, -2 ) ) exit( -1 );
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
lua_pop( L, 1 );
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
hup = 1;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// cancel on ignored or resetting
|
2018-03-27 07:14:53 +00:00
|
|
|
|
if( event && ( IN_IGNORED & event->mask ) ) return;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
if( event && event->len == 0 )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// sometimes inotify sends such strange events,
|
|
|
|
|
// (e.g. when touching a dir
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( event == NULL )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// a buffered MOVE_FROM is not followed by anything,
|
|
|
|
|
// thus it is unary
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event = move_event_buf;
|
2010-11-24 18:19:13 +00:00
|
|
|
|
event_type = "Delete";
|
2010-11-22 20:09:52 +00:00
|
|
|
|
move_event = false;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if(
|
2017-02-06 16:00:39 +00:00
|
|
|
|
move_event
|
|
|
|
|
&& (
|
|
|
|
|
!( IN_MOVED_TO & event->mask )
|
|
|
|
|
|| event->cookie != move_event_buf->cookie
|
2012-10-05 07:41:46 +00:00
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// there is a MOVE_FROM event in the buffer and this is not the match
|
|
|
|
|
// continue in this function iteration to handle the buffer instead */
|
2012-10-05 07:41:46 +00:00
|
|
|
|
logstring(
|
|
|
|
|
"Inotify",
|
|
|
|
|
"icore, changing unary MOVE_FROM into DELETE"
|
2017-02-06 16:00:39 +00:00
|
|
|
|
);
|
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
after_buf = event;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event = move_event_buf;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-24 18:19:13 +00:00
|
|
|
|
event_type = "Delete";
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
move_event = false;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if(
|
2017-02-06 16:00:39 +00:00
|
|
|
|
move_event
|
|
|
|
|
&& ( IN_MOVED_TO & event->mask )
|
|
|
|
|
&& event->cookie == move_event_buf->cookie
|
|
|
|
|
)
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// this is indeed a matched move */
|
2010-11-24 18:19:13 +00:00
|
|
|
|
event_type = "Move";
|
2010-11-22 20:09:52 +00:00
|
|
|
|
move_event = false;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if( IN_MOVED_FROM & event->mask )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// just the MOVE_FROM, buffers this event, and wait if next event is
|
|
|
|
|
// a matching MOVED_TO of this was an unary move out of the watched
|
|
|
|
|
// tree.
|
2012-10-05 07:41:46 +00:00
|
|
|
|
size_t el = sizeof( struct inotify_event ) + event->len;
|
|
|
|
|
|
|
|
|
|
if( move_event_buf_size < el )
|
|
|
|
|
{
|
2010-11-22 20:09:52 +00:00
|
|
|
|
move_event_buf_size = el;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
move_event_buf = s_realloc( move_event_buf, el );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
memcpy( move_event_buf, event, el );
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
move_event = true;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if( IN_MOVED_TO & event->mask )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// must be an unary move-to
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event_type = CREATE;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if( IN_ATTRIB & event->mask )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// just attrib change
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event_type = ATTRIB;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if( ( IN_CLOSE_WRITE | IN_MODIFY) & event->mask )
|
|
|
|
|
{
|
2012-03-16 15:30:55 +00:00
|
|
|
|
// modify, or closed after written something
|
|
|
|
|
// the event type received depends settings.inotifyMode
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event_type = MODIFY;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if( IN_CREATE & event->mask )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// a new file
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event_type = CREATE;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else if( IN_DELETE & event->mask )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// rm'ed
|
2010-11-22 20:09:52 +00:00
|
|
|
|
event_type = DELETE;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
logstring( "Inotify", "skipped some inotify event.");
|
2010-11-22 20:09:52 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
// hands the event over to the runner
|
2018-03-15 08:27:14 +00:00
|
|
|
|
load_mci( L, "inotifyEvent" );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
if( !event_type )
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
logstring( "Error", "internal failure: unknown event in handle_event()" );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
exit( -1 );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
lua_pushstring( L, event_type );
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( event_type != MOVE )
|
|
|
|
|
{
|
|
|
|
|
lua_pushnumber( L, event->wd );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lua_pushnumber( L, move_event_buf->wd );
|
|
|
|
|
}
|
|
|
|
|
lua_pushboolean( L, ( event->mask & IN_ISDIR ) != 0 );
|
|
|
|
|
|
|
|
|
|
l_now( L );
|
|
|
|
|
|
|
|
|
|
if( event_type == MOVE )
|
|
|
|
|
{
|
|
|
|
|
lua_pushstring( L, move_event_buf->name );
|
|
|
|
|
lua_pushnumber( L, event->wd );
|
|
|
|
|
lua_pushstring( L, event->name );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lua_pushstring( L, event->name );
|
|
|
|
|
lua_pushnil( L );
|
|
|
|
|
lua_pushnil( L );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
2018-03-09 14:41:16 +00:00
|
|
|
|
if( lua_pcall( L, 7, 0, -9 ) ) exit( -1 );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
lua_pop( L, 1 );
|
2010-11-23 23:19:01 +00:00
|
|
|
|
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// if there is a buffered event, executes it
|
2018-03-13 11:29:43 +00:00
|
|
|
|
if (after_buf)
|
|
|
|
|
{
|
|
|
|
|
logstring( "Inotify", "icore, handling buffered event." );
|
|
|
|
|
handle_event( L, after_buf );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| buffer to read inotify events into
|
|
|
|
|
*/
|
2018-03-27 07:14:53 +00:00
|
|
|
|
static size_t readbuf_size = 4196;
|
2017-02-06 16:00:39 +00:00
|
|
|
|
|
2010-11-22 21:17:08 +00:00
|
|
|
|
static char * readbuf = NULL;
|
2010-11-22 20:09:52 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Called when the inotify file descriptor became ready.
|
|
|
|
|
| Reads it contents and forwards all received events
|
|
|
|
|
| to the runner.
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
static void
|
2012-10-05 07:41:46 +00:00
|
|
|
|
inotify_ready(
|
|
|
|
|
lua_State *L,
|
2018-03-28 07:17:49 +00:00
|
|
|
|
int fd,
|
|
|
|
|
void * extra
|
2012-10-05 07:41:46 +00:00
|
|
|
|
)
|
2010-11-22 20:09:52 +00:00
|
|
|
|
{
|
2012-10-05 07:41:46 +00:00
|
|
|
|
// sanity check
|
2018-03-28 07:17:49 +00:00
|
|
|
|
if( fd != inotify_fd )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
2018-03-09 14:41:16 +00:00
|
|
|
|
logstring( "Error", "internal failure, inotify_fd != obs->fd" );
|
2018-03-27 07:14:53 +00:00
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit( -1 );
|
2010-11-28 10:47:57 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
while( true )
|
|
|
|
|
{
|
2011-11-23 10:22:10 +00:00
|
|
|
|
ptrdiff_t len;
|
2010-11-23 23:19:01 +00:00
|
|
|
|
int err;
|
2018-03-13 11:29:43 +00:00
|
|
|
|
do
|
|
|
|
|
{
|
2012-10-05 07:41:46 +00:00
|
|
|
|
len = read( inotify_fd, readbuf, readbuf_size );
|
2010-11-23 23:19:01 +00:00
|
|
|
|
err = errno;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( len < 0 && err == EINVAL )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// kernel > 2.6.21 indicates that way that way that
|
|
|
|
|
// the buffer was too small to fit a filename.
|
|
|
|
|
// double its size and try again. When using a lower
|
|
|
|
|
// kernel and a filename > 2KB appears lsyncd
|
|
|
|
|
// will fail. (but does a 2KB filename really happen?)
|
|
|
|
|
//
|
2010-11-22 20:09:52 +00:00
|
|
|
|
readbuf_size *= 2;
|
|
|
|
|
readbuf = s_realloc(readbuf, readbuf_size);
|
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
} while( len < 0 && err == EINVAL );
|
|
|
|
|
|
2018-03-27 07:14:53 +00:00
|
|
|
|
// no more inotify events
|
|
|
|
|
if( len == 0 ) break;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
if (len < 0)
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
if( err != EAGAIN )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
printlogf( L, "Error", "Read fail on inotify" );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit( -1 );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2018-03-13 11:29:43 +00:00
|
|
|
|
|
|
|
|
|
// nothing more on inotify
|
|
|
|
|
break;
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
2010-11-22 21:17:08 +00:00
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
2012-10-05 07:41:46 +00:00
|
|
|
|
while( i < len && !hup && !term )
|
|
|
|
|
{
|
2018-03-27 07:14:53 +00:00
|
|
|
|
struct inotify_event *event = ( struct inotify_event * ) ( readbuf + i );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
handle_event( L, event );
|
|
|
|
|
|
|
|
|
|
i += sizeof( struct inotify_event ) + event->len;
|
2010-11-22 21:17:08 +00:00
|
|
|
|
}
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
if( !move_event )
|
|
|
|
|
{
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// give it a pause if not endangering splitting a move
|
2010-11-22 20:09:52 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2010-11-22 21:17:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-16 15:49:34 +00:00
|
|
|
|
// checks if there is an unary MOVE_FROM left in the buffer
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( move_event )
|
|
|
|
|
{
|
2018-03-27 07:14:53 +00:00
|
|
|
|
logstring( "Inotify", "handling unary move from." );
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
handle_event( L, NULL );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Registers the inotify functions.
|
2018-03-13 11:29:43 +00:00
|
|
|
|
|
|
|
|
|
|
| Leaves a table of the inotify functions on Lua stack.
|
2012-10-05 07:41:46 +00:00
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
extern void
|
2012-10-05 07:41:46 +00:00
|
|
|
|
register_inotify( lua_State *L )
|
2010-12-01 16:12:15 +00:00
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
lua_newtable( L );
|
|
|
|
|
luaL_setfuncs( L, inotifylib, 0 );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
| Cleans up the inotify handling.
|
|
|
|
|
*/
|
2010-11-28 09:15:54 +00:00
|
|
|
|
static void
|
2018-03-28 07:17:49 +00:00
|
|
|
|
inotify_tidy( int fd, void * extra )
|
2010-12-01 16:12:15 +00:00
|
|
|
|
{
|
2018-03-28 07:17:49 +00:00
|
|
|
|
if( fd != inotify_fd )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
logstring( "Error", "internal failure: inotify_fd != ob->fd" );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit( -1 );
|
2010-11-28 09:15:54 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
close( inotify_fd );
|
|
|
|
|
free( readbuf );
|
2018-03-27 07:14:53 +00:00
|
|
|
|
|
2010-11-28 09:15:54 +00:00
|
|
|
|
readbuf = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2012-10-05 07:41:46 +00:00
|
|
|
|
/*
|
|
|
|
|
| Initalizes inotify handling
|
|
|
|
|
*/
|
2010-11-22 20:09:52 +00:00
|
|
|
|
extern void
|
2012-10-05 07:41:46 +00:00
|
|
|
|
open_inotify( lua_State *L )
|
2010-12-01 16:12:15 +00:00
|
|
|
|
{
|
2012-10-05 07:41:46 +00:00
|
|
|
|
if( readbuf )
|
|
|
|
|
{
|
2018-03-13 11:29:43 +00:00
|
|
|
|
logstring( "Error", "internal failure, inotify readbuf != NULL in open_inotify()" )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
exit(-1);
|
2010-11-22 21:17:08 +00:00
|
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
readbuf = s_malloc( readbuf_size );
|
|
|
|
|
|
|
|
|
|
inotify_fd = inotify_init( );
|
|
|
|
|
|
|
|
|
|
if( inotify_fd < 0 )
|
|
|
|
|
{
|
|
|
|
|
printlogf(
|
2018-03-13 11:29:43 +00:00
|
|
|
|
L, "Error",
|
|
|
|
|
"Cannot access inotify monitor! ( %d : %s )", errno, strerror( errno )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
);
|
|
|
|
|
exit( -1 );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-13 11:29:43 +00:00
|
|
|
|
printlogf( L, "Inotify", "inotify fd = %d", inotify_fd );
|
2012-10-05 07:41:46 +00:00
|
|
|
|
|
|
|
|
|
close_exec_fd( inotify_fd );
|
|
|
|
|
non_block_fd( inotify_fd );
|
2018-03-27 07:14:53 +00:00
|
|
|
|
|
2018-03-09 14:41:16 +00:00
|
|
|
|
observe_fd( inotify_fd, inotify_ready, NULL, inotify_tidy, NULL );
|
2010-11-22 20:09:52 +00:00
|
|
|
|
}
|
|
|
|
|
|