Giter VIP home page Giter VIP logo

spiffs's Introduction

SPIFFS (SPI Flash File System)

V0.3.7

Build Status

Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976 at gmail.com)

For legal stuff, see LICENSE. Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible.

Love to hear feedback though!

INTRODUCTION

Spiffs is a file system intended for SPI NOR flash devices on embedded targets.

Spiffs is designed with following characteristics in mind:

  • Small (embedded) targets, sparse RAM without heap
  • Only big areas of data (blocks) can be erased
  • An erase will reset all bits in block to ones
  • Writing pulls one to zeroes
  • Zeroes can only be pulled to ones by erase
  • Wear leveling

BUILDING

mkdir build; make

Otherwise, configure the builddir variable towards the top of makefile as something opposed to the default build. Sanity check on the host via make test and refer to .travis.yml for the official in-depth testing procedure. See the wiki for integrating spiffs into projects and spiffsimg from nodemcu is a good example on the subject.

FEATURES

What spiffs does:

  • Specifically designed for low ram usage
  • Uses statically sized ram buffers, independent of number of files
  • Posix-like api: open, close, read, write, seek, stat, etc
  • It can run on any NOR flash, not only SPI flash - theoretically also on embedded flash of a microprocessor
  • Multiple spiffs configurations can run on same target - and even on same SPI flash device
  • Implements static wear leveling
  • Built in file system consistency checks
  • Highly configurable

What spiffs does not:

  • Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path tmp/myfile.txt will create a file called tmp/myfile.txt instead of a myfile.txt under directory tmp.
  • It is not a realtime stack. One write operation might last much longer than another.
  • Poor scalability. Spiffs is intended for small memory devices - the normal sizes for SPI flashes. Going beyond ~128Mbyte is probably a bad idea. This is a side effect of the design goal to use as little ram as possible.
  • Presently, it does not detect or handle bad blocks.
  • One configuration, one binary. There's no generic spiffs binary that handles all types of configurations.

NOTICE

0.4.0 is under construction. This is a full rewrite and will change the underlying structure. Hence, it will not be compatible with earlier versions of the filesystem. The API is the same, with minor modifications. Some config flags will be removed (as they are mandatory in 0.4.0) and some features might fall away until 0.4.1. If you have any worries or questions, it can be discussed in issue #179

MORE INFO

See the wiki for configuring, integrating, using, and optimizing spiffs.

For design, see docs/TECH_SPEC.

For a generic spi flash driver, see this.

HISTORY

0.3.7

  • fixed prevent seeking to negative offsets #158
  • fixed file descriptor offsets not updated for multiple fds on same file #157
  • fixed cache page not closed for removed files #156
  • fixed a lseek bug when seeking exactly to end of a fully indexed first level LUT #148
  • fixed wear leveling issue #145
  • fixed attempt to write out of bounds in flash #130,
  • set file offset when seeking over end #121 (thanks @sensslen)
  • fixed seeking in virgin files #120 (thanks @sensslen)
  • Optional file metadata #128 (thanks @cesanta)
  • AFL testing framework #100 #143 (thanks @pjsg)
  • Testframe updates

New API functions:

  • SPIFFS_update_meta, SPIFFS_fupdate_meta - updates metadata for a file

New config defines:

  • SPIFFS_OBJ_META_LEN - enable possibility to add extra metadata to files

0.3.6

  • Fix range bug in index memory mapping #98
  • Add index memory mapping #97
  • Optimize SPIFFS_read for large files #96
  • Add temporal cache for opening files #95
  • More robust gc #93 (thanks @dismirlian)
  • Fixed a double write of same data in certain cache situations
  • Fixed an open bug in READ_ONLY builds
  • File not visible in SPIFFS_readdir #90 (thanks @benpicco-tmp)
  • Cache load code cleanup #92 (thanks @niclash)
  • Fixed lock/unlock asymmetry #88 #87 (thanks @JackJefferson, @dpruessner)
  • Testframe updates

New API functions:

  • SPIFFS_ix_map - map index meta data to memory for a file
  • SPIFFS_ix_unmap - unmaps index meta data for a file
  • SPIFFS_ix_remap - changes file offset for index metadata map
  • SPIFFS_bytes_to_ix_map_entries - utility, get length of needed vector for given amount of bytes
  • SPIFFS_ix_map_entries_to_bytes - utility, get number of bytes a vector can represent given length

New config defines:

  • SPIFFS_IX_MAP - enable possibility to map index meta data to memory for reading faster
  • SPIFFS_TEMPORAL_FD_CACHE - enable temporal cache for opening files faster
  • SPIFFS_TEMPORAL_CACHE_HIT_SCORE - for tuning the temporal cache

0.3.5

  • Fixed a bug in fs check
  • API returns actual error codes #84) (thanks @Nails)
  • Fix compiler warnings for non-gcc #83 #81 (thanks @Nails)
  • Unable to recover from full fs #82 (thanks @rojer)
  • Define SPIFFS_O_* flags #80
  • Problem with long filenames #79 (thanks @psjg)
  • Duplicate file name bug fix #74 (thanks @igrr)
  • SPIFFS_eof and SPIFFS_tell return wrong value #72 (thanks @ArtemPisarenko)
  • Bunch of testframe updates #77 #78 #86 (thanks @dpreussner, @psjg a.o)

0.3.4

  • Added user callback file func.
  • Fixed a stat bug with obj id.
  • SPIFFS_probe_fs added
  • Add possibility to compile a read-only version of spiffs
  • Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke)
  • Exposed SPIFFS_open_by_page_function
  • Zero-size file cannot be seek #57 (thanks @lishen2)
  • Add tell and eof functions #54 (thanks @raburton)
  • Make api string params const #53 (thanks @raburton)
  • Preserve user_data during mount() #51 (thanks @rojer)

New API functions:

  • SPIFFS_set_file_callback_func - register a callback informing about file events
  • SPIFFS_probe_fs - probe a spi flash trying to figure out size of fs
  • SPIFFS_open_by_page - open a file by page index
  • SPIFFS_eof - checks if end of file is reached
  • SPIFFS_tell - returns current file offset

New config defines:

  • SPIFFS_READ_ONLY
  • SPIFFS_USE_MAGIC_LENGTH

0.3.3

Might not be compatible with 0.3.2 structures. See issue #40

  • Possibility to add integer offset to file handles
  • Truncate function presumes too few free pages #49
  • Bug in truncate function #48 (thanks @PawelDefee)
  • Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee)
  • Update INTEGRATION docs (thanks @PawelDefee)
  • Fix pointer truncation in 64-bit platforms (thanks @igrr)
  • Zero-sized files cannot be read #44 (thanks @rojer)
  • (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2)
  • Check correct error code in obj_lu_find_free #41 (thanks @lishen2)
  • Moar comments for SPIFFS_lseek (thanks @igrr)
  • Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2)
  • Fixed gc_quick test (thanks @jmattsson)
  • Add SPIFFS_EXCL flag #36
  • SPIFFS_close may fail silently if cache is enabled #37
  • User data in callbacks #34
  • Ignoring SINGLETON build in cache setup (thanks Luca)
  • Compilation error fixed #32 (thanks @chotasanjiv)
  • Align cand_scores (thanks @hefloryd)
  • Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav)

New config defines:

  • SPIFFS_FILEHDL_OFFSET

0.3.2

  • Limit cache size if too much cache is given (thanks pgeiem)
  • New feature - Controlled erase. #23
  • SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
  • moved dbg print defines in test framework to params_test.h
  • lseek should return the resulting offset (thanks hefloryd)
  • fixed type on dbg ifdefs
  • silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
  • Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
  • Cache might writethrough too often #16
  • even moar testrunner updates
  • Test framework update and some added tests
  • Some thoughts for next gen
  • Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
  • GC might be suboptimal #11
  • Fix eternal readdir when objheader at last block, last entry

New API functions:

  • SPIFFS_gc_quick - call a nonintrusive gc
  • SPIFFS_gc - call a full-scale intrusive gc

0.3.1

  • Removed two return warnings, was too triggerhappy on release

0.3.0

  • Added existing namecheck when creating files
  • Lots of static analysis bugs #6
  • Added rename func
  • Fix SPIFFS_read length when reading beyond file size
  • Added reading beyond file length testcase
  • Made build a bit more configurable
  • Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw
  • Improved GC checks, fixed an append bug, more robust truncate for very special case
  • GC checks preempts GC, truncate even less picky
  • Struct alignment needed for some targets, define in spiffs config #10
  • Spiffs filesystem magic, definable in config

New config defines:

  • SPIFFS_USE_MAGIC - enable or disable magic check upon mount
  • SPIFFS_ALIGNED_OBJECT_INDEX_TABLES - alignment for certain targets

New API functions:

  • SPIFFS_rename - rename files
  • SPIFFS_clearerr - clears last errno
  • SPIFFS_info - returns info on used and total bytes in fs
  • SPIFFS_format - formats the filesystem
  • SPIFFS_mounted - checks if filesystem is mounted

spiffs's People

Contributors

3adev avatar ajaybhargav avatar b4yuan avatar benpicco avatar eufyteam-bruce avatar funshine avatar hefloryd avatar igrr avatar jmattsson avatar khalidjmi1200 avatar markrages avatar mikee47 avatar mmi avatar neuhaus avatar paweldefee avatar pellepl avatar pjsg avatar raburton avatar reiyawea avatar rojer avatar samcaulfield-ubotica avatar sensslen avatar svpcom avatar tornadocean avatar vamshi51 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spiffs's Issues

