@@ -77,11 +77,13 @@ static int unconfigure_drivers(dmfsi_context_t ctx);
7777static bool is_file (const char * path );
7878static bool is_driver ( const char * name );
7979static void read_base_name (const char * path , char * base_name , size_t name_size );
80+ static void read_dir_name_from_path (const char * path , char * dir_name , size_t name_size );
8081static dmini_context_t read_driver_for_config (const char * config_path , char * driver_name , size_t name_size , const char * default_driver );
8182static Dmod_Context_t * prepare_driver_module (const char * driver_name , bool * was_loaded , bool * was_enabled );
8283static void cleanup_driver_module (const char * driver_name , bool was_loaded , bool was_enabled );
8384static int read_driver_parent_directory ( const driver_node_t * node , char * path_buffer , size_t buffer_size );
8485static int read_driver_node_path ( const driver_node_t * node , char * path_buffer , size_t buffer_size );
86+ static int compare_paths_ignore_trailing_slash ( const char * path1 , const char * path2 );
8587static int compare_driver_directory ( const void * data , const void * user_data );
8688static int compare_driver_node_path ( const void * data , const void * user_data );
8789static int compare_driver (const void * data , const void * user_data );
@@ -643,10 +645,11 @@ dmod_dmfsi_dif_api_declaration( 1.0, dmdevfs, int, _readdir, (dmfsi_context_t ct
643645 return DMFSI_ERR_GENERAL ;
644646 }
645647
646- bool file_should_be_listed = strcmp (dir_node -> directory_path , parent_dir ) == 0 ;
648+ bool file_should_be_listed = compare_paths_ignore_trailing_slash (dir_node -> directory_path , parent_dir ) == 0 ;
647649 if (file_should_be_listed )
648650 {
649- strncpy (entry -> name , driver -> path , sizeof (entry -> name ));
651+ // Extract basename from the full path for the directory entry
652+ read_base_name (driver -> path , entry -> name , sizeof (entry -> name ));
650653
651654 dmdrvi_stat_t stat ;
652655 int res = driver_stat (driver , driver -> path , & stat );
@@ -661,7 +664,9 @@ dmod_dmfsi_dif_api_declaration( 1.0, dmdevfs, int, _readdir, (dmfsi_context_t ct
661664 }
662665 else
663666 {
664- strncpy (entry -> name , parent_dir , sizeof (entry -> name ));
667+ // Extract directory name from parent path for subdirectory entries
668+ // This handles paths like "dev/" -> "dev"
669+ read_dir_name_from_path (parent_dir , entry -> name , sizeof (entry -> name ));
665670 entry -> size = 0 ;
666671 entry -> attr = DMFSI_ATTR_DIRECTORY ;
667672 }
@@ -1006,6 +1011,66 @@ static void read_base_name(const char* path, char* base_name, size_t name_size)
10061011 base_name [name_size - 1 ] = '\0' ;
10071012}
10081013
1014+ /**
1015+ * @brief Extract directory name from a path, handling trailing slashes
1016+ * @param path Path to extract directory name from (may have trailing slash)
1017+ * @param dir_name Output buffer for directory name
1018+ * @param name_size Size of output buffer
1019+ *
1020+ * Examples:
1021+ * - "dev/" -> "dev"
1022+ * - "/dev/" -> "dev"
1023+ * - "dmspiflash0/" -> "dmspiflash0"
1024+ * - "/" -> "" (root has no name)
1025+ */
1026+ static void read_dir_name_from_path (const char * path , char * dir_name , size_t name_size )
1027+ {
1028+ if (path == NULL || dir_name == NULL || name_size == 0 )
1029+ {
1030+ if (dir_name && name_size > 0 )
1031+ {
1032+ dir_name [0 ] = '\0' ;
1033+ }
1034+ return ;
1035+ }
1036+
1037+ // Find the length without trailing slashes
1038+ size_t len = strlen (path );
1039+ while (len > 1 && path [len - 1 ] == '/' )
1040+ {
1041+ len -- ;
1042+ }
1043+
1044+ // Special case: if path is just "/", return empty
1045+ if (len == 1 && path [0 ] == '/' )
1046+ {
1047+ dir_name [0 ] = '\0' ;
1048+ return ;
1049+ }
1050+
1051+ // Find the last slash before the directory name
1052+ const char * last_slash = NULL ;
1053+ for (size_t i = 0 ; i < len ; i ++ )
1054+ {
1055+ if (path [i ] == '/' )
1056+ {
1057+ last_slash = & path [i ];
1058+ }
1059+ }
1060+
1061+ // Extract the directory name
1062+ const char * name_start = (last_slash != NULL ) ? last_slash + 1 : path ;
1063+ size_t name_len = len - (name_start - path );
1064+
1065+ // Use snprintf for safe copying with guaranteed null-termination
1066+ int written = Dmod_SnPrintf (dir_name , name_size , "%.*s" , (int )name_len , name_start );
1067+ if (written < 0 || (size_t )written >= name_size )
1068+ {
1069+ // Truncated, but snprintf ensures null-termination
1070+ dir_name [name_size - 1 ] = '\0' ;
1071+ }
1072+ }
1073+
10091074/**
10101075 * @brief Read driver name from configuration file
10111076 */
@@ -1168,8 +1233,66 @@ static int read_driver_node_path( const driver_node_t* node, char* path_buffer,
11681233 return DMFSI_OK ;
11691234}
11701235
1236+ /**
1237+ * @brief Compare two paths, ignoring trailing slashes
1238+ * @param path1 First path to compare
1239+ * @param path2 Second path to compare
1240+ * @return 0 if equal, non-zero if different
1241+ *
1242+ * Note: The root path "/" is treated specially and retains its slash.
1243+ * For example, "/" and "//" are considered equal, but "dir" and "dir/" are also equal.
1244+ */
1245+ static int compare_paths_ignore_trailing_slash ( const char * path1 , const char * path2 )
1246+ {
1247+ // Handle NULL pointers - both NULL is equal, one NULL is different
1248+ if (path1 == NULL && path2 == NULL )
1249+ {
1250+ return 0 ;
1251+ }
1252+ if (path1 == NULL || path2 == NULL )
1253+ {
1254+ return 1 ;
1255+ }
1256+
1257+ // Get lengths
1258+ size_t len1 = strlen (path1 );
1259+ size_t len2 = strlen (path2 );
1260+
1261+ // Remove trailing slashes from both paths for comparison
1262+ // Keep at least "/" if that's the entire path (len > 1 ensures we keep root "/")
1263+ while (len1 > 1 && path1 [len1 - 1 ] == '/' )
1264+ {
1265+ len1 -- ;
1266+ }
1267+ while (len2 > 1 && path2 [len2 - 1 ] == '/' )
1268+ {
1269+ len2 -- ;
1270+ }
1271+
1272+ // Lengths must match
1273+ if (len1 != len2 )
1274+ {
1275+ return 1 ;
1276+ }
1277+
1278+ // Content must match
1279+ return strncmp (path1 , path2 , len1 );
1280+ }
1281+
11711282/**
11721283 * @brief Compare the path of a driver directory with a given path
1284+ *
1285+ * This function compares the parent directory of a driver node with a given path.
1286+ * It's used by opendir/readdir to find all driver nodes that belong to a specific directory.
1287+ *
1288+ * @param data Pointer to driver_node_t
1289+ * @param user_data Pointer to directory path string
1290+ * @return 0 if the node's parent matches the given path, non-zero otherwise
1291+ *
1292+ * Example: When listing directory "dmspiflash0", this function finds all nodes
1293+ * whose parent directory is "dmspiflash0" (e.g., nodes with path "dmspiflash0/1").
1294+ *
1295+ * Note: Trailing slashes are ignored in comparison, so "dmspiflash0" matches "dmspiflash0/".
11731296 */
11741297static int compare_driver_directory ( const void * data , const void * user_data )
11751298{
@@ -1180,23 +1303,16 @@ static int compare_driver_directory( const void* data, const void* user_data )
11801303 return 0 ;
11811304 }
11821305
1183- char directory_path [MAX_PATH_LENGTH ] = {0 };
1184- if (read_driver_parent_directory (node , directory_path , sizeof (directory_path )) != 0 )
1306+ char parent_dir [MAX_PATH_LENGTH ] = {0 };
1307+ if (read_driver_parent_directory (node , parent_dir , sizeof (parent_dir )) != 0 )
11851308 {
11861309 return -1 ;
11871310 }
11881311
1189- char * driver_path = directory_path ;
1190- while (* path )
1191- {
1192- if (* path != * driver_path )
1193- {
1194- return 1 ;
1195- }
1196- path ++ ;
1197- driver_path ++ ;
1198- }
1199- return 0 ;
1312+ // Use helper function to compare paths, handling optional trailing slashes
1313+ // This ensures exact path matching (not prefix matching) which is critical
1314+ // to prevent "/" from incorrectly matching subdirectories like "dmspiflash0/"
1315+ return compare_paths_ignore_trailing_slash (path , parent_dir );
12001316}
12011317
12021318/**
0 commit comments