extmod/vfs_fat.c: Add vfs.stat().

The call to stat() returns a 10 element tuple consistent to the os.stat()
call. At the moment, the only relevant information returned are file
type and file size.
This commit is contained in:
Robert HH 2016-05-30 21:09:20 +02:00 committed by Paul Sokolovsky
parent 7d4fd8b6db
commit ee009d713a
2 changed files with 92 additions and 0 deletions

View File

@ -35,6 +35,7 @@
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
#include "extmod/fsusermount.h"
#include "timeutils.h"
#define mp_obj_fat_vfs_t fs_user_mount_t
@ -152,6 +153,94 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal(const char *path, const char *path_canonical) {
while (*path_canonical != '\0' && *path == *path_canonical) {
++path;
++path_canonical;
}
if (*path_canonical != '\0') {
return false;
}
while (*path == '/') {
++path;
}
return *path == '\0';
}
/// \function stat(path)
/// Get the status of a file or directory.
STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
FRESULT res;
if (path_equal(path, "/")) {
// stat root directory
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
} else {
res = FR_NO_PATH;
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
if (vfs != NULL && path_equal(path, vfs->str)) {
// stat mounted device directory
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
res = FR_OK;
}
}
if (res == FR_NO_PATH) {
// stat normal file
res = f_stat(path, &fno);
}
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
mp_int_t mode = 0;
if (fno.fattrib & AM_DIR) {
mode |= 0x4000; // stat.S_IFDIR
} else {
mode |= 0x8000; // stat.S_IFREG
}
mp_int_t seconds = timeutils_seconds_since_2000(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
(fno.ftime >> 11) & 0x1f,
(fno.ftime >> 5) & 0x3f,
2 * (fno.ftime & 0x1f)
);
t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size
t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime
t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime
t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime
return MP_OBJ_FROM_PTR(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
@ -161,6 +250,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);

View File

@ -15,6 +15,7 @@ include ../py/py.mk
INC += -I.
INC += -I..
INC += -I../lib/timeutils
INC += -I$(BUILD)
# compiler settings
@ -163,6 +164,7 @@ LIB_SRC_C = $(addprefix lib/,\
utils/printf.c \
fatfs/ff.c \
fatfs/option/ccsbcs.c \
timeutils/timeutils.c \
)
OBJ = $(PY_O)