2 * fastindex - fast lua module indexing plugin
3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <sys/types.h>
17 #include <sys/cdefs.h>
19 #ifndef _POSIX_C_SOURCE
20 #define _POSIX_C_SOURCE /* XXX: portability hack for timestamp */
35 #define MODNAME "luci.fastindex"
36 #define DEFAULT_BUFLEN 1024
41 #define DPRINTF(...) fprintf(stderr, __VA_ARGS__)
43 #define DPRINTF(...) do {} while (0)
47 * list_for_each_offset - iterate over a list, start with the provided pointer
48 * @pos: the &struct list_head to use as a loop cursor.
49 * @head: the head for your list.
51 #define list_for_each_offset(pos, head, offset) \
52 for (pos = (offset)->next; pos != (offset); \
53 pos = ((pos->next == (head)) && ((offset) != (head)) ? (head)->next : pos->next))
55 static char *namespace = NULL
;
57 struct fastindex_entry
{
58 struct list_head list
;
64 struct fastindex_pattern
{
65 struct list_head list
;
73 struct list_head patterns
;
74 struct list_head
*last
;
75 struct list_head entries
;
81 static inline struct fastindex
*
82 to_fastindex(struct lua_State
*L
)
85 lua_getfield(L
, lua_upvalueindex(1), "__data");
86 f
= lua_touserdata(L
, -1);
92 fastindex_module(lua_State
*L
)
95 s
= luaL_checkstring(L
, 1);
100 namespace = strdup(s
);
106 static struct fastindex_entry
*
107 find_entry(struct fastindex
*f
, char *name
)
112 f
->last
= &f
->entries
;
114 list_for_each_offset(p
, &f
->entries
, f
->last
) {
115 struct fastindex_entry
*e
;
116 e
= container_of(p
, struct fastindex_entry
, list
);
117 if (!strcmp(e
->name
, name
))
123 static struct fastindex_entry
*
124 new_entry(struct fastindex
*f
, char *name
)
126 struct fastindex_entry
*e
;
128 e
= malloc(sizeof(struct fastindex_entry
));
132 memset(e
, 0, sizeof(struct fastindex_entry
));
133 e
->name
= strdup(name
);
138 INIT_LIST_HEAD(&e
->list
);
146 static void free_entry(struct fastindex_entry
*e
)
153 int bufferwriter(lua_State
*L
, const void *p
, size_t sz
, void *ud
)
155 struct fastindex
*f
= ud
;
157 while (f
->ofs
+ sz
> f
->buflen
) {
160 f
->buf
= realloc(f
->buf
, f
->buflen
);
166 memcpy(f
->buf
+ f
->ofs
, p
, sz
);
172 load_index(struct fastindex
*f
, struct fastindex_entry
*e
)
176 DPRINTF("Loading module: %s\n", e
->name
);
179 f
->buf
= malloc(f
->buflen
);
182 luaL_error(f
->L
, "Out of memory!\n");
191 lua_pushcfunction(L
, fastindex_module
);
192 lua_setfield(L
, LUA_GLOBALSINDEX
, "module");
195 if (luaL_dofile(L
, e
->name
)) {
196 DPRINTF("Warning: unable to open module '%s'\n", e
->name
);
200 lua_getglobal(L
, f
->func
);
201 lua_dump(L
, bufferwriter
, f
);
202 DPRINTF("Got %d bytes\n", f
->ofs
);
205 lua_createtable(f
->L
, (namespace ? 2 : 1), 0);
206 luaL_loadbuffer(f
->L
, f
->buf
, f
->ofs
, "tmp");
207 lua_rawseti(f
->L
, -2, 1);
209 DPRINTF("Module has namespace '%s'\n", namespace);
210 lua_pushstring(f
->L
, namespace);
211 lua_rawseti(f
->L
, -2, 2);
215 lua_setfield(f
->L
, -2, e
->name
);
223 fastindex_scan(lua_State
*L
)
225 struct list_head
*tmp
, *p
;
229 int gl_flags
= GLOB_NOESCAPE
| GLOB_NOSORT
| GLOB_MARK
;
235 if (list_empty(&f
->patterns
))
238 lua_getfield(L
, lua_upvalueindex(1), "indexes");
239 list_for_each(p
, &f
->patterns
) {
240 struct fastindex_pattern
*pt
= container_of(p
, struct fastindex_pattern
, list
);
241 glob(pt
->pattern
, gl_flags
, NULL
, &gl
);
242 gl_flags
|= GLOB_APPEND
;
244 for (i
= 0; i
< gl
.gl_pathc
; i
++) {
245 struct fastindex_entry
*e
;
248 if (stat(gl
.gl_pathv
[i
], &st
))
251 if ((st
.st_mode
& S_IFMT
) != S_IFREG
)
254 e
= find_entry(f
, gl
.gl_pathv
[i
]);
256 e
= new_entry(f
, gl
.gl_pathv
[i
]);
257 list_add_tail(&e
->list
, &f
->entries
);
260 e
->checked
= f
->checked
;
261 if ((e
->timestamp
< st
.st_mtime
)) {
263 e
->timestamp
= st
.st_mtime
;
267 list_for_each_safe(p
, tmp
, &f
->entries
) {
268 struct fastindex_entry
*e
= container_of(p
, struct fastindex_entry
, list
);
269 if (e
->checked
< f
->checked
) {
271 lua_setfield(f
->L
, -2, e
->name
);
281 fastindex_free(lua_State
*L
)
284 struct list_head
*p
, *tmp
;
286 f
= lua_touserdata(L
, -1);
287 list_for_each_safe(p
, tmp
, &f
->patterns
) {
288 struct fastindex_pattern
*pt
;
289 pt
= container_of(p
, struct fastindex_pattern
, list
);
293 list_for_each_safe(p
, tmp
, &f
->entries
) {
294 struct fastindex_entry
*e
;
295 e
= container_of(p
, struct fastindex_entry
, list
);
302 fastindex_add(lua_State
*L
)
304 struct fastindex_pattern
*pt
;
309 str
= luaL_checkstring(L
, 1);
311 luaL_error(L
, "Invalid argument");
313 pt
= malloc(sizeof(struct fastindex_pattern
) + strlen(str
) + 1);
315 luaL_error(L
, "Out of memory");
317 INIT_LIST_HEAD(&pt
->list
);
318 strcpy(pt
->pattern
, str
);
319 list_add(&pt
->list
, &f
->patterns
);
324 static const luaL_Reg fastindex_m
[] = {
325 { "add", fastindex_add
},
326 { "scan", fastindex_scan
},
331 fastindex_new(lua_State
*L
)
336 func
= luaL_checkstring(L
, 1);
338 f
= lua_newuserdata(L
, sizeof(struct fastindex
));
339 lua_createtable(L
, 0, 2);
340 lua_pushvalue(L
, -1);
341 lua_setfield(L
, -2, "__index");
342 lua_pushcfunction(L
, fastindex_free
);
343 lua_setfield(L
, -2, "__gc");
344 lua_pushvalue(L
, -1);
345 lua_setmetatable(L
, -3);
346 lua_pushvalue(L
, -2);
347 lua_setfield(L
, -2, "__data");
348 lua_createtable(L
, 0, 1);
349 lua_setfield(L
, -2, "indexes");
350 lua_pushvalue(L
, -2);
351 luaI_openlib(L
, NULL
, fastindex_m
, 1);
353 memset(f
, 0, sizeof(struct fastindex
));
355 f
->buflen
= DEFAULT_BUFLEN
;
356 INIT_LIST_HEAD(&f
->entries
);
357 INIT_LIST_HEAD(&f
->patterns
);
359 f
->func
= strdup(func
);
363 luaL_error(L
, "Out of memory\n");
369 static const luaL_Reg fastindex
[] = {
370 { "new", fastindex_new
},
375 luaopen_luci_fastindex(lua_State
*L
)
377 luaL_register(L
, MODNAME
, fastindex
);