39
39
#include "lib/oofatfs/ff.h"
40
40
#include "extmod/vfs_fat.h"
41
41
#include "lib/timeutils/timeutils.h"
42
-
42
+ #include "supervisor/filesystem.h"
43
43
#include "supervisor/shared/translate.h"
44
44
45
45
#if _MAX_SS == _MIN_SS
@@ -99,6 +99,12 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, const
99
99
return MP_OBJ_FROM_PTR (vfs );
100
100
}
101
101
102
+ STATIC void verify_fs_writable (fs_user_mount_t * vfs ) {
103
+ if (!filesystem_is_writable_by_python (vfs )) {
104
+ mp_raise_OSError (MP_EROFS );
105
+ }
106
+ }
107
+
102
108
#if _FS_REENTRANT
103
109
STATIC mp_obj_t fat_vfs_del (mp_obj_t self_in ) {
104
110
mp_obj_fat_vfs_t * self = MP_OBJ_TO_PTR (self_in );
@@ -201,6 +207,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_i
201
207
202
208
STATIC mp_obj_t fat_vfs_remove_internal (mp_obj_t vfs_in , mp_obj_t path_in , mp_int_t attr ) {
203
209
mp_obj_fat_vfs_t * self = MP_OBJ_TO_PTR (vfs_in );
210
+ verify_fs_writable (self );
204
211
const char * path = mp_obj_str_get_str (path_in );
205
212
206
213
FILINFO fno ;
@@ -235,9 +242,26 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir);
235
242
236
243
STATIC mp_obj_t fat_vfs_rename (mp_obj_t vfs_in , mp_obj_t path_in , mp_obj_t path_out ) {
237
244
mp_obj_fat_vfs_t * self = MP_OBJ_TO_PTR (vfs_in );
245
+ verify_fs_writable (self );
238
246
const char * old_path = mp_obj_str_get_str (path_in );
239
247
const char * new_path = mp_obj_str_get_str (path_out );
240
- FRESULT res = f_rename (& self -> fatfs , old_path , new_path );
248
+
249
+ // Check to see if we're moving a directory into itself. This occurs when we're moving a
250
+ // directory where the old path is a prefix of the new and the next character is a "/" and thus
251
+ // preserves the original directory name.
252
+ FILINFO fno ;
253
+ FRESULT res = f_stat (& self -> fatfs , old_path , & fno );
254
+ if (res != FR_OK ) {
255
+ mp_raise_OSError (fresult_to_errno_table [res ]);
256
+ }
257
+ if ((fno .fattrib & AM_DIR ) != 0 &&
258
+ strlen (new_path ) > strlen (old_path ) &&
259
+ new_path [strlen (old_path )] == '/' &&
260
+ strncmp (old_path , new_path , strlen (old_path )) == 0 ) {
261
+ mp_raise_OSError (MP_EINVAL );
262
+ }
263
+
264
+ res = f_rename (& self -> fatfs , old_path , new_path );
241
265
if (res == FR_EXIST ) {
242
266
// if new_path exists then try removing it (but only if it's a file)
243
267
fat_vfs_remove_internal (vfs_in , path_out , 0 ); // 0 == file attribute
@@ -255,6 +279,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename);
255
279
256
280
STATIC mp_obj_t fat_vfs_mkdir (mp_obj_t vfs_in , mp_obj_t path_o ) {
257
281
mp_obj_fat_vfs_t * self = MP_OBJ_TO_PTR (vfs_in );
282
+ verify_fs_writable (self );
258
283
const char * path = mp_obj_str_get_str (path_o );
259
284
FRESULT res = f_mkdir (& self -> fatfs , path );
260
285
if (res == FR_OK ) {
@@ -419,6 +444,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel);
419
444
420
445
STATIC mp_obj_t vfs_fat_setlabel (mp_obj_t self_in , mp_obj_t label_in ) {
421
446
fs_user_mount_t * self = MP_OBJ_TO_PTR (self_in );
447
+ verify_fs_writable (self );
422
448
const char * label_str = mp_obj_str_get_str (label_in );
423
449
FRESULT res = f_setlabel (& self -> fatfs , label_str );
424
450
if (res != FR_OK ) {
0 commit comments