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:
parent
7d4fd8b6db
commit
ee009d713a
@ -35,6 +35,7 @@
|
|||||||
#include "lib/fatfs/diskio.h"
|
#include "lib/fatfs/diskio.h"
|
||||||
#include "extmod/vfs_fat_file.h"
|
#include "extmod/vfs_fat_file.h"
|
||||||
#include "extmod/fsusermount.h"
|
#include "extmod/fsusermount.h"
|
||||||
|
#include "timeutils.h"
|
||||||
|
|
||||||
#define mp_obj_fat_vfs_t fs_user_mount_t
|
#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);
|
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[] = {
|
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_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_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_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_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_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);
|
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ include ../py/py.mk
|
|||||||
|
|
||||||
INC += -I.
|
INC += -I.
|
||||||
INC += -I..
|
INC += -I..
|
||||||
|
INC += -I../lib/timeutils
|
||||||
INC += -I$(BUILD)
|
INC += -I$(BUILD)
|
||||||
|
|
||||||
# compiler settings
|
# compiler settings
|
||||||
@ -163,6 +164,7 @@ LIB_SRC_C = $(addprefix lib/,\
|
|||||||
utils/printf.c \
|
utils/printf.c \
|
||||||
fatfs/ff.c \
|
fatfs/ff.c \
|
||||||
fatfs/option/ccsbcs.c \
|
fatfs/option/ccsbcs.c \
|
||||||
|
timeutils/timeutils.c \
|
||||||
)
|
)
|
||||||
|
|
||||||
OBJ = $(PY_O)
|
OBJ = $(PY_O)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user