mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-22 12:51:39 +03:00
[FL-3461] RPC: md5 in storage list (#2929)
* Protobuf: update * Toolbox: md5 for file. Unit-Tests: test md5_calc. * Storage RPC, CLI, unit tests: use new md5_calc * Protobuf: update * RPC, StorageList: append md5 info to file * fbt: attempt to fix shallow submodule checkouts * pvs: make happy * Protobuf: update to latest release Co-authored-by: hedger <hedger@nanode.su> Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
e9f1af44f2
commit
00cdc3d1cb
1
.gitmodules
vendored
1
.gitmodules
vendored
@ -10,6 +10,7 @@
|
||||
[submodule "assets/protobuf"]
|
||||
path = assets/protobuf
|
||||
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
||||
shallow = false
|
||||
[submodule "lib/libusb_stm32"]
|
||||
path = lib/libusb_stm32
|
||||
url = https://github.com/flipperdevices/libusb_stm32.git
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <pb.h>
|
||||
#include <pb_encode.h>
|
||||
#include <m-list.h>
|
||||
#include <lib/toolbox/md5.h>
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <cli/cli.h>
|
||||
#include <loader/loader.h>
|
||||
@ -287,7 +287,8 @@ static void test_rpc_create_simple_message(
|
||||
PB_Main* message,
|
||||
uint16_t tag,
|
||||
const char* str,
|
||||
uint32_t command_id) {
|
||||
uint32_t command_id,
|
||||
bool flag) {
|
||||
furi_check(message);
|
||||
|
||||
char* str_copy = NULL;
|
||||
@ -308,6 +309,7 @@ static void test_rpc_create_simple_message(
|
||||
break;
|
||||
case PB_Main_storage_list_request_tag:
|
||||
message->content.storage_list_request.path = str_copy;
|
||||
message->content.storage_list_request.include_md5 = flag;
|
||||
break;
|
||||
case PB_Main_storage_mkdir_request_tag:
|
||||
message->content.storage_mkdir_request.path = str_copy;
|
||||
@ -419,6 +421,7 @@ static void
|
||||
}
|
||||
mu_check(result_msg_file->size == expected_msg_file->size);
|
||||
mu_check(result_msg_file->type == expected_msg_file->type);
|
||||
mu_assert_string_eq(expected_msg_file->md5sum, result_msg_file->md5sum);
|
||||
|
||||
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
|
||||
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
|
||||
@ -430,10 +433,10 @@ static void
|
||||
}
|
||||
|
||||
static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
||||
mu_check(result->command_id == expected->command_id);
|
||||
mu_check(result->command_status == expected->command_status);
|
||||
mu_check(result->has_next == expected->has_next);
|
||||
mu_check(result->which_content == expected->which_content);
|
||||
mu_assert_int_eq(expected->command_id, result->command_id);
|
||||
mu_assert_int_eq(expected->command_status, result->command_status);
|
||||
mu_assert_int_eq(expected->has_next, result->has_next);
|
||||
mu_assert_int_eq(expected->which_content, result->which_content);
|
||||
if(result->command_status != PB_CommandStatus_OK) {
|
||||
mu_check(result->which_content == PB_Main_empty_tag);
|
||||
}
|
||||
@ -573,10 +576,15 @@ static void
|
||||
static void test_rpc_storage_list_create_expected_list(
|
||||
MsgList_t msg_list,
|
||||
const char* path,
|
||||
uint32_t command_id) {
|
||||
uint32_t command_id,
|
||||
bool append_md5) {
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* dir = storage_file_alloc(fs_api);
|
||||
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FuriString* md5_path = furi_string_alloc();
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
|
||||
PB_Main response = {
|
||||
.command_id = command_id,
|
||||
.has_next = false,
|
||||
@ -614,6 +622,17 @@ static void test_rpc_storage_list_create_expected_list(
|
||||
list->file[i].data = NULL;
|
||||
/* memory free inside rpc_encode_and_send() -> pb_release() */
|
||||
list->file[i].name = name;
|
||||
|
||||
if(append_md5 && !file_info_is_dir(&fileinfo)) {
|
||||
furi_string_printf(md5_path, "%s/%s", path, name);
|
||||
|
||||
if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) {
|
||||
char* md5sum = list->file[i].md5sum;
|
||||
size_t md5sum_size = sizeof(list->file[i].md5sum);
|
||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
@ -626,6 +645,10 @@ static void test_rpc_storage_list_create_expected_list(
|
||||
response.has_next = false;
|
||||
MsgList_push_back(msg_list, response);
|
||||
|
||||
furi_string_free(md5);
|
||||
furi_string_free(md5_path);
|
||||
storage_file_free(file);
|
||||
|
||||
storage_dir_close(dir);
|
||||
storage_file_free(dir);
|
||||
|
||||
@ -675,16 +698,17 @@ static void test_rpc_free_msg_list(MsgList_t msg_list) {
|
||||
MsgList_clear(msg_list);
|
||||
}
|
||||
|
||||
static void test_rpc_storage_list_run(const char* path, uint32_t command_id) {
|
||||
static void test_rpc_storage_list_run(const char* path, uint32_t command_id, bool md5) {
|
||||
PB_Main request;
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_list_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_list_request_tag, path, command_id, md5);
|
||||
if(!strcmp(path, "/")) {
|
||||
test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id);
|
||||
} else {
|
||||
test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id);
|
||||
test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id, md5);
|
||||
}
|
||||
test_rpc_encode_and_feed_one(&request, 0);
|
||||
test_rpc_decode_and_compare(expected_msg_list, 0);
|
||||
@ -694,15 +718,25 @@ static void test_rpc_storage_list_run(const char* path, uint32_t command_id) {
|
||||
}
|
||||
|
||||
MU_TEST(test_storage_list) {
|
||||
test_rpc_storage_list_run("/", ++command_id);
|
||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id);
|
||||
test_rpc_storage_list_run("/", ++command_id, false);
|
||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false);
|
||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false);
|
||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false);
|
||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false);
|
||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false);
|
||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false);
|
||||
test_rpc_storage_list_run("error_path", ++command_id, false);
|
||||
}
|
||||
|
||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id);
|
||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id);
|
||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id);
|
||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id);
|
||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id);
|
||||
test_rpc_storage_list_run("error_path", ++command_id);
|
||||
MU_TEST(test_storage_list_md5) {
|
||||
test_rpc_storage_list_run("/", ++command_id, true);
|
||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true);
|
||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true);
|
||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true);
|
||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true);
|
||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true);
|
||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true);
|
||||
test_rpc_storage_list_run("error_path", ++command_id, true);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -770,7 +804,8 @@ static void test_storage_read_run(const char* path, uint32_t command_id) {
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_add_read_to_list_by_reading_real_file(expected_msg_list, path, command_id);
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_read_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_read_request_tag, path, command_id, false);
|
||||
test_rpc_encode_and_feed_one(&request, 0);
|
||||
test_rpc_decode_and_compare(expected_msg_list, 0);
|
||||
|
||||
@ -824,7 +859,8 @@ static void test_rpc_storage_info_run(const char* path, uint32_t command_id) {
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_info_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_info_request_tag, path, command_id, false);
|
||||
|
||||
PB_Main* response = MsgList_push_new(expected_msg_list);
|
||||
response->command_id = command_id;
|
||||
@ -856,7 +892,8 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) {
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_stat_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_stat_request_tag, path, command_id, false);
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
FileInfo fileinfo;
|
||||
@ -968,7 +1005,11 @@ static void test_storage_write_read_run(
|
||||
test_rpc_add_empty_to_list(expected_msg_list, PB_CommandStatus_OK, *command_id);
|
||||
|
||||
test_rpc_create_simple_message(
|
||||
MsgList_push_raw(input_msg_list), PB_Main_storage_read_request_tag, path, ++*command_id);
|
||||
MsgList_push_raw(input_msg_list),
|
||||
PB_Main_storage_read_request_tag,
|
||||
path,
|
||||
++*command_id,
|
||||
false);
|
||||
test_rpc_add_read_or_write_to_list(
|
||||
expected_msg_list,
|
||||
READ_RESPONSE,
|
||||
@ -1041,7 +1082,8 @@ MU_TEST(test_storage_interrupt_continuous_same_system) {
|
||||
MsgList_push_new(input_msg_list),
|
||||
PB_Main_storage_mkdir_request_tag,
|
||||
TEST_DIR "dir1",
|
||||
command_id + 1);
|
||||
command_id + 1,
|
||||
false);
|
||||
test_rpc_add_read_or_write_to_list(
|
||||
input_msg_list,
|
||||
WRITE_REQUEST,
|
||||
@ -1121,7 +1163,8 @@ static void test_storage_delete_run(
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_delete_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_delete_request_tag, path, command_id, false);
|
||||
request.content.storage_delete_request.recursive = recursive;
|
||||
test_rpc_add_empty_to_list(expected_msg_list, status, command_id);
|
||||
|
||||
@ -1202,7 +1245,8 @@ static void test_storage_mkdir_run(const char* path, size_t command_id, PB_Comma
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_mkdir_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_mkdir_request_tag, path, command_id, false);
|
||||
test_rpc_add_empty_to_list(expected_msg_list, status, command_id);
|
||||
|
||||
test_rpc_encode_and_feed_one(&request, 0);
|
||||
@ -1229,33 +1273,15 @@ MU_TEST(test_storage_mkdir) {
|
||||
static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) {
|
||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(api);
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
|
||||
if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
const uint16_t once_read_size = 512;
|
||||
const uint8_t hash_size = MD5SUM_SIZE;
|
||||
uint8_t* data = malloc(once_read_size);
|
||||
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||
|
||||
md5_starts(md5_ctx);
|
||||
while(true) {
|
||||
uint16_t read_size = storage_file_read(file, data, once_read_size);
|
||||
if(read_size == 0) break;
|
||||
md5_update(md5_ctx, data, read_size);
|
||||
}
|
||||
md5_finish(md5_ctx, hash);
|
||||
free(md5_ctx);
|
||||
|
||||
for(uint8_t i = 0; i < hash_size; i++) {
|
||||
md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]);
|
||||
}
|
||||
|
||||
free(hash);
|
||||
free(data);
|
||||
if(md5_string_calc_file(file, path, md5, NULL)) {
|
||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||
} else {
|
||||
furi_check(0);
|
||||
}
|
||||
|
||||
furi_string_free(md5);
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
@ -1271,11 +1297,12 @@ static void test_storage_md5sum_run(
|
||||
MsgList_t expected_msg_list;
|
||||
MsgList_init(expected_msg_list);
|
||||
|
||||
test_rpc_create_simple_message(&request, PB_Main_storage_md5sum_request_tag, path, command_id);
|
||||
test_rpc_create_simple_message(
|
||||
&request, PB_Main_storage_md5sum_request_tag, path, command_id, false);
|
||||
if(status == PB_CommandStatus_OK) {
|
||||
PB_Main* response = MsgList_push_new(expected_msg_list);
|
||||
test_rpc_create_simple_message(
|
||||
response, PB_Main_storage_md5sum_response_tag, md5sum, command_id);
|
||||
response, PB_Main_storage_md5sum_response_tag, md5sum, command_id, false);
|
||||
response->command_status = status;
|
||||
} else {
|
||||
test_rpc_add_empty_to_list(expected_msg_list, status, command_id);
|
||||
@ -1433,6 +1460,7 @@ MU_TEST_SUITE(test_rpc_storage) {
|
||||
MU_RUN_TEST(test_storage_info);
|
||||
MU_RUN_TEST(test_storage_stat);
|
||||
MU_RUN_TEST(test_storage_list);
|
||||
MU_RUN_TEST(test_storage_list_md5);
|
||||
MU_RUN_TEST(test_storage_read);
|
||||
MU_RUN_TEST(test_storage_write_read);
|
||||
MU_RUN_TEST(test_storage_write);
|
||||
@ -1731,7 +1759,8 @@ MU_TEST(test_rpc_multisession_storage) {
|
||||
MsgList_push_raw(input_0),
|
||||
PB_Main_storage_read_request_tag,
|
||||
TEST_DIR "file0.txt",
|
||||
++command_id);
|
||||
++command_id,
|
||||
false);
|
||||
test_rpc_add_read_or_write_to_list(
|
||||
expected_0, READ_RESPONSE, TEST_DIR "file0.txt", pattern, sizeof(pattern), 1, command_id);
|
||||
|
||||
@ -1739,7 +1768,8 @@ MU_TEST(test_rpc_multisession_storage) {
|
||||
MsgList_push_raw(input_1),
|
||||
PB_Main_storage_read_request_tag,
|
||||
TEST_DIR "file1.txt",
|
||||
++command_id);
|
||||
++command_id,
|
||||
false);
|
||||
test_rpc_add_read_or_write_to_list(
|
||||
expected_1, READ_RESPONSE, TEST_DIR "file1.txt", pattern, sizeof(pattern), 1, command_id);
|
||||
|
||||
|
@ -582,6 +582,49 @@ MU_TEST(test_storage_common_migrate) {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
#define MD5_HASH_SIZE (16)
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
|
||||
MU_TEST(test_md5_calc) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
const char* path = UNIT_TESTS_PATH("storage/md5.txt");
|
||||
const char* md5_cstr = "2a456fa43e75088fdde41c93159d62a2";
|
||||
const uint8_t md5[MD5_HASH_SIZE] = {
|
||||
0x2a,
|
||||
0x45,
|
||||
0x6f,
|
||||
0xa4,
|
||||
0x3e,
|
||||
0x75,
|
||||
0x08,
|
||||
0x8f,
|
||||
0xdd,
|
||||
0xe4,
|
||||
0x1c,
|
||||
0x93,
|
||||
0x15,
|
||||
0x9d,
|
||||
0x62,
|
||||
0xa2,
|
||||
};
|
||||
|
||||
uint8_t md5_output[MD5_HASH_SIZE];
|
||||
FuriString* md5_output_str = furi_string_alloc();
|
||||
memset(md5_output, 0, MD5_HASH_SIZE);
|
||||
|
||||
mu_check(md5_calc_file(file, path, md5_output, NULL));
|
||||
mu_check(md5_string_calc_file(file, path, md5_output_str, NULL));
|
||||
|
||||
mu_assert_mem_eq(md5, md5_output, MD5_HASH_SIZE);
|
||||
mu_assert_string_eq(md5_cstr, furi_string_get_cstr(md5_output_str));
|
||||
|
||||
storage_file_free(file);
|
||||
furi_string_free(md5_output_str);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_data_path) {
|
||||
MU_RUN_TEST(test_storage_data_path);
|
||||
MU_RUN_TEST(test_storage_data_path_apps);
|
||||
@ -591,11 +634,16 @@ MU_TEST_SUITE(test_storage_common) {
|
||||
MU_RUN_TEST(test_storage_common_migrate);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_md5_calc_suite) {
|
||||
MU_RUN_TEST(test_md5_calc);
|
||||
}
|
||||
|
||||
int run_minunit_test_storage() {
|
||||
MU_RUN_SUITE(storage_file);
|
||||
MU_RUN_SUITE(storage_dir);
|
||||
MU_RUN_SUITE(storage_rename);
|
||||
MU_RUN_SUITE(test_data_path);
|
||||
MU_RUN_SUITE(test_storage_common);
|
||||
MU_RUN_SUITE(test_md5_calc_suite);
|
||||
return MU_EXIT_CODE;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "storage/filesystem_api_defines.h"
|
||||
#include "storage/storage.h"
|
||||
#include <stdint.h>
|
||||
#include <lib/toolbox/md5.h>
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <update_util/lfs_backup.h>
|
||||
|
||||
@ -271,6 +271,11 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
};
|
||||
PB_Storage_ListResponse* list = &response.content.storage_list_response;
|
||||
|
||||
bool include_md5 = request->content.storage_list_request.include_md5;
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FuriString* md5_path = furi_string_alloc();
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
|
||||
bool finish = false;
|
||||
int i = 0;
|
||||
|
||||
@ -296,6 +301,21 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
list->file[i].size = fileinfo.size;
|
||||
list->file[i].data = NULL;
|
||||
list->file[i].name = name;
|
||||
|
||||
if(include_md5 && !file_info_is_dir(&fileinfo)) {
|
||||
furi_string_printf( //-V576
|
||||
md5_path,
|
||||
"%s/%s",
|
||||
request->content.storage_list_request.path,
|
||||
name);
|
||||
|
||||
if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) {
|
||||
char* md5sum = list->file[i].md5sum;
|
||||
size_t md5sum_size = sizeof(list->file[i].md5sum);
|
||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
} else {
|
||||
free(name);
|
||||
@ -310,8 +330,11 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
||||
response.has_next = false;
|
||||
rpc_send_and_release(session, &response);
|
||||
|
||||
furi_string_free(md5);
|
||||
furi_string_free(md5_path);
|
||||
storage_dir_close(dir);
|
||||
storage_file_free(dir);
|
||||
storage_file_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
@ -569,23 +592,10 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
||||
|
||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(fs_api);
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FS_Error file_error;
|
||||
|
||||
if(storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
const uint16_t size_to_read = 512;
|
||||
const uint8_t hash_size = 16;
|
||||
uint8_t* data = malloc(size_to_read);
|
||||
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||
|
||||
md5_starts(md5_ctx);
|
||||
while(true) {
|
||||
uint16_t read_size = storage_file_read(file, data, size_to_read);
|
||||
if(read_size == 0) break;
|
||||
md5_update(md5_ctx, data, read_size);
|
||||
}
|
||||
md5_finish(md5_ctx, hash);
|
||||
free(md5_ctx);
|
||||
|
||||
if(md5_string_calc_file(file, filename, md5, &file_error)) {
|
||||
PB_Main response = {
|
||||
.command_id = request->command_id,
|
||||
.command_status = PB_CommandStatus_OK,
|
||||
@ -595,21 +605,15 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
||||
|
||||
char* md5sum = response.content.storage_md5sum_response.md5sum;
|
||||
size_t md5sum_size = sizeof(response.content.storage_md5sum_response.md5sum);
|
||||
(void)md5sum_size;
|
||||
furi_assert(hash_size <= ((md5sum_size - 1) / 2)); //-V547
|
||||
for(uint8_t i = 0; i < hash_size; i++) {
|
||||
md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]);
|
||||
}
|
||||
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||
|
||||
free(hash);
|
||||
free(data);
|
||||
storage_file_close(file);
|
||||
rpc_send_and_release(session, &response);
|
||||
} else {
|
||||
rpc_send_and_release_empty(
|
||||
session, request->command_id, rpc_system_storage_get_file_error(file));
|
||||
session, request->command_id, rpc_system_storage_get_error(file_error));
|
||||
}
|
||||
|
||||
furi_string_free(md5);
|
||||
storage_file_free(file);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <cli/cli.h>
|
||||
#include <lib/toolbox/args.h>
|
||||
#include <lib/toolbox/md5.h>
|
||||
#include <lib/toolbox/md5_calc.h>
|
||||
#include <lib/toolbox/dir_walk.h>
|
||||
#include <storage/storage.h>
|
||||
#include <storage/storage_sd_api.h>
|
||||
@ -482,34 +482,16 @@ static void storage_cli_md5(Cli* cli, FuriString* path) {
|
||||
UNUSED(cli);
|
||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(api);
|
||||
FuriString* md5 = furi_string_alloc();
|
||||
FS_Error file_error;
|
||||
|
||||
if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||
const uint16_t buffer_size = 512;
|
||||
const uint8_t hash_size = 16;
|
||||
uint8_t* data = malloc(buffer_size);
|
||||
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||
|
||||
md5_starts(md5_ctx);
|
||||
while(true) {
|
||||
uint16_t read_size = storage_file_read(file, data, buffer_size);
|
||||
if(read_size == 0) break;
|
||||
md5_update(md5_ctx, data, read_size);
|
||||
}
|
||||
md5_finish(md5_ctx, hash);
|
||||
free(md5_ctx);
|
||||
|
||||
for(uint8_t i = 0; i < hash_size; i++) {
|
||||
printf("%02x", hash[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
|
||||
free(hash);
|
||||
free(data);
|
||||
if(md5_string_calc_file(file, furi_string_get_cstr(path), md5, &file_error)) {
|
||||
printf("%s\r\n", furi_string_get_cstr(md5));
|
||||
} else {
|
||||
storage_cli_print_error(storage_file_get_error(file));
|
||||
storage_cli_print_error(file_error);
|
||||
}
|
||||
|
||||
furi_string_free(md5);
|
||||
storage_file_close(file);
|
||||
storage_file_free(file);
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 08a907d95733600becc41c0602ef5ee4c4baf782
|
||||
Subproject commit 7e011a95863716e72e7c6b5d552bca241d688304
|
1
assets/unit_tests/storage/md5.txt
Normal file
1
assets/unit_tests/storage/md5.txt
Normal file
@ -0,0 +1 @@
|
||||
Yo dawg, I heard you like md5...
|
2
fbt
2
fbt
@ -29,7 +29,7 @@ if [ -z "$FBT_NO_SYNC" ]; then
|
||||
echo "\".git\" directory not found, please clone repo via \"git clone\"";
|
||||
exit 1;
|
||||
fi
|
||||
git submodule update --init --depth 1 --jobs "$N_GIT_THREADS";
|
||||
git submodule update --init --jobs "$N_GIT_THREADS";
|
||||
fi
|
||||
|
||||
$SCONS_EP $SCONS_DEFAULT_FLAGS "$@"
|
||||
|
@ -92,10 +92,10 @@ static void furi_thread_body(void* context) {
|
||||
if(thread->heap_trace_enabled == true) {
|
||||
furi_delay_ms(33);
|
||||
thread->heap_size = memmgr_heap_get_thread_memory((FuriThreadId)task_handle);
|
||||
furi_log_print_format( //-V576
|
||||
furi_log_print_format(
|
||||
thread->heap_size ? FuriLogLevelError : FuriLogLevelInfo,
|
||||
TAG,
|
||||
"%s allocation balance: %u",
|
||||
"%s allocation balance: %zu",
|
||||
thread->name ? thread->name : "Thread",
|
||||
thread->heap_size);
|
||||
memmgr_heap_disable_thread_trace((FuriThreadId)task_handle);
|
||||
|
@ -892,7 +892,7 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) {
|
||||
ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it);
|
||||
total_size += itref->value.size;
|
||||
}
|
||||
FURI_LOG_I(TAG, "Total size of loaded sections: %u", total_size); //-V576
|
||||
FURI_LOG_I(TAG, "Total size of loaded sections: %zu", total_size);
|
||||
}
|
||||
|
||||
return status;
|
||||
|
44
lib/toolbox/md5_calc.c
Normal file
44
lib/toolbox/md5_calc.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "md5.h"
|
||||
#include "md5_calc.h"
|
||||
|
||||
bool md5_calc_file(File* file, const char* path, unsigned char output[16], FS_Error* file_error) {
|
||||
bool result = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
|
||||
if(result) {
|
||||
const uint16_t size_to_read = 512;
|
||||
uint8_t* data = malloc(size_to_read);
|
||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
||||
|
||||
md5_starts(md5_ctx);
|
||||
while(true) {
|
||||
uint16_t read_size = storage_file_read(file, data, size_to_read);
|
||||
if(read_size == 0) break;
|
||||
md5_update(md5_ctx, data, read_size);
|
||||
}
|
||||
md5_finish(md5_ctx, output);
|
||||
free(md5_ctx);
|
||||
free(data);
|
||||
}
|
||||
|
||||
if(file_error != NULL) {
|
||||
*file_error = storage_file_get_error(file);
|
||||
}
|
||||
|
||||
storage_file_close(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool md5_string_calc_file(File* file, const char* path, FuriString* output, FS_Error* file_error) {
|
||||
const size_t hash_size = 16;
|
||||
unsigned char hash[hash_size];
|
||||
bool result = md5_calc_file(file, path, hash, file_error);
|
||||
|
||||
if(result) {
|
||||
furi_string_set(output, "");
|
||||
for(size_t i = 0; i < hash_size; i++) {
|
||||
furi_string_cat_printf(output, "%02x", hash[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
16
lib/toolbox/md5_calc.h
Normal file
16
lib/toolbox/md5_calc.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool md5_calc_file(File* file, const char* path, unsigned char output[16], FS_Error* file_error);
|
||||
|
||||
bool md5_string_calc_file(File* file, const char* path, FuriString* output, FS_Error* file_error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user