diff --git a/applications/services/storage/storage.c b/applications/services/storage/storage.c index bfe2a08b21..d05ffb6356 100644 --- a/applications/services/storage/storage.c +++ b/applications/services/storage/storage.c @@ -102,11 +102,6 @@ int32_t storage_srv(void* p) { Storage* app = storage_app_alloc(); furi_record_create(RECORD_STORAGE, app); - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStorageFormatInternal)) { - FURI_LOG_W(TAG, "Format Internal not supported, clearing flag"); - furi_hal_rtc_reset_flag(FuriHalRtcFlagStorageFormatInternal); - } - StorageMessage message; while(1) { if(furi_message_queue_get(app->message_queue, &message, STORAGE_TICK) == FuriStatusOk) { diff --git a/applications/services/storage/storage_internal_dirname_i.h b/applications/services/storage/storage_internal_dirname_i.h new file mode 100644 index 0000000000..889bdc4976 --- /dev/null +++ b/applications/services/storage/storage_internal_dirname_i.h @@ -0,0 +1,3 @@ +#pragma once + +#define STORAGE_INTERNAL_DIR_NAME ".int" diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index 5645899307..8d86dd3851 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -1,7 +1,9 @@ -#include "storage_processing.h" #include #include +#include "storage_processing.h" +#include "storage_internal_dirname_i.h" + #define TAG "Storage" #define STORAGE_PATH_PREFIX_LEN 4u @@ -555,9 +557,9 @@ void storage_process_alias( } else if(furi_string_start_with(path, STORAGE_INT_PATH_PREFIX)) { furi_string_replace_at( - path, 0, strlen(STORAGE_INT_PATH_PREFIX), STORAGE_EXT_PATH_PREFIX "/.int"); + path, 0, strlen(STORAGE_INT_PATH_PREFIX), EXT_PATH(STORAGE_INTERNAL_DIR_NAME)); - FuriString* int_on_ext_path = furi_string_alloc_set(STORAGE_EXT_PATH_PREFIX "/.int"); + FuriString* int_on_ext_path = furi_string_alloc_set(EXT_PATH(STORAGE_INTERNAL_DIR_NAME)); if(storage_process_common_stat(app, int_on_ext_path, NULL) != FSE_OK) { storage_process_common_mkdir(app, int_on_ext_path); } diff --git a/applications/services/storage/storages/storage_ext.c b/applications/services/storage/storages/storage_ext.c index 93e06f6632..a945f1cd51 100644 --- a/applications/services/storage/storages/storage_ext.c +++ b/applications/services/storage/storages/storage_ext.c @@ -1,10 +1,13 @@ -#include "fatfs.h" -#include "../filesystem_api_internal.h" -#include "storage_ext.h" +#include #include -#include "sd_notify.h" #include +#include "sd_notify.h" +#include "storage_ext.h" + +#include "../filesystem_api_internal.h" +#include "../storage_internal_dirname_i.h" + typedef FIL SDFile; typedef DIR SDDir; typedef FILINFO SDFileInfo; @@ -93,6 +96,64 @@ static bool sd_mount_card_internal(StorageData* storage, bool notify) { return result; } +static bool sd_remove_recursive(const char* path) { + SDDir* current_dir = malloc(sizeof(DIR)); + SDFileInfo* file_info = malloc(sizeof(FILINFO)); + FuriString* current_path = furi_string_alloc_set(path); + + bool go_deeper = false; + SDError status; + + while(true) { + status = f_opendir(current_dir, furi_string_get_cstr(current_path)); + if(status != FR_OK) break; + + while(true) { + status = f_readdir(current_dir, file_info); + if(status != FR_OK || !strlen(file_info->fname)) break; + + if(file_info->fattrib & AM_DIR) { + furi_string_cat_printf(current_path, "/%s", file_info->fname); + go_deeper = true; + break; + + } else { + FuriString* file_path = furi_string_alloc_printf( + "%s/%s", furi_string_get_cstr(current_path), file_info->fname); + status = f_unlink(furi_string_get_cstr(file_path)); + furi_string_free(file_path); + + if(status != FR_OK) break; + } + } + + status = f_closedir(current_dir); + if(status != FR_OK) break; + + if(go_deeper) { + go_deeper = false; + continue; + } + + status = f_unlink(furi_string_get_cstr(current_path)); + if(status != FR_OK) break; + + if(!furi_string_equal(current_path, path)) { + size_t last_char_pos = furi_string_search_rchar(current_path, '/'); + furi_assert(last_char_pos != FURI_STRING_FAILURE); + furi_string_left(current_path, last_char_pos); + } else { + break; + } + } + + free(current_dir); + free(file_info); + furi_string_free(current_path); + + return status == FR_OK; +} + FS_Error sd_unmount_card(StorageData* storage) { SDData* sd_data = storage->data; SDError error; @@ -112,21 +173,32 @@ FS_Error sd_mount_card(StorageData* storage, bool notify) { if(storage->status != StorageStatusOK) { FURI_LOG_E(TAG, "sd init error: %s", storage_data_status_text(storage)); - if(notify) { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - sd_notify_error(notification); - furi_record_close(RECORD_NOTIFICATION); - } error = FSE_INTERNAL; + } else { FURI_LOG_I(TAG, "card mounted"); - if(notify) { - NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); - sd_notify_success(notification); - furi_record_close(RECORD_NOTIFICATION); - } +#ifndef FURI_RAM_EXEC + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagStorageFormatInternal)) { + FURI_LOG_I(TAG, "deleting internal storage directory"); + error = sd_remove_recursive(STORAGE_INTERNAL_DIR_NAME) ? FSE_OK : FSE_INTERNAL; + } else { + error = FSE_OK; + } +#else + UNUSED(sd_remove_recursive); error = FSE_OK; +#endif + } + + if(notify) { + NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); + if(error != FSE_OK) { + sd_notify_error(notification); + } else { + sd_notify_success(notification); + } + furi_record_close(RECORD_NOTIFICATION); } return error; @@ -654,4 +726,8 @@ void storage_ext_init(StorageData* storage) { // do not notify on first launch, notifications app is waiting for our thread to read settings storage_ext_tick_internal(storage, false); +#ifndef FURI_RAM_EXEC + // always reset the flag to prevent accidental wipe on SD card insertion + furi_hal_rtc_reset_flag(FuriHalRtcFlagStorageFormatInternal); +#endif }