From 1d50a5981e818e6033512fb6bd633a181aef9539 Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 9 Aug 2022 18:57:11 +0300 Subject: [PATCH] [FL-2059] Storage fixes for handling empty files (#1563) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * storage: fixed handling of zero-length files * docs: added ReadMe.md for vscode workspace * rpc: storage: improved empty file & error handling in write handler * docs: markdown fix * docs: typo fixes Co-authored-by: SG Co-authored-by: あく --- .vscode/ReadMe.md | 17 ++++++++ applications/rpc/rpc_storage.c | 64 +++++++++++++++++------------- applications/storage/storage_cli.c | 44 ++++++++++---------- lib/toolbox/path.c | 4 ++ 4 files changed, 82 insertions(+), 47 deletions(-) create mode 100644 .vscode/ReadMe.md diff --git a/.vscode/ReadMe.md b/.vscode/ReadMe.md new file mode 100644 index 00000000..5aed0435 --- /dev/null +++ b/.vscode/ReadMe.md @@ -0,0 +1,17 @@ +# Visual Studio Code workspace for Flipper Zero + +## Setup + + * To start developing with VSCode, run `./fbt vscode_dist` in project root. _That should only be done once_ + * After that, open firmware folder in VSCode: "File" > "Open folder" + + For more details on fbt, see [fbt docs](../documentation/fbt.md). + + +## Workflow + +Commands for building firmware are invoked through Build menu: Ctrl+Shift+B. + +To attach a debugging session, first build and flash firmware, then choose your debug probe in Debug menu (Ctrl+Shift+D). + +Note that you have to detach debugging session before rebuilding and re-flashing firmware. diff --git a/applications/rpc/rpc_storage.c b/applications/rpc/rpc_storage.c index 1e2920f5..48ea9e99 100644 --- a/applications/rpc/rpc_storage.c +++ b/applications/rpc/rpc_storage.c @@ -305,21 +305,27 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex response->command_id = request->command_id; response->which_content = PB_Main_storage_read_response_tag; response->command_status = PB_CommandStatus_OK; - response->content.storage_read_response.has_file = true; - response->content.storage_read_response.file.data = - malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(MIN(size_left, MAX_DATA_SIZE))); - uint8_t* buffer = response->content.storage_read_response.file.data->bytes; - uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size; size_t read_size = MIN(size_left, MAX_DATA_SIZE); - *read_size_msg = storage_file_read(file, buffer, read_size); - size_left -= read_size; - result = (*read_size_msg == read_size); + if(read_size) { + response->content.storage_read_response.has_file = true; + response->content.storage_read_response.file.data = + malloc(PB_BYTES_ARRAY_T_ALLOCSIZE()); + uint8_t* buffer = response->content.storage_read_response.file.data->bytes; + uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size; - if(result) { - response->has_next = (size_left > 0); - rpc_send_and_release(session, response); + *read_size_msg = storage_file_read(file, buffer, read_size); + size_left -= read_size; + result = (*read_size_msg == read_size); + + response->has_next = result && (size_left > 0); + } else { + response->content.storage_read_response.has_file = false; + response->has_next = false; + result = true; } + + rpc_send_and_release(session, response); } while((size_left != 0) && result); if(!result) { @@ -349,7 +355,7 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte RpcSession* session = rpc_storage->session; furi_assert(session); - bool result = true; + bool fs_operation_success = true; if(!path_contains_only_ascii(request->content.storage_write_request.path)) { rpc_storage->current_command_id = request->command_id; @@ -370,28 +376,32 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte rpc_storage->current_command_id = request->command_id; rpc_storage->state = RpcStorageStateWriting; const char* path = request->content.storage_write_request.path; - result = storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS); + fs_operation_success = + storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS); } File* file = rpc_storage->file; + bool send_response = false; - if(result) { - uint8_t* buffer = request->content.storage_write_request.file.data->bytes; - size_t buffer_size = request->content.storage_write_request.file.data->size; - - uint16_t written_size = storage_file_write(file, buffer, buffer_size); - result = (written_size == buffer_size); - - if(result && !request->has_next) { - rpc_send_and_release_empty( - session, rpc_storage->current_command_id, PB_CommandStatus_OK); - rpc_system_storage_reset_state(rpc_storage, session, false); + if(fs_operation_success) { + if(request->content.storage_write_request.has_file) { + uint8_t* buffer = request->content.storage_write_request.file.data->bytes; + size_t buffer_size = request->content.storage_write_request.file.data->size; + uint16_t written_size = storage_file_write(file, buffer, buffer_size); + fs_operation_success = (written_size == buffer_size); } + + send_response = !request->has_next; } - if(!result) { - rpc_send_and_release_empty( - session, rpc_storage->current_command_id, rpc_system_storage_get_file_error(file)); + PB_CommandStatus command_status = PB_CommandStatus_OK; + if(!fs_operation_success) { + send_response = true; + command_status = rpc_system_storage_get_file_error(file); + } + + if(send_response) { + rpc_send_and_release_empty(session, rpc_storage->current_command_id, command_status); rpc_system_storage_reset_state(rpc_storage, session, false); } } diff --git a/applications/storage/storage_cli.c b/applications/storage/storage_cli.c index fd988da7..802ebd54 100644 --- a/applications/storage/storage_cli.c +++ b/applications/storage/storage_cli.c @@ -274,24 +274,26 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) { if(parsed_count == EOF || parsed_count != 1) { storage_cli_print_usage(); } else if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - uint8_t* data = malloc(buffer_size); uint64_t file_size = storage_file_size(file); printf("Size: %lu\r\n", (uint32_t)file_size); - while(file_size > 0) { - printf("\r\nReady?\r\n"); - cli_getc(cli); + if(buffer_size) { + uint8_t* data = malloc(buffer_size); + while(file_size > 0) { + printf("\r\nReady?\r\n"); + cli_getc(cli); - uint16_t read_size = storage_file_read(file, data, buffer_size); - for(uint16_t i = 0; i < read_size; i++) { - putchar(data[i]); + uint16_t read_size = storage_file_read(file, data, buffer_size); + for(uint16_t i = 0; i < read_size; i++) { + putchar(data[i]); + } + file_size -= read_size; } - file_size -= read_size; + free(data); } printf("\r\n"); - free(data); } else { storage_cli_print_error(storage_file_get_error(file)); } @@ -315,19 +317,21 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) { if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) { printf("Ready\r\n"); - uint8_t* buffer = malloc(buffer_size); + if(buffer_size) { + uint8_t* buffer = malloc(buffer_size); - for(uint32_t i = 0; i < buffer_size; i++) { - buffer[i] = cli_getc(cli); + for(uint32_t i = 0; i < buffer_size; i++) { + buffer[i] = cli_getc(cli); + } + + uint16_t written_size = storage_file_write(file, buffer, buffer_size); + + if(written_size != buffer_size) { + storage_cli_print_error(storage_file_get_error(file)); + } + + free(buffer); } - - uint16_t written_size = storage_file_write(file, buffer, buffer_size); - - if(written_size != buffer_size) { - storage_cli_print_error(storage_file_get_error(file)); - } - - free(buffer); } else { storage_cli_print_error(storage_file_get_error(file)); } diff --git a/lib/toolbox/path.c b/lib/toolbox/path.c index 38af1efe..1262362e 100644 --- a/lib/toolbox/path.c +++ b/lib/toolbox/path.c @@ -85,6 +85,10 @@ void path_concat(const char* path, const char* suffix, string_t out_path) { } bool path_contains_only_ascii(const char* path) { + if(!path) { + return false; + } + const char* name_pos = strrchr(path, '/'); if(name_pos == NULL) { name_pos = path;