mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-11 06:09:08 -07:00
Merge branch 'dev' of https://github.com/flipperdevices/flipperzero-firmware into mntm-dev
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, ISO14443-4B, ISO15693-3, FeliCa, NTAG/Ultralight, Mifare Classic, Mifare DESFire, SLIX, ST25TB
|
||||
Device type: FeliCa
|
||||
# UID is common for all formats
|
||||
UID: 29 9F FA 53 AB 75 87 6E
|
||||
# FeliCa specific data
|
||||
Data format version: 1
|
||||
Manufacture id: 29 9F FA 53 AB 75 87 6E
|
||||
Manufacture parameter: 57 4E 10 2A 94 16 BC 8E
|
||||
Blocks total: 28
|
||||
Blocks read: 28
|
||||
Block 0: 00 00 DE AD BE AF 00 00 00 00 00 00 00 00 DE AD BE AF
|
||||
Block 1: 00 00 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
|
||||
Block 2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 3: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 4: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 5: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 6: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 7: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 9: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 11: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 12: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 13: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 14: 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
Block 15: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 16: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 17: 00 00 29 9F FA 53 AB 75 87 6E 57 4E 10 2A 94 16 BC 8E
|
||||
Block 18: 00 00 29 9F FA 53 AB 75 87 6E 00 F1 00 00 00 01 43 00
|
||||
Block 19: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 20: 00 00 88 B4 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 21: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 22: 00 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
|
||||
Block 23: 00 00 FF FF FF 00 FF 00 10 00 00 00 00 00 00 00 00 00
|
||||
Block 24: 00 00 24 FE FF 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 25: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 26: 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Block 27: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||
#include <nfc/protocols/felica/felica.h>
|
||||
#include <nfc/protocols/felica/felica_poller_sync.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic_poller.h>
|
||||
#include <nfc/protocols/iso15693_3/iso15693_3_poller.h>
|
||||
#include <nfc/protocols/slix/slix.h>
|
||||
@@ -646,6 +648,56 @@ MU_TEST(mf_classic_dict_test) {
|
||||
"Remove test dict failed");
|
||||
}
|
||||
|
||||
static FelicaError
|
||||
felica_do_request_response(FelicaData* felica_data, const FelicaCardKey* card_key) {
|
||||
NfcDeviceData* nfc_device = nfc_device_alloc();
|
||||
|
||||
FelicaError error = FelicaErrorNone;
|
||||
if(!nfc_device_load(nfc_device, EXT_PATH("unit_tests/nfc/Felica.nfc"))) {
|
||||
error = FelicaErrorNotPresent;
|
||||
} else {
|
||||
Nfc* poller = nfc_alloc();
|
||||
Nfc* listener = nfc_alloc();
|
||||
NfcListener* felica_listener = nfc_listener_alloc(
|
||||
listener, NfcProtocolFelica, nfc_device_get_data(nfc_device, NfcProtocolFelica));
|
||||
nfc_listener_start(felica_listener, NULL, NULL);
|
||||
|
||||
error = felica_poller_sync_read(poller, felica_data, card_key);
|
||||
|
||||
nfc_listener_stop(felica_listener);
|
||||
nfc_listener_free(felica_listener);
|
||||
|
||||
nfc_free(listener);
|
||||
nfc_free(poller);
|
||||
}
|
||||
|
||||
nfc_device_free(nfc_device);
|
||||
return error;
|
||||
}
|
||||
|
||||
MU_TEST(felica_read) {
|
||||
FelicaData* felica_data = felica_alloc();
|
||||
FelicaError error = felica_do_request_response(felica_data, NULL);
|
||||
mu_assert(error == FelicaErrorNone, "felica_poller() failed");
|
||||
mu_assert(felica_data->data.fs.spad[4].SF1 == 0x01, "block[4].SF1 != 0x01");
|
||||
mu_assert(felica_data->data.fs.spad[4].SF2 == 0xB1, "block[4].SF2 != 0xB1");
|
||||
|
||||
felica_free(felica_data);
|
||||
}
|
||||
|
||||
MU_TEST(felica_read_auth) {
|
||||
FelicaData* felica_data = felica_alloc();
|
||||
FelicaCardKey card_key;
|
||||
memset(card_key.data, 0xFF, FELICA_DATA_BLOCK_SIZE);
|
||||
|
||||
FelicaError error = felica_do_request_response(felica_data, &card_key);
|
||||
mu_assert(error == FelicaErrorNone, "felica_poller() failed");
|
||||
mu_assert(felica_data->data.fs.spad[4].SF1 == 0x00, "block[4].SF1 != 0x00");
|
||||
mu_assert(felica_data->data.fs.spad[4].SF2 == 0x00, "block[4].SF2 != 0x00");
|
||||
|
||||
felica_free(felica_data);
|
||||
}
|
||||
|
||||
MU_TEST(slix_file_with_capabilities_test) {
|
||||
NfcDevice* nfc_device_missed_cap = nfc_device_alloc();
|
||||
mu_assert(
|
||||
@@ -807,6 +859,8 @@ MU_TEST_SUITE(nfc) {
|
||||
MU_RUN_TEST(mf_classic_value_block);
|
||||
MU_RUN_TEST(mf_classic_send_frame_test);
|
||||
MU_RUN_TEST(mf_classic_dict_test);
|
||||
MU_RUN_TEST(felica_read);
|
||||
MU_RUN_TEST(felica_read_auth);
|
||||
|
||||
MU_RUN_TEST(slix_file_with_capabilities_test);
|
||||
MU_RUN_TEST(slix_set_password_default_cap_correct_pass);
|
||||
|
||||
@@ -20,6 +20,7 @@ void archive_scene_rename_on_enter(void* context) {
|
||||
|
||||
TextInput* text_input = archive->text_input;
|
||||
ArchiveFile_t* current = archive_get_current_file(archive->browser);
|
||||
const bool is_file = current->type != ArchiveFileTypeFolder;
|
||||
|
||||
FuriString* path_name = furi_string_alloc();
|
||||
FuriString* path_folder = furi_string_alloc();
|
||||
@@ -27,16 +28,15 @@ void archive_scene_rename_on_enter(void* context) {
|
||||
ArchiveTabEnum tab = archive_get_tab(archive->browser);
|
||||
bool hide_ext = tab != ArchiveTabBrowser && tab != ArchiveTabInternal;
|
||||
|
||||
if(current->type == ArchiveFileTypeFolder || !hide_ext) {
|
||||
furi_string_reset(archive->file_extension);
|
||||
path_extract_basename(furi_string_get_cstr(current->path), path_name);
|
||||
} else {
|
||||
if(is_file && !hide_ext) {
|
||||
path_extract_ext_str(current->path, archive->file_extension);
|
||||
path_extract_filename(current->path, path_name, true);
|
||||
} else {
|
||||
furi_string_reset(archive->file_extension);
|
||||
path_extract_basename(furi_string_get_cstr(current->path), path_name);
|
||||
}
|
||||
strlcpy(archive->text_store, furi_string_get_cstr(path_name), MAX_NAME_LEN);
|
||||
text_input_set_header_text(
|
||||
text_input, current->type == ArchiveFileTypeFolder ? "Rename directory:" : "Rename file:");
|
||||
text_input_set_header_text(text_input, is_file ? "Rename file:" : "Rename directory:");
|
||||
|
||||
// Get current folder (for file) or previous folder (for folder) for validator
|
||||
path_extract_dirname(furi_string_get_cstr(current->path), path_folder);
|
||||
@@ -44,7 +44,7 @@ void archive_scene_rename_on_enter(void* context) {
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
archive_scene_rename_text_input_callback,
|
||||
context,
|
||||
archive,
|
||||
archive->text_store,
|
||||
MAX_NAME_LEN,
|
||||
false);
|
||||
|
||||
@@ -26,12 +26,6 @@ static void nfc_scene_info_on_enter_felica(NfcApp* instance) {
|
||||
widget_add_text_scroll_element(
|
||||
instance->widget, 0, 0, 128, 48, furi_string_get_cstr(temp_str));
|
||||
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeRight,
|
||||
"More",
|
||||
nfc_protocol_support_common_widget_callback,
|
||||
instance);
|
||||
furi_string_free(temp_str);
|
||||
}
|
||||
|
||||
@@ -177,7 +171,7 @@ static bool nfc_scene_read_menu_on_event_felica(NfcApp* instance, SceneManagerEv
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_felica = {
|
||||
.features = NfcProtocolFeatureEmulateUid,
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ typedef enum {
|
||||
SubGhzRxKeyStateAddKey,
|
||||
SubGhzRxKeyStateExit,
|
||||
SubGhzRxKeyStateRAWLoad,
|
||||
SubGhzRxKeyStateRAWMore,
|
||||
SubGhzRxKeyStateRAWSave,
|
||||
SubGhzRxKeyStateTX,
|
||||
} SubGhzRxKeyState;
|
||||
|
||||
@@ -66,7 +66,13 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.event == SubGhzCustomEventSceneDeleteRAW) {
|
||||
furi_string_set(subghz->file_path_tmp, subghz->file_path);
|
||||
if(subghz_delete_file(subghz)) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
|
||||
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateRAWLoad) {
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess);
|
||||
} else {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaved);
|
||||
}
|
||||
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneStart);
|
||||
|
||||
@@ -80,6 +80,7 @@ void subghz_scene_read_raw_on_enter(void* context) {
|
||||
subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, "", threshold_rssi);
|
||||
break;
|
||||
case SubGhzRxKeyStateRAWLoad:
|
||||
case SubGhzRxKeyStateRAWMore:
|
||||
path_extract_filename(subghz->file_path, file_name, true);
|
||||
subghz_read_raw_set_status(
|
||||
subghz->subghz_read_raw,
|
||||
@@ -101,7 +102,8 @@ void subghz_scene_read_raw_on_enter(void* context) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) {
|
||||
if((subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateBack) &&
|
||||
(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateRAWLoad)) {
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateIDLE);
|
||||
|
||||
if(furi_string_empty(file_name)) {
|
||||
@@ -204,7 +206,9 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) {
|
||||
if(subghz_scene_read_raw_update_filename(subghz)) {
|
||||
scene_manager_set_scene_state(
|
||||
subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerSet);
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad);
|
||||
if(subghz_rx_key_state_get(subghz) != SubGhzRxKeyStateRAWLoad) {
|
||||
subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWMore);
|
||||
}
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneMoreRAW);
|
||||
consumed = true;
|
||||
} else {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <update_util/lfs_backup.h>
|
||||
#include <toolbox/tar/tar_archive.h>
|
||||
|
||||
#include <pb_decode.h>
|
||||
#include <storage.pb.h>
|
||||
@@ -50,7 +51,6 @@ static void rpc_system_storage_reset_state(
|
||||
if(rpc_storage->state == RpcStorageStateWriting) {
|
||||
storage_file_close(rpc_storage->file);
|
||||
storage_file_free(rpc_storage->file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
rpc_storage->state = RpcStorageStateIdle;
|
||||
@@ -118,10 +118,8 @@ static void rpc_system_storage_info_process(const PB_Main* request, void* contex
|
||||
PB_Main* response = malloc(sizeof(PB_Main));
|
||||
response->command_id = request->command_id;
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
FS_Error error = storage_common_fs_info(
|
||||
fs_api,
|
||||
rpc_storage->api,
|
||||
request->content.storage_info_request.path,
|
||||
&response->content.storage_info_response.total_space,
|
||||
&response->content.storage_info_response.free_space);
|
||||
@@ -135,7 +133,6 @@ static void rpc_system_storage_info_process(const PB_Main* request, void* contex
|
||||
|
||||
rpc_send_and_release(session, response);
|
||||
free(response);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_timestamp_process(const PB_Main* request, void* context) {
|
||||
@@ -154,11 +151,9 @@ static void rpc_system_storage_timestamp_process(const PB_Main* request, void* c
|
||||
PB_Main* response = malloc(sizeof(PB_Main));
|
||||
response->command_id = request->command_id;
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
const char* path = request->content.storage_timestamp_request.path;
|
||||
uint32_t timestamp = 0;
|
||||
FS_Error error = storage_common_timestamp(fs_api, path, ×tamp);
|
||||
FS_Error error = storage_common_timestamp(rpc_storage->api, path, ×tamp);
|
||||
|
||||
response->command_status = rpc_system_storage_get_error(error);
|
||||
response->which_content = PB_Main_empty_tag;
|
||||
@@ -170,7 +165,6 @@ static void rpc_system_storage_timestamp_process(const PB_Main* request, void* c
|
||||
|
||||
rpc_send_and_release(session, response);
|
||||
free(response);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_stat_process(const PB_Main* request, void* context) {
|
||||
@@ -189,11 +183,9 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex
|
||||
PB_Main* response = malloc(sizeof(PB_Main));
|
||||
response->command_id = request->command_id;
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
const char* path = request->content.storage_stat_request.path;
|
||||
FileInfo fileinfo;
|
||||
FS_Error error = storage_common_stat(fs_api, path, &fileinfo);
|
||||
FS_Error error = storage_common_stat(rpc_storage->api, path, &fileinfo);
|
||||
|
||||
response->command_status = rpc_system_storage_get_error(error);
|
||||
response->which_content = PB_Main_empty_tag;
|
||||
@@ -209,12 +201,12 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex
|
||||
|
||||
rpc_send_and_release(session, response);
|
||||
free(response);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_list_root(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(context);
|
||||
|
||||
RpcStorageSystem* rpc_storage = context;
|
||||
RpcSession* session = rpc_storage->session;
|
||||
furi_assert(session);
|
||||
@@ -279,8 +271,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
return;
|
||||
}
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* dir = storage_file_alloc(fs_api);
|
||||
File* dir = storage_file_alloc(rpc_storage->api);
|
||||
|
||||
PB_Main response = {
|
||||
.command_id = request->command_id,
|
||||
@@ -293,7 +284,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
bool include_md5 = list_request->include_md5;
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FuriString* md5_path = furi_string_alloc();
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
File* file = storage_file_alloc(rpc_storage->api);
|
||||
|
||||
bool finish = false;
|
||||
int i = 0;
|
||||
@@ -350,8 +341,6 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
storage_dir_close(dir);
|
||||
storage_file_free(dir);
|
||||
storage_file_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_read_process(const PB_Main* request, void* context) {
|
||||
@@ -370,8 +359,7 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
|
||||
/* use same message memory to send response */
|
||||
PB_Main* response = malloc(sizeof(PB_Main));
|
||||
const char* path = request->content.storage_read_request.path;
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
File* file = storage_file_alloc(rpc_storage->api);
|
||||
bool fs_operation_success = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
if(fs_operation_success) {
|
||||
@@ -420,8 +408,6 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
|
||||
free(response);
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_write_process(const PB_Main* request, void* context) {
|
||||
@@ -451,7 +437,6 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
||||
}
|
||||
|
||||
if(rpc_storage->state != RpcStorageStateWriting) {
|
||||
rpc_storage->api = furi_record_open(RECORD_STORAGE);
|
||||
rpc_storage->file = storage_file_alloc(rpc_storage->api);
|
||||
rpc_storage->current_command_id = request->command_id;
|
||||
rpc_storage->state = RpcStorageStateWriting;
|
||||
@@ -492,14 +477,15 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
||||
}
|
||||
}
|
||||
|
||||
static bool rpc_system_storage_is_dir_is_empty(Storage* fs_api, const char* path) {
|
||||
furi_assert(fs_api);
|
||||
static bool rpc_system_storage_is_dir_is_empty(Storage* storage, const char* path) {
|
||||
furi_assert(storage);
|
||||
furi_assert(path);
|
||||
|
||||
FileInfo fileinfo;
|
||||
bool is_dir_is_empty = true;
|
||||
FS_Error error = storage_common_stat(fs_api, path, &fileinfo);
|
||||
FS_Error error = storage_common_stat(storage, path, &fileinfo);
|
||||
if((error == FSE_OK) && file_info_is_dir(&fileinfo)) {
|
||||
File* dir = storage_file_alloc(fs_api);
|
||||
File* dir = storage_file_alloc(storage);
|
||||
if(storage_dir_open(dir, path)) {
|
||||
char* name = malloc(MAX_NAME_LENGTH);
|
||||
while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) {
|
||||
@@ -531,18 +517,17 @@ static void rpc_system_storage_delete_process(const PB_Main* request, void* cont
|
||||
PB_CommandStatus status = PB_CommandStatus_ERROR;
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
char* path = request->content.storage_delete_request.path;
|
||||
if(!path) {
|
||||
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||
} else {
|
||||
FS_Error error_remove = storage_common_remove(fs_api, path);
|
||||
FS_Error error_remove = storage_common_remove(rpc_storage->api, path);
|
||||
// FSE_DENIED is for empty directory, but not only for this
|
||||
// that's why we have to check it
|
||||
if((error_remove == FSE_DENIED) && !rpc_system_storage_is_dir_is_empty(fs_api, path)) {
|
||||
if((error_remove == FSE_DENIED) &&
|
||||
!rpc_system_storage_is_dir_is_empty(rpc_storage->api, path)) {
|
||||
if(request->content.storage_delete_request.recursive) {
|
||||
bool deleted = storage_simply_remove_recursive(fs_api, path);
|
||||
bool deleted = storage_simply_remove_recursive(rpc_storage->api, path);
|
||||
status = deleted ? PB_CommandStatus_OK : PB_CommandStatus_ERROR;
|
||||
} else {
|
||||
status = PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY;
|
||||
@@ -554,7 +539,6 @@ static void rpc_system_storage_delete_process(const PB_Main* request, void* cont
|
||||
}
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
rpc_send_and_release_empty(session, request->command_id, status);
|
||||
}
|
||||
|
||||
@@ -572,11 +556,10 @@ static void rpc_system_storage_mkdir_process(const PB_Main* request, void* conte
|
||||
PB_CommandStatus status;
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
char* path = request->content.storage_mkdir_request.path;
|
||||
if(path) {
|
||||
if(path_contains_only_ascii(path)) {
|
||||
FS_Error error = storage_common_mkdir(fs_api, path);
|
||||
FS_Error error = storage_common_mkdir(rpc_storage->api, path);
|
||||
status = rpc_system_storage_get_error(error);
|
||||
} else {
|
||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||
@@ -584,7 +567,6 @@ static void rpc_system_storage_mkdir_process(const PB_Main* request, void* conte
|
||||
} else {
|
||||
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
rpc_send_and_release_empty(session, request->command_id, status);
|
||||
}
|
||||
|
||||
@@ -608,8 +590,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
||||
return;
|
||||
}
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
File* file = storage_file_alloc(rpc_storage->api);
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FS_Error file_error;
|
||||
|
||||
@@ -633,8 +614,6 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
||||
|
||||
furi_string_free(md5);
|
||||
storage_file_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_rename_process(const PB_Main* request, void* context) {
|
||||
@@ -651,11 +630,9 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont
|
||||
PB_CommandStatus status;
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
if(path_contains_only_ascii(request->content.storage_rename_request.new_path)) {
|
||||
FS_Error error = storage_common_rename_safe(
|
||||
fs_api,
|
||||
rpc_storage->api,
|
||||
request->content.storage_rename_request.old_path,
|
||||
request->content.storage_rename_request.new_path);
|
||||
status = rpc_system_storage_get_error(error);
|
||||
@@ -663,7 +640,6 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont
|
||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||
}
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
rpc_send_and_release_empty(session, request->command_id, status);
|
||||
}
|
||||
|
||||
@@ -678,12 +654,10 @@ static void rpc_system_storage_backup_create_process(const PB_Main* request, voi
|
||||
RpcSession* session = rpc_storage->session;
|
||||
furi_assert(session);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
bool backup_ok =
|
||||
lfs_backup_create(fs_api, request->content.storage_backup_create_request.archive_path);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
bool backup_ok = lfs_backup_create(
|
||||
rpc_storage->api, request->content.storage_backup_create_request.archive_path);
|
||||
|
||||
rpc_send_and_release_empty(
|
||||
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||
@@ -700,17 +674,58 @@ static void rpc_system_storage_backup_restore_process(const PB_Main* request, vo
|
||||
RpcSession* session = rpc_storage->session;
|
||||
furi_assert(session);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
bool backup_ok =
|
||||
lfs_backup_unpack(fs_api, request->content.storage_backup_restore_request.archive_path);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
bool backup_ok = lfs_backup_unpack(
|
||||
rpc_storage->api, request->content.storage_backup_restore_request.archive_path);
|
||||
|
||||
rpc_send_and_release_empty(
|
||||
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||
}
|
||||
|
||||
static void rpc_system_storage_tar_extract_process(const PB_Main* request, void* context) {
|
||||
furi_assert(request);
|
||||
furi_assert(request->which_content == PB_Main_storage_tar_extract_request_tag);
|
||||
furi_assert(context);
|
||||
|
||||
FURI_LOG_D(TAG, "TarExtract");
|
||||
|
||||
RpcStorageSystem* rpc_storage = context;
|
||||
RpcSession* session = rpc_storage->session;
|
||||
furi_assert(session);
|
||||
|
||||
PB_CommandStatus status;
|
||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||
|
||||
TarArchive* archive = tar_archive_alloc(rpc_storage->api);
|
||||
|
||||
do {
|
||||
if(!path_contains_only_ascii(request->content.storage_tar_extract_request.out_path)) {
|
||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!tar_archive_open(
|
||||
archive,
|
||||
request->content.storage_tar_extract_request.tar_path,
|
||||
TAR_OPEN_MODE_READ)) {
|
||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!tar_archive_unpack_to(
|
||||
archive, request->content.storage_tar_extract_request.out_path, NULL)) {
|
||||
status = PB_CommandStatus_ERROR_STORAGE_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
status = PB_CommandStatus_OK;
|
||||
} while(0);
|
||||
|
||||
tar_archive_free(archive);
|
||||
rpc_send_and_release_empty(session, request->command_id, status);
|
||||
}
|
||||
|
||||
void* rpc_system_storage_alloc(RpcSession* session) {
|
||||
furi_assert(session);
|
||||
|
||||
@@ -761,6 +776,9 @@ void* rpc_system_storage_alloc(RpcSession* session) {
|
||||
rpc_handler.message_handler = rpc_system_storage_backup_restore_process;
|
||||
rpc_add_handler(session, PB_Main_storage_backup_restore_request_tag, &rpc_handler);
|
||||
|
||||
rpc_handler.message_handler = rpc_system_storage_tar_extract_process;
|
||||
rpc_add_handler(session, PB_Main_storage_tar_extract_request_tag, &rpc_handler);
|
||||
|
||||
return rpc_storage;
|
||||
}
|
||||
|
||||
@@ -771,5 +789,8 @@ void rpc_system_storage_free(void* context) {
|
||||
furi_assert(session);
|
||||
|
||||
rpc_system_storage_reset_state(rpc_storage, session, false);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
rpc_storage->api = NULL;
|
||||
free(rpc_storage);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user