Spiffs file taking up more room than it should

I have an ESP201 running on a wake/sleep cycle (coded in Sming). During the wake part of the cycle a certain amount of information that the ESP201 gathers is logged in Spiffs storage. The most it can write in a single line is 66 bytes, which is 67 with the newline included. The flash space, using sming, should be 262144 bytes. The ESP201 should have room for about 3900 lines of data then.

However, it seems that I am unable to store anywhere near that much data. After the device has been running for a while (not even close to enough time to fill the file system) the file entirely disappears from the system, and from there on out I get open, write, and read errors. In an effort to determine the problem I stopped the device early on in it's runtime and used esptool to read what was stored in Spiffs. This is what I got (N.B. I replaced a list of actual BSSIDS with "BSSIDS"):

ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x��������ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ����¸Device ID:
BSSIDS 63031
s 63031
s 63031
s 63032
s 63031
s 63032
s 63032
s 63031
BSSIDS 63032
s 63031
s 63032
s 63032
s 63031
s 63031
s 63032
s �Ä��x���G����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���N����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���O����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���V����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���W����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���^����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���_����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���f����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���g����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���n����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���o����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���v����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���w����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���~����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x��������ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���Ü����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���¬����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���…����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x��� ����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���—����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���“����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���Ÿ����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���⁄����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���·����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���‚����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���È����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���Í����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���Ò����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���Ú����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ��������������������������������������������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���˘����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���˙����ap_list.txt������������������������ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ����¸63032
BSSIDS 63031
s 63031
s 63031
s 63031
s 63031
s 63032
s 63031
s 63031
BSSIDS 63031
s 63031
s 63031
s 63031
s 63031
s 63032
s 63031
s 63031�Ä��x��������ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���=����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���D����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���E����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���L����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���M����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ�Ä��x���T����ap_list.txt������������������������#�ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ

This is repeated on and on until the end of the file is reached.

What is all that junk between the written data? It appears to be written at pretty regular intervals.

My hypothesis is that the stuff between the data is massively enlarging the size of the file such that it fills up the available space much faster than it would normally. My guess is that Spiffs will wipe itself once its capacity is reached.

This isn't as much of an issue with the code as it is with my understanding of how spiffs works. What is happening here, and how can I get rid of my problem?

Thanks!

Zero-size file cannot be seek

An empty file (zero bytes) cannot be seek to the end or beginning
The errno returned is SPIFFS_ERR_END_OF_OBJECT

Bug is in 'SPIFFS_lseek'

  if (offs > (s32_t)fd->size) {
    res = SPIFFS_ERR_END_OF_OBJECT;
  }

When seeking empty file, fd->size is SPIFFS_UNDEFINED_LEN , the statement (offs > (s32_t)fd->size) success (zero is bigger than negative number).
The following modification will work:

  if ((offs > (s32_t)fd->size) && (SPIFFS_UNDEFINED_LEN != fd->size)) {
    res = SPIFFS_ERR_END_OF_OBJECT;
  }

SPIFFS_rename leaks file descriptors

Hello again,
SPIFFS_rename does leak file descriptors, it only returns them in the error case. This makes it impossible to open new files after a few renames:

> hexdump foo
2015-07-08 15:24:57,428 - INFO # SPIFFS_open(foo) = 1
2015-07-08 15:24:57,429 - INFO # …
2015-07-08 15:24:57,508 - INFO # SPIFFS_close(1)
> hexdump foo
2015-07-08 15:24:59,428 - INFO # SPIFFS_open(foo) = 1
2015-07-08 15:24:59,429 - INFO # …
2015-07-08 15:24:59,508 - INFO # SPIFFS_close(1)
> mv foo bar
2015-07-08 15:25:02,690 - INFO # SPIFFS_rename(foo, bar)
> hexdump bar
2015-07-08 15:25:05,043 - INFO # SPIFFS_open(bar) = 2
2015-07-08 15:25:05,043 - INFO # …
2015-07-08 15:25:05,123 - INFO # SPIFFS_close(2)
> mv bar foobar
2015-07-08 15:25:16,404 - INFO # SPIFFS_rename(bar, foobar)
> hexdump foobar
2015-07-08 15:25:19,524 - INFO # cannot open foobar (-10007)
> mv foobar bar
2015-07-08 15:25:24,443 - INFO # SPIFFS_rename(foobar, bar)
2015-07-08 15:25:24,491 - INFO # cannot rename file (-10007)

This seems to fix it:

--- a/src/spiffs_hydrogen.c
+++ b/src/spiffs_hydrogen.c
@@ -720,6 +720,8 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
   }
   SPIFFS_API_CHECK_RES_UNLOCK(fs, res);

+  spiffs_fd_return(fs, fd->file_nbr);
+
   SPIFFS_UNLOCK(fs);

   return res;

SPIFFS_USE_MAGIC checking filesystem

When mounting a FS with the the SPIFFS_USE_MAGIC set to 1, is then only checked whether all blocks within the "FS range" have a magic number ?

If so, would you detect a failure when FS is created with size 1000 and mounted with size 500 ?

If I missed the documentation for this, please point me to the location and I will work from that.

Compilation warning

Hi,
My compiler warns me about the following line of code in spiffs_check.c, line 278:
if (objix_pix_ph == 0 || objix_pix_ph == 0)
Is this correct or should it be something like:
if (objix_pix_ph == 0 || objix_pix_lu == 0)
Regards,
Daniel

Possible error in test_spiffs.c

test_spiffs.c:
339 void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size,
340 u32_t phys_sector_size,
341 u32_t log_block_size, u32_t log_page_size) {
342 fs_set_addr_offset(addr_offset);
....
360 res = SPIFFS_mount(&__fs, &c, _work, _fds, sizeof(_fds), _cache, sizeof(_cache), spiffs_check_cb_f)

Calling SPIFFS_mount with parameters undefined in fs_reset_specific (c for example). Suggest there should be

res = fs_mount_specific(phys_addr, phys_size, phys_sector_size, log_block_size, log_page_size);

instead.

New feature - Controlled erase.

Hi Peter,

I have tried spiffs as an alternative to commercial embedded FS. It is interesting how SPIFFS uses free space - it does not erase flash sectors until all of them are used after a format. This is good and bad at the same time, bad because erase is very slow and FS performance in the beginning will differ, good because you probably could distribute erase operations over time or even control them. Have you thought about making a function that will erase several unused sectors ? It also would be nice to have a mean to check whether format is needed or not too.

Vlad.

Specifying a non-zero SPI start physical address does not work

Tested using a 128Mbit flash. Configured spiffs to use the last 2MB as SPIFFS, with a start address of 0x00E00000. When testing, an assert was triggered in the spiffs_read() user function because of an out of range address when calling the SPI interface code.

The cause of this out-of-range physical address is that some of the calls to _spiffs_rd() include a sum expression in the address parameter that actually adds the base physical address together.

For example, in spiffs_obj_lu_find_entry_visitor() the call to _spiffs_rd() reads the address specified by SPIFFS_PAGE_TO_PADDR() added to cur_block_addr. cur_block_addr is initially set with the SPIFFS_BLOCK_TO_PADDR() macro. Both macros include the phys_addr of the start of the SPI flash which gets sum therefore giving an incorrect address.

The workaround is to specify the physical start address as zero and to set the correct physical address offset in the user-defined code for spiffs_read, spiffs_write, and spiffs_erase.

SPIFFS_USE_MAGIC and erase race problem

Hello,

I found one issue with SPIFFS_USE_MAGIC. Problem is simple: erase a sector, and reset/turn off the device before a magic write. In this case the sector is erased, but lost for SPIFFS, because does not contain the magic on its begining.

Fix for this can be simple, but incomplete (see below): write the magic into the sector, when it is detected as erased during a mount.

But switch off during an undesirable moment and flash content is more complicated problem. It can happen during erasing flash in physical layer. After this, flash sector will not be completely erased and can't be used for SPIFFS (independent if the magic is used or not).

Therefore here is better solution:

  • use magic every time
  • when sector does not contain magic, erase it and write the magic on mount
  • when sector contain invalid non-SPIFFS data, erase it and write the magic on mount

Add a defrag method

Hello, I implemented your amazing piece of work into the latest Arduino framework for ESP8266 WiFi MCUs, and I run into some problems :)
Here is the current status of my partition

==== SPIFFS Info ====
FS Mount: 1
FS Size: 7.00MB
FS Bytes: total: 27.45KB, used: 27.45KB
FS Blocks: total: 896, free: 335, size: 8.00KB
FS Pages: allocated: 112, deleted: 17276, size: 256B
FS File: /edit.htm, type: file, size: 19.43KB
FS File: /favicon.ico, type: file, size: 1.12KB
FS File: /graphs.js, type: file, size: 3.76KB
FS File: /index.htm, type: file, size: 1.51KB

