Storage: unzip

This commit is contained in:
SG
2023-10-18 16:03:34 +03:00
parent e664159188
commit 14c0240411
6 changed files with 185 additions and 0 deletions
+3
View File
@@ -38,3 +38,6 @@
[submodule "lib/stm32wb_copro"]
path = lib/stm32wb_copro
url = https://github.com/flipperdevices/stm32wb_copro.git
[submodule "lib/uzlib"]
path = lib/uzlib
url = https://github.com/pfalcon/uzlib.git
+145
View File
@@ -445,6 +445,146 @@ static void storage_cli_remove(Cli* cli, FuriString* path) {
furi_record_close(RECORD_STORAGE);
}
#include <lib/uzlib/src/uzlib.h>
typedef struct {
File* file;
uint8_t* buffer;
size_t buffer_size;
uint8_t* dict;
size_t dict_size;
struct uzlib_uncomp uzlib;
bool eof;
} UnZipData;
typedef int (*UnizpDataReadCb)(struct uzlib_uncomp* uncomp);
UnZipData* unzip_data_alloc(size_t dict_size, size_t buffer_size, UnizpDataReadCb cb, File* file) {
UnZipData* data = malloc(sizeof(UnZipData));
data->file = file;
data->buffer_size = buffer_size;
data->buffer = malloc(buffer_size);
data->dict_size = dict_size;
data->dict = malloc(dict_size);
uzlib_uncompress_init(&data->uzlib, data->dict, data->dict_size);
data->uzlib.source = 0;
data->uzlib.source_limit = 0;
data->uzlib.source_read_cb = cb;
data->eof = false;
return data;
}
void unzip_data_free(UnZipData* uzlib) {
free(uzlib->buffer);
free(uzlib->dict);
free(uzlib);
}
int unzip_read_cb(struct uzlib_uncomp* uncomp) {
void* data_p = uncomp;
data_p -= offsetof(UnZipData, uzlib);
UnZipData* data = data_p;
uint16_t read_size = storage_file_read(data->file, data->buffer, data->buffer_size);
data->uzlib.source = &data->buffer[1]; // we will return buffer[0] at exit
data->uzlib.source_limit = data->buffer + read_size;
if(read_size == 0) {
return -1;
}
return data->buffer[0];
}
int32_t unzip_get_data(UnZipData* data, void* out, size_t out_len) {
if(data->eof) {
return 0;
}
data->uzlib.dest = out;
data->uzlib.dest_limit = (uint8_t*)out + out_len;
int status = uzlib_uncompress_chksum(&data->uzlib);
if(status == TINF_DONE) {
data->eof = true;
}
if(status < 0) {
return status;
}
return data->uzlib.dest - (uint8_t*)out;
}
#include <lib/toolbox/profiler.h>
static void storage_cli_unzip(Cli* cli, FuriString* path) {
UNUSED(cli);
UNUSED(path);
Storage* api = furi_record_open(RECORD_STORAGE);
File* in_file = storage_file_alloc(api);
File* out_file = storage_file_alloc(api);
UnZipData* data = unzip_data_alloc(32 * 1024, 10 * 1024, unzip_read_cb, in_file);
Profiler* profiler = profiler_alloc();
int res;
const size_t out_size = 10 * 1024;
uint8_t* out = malloc(out_size);
profiler_start(profiler, "unzip");
do {
if(!storage_file_open(in_file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) {
storage_cli_print_error(storage_file_get_error(in_file));
break;
}
if(!storage_file_open(out_file, "/ext/out.txt", FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
storage_cli_print_error(storage_file_get_error(out_file));
break;
}
res = uzlib_gzip_parse_header(&data->uzlib);
if(res != TINF_OK) {
printf("Error parsing header: %d\n", res);
break;
}
while(true) {
res = unzip_get_data(data, out, out_size);
if(res < 0) {
printf("Error during decompression: %d\n", res);
break;
}
if(res == 0) {
printf("End\n");
break;
}
uint16_t written_size = storage_file_write(out_file, out, res);
if(written_size != res) {
storage_cli_print_error(storage_file_get_error(out_file));
break;
}
}
} while(false);
profiler_stop(profiler, "unzip");
profiler_dump(profiler);
profiler_free(profiler);
storage_file_free(in_file);
storage_file_free(out_file);
unzip_data_free(data);
free(out);
furi_record_close(RECORD_STORAGE);
}
static void storage_cli_rename(Cli* cli, FuriString* old_path, FuriString* args) {
UNUSED(cli);
Storage* api = furi_record_open(RECORD_STORAGE);
@@ -566,6 +706,11 @@ void storage_cli(Cli* cli, FuriString* args, void* context) {
break;
}
if(furi_string_cmp_str(cmd, "unzip") == 0) {
storage_cli_unzip(cli, path);
break;
}
if(furi_string_cmp_str(cmd, "rename") == 0) {
storage_cli_rename(cli, path, args);
break;
+1
View File
@@ -29,6 +29,7 @@
"toolbox",
"nfc",
"digital_signal",
"uzlib",
"pulse_reader",
"microtar",
"usb_stm32",
+1
View File
@@ -102,6 +102,7 @@ libs = env.BuildModules(
"lfrfid",
"flipper_application",
"music_worker",
"uzlib",
],
)
Submodule
+1
Submodule lib/uzlib added at 6d60d651a4
+34
View File
@@ -0,0 +1,34 @@
Import("env")
env.Append(
# CPPPATH=[
# "#/lib/subghz",
# ],
# SDK_HEADERS=[
# File("environment.h"),
# ],
)
libenv = env.Clone(FW_LIB_NAME="uzlib")
libenv.ApplyLibFlags()
libenv.AppendUnique(
CCFLAGS=[
"-Wno-redundant-decls",
"-Wno-sign-compare",
],
)
sources = [
"uzlib/src/adler32.c",
"uzlib/src/crc32.c",
"uzlib/src/defl_static.c",
"uzlib/src/genlz77.c",
"uzlib/src/tinfgzip.c",
"uzlib/src/tinflate.c",
"uzlib/src/tinfzlib.c",
]
lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources)
libenv.Install("${LIB_DIST_DIR}", lib)
Return("lib")