176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Code implementing read only functionality copied from
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** src/lfs.c at commit 2fd989cd6c777583be1c93616018c55b2cbb1bcf:
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman**
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** LuaFileSystem 1.6.2
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Copyright 2003-2014 Kepler Project
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** http://www.keplerproject.org/luafilesystem
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman**
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** File system manipulation library.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** This library offers these functions:
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** lfs.attributes (filepath [, attributename])
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** lfs.chdir (path)
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** lfs.currentdir ()
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** lfs.dir (path)
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman**
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <dirent.h>
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h>
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <fcntl.h>
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/stat.h>
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <sys/types.h>
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <unistd.h>
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lua.h"
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lauxlib.h"
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lualib.h"
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define chdir_error	strerror(errno)
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Size of path buffer string, stolen from pwd.c */
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef PATH_MAX
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  ifdef NAME_MAX
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    define PATH_MAX   NAME_MAX
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  elif FILENAME_MAX
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    define PATH_MAX   FILENAME_MAX
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  else
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#    define PATH_MAX   256
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#  endif       /* NAME_MAX */
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif /* PATH_MAX */
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define DIR_METATABLE "directory metatable"
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef struct dir_data {
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        int  closed;
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        DIR *dir;
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} dir_data;
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define STAT_STRUCT struct stat
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define STAT_FUNC stat_via_fstat
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Emulate stat via fstat */
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint stat_via_fstat (const char *path, struct stat *buf)
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int fd = open (path, O_RDONLY);
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (fd == -1) {
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    DIR *dir = opendir (path);
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!dir) return -1;
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    closedir (dir);
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    buf->st_mode=S_IFDIR;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    buf->st_size=0;
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (fstat (fd, buf) == -1) {
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int err = errno;
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    close (fd);
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    errno = err;
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return -1;
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  close (fd);
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 0;
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** This function changes the working (current) directory
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int change_dir (lua_State *L) {
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        const char *path = luaL_checkstring(L, 1);
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (chdir(path)) {
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushnil (L);
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n",
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                                path, chdir_error);
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 2;
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else {
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushboolean (L, 1);
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 1;
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** This function returns the current directory
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** If unable to get the current directory, it returns nil
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** and a string describing the error
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int get_dir (lua_State *L) {
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char *path;
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char buf[PATH_MAX];
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if ((path = getcwd(buf, PATH_MAX)) == NULL) {
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushnil(L);
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushstring(L, strerror(errno));
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 2;
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else {
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    lua_pushstring(L, path);
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Directory iterator
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int dir_iter (lua_State *L) {
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        struct dirent *entry;
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE);
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        luaL_argcheck (L, d->closed == 0, 1, "closed directory");
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if ((entry = readdir (d->dir)) != NULL) {
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushstring (L, entry->d_name);
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 1;
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else {
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                /* no more entries => close directory */
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                closedir (d->dir);
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                d->closed = 1;
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 0;
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Closes directory iterators
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int dir_close (lua_State *L) {
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        dir_data *d = (dir_data *)lua_touserdata (L, 1);
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (!d->closed && d->dir) {
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                closedir (d->dir);
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d->closed = 1;
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 0;
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Factory of directory iterators
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int dir_iter_factory (lua_State *L) {
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        const char *path = luaL_checkstring (L, 1);
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        dir_data *d;
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushcfunction (L, dir_iter);
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d = (dir_data *) lua_newuserdata (L, sizeof(dir_data));
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        luaL_getmetatable (L, DIR_METATABLE);
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_setmetatable (L, -2);
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d->closed = 0;
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        d->dir = opendir (path);
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (d->dir == NULL)
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          luaL_error (L, "cannot open %s: %s", path, strerror (errno));
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 2;
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Creates directory metatable.
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int dir_create_meta (lua_State *L) {
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        luaL_newmetatable (L, DIR_METATABLE);
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Method table */
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_newtable(L);
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushcfunction (L, dir_iter);
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_setfield(L, -2, "next");
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushcfunction (L, dir_close);
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_setfield(L, -2, "close");
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* Metamethods */
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_setfield(L, -2, "__index");
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushcfunction (L, dir_close);
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_setfield (L, -2, "__gc");
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 1;
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Convert the inode protection mode to a string.
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const char *mode2string (mode_t mode) {
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if ( S_ISREG(mode) )
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return "file";
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISDIR(mode) )
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return "directory";
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISLNK(mode) )
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return "link";
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISSOCK(mode) )
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return "socket";
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISFIFO(mode) )
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return "named pipe";
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISCHR(mode) )
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return "char device";
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else if ( S_ISBLK(mode) )
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return "block device";
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  else
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return "other";
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* inode protection mode */
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void push_st_mode (lua_State *L, STAT_STRUCT *info) {
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushstring (L, mode2string (info->st_mode));
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* file size, in bytes */
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void push_st_size (lua_State *L, STAT_STRUCT *info) {
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        lua_pushnumber (L, (lua_Number)info->st_size);
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void push_invalid (lua_State *L, STAT_STRUCT *info) {
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  luaL_error(L, "invalid attribute name");
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  info->st_size = 0; /* never reached */
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmantypedef void (*_push_function) (lua_State *L, STAT_STRUCT *info);
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct _stat_members {
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        const char *name;
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        _push_function push;
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct _stat_members members[] = {
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        { "mode",         push_st_mode },
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        { "size",         push_st_size },
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        { NULL, push_invalid }
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Get file or symbolic link information
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) {
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        int i;
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        STAT_STRUCT info;
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        const char *file = luaL_checkstring (L, 1);
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (st(file, &info)) {
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushnil (L);
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushfstring (L, "cannot obtain information from file `%s'", file);
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 2;
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        if (lua_isstring (L, 2)) {
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                int v;
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                const char *member = lua_tostring (L, 2);
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                if (strcmp (member, "mode") == 0) v = 0;
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef _WIN32
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                else if (strcmp (member, "blocks")  == 0) v = 11;
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                else if (strcmp (member, "blksize") == 0) v = 12;
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                else /* look for member */
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                        for (v = 1; members[v].name; v++)
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                                if (*members[v].name == *member)
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                                        break;
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                /* push member value and return */
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                members[v].push (L, &info);
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                return 1;
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        } else if (!lua_istable (L, 2))
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                /* creates a table if none is given */
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_newtable (L);
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        /* stores all members in table on top of the stack */
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        for (i = 0; members[i].name; i++) {
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_pushstring (L, members[i].name);
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                members[i].push (L, &info);
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman                lua_rawset (L, -3);
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        }
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return 1;
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman** Get file information using stat.
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman*/
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int file_info (lua_State *L) {
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return _file_info_ (L, STAT_FUNC);
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic const struct luaL_Reg fslib[] = {
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        {"attributes", file_info},
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        {"chdir", change_dir},
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        {"currentdir", get_dir},
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        {"dir", dir_iter_factory},
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        {NULL, NULL},
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman};
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
29276d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanLUALIB_API int luaopen_lfs (lua_State *L) {
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  dir_create_meta (L);
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  luaL_newlib (L, fslib);
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
297