diff options
Diffstat (limited to 'extmod/vfs_fat.c')
| -rw-r--r-- | extmod/vfs_fat.c | 116 |
1 files changed, 105 insertions, 11 deletions
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 81ca1e23d..633c04389 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -48,6 +48,21 @@ #define mp_obj_fat_vfs_t fs_user_mount_t +STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) { + fs_user_mount_t *vfs = vfs_in; + FILINFO fno; + assert(vfs != NULL); + FRESULT res = f_stat(&vfs->fatfs, path, &fno); + if (res == FR_OK) { + if ((fno.fattrib & AM_DIR) != 0) { + return MP_IMPORT_STAT_DIR; + } else { + return MP_IMPORT_STAT_FILE; + } + } + return MP_IMPORT_STAT_NO_EXIST; +} + STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); @@ -70,9 +85,28 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ mp_load_method(args[0], MP_QSTR_count, vfs->u.old.count); } + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res == FR_NO_FILESYSTEM) { + // don't error out if no filesystem, to let mkfs()/mount() create one if wanted + vfs->flags |= FSUSER_NO_FILESYSTEM; + } else if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return MP_OBJ_FROM_PTR(vfs); } +#if _FS_REENTRANT +STATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) { + mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in); + // f_umount only needs to be called to release the sync object + f_umount(&self->fatfs); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del); +#endif + STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { // create new object fs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in)); @@ -89,7 +123,52 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj)); -STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self); +typedef struct _mp_vfs_fat_ilistdir_it_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + bool is_str; + FF_DIR dir; +} mp_vfs_fat_ilistdir_it_t; + +STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { + mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + + for (;;) { + FILINFO fno; + FRESULT res = f_readdir(&self->dir, &fno); + char *fn = fno.fname; + if (res != FR_OK || fn[0] == 0) { + // stop on error or end of dir + break; + } + + // Note that FatFS already filters . and .., so we don't need to + + // make 4-tuple with info about this entry + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); + if (self->is_str) { + t->items[0] = mp_obj_new_str(fn, strlen(fn)); + } else { + t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn)); + } + if (fno.fattrib & AM_DIR) { + // dir + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); + } else { + // file + t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG); + } + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number + t->items[3] = mp_obj_new_int_from_uint(fno.fsize); + + return MP_OBJ_FROM_PTR(t); + } + + // ignore error because we may be closing a second time + f_closedir(&self->dir); + + return MP_OBJ_STOP_ITERATION; +} STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); @@ -104,7 +183,17 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { path = ""; } - return fat_vfs_ilistdir2(self, path, is_str_type); + // Create a new iterator object to list the dir + mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = mp_vfs_fat_ilistdir_it_iternext; + iter->is_str = is_str_type; + FRESULT res = f_opendir(&self->fatfs, &iter->dir, path); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + + return MP_OBJ_FROM_PTR(iter); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func); @@ -198,7 +287,7 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } - return mp_obj_new_str(buf, strlen(buf), false); + return mp_obj_new_str(buf, strlen(buf)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); @@ -292,10 +381,8 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs self->writeblocks[0] = MP_OBJ_NULL; } - // mount the block device - FRESULT res = f_mount(&self->fatfs); - // check if we need to make the filesystem + FRESULT res = (self->flags & FSUSER_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; if (res == FR_NO_FILESYSTEM && mp_obj_is_true(mkfs)) { uint8_t working_buf[_MAX_SS]; res = f_mkfs(&self->fatfs, FM_FAT | FM_SFD, 0, working_buf, sizeof(working_buf)); @@ -303,17 +390,15 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } + self->flags &= ~FSUSER_NO_FILESYSTEM; return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount); STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { - fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); - FRESULT res = f_umount(&self->fatfs); - if (res != FR_OK) { - mp_raise_OSError(fresult_to_errno_table[res]); - } + (void)self_in; + // keep the FAT filesystem mounted internally so the VFS methods can still be used return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); @@ -352,6 +437,9 @@ STATIC const mp_obj_property_t fat_vfs_label_obj = { #endif STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { + #if _FS_REENTRANT + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) }, + #endif { 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_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) }, @@ -371,11 +459,17 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); +STATIC const mp_vfs_proto_t fat_vfs_proto = { + .import_stat = fat_vfs_import_stat, +}; + const mp_obj_type_t mp_fat_vfs_type = { { &mp_type_type }, .name = MP_QSTR_VfsFat, .make_new = fat_vfs_make_new, + .protocol = &fat_vfs_proto, .locals_dict = (mp_obj_dict_t*)&fat_vfs_locals_dict, + }; #endif // MICROPY_VFS_FAT |
