123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899 |
- #include "spiffs.h"
- #include "spiffs_nucleus.h"
- static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
- s32_t res = SPIFFS_OK;
- if (pix == (spiffs_page_ix)-1) {
- // referring to page 0xffff...., bad object index
- return SPIFFS_ERR_INDEX_REF_FREE;
- }
- if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- // referring to an object lookup page, bad object index
- return SPIFFS_ERR_INDEX_REF_LU;
- }
- if (pix > SPIFFS_MAX_PAGES(fs)) {
- // referring to a bad page
- return SPIFFS_ERR_INDEX_REF_INVALID;
- }
- #if SPIFFS_PAGE_CHECK
- spiffs_page_header ph;
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, pix),
- sizeof(spiffs_page_header),
- (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_DATA(ph, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, spix);
- #endif
- return res;
- }
- static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
- s32_t res = SPIFFS_OK;
- if (pix == (spiffs_page_ix)-1) {
- // referring to page 0xffff...., bad object index
- return SPIFFS_ERR_INDEX_FREE;
- }
- if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- // referring to an object lookup page, bad object index
- return SPIFFS_ERR_INDEX_LU;
- }
- if (pix > SPIFFS_MAX_PAGES(fs)) {
- // referring to a bad page
- return SPIFFS_ERR_INDEX_INVALID;
- }
- #if SPIFFS_PAGE_CHECK
- spiffs_page_header ph;
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, pix),
- sizeof(spiffs_page_header),
- (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(ph, fd->obj_id, spix);
- #endif
- return res;
- }
- #if !SPIFFS_CACHE
- s32_t spiffs_phys_rd(
- spiffs *fs,
- u32_t addr,
- u32_t len,
- u8_t *dst) {
- return fs->cfg.hal_read_f(addr, len, dst);
- }
- s32_t spiffs_phys_wr(
- spiffs *fs,
- u32_t addr,
- u32_t len,
- u8_t *src) {
- return fs->cfg.hal_write_f(addr, len, src);
- }
- #endif
- s32_t spiffs_phys_cpy(
- spiffs *fs,
- spiffs_file fh,
- u32_t dst,
- u32_t src,
- u32_t len) {
- s32_t res;
- u8_t b[SPIFFS_COPY_BUFFER_STACK];
- while (len > 0) {
- u32_t chunk_size = MIN(SPIFFS_COPY_BUFFER_STACK, len);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVS, fh, src, chunk_size, b);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_MOVD, fh, dst, chunk_size, b);
- SPIFFS_CHECK_RES(res);
- len -= chunk_size;
- src += chunk_size;
- dst += chunk_size;
- }
- return SPIFFS_OK;
- }
- // Find object lookup entry containing given id with visitor.
- // Iterate over object lookup pages in each block until a given object id entry is found.
- // When found, the visitor function is called with block index, entry index and user_data.
- // If visitor returns SPIFFS_VIS_CONTINUE, the search goes on. Otherwise, the search will be
- // ended and visitor's return code is returned to caller.
- // If no visitor is given (0) the search returns on first entry with matching object id.
- // If no match is found in all look up, SPIFFS_VIS_END is returned.
- // @param fs the file system
- // @param starting_block the starting block to start search in
- // @param starting_lu_entry the look up index entry to start search in
- // @param flags ored combination of SPIFFS_VIS_CHECK_ID, SPIFFS_VIS_CHECK_PH,
- // SPIFFS_VIS_NO_WRAP
- // @param obj_id argument object id
- // @param v visitor callback function
- // @param user_data any data, passed to the callback visitor function
- // @param user_p any pointer, passed to the callback visitor function
- // @param block_ix reported block index where match was found
- // @param lu_entry reported look up index where match was found
- s32_t spiffs_obj_lu_find_entry_visitor(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- u8_t flags,
- spiffs_obj_id obj_id,
- spiffs_visitor_f v,
- u32_t user_data,
- void *user_p,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res = SPIFFS_OK;
- s32_t entry_count = fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs);
- spiffs_block_ix cur_block = starting_block;
- u32_t cur_block_addr = starting_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
- int cur_entry = starting_lu_entry;
- int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
- // wrap initial
- if (cur_entry >= (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) - 1) {
- cur_entry = 0;
- cur_block++;
- cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- if (cur_block >= fs->block_count) {
- if (flags & SPIFFS_VIS_NO_WRAP) {
- return SPIFFS_VIS_END;
- } else {
- // block wrap
- cur_block = 0;
- cur_block_addr = 0;
- }
- }
- }
- // check each block
- while (res == SPIFFS_OK && entry_count > 0) {
- int obj_lookup_page = cur_entry / entries_per_page;
- // check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
- int entry_offset = obj_lookup_page * entries_per_page;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- // check each entry
- while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && // for non-last obj lookup pages
- cur_entry < (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) // for last obj lookup page
- {
- if ((flags & SPIFFS_VIS_CHECK_ID) == 0 || obj_lu_buf[cur_entry-entry_offset] == obj_id) {
- if (block_ix) *block_ix = cur_block;
- if (lu_entry) *lu_entry = cur_entry;
- if (v) {
- res = v(
- fs,
- (flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry-entry_offset],
- cur_block,
- cur_entry,
- user_data,
- user_p);
- if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
- if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
- SPIFFS_CHECK_RES(res);
- }
- res = SPIFFS_OK;
- cur_entry++;
- entry_count--;
- continue;
- } else {
- return res;
- }
- } else {
- return SPIFFS_OK;
- }
- }
- entry_count--;
- cur_entry++;
- } // per entry
- obj_lookup_page++;
- } // per object lookup page
- cur_entry = 0;
- cur_block++;
- cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- if (cur_block >= fs->block_count) {
- if (flags & SPIFFS_VIS_NO_WRAP) {
- return SPIFFS_VIS_END;
- } else {
- // block wrap
- cur_block = 0;
- cur_block_addr = 0;
- }
- }
- } // per block
- SPIFFS_CHECK_RES(res);
- return SPIFFS_VIS_END;
- }
- s32_t spiffs_erase_block(
- spiffs *fs,
- spiffs_block_ix bix) {
- s32_t res;
- u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
- s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
- // here we ignore res, just try erasing the block
- while (size > 0) {
- SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
- (void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
- addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
- size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
- }
- fs->free_blocks++;
- // register erase count for this block
- res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_ERASE_COUNT_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
- SPIFFS_CHECK_RES(res);
- #if SPIFFS_USE_MAGIC
- // finally, write magic
- spiffs_obj_id magic = SPIFFS_MAGIC(fs);
- res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
- SPIFFS_MAGIC_PADDR(fs, bix),
- sizeof(spiffs_obj_id), (u8_t *)&magic);
- SPIFFS_CHECK_RES(res);
- #endif
- fs->max_erase_count++;
- if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
- fs->max_erase_count = 0;
- }
- return res;
- }
- static s32_t spiffs_obj_lu_scan_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- u32_t user_data,
- void *user_p) {
- (void)bix;
- (void)user_data;
- (void)user_p;
- if (obj_id == SPIFFS_OBJ_ID_FREE) {
- if (ix_entry == 0) {
- fs->free_blocks++;
- // todo optimize further, return SPIFFS_NEXT_BLOCK
- }
- } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
- fs->stats_p_deleted++;
- } else {
- fs->stats_p_allocated++;
- }
- return SPIFFS_VIS_COUNTINUE;
- }
- // Scans thru all obj lu and counts free, deleted and used pages
- // Find the maximum block erase count
- // Checks magic if enabled
- s32_t spiffs_obj_lu_scan(
- spiffs *fs) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
- #if SPIFFS_USE_MAGIC
- spiffs_block_ix unerased_bix = (spiffs_block_ix)-1;
- #endif
- // find out erase count
- // if enabled, check magic
- bix = 0;
- spiffs_obj_id erase_count_final;
- spiffs_obj_id erase_count_min = SPIFFS_OBJ_ID_FREE;
- spiffs_obj_id erase_count_max = 0;
- while (bix < fs->block_count) {
- #if SPIFFS_USE_MAGIC
- spiffs_obj_id magic;
- res = _spiffs_rd(fs,
- SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_MAGIC_PADDR(fs, bix) ,
- sizeof(spiffs_obj_id), (u8_t *)&magic);
- SPIFFS_CHECK_RES(res);
- if (magic != SPIFFS_MAGIC(fs)) {
- if (unerased_bix == (spiffs_block_ix)-1) {
- // allow one unerased block as it might be powered down during an erase
- unerased_bix = bix;
- } else {
- // more than one unerased block, bail out
- SPIFFS_CHECK_RES(SPIFFS_ERR_NOT_A_FS);
- }
- }
- #endif
- spiffs_obj_id erase_count;
- res = _spiffs_rd(fs,
- SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_ERASE_COUNT_PADDR(fs, bix) ,
- sizeof(spiffs_obj_id), (u8_t *)&erase_count);
- SPIFFS_CHECK_RES(res);
- if (erase_count != SPIFFS_OBJ_ID_FREE) {
- erase_count_min = MIN(erase_count_min, erase_count);
- erase_count_max = MAX(erase_count_max, erase_count);
- }
- bix++;
- }
- if (erase_count_min == 0 && erase_count_max == SPIFFS_OBJ_ID_FREE) {
- // clean system, set counter to zero
- erase_count_final = 0;
- } else if (erase_count_max - erase_count_min > (SPIFFS_OBJ_ID_FREE)/2) {
- // wrap, take min
- erase_count_final = erase_count_min+1;
- } else {
- erase_count_final = erase_count_max+1;
- }
- fs->max_erase_count = erase_count_final;
- #if SPIFFS_USE_MAGIC
- if (unerased_bix != (spiffs_block_ix)-1) {
- // found one unerased block, remedy
- SPIFFS_DBG("mount: erase block %i\n", bix);
- res = spiffs_erase_block(fs, unerased_bix);
- SPIFFS_CHECK_RES(res);
- }
- #endif
- // count blocks
- fs->free_blocks = 0;
- fs->stats_p_allocated = 0;
- fs->stats_p_deleted = 0;
- res = spiffs_obj_lu_find_entry_visitor(fs,
- 0,
- 0,
- 0,
- 0,
- spiffs_obj_lu_scan_v,
- 0,
- 0,
- &bix,
- &entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_OK;
- }
- SPIFFS_CHECK_RES(res);
- return res;
- }
- // Find free object lookup entry
- // Iterate over object lookup pages in each block until a free object id entry is found
- s32_t spiffs_obj_lu_find_free(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res;
- if (!fs->cleaning && fs->free_blocks < 2) {
- res = spiffs_gc_quick(fs, 0);
- if (res == SPIFFS_ERR_NO_DELETED_BLOCKS) {
- res = SPIFFS_OK;
- }
- SPIFFS_CHECK_RES(res);
- if (fs->free_blocks < 2) {
- return SPIFFS_ERR_FULL;
- }
- }
- res = spiffs_obj_lu_find_id(fs, starting_block, starting_lu_entry,
- SPIFFS_OBJ_ID_FREE, block_ix, lu_entry);
- if (res == SPIFFS_OK) {
- fs->free_cursor_block_ix = *block_ix;
- fs->free_cursor_obj_lu_entry = *lu_entry;
- if (*lu_entry == 0) {
- fs->free_blocks--;
- }
- }
- if (res == SPIFFS_VIS_END) {
- SPIFFS_DBG("fs full\n");
- }
- return res == SPIFFS_VIS_END ? SPIFFS_ERR_FULL : res;
- }
- // Find object lookup entry containing given id
- // Iterate over object lookup pages in each block until a given object id entry is found
- s32_t spiffs_obj_lu_find_id(
- spiffs *fs,
- spiffs_block_ix starting_block,
- int starting_lu_entry,
- spiffs_obj_id obj_id,
- spiffs_block_ix *block_ix,
- int *lu_entry) {
- s32_t res = spiffs_obj_lu_find_entry_visitor(
- fs, starting_block, starting_lu_entry, SPIFFS_VIS_CHECK_ID, obj_id, 0, 0, 0, block_ix, lu_entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- return res;
- }
- static s32_t spiffs_obj_lu_find_id_and_span_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- u32_t user_data,
- void *user_p) {
- s32_t res;
- spiffs_page_header ph;
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- res = _spiffs_rd(fs, 0, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
- SPIFFS_CHECK_RES(res);
- if (ph.obj_id == obj_id &&
- ph.span_ix == (spiffs_span_ix)user_data &&
- (ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET &&
- !((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) &&
- (user_p == 0 || *((spiffs_page_ix *)user_p) != pix)) {
- return SPIFFS_OK;
- } else {
- return SPIFFS_VIS_COUNTINUE;
- }
- }
- // Find object lookup entry containing given id and span index
- // Iterate over object lookup pages in each block until a given object id entry is found
- s32_t spiffs_obj_lu_find_id_and_span(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- SPIFFS_VIS_CHECK_ID,
- obj_id,
- spiffs_obj_lu_find_id_and_span_v,
- (u32_t)spix,
- exclusion_pix ? &exclusion_pix : 0,
- &bix,
- &entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- SPIFFS_CHECK_RES(res);
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
- return res;
- }
- // Find object lookup entry containing given id and span index in page headers only
- // Iterate over object lookup pages in each block until a given object id entry is found
- s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix exclusion_pix,
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- SPIFFS_VIS_CHECK_PH,
- obj_id,
- spiffs_obj_lu_find_id_and_span_v,
- (u32_t)spix,
- exclusion_pix ? &exclusion_pix : 0,
- &bix,
- &entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- SPIFFS_CHECK_RES(res);
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
- return res;
- }
- // Allocates a free defined page with given obj_id
- // Occupies object lookup entry and page
- // data may be NULL; where only page header is stored, len and page_offs is ignored
- s32_t spiffs_page_allocate_data(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_page_header *ph,
- u8_t *data,
- u32_t len,
- u32_t page_offs,
- u8_t finalize,
- spiffs_page_ix *pix) {
- s32_t res = SPIFFS_OK;
- spiffs_block_ix bix;
- int entry;
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- // occupy page in object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&obj_id);
- SPIFFS_CHECK_RES(res);
- fs->stats_p_allocated++;
- // write page header
- ph->flags &= ~SPIFFS_PH_FLAG_USED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_header), (u8_t*)ph);
- SPIFFS_CHECK_RES(res);
- // write page data
- if (data) {
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0,SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + sizeof(spiffs_page_header) + page_offs, len, data);
- SPIFFS_CHECK_RES(res);
- }
- // finalize header if necessary
- if (finalize && (ph->flags & SPIFFS_PH_FLAG_FINAL)) {
- ph->flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&ph->flags);
- SPIFFS_CHECK_RES(res);
- }
- // return written page
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
- return res;
- }
- // Moves a page from src to a free page and finalizes it. Updates page index. Page data is given in param page.
- // If page data is null, provided header is used for metainfo and page data is physically copied.
- s32_t spiffs_page_move(
- spiffs *fs,
- spiffs_file fh,
- u8_t *page_data,
- spiffs_obj_id obj_id,
- spiffs_page_header *page_hdr,
- spiffs_page_ix src_pix,
- spiffs_page_ix *dst_pix) {
- s32_t res;
- u8_t was_final = 0;
- spiffs_page_header *p_hdr;
- spiffs_block_ix bix;
- int entry;
- spiffs_page_ix free_pix;
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- if (dst_pix) *dst_pix = free_pix;
- p_hdr = page_data ? (spiffs_page_header *)page_data : page_hdr;
- if (page_data) {
- // got page data
- was_final = (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) == 0;
- // write unfinalized page
- p_hdr->flags |= SPIFFS_PH_FLAG_FINAL;
- p_hdr->flags &= ~SPIFFS_PH_FLAG_USED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), page_data);
- } else {
- // copy page data
- 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));
- }
- SPIFFS_CHECK_RES(res);
- // mark entry in destination object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 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),
- sizeof(spiffs_obj_id),
- (u8_t *)&obj_id);
- SPIFFS_CHECK_RES(res);
- fs->stats_p_allocated++;
- if (was_final) {
- // mark finalized in destination page
- p_hdr->flags &= ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_USED);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fh,
- SPIFFS_PAGE_TO_PADDR(fs, free_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr->flags);
- SPIFFS_CHECK_RES(res);
- }
- // mark source deleted
- res = spiffs_page_delete(fs, src_pix);
- return res;
- }
- // Deletes a page and removes it from object lookup.
- s32_t spiffs_page_delete(
- spiffs *fs,
- spiffs_page_ix pix) {
- s32_t res;
- spiffs_page_header hdr;
- hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED);
- // mark deleted entry in source object lookup
- spiffs_obj_id d_obj_id = SPIFFS_OBJ_ID_DELETED;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_DELE,
- 0,
- SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_page_ix),
- sizeof(spiffs_obj_id),
- (u8_t *)&d_obj_id);
- SPIFFS_CHECK_RES(res);
- fs->stats_p_deleted++;
- fs->stats_p_allocated--;
- // mark deleted in source page
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_DELE,
- 0,
- SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&hdr.flags);
- return res;
- }
- // Create an object index header page with empty index and undefined length
- s32_t spiffs_object_create(
- spiffs *fs,
- spiffs_obj_id obj_id,
- u8_t name[SPIFFS_OBJ_NAME_LEN],
- spiffs_obj_type type,
- spiffs_page_ix *objix_hdr_pix) {
- s32_t res = SPIFFS_OK;
- spiffs_block_ix bix;
- spiffs_page_object_ix_header oix_hdr;
- int entry;
- res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
- obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
- // find free entry
- res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("create: found free page @ %04x bix:%i entry:%i\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
- // occupy page in object lookup
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&obj_id);
- SPIFFS_CHECK_RES(res);
- fs->stats_p_allocated++;
- // write empty object index page
- oix_hdr.p_hdr.obj_id = obj_id;
- oix_hdr.p_hdr.span_ix = 0;
- oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED);
- oix_hdr.type = type;
- oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page
- strncpy((char *)&oix_hdr.name, (char *)name, SPIFFS_OBJ_NAME_LEN);
- // update page
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_object_ix_header), (u8_t*)&oix_hdr);
- SPIFFS_CHECK_RES(res);
- 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);
- if (objix_hdr_pix) {
- *objix_hdr_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
- return res;
- }
- // update object index header with any combination of name/size/index
- // new_objix_hdr_data may be null, if so the object index header page is loaded
- // name may be null, if so name is not changed
- // size may be null, if so size is not changed
- s32_t spiffs_object_update_index_hdr(
- spiffs *fs,
- spiffs_fd *fd,
- spiffs_obj_id obj_id,
- spiffs_page_ix objix_hdr_pix,
- u8_t *new_objix_hdr_data,
- u8_t name[SPIFFS_OBJ_NAME_LEN],
- u32_t size,
- spiffs_page_ix *new_pix) {
- s32_t res = SPIFFS_OK;
- spiffs_page_object_ix_header *objix_hdr;
- spiffs_page_ix new_objix_hdr_pix;
- obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
- if (new_objix_hdr_data) {
- // object index header page already given to us, no need to load it
- objix_hdr = (spiffs_page_object_ix_header *)new_objix_hdr_data;
- } else {
- // read object index header page
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- }
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, obj_id, 0);
- // change name
- if (name) {
- strncpy((char *)objix_hdr->name, (char *)name, SPIFFS_OBJ_NAME_LEN);
- }
- if (size) {
- objix_hdr->size = size;
- }
- // move and update page
- 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);
- if (res == SPIFFS_OK) {
- if (new_pix) {
- *new_pix = new_objix_hdr_pix;
- }
- // callback on object index update
- 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);
- if (fd) fd->objix_hdr_pix = new_objix_hdr_pix; // if this is not in the registered cluster
- }
- return res;
- }
- void spiffs_cb_object_event(
- spiffs *fs,
- spiffs_fd *fd,
- int ev,
- spiffs_obj_id obj_id,
- spiffs_span_ix spix,
- spiffs_page_ix new_pix,
- u32_t new_size) {
- (void)fd;
- // update index caches in all file descriptors
- obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr == 0 || (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue;
- if (spix == 0) {
- if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
- 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);
- cur_fd->objix_hdr_pix = new_pix;
- if (new_size != 0) {
- cur_fd->size = new_size;
- }
- } else if (ev == SPIFFS_EV_IX_DEL) {
- cur_fd->file_nbr = 0;
- cur_fd->obj_id = SPIFFS_OBJ_ID_DELETED;
- }
- }
- if (cur_fd->cursor_objix_spix == spix) {
- if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
- 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);
- cur_fd->cursor_objix_pix = new_pix;
- } else {
- cur_fd->cursor_objix_pix = 0;
- }
- }
- }
- }
- // Open object by id
- s32_t spiffs_object_open_by_id(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode) {
- s32_t res = SPIFFS_OK;
- spiffs_page_ix pix;
- res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_object_open_by_page(fs, pix, fd, flags, mode);
- return res;
- }
- // Open object by page index
- s32_t spiffs_object_open_by_page(
- spiffs *fs,
- spiffs_page_ix pix,
- spiffs_fd *fd,
- spiffs_flags flags,
- spiffs_mode mode) {
- (void)mode;
- s32_t res = SPIFFS_OK;
- spiffs_page_object_ix_header oix_hdr;
- spiffs_obj_id obj_id;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&oix_hdr);
- SPIFFS_CHECK_RES(res);
- spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(fs, pix);
- int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
- 0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
- fd->fs = fs;
- fd->objix_hdr_pix = pix;
- fd->size = oix_hdr.size;
- fd->offset = 0;
- fd->cursor_objix_pix = pix;
- fd->cursor_objix_spix = 0;
- fd->obj_id = obj_id;
- fd->flags = flags;
- SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
- SPIFFS_DBG("open: fd %i is obj id %04x\n", fd->file_nbr, fd->obj_id);
- return res;
- }
- // Append to object
- // keep current object index (header) page in fs->work buffer
- s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
- spiffs *fs = fd->fs;
- s32_t res = SPIFFS_OK;
- u32_t written = 0;
- SPIFFS_DBG("append: %i bytes @ offs %i of size %i\n", len, offset, fd->size);
- if (offset > fd->size) {
- SPIFFS_DBG("append: offset reversed to size\n");
- offset = fd->size;
- }
- res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta
- if (res != SPIFFS_OK) {
- SPIFFS_DBG("append: gc check fail %i\n", res);
- }
- SPIFFS_CHECK_RES(res);
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_header p_hdr;
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
- spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
- spiffs_page_ix new_objix_hdr_page;
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- spiffs_page_ix data_page;
- u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
- // write all data
- while (res == SPIFFS_OK && written < len) {
- // calculate object index page span index
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- // handle storing and loading of object indices
- if (cur_objix_spix != prev_objix_spix) {
- // new object index page
- // within this clause we return directly if something fails, object index mess-up
- if (written > 0) {
- // store previous object index page, unless first pass
- SPIFFS_DBG("append: %04x store objix %04x:%04x, written %i\n", fd->obj_id,
- cur_objix_pix, prev_objix_spix, written);
- if (prev_objix_spix == 0) {
- // this is an update to object index header page
- objix_hdr->size = offset+written;
- if (offset == 0) {
- // was an empty object, update same page (size was 0xffffffff)
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, 0);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- } else {
- // was a nonempty object, update to new page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
- new_objix_hdr_page, 0, written);
- }
- } else {
- // this is an update to an object index page
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD,fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
- // update length in object index header page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
- SPIFFS_CHECK_RES(res);
- SPIFFS_DBG("append: %04x store new size I %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
- offset+written, new_objix_hdr_page, 0, written);
- }
- fd->size = offset+written;
- fd->offset = offset+written;
- }
- // create or load new object index page
- if (cur_objix_spix == 0) {
- // load object index header page, must always exist
- SPIFFS_DBG("append: %04x load objixhdr page %04x:%04x\n", fd->obj_id, cur_objix_pix, cur_objix_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- } else {
- spiffs_span_ix len_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, (fd->size-1)/SPIFFS_DATA_PAGE_SIZE(fs));
- // on subsequent passes, create a new object index page
- if (written > 0 || cur_objix_spix > len_objix_spix) {
- p_hdr.obj_id = fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = cur_objix_spix;
- p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
- res = spiffs_page_allocate_data(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 1, &cur_objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0);
- // quick "load" of new object index page
- c_memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- c_memcpy(fs->work, &p_hdr, sizeof(spiffs_page_header));
- SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %i\n", fd->obj_id
- , cur_objix_pix, cur_objix_spix, written);
- } else {
- // on first pass, we load existing object index page
- spiffs_page_ix pix;
- SPIFFS_DBG("append: %04x find objix span_ix:%04x\n", fd->obj_id, cur_objix_spix);
- if (fd->cursor_objix_spix == cur_objix_spix) {
- pix = fd->cursor_objix_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("append: %04x found object index at page %04x [fd size %i]\n", fd->obj_id, pix, fd->size);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- cur_objix_pix = pix;
- }
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = offset+written;
- fd->size = offset+written;
- }
- prev_objix_spix = cur_objix_spix;
- }
- // write data
- u32_t to_write = MIN(len-written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
- if (page_offs == 0) {
- // at beginning of a page, allocate and write a new page of data
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, &data[written], to_write, page_offs, 1, &data_page);
- SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id,
- data_page, data_spix, page_offs, to_write, written);
- } else {
- // append to existing page, fill out free data in existing page
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_page = ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- data_page = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
- res = spiffs_page_data_check(fs, fd, data_page, data_spix);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
- SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id
- , data_page, data_spix, page_offs, to_write, written);
- }
- if (res != SPIFFS_OK) break;
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_page;
- SPIFFS_DBG("append: %04x wrote page %04x to objix_hdr entry %02x in mem\n", fd->obj_id
- , data_page, data_spix);
- objix_hdr->size = offset+written;
- } else {
- // update object index page
- ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_page;
- SPIFFS_DBG("append: %04x wrote page %04x to objix entry %02x in mem\n", fd->obj_id
- , data_page, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
- // update internals
- page_offs = 0;
- data_spix++;
- written += to_write;
- } // while all data
- fd->size = offset+written;
- fd->offset = offset+written;
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- // finalize updated object indices
- s32_t res2 = SPIFFS_OK;
- if (cur_objix_spix != 0) {
- // wrote beyond object index header page
- // write last modified object index page, unless object header index page
- SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %i\n", fd->obj_id,
- cur_objix_pix, cur_objix_spix, written);
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
- res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res2);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
- // update size in object header index page
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
- SPIFFS_DBG("append: %04x store new size II %i in objix_hdr, %04x:%04x, written %i, res %i\n", fd->obj_id
- , offset+written, new_objix_hdr_page, 0, written, res2);
- SPIFFS_CHECK_RES(res2);
- } else {
- // wrote within object index header page
- if (offset == 0) {
- // wrote to empty object - simply update size and write whole page
- objix_hdr->size = offset+written;
- SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
- , cur_objix_pix, cur_objix_spix, written);
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
- res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res2);
- // callback on object index update
- 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);
- } else {
- // modifying object index header page, update size and make new copy
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
- SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
- , new_objix_hdr_page, 0, written);
- SPIFFS_CHECK_RES(res2);
- }
- }
- return res;
- }
- // Modify object
- // keep current object index (header) page in fs->work buffer
- s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
- spiffs *fs = fd->fs;
- s32_t res = SPIFFS_OK;
- u32_t written = 0;
- res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_header p_hdr;
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
- spiffs_page_ix cur_objix_pix = fd->objix_hdr_pix;
- spiffs_page_ix new_objix_hdr_pix;
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- spiffs_page_ix data_pix;
- u32_t page_offs = offset % SPIFFS_DATA_PAGE_SIZE(fs);
- // write all data
- while (res == SPIFFS_OK && written < len) {
- // calculate object index page span index
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- // handle storing and loading of object indices
- if (cur_objix_spix != prev_objix_spix) {
- // new object index page
- // within this clause we return directly if something fails, object index mess-up
- if (written > 0) {
- // store previous object index (header) page, unless first pass
- if (prev_objix_spix == 0) {
- // store previous object index header page
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
- SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
- SPIFFS_CHECK_RES(res);
- } else {
- // store new version of previous object index page
- spiffs_page_ix new_objix_pix;
- res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
- SPIFFS_DBG("modify: store previous modified objix page, %04x:%04x, written %i\n", new_objix_pix, objix->p_hdr.span_ix, written);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- }
- }
- // load next object index page
- if (cur_objix_spix == 0) {
- // load object index header page, must exist
- SPIFFS_DBG("modify: load objixhdr page %04x:%04x\n", cur_objix_pix, cur_objix_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- } else {
- // load existing object index page on first pass
- spiffs_page_ix pix;
- SPIFFS_DBG("modify: find objix span_ix:%04x\n", cur_objix_spix);
- if (fd->cursor_objix_spix == cur_objix_spix) {
- pix = fd->cursor_objix_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("modify: found object index at page %04x\n", pix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- cur_objix_pix = pix;
- }
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = offset+written;
- prev_objix_spix = cur_objix_spix;
- }
- // write partial data
- u32_t to_write = MIN(len-written, SPIFFS_DATA_PAGE_SIZE(fs) - page_offs);
- spiffs_page_ix orig_data_pix;
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- orig_data_pix = ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- orig_data_pix = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff;
- if (page_offs == 0 && to_write == SPIFFS_DATA_PAGE_SIZE(fs)) {
- // a full page, allocate and write a new page of data
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
- 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);
- } else {
- // write to existing page, allocate new and copy unmodified data
- res = spiffs_page_data_check(fs, fd, orig_data_pix, data_spix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 0, &data_pix);
- if (res != SPIFFS_OK) break;
- // copy unmodified data
- if (page_offs > 0) {
- // before modification
- res = spiffs_phys_cpy(fs, fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header),
- page_offs);
- if (res != SPIFFS_OK) break;
- }
- if (page_offs + to_write < SPIFFS_DATA_PAGE_SIZE(fs)) {
- // after modification
- res = spiffs_phys_cpy(fs, fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
- SPIFFS_PAGE_TO_PADDR(fs, orig_data_pix) + sizeof(spiffs_page_header) + page_offs + to_write,
- SPIFFS_DATA_PAGE_SIZE(fs) - (page_offs + to_write));
- if (res != SPIFFS_OK) break;
- }
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
- if (res != SPIFFS_OK) break;
- p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr.flags);
- if (res != SPIFFS_OK) break;
- 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);
- }
- // delete original data page
- res = spiffs_page_delete(fs, orig_data_pix);
- if (res != SPIFFS_OK) break;
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_pix;
- SPIFFS_DBG("modify: wrote page %04x to objix_hdr entry %02x in mem\n", data_pix, data_spix);
- } else {
- // update object index page
- ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = data_pix;
- SPIFFS_DBG("modify: wrote page %04x to objix entry %02x in mem\n", data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
- // update internals
- page_offs = 0;
- data_spix++;
- written += to_write;
- } // while all data
- fd->offset = offset+written;
- fd->cursor_objix_pix = cur_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- // finalize updated object indices
- s32_t res2 = SPIFFS_OK;
- if (cur_objix_spix != 0) {
- // wrote beyond object index header page
- // write last modified object index page
- // move and update page
- spiffs_page_ix new_objix_pix;
- res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res2);
- res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
- SPIFFS_DBG("modify: store modified objix page, %04x:%04x, written %i\n", new_objix_pix, cur_objix_spix, written);
- fd->cursor_objix_pix = new_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- SPIFFS_CHECK_RES(res2);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- } else {
- // wrote within object index header page
- res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
- SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
- SPIFFS_CHECK_RES(res2);
- }
- return res;
- }
- static s32_t spiffs_object_find_object_index_header_by_name_v(
- spiffs *fs,
- spiffs_obj_id obj_id,
- spiffs_block_ix bix,
- int ix_entry,
- u32_t user_data,
- void *user_p) {
- (void)user_data;
- s32_t res;
- spiffs_page_object_ix_header objix_hdr;
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
- (obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
- return SPIFFS_VIS_COUNTINUE;
- }
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- SPIFFS_CHECK_RES(res);
- if (objix_hdr.p_hdr.span_ix == 0 &&
- (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- if (strncmp((char *)user_p, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) {
- return SPIFFS_OK;
- }
- }
- return SPIFFS_VIS_COUNTINUE;
- }
- // Finds object index header page by name
- s32_t spiffs_object_find_object_index_header_by_name(
- spiffs *fs,
- u8_t name[SPIFFS_OBJ_NAME_LEN],
- spiffs_page_ix *pix) {
- s32_t res;
- spiffs_block_ix bix;
- int entry;
- res = spiffs_obj_lu_find_entry_visitor(fs,
- fs->cursor_block_ix,
- fs->cursor_obj_lu_entry,
- 0,
- 0,
- spiffs_object_find_object_index_header_by_name_v,
- 0,
- name,
- &bix,
- &entry);
- if (res == SPIFFS_VIS_END) {
- res = SPIFFS_ERR_NOT_FOUND;
- }
- SPIFFS_CHECK_RES(res);
- if (pix) {
- *pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
- }
- fs->cursor_block_ix = bix;
- fs->cursor_obj_lu_entry = entry;
- return res;
- }
- // Truncates object to new size. If new size is null, object may be removed totally
- s32_t spiffs_object_truncate(
- spiffs_fd *fd,
- u32_t new_size,
- u8_t remove) {
- s32_t res = SPIFFS_OK;
- spiffs *fs = fd->fs;
- res = spiffs_gc_check(fs, remove ? 0 : SPIFFS_DATA_PAGE_SIZE(fs));
- SPIFFS_CHECK_RES(res);
- spiffs_page_ix objix_pix = fd->objix_hdr_pix;
- spiffs_span_ix data_spix = (fd->size > 0 ? fd->size-1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t cur_size = fd->size == (u32_t)SPIFFS_UNDEFINED_LEN ? 0 : fd->size ;
- spiffs_span_ix cur_objix_spix = 0;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- spiffs_page_ix data_pix;
- spiffs_page_ix new_objix_hdr_pix;
- // before truncating, check if object is to be fully removed and mark this
- if (remove && new_size == 0) {
- u8_t flags = ~( SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE);
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, fd->objix_hdr_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&flags);
- SPIFFS_CHECK_RES(res);
- }
- // delete from end of object until desired len is reached
- while (cur_size > new_size) {
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- // put object index for current data span index in work buffer
- if (prev_objix_spix != cur_objix_spix) {
- if (prev_objix_spix != (spiffs_span_ix)-1) {
- // remove previous object index page
- SPIFFS_DBG("truncate: delete objix page %04x:%04x\n", objix_pix, prev_objix_spix);
- res = spiffs_page_index_check(fs, fd, objix_pix, prev_objix_spix);
- SPIFFS_CHECK_RES(res);
- res = spiffs_page_delete(fs, objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
- if (prev_objix_spix > 0) {
- // update object index header page
- SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- fd->size = cur_size;
- }
- }
- // load current object index (header) page
- if (cur_objix_spix == 0) {
- objix_pix = fd->objix_hdr_pix;
- } else {
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("truncate: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, fd->obj_id, cur_objix_spix);
- fd->cursor_objix_pix = objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = cur_size;
- prev_objix_spix = cur_objix_spix;
- }
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_pix = ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = SPIFFS_OBJ_ID_FREE;
- } else {
- // get data page from object index page
- data_pix = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = SPIFFS_OBJ_ID_FREE;
- }
- SPIFFS_DBG("truncate: got data pix %04x\n", data_pix);
- if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size) {
- // delete full data page
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
- SPIFFS_DBG("truncate: err validating data pix %i\n", res);
- break;
- }
- if (res == SPIFFS_OK) {
- res = spiffs_page_delete(fs, data_pix);
- if (res != SPIFFS_OK) {
- SPIFFS_DBG("truncate: err deleting data pix %i\n", res);
- break;
- }
- } else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) {
- res = SPIFFS_OK;
- }
- // update current size
- if (cur_size % SPIFFS_DATA_PAGE_SIZE(fs) == 0) {
- cur_size -= SPIFFS_DATA_PAGE_SIZE(fs);
- } else {
- cur_size -= cur_size % SPIFFS_DATA_PAGE_SIZE(fs);
- }
- fd->size = cur_size;
- fd->offset = cur_size;
- SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%i\n", data_pix, data_spix, cur_size);
- } else {
- // delete last page, partially
- spiffs_page_header p_hdr;
- spiffs_page_ix new_data_pix;
- u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs));
- 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);
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- if (res != SPIFFS_OK) break;
- p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
- p_hdr.span_ix = data_spix;
- p_hdr.flags = 0xff;
- // allocate new page and copy unmodified data
- res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
- &p_hdr, 0, 0, 0, 0, &new_data_pix);
- if (res != SPIFFS_OK) break;
- res = spiffs_phys_cpy(fs, 0,
- SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + sizeof(spiffs_page_header),
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header),
- SPIFFS_DATA_PAGE_SIZE(fs) - bytes_to_remove);
- if (res != SPIFFS_OK) break;
- // delete original data page
- res = spiffs_page_delete(fs, data_pix);
- if (res != SPIFFS_OK) break;
- p_hdr.flags &= ~SPIFFS_PH_FLAG_FINAL;
- res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + offsetof(spiffs_page_header, flags),
- sizeof(u8_t),
- (u8_t *)&p_hdr.flags);
- if (res != SPIFFS_OK) break;
- // update memory representation of object index page with new data page
- if (cur_objix_spix == 0) {
- // update object index header page
- ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
- SPIFFS_DBG("truncate: wrote page %04x to objix_hdr entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- } else {
- // update object index page
- ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
- SPIFFS_DBG("truncate: wrote page %04x to objix entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, data_spix));
- }
- cur_size = new_size;
- fd->size = new_size;
- fd->offset = cur_size;
- break;
- }
- data_spix--;
- } // while all data
- // update object indices
- if (cur_objix_spix == 0) {
- // update object index header page
- if (cur_size == 0) {
- if (remove) {
- // remove object altogether
- SPIFFS_DBG("truncate: remove object index header page %04x\n", objix_pix);
- res = spiffs_page_index_check(fs, fd, objix_pix, 0);
- SPIFFS_CHECK_RES(res);
- res = spiffs_page_delete(fs, objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, 0, objix_pix, 0);
- } else {
- // make uninitialized object
- SPIFFS_DBG("truncate: reset objix_hdr page %04x\n", objix_pix);
- c_memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff,
- SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header));
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- } else {
- // update object index header page
- SPIFFS_DBG("truncate: update object index header page with indices and size\n");
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- objix_pix, fs->work, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- } else {
- // update both current object index page and object index header page
- spiffs_page_ix new_objix_pix;
- res = spiffs_page_index_check(fs, fd, objix_pix, cur_objix_spix);
- SPIFFS_CHECK_RES(res);
- // move and update object index page
- res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix_hdr, fd->obj_id, 0, objix_pix, &new_objix_pix);
- SPIFFS_CHECK_RES(res);
- spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
- SPIFFS_DBG("truncate: store modified objix page, %04x:%04x\n", new_objix_pix, cur_objix_spix);
- fd->cursor_objix_pix = new_objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- fd->offset = cur_size;
- // update object index header page with new size
- res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
- fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
- SPIFFS_CHECK_RES(res);
- }
- fd->size = cur_size;
- return res;
- }
- s32_t spiffs_object_read(
- spiffs_fd *fd,
- u32_t offset,
- u32_t len,
- u8_t *dst) {
- s32_t res = SPIFFS_OK;
- spiffs *fs = fd->fs;
- spiffs_page_ix objix_pix;
- spiffs_page_ix data_pix;
- spiffs_span_ix data_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t cur_offset = offset;
- spiffs_span_ix cur_objix_spix;
- spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
- spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
- spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
- while (cur_offset < offset + len) {
- cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
- if (prev_objix_spix != cur_objix_spix) {
- // load current object index (header) page
- if (cur_objix_spix == 0) {
- objix_pix = fd->objix_hdr_pix;
- } else {
- SPIFFS_DBG("read: find objix %04x:%04x\n", fd->obj_id, cur_objix_spix);
- res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
- SPIFFS_CHECK_RES(res);
- }
- SPIFFS_DBG("read: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
- fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
- SPIFFS_CHECK_RES(res);
- SPIFFS_VALIDATE_OBJIX(objix->p_hdr, fd->obj_id, cur_objix_spix);
- fd->offset = cur_offset;
- fd->cursor_objix_pix = objix_pix;
- fd->cursor_objix_spix = cur_objix_spix;
- prev_objix_spix = cur_objix_spix;
- }
- if (cur_objix_spix == 0) {
- // get data page from object index header page
- data_pix = ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix];
- } else {
- // get data page from object index page
- data_pix = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)];
- }
- // all remaining data
- u32_t len_to_read = offset + len - cur_offset;
- // remaining data in page
- len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
- // remaining data in file
- len_to_read = MIN(len_to_read, fd->size);
- 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,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
- if (len_to_read <= 0) {
- res = SPIFFS_ERR_END_OF_OBJECT;
- break;
- }
- res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
- SPIFFS_CHECK_RES(res);
- res = _spiffs_rd(
- fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ,
- fd->file_nbr,
- SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)),
- len_to_read,
- dst);
- SPIFFS_CHECK_RES(res);
- dst += len_to_read;
- cur_offset += len_to_read;
- fd->offset = cur_offset;
- data_spix++;
- }
- return res;
- }
- typedef struct {
- spiffs_obj_id min_obj_id;
- spiffs_obj_id max_obj_id;
- u32_t compaction;
- const u8_t *conflicting_name;
- } spiffs_free_obj_id_state;
- 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,
- u32_t user_data, void *user_p) {
- if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
- spiffs_obj_id min_obj_id = user_data;
- u8_t *conflicting_name = (u8_t *)user_p;
- // if conflicting name parameter is given, also check if this name is found in object index hdrs
- if (conflicting_name && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
- spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
- int res;
- spiffs_page_object_ix_header objix_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
- SPIFFS_CHECK_RES(res);
- if (objix_hdr.p_hdr.span_ix == 0 &&
- (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
- (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
- if (strncmp((char *)user_p, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) {
- return SPIFFS_ERR_CONFLICTING_NAME;
- }
- }
- }
- id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- u32_t bit_ix = (id-min_obj_id) & 7;
- int byte_ix = (id-min_obj_id) >> 3;
- if (byte_ix >= 0 && (u32_t)byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
- fs->work[byte_ix] |= (1<<bit_ix);
- }
- }
- return SPIFFS_VIS_COUNTINUE;
- }
- 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,
- u32_t user_data, void *user_p) {
- (void)user_data;
- if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
- s32_t res;
- spiffs_free_obj_id_state *state = (spiffs_free_obj_id_state *)user_p;
- spiffs_page_object_ix_header objix_hdr;
- res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
- 0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, ix_entry), sizeof(spiffs_page_object_ix_header), (u8_t*)&objix_hdr);
- if (res == SPIFFS_OK && objix_hdr.p_hdr.span_ix == 0 &&
- ((objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
- (SPIFFS_PH_FLAG_DELET))) {
- // ok object look up entry
- if (state->conflicting_name && strncmp((const char *)state->conflicting_name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN) == 0) {
- return SPIFFS_ERR_CONFLICTING_NAME;
- }
- id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- if (id >= state->min_obj_id && id <= state->max_obj_id) {
- u8_t *map = (u8_t *)fs->work;
- int ix = (id - state->min_obj_id) / state->compaction;
- //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);
- map[ix]++;
- }
- }
- }
- return SPIFFS_VIS_COUNTINUE;
- }
- // Scans thru all object lookup for object index header pages. If total possible number of
- // object ids cannot fit into a work buffer, these are grouped. When a group containing free
- // object ids is found, the object lu is again scanned for object ids within group and bitmasked.
- // Finally, the bitmasked is searched for a free id
- s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *conflicting_name) {
- s32_t res = SPIFFS_OK;
- u32_t max_objects = (SPIFFS_CFG_PHYS_SZ(fs) / (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) / 2;
- spiffs_free_obj_id_state state;
- spiffs_obj_id free_obj_id = SPIFFS_OBJ_ID_FREE;
- state.min_obj_id = 1;
- state.max_obj_id = max_objects + 1;
- if (state.max_obj_id & SPIFFS_OBJ_ID_IX_FLAG) {
- state.max_obj_id = ((spiffs_obj_id)-1) & ~SPIFFS_OBJ_ID_IX_FLAG;
- }
- state.compaction = 0;
- state.conflicting_name = conflicting_name;
- while (res == SPIFFS_OK && free_obj_id == SPIFFS_OBJ_ID_FREE) {
- if (state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs)*8) {
- // possible to represent in bitmap
- u32_t i, j;
- SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id);
- c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- 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,
- conflicting_name, 0, 0);
- if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
- SPIFFS_CHECK_RES(res);
- // traverse bitmask until found free obj_id
- for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs); i++) {
- u8_t mask = fs->work[i];
- if (mask == 0xff) {
- continue;
- }
- for (j = 0; j < 8; j++) {
- if ((mask & (1<<j)) == 0) {
- *obj_id = (i<<3)+j+state.min_obj_id;
- return SPIFFS_OK;
- }
- }
- }
- return SPIFFS_ERR_FULL;
- } else {
- // not possible to represent all ids in range in a bitmap, compact and count
- if (state.compaction != 0) {
- // select element in compacted table, decrease range and recompact
- u32_t i, min_i = 0;
- u8_t *map = (u8_t *)fs->work;
- u8_t min_count = 0xff;
- for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(u8_t); i++) {
- if (map[i] < min_count) {
- min_count = map[i];
- min_i = i;
- if (min_count == 0) {
- break;
- }
- }
- }
- if (min_count == state.compaction) {
- // there are no free objids!
- SPIFFS_DBG("free_obj_id: compacted table is full\n");
- return SPIFFS_ERR_FULL;
- }
- 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);
- if (min_count == 0) {
- // no id in this range, skip compacting and use directly
- *obj_id = min_i * state.compaction + state.min_obj_id;
- return SPIFFS_OK;
- } else {
- 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);
- state.min_obj_id += min_i * state.compaction;
- state.max_obj_id = state.min_obj_id + state.compaction;
- // decrease compaction
- }
- if ((state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs)*8)) {
- // no need for compacting, use bitmap
- continue;
- }
- }
- // in a work memory of log_page_size bytes, we may fit in log_page_size ids
- // todo what if compaction is > 255 - then we cannot fit it in a byte
- state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));
- SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction);
- c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- 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);
- if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
- SPIFFS_CHECK_RES(res);
- state.conflicting_name = 0; // searched for conflicting name once, no need to do it again
- }
- }
- return res;
- }
- s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
- u32_t i;
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- for (i = 0; i < fs->fd_count; i++) {
- spiffs_fd *cur_fd = &fds[i];
- if (cur_fd->file_nbr == 0) {
- cur_fd->file_nbr = i+1;
- *fd = cur_fd;
- return SPIFFS_OK;
- }
- }
- return SPIFFS_ERR_OUT_OF_FILE_DESCS;
- }
- s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
- if (f <= 0 || f > (s16_t)fs->fd_count) {
- return SPIFFS_ERR_BAD_DESCRIPTOR;
- }
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- spiffs_fd *fd = &fds[f-1];
- if (fd->file_nbr == 0) {
- return SPIFFS_ERR_FILE_CLOSED;
- }
- fd->file_nbr = 0;
- return SPIFFS_OK;
- }
- s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
- if (f <= 0 || f > (s16_t)fs->fd_count) {
- return SPIFFS_ERR_BAD_DESCRIPTOR;
- }
- spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
- *fd = &fds[f-1];
- if ((*fd)->file_nbr == 0) {
- return SPIFFS_ERR_FILE_CLOSED;
- }
- return SPIFFS_OK;
- }
|