@ -35,6 +35,7 @@
# include "lib/fatfs/diskio.h"
# include "extmod/vfs_fat_file.h"
# include "extmod/fsusermount.h"
# include "timeutils.h"
# define mp_obj_fat_vfs_t fs_user_mount_t
@ -152,6 +153,94 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1 ( fat_vfs_getcwd_obj , fat_vfs_getcwd ) ;
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal ( const char * path , const char * path_canonical ) {
while ( * path_canonical ! = ' \0 ' & & * path = = * path_canonical ) {
+ + path ;
+ + path_canonical ;
}
if ( * path_canonical ! = ' \0 ' ) {
return false ;
}
while ( * path = = ' / ' ) {
+ + path ;
}
return * path = = ' \0 ' ;
}
/// \function stat(path)
/// Get the status of a file or directory.
STATIC mp_obj_t fat_vfs_stat ( mp_obj_t vfs_in , mp_obj_t path_in ) {
const char * path = mp_obj_str_get_str ( path_in ) ;
FILINFO fno ;
# if _USE_LFN
fno . lfname = NULL ;
fno . lfsize = 0 ;
# endif
FRESULT res ;
if ( path_equal ( path , " / " ) ) {
// stat root directory
fno . fsize = 0 ;
fno . fdate = 0 ;
fno . ftime = 0 ;
fno . fattrib = AM_DIR ;
} else {
res = FR_NO_PATH ;
for ( size_t i = 0 ; i < MP_ARRAY_SIZE ( MP_STATE_PORT ( fs_user_mount ) ) ; + + i ) {
fs_user_mount_t * vfs = MP_STATE_PORT ( fs_user_mount ) [ i ] ;
if ( vfs ! = NULL & & path_equal ( path , vfs - > str ) ) {
// stat mounted device directory
fno . fsize = 0 ;
fno . fdate = 0 ;
fno . ftime = 0 ;
fno . fattrib = AM_DIR ;
res = FR_OK ;
}
}
if ( res = = FR_NO_PATH ) {
// stat normal file
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_TO_PTR ( mp_obj_new_tuple ( 10 , NULL ) ) ;
mp_int_t mode = 0 ;
if ( fno . fattrib & AM_DIR ) {
mode | = 0x4000 ; // stat.S_IFDIR
} else {
mode | = 0x8000 ; // stat.S_IFREG
}
mp_int_t seconds = timeutils_seconds_since_2000 (
1980 + ( ( fno . fdate > > 9 ) & 0x7f ) ,
( fno . fdate > > 5 ) & 0x0f ,
fno . fdate & 0x1f ,
( fno . ftime > > 11 ) & 0x1f ,
( fno . ftime > > 5 ) & 0x3f ,
2 * ( fno . ftime & 0x1f )
) ;
t - > items [ 0 ] = MP_OBJ_NEW_SMALL_INT ( mode ) ; // st_mode
t - > items [ 1 ] = MP_OBJ_NEW_SMALL_INT ( 0 ) ; // st_ino
t - > items [ 2 ] = MP_OBJ_NEW_SMALL_INT ( 0 ) ; // st_dev
t - > items [ 3 ] = MP_OBJ_NEW_SMALL_INT ( 0 ) ; // st_nlink
t - > items [ 4 ] = MP_OBJ_NEW_SMALL_INT ( 0 ) ; // st_uid
t - > items [ 5 ] = MP_OBJ_NEW_SMALL_INT ( 0 ) ; // st_gid
t - > items [ 6 ] = MP_OBJ_NEW_SMALL_INT ( fno . fsize ) ; // st_size
t - > items [ 7 ] = MP_OBJ_NEW_SMALL_INT ( seconds ) ; // st_atime
t - > items [ 8 ] = MP_OBJ_NEW_SMALL_INT ( seconds ) ; // st_mtime
t - > items [ 9 ] = MP_OBJ_NEW_SMALL_INT ( seconds ) ; // st_ctime
return MP_OBJ_FROM_PTR ( t ) ;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2 ( fat_vfs_stat_obj , fat_vfs_stat ) ;
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 ) } ,
@ -161,6 +250,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR ( MP_QSTR_getcwd ) , MP_ROM_PTR ( & fat_vfs_getcwd_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_remove ) , MP_ROM_PTR ( & fat_vfs_remove_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_rename ) , MP_ROM_PTR ( & fat_vfs_rename_obj ) } ,
{ MP_ROM_QSTR ( MP_QSTR_stat ) , MP_ROM_PTR ( & fat_vfs_stat_obj ) } ,
} ;
STATIC MP_DEFINE_CONST_DICT ( fat_vfs_locals_dict , fat_vfs_locals_dict_table ) ;