aboutsummaryrefslogtreecommitdiff
path: root/extmod/vfs_fat.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-11-16 16:01:47 +1100
committerDamien George <damien.p.george@gmail.com>2017-11-20 11:46:40 +1100
commit12ad64bc554fe33772c492efc55eb9290463048a (patch)
tree6055de58a2e8d73bec8fbb97574ceb93fcf64ef1 /extmod/vfs_fat.c
parentccaa5f5b0bad69f0f0ea81151e34c218fe13ce66 (diff)
extmod/vfs_fat: Mount FatFS on creation so VFS methods can be used.
It's possible to use the methods (eg ilistdir) of a VFS FatFS object without it being mounted in the VFS itself. This previously worked but only because FatFS was "mounting" the filesystem automatically when any function (eg f_opendir) was called. But it didn't work for ports that used synchronisation objects (_FS_REENTRANT) because they are only initialised via a call to f_mount. So, call f_mount explicitly when creating a new FatFS object so that everything is set up correctly. Then also provide a finaliser to do the f_umount call, but only if synchronisation objects are enabled (since otherwise the f_umount call does nothing).
Diffstat (limited to 'extmod/vfs_fat.c')
-rw-r--r--extmod/vfs_fat.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 9942ddeb5..0076df262 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -69,9 +69,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));
@@ -291,10 +310,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));
@@ -302,22 +319,23 @@ 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);
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) },