LCOV - code coverage report
Current view: top level - core - filesystem.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 34.7 % 118 41
Test Date: 2026-03-04 10:22:18 Functions: 40.0 % 15 6

            Line data    Source code
       1              : #include "cfd/core/filesystem.h"
       2              : #include "cfd/core/logging.h"
       3              : 
       4              : #include <stdio.h>
       5              : #include <stdlib.h>
       6              : #include <string.h>
       7              : #include <time.h>
       8              : 
       9              : #ifdef _WIN32
      10              : #include <direct.h>
      11              : #else
      12              : #include <sys/stat.h>
      13              : #include <unistd.h>
      14              : #endif
      15              : 
      16              : //=============================================================================
      17              : // FILE SYSTEM
      18              : //=============================================================================
      19              : 
      20           76 : int ensure_directory_exists(const char* path) {
      21              : #ifdef _WIN32
      22              :     if (_access(path, 0) == 0) {
      23              :         return 1;  // Directory exists
      24              :     }
      25              :     return _mkdir(path) == 0;
      26              : #else
      27           76 :     struct stat st = {0};
      28           76 :     if (stat(path, &st) == 0) {
      29              :         return 1;  // Directory exists
      30              :     }
      31           15 :     return mkdir(path, 0755) == 0;
      32              : #endif
      33              : }
      34              : 
      35              : //=============================================================================
      36              : // OUTPUT PATH CONFIGURATION
      37              : //=============================================================================
      38              : 
      39              : static char artifacts_base_path[512] = "";
      40              : static cfd_default_path_mode_t default_path_mode = CFD_PATH_CURRENT_DIR;
      41              : 
      42            0 : void cfd_set_output_base_dir(const char* path) {
      43            0 :     if (path && strlen(path) > 0) {
      44            0 :         snprintf(artifacts_base_path, sizeof(artifacts_base_path), "%s", path);
      45              :     } else {
      46            0 :         artifacts_base_path[0] = '\0';  // Reset to default
      47              :     }
      48            0 : }
      49              : 
      50            0 : void cfd_set_default_path_mode(cfd_default_path_mode_t mode) {
      51            0 :     default_path_mode = mode;
      52            0 : }
      53              : 
      54              : 
      55           65 : void cfd_get_artifacts_path(char* buffer, size_t size) {
      56           65 :     if (!buffer || size == 0) {
      57              :         return;
      58              :     }
      59              : 
      60           65 :     if (strlen(artifacts_base_path) > 0) {
      61            0 :         snprintf(buffer, size, "%s", artifacts_base_path);
      62            0 :         return;
      63              :     }
      64              : 
      65              :     // Generate default path based on mode
      66           65 :     switch (default_path_mode) {
      67              :         case CFD_PATH_CURRENT_DIR:
      68           65 :             snprintf(buffer, size, ".");
      69           65 :             break;
      70              : 
      71            0 :         case CFD_PATH_TEMP_DIR:
      72              : #ifdef _WIN32
      73              :         {
      74              :             char* temp_dir = getenv("TEMP");
      75              :             if (!temp_dir) {
      76              :                 temp_dir = getenv("TMP");
      77              :             }
      78              :             if (!temp_dir) {
      79              :                 temp_dir = "C:\\temp";
      80              :             }
      81              :             snprintf(buffer, size, "%s", temp_dir);
      82              :         }
      83              : #else
      84              :         {
      85            0 :             char* temp_dir = getenv("TMPDIR");
      86            0 :             if (!temp_dir)
      87            0 :                 temp_dir = "/tmp";
      88            0 :             snprintf(buffer, size, "%s", temp_dir);
      89              :         }
      90              : #endif
      91            0 :         break;
      92              : 
      93              :         case CFD_PATH_RELATIVE_BUILD:
      94              : #ifdef _WIN32
      95              :             snprintf(buffer, size, "..\\..\\artifacts");
      96              : #else
      97            0 :             snprintf(buffer, size, "../../artifacts");
      98              : #endif
      99            0 :             break;
     100              : 
     101              :         default:
     102            0 :             snprintf(buffer, size, ".");
     103            0 :             break;
     104              :     }
     105           65 :     buffer[size - 1] = '\0';
     106              : }
     107              : 
     108            0 : void cfd_reset_artifacts_path(void) {
     109            0 :     artifacts_base_path[0] = '\0';
     110            0 : }
     111              : 
     112              : //=============================================================================
     113              : // PATH CONSTRUCTION
     114              : //=============================================================================
     115           32 : void make_output_path(char* buffer, size_t buffer_size, const char* filename) {
     116           32 :     char base_path[512];
     117           32 :     cfd_get_artifacts_path(base_path, sizeof(base_path));
     118              : 
     119              : #ifdef _WIN32
     120              :     snprintf(buffer, buffer_size, "%s\\output\\%s", base_path, filename);
     121              : #else
     122           32 :     snprintf(buffer, buffer_size, "%s/output/%s", base_path, filename);
     123              : #endif
     124           32 : }
     125              : 
     126           33 : void make_artifacts_path(char* buffer, size_t buffer_size, const char* subdir) {
     127           33 :     char base_path[512];
     128           33 :     cfd_get_artifacts_path(base_path, sizeof(base_path));
     129              : 
     130           33 :     if (subdir && strlen(subdir) > 0) {
     131              : #ifdef _WIN32
     132              :         snprintf(buffer, buffer_size, "%s\\%s", base_path, subdir);
     133              : #else
     134           31 :         snprintf(buffer, buffer_size, "%s/%s", base_path, subdir);
     135              : #endif
     136              :     } else {
     137            2 :         snprintf(buffer, buffer_size, "%s", base_path);
     138              :     }
     139           33 : }
     140              : 
     141              : //=============================================================================
     142              : // RUN DIRECTORY MANAGEMENT
     143              : //=============================================================================
     144              : 
     145              : static char current_run_directory[512] = {0};  // Keep state, but no direct access
     146              : 
     147            5 : static void create_run_directory_internal(char* buffer, size_t buffer_size, const char* base_dir,
     148              :                                           const char* timestamp_name) {
     149              :     // Use provided base directory
     150            5 :     const char* root_path = (base_dir && strlen(base_dir) > 0) ? base_dir : ".";
     151              : 
     152              : #ifdef _WIN32
     153              :     snprintf(buffer, buffer_size, "%s\\output\\%s", root_path, timestamp_name);
     154              : #else
     155            5 :     snprintf(buffer, buffer_size, "%s/output/%s", root_path, timestamp_name);
     156              : #endif
     157              : 
     158              :     // Ensure base output directory exists
     159            5 :     char output_base[512];
     160              : #ifdef _WIN32
     161              :     snprintf(output_base, sizeof(output_base), "%s\\output", root_path);
     162              : #else
     163            5 :     snprintf(output_base, sizeof(output_base), "%s/output", root_path);
     164              : #endif
     165            5 :     ensure_directory_exists(output_base);
     166              : 
     167              :     // Create run-specific directory
     168            5 :     if (!ensure_directory_exists(buffer)) {
     169            3 :         cfd_warning("Failed to create run directory, using base output directory");
     170            3 :         snprintf(buffer, buffer_size, "%s", output_base);
     171              :     }
     172            5 : }
     173              : 
     174            0 : void cfd_create_run_directory(char* buffer, size_t buffer_size) {
     175            0 :     cfd_create_run_directory_with_prefix(buffer, buffer_size, "run");
     176            0 : }
     177              : 
     178            0 : void cfd_create_run_directory_with_prefix(char* buffer, size_t buffer_size, const char* prefix) {
     179            0 :     time_t now = time(NULL);
     180            0 :     struct tm* t = localtime(&now);
     181              : 
     182              :     // Format: prefix_YYYYMMDD_HHMMSS
     183            0 :     char timestamp[64];
     184            0 :     snprintf(timestamp, sizeof(timestamp), "%s_%04d%02d%02d_%02d%02d%02d", prefix,
     185            0 :              t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
     186              : 
     187              :     // Create full path
     188            0 :     char base_path[512];
     189            0 :     cfd_get_artifacts_path(base_path, sizeof(base_path));
     190              : 
     191              : #ifdef _WIN32
     192              :     snprintf(buffer, buffer_size, "%s\\output\\%s", base_path, timestamp);
     193              : #else
     194            0 :     snprintf(buffer, buffer_size, "%s/output/%s", base_path, timestamp);
     195              : #endif
     196              : 
     197              :     // Ensure base output directory exists
     198            0 :     char output_base[512];
     199              : #ifdef _WIN32
     200              :     snprintf(output_base, sizeof(output_base), "%s\\output", base_path);
     201              : #else
     202            0 :     snprintf(output_base, sizeof(output_base), "%s/output", base_path);
     203              : #endif
     204            0 :     ensure_directory_exists(output_base);
     205              : 
     206              :     // Create run-specific directory
     207            0 :     if (!ensure_directory_exists(buffer)) {
     208            0 :         cfd_warning("Failed to create run directory, using base output directory");
     209            0 :         snprintf(buffer, buffer_size, "%s", output_base);
     210              :     }
     211              : 
     212              :     // Store in global state
     213            0 :     snprintf(current_run_directory, sizeof(current_run_directory), "%s", buffer);
     214            0 : }
     215              : 
     216            0 : void cfd_create_run_directory_ex(char* buffer, size_t buffer_size, const char* solver_name,
     217              :                                  size_t nx, size_t ny) {
     218            0 :     time_t now = time(NULL);
     219            0 :     struct tm* t = localtime(&now);
     220              : 
     221              :     // Format: solvername_gridsize_YYYYMMDD_HHMMSS
     222            0 :     char timestamp[128];
     223            0 :     snprintf(timestamp, sizeof(timestamp), "%s_%zux%zu_%04d%02d%02d_%02d%02d%02d",
     224            0 :              solver_name ? solver_name : "sim", nx, ny, t->tm_year + 1900, t->tm_mon + 1,
     225              :              t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
     226              : 
     227              :     // Create full path
     228            0 :     char base_path[512];
     229            0 :     cfd_get_artifacts_path(base_path, sizeof(base_path));
     230              : 
     231              : #ifdef _WIN32
     232              :     snprintf(buffer, buffer_size, "%s\\output\\%s", base_path, timestamp);
     233              : #else
     234            0 :     snprintf(buffer, buffer_size, "%s/output/%s", base_path, timestamp);
     235              : #endif
     236              : 
     237              :     // Ensure base output directory exists
     238            0 :     char output_base[512];
     239              : #ifdef _WIN32
     240              :     snprintf(output_base, sizeof(output_base), "%s\\output", base_path);
     241              : #else
     242            0 :     snprintf(output_base, sizeof(output_base), "%s/output", base_path);
     243              : #endif
     244            0 :     ensure_directory_exists(output_base);
     245              : 
     246              :     // Create run-specific directory
     247            0 :     if (!ensure_directory_exists(buffer)) {
     248            0 :         cfd_warning("Failed to create run directory, using base output directory");
     249            0 :         snprintf(buffer, buffer_size, "%s", output_base);
     250              :     }
     251              : 
     252              :     // Store in global state
     253            0 :     snprintf(current_run_directory, sizeof(current_run_directory), "%s", buffer);
     254            0 : }
     255              : 
     256            0 : void cfd_create_run_directory_with_base(char* buffer, size_t buffer_size, const char* base_dir,
     257              :                                         const char* prefix) {
     258            0 :     time_t now = time(NULL);
     259            0 :     struct tm* t = localtime(&now);
     260              : 
     261              :     // Format: prefix_YYYYMMDD_HHMMSS
     262            0 :     char timestamp[64];
     263            0 :     snprintf(timestamp, sizeof(timestamp), "%s_%04d%02d%02d_%02d%02d%02d", prefix,
     264            0 :              t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
     265              : 
     266            0 :     create_run_directory_internal(buffer, buffer_size, base_dir, timestamp);
     267            0 : }
     268              : 
     269            5 : void cfd_create_run_directory_ex_with_base(char* buffer, size_t buffer_size, const char* base_dir,
     270              :                                            const char* solver_name, size_t nx, size_t ny) {
     271            5 :     time_t now = time(NULL);
     272            5 :     struct tm* t = localtime(&now);
     273              : 
     274              :     // Format: solvername_gridsize_YYYYMMDD_HHMMSS
     275            5 :     char timestamp[128];
     276           10 :     snprintf(timestamp, sizeof(timestamp), "%s_%zux%zu_%04d%02d%02d_%02d%02d%02d",
     277            5 :              solver_name ? solver_name : "sim", nx, ny, t->tm_year + 1900, t->tm_mon + 1,
     278              :              t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
     279              : 
     280            5 :     create_run_directory_internal(buffer, buffer_size, base_dir, timestamp);
     281            5 : }
     282              : 
     283            0 : void cfd_get_run_directory(char* buffer, size_t size) {
     284            0 :     if (!buffer || size == 0) {
     285              :         return;
     286              :     }
     287              : 
     288            0 :     if (current_run_directory[0] != '\0') {
     289            0 :         snprintf(buffer, size, "%s", current_run_directory);
     290              :     } else {
     291            0 :         buffer[0] = '\0';
     292              :     }
     293            0 :     buffer[size - 1] = '\0';
     294              : }
     295              : 
     296            0 : void cfd_reset_run_directory(void) {
     297            0 :     current_run_directory[0] = '\0';
     298            0 : }
        

Generated by: LCOV version 2.0-1