[FL-3664] 64k does not enough (#3216)
* Unit tests: add "exists" to furi_record tests * Unit tests: mu_warn, storage 64k test * Storage: read/write over 64k * Unit tests: moar tests for storage r/w for >64k cases * Apps, libs: replace uint16_t with size_t on storage r/w operations * Unit tests: better data pattern, subghz: warning if transmission is prohibited Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									98d5718ec9
								
							
						
					
					
						commit
						4b3e8aba29
					
				| @ -3,18 +3,29 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include "../minunit.h" | #include "../minunit.h" | ||||||
| 
 | 
 | ||||||
| void test_furi_create_open() { | #define TEST_RECORD_NAME "test/holding" | ||||||
|     // 1. Create record
 |  | ||||||
|     uint8_t test_data = 0; |  | ||||||
|     furi_record_create("test/holding", (void*)&test_data); |  | ||||||
| 
 | 
 | ||||||
|     // 2. Open it
 | void test_furi_create_open() { | ||||||
|     void* record = furi_record_open("test/holding"); |     // Test that record does not exist
 | ||||||
|  |     mu_check(furi_record_exists(TEST_RECORD_NAME) == false); | ||||||
|  | 
 | ||||||
|  |     // Create record
 | ||||||
|  |     uint8_t test_data = 0; | ||||||
|  |     furi_record_create(TEST_RECORD_NAME, (void*)&test_data); | ||||||
|  | 
 | ||||||
|  |     // Test that record exists
 | ||||||
|  |     mu_check(furi_record_exists(TEST_RECORD_NAME) == true); | ||||||
|  | 
 | ||||||
|  |     // Open it
 | ||||||
|  |     void* record = furi_record_open(TEST_RECORD_NAME); | ||||||
|     mu_assert_pointers_eq(record, &test_data); |     mu_assert_pointers_eq(record, &test_data); | ||||||
| 
 | 
 | ||||||
|     // 3. Close it
 |     // Close it
 | ||||||
|     furi_record_close("test/holding"); |     furi_record_close(TEST_RECORD_NAME); | ||||||
| 
 | 
 | ||||||
|     // 4. Clean up
 |     // Clean up
 | ||||||
|     furi_record_destroy("test/holding"); |     furi_record_destroy(TEST_RECORD_NAME); | ||||||
|  | 
 | ||||||
|  |     // Test that record does not exist
 | ||||||
|  |     mu_check(furi_record_exists(TEST_RECORD_NAME) == false); | ||||||
| } | } | ||||||
|  | |||||||
| @ -81,6 +81,7 @@ __attribute__((unused)) static void (*minunit_teardown)(void) = NULL; | |||||||
| 
 | 
 | ||||||
| void minunit_print_progress(void); | void minunit_print_progress(void); | ||||||
| void minunit_print_fail(const char* error); | void minunit_print_fail(const char* error); | ||||||
|  | void minunit_printf_warning(const char* format, ...); | ||||||
| 
 | 
 | ||||||
| /*  Definitions */ | /*  Definitions */ | ||||||
| #define MU_TEST(method_name) static void method_name(void) | #define MU_TEST(method_name) static void method_name(void) | ||||||
| @ -150,6 +151,10 @@ void minunit_print_fail(const char* error); | |||||||
|                        minunit_end_proc_timer - minunit_proc_timer);) |                        minunit_end_proc_timer - minunit_proc_timer);) | ||||||
| #define MU_EXIT_CODE minunit_fail | #define MU_EXIT_CODE minunit_fail | ||||||
| 
 | 
 | ||||||
|  | /* Warnings */ | ||||||
|  | #define mu_warn(message) \ | ||||||
|  |     MU__SAFE_BLOCK(minunit_printf_warning("%s:%d: %s", __FILE__, __LINE__, message);) | ||||||
|  | 
 | ||||||
