Filesystem library designed for flash devices

Dependents:   flash-fs-example Dragonfly_Filesystem_Example STM32F407VET6_SPIFlash Dragonfly_Filesystem_Example_mbed_5

Committer:
Leon Lindenfelser
Date:
Fri Jun 26 14:21:17 2020 -0500
Revision:
4:7a3c79b0d570
Parent:
2:de478b250060
Update to latest from Multitech git repo

1. Change "errno" to "err_code" to address ARM compiler errors
2. Feature: add move file support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mfiore 0:bb4e812f7c97 1 #include "spiffs.h"
mfiore 0:bb4e812f7c97 2 #include "spiffs_nucleus.h"
mfiore 0:bb4e812f7c97 3
mfiore 0:bb4e812f7c97 4 static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
mfiore 0:bb4e812f7c97 5 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 6 if (pix == (spiffs_page_ix)-1) {
mfiore 0:bb4e812f7c97 7 // referring to page 0xffff...., bad object index
mfiore 0:bb4e812f7c97 8 return SPIFFS_ERR_INDEX_REF_FREE;
mfiore 0:bb4e812f7c97 9 }
mfiore 0:bb4e812f7c97 10 if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
mfiore 0:bb4e812f7c97 11 // referring to an object lookup page, bad object index
mfiore 0:bb4e812f7c97 12 return SPIFFS_ERR_INDEX_REF_LU;
mfiore 0:bb4e812f7c97 13 }
mfiore 0:bb4e812f7c97 14 if (pix > SPIFFS_MAX_PAGES(fs)) {
mfiore 0:bb4e812f7c97 15 // referring to a bad page
mfiore 0:bb4e812f7c97 16 return SPIFFS_ERR_INDEX_REF_INVALID;
mfiore 0:bb4e812f7c97 17 }
mfiore 0:bb4e812f7c97 18 #if SPIFFS_PAGE_CHECK
mfiore 0:bb4e812f7c97 19 spiffs_page_header ph;
mfiore 0:bb4e812f7c97 20 res = _spiffs_rd(
mfiore 0:bb4e812f7c97 21 fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 22 fd->file_nbr,
mfiore 0:bb4e812f7c97 23 SPIFFS_PAGE_TO_PADDR(fs, pix),
mfiore 0:bb4e812f7c97 24 sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 25 (u8_t *)&ph);
mfiore 0:bb4e812f7c97 26 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 27 SPIFFS_VALIDATE_DATA(ph, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, spix);
mfiore 0:bb4e812f7c97 28 #endif
mfiore 0:bb4e812f7c97 29 return res;
mfiore 0:bb4e812f7c97 30 }
mfiore 0:bb4e812f7c97 31
mfiore 0:bb4e812f7c97 32 static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
mfiore 0:bb4e812f7c97 33 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 34 if (pix == (spiffs_page_ix)-1) {
mfiore 0:bb4e812f7c97 35 // referring to page 0xffff...., bad object index
mfiore 0:bb4e812f7c97 36 return SPIFFS_ERR_INDEX_FREE;
mfiore 0:bb4e812f7c97 37 }
mfiore 0:bb4e812f7c97 38 if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
mfiore 0:bb4e812f7c97 39 // referring to an object lookup page, bad object index
mfiore 0:bb4e812f7c97 40 return SPIFFS_ERR_INDEX_LU;
mfiore 0:bb4e812f7c97 41 }
mfiore 0:bb4e812f7c97 42 if (pix > SPIFFS_MAX_PAGES(fs)) {
mfiore 0:bb4e812f7c97 43 // referring to a bad page
mfiore 0:bb4e812f7c97 44 return SPIFFS_ERR_INDEX_INVALID;
mfiore 0:bb4e812f7c97 45 }
mfiore 0:bb4e812f7c97 46 #if SPIFFS_PAGE_CHECK
mfiore 0:bb4e812f7c97 47 spiffs_page_header ph;
mfiore 0:bb4e812f7c97 48 res = _spiffs_rd(
mfiore 0:bb4e812f7c97 49 fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 50 fd->file_nbr,
mfiore 0:bb4e812f7c97 51 SPIFFS_PAGE_TO_PADDR(fs, pix),
mfiore 0:bb4e812f7c97 52 sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 53 (u8_t *)&ph);
mfiore 0:bb4e812f7c97 54 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 55 SPIFFS_VALIDATE_OBJIX(ph, fd->obj_id, spix);
mfiore 0:bb4e812f7c97 56 #endif
mfiore 0:bb4e812f7c97 57 return res;
mfiore 0:bb4e812f7c97 58 }
mfiore 0:bb4e812f7c97 59
mfiore 0:bb4e812f7c97 60 #if !SPIFFS_CACHE
mfiore 0:bb4e812f7c97 61
mfiore 0:bb4e812f7c97 62 s32_t spiffs_phys_rd(
mfiore 0:bb4e812f7c97 63 spiffs *fs,
mfiore 0:bb4e812f7c97 64 u32_t addr,
mfiore 0:bb4e812f7c97 65 u32_t len,
mfiore 0:bb4e812f7c97 66 u8_t *dst) {
mfiore 0:bb4e812f7c97 67 return fs->cfg.hal_read_f(addr, len, dst);
mfiore 0:bb4e812f7c97 68 }
mfiore 0:bb4e812f7c97 69
mfiore 0:bb4e812f7c97 70 s32_t spiffs_phys_wr(
mfiore 0:bb4e812f7c97 71 spiffs *fs,
mfiore 0:bb4e812f7c97 72 u32_t addr,
mfiore 0:bb4e812f7c97 73 u32_t len,
mfiore 0:bb4e812f7c97 74 u8_t *src) {
mfiore 0:bb4e812f7c97 75 return fs->cfg.hal_write_f(addr, len, src);
mfiore 0:bb4e812f7c97 76 }
mfiore 0:bb4e812f7c97 77
mfiore 0:bb4e812f7c97 78 #endif
mfiore 0:bb4e812f7c97 79
mfiore 0:bb4e812f7c97 80 s32_t spiffs_phys_cpy(
mfiore 0:bb4e812f7c97 81 spiffs *fs,
mfiore 0:bb4e812f7c97 82 spiffs_file fh,
mfiore 0:bb4e812f7c97 83 u32_t dst,
mfiore 0:bb4e812f7c97 84 u32_t src,
mfiore 0:bb4e812f7c97 85 u32_t len) {
mfiore 0:bb4e812f7c97 86 s32_t res;
mfiore 0:bb4e812f7c97 87 u8_t b[SPIFFS_COPY_BUFFER_STACK];
mfiore 0:bb4e812f7c97 88 while (len > 0) {
mfiore 0:bb4e812f7c97 89 u32_t chunk_size = MIN(SPIFFS_COPY_BUFFER_STACK, len);
mfiore 0:bb4e812f7c97 90 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVS, fh, src, chunk_size, b);
mfiore 0:bb4e812f7c97 91 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 92 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVD, fh, dst, chunk_size, b);
mfiore 0:bb4e812f7c97 93 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 94 len -= chunk_size;
mfiore 0:bb4e812f7c97 95 src += chunk_size;
mfiore 0:bb4e812f7c97 96 dst += chunk_size;
mfiore 0:bb4e812f7c97 97 }
mfiore 0:bb4e812f7c97 98 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 99 }
mfiore 0:bb4e812f7c97 100
mfiore 0:bb4e812f7c97 101 // Find object lookup entry containing given id with visitor.
mfiore 0:bb4e812f7c97 102 // Iterate over object lookup pages in each block until a given object id entry is found.
mfiore 0:bb4e812f7c97 103 // When found, the visitor function is called with block index, entry index and user_data.
mfiore 0:bb4e812f7c97 104 // If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be
mfiore 0:bb4e812f7c97 105 // ended and visitor's return code is returned to caller.
mfiore 0:bb4e812f7c97 106 // If no visitor is given (0) the search returns on first entry with matching object id.
mfiore 0:bb4e812f7c97 107 // If no match is found in all look up, SPIFFS_VIS_END is returned.
mfiore 0:bb4e812f7c97 108 // @param fs the file system
mfiore 0:bb4e812f7c97 109 // @param starting_block the starting block to start search in
mfiore 0:bb4e812f7c97 110 // @param starting_lu_entry the look up index entry to start search in
mfiore 0:bb4e812f7c97 111 // @param flags ored combination of SPIFFS_VIS_CHECK_ID, SPIFFS_VIS_CHECK_PH,
mfiore 0:bb4e812f7c97 112 // SPIFFS_VIS_NO_WRAP
mfiore 0:bb4e812f7c97 113 // @param obj_id argument object id
mfiore 0:bb4e812f7c97 114 // @param v visitor callback function
mfiore 0:bb4e812f7c97 115 // @param user_data any data, passed to the callback visitor function
mfiore 0:bb4e812f7c97 116 // @param user_p any pointer, passed to the callback visitor function
mfiore 0:bb4e812f7c97 117 // @param block_ix reported block index where match was found
mfiore 0:bb4e812f7c97 118 // @param lu_entry reported look up index where match was found
mfiore 0:bb4e812f7c97 119 s32_t spiffs_obj_lu_find_entry_visitor(
mfiore 0:bb4e812f7c97 120 spiffs *fs,
mfiore 0:bb4e812f7c97 121 spiffs_block_ix starting_block,
mfiore 0:bb4e812f7c97 122 int starting_lu_entry,
mfiore 0:bb4e812f7c97 123 u8_t flags,
mfiore 0:bb4e812f7c97 124 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 125 spiffs_visitor_f v,
mfiore 0:bb4e812f7c97 126 u32_t user_data,
mfiore 0:bb4e812f7c97 127 void *user_p,
mfiore 0:bb4e812f7c97 128 spiffs_block_ix *block_ix,
mfiore 0:bb4e812f7c97 129 int *lu_entry) {
mfiore 0:bb4e812f7c97 130 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 131 s32_t entry_count = fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs);
mfiore 0:bb4e812f7c97 132 spiffs_block_ix cur_block = starting_block;
mfiore 0:bb4e812f7c97 133 u32_t cur_block_addr = starting_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
mfiore 0:bb4e812f7c97 134
mfiore 0:bb4e812f7c97 135 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
mfiore 0:bb4e812f7c97 136 int cur_entry = starting_lu_entry;
mfiore 0:bb4e812f7c97 137 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
mfiore 0:bb4e812f7c97 138
mfiore 0:bb4e812f7c97 139 // wrap initial
mfiore 0:bb4e812f7c97 140 if (cur_entry >= SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) - 1) {
mfiore 0:bb4e812f7c97 141 cur_entry = 0;
mfiore 0:bb4e812f7c97 142 cur_block++;
mfiore 0:bb4e812f7c97 143 cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
mfiore 0:bb4e812f7c97 144 if (cur_block >= fs->block_count) {
mfiore 0:bb4e812f7c97 145 // block wrap
mfiore 0:bb4e812f7c97 146 cur_block = 0;
mfiore 0:bb4e812f7c97 147 cur_block_addr = 0;
mfiore 0:bb4e812f7c97 148 }
mfiore 0:bb4e812f7c97 149 }
mfiore 0:bb4e812f7c97 150
mfiore 0:bb4e812f7c97 151 // check each block
mfiore 0:bb4e812f7c97 152 while (res == SPIFFS_OK && entry_count > 0) {
mfiore 0:bb4e812f7c97 153 int obj_lookup_page = cur_entry / entries_per_page;
mfiore 0:bb4e812f7c97 154 // check each object lookup page
mfiore 0:bb4e812f7c97 155 while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
mfiore 0:bb4e812f7c97 156 int entry_offset = obj_lookup_page * entries_per_page;
mfiore 0:bb4e812f7c97 157 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 158 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
mfiore 0:bb4e812f7c97 159 // check each entry
mfiore 0:bb4e812f7c97 160 while (res == SPIFFS_OK &&
mfiore 0:bb4e812f7c97 161 cur_entry - entry_offset < entries_per_page && // for non-last obj lookup pages
mfiore 0:bb4e812f7c97 162 cur_entry < SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) // for last obj lookup page
mfiore 0:bb4e812f7c97 163 {
mfiore 0:bb4e812f7c97 164 if ((flags & SPIFFS_VIS_CHECK_ID) == 0 || obj_lu_buf[cur_entry-entry_offset] == obj_id) {
mfiore 0:bb4e812f7c97 165 if (block_ix) *block_ix = cur_block;
mfiore 0:bb4e812f7c97 166 if (lu_entry) *lu_entry = cur_entry;
mfiore 0:bb4e812f7c97 167 if (v) {
mfiore 0:bb4e812f7c97 168 res = v(
mfiore 0:bb4e812f7c97 169 fs,
mfiore 0:bb4e812f7c97 170 (flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry-entry_offset],
mfiore 0:bb4e812f7c97 171 cur_block,
mfiore 0:bb4e812f7c97 172 cur_entry,
mfiore 0:bb4e812f7c97 173 user_data,
mfiore 0:bb4e812f7c97 174 user_p);
mfiore 0:bb4e812f7c97 175 if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
mfiore 0:bb4e812f7c97 176 if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
mfiore 0:bb4e812f7c97 177 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 178 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
mfiore 0:bb4e812f7c97 179 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 180 }
mfiore 0:bb4e812f7c97 181 res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 182 cur_entry++;
mfiore 0:bb4e812f7c97 183 entry_count--;
mfiore 0:bb4e812f7c97 184 continue;
mfiore 0:bb4e812f7c97 185 } else {
mfiore 0:bb4e812f7c97 186 return res;
mfiore 0:bb4e812f7c97 187 }
mfiore 0:bb4e812f7c97 188 } else {
mfiore 0:bb4e812f7c97 189 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 190 }
mfiore 0:bb4e812f7c97 191 }
mfiore 0:bb4e812f7c97 192 entry_count--;
mfiore 0:bb4e812f7c97 193 cur_entry++;
mfiore 0:bb4e812f7c97 194 } // per entry
mfiore 0:bb4e812f7c97 195 obj_lookup_page++;
mfiore 0:bb4e812f7c97 196 } // per object lookup page
mfiore 0:bb4e812f7c97 197 cur_entry = 0;
mfiore 0:bb4e812f7c97 198 cur_block++;
mfiore 0:bb4e812f7c97 199 cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
mfiore 0:bb4e812f7c97 200 if (cur_block >= fs->block_count) {
mfiore 0:bb4e812f7c97 201 if (flags & SPIFFS_VIS_NO_WRAP) {
mfiore 0:bb4e812f7c97 202 return SPIFFS_VIS_END;
mfiore 0:bb4e812f7c97 203 } else {
mfiore 0:bb4e812f7c97 204 // block wrap
mfiore 0:bb4e812f7c97 205 cur_block = 0;
mfiore 0:bb4e812f7c97 206 cur_block_addr = 0;
mfiore 0:bb4e812f7c97 207 }
mfiore 0:bb4e812f7c97 208 }
mfiore 0:bb4e812f7c97 209 } // per block
mfiore 0:bb4e812f7c97 210
mfiore 0:bb4e812f7c97 211 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 212
mfiore 0:bb4e812f7c97 213 return SPIFFS_VIS_END;
mfiore 0:bb4e812f7c97 214 }
mfiore 0:bb4e812f7c97 215
mfiore 0:bb4e812f7c97 216
mfiore 0:bb4e812f7c97 217 static s32_t spiffs_obj_lu_scan_v(
mfiore 0:bb4e812f7c97 218 spiffs *fs,
mfiore 0:bb4e812f7c97 219 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 220 spiffs_block_ix bix,
mfiore 0:bb4e812f7c97 221 int ix_entry,
mfiore 0:bb4e812f7c97 222 u32_t user_data,
mfiore 0:bb4e812f7c97 223 void *user_p) {
mfiore 0:bb4e812f7c97 224 if (obj_id == SPIFFS_OBJ_ID_FREE) {
mfiore 0:bb4e812f7c97 225 if (ix_entry == 0) {
mfiore 0:bb4e812f7c97 226 fs->free_blocks++;
mfiore 0:bb4e812f7c97 227 // todo optimize further, return SPIFFS_NEXT_BLOCK
mfiore 0:bb4e812f7c97 228 }
mfiore 0:bb4e812f7c97 229 } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
mfiore 0:bb4e812f7c97 230 fs->stats_p_deleted++;
mfiore 0:bb4e812f7c97 231 } else {
mfiore 0:bb4e812f7c97 232 fs->stats_p_allocated++;
mfiore 0:bb4e812f7c97 233 }
mfiore 0:bb4e812f7c97 234
mfiore 0:bb4e812f7c97 235 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 236 }
mfiore 0:bb4e812f7c97 237
mfiore 0:bb4e812f7c97 238 // Scans thru all obj lu and counts free, deleted and used pages
mfiore 0:bb4e812f7c97 239 // Find the maximum block erase count
mfiore 0:bb4e812f7c97 240 s32_t spiffs_obj_lu_scan(
mfiore 0:bb4e812f7c97 241 spiffs *fs) {
mfiore 0:bb4e812f7c97 242 s32_t res;
mfiore 0:bb4e812f7c97 243 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 244 int entry;
mfiore 0:bb4e812f7c97 245
mfiore 0:bb4e812f7c97 246 fs->free_blocks = 0;
mfiore 0:bb4e812f7c97 247 fs->stats_p_allocated = 0;
mfiore 0:bb4e812f7c97 248 fs->stats_p_deleted = 0;
mfiore 0:bb4e812f7c97 249
mfiore 0:bb4e812f7c97 250 res = spiffs_obj_lu_find_entry_visitor(fs,
mfiore 0:bb4e812f7c97 251 0,
mfiore 0:bb4e812f7c97 252 0,
mfiore 0:bb4e812f7c97 253 0,
mfiore 0:bb4e812f7c97 254 0,
mfiore 0:bb4e812f7c97 255 spiffs_obj_lu_scan_v,
mfiore 0:bb4e812f7c97 256 0,
mfiore 0:bb4e812f7c97 257 0,
mfiore 0:bb4e812f7c97 258 &bix,
mfiore 0:bb4e812f7c97 259 &entry);
mfiore 0:bb4e812f7c97 260
mfiore 0:bb4e812f7c97 261 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 262 res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 263 }
mfiore 0:bb4e812f7c97 264
mfiore 0:bb4e812f7c97 265 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 266
mfiore 0:bb4e812f7c97 267 bix = 0;
mfiore 0:bb4e812f7c97 268 spiffs_obj_id erase_count_final;
mfiore 0:bb4e812f7c97 269 spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
mfiore 0:bb4e812f7c97 270 spiffs_obj_id erase_count_max = 0;
mfiore 0:bb4e812f7c97 271 while (bix < fs->block_count) {
mfiore 0:bb4e812f7c97 272 spiffs_obj_id erase_count;
mfiore 0:bb4e812f7c97 273 res = _spiffs_rd(fs,
mfiore 0:bb4e812f7c97 274 SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 275 0, SPIFFS_ERASE_COUNT_PADDR(fs, bix) ,
mfiore 0:bb4e812f7c97 276 sizeof(spiffs_obj_id), (u8_t *)&erase_count);
mfiore 0:bb4e812f7c97 277 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 278 if (erase_count != SPIFFS_OBJ_ID_FREE) {
mfiore 0:bb4e812f7c97 279 erase_count_min = MIN(erase_count_min, erase_count);
mfiore 0:bb4e812f7c97 280 erase_count_max = MAX(erase_count_max, erase_count);
mfiore 0:bb4e812f7c97 281 }
mfiore 0:bb4e812f7c97 282 bix++;
mfiore 0:bb4e812f7c97 283 }
mfiore 0:bb4e812f7c97 284
mfiore 0:bb4e812f7c97 285 if (erase_count_min == 0 && erase_count_max == SPIFFS_OBJ_ID_FREE) {
mfiore 0:bb4e812f7c97 286 // clean system, set counter to zero
mfiore 0:bb4e812f7c97 287 erase_count_final = 0;
mfiore 0:bb4e812f7c97 288 } else if (erase_count_max - erase_count_min > (SPIFFS_OBJ_ID_FREE)/2) {
mfiore 0:bb4e812f7c97 289 // wrap, take min
mfiore 0:bb4e812f7c97 290 erase_count_final = erase_count_min+1;
mfiore 0:bb4e812f7c97 291 } else {
mfiore 0:bb4e812f7c97 292 erase_count_final = erase_count_max+1;
mfiore 0:bb4e812f7c97 293 }
mfiore 0:bb4e812f7c97 294
mfiore 0:bb4e812f7c97 295 fs->max_erase_count = erase_count_final;
mfiore 0:bb4e812f7c97 296
mfiore 0:bb4e812f7c97 297 return res;
mfiore 0:bb4e812f7c97 298 }
mfiore 0:bb4e812f7c97 299
mfiore 0:bb4e812f7c97 300 // Find free object lookup entry
mfiore 0:bb4e812f7c97 301 // Iterate over object lookup pages in each block until a free object id entry is found
mfiore 0:bb4e812f7c97 302 s32_t spiffs_obj_lu_find_free(
mfiore 0:bb4e812f7c97 303 spiffs *fs,
mfiore 0:bb4e812f7c97 304 spiffs_block_ix starting_block,
mfiore 0:bb4e812f7c97 305 int starting_lu_entry,
mfiore 0:bb4e812f7c97 306 spiffs_block_ix *block_ix,
mfiore 0:bb4e812f7c97 307 int *lu_entry) {
mfiore 0:bb4e812f7c97 308 s32_t res;
mfiore 0:bb4e812f7c97 309 if (!fs->cleaning && fs->free_blocks < 2) {
mfiore 0:bb4e812f7c97 310 res = spiffs_gc_quick(fs);
mfiore 0:bb4e812f7c97 311 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 312 if (fs->free_blocks < 2) {
mfiore 0:bb4e812f7c97 313 return SPIFFS_ERR_FULL;
mfiore 0:bb4e812f7c97 314 }
mfiore 0:bb4e812f7c97 315 }
mfiore 0:bb4e812f7c97 316 res = spiffs_obj_lu_find_id(fs, starting_block, starting_lu_entry,
mfiore 0:bb4e812f7c97 317 SPIFFS_OBJ_ID_FREE, block_ix, lu_entry);
mfiore 0:bb4e812f7c97 318 if (res == SPIFFS_OK) {
mfiore 0:bb4e812f7c97 319 fs->free_cursor_block_ix = *block_ix;
mfiore 0:bb4e812f7c97 320 fs->free_cursor_obj_lu_entry = *lu_entry;
mfiore 0:bb4e812f7c97 321 if (*lu_entry == 0) {
mfiore 0:bb4e812f7c97 322 fs->free_blocks--;
mfiore 0:bb4e812f7c97 323 }
mfiore 0:bb4e812f7c97 324 }
mfiore 0:bb4e812f7c97 325 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 326 SPIFFS_DBG("fs full\n");
mfiore 0:bb4e812f7c97 327 }
mfiore 0:bb4e812f7c97 328
mfiore 0:bb4e812f7c97 329 return res == SPIFFS_VIS_END ? SPIFFS_ERR_FULL : res;
mfiore 0:bb4e812f7c97 330 }
mfiore 0:bb4e812f7c97 331
mfiore 0:bb4e812f7c97 332 // Find object lookup entry containing given id
mfiore 0:bb4e812f7c97 333 // Iterate over object lookup pages in each block until a given object id entry is found
mfiore 0:bb4e812f7c97 334 s32_t spiffs_obj_lu_find_id(
mfiore 0:bb4e812f7c97 335 spiffs *fs,
mfiore 0:bb4e812f7c97 336 spiffs_block_ix starting_block,
mfiore 0:bb4e812f7c97 337 int starting_lu_entry,
mfiore 0:bb4e812f7c97 338 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 339 spiffs_block_ix *block_ix,
mfiore 0:bb4e812f7c97 340 int *lu_entry) {
mfiore 0:bb4e812f7c97 341 s32_t res = spiffs_obj_lu_find_entry_visitor(
mfiore 0:bb4e812f7c97 342 fs, starting_block, starting_lu_entry, SPIFFS_VIS_CHECK_ID, obj_id, 0, 0, 0, block_ix, lu_entry);
mfiore 0:bb4e812f7c97 343 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 344 res = SPIFFS_ERR_NOT_FOUND;
mfiore 0:bb4e812f7c97 345 }
mfiore 0:bb4e812f7c97 346 return res;
mfiore 0:bb4e812f7c97 347 }
mfiore 0:bb4e812f7c97 348
mfiore 0:bb4e812f7c97 349
mfiore 0:bb4e812f7c97 350 static s32_t spiffs_obj_lu_find_id_and_span_v(
mfiore 0:bb4e812f7c97 351 spiffs *fs,
mfiore 0:bb4e812f7c97 352 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 353 spiffs_block_ix bix,
mfiore 0:bb4e812f7c97 354 int ix_entry,
mfiore 0:bb4e812f7c97 355 u32_t user_data,
mfiore 0:bb4e812f7c97 356 void *user_p) {
mfiore 0:bb4e812f7c97 357 s32_t res;
mfiore 0:bb4e812f7c97 358 spiffs_page_header ph;
mfiore 0:bb4e812f7c97 359 spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
mfiore 0:bb4e812f7c97 360 res = _spiffs_rd(fs, 0, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 361 SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
mfiore 0:bb4e812f7c97 362 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 363 if (ph.obj_id == obj_id &&
mfiore 0:bb4e812f7c97 364 ph.span_ix == (spiffs_span_ix)user_data &&
mfiore 0:bb4e812f7c97 365 (ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET &&
mfiore 0:bb4e812f7c97 366 !((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) &&
mfiore 0:bb4e812f7c97 367 (user_p == 0 || *((spiffs_page_ix *)user_p) != pix)) {
mfiore 0:bb4e812f7c97 368 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 369 } else {
mfiore 0:bb4e812f7c97 370 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 371 }
mfiore 0:bb4e812f7c97 372 }
mfiore 0:bb4e812f7c97 373
mfiore 0:bb4e812f7c97 374 // Find object lookup entry containing given id and span index
mfiore 0:bb4e812f7c97 375 // Iterate over object lookup pages in each block until a given object id entry is found
mfiore 0:bb4e812f7c97 376 s32_t spiffs_obj_lu_find_id_and_span(
mfiore 0:bb4e812f7c97 377 spiffs *fs,
mfiore 0:bb4e812f7c97 378 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 379 spiffs_span_ix spix,
mfiore 0:bb4e812f7c97 380 spiffs_page_ix exclusion_pix,
mfiore 0:bb4e812f7c97 381 spiffs_page_ix *pix) {
mfiore 0:bb4e812f7c97 382 s32_t res;
mfiore 0:bb4e812f7c97 383 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 384 int entry;
mfiore 0:bb4e812f7c97 385
mfiore 0:bb4e812f7c97 386 res = spiffs_obj_lu_find_entry_visitor(fs,
mfiore 0:bb4e812f7c97 387 fs->cursor_block_ix,
mfiore 0:bb4e812f7c97 388 fs->cursor_obj_lu_entry,
mfiore 0:bb4e812f7c97 389 SPIFFS_VIS_CHECK_ID,
mfiore 0:bb4e812f7c97 390 obj_id,
mfiore 0:bb4e812f7c97 391 spiffs_obj_lu_find_id_and_span_v,
mfiore 0:bb4e812f7c97 392 (u32_t)spix,
mfiore 0:bb4e812f7c97 393 exclusion_pix ? &exclusion_pix : 0,
mfiore 0:bb4e812f7c97 394 &bix,
mfiore 0:bb4e812f7c97 395 &entry);
mfiore 0:bb4e812f7c97 396
mfiore 0:bb4e812f7c97 397 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 398 res = SPIFFS_ERR_NOT_FOUND;
mfiore 0:bb4e812f7c97 399 }
mfiore 0:bb4e812f7c97 400
mfiore 0:bb4e812f7c97 401 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 402
mfiore 0:bb4e812f7c97 403 if (pix) {
mfiore 0:bb4e812f7c97 404 *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 405 }
mfiore 0:bb4e812f7c97 406
mfiore 0:bb4e812f7c97 407 fs->cursor_block_ix = bix;
mfiore 0:bb4e812f7c97 408 fs->cursor_obj_lu_entry = entry;
mfiore 0:bb4e812f7c97 409
mfiore 0:bb4e812f7c97 410 return res;
mfiore 0:bb4e812f7c97 411 }
mfiore 0:bb4e812f7c97 412
mfiore 0:bb4e812f7c97 413 // Find object lookup entry containing given id and span index in page headers only
mfiore 0:bb4e812f7c97 414 // Iterate over object lookup pages in each block until a given object id entry is found
mfiore 0:bb4e812f7c97 415 s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
mfiore 0:bb4e812f7c97 416 spiffs *fs,
mfiore 0:bb4e812f7c97 417 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 418 spiffs_span_ix spix,
mfiore 0:bb4e812f7c97 419 spiffs_page_ix exclusion_pix,
mfiore 0:bb4e812f7c97 420 spiffs_page_ix *pix) {
mfiore 0:bb4e812f7c97 421 s32_t res;
mfiore 0:bb4e812f7c97 422 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 423 int entry;
mfiore 0:bb4e812f7c97 424
mfiore 0:bb4e812f7c97 425 res = spiffs_obj_lu_find_entry_visitor(fs,
mfiore 0:bb4e812f7c97 426 fs->cursor_block_ix,
mfiore 0:bb4e812f7c97 427 fs->cursor_obj_lu_entry,
mfiore 0:bb4e812f7c97 428 SPIFFS_VIS_CHECK_PH,
mfiore 0:bb4e812f7c97 429 obj_id,
mfiore 0:bb4e812f7c97 430 spiffs_obj_lu_find_id_and_span_v,
mfiore 0:bb4e812f7c97 431 (u32_t)spix,
mfiore 0:bb4e812f7c97 432 exclusion_pix ? &exclusion_pix : 0,
mfiore 0:bb4e812f7c97 433 &bix,
mfiore 0:bb4e812f7c97 434 &entry);
mfiore 0:bb4e812f7c97 435
mfiore 0:bb4e812f7c97 436 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 437 res = SPIFFS_ERR_NOT_FOUND;
mfiore 0:bb4e812f7c97 438 }
mfiore 0:bb4e812f7c97 439
mfiore 0:bb4e812f7c97 440 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 441
mfiore 0:bb4e812f7c97 442 if (pix) {
mfiore 0:bb4e812f7c97 443 *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 444 }
mfiore 0:bb4e812f7c97 445
mfiore 0:bb4e812f7c97 446 fs->cursor_block_ix = bix;
mfiore 0:bb4e812f7c97 447 fs->cursor_obj_lu_entry = entry;
mfiore 0:bb4e812f7c97 448
mfiore 0:bb4e812f7c97 449 return res;
mfiore 0:bb4e812f7c97 450 }
mfiore 0:bb4e812f7c97 451
mfiore 0:bb4e812f7c97 452 // Allocates a free defined page with given obj_id
mfiore 0:bb4e812f7c97 453 // Occupies object lookup entry and page
mfiore 0:bb4e812f7c97 454 // data may be NULL; where only page header is stored, len and page_offs is ignored
mfiore 0:bb4e812f7c97 455 s32_t spiffs_page_allocate_data(
mfiore 0:bb4e812f7c97 456 spiffs *fs,
mfiore 0:bb4e812f7c97 457 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 458 spiffs_page_header *ph,
mfiore 0:bb4e812f7c97 459 u8_t *data,
mfiore 0:bb4e812f7c97 460 u32_t len,
mfiore 0:bb4e812f7c97 461 u32_t page_offs,
mfiore 0:bb4e812f7c97 462 u8_t finalize,
mfiore 0:bb4e812f7c97 463 spiffs_page_ix *pix) {
mfiore 0:bb4e812f7c97 464 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 465 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 466 int entry;
mfiore 0:bb4e812f7c97 467
mfiore 0:bb4e812f7c97 468 // find free entry
mfiore 0:bb4e812f7c97 469 res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
mfiore 0:bb4e812f7c97 470 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 471
mfiore 0:bb4e812f7c97 472 // occupy page in object lookup
mfiore 0:bb4e812f7c97 473 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 474 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&obj_id);
mfiore 0:bb4e812f7c97 475 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 476
mfiore 0:bb4e812f7c97 477 fs->stats_p_allocated++;
mfiore 0:bb4e812f7c97 478
mfiore 0:bb4e812f7c97 479 // write page header
mfiore 0:bb4e812f7c97 480 ph->flags &= ~SPIFFS_PH_FLAG_USED;
mfiore 0:bb4e812f7c97 481 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 482 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_header), (u8_t*)ph);
mfiore 0:bb4e812f7c97 483 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 484
mfiore 0:bb4e812f7c97 485 // write page data
mfiore 0:bb4e812f7c97 486 if (data) {
mfiore 0:bb4e812f7c97 487 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 488 0,SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + sizeof(spiffs_page_header) + page_offs, len, data);
mfiore 0:bb4e812f7c97 489 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 490 }
mfiore 0:bb4e812f7c97 491
mfiore 0:bb4e812f7c97 492 // finalize header if necessary
mfiore 0:bb4e812f7c97 493 if (finalize && (ph->flags & SPIFFS_PH_FLAG_FINAL)) {
mfiore 0:bb4e812f7c97 494 ph->flags &= ~SPIFFS_PH_FLAG_FINAL;
mfiore 0:bb4e812f7c97 495 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 496 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 497 sizeof(u8_t),
mfiore 0:bb4e812f7c97 498 (u8_t *)&ph->flags);
mfiore 0:bb4e812f7c97 499 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 500 }
mfiore 0:bb4e812f7c97 501
mfiore 0:bb4e812f7c97 502 // return written page
mfiore 0:bb4e812f7c97 503 if (pix) {
mfiore 0:bb4e812f7c97 504 *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 505 }
mfiore 0:bb4e812f7c97 506
mfiore 0:bb4e812f7c97 507 return res;
mfiore 0:bb4e812f7c97 508 }
mfiore 0:bb4e812f7c97 509
mfiore 0:bb4e812f7c97 510 // Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page.
mfiore 0:bb4e812f7c97 511 // If page data is null, provided header is used for metainfo and page data is physically copied.
mfiore 0:bb4e812f7c97 512 s32_t spiffs_page_move(
mfiore 0:bb4e812f7c97 513 spiffs *fs,
mfiore 0:bb4e812f7c97 514 spiffs_file fh,
mfiore 0:bb4e812f7c97 515 u8_t *page_data,
mfiore 0:bb4e812f7c97 516 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 517 spiffs_page_header *page_hdr,
mfiore 0:bb4e812f7c97 518 spiffs_page_ix src_pix,
mfiore 0:bb4e812f7c97 519 spiffs_page_ix *dst_pix) {
mfiore 0:bb4e812f7c97 520 s32_t res;
mfiore 0:bb4e812f7c97 521 u8_t was_final = 0;
mfiore 0:bb4e812f7c97 522 spiffs_page_header *p_hdr;
mfiore 0:bb4e812f7c97 523 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 524 int entry;
mfiore 0:bb4e812f7c97 525 spiffs_page_ix free_pix;
mfiore 0:bb4e812f7c97 526
mfiore 0:bb4e812f7c97 527 // find free entry
mfiore 0:bb4e812f7c97 528 res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
mfiore 0:bb4e812f7c97 529 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 530 free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 531
mfiore 0:bb4e812f7c97 532 if (dst_pix) *dst_pix = free_pix;
mfiore 0:bb4e812f7c97 533
mfiore 0:bb4e812f7c97 534 p_hdr = page_data ? (spiffs_page_header *)page_data : page_hdr;
mfiore 0:bb4e812f7c97 535 if (page_data) {
mfiore 0:bb4e812f7c97 536 // got page data
mfiore 0:bb4e812f7c97 537 was_final = (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) == 0;
mfiore 0:bb4e812f7c97 538 // write unfinalized page
mfiore 0:bb4e812f7c97 539 p_hdr->flags |= SPIFFS_PH_FLAG_FINAL;
mfiore 0:bb4e812f7c97 540 p_hdr->flags &= ~SPIFFS_PH_FLAG_USED;
mfiore 0:bb4e812f7c97 541 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 542 0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), page_data);
mfiore 0:bb4e812f7c97 543 } else {
mfiore 0:bb4e812f7c97 544 // copy page data
mfiore 0:bb4e812f7c97 545 res = spiffs_phys_cpy(fs, fh, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_PAGE_TO_PADDR(fs, src_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 546 }
mfiore 0:bb4e812f7c97 547 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 548
mfiore 0:bb4e812f7c97 549 // mark entry in destination object lookup
mfiore 0:bb4e812f7c97 550 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 551 0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix),
mfiore 0:bb4e812f7c97 552 sizeof(spiffs_obj_id),
mfiore 0:bb4e812f7c97 553 (u8_t *)&obj_id);
mfiore 0:bb4e812f7c97 554 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 555
mfiore 0:bb4e812f7c97 556 fs->stats_p_allocated++;
mfiore 0:bb4e812f7c97 557
mfiore 0:bb4e812f7c97 558 if (was_final) {
mfiore 0:bb4e812f7c97 559 // mark finalized in destination page
mfiore 0:bb4e812f7c97 560 p_hdr->flags &= ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_USED);
mfiore 0:bb4e812f7c97 561 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 562 fh,
mfiore 0:bb4e812f7c97 563 SPIFFS_PAGE_TO_PADDR(fs, free_pix) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 564 sizeof(u8_t),
mfiore 0:bb4e812f7c97 565 (u8_t *)&p_hdr->flags);
mfiore 0:bb4e812f7c97 566 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 567 }
mfiore 0:bb4e812f7c97 568 // mark source deleted
mfiore 0:bb4e812f7c97 569 res = spiffs_page_delete(fs, src_pix);
mfiore 0:bb4e812f7c97 570 return res;
mfiore 0:bb4e812f7c97 571 }
mfiore 0:bb4e812f7c97 572
mfiore 0:bb4e812f7c97 573 // Deletes a page and removes it from object lookup.
mfiore 0:bb4e812f7c97 574 s32_t spiffs_page_delete(
mfiore 0:bb4e812f7c97 575 spiffs *fs,
mfiore 0:bb4e812f7c97 576 spiffs_page_ix pix) {
mfiore 0:bb4e812f7c97 577 s32_t res;
mfiore 0:bb4e812f7c97 578 spiffs_page_header hdr;
mfiore 0:bb4e812f7c97 579 hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED);
mfiore 0:bb4e812f7c97 580 // mark deleted entry in source object lookup
mfiore 0:bb4e812f7c97 581 spiffs_obj_id d_obj_id = SPIFFS_OBJ_ID_DELETED;
mfiore 0:bb4e812f7c97 582 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_DELE,
mfiore 0:bb4e812f7c97 583 0,
mfiore 0:bb4e812f7c97 584 SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_page_ix),
mfiore 0:bb4e812f7c97 585 sizeof(spiffs_obj_id),
mfiore 0:bb4e812f7c97 586 (u8_t *)&d_obj_id);
mfiore 0:bb4e812f7c97 587 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 588
mfiore 0:bb4e812f7c97 589 fs->stats_p_deleted++;
mfiore 0:bb4e812f7c97 590 fs->stats_p_allocated--;
mfiore 0:bb4e812f7c97 591
mfiore 0:bb4e812f7c97 592 // mark deleted in source page
mfiore 0:bb4e812f7c97 593 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_DELE,
mfiore 0:bb4e812f7c97 594 0,
mfiore 0:bb4e812f7c97 595 SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 596 sizeof(u8_t),
mfiore 0:bb4e812f7c97 597 (u8_t *)&hdr.flags);
mfiore 0:bb4e812f7c97 598
mfiore 0:bb4e812f7c97 599 return res;
mfiore 0:bb4e812f7c97 600 }
mfiore 0:bb4e812f7c97 601
mfiore 0:bb4e812f7c97 602 // Create an object index header page with empty index and undefined length
mfiore 0:bb4e812f7c97 603 s32_t spiffs_object_create(
mfiore 0:bb4e812f7c97 604 spiffs *fs,
mfiore 0:bb4e812f7c97 605 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 606 u8_t name[SPIFFS_OBJ_NAME_LEN],
mfiore 0:bb4e812f7c97 607 spiffs_obj_type type,
mfiore 0:bb4e812f7c97 608 spiffs_page_ix *objix_hdr_pix) {
mfiore 0:bb4e812f7c97 609 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 610 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 611 spiffs_page_object_ix_header oix_hdr;
mfiore 0:bb4e812f7c97 612 int entry;
mfiore 0:bb4e812f7c97 613
mfiore 0:bb4e812f7c97 614 res = spiffs_gc_check(fs, 0);
mfiore 0:bb4e812f7c97 615 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 616
mfiore 0:bb4e812f7c97 617 obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 618
mfiore 0:bb4e812f7c97 619 // find free entry
mfiore 0:bb4e812f7c97 620 res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
mfiore 0:bb4e812f7c97 621 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 622 SPIFFS_DBG("create: found free page @ %04x bix:%i entry:%i\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
mfiore 0:bb4e812f7c97 623
mfiore 0:bb4e812f7c97 624 // occupy page in object lookup
mfiore 0:bb4e812f7c97 625 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 626 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&obj_id);
mfiore 0:bb4e812f7c97 627 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 628
mfiore 0:bb4e812f7c97 629 fs->stats_p_allocated++;
mfiore 0:bb4e812f7c97 630
mfiore 0:bb4e812f7c97 631 // write empty object index page
mfiore 0:bb4e812f7c97 632 oix_hdr.p_hdr.obj_id = obj_id;
mfiore 0:bb4e812f7c97 633 oix_hdr.p_hdr.span_ix = 0;
mfiore 0:bb4e812f7c97 634 oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED);
mfiore 0:bb4e812f7c97 635 oix_hdr.type = type;
mfiore 0:bb4e812f7c97 636 oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page
mfiore 0:bb4e812f7c97 637 strncpy((char *)&oix_hdr.name, (char *)name, SPIFFS_OBJ_NAME_LEN);
mfiore 0:bb4e812f7c97 638
mfiore 0:bb4e812f7c97 639
mfiore 0:bb4e812f7c97 640 // update page
mfiore 0:bb4e812f7c97 641 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 642 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_object_ix_header), (u8_t*)&oix_hdr);
mfiore 0:bb4e812f7c97 643
mfiore 0:bb4e812f7c97 644 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 645 spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_NEW, obj_id, 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), SPIFFS_UNDEFINED_LEN);
mfiore 0:bb4e812f7c97 646
mfiore 0:bb4e812f7c97 647 if (objix_hdr_pix) {
mfiore 0:bb4e812f7c97 648 *objix_hdr_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 649 }
mfiore 0:bb4e812f7c97 650
mfiore 0:bb4e812f7c97 651 return res;
mfiore 0:bb4e812f7c97 652 }
mfiore 0:bb4e812f7c97 653
mfiore 0:bb4e812f7c97 654 // update object index header with any combination of name/size/index
mfiore 0:bb4e812f7c97 655 // new_objix_hdr_data may be null, if so the object index header page is loaded
mfiore 0:bb4e812f7c97 656 // name may be null, if so name is not changed
mfiore 0:bb4e812f7c97 657 // size may be null, if so size is not changed
mfiore 0:bb4e812f7c97 658 s32_t spiffs_object_update_index_hdr(
mfiore 0:bb4e812f7c97 659 spiffs *fs,
mfiore 0:bb4e812f7c97 660 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 661 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 662 spiffs_page_ix objix_hdr_pix,
mfiore 0:bb4e812f7c97 663 u8_t *new_objix_hdr_data,
mfiore 0:bb4e812f7c97 664 u8_t name[SPIFFS_OBJ_NAME_LEN],
mfiore 0:bb4e812f7c97 665 u32_t size,
mfiore 0:bb4e812f7c97 666 spiffs_page_ix *new_pix) {
mfiore 0:bb4e812f7c97 667 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 668 spiffs_page_object_ix_header *objix_hdr;
mfiore 0:bb4e812f7c97 669 spiffs_page_ix new_objix_hdr_pix;
mfiore 0:bb4e812f7c97 670
mfiore 0:bb4e812f7c97 671 obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 672
mfiore 0:bb4e812f7c97 673 if (new_objix_hdr_data) {
mfiore 0:bb4e812f7c97 674 // object index header page already given to us, no need to load it
mfiore 0:bb4e812f7c97 675 objix_hdr = (spiffs_page_object_ix_header *)new_objix_hdr_data;
mfiore 0:bb4e812f7c97 676 } else {
mfiore 0:bb4e812f7c97 677 // read object index header page
mfiore 0:bb4e812f7c97 678 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 679 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 680 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 681 objix_hdr = (spiffs_page_object_ix_header *)fs->work;
mfiore 0:bb4e812f7c97 682 }
mfiore 0:bb4e812f7c97 683
mfiore 0:bb4e812f7c97 684 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, obj_id, 0);
mfiore 0:bb4e812f7c97 685
mfiore 0:bb4e812f7c97 686 // change name
mfiore 0:bb4e812f7c97 687 if (name) {
mfiore 0:bb4e812f7c97 688 strncpy((char *)objix_hdr->name, (char *)name, SPIFFS_OBJ_NAME_LEN);
mfiore 0:bb4e812f7c97 689 }
mfiore 0:bb4e812f7c97 690 if (size) {
mfiore 0:bb4e812f7c97 691 objix_hdr->size = size;
mfiore 0:bb4e812f7c97 692 }
mfiore 0:bb4e812f7c97 693
mfiore 0:bb4e812f7c97 694 // move and update page
mfiore 0:bb4e812f7c97 695 res = spiffs_page_move(fs, fd == 0 ? 0 : fd->file_nbr, (u8_t*)objix_hdr, obj_id, 0, objix_hdr_pix, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 696
mfiore 0:bb4e812f7c97 697 if (res == SPIFFS_OK) {
mfiore 0:bb4e812f7c97 698 if (new_pix) {
mfiore 0:bb4e812f7c97 699 *new_pix = new_objix_hdr_pix;
mfiore 0:bb4e812f7c97 700 }
mfiore 0:bb4e812f7c97 701 // callback on object index update
mfiore 0:bb4e812f7c97 702 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, obj_id, objix_hdr->p_hdr.span_ix, new_objix_hdr_pix, objix_hdr->size);
mfiore 0:bb4e812f7c97 703 if (fd) fd->objix_hdr_pix = new_objix_hdr_pix; // if this is not in the registered cluster
mfiore 0:bb4e812f7c97 704 }
mfiore 0:bb4e812f7c97 705
mfiore 0:bb4e812f7c97 706 return res;
mfiore 0:bb4e812f7c97 707 }
mfiore 0:bb4e812f7c97 708
mfiore 0:bb4e812f7c97 709 void spiffs_cb_object_event(
mfiore 0:bb4e812f7c97 710 spiffs *fs,
mfiore 0:bb4e812f7c97 711 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 712 int ev,
mfiore 0:bb4e812f7c97 713 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 714 spiffs_span_ix spix,
mfiore 0:bb4e812f7c97 715 spiffs_page_ix new_pix,
mfiore 0:bb4e812f7c97 716 u32_t new_size) {
mfiore 0:bb4e812f7c97 717 // update index caches in all file descriptors
mfiore 0:bb4e812f7c97 718 obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 719 int i;
mfiore 0:bb4e812f7c97 720 spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
mfiore 0:bb4e812f7c97 721 for (i = 0; i < fs->fd_count; i++) {
mfiore 0:bb4e812f7c97 722 spiffs_fd *cur_fd = &fds[i];
mfiore 0:bb4e812f7c97 723 if (cur_fd->file_nbr == 0 || (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue;
mfiore 0:bb4e812f7c97 724 if (spix == 0) {
mfiore 0:bb4e812f7c97 725 if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
mfiore 0:bb4e812f7c97 726 SPIFFS_DBG(" callback: setting fd %i:%04x objix_hdr_pix to %04x, size:%i\n", cur_fd->file_nbr, cur_fd->obj_id, new_pix, new_size);
mfiore 0:bb4e812f7c97 727 cur_fd->objix_hdr_pix = new_pix;
mfiore 0:bb4e812f7c97 728 if (new_size != 0) {
mfiore 0:bb4e812f7c97 729 cur_fd->size = new_size;
mfiore 0:bb4e812f7c97 730 }
mfiore 0:bb4e812f7c97 731 } else if (ev == SPIFFS_EV_IX_DEL) {
mfiore 0:bb4e812f7c97 732 cur_fd->file_nbr = 0;
mfiore 0:bb4e812f7c97 733 cur_fd->obj_id = SPIFFS_OBJ_ID_DELETED;
mfiore 0:bb4e812f7c97 734 }
mfiore 0:bb4e812f7c97 735 }
mfiore 0:bb4e812f7c97 736 if (cur_fd->cursor_objix_spix == spix) {
mfiore 0:bb4e812f7c97 737 if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
mfiore 0:bb4e812f7c97 738 SPIFFS_DBG(" callback: setting fd %i:%04x span:%04x objix_pix to %04x\n", cur_fd->file_nbr, cur_fd->obj_id, spix, new_pix);
mfiore 0:bb4e812f7c97 739 cur_fd->cursor_objix_pix = new_pix;
mfiore 0:bb4e812f7c97 740 } else {
mfiore 0:bb4e812f7c97 741 cur_fd->cursor_objix_pix = 0;
mfiore 0:bb4e812f7c97 742 }
mfiore 0:bb4e812f7c97 743 }
mfiore 0:bb4e812f7c97 744 }
mfiore 0:bb4e812f7c97 745 }
mfiore 0:bb4e812f7c97 746
mfiore 0:bb4e812f7c97 747 // Open object by id
mfiore 0:bb4e812f7c97 748 s32_t spiffs_object_open_by_id(
mfiore 0:bb4e812f7c97 749 spiffs *fs,
mfiore 0:bb4e812f7c97 750 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 751 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 752 spiffs_flags flags,
mfiore 0:bb4e812f7c97 753 spiffs_mode mode) {
mfiore 0:bb4e812f7c97 754 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 755 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 756
mfiore 0:bb4e812f7c97 757 res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix);
mfiore 0:bb4e812f7c97 758 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 759
mfiore 0:bb4e812f7c97 760 res = spiffs_object_open_by_page(fs, pix, fd, flags, mode);
mfiore 0:bb4e812f7c97 761
mfiore 0:bb4e812f7c97 762 return res;
mfiore 0:bb4e812f7c97 763 }
mfiore 0:bb4e812f7c97 764
mfiore 0:bb4e812f7c97 765 // Open object by page index
mfiore 0:bb4e812f7c97 766 s32_t spiffs_object_open_by_page(
mfiore 0:bb4e812f7c97 767 spiffs *fs,
mfiore 0:bb4e812f7c97 768 spiffs_page_ix pix,
mfiore 0:bb4e812f7c97 769 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 770 spiffs_flags flags,
mfiore 0:bb4e812f7c97 771 spiffs_mode mode) {
mfiore 0:bb4e812f7c97 772 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 773 spiffs_page_object_ix_header oix_hdr;
mfiore 0:bb4e812f7c97 774 spiffs_obj_id obj_id;
mfiore 0:bb4e812f7c97 775
mfiore 0:bb4e812f7c97 776 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 777 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&oix_hdr);
mfiore 0:bb4e812f7c97 778 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 779
mfiore 0:bb4e812f7c97 780 spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(fs, pix);
mfiore 0:bb4e812f7c97 781 int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix);
mfiore 0:bb4e812f7c97 782
mfiore 0:bb4e812f7c97 783 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 784 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
mfiore 0:bb4e812f7c97 785
mfiore 0:bb4e812f7c97 786 fd->fs = fs;
mfiore 0:bb4e812f7c97 787 fd->objix_hdr_pix = pix;
mfiore 0:bb4e812f7c97 788 fd->size = oix_hdr.size;
mfiore 0:bb4e812f7c97 789 fd->offset = 0;
mfiore 0:bb4e812f7c97 790 fd->cursor_objix_pix = pix;
mfiore 0:bb4e812f7c97 791 fd->cursor_objix_spix = 0;
mfiore 0:bb4e812f7c97 792 fd->obj_id = obj_id;
mfiore 0:bb4e812f7c97 793 fd->flags = flags;
mfiore 0:bb4e812f7c97 794
mfiore 0:bb4e812f7c97 795 SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
mfiore 0:bb4e812f7c97 796
mfiore 0:bb4e812f7c97 797 SPIFFS_DBG("open: fd %i is obj id %04x\n", fd->file_nbr, fd->obj_id);
mfiore 0:bb4e812f7c97 798
mfiore 0:bb4e812f7c97 799 return res;
mfiore 0:bb4e812f7c97 800 }
mfiore 0:bb4e812f7c97 801
mfiore 0:bb4e812f7c97 802 // Append to object
mfiore 0:bb4e812f7c97 803 // keep current object index (header) page in fs->work buffer
mfiore 0:bb4e812f7c97 804 s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
mfiore 0:bb4e812f7c97 805 spiffs *fs = fd->fs;
mfiore 0:bb4e812f7c97 806 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 807 u32_t written = 0;
mfiore 0:bb4e812f7c97 808
mfiore 0:bb4e812f7c97 809 res = spiffs_gc_check(fs, len);
mfiore 0:bb4e812f7c97 810 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 811
mfiore 0:bb4e812f7c97 812 spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
mfiore 0:bb4e812f7c97 813 spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
mfiore 0:bb4e812f7c97 814 spiffs_page_header p_hdr;
mfiore 0:bb4e812f7c97 815
mfiore 0:bb4e812f7c97 816 spiffs_span_ix cur_objix_spix = 0;
mfiore 0:bb4e812f7c97 817 spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
mfiore 0:bb4e812f7c97 818 spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
mfiore 0:bb4e812f7c97 819 spiffs_page_ix new_objix_hdr_page;
mfiore 0:bb4e812f7c97 820
mfiore 0:bb4e812f7c97 821 spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 822 spiffs_page_ix data_page;
mfiore 0:bb4e812f7c97 823 u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 824
mfiore 0:bb4e812f7c97 825 // write all data
mfiore 0:bb4e812f7c97 826 while (res == SPIFFS_OK && written < len) {
mfiore 0:bb4e812f7c97 827 // calculate object index page span index
mfiore 0:bb4e812f7c97 828 cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
mfiore 0:bb4e812f7c97 829
mfiore 0:bb4e812f7c97 830 // handle storing and loading of object indices
mfiore 0:bb4e812f7c97 831 if (cur_objix_spix != prev_objix_spix) {
mfiore 0:bb4e812f7c97 832 // new object index page
mfiore 0:bb4e812f7c97 833 // within this clause we return directly if something fails, object index mess-up
mfiore 0:bb4e812f7c97 834 if (written > 0) {
mfiore 0:bb4e812f7c97 835 // store previous object index page, unless first pass
mfiore 0:bb4e812f7c97 836 SPIFFS_DBG("append: %04x store objix %04x:%04x, written %i\n", fd->obj_id,
mfiore 0:bb4e812f7c97 837 cur_objix_pix, prev_objix_spix, written);
mfiore 0:bb4e812f7c97 838 if (prev_objix_spix == 0) {
mfiore 0:bb4e812f7c97 839 // this is an update to object index header page
mfiore 0:bb4e812f7c97 840 objix_hdr->size = offset+written;
mfiore 0:bb4e812f7c97 841 if (offset == 0) {
mfiore 0:bb4e812f7c97 842 // was an empty object, update same page (size was 0xffffffff)
mfiore 0:bb4e812f7c97 843 res = spiffs_page_index_check(fs, fd, cur_objix_pix, 0);
mfiore 0:bb4e812f7c97 844 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 845 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 846 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 847 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 848 } else {
mfiore 0:bb4e812f7c97 849 // was a nonempty object, update to new page
mfiore 0:bb4e812f7c97 850 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 851 fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
mfiore 0:bb4e812f7c97 852 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 853 SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
mfiore 0:bb4e812f7c97 854 new_objix_hdr_page, 0, written);
mfiore 0:bb4e812f7c97 855 }
mfiore 0:bb4e812f7c97 856 } else {
mfiore 0:bb4e812f7c97 857 // this is an update to an object index page
mfiore 0:bb4e812f7c97 858 res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
mfiore 0:bb4e812f7c97 859 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 860
mfiore 0:bb4e812f7c97 861 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 862 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 863 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 864 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD,fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
mfiore 0:bb4e812f7c97 865 // update length in object index header page
mfiore 0:bb4e812f7c97 866 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 867 fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
mfiore 0:bb4e812f7c97 868 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 869 SPIFFS_DBG("append: %04x store new size I %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
mfiore 0:bb4e812f7c97 870 offset+written, new_objix_hdr_page, 0, written);
mfiore 0:bb4e812f7c97 871 }
mfiore 0:bb4e812f7c97 872 fd->size = offset+written;
mfiore 0:bb4e812f7c97 873 fd->offset = offset+written;
mfiore 0:bb4e812f7c97 874 }
mfiore 0:bb4e812f7c97 875
mfiore 0:bb4e812f7c97 876 // create or load new object index page
mfiore 0:bb4e812f7c97 877 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 878 // load object index header page, must always exist
mfiore 0:bb4e812f7c97 879 SPIFFS_DBG("append: %04x load objixhdr page %04x:%04x\n", fd->obj_id, cur_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 880 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 881 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 882 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 883 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 884 } else {
mfiore 0:bb4e812f7c97 885 spiffs_span_ix len_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, (fd->size-1)/SPIFFS_DATA_PAGE_SIZE(fs));
mfiore 0:bb4e812f7c97 886 // on subsequent passes, create a new object index page
mfiore 0:bb4e812f7c97 887 if (written > 0 || cur_objix_spix > len_objix_spix) {
mfiore 0:bb4e812f7c97 888 p_hdr.obj_id = fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 889 p_hdr.span_ix = cur_objix_spix;
mfiore 0:bb4e812f7c97 890 p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
mfiore 0:bb4e812f7c97 891 res = spiffs_page_allocate_data(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
mfiore 0:bb4e812f7c97 892 &p_hdr, 0, 0, 0, 1, &cur_objix_pix);
mfiore 0:bb4e812f7c97 893 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 894 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0);
mfiore 0:bb4e812f7c97 895 // quick "load" of new object index page
mfiore 0:bb4e812f7c97 896 memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 897 memcpy(fs->work, &p_hdr, sizeof(spiffs_page_header));
mfiore 0:bb4e812f7c97 898 SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %i\n", fd->obj_id
mfiore 0:bb4e812f7c97 899 , cur_objix_pix, cur_objix_spix, written);
mfiore 0:bb4e812f7c97 900 } else {
mfiore 0:bb4e812f7c97 901 // on first pass, we load existing object index page
mfiore 0:bb4e812f7c97 902 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 903 SPIFFS_DBG("append: %04x find objix span_ix:%04x\n", fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 904 if (fd->cursor_objix_spix == cur_objix_spix) {
mfiore 0:bb4e812f7c97 905 pix = fd->cursor_objix_pix;
mfiore 0:bb4e812f7c97 906 } else {
mfiore 0:bb4e812f7c97 907 res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
mfiore 0:bb4e812f7c97 908 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 909 }
mfiore 0:bb4e812f7c97 910 SPIFFS_DBG("append: %04x found object index at page %04x\n", fd->obj_id, pix);
mfiore 0:bb4e812f7c97 911 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 912 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 913 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 914 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 915 cur_objix_pix = pix;
mfiore 0:bb4e812f7c97 916 }
mfiore 0:bb4e812f7c97 917 fd->cursor_objix_pix = cur_objix_pix;
mfiore 0:bb4e812f7c97 918 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 919 fd->offset = offset+written;
mfiore 0:bb4e812f7c97 920 fd->size = offset+written;
mfiore 0:bb4e812f7c97 921 }
mfiore 0:bb4e812f7c97 922 prev_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 923 }
mfiore 0:bb4e812f7c97 924
mfiore 0:bb4e812f7c97 925 // write data
mfiore 0:bb4e812f7c97 926 u32_t to_write = MIN(len-written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
mfiore 0:bb4e812f7c97 927 if (page_offs == 0) {
mfiore 0:bb4e812f7c97 928 // at beginning of a page, allocate and write a new page of data
mfiore 0:bb4e812f7c97 929 p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 930 p_hdr.span_ix = data_spix;
mfiore 0:bb4e812f7c97 931 p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
mfiore 0:bb4e812f7c97 932 res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
mfiore 0:bb4e812f7c97 933 &p_hdr, &data[written], to_write, page_offs, 1, &data_page);
mfiore 0:bb4e812f7c97 934 SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id,
mfiore 0:bb4e812f7c97 935 data_page, data_spix, page_offs, to_write, written);
mfiore 0:bb4e812f7c97 936 } else {
mfiore 0:bb4e812f7c97 937 // append to existing page, fill out free data in existing page
mfiore 0:bb4e812f7c97 938 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 939 // get data page from object index header page
Mike Fiore 2:de478b250060 940 data_page = ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
mfiore 0:bb4e812f7c97 941 } else {
mfiore 0:bb4e812f7c97 942 // get data page from object index page
Mike Fiore 2:de478b250060 943 data_page = ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
mfiore 0:bb4e812f7c97 944 }
mfiore 0:bb4e812f7c97 945
mfiore 0:bb4e812f7c97 946 res = spiffs_page_data_check(fs, fd, data_page, data_spix);
mfiore 0:bb4e812f7c97 947 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 948
mfiore 0:bb4e812f7c97 949 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 950 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
mfiore 0:bb4e812f7c97 951 SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id
mfiore 0:bb4e812f7c97 952 , data_page, data_spix, page_offs, to_write, written);
mfiore 0:bb4e812f7c97 953 }
mfiore 0:bb4e812f7c97 954
mfiore 0:bb4e812f7c97 955 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 956
mfiore 0:bb4e812f7c97 957 // update memory representation of object index page with new data page
mfiore 0:bb4e812f7c97 958 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 959 // update object index header page
Mike Fiore 2:de478b250060 960 ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_page;
mfiore 0:bb4e812f7c97 961 SPIFFS_DBG("append: %04x wrote page %04x to objix_hdr entry %02x in mem\n", fd->obj_id
mfiore 0:bb4e812f7c97 962 , data_page, data_spix);
mfiore 0:bb4e812f7c97 963 objix_hdr->size = offset+written;
mfiore 0:bb4e812f7c97 964 } else {
mfiore 0:bb4e812f7c97 965 // update object index page
Mike Fiore 2:de478b250060 966 ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_page;
mfiore 0:bb4e812f7c97 967 SPIFFS_DBG("append: %04x wrote page %04x to objix entry %02x in mem\n", fd->obj_id
mfiore 0:bb4e812f7c97 968 , data_page, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
mfiore 0:bb4e812f7c97 969 }
mfiore 0:bb4e812f7c97 970
mfiore 0:bb4e812f7c97 971 // update internals
mfiore 0:bb4e812f7c97 972 page_offs = 0;
mfiore 0:bb4e812f7c97 973 data_spix++;
mfiore 0:bb4e812f7c97 974 written += to_write;
mfiore 0:bb4e812f7c97 975 } // while all data
mfiore 0:bb4e812f7c97 976
mfiore 0:bb4e812f7c97 977 fd->size = offset+written;
mfiore 0:bb4e812f7c97 978 fd->offset = offset+written;
mfiore 0:bb4e812f7c97 979 fd->cursor_objix_pix = cur_objix_pix;
mfiore 0:bb4e812f7c97 980 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 981
mfiore 0:bb4e812f7c97 982 // finalize updated object indices
mfiore 0:bb4e812f7c97 983 s32_t res2 = SPIFFS_OK;
mfiore 0:bb4e812f7c97 984 if (cur_objix_spix != 0) {
mfiore 0:bb4e812f7c97 985 // wrote beyond object index header page
mfiore 0:bb4e812f7c97 986 // write last modified object index page, unless object header index page
mfiore 0:bb4e812f7c97 987 SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %i\n", fd->obj_id,
mfiore 0:bb4e812f7c97 988 cur_objix_pix, cur_objix_spix, written);
mfiore 0:bb4e812f7c97 989
mfiore 0:bb4e812f7c97 990 res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 991 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 992
mfiore 0:bb4e812f7c97 993 res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 994 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 995 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 996 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
mfiore 0:bb4e812f7c97 997
mfiore 0:bb4e812f7c97 998 // update size in object header index page
mfiore 0:bb4e812f7c97 999 res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1000 fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
mfiore 0:bb4e812f7c97 1001 SPIFFS_DBG("append: %04x store new size II %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id
mfiore 0:bb4e812f7c97 1002 , offset+written, new_objix_hdr_page, 0, written);
mfiore 0:bb4e812f7c97 1003 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1004 } else {
mfiore 0:bb4e812f7c97 1005 // wrote within object index header page
mfiore 0:bb4e812f7c97 1006 if (offset == 0) {
mfiore 0:bb4e812f7c97 1007 // wrote to empty object - simply update size and write whole page
mfiore 0:bb4e812f7c97 1008 objix_hdr->size = offset+written;
mfiore 0:bb4e812f7c97 1009 SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
mfiore 0:bb4e812f7c97 1010 , cur_objix_pix, cur_objix_spix, written);
mfiore 0:bb4e812f7c97 1011
mfiore 0:bb4e812f7c97 1012 res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 1013 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1014
mfiore 0:bb4e812f7c97 1015 res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 1016 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 1017 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1018 // callback on object index update
mfiore 0:bb4e812f7c97 1019 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix_hdr->p_hdr.span_ix, cur_objix_pix, objix_hdr->size);
mfiore 0:bb4e812f7c97 1020 } else {
mfiore 0:bb4e812f7c97 1021 // modifying object index header page, update size and make new copy
mfiore 0:bb4e812f7c97 1022 res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1023 fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
mfiore 0:bb4e812f7c97 1024 SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
mfiore 0:bb4e812f7c97 1025 , new_objix_hdr_page, 0, written);
mfiore 0:bb4e812f7c97 1026 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1027 }
mfiore 0:bb4e812f7c97 1028 }
mfiore 0:bb4e812f7c97 1029
mfiore 0:bb4e812f7c97 1030 return res;
mfiore 0:bb4e812f7c97 1031 }
mfiore 0:bb4e812f7c97 1032
mfiore 0:bb4e812f7c97 1033 // Modify object
mfiore 0:bb4e812f7c97 1034 // keep current object index (header) page in fs->work buffer
mfiore 0:bb4e812f7c97 1035 s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
mfiore 0:bb4e812f7c97 1036 spiffs *fs = fd->fs;
mfiore 0:bb4e812f7c97 1037 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1038 u32_t written = 0;
mfiore 0:bb4e812f7c97 1039
mfiore 0:bb4e812f7c97 1040 res = spiffs_gc_check(fs, len);
mfiore 0:bb4e812f7c97 1041 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1042
mfiore 0:bb4e812f7c97 1043 spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
mfiore 0:bb4e812f7c97 1044 spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
mfiore 0:bb4e812f7c97 1045 spiffs_page_header p_hdr;
mfiore 0:bb4e812f7c97 1046
mfiore 0:bb4e812f7c97 1047 spiffs_span_ix cur_objix_spix = 0;
mfiore 0:bb4e812f7c97 1048 spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
mfiore 0:bb4e812f7c97 1049 spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
mfiore 0:bb4e812f7c97 1050 spiffs_page_ix new_objix_hdr_pix;
mfiore 0:bb4e812f7c97 1051
mfiore 0:bb4e812f7c97 1052 spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1053 spiffs_page_ix data_pix;
mfiore 0:bb4e812f7c97 1054 u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1055
mfiore 0:bb4e812f7c97 1056
mfiore 0:bb4e812f7c97 1057 // write all data
mfiore 0:bb4e812f7c97 1058 while (res == SPIFFS_OK && written < len) {
mfiore 0:bb4e812f7c97 1059 // calculate object index page span index
mfiore 0:bb4e812f7c97 1060 cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
mfiore 0:bb4e812f7c97 1061
mfiore 0:bb4e812f7c97 1062 // handle storing and loading of object indices
mfiore 0:bb4e812f7c97 1063 if (cur_objix_spix != prev_objix_spix) {
mfiore 0:bb4e812f7c97 1064 // new object index page
mfiore 0:bb4e812f7c97 1065 // within this clause we return directly if something fails, object index mess-up
mfiore 0:bb4e812f7c97 1066 if (written > 0) {
mfiore 0:bb4e812f7c97 1067 // store previous object index (header) page, unless first pass
mfiore 0:bb4e812f7c97 1068 if (prev_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1069 // store previous object index header page
mfiore 0:bb4e812f7c97 1070 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1071 fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1072 SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
mfiore 0:bb4e812f7c97 1073 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1074 } else {
mfiore 0:bb4e812f7c97 1075 // store new version of previous object index page
mfiore 0:bb4e812f7c97 1076 spiffs_page_ix new_objix_pix;
mfiore 0:bb4e812f7c97 1077
mfiore 0:bb4e812f7c97 1078 res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
mfiore 0:bb4e812f7c97 1079 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1080
mfiore 0:bb4e812f7c97 1081 res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
mfiore 0:bb4e812f7c97 1082 SPIFFS_DBG("modify: store previous modified objix page, %04x:%04x, written %i\n", new_objix_pix, objix->p_hdr.span_ix, written);
mfiore 0:bb4e812f7c97 1083 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1084 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
mfiore 0:bb4e812f7c97 1085 }
mfiore 0:bb4e812f7c97 1086 }
mfiore 0:bb4e812f7c97 1087
mfiore 0:bb4e812f7c97 1088 // load next object index page
mfiore 0:bb4e812f7c97 1089 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1090 // load object index header page, must exist
mfiore 0:bb4e812f7c97 1091 SPIFFS_DBG("modify: load objixhdr page %04x:%04x\n", cur_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 1092 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1093 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 1094 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1095 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 1096 } else {
mfiore 0:bb4e812f7c97 1097 // load existing object index page on first pass
mfiore 0:bb4e812f7c97 1098 spiffs_page_ix pix;
mfiore 0:bb4e812f7c97 1099 SPIFFS_DBG("modify: find objix span_ix:%04x\n", cur_objix_spix);
mfiore 0:bb4e812f7c97 1100 if (fd->cursor_objix_spix == cur_objix_spix) {
mfiore 0:bb4e812f7c97 1101 pix = fd->cursor_objix_pix;
mfiore 0:bb4e812f7c97 1102 } else {
mfiore 0:bb4e812f7c97 1103 res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
mfiore 0:bb4e812f7c97 1104 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1105 }
mfiore 0:bb4e812f7c97 1106 SPIFFS_DBG("modify: found object index at page %04x\n", pix);
mfiore 0:bb4e812f7c97 1107 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1108 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 1109 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1110 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 1111 cur_objix_pix = pix;
mfiore 0:bb4e812f7c97 1112 }
mfiore 0:bb4e812f7c97 1113 fd->cursor_objix_pix = cur_objix_pix;
mfiore 0:bb4e812f7c97 1114 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1115 fd->offset = offset+written;
mfiore 0:bb4e812f7c97 1116 prev_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1117 }
mfiore 0:bb4e812f7c97 1118
mfiore 0:bb4e812f7c97 1119 // write partial data
mfiore 0:bb4e812f7c97 1120 u32_t to_write = MIN(len-written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
mfiore 0:bb4e812f7c97 1121 spiffs_page_ix orig_data_pix;
mfiore 0:bb4e812f7c97 1122 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1123 // get data page from object index header page
Mike Fiore 2:de478b250060 1124 orig_data_pix = ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
mfiore 0:bb4e812f7c97 1125 } else {
mfiore 0:bb4e812f7c97 1126 // get data page from object index page
Mike Fiore 2:de478b250060 1127 orig_data_pix = ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
mfiore 0:bb4e812f7c97 1128 }
mfiore 0:bb4e812f7c97 1129
mfiore 0:bb4e812f7c97 1130 p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 1131 p_hdr.span_ix = data_spix;
mfiore 0:bb4e812f7c97 1132 p_hdr.flags = 0xff;
mfiore 0:bb4e812f7c97 1133 if (page_offs == 0 && to_write == SPIFFS_DATA_PAGE_SIZE(fs)) {
mfiore 0:bb4e812f7c97 1134 // a full page, allocate and write a new page of data
mfiore 0:bb4e812f7c97 1135 res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
mfiore 0:bb4e812f7c97 1136 &p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
mfiore 0:bb4e812f7c97 1137 SPIFFS_DBG("modify: store new data page, %04x:%04x offset:%i, len %i, written %i\n", data_pix, data_spix, page_offs, to_write, written);
mfiore 0:bb4e812f7c97 1138 } else {
mfiore 0:bb4e812f7c97 1139 // write to existing page, allocate new and copy unmodified data
mfiore 0:bb4e812f7c97 1140
mfiore 0:bb4e812f7c97 1141 res = spiffs_page_data_check(fs, fd, orig_data_pix, data_spix);
mfiore 0:bb4e812f7c97 1142 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1143
mfiore 0:bb4e812f7c97 1144 res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
mfiore 0:bb4e812f7c97 1145 &p_hdr, 0, 0, 0, 0, &data_pix);
mfiore 0:bb4e812f7c97 1146 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1147
mfiore 0:bb4e812f7c97 1148 // copy unmodified data
mfiore 0:bb4e812f7c97 1149 if (page_offs > 0) {
mfiore 0:bb4e812f7c97 1150 // before modification
mfiore 0:bb4e812f7c97 1151 res = spiffs_phys_cpy(fs, fd->file_nbr,
mfiore 0:bb4e812f7c97 1152 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 1153 SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 1154 page_offs);
mfiore 0:bb4e812f7c97 1155 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1156 }
mfiore 0:bb4e812f7c97 1157 if (page_offs + to_write < SPIFFS_DATA_PAGE_SIZE(fs)) {
mfiore 0:bb4e812f7c97 1158 // after modification
mfiore 0:bb4e812f7c97 1159 res = spiffs_phys_cpy(fs, fd->file_nbr,
mfiore 0:bb4e812f7c97 1160 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
mfiore 0:bb4e812f7c97 1161 SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
mfiore 0:bb4e812f7c97 1162 SPIFFS_DATA_PAGE_SIZE(fs) - (page_offs + to_write));
mfiore 0:bb4e812f7c97 1163 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1164 }
mfiore 0:bb4e812f7c97 1165
mfiore 0:bb4e812f7c97 1166 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 1167 fd->file_nbr,
mfiore 0:bb4e812f7c97 1168 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
mfiore 0:bb4e812f7c97 1169 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1170 p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
mfiore 0:bb4e812f7c97 1171 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 1172 fd->file_nbr,
mfiore 0:bb4e812f7c97 1173 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 1174 sizeof(u8_t),
mfiore 0:bb4e812f7c97 1175 (u8_t *)&p_hdr.flags);
mfiore 0:bb4e812f7c97 1176 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1177
mfiore 0:bb4e812f7c97 1178 SPIFFS_DBG("modify: store to existing data page, src:%04x, dst:%04x:%04x offset:%i, len %i, written %i\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written);
mfiore 0:bb4e812f7c97 1179 }
mfiore 0:bb4e812f7c97 1180
mfiore 0:bb4e812f7c97 1181 // delete original data page
mfiore 0:bb4e812f7c97 1182 res = spiffs_page_delete(fs, orig_data_pix);
mfiore 0:bb4e812f7c97 1183 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1184 // update memory representation of object index page with new data page
mfiore 0:bb4e812f7c97 1185 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1186 // update object index header page
Mike Fiore 2:de478b250060 1187 ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_pix;
mfiore 0:bb4e812f7c97 1188 SPIFFS_DBG("modify: wrote page %04x to objix_hdr entry %02x in mem\n", data_pix, data_spix);
mfiore 0:bb4e812f7c97 1189 } else {
mfiore 0:bb4e812f7c97 1190 // update object index page
Mike Fiore 2:de478b250060 1191 ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_pix;
mfiore 0:bb4e812f7c97 1192 SPIFFS_DBG("modify: wrote page %04x to objix entry %02x in mem\n", data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
mfiore 0:bb4e812f7c97 1193 }
mfiore 0:bb4e812f7c97 1194
mfiore 0:bb4e812f7c97 1195 // update internals
mfiore 0:bb4e812f7c97 1196 page_offs = 0;
mfiore 0:bb4e812f7c97 1197 data_spix++;
mfiore 0:bb4e812f7c97 1198 written += to_write;
mfiore 0:bb4e812f7c97 1199 } // while all data
mfiore 0:bb4e812f7c97 1200
mfiore 0:bb4e812f7c97 1201 fd->offset = offset+written;
mfiore 0:bb4e812f7c97 1202 fd->cursor_objix_pix = cur_objix_pix;
mfiore 0:bb4e812f7c97 1203 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1204
mfiore 0:bb4e812f7c97 1205 // finalize updated object indices
mfiore 0:bb4e812f7c97 1206 s32_t res2 = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1207 if (cur_objix_spix != 0) {
mfiore 0:bb4e812f7c97 1208 // wrote beyond object index header page
mfiore 0:bb4e812f7c97 1209 // write last modified object index page
mfiore 0:bb4e812f7c97 1210 // move and update page
mfiore 0:bb4e812f7c97 1211 spiffs_page_ix new_objix_pix;
mfiore 0:bb4e812f7c97 1212
mfiore 0:bb4e812f7c97 1213 res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 1214 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1215
mfiore 0:bb4e812f7c97 1216 res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
mfiore 0:bb4e812f7c97 1217 SPIFFS_DBG("modify: store modified objix page, %04x:%04x, written %i\n", new_objix_pix, cur_objix_spix, written);
mfiore 0:bb4e812f7c97 1218 fd->cursor_objix_pix = new_objix_pix;
mfiore 0:bb4e812f7c97 1219 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1220 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1221 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
mfiore 0:bb4e812f7c97 1222
mfiore 0:bb4e812f7c97 1223 } else {
mfiore 0:bb4e812f7c97 1224 // wrote within object index header page
mfiore 0:bb4e812f7c97 1225 res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1226 fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1227 SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
mfiore 0:bb4e812f7c97 1228 SPIFFS_CHECK_RES(res2);
mfiore 0:bb4e812f7c97 1229 }
mfiore 0:bb4e812f7c97 1230
mfiore 0:bb4e812f7c97 1231 return res;
mfiore 0:bb4e812f7c97 1232 }
mfiore 0:bb4e812f7c97 1233
mfiore 0:bb4e812f7c97 1234 static s32_t spiffs_object_find_object_index_header_by_name_v(
mfiore 0:bb4e812f7c97 1235 spiffs *fs,
mfiore 0:bb4e812f7c97 1236 spiffs_obj_id obj_id,
mfiore 0:bb4e812f7c97 1237 spiffs_block_ix bix,
mfiore 0:bb4e812f7c97 1238 int ix_entry,
mfiore 0:bb4e812f7c97 1239 u32_t user_data,
mfiore 0:bb4e812f7c97 1240 void *user_p) {
mfiore 0:bb4e812f7c97 1241 s32_t res;
mfiore 0:bb4e812f7c97 1242 spiffs_page_object_ix_header objix_hdr;
mfiore 0:bb4e812f7c97 1243 spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
mfiore 0:bb4e812f7c97 1244 if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
mfiore 0:bb4e812f7c97 1245 (obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
mfiore 0:bb4e812f7c97 1246 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 1247 }
mfiore 0:bb4e812f7c97 1248 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1249 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
mfiore 0:bb4e812f7c97 1250 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1251 if (objix_hdr.p_hdr.span_ix == 0 &&
mfiore 0:bb4e812f7c97 1252 (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
mfiore 0:bb4e812f7c97 1253 (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
mfiore 0:bb4e812f7c97 1254 if (strcmp((char *)user_p, (char *)objix_hdr.name) == 0) {
mfiore 0:bb4e812f7c97 1255 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 1256 }
mfiore 0:bb4e812f7c97 1257 }
mfiore 0:bb4e812f7c97 1258
mfiore 0:bb4e812f7c97 1259 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 1260 }
mfiore 0:bb4e812f7c97 1261
mfiore 0:bb4e812f7c97 1262 // Finds object index header page by name
mfiore 0:bb4e812f7c97 1263 s32_t spiffs_object_find_object_index_header_by_name(
mfiore 0:bb4e812f7c97 1264 spiffs *fs,
mfiore 0:bb4e812f7c97 1265 u8_t name[SPIFFS_OBJ_NAME_LEN],
mfiore 0:bb4e812f7c97 1266 spiffs_page_ix *pix) {
mfiore 0:bb4e812f7c97 1267 s32_t res;
mfiore 0:bb4e812f7c97 1268 spiffs_block_ix bix;
mfiore 0:bb4e812f7c97 1269 int entry;
mfiore 0:bb4e812f7c97 1270
mfiore 0:bb4e812f7c97 1271 res = spiffs_obj_lu_find_entry_visitor(fs,
mfiore 0:bb4e812f7c97 1272 fs->cursor_block_ix,
mfiore 0:bb4e812f7c97 1273 fs->cursor_obj_lu_entry,
mfiore 0:bb4e812f7c97 1274 0,
mfiore 0:bb4e812f7c97 1275 0,
mfiore 0:bb4e812f7c97 1276 spiffs_object_find_object_index_header_by_name_v,
mfiore 0:bb4e812f7c97 1277 0,
mfiore 0:bb4e812f7c97 1278 name,
mfiore 0:bb4e812f7c97 1279 &bix,
mfiore 0:bb4e812f7c97 1280 &entry);
mfiore 0:bb4e812f7c97 1281
mfiore 0:bb4e812f7c97 1282 if (res == SPIFFS_VIS_END) {
mfiore 0:bb4e812f7c97 1283 res = SPIFFS_ERR_NOT_FOUND;
mfiore 0:bb4e812f7c97 1284 }
mfiore 0:bb4e812f7c97 1285 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1286
mfiore 0:bb4e812f7c97 1287 if (pix) {
mfiore 0:bb4e812f7c97 1288 *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
mfiore 0:bb4e812f7c97 1289 }
mfiore 0:bb4e812f7c97 1290
mfiore 0:bb4e812f7c97 1291 fs->cursor_block_ix = bix;
mfiore 0:bb4e812f7c97 1292 fs->cursor_obj_lu_entry = entry;
mfiore 0:bb4e812f7c97 1293
mfiore 0:bb4e812f7c97 1294 return res;
mfiore 0:bb4e812f7c97 1295 }
mfiore 0:bb4e812f7c97 1296
mfiore 0:bb4e812f7c97 1297 // Truncates object to new size. If new size is null, object may be removed totally
mfiore 0:bb4e812f7c97 1298 s32_t spiffs_object_truncate(
mfiore 0:bb4e812f7c97 1299 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 1300 u32_t new_size,
mfiore 0:bb4e812f7c97 1301 u8_t remove) {
mfiore 0:bb4e812f7c97 1302 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1303 spiffs *fs = fd->fs;
mfiore 0:bb4e812f7c97 1304
mfiore 0:bb4e812f7c97 1305 res = spiffs_gc_check(fs, 0);
mfiore 0:bb4e812f7c97 1306 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1307
mfiore 0:bb4e812f7c97 1308 spiffs_page_ix objix_pix = fd->objix_hdr_pix;
mfiore 0:bb4e812f7c97 1309 spiffs_span_ix data_spix = (fd->size > 0 ? fd->size-1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1310 u32_t cur_size = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size ;
mfiore 0:bb4e812f7c97 1311 spiffs_span_ix cur_objix_spix = 0;
mfiore 0:bb4e812f7c97 1312 spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
mfiore 0:bb4e812f7c97 1313 spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
mfiore 0:bb4e812f7c97 1314 spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
mfiore 0:bb4e812f7c97 1315 spiffs_page_ix data_pix;
mfiore 0:bb4e812f7c97 1316 spiffs_page_ix new_objix_hdr_pix;
mfiore 0:bb4e812f7c97 1317
mfiore 0:bb4e812f7c97 1318 // before truncating, check if object is to be fully removed and mark this
mfiore 0:bb4e812f7c97 1319 if (remove && new_size == 0) {
mfiore 0:bb4e812f7c97 1320 u8_t flags = ~( SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE);
mfiore 0:bb4e812f7c97 1321 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 1322 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, fd->objix_hdr_pix) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 1323 sizeof(u8_t),
mfiore 0:bb4e812f7c97 1324 (u8_t *)&flags);
mfiore 0:bb4e812f7c97 1325 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1326 }
mfiore 0:bb4e812f7c97 1327
mfiore 0:bb4e812f7c97 1328 // delete from end of object until desired len is reached
mfiore 0:bb4e812f7c97 1329 while (cur_size > new_size) {
mfiore 0:bb4e812f7c97 1330 cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
mfiore 0:bb4e812f7c97 1331
mfiore 0:bb4e812f7c97 1332 // put object index for current data span index in work buffer
mfiore 0:bb4e812f7c97 1333 if (prev_objix_spix != cur_objix_spix) {
mfiore 0:bb4e812f7c97 1334 if (prev_objix_spix != (spiffs_span_ix)-1) {
mfiore 0:bb4e812f7c97 1335 // remove previous object index page
mfiore 0:bb4e812f7c97 1336 SPIFFS_DBG("truncate: delete objix page %04x:%04x\n", objix_pix, prev_objix_spix);
mfiore 0:bb4e812f7c97 1337
mfiore 0:bb4e812f7c97 1338 res = spiffs_page_index_check(fs, fd, objix_pix, prev_objix_spix);
mfiore 0:bb4e812f7c97 1339 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1340
mfiore 0:bb4e812f7c97 1341 res = spiffs_page_delete(fs, objix_pix);
mfiore 0:bb4e812f7c97 1342 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1343 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
mfiore 0:bb4e812f7c97 1344 if (prev_objix_spix > 0) {
mfiore 0:bb4e812f7c97 1345 // update object index header page
mfiore 0:bb4e812f7c97 1346 SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
mfiore 0:bb4e812f7c97 1347 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1348 fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1349 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1350 fd->size = cur_size;
mfiore 0:bb4e812f7c97 1351 }
mfiore 0:bb4e812f7c97 1352 }
mfiore 0:bb4e812f7c97 1353 // load current object index (header) page
mfiore 0:bb4e812f7c97 1354 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1355 objix_pix = fd->objix_hdr_pix;
mfiore 0:bb4e812f7c97 1356 } else {
mfiore 0:bb4e812f7c97 1357 res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
mfiore 0:bb4e812f7c97 1358 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1359 }
mfiore 0:bb4e812f7c97 1360
mfiore 0:bb4e812f7c97 1361 SPIFFS_DBG("truncate: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
mfiore 0:bb4e812f7c97 1362 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1363 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 1364 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1365 SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 1366 fd->cursor_objix_pix = objix_pix;
mfiore 0:bb4e812f7c97 1367 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1368 fd->offset = cur_size;
mfiore 0:bb4e812f7c97 1369
mfiore 0:bb4e812f7c97 1370 prev_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1371 }
mfiore 0:bb4e812f7c97 1372
mfiore 0:bb4e812f7c97 1373 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1374 // get data page from object index header page
Mike Fiore 2:de478b250060 1375 data_pix = ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
Mike Fiore 2:de478b250060 1376 ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = SPIFFS_OBJ_ID_FREE;
mfiore 0:bb4e812f7c97 1377 } else {
mfiore 0:bb4e812f7c97 1378 // get data page from object index page
Mike Fiore 2:de478b250060 1379 data_pix = ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
Mike Fiore 2:de478b250060 1380 ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE;
mfiore 0:bb4e812f7c97 1381 }
mfiore 0:bb4e812f7c97 1382
mfiore 0:bb4e812f7c97 1383 if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) {
mfiore 0:bb4e812f7c97 1384 // delete full data page
mfiore 0:bb4e812f7c97 1385 res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
mfiore 0:bb4e812f7c97 1386 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1387
mfiore 0:bb4e812f7c97 1388 res = spiffs_page_delete(fs, data_pix);
mfiore 0:bb4e812f7c97 1389 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1390 // update current size
mfiore 0:bb4e812f7c97 1391 if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) {
mfiore 0:bb4e812f7c97 1392 cur_size -= SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1393 } else {
mfiore 0:bb4e812f7c97 1394 cur_size -= cur_size % SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1395 }
mfiore 0:bb4e812f7c97 1396 fd->size = cur_size;
mfiore 0:bb4e812f7c97 1397 fd->offset = cur_size;
mfiore 0:bb4e812f7c97 1398 SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%i\n", data_pix, data_spix, cur_size);
mfiore 0:bb4e812f7c97 1399 } else {
mfiore 0:bb4e812f7c97 1400 // delete last page, partially
mfiore 0:bb4e812f7c97 1401 spiffs_page_header p_hdr;
mfiore 0:bb4e812f7c97 1402 spiffs_page_ix new_data_pix;
mfiore 0:bb4e812f7c97 1403 u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs));
mfiore 0:bb4e812f7c97 1404 SPIFFS_DBG("truncate: delete %i bytes from data page %04x for data spix:%04x, cur_size:%i\n", bytes_to_remove, data_pix, data_spix, cur_size);
mfiore 0:bb4e812f7c97 1405
mfiore 0:bb4e812f7c97 1406 res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
mfiore 0:bb4e812f7c97 1407 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1408
mfiore 0:bb4e812f7c97 1409 p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 1410 p_hdr.span_ix = data_spix;
mfiore 0:bb4e812f7c97 1411 p_hdr.flags = 0xff;
mfiore 0:bb4e812f7c97 1412 // allocate new page and copy unmodified data
mfiore 0:bb4e812f7c97 1413 res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
mfiore 0:bb4e812f7c97 1414 &p_hdr, 0, 0, 0, 0, &new_data_pix);
mfiore 0:bb4e812f7c97 1415 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1416 res = spiffs_phys_cpy(fs, 0,
mfiore 0:bb4e812f7c97 1417 SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 1418 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
mfiore 0:bb4e812f7c97 1419 SPIFFS_DATA_PAGE_SIZE(fs) - bytes_to_remove);
mfiore 0:bb4e812f7c97 1420 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1421 // delete original data page
mfiore 0:bb4e812f7c97 1422 res = spiffs_page_delete(fs, data_pix);
mfiore 0:bb4e812f7c97 1423 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1424 p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
mfiore 0:bb4e812f7c97 1425 res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
mfiore 0:bb4e812f7c97 1426 fd->file_nbr,
mfiore 0:bb4e812f7c97 1427 SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + offsetof(spiffs_page_header, flags),
mfiore 0:bb4e812f7c97 1428 sizeof(u8_t),
mfiore 0:bb4e812f7c97 1429 (u8_t *)&p_hdr.flags);
mfiore 0:bb4e812f7c97 1430 if (res != SPIFFS_OK) break;
mfiore 0:bb4e812f7c97 1431
mfiore 0:bb4e812f7c97 1432 // update memory representation of object index page with new data page
mfiore 0:bb4e812f7c97 1433 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1434 // update object index header page
Mike Fiore 2:de478b250060 1435 ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
mfiore 0:bb4e812f7c97 1436 SPIFFS_DBG("truncate: wrote page %04x to objix_hdr entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
mfiore 0:bb4e812f7c97 1437 } else {
mfiore 0:bb4e812f7c97 1438 // update object index page
Mike Fiore 2:de478b250060 1439 ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
mfiore 0:bb4e812f7c97 1440 SPIFFS_DBG("truncate: wrote page %04x to objix entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
mfiore 0:bb4e812f7c97 1441 }
mfiore 0:bb4e812f7c97 1442 cur_size = new_size;
mfiore 0:bb4e812f7c97 1443 fd->size = new_size;
mfiore 0:bb4e812f7c97 1444 fd->offset = cur_size;
mfiore 0:bb4e812f7c97 1445 break;
mfiore 0:bb4e812f7c97 1446 }
mfiore 0:bb4e812f7c97 1447 data_spix--;
mfiore 0:bb4e812f7c97 1448 } // while all data
mfiore 0:bb4e812f7c97 1449
mfiore 0:bb4e812f7c97 1450 // update object indices
mfiore 0:bb4e812f7c97 1451 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1452 // update object index header page
mfiore 0:bb4e812f7c97 1453 if (cur_size == 0) {
mfiore 0:bb4e812f7c97 1454 if (remove) {
mfiore 0:bb4e812f7c97 1455 // remove object altogether
mfiore 0:bb4e812f7c97 1456 SPIFFS_DBG("truncate: remove object index header page %04x\n", objix_pix);
mfiore 0:bb4e812f7c97 1457
mfiore 0:bb4e812f7c97 1458 res = spiffs_page_index_check(fs, fd, objix_pix, 0);
mfiore 0:bb4e812f7c97 1459 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1460
mfiore 0:bb4e812f7c97 1461 res = spiffs_page_delete(fs, objix_pix);
mfiore 0:bb4e812f7c97 1462 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1463 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, 0, objix_pix, 0);
mfiore 0:bb4e812f7c97 1464 } else {
mfiore 0:bb4e812f7c97 1465 // make uninitialized object
mfiore 0:bb4e812f7c97 1466 SPIFFS_DBG("truncate: reset objix_hdr page %04x\n", objix_pix);
mfiore 0:bb4e812f7c97 1467 memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff,
mfiore 0:bb4e812f7c97 1468 SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header));
mfiore 0:bb4e812f7c97 1469 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1470 objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1471 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1472 }
mfiore 0:bb4e812f7c97 1473 } else {
mfiore 0:bb4e812f7c97 1474 // update object index header page
mfiore 0:bb4e812f7c97 1475 SPIFFS_DBG("truncate: update object index header page with indices and size\n");
mfiore 0:bb4e812f7c97 1476 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1477 objix_pix, fs->work, 0, cur_size, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1478 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1479 }
mfiore 0:bb4e812f7c97 1480 } else {
mfiore 0:bb4e812f7c97 1481 // update both current object index page and object index header page
mfiore 0:bb4e812f7c97 1482 spiffs_page_ix new_objix_pix;
mfiore 0:bb4e812f7c97 1483
mfiore 0:bb4e812f7c97 1484 res = spiffs_page_index_check(fs, fd, objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 1485 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1486
mfiore 0:bb4e812f7c97 1487 // move and update object index page
mfiore 0:bb4e812f7c97 1488 res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix_hdr, fd->obj_id, 0, objix_pix, &new_objix_pix);
mfiore 0:bb4e812f7c97 1489 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1490 spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
mfiore 0:bb4e812f7c97 1491 SPIFFS_DBG("truncate: store modified objix page, %04x:%04x\n", new_objix_pix, cur_objix_spix);
mfiore 0:bb4e812f7c97 1492 fd->cursor_objix_pix = new_objix_pix;
mfiore 0:bb4e812f7c97 1493 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1494 fd->offset = cur_size;
mfiore 0:bb4e812f7c97 1495 // update object index header page with new size
mfiore 0:bb4e812f7c97 1496 res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
mfiore 0:bb4e812f7c97 1497 fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
mfiore 0:bb4e812f7c97 1498 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1499 }
mfiore 0:bb4e812f7c97 1500 fd->size = cur_size;
mfiore 0:bb4e812f7c97 1501
mfiore 0:bb4e812f7c97 1502 return res;
mfiore 0:bb4e812f7c97 1503 }
mfiore 0:bb4e812f7c97 1504
mfiore 0:bb4e812f7c97 1505 s32_t spiffs_object_read(
mfiore 0:bb4e812f7c97 1506 spiffs_fd *fd,
mfiore 0:bb4e812f7c97 1507 u32_t offset,
mfiore 0:bb4e812f7c97 1508 u32_t len,
mfiore 0:bb4e812f7c97 1509 u8_t *dst) {
mfiore 0:bb4e812f7c97 1510 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1511 spiffs *fs = fd->fs;
mfiore 0:bb4e812f7c97 1512 spiffs_page_ix objix_pix;
mfiore 0:bb4e812f7c97 1513 spiffs_page_ix data_pix;
mfiore 0:bb4e812f7c97 1514 spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
mfiore 0:bb4e812f7c97 1515 u32_t cur_offset = offset;
mfiore 0:bb4e812f7c97 1516 spiffs_span_ix cur_objix_spix;
mfiore 0:bb4e812f7c97 1517 spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
mfiore 0:bb4e812f7c97 1518 spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
mfiore 0:bb4e812f7c97 1519 spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
mfiore 0:bb4e812f7c97 1520
mfiore 0:bb4e812f7c97 1521 while (cur_offset < offset + len) {
mfiore 0:bb4e812f7c97 1522 cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
mfiore 0:bb4e812f7c97 1523 if (prev_objix_spix != cur_objix_spix) {
mfiore 0:bb4e812f7c97 1524 // load current object index (header) page
mfiore 0:bb4e812f7c97 1525 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1526 objix_pix = fd->objix_hdr_pix;
mfiore 0:bb4e812f7c97 1527 } else {
mfiore 0:bb4e812f7c97 1528 SPIFFS_DBG("read: find objix %04x:%04x\n", fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 1529 res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
mfiore 0:bb4e812f7c97 1530 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1531 }
mfiore 0:bb4e812f7c97 1532 SPIFFS_DBG("read: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
mfiore 0:bb4e812f7c97 1533 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1534 fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
mfiore 0:bb4e812f7c97 1535 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1536 SPIFFS_VALIDATE_OBJIX(objix->p_hdr, fd->obj_id, cur_objix_spix);
mfiore 0:bb4e812f7c97 1537
mfiore 0:bb4e812f7c97 1538 fd->offset = cur_offset;
mfiore 0:bb4e812f7c97 1539 fd->cursor_objix_pix = objix_pix;
mfiore 0:bb4e812f7c97 1540 fd->cursor_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1541
mfiore 0:bb4e812f7c97 1542 prev_objix_spix = cur_objix_spix;
mfiore 0:bb4e812f7c97 1543 }
mfiore 0:bb4e812f7c97 1544
mfiore 0:bb4e812f7c97 1545 if (cur_objix_spix == 0) {
mfiore 0:bb4e812f7c97 1546 // get data page from object index header page
Mike Fiore 2:de478b250060 1547 data_pix = ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
mfiore 0:bb4e812f7c97 1548 } else {
mfiore 0:bb4e812f7c97 1549 // get data page from object index page
Mike Fiore 2:de478b250060 1550 data_pix = ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
mfiore 0:bb4e812f7c97 1551 }
mfiore 0:bb4e812f7c97 1552
mfiore 0:bb4e812f7c97 1553 // all remaining data
mfiore 0:bb4e812f7c97 1554 u32_t len_to_read = offset + len - cur_offset;
mfiore 0:bb4e812f7c97 1555 // remaining data in page
mfiore 0:bb4e812f7c97 1556 len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
mfiore 0:bb4e812f7c97 1557 // remaining data in file
mfiore 0:bb4e812f7c97 1558 len_to_read = MIN(len_to_read, fd->size);
mfiore 0:bb4e812f7c97 1559 SPIFFS_DBG("read: offset:%i rd:%i data spix:%04x is data_pix:%04x addr:%08x\n", cur_offset, len_to_read, data_spix, data_pix,
mfiore 0:bb4e812f7c97 1560 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
mfiore 0:bb4e812f7c97 1561 if (len_to_read <= 0) {
mfiore 0:bb4e812f7c97 1562 res = SPIFFS_ERR_END_OF_OBJECT;
mfiore 0:bb4e812f7c97 1563 break;
mfiore 0:bb4e812f7c97 1564 }
mfiore 0:bb4e812f7c97 1565 res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
mfiore 0:bb4e812f7c97 1566 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1567 res = _spiffs_rd(
mfiore 0:bb4e812f7c97 1568 fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1569 fd->file_nbr,
mfiore 0:bb4e812f7c97 1570 SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)),
mfiore 0:bb4e812f7c97 1571 len_to_read,
mfiore 0:bb4e812f7c97 1572 dst);
mfiore 0:bb4e812f7c97 1573 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1574 dst += len_to_read;
mfiore 0:bb4e812f7c97 1575 cur_offset += len_to_read;
mfiore 0:bb4e812f7c97 1576 fd->offset = cur_offset;
mfiore 0:bb4e812f7c97 1577 data_spix++;
mfiore 0:bb4e812f7c97 1578 }
mfiore 0:bb4e812f7c97 1579
mfiore 0:bb4e812f7c97 1580 return res;
mfiore 0:bb4e812f7c97 1581 }
mfiore 0:bb4e812f7c97 1582
mfiore 0:bb4e812f7c97 1583 typedef struct {
mfiore 0:bb4e812f7c97 1584 spiffs_obj_id min_obj_id;
mfiore 0:bb4e812f7c97 1585 spiffs_obj_id max_obj_id;
mfiore 0:bb4e812f7c97 1586 u32_t compaction;
mfiore 0:bb4e812f7c97 1587 } spiffs_free_obj_id_state;
mfiore 0:bb4e812f7c97 1588
mfiore 0:bb4e812f7c97 1589 static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
mfiore 0:bb4e812f7c97 1590 u32_t user_data, void *user_p) {
mfiore 0:bb4e812f7c97 1591 if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
mfiore 0:bb4e812f7c97 1592 spiffs_obj_id min_obj_id = user_data;
mfiore 0:bb4e812f7c97 1593 id &= ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 1594 int bit_ix = (id-min_obj_id) & 7;
mfiore 0:bb4e812f7c97 1595 int byte_ix = (id-min_obj_id) >> 3;
mfiore 0:bb4e812f7c97 1596 if (byte_ix >= 0 && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
mfiore 0:bb4e812f7c97 1597 fs->work[byte_ix] |= (1<<bit_ix);
mfiore 0:bb4e812f7c97 1598 }
mfiore 0:bb4e812f7c97 1599 }
mfiore 0:bb4e812f7c97 1600 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 1601 }
mfiore 0:bb4e812f7c97 1602
mfiore 0:bb4e812f7c97 1603 static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
mfiore 0:bb4e812f7c97 1604 u32_t user_data, void *user_p) {
mfiore 0:bb4e812f7c97 1605 if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
mfiore 0:bb4e812f7c97 1606 s32_t res;
mfiore 0:bb4e812f7c97 1607 spiffs_free_obj_id_state *state = (spiffs_free_obj_id_state *)user_p;
mfiore 0:bb4e812f7c97 1608 spiffs_page_header ph;
mfiore 0:bb4e812f7c97 1609
mfiore 0:bb4e812f7c97 1610 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
mfiore 0:bb4e812f7c97 1611 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, ix_entry), sizeof(spiffs_page_header), (u8_t*)&ph);
mfiore 0:bb4e812f7c97 1612 if (res == SPIFFS_OK && ph.span_ix == 0 &&
mfiore 0:bb4e812f7c97 1613 ((ph.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
mfiore 0:bb4e812f7c97 1614 (SPIFFS_PH_FLAG_DELET))) {
mfiore 0:bb4e812f7c97 1615 // ok object look up entry
mfiore 0:bb4e812f7c97 1616 id &= ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 1617 if (id >= state->min_obj_id && id <= state->max_obj_id) {
mfiore 0:bb4e812f7c97 1618 u8_t *map = (u8_t *)fs->work;
mfiore 0:bb4e812f7c97 1619 int ix = (id - state->min_obj_id) / state->compaction;
mfiore 0:bb4e812f7c97 1620 //SPIFFS_DBG("free_obj_id: add ix %i for id %04x min:%04x max%04x comp:%i\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction);
mfiore 0:bb4e812f7c97 1621 map[ix]++;
mfiore 0:bb4e812f7c97 1622 }
mfiore 0:bb4e812f7c97 1623 }
mfiore 0:bb4e812f7c97 1624 }
mfiore 0:bb4e812f7c97 1625 return SPIFFS_VIS_COUNTINUE;
mfiore 0:bb4e812f7c97 1626 }
mfiore 0:bb4e812f7c97 1627
mfiore 0:bb4e812f7c97 1628 // Scans thru all object lookup for object index header pages. If total possible number of
mfiore 0:bb4e812f7c97 1629 // object ids cannot fit into a work buffer, these are grouped. When a group containing free
mfiore 0:bb4e812f7c97 1630 // object ids is found, the object lu is again scanned for object ids within group and bitmasked.
mfiore 0:bb4e812f7c97 1631 // Finally, the bitmasked is searched for a free id
mfiore 0:bb4e812f7c97 1632 s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
mfiore 0:bb4e812f7c97 1633 s32_t res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1634 u32_t max_objects = (SPIFFS_CFG_PHYS_SZ(fs) / (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) / 2;
mfiore 0:bb4e812f7c97 1635 spiffs_free_obj_id_state state;
mfiore 0:bb4e812f7c97 1636 spiffs_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE;
mfiore 0:bb4e812f7c97 1637 state.min_obj_id = 1;
mfiore 0:bb4e812f7c97 1638 state.max_obj_id = max_objects + 1;
mfiore 0:bb4e812f7c97 1639 if (state.max_obj_id & SPIFFS_OBJ_ID_IX_FLAG) {
mfiore 0:bb4e812f7c97 1640 state.max_obj_id = ((spiffs_obj_id)-1) & ~SPIFFS_OBJ_ID_IX_FLAG;
mfiore 0:bb4e812f7c97 1641 }
mfiore 0:bb4e812f7c97 1642 state.compaction = 0;
mfiore 0:bb4e812f7c97 1643 while (res == SPIFFS_OK && free_obj_id == SPIFFS_OBJ_ID_FREE) {
mfiore 0:bb4e812f7c97 1644 if (state.max_obj_id - state.min_obj_id <= SPIFFS_CFG_LOG_PAGE_SZ(fs)*8) {
mfiore 0:bb4e812f7c97 1645 // possible to represent in bitmap
mfiore 0:bb4e812f7c97 1646 int i, j;
mfiore 0:bb4e812f7c97 1647 SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id);
mfiore 0:bb4e812f7c97 1648
mfiore 0:bb4e812f7c97 1649 memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 1650 res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id, 0, 0, 0);
mfiore 0:bb4e812f7c97 1651 if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1652 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1653 // traverse bitmask until found free obj_id
mfiore 0:bb4e812f7c97 1654 for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs); i++) {
mfiore 0:bb4e812f7c97 1655 u8_t mask = fs->work[i];
mfiore 0:bb4e812f7c97 1656 if (mask == 0xff) {
mfiore 0:bb4e812f7c97 1657 continue;
mfiore 0:bb4e812f7c97 1658 }
mfiore 0:bb4e812f7c97 1659 for (j = 0; j < 8; j++) {
mfiore 0:bb4e812f7c97 1660 if ((mask & (1<<j)) == 0) {
mfiore 0:bb4e812f7c97 1661 *obj_id = (i<<3)+j+state.min_obj_id;
mfiore 0:bb4e812f7c97 1662 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 1663 }
mfiore 0:bb4e812f7c97 1664 }
mfiore 0:bb4e812f7c97 1665 }
mfiore 0:bb4e812f7c97 1666 return SPIFFS_ERR_FULL;
mfiore 0:bb4e812f7c97 1667 } else {
mfiore 0:bb4e812f7c97 1668 // not possible to represent all ids in range in a bitmap, compact and count
mfiore 0:bb4e812f7c97 1669 if (state.compaction != 0) {
mfiore 0:bb4e812f7c97 1670 // select element in compacted table, decrease range and recompact
mfiore 0:bb4e812f7c97 1671 int i, min_i = 0;
mfiore 0:bb4e812f7c97 1672 u8_t *map = (u8_t *)fs->work;
mfiore 0:bb4e812f7c97 1673 u8_t min_count = 0xff;
mfiore 0:bb4e812f7c97 1674
mfiore 0:bb4e812f7c97 1675 for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(u8_t); i++) {
mfiore 0:bb4e812f7c97 1676 if (map[i] < min_count) {
mfiore 0:bb4e812f7c97 1677 min_count = map[i];
mfiore 0:bb4e812f7c97 1678 min_i = i;
mfiore 0:bb4e812f7c97 1679 if (min_count == 0) {
mfiore 0:bb4e812f7c97 1680 break;
mfiore 0:bb4e812f7c97 1681 }
mfiore 0:bb4e812f7c97 1682 }
mfiore 0:bb4e812f7c97 1683 }
mfiore 0:bb4e812f7c97 1684
mfiore 0:bb4e812f7c97 1685 if (min_count == state.compaction) {
mfiore 0:bb4e812f7c97 1686 // there are no free objids!
mfiore 0:bb4e812f7c97 1687 SPIFFS_DBG("free_obj_id: compacted table is full\n");
mfiore 0:bb4e812f7c97 1688 return SPIFFS_ERR_FULL;
mfiore 0:bb4e812f7c97 1689 }
mfiore 0:bb4e812f7c97 1690
mfiore 0:bb4e812f7c97 1691 SPIFFS_DBG("free_obj_id: COMP select index:%i min_count:%i min:%04x max:%04x compact:%i\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction);
mfiore 0:bb4e812f7c97 1692
mfiore 0:bb4e812f7c97 1693 if (min_count == 0) {
mfiore 0:bb4e812f7c97 1694 // no id in this range, skip compacting and use directly
mfiore 0:bb4e812f7c97 1695 *obj_id = min_i * state.compaction + state.min_obj_id;
mfiore 0:bb4e812f7c97 1696 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 1697 } else {
mfiore 0:bb4e812f7c97 1698 SPIFFS_DBG("free_obj_id: COMP SEL chunk:%04x min:%04x -> %04x\n", state.compaction, state.min_obj_id, state.min_obj_id + min_i * state.compaction);
mfiore 0:bb4e812f7c97 1699 state.min_obj_id += min_i * state.compaction;
mfiore 0:bb4e812f7c97 1700 state.max_obj_id = state.min_obj_id + state.compaction;
mfiore 0:bb4e812f7c97 1701 // decrease compaction
mfiore 0:bb4e812f7c97 1702 }
mfiore 0:bb4e812f7c97 1703 if ((state.max_obj_id - state.min_obj_id <= SPIFFS_CFG_LOG_PAGE_SZ(fs)*8)) {
mfiore 0:bb4e812f7c97 1704 // no need for compacting, use bitmap
mfiore 0:bb4e812f7c97 1705 continue;
mfiore 0:bb4e812f7c97 1706 }
mfiore 0:bb4e812f7c97 1707 }
mfiore 0:bb4e812f7c97 1708 // in a work memory of log_page_size bytes, we may fit in log_page_size ids
mfiore 0:bb4e812f7c97 1709 // todo what if compaction is > 255 - then we cannot fit it in a byte
mfiore 0:bb4e812f7c97 1710 state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));
mfiore 0:bb4e812f7c97 1711 SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction);
mfiore 0:bb4e812f7c97 1712
mfiore 0:bb4e812f7c97 1713 memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
mfiore 0:bb4e812f7c97 1714 res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, 0, &state, 0, 0);
mfiore 0:bb4e812f7c97 1715 if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
mfiore 0:bb4e812f7c97 1716 SPIFFS_CHECK_RES(res);
mfiore 0:bb4e812f7c97 1717 }
mfiore 0:bb4e812f7c97 1718 }
mfiore 0:bb4e812f7c97 1719
mfiore 0:bb4e812f7c97 1720 return res;
mfiore 0:bb4e812f7c97 1721 }
mfiore 0:bb4e812f7c97 1722
mfiore 0:bb4e812f7c97 1723 s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
mfiore 0:bb4e812f7c97 1724 int i;
mfiore 0:bb4e812f7c97 1725 spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
mfiore 0:bb4e812f7c97 1726 for (i = 0; i < fs->fd_count; i++) {
mfiore 0:bb4e812f7c97 1727 spiffs_fd *cur_fd = &fds[i];
mfiore 0:bb4e812f7c97 1728 if (cur_fd->file_nbr == 0) {
mfiore 0:bb4e812f7c97 1729 cur_fd->file_nbr = i+1;
mfiore 0:bb4e812f7c97 1730 *fd = cur_fd;
mfiore 0:bb4e812f7c97 1731 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 1732 }
mfiore 0:bb4e812f7c97 1733 }
mfiore 0:bb4e812f7c97 1734 return SPIFFS_ERR_OUT_OF_FILE_DESCS;
mfiore 0:bb4e812f7c97 1735 }
mfiore 0:bb4e812f7c97 1736
mfiore 0:bb4e812f7c97 1737 s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
mfiore 0:bb4e812f7c97 1738 if (f <= 0 || f > fs->fd_count) {
mfiore 0:bb4e812f7c97 1739 return SPIFFS_ERR_BAD_DESCRIPTOR;
mfiore 0:bb4e812f7c97 1740 }
mfiore 0:bb4e812f7c97 1741 spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
mfiore 0:bb4e812f7c97 1742 spiffs_fd *fd = &fds[f-1];
mfiore 0:bb4e812f7c97 1743 if (fd->file_nbr == 0) {
mfiore 0:bb4e812f7c97 1744 return SPIFFS_ERR_FILE_CLOSED;
mfiore 0:bb4e812f7c97 1745 }
mfiore 0:bb4e812f7c97 1746 fd->file_nbr = 0;
mfiore 0:bb4e812f7c97 1747 return SPIFFS_OK;
mfiore 0:bb4e812f7c97 1748 }
mfiore 0:bb4e812f7c97 1749
mfiore 0:bb4e812f7c97 1750 s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
mfiore 0:bb4e812f7c97 1751 if (f <= 0 || f > fs->fd_count) {
mfiore 0:bb4e812f7c97 1752 return SPIFFS_ERR_BAD_DESCRIPTOR;
mfiore 0:bb4e812f7c97 1753 }
mfiore 0:bb4e812f7c97 1754 spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
mfiore 0:bb4e812f7c97 1755 *fd = &fds[f-1];
mfiore 0:bb4e812f7c97 1756 if ((*fd)->file_nbr == 0) {
mfiore 0:bb4e812f7c97 1757 return SPIFFS_ERR_FILE_CLOSED;
mfiore 0:bb4e812f7c97 1758 }
mfiore 0:bb4e812f7c97 1759 return SPIFFS_OK;
Mike Fiore 2:de478b250060 1760 }