Now onto the issues:
When written often onto, the FS generates lots of blocks with a few pages of data, or all deleted pages, which is part of the design, but when you get to the edges and have a larger file coming in (let's say I upload 900KB jpeg image), the time it takes to do a garbage cleanup for space triggers a watchdog reset. I do not know how familiar you are with the MCU, but the SPIFFS lives on the same flash as the firmware,so when it's accessed, all interrupts are stopped and CPU is locked.
When you have a larger partition like this 7MB one in my example, listing the root folder also takes way too long (i guess it goes to search for files in all blocks/pages), now I have tried using larger blocks but at some point the FS is unusable due to the mentioned watchdog resets (do not know the reason for those here).
I read that you run such a routine when a file is being written, and you check if there are enough free blocks to write the file, and if there are not enough or the free blocks are less than 3, garbage cleaner runs to free that space. I tried implementing that but had no luck on properly using the FS afterwards (could read fine but not write to it).
So I think that if you add such routine to the API, the user/firmware can decide when to run it and keep data aligned.

SPIFFS_remove() gets stuck in spiffs_object_truncate()/spiffs_gc_clean()

Hi again ;)

I managed to get the fs to a state where attempting to remove a certain file (I haven't checked other files yet because I'm afraid I might not be able to reproduce this again) gets the system stuck - which is a bit of an unfortunate outcome.

Enabling the debug output suggests the culprit is spiffs_gc_clean() or rather spiffs_obj_lu_find_entry_visitor() where it gets stuck on _spiffs_rd.

The output is

2015-06-12 13:13:44,767 - INFO # open: fd 1 is obj id 8071
2015-06-12 13:13:44,776 - INFO # gc_check #0: run gc free_blocks:3 pfree:59 pallo:2686 pdele:1161 [3906] len:0 of 7257
2015-06-12 13:13:44,779 - INFO # gc_check: bix:0 del:5 use:26 score:4449
2015-06-12 13:13:44,783 - INFO # gc_check: bix:1 del:6 use:25 score:4555
2015-06-12 13:13:44,786 - INFO # gc_check: bix:2 del:7 use:24 score:4411
2015-06-12 13:13:44,790 - INFO # gc_check: bix:3 del:8 use:23 score:4367
2015-06-12 13:13:44,793 - INFO # gc_check: bix:4 del:8 use:23 score:4317
2015-06-12 13:13:44,797 - INFO # gc_check: bix:5 del:7 use:24 score:4261
2015-06-12 13:13:44,800 - INFO # gc_check: bix:6 del:5 use:26 score:4199
2015-06-12 13:13:44,804 - INFO # gc_check: bix:7 del:7 use:24 score:4161
2015-06-12 13:13:44,807 - INFO # gc_check: bix:8 del:8 use:23 score:4117
2015-06-12 13:13:44,811 - INFO # gc_check: bix:9 del:6 use:25 score:4055
2015-06-12 13:13:44,814 - INFO # gc_check: bix:10 del:5 use:26 score:3999
2015-06-12 13:13:44,818 - INFO # gc_check: bix:11 del:5 use:26 score:3949
2015-06-12 13:13:44,821 - INFO # gc_check: bix:12 del:7 use:24 score:3911
2015-06-12 13:13:44,825 - INFO # gc_check: bix:13 del:6 use:25 score:3855
2015-06-12 13:13:44,829 - INFO # gc_check: bix:14 del:7 use:24 score:3811
2015-06-12 13:13:44,832 - INFO # gc_check: bix:15 del:12 use:19 score:3791
2015-06-12 13:13:44,836 - INFO # gc_check: bix:16 del:7 use:24 score:3711
2015-06-12 13:13:44,840 - INFO # gc_check: bix:17 del:3 use:28 score:3637
2015-06-12 13:13:44,843 - INFO # gc_check: bix:18 del:5 use:26 score:3599
2015-06-12 13:13:44,847 - INFO # gc_check: bix:19 del:4 use:27 score:3543
2015-06-12 13:13:44,850 - INFO # gc_check: bix:20 del:4 use:27 score:3493
2015-06-12 13:13:44,854 - INFO # gc_check: bix:21 del:4 use:27 score:3443
2015-06-12 13:13:44,858 - INFO # gc_check: bix:22 del:4 use:27 score:3393
2015-06-12 13:13:44,861 - INFO # gc_check: bix:23 del:11 use:20 score:3385
2015-06-12 13:13:44,865 - INFO # gc_check: bix:24 del:3 use:28 score:3287
2015-06-12 13:13:44,868 - INFO # gc_check: bix:25 del:5 use:26 score:3249
2015-06-12 13:13:44,872 - INFO # gc_check: bix:26 del:7 use:24 score:3211
2015-06-12 13:13:44,876 - INFO # gc_check: bix:27 del:10 use:21 score:3179
2015-06-12 13:13:44,879 - INFO # gc_check: bix:28 del:7 use:24 score:3111
2015-06-12 13:13:44,883 - INFO # gc_check: bix:29 del:12 use:19 score:3091
2015-06-12 13:13:44,887 - INFO # gc_check: bix:30 del:14 use:17 score:3053
2015-06-12 13:13:44,890 - INFO # gc_check: bix:31 del:11 use:20 score:2935
2015-06-12 13:13:44,894 - INFO # gc_check: bix:32 del:6 use:25 score:2955
2015-06-12 13:13:44,898 - INFO # gc_check: bix:33 del:6 use:25 score:2805
2015-06-12 13:13:44,901 - INFO # gc_check: bix:34 del:5 use:26 score:2849
2015-06-12 13:13:44,905 - INFO # gc_check: bix:35 del:6 use:25 score:2755
2015-06-12 13:13:44,908 - INFO # gc_check: bix:36 del:10 use:21 score:2729
2015-06-12 13:13:44,912 - INFO # gc_check: bix:37 del:12 use:19 score:2691
2015-06-12 13:13:44,916 - INFO # gc_check: bix:38 del:10 use:21 score:2629
2015-06-12 13:13:44,919 - INFO # gc_check: bix:39 del:12 use:19 score:2591
2015-06-12 13:13:44,923 - INFO # gc_check: bix:40 del:10 use:21 score:2529
2015-06-12 13:13:44,927 - INFO # gc_check: bix:41 del:11 use:20 score:2485
2015-06-12 13:13:44,931 - INFO # gc_check: bix:42 del:10 use:21 score:2429
2015-06-12 13:13:44,934 - INFO # gc_check: bix:43 del:11 use:20 score:2385
2015-06-12 13:13:44,938 - INFO # gc_check: bix:44 del:9 use:22 score:2323
2015-06-12 13:13:44,941 - INFO # gc_check: bix:45 del:8 use:23 score:2267
2015-06-12 13:13:44,945 - INFO # gc_check: bix:46 del:8 use:23 score:2217
2015-06-12 13:13:44,949 - INFO # gc_check: bix:47 del:10 use:21 score:2179
2015-06-12 13:13:44,952 - INFO # gc_check: bix:48 del:8 use:23 score:2117
2015-06-12 13:13:44,956 - INFO # gc_check: bix:49 del:10 use:21 score:2079
2015-06-12 13:13:44,960 - INFO # gc_check: bix:50 del:10 use:21 score:2029
2015-06-12 13:13:44,963 - INFO # gc_check: bix:51 del:11 use:20 score:1985
2015-06-12 13:13:44,967 - INFO # gc_check: bix:52 del:6 use:25 score:1905
2015-06-12 13:13:44,971 - INFO # gc_check: bix:53 del:10 use:21 score:1879
2015-06-12 13:13:44,974 - INFO # gc_check: bix:54 del:10 use:21 score:1829
2015-06-12 13:13:44,978 - INFO # gc_check: bix:55 del:9 use:22 score:1773
2015-06-12 13:13:44,982 - INFO # gc_check: bix:56 del:6 use:25 score:1705
2015-06-12 13:13:44,985 - INFO # gc_check: bix:57 del:9 use:22 score:1673
2015-06-12 13:13:44,989 - INFO # gc_check: bix:58 del:10 use:21 score:1629
2015-06-12 13:13:44,992 - INFO # gc_check: bix:59 del:5 use:26 score:1549
2015-06-12 13:13:44,996 - INFO # gc_check: bix:60 del:6 use:25 score:1505
2015-06-12 13:13:45,000 - INFO # gc_check: bix:61 del:7 use:24 score:1461
2015-06-12 13:13:45,003 - INFO # gc_check: bix:62 del:6 use:25 score:1405
2015-06-12 13:13:45,007 - INFO # gc_check: bix:63 del:7 use:24 score:1361
2015-06-12 13:13:45,010 - INFO # gc_check: bix:64 del:11 use:20 score:1335
2015-06-12 13:13:45,014 - INFO # gc_check: bix:65 del:4 use:27 score:1243
2015-06-12 13:13:45,018 - INFO # gc_check: bix:66 del:6 use:25 score:1205
2015-06-12 13:13:45,021 - INFO # gc_check: bix:67 del:10 use:21 score:1179
2015-06-12 13:13:45,025 - INFO # gc_check: bix:68 del:3 use:28 score:1037
2015-06-12 13:13:45,029 - INFO # gc_check: bix:69 del:11 use:20 score:1035
2015-06-12 13:13:45,032 - INFO # gc_check: bix:70 del:15 use:16 score:1159
2015-06-12 13:13:45,036 - INFO # gc_check: bix:71 del:8 use:23 score:917
2015-06-12 13:13:45,039 - INFO # gc_check: bix:72 del:8 use:23 score:967
2015-06-12 13:13:45,043 - INFO # gc_check: bix:73 del:9 use:22 score:873
2015-06-12 13:13:45,046 - INFO # gc_check: bix:74 del:9 use:22 score:773
2015-06-12 13:13:45,050 - INFO # gc_check: bix:75 del:12 use:19 score:841
2015-06-12 13:13:45,053 - INFO # gc_check: bix:76 del:7 use:24 score:711
2015-06-12 13:13:45,057 - INFO # gc_check: bix:77 del:6 use:25 score:655
2015-06-12 13:13:45,060 - INFO # gc_check: bix:78 del:16 use:15 score:6215
2015-06-12 13:13:45,064 - INFO # gc_check: bix:79 del:13 use:18 score:6147
2015-06-12 13:13:45,068 - INFO # gc_check: bix:80 del:5 use:26 score:549
2015-06-12 13:13:45,071 - INFO # gc_check: bix:81 del:15 use:16 score:6059
2015-06-12 13:13:45,075 - INFO # gc_check: bix:82 del:13 use:18 score:6097
2015-06-12 13:13:45,079 - INFO # gc_check: bix:83 del:6 use:25 score:605
2015-06-12 13:13:45,082 - INFO # gc_check: bix:84 del:6 use:25 score:455
2015-06-12 13:13:45,086 - INFO # gc_check: bix:85 del:16 use:15 score:6015
2015-06-12 13:13:45,089 - INFO # gc_check: bix:86 del:15 use:16 score:5959
2015-06-12 13:13:45,093 - INFO # gc_check: bix:87 del:15 use:16 score:5909
2015-06-12 13:13:45,096 - INFO # gc_check: bix:88 del:5 use:26 score:499
2015-06-12 13:13:45,100 - INFO # gc_check: bix:89 del:16 use:15 score:5865
2015-06-12 13:13:45,103 - INFO # gc_check: bix:90 del:17 use:14 score:5821
2015-06-12 13:13:45,107 - INFO # gc_check: bix:91 del:17 use:14 score:5771
2015-06-12 13:13:45,110 - INFO # gc_check: bix:92 del:7 use:24 score:361
2015-06-12 13:13:45,114 - INFO # gc_check: bix:93 del:5 use:26 score:399
2015-06-12 13:13:45,118 - INFO # gc_check: bix:94 del:17 use:14 score:5721
2015-06-12 13:13:45,121 - INFO # gc_check: bix:95 del:20 use:11 score:5689
2015-06-12 13:13:45,125 - INFO # gc_check: bix:96 del:5 use:26 score:249
2015-06-12 13:13:45,128 - INFO # gc_check: bix:97 del:17 use:14 score:5621
2015-06-12 13:13:45,132 - INFO # gc_check: bix:98 del:6 use:25 score:305
2015-06-12 13:13:45,136 - INFO # gc_check: bix:99 del:16 use:15 score:5565
2015-06-12 13:13:45,140 - INFO # gc_check: bix:100 del:17 use:14 score:5521
2015-06-12 13:13:45,143 - INFO # gc_check: bix:101 del:12 use:19 score:5441
2015-06-12 13:13:45,147 - INFO # gc_check: bix:102 del:17 use:14 score:5421
2015-06-12 13:13:45,151 - INFO # gc_check: bix:103 del:1 use:2 score:203
2015-06-12 13:13:45,154 - INFO # gc_check: bix:104 del:17 use:14 score:5371
2015-06-12 13:13:45,158 - INFO # gc_check: bix:105 del:17 use:14 score:5321
2015-06-12 13:13:45,162 - INFO # gc_check: bix:106 del:18 use:13 score:5277
2015-06-12 13:13:45,166 - INFO # gc_check: bix:109 del:15 use:16 score:5209
2015-06-12 13:13:45,169 - INFO # gc_check: bix:110 del:9 use:22 score:5123
2015-06-12 13:13:45,173 - INFO # gc_check: bix:111 del:8 use:23 score:6417
2015-06-12 13:13:45,177 - INFO # gc_check: bix:112 del:14 use:17 score:5103
2015-06-12 13:13:45,181 - INFO # gc_check: bix:114 del:18 use:13 score:5077
2015-06-12 13:13:45,184 - INFO # gc_check: bix:115 del:6 use:25 score:6305
2015-06-12 13:13:45,188 - INFO # gc_check: bix:116 del:9 use:22 score:4973
2015-06-12 13:13:45,192 - INFO # gc_check: bix:117 del:8 use:23 score:4917
2015-06-12 13:13:45,195 - INFO # gc_check: bix:118 del:8 use:23 score:6367
2015-06-12 13:13:45,199 - INFO # gc_check: bix:119 del:18 use:13 score:6277
2015-06-12 13:13:45,203 - INFO # gc_check: bix:120 del:19 use:12 score:4933
2015-06-12 13:13:45,207 - INFO # gc_check: bix:121 del:6 use:25 score:4755
2015-06-12 13:13:45,210 - INFO # gc_check: bix:122 del:6 use:25 score:4805
2015-06-12 13:13:45,214 - INFO # gc_check: bix:123 del:7 use:24 score:6261
2015-06-12 13:13:45,218 - INFO # gc_check: bix:124 del:10 use:21 score:4729
2015-06-12 13:13:45,221 - INFO # gc_check: bix:125 del:7 use:24 score:4611
2015-06-12 13:13:45,225 - INFO # gc_check: bix:126 del:6 use:25 score:4655
2015-06-12 13:13:45,229 - INFO # gc_check: bix:127 del:7 use:24 score:4511
2015-06-12 13:13:45,231 - INFO # gc_clean: cleaning block 111
2015-06-12 13:13:45,234 - INFO # gc_clean: state = 0 entry:0
2015-06-12 13:13:45,238 - INFO # gc_clean: FIND_DATA state:0 - found obj id 0041
2015-06-12 13:13:45,242 - INFO # gc_clean: FIND_DATA find objix span_ix:0004
2015-06-12 13:13:45,245 - INFO # spiffs_obj_lu_find_entry_visitor:135 | 0
2015-06-12 13:13:45,249 - INFO # spiffs_obj_lu_find_entry_visitor:141 | 0
2015-06-12 13:13:45,253 - INFO # spiffs_obj_lu_find_entry_visitor:158 | 0
2015-06-12 13:13:45,258 - INFO # spiffs_obj_lu_find_entry_visitor:161 | entry_count = 3968
2015-06-12 13:13:45,263 - INFO # spiffs_obj_lu_find_entry_visitor:165 | obj_lookup_page = 0

