Merge branch 'ofw-dev' into dev

This commit is contained in:
MX
2023-08-09 15:05:12 +03:00
19 changed files with 263 additions and 116 deletions

1
.gitmodules vendored
View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -0,0 +1 @@
Yo dawg, I heard you like md5...

2
fbt
View File

@@ -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 "$@"

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,34.3,,
Version,+,34.4,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -164,6 +164,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,,
Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,,
Header,+,lib/toolbox/api_lock.h,,
Header,+,lib/toolbox/args.h,,
Header,+,lib/toolbox/compress.h,,
Header,+,lib/toolbox/crc32_calc.h,,
Header,+,lib/toolbox/dir_walk.h,,
Header,+,lib/toolbox/float_tools.h,,
@@ -627,6 +628,13 @@ Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiI
Function,+,composite_api_resolver_alloc,CompositeApiResolver*,
Function,+,composite_api_resolver_free,void,CompositeApiResolver*
Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver*
Function,+,compress_alloc,Compress*,uint16_t
Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
Function,+,compress_free,void,Compress*
Function,+,compress_icon_alloc,CompressIcon*,
Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**"
Function,+,compress_icon_free,void,CompressIcon*
Function,-,copysign,double,"double, double"
Function,-,copysignf,float,"float, float"
Function,-,copysignl,long double,"long double, long double"
1 entry status name type params
2 Version + 34.3 34.4
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
164 Header + lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h
165 Header + lib/toolbox/api_lock.h
166 Header + lib/toolbox/args.h
167 Header + lib/toolbox/compress.h
168 Header + lib/toolbox/crc32_calc.h
169 Header + lib/toolbox/dir_walk.h
170 Header + lib/toolbox/float_tools.h
628 Function + composite_api_resolver_alloc CompositeApiResolver*
629 Function + composite_api_resolver_free void CompositeApiResolver*
630 Function + composite_api_resolver_get const ElfApiInterface* CompositeApiResolver*
631 Function + compress_alloc Compress* uint16_t
632 Function + compress_decode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
633 Function + compress_encode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
634 Function + compress_free void Compress*
635 Function + compress_icon_alloc CompressIcon*
636 Function + compress_icon_decode void CompressIcon*, const uint8_t*, uint8_t**
637 Function + compress_icon_free void CompressIcon*
638 Function - copysign double double, double
639 Function - copysignf float float, float
640 Function - copysignl long double long double, long double

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,34.3,,
Version,+,34.4,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
@@ -207,6 +207,7 @@ Header,+,lib/subghz/subghz_worker.h,,
Header,+,lib/subghz/transmitter.h,,
Header,+,lib/toolbox/api_lock.h,,
Header,+,lib/toolbox/args.h,,
Header,+,lib/toolbox/compress.h,,
Header,+,lib/toolbox/crc32_calc.h,,
Header,+,lib/toolbox/dir_walk.h,,
Header,+,lib/toolbox/float_tools.h,,
@@ -703,6 +704,13 @@ Function,+,composite_api_resolver_add,void,"CompositeApiResolver*, const ElfApiI
Function,+,composite_api_resolver_alloc,CompositeApiResolver*,
Function,+,composite_api_resolver_free,void,CompositeApiResolver*
Function,+,composite_api_resolver_get,const ElfApiInterface*,CompositeApiResolver*
Function,+,compress_alloc,Compress*,uint16_t
Function,+,compress_decode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
Function,+,compress_encode,_Bool,"Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*"
Function,+,compress_free,void,Compress*
Function,+,compress_icon_alloc,CompressIcon*,
Function,+,compress_icon_decode,void,"CompressIcon*, const uint8_t*, uint8_t**"
Function,+,compress_icon_free,void,CompressIcon*
Function,-,copysign,double,"double, double"
Function,-,copysignf,float,"float, float"
Function,-,copysignl,long double,"long double, long double"
1 entry status name type params
2 Version + 34.3 34.4
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/cli/cli.h
207 Header + lib/subghz/transmitter.h
208 Header + lib/toolbox/api_lock.h
209 Header + lib/toolbox/args.h
210 Header + lib/toolbox/compress.h
211 Header + lib/toolbox/crc32_calc.h
212 Header + lib/toolbox/dir_walk.h
213 Header + lib/toolbox/float_tools.h
704 Function + composite_api_resolver_alloc CompositeApiResolver*
705 Function + composite_api_resolver_free void CompositeApiResolver*
706 Function + composite_api_resolver_get const ElfApiInterface* CompositeApiResolver*
707 Function + compress_alloc Compress* uint16_t
708 Function + compress_decode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
709 Function + compress_encode _Bool Compress*, uint8_t*, size_t, uint8_t*, size_t, size_t*
710 Function + compress_free void Compress*
711 Function + compress_icon_alloc CompressIcon*
712 Function + compress_icon_decode void CompressIcon*, const uint8_t*, uint8_t**
713 Function + compress_icon_free void CompressIcon*
714 Function - copysign double double, double
715 Function - copysignf float float, float
716 Function - copysignl long double long double, long double