| /*  Assertions */ | /*  Assertions */ | ||||||
| #define mu_check(test)                       \ | #define mu_check(test)                       \ | ||||||
|     MU__SAFE_BLOCK(                          \ |     MU__SAFE_BLOCK(                          \ | ||||||
|  | |||||||
| @ -139,7 +139,7 @@ static bool write_file_13DA(Storage* storage, const char* path) { | |||||||
|     File* file = storage_file_alloc(storage); |     File* file = storage_file_alloc(storage); | ||||||
|     bool result = false; |     bool result = false; | ||||||
|     if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { |     if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) { | ||||||
|         result = storage_file_write(file, "13DA", 4) == 4; |         result = (storage_file_write(file, "13DA", 4) == 4); | ||||||
|     } |     } | ||||||
|     storage_file_close(file); |     storage_file_close(file); | ||||||
|     storage_file_free(file); |     storage_file_free(file); | ||||||
|  | |||||||
| @ -115,6 +115,66 @@ MU_TEST(storage_file_open_close) { | |||||||
|     furi_record_close(RECORD_STORAGE); |     furi_record_close(RECORD_STORAGE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static bool storage_file_read_write_test(File* file, uint8_t* data, size_t test_size) { | ||||||
|  |     const char* filename = UNIT_TESTS_PATH("storage_chunk.test"); | ||||||
|  | 
 | ||||||
|  |     // fill with pattern
 | ||||||
|  |     for(size_t i = 0; i < test_size; i++) { | ||||||
|  |         data[i] = (i % 113); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool result = false; | ||||||
|  |     do { | ||||||
|  |         if(!storage_file_open(file, filename, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break; | ||||||
|  |         if(test_size != storage_file_write(file, data, test_size)) break; | ||||||
|  |         storage_file_close(file); | ||||||
|  | 
 | ||||||
|  |         // reset data
 | ||||||
|  |         memset(data, 0, test_size); | ||||||
|  | 
 | ||||||
|  |         if(!storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) break; | ||||||
|  |         if(test_size != storage_file_read(file, data, test_size)) break; | ||||||
|  |         storage_file_close(file); | ||||||
|  | 
 | ||||||
|  |         // check that data is correct
 | ||||||
|  |         for(size_t i = 0; i < test_size; i++) { | ||||||
|  |             if(data[i] != (i % 113)) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         result = true; | ||||||
|  |     } while(false); | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MU_TEST(storage_file_read_write_64k) { | ||||||
|  |     Storage* storage = furi_record_open(RECORD_STORAGE); | ||||||
|  |     File* file = storage_file_alloc(storage); | ||||||
|  | 
 | ||||||
|  |     size_t size_1k = 1024; | ||||||
|  |     size_t size_64k = size_1k + size_1k * 63; | ||||||
|  |     size_t size_65k = size_64k + size_1k; | ||||||
|  |     size_t size_max = size_65k + 8; | ||||||
|  | 
 | ||||||
|  |     size_t max_ram_block = memmgr_heap_get_max_free_block(); | ||||||
|  | 
 | ||||||
|  |     if(max_ram_block < size_max) { | ||||||
|  |         mu_warn("Not enough RAM for >64k block test"); | ||||||
|  |     } else { | ||||||
|  |         uint8_t* data = malloc(size_max); | ||||||
|  |         mu_check(storage_file_read_write_test(file, data, size_1k)); | ||||||
|  |         mu_check(storage_file_read_write_test(file, data, size_64k)); | ||||||
|  |         mu_check(storage_file_read_write_test(file, data, size_65k)); | ||||||
|  |         mu_check(storage_file_read_write_test(file, data, size_max)); | ||||||
|  |         free(data); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     storage_file_free(file); | ||||||
|  |     furi_record_close(RECORD_STORAGE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST_SUITE(storage_file) { | MU_TEST_SUITE(storage_file) { | ||||||
|     storage_file_open_lock_setup(); |     storage_file_open_lock_setup(); | ||||||
|     MU_RUN_TEST(storage_file_open_close); |     MU_RUN_TEST(storage_file_open_close); | ||||||
| @ -122,6 +182,10 @@ MU_TEST_SUITE(storage_file) { | |||||||
|     storage_file_open_lock_teardown(); |     storage_file_open_lock_teardown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST_SUITE(storage_file_64k) { | ||||||
|  |     MU_RUN_TEST(storage_file_read_write_64k); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST(storage_dir_open_close) { | MU_TEST(storage_dir_open_close) { | ||||||
|     Storage* storage = furi_record_open(RECORD_STORAGE); |     Storage* storage = furi_record_open(RECORD_STORAGE); | ||||||
|     File* file; |     File* file; | ||||||
| @ -640,6 +704,7 @@ MU_TEST_SUITE(test_md5_calc_suite) { | |||||||
| 
 | 
 | ||||||
| int run_minunit_test_storage() { | int run_minunit_test_storage() { | ||||||
|     MU_RUN_SUITE(storage_file); |     MU_RUN_SUITE(storage_file); | ||||||
|  |     MU_RUN_SUITE(storage_file_64k); | ||||||
|     MU_RUN_SUITE(storage_dir); |     MU_RUN_SUITE(storage_dir); | ||||||
|     MU_RUN_SUITE(storage_rename); |     MU_RUN_SUITE(storage_rename); | ||||||
|     MU_RUN_SUITE(test_data_path); |     MU_RUN_SUITE(test_data_path); | ||||||
|  | |||||||
| @ -326,6 +326,7 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) { | |||||||
|     furi_hal_subghz_set_frequency_and_path(433920000); |     furi_hal_subghz_set_frequency_and_path(433920000); | ||||||
| 
 | 
 | ||||||
|     if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { |     if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) { | ||||||
|  |         mu_warn("SubGHZ transmission is prohibited"); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -78,6 +78,16 @@ void minunit_print_fail(const char* str) { | |||||||
|     printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); |     printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void minunit_printf_warning(const char* format, ...) { | ||||||
|  |     FuriString* str = furi_string_alloc(); | ||||||
|  |     va_list args; | ||||||
|  |     va_start(args, format); | ||||||
|  |     furi_string_vprintf(str, format, args); | ||||||
|  |     va_end(args); | ||||||
|  |     printf(_FURI_LOG_CLR_W "%s\r\n" _FURI_LOG_CLR_RESET, furi_string_get_cstr(str)); | ||||||
|  |     furi_string_free(str); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void unit_tests_cli(Cli* cli, FuriString* args, void* context) { | void unit_tests_cli(Cli* cli, FuriString* args, void* context) { | ||||||
|     UNUSED(cli); |     UNUSED(cli); | ||||||
|     UNUSED(args); |     UNUSED(args); | ||||||
|  | |||||||
| @ -12,12 +12,12 @@ static bool archive_favorites_read_line(File* file, FuriString* str_result) { | |||||||
|     bool result = false; |     bool result = false; | ||||||
| 
 | 
 | ||||||
|     do { |     do { | ||||||
|         uint16_t read_count = storage_file_read(file, buffer, ARCHIVE_FAV_FILE_BUF_LEN); |         size_t read_count = storage_file_read(file, buffer, ARCHIVE_FAV_FILE_BUF_LEN); | ||||||
|         if(storage_file_get_error(file) != FSE_OK) { |         if(storage_file_get_error(file) != FSE_OK) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for(uint16_t i = 0; i < read_count; i++) { |         for(size_t i = 0; i < read_count; i++) { | ||||||
|             if(buffer[i] == '\n') { |             if(buffer[i] == '\n') { | ||||||
|                 uint32_t position = storage_file_tell(file); |                 uint32_t position = storage_file_tell(file); | ||||||
|                 if(storage_file_get_error(file) != FSE_OK) { |                 if(storage_file_get_error(file) != FSE_OK) { | ||||||
|  | |||||||
| @ -946,7 +946,7 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) { | |||||||
| static bool | static bool | ||||||
|     subghz_on_system_start_istream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { |     subghz_on_system_start_istream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) { | ||||||
|     File* file = istream->state; |     File* file = istream->state; | ||||||
|     uint16_t ret = storage_file_read(file, buf, count); |     size_t ret = storage_file_read(file, buf, count); | ||||||
|     return (count == ret); |     return (count == ret); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -444,7 +444,7 @@ static bool notification_load_settings(NotificationApp* app) { | |||||||
|         storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING); |         storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING); | ||||||
| 
 | 
 | ||||||
|     if(fs_result) { |     if(fs_result) { | ||||||
|         uint16_t bytes_count = storage_file_read(file, &settings, settings_size); |         size_t bytes_count = storage_file_read(file, &settings, settings_size); | ||||||
| 
 | 
 | ||||||
|         if(bytes_count != settings_size) { |         if(bytes_count != settings_size) { | ||||||
|             fs_result = false; |             fs_result = false; | ||||||
| @ -488,7 +488,7 @@ static bool notification_save_settings(NotificationApp* app) { | |||||||
|         storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS); |         storage_file_open(file, NOTIFICATION_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS); | ||||||
| 
 | 
 | ||||||
|     if(fs_result) { |     if(fs_result) { | ||||||
|         uint16_t bytes_count = storage_file_write(file, &settings, settings_size); |         size_t bytes_count = storage_file_write(file, &settings, settings_size); | ||||||
| 
 | 
 | ||||||
|         if(bytes_count != settings_size) { |         if(bytes_count != settings_size) { | ||||||
|             fs_result = false; |             fs_result = false; | ||||||
|  | |||||||
| @ -466,7 +466,7 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte | |||||||
|            request->content.storage_write_request.file.data->size) { |            request->content.storage_write_request.file.data->size) { | ||||||
|             uint8_t* buffer = request->content.storage_write_request.file.data->bytes; |             uint8_t* buffer = request->content.storage_write_request.file.data->bytes; | ||||||
|             size_t buffer_size = request->content.storage_write_request.file.data->size; |             size_t buffer_size = request->content.storage_write_request.file.data->size; | ||||||
|             uint16_t written_size = storage_file_write(file, buffer, buffer_size); |             size_t written_size = storage_file_write(file, buffer, buffer_size); | ||||||
|             fs_operation_success = (written_size == buffer_size); |             fs_operation_success = (written_size == buffer_size); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -123,7 +123,7 @@ bool storage_file_is_dir(File* file); | |||||||
|  * @param bytes_to_read number of bytes to read. Must be less than or equal to the size of the buffer. |  * @param bytes_to_read number of bytes to read. Must be less than or equal to the size of the buffer. | ||||||
|  * @return actual number of bytes read (may be fewer than requested). |  * @return actual number of bytes read (may be fewer than requested). | ||||||
|  */ |  */ | ||||||
| uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read); | size_t storage_file_read(File* file, void* buff, size_t bytes_to_read); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Write bytes from a buffer to a file. |  * @brief Write bytes from a buffer to a file. | ||||||
| @ -133,7 +133,7 @@ uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read); | |||||||
|  * @param bytes_to_write number of bytes to write. Must be less than or equal to the size of the buffer. |  * @param bytes_to_write number of bytes to write. Must be less than or equal to the size of the buffer. | ||||||
|  * @return actual number of bytes written (may be fewer than requested). |  * @return actual number of bytes written (may be fewer than requested). | ||||||
|  */ |  */ | ||||||
| uint16_t storage_file_write(File* file, const void* buff, uint16_t bytes_to_write); | size_t storage_file_write(File* file, const void* buff, size_t bytes_to_write); | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief Change the current access position in a file. |  * @brief Change the current access position in a file. | ||||||
| @ -207,7 +207,7 @@ bool storage_file_exists(Storage* storage, const char* path); | |||||||
|  * @param size data size to be copied, in bytes. |  * @param size data size to be copied, in bytes. | ||||||
|  * @return true if the data was successfully copied, false otherwise. |  * @return true if the data was successfully copied, false otherwise. | ||||||
|  */ |  */ | ||||||
| bool storage_file_copy_to_file(File* source, File* destination, uint32_t size); | bool storage_file_copy_to_file(File* source, File* destination, size_t size); | ||||||
| 
 | 
 | ||||||
| /******************* Directory Functions *******************/ | /******************* Directory Functions *******************/ | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -198,15 +198,15 @@ static void storage_cli_read(Cli* cli, FuriString* path) { | |||||||
|     File* file = storage_file_alloc(api); |     File* file = storage_file_alloc(api); | ||||||
| 
 | 
 | ||||||
|     if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { |     if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||||
|         const uint16_t buffer_size = 128; |         const size_t buffer_size = 128; | ||||||
|         uint16_t read_size = 0; |         size_t read_size = 0; | ||||||
|         uint8_t* data = malloc(buffer_size); |         uint8_t* data = malloc(buffer_size); | ||||||
| 
 | 
 | ||||||
|         printf("Size: %lu\r\n", (uint32_t)storage_file_size(file)); |         printf("Size: %lu\r\n", (uint32_t)storage_file_size(file)); | ||||||
| 
 | 
 | ||||||
|         do { |         do { | ||||||
|             read_size = storage_file_read(file, data, buffer_size); |             read_size = storage_file_read(file, data, buffer_size); | ||||||
|             for(uint16_t i = 0; i < read_size; i++) { |             for(size_t i = 0; i < read_size; i++) { | ||||||
|                 printf("%c", data[i]); |                 printf("%c", data[i]); | ||||||
|             } |             } | ||||||
|         } while(read_size > 0); |         } while(read_size > 0); | ||||||
| @ -227,7 +227,7 @@ static void storage_cli_write(Cli* cli, FuriString* path) { | |||||||
|     Storage* api = furi_record_open(RECORD_STORAGE); |     Storage* api = furi_record_open(RECORD_STORAGE); | ||||||
|     File* file = storage_file_alloc(api); |     File* file = storage_file_alloc(api); | ||||||
| 
 | 
 | ||||||
|     const uint16_t buffer_size = 512; |     const size_t buffer_size = 512; | ||||||
|     uint8_t* buffer = malloc(buffer_size); |     uint8_t* buffer = malloc(buffer_size); | ||||||
| 
 | 
 | ||||||
|     if(storage_file_open(file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { |     if(storage_file_open(file, furi_string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { | ||||||
| @ -239,10 +239,10 @@ static void storage_cli_write(Cli* cli, FuriString* path) { | |||||||
|             uint8_t symbol = cli_getc(cli); |             uint8_t symbol = cli_getc(cli); | ||||||
| 
 | 
 | ||||||
|             if(symbol == CliSymbolAsciiETX) { |             if(symbol == CliSymbolAsciiETX) { | ||||||
|                 uint16_t write_size = read_index % buffer_size; |                 size_t write_size = read_index % buffer_size; | ||||||
| 
 | 
 | ||||||
|                 if(write_size > 0) { |                 if(write_size > 0) { | ||||||
|                     uint16_t written_size = storage_file_write(file, buffer, write_size); |                     size_t written_size = storage_file_write(file, buffer, write_size); | ||||||
| 
 | 
 | ||||||
|                     if(written_size != write_size) { |                     if(written_size != write_size) { | ||||||
|                         storage_cli_print_error(storage_file_get_error(file)); |                         storage_cli_print_error(storage_file_get_error(file)); | ||||||
| @ -257,7 +257,7 @@ static void storage_cli_write(Cli* cli, FuriString* path) { | |||||||
|             read_index++; |             read_index++; | ||||||
| 
 | 
 | ||||||
|             if(((read_index % buffer_size) == 0)) { |             if(((read_index % buffer_size) == 0)) { | ||||||
|                 uint16_t written_size = storage_file_write(file, buffer, buffer_size); |                 size_t written_size = storage_file_write(file, buffer, buffer_size); | ||||||
| 
 | 
 | ||||||
|                 if(written_size != buffer_size) { |                 if(written_size != buffer_size) { | ||||||
|                     storage_cli_print_error(storage_file_get_error(file)); |                     storage_cli_print_error(storage_file_get_error(file)); | ||||||
| @ -289,7 +289,7 @@ static void storage_cli_read_chunks(Cli* cli, FuriString* path, FuriString* args | |||||||
|     } else if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { |     } else if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||||
|         uint64_t file_size = storage_file_size(file); |         uint64_t file_size = storage_file_size(file); | ||||||
| 
 | 
 | ||||||
|         printf("Size: %lu\r\n", (uint32_t)file_size); |         printf("Size: %llu\r\n", file_size); | ||||||
| 
 | 
 | ||||||
|         if(buffer_size) { |         if(buffer_size) { | ||||||
|             uint8_t* data = malloc(buffer_size); |             uint8_t* data = malloc(buffer_size); | ||||||
| @ -297,8 +297,8 @@ static void storage_cli_read_chunks(Cli* cli, FuriString* path, FuriString* args | |||||||
|                 printf("\r\nReady?\r\n"); |                 printf("\r\nReady?\r\n"); | ||||||
|                 cli_getc(cli); |                 cli_getc(cli); | ||||||
| 
 | 
 | ||||||
|                 uint16_t read_size = storage_file_read(file, data, buffer_size); |                 size_t read_size = storage_file_read(file, data, buffer_size); | ||||||
|                 for(uint16_t i = 0; i < read_size; i++) { |                 for(size_t i = 0; i < read_size; i++) { | ||||||
|                     putchar(data[i]); |                     putchar(data[i]); | ||||||
|                 } |                 } | ||||||
|                 file_size -= read_size; |                 file_size -= read_size; | ||||||
| @ -335,7 +335,7 @@ static void storage_cli_write_chunk(Cli* cli, FuriString* path, FuriString* args | |||||||
| 
 | 
 | ||||||
|                 size_t read_bytes = cli_read(cli, buffer, buffer_size); |                 size_t read_bytes = cli_read(cli, buffer, buffer_size); | ||||||
| 
 | 
 | ||||||
|                 uint16_t written_size = storage_file_write(file, buffer, read_bytes); |                 size_t written_size = storage_file_write(file, buffer, read_bytes); | ||||||
| 
 | 
 | ||||||
|                 if(written_size != buffer_size) { |                 if(written_size != buffer_size) { | ||||||
|                     storage_cli_print_error(storage_file_get_error(file)); |                     storage_cli_print_error(storage_file_get_error(file)); | ||||||
|  | |||||||
| @ -139,7 +139,7 @@ bool storage_file_close(File* file) { | |||||||
|     return S_RETURN_BOOL; |     return S_RETURN_BOOL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { | static uint16_t storage_file_read_underlying(File* file, void* buff, uint16_t bytes_to_read) { | ||||||
|     if(bytes_to_read == 0) { |     if(bytes_to_read == 0) { | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| @ -159,7 +159,8 @@ uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { | |||||||
|     return S_RETURN_UINT16; |     return S_RETURN_UINT16; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint16_t storage_file_write(File* file, const void* buff, uint16_t bytes_to_write) { | static uint16_t | ||||||
|  |     storage_file_write_underlying(File* file, const void* buff, uint16_t bytes_to_write) { | ||||||
|     if(bytes_to_write == 0) { |     if(bytes_to_write == 0) { | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| @ -179,6 +180,40 @@ uint16_t storage_file_write(File* file, const void* buff, uint16_t bytes_to_writ | |||||||
|     return S_RETURN_UINT16; |     return S_RETURN_UINT16; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | size_t storage_file_read(File* file, void* buff, size_t to_read) { | ||||||
|  |     size_t total = 0; | ||||||
|  | 
 | ||||||
|  |     const size_t max_chunk = UINT16_MAX; | ||||||
|  |     do { | ||||||
|  |         const size_t chunk = MIN((to_read - total), max_chunk); | ||||||
|  |         size_t read = storage_file_read_underlying(file, buff + total, chunk); | ||||||
|  |         total += read; | ||||||
|  | 
 | ||||||
|  |         if(storage_file_get_error(file) != FSE_OK || read != chunk) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } while(total != to_read); | ||||||
|  | 
 | ||||||
|  |     return total; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t storage_file_write(File* file, const void* buff, size_t to_write) { | ||||||
|  |     size_t total = 0; | ||||||
|  | 
 | ||||||
|  |     const size_t max_chunk = UINT16_MAX; | ||||||
|  |     do { | ||||||
|  |         const size_t chunk = MIN((to_write - total), max_chunk); | ||||||
|  |         size_t written = storage_file_write_underlying(file, buff + total, chunk); | ||||||
|  |         total += written; | ||||||
|  | 
 | ||||||
|  |         if(storage_file_get_error(file) != FSE_OK || written != chunk) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } while(total != to_write); | ||||||
|  | 
 | ||||||
|  |     return total; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool storage_file_seek(File* file, uint32_t offset, bool from_start) { | bool storage_file_seek(File* file, uint32_t offset, bool from_start) { | ||||||
|     S_FILE_API_PROLOGUE; |     S_FILE_API_PROLOGUE; | ||||||
|     S_API_PROLOGUE; |     S_API_PROLOGUE; | ||||||
| @ -252,7 +287,7 @@ bool storage_file_exists(Storage* storage, const char* path) { | |||||||
|     return exist; |     return exist; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool storage_file_copy_to_file(File* source, File* destination, uint32_t size) { | bool storage_file_copy_to_file(File* source, File* destination, size_t size) { | ||||||
|     uint8_t* buffer = malloc(FILE_BUFFER_SIZE); |     uint8_t* buffer = malloc(FILE_BUFFER_SIZE); | ||||||
| 
 | 
 | ||||||
|     while(size) { |     while(size) { | ||||||
|  | |||||||
| @ -44,7 +44,7 @@ static bool storage_settings_scene_bench_write( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|     storage_settings_scene_bench_read(Storage* api, uint16_t size, uint8_t* data, uint32_t* speed) { |     storage_settings_scene_bench_read(Storage* api, size_t size, uint8_t* data, uint32_t* speed) { | ||||||
|     File* file = storage_file_alloc(api); |     File* file = storage_file_alloc(api); | ||||||
|     bool result = true; |     bool result = true; | ||||||
|     *speed = -1; |     *speed = -1; | ||||||
| @ -82,7 +82,7 @@ static void storage_settings_scene_benchmark(StorageSettings* app) { | |||||||
|         bench_data[i] = (uint8_t)i; |         bench_data[i] = (uint8_t)i; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint16_t bench_size[BENCH_COUNT] = {1, 8, 32, 256, 512, 1024}; |     size_t bench_size[BENCH_COUNT] = {1, 8, 32, 256, 512, 1024}; | ||||||
|     uint32_t bench_w_speed[BENCH_COUNT] = {0, 0, 0, 0, 0, 0}; |     uint32_t bench_w_speed[BENCH_COUNT] = {0, 0, 0, 0, 0, 0}; | ||||||
|     uint32_t bench_r_speed[BENCH_COUNT] = {0, 0, 0, 0, 0, 0}; |     uint32_t bench_r_speed[BENCH_COUNT] = {0, 0, 0, 0, 0, 0}; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -104,7 +104,7 @@ static bool update_task_write_stack_data(UpdateTask* update_task) { | |||||||
| 
 | 
 | ||||||
|     update_task_set_progress(update_task, UpdateTaskStageRadioWrite, 0); |     update_task_set_progress(update_task, UpdateTaskStageRadioWrite, 0); | ||||||
|     uint8_t* fw_block = malloc(FLASH_PAGE_SIZE); |     uint8_t* fw_block = malloc(FLASH_PAGE_SIZE); | ||||||
|     uint16_t bytes_read = 0; |     size_t bytes_read = 0; | ||||||
|     uint32_t element_offs = 0; |     uint32_t element_offs = 0; | ||||||
| 
 | 
 | ||||||
|     while(element_offs < stack_size) { |     while(element_offs < stack_size) { | ||||||
|  | |||||||
| @ -101,7 +101,7 @@ static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, FuriString* | |||||||
|         buffer[ELF_NAME_BUFFER_LEN] = 0; |         buffer[ELF_NAME_BUFFER_LEN] = 0; | ||||||
| 
 | 
 | ||||||
|         while(true) { |         while(true) { | ||||||
|             uint16_t read = storage_file_read(elf->fd, buffer, ELF_NAME_BUFFER_LEN); |             size_t read = storage_file_read(elf->fd, buffer, ELF_NAME_BUFFER_LEN); | ||||||
|             furi_string_cat(name, buffer); |             furi_string_cat(name, buffer); | ||||||
|             if(strlen(buffer) < ELF_NAME_BUFFER_LEN) { |             if(strlen(buffer) < ELF_NAME_BUFFER_LEN) { | ||||||
|                 result = true; |                 result = true; | ||||||
|  | |||||||
| @ -396,7 +396,7 @@ bool music_worker_load_rtttl_from_file(MusicWorker* instance, const char* file_p | |||||||
|             break; |             break; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         uint16_t ret = 0; |         size_t ret = 0; | ||||||
|         do { |         do { | ||||||
|             uint8_t buffer[65] = {0}; |             uint8_t buffer[65] = {0}; | ||||||
|             ret = storage_file_read(file, buffer, sizeof(buffer) - 1); |             ret = storage_file_read(file, buffer, sizeof(buffer) - 1); | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ uint32_t crc32_calc_file(File* file, const FileCrcProgressCb progress_cb, void* | |||||||
|     uint32_t file_crc = 0; |     uint32_t file_crc = 0; | ||||||
| 
 | 
 | ||||||
|     uint8_t* data_buffer = malloc(CRC_DATA_BUFFER_MAX_LEN); |     uint8_t* data_buffer = malloc(CRC_DATA_BUFFER_MAX_LEN); | ||||||
|     uint16_t data_buffer_valid_len; |     size_t data_buffer_valid_len; | ||||||
| 
 | 
 | ||||||
|     uint32_t file_size = storage_file_size(file); |     uint32_t file_size = storage_file_size(file); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,13 +5,13 @@ bool md5_calc_file(File* file, const char* path, unsigned char output[16], FS_Er | |||||||
|     bool result = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); |     bool result = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); | ||||||
| 
 | 
 | ||||||
|     if(result) { |     if(result) { | ||||||
|         const uint16_t size_to_read = 512; |         const size_t size_to_read = 512; | ||||||
|         uint8_t* data = malloc(size_to_read); |         uint8_t* data = malloc(size_to_read); | ||||||
|         md5_context* md5_ctx = malloc(sizeof(md5_context)); |         md5_context* md5_ctx = malloc(sizeof(md5_context)); | ||||||
| 
 | 
 | ||||||
|         md5_starts(md5_ctx); |         md5_starts(md5_ctx); | ||||||
|         while(true) { |         while(true) { | ||||||
|             uint16_t read_size = storage_file_read(file, data, size_to_read); |             size_t read_size = storage_file_read(file, data, size_to_read); | ||||||
|             if(read_size == 0) break; |             if(read_size == 0) break; | ||||||
|             md5_update(md5_ctx, data, read_size); |             md5_update(md5_ctx, data, read_size); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic, | |||||||
|         header.flags = 0; |         header.flags = 0; | ||||||
|         header.timestamp = 0; |         header.timestamp = 0; | ||||||
| 
 | 
 | ||||||
|         uint16_t bytes_count = storage_file_write(file, &header, sizeof(header)); |         size_t bytes_count = storage_file_write(file, &header, sizeof(header)); | ||||||
|         bytes_count += storage_file_write(file, data, size); |         bytes_count += storage_file_write(file, data, size); | ||||||
| 
 | 
 | ||||||
|         if(bytes_count != (size + sizeof(header))) { |         if(bytes_count != (size + sizeof(header))) { | ||||||
| @ -79,7 +79,7 @@ bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic, | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if(result) { |     if(result) { | ||||||
|         uint16_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader)); |         size_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader)); | ||||||
|         bytes_count += storage_file_read(file, data_read, size); |         bytes_count += storage_file_read(file, data_read, size); | ||||||
| 
 | 
 | ||||||
|         if(bytes_count != (sizeof(SavedStructHeader) + size)) { |         if(bytes_count != (sizeof(SavedStructHeader) + size)) { | ||||||
| @ -146,7 +146,7 @@ bool saved_struct_get_payload_size( | |||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         uint16_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader)); |         size_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader)); | ||||||
|         if(bytes_count != sizeof(SavedStructHeader)) { |         if(bytes_count != sizeof(SavedStructHeader)) { | ||||||
|             FURI_LOG_E(TAG, "Failed to read header"); |             FURI_LOG_E(TAG, "Failed to read header"); | ||||||
|             break; |             break; | ||||||
|  | |||||||
| @ -134,31 +134,11 @@ static size_t file_stream_size(FileStream* stream) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static size_t file_stream_write(FileStream* stream, const uint8_t* data, size_t size) { | static size_t file_stream_write(FileStream* stream, const uint8_t* data, size_t size) { | ||||||
|     // TODO FL-3545: cache
 |     return storage_file_write(stream->file, data, size); | ||||||
|     size_t need_to_write = size; |  | ||||||
|     while(need_to_write > 0) { |  | ||||||
|         uint16_t was_written = |  | ||||||
|             storage_file_write(stream->file, data + (size - need_to_write), need_to_write); |  | ||||||
|         need_to_write -= was_written; |  | ||||||
| 
 |  | ||||||
|         if(was_written == 0) break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return size - need_to_write; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static size_t file_stream_read(FileStream* stream, uint8_t* data, size_t size) { | static size_t file_stream_read(FileStream* stream, uint8_t* data, size_t size) { | ||||||
|     // TODO FL-3545: cache
 |     return storage_file_read(stream->file, data, size); | ||||||
|     size_t need_to_read = size; |  | ||||||
|     while(need_to_read > 0) { |  | ||||||
|         uint16_t was_read = |  | ||||||
|             storage_file_read(stream->file, data + (size - need_to_read), need_to_read); |  | ||||||
|         need_to_read -= was_read; |  | ||||||
| 
 |  | ||||||
|         if(was_read == 0) break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return size - need_to_read; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool file_stream_delete_and_insert( | static bool file_stream_delete_and_insert( | ||||||
|  | |||||||
| @ -22,7 +22,7 @@ uint8_t dfu_file_validate_headers(File* dfuf, const DfuValidationParams* referen | |||||||
| 
 | 
 | ||||||
|     DfuPrefix dfu_prefix = {0}; |     DfuPrefix dfu_prefix = {0}; | ||||||
|     DfuSuffix dfu_suffix = {0}; |     DfuSuffix dfu_suffix = {0}; | ||||||
|     uint16_t bytes_read = 0; |     size_t bytes_read = 0; | ||||||
| 
 | 
 | ||||||
|     if(!storage_file_is_open(dfuf) || !storage_file_seek(dfuf, 0, true)) { |     if(!storage_file_is_open(dfuf) || !storage_file_seek(dfuf, 0, true)) { | ||||||
|         return 0; |         return 0; | ||||||
| @ -90,7 +90,7 @@ static DfuUpdateBlockResult dfu_file_perform_task_for_update_pages( | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint8_t* fw_block = malloc(FLASH_PAGE_SIZE); |     uint8_t* fw_block = malloc(FLASH_PAGE_SIZE); | ||||||
|     uint16_t bytes_read = 0; |     size_t bytes_read = 0; | ||||||
|     uint32_t element_offs = 0; |     uint32_t element_offs = 0; | ||||||
| 
 | 
 | ||||||
|     while(element_offs < header->dwElementSize) { |     while(element_offs < header->dwElementSize) { | ||||||
| @ -125,7 +125,7 @@ static DfuUpdateBlockResult dfu_file_perform_task_for_update_pages( | |||||||
| bool dfu_file_process_targets(const DfuUpdateTask* task, File* dfuf, const uint8_t n_targets) { | bool dfu_file_process_targets(const DfuUpdateTask* task, File* dfuf, const uint8_t n_targets) { | ||||||
|     TargetPrefix target_prefix = {0}; |     TargetPrefix target_prefix = {0}; | ||||||
|     ImageElementHeader image_element = {0}; |     ImageElementHeader image_element = {0}; | ||||||
|     uint16_t bytes_read = 0; |     size_t bytes_read = 0; | ||||||
| 
 | 
 | ||||||
|     if(!storage_file_seek(dfuf, sizeof(DfuPrefix), true)) { |     if(!storage_file_seek(dfuf, sizeof(DfuPrefix), true)) { | ||||||
|         return UpdateBlockResult_Failed; |         return UpdateBlockResult_Failed; | ||||||
|  | |||||||
| @ -85,7 +85,7 @@ bool update_operation_get_current_package_manifest_path(Storage* storage, FuriSt | |||||||
|                    upd_file, UPDATE_FILE_POINTER_FN, FSAM_READ, FSOM_OPEN_EXISTING)) { |                    upd_file, UPDATE_FILE_POINTER_FN, FSAM_READ, FSOM_OPEN_EXISTING)) { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             uint16_t bytes_read = |             size_t bytes_read = | ||||||
|                 storage_file_read(upd_file, manifest_name_buffer, UPDATE_MANIFEST_MAX_PATH_LEN); |                 storage_file_read(upd_file, manifest_name_buffer, UPDATE_MANIFEST_MAX_PATH_LEN); | ||||||
|             if((bytes_read == 0) || (bytes_read == UPDATE_MANIFEST_MAX_PATH_LEN)) { |             if((bytes_read == 0) || (bytes_read == UPDATE_MANIFEST_MAX_PATH_LEN)) { | ||||||
|                 break; |                 break; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,45.1,, | Version,+,46.0,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| Header,+,applications/services/cli/cli_vcp.h,, | Header,+,applications/services/cli/cli_vcp.h,, | ||||||
| @ -1376,7 +1376,7 @@ Function,+,furi_pubsub_subscribe,FuriPubSubSubscription*,"FuriPubSub*, FuriPubSu | |||||||
| Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" | Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" | ||||||
| Function,+,furi_record_close,void,const char* | Function,+,furi_record_close,void,const char* | ||||||
| Function,+,furi_record_create,void,"const char*, void*" | Function,+,furi_record_create,void,"const char*, void*" | ||||||
| Function,-,furi_record_destroy,_Bool,const char* | Function,+,furi_record_destroy,_Bool,const char* | ||||||
| Function,+,furi_record_exists,_Bool,const char* | Function,+,furi_record_exists,_Bool,const char* | ||||||
| Function,-,furi_record_init,void, | Function,-,furi_record_init,void, | ||||||
| Function,+,furi_record_open,void*,const char* | Function,+,furi_record_open,void*,const char* | ||||||
| @ -2090,7 +2090,7 @@ Function,-,storage_dir_rewind,_Bool,File* | |||||||
| Function,+,storage_error_get_desc,const char*,FS_Error | Function,+,storage_error_get_desc,const char*,FS_Error | ||||||
| Function,+,storage_file_alloc,File*,Storage* | Function,+,storage_file_alloc,File*,Storage* | ||||||
| Function,+,storage_file_close,_Bool,File* | Function,+,storage_file_close,_Bool,File* | ||||||
| Function,+,storage_file_copy_to_file,_Bool,"File*, File*, uint32_t" | Function,+,storage_file_copy_to_file,_Bool,"File*, File*, size_t" | ||||||
| Function,+,storage_file_eof,_Bool,File* | Function,+,storage_file_eof,_Bool,File* | ||||||
| Function,+,storage_file_exists,_Bool,"Storage*, const char*" | Function,+,storage_file_exists,_Bool,"Storage*, const char*" | ||||||
| Function,+,storage_file_free,void,File* | Function,+,storage_file_free,void,File* | ||||||
| @ -2100,13 +2100,13 @@ Function,-,storage_file_get_internal_error,int32_t,File* | |||||||
| Function,+,storage_file_is_dir,_Bool,File* | Function,+,storage_file_is_dir,_Bool,File* | ||||||
| Function,+,storage_file_is_open,_Bool,File* | Function,+,storage_file_is_open,_Bool,File* | ||||||
| Function,+,storage_file_open,_Bool,"File*, const char*, FS_AccessMode, FS_OpenMode" | Function,+,storage_file_open,_Bool,"File*, const char*, FS_AccessMode, FS_OpenMode" | ||||||
| Function,+,storage_file_read,uint16_t,"File*, void*, uint16_t" | Function,+,storage_file_read,size_t,"File*, void*, size_t" | ||||||
| Function,+,storage_file_seek,_Bool,"File*, uint32_t, _Bool" | Function,+,storage_file_seek,_Bool,"File*, uint32_t, _Bool" | ||||||
| Function,+,storage_file_size,uint64_t,File* | Function,+,storage_file_size,uint64_t,File* | ||||||
| Function,+,storage_file_sync,_Bool,File* | Function,+,storage_file_sync,_Bool,File* | ||||||
| Function,+,storage_file_tell,uint64_t,File* | Function,+,storage_file_tell,uint64_t,File* | ||||||
| Function,+,storage_file_truncate,_Bool,File* | Function,+,storage_file_truncate,_Bool,File* | ||||||
| Function,+,storage_file_write,uint16_t,"File*, const void*, uint16_t" | Function,+,storage_file_write,size_t,"File*, const void*, size_t" | ||||||
| Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" | Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" | ||||||
| Function,+,storage_get_pubsub,FuriPubSub*,Storage* | Function,+,storage_get_pubsub,FuriPubSub*,Storage* | ||||||
| Function,+,storage_int_backup,FS_Error,"Storage*, const char*" | Function,+,storage_int_backup,FS_Error,"Storage*, const char*" | ||||||
|  | |||||||
| 
 | 
| @ -1,5 +1,5 @@ | |||||||
| entry,status,name,type,params | entry,status,name,type,params | ||||||
| Version,+,45.1,, | Version,+,46.0,, | ||||||
| Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, | Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, | ||||||
| Header,+,applications/services/bt/bt_service/bt.h,, | Header,+,applications/services/bt/bt_service/bt.h,, | ||||||
| Header,+,applications/services/cli/cli.h,, | Header,+,applications/services/cli/cli.h,, | ||||||
| @ -1571,7 +1571,7 @@ Function,+,furi_pubsub_subscribe,FuriPubSubSubscription*,"FuriPubSub*, FuriPubSu | |||||||
| Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" | Function,+,furi_pubsub_unsubscribe,void,"FuriPubSub*, FuriPubSubSubscription*" | ||||||
| Function,+,furi_record_close,void,const char* | Function,+,furi_record_close,void,const char* | ||||||
| Function,+,furi_record_create,void,"const char*, void*" | Function,+,furi_record_create,void,"const char*, void*" | ||||||
| Function,-,furi_record_destroy,_Bool,const char* | Function,+,furi_record_destroy,_Bool,const char* | ||||||
| Function,+,furi_record_exists,_Bool,const char* | Function,+,furi_record_exists,_Bool,const char* | ||||||
| Function,-,furi_record_init,void, | Function,-,furi_record_init,void, | ||||||
| Function,+,furi_record_open,void*,const char* | Function,+,furi_record_open,void*,const char* | ||||||
| @ -2717,7 +2717,7 @@ Function,-,storage_dir_rewind,_Bool,File* | |||||||
| Function,+,storage_error_get_desc,const char*,FS_Error | Function,+,storage_error_get_desc,const char*,FS_Error | ||||||
| Function,+,storage_file_alloc,File*,Storage* | Function,+,storage_file_alloc,File*,Storage* | ||||||
| Function,+,storage_file_close,_Bool,File* | Function,+,storage_file_close,_Bool,File* | ||||||
| Function,+,storage_file_copy_to_file,_Bool,"File*, File*, uint32_t" | Function,+,storage_file_copy_to_file,_Bool,"File*, File*, size_t" | ||||||
| Function,+,storage_file_eof,_Bool,File* | Function,+,storage_file_eof,_Bool,File* | ||||||
| Function,+,storage_file_exists,_Bool,"Storage*, const char*" | Function,+,storage_file_exists,_Bool,"Storage*, const char*" | ||||||
| Function,+,storage_file_free,void,File* | Function,+,storage_file_free,void,File* | ||||||
| @ -2727,13 +2727,13 @@ Function,-,storage_file_get_internal_error,int32_t,File* | |||||||
| Function,+,storage_file_is_dir,_Bool,File* | Function,+,storage_file_is_dir,_Bool,File* | ||||||
| Function,+,storage_file_is_open,_Bool,File* | Function,+,storage_file_is_open,_Bool,File* | ||||||
| Function,+,storage_file_open,_Bool,"File*, const char*, FS_AccessMode, FS_OpenMode" | Function,+,storage_file_open,_Bool,"File*, const char*, FS_AccessMode, FS_OpenMode" | ||||||
| Function,+,storage_file_read,uint16_t,"File*, void*, uint16_t" | Function,+,storage_file_read,size_t,"File*, void*, size_t" | ||||||
| Function,+,storage_file_seek,_Bool,"File*, uint32_t, _Bool" | Function,+,storage_file_seek,_Bool,"File*, uint32_t, _Bool" | ||||||
| Function,+,storage_file_size,uint64_t,File* | Function,+,storage_file_size,uint64_t,File* | ||||||
| Function,+,storage_file_sync,_Bool,File* | Function,+,storage_file_sync,_Bool,File* | ||||||
| Function,+,storage_file_tell,uint64_t,File* | Function,+,storage_file_tell,uint64_t,File* | ||||||
| Function,+,storage_file_truncate,_Bool,File* | Function,+,storage_file_truncate,_Bool,File* | ||||||
| Function,+,storage_file_write,uint16_t,"File*, const void*, uint16_t" | Function,+,storage_file_write,size_t,"File*, const void*, size_t" | ||||||
| Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" | Function,+,storage_get_next_filename,void,"Storage*, const char*, const char*, const char*, FuriString*, uint8_t" | ||||||
| Function,+,storage_get_pubsub,FuriPubSub*,Storage* | Function,+,storage_get_pubsub,FuriPubSub*,Storage* | ||||||
| Function,+,storage_int_backup,FS_Error,"Storage*, const char*" | Function,+,storage_int_backup,FS_Error,"Storage*, const char*" | ||||||
|  | |||||||
| 
 | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sergey Gavrilov
						Sergey Gavrilov