Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 870b4cc

Browse files
committed
init
0 parents  commit 870b4cc

5 files changed

Lines changed: 1653 additions & 0 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
*.o
2+
gpn-info
3+
data/

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CFLAGS=-I/usr/include/lua5.1
2+
LDFLAGS=-llua5.1 -levent -lglfw
3+
4+
all: gpn-info
5+
6+
gpn-info: main.o
7+
$(CC) -o $@ $^ $(LDFLAGS)
8+
9+
.PHONY: clean
10+
11+
clean:
12+
rm -f *.o gpn-info

main.c

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#include <unistd.h>
2+
#include <stdio.h>
3+
#include <stdarg.h>
4+
#include <stdlib.h>
5+
#include <assert.h>
6+
#include <errno.h>
7+
#include <dirent.h>
8+
#include <sys/types.h>
9+
#include <sys/stat.h>
10+
11+
12+
#include <sys/inotify.h>
13+
14+
#include <GL/glfw.h>
15+
#include <event.h>
16+
#include <lualib.h>
17+
#include <lauxlib.h>
18+
19+
#include "uthash.h"
20+
21+
#define MAX_MEM 2000 // KB
22+
#define MIN_DELTA 500 // ms
23+
#define MAX_DELTA 2000 // ms
24+
25+
struct node_s {
26+
int wd; // inotify watch descriptor
27+
int prio;
28+
const char *name;
29+
const char *path;
30+
struct node_s *childs;
31+
struct node_s *parent;
32+
lua_State *L;
33+
int enforce_mem;
34+
UT_hash_handle by_wd;
35+
};
36+
37+
typedef struct node_s node_t;
38+
39+
static node_t *nodes = NULL;
40+
41+
static node_t root;
42+
static int inotify_fd;
43+
44+
static void die(const char *fmt, ...) {
45+
va_list ap;
46+
va_start(ap, fmt);
47+
printf("CRITICAL ERROR: ");
48+
vprintf(fmt, ap);
49+
printf("\n");
50+
va_end(ap);
51+
exit(1);
52+
}
53+
54+
static void *xmalloc(size_t size) {
55+
void *ptr = calloc(1, size);
56+
if (!ptr) die("cannot malloc");
57+
return ptr;
58+
}
59+
60+
static void node_init(node_t *node, node_t *parent, const char *path);
61+
62+
static void *node_alloc(void *ud, void *ptr, size_t osize, size_t nsize) {
63+
node_t *node = ud;
64+
(void)osize; /* not used */
65+
if (nsize == 0) {
66+
free(ptr);
67+
return NULL;
68+
} else {
69+
if (node->enforce_mem && lua_gc(node->L, LUA_GCCOUNT, 0) > MAX_MEM);
70+
return NULL;
71+
return realloc(ptr, nsize);
72+
}
73+
}
74+
75+
76+
static void node_add_child(node_t* node, const char *path) {
77+
printf("adding child %s\n", path);
78+
node_t *child = xmalloc(sizeof(node_t));
79+
node_init(child, node, path);
80+
}
81+
82+
static void node_update_content(node_t *node, const char *filename) {
83+
printf("updated content for %s in %s\n", filename, node->path);
84+
}
85+
86+
static void node_remove(node_t *node, const char *path) {
87+
printf("removing content %s in %s\n", path, node->path);
88+
}
89+
90+
91+
static void node_init(node_t *node, node_t *parent, const char *path) {
92+
node->wd = inotify_add_watch(inotify_fd, path, IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF);
93+
if (node->wd == -1)
94+
die("cannot inotify_add_watch on %s", path);
95+
96+
node->parent = parent;
97+
node->path = strdup(path);
98+
node->enforce_mem = 0;
99+
node->L = lua_newstate(node_alloc, node);
100+
101+
HASH_ADD(by_wd, nodes, wd, sizeof(int), node);
102+
103+
DIR *dp;
104+
105+
dp = opendir(path);
106+
if (dp == NULL)
107+
die("cannot open directory");
108+
109+
// recurse into directories
110+
struct dirent *ep;
111+
while (ep = readdir(dp)) {
112+
if (ep->d_name[0] == '.')
113+
continue;
114+
115+
if (ep->d_type == DT_DIR) {
116+
char child_path[PATH_MAX];
117+
snprintf(child_path, sizeof(child_path), "%s/%s", node->path, ep->d_name);
118+
node_add_child(node, child_path);
119+
} else if (ep->d_type == DT_REG) {
120+
node_update_content(node, ep->d_name);
121+
}
122+
}
123+
closedir(dp);
124+
}
125+
126+
static void node_free(node_t *node) {
127+
inotify_rm_watch(inotify_fd, node->wd);
128+
lua_close(node->L);
129+
HASH_DELETE(by_wd, nodes, node);
130+
}
131+
132+
static void check_inotify() {
133+
static char inotify_buffer[sizeof(struct inotify_event) + PATH_MAX + 1];
134+
while (1) {
135+
size_t size = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer));
136+
if (size == -1) {
137+
if (errno == EAGAIN)
138+
break;
139+
die("error reading from inotfy fd");
140+
}
141+
142+
char *pos = inotify_buffer;
143+
char *end = pos + size;
144+
while (pos < end) {
145+
struct inotify_event *event = (struct inotify_event*)pos;
146+
pos += sizeof(struct inotify_event) + event->len;
147+
148+
if (event->len && event->name[0] == '.')
149+
continue; // ignore dot files
150+
151+
node_t *node;
152+
HASH_FIND(by_wd, nodes, &event->wd, sizeof(int), node);
153+
if (!node)
154+
die("node not found");
155+
156+
char child_path[PATH_MAX];
157+
snprintf(child_path, sizeof(child_path), "%s/%s", node->path, event->name);
158+
printf("event for %s\n", child_path);
159+
160+
printf("mask: %d\n", event->mask);
161+
if (event->mask & IN_CREATE) {
162+
struct stat stat_buf;
163+
if (stat(child_path, &stat_buf) == -1)
164+
die("cannot stat %s", child_path);
165+
166+
if (S_ISDIR(stat_buf.st_mode)) {
167+
node_add_child(node, child_path);
168+
} else if (S_ISREG(stat_buf.st_mode)) {
169+
node_update_content(node, event->name);
170+
}
171+
} else if (event->mask & IN_CLOSE_WRITE) {
172+
node_update_content(node, event->name);
173+
} else if (event->mask & IN_DELETE) {
174+
node_remove(node, event->name);
175+
}
176+
}
177+
}
178+
}
179+
180+
181+
static void tick(int delta) {
182+
check_inotify();
183+
event_loop(EVLOOP_NONBLOCK);
184+
}
185+
186+
int main(int argc, char *argv[]) {
187+
188+
inotify_fd = inotify_init1(IN_NONBLOCK);
189+
if (inotify_fd == -1)
190+
die("cannot open inotify");
191+
192+
node_init(&root, NULL, "data");
193+
194+
event_init();
195+
glfwInit();
196+
197+
double last = glfwGetTime();
198+
while (1) {
199+
double current = glfwGetTime();
200+
int delta = (current - last) * 1000;
201+
if (delta < MIN_DELTA) {
202+
glfwSleep((MIN_DELTA-delta)/1000.0);
203+
continue;
204+
}
205+
last = current;
206+
if (delta > MAX_DELTA)
207+
continue;
208+
tick(delta);
209+
}
210+
return 0;
211+
}

0 commit comments

Comments
 (0)