Cache is disabled here as I use this in my bootloader where I wanted to save as much space as possible.
edit: just tried it with cache enabled and it gets stuck regardless

Implementation of "defragmentation" method needed

Hello :) this is a cry out for a defragmentation function.
The case is as follows:
We are using 4MB ESP8266 mcus and run web servers on them.
We often edit, write and change files on the system and all is fine and dandy until we get to the point where all of our free blocks are gone, we are full of deleted pages and each new write requires to go around, relocate pages to free blocks and so on. While that is usually not a big deal for small files, it's really noticeable on larger ones that require many blocks to be cleared. And since recent changes in Espressifs SDK, while running asynchronous network and writing an upload to a file, the stack loses retransmitted packets and data is lost. I know that fact has nothing to do with you, but I still find in many cases the need to speed up the file system.
As an example, I have this 100K test file that get's uploaded for 440ms when SPIFFS has enough free blocks and for 2000ms when there are none (if the upload succeeds). And I have filled actually less than 10% of the available space with data. The rest is all deleted pages.

Nonissue: ESP8266 Arduino examples

With SPIFFS more integrated into the ESP8266 Arduino environment (there is a default 64K FS now in latest builds) and the sizes are adjustable by setting new targets), it would be extremely helpful to have a couple examples of how to use the calls and load files onto the system and read them off.

If you don't have time, not a problem but several ESP enthusiasts are eager to try your great work.

Thank you for your consideration, Mike

0.3.2 <-> 0.3.3 incompatibility

it's not mentioned in the readme, so i thought i'd ask: is the incompatibility b/w 0.3.2 and 0.3.3 expected?
filesystems produced by them are mutually incompatible, though in a slightly different way.

ideally, of course, i'd like this fixed and compatibility restored, but i do realize we're at version 0.3 here, so i'll accept "yes, deal with it" as an answer, but i want to be sure it's expected. in which case it should be in readme.

fwiw, here's my test output. fs1.{old,new}.spiffs are filesystem images that contain two files" badger_badger.json and mushroom.html, created by 0.3.2-ish and current master respectively. dump_spiffs mounts and lists files on the filesystem image, old and new have been compiled with the same source respectively:

$ ./dump_spiffs.old fs1.old.spiffs 
mounted fs1.old.spiffs (65536 bytes)
   0 iddiddddddddddd    era_cnt: N/A
   1 ddddddddddddddd    era_cnt: N/A
   2 ddddddddddddddd    era_cnt: N/A
   3 ddddddddddddddd    era_cnt: N/A
   4 ddd____________    era_cnt: N/A
   5 _______________    era_cnt: N/A
   6 _______________    era_cnt: N/A
   7 _______________    era_cnt: N/A
   8 _______________    era_cnt: N/A
   9 _______________    era_cnt: N/A
  10 _______________    era_cnt: N/A
  11 _______________    era_cnt: N/A
  12 _______________    era_cnt: N/A
  13 _______________    era_cnt: N/A
  14 _______________    era_cnt: N/A
  15 _______________    era_cnt: N/A
era_cnt_max: 1
last_errno:  0
blocks:      16
free_blocks: 11
page_alloc:  63
page_delet:  0
used:        15813 of 52961
check result: 0
entry: |badger_badger.json|
entry: |mushroom.html|

