Add file.stat() to query file/directory attributes. (#1724)

* add file.stat()

* set default time/date to 1970-01-01
use lua_setfield
This commit is contained in:
Arnim Läuger 2017-01-17 21:54:23 +01:00 committed by Marcel Stör
parent 07031f569a
commit 305d7c4672
2 changed files with 130 additions and 6 deletions

View File

@ -13,6 +13,14 @@
#define FILE_READ_CHUNK 1024 #define FILE_READ_CHUNK 1024
// use this time/date in absence of a timestamp
#define FILE_TIMEDEF_YEAR 1970
#define FILE_TIMEDEF_MON 01
#define FILE_TIMEDEF_DAY 01
#define FILE_TIMEDEF_HOUR 00
#define FILE_TIMEDEF_MIN 00
#define FILE_TIMEDEF_SEC 00
static int file_fd = 0; static int file_fd = 0;
static int file_fd_ref = LUA_NOREF; static int file_fd_ref = LUA_NOREF;
static int rtc_cb_ref = LUA_NOREF; static int rtc_cb_ref = LUA_NOREF;
@ -33,12 +41,12 @@ static void table2tm( lua_State *L, vfs_time *tm )
lua_getfield( L, idx, "min" ); lua_getfield( L, idx, "min" );
lua_getfield( L, idx, "sec" ); lua_getfield( L, idx, "sec" );
tm->year = luaL_optint( L, ++idx, 2016 ); tm->year = luaL_optint( L, ++idx, FILE_TIMEDEF_YEAR );
tm->mon = luaL_optint( L, ++idx, 6 ); tm->mon = luaL_optint( L, ++idx, FILE_TIMEDEF_MON );
tm->day = luaL_optint( L, ++idx, 21 ); tm->day = luaL_optint( L, ++idx, FILE_TIMEDEF_DAY );
tm->hour = luaL_optint( L, ++idx, 0 ); tm->hour = luaL_optint( L, ++idx, FILE_TIMEDEF_HOUR );
tm->min = luaL_optint( L, ++idx, 0 ); tm->min = luaL_optint( L, ++idx, FILE_TIMEDEF_MIN );
tm->sec = luaL_optint( L, ++idx, 0 ); tm->sec = luaL_optint( L, ++idx, FILE_TIMEDEF_SEC );
// remove items from stack // remove items from stack
lua_pop( L, 6 ); lua_pop( L, 6 );
@ -317,6 +325,72 @@ static int file_rename( lua_State* L )
return 1; return 1;
} }
// Lua: stat(filename)
static int file_stat( lua_State* L )
{
size_t len;
const char *fname = luaL_checklstring( L, 1, &len );
luaL_argcheck( L, c_strlen(fname) <= FS_OBJ_NAME_LEN && c_strlen(fname) == len, 1, "filename invalid" );
vfs_item *stat = vfs_stat( (char *)fname );
if (!stat) {
lua_pushnil( L );
return 1;
}
lua_createtable( L, 0, 7 );
lua_pushinteger( L, vfs_item_size( stat ) );
lua_setfield( L, -2, "size" );
lua_pushstring( L, vfs_item_name( stat ) );
lua_setfield( L, -2, "name" );
lua_pushboolean( L, vfs_item_is_dir( stat ) );
lua_setfield( L, -2, "is_dir" );
lua_pushboolean( L, vfs_item_is_rdonly( stat ) );
lua_setfield( L, -2, "is_rdonly" );
lua_pushboolean( L, vfs_item_is_hidden( stat ) );
lua_setfield( L, -2, "is_hidden" );
lua_pushboolean( L, vfs_item_is_sys( stat ) );
lua_setfield( L, -2, "is_sys" );
lua_pushboolean( L, vfs_item_is_arch( stat ) );
lua_setfield( L, -2, "is_arch" );
// time stamp as sub-table
vfs_time tm;
int got_time = VFS_RES_OK == vfs_item_time( stat, &tm ) ? TRUE : FALSE;
lua_createtable( L, 0, 6 );
lua_pushinteger( L, got_time ? tm.year : FILE_TIMEDEF_YEAR );
lua_setfield( L, -2, "year" );
lua_pushinteger( L, got_time ? tm.mon : FILE_TIMEDEF_MON );
lua_setfield( L, -2, "mon" );
lua_pushinteger( L, got_time ? tm.day : FILE_TIMEDEF_DAY );
lua_setfield( L, -2, "day" );
lua_pushinteger( L, got_time ? tm.hour : FILE_TIMEDEF_HOUR );
lua_setfield( L, -2, "hour" );
lua_pushinteger( L, got_time ? tm.min : FILE_TIMEDEF_MIN );
lua_setfield( L, -2, "min" );
lua_pushinteger( L, got_time ? tm.sec : FILE_TIMEDEF_SEC );
lua_setfield( L, -2, "sec" );
lua_setfield( L, -2, "time" );
return 1;
}
// g_read() // g_read()
static int file_g_read( lua_State* L, int n, int16_t end_char, int fd ) static int file_g_read( lua_State* L, int n, int16_t end_char, int fd )
{ {
@ -561,6 +635,7 @@ static const LUA_REG_TYPE file_map[] = {
{ LSTRKEY( "exists" ), LFUNCVAL( file_exists ) }, { LSTRKEY( "exists" ), LFUNCVAL( file_exists ) },
{ LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) }, { LSTRKEY( "fsinfo" ), LFUNCVAL( file_fsinfo ) },
{ LSTRKEY( "on" ), LFUNCVAL( file_on ) }, { LSTRKEY( "on" ), LFUNCVAL( file_on ) },
{ LSTRKEY( "stat" ), LFUNCVAL( file_stat ) },
#ifdef BUILD_FATFS #ifdef BUILD_FATFS
{ LSTRKEY( "mount" ), LFUNCVAL( file_mount ) }, { LSTRKEY( "mount" ), LFUNCVAL( file_mount ) },
{ LSTRKEY( "chdir" ), LFUNCVAL( file_chdir ) }, { LSTRKEY( "chdir" ), LFUNCVAL( file_chdir ) },

View File

@ -294,6 +294,55 @@ Renames a file. If a file is currently open, it will be closed first.
file.rename("temp.lua","init.lua") file.rename("temp.lua","init.lua")
``` ```
## file.stat()
Get attribtues of a file or directory in a table:
- `size` file size in bytes
- `name` file name
- `time` table with time stamp information. Default is 1970-01-01 00:00:00 in case time stamps are not supported (on SPIFFS).
- `year`
- `mon`
- `day`
- `hour`
- `min`
- `sec`
- `is_dir` flag `true` if item is a directory, otherwise `false`
- `is_rdonly` flag `true` if item is read-only, otherwise `false`
- `is_hidden` flag `true` if item is hidden, otherwise `false`
- `is_sys` flag `true` if item is system, otherwise `false`
- `is_arch` flag `true` if item is archive, otherwise `false`
#### Syntax
`file.stat(filename)`
#### Parameters
`filename` file name
#### Returns
table containing file attributes
#### Example
```lua
s = file.stat("/SD0/myfile")
print("name: " .. s.name)
print("size: " .. s.size)
t = s.time
print(string.format("%02d:%02d:%02d", t.hour, t.min, t.sec))
print(string.format("%04d-%02d-%02d", t.year, t.mon, t.day))
if s.is_dir then print("is directory") else print("is file") end
if s.is_rdonly then print("is read-only") else print("is writable") end
if s.is_hidden then print("is hidden") else print("is not hidden") end
if s.is_sys then print("is system") else print("is not system") end
if s.is_arch then print("is archive") else print("is not archive") end
s = nil
t = nil
```
# File access functions # File access functions
The `file` module provides several functions to access the content of a file after it has been opened with [`file.open()`](#fileopen). They can be used as part of a basic model or an object model: The `file` module provides several functions to access the content of a file after it has been opened with [`file.open()`](#fileopen). They can be used as part of a basic model or an object model: