mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2025-10-10 15:12:41 +02:00
RPC: Add TarExtract command, some small fixes (#3685)
* RPC: Add TarExtract command * Tar: Fix unpack when not at FS root * RPC: Add missing storage state resets * Fix dupe state reset * Bump pb submodule * Switch to latest protobuf release * RPC: cleanup excessive furi_record calls in rpc_storage Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
#include <lib/toolbox/md5_calc.h>
|
#include <lib/toolbox/md5_calc.h>
|
||||||
#include <lib/toolbox/path.h>
|
#include <lib/toolbox/path.h>
|
||||||
#include <update_util/lfs_backup.h>
|
#include <update_util/lfs_backup.h>
|
||||||
|
#include <toolbox/tar/tar_archive.h>
|
||||||
|
|
||||||
#include <pb_decode.h>
|
#include <pb_decode.h>
|
||||||
#include <storage.pb.h>
|
#include <storage.pb.h>
|
||||||
@@ -50,7 +51,6 @@ static void rpc_system_storage_reset_state(
|
|||||||
if(rpc_storage->state == RpcStorageStateWriting) {
|
if(rpc_storage->state == RpcStorageStateWriting) {
|
||||||
storage_file_close(rpc_storage->file);
|
storage_file_close(rpc_storage->file);
|
||||||
storage_file_free(rpc_storage->file);
|
storage_file_free(rpc_storage->file);
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpc_storage->state = RpcStorageStateIdle;
|
rpc_storage->state = RpcStorageStateIdle;
|
||||||
@@ -118,10 +118,8 @@ static void rpc_system_storage_info_process(const PB_Main* request, void* contex
|
|||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
PB_Main* response = malloc(sizeof(PB_Main));
|
||||||
response->command_id = request->command_id;
|
response->command_id = request->command_id;
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
|
|
||||||
FS_Error error = storage_common_fs_info(
|
FS_Error error = storage_common_fs_info(
|
||||||
fs_api,
|
rpc_storage->api,
|
||||||
request->content.storage_info_request.path,
|
request->content.storage_info_request.path,
|
||||||
&response->content.storage_info_response.total_space,
|
&response->content.storage_info_response.total_space,
|
||||||
&response->content.storage_info_response.free_space);
|
&response->content.storage_info_response.free_space);
|
||||||
@@ -135,7 +133,6 @@ static void rpc_system_storage_info_process(const PB_Main* request, void* contex
|
|||||||
|
|
||||||
rpc_send_and_release(session, response);
|
rpc_send_and_release(session, response);
|
||||||
free(response);
|
free(response);
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_timestamp_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_timestamp_process(const PB_Main* request, void* context) {
|
||||||
@@ -154,11 +151,9 @@ static void rpc_system_storage_timestamp_process(const PB_Main* request, void* c
|
|||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
PB_Main* response = malloc(sizeof(PB_Main));
|
||||||
response->command_id = request->command_id;
|
response->command_id = request->command_id;
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
|
|
||||||
const char* path = request->content.storage_timestamp_request.path;
|
const char* path = request->content.storage_timestamp_request.path;
|
||||||
uint32_t timestamp = 0;
|
uint32_t timestamp = 0;
|
||||||
FS_Error error = storage_common_timestamp(fs_api, path, ×tamp);
|
FS_Error error = storage_common_timestamp(rpc_storage->api, path, ×tamp);
|
||||||
|
|
||||||
response->command_status = rpc_system_storage_get_error(error);
|
response->command_status = rpc_system_storage_get_error(error);
|
||||||
response->which_content = PB_Main_empty_tag;
|
response->which_content = PB_Main_empty_tag;
|
||||||
@@ -170,7 +165,6 @@ static void rpc_system_storage_timestamp_process(const PB_Main* request, void* c
|
|||||||
|
|
||||||
rpc_send_and_release(session, response);
|
rpc_send_and_release(session, response);
|
||||||
free(response);
|
free(response);
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_stat_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_stat_process(const PB_Main* request, void* context) {
|
||||||
@@ -189,11 +183,9 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex
|
|||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
PB_Main* response = malloc(sizeof(PB_Main));
|
||||||
response->command_id = request->command_id;
|
response->command_id = request->command_id;
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
|
|
||||||
const char* path = request->content.storage_stat_request.path;
|
const char* path = request->content.storage_stat_request.path;
|
||||||
FileInfo fileinfo;
|
FileInfo fileinfo;
|
||||||
FS_Error error = storage_common_stat(fs_api, path, &fileinfo);
|
FS_Error error = storage_common_stat(rpc_storage->api, path, &fileinfo);
|
||||||
|
|
||||||
response->command_status = rpc_system_storage_get_error(error);
|
response->command_status = rpc_system_storage_get_error(error);
|
||||||
response->which_content = PB_Main_empty_tag;
|
response->which_content = PB_Main_empty_tag;
|
||||||
@@ -209,12 +201,12 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex
|
|||||||
|
|
||||||
rpc_send_and_release(session, response);
|
rpc_send_and_release(session, response);
|
||||||
free(response);
|
free(response);
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_list_root(const PB_Main* request, void* context) {
|
static void rpc_system_storage_list_root(const PB_Main* request, void* context) {
|
||||||
furi_assert(request);
|
furi_assert(request);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|
||||||
RpcStorageSystem* rpc_storage = context;
|
RpcStorageSystem* rpc_storage = context;
|
||||||
RpcSession* session = rpc_storage->session;
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
@@ -279,8 +271,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
File* dir = storage_file_alloc(rpc_storage->api);
|
||||||
File* dir = storage_file_alloc(fs_api);
|
|
||||||
|
|
||||||
PB_Main response = {
|
PB_Main response = {
|
||||||
.command_id = request->command_id,
|
.command_id = request->command_id,
|
||||||
@@ -293,7 +284,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
|||||||
bool include_md5 = list_request->include_md5;
|
bool include_md5 = list_request->include_md5;
|
||||||
FuriString* md5 = furi_string_alloc();
|
FuriString* md5 = furi_string_alloc();
|
||||||
FuriString* md5_path = furi_string_alloc();
|
FuriString* md5_path = furi_string_alloc();
|
||||||
File* file = storage_file_alloc(fs_api);
|
File* file = storage_file_alloc(rpc_storage->api);
|
||||||
|
|
||||||
bool finish = false;
|
bool finish = false;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -350,8 +341,6 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
|||||||
storage_dir_close(dir);
|
storage_dir_close(dir);
|
||||||
storage_file_free(dir);
|
storage_file_free(dir);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_read_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_read_process(const PB_Main* request, void* context) {
|
||||||
@@ -370,8 +359,7 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
|
|||||||
/* use same message memory to send response */
|
/* use same message memory to send response */
|
||||||
PB_Main* response = malloc(sizeof(PB_Main));
|
PB_Main* response = malloc(sizeof(PB_Main));
|
||||||
const char* path = request->content.storage_read_request.path;
|
const char* path = request->content.storage_read_request.path;
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
File* file = storage_file_alloc(rpc_storage->api);
|
||||||
File* file = storage_file_alloc(fs_api);
|
|
||||||
bool fs_operation_success = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
|
bool fs_operation_success = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
|
|
||||||
if(fs_operation_success) {
|
if(fs_operation_success) {
|
||||||
@@ -420,8 +408,6 @@ static void rpc_system_storage_read_process(const PB_Main* request, void* contex
|
|||||||
free(response);
|
free(response);
|
||||||
storage_file_close(file);
|
storage_file_close(file);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_write_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_write_process(const PB_Main* request, void* context) {
|
||||||
@@ -451,7 +437,6 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(rpc_storage->state != RpcStorageStateWriting) {
|
if(rpc_storage->state != RpcStorageStateWriting) {
|
||||||
rpc_storage->api = furi_record_open(RECORD_STORAGE);
|
|
||||||
rpc_storage->file = storage_file_alloc(rpc_storage->api);
|
rpc_storage->file = storage_file_alloc(rpc_storage->api);
|
||||||
rpc_storage->current_command_id = request->command_id;
|
rpc_storage->current_command_id = request->command_id;
|
||||||
rpc_storage->state = RpcStorageStateWriting;
|
rpc_storage->state = RpcStorageStateWriting;
|
||||||
@@ -492,14 +477,15 @@ static void rpc_system_storage_write_process(const PB_Main* request, void* conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rpc_system_storage_is_dir_is_empty(Storage* fs_api, const char* path) {
|
static bool rpc_system_storage_is_dir_is_empty(Storage* storage, const char* path) {
|
||||||
furi_assert(fs_api);
|
furi_assert(storage);
|
||||||
furi_assert(path);
|
furi_assert(path);
|
||||||
|
|
||||||
FileInfo fileinfo;
|
FileInfo fileinfo;
|
||||||
bool is_dir_is_empty = true;
|
bool is_dir_is_empty = true;
|
||||||
FS_Error error = storage_common_stat(fs_api, path, &fileinfo);
|
FS_Error error = storage_common_stat(storage, path, &fileinfo);
|
||||||
if((error == FSE_OK) && file_info_is_dir(&fileinfo)) {
|
if((error == FSE_OK) && file_info_is_dir(&fileinfo)) {
|
||||||
File* dir = storage_file_alloc(fs_api);
|
File* dir = storage_file_alloc(storage);
|
||||||
if(storage_dir_open(dir, path)) {
|
if(storage_dir_open(dir, path)) {
|
||||||
char* name = malloc(MAX_NAME_LENGTH);
|
char* name = malloc(MAX_NAME_LENGTH);
|
||||||
while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) {
|
while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) {
|
||||||
@@ -531,18 +517,17 @@ static void rpc_system_storage_delete_process(const PB_Main* request, void* cont
|
|||||||
PB_CommandStatus status = PB_CommandStatus_ERROR;
|
PB_CommandStatus status = PB_CommandStatus_ERROR;
|
||||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
|
|
||||||
char* path = request->content.storage_delete_request.path;
|
char* path = request->content.storage_delete_request.path;
|
||||||
if(!path) {
|
if(!path) {
|
||||||
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||||
} else {
|
} else {
|
||||||
FS_Error error_remove = storage_common_remove(fs_api, path);
|
FS_Error error_remove = storage_common_remove(rpc_storage->api, path);
|
||||||
// FSE_DENIED is for empty directory, but not only for this
|
// FSE_DENIED is for empty directory, but not only for this
|
||||||
// that's why we have to check it
|
// that's why we have to check it
|
||||||
if((error_remove == FSE_DENIED) && !rpc_system_storage_is_dir_is_empty(fs_api, path)) {
|
if((error_remove == FSE_DENIED) &&
|
||||||
|
!rpc_system_storage_is_dir_is_empty(rpc_storage->api, path)) {
|
||||||
if(request->content.storage_delete_request.recursive) {
|
if(request->content.storage_delete_request.recursive) {
|
||||||
bool deleted = storage_simply_remove_recursive(fs_api, path);
|
bool deleted = storage_simply_remove_recursive(rpc_storage->api, path);
|
||||||
status = deleted ? PB_CommandStatus_OK : PB_CommandStatus_ERROR;
|
status = deleted ? PB_CommandStatus_OK : PB_CommandStatus_ERROR;
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY;
|
status = PB_CommandStatus_ERROR_STORAGE_DIR_NOT_EMPTY;
|
||||||
@@ -554,7 +539,6 @@ static void rpc_system_storage_delete_process(const PB_Main* request, void* cont
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,11 +556,10 @@ static void rpc_system_storage_mkdir_process(const PB_Main* request, void* conte
|
|||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
char* path = request->content.storage_mkdir_request.path;
|
char* path = request->content.storage_mkdir_request.path;
|
||||||
if(path) {
|
if(path) {
|
||||||
if(path_contains_only_ascii(path)) {
|
if(path_contains_only_ascii(path)) {
|
||||||
FS_Error error = storage_common_mkdir(fs_api, path);
|
FS_Error error = storage_common_mkdir(rpc_storage->api, path);
|
||||||
status = rpc_system_storage_get_error(error);
|
status = rpc_system_storage_get_error(error);
|
||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||||
@@ -584,7 +567,6 @@ static void rpc_system_storage_mkdir_process(const PB_Main* request, void* conte
|
|||||||
} else {
|
} else {
|
||||||
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
status = PB_CommandStatus_ERROR_INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,8 +590,7 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
File* file = storage_file_alloc(rpc_storage->api);
|
||||||
File* file = storage_file_alloc(fs_api);
|
|
||||||
FuriString* md5 = furi_string_alloc();
|
FuriString* md5 = furi_string_alloc();
|
||||||
FS_Error file_error;
|
FS_Error file_error;
|
||||||
|
|
||||||
@@ -633,8 +614,6 @@ static void rpc_system_storage_md5sum_process(const PB_Main* request, void* cont
|
|||||||
|
|
||||||
furi_string_free(md5);
|
furi_string_free(md5);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_system_storage_rename_process(const PB_Main* request, void* context) {
|
static void rpc_system_storage_rename_process(const PB_Main* request, void* context) {
|
||||||
@@ -651,11 +630,9 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont
|
|||||||
PB_CommandStatus status;
|
PB_CommandStatus status;
|
||||||
rpc_system_storage_reset_state(rpc_storage, session, true);
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
|
||||||
|
|
||||||
if(path_contains_only_ascii(request->content.storage_rename_request.new_path)) {
|
if(path_contains_only_ascii(request->content.storage_rename_request.new_path)) {
|
||||||
FS_Error error = storage_common_rename(
|
FS_Error error = storage_common_rename(
|
||||||
fs_api,
|
rpc_storage->api,
|
||||||
request->content.storage_rename_request.old_path,
|
request->content.storage_rename_request.old_path,
|
||||||
request->content.storage_rename_request.new_path);
|
request->content.storage_rename_request.new_path);
|
||||||
status = rpc_system_storage_get_error(error);
|
status = rpc_system_storage_get_error(error);
|
||||||
@@ -663,7 +640,6 @@ static void rpc_system_storage_rename_process(const PB_Main* request, void* cont
|
|||||||
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
rpc_send_and_release_empty(session, request->command_id, status);
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -678,12 +654,10 @@ static void rpc_system_storage_backup_create_process(const PB_Main* request, voi
|
|||||||
RpcSession* session = rpc_storage->session;
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
bool backup_ok =
|
bool backup_ok = lfs_backup_create(
|
||||||
lfs_backup_create(fs_api, request->content.storage_backup_create_request.archive_path);
|
rpc_storage->api, request->content.storage_backup_create_request.archive_path);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
|
|
||||||
rpc_send_and_release_empty(
|
rpc_send_and_release_empty(
|
||||||
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||||
@@ -700,17 +674,58 @@ static void rpc_system_storage_backup_restore_process(const PB_Main* request, vo
|
|||||||
RpcSession* session = rpc_storage->session;
|
RpcSession* session = rpc_storage->session;
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
bool backup_ok =
|
bool backup_ok = lfs_backup_unpack(
|
||||||
lfs_backup_unpack(fs_api, request->content.storage_backup_restore_request.archive_path);
|
rpc_storage->api, request->content.storage_backup_restore_request.archive_path);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
|
|
||||||
rpc_send_and_release_empty(
|
rpc_send_and_release_empty(
|
||||||
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
session, request->command_id, backup_ok ? PB_CommandStatus_OK : PB_CommandStatus_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rpc_system_storage_tar_extract_process(const PB_Main* request, void* context) {
|
||||||
|
furi_assert(request);
|
||||||
|
furi_assert(request->which_content == PB_Main_storage_tar_extract_request_tag);
|
||||||
|
furi_assert(context);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "TarExtract");
|
||||||
|
|
||||||
|
RpcStorageSystem* rpc_storage = context;
|
||||||
|
RpcSession* session = rpc_storage->session;
|
||||||
|
furi_assert(session);
|
||||||
|
|
||||||
|
PB_CommandStatus status;
|
||||||
|
rpc_system_storage_reset_state(rpc_storage, session, true);
|
||||||
|
|
||||||
|
TarArchive* archive = tar_archive_alloc(rpc_storage->api);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!path_contains_only_ascii(request->content.storage_tar_extract_request.out_path)) {
|
||||||
|
status = PB_CommandStatus_ERROR_STORAGE_INVALID_NAME;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tar_archive_open(
|
||||||
|
archive,
|
||||||
|
request->content.storage_tar_extract_request.tar_path,
|
||||||
|
TAR_OPEN_MODE_READ)) {
|
||||||
|
status = PB_CommandStatus_ERROR_STORAGE_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tar_archive_unpack_to(
|
||||||
|
archive, request->content.storage_tar_extract_request.out_path, NULL)) {
|
||||||
|
status = PB_CommandStatus_ERROR_STORAGE_INTERNAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = PB_CommandStatus_OK;
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
tar_archive_free(archive);
|
||||||
|
rpc_send_and_release_empty(session, request->command_id, status);
|
||||||
|
}
|
||||||
|
|
||||||
void* rpc_system_storage_alloc(RpcSession* session) {
|
void* rpc_system_storage_alloc(RpcSession* session) {
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
@@ -761,6 +776,9 @@ void* rpc_system_storage_alloc(RpcSession* session) {
|
|||||||
rpc_handler.message_handler = rpc_system_storage_backup_restore_process;
|
rpc_handler.message_handler = rpc_system_storage_backup_restore_process;
|
||||||
rpc_add_handler(session, PB_Main_storage_backup_restore_request_tag, &rpc_handler);
|
rpc_add_handler(session, PB_Main_storage_backup_restore_request_tag, &rpc_handler);
|
||||||
|
|
||||||
|
rpc_handler.message_handler = rpc_system_storage_tar_extract_process;
|
||||||
|
rpc_add_handler(session, PB_Main_storage_tar_extract_request_tag, &rpc_handler);
|
||||||
|
|
||||||
return rpc_storage;
|
return rpc_storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,5 +789,8 @@ void rpc_system_storage_free(void* context) {
|
|||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
|
|
||||||
rpc_system_storage_reset_state(rpc_storage, session, false);
|
rpc_system_storage_reset_state(rpc_storage, session, false);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
rpc_storage->api = NULL;
|
||||||
free(rpc_storage);
|
free(rpc_storage);
|
||||||
}
|
}
|
||||||
|
Submodule assets/protobuf updated: 1956b83bba...816de200a4
@@ -224,6 +224,11 @@ static int archive_extract_foreach_cb(mtar_t* tar, const mtar_header_t* header,
|
|||||||
|
|
||||||
FuriString* full_extracted_fname;
|
FuriString* full_extracted_fname;
|
||||||
if(header->type == MTAR_TDIR) {
|
if(header->type == MTAR_TDIR) {
|
||||||
|
// Skip "/" entry since concat would leave it dangling, also want caller to mkdir destination
|
||||||
|
if(strcmp(header->name, "/") == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
full_extracted_fname = furi_string_alloc();
|
full_extracted_fname = furi_string_alloc();
|
||||||
path_concat(op_params->work_dir, header->name, full_extracted_fname);
|
path_concat(op_params->work_dir, header->name, full_extracted_fname);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user