new code reads old image with filenames truncated:

$ ./dump_spiffs.new fs1.old.spiffs                                                                                                                                                
...same stuff here...
check result: 0
entry: |dger_badger.json|
entry: |shroom.html|

old code just doesn't find any files at all:

$ ./dump_spiffs.old fs1.new.spiffs 
mounted fs1.new.spiffs (65536 bytes)
   0 iddiddddddddddd    era_cnt: N/A
   1 ddddddddddddddd    era_cnt: N/A
   2 ddddddddddddddd    era_cnt: N/A
   3 ddddddddddddddd    era_cnt: N/A
   4 ddd____________    era_cnt: N/A
   5 _______________    era_cnt: N/A
   6 _______________    era_cnt: N/A
   7 _______________    era_cnt: N/A
   8 _______________    era_cnt: N/A
   9 _______________    era_cnt: N/A
  10 _______________    era_cnt: N/A
  11 _______________    era_cnt: N/A
  12 _______________    era_cnt: N/A
  13 _______________    era_cnt: N/A
  14 _______________    era_cnt: N/A
  15 _______________    era_cnt: N/A
era_cnt_max: 1
last_errno:  0
blocks:      16
free_blocks: 11
page_alloc:  63
page_delet:  0
used:        15813 of 52961
check result: 0

(nothing after SPIFFS_check result, so SPIFFS_readdir must've returned NULL straight away)

SPIFFS_write function does not work when SPIFFS_APPEND is specified

I'm on Mac OSX 10.11.1, and I'm using the spiffs framework with sming to program an ESP201

I ran into a problem where I was unable to write to a file (using SPIFFS_write) I had opened with the SPIFFS_APPEND flag called. I was getting the error SPIFFS_ERR_NOT_WRITABLE with the error code -10021. After some testing I discovered that the root of the problem seems to be this section of code,

if ((fd->flags & SPIFFS_WRONLY) == 0) {
  res = SPIFFS_ERR_NOT_WRITABLE;
  SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}

I believe this code dictates that SPIFFS_write will only work if opened when the flag is set to SPIFFS_WRONLY this becomes a problem when calling SPIFFS_write when a file is opened in SPIFFS_APPEND

If I change the bitwise operation in the if clause's condition to
(fd-> flags & (SPIFFS_WRONLY | SPIFFS_APPEND)) == 0
I am able to append to the file I opened, and my code behaves as it should.

Got 31 failed by running ./build/linux_spiffs_test

I am making 'linux_spiffs_test' with revision 1aa4d63 (without any modifications) by following commands in my Mint17 64 bits Linux host :
mkdir build
make
./build/linux_spiffs_test

Got some report like this :
...
...
Test report, 60 tests
29 succeeded
31 failed
lu_check1
page_cons1
page_cons2
page_cons3
page_cons_final
index_cons1
index_cons2
index_cons3
index_cons4
open_by_dirent
write_big_file_chunks_page
write_big_files_chunks_page
write_big_file_chunks_index
write_big_files_chunks_index
write_big_file_chunks_huge
write_big_files_chunks_huge
truncate_big_file
bad_index_1
bad_index_2
lseek_simple_modification
lseek_modification_append
lseek_modification_append_multi
gc_quick
write_small_file_chunks_1
write_small_files_chunks_1
write_big_file_chunks_1
write_big_files_chunks_1
long_run_config_many_small_one_long
long_run_config_many_medium
long_run_config_many_small
long_run
0 stopped

FAILED

Is there any suggestion on these failed messages ?

Bug in truncate function

Hello,

I was trying to truncate a file using the function spiffs_object_truncate() and I noticed it was not working properly with smaller files. (I tried to truncate a 51 bytes file to 5, for example).

So I noticed this line inside its implementation:

if (cur_size - SPIFFS_DATA_PAGE_SIZE(fs) >= new_size)

In this case, both cur_size and new_size are u32_t. For this reason, even though the left argument in the comparison should be negative, it is not, it is a a very big unsigned int and therefore this condition becomes true when it should be false.

So I changed this line to the following and the issue seemed to be fixed.

if ((s32_t)cur_size - (s32_t)(SPIFFS_DATA_PAGE_SIZE(fs)) >= (s32_t)new_size)

Please confirm that this spotted issue is correct!

Thanks

Confused about padding in "spiffs_page_object_ix"

I was confused about padding in "spiffs_page_object_ix", do you mean
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : 4 - (sizeof(spiffs_page_header)&3)];
instead of
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)];
to make "spiffs_page_object_ix" 4-byte alignment ?

Add SPIFFS_EXCL

As spiffs nowadays are checking if filename exists, it would be easy adding SPIFFS_EXCL to SPIFFS_open

compilation error

got the following compilation error for SPIFFS_readdir,
SPIFFS_LOCK(fs);

fixed by SPIFFS_LOCK(d->fs);

Lots of static analysis bugs

spiffs_nucleus.c spiffs_object_modify line 1218 new_objix_pix is never initialized
spiffs_nucleus.c spiffs_obj_lu_find_free_obj_id line 1710 possible division by zero

state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));

Also lots of warnings for never read result value. Better to not store result at all otherwise written code has no effect.

spiffs_nucleus.c spiffs_object_modify line 1135 value of res is never read
spiffs_hydrogen.c SPIFFS_write line 324 value of res never read
spiffs_hydrogen.c SPIFFS_check line 700 res never read
...

two files with the same name

Hi again 😉
I just discovered this on one of my nodes and I find it a bit unsettling

2015-06-16 17:41:49,324 - INFO # > ls
2015-06-16 17:41:49,324 - INFO # 
2015-06-16 17:41:49,326 - INFO #    4 >dummy.hex.tmp<
2015-06-16 17:41:49,328 - INFO #    4096 >dummy.hex.tmp<

where ls is

int ls(void) {
    spiffs_DIR dir;
    struct spiffs_dirent file;

    SPIFFS_opendir(&spi_fs, 0, &dir);

    while (SPIFFS_readdir(&dir, &file)) {
        printf("\t%d >%s<\n", file.size, file.name);
    }

    SPIFFS_closedir(&dir);

    return 0;
}

I'm not exactly sure how I got there (Yes, I know this makes for a great bug report), but I think the fs shouldn't allow this.

(the 4 byte file should be the one with the .tmp suffix and later gets renamed to .a32 - it contains the checksum of the file without the suffix)

creating a file fails with different errors

Hi,
again, I'm having a strange issue - which might well be on my part, but I'm not sure where to look.
We changed our MCU on the new board but kept all the code and also the flash chip, so after implementing my interface for spi, spiffs should work again happily, right?
The flash driver remained untouched and it does write and read back the raw data, at least in my test cases so far - so spiffs shouldn't behave any different than on the old hardware. (old hardware -new hardware)

Except for when it does - in interesting ways.

I've narrowed it down to one byte being different after initializing the fs (at least that's consistent), what happens afterwards (especially the error values that I pull out of spiffs) seems to be rather random:

> ls
2016-01-12 18:20:56,238 - INFO #    0 .volaWare
> dump_rom hello_cli.hex
2016-01-12 18:21:06,240 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:21:07,752 - INFO # 0 bytes written
2016-01-12 18:21:07,758 - INFO # error: -10072
> ls
2016-01-12 18:21:16,956 - INFO #    0 .volaWare
2016-01-12 18:21:16,956 - INFO #    0 hello_cli.hex
2016-01-12 18:21:16,962 - INFO #    4 hello_cli.hex.a32
> dump_rom hello_cli.hex
2016-01-12 18:23:20,202 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:23:20,202 - INFO # 0 bytes written
2016-01-12 18:23:20,203 - INFO # error: -10072
> dump_rom hello_cli.hex
2016-01-12 18:23:22,243 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:23:23,754 - INFO # 0 bytes written
2016-01-12 18:23:23,760 - INFO # error: -10002
> dump_rom hello_cli.hex
2016-01-12 18:23:25,800 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:23:25,801 - INFO # 0 bytes written
2016-01-12 18:23:25,806 - INFO # error: -10015
> dump_rom hello_cli.hex
2016-01-12 18:23:26,628 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:23:26,629 - INFO # 0 bytes written
2016-01-12 18:23:26,630 - INFO # error: -10003
> dump_rom hello_cli.hex
2016-01-12 18:23:27,150 - INFO # writing firmware to hello_cli.hex…
2016-01-12 18:23:27,151 - INFO # 0 bytes written
2016-01-12 18:23:27,156 - INFO # error: -10015
> ls
2016-01-12 18:23:32,869 - INFO #    0 .volaWare
2016-01-12 18:23:32,874 - INFO #    0 hello_cli.hex
2016-01-12 18:23:32,875 - INFO #    0 hello_cli.hex.a32
2016-01-12 18:23:32,880 - INFO #    4 hello_cli.hex.a32

(that dump_rom fails at SPIFFS_open(&spi_fs, file, SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_RDWR, 0); already, I'm not sure why a later open that creates the checksum file does through)

The initialization looks like this

#define LOG_PAGE_SIZE 128
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
static u8_t spiffs_fds[32*4];
static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];

spiffs spi_fs;

