aboutsummaryrefslogtreecommitdiff
path: root/extmod/vfs_fat.c
diff options
context:
space:
mode:
authorRobert HH <robert@hammelrath.com>2016-05-30 21:09:20 +0200
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-05-31 13:03:12 +0300
commitee009d713a40e710bd6c7d5e98b47f5825fd3e69 (patch)
tree9eda6e3b5d6821fe31e8474dd842826121e9bf63 /extmod/vfs_fat.c
parent7d4fd8b6db5ce81ea239efa53118e126a2b8dd54 (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.c90
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);