[FL-2831] Resources cleanup in updater (#1796)

* updater: remove files from existing resources Manifest file before deploying new resources
* toolbox: tar: single file extraction API

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
hedger
2022-09-28 21:13:12 +04:00
committed by GitHub
parent e25b424188
commit f8b532f063
9 changed files with 281 additions and 46 deletions

View File

@@ -0,0 +1,115 @@
#include "manifest.h"
#include <toolbox/stream/buffered_file_stream.h>
#include <toolbox/hex.h>
struct ResourceManifestReader {
Storage* storage;
Stream* stream;
string_t linebuf;
ResourceManifestEntry entry;
};
ResourceManifestReader* resource_manifest_reader_alloc(Storage* storage) {
ResourceManifestReader* resource_manifest =
(ResourceManifestReader*)malloc(sizeof(ResourceManifestReader));
resource_manifest->storage = storage;
resource_manifest->stream = buffered_file_stream_alloc(resource_manifest->storage);
memset(&resource_manifest->entry, 0, sizeof(ResourceManifestEntry));
string_init(resource_manifest->entry.name);
string_init(resource_manifest->linebuf);
return resource_manifest;
}
void resource_manifest_reader_free(ResourceManifestReader* resource_manifest) {
furi_assert(resource_manifest);
string_clear(resource_manifest->linebuf);
string_clear(resource_manifest->entry.name);
buffered_file_stream_close(resource_manifest->stream);
stream_free(resource_manifest->stream);
free(resource_manifest);
}
bool resource_manifest_reader_open(ResourceManifestReader* resource_manifest, const char* filename) {
furi_assert(resource_manifest);
return buffered_file_stream_open(
resource_manifest->stream, filename, FSAM_READ, FSOM_OPEN_EXISTING);
}
/* Read entries in format of
* F:<hash>:<size>:<name>
* D:<name>
*/
ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* resource_manifest) {
furi_assert(resource_manifest);
string_reset(resource_manifest->entry.name);
resource_manifest->entry.type = ResourceManifestEntryTypeUnknown;
resource_manifest->entry.size = 0;
memset(resource_manifest->entry.hash, 0, sizeof(resource_manifest->entry.hash));
do {
if(!stream_read_line(resource_manifest->stream, resource_manifest->linebuf)) {
return NULL;
}
/* Trim end of line */
string_strim(resource_manifest->linebuf);
char type_code = string_get_char(resource_manifest->linebuf, 0);
switch(type_code) {
case 'F':
resource_manifest->entry.type = ResourceManifestEntryTypeFile;
break;
case 'D':
resource_manifest->entry.type = ResourceManifestEntryTypeDirectory;
break;
default: /* Skip other entries - version, timestamp, etc */
continue;
};
if(resource_manifest->entry.type == ResourceManifestEntryTypeFile) {
/* Parse file entry
F:<hash>:<size>:<name> */
/* Remove entry type code */
string_right(resource_manifest->linebuf, 2);
if(string_search_char(resource_manifest->linebuf, ':') !=
sizeof(resource_manifest->entry.hash) * 2) {
/* Invalid hash */
continue;
}
/* Read hash */
hex_chars_to_uint8(
string_get_cstr(resource_manifest->linebuf), resource_manifest->entry.hash);
/* Remove hash */
string_right(
resource_manifest->linebuf, sizeof(resource_manifest->entry.hash) * 2 + 1);
resource_manifest->entry.size = atoi(string_get_cstr(resource_manifest->linebuf));
/* Remove size */
size_t offs = string_search_char(resource_manifest->linebuf, ':');
string_right(resource_manifest->linebuf, offs + 1);
string_set(resource_manifest->entry.name, resource_manifest->linebuf);
} else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) {
/* Parse directory entry
D:<name> */
/* Remove entry type code */
string_right(resource_manifest->linebuf, 2);
string_set(resource_manifest->entry.name, resource_manifest->linebuf);
}
return &resource_manifest->entry;
} while(true);
return NULL;
}

View File

@@ -0,0 +1,58 @@
#pragma once
#include <storage/storage.h>
#include <m-string.h>
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
ResourceManifestEntryTypeUnknown = 0,
ResourceManifestEntryTypeDirectory,
ResourceManifestEntryTypeFile,
} ResourceManifestEntryType;
typedef struct {
ResourceManifestEntryType type;
string_t name;
uint32_t size;
uint8_t hash[16];
} ResourceManifestEntry;
typedef struct ResourceManifestReader ResourceManifestReader;
/**
* @brief Initialize resource manifest reader
* @param storage Storage API pointer
* @return allocated object
*/
ResourceManifestReader* resource_manifest_reader_alloc(Storage* storage);
/**
* @brief Release resource manifest reader
* @param resource_manifest allocated object
*/
void resource_manifest_reader_free(ResourceManifestReader* resource_manifest);
/**
* @brief Initialize resource manifest reader iteration
* @param resource_manifest allocated object
* @param filename manifest file name
* @return true if file opened
*/
bool resource_manifest_reader_open(ResourceManifestReader* resource_manifest, const char* filename);
/**
* @brief Read next file/dir entry from manifest
* @param resource_manifest allocated object
* @return entry or NULL if end of file
*/
ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* resource_manifest);
#ifdef __cplusplus
} // extern "C"
#endif