void my_spiffs_mount(bool create_magic) {
    spiffs_config cfg;
    cfg.phys_addr        = 0;           // start spiffs at start of spi flash
    cfg.phys_size        = flash_get_size() - cfg.phys_addr; // use all spi flash
    cfg.phys_erase_block = BLOCK_4K;    // according to datasheet
    cfg.log_block_size   = BLOCK_4K;    // let us not complicate things
    cfg.log_page_size    = LOG_PAGE_SIZE;
    cfg.hal_read_f  = (spiffs_read)  flash_read_page;
    cfg.hal_write_f = (spiffs_write) flash_write_page;
    cfg.hal_erase_f = (spiffs_erase) flash_erase_block;
    int res = SPIFFS_mount(&spi_fs,
        &cfg,
        spiffs_work_buf,
        spiffs_fds,
        sizeof(spiffs_fds),
        spiffs_cache_buf,
        sizeof(spiffs_cache_buf),
        0);

    if (res == 0) {
        // 'magic' file
        res = SPIFFS_open(&spi_fs, ".volaWare", create_magic ? SPIFFS_CREAT : SPIFFS_RDONLY, 0);
        if (res > 0)
            SPIFFS_close(&spi_fs, res);
    }
    if (res < 0) {
        printf("mount failed (%d), formatting device…\n", res);
        flash_erase_block(0, BLOCK_ALL);
        printf("done.\n");

        my_spiffs_mount(true);
    }
}

Do you have any idea what that might be, when that byte is written and what might happen here?
There is no OS in the background and only the uart interrupt triggering - just to be sure I also disable all interrupts during an spi transfer.

Thanks again!

i2c version?

Does this file system usable with i2c devices like 24lc1024?
They have 64byte page and need to wait before send another page (i2c nack)

30 out of 49 tests fail

I've checked out the repository and ran make which got me linux_spiffs_test.
Running this invokes the spiff test suite that prints:

Test report, 49 tests
19 succeeded
30 failed
  lu_check1
  page_cons1
  page_cons2
  page_cons3
  page_cons_final
  index_cons1
  index_cons2
  index_cons3
  index_cons4
  open_by_dirent
  write_big_file_chunks_page
  write_big_files_chunks_page
  write_big_file_chunks_index
  write_big_files_chunks_index
  write_big_file_chunks_huge
  write_big_files_chunks_huge
  truncate_big_file
  bad_index_1
  bad_index_2
  lseek_simple_modification
  lseek_modification_append
  lseek_modification_append_multi
  write_small_file_chunks_1
  write_small_files_chunks_1
  write_big_file_chunks_1
  write_big_files_chunks_1
  long_run_config_many_small_one_long
  long_run_config_many_medium
  long_run_config_many_small
  long_run
0 stopped

Does that mean the file system is still full of errors?

spiffs_cache buffer declaration steps on spiffs_cache struct

The integration guide calls out 3 buffers
static u8_t spiffs_work_buf[LOG_PAGE_SIZE_2];
static u8_t spiffs_fds[32_4];
static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*4];

Use of a buffer named spiffs_cache steps on the already defined spiffs_cache struct

Recommend changing name of spiffs_cache buffer (also used in mount example code) to spiffs_cache_buf.

Zero-size files cannot be read

An empty file (zero bytes) can be successfully written but cannot be read.
The errno returned is -10015 (SPIFFS_ERR_INDEX_REF_FREE)

Add typesize info to integration docs

Mention these in integration doc also, spiffs_config.h

typedef u16_t spiffs_block_ix;
typedef u16_t spiffs_page_ix;
typedef u16_t spiffs_obj_id;
typedef u16_t spiffs_span_ix;

[feature request] store checksum for files

Hi,
Have you thought about storing a checksum for files somewhere to make it possible to detect corruption?
I'm thinking about changing my file format for firmware binaries to include a checksum, but I'm wondering whether it wouldn't be better to do at file system level (mostly because my firmware files are currently just a ROM dump and I like to keep things simple 😉)

0 free blocks after mounting on a fresh fs

Hi,
I'm not sure if that's the right place to ask support questions, but then again I just followed your steps in docs/INTEGRATION so it might as well be a bug 😉

I pretty much hooked up spiffs as suggested, I didn't change the default config except for enabling SPIFFS_USE_MAGIC to see if the fs gets properly created at all - it appears to be.
But no matter what I do, SPIFFS_mount will always report 0 free blocks - and subsequently attempting to create a file obviously fails. The Flash is freshly formatted with SPIFFS_format, there shouldn't be anything on it.

What might I be missing?

