Load configuration from a given configuration file. A configuration file is a text file in a .ini style format, that lists configuration options and their values. Lines starting with # are comment lines. Example: \verbatim [configoptions] # set BAR as the value of configuration option FOO FOO=BAR \endverbatim Starting with GDAL 3.5, a configuration file can also contain credentials (or more gen
| 2336 | @since GDAL 3.3 |
| 2337 | */ |
| 2338 | void CPLLoadConfigOptionsFromFile(const char *pszFilename, int bOverrideEnvVars) |
| 2339 | { |
| 2340 | VSILFILE *fp = VSIFOpenL(pszFilename, "rb"); |
| 2341 | if (fp == nullptr) |
| 2342 | return; |
| 2343 | CPLDebug("CPL", "Loading configuration from %s", pszFilename); |
| 2344 | const char *pszLine; |
| 2345 | enum class Section |
| 2346 | { |
| 2347 | NONE, |
| 2348 | GENERAL, |
| 2349 | CONFIG_OPTIONS, |
| 2350 | CREDENTIALS, |
| 2351 | }; |
| 2352 | Section eCurrentSection = Section::NONE; |
| 2353 | bool bInSubsection = false; |
| 2354 | std::string osPath; |
| 2355 | int nSectionCounter = 0; |
| 2356 | |
| 2357 | const auto IsSpaceOnly = [](const char *pszStr) |
| 2358 | { |
| 2359 | for (; *pszStr; ++pszStr) |
| 2360 | { |
| 2361 | if (!isspace(static_cast<unsigned char>(*pszStr))) |
| 2362 | return false; |
| 2363 | } |
| 2364 | return true; |
| 2365 | }; |
| 2366 | |
| 2367 | while ((pszLine = CPLReadLine2L(fp, -1, nullptr)) != nullptr) |
| 2368 | { |
| 2369 | if (IsSpaceOnly(pszLine)) |
| 2370 | { |
| 2371 | // Blank line |
| 2372 | } |
| 2373 | else if (pszLine[0] == '#') |
| 2374 | { |
| 2375 | // Comment line |
| 2376 | } |
| 2377 | else if (strcmp(pszLine, "[configoptions]") == 0) |
| 2378 | { |
| 2379 | nSectionCounter++; |
| 2380 | eCurrentSection = Section::CONFIG_OPTIONS; |
| 2381 | } |
| 2382 | else if (strcmp(pszLine, "[credentials]") == 0) |
| 2383 | { |
| 2384 | nSectionCounter++; |
| 2385 | eCurrentSection = Section::CREDENTIALS; |
| 2386 | bInSubsection = false; |
| 2387 | osPath.clear(); |
| 2388 | } |
| 2389 | else if (strcmp(pszLine, "[directives]") == 0) |
| 2390 | { |
| 2391 | nSectionCounter++; |
| 2392 | if (nSectionCounter != 1) |
| 2393 | { |
| 2394 | CPLError(CE_Warning, CPLE_AppDefined, |
| 2395 | "The [directives] section should be the first one in " |