77#include <errno.h>
88#include <sys/stat.h>
99#include <unistd.h>
10+ #include <fcntl.h>
1011#include <ctype.h>
1112
1213#include "esp_heap_caps.h"
102103#endif
103104
104105//Version number
105- #define JANOS_VERSION "1.3.2 "
106+ #define JANOS_VERSION "1.3.3 "
106107
107108#define OTA_GITHUB_OWNER "C5Lab"
108109#define OTA_GITHUB_REPO "projectZero"
@@ -950,6 +951,7 @@ static char (*sd_html_files)[MAX_HTML_FILENAME] = NULL; // ~3.2 KB in PSRAM
950951static int sd_html_count = 0 ;
951952static char * custom_portal_html = NULL ;
952953static bool sd_card_mounted = false;
954+ static sdmmc_card_t * sd_card_handle = NULL ;
953955#define MAX_SSID_PRESETS 64
954956#define MAX_SSID_NAME_LEN 32
955957#define SSID_PRESET_PATH "/sdcard/lab/ssid.txt"
@@ -1170,6 +1172,8 @@ static void gps_load_state_from_nvs(void);
11701172static void gps_save_state_to_nvs (void );
11711173static esp_err_t init_sd_card (void );
11721174static esp_err_t create_sd_directories (void );
1175+ static void sd_sync (void );
1176+ static void safe_restart (void );
11731177static bool parse_gps_nmea (const char * nmea_sentence );
11741178static void get_timestamp_string (char * buffer , size_t size );
11751179static const char * get_auth_mode_wiggle (wifi_auth_mode_t mode );
@@ -2075,7 +2079,9 @@ static void ota_check_task(void *pvParameters) {
20752079 ota_led_stop ();
20762080 if (err == ESP_OK ) {
20772081 MY_LOG_INFO (TAG , "OTA: update applied, restarting" );
2078- esp_restart ();
2082+ ota_check_in_progress = false;
2083+ free (args );
2084+ safe_restart (); // unmount SD card before restart
20792085 } else {
20802086 MY_LOG_INFO (TAG , "OTA: update failed: %s" , esp_err_to_name (err ));
20812087 }
@@ -5999,7 +6005,7 @@ static int cmd_ota_boot(int argc, char **argv) {
59996005 }
60006006
60016007 MY_LOG_INFO (TAG , "OTA: boot set to %s, restarting" , target -> label );
6002- esp_restart ();
6008+ safe_restart (); // unmount SD card before restart
60036009 return 0 ;
60046010}
60056011
@@ -7630,8 +7636,7 @@ static int cmd_reboot(int argc, char **argv)
76307636{
76317637 (void )argc ; (void )argv ;
76327638 MY_LOG_INFO (TAG ,"Restart..." );
7633- vTaskDelay (pdMS_TO_TICKS (100 ));
7634- esp_restart ();
7639+ safe_restart (); // unmount SD card before restart
76357640 return 0 ;
76367641}
76377642
@@ -8304,6 +8309,7 @@ static int cmd_file_delete(int argc, char **argv)
83048309 MY_LOG_INFO (TAG , "Failed to delete %s: %s" , full_path , strerror (errno ));
83058310 return 1 ;
83068311 }
8312+ sd_sync ();
83078313
83088314 MY_LOG_INFO (TAG , "Deleted %s" , full_path );
83098315 return 0 ;
@@ -8652,6 +8658,7 @@ static void wardrive_task(void *pvParameters) {
86528658
86538659 // Close file to ensure data is written
86548660 fclose (file );
8661+ sd_sync ();
86558662
86568663 if (scan_count > 0 ) {
86578664 MY_LOG_INFO (TAG , "Logged %d networks to %s" , scan_count , filename );
@@ -13014,6 +13021,31 @@ static void gps_load_state_from_nvs(void) {
1301413021 }
1301513022}
1301613023
13024+ // Flush FAT filesystem buffers to SD card to ensure metadata consistency.
13025+ // ESP-IDF newlib does not implement POSIX sync(), so we force a flush by
13026+ // opening a temporary file, calling fsync() on its descriptor (which
13027+ // triggers FatFs f_sync and flushes the FAT table), then removing it.
13028+ static void sd_sync (void ) {
13029+ int fd = open ("/sdcard/.sync" , O_WRONLY | O_CREAT | O_TRUNC , 0644 );
13030+ if (fd >= 0 ) {
13031+ fsync (fd );
13032+ close (fd );
13033+ unlink ("/sdcard/.sync" );
13034+ }
13035+ }
13036+
13037+ // Safely unmount SD card and restart to prevent FAT filesystem corruption
13038+ static void safe_restart (void ) {
13039+ if (sd_card_mounted && sd_card_handle ) {
13040+ MY_LOG_INFO (TAG , "Unmounting SD card before restart..." );
13041+ esp_vfs_fat_sdcard_unmount ("/sdcard" , sd_card_handle );
13042+ sd_card_mounted = false;
13043+ sd_card_handle = NULL ;
13044+ }
13045+ vTaskDelay (pdMS_TO_TICKS (100 ));
13046+ esp_restart ();
13047+ }
13048+
1301713049static esp_err_t init_sd_card (void ) {
1301813050 esp_err_t ret ;
1301913051
@@ -13030,7 +13062,6 @@ static esp_err_t init_sd_card(void) {
1303013062 .disk_status_check_enable = false
1303113063 };
1303213064
13033- sdmmc_card_t * card ;
1303413065 const char mount_point [] = "/sdcard" ;
1303513066
1303613067 // Configure SPI bus (balanced for SD card requirements and memory)
@@ -13057,15 +13088,15 @@ static esp_err_t init_sd_card(void) {
1305713088 slot_config .gpio_cs = SD_CS_PIN ;
1305813089 slot_config .host_id = host .slot ;
1305913090
13060- ret = esp_vfs_fat_sdspi_mount (mount_point , & host , & slot_config , & mount_config , & card );
13091+ ret = esp_vfs_fat_sdspi_mount (mount_point , & host , & slot_config , & mount_config , & sd_card_handle );
1306113092
1306213093 if (ret != ESP_OK ) {
1306313094 return ret ;
1306413095 }
1306513096
1306613097 // Print card info
1306713098 MY_LOG_INFO (TAG , "SD card mounted successfully" );
13068- sdmmc_card_print_info (stdout , card );
13099+ sdmmc_card_print_info (stdout , sd_card_handle );
1306913100
1307013101 // Test file creation to verify write access
1307113102 FILE * test_file = fopen ("/sdcard/test.txt" , "w" );
@@ -13075,6 +13106,7 @@ static esp_err_t init_sd_card(void) {
1307513106 MY_LOG_INFO (TAG , "SD card write test successful" );
1307613107 // Clean up test file
1307713108 unlink ("/sdcard/test.txt" );
13109+ sd_sync ();
1307813110 } else {
1307913111 MY_LOG_INFO (TAG , "SD card write test failed, errno: %d (%s)" , errno , strerror (errno ));
1308013112 }
@@ -13098,6 +13130,7 @@ static esp_err_t create_sd_directories(void) {
1309813130 MY_LOG_INFO (TAG , "Failed to create /sdcard/lab directory: %s" , strerror (errno ));
1309913131 return ESP_FAIL ;
1310013132 }
13133+ sd_sync ();
1310113134 MY_LOG_INFO (TAG , "/sdcard/lab created successfully" );
1310213135 } else {
1310313136 MY_LOG_INFO (TAG , "/sdcard/lab already exists" );
@@ -13110,6 +13143,7 @@ static esp_err_t create_sd_directories(void) {
1311013143 MY_LOG_INFO (TAG , "Failed to create /sdcard/lab/htmls directory: %s" , strerror (errno ));
1311113144 return ESP_FAIL ;
1311213145 }
13146+ sd_sync ();
1311313147 MY_LOG_INFO (TAG , "/sdcard/lab/htmls created successfully" );
1311413148 } else {
1311513149 MY_LOG_INFO (TAG , "/sdcard/lab/htmls already exists" );
@@ -13122,6 +13156,7 @@ static esp_err_t create_sd_directories(void) {
1312213156 MY_LOG_INFO (TAG , "Failed to create /sdcard/lab/handshakes directory: %s" , strerror (errno ));
1312313157 return ESP_FAIL ;
1312413158 }
13159+ sd_sync ();
1312513160 MY_LOG_INFO (TAG , "/sdcard/lab/handshakes created successfully" );
1312613161 } else {
1312713162 MY_LOG_INFO (TAG , "/sdcard/lab/handshakes already exists" );
@@ -13134,6 +13169,7 @@ static esp_err_t create_sd_directories(void) {
1313413169 MY_LOG_INFO (TAG , "Failed to create /sdcard/lab/wardrives directory: %s" , strerror (errno ));
1313513170 return ESP_FAIL ;
1313613171 }
13172+ sd_sync ();
1313713173 MY_LOG_INFO (TAG , "/sdcard/lab/wardrives created successfully" );
1313813174 } else {
1313913175 MY_LOG_INFO (TAG , "/sdcard/lab/wardrives already exists" );
@@ -13359,6 +13395,7 @@ static void save_evil_twin_password(const char* ssid, const char* password) {
1335913395 // Flush and close file to ensure data is written to disk
1336013396 fflush (file );
1336113397 fclose (file );
13398+ sd_sync ();
1336213399
1336313400 MY_LOG_INFO (TAG , "Password saved to eviltwin.txt" );
1336413401}
@@ -13408,6 +13445,7 @@ static void save_portal_data(const char* ssid, const char* form_data) {
1340813445 char * data_copy = strdup (form_data );
1340913446 if (data_copy == NULL ) {
1341013447 fclose (file );
13448+ sd_sync ();
1341113449 return ;
1341213450 }
1341313451
@@ -13418,6 +13456,7 @@ static void save_portal_data(const char* ssid, const char* form_data) {
1341813456 MY_LOG_INFO (TAG , "Memory allocation failed for temp_copy" );
1341913457 free (data_copy );
1342013458 fclose (file );
13459+ sd_sync ();
1342113460 return ;
1342213461 }
1342313462
@@ -13488,6 +13527,7 @@ static void save_portal_data(const char* ssid, const char* form_data) {
1348813527 // Flush and close file to ensure data is written to disk
1348913528 fflush (file );
1349013529 fclose (file );
13530+ sd_sync ();
1349113531
1349213532 free (data_copy );
1349313533
0 commit comments