Skip to content

Commit 1d50a59

Browse files
hedgerDrZlo13skotopes
authored
[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>
1 parent 01eb92d commit 1d50a59

File tree

4 files changed

+81
-46
lines changed

4 files changed

+81
-46
lines changed

.vscode/ReadMe.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Visual Studio Code workspace for Flipper Zero
2+
3+
## Setup
4+
5+
* To start developing with VSCode, run `./fbt vscode_dist` in project root. _That should only be done once_
6+
* After that, open firmware folder in VSCode: "File" > "Open folder"
7+
8+
For more details on fbt, see [fbt docs](../documentation/fbt.md).
9+
10+
11+
## Workflow
12+
13+
Commands for building firmware are invoked through Build menu: Ctrl+Shift+B.
14+
15+
To attach a debugging session, first build and flash firmware, then choose your debug probe in Debug menu (Ctrl+Shift+D).
16+
17+
Note that you have to detach debugging session before rebuilding and re-flashing firmware.

applications/rpc/rpc_storage.c

+38-28
Original file line numberDiff line numberDiff line change
@@ -305,21 +305,27 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
305305
response->command_id = request->command_id;
306306
response->which_content = PB_Main_storage_read_response_tag;
307307
response->command_status = PB_CommandStatus_OK;
308-
response->content.storage_read_response.has_file = true;
309-
response->content.storage_read_response.file.data =
310-
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(MIN(size_left, MAX_DATA_SIZE)));
311-
uint8_t* buffer = response->content.storage_read_response.file.data->bytes;
312-
uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size;
313308

314309
size_t read_size = MIN(size_left, MAX_DATA_SIZE);
315-
*read_size_msg = storage_file_read(file, buffer, read_size);
316-
size_left -= read_size;
317-
result = (*read_size_msg == read_size);
318-
319-
if(result) {
320-
response->has_next = (size_left > 0);
321-
rpc_send_and_release(session, response);
310+
if(read_size) {
311+
response->content.storage_read_response.has_file = true;
312+
response->content.storage_read_response.file.data =
313+
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE());
314+
uint8_t* buffer = response->content.storage_read_response.file.data->bytes;
315+
uint16_t* read_size_msg = &response->content.storage_read_response.file.data->size;
316+
317+
*read_size_msg = storage_file_read(file, buffer, read_size);
318+
size_left -= read_size;
319+
result = (*read_size_msg == read_size);
320+
321+
response->has_next = result && (size_left > 0);
322+
} else {
323+
response->content.storage_read_response.has_file = false;
324+
response->has_next = false;
325+
result = true;
322326
}
327+
328+
rpc_send_and_release(session, response);
323329
} while((size_left != 0) && result);
324330

