diff options
-rw-r--r-- | unix/modos.c | 47 | ||||
-rw-r--r-- | unix/mpconfigport.h | 9 | ||||
-rw-r--r-- | unix/qstrdefsport.h | 1 |
3 files changed, 57 insertions, 0 deletions
diff --git a/unix/modos.c b/unix/modos.c index f681acaff2..abc96e638d 100644 --- a/unix/modos.c +++ b/unix/modos.c @@ -31,6 +31,7 @@ #include <errno.h> #include <stdlib.h> #include <string.h> +#include <dirent.h> #include "py/mpconfig.h" #include "py/nlr.h" @@ -155,6 +156,51 @@ STATIC mp_obj_t mod_os_mkdir(mp_obj_t path_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_mkdir_obj, mod_os_mkdir); +typedef struct _mp_obj_listdir_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + DIR *dir; +} mp_obj_listdir_t; + +STATIC mp_obj_t listdir_next(mp_obj_t self_in) { + mp_obj_listdir_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->dir == NULL) { + goto done; + } + struct dirent *dirent = readdir(self->dir); + if (dirent == NULL) { + closedir(self->dir); + self->dir = NULL; + done: + return MP_OBJ_STOP_ITERATION; + } + + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); + t->items[0] = mp_obj_new_str(dirent->d_name, strlen(dirent->d_name), false); + #ifdef _DIRENT_HAVE_D_TYPE + t->items[1] = MP_OBJ_NEW_SMALL_INT(dirent->d_type); + #else + // DT_UNKNOWN should have 0 value on any reasonable system + t->items[1] = 0; + #endif + t->items[2] = MP_OBJ_NEW_SMALL_INT(dirent->d_ino); + return MP_OBJ_FROM_PTR(t); +} + +STATIC mp_obj_t mod_os_ilistdir(mp_uint_t n_args, const mp_obj_t *args) { + const char *path = "."; + if (n_args > 0) { + path = mp_obj_str_get_str(args[0]); + } + mp_obj_listdir_t *o = m_new_obj(mp_obj_listdir_t); + o->base.type = &mp_type_polymorph_iter; + o->dir = opendir(path); + o->iternext = listdir_next; + return MP_OBJ_FROM_PTR(o); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_ilistdir_obj, 0, 1, mod_os_ilistdir); + STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mod_os_stat_obj) }, @@ -165,6 +211,7 @@ STATIC const mp_rom_map_elem_t mp_module_os_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mod_os_unlink_obj) }, { MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mod_os_getenv_obj) }, { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mod_os_mkdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mod_os_ilistdir_obj) }, }; STATIC MP_DEFINE_CONST_DICT(mp_module_os_globals, mp_module_os_globals_table); diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h index ad75f5287e..5fd122e96e 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -250,3 +250,12 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj; #include <alloca.h> #endif #endif + +// From "man readdir": "Under glibc, programs can check for the availability +// of the fields [in struct dirent] not defined in POSIX.1 by testing whether +// the macros [...], _DIRENT_HAVE_D_TYPE are defined." +// Other libc's don't define it, but proactively assume that dirent->d_type +// is available on a modern *nix system. +#ifndef _DIRENT_HAVE_D_TYPE +#define _DIRENT_HAVE_D_TYPE (1) +#endif diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h index 608234e232..9965c030c4 100644 --- a/unix/qstrdefsport.h +++ b/unix/qstrdefsport.h @@ -43,6 +43,7 @@ Q(system) Q(unlink) Q(getenv) Q(mkdir) +Q(ilistdir) Q(uselect) Q(poll) |