diff options
| author | Damien George <damien.p.george@gmail.com> | 2014-07-31 23:44:04 +0100 |
|---|---|---|
| committer | Damien George <damien.p.george@gmail.com> | 2014-07-31 23:44:04 +0100 |
| commit | 65dd7bc13d2083a7db5a974bf6480b1652a35c82 (patch) | |
| tree | af18c5f8ad6c33a33d7a57e8d495b1890655f15b /stmhal/modos.c | |
| parent | 5aac6aa445d343074b64bb7fa3ddc9184b0c65be (diff) | |
stmhal: Change 0:/ and 1:/ to /flash and /sd; add CWD support.
Some important changes to the way the file system is structured on the
pyboard:
1. 0: and 1: drive names are now replaced with POSIX inspired
directories, namely /flash and /sd.
2. Filesystem now supports the notion of a current working directory.
Supports the standard Python way of manipulating it: os.chdir and
os.getcwd.
3. On boot up, current directory is /flash if no SD inserted, else /sd
if SD inserted. Then runs boot.py and main.py from the current dir.
This is the same as the old behaviour, but is much more consistent and
flexible (eg you can os.chdir in boot.py to change where main.py is run
from).
4. sys.path (for import) is now set to '' (current dir), plus /flash
and /flash/lib, and then /sd and /sd/lib if SD inserted. This, along
with CWD, means that import now works properly. You can import a file
from the current directory.
5. os.listdir is fixed to return just the basename, not the full path.
See issue #537 for background and discussion.
Diffstat (limited to 'stmhal/modos.c')
| -rw-r--r-- | stmhal/modos.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/stmhal/modos.c b/stmhal/modos.c index 35979ae97..67daf9250 100644 --- a/stmhal/modos.c +++ b/stmhal/modos.c @@ -38,22 +38,64 @@ #include "storage.h" #include "ff.h" #include "file.h" +#include "sdcard.h" #include "portmodules.h" #if _USE_LFN static char lfn[_MAX_LFN + 1]; /* Buffer to store the LFN */ #endif +STATIC mp_obj_t os_chdir(mp_obj_t path_in) { + const char *path; + path = mp_obj_str_get_str(path_in); + + FRESULT res = f_chdrive(path); + + if (res == FR_OK) { + res = f_chdir(path); + } + + if (res != FR_OK) { + // TODO should be mp_type_FileNotFoundError + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path)); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); + +STATIC mp_obj_t os_getcwd(void) { + char buf[MICROPY_ALLOC_PATH_MAX + 1]; + FRESULT res = f_getcwd(buf, sizeof buf); + + if (res != FR_OK) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + } + + return mp_obj_new_str(buf, strlen(buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); + STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { - const mp_obj_type_t *local_str_type = &mp_type_str; + bool is_str_type = true; const char *path; if (n_args == 1) { if (mp_obj_get_type(args[0]) == &mp_type_bytes) { - local_str_type = &mp_type_bytes; + is_str_type = false; } path = mp_obj_str_get_str(args[0]); } else { - path = "0:"; + path = ""; + } + + // "hack" to list root directory + if (path[0] == '/' && path[1] == '\0') { + mp_obj_t dir_list = mp_obj_new_list(0, NULL); + mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_flash)); + if (sdcard_is_present()) { // TODO this is not the correct logic to check for /sd + mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_sd)); + } + return dir_list; } FRESULT res; @@ -72,11 +114,6 @@ STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { mp_obj_t dir_list = mp_obj_new_list(0, NULL); - uint path_len = strlen(path); - if (path[path_len - 1] == '/') { - path_len--; - } - 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 */ @@ -89,20 +126,24 @@ STATIC mp_obj_t os_listdir(uint n_args, const mp_obj_t *args) { char *fn = fno.fname; #endif - if (fno.fattrib & AM_DIR) { /* It is a directory */ - } else { /* It is a file. */ + /* + if (fno.fattrib & AM_DIR) { + // dir + } else { + // file } + */ // make a string object for this entry - byte *data; - uint fn_len = strlen(fn); - mp_obj_t entry_o = mp_obj_str_builder_start(local_str_type, path_len + 1 + fn_len, &data); - memcpy(data, path, path_len); - data[path_len] = '/'; - memcpy(data + path_len + 1, fn, fn_len); + 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, mp_obj_str_builder_end(entry_o)); + mp_obj_list_append(dir_list, entry_o); } f_closedir(&dir); @@ -161,9 +202,17 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) { fno.lfsize = 0; #endif - FRESULT 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]))); + if (path[0] == '/' && path[1] == '\0') { + // stat root directory + fno.fsize = 0; + fno.fdate = 0; + fno.ftime = 0; + fno.fattrib = AM_DIR; + } else { + FRESULT 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_new_tuple(10, NULL); @@ -216,6 +265,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); STATIC const mp_map_elem_t os_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_os) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj }, |