325331
if(!result) {
@@ -349,7 +355,7 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
349355
RpcSession* session = rpc_storage->session;
350356
furi_assert(session);
351357

352-
bool result = true;
358+
bool fs_operation_success = true;
353359

354360
if(!path_contains_only_ascii(request->content.storage_write_request.path)) {
355361
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
370376
rpc_storage->current_command_id = request->command_id;
371377
rpc_storage->state = RpcStorageStateWriting;
372378
const char* path = request->content.storage_write_request.path;
373-
result = storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
379+
fs_operation_success =
380+
storage_file_open(rpc_storage->file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
374381
}
375382

376383
File* file = rpc_storage->file;
384+
bool send_response = false;
385+
386+
if(fs_operation_success) {
387+
if(request->content.storage_write_request.has_file) {
388+
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
389+
size_t buffer_size = request->content.storage_write_request.file.data->size;
390+
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
391+
fs_operation_success = (written_size == buffer_size);
392+
}
377393

378-
if(result) {
379-
uint8_t* buffer = request->content.storage_write_request.file.data->bytes;
380-
size_t buffer_size = request->content.storage_write_request.file.data->size;
381-
382-
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
383-
result = (written_size == buffer_size);
394+
send_response = !request->has_next;
395+
}
384396

385-
if(result && !request->has_next) {
386-
rpc_send_and_release_empty(
387-
session, rpc_storage->current_command_id, PB_CommandStatus_OK);
388-
rpc_system_storage_reset_state(rpc_storage, session, false);
389-
}
397+
PB_CommandStatus command_status = PB_CommandStatus_OK;
398+
if(!fs_operation_success) {
399+
send_response = true;
400+
command_status = rpc_system_storage_get_file_error(file);
390401
}
391402

392-
if(!result) {
393-
rpc_send_and_release_empty(
394-
session, rpc_storage->current_command_id, rpc_system_storage_get_file_error(file));
403+
if(send_response) {
404+
rpc_send_and_release_empty(session, rpc_storage->current_command_id, command_status);
395405
rpc_system_storage_reset_state(rpc_storage, session, false);
396406
}
397407
}

applications/storage/storage_cli.c

+22-18
Original file line numberDiff line numberDiff line change
@@ -274,24 +274,26 @@ static void storage_cli_read_chunks(Cli* cli, string_t path, string_t args) {
274274
if(parsed_count == EOF || parsed_count != 1) {
275275
storage_cli_print_usage();
276276
} else if(storage_file_open(file, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
277-
uint8_t* data = malloc(buffer_size);
278277
uint64_t file_size = storage_file_size(file);
279278

280279
printf("Size: %lu\r\n", (uint32_t)file_size);
281280

282-
while(file_size > 0) {
283-
printf("\r\nReady?\r\n");
284-
cli_getc(cli);
281+
if(buffer_size) {
282+
uint8_t* data = malloc(buffer_size);
283+
while(file_size > 0) {
284+
printf("\r\nReady?\r\n");
285+
cli_getc(cli);
285286

286-
uint16_t read_size = storage_file_read(file, data, buffer_size);
287-
for(uint16_t i = 0; i < read_size; i++) {
288-
putchar(data[i]);
287+
uint16_t read_size = storage_file_read(file, data, buffer_size);
288+
for(uint16_t i = 0; i < read_size; i++) {
289+
putchar(data[i]);
290+
}
291+
file_size -= read_size;
289292
}
290-
file_size -= read_size;
293+
free(data);
291294
}
292295
printf("\r\n");
293296

294-
free(data);
295297
} else {
296298
storage_cli_print_error(storage_file_get_error(file));
297299
}
@@ -315,19 +317,21 @@ static void storage_cli_write_chunk(Cli* cli, string_t path, string_t args) {
315317
if(storage_file_open(file, string_get_cstr(path), FSAM_WRITE, FSOM_OPEN_APPEND)) {
316318
printf("Ready\r\n");
317319

318-
uint8_t* buffer = malloc(buffer_size);
320+
if(buffer_size) {
321+
uint8_t* buffer = malloc(buffer_size);
319322

320-
for(uint32_t i = 0; i < buffer_size; i++) {
321-
buffer[i] = cli_getc(cli);
322-
}
323+
for(uint32_t i = 0; i < buffer_size; i++) {
324+
buffer[i] = cli_getc(cli);
325+
}
323326

324-
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
327+
uint16_t written_size = storage_file_write(file, buffer, buffer_size);
325328

326-
if(written_size != buffer_size) {
327-
storage_cli_print_error(storage_file_get_error(file));
328-
}
329+
if(written_size != buffer_size) {
330+
storage_cli_print_error(storage_file_get_error(file));
331+
}
329332

330-
free(buffer);
333+
free(buffer);
334+
}
331335
} else {
332336
storage_cli_print_error(storage_file_get_error(file));
333337
}

lib/toolbox/path.c

+4
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ void path_concat(const char* path, const char* suffix, string_t out_path) {
8585
}
8686

8787
bool path_contains_only_ascii(const char* path) {
88+
if(!path) {
89+
return false;
90+
}
91+
8892
const char* name_pos = strrchr(path, '/');
8993
if(name_pos == NULL) {
9094
name_pos = path;

0 commit comments

Comments
 (0)