From 968763aa1d4ee5ed597d6f32b19fef6cbbed5c5c Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 1/5] factor out storage_object_from_path --- shared-module/storage/__init__.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 97a049bac6..3e7b90384a 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -109,19 +109,15 @@ void common_hal_storage_umount_object(mp_obj_t vfs_obj) { mp_vfs_proxy_call(vfs, MP_QSTR_umount, 0, NULL); } -void common_hal_storage_umount_path(const char* mount_path) { - // remove vfs from the mount table - mp_obj_t *vfs_obj = NULL; +STATIC mp_obj_t storage_object_from_path(const char* mount_path) { for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { if (strcmp(mount_path, (*vfsp)->str) == 0) { - vfs_obj = (*vfsp)->obj; - break; + return (*vfsp)->obj; } } - - if (vfs_obj == NULL) { - mp_raise_OSError(MP_EINVAL); - } - - common_hal_storage_umount_object(vfs_obj); + mp_raise_OSError(MP_EINVAL); +} + +void common_hal_storage_umount_path(const char* mount_path) { + common_hal_storage_umount_object(storage_object_from_path(mount_path)); } From c08f5a3a0071dd1940a09c6b5f0bdd8e4768c7f0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 2/5] Add storage.getmount to retrieve the mount object associated with a path --- shared-bindings/storage/__init__.c | 10 ++++++++++ shared-bindings/storage/__init__.h | 1 + shared-module/storage/__init__.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 6f6a30da6d..837017ef9e 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -122,12 +122,22 @@ mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a } MP_DEFINE_CONST_FUN_OBJ_KW(storage_remount_obj, 1, storage_remount); +//| .. function:: getmount(mount_path) +//| +//| Retrieves the mount object associated with the mount path +//| +mp_obj_t storage_getmount(const mp_obj_t mnt_in) { + return common_hal_storage_getmount(mp_obj_str_get_str(mnt_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); + STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_storage) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&storage_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&storage_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_remount), MP_ROM_PTR(&storage_remount_obj) }, + { MP_ROM_QSTR(MP_QSTR_getmount), MP_ROM_PTR(&storage_getmount_obj) }, //| .. class:: VfsFat(block_device) //| diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index 574b5ff8dd..76b9ae854f 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -34,5 +34,6 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char* path, bool readonly) void common_hal_storage_umount_path(const char* path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char* path, bool readonly); +mp_obj_t common_hal_storage_getmount(const char* path); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_STORAGE___INIT___H diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 3e7b90384a..5b0bbe01ec 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -121,3 +121,7 @@ STATIC mp_obj_t storage_object_from_path(const char* mount_path) { void common_hal_storage_umount_path(const char* mount_path) { common_hal_storage_umount_object(storage_object_from_path(mount_path)); } + +mp_obj_t common_hal_storage_getmount(const char *mount_path) { + return storage_object_from_path(mount_path); +} From fe7f405fc7708cdbe426e2f255b01a1a77e574d9 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:18 -0500 Subject: [PATCH 3/5] Add VfsFat.label property These allow accessing the filesystem label. For instance, in boot.py, you can set the label on the built-in storage with: storage.remount('/', False) storage.getmount('/').label = "NEWLABEL" storage.remount('/', True) Users with multiple CIRCUITPY boards may find it desirable to choose a different label for each board they own. --- extmod/vfs_fat.c | 34 +++++++++++++++++++++++++++++ ports/unix/mpconfigport_coverage.h | 1 + tests/extmod/vfs_fat_ramdisk.py | 2 ++ tests/extmod/vfs_fat_ramdisk.py.exp | 1 + 4 files changed, 38 insertions(+) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 22346bdf1d..66d3136ebb 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -33,6 +33,7 @@ #endif #include +#include "py/objproperty.h" #include "py/runtime.h" #include "py/mperrno.h" #include "lib/oofatfs/ff.h" @@ -317,6 +318,36 @@ STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); +#if MICROPY_FATFS_USE_LABEL +STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + char working_buf[12]; + FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_obj_new_str(working_buf, strlen(working_buf), false); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel); + +static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { + fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); + const char *label_str = mp_obj_str_get_str(label_in); + FRESULT res = f_setlabel(&self->fatfs, label_str); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_setlabel_obj, vfs_fat_setlabel); +STATIC const mp_obj_property_t fat_vfs_label_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&fat_vfs_getlabel_obj, + (mp_obj_t)&fat_vfs_setlabel_obj, + (mp_obj_t)&mp_const_none_obj}, +}; +#endif + 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) }, @@ -331,6 +362,9 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_fat_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) }, +#if MICROPY_FATFS_USE_LABEL + { MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) }, +#endif }; STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h index 367b4853af..86d95eb39b 100644 --- a/ports/unix/mpconfigport_coverage.h +++ b/ports/unix/mpconfigport_coverage.h @@ -43,4 +43,5 @@ #define MICROPY_PY_IO_BUFFEREDWRITER (1) #undef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (1) +#define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_PY_FRAMEBUF (1) diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 801c697862..896641ab3b 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -54,6 +54,8 @@ print(b"hello!" not in bdev.data) vfs = uos.VfsFat(bdev) uos.mount(vfs, "/ramdisk") +vfs.label = 'label test' +print("label:", vfs.label) print("statvfs:", vfs.statvfs("/ramdisk")) print("getcwd:", vfs.getcwd()) diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp index ccd0f7134c..a3c3470a94 100644 --- a/tests/extmod/vfs_fat_ramdisk.py.exp +++ b/tests/extmod/vfs_fat_ramdisk.py.exp @@ -1,5 +1,6 @@ True True +label: LABEL TEST statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255) getcwd: / True From 9c47fd9c13b4d5a35d28c4c9eca8f1644cb882da Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:19 -0500 Subject: [PATCH 4/5] Specifically give a better error message for setlabel on RO fs --- extmod/vfs_fat.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 66d3136ebb..81ca1e23dc 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -335,6 +335,9 @@ static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { const char *label_str = mp_obj_str_get_str(label_in); FRESULT res = f_setlabel(&self->fatfs, label_str); if (res != FR_OK) { + if(res == FR_WRITE_PROTECTED) { + mp_raise_msg(&mp_type_OSError, "Read-only filesystem"); + } mp_raise_OSError(fresult_to_errno_table[res]); } return mp_const_none; From 34f5498760452e30cb9b76e43f5ec65f36936376 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 27 Mar 2018 21:28:19 -0500 Subject: [PATCH 5/5] Document storage.VfsFat more thoroughly --- shared-bindings/storage/__init__.c | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index 837017ef9e..734cabcc1c 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -145,6 +145,49 @@ STATIC const mp_rom_map_elem_t storage_module_globals_table[] = { //| //| :param block_device: Block device the the filesystem lives on //| + //| .. attribute:: label + //| + //| The filesystem label, up to 11 case-insensitive bytes. Note that + //| this property can only be set when the device is writable by the + //| microcontroller. + //| + //| .. method:: mkfs + //| + //| Format the block device, deleting any data that may have been there + //| + //| .. method:: open(path, mode) + //| + //| Like builtin ``open()`` + //| + //| .. method:: ilistdir([path]) + //| + //| Return an iterator whose values describe files and folders within + //| ``path`` + //| + //| .. method:: mkdir(path) + //| + //| Like `os.mkdir` + //| + //| .. method:: rmdir(path) + //| + //| Like `os.rmdir` + //| + //| .. method:: stat(path) + //| + //| Like `os.stat` + //| + //| .. method:: statvfs(path) + //| + //| Like `os.statvfs` + //| + //| .. method:: mount(readonly, mkfs) + //| + //| Don't call this directly, call `storage.mount`. + //| + //| .. method:: umount + //| + //| Don't call this directly, call `storage.umount`. + //| { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, };