2015-05-28 17:52:20,611 - INFO # INIT FLASH MEMORY (JEDEC format)
2015-05-28 17:52:20,616 - INFO #           MANUFACTURER:              0x44 (ADESTO)
2015-05-28 17:52:20,619 - INFO #           DEVICE-ID-1:               0x1f
2015-05-28 17:52:20,623 - INFO #           DEVICE-ID-2:               0x01
2015-05-28 17:52:20,625 - INFO #           -------------
2015-05-28 17:52:20,629 - INFO #           DENSITY:                   4MBit
2015-05-28 17:52:20,632 - INFO # -- init done, starting main --
2015-05-28 17:52:20,633 - INFO # erasing flash…
2015-05-28 17:52:23,363 - INFO # mounting…
2015-05-28 17:52:23,363 - INFO # mount res: -1
2015-05-28 17:52:23,364 - INFO # SPIFFS_format
2015-05-28 17:52:23,367 - INFO # erase 00000000:00001000
2015-05-28 17:52:23,404 - INFO # erase 00001000:00001000
2015-05-28 17:52:23,443 - INFO # erase 00002000:00001000
2015-05-28 17:52:23,479 - INFO # erase 00003000:00001000
2015-05-28 17:52:23,516 - INFO # erase 00004000:00001000
2015-05-28 17:52:23,553 - INFO # erase 00005000:00001000
2015-05-28 17:52:23,590 - INFO # erase 00006000:00001000
2015-05-28 17:52:23,628 - INFO # erase 00007000:00001000
2015-05-28 17:52:23,666 - INFO # erase 00008000:00001000
2015-05-28 17:52:23,704 - INFO # erase 00009000:00001000
2015-05-28 17:52:23,742 - INFO # erase 0000a000:00001000
2015-05-28 17:52:23,779 - INFO # erase 0000b000:00001000
2015-05-28 17:52:23,817 - INFO # erase 0000c000:00001000
2015-05-28 17:52:23,854 - INFO # erase 0000d000:00001000
2015-05-28 17:52:23,891 - INFO # erase 0000e000:00001000
2015-05-28 17:52:23,930 - INFO # erase 0000f000:00001000
2015-05-28 17:52:23,967 - INFO # erase 00010000:00001000
2015-05-28 17:52:24,004 - INFO # erase 00011000:00001000
2015-05-28 17:52:24,040 - INFO # erase 00012000:00001000
2015-05-28 17:52:24,079 - INFO # erase 00013000:00001000
2015-05-28 17:52:24,117 - INFO # erase 00014000:00001000
2015-05-28 17:52:24,154 - INFO # erase 00015000:00001000
2015-05-28 17:52:24,192 - INFO # erase 00016000:00001000
2015-05-28 17:52:24,229 - INFO # erase 00017000:00001000
2015-05-28 17:52:24,266 - INFO # erase 00018000:00001000
2015-05-28 17:52:24,304 - INFO # erase 00019000:00001000
2015-05-28 17:52:24,341 - INFO # erase 0001a000:00001000
2015-05-28 17:52:24,377 - INFO # erase 0001b000:00001000
2015-05-28 17:52:24,414 - INFO # erase 0001c000:00001000
2015-05-28 17:52:24,451 - INFO # erase 0001d000:00001000
2015-05-28 17:52:24,487 - INFO # erase 0001e000:00001000
2015-05-28 17:52:24,525 - INFO # erase 0001f000:00001000
2015-05-28 17:52:24,561 - INFO # erase 00020000:00001000
2015-05-28 17:52:24,597 - INFO # erase 00021000:00001000
2015-05-28 17:52:24,634 - INFO # erase 00022000:00001000
2015-05-28 17:52:24,671 - INFO # erase 00023000:00001000
2015-05-28 17:52:24,709 - INFO # erase 00024000:00001000
2015-05-28 17:52:24,746 - INFO # erase 00025000:00001000
2015-05-28 17:52:24,783 - INFO # erase 00026000:00001000
2015-05-28 17:52:24,820 - INFO # erase 00027000:00001000
2015-05-28 17:52:24,857 - INFO # erase 00028000:00001000
2015-05-28 17:52:24,894 - INFO # erase 00029000:00001000
2015-05-28 17:52:24,931 - INFO # erase 0002a000:00001000
2015-05-28 17:52:24,968 - INFO # erase 0002b000:00001000
2015-05-28 17:52:25,005 - INFO # erase 0002c000:00001000
2015-05-28 17:52:25,042 - INFO # erase 0002d000:00001000
2015-05-28 17:52:25,080 - INFO # erase 0002e000:00001000
2015-05-28 17:52:25,117 - INFO # erase 0002f000:00001000
2015-05-28 17:52:25,154 - INFO # erase 00030000:00001000
2015-05-28 17:52:25,191 - INFO # erase 00031000:00001000
2015-05-28 17:52:25,228 - INFO # erase 00032000:00001000
2015-05-28 17:52:25,265 - INFO # erase 00033000:00001000
2015-05-28 17:52:25,302 - INFO # erase 00034000:00001000
2015-05-28 17:52:25,340 - INFO # erase 00035000:00001000
2015-05-28 17:52:25,377 - INFO # erase 00036000:00001000
2015-05-28 17:52:25,414 - INFO # erase 00037000:00001000
2015-05-28 17:52:25,452 - INFO # erase 00038000:00001000
2015-05-28 17:52:25,488 - INFO # erase 00039000:00001000
2015-05-28 17:52:25,525 - INFO # erase 0003a000:00001000
2015-05-28 17:52:25,562 - INFO # erase 0003b000:00001000
2015-05-28 17:52:25,599 - INFO # erase 0003c000:00001000
2015-05-28 17:52:25,637 - INFO # erase 0003d000:00001000
2015-05-28 17:52:25,673 - INFO # erase 0003e000:00001000
2015-05-28 17:52:25,710 - INFO # erase 0003f000:00001000
2015-05-28 17:52:25,747 - INFO # erase 00040000:00001000
2015-05-28 17:52:25,783 - INFO # erase 00041000:00001000
2015-05-28 17:52:25,820 - INFO # erase 00042000:00001000
2015-05-28 17:52:25,858 - INFO # erase 00043000:00001000
2015-05-28 17:52:25,896 - INFO # erase 00044000:00001000
2015-05-28 17:52:25,934 - INFO # erase 00045000:00001000
2015-05-28 17:52:25,972 - INFO # erase 00046000:00001000
2015-05-28 17:52:26,011 - INFO # erase 00047000:00001000
2015-05-28 17:52:26,048 - INFO # erase 00048000:00001000
2015-05-28 17:52:26,086 - INFO # erase 00049000:00001000
2015-05-28 17:52:26,122 - INFO # erase 0004a000:00001000
2015-05-28 17:52:26,160 - INFO # erase 0004b000:00001000
2015-05-28 17:52:26,198 - INFO # erase 0004c000:00001000
2015-05-28 17:52:26,236 - INFO # erase 0004d000:00001000
2015-05-28 17:52:26,273 - INFO # erase 0004e000:00001000
2015-05-28 17:52:26,311 - INFO # erase 0004f000:00001000
2015-05-28 17:52:26,349 - INFO # erase 00050000:00001000
2015-05-28 17:52:26,386 - INFO # erase 00051000:00001000
2015-05-28 17:52:26,425 - INFO # erase 00052000:00001000
2015-05-28 17:52:26,462 - INFO # erase 00053000:00001000
2015-05-28 17:52:26,499 - INFO # erase 00054000:00001000
2015-05-28 17:52:26,536 - INFO # erase 00055000:00001000
2015-05-28 17:52:26,574 - INFO # erase 00056000:00001000
2015-05-28 17:52:26,611 - INFO # erase 00057000:00001000
2015-05-28 17:52:26,649 - INFO # erase 00058000:00001000
2015-05-28 17:52:26,686 - INFO # erase 00059000:00001000
2015-05-28 17:52:26,722 - INFO # erase 0005a000:00001000
2015-05-28 17:52:26,759 - INFO # erase 0005b000:00001000
2015-05-28 17:52:26,800 - INFO # erase 0005c000:00001000
2015-05-28 17:52:26,834 - INFO # erase 0005d000:00001000
2015-05-28 17:52:26,870 - INFO # erase 0005e000:00001000
2015-05-28 17:52:26,909 - INFO # erase 0005f000:00001000
2015-05-28 17:52:26,947 - INFO # erase 00060000:00001000
2015-05-28 17:52:26,985 - INFO # erase 00061000:00001000
2015-05-28 17:52:27,022 - INFO # erase 00062000:00001000
2015-05-28 17:52:27,058 - INFO # erase 00063000:00001000
2015-05-28 17:52:27,095 - INFO # erase 00064000:00001000
2015-05-28 17:52:27,133 - INFO # erase 00065000:00001000
2015-05-28 17:52:27,171 - INFO # erase 00066000:00001000
2015-05-28 17:52:27,208 - INFO # erase 00067000:00001000
2015-05-28 17:52:27,244 - INFO # erase 00068000:00001000
2015-05-28 17:52:27,281 - INFO # erase 00069000:00001000
2015-05-28 17:52:27,318 - INFO # erase 0006a000:00001000
2015-05-28 17:52:27,357 - INFO # erase 0006b000:00001000
2015-05-28 17:52:27,394 - INFO # erase 0006c000:00001000
2015-05-28 17:52:27,431 - INFO # erase 0006d000:00001000
2015-05-28 17:52:27,469 - INFO # erase 0006e000:00001000
2015-05-28 17:52:27,507 - INFO # erase 0006f000:00001000
2015-05-28 17:52:27,544 - INFO # erase 00070000:00001000
2015-05-28 17:52:27,581 - INFO # erase 00071000:00001000
2015-05-28 17:52:27,619 - INFO # erase 00072000:00001000
2015-05-28 17:52:27,657 - INFO # erase 00073000:00001000
2015-05-28 17:52:27,694 - INFO # erase 00074000:00001000
2015-05-28 17:52:27,732 - INFO # erase 00075000:00001000
2015-05-28 17:52:27,769 - INFO # erase 00076000:00001000
2015-05-28 17:52:27,807 - INFO # erase 00077000:00001000
2015-05-28 17:52:27,843 - INFO # erase 00078000:00001000
2015-05-28 17:52:27,881 - INFO # erase 00079000:00001000
2015-05-28 17:52:27,917 - INFO # erase 0007a000:00001000
2015-05-28 17:52:27,954 - INFO # erase 0007b000:00001000
2015-05-28 17:52:27,992 - INFO # erase 0007c000:00001000
2015-05-28 17:52:28,029 - INFO # erase 0007d000:00001000
2015-05-28 17:52:28,066 - INFO # erase 0007e000:00001000
2015-05-28 17:52:28,194 - INFO # page index byte len:         128
2015-05-28 17:52:28,197 - INFO # object lookup pages:         1
2015-05-28 17:52:28,200 - INFO # page pages per block:        32
2015-05-28 17:52:28,203 - INFO # page header length:          5
2015-05-28 17:52:28,205 - INFO # object header index entries: 42
2015-05-28 17:52:28,211 - INFO # object index entries:        61
2015-05-28 17:52:28,211 - INFO # available file descriptors:  3
2015-05-28 17:52:28,214 - INFO # free blocks:                 0
2015-05-28 17:52:28,215 - INFO # mount res: 0
2015-05-28 17:52:28,216 - INFO # testing…
2015-05-28 17:52:28,303 - INFO # free_obj_id: COMP min:0001 max:0800 compact:15
2015-05-28 17:52:28,390 - INFO # free_obj_id: COMP select index:0 min_count:0 min:0001 max:0800 compact:15
2015-05-28 17:52:28,470 - INFO # erase 00000000:00001000
2015-05-28 17:52:28,588 - INFO # erase 00000000:00001000
2015-05-28 17:52:28,705 - INFO # erase 00000000:00001000
2015-05-28 17:52:28,817 - INFO # errno -10010
2015-05-28 17:52:28,901 - INFO # errno -10010
2015-05-28 17:52:28,902 - INFO # -->  <--

SPIFFS_lseek does not create gaps in files

SPIFFS_lseek behaves different than POSIX lseek. When creating a file and putting the offset to a random position, data is written to that position and previous bytes in the file are filled with \0. With SPIFFS this doesn't work, the data is written to the start of the file, the offset is ignored.

This testcase illustrates the issue

TEST(lseek_create_file) {
  int res;
  spiffs_file fd;
  char *fname = "sparsefile";
  char *message = "Hello World!";
  int offset = 1024;

  fd = SPIFFS_open(FS, fname, SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0);
  TEST_CHECK(fd > 0);
  int pfd = open(make_test_fname(fname), O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);

  SPIFFS_lseek(FS, fd, offset, SPIFFS_SEEK_SET);
  lseek(pfd, offset, SEEK_SET);

  res = SPIFFS_write(FS, fd, message, sizeof(message));
  TEST_CHECK(res >= 0);
  write(pfd, message, sizeof(message));
  res = read_and_verify(fname);
  TEST_CHECK(res >= 0);

  SPIFFS_close(FS, fd);
  close(pfd);

  return TEST_RES_OK;
}
TEST_END(lseek_create_file)

On Linux, the file starts with 1024 \0 bytes, SPIFFS however writes Hello World! to position 0.

TEST 53/59 : running test lseek_create_file
file verification mismatch @ 0, 48 H != 00 
Hello Wo
........
data mismatch

Two issues and one question.

Hi Peter, I got two issues and one question:

1, In function 'spiffs_obj_lu_find_free_obj_id', I think it shouldn't count object lookup pages when calculate 'max_objects'. So tt's should be
'u32_t max_objects = (fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) / 2;' instead of
'u32_t max_objects = (SPIFFS_CFG_PHYS_SZ(fs) / (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) / 2;'

2,In function 'spiffs_obj_lu_find_free' when not found free object id, 'spiffs_obj_lu_find_id' return 'SPIFFS_ERR_NOT_FOUND', not 'SPIFFS_VIS_END'.

Question:
About power loss. When should I perform SPIFFS_check? In other word, how to detect data corruption?

thank you

how spiffs mount filesystem?

I read the code of SPIFFS_mount(), but I didnot find you get information from flash. So how did spiffs mount filesystem ,construct file information.
What's more, how did spiff do with suddenly power loss ?

Fatal exception 9(LoadStoreAlignmentCause).

