diff --git a/CMakeLists.txt b/CMakeLists.txt index 0286cdb4..ea8ac60d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,13 +25,10 @@ endif( WITH_INOTIFY ) if( WITH_FSEVENTS ) set( LSYNCD_SRC ${LSYNCD_SRC} fsevents.c ) - option( XNU_DIR "Path to the xnu sources" ) - -# if( NOT XNU_DIR/bsd/sys/fsevents.h ) -# message( SEND_ERROR "Cannot find bsd/sys/fsevents.h in XNU_DIR" ) -# endif( ) - - include_directories( ${XNU_DIR} ) + FIND_LIBRARY( CORE_FOUNDATION_LIBRARY CoreFoundation ) + FIND_LIBRARY( CORE_SERVICES_LIBRARY CoreServices ) + MARK_AS_ADVANCED ( CORE_FOUNDATION_LIBRARY CORE_SERVICES_LIBRARY ) + SET( EXTRA_LIBS ${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ) endif( WITH_FSEVENTS ) @@ -103,7 +100,7 @@ add_custom_target( tests # compiling and linking it all together add_executable( lsyncd ${LSYNCD_SRC} ) -target_link_libraries( lsyncd ${LUA_LIBRARIES} ) +target_link_libraries( lsyncd ${LUA_LIBRARIES} ${EXTRA_LIBS} ) install( TARGETS lsyncd RUNTIME DESTINATION bin ) install( FILES doc/manpage/lsyncd.1 DESTINATION man ) diff --git a/fsevents.c b/fsevents.c index d01bafe0..4acba5cf 100644 --- a/fsevents.c +++ b/fsevents.c @@ -28,17 +28,23 @@ */ #include "lsyncd.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bsd/sys/fsevents.h" +#include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #include "bsd/sys/fsevents.h" + +#include "fsevents.h" + +#include +#include #include #include @@ -46,237 +52,263 @@ /* the fsevents pseudo-device */ -#define DEV_FSEVENTS "/dev/fsevents" +// #define DEV_FSEVENTS "/dev/fsevents" -/* buffer for reading from the device */ -#define FSEVENT_BUFSIZ 131072 +// /* buffer for reading from the device */ +// #define FSEVENT_BUFSIZ 131072 -/* limited by MAX_KFS_EVENTS */ -#define EVENT_QUEUE_SIZE 4096 +// /* limited by MAX_KFS_EVENTS */ +// #define EVENT_QUEUE_SIZE 4096 -#define KFS_NUM_ARGS FSE_MAX_ARGS +// #define KFS_NUM_ARGS FSE_MAX_ARGS -/* OS 10.5 structuce */ -/* an event argument */ -struct kfs_event_arg { - /* argument type */ - u_int16_t type; +// /* OS 10.5 structuce */ +// /* an event argument */ +// struct kfs_event_arg { +// /* argument type */ +// u_int16_t type; - /* size of argument data that follows this field */ - u_int16_t len; +// /* size of argument data that follows this field */ +// u_int16_t len; - union { - struct vnode *vp; - char *str; - void *ptr; - int32_t int32; - dev_t dev; - ino_t ino; - int32_t mode; - uid_t uid; - gid_t gid; - uint64_t timestamp; - } data; -}; +// union { +// struct vnode *vp; +// char *str; +// void *ptr; +// int32_t int32; +// dev_t dev; +// ino_t ino; +// int32_t mode; +// uid_t uid; +// gid_t gid; +// uint64_t timestamp; +// } data; +// }; -/* OS 10.5 structuce */ -/* an event */ -struct kfs_event { +// /* OS 10.5 structuce */ +// /* an event */ +// struct kfs_event { - /* event type */ - int32_t type; +// /* event type */ +// int32_t type; - /* pid of the process that performed the operation */ - pid_t pid; +// /* pid of the process that performed the operation */ +// pid_t pid; - /* event arguments */ - struct kfs_event_arg* args[FSE_MAX_ARGS]; -}; +// /* event arguments */ +// struct kfs_event_arg* args[FSE_MAX_ARGS]; +// }; /** * fsevents (cloned) filedescriptor */ static int fsevents_fd = -1; -/* event names */ -/*static const char *eventNames[FSE_MAX_EVENTS] = { - "CREATE_FILE", - "DELETE", - "STAT_CHANGED", - "RENAME", - "CONTENT_MODIFIED", - "EXCHANGE", - "FINDER_INFO_CHANGED", - "CREATE_DIR", - "CHOWN", - "XATTR_MODIFIED", - "XATTR_REMOVED", -};*/ - -/* argument names*/ -/*static const char *argNames[] = { - "UNKNOWN", - "VNODE", - "STRING", - "PATH", - "INT32", - "INT64", - "RAW", - "INO", - "UID", - "DEV", - "MODE", - "GID", - "FINFO", -};*/ - -/** - * The read buffer - */ -static size_t const readbuf_size = 131072; -static char * readbuf = NULL; +CFRunLoopRef rl = NULL; + +// /* event names */ +// static const char *eventNames[FSE_MAX_EVENTS] = { +// "CREATE_FILE", +// "DELETE", +// "STAT_CHANGED", +// "RENAME", +// "CONTENT_MODIFIED", +// "EXCHANGE", +// "FINDER_INFO_CHANGED", +// "CREATE_DIR", +// "CHOWN", +// "XATTR_MODIFIED", +// "XATTR_REMOVED", +// }; + +// /* argument names*/ +// /*static const char *argNames[] = { +// "UNKNOWN", +// "VNODE", +// "STRING", +// "PATH", +// "INT32", +// "INT64", +// "RAW", +// "INO", +// "UID", +// "DEV", +// "MODE", +// "GID", +// "FINFO", +// };*/ + +// /** +// * The read buffer +// */ +// static size_t const readbuf_size = 131072; +// static char * readbuf = NULL; + +// /** +// * The event buffer +// */ +// static size_t const eventbuf_size = FSEVENT_BUFSIZ; +// static char* eventbuf = NULL; + +// /** +// * Handles one fsevents event +// */ +// static void +// handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) +// { +// int32_t atype; +// const char *path = NULL; +// const char *trg = NULL; +// const char *etype = NULL; +// int isdir = -1; + +// if (event->type == FSE_EVENTS_DROPPED) { +// logstring("Fsevents", "Events dropped!"); +// load_runner_func(L, "overflow"); +// if (lua_pcall(L, 0, 0, -2)) { +// exit(-1); // ERRNO +// } +// lua_pop(L, 1); +// hup = 1; +// return; +// } + +// atype = event->type & FSE_TYPE_MASK; +// uint32_t aflags = FSE_GET_FLAGS(event->type); + +// // if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) { +// // printlogf(L, "Fsevents", "got event %s", eventNames[atype]); +// // if (aflags & FSE_COMBINED_EVENTS) { +// // logstring("Fsevents", "combined events"); +// // } +// // if (aflags & FSE_CONTAINS_DROPPED_EVENTS) { +// // logstring("Fsevents", "contains dropped events"); +// // } +// // } else { +// // printlogf(L, "Error", "unknown event(%d) in fsevents.", atype); +// // exit(-1); // ERRNO +// // } + +// if (atype >= FSE_MAX_EVENTS || atype < -1) { +// printlogf(L, "Error", "unknown event(%d) in fsevents.", atype); + +// if (aflags & FSE_COMBINED_EVENTS) { +// printlogf(L, "Error", "Fsevents: combined events"); +// } + +// if (aflags & FSE_CONTAINS_DROPPED_EVENTS) { +// printlogf(L, "Error", "Fsevents: contains dropped events"); +// } + +// exit(-1); // ERRNO +// } + +// { +// /* assigns the expected arguments */ +// int whichArg = 0; +// while (whichArg < FSE_MAX_ARGS) { +// struct kfs_event_arg * arg = event->args[whichArg++]; +// if (arg->type == FSE_ARG_DONE) { +// break; +// } + +// switch (arg->type) { +// case FSE_ARG_STRING : +// switch(atype) { +// case FSE_RENAME : +// if (path) { +// // for move events second string is target +// trg = (char *) &arg->data.str; +// } +// // fallthrough +// case FSE_CHOWN : +// case FSE_CONTENT_MODIFIED : +// case FSE_CREATE_FILE : +// case FSE_CREATE_DIR : +// case FSE_DELETE : +// case FSE_STAT_CHANGED : +// if (!path) path = (char *)&arg->data.str; +// break; +// } +// break; +// case FSE_ARG_MODE : +// switch(atype) { +// case FSE_RENAME : +// case FSE_CHOWN : +// case FSE_CONTENT_MODIFIED : +// case FSE_CREATE_FILE : +// case FSE_CREATE_DIR : +// case FSE_DELETE : +// case FSE_STAT_CHANGED : +// isdir = arg->data.mode & S_IFDIR ? 1 : 0; +// break; +// } +// break; +// } +// } +// } + +// switch(atype) { +// case FSE_CHOWN : +// case FSE_STAT_CHANGED : +// etype = "Attrib"; +// break; +// case FSE_CREATE_DIR : +// case FSE_CREATE_FILE : +// etype = "Create"; +// break; +// case FSE_DELETE : +// etype = "Delete"; +// break; +// case FSE_RENAME : +// etype = "Move"; +// break; +// case FSE_CONTENT_MODIFIED : +// etype = "Modify"; +// break; +// } + +// if (etype) { +// if (!path) { +// printlogf(L, "Error", "Internal fail, fsevents, no path."); +// printlogf(L, "Error", "atype (%d), etype (%s)", atype, etype); +// exit(-1); +// } +// if (isdir < 0) { +// printlogf(L, "Error", "Internal fail, fsevents, neither dir nor file."); +// exit(-1); +// } +// load_runner_func(L, "fsEventsEvent"); +// lua_pushstring(L, etype); +// lua_pushboolean(L, isdir); +// l_now(L); +// lua_pushstring(L, path); +// if (trg) { +// lua_pushstring(L, trg); +// } else { +// lua_pushnil(L); +// } + +// if (lua_pcall(L, 5, 0, -7)) { +// exit(-1); // ERRNO +// } +// lua_pop(L, 1); +// } +// } -/** - * The event buffer - */ -static size_t const eventbuf_size = FSEVENT_BUFSIZ; -static char* eventbuf = NULL; -/** - * Handles one fsevents event - */ static void -handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) +handle_event(file_paths_t *file_paths, char *path) { - int32_t atype; - const char *path = NULL; - const char *trg = NULL; - const char *etype = NULL; - int isdir = -1; - - if (event->type == FSE_EVENTS_DROPPED) { - logstring("Fsevents", "Events dropped!"); - load_runner_func(L, "overflow"); - if (lua_pcall(L, 0, 0, -2)) { - exit(-1); // ERRNO - } - lua_pop(L, 1); - hup = 1; - return; - } - - atype = event->type & FSE_TYPE_MASK; - /*uint32_t aflags = FSE_GET_FLAGS(event->type);*/ - - if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) { - /*printlogf(L, "Fsevents", "got event %s", eventNames[atype]); - if (aflags & FSE_COMBINED_EVENTS) { - logstring("Fsevents", "combined events"); - } - if (aflags & FSE_CONTAINS_DROPPED_EVENTS) { - logstring("Fsevents", "contains dropped events"); - }*/ - } else { - printlogf( - L, - "Error", - "unknown event(%d) in fsevents.", - atype - ); - - exit(-1); // ERRNO - } - - { - /* assigns the expected arguments */ - int whichArg = 0; - while (whichArg < FSE_MAX_ARGS) { - struct kfs_event_arg * arg = event->args[whichArg++]; - if (arg->type == FSE_ARG_DONE) { - break; - } - - switch (arg->type) { - case FSE_ARG_STRING : - switch(atype) { - case FSE_RENAME : - if (path) { - // for move events second string is target - trg = (char *) &arg->data.str; - } - // fallthrough - case FSE_CHOWN : - case FSE_CONTENT_MODIFIED : - case FSE_CREATE_FILE : - case FSE_CREATE_DIR : - case FSE_DELETE : - case FSE_STAT_CHANGED : - if (!path) path = (char *)&arg->data.str; - break; - } - break; - case FSE_ARG_MODE : - switch(atype) { - case FSE_RENAME : - case FSE_CHOWN : - case FSE_CONTENT_MODIFIED : - case FSE_CREATE_FILE : - case FSE_CREATE_DIR : - case FSE_DELETE : - case FSE_STAT_CHANGED : - isdir = arg->data.mode & S_IFDIR ? 1 : 0; - break; - } - break; - } - } - } - - switch(atype) { - case FSE_CHOWN : - case FSE_STAT_CHANGED : - etype = "Attrib"; - break; - case FSE_CREATE_DIR : - case FSE_CREATE_FILE : - etype = "Create"; - break; - case FSE_DELETE : - etype = "Delete"; - break; - case FSE_RENAME : - etype = "Move"; - break; - case FSE_CONTENT_MODIFIED : - etype = "Modify"; - break; - } - - if (etype) { - if (!path) { - printlogf(L, "Error", "Internal fail, fsevents, no path."); - exit(-1); - } - if (isdir < 0) { - printlogf(L, "Error", "Internal fail, fsevents, neither dir nor file."); - exit(-1); - } - load_runner_func(L, "fsEventsEvent"); - lua_pushstring(L, etype); - lua_pushboolean(L, isdir); - l_now(L); - lua_pushstring(L, path); - if (trg) { - lua_pushstring(L, trg); - } else { - lua_pushnil(L); - } - - if (lua_pcall(L, 5, 0, -7)) { - exit(-1); // ERRNO - } - lua_pop(L, 1); - } + printf("adding %s length %lu size %lu\n", path, (unsigned long)file_paths->len, (unsigned long)file_paths->size); + + if (file_paths->len == file_paths->size) { + file_paths->size = file_paths->size * 1.5; + file_paths->paths = realloc(file_paths->paths, file_paths->size * sizeof(char *)); + } + + file_paths->paths[file_paths->len] = strdup(path); + file_paths->len++; } /** @@ -285,77 +317,80 @@ handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen) static void fsevents_ready(lua_State *L, struct observance *obs) { - if (obs->fd != fsevents_fd) { - logstring("Error", "Internal, fsevents_fd != ob->fd"); - exit(-1); // ERRNO - } - - ptrdiff_t len = read (fsevents_fd, readbuf, readbuf_size); - int err = errno; - if (len == 0) { - return; - } - if (len < 0) { - if (err == EAGAIN) { - /* nothing more */ - return; - } else { - printlogf(L, "Error", "Read fail on fsevents"); - exit(-1); // ERRNO - } - } - { - int off = 0; - while (off < len && !hup && !term) { - /* deals with alignment issues on 64 bit by copying data bit by bit */ - struct kfs_event* event = (struct kfs_event *) eventbuf; - event->type = *(int32_t*)(readbuf+off); - off += sizeof(int32_t); - event->pid = *(pid_t*)(readbuf+off); - off += sizeof(pid_t); - /* arguments */ - int whichArg = 0; - int eventbufOff = sizeof(struct kfs_event); - size_t ptrSize = sizeof(void*); - if ((eventbufOff % ptrSize) != 0) { - eventbufOff += ptrSize-(eventbufOff%ptrSize); - } - while (off < len && whichArg < FSE_MAX_ARGS) { - /* assign argument pointer to eventbuf based on - known current offset into eventbuf */ - uint16_t argLen = 0; - event->args[whichArg] = (struct kfs_event_arg *) (eventbuf + eventbufOff); - /* copy type */ - uint16_t argType = *(uint16_t*)(readbuf + off); - event->args[whichArg]->type = argType; - off += sizeof(uint16_t); - if (argType == FSE_ARG_DONE) { - /* done */ - break; - } else { - /* copy data length */ - argLen = *(uint16_t *)(readbuf + off); - event->args[whichArg]->len = argLen; - off += sizeof(uint16_t); - /* copy data */ - memcpy(&(event->args[whichArg]->data), readbuf + off, argLen); - off += argLen; - } - /* makes sure alignment is correct for 64 bit systems */ - size_t argStructLen = sizeof(uint16_t) + sizeof(uint16_t); - if ((argStructLen % ptrSize) != 0) { - argStructLen += ptrSize-(argStructLen % ptrSize); - } - argStructLen += argLen; - if ((argStructLen % ptrSize) != 0) { - argStructLen += ptrSize-(argStructLen % ptrSize); - } - eventbufOff += argStructLen; - whichArg++; - } - handle_event(L, event, len); - } - } + printlogf(L, "Warn", "Call fsevents_ready"); + printf("HERE fsevents_ready\n"); + +// if (obs->fd != fsevents_fd) { +// logstring("Error", "Internal, fsevents_fd != ob->fd"); +// exit(-1); // ERRNO +// } + +// ptrdiff_t len = read (fsevents_fd, readbuf, readbuf_size); +// int err = errno; +// if (len == 0) { +// return; +// } +// if (len < 0) { +// if (err == EAGAIN) { +// /* nothing more */ +// return; +// } else { +// printlogf(L, "Error", "Read fail on fsevents"); +// exit(-1); // ERRNO +// } +// } +// { +// int off = 0; +// while (off < len && !hup && !term) { +// /* deals with alignment issues on 64 bit by copying data bit by bit */ +// struct kfs_event* event = (struct kfs_event *) eventbuf; +// event->type = *(int32_t*)(readbuf+off); +// off += sizeof(int32_t); +// event->pid = *(pid_t*)(readbuf+off); +// off += sizeof(pid_t); +// /* arguments */ +// int whichArg = 0; +// int eventbufOff = sizeof(struct kfs_event); +// size_t ptrSize = sizeof(void*); +// if ((eventbufOff % ptrSize) != 0) { +// eventbufOff += ptrSize-(eventbufOff%ptrSize); +// } +// while (off < len && whichArg < FSE_MAX_ARGS) { +// /* assign argument pointer to eventbuf based on +// known current offset into eventbuf */ +// uint16_t argLen = 0; +// event->args[whichArg] = (struct kfs_event_arg *) (eventbuf + eventbufOff); +// /* copy type */ +// uint16_t argType = *(uint16_t*)(readbuf + off); +// event->args[whichArg]->type = argType; +// off += sizeof(uint16_t); +// if (argType == FSE_ARG_DONE) { +// /* done */ +// break; +// } else { +// /* copy data length */ +// argLen = *(uint16_t *)(readbuf + off); +// event->args[whichArg]->len = argLen; +// off += sizeof(uint16_t); +// /* copy data */ +// memcpy(&(event->args[whichArg]->data), readbuf + off, argLen); +// off += argLen; +// } +// /* makes sure alignment is correct for 64 bit systems */ +// size_t argStructLen = sizeof(uint16_t) + sizeof(uint16_t); +// if ((argStructLen % ptrSize) != 0) { +// argStructLen += ptrSize-(argStructLen % ptrSize); +// } +// argStructLen += argLen; +// if ((argStructLen % ptrSize) != 0) { +// argStructLen += ptrSize-(argStructLen % ptrSize); +// } +// eventbufOff += argStructLen; +// whichArg++; +// } +// handle_event(L, event, len); +// } +// } } /** @@ -364,77 +399,216 @@ fsevents_ready(lua_State *L, struct observance *obs) static void fsevents_tidy(struct observance *obs) { - if (obs->fd != fsevents_fd) { - logstring("Error", "Internal, fsevents_fd != ob->fd"); - exit(-1); // ERRNO - } - close(fsevents_fd); - free(readbuf); - readbuf = NULL; - free(eventbuf); - eventbuf = NULL; + printf("Call fsevents_tidy\n"); + +// if (obs->fd != fsevents_fd) { +// logstring("Error", "Internal, fsevents_fd != ob->fd"); +// exit(-1); // ERRNO +// } +// close(fsevents_fd); +// free(readbuf); +// readbuf = NULL; +// free(eventbuf); +// eventbuf = NULL; +} + +// /** +// * opens and initalizes fsevents. +// */ +// extern void +// open_fsevents(lua_State *L) +// { +// int8_t event_list[] = { // action to take for each event +// FSE_REPORT, // FSE_CREATE_FILE +// FSE_REPORT, // FSE_DELETE +// FSE_REPORT, // FSE_STAT_CHANGED +// FSE_REPORT, // FSE_RENAME +// FSE_REPORT, // FSE_CONTENT_MODIFIED +// FSE_REPORT, // FSE_EXCHANGE +// FSE_REPORT, // FSE_FINDER_INFO_CHANGED +// FSE_REPORT, // FSE_CREATE_DIR +// FSE_REPORT, // FSE_CHOWN +// FSE_REPORT, // FSE_XATTR_MODIFIED +// FSE_REPORT, // FSE_XATTR_REMOVED +// }; +// struct fsevent_clone_args fca = { +// .event_list = (int8_t *) event_list, +// .num_events = sizeof(event_list)/sizeof(int8_t), +// .event_queue_depth = EVENT_QUEUE_SIZE, +// .fd = &fsevents_fd, +// }; +// int fd = open(DEV_FSEVENTS, O_RDONLY); +// int err = errno; +// printlogf(L, "Warn", +// "Using /dev/fsevents which is considered an OSX internal interface."); +// printlogf(L, "Warn", +// "Functionality might break across OSX versions (This is for 10.5.X)"); +// printlogf(L, "Warn", +// "A hanging Lsyncd might cause Spotlight/Timemachine doing extra work."); + +// if (fd < 0) { +// printlogf(L, "Error", +// "Cannot access %s monitor! (%d:%s)", +// DEV_FSEVENTS, err, strerror(err)); +// exit(-1); // ERRNO +// } + +// if (ioctl(fd, FSEVENTS_CLONE, (char *)&fca) < 0) { +// printlogf(L, "Error", +// "Cannot control %s monitor! (%d:%s)", +// DEV_FSEVENTS, errno, strerror(errno)); +// exit(-1); // ERRNO +// } + +// if (readbuf) { +// logstring("Error", +// "internal fail, inotify readbuf!=NULL in open_inotify()") +// exit(-1); // ERRNO +// } +// readbuf = s_malloc(readbuf_size); +// eventbuf = s_malloc(eventbuf_size); +// // fd has been cloned, closes access fd +// close(fd); +// close_exec_fd(fsevents_fd); +// non_block_fd(fsevents_fd); +// observe_fd(fsevents_fd, fsevents_ready, NULL, fsevents_tidy, NULL); +// } + +void +event_callback( + ConstFSEventStreamRef streamRef, + void *ctx, + size_t count, + void *paths, + const FSEventStreamEventFlags flags[], + const FSEventStreamEventId ids[] +) +{ + printf("%s\n", "hit callback"); + + file_paths_t *file_paths = (file_paths_t *)ctx; + size_t i; + size_t ignored_paths = 0; + + printf("count of events %lu\n", count); + + for (i = 0; i < count; i++) { + char *path = ((char **)paths)[i]; + // uint64_t fd = ids[i]; + /* flags are unsigned long, IDs are uint64_t */ + printf("Change %llu in %s, flags %lu\n", ids[i], path, (long)flags[i]); + // size_t j; + + // close_exec_fd(ids[i]); + // non_block_fd(ids[i]); + printf("before observe_fd\n"); + observe_fd(ids[i], fsevents_ready, NULL, fsevents_tidy, NULL); + printf("after observe_fd\n"); + // printf("length: %l\n", file_paths->len); + // for (j = 0; j < file_paths->len; j++) { + // char *file_path = file_paths->paths[j]; + + // printf(" - file_path: %s\n", file_path); + // printf(" - path: %s\n", path); + + // if (strcmp(file_path, path) == 0) { + // printf(" - matched %s, notifying\n", file_path); + // } else { + // printf(" - ignoring\n"); + // ignored_paths++; + // } + // } + } + + + CFRunLoopStop(rl); + + // FSEventStreamStop((FSEventStreamRef)streamRef); + // FSEventStreamInvalidate((FSEventStreamRef)streamRef); + + /* Shut down if we aren't watching for files, or if files were changed that we + * didn't ignore. + */ + // if (file_paths->len == 0) { + // printf(" - matched directory, notifying\n"); + + // if (count > ignored_paths) { + // FSEventStreamStop((FSEventStreamRef)streamRef); + // FSEventStreamRelease((FSEventStreamRef)streamRef); + // exit(0); + // } + // } } -/** - * opens and initalizes fsevents. - */ extern void open_fsevents(lua_State *L) { - int8_t event_list[] = { // action to take for each event - FSE_REPORT, // FSE_CREATE_FILE - FSE_REPORT, // FSE_DELETE - FSE_REPORT, // FSE_STAT_CHANGED - FSE_REPORT, // FSE_RENAME - FSE_REPORT, // FSE_CONTENT_MODIFIED - FSE_REPORT, // FSE_EXCHANGE - FSE_REPORT, // FSE_FINDER_INFO_CHANGED - FSE_REPORT, // FSE_CREATE_DIR - FSE_REPORT, // FSE_CHOWN - FSE_REPORT, // FSE_XATTR_MODIFIED - FSE_REPORT, // FSE_XATTR_REMOVED - }; - struct fsevent_clone_args fca = { - .event_list = (int8_t *) event_list, - .num_events = sizeof(event_list)/sizeof(int8_t), - .event_queue_depth = EVENT_QUEUE_SIZE, - .fd = &fsevents_fd, - }; - int fd = open(DEV_FSEVENTS, O_RDONLY); - int err = errno; - printlogf(L, "Warn", - "Using /dev/fsevents which is considered an OSX internal interface."); - printlogf(L, "Warn", - "Functionality might break across OSX versions (This is for 10.5.X)"); - printlogf(L, "Warn", - "A hanging Lsyncd might cause Spotlight/Timemachine doing extra work."); - - if (fd < 0) { - printlogf(L, "Error", - "Cannot access %s monitor! (%d:%s)", - DEV_FSEVENTS, err, strerror(err)); - exit(-1); // ERRNO - } - - if (ioctl(fd, FSEVENTS_CLONE, (char *)&fca) < 0) { - printlogf(L, "Error", - "Cannot control %s monitor! (%d:%s)", - DEV_FSEVENTS, errno, strerror(errno)); - exit(-1); // ERRNO - } - - if (readbuf) { - logstring("Error", - "internal fail, inotify readbuf!=NULL in open_inotify()") - exit(-1); // ERRNO - } - readbuf = s_malloc(readbuf_size); - eventbuf = s_malloc(eventbuf_size); - // fd has been cloned, closes access fd - close(fd); - close_exec_fd(fsevents_fd); - non_block_fd(fsevents_fd); - observe_fd(fsevents_fd, fsevents_ready, NULL, fsevents_tidy, NULL); + printlogf( + L, + "Warn", + "initialize" + ); + + CFMutableArrayRef paths = CFArrayCreateMutable(NULL, 2, NULL); + CFStringRef cfs_path; + + file_paths_t *file_paths = malloc(sizeof(file_paths_t)); + file_paths->len = 0; + file_paths->size = 2; + file_paths->paths = malloc(file_paths->size * sizeof(char *)); + file_paths->L = L; + + // printlogf( + // L, + // "Warn", + // "initialize FSEventStreamContext" + // ); + + FSEventStreamContext ctx = { + 0, + file_paths, + NULL, + NULL, + NULL + }; + + int stat_value; + struct stat stat_data; + char *dir_path; + + dir_path = "/Users/vadim/projects/cw-dev-api"; + // stat_value = stat(dir_path, &stat_data); + + printlogf(L, "Warn", "stat: %d", stat_value); + + // if (stat_value < 0) { + // // File doesn't exist yet. Watch parent dir instead. + // stat_data.st_mode = S_IFREG; + // printlogf(L, "Warn", "hit here 1"); + // } + + // if (stat_data.st_mode & S_IFREG) { + // printlogf(L, "Warn", "hit here 2"); + // handle_event(file_paths, dir_path); + // } + handle_event(file_paths, dir_path); + + cfs_path = CFStringCreateWithCString(NULL, dir_path, kCFStringEncodingUTF8); + CFArrayAppendValue(paths, cfs_path); + + printlogf(L, "Warn", "create FSEventStreamRef"); + + FSEventStreamRef stream; + FSEventStreamCreateFlags flags = kFSEventStreamCreateFlagFileEvents; + + printlogf(L, "Warn", "paths: %d", (int32_t)sizeof(paths)); + + stream = FSEventStreamCreate(NULL, &event_callback, &ctx, paths, kFSEventStreamEventIdSinceNow, 0, flags); + rl = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(stream, rl, kCFRunLoopDefaultMode); + FSEventStreamStart(stream); + + printlogf(L, "Warn", "before loop run"); + + CFRunLoopRun(); } - - diff --git a/fsevents.h b/fsevents.h new file mode 100644 index 00000000..40d53b31 --- /dev/null +++ b/fsevents.h @@ -0,0 +1,24 @@ +#include +#include + +typedef struct { + size_t len; + size_t size; + char **paths; + lua_State *L; +} file_paths_t; + + +static void handle_event( + file_paths_t *file_paths, + char *path +); + +void event_callback( + ConstFSEventStreamRef streamRef, + void *ctx, + size_t count, + void *paths, + const FSEventStreamEventFlags flags[], + const FSEventStreamEventId ids[] +); diff --git a/lsyncd.c b/lsyncd.c index 746f2d4d..eb41a9b5 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -1176,7 +1176,7 @@ l_exec( lua_State *L ) // replaces midfile 0 chars by linefeed size_t len = 0; const char * cs = lua_tolstring( L, -1, &len ); - char * s = s_calloc( len + 1, sizeof( char ) ); + char * s = s_calloc( len + 1, sizeof( char ) ); for( i = 0; i < len; i++ ) {