pax_global_header00006660000000000000000000000064126234430530014514gustar00rootroot0000000000000052 comment=c04d5d1ca2a206030209fe69890ba2481daa8ab2 linotify-master/000077500000000000000000000000001262344305300142065ustar00rootroot00000000000000linotify-master/.gitignore000066400000000000000000000000111262344305300161660ustar00rootroot00000000000000*.o *.so linotify-master/COPYRIGHT000066400000000000000000000020641262344305300155030ustar00rootroot00000000000000Copyright (c) 2009-2014 Robert Hoelz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. linotify-master/Changes000066400000000000000000000013041262344305300154770ustar00rootroot000000000000000.4 2014 May 25 - Add getfd as an alias for fileno. 0.3 2014 Apr 02 - Remove deprecated global proxy table for library. Module now completely follows 5.2 module conventions. - Add interface for enabling non-blocking handles - Document fileno method 0.2 2012 Dec 28 - Issue a deprecation warning when using _G.inotify. Make sure you use the return value of require 'inotify' for your library calls! - Documentation improvements (thanks to Craig Barnes) - Add iterator interface to inotify handles - Add __type metafield for typical and other type libraries. 0.1 2012 Sep 18 - Initial release. linotify-master/Makefile000066400000000000000000000021061262344305300156450ustar00rootroot00000000000000 SRCNAME = linotify.c OBJNAME = linotify.o LIBNAME = inotify.so # Gives a nice speedup but also spoils debugging on x86. Comment # out this line when debugging. OMIT_FRAME_POINTER = -fomit-frame-pointer # Seach for lua .pc file LUAPKG_CMD = $(shell pkg-config --list-all | grep Lua | awk 'FNR == 1 {print $$1}') CFLAGS = -fPIC -O3 -Wall $(shell pkg-config "$(LUAPKG_CMD)" --cflags) LFLAGS = -shared $(OMIT_FRAME_POINTER) INSTALL_PATH = $(shell pkg-config "$(LUAPKG_CMD)" --variable=INSTALL_CMOD) ## If your system doesn't have pkg-config, comment out the previous ## lines and uncomment and change the following ones according to your ## building enviroment. #CFLAGS = -I/usr/include/lua5.1/ -fPIC -O3 -Wall #LFLAGS = -shared $(OMIT_FRAME_POINTER) #INSTALL_PATH = /usr/lib/lua/5.1 all: $(LIBNAME) $(OBJNAME): $(SRCNAME) $(CC) -o $(OBJNAME) -c $(SRCNAME) $(CFLAGS) $(LIBNAME): $(OBJNAME) $(CC) -o $(LIBNAME) -shared $(OBJNAME) $(LFLAGS) install: $(LIBNAME) install -D -s $(LIBNAME) $(DESTDIR)$(INSTALL_PATH)/$(LIBNAME) clean: $(RM) $(LIBNAME) $(OBJNAME) .PHONY: all install clean linotify-master/README.md000066400000000000000000000074521262344305300154750ustar00rootroot00000000000000linotify ======== A Lua binding for the Linux inotify library Building -------- To build `inotify.so`, simply type `make`. Usage ----- All of the constants are contained in the `inotify` table returned by require. Constants are named after their counterparts in the C header file (for example: `inotify.IN_ACCESS`). The only function to be found in the inotify table is `init`, which returns an inotify handle. `init` can optionally take a table a single argument. This table should contain attributes for the inotify handle's creation. The supported attributes are: * **blocking** - If set to false, the I/O operations performed on this inotify handle are non-blocking. Otherwise, they are blocking. Inotify handles have a variety of methods: ### handle:read() Reads events from the handle, returning a table. Each element of the table is itself a table, with the members of the `inotify_event` struct as its keys and values (except for len). If the handle is in non-blocking mode and no events are available, an empty table is returned. If an error occurs, `nil`, the error message, and errno are returned. ### handle:events() Returns an iterator that reads events from the handle, one at a time. Each value yielded from the iterator is a table with the members of the `inotify_event` struct as its keys and values (except for len). If an error occurs during reading, an error is thrown. If this method is run on a handle in non-blocking mode, it will yield events until no more events are available without blocking. ### handle:close() Closes the inotify event handle. This is done automatically on garbage collection. ### handle:addwatch(path, [event_masks...]) Adds a watch on `event_masks` for the file located at path, returning a watch identifier on success, and the traditional `nil, error, errno` triplet on error. `event_masks` is a variadic sequence of integer constants, taken from `inotify.IN_*`. All of the values in `event_masks` are OR'd together but this can also be done manually with `bit.bor()`. The following two examples are equivalent: ```lua -- Event masks passed as arguments local handle = inotify.init() local wd = handle:addwatch('/tmp/foo/', inotify.IN_CREATE, inotify.IN_MOVE) -- Event masks passed as a single, manually OR'd variable local handle = inotify.init() local options = bit.bor(inotify.IN_CREATE, inotify.IN_MOVE) local wd = handle:addwatch('/tmp/foo/', options) ``` ### handle:rmwatch(watchid) Removes the watch specified by watchid from the list of watches for this inotify handle. Returns true on success, and `nil, error, errno` on error. ### handle:fileno() Returns the integer file descriptor for the given handle. Useful when used in combination with an event loop. ### handle:getfd() Alias for [handle:fileno()](#handlefileno). Example ------- ```lua local inotify = require 'inotify' local handle = inotify.init() -- Watch for new files and renames local wd = handle:addwatch('/home/rob/', inotify.IN_CREATE, inotify.IN_MOVE) local events = handle:read() for _, ev in ipairs(events) do print(ev.name .. ' was created or renamed') end -- Done automatically on close, I think, but kept to be thorough handle:rmwatch(wd) handle:close() ``` Example (Iterator) ------------------ ```lua local inotify = require 'inotify' local handle = inotify.init() -- Watch for new files and renames local wd = handle:addwatch('/home/rob/', inotify.IN_CREATE, inotify.IN_MOVE) for ev in handle:events() do print(ev.name .. ' was created or renamed') end -- Done automatically on close, I think, but kept to be thorough handle:rmwatch(wd) handle:close() ``` No More Global Table ------------------- As of version 0.3, the global `inotify` table has been completely removed. You now need to handle the return value from `require`, like so: ```lua local inotify = require 'inotify' ``` linotify-master/inotify-0.4-1.rockspec000066400000000000000000000013131262344305300200550ustar00rootroot00000000000000package = "inotify" version = "0.4-1" source = { url = 'https://github.com/hoelzro/linotify/archive/0.4.tar.gz', dir = 'linotify-0.4', } description = { summary = "Inotify bindings for Lua", homepage = "http://hoelz.ro/projects/linotify", license = "MIT" } dependencies = { "lua >= 5.1" } external_dependencies = { INOTIFY = { header = "sys/inotify.h" } } build = { type = "builtin", modules = { inotify = { sources = {"linotify.c"}, incdirs = {"$(INOTIFY_INCDIR)"}, libdirs = {"$(INOTIFY_LIBDIR)"} } } } linotify-master/linotify.c000066400000000000000000000166041262344305300162160ustar00rootroot00000000000000/* * Copyright (c) 2009-2014 Robert Hoelz * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #define MT_NAME "INOTIFY_HANDLE" #define READ_BUFFER_SIZE 1024 struct inotify_context { char buffer[READ_BUFFER_SIZE]; int offset; int bytes_remaining; }; void push_inotify_handle(lua_State *L, int fd) { int *udata = (int *) lua_newuserdata(L, sizeof(int)); *udata = fd; luaL_getmetatable(L, MT_NAME); lua_setmetatable(L, -2); } int get_inotify_handle(lua_State *L, int index) { return *((int *) luaL_checkudata(L, index, MT_NAME)); } static int handle_error(lua_State *L) { lua_pushnil(L); lua_pushstring(L, strerror(errno)); lua_pushinteger(L, errno); return 3; } static int init(lua_State *L) { int fd; int flags = 0; if(lua_type(L, 1) == LUA_TTABLE) { lua_getfield(L, 1, "blocking"); if(lua_type(L, -1) != LUA_TNIL && !lua_toboolean(L, -1)) { flags |= IN_NONBLOCK; } lua_pop(L, 1); } if((fd = inotify_init1(flags)) == -1) { return handle_error(L); } else { push_inotify_handle(L, fd); return 1; } } static int handle_fileno(lua_State *L) { lua_pushinteger(L, get_inotify_handle(L, 1)); return 1; } static void push_inotify_event(lua_State *L, struct inotify_event *ev) { lua_createtable(L, 0, 4); lua_pushinteger(L, ev->wd); lua_setfield(L, -2, "wd"); lua_pushinteger(L, ev->mask); lua_setfield(L, -2, "mask"); lua_pushinteger(L, ev->cookie); lua_setfield(L, -2, "cookie"); if(ev->len) { lua_pushstring(L, ev->name); lua_setfield(L, -2, "name"); } } static int handle_read(lua_State *L) { int fd; int i = 0; int n = 1; ssize_t bytes; struct inotify_event *iev; char buffer[1024]; fd = get_inotify_handle(L, 1); if((bytes = read(fd, buffer, 1024)) < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK) { lua_newtable(L); return 1; } return handle_error(L); } lua_newtable(L); while(bytes >= sizeof(struct inotify_event)) { iev = (struct inotify_event *) (buffer + i); push_inotify_event(L, iev); lua_rawseti(L, -2, n++); i += (sizeof(struct inotify_event) + iev->len); bytes -= (sizeof(struct inotify_event) + iev->len); } return 1; } static int handle_events_iterator(lua_State *L) { struct inotify_context *context; struct inotify_event *event; int fd; fd = get_inotify_handle(L, 1); context = lua_touserdata(L, lua_upvalueindex(1)); if(context->bytes_remaining < sizeof(struct inotify_event)) { context->offset = 0; if((context->bytes_remaining = read(fd, context->buffer, READ_BUFFER_SIZE)) < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK) { lua_pushnil(L); return 1; } return luaL_error(L, "read error: %s\n", strerror(errno)); } } event = (struct inotify_event *) (context->buffer + context->offset); context->bytes_remaining -= (sizeof(struct inotify_event) + event->len); context->offset += (sizeof(struct inotify_event) + event->len); push_inotify_event(L, event); return 1; } static int handle_events(lua_State *L) { struct inotify_context *context; context = lua_newuserdata(L, sizeof(struct inotify_context)); memset(context, 0, sizeof(struct inotify_context)); lua_pushcclosure(L, handle_events_iterator, 1); lua_pushvalue(L, 1); return 2; } static int handle_close(lua_State *L) { int fd = get_inotify_handle(L, 1); close(fd); return 0; } static int handle_add_watch(lua_State *L) { int fd; int wd; int top; int i; const char *path; uint32_t mask = 0; fd = get_inotify_handle(L, 1); path = luaL_checkstring(L, 2); top = lua_gettop(L); for(i = 3; i <= top; i++) { mask |= luaL_checkinteger(L, i); } if((wd = inotify_add_watch(fd, path, mask)) == -1) { return handle_error(L); } else { lua_pushinteger(L, wd); return 1; } } static int handle_rm_watch(lua_State *L) { int fd; int wd; fd = get_inotify_handle(L, 1); wd = luaL_checkinteger(L, 2); if(inotify_rm_watch(fd, wd) == -1) { return handle_error(L); } lua_pushboolean(L, 1); return 1; } static int handle__gc(lua_State *L) { return handle_close(L); } static luaL_Reg inotify_funcs[] = { {"init", init}, {NULL, NULL} }; static luaL_Reg handle_funcs[] = { {"read", handle_read}, {"close", handle_close}, {"addwatch", handle_add_watch}, {"rmwatch", handle_rm_watch}, {"fileno", handle_fileno}, {"getfd", handle_fileno}, {"events", handle_events}, {NULL, NULL} }; #define register_constant(s)\ lua_pushinteger(L, s);\ lua_setfield(L, -2, #s); int luaopen_inotify(lua_State *L) { luaL_newmetatable(L, MT_NAME); lua_createtable(L, 0, sizeof(handle_funcs) / sizeof(luaL_Reg) - 1); #if LUA_VERSION_NUM > 501 luaL_setfuncs(L, handle_funcs, 0); #else luaL_register(L, NULL, handle_funcs); #endif lua_setfield(L, -2, "__index"); lua_pushcfunction(L, handle__gc); lua_setfield(L, -2, "__gc"); lua_pushliteral(L, "inotify_handle"); lua_setfield(L, -2, "__type"); lua_pop(L, 1); lua_newtable(L); #if LUA_VERSION_NUM > 501 luaL_setfuncs(L, inotify_funcs,0); #else luaL_register(L, NULL, inotify_funcs); #endif register_constant(IN_ACCESS); register_constant(IN_ATTRIB); register_constant(IN_CLOSE_WRITE); register_constant(IN_CLOSE_NOWRITE); register_constant(IN_CREATE); register_constant(IN_DELETE); register_constant(IN_DELETE_SELF); register_constant(IN_MODIFY); register_constant(IN_MOVE_SELF); register_constant(IN_MOVED_FROM); register_constant(IN_MOVED_TO); register_constant(IN_OPEN); register_constant(IN_ALL_EVENTS); register_constant(IN_MOVE); register_constant(IN_CLOSE); register_constant(IN_DONT_FOLLOW); register_constant(IN_MASK_ADD); register_constant(IN_ONESHOT); register_constant(IN_ONLYDIR); register_constant(IN_IGNORED); register_constant(IN_ISDIR); register_constant(IN_Q_OVERFLOW); register_constant(IN_UNMOUNT); return 1; }