diff options
author | Robert HH <robert@hammelrath.com> | 2016-05-30 21:09:20 +0200 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2016-05-31 13:03:12 +0300 |
commit | ee009d713a40e710bd6c7d5e98b47f5825fd3e69 (patch) | |
tree | 9eda6e3b5d6821fe31e8474dd842826121e9bf63 /extmod/vfs_fat.c | |
parent | 7d4fd8b6db5ce81ea239efa53118e126a2b8dd54 (diff) |
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.
Diffstat (limited to 'extmod/vfs_fat.c')
-rw-r--r-- | extmod/vfs_fat.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 07b26f05f..e68f375ef 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -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); |