lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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