I tried to enumerate all the files on my sd card and get the long file names by the way through mfs using k70 with mqx 4.0.0. I just find it a rough work to get the long name of a specified file because it takes too much time.
In the _io_mfs_ioctl method, we can see the IO_IOCTL_GET_LFN' code. It disables the efficient code with #if 0 and just use MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME) to search the entire fs to find the corresponding long file name.
I tried to enable the dummy code and disable the above MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME). Using the MFS_SEARCH_PARAM variable obtained from last find file passed to ioctl() IO_IOCTL_GET_LFN, The result unexpectedly came wrong with no lfn . Something is wrong with this code or the parameter.
Then I checked the dir entries sector cached into memory, I can see that "entry_ptr" a pointer that should point to the short dir entry points to a wrong entry(points to an entry begin with 0x42 which is a tag of the end of long dir entry) .When the program goes on, the desired long dir entry pointer points to a short dir entry leading to a failed finding.Obviously it is an "off-one" issue and the parameter should be changed.
Actually, the DIR_ENTRY_INDEX in SEARCH_DATA is the next index to search and nont the current one, this can be verified in mfs_search.c line 641~645. So something need to be done to decrease the index.Note that you should store and restore the data you changed. I wrote a function MFS_Decrement_dir_index to do that and Insert it in my app.
Finally, I tried, It worked well. Worked code shows below
My app code:
lfn_data.PATHNAME = search_data->NAME;
lfn_data.LONG_FILENAME = (char_ptr)lfn;
lfn_data.SEARCH_DATA_PTR = search_data;
//store the data
tmp_pre_cluster = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER;
tmp_cluster = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER;
tmp_index = lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX;
//current index indicates the next directory entry, so we decrement it here
MFS_Decrement_dir_index(
&lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
&lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX,
&lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER);
error = ioctl(fs_ptr, IO_IOCTL_GET_LFN, (pointer) (&lfn_data));
// restore
lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER = tmp_pre_cluster;
lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER = tmp_cluster;
lfn_data.SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX = tmp_index;
Mfs driver code:
case IO_IOCTL_GET_LFN: MFS_lock(file_ptr, &drive_ptr);
{
MFS_GET_LFN_STRUCT_PTR lfn_ptr = ((MFS_GET_LFN_STRUCT_PTR) param_ptr);
char_ptr pathname = MFS_Parse_Out_Device_Name(lfn_ptr->PATHNAME);
#if 0
result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);
#endif
#if 1 //change from 0 to1
// _mfs_error result;
MFS_DIR_ENTRY_PTR entry_ptr;
if ( lfn_ptr->SEARCH_DATA_PTR )
{
entry_ptr =
MFS_Read_directory_sector(drive_ptr,lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
INDEX_TO_SECTOR(lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX), &result);
if ( (result== MFS_NO_ERROR && entry_ptr!=NULL) )
{
entry_ptr += INDEX_TO_OFFSET (lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX) ;
result = MFS_get_lfn_of_entry(drive_ptr,entry_ptr,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX ,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER,
lfn_ptr->LONG_FILENAME);
}
}
else
{
result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);
}
}
MFS_Decrement_dir_index() implementation is below
/*FUNCTION*-------------------------------------------------------------------
*
* Function Name : MFS_Decrement_dir_index
* Returned Value : uint_32 error_code
* Comments :
*END*---------------------------------------------------------------------*/
_mfs_error MFS_Decrement_dir_index
(
uint_32_ptr cluster_ptr, /*[IN/OUT] the initial/next cluster # */
uint_32_ptr index_ptr, /*[IN/OUT] the initial/next index */
uint_32_ptr prev_cluster_ptr /*[IN/OUT] the prev cluster # */
)
{
uint_32 index;
uint_32 cluster;
_mfs_error error_code;
error_code = MFS_NO_ERROR;
index = *index_ptr;
cluster = *cluster_ptr;
if(0 == index)
{
if ( *prev_cluster_ptr != 0 )
{
//restore prev cluster to current cluster
cluster = *prev_cluster_ptr;
index = 127;
}
else
{
error_code = MFS_INVALID_CLUSTER_NUMBER;
return error_code;
}
}
else
{
index --;
}
if ( (cluster != *cluster_ptr) )
{
if ( prev_cluster_ptr != NULL )
{
*prev_cluster_ptr = 0; //now *prev_cluster_ptr set to 0
}
}
//error is here when index is 138 ,above does not executed and wrongly increased
*index_ptr = index;
*cluster_ptr = cluster;
return(error_code);
}
#endif
Test result:
Sample: 27 directories and 803 files, directory depth is 4.
Currently time cost
Only SLN SLN&LFN
216ms 275ms
Previously the time
Only SLN SLN&LFN
216ms 751ms
case IO_IOCTL_GET_LFN:
MFS_lock(file_ptr, &drive_ptr);
{
MFS_GET_LFN_STRUCT_PTR lfn_ptr = ((MFS_GET_LFN_STRUCT_PTR) param_ptr);
char_ptr pathname = MFS_Parse_Out_Device_Name(lfn_ptr->PATHNAME);
// result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);
#if 1
// _mfs_error result;
MFS_DIR_ENTRY_PTR entry_ptr;
uint_32 tmp_pre_cluster, tmp_cluster, tmp_index;
tmp_pre_cluster = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER;
tmp_cluster = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER;
tmp_index = lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX;
MFS_Decrement_dir_index(
&lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
&lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX,
&lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER);
if ( lfn_ptr->SEARCH_DATA_PTR )
{
entry_ptr =
MFS_Read_directory_sector(drive_ptr,lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
INDEX_TO_SECTOR(lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX), &result);
if ( (result== MFS_NO_ERROR && entry_ptr!=NULL) )
{
entry_ptr += INDEX_TO_OFFSET (lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX);
result = MFS_get_lfn_of_entry(drive_ptr,entry_ptr,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX,
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER,
lfn_ptr->LONG_FILENAME);
}
}
else
{
result = MFS_get_lfn(drive_ptr, pathname, lfn_ptr->LONG_FILENAME);
}
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.PREV_CLUSTER = tmp_pre_cluster;
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.CURRENT_CLUSTER = tmp_cluster;
lfn_ptr->SEARCH_DATA_PTR->INTERNAL_SEARCH_DATA.DIR_ENTRY_INDEX = tmp_index;
#endif
}
MFS_unlock(drive_ptr,FALSE);
break;
maybe we can modify the driver code like this, so we don't need to modify the app code. thank you for save the lfn problem.
Of course it works. But we expect the new patch of the dummy code. I patched the dummy code firstly in this way but then moved it to app because it would not affect others or in other words it is not sure that the dummy code is incorrect. So just make it in app will be more compatible with others and wait the mqx patch or new release.