[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Creating a lua extension from a recursive C function
- From: Emmanuel Oga <emmanueloga@...>
- Date: Sat, 7 May 2011 20:58:29 -0300
On Sat, May 7, 2011 at 8:08 PM, Francesco Abbate
<francesco.bbt@gmail.com> wrote:
> Hi,
>
> I did not resist to the temptation to write myself the code, this is
> actually a very nice exercise for the Lua C API.
>
> Here the code:
> #include <lua.h>
> #include <lauxlib.h>
>
> #include <errno.h>
> #include <dirent.h>
> #include <sys/stat.h>
> #include <string.h>
> #include <stdio.h>
>
> #define TREE_FILE_LIMIT 1024 /* Directory with more file than this get
> ignored. */
>
> static void tree(lua_State *L, const char *pathbuf) {
> const char *dirbuf = lua_pushfstring (L, "%s/", pathbuf);
>
> DIR *d = opendir(dirbuf);
>
> if (!d)
> luaL_error (L, "cannot read directory: %s", pathbuf);
>
> lua_pop (L, 1);
> lua_newtable (L);
>
> struct dirent *entry;
>
> int entries = 0;
> while(entry = readdir(d)) { entries++; }
> if (entries > TREE_FILE_LIMIT) {
> closedir(d);
> goto endls;
> }
>
> rewinddir(d);
>
> int k = 1;
> while ((entry = readdir(d)) != NULL) {
> char *name = entry-> d_name;
>
> char c0 = name[0], c1 = name[1];
> if (!(c0 == '.' && (!c1 || (c1 == '.' && !name[2])))) { // quickly
> skip . and ..
> const char *filename = lua_pushfstring (L, "%s/%s", pathbuf, name);
>
> struct stat s;
> if (lstat(filename, &s) != -1) {
> lua_pop (L, 1);
> if (S_ISDIR(s.st_mode)) {
> lua_newtable (L);
> tree(L, filename);
> lua_setfield (L, -2, name);
> } else {
> lua_pushstring (L, name);
> lua_rawseti (L, -2, k);
> k++;
> }
> }
> }
> }
>
> closedir(d);
> };
>
> int get_tree(lua_State *L) {
> const char *pathbuf = luaL_checkstring(L, 1);
> lua_newtable (L);
> tree(L, pathbuf);
> lua_setfield (L, -2, pathbuf);
> return 1;
> }
>
> Please note that I didn't test it and there could be some errors!!
> Note also that there are no checks about the growing Lua stack, this
> test should be added because the Lua C call does not check that
> automatically.
>
> I think the lua_pushfstring is very useful and it does suppress the
> potential buffer overflow that you have in your application.
>
> Best regards,
> Francesco
>
>
Awesome Franceso, txs :)
I coded it a bit differently to store the tree in a format that's
better for my application:
{
base="dirname",
files = {a, b, c, ... },
dirs = { recurse with this format },
}
I updated my gist:
https://gist.github.com/960827
Since I'm pretty sure the path names are never gonna be bigger than
1024 chars, I used a fixed size buffer instead of lua_pushfstring. It
is a small micro optimization but a very easy one, and I relieve the
G.C. of having to create and collect a lot of small strings.
This version though, like yours, just keeps making the stack grow with
each recursion.
About the stack, is there a hard limit on its size or can I grow it
until there are no longer any available system memory?
--------------------------------------------------------------
EmmanuelOga.com - Software Developer