saved_struct.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "saved_struct.h"
  2. #include <furi.h>
  3. #include <stdint.h>
  4. #include <storage/storage.h>
  5. #define TAG "SavedStruct"
  6. typedef struct {
  7. uint8_t magic;
  8. uint8_t version;
  9. uint8_t checksum;
  10. uint8_t flags;
  11. uint32_t timestamp;
  12. } SavedStructHeader;
  13. bool saved_struct_save(const char* path, void* data, size_t size, uint8_t magic, uint8_t version) {
  14. furi_assert(path);
  15. furi_assert(data);
  16. furi_assert(size);
  17. SavedStructHeader header;
  18. FURI_LOG_I(TAG, "Saving \"%s\"", path);
  19. // Store
  20. Storage* storage = furi_record_open(RECORD_STORAGE);
  21. File* file = storage_file_alloc(storage);
  22. bool result = true;
  23. bool saved = storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS);
  24. if(!saved) {
  25. FURI_LOG_E(
  26. TAG, "Open failed \"%s\". Error: \'%s\'", path, storage_file_get_error_desc(file));
  27. result = false;
  28. }
  29. if(result) {
  30. // Calculate checksum
  31. uint8_t checksum = 0;
  32. uint8_t* source = data;
  33. for(size_t i = 0; i < size; i++) {
  34. checksum += source[i];
  35. }
  36. // Set header
  37. header.magic = magic;
  38. header.version = version;
  39. header.checksum = checksum;
  40. header.flags = 0;
  41. header.timestamp = 0;
  42. uint16_t bytes_count = storage_file_write(file, &header, sizeof(header));
  43. bytes_count += storage_file_write(file, data, size);
  44. if(bytes_count != (size + sizeof(header))) {
  45. FURI_LOG_E(
  46. TAG, "Write failed \"%s\". Error: \'%s\'", path, storage_file_get_error_desc(file));
  47. result = false;
  48. }
  49. }
  50. storage_file_close(file);
  51. storage_file_free(file);
  52. furi_record_close(RECORD_STORAGE);
  53. return result;
  54. }
  55. bool saved_struct_load(const char* path, void* data, size_t size, uint8_t magic, uint8_t version) {
  56. FURI_LOG_I(TAG, "Loading \"%s\"", path);
  57. SavedStructHeader header;
  58. uint8_t* data_read = malloc(size);
  59. Storage* storage = furi_record_open(RECORD_STORAGE);
  60. File* file = storage_file_alloc(storage);
  61. bool result = true;
  62. bool loaded = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING);
  63. if(!loaded) {
  64. FURI_LOG_E(
  65. TAG, "Failed to read \"%s\". Error: %s", path, storage_file_get_error_desc(file));
  66. result = false;
  67. }
  68. if(result) {
  69. uint16_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader));
  70. bytes_count += storage_file_read(file, data_read, size);
  71. if(bytes_count != (sizeof(SavedStructHeader) + size)) {
  72. FURI_LOG_E(TAG, "Size mismatch of file \"%s\"", path);
  73. result = false;
  74. }
  75. }
  76. if(result && (header.magic != magic || header.version != version)) {
  77. FURI_LOG_E(
  78. TAG,
  79. "Magic(%d != %d) or Version(%d != %d) mismatch of file \"%s\"",
  80. header.magic,
  81. magic,
  82. header.version,
  83. version,
  84. path);
  85. result = false;
  86. }
  87. if(result) {
  88. uint8_t checksum = 0;
  89. const uint8_t* source = (const uint8_t*)data_read;
  90. for(size_t i = 0; i < size; i++) {
  91. checksum += source[i];
  92. }
  93. if(header.checksum != checksum) {
  94. FURI_LOG_E(
  95. TAG, "Checksum(%d != %d) mismatch of file \"%s\"", header.checksum, checksum, path);
  96. result = false;
  97. }
  98. }
  99. if(result) {
  100. memcpy(data, data_read, size);
  101. }
  102. storage_file_close(file);
  103. storage_file_free(file);
  104. furi_record_close(RECORD_STORAGE);
  105. free(data_read);
  106. return result;
  107. }
  108. bool saved_struct_get_payload_size(
  109. const char* path,
  110. uint8_t magic,
  111. uint8_t version,
  112. size_t* payload_size) {
  113. furi_assert(path);
  114. furi_assert(payload_size);
  115. SavedStructHeader header;
  116. Storage* storage = furi_record_open(RECORD_STORAGE);
  117. File* file = storage_file_alloc(storage);
  118. bool result = false;
  119. do {
  120. if(!storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
  121. FURI_LOG_E(
  122. TAG, "Failed to read \"%s\". Error: %s", path, storage_file_get_error_desc(file));
  123. break;
  124. }
  125. uint16_t bytes_count = storage_file_read(file, &header, sizeof(SavedStructHeader));
  126. if(bytes_count != sizeof(SavedStructHeader)) {
  127. FURI_LOG_E(TAG, "Failed to read header");
  128. break;
  129. }
  130. if((header.magic != magic) || (header.version != version)) {
  131. FURI_LOG_E(
  132. TAG,
  133. "Magic(%d != %d) or Version(%d != %d) mismatch of file \"%s\"",
  134. header.magic,
  135. magic,
  136. header.version,
  137. version,
  138. path);
  139. break;
  140. }
  141. uint64_t file_size = storage_file_size(file);
  142. *payload_size = file_size - sizeof(SavedStructHeader);
  143. result = true;
  144. } while(false);
  145. storage_file_close(file);
  146. storage_file_free(file);
  147. furi_record_close(RECORD_STORAGE);
  148. return result;
  149. }