Просмотр исходного кода

[FL-2059] Storage fixes for handling empty files (#1563)

* 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 <who.just.the.doctor@gmail.com>
Co-authored-by: あく <alleteam@gmail.com>
hedger 3 лет назад
Родитель
Сommit
1d50a5981e
4 измененных файлов с 81 добавлено и 46 удалено
  1. 17 0
      .vscode/ReadMe.md
  2. 38 28
      applications/rpc/rpc_storage.c
  3. 22 18
      applications/storage/storage_cli.c
  4. 4 0
      lib/toolbox/path.c

+ 17 - 0
.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.

+ 38 - 28
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(result) {
-                response->has_next = (size_left > 0);
-                rpc_send_and_release(session, response);
+            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;
+
+                *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(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);
+        }
 
-    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);
+        send_response = !request->has_next;
+    }
 
-        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);
-        }
+    PB_CommandStatus command_status = PB_CommandStatus_OK;
+    if(!fs_operation_success) {
+        send_response = true;
+        command_status = rpc_system_storage_get_file_error(file);
     }
 
-    if(!result) {
-        rpc_send_and_release_empty(
-            session, rpc_storage->current_command_id, 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);
     }
 }

+ 22 - 18
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);
+                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));
-            }
+                if(written_size != buffer_size) {
+                    storage_cli_print_error(storage_file_get_error(file));
+                }
 
-            free(buffer);
+                free(buffer);
+            }
         } else {
             storage_cli_print_error(storage_file_get_error(file));
         }

+ 4 - 0
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;