diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index dee4f92988..41c32c6b6a 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -91,7 +91,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self); -STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) { +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]); bool is_str_type = true; const char *path; @@ -104,9 +104,9 @@ STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) { path = ""; } - return fat_vfs_listdir2(self, path, is_str_type); + return fat_vfs_ilistdir2(self, path, is_str_type); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func); STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); @@ -321,7 +321,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); 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) }, - { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) }, diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h index 7eb865254f..6c7c05a9ac 100644 --- a/extmod/vfs_fat.h +++ b/extmod/vfs_fat.h @@ -57,4 +57,4 @@ mp_import_stat_t fat_vfs_import_stat(struct _fs_user_mount_t *vfs, const char *p mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode); MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj); -mp_obj_t fat_vfs_listdir2(struct _fs_user_mount_t *vfs, const char *path, bool is_str_type); +mp_obj_t fat_vfs_ilistdir2(struct _fs_user_mount_t *vfs, const char *path, bool is_str_type); diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c index 19db99c7f7..5b906189f2 100644 --- a/extmod/vfs_fat_misc.c +++ b/extmod/vfs_fat_misc.c @@ -34,51 +34,64 @@ #include "extmod/vfs_fat.h" #include "py/lexer.h" -// TODO: actually, the core function should be ilistdir() - -mp_obj_t fat_vfs_listdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) { - FRESULT res; - FILINFO fno; +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; - res = f_opendir(&vfs->fatfs, &dir, path); +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; + } + if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) { + // skip . and .. + continue; + } + + // make 3-tuple with info about this entry + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); + if (self->is_str) { + t->items[0] = mp_obj_new_str(fn, strlen(fn), false); + } 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 + + 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; +} + +mp_obj_t fat_vfs_ilistdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) { + 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(&vfs->fatfs, &iter->dir, path); if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } - - mp_obj_t dir_list = mp_obj_new_list(0, NULL); - - for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ - if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */ - if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */ - - char *fn = fno.fname; - - /* - if (fno.fattrib & AM_DIR) { - // dir - } else { - // file - } - */ - - // make a string object for this entry - mp_obj_t entry_o; - if (is_str_type) { - entry_o = mp_obj_new_str(fn, strlen(fn), false); - } else { - entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn)); - } - - // add the entry to the list - mp_obj_list_append(dir_list, entry_o); - } - - f_closedir(&dir); - - return dir_list; + return MP_OBJ_FROM_PTR(iter); } mp_import_stat_t fat_vfs_import_stat(fs_user_mount_t *vfs, const char *path) {