View File

@@ -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);

View File

@@ -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;

View File

@@ -325,7 +325,7 @@ void protocol_fdx_b_render_brief_data(ProtocolFDXB* protocol, FuriString* result
float temperature;
if(protocol_fdx_b_get_temp(protocol->data, &temperature)) {
if(furi_hal_rtc_get_locale_units() == FuriHalRtcLocaleUnitsMetric) {
float temperature_c = (temperature - 32) / 1.8;
float temperature_c = (temperature - 32.0f) / 1.8f;
furi_string_cat_printf(result, "T: %.2fC", (double)temperature_c);
} else {
furi_string_cat_printf(result, "T: %.2fF", (double)temperature);

View File

@@ -244,7 +244,9 @@ bool subghz_file_encoder_worker_start(
furi_stream_buffer_reset(instance->stream);
furi_string_set(instance->file_path, file_path);
instance->device = subghz_devices_get_by_name(radio_device_name);
if(radio_device_name) {
instance->device = subghz_devices_get_by_name(radio_device_name);
}
instance->worker_running = true;
furi_thread_start(instance->thread);

View File

@@ -10,6 +10,7 @@ env.Append(
SDK_HEADERS=[
File("api_lock.h"),
File("value_index.h"),
File("compress.h"),
File("manchester_decoder.h"),
File("manchester_encoder.h"),
File("path.h"),

44
lib/toolbox/md5_calc.c Normal file
View 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
View 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

View File

@@ -59,7 +59,9 @@ def extract_abs_dir_path(node):
if abs_dir_node is None:
raise StopError(f"Can't find absolute path for {node.name}")
return abs_dir_node.abspath
# Don't return abspath attribute (type is str), it will break in
# OverrideEnvironment.subst_list() by splitting path on spaces
return abs_dir_node
def path_as_posix(path):

View File

@@ -137,14 +137,14 @@ def generate(env):
BUILDERS={
"IconBuilder": Builder(
action=Action(
'${PYTHON3} "${ASSETS_COMPILER}" icons "${ABSPATHGETTERFUNC(SOURCE)}" "${TARGET.dir}" --filename ${ICON_FILE_NAME}',
'${PYTHON3} ${ASSETS_COMPILER} icons ${ABSPATHGETTERFUNC(SOURCE)} ${TARGET.dir} --filename "${ICON_FILE_NAME}"',
"${ICONSCOMSTR}",
),
emitter=icons_emitter,
),
"ProtoBuilder": Builder(
action=Action(
'${PYTHON3} "${NANOPB_COMPILER}" -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}',
"${PYTHON3} ${NANOPB_COMPILER} -q -I${SOURCE.dir.posix} -D${TARGET.dir.posix} ${SOURCES.posix}",
"${PROTOCOMSTR}",
),
emitter=proto_emitter,
@@ -153,14 +153,14 @@ def generate(env):
),
"DolphinSymBuilder": Builder(
action=Action(
'${PYTHON3} "${ASSETS_COMPILER}" dolphin -s dolphin_${DOLPHIN_RES_TYPE} "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
"${PYTHON3} ${ASSETS_COMPILER} dolphin -s dolphin_${DOLPHIN_RES_TYPE} ${SOURCE} ${_DOLPHIN_OUT_DIR}",
"${DOLPHINCOMSTR}",
),
emitter=dolphin_emitter,
),
"DolphinExtBuilder": Builder(
action=Action(
'${PYTHON3} "${ASSETS_COMPILER}" dolphin "${SOURCE}" "${_DOLPHIN_OUT_DIR}"',
"${PYTHON3} ${ASSETS_COMPILER} dolphin ${SOURCE} ${_DOLPHIN_OUT_DIR}",
"${DOLPHINCOMSTR}",
),
emitter=dolphin_emitter,