diff --git a/src/spiffs_hydrogen.c b/src/spiffs_hydrogen.c index db6dd16..1cf64ff 100644 --- a/src/spiffs_hydrogen.c +++ b/src/spiffs_hydrogen.c @@ -1127,6 +1127,7 @@ s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map, map->map_buf = map_buf; map->offset = offset; + // nb: spix range includes last map->start_spix = offset / SPIFFS_DATA_PAGE_SIZE(fs); map->end_spix = (offset + len) / SPIFFS_DATA_PAGE_SIZE(fs); memset(map_buf, 0, sizeof(spiffs_page_ix) * (map->end_spix - map->start_spix + 1)); @@ -1187,29 +1188,34 @@ s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) { if (spix_diff != 0) { // move vector int i; - const s32_t vec_len = map->end_spix - map->start_spix + 1; + const s32_t vec_len = map->end_spix - map->start_spix + 1; // spix range includes last map->start_spix += spix_diff; map->end_spix += spix_diff; if (spix_diff >= vec_len) { // moving beyond range memset(&map->map_buf, 0, vec_len * sizeof(spiffs_page_ix)); - res = spiffs_populate_ix_map(fs, fd, 0, vec_len); + // populate_ix_map is inclusive + res = spiffs_populate_ix_map(fs, fd, 0, vec_len-1); SPIFFS_API_CHECK_RES_UNLOCK(fs, res); } else if (spix_diff > 0) { // diff positive - for (i = 0; i < vec_len - spix_diff - 1; i++) { + for (i = 0; i < vec_len - spix_diff; i++) { map->map_buf[i] = map->map_buf[i + spix_diff]; } - memset(&map->map_buf[vec_len - spix_diff - 1], 0, spix_diff * sizeof(spiffs_page_ix)); - res = spiffs_populate_ix_map(fs, fd, vec_len - spix_diff, vec_len); + // memset is non-inclusive + memset(&map->map_buf[vec_len - spix_diff], 0, spix_diff * sizeof(spiffs_page_ix)); + // populate_ix_map is inclusive + res = spiffs_populate_ix_map(fs, fd, vec_len - spix_diff, vec_len-1); SPIFFS_API_CHECK_RES_UNLOCK(fs, res); } else { // diff negative for (i = vec_len - 1; i >= -spix_diff; i--) { map->map_buf[i] = map->map_buf[i + spix_diff]; } + // memset is non-inclusive memset(&map->map_buf[0], 0, -spix_diff * sizeof(spiffs_page_ix)); - res = spiffs_populate_ix_map(fs, fd, 0, spix_diff); + // populate_ix_map is inclusive + res = spiffs_populate_ix_map(fs, fd, 0, -spix_diff - 1); SPIFFS_API_CHECK_RES_UNLOCK(fs, res); } @@ -1221,7 +1227,8 @@ s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) { s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) { SPIFFS_API_CHECK_CFG(fs); - return (bytes + (SPIFFS_DATA_PAGE_SIZE(fs) -1) ) / SPIFFS_DATA_PAGE_SIZE(fs); + // always add one extra page, the offset might change to the middle of a page + return (bytes + SPIFFS_DATA_PAGE_SIZE(fs) ) / SPIFFS_DATA_PAGE_SIZE(fs); } s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entries) { diff --git a/src/spiffs_nucleus.c b/src/spiffs_nucleus.c index a64b101..35fe0d4 100644 --- a/src/spiffs_nucleus.c +++ b/src/spiffs_nucleus.c @@ -708,6 +708,7 @@ static s32_t spiffs_populate_ix_map_v( return res; } +// populates index map, from vector entry start to vector entry end, inclusive s32_t spiffs_populate_ix_map(spiffs *fs, spiffs_fd *fd, u32_t vec_entry_start, u32_t vec_entry_end) { s32_t res; spiffs_ix_map *map = fd->ix_map; diff --git a/src/test/test_hydrogen.c b/src/test/test_hydrogen.c index 6fd4cbb..8244db4 100644 --- a/src/test/test_hydrogen.c +++ b/src/test/test_hydrogen.c @@ -2047,37 +2047,78 @@ TEST(ix_map_remap) fd1 = SPIFFS_open(FS, "1", SPIFFS_O_RDONLY, 0); TEST_CHECK_GT(fd1, 0); - printf(".. corresponding pix entries: %i\n", SPIFFS_bytes_to_ix_map_entries(FS, size)); - TEST_CHECK_EQ(SPIFFS_bytes_to_ix_map_entries(FS, size), size_pages); + printf(".. corresponding pix entries: %i\n", SPIFFS_bytes_to_ix_map_entries(FS, size) + 1); + TEST_CHECK_EQ(SPIFFS_bytes_to_ix_map_entries(FS, size), size_pages + 1); // map index to memory // move around, check validity const int entries = SPIFFS_bytes_to_ix_map_entries(FS, size/2); spiffs_ix_map map; - spiffs_page_ix ixbuf[entries]; - spiffs_page_ix ixbuf_ref[entries]; + // add one extra for stack safeguarding + spiffs_page_ix ixbuf[entries+1]; + spiffs_page_ix ixbuf_ref[entries+1]; + const spiffs_page_ix canary = (spiffs_page_ix)0x87654321; + memset(ixbuf, 0xee, sizeof(ixbuf)); + ixbuf[entries] = canary; + res = SPIFFS_ix_map(FS, fd1, &map, 0, size/2, ixbuf); TEST_CHECK_GE(res, SPIFFS_OK); - memcpy(ixbuf_ref, ixbuf, sizeof(ixbuf)); + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); + } + printf("\n"); + + memcpy(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries); TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, 0), SPIFFS_OK); - TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(ixbuf))); + TEST_CHECK_EQ(canary, ixbuf[entries]); + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); + } + printf("\n"); + TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries)); TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, SPIFFS_DATA_PAGE_SIZE(FS)), SPIFFS_OK); + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); + } + printf("\n"); + TEST_CHECK_EQ(canary, ixbuf[entries]); TEST_CHECK_EQ(0, memcmp(&ixbuf_ref[1], ixbuf, sizeof(spiffs_page_ix) * (entries-1))); TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, 0), SPIFFS_OK); - TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(ixbuf))); + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); + } + printf("\n"); + TEST_CHECK_EQ(canary, ixbuf[entries]); + TEST_CHECK_EQ(0, memcmp(ixbuf_ref, ixbuf, sizeof(spiffs_page_ix) * entries)); TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd1, size/2), SPIFFS_OK); + TEST_CHECK_EQ(canary, ixbuf[entries]); + + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf_ref[i]); + } + printf("\n"); + + for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); + } + printf("\n"); + + int matches = 0; for (i = 0; i < entries; i++) { int j; for (j = 0; j < entries; j++) { - TEST_CHECK_NEQ(ixbuf_ref[i], ixbuf[j]); + if (ixbuf_ref[i] == ixbuf[i]) { + matches++; + } } } + TEST_CHECK_LE(matches, 1); return TEST_RES_OK; } @@ -2180,15 +2221,18 @@ TEST(ix_map_beyond) const int entries = SPIFFS_bytes_to_ix_map_entries(FS, size); spiffs_ix_map map; spiffs_page_ix ixbuf[entries]; + printf("map has %i entries\n", entries); printf("map 100-200%%\n"); - res = SPIFFS_ix_map(FS, fd, &map, size, size*2, ixbuf); + res = SPIFFS_ix_map(FS, fd, &map, size, size, ixbuf); TEST_CHECK_GE(res, SPIFFS_OK); - // make sure map is empty + printf("make sure map is empty\n"); for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); TEST_CHECK_EQ(ixbuf[i], 0); } + printf("\n"); printf("elongate by 100%%\n"); for (i = 0; i < size_pages; i++) { @@ -2203,19 +2247,25 @@ TEST(ix_map_beyond) size = s.size; printf("file elongated, size: %i..\n", size); - // make sure map is non-empty + printf("make sure map is full but for one element\n"); + int zeroed = 0; for (i = 0; i < entries; i++) { - TEST_CHECK_NEQ(ixbuf[i], 0); + printf("%04x ", ixbuf[i]); + if (ixbuf[i] == 0) zeroed++; } + printf("\n"); + TEST_CHECK_LE(zeroed, 1); printf("remap till end\n"); TEST_CHECK_EQ(SPIFFS_ix_remap(FS, fd, size), SPIFFS_OK); - // make sure map is empty but for one element + printf("make sure map is empty but for one element\n"); int nonzero = 0; for (i = 0; i < entries; i++) { + printf("%04x ", ixbuf[i]); if (ixbuf[i]) nonzero++; } + printf("\n"); TEST_CHECK_LE(nonzero, 1); printf("elongate again, by other fd\n"); @@ -2230,10 +2280,14 @@ TEST(ix_map_beyond) } TEST_CHECK_GE(SPIFFS_close(FS, fd2), SPIFFS_OK); - // make sure map is non-empty + printf("make sure map is full but for one element\n"); + zeroed = 0; for (i = 0; i < entries; i++) { - TEST_CHECK_NEQ(ixbuf[i], 0); + printf("%04x ", ixbuf[i]); + if (ixbuf[i] == 0) zeroed++; } + printf("\n"); + TEST_CHECK_LE(zeroed, 1); return TEST_RES_OK; }