lua-users home
lua-l archive

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


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