Skip to content
Permalink
Browse files

init

  • Loading branch information...
dividuum committed Jan 29, 2012
0 parents commit 870b4cc6930afd18ddf5cc37c88136d02be90311
Showing with 1,653 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +12 −0 Makefile
  3. +211 −0 main.c
  4. +905 −0 uthash.h
  5. +522 −0 utlist.h
@@ -0,0 +1,3 @@
*.o
gpn-info
data/
@@ -0,0 +1,12 @@
CFLAGS=-I/usr/include/lua5.1
LDFLAGS=-llua5.1 -levent -lglfw

all: gpn-info

gpn-info: main.o
$(CC) -o $@ $^ $(LDFLAGS)

.PHONY: clean

clean:
rm -f *.o gpn-info
211 main.c
@@ -0,0 +1,211 @@
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>


#include <sys/inotify.h>

#include <GL/glfw.h>
#include <event.h>
#include <lualib.h>
#include <lauxlib.h>

#include "uthash.h"

#define MAX_MEM 2000 // KB
#define MIN_DELTA 500 // ms
#define MAX_DELTA 2000 // ms

struct node_s {
int wd; // inotify watch descriptor
int prio;
const char *name;
const char *path;
struct node_s *childs;
struct node_s *parent;
lua_State *L;
int enforce_mem;
UT_hash_handle by_wd;
};

typedef struct node_s node_t;

static node_t *nodes = NULL;

static node_t root;
static int inotify_fd;

static void die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
printf("CRITICAL ERROR: ");
vprintf(fmt, ap);
printf("\n");
va_end(ap);
exit(1);
}

static void *xmalloc(size_t size) {
void *ptr = calloc(1, size);
if (!ptr) die("cannot malloc");
return ptr;
}

static void node_init(node_t *node, node_t *parent, const char *path);

static void *node_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
node_t *node = ud;
(void)osize; /* not used */
if (nsize == 0) {
free(ptr);
return NULL;
} else {
if (node->enforce_mem && lua_gc(node->L, LUA_GCCOUNT, 0) > MAX_MEM);
return NULL;
return realloc(ptr, nsize);
}
}


static void node_add_child(node_t* node, const char *path) {
printf("adding child %s\n", path);
node_t *child = xmalloc(sizeof(node_t));
node_init(child, node, path);
}

static void node_update_content(node_t *node, const char *filename) {
printf("updated content for %s in %s\n", filename, node->path);
}

static void node_remove(node_t *node, const char *path) {
printf("removing content %s in %s\n", path, node->path);
}


static void node_init(node_t *node, node_t *parent, const char *path) {
node->wd = inotify_add_watch(inotify_fd, path, IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF);
if (node->wd == -1)
die("cannot inotify_add_watch on %s", path);

node->parent = parent;
node->path = strdup(path);
node->enforce_mem = 0;
node->L = lua_newstate(node_alloc, node);

HASH_ADD(by_wd, nodes, wd, sizeof(int), node);

DIR *dp;

dp = opendir(path);
if (dp == NULL)
die("cannot open directory");

// recurse into directories
struct dirent *ep;
while (ep = readdir(dp)) {
if (ep->d_name[0] == '.')
continue;

if (ep->d_type == DT_DIR) {
char child_path[PATH_MAX];
snprintf(child_path, sizeof(child_path), "%s/%s", node->path, ep->d_name);
node_add_child(node, child_path);
} else if (ep->d_type == DT_REG) {
node_update_content(node, ep->d_name);
}
}
closedir(dp);
}

static void node_free(node_t *node) {
inotify_rm_watch(inotify_fd, node->wd);
lua_close(node->L);
HASH_DELETE(by_wd, nodes, node);
}

static void check_inotify() {
static char inotify_buffer[sizeof(struct inotify_event) + PATH_MAX + 1];
while (1) {
size_t size = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer));
if (size == -1) {
if (errno == EAGAIN)
break;
die("error reading from inotfy fd");
}

char *pos = inotify_buffer;
char *end = pos + size;
while (pos < end) {
struct inotify_event *event = (struct inotify_event*)pos;
pos += sizeof(struct inotify_event) + event->len;

if (event->len && event->name[0] == '.')
continue; // ignore dot files

node_t *node;
HASH_FIND(by_wd, nodes, &event->wd, sizeof(int), node);
if (!node)
die("node not found");

char child_path[PATH_MAX];
snprintf(child_path, sizeof(child_path), "%s/%s", node->path, event->name);
printf("event for %s\n", child_path);

printf("mask: %d\n", event->mask);
if (event->mask & IN_CREATE) {
struct stat stat_buf;
if (stat(child_path, &stat_buf) == -1)
die("cannot stat %s", child_path);

if (S_ISDIR(stat_buf.st_mode)) {
node_add_child(node, child_path);
} else if (S_ISREG(stat_buf.st_mode)) {
node_update_content(node, event->name);
}
} else if (event->mask & IN_CLOSE_WRITE) {
node_update_content(node, event->name);
} else if (event->mask & IN_DELETE) {
node_remove(node, event->name);
}
}
}
}


static void tick(int delta) {
check_inotify();
event_loop(EVLOOP_NONBLOCK);
}

int main(int argc, char *argv[]) {

inotify_fd = inotify_init1(IN_NONBLOCK);
if (inotify_fd == -1)
die("cannot open inotify");

node_init(&root, NULL, "data");

event_init();
glfwInit();

double last = glfwGetTime();
while (1) {
double current = glfwGetTime();
int delta = (current - last) * 1000;
if (delta < MIN_DELTA) {
glfwSleep((MIN_DELTA-delta)/1000.0);
continue;
}
last = current;
if (delta > MAX_DELTA)
continue;
tick(delta);
}
return 0;
}
Oops, something went wrong.

0 comments on commit 870b4cc

Please sign in to comment.
You can’t perform that action at this time.