I try to use the lib with an ESP8266 module.

But, the code crash with this line :

((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[data_spix] = data_page;

Fatal exception 9(LoadStoreAlignmentCause).

Thanks for your help

Stéphane

Some trace :

  1. mounting
    Read flash 0x002581fe Read flash 0x002681fe Read flash 0x002781fe Read flash 0x002881fe Read flash 0x002981fe Read flash 0x002a81fe Read flash 0x002b81fe Read flash 0x002c81fe Read flash 0x002d81fe Read flash 0x002e81fe Read flash 0x002f81fe Read flash 0x003081fe Read flash 0x003181fe Read flash 0x003281fe Read flash 0x003381fe Read flash 0x003481fe Read flash 0x003581fe Read flash 0x003681fe Read flash 0x003781fe Read flash 0x003881fe Read flash 0x003981fe Read flash 0x003a81fe Read flash 0x003b81fe Read flash 0x003c81fe Read flash 0x003d81fe Read flash 0x003e81fe Read flash 0x003f81fe Read flash 0x004081fe Read flash 0x004181fe Read flash 0x004281fe Read flash 0x004381fe Read flash 0x004481fe Read flash 0x00258000 Read flash 0x00258100 Read flash 0x00268000 Read flash 0x00268100 Read flash 0x00278000 Read flash 0x00278100 Read flash 0x00288000 Read flash 0x00288100 Read flash 0x00298000 Read flash 0x00298100 Read flash 0x002a8000 Read flash 0x002a8100 Read flash 0x002b8000 Read flash 0x002b8100 Read flash 0x002c8000 Read flash 0x002c8100 Read flash 0x002d8000 Read flash 0x002d8100 Read flash 0x002e8000 Read flash 0x002e8100 Read flash 0x002f8000 Read flash 0x002f8100 Read flash 0x00308000 Read flash 0x00308100 Read flash 0x00318000 Read flash 0x00318100 Read flash 0x00328000 Read flash 0x00328100 Read flash 0x00338000 Read flash 0x00338100 Read flash 0x00348000 Read flash 0x00348100 Read flash 0x00358000 Read flash 0x00358100 Read flash 0x00368000 Read flash 0x00368100 Read flash 0x00378000 Read flash 0x00378100 Read flash 0x00388000 Read flash 0x00388100 Read flash 0x00398000 Read flash 0x00398100 Read flash 0x003a8000 Read flash 0x003a8100 Read flash 0x003b8000 Read flash 0x003b8100 Read flash 0x003c8000 Read flash 0x003c8100 Read flash 0x003d8000 Read flash 0x003d8100 Read flash 0x003e8000 Read flash 0x003e8100 Read flash 0x003f8000 Read flash 0x003f8100 Read flash 0x00408000 page index byte len: 256
    object lookup pages: 2
    page pages per block: 256
    page header length: 5
    object header index entries: 106
    object index entries: 125
    available file descriptors: 6
    free blocks: 26
    mount res: 0
  2. openning a file
    Read flash 0x00258000 Read flash 0x00258100 Read flash 0x00268000 Read flash 0x00268100 Read flash 0x00278000 Read flash 0x00278100 Read flash 0x00288000 Read flash 0x00288100 Read flash 0x00298000 Read flash 0x00298100 Read flash 0x002a8000 Read flash 0x002a8100 Read flash 0x002b8000 Read flash 0x002b8100 Read flash 0x002c8000 Read flash 0x002c8100 Read flash 0x002d8000 Read flash 0x002d8100 Read flash 0x002e8000 Read flash 0x002e8100 Read flash 0x002f8000 Read flash 0x002f8100 Read flash 0x00308000 Read flash 0x00308100 Read flash 0x00318000 Read flash 0x00318100 Read flash 0x00328000 Read flash 0x00328100 Read flash 0x00338000 Read flash 0x00338100 Read flash 0x00348000 Read flash 0x00348100 Read flash 0x00358000 Read flash 0x00358100 Read flash 0x00368000 Read flash 0x00368100 Read flash 0x00378000 Read flash 0x00378100 Read flash 0x00388000 Read flash 0x00388100 Read flash 0x00398000 Read flash 0x00398100 Read flash 0x003a8000 Read flash 0x003a8100 Read flash 0x003b8000 Read flash 0x003b8100 Read flash 0x003c8000 Read flash 0x003c8100 Read flash 0x003d8000 Read flash 0x003d8100 Read flash 0x003e8000 Read flash 0x003e8a00 Read flash 0x003e8100 Read flash 0x003f8000 Read flash 0x003f8100 Read flash 0x00408000 free_obj_id: COMP min:0001 max:1001 compact:16
    Read flash 0x00258000 Read flash 0x00258100 Read flash 0x00268000 Read flash 0x00268100 Read flash 0x00278000 Read flash 0x00278100 Read flash 0x00288000 Read flash 0x00288100 Read flash 0x00298000 Read flash 0x00298100 Read flash 0x002a8000 Read flash 0x002a8100 Read flash 0x002b8000 Read flash 0x002b8100 Read flash 0x002c8000 Read flash 0x002c8100 Read flash 0x002d8000 Read flash 0x002d8100 Read flash 0x002e8000 Read flash 0x002e8100 Read flash 0x002f8000 Read flash 0x002f8100 Read flash 0x00308000 Read flash 0x00308100 Read flash 0x00318000 Read flash 0x00318100 Read flash 0x00328000 Read flash 0x00328100 Read flash 0x00338000 Read flash 0x00338100 Read flash 0x00348000 Read flash 0x00348100 Read flash 0x00358000 Read flash 0x00358100 Read flash 0x00368000 Read flash 0x00368100 Read flash 0x00378000 Read flash 0x00378100 Read flash 0x00388000 Read flash 0x00388100 Read flash 0x00398000 Read flash 0x00398100 Read flash 0x003a8000 Read flash 0x003a8100 Read flash 0x003b8000 Read flash 0x003b8100 Read flash 0x003c8000 Read flash 0x003c8100 Read flash 0x003d8000 Read flash 0x003d8100 Read flash 0x003e8000 Read flash 0x003e8a00 Read flash 0x003e8100 Read flash 0x003f8000 Read flash 0x003f8100 Read flash 0x00408000 free_obj_id: COMP select index:0 min_count:0 min:0001 max:1001 compact:16
    Read flash 0x00258000 create: found free page @ 0002 bix:0 entry:0

spiffs write 0x 258000 [▒▒?] [2] bytes

spiffs write 0x 258200 [▒] [43] bytes
Read flash 0x00258200 open: fd 1 is obj id 8001

  1. writing to a file
    append: 12 bytes @ offs 0 of size -1
    append: 8001 load objixhdr page 0002:0000

spiffs write 0x 258002 [] [2] bytes

spiffs write 0x 258300 [] [5] bytes

spiffs write 0x 258305 [Hello world] [12] bytes
append: 8001 store new data page, 0003:0000 offset:0, len 12, written 0
append: 8001 wrote page 0003 to objix_hdr entry 00 in mem

Fatal exception 9(LoadStoreAlignmentCause):
epc1=0x4028a888, epc2=0x00000000, epc3=0x00000000, excvaddr=0x3ffeb4a7, depc=0x00000000

ets Jan 8 2013,rst cause:1, boot mode:(3,7)

Suggest to safely remove "GCC diagnostic" pragmas

Instead of

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
    u8_t addr_lsb = ((u8_t)fd_space) & (ptr_size-1);
#pragma GCC diagnostic pop

you can write

    u8_t addr_lsb = (u8_t)(((intptr_t)fd_space) & (ptr_size-1));

it assumes including <stdint.h> for intptr_t definition

User data in callbacks

Currently callbacks are defined as follows:

typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);

There is no way to pass any kind of user value here, which would let user distinguish between instances of SPIFFS mounts. Who in the world would need this, you ask?
Well, I won't bore you with details, but we have an application that would benefit from having more than one mount at a time.

I know it's hard to change API at this stage, but would you be open to having a compile-time option to have user data pointer in the callbacks? Perhaps something like this:

#ifdef SPIFFS_NEW_CALLBACKS
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst, void *user_data);
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src, void *user_data);
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size, void *user_data);
#else
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
#endif

that, plus a field in the spiffs struct should be all that's necessary.

WDYT?

Make does not generate spiffs binary

Hi there,

When I run 'make' , it builds without errors but no binary is created in the build folder.

Any idea what could be wrong? Perhaps missing dependency? I'm running Ubuntu 14.04.

... removing build files in build
... depend build/testrunner.d
... depend build/testsuites.d
... depend build/test_bugreports.d
... depend build/test_hydrogen.d
... depend build/test_check.d
... depend build/test_dev.d
... depend build/test_spiffs.d
... depend build/main.d
... depend build/spiffs_check.d
... depend build/spiffs_cache.d
... depend build/spiffs_hydrogen.d
... depend build/spiffs_gc.d
... depend build/spiffs_nucleus.d
... compile build/spiffs_nucleus.o
... compile build/spiffs_gc.o
... compile build/spiffs_hydrogen.o
... compile build/spiffs_cache.o
... compile build/spiffs_check.o
... compile build/main.o
... compile build/test_spiffs.o
... compile build/test_dev.o
... compile build/test_check.o
... compile build/test_hydrogen.o
... compile build/test_bugreports.o
... compile build/testsuites.o
... compile build/testrunner.o
... linking

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.