|
23 | 23 | #define DMDEVFS_CONTEXT_MAGIC 0x444D4456 // 'DMDV' |
24 | 24 | #define ROOT_DIRECTORY_NAME "/" |
25 | 25 | #define MAX_PATH_LENGTH (DMOD_MAX_MODULE_NAME_LENGTH + 20) |
26 | | -#define INI_LINE_BUFFER_SIZE 256 |
27 | 26 | #define INI_MAIN_SECTION "main" |
28 | 27 |
|
29 | 28 | /** |
@@ -75,7 +74,7 @@ struct dmfsi_context |
75 | 74 | // ============================================================================ |
76 | 75 | static int configure_drivers(dmfsi_context_t ctx, const char* driver_name, const char* config_path); |
77 | 76 | static driver_node_t* configure_driver(const char* driver_name, dmini_context_t config_ctx); |
78 | | -static int configure_section_drivers(dmfsi_context_t ctx, dmini_context_t config_ctx, const char* config_path); |
| 77 | +static int configure_section_drivers(dmfsi_context_t ctx, dmini_context_t config_ctx); |
79 | 78 | static int unconfigure_drivers(dmfsi_context_t ctx); |
80 | 79 | static bool is_file(const char* path); |
81 | 80 | static bool is_driver( const char* name); |
@@ -857,7 +856,7 @@ static int configure_drivers(dmfsi_context_t ctx, const char* driver_name, const |
857 | 856 | // Section-specific driver_name entries take priority over the file/directory |
858 | 857 | // derived driver name. Only configure the main driver when no section-level |
859 | 858 | // drivers are present in the file. |
860 | | - int section_drivers_added = configure_section_drivers(ctx, config_ctx, full_path); |
| 859 | + int section_drivers_added = configure_section_drivers(ctx, config_ctx); |
861 | 860 | if (section_drivers_added == 0) |
862 | 861 | { |
863 | 862 | driver_node_t* driver_node = configure_driver(module_name, config_ctx); |
@@ -967,90 +966,112 @@ static driver_node_t* configure_driver(const char* driver_name, dmini_context_t |
967 | 966 | /** |
968 | 967 | * @brief Configure drivers for non-main sections that contain a driver_name key |
969 | 968 | * |
970 | | - * Scans the config file line by line for INI section headers. For each section |
971 | | - * other than "main" that contains a driver_name key, a new driver is configured |
972 | | - * with the INI context restricted to that section via dmini_set_active_section, |
973 | | - * so the driver only sees the keys belonging to its own section. |
| 969 | + * Uses dmini_generate_string to obtain the full INI content from the |
| 970 | + * already-parsed context (avoiding a second read of the config file from |
| 971 | + * disk). Each non-main section that contains a driver_name key is configured |
| 972 | + * as a separate driver with the INI context restricted to that section via |
| 973 | + * dmini_set_active_section, so the driver only sees the keys belonging to its |
| 974 | + * own section. |
974 | 975 | * |
975 | 976 | * Returns the number of section-specific drivers that were successfully added. |
976 | 977 | * A non-zero return value signals to the caller that the file is a multi-driver |
977 | 978 | * config and no fallback main driver should be configured. |
978 | 979 | */ |
979 | | -static int configure_section_drivers(dmfsi_context_t ctx, dmini_context_t config_ctx, const char* config_path) |
| 980 | +static int configure_section_drivers(dmfsi_context_t ctx, dmini_context_t config_ctx) |
980 | 981 | { |
981 | | - void* file = Dmod_FileOpen(config_path, "r"); |
982 | | - if (file == NULL) |
| 982 | + // Generate the full INI content from the already-parsed dmini context. |
| 983 | + // This avoids re-reading the file from disk; we work entirely with the |
| 984 | + // in-memory representation that dmini built during dmini_parse_file. |
| 985 | + int content_size = dmini_generate_string(config_ctx, NULL, 0); |
| 986 | + if (content_size <= 0) |
983 | 987 | { |
984 | | - DMOD_LOG_ERROR("Failed to open config file for section scan: %s\n", config_path); |
985 | 988 | return 0; |
986 | 989 | } |
987 | 990 |
|
988 | | - int num_added = 0; |
989 | | - char line[INI_LINE_BUFFER_SIZE]; |
990 | | - while (Dmod_FileReadLine(line, sizeof(line), file) != NULL) |
| 991 | + char* ini_content = (char*)Dmod_Malloc((size_t)content_size); |
| 992 | + if (ini_content == NULL) |
991 | 993 | { |
992 | | - // Skip lines that don't start with '[' (ignore leading whitespace) |
993 | | - char* p = line; |
994 | | - while (*p == ' ' || *p == '\t') p++; |
995 | | - if (*p != '[') continue; |
996 | | - |
997 | | - // Find closing bracket |
998 | | - char* end = strchr(p, ']'); |
999 | | - if (end == NULL || end <= p) continue; |
| 994 | + DMOD_LOG_ERROR("Failed to allocate buffer for INI content scan\n"); |
| 995 | + return 0; |
| 996 | + } |
1000 | 997 |
|
1001 | | - // Extract section name |
1002 | | - size_t name_len = (size_t)(end - p - 1); |
1003 | | - if (name_len == 0 || name_len >= DMOD_MAX_MODULE_NAME_LENGTH) continue; |
| 998 | + if (dmini_generate_string(config_ctx, ini_content, (size_t)content_size) <= 0) |
| 999 | + { |
| 1000 | + Dmod_Free(ini_content); |
| 1001 | + return 0; |
| 1002 | + } |
1004 | 1003 |
|
1005 | | - char section_name[DMOD_MAX_MODULE_NAME_LENGTH]; |
1006 | | - strncpy(section_name, p + 1, name_len); |
1007 | | - section_name[name_len] = '\0'; |
| 1004 | + int num_added = 0; |
| 1005 | + const char* p = ini_content; |
| 1006 | + while (*p != '\0') |
| 1007 | + { |
| 1008 | + // Skip leading whitespace on the line |
| 1009 | + while (*p == ' ' || *p == '\t') p++; |
1008 | 1010 |
|
1009 | | - // Trim trailing whitespace from section name |
1010 | | - size_t slen = strlen(section_name); |
1011 | | - while (slen > 0 && (section_name[slen - 1] == ' ' || section_name[slen - 1] == '\t')) |
| 1011 | + if (*p == '[') |
1012 | 1012 | { |
1013 | | - slen--; |
1014 | | - } |
1015 | | - section_name[slen] = '\0'; |
1016 | | - |
1017 | | - // Skip empty section names and the "main" section (handled by existing logic) |
1018 | | - if (slen == 0 || strcmp(section_name, INI_MAIN_SECTION) == 0) continue; |
1019 | | - |
1020 | | - // Check if this section has a driver_name key |
1021 | | - if (!dmini_has_key(config_ctx, section_name, "driver_name")) continue; |
| 1013 | + // Extract section name between '[' and ']' |
| 1014 | + const char* name_start = p + 1; |
| 1015 | + const char* name_end = name_start; |
| 1016 | + while (*name_end != '\0' && *name_end != ']' && *name_end != '\n') name_end++; |
1022 | 1017 |
|
1023 | | - const char* drv_name = dmini_get_string(config_ctx, section_name, "driver_name", NULL); |
1024 | | - if (drv_name == NULL) continue; |
1025 | | - |
1026 | | - char module_name[DMOD_MAX_MODULE_NAME_LENGTH]; |
1027 | | - strncpy(module_name, drv_name, sizeof(module_name)); |
1028 | | - module_name[sizeof(module_name) - 1] = '\0'; |
| 1018 | + if (*name_end == ']') |
| 1019 | + { |
| 1020 | + // Trim leading whitespace inside the brackets |
| 1021 | + while (name_start < name_end && (*name_start == ' ' || *name_start == '\t')) name_start++; |
| 1022 | + // Trim trailing whitespace inside the brackets |
| 1023 | + while (name_end > name_start && (*(name_end - 1) == ' ' || *(name_end - 1) == '\t')) name_end--; |
1029 | 1024 |
|
1030 | | - // Restrict the INI context to this section and configure the driver. |
1031 | | - // Token 0 means no owner-token protection (context was created with dmini_create). |
1032 | | - dmini_set_active_section(config_ctx, section_name, 0); |
1033 | | - driver_node_t* driver_node = configure_driver(module_name, config_ctx); |
1034 | | - dmini_clear_active_section(config_ctx, 0); |
| 1025 | + size_t name_len = (size_t)(name_end - name_start); |
| 1026 | + if (name_len > 0 && name_len < DMOD_MAX_MODULE_NAME_LENGTH) |
| 1027 | + { |
| 1028 | + char section_name[DMOD_MAX_MODULE_NAME_LENGTH]; |
| 1029 | + strncpy(section_name, name_start, name_len); |
| 1030 | + section_name[name_len] = '\0'; |
1035 | 1031 |
|
1036 | | - if (driver_node == NULL) |
1037 | | - { |
1038 | | - DMOD_LOG_ERROR("Failed to configure driver for section [%s]: %s\n", section_name, module_name); |
1039 | | - continue; |
| 1032 | + // Skip the [main] section; it is handled by existing logic |
| 1033 | + if (strcmp(section_name, INI_MAIN_SECTION) != 0 && |
| 1034 | + dmini_has_key(config_ctx, section_name, "driver_name")) |
| 1035 | + { |
| 1036 | + const char* drv_name = dmini_get_string(config_ctx, section_name, "driver_name", NULL); |
| 1037 | + if (drv_name != NULL) |
| 1038 | + { |
| 1039 | + char module_name[DMOD_MAX_MODULE_NAME_LENGTH]; |
| 1040 | + strncpy(module_name, drv_name, sizeof(module_name)); |
| 1041 | + module_name[sizeof(module_name) - 1] = '\0'; |
| 1042 | + |
| 1043 | + // Restrict the INI context to this section and configure the driver. |
| 1044 | + // Token 0 means no owner-token protection (context was created with dmini_create). |
| 1045 | + dmini_set_active_section(config_ctx, section_name, 0); |
| 1046 | + driver_node_t* driver_node = configure_driver(module_name, config_ctx); |
| 1047 | + dmini_clear_active_section(config_ctx, 0); |
| 1048 | + |
| 1049 | + if (driver_node == NULL) |
| 1050 | + { |
| 1051 | + DMOD_LOG_ERROR("Failed to configure driver for section [%s]: %s\n", |
| 1052 | + section_name, module_name); |
| 1053 | + } |
| 1054 | + else if (!dmlist_push_back(ctx->drivers, driver_node)) |
| 1055 | + { |
| 1056 | + DMOD_LOG_ERROR("Failed to add driver to list: %s\n", module_name); |
| 1057 | + Dmod_Free(driver_node); |
| 1058 | + } |
| 1059 | + else |
| 1060 | + { |
| 1061 | + num_added++; |
| 1062 | + } |
| 1063 | + } |
| 1064 | + } |
| 1065 | + } |
| 1066 | + } |
1040 | 1067 | } |
1041 | 1068 |
|
1042 | | - if (!dmlist_push_back(ctx->drivers, driver_node)) |
1043 | | - { |
1044 | | - DMOD_LOG_ERROR("Failed to add driver to list: %s\n", module_name); |
1045 | | - Dmod_Free(driver_node); |
1046 | | - } |
1047 | | - else |
1048 | | - { |
1049 | | - num_added++; |
1050 | | - } |
| 1069 | + // Advance to the next line |
| 1070 | + while (*p != '\0' && *p != '\n') p++; |
| 1071 | + if (*p == '\n') p++; |
1051 | 1072 | } |
1052 | 1073 |
|
1053 | | - Dmod_FileClose(file); |
| 1074 | + Dmod_Free(ini_content); |
1054 | 1075 | return num_added; |
1055 | 1076 | } |
1056 | 1077 |
|
|
0 commit comments