manifest.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #include "manifest.h"
  2. #include <toolbox/stream/buffered_file_stream.h>
  3. #include <toolbox/hex.h>
  4. struct ResourceManifestReader {
  5. Storage* storage;
  6. Stream* stream;
  7. FuriString* linebuf;
  8. ResourceManifestEntry entry;
  9. };
  10. ResourceManifestReader* resource_manifest_reader_alloc(Storage* storage) {
  11. ResourceManifestReader* resource_manifest =
  12. (ResourceManifestReader*)malloc(sizeof(ResourceManifestReader));
  13. resource_manifest->storage = storage;
  14. resource_manifest->stream = buffered_file_stream_alloc(resource_manifest->storage);
  15. memset(&resource_manifest->entry, 0, sizeof(ResourceManifestEntry));
  16. resource_manifest->entry.name = furi_string_alloc();
  17. resource_manifest->linebuf = furi_string_alloc();
  18. return resource_manifest;
  19. }
  20. void resource_manifest_reader_free(ResourceManifestReader* resource_manifest) {
  21. furi_assert(resource_manifest);
  22. furi_string_free(resource_manifest->linebuf);
  23. furi_string_free(resource_manifest->entry.name);
  24. buffered_file_stream_close(resource_manifest->stream);
  25. stream_free(resource_manifest->stream);
  26. free(resource_manifest);
  27. }
  28. bool resource_manifest_reader_open(ResourceManifestReader* resource_manifest, const char* filename) {
  29. furi_assert(resource_manifest);
  30. return buffered_file_stream_open(
  31. resource_manifest->stream, filename, FSAM_READ, FSOM_OPEN_EXISTING);
  32. }
  33. /* Read entries in format of
  34. * F:<hash>:<size>:<name>
  35. * D:<name>
  36. */
  37. ResourceManifestEntry* resource_manifest_reader_next(ResourceManifestReader* resource_manifest) {
  38. furi_assert(resource_manifest);
  39. furi_string_reset(resource_manifest->entry.name);
  40. resource_manifest->entry.type = ResourceManifestEntryTypeUnknown;
  41. resource_manifest->entry.size = 0;
  42. memset(resource_manifest->entry.hash, 0, sizeof(resource_manifest->entry.hash));
  43. do {
  44. if(!stream_read_line(resource_manifest->stream, resource_manifest->linebuf)) {
  45. return NULL;
  46. }
  47. /* Trim end of line */
  48. furi_string_trim(resource_manifest->linebuf);
  49. char type_code = furi_string_get_char(resource_manifest->linebuf, 0);
  50. switch(type_code) {
  51. case 'F':
  52. resource_manifest->entry.type = ResourceManifestEntryTypeFile;
  53. break;
  54. case 'D':
  55. resource_manifest->entry.type = ResourceManifestEntryTypeDirectory;
  56. break;
  57. default: /* Skip other entries - version, timestamp, etc */
  58. continue;
  59. };
  60. if(resource_manifest->entry.type == ResourceManifestEntryTypeFile) {
  61. /* Parse file entry
  62. F:<hash>:<size>:<name> */
  63. /* Remove entry type code */
  64. furi_string_right(resource_manifest->linebuf, 2);
  65. if(furi_string_search_char(resource_manifest->linebuf, ':') !=
  66. sizeof(resource_manifest->entry.hash) * 2) {
  67. /* Invalid hash */
  68. continue;
  69. }
  70. /* Read hash */
  71. hex_chars_to_uint8(
  72. furi_string_get_cstr(resource_manifest->linebuf), resource_manifest->entry.hash);
  73. /* Remove hash */
  74. furi_string_right(
  75. resource_manifest->linebuf, sizeof(resource_manifest->entry.hash) * 2 + 1);
  76. resource_manifest->entry.size = atoi(furi_string_get_cstr(resource_manifest->linebuf));
  77. /* Remove size */
  78. size_t offs = furi_string_search_char(resource_manifest->linebuf, ':');
  79. furi_string_right(resource_manifest->linebuf, offs + 1);
  80. furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf);
  81. } else if(resource_manifest->entry.type == ResourceManifestEntryTypeDirectory) {
  82. /* Parse directory entry
  83. D:<name> */
  84. /* Remove entry type code */
  85. furi_string_right(resource_manifest->linebuf, 2);
  86. furi_string_set(resource_manifest->entry.name, resource_manifest->linebuf);
  87. }
  88. return &resource_manifest->entry;
  89. } while(true);
  90. return NULL;
  91. }