From 5de54a6750abcf408ebf4beb63ea10e5c15ef387 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Mon, 16 Dec 2019 13:02:34 -0800 Subject: [PATCH] more reorg to build using pio --- data/spiffs/console.html | 56 - data/spiffs/console.js | 72 - data/spiffs/favicon.ico | Bin 874 -> 0 bytes data/spiffs/flash.html | 6 - data/spiffs/flash.js | 20 - data/spiffs/home.html | 10 - data/spiffs/log.html | 31 - data/spiffs/mqtt.html | 7 - data/spiffs/mqtt.js | 46 - data/spiffs/pure.css | 9 - data/spiffs/services.html | 8 - data/spiffs/services.js | 47 - data/spiffs/style.css | 1 - data/spiffs/ui.js | 213 --- data/spiffs/userpage.js | 115 -- data/spiffs/web-server.html | 10 - data/spiffs/wifi/icons.png | Bin 425 -> 0 bytes data/spiffs/wifi/wifiAp.html | 10 - data/spiffs/wifi/wifiAp.js | 53 - data/spiffs/wifi/wifiSta.html | 10 - data/spiffs/wifi/wifiSta.js | 134 -- {data/html => html}/console.html | 0 {data/html => html}/console.js | 0 {data/html => html}/favicon.ico | Bin {data/html => html}/flash.html | 0 {data/html => html}/flash.js | 0 {data/html => html}/head- | 0 {data/html => html}/home.html | 0 {data/html => html}/jl-400x110.png- | Bin {data/html => html}/log.html | 0 {data/html => html}/mqtt.html | 0 {data/html => html}/mqtt.js | 0 {data/html => html}/pure.css | 0 {data/html => html}/services.html | 0 {data/html => html}/services.js | 0 {data/html => html}/style.css | 0 {data/html => html}/ui.js | 0 {data/html => html}/userpage.js | 0 {data/html => html}/web-server.html | 0 {data/html => html}/wifi/icons.png | Bin {data/html => html}/wifi/wifiAp.html | 0 {data/html => html}/wifi/wifiAp.js | 0 {data/html => html}/wifi/wifiSta.html | 0 {data/html => html}/wifi/wifiSta.js | 0 src/spiffs/LICENSE | 20 - src/spiffs/README.md | 223 --- src/spiffs/default/spiffs_config.h | 373 ---- src/spiffs/spiffs.h | 816 -------- src/spiffs/spiffs_cache.c | 319 ---- src/spiffs/spiffs_check.c | 1008 ---------- src/spiffs/spiffs_config.h | 369 ---- src/spiffs/spiffs_gc.c | 606 ------ src/spiffs/spiffs_hydrogen.c | 1451 -------------- src/spiffs/spiffs_nucleus.c | 2364 ----------------------- src/spiffs/spiffs_nucleus.h | 842 --------- src/spiffs/test/main.c | 12 - src/spiffs/test/params_test.h | 84 - src/spiffs/test/test_bugreports.c | 1266 ------------- src/spiffs/test/test_check.c | 427 ----- src/spiffs/test/test_dev.c | 122 -- src/spiffs/test/test_hydrogen.c | 2507 ------------------------- src/spiffs/test/test_spiffs.c | 1114 ----------- src/spiffs/test/test_spiffs.h | 109 -- src/spiffs/test/testrunner.c | 238 --- src/spiffs/test/testrunner.h | 165 -- src/spiffs/test/testsuites.c | 15 - 66 files changed, 15308 deletions(-) delete mode 100644 data/spiffs/console.html delete mode 100644 data/spiffs/console.js delete mode 100755 data/spiffs/favicon.ico delete mode 100644 data/spiffs/flash.html delete mode 100644 data/spiffs/flash.js delete mode 100644 data/spiffs/home.html delete mode 100644 data/spiffs/log.html delete mode 100644 data/spiffs/mqtt.html delete mode 100644 data/spiffs/mqtt.js delete mode 100644 data/spiffs/pure.css delete mode 100644 data/spiffs/services.html delete mode 100644 data/spiffs/services.js delete mode 100644 data/spiffs/style.css delete mode 100644 data/spiffs/ui.js delete mode 100644 data/spiffs/userpage.js delete mode 100644 data/spiffs/web-server.html delete mode 100644 data/spiffs/wifi/icons.png delete mode 100644 data/spiffs/wifi/wifiAp.html delete mode 100644 data/spiffs/wifi/wifiAp.js delete mode 100644 data/spiffs/wifi/wifiSta.html delete mode 100644 data/spiffs/wifi/wifiSta.js rename {data/html => html}/console.html (100%) rename {data/html => html}/console.js (100%) rename {data/html => html}/favicon.ico (100%) rename {data/html => html}/flash.html (100%) rename {data/html => html}/flash.js (100%) rename {data/html => html}/head- (100%) rename {data/html => html}/home.html (100%) rename {data/html => html}/jl-400x110.png- (100%) rename {data/html => html}/log.html (100%) rename {data/html => html}/mqtt.html (100%) rename {data/html => html}/mqtt.js (100%) rename {data/html => html}/pure.css (100%) rename {data/html => html}/services.html (100%) rename {data/html => html}/services.js (100%) rename {data/html => html}/style.css (100%) rename {data/html => html}/ui.js (100%) rename {data/html => html}/userpage.js (100%) rename {data/html => html}/web-server.html (100%) rename {data/html => html}/wifi/icons.png (100%) rename {data/html => html}/wifi/wifiAp.html (100%) rename {data/html => html}/wifi/wifiAp.js (100%) rename {data/html => html}/wifi/wifiSta.html (100%) rename {data/html => html}/wifi/wifiSta.js (100%) delete mode 100644 src/spiffs/LICENSE delete mode 100644 src/spiffs/README.md delete mode 100644 src/spiffs/default/spiffs_config.h delete mode 100644 src/spiffs/spiffs.h delete mode 100644 src/spiffs/spiffs_cache.c delete mode 100644 src/spiffs/spiffs_check.c delete mode 100644 src/spiffs/spiffs_config.h delete mode 100644 src/spiffs/spiffs_gc.c delete mode 100644 src/spiffs/spiffs_hydrogen.c delete mode 100644 src/spiffs/spiffs_nucleus.c delete mode 100644 src/spiffs/spiffs_nucleus.h delete mode 100644 src/spiffs/test/main.c delete mode 100644 src/spiffs/test/params_test.h delete mode 100644 src/spiffs/test/test_bugreports.c delete mode 100644 src/spiffs/test/test_check.c delete mode 100644 src/spiffs/test/test_dev.c delete mode 100644 src/spiffs/test/test_hydrogen.c delete mode 100644 src/spiffs/test/test_spiffs.c delete mode 100644 src/spiffs/test/test_spiffs.h delete mode 100644 src/spiffs/test/testrunner.c delete mode 100644 src/spiffs/test/testrunner.h delete mode 100644 src/spiffs/test/testsuites.c diff --git a/data/spiffs/console.html b/data/spiffs/console.html deleted file mode 100644 index d811640..0000000 --- a/data/spiffs/console.html +++ /dev/null @@ -1,56 +0,0 @@ -esp-link

Microcontroller Console

Reset µC   Clear Log   Baud:   Fmt:

Console
--- No Content ---
Console entry
(ENTER to submit, ESC to clear)
Add:
History buffer
(UP/DOWN arrows to select)
\ No newline at end of file diff --git a/data/spiffs/console.js b/data/spiffs/console.js deleted file mode 100644 index e2451ff..0000000 --- a/data/spiffs/console.js +++ /dev/null @@ -1,72 +0,0 @@ -function fetchText(a,c){var b=$("#console"); -if(b.textEnd==undefined){b.textEnd=0; -b.innerHTML="" -}window.setTimeout(function(){ajaxJson("GET",console_url+"?start="+b.textEnd,function(e){var d=updateText(e); -if(c){fetchText(d,c) -}},function(){retryLoad(c) -}) -},a) -}function updateText(d){var b=$("#console"); -var a=3000; -if(d!=null&&d.len>0){var c=b.scrollHeight-b.clientHeight<=b.scrollTop+1; -if(d.start>b.textEnd){b.innerHTML=b.innerHTML.concat("\r\n/g,">").replace(/"/g,""")); -b.textEnd=d.start+d.len; -a=500; -if(c){b.scrollTop=b.scrollHeight-b.clientHeight -}}return a -}function retryLoad(a){fetchText(1000,a) -}function consoleSendInit(){var e=$("#send-history"); -var h=$("#input-text"); -var d=$("#input-add-cr"); -var b=$("#input-add-lf"); -function g(k){for(var j=0; -j=e.children.length){i=0 -}a(i) -}e.addEventListener("change",function(i){h.value=e.value -}); -function c(k){var i=g(k); -if(i!==null){a(i); -return false -}var j=m(""); -j.value=k; -e.appendChild(j); -e.value=k; -for(; -e.children.length>15; -){e.removeChild(e.children[0]) -}return true -}h.addEventListener("keydown",function(i){switch(i.keyCode){case 38:i.preventDefault(); -f(-1); -break; -case 40:i.preventDefault(); -f(+1); -break; -case 27:i.preventDefault(); -h.value=""; -e.value=""; -break; -case 13:i.preventDefault(); -var j=h.value; -if(d.checked){j+="\r" -}if(b.checked){j+="\n" -}c(h.value); -h.value=""; -ajaxSpin("POST","/console/send?text="+encodeURIComponent(j),function(k){showNotification("Text sent") -},function(l,k){showWarning("Error sending text") -}); -break -}}) -}function showDbgMode(c){var b=$(".dbg-btn"); -for(var a=0; -aNktgRs>r5G6Aq^!kV zV*l^&R#sN6EiJ7W7^MspA^8LW00031EC2ui06+jh000F4Fvv-(wIb^+uK!?I6(nbp zg{ZEh>Aoo|Tg+?U-OMrt?w>kU4OcK2kA|Kv__-AcfT(l|AS7?h%FVE#dc6w+Hf!U4 z&tI`Crc-hX==j;aVYBEOs64Kp64o*=U3+K*3||Cz87wD+az$v0D~*nE0)1bSA$V|= z01B83nn0Vsd5Sf0|x^NqKAZkbsj?+ot_Q50}oP3m1-Lo zCZ16V2)wn zS4jY|&=Txy^$gv*0*c4URS~k3zN^KqjE4Lefdvb$f5En_*)gyK;$ocs4mq#|tPmh@ z;H7t1;Nl2OmA7<)OSgW#s5a`g@h;QUxWfkj9i4D@04Ai#)J#D84ImF56h!oi1NkVB zKmrO}lM+Y3*+kNXAchzsCbVQ_*8jg_yR@t#1B&+Nf3(Q9PEVR)wlH3m^RQsz9+IH(L1rY!MJGW+g AmH+?% diff --git a/data/spiffs/flash.html b/data/spiffs/flash.html deleted file mode 100644 index fd26c58..0000000 --- a/data/spiffs/flash.html +++ /dev/null @@ -1,6 +0,0 @@ -esp-link

Upgrade Firmware

Upgrade Firmware

\ No newline at end of file diff --git a/data/spiffs/flash.js b/data/spiffs/flash.js deleted file mode 100644 index b1ff173..0000000 --- a/data/spiffs/flash.js +++ /dev/null @@ -1,20 +0,0 @@ -function flashFirmware(b){b.preventDefault(); -var a=document.getElementById("fw-file").files[0]; -$("#fw-form").setAttribute("hidden",""); -$("#fw-spinner").removeAttribute("hidden"); -showNotification("Firmware is being updated ..."); -ajaxReq("POST","/flash/upload",function(c){ajaxReq("GET","/flash/reboot",function(d){showNotification("Firmware has been successfully updated!"); -setTimeout(function(){window.location.reload() -},4000); -$("#fw-spinner").setAttribute("hidden",""); -$("#fw-form").removeAttribute("hidden") -}) -},null,a) -}function fetchFlash(){ajaxReq("GET","/flash/next",function(a){$("#fw-slot").innerHTML=a; -$("#fw-spinner").setAttribute("hidden",""); -$("#fw-form").removeAttribute("hidden") -}); -ajaxJson("GET","/menu",function(b){var a=$("#current-fw"); -if(a!=null){a.innerHTML=b.version -}}) -}; \ No newline at end of file diff --git a/data/spiffs/home.html b/data/spiffs/home.html deleted file mode 100644 index 3f14706..0000000 --- a/data/spiffs/home.html +++ /dev/null @@ -1,10 +0,0 @@ -esp-link
JEELABS

esp-link

System overview

Info

The JeeLabs esp-link firmware bridges the ESP8266 serial port to WiFi and can program microcontrollers over the serial port, in particular Arduinos, AVRs, and NXP's LPC800 and other ARM processors. Typical avrdude command line to program an Arduino:

/home/arduino/hardware/tools/avrdude \
  -DV -patmega328p \
  -Pnet:esp-link.local:23 \
  -carduino -b115200 \
  -U flash:w:my_sketch.hex:i\
  -C /home/arduino/hardware/tools/avrdude.conf

where -Pnet:esp-link.local:23 tells avrdude to connect to port 23 of esp-link. You can substitute the IP address of your esp-link for esp-link.local if necessary. Please refer to the online README for up-to-date help.

Pin assignment

System details

\ No newline at end of file diff --git a/data/spiffs/log.html b/data/spiffs/log.html deleted file mode 100644 index b50e772..0000000 --- a/data/spiffs/log.html +++ /dev/null @@ -1,31 +0,0 @@ -esp-link

Debug Log

The debug log shows the most recent characters printed by the esp-link software itself to its own debug log.

\ No newline at end of file diff --git a/data/spiffs/mqtt.html b/data/spiffs/mqtt.html deleted file mode 100644 index 4c4537d..0000000 --- a/data/spiffs/mqtt.html +++ /dev/null @@ -1,7 +0,0 @@ -esp-link

REST & MQTT

The REST & MQTT support uses the SLIP protocol over the serial port to enable the attached microcontroller to initiate outbound connections. The REST support lets the uC initiate simple HTTP requests while the MQTT support lets it communicate with an MQTT server bidirectionally at QoS 0 thru 2.

The MQTT support is in the form of a built-in client that connects to a server using parameters set below and stored in esp-link's flash settings. This allows esp-link to take care of connection parameters and disconnect/reconnect operations.

The MQTT client also supports sending periodic status messages about esp-link itself, including WiFi RSSI, and free heap memory.

MQTT

Status reporting

REST

REST requests are enabled as soon as SLIP is enabled. There are no REST-specific settings.

\ No newline at end of file diff --git a/data/spiffs/mqtt.js b/data/spiffs/mqtt.js deleted file mode 100644 index 1b3ffb1..0000000 --- a/data/spiffs/mqtt.js +++ /dev/null @@ -1,46 +0,0 @@ -function changeMqtt(f){f.preventDefault(); -var c="mqtt?1=1"; -var d,b=document.querySelectorAll("#mqtt-form input"); -for(d=0; -d0 -}else{el.value=c[d] -}}}); -$("#mqtt-spinner").setAttribute("hidden",""); -$("#mqtt-status-spinner").setAttribute("hidden",""); -$("#mqtt-form").removeAttribute("hidden"); -$("#mqtt-status-form").removeAttribute("hidden"); -var b,a=$("input"); -for(b=0; -b.pure-menu-children,.pure-menu-active>.pure-menu-children{display:block;position:absolute}.pure-menu-has-children>.pure-menu-link:after{padding-left:.5em;content:"\25B8";font-size:small}.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after{content:"\25BE"}.pure-menu-scrollable{overflow-y:scroll;overflow-x:hidden}.pure-menu-scrollable .pure-menu-list{display:block}.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list{display:inline-block}.pure-menu-horizontal.pure-menu-scrollable{white-space:nowrap;overflow-y:hidden;overflow-x:auto;-ms-overflow-style:none;-webkit-overflow-scrolling:touch;padding:.5em 0}.pure-menu-horizontal.pure-menu-scrollable::-webkit-scrollbar{display:none}.pure-menu-separator{background-color:#ccc;height:1px;margin:.3em 0}.pure-menu-horizontal .pure-menu-separator{width:1px;height:1.3em;margin:0 .3em}.pure-menu-heading{text-transform:uppercase;color:#565d64}.pure-menu-link{color:#777}.pure-menu-children{background-color:#fff}.pure-menu-link,.pure-menu-disabled,.pure-menu-heading{padding:.5em 1em}.pure-menu-disabled{opacity:.5}.pure-menu-disabled .pure-menu-link:hover{background-color:transparent}.pure-menu-active>.pure-menu-link,.pure-menu-link:hover,.pure-menu-link:focus{background-color:#eee}.pure-menu-selected .pure-menu-link,.pure-menu-selected .pure-menu-link:visited{color:#000}.pure-table{border-collapse:collapse;border-spacing:0;empty-cells:show;border:1px solid #cbcbcb}.pure-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.pure-table td,.pure-table th{border-left:1px solid #cbcbcb;border-width:0 0 0 1px;font-size:inherit;margin:0;overflow:visible;padding:.5em 1em}.pure-table td:first-child,.pure-table th:first-child{border-left-width:0}.pure-table thead{background-color:#e0e0e0;color:#000;text-align:left;vertical-align:bottom}.pure-table td{background-color:transparent}.pure-table-odd td{background-color:#f2f2f2}.pure-table-striped tr:nth-child(2n-1) td{background-color:#f2f2f2}.pure-table-bordered td{border-bottom:1px solid #cbcbcb}.pure-table-bordered tbody>tr:last-child>td{border-bottom-width:0}.pure-table-horizontal td,.pure-table-horizontal th{border-width:0 0 1px 0;border-bottom:1px solid #cbcbcb}.pure-table-horizontal tbody>tr:last-child>td{border-bottom-width:0} \ No newline at end of file diff --git a/data/spiffs/services.html b/data/spiffs/services.html deleted file mode 100644 index ee84f4e..0000000 --- a/data/spiffs/services.html +++ /dev/null @@ -1,8 +0,0 @@ -esp-link

Services

Syslog

mDNS

SNTP

\ No newline at end of file diff --git a/data/spiffs/services.js b/data/spiffs/services.js deleted file mode 100644 index 5786505..0000000 --- a/data/spiffs/services.js +++ /dev/null @@ -1,47 +0,0 @@ -function changeServices(f){f.preventDefault(); -var c="services/update?1=1"; -var d,b=document.querySelectorAll("#"+f.target.id+" input,select"); -for(d=0; -d=200&&g.status<300){h(g.responseText) -}else{console.log("XHR ERR :",i,a,"->",g.status,g.responseText,g); -c(g.status,g.responseText) -}}; -try{g.send(f) -}catch(b){console.log("XHR EXC :",i,a,"->",b); -c(599,b) -}}function dispatchJson(f,d,c){var a; -try{a=JSON.parse(f) -}catch(b){console.log("JSON parse error: "+b+". In: "+f); -c(500,"JSON parse error: "+b); -return -}d(a) -}function ajaxJson(d,a,c,b){ajaxReq(d,a,function(f){dispatchJson(f,c,b) -},b) -}function ajaxSpin(d,a,c,b){$("#spinner").removeAttribute("hidden"); -ajaxReq(d,a,function(f){$("#spinner").setAttribute("hidden",""); -c(f) -},function(f,g){$("#spinner").setAttribute("hidden",""); -b(f,g) -}) -}function ajaxJsonSpin(d,a,c,b){ajaxSpin(d,a,function(f){dispatchJson(f,c,b) -},b) -}function hidePopup(a){addClass(a,"popup-hidden"); -addClass(a.parentNode,"popup-target") -}onLoad(function(){var a=$("#layout"); -var d=a.childNodes[0]; -a.insertBefore(m(''),d); -a.insertBefore(m('
'),d); -a.insertBefore(m(''),d); -var c=m(' '); -a.insertBefore(c,d); -var f=$("#menuLink"),c=$("#menu"); -bnd(f,"click",function(h){var g="active"; -h.preventDefault(); -toggleClass(a,g); -toggleClass(c,g); -toggleClass(f,g) -}); -domForEach($(".popup"),function(g){hidePopup(g) -}); -var b=function(){ajaxJson("GET","/menu",function(n){var l="",o=window.location.pathname; -for(var k=0; -k'+n.menu[k]+"") -}$("#menu-list").innerHTML=l; -var g=$("#version"); -if(g!=null){g.innerHTML=n.version -}$("title")[0].innerHTML=n.name; -setEditToClick("system-name",n.name) -},function(){setTimeout(b,1000) -}) -}; -b() -}); -function showWifiInfo(b){Object.keys(b).forEach(function(c){el=$("#wifi-"+c); -if(el!=null){if(el.nodeName==="INPUT"){el.value=b[c] -}else{el.innerHTML=b[c] -}}}); -var a=$("#dhcp-r"+b.dhcp); -if(a){a.click() -}$("#wifi-spinner").setAttribute("hidden",""); -$("#wifi-table").removeAttribute("hidden"); -currAp=b.ssid -}function getWifiInfo(){ajaxJson("GET","/wifi/info",showWifiInfo,function(b,a){window.setTimeout(getWifiInfo,1000) -}) -}function showSystemInfo(a){Object.keys(a).forEach(function(b){setEditToClick("system-"+b,a[b]) -}); -$("#system-spinner").setAttribute("hidden",""); -$("#system-table").removeAttribute("hidden"); -currAp=a.ssid -}function getSystemInfo(){ajaxJson("GET","/system/info",showSystemInfo,function(b,a){window.setTimeout(getSystemInfo,1000) -}) -}function makeAjaxInput(a,b){domForEach($("."+a+"-"+b),function(i){var f=$(".edit-on",i); -var d=$(".edit-off",i)[0]; -var c="/"+a+"/update?"+b; -if(d===undefined||f==undefined){return -}var h=function(){d.setAttribute("hidden",""); -domForEach(f,function(k){k.removeAttribute("hidden") -}); -f[0].select(); -return false -}; -var g=function(k){ajaxSpin("POST",c+"="+k,function(){domForEach(f,function(l){l.setAttribute("hidden","") -}); -d.removeAttribute("hidden"); -setEditToClick(a+"-"+b,k); -showNotification(b+" changed to "+k) -},function(){showWarning(b+" change failed") -}); -return false -}; -bnd(d,"click",function(){return h() -}); -bnd(f[0],"blur",function(){return g(f[0].value) -}); -bnd(f[0],"keyup",function(k){if((k||window.event).keyCode==13){return g(f[0].value) -}}) -}) -}function setEditToClick(a,b){domForEach($("."+a),function(c){if(c.children.length>0){domForEach(c.children,function(d){if(d.nodeName==="INPUT"){d.value=b -}else{if(d.nodeName!=="DIV"){d.innerHTML=b -}}}) -}else{c.innerHTML=b -}}) -}function showWarning(b){var a=$("#warning"); -a.innerHTML=b; -a.removeAttribute("hidden"); -window.scrollTo(0,0) -}function hideWarning(){el=$("#warning").setAttribute("hidden","") -}var notifTimeout=null; -function showNotification(b){var a=$("#notification"); -a.innerHTML=b; -a.removeAttribute("hidden"); -if(notifTimeout!=null){clearTimeout(notifTimeout) -}notifTimout=setTimeout(function(){a.setAttribute("hidden",""); -notifTimout=null -},4000) -}var pinPresets={"esp-01":[0,-1,2,-1,0,1],"esp-12":[12,14,0,2,0,1],"esp-12 swap":[1,3,0,2,1,1],"esp-bridge":[12,13,0,14,0,0],"wifi-link-12":[1,3,0,2,1,0]}; -function createPresets(c){for(var d in pinPresets){var a=m('"); -c.appendChild(a) -}function b(h){var f=pinPresets[h]; -if(f===undefined){return f -}function g(l,i){$("#pin-"+l).value=i -}g("reset",f[0]); -g("isp",f[1]); -g("conn",f[2]); -g("ser",f[3]); -g("swap",f[4]); -$("#pin-rxpup").checked=!!f[5]; -c.value=0 -}bnd(c,"change",function(f){f.preventDefault(); -b(c.value) -}) -}function displayPins(b){function a(f,c){var g=$("#pin-"+f); -addClass(g,"pure-button"); -g.innerHTML=""; -[-1,0,1,2,3,4,5,12,13,14,15].forEach(function(k){var h=document.createElement("option"); -h.value=k; -if(k>=0){h.innerHTML="gpio"+k -}else{h.innerHTML="disabled" -}if(k===1){h.innerHTML+="/TX0" -}if(k===2){h.innerHTML+="/TX1" -}if(k===3){h.innerHTML+="/RX0" -}if(k==c){h.selected=true -}g.appendChild(h) -}); -var d=$(".popup",g.parentNode); -if(d!==undefined){hidePopup(d[0]) -}}a("reset",b.reset); -a("isp",b.isp); -a("conn",b.conn); -a("ser",b.ser); -$("#pin-swap").value=b.swap; -$("#pin-rxpup").checked=!!b.rxpup; -createPresets($("#pin-preset")); -$("#pin-spinner").setAttribute("hidden",""); -$("#pin-table").removeAttribute("hidden") -}function fetchPins(){ajaxJson("GET","/pins",displayPins,function(){window.setTimeout(fetchPins,1000) -}) -}function setPins(c){c.preventDefault(); -var b="/pins"; -var a="?"; -["reset","isp","conn","ser","swap"].forEach(function(d){b+=a+d+"="+$("#pin-"+d).value; -a="&" -}); -b+="&rxpup="+($("#pin-rxpup").checked?"1":"0"); -ajaxSpin("POST",b,function(){showNotification("Pin assignment changed") -},function(d,f){showWarning(f); -window.setTimeout(fetchPins,100) -}) -}; \ No newline at end of file diff --git a/data/spiffs/userpage.js b/data/spiffs/userpage.js deleted file mode 100644 index adcc050..0000000 --- a/data/spiffs/userpage.js +++ /dev/null @@ -1,115 +0,0 @@ -var loadCounter=0; -var refreshRate=0; -var refreshTimer; -var hiddenInputs=[]; -function notifyResponse(a){Object.keys(a).forEach(function(m){var c=document.getElementsByName(m); -var n; -for(n=0; -n"+l[h]+"") -}e.innerHTML=k -}if(e.tagName=="TABLE"){var l=a[m]; -var k=""; -if(l.length>0){var b=l[0]; -k=k.concat(""); -for(var h=0; -h"+b[h]+"") -}k=k.concat("") -}for(var h=1; -h"); -for(var f=0; -f"+g[f]+"") -}k=k.concat("") -}e.innerHTML=k -}}}); -if(refreshRate!=0){clearTimeout(refreshTimer); -refreshTimer=setTimeout(function(){ajaxJson("GET",window.location.pathname+".json?reason=refresh",notifyResponse) -},refreshRate) -}}function notifyButtonPressed(a){ajaxJson("POST",window.location.pathname+".json?reason=button&id="+a,notifyResponse) -}function refreshFormData(){setTimeout(function(){ajaxJson("GET",window.location.pathname+".json?reason=refresh",function(a){notifyResponse(a); -if(loadCounter>0){loadCounter--; -refreshFormData() -}}) -},250) -}function recalculateHiddenInputs(){for(var f=0; -fesp-link

Web Server

User defined web pages can be uploaded to esp-link. This is useful if esp-link acts as a web server while MCU provides the measurement data.

The custom web page to upload:
\ No newline at end of file diff --git a/data/spiffs/wifi/icons.png b/data/spiffs/wifi/icons.png deleted file mode 100644 index 08c933f490afa8a693db04ce25735bb2c52f90be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 425 zcmV;a0apHrP)V@pd*X<^C$qTT>#j{pDw09t$Kw)xrs0004WQchCg8e_v1xB``-vETqS+gs6dg*}0-2cX%Oa&O?N99WZY zSZ4}h65KF}mGA3>@Fz=lj4`eB{mD5uNZ{#czW+qm-6k+(X9o1e3|jiA09t?nh^qlC z5CBd7m}eOWFag|oP)&0YfgcHAfe6&z6F^)6V27r;%D|RNfMy*C)3P8BAp7^xI02}C z#-D)qlSFy81gL)u5LWesp-link

WiFi Soft-AP Configuration

Soft-AP State

Soft-AP Settings

\ No newline at end of file diff --git a/data/spiffs/wifi/wifiAp.js b/data/spiffs/wifi/wifiAp.js deleted file mode 100644 index 0740996..0000000 --- a/data/spiffs/wifi/wifiAp.js +++ /dev/null @@ -1,53 +0,0 @@ -var specials=[]; -specials.ap_ssid="SSID name"; -specials.ap_password="PASSWORD"; -specials.ap_maxconn="Max Connections number"; -specials.ap_beacon="Beacon Interval"; -function changeWifiMode(a){blockScan=1; -hideWarning(); -ajaxSpin("POST","setmode?mode="+a,function(b){showNotification("Mode changed"); -window.setTimeout(getWifiInfo,100); -blockScan=0 -},function(c,b){showWarning("Error changing mode: "+b); -window.setTimeout(getWifiInfo,100); -blockScan=0 -}) -}function changeApSettings(j){j.preventDefault(); -var a="/wifi/apchange?100=1"; -var f,h=document.querySelectorAll("#"+j.target.id+" input,select"); -for(f=0; -fesp-link

WiFi Station Configuration

WiFi State

WiFi Association

To connect to a WiFi network, please select one of the detected networks, enter the password, and hit the connect button...
Scanning...

Special Settings

Special settings, use with care!
\ No newline at end of file diff --git a/data/spiffs/wifi/wifiSta.js b/data/spiffs/wifi/wifiSta.js deleted file mode 100644 index 137e1a4..0000000 --- a/data/spiffs/wifi/wifiSta.js +++ /dev/null @@ -1,134 +0,0 @@ -var currAp=""; -var blockScan=0; -function createInputForAp(b){if(b.essid==""&&b.rssi==0){return -}var g=e("input"); -g.type="radio"; -g.name="essid"; -g.value=b.essid; -g.id="opt-"+b.essid; -if(currAp==b.essid){g.checked="1" -}var i=e("div"); -var j=-Math.floor(b.rssi/51)*32; -i.className="lock-icon"; -i.style.backgroundPosition="0px "+(j-1)+"px"; -var d=e("div"); -d.innerHTML=""+b.rssi+"dB"; -var c=e("div"); -var h="-65"; -if(b.enc=="0"){h="0" -}if(b.enc=="1"){h="-33" -}c.className="lock-icon"; -c.style.backgroundPosition="-32px "+h+"px"; -var f=e("div"); -f.innerHTML=b.essid; -var a=m('').childNodes[0]; -a.appendChild(g); -a.appendChild(c); -a.appendChild(i); -a.appendChild(d); -a.appendChild(f); -return a -}function getSelectedEssid(){var c=document.forms.wifiform.elements; -for(var b=0; -b60){return scanAPs() -}scanReqCnt+=1; -ajaxJson("GET","scan",function(c){currAp=getSelectedEssid(); -if(c.result.inProgress=="0"&&c.result.APs.length>0){$("#aps").innerHTML=""; -var d=0; -for(var b=0; -b'+c.ip+", else connect to network "+c.ssid+" first." -}else{blockScan=0; -showWarning("Connection failed: "+c.status+", "+c.reason); -$("#aps").innerHTML='Check password and selected AP. Go Back' -}}},function(b,a){window.setTimeout(getStatus,2000) -}) -}function changeWifiMode(a){blockScan=1; -hideWarning(); -ajaxSpin("POST","setmode?mode="+a,function(b){showNotification("Mode changed"); -window.setTimeout(getWifiInfo,100); -blockScan=0; -window.setTimeout(scanAPs,500); -$("#aps").innerHTML='Scanning...
' -},function(c,b){showWarning("Error changing mode: "+b); -window.setTimeout(getWifiInfo,100); -blockScan=0 -}) -}function changeWifiAp(d){d.preventDefault(); -var b=$("#wifi-passwd").value; -var f=getSelectedEssid(); -showNotification("Connecting to "+f); -var c="connect?essid="+encodeURIComponent(f)+"&passwd="+encodeURIComponent(b); -hideWarning(); -$("#reconnect").setAttribute("hidden",""); -$("#wifi-passwd").value=""; -var a=$("#connect-button"); -var g=a.className; -a.className+=" pure-button-disabled"; -blockScan=1; -ajaxSpin("POST",c,function(h){$("#spinner").removeAttribute("hidden"); -showNotification("Waiting for network change..."); -window.scrollTo(0,0); -window.setTimeout(getStatus,2000) -},function(i,h){showWarning("Error switching network: "+h); -a.className=g; -window.setTimeout(scanAPs,1000) -}) -}function changeSpecial(c){c.preventDefault(); -var b="special"; -b+="?dhcp="+document.querySelector('input[name="dhcp"]:checked').value; -b+="&staticip="+encodeURIComponent($("#wifi-staticip").value); -b+="&netmask="+encodeURIComponent($("#wifi-netmask").value); -b+="&gateway="+encodeURIComponent($("#wifi-gateway").value); -hideWarning(); -var a=$("#special-button"); -addClass(a,"pure-button-disabled"); -ajaxSpin("POST",b,function(d){removeClass(a,"pure-button-disabled") -},function(f,d){showWarning("Error: "+d); -removeClass(a,"pure-button-disabled"); -getWifiInfo() -}) -}function doDhcp(){$("#dhcp-on").removeAttribute("hidden"); -$("#dhcp-off").setAttribute("hidden","") -}function doStatic(){$("#dhcp-off").removeAttribute("hidden"); -$("#dhcp-on").setAttribute("hidden","") -}; \ No newline at end of file diff --git a/data/html/console.html b/html/console.html similarity index 100% rename from data/html/console.html rename to html/console.html diff --git a/data/html/console.js b/html/console.js similarity index 100% rename from data/html/console.js rename to html/console.js diff --git a/data/html/favicon.ico b/html/favicon.ico similarity index 100% rename from data/html/favicon.ico rename to html/favicon.ico diff --git a/data/html/flash.html b/html/flash.html similarity index 100% rename from data/html/flash.html rename to html/flash.html diff --git a/data/html/flash.js b/html/flash.js similarity index 100% rename from data/html/flash.js rename to html/flash.js diff --git a/data/html/head- b/html/head- similarity index 100% rename from data/html/head- rename to html/head- diff --git a/data/html/home.html b/html/home.html similarity index 100% rename from data/html/home.html rename to html/home.html diff --git a/data/html/jl-400x110.png- b/html/jl-400x110.png- similarity index 100% rename from data/html/jl-400x110.png- rename to html/jl-400x110.png- diff --git a/data/html/log.html b/html/log.html similarity index 100% rename from data/html/log.html rename to html/log.html diff --git a/data/html/mqtt.html b/html/mqtt.html similarity index 100% rename from data/html/mqtt.html rename to html/mqtt.html diff --git a/data/html/mqtt.js b/html/mqtt.js similarity index 100% rename from data/html/mqtt.js rename to html/mqtt.js diff --git a/data/html/pure.css b/html/pure.css similarity index 100% rename from data/html/pure.css rename to html/pure.css diff --git a/data/html/services.html b/html/services.html similarity index 100% rename from data/html/services.html rename to html/services.html diff --git a/data/html/services.js b/html/services.js similarity index 100% rename from data/html/services.js rename to html/services.js diff --git a/data/html/style.css b/html/style.css similarity index 100% rename from data/html/style.css rename to html/style.css diff --git a/data/html/ui.js b/html/ui.js similarity index 100% rename from data/html/ui.js rename to html/ui.js diff --git a/data/html/userpage.js b/html/userpage.js similarity index 100% rename from data/html/userpage.js rename to html/userpage.js diff --git a/data/html/web-server.html b/html/web-server.html similarity index 100% rename from data/html/web-server.html rename to html/web-server.html diff --git a/data/html/wifi/icons.png b/html/wifi/icons.png similarity index 100% rename from data/html/wifi/icons.png rename to html/wifi/icons.png diff --git a/data/html/wifi/wifiAp.html b/html/wifi/wifiAp.html similarity index 100% rename from data/html/wifi/wifiAp.html rename to html/wifi/wifiAp.html diff --git a/data/html/wifi/wifiAp.js b/html/wifi/wifiAp.js similarity index 100% rename from data/html/wifi/wifiAp.js rename to html/wifi/wifiAp.js diff --git a/data/html/wifi/wifiSta.html b/html/wifi/wifiSta.html similarity index 100% rename from data/html/wifi/wifiSta.html rename to html/wifi/wifiSta.html diff --git a/data/html/wifi/wifiSta.js b/html/wifi/wifiSta.js similarity index 100% rename from data/html/wifi/wifiSta.js rename to html/wifi/wifiSta.js diff --git a/src/spiffs/LICENSE b/src/spiffs/LICENSE deleted file mode 100644 index 5fb2427..0000000 --- a/src/spiffs/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976gmail.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/spiffs/README.md b/src/spiffs/README.md deleted file mode 100644 index c69a077..0000000 --- a/src/spiffs/README.md +++ /dev/null @@ -1,223 +0,0 @@ -# SPIFFS (SPI Flash File System) -**V0.3.7** - -## ESP-LINK - -The spiffs code has been copied from [Peter Andersson's -repository](https://github.com/pellepl/spiffs) and adapted to the use in esp-link. -The only file modified is `spiffs_config.h`. - -## Original README - -[![Build Status](https://travis-ci.org/pellepl/spiffs.svg?branch=master)](https://travis-ci.org/pellepl/spiffs) - -Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976 at gmail.com) - -For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/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](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs) spiffs into projects and [spiffsimg](https://github.com/nodemcu/nodemcu-firmware/tree/master/tools/spiffsimg) from [nodemcu](https://github.com/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](https://github.com/pellepl/spiffs/issues/179) - -## MORE INFO - -See the [wiki](https://github.com/pellepl/spiffs/wiki) for [configuring](https://github.com/pellepl/spiffs/wiki/Configure-spiffs), [integrating](https://github.com/pellepl/spiffs/wiki/Integrate-spiffs), [using](https://github.com/pellepl/spiffs/wiki/Using-spiffs), and [optimizing](https://github.com/pellepl/spiffs/wiki/Performance-and-Optimizing) spiffs. - -For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC). - -For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver). - -## 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 diff --git a/src/spiffs/default/spiffs_config.h b/src/spiffs/default/spiffs_config.h deleted file mode 100644 index 376d082..0000000 --- a/src/spiffs/default/spiffs_config.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * spiffs_config.h - * - * Created on: Jul 3, 2013 - * Author: petera - */ - -#ifndef SPIFFS_CONFIG_H_ -#define SPIFFS_CONFIG_H_ - -// ----------- 8< ------------ -// Following includes are for the linux test build of spiffs -// These may/should/must be removed/altered/replaced in your target -#include "params_test.h" -#include -#include -#include -#include -#include -#ifdef _SPIFFS_TEST -#include "testrunner.h" -#endif -// ----------- >8 ------------ - -// compile time switches - -// Set generic spiffs debug output call. -#ifndef SPIFFS_DBG -#define SPIFFS_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for garbage collecting. -#ifndef SPIFFS_GC_DBG -#define SPIFFS_GC_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for caching. -#ifndef SPIFFS_CACHE_DBG -#define SPIFFS_CACHE_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for system consistency checks. -#ifndef SPIFFS_CHECK_DBG -#define SPIFFS_CHECK_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for all api invocations. -#ifndef SPIFFS_API_DBG -#define SPIFFS_API_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif - - - -// Defines spiffs debug print formatters -// some general signed number -#ifndef _SPIPRIi -#define _SPIPRIi "%d" -#endif -// address -#ifndef _SPIPRIad -#define _SPIPRIad "%08x" -#endif -// block -#ifndef _SPIPRIbl -#define _SPIPRIbl "%04x" -#endif -// page -#ifndef _SPIPRIpg -#define _SPIPRIpg "%04x" -#endif -// span index -#ifndef _SPIPRIsp -#define _SPIPRIsp "%04x" -#endif -// file descriptor -#ifndef _SPIPRIfd -#define _SPIPRIfd "%d" -#endif -// file object id -#ifndef _SPIPRIid -#define _SPIPRIid "%04x" -#endif -// file flags -#ifndef _SPIPRIfl -#define _SPIPRIfl "%02x" -#endif - - -// Enable/disable API functions to determine exact number of bytes -// for filedescriptor and cache buffers. Once decided for a configuration, -// this can be disabled to reduce flash. -#ifndef SPIFFS_BUFFER_HELP -#define SPIFFS_BUFFER_HELP 0 -#endif - -// Enables/disable memory read caching of nucleus file system operations. -// If enabled, memory area must be provided for cache in SPIFFS_mount. -#ifndef SPIFFS_CACHE -#define SPIFFS_CACHE 1 -#endif -#if SPIFFS_CACHE -// Enables memory write caching for file descriptors in hydrogen -#ifndef SPIFFS_CACHE_WR -#define SPIFFS_CACHE_WR 1 -#endif - -// Enable/disable statistics on caching. Debug/test purpose only. -#ifndef SPIFFS_CACHE_STATS -#define SPIFFS_CACHE_STATS 1 -#endif -#endif - -// Always check header of each accessed page to ensure consistent state. -// If enabled it will increase number of reads, will increase flash. -#ifndef SPIFFS_PAGE_CHECK -#define SPIFFS_PAGE_CHECK 1 -#endif - -// Define maximum number of gc runs to perform to reach desired free pages. -#ifndef SPIFFS_GC_MAX_RUNS -#define SPIFFS_GC_MAX_RUNS 5 -#endif - -// Enable/disable statistics on gc. Debug/test purpose only. -#ifndef SPIFFS_GC_STATS -#define SPIFFS_GC_STATS 1 -#endif - -// Garbage collecting examines all pages in a block which and sums up -// to a block score. Deleted pages normally gives positive score and -// used pages normally gives a negative score (as these must be moved). -// To have a fair wear-leveling, the erase age is also included in score, -// whose factor normally is the most positive. -// The larger the score, the more likely it is that the block will -// picked for garbage collection. - -// Garbage collecting heuristics - weight used for deleted pages. -#ifndef SPIFFS_GC_HEUR_W_DELET -#define SPIFFS_GC_HEUR_W_DELET (5) -#endif -// Garbage collecting heuristics - weight used for used pages. -#ifndef SPIFFS_GC_HEUR_W_USED -#define SPIFFS_GC_HEUR_W_USED (-1) -#endif -// Garbage collecting heuristics - weight used for time between -// last erased and erase of this block. -#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE -#define SPIFFS_GC_HEUR_W_ERASE_AGE (50) -#endif - -// Object name maximum length. Note that this length include the -// zero-termination character, meaning maximum string of characters -// can at most be SPIFFS_OBJ_NAME_LEN - 1. -#ifndef SPIFFS_OBJ_NAME_LEN -#define SPIFFS_OBJ_NAME_LEN (32) -#endif - -// Maximum length of the metadata associated with an object. -// Setting to non-zero value enables metadata-related API but also -// changes the on-disk format, so the change is not backward-compatible. -// -// Do note: the meta length must never exceed -// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64) -// -// This is derived from following: -// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) + -// spiffs_object_ix_header fields + at least some LUT entries) -#ifndef SPIFFS_OBJ_META_LEN -#define SPIFFS_OBJ_META_LEN (0) -#endif - -// Size of buffer allocated on stack used when copying data. -// Lower value generates more read/writes. No meaning having it bigger -// than logical page size. -#ifndef SPIFFS_COPY_BUFFER_STACK -#define SPIFFS_COPY_BUFFER_STACK (64) -#endif - -// Enable this to have an identifiable spiffs filesystem. This will look for -// a magic in all sectors to determine if this is a valid spiffs system or -// not on mount point. If not, SPIFFS_format must be called prior to mounting -// again. -#ifndef SPIFFS_USE_MAGIC -#define SPIFFS_USE_MAGIC (0) -#endif - -#if SPIFFS_USE_MAGIC -// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is -// enabled, the magic will also be dependent on the length of the filesystem. -// For example, a filesystem configured and formatted for 4 megabytes will not -// be accepted for mounting with a configuration defining the filesystem as 2 -// megabytes. -#ifndef SPIFFS_USE_MAGIC_LENGTH -#define SPIFFS_USE_MAGIC_LENGTH (0) -#endif -#endif - -// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level -// These should be defined on a multithreaded system - -// define this to enter a mutex if you're running on a multithreaded system -#ifndef SPIFFS_LOCK -#define SPIFFS_LOCK(fs) -#endif -// define this to exit a mutex if you're running on a multithreaded system -#ifndef SPIFFS_UNLOCK -#define SPIFFS_UNLOCK(fs) -#endif - -// Enable if only one spiffs instance with constant configuration will exist -// on the target. This will reduce calculations, flash and memory accesses. -// Parts of configuration must be defined below instead of at time of mount. -#ifndef SPIFFS_SINGLETON -#define SPIFFS_SINGLETON 0 -#endif - -#if SPIFFS_SINGLETON -// Instead of giving parameters in config struct, singleton build must -// give parameters in defines below. -#ifndef SPIFFS_CFG_PHYS_SZ -#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2) -#endif -#ifndef SPIFFS_CFG_PHYS_ERASE_SZ -#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536) -#endif -#ifndef SPIFFS_CFG_PHYS_ADDR -#define SPIFFS_CFG_PHYS_ADDR(ignore) (0) -#endif -#ifndef SPIFFS_CFG_LOG_PAGE_SZ -#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256) -#endif -#ifndef SPIFFS_CFG_LOG_BLOCK_SZ -#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536) -#endif -#endif - -// Enable this if your target needs aligned data for index tables -#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES -#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 0 -#endif - -// Enable this if you want the HAL callbacks to be called with the spiffs struct -#ifndef SPIFFS_HAL_CALLBACK_EXTRA -#define SPIFFS_HAL_CALLBACK_EXTRA 0 -#endif - -// Enable this if you want to add an integer offset to all file handles -// (spiffs_file). This is useful if running multiple instances of spiffs on -// same target, in order to recognise to what spiffs instance a file handle -// belongs. -// NB: This adds config field fh_ix_offset in the configuration struct when -// mounting, which must be defined. -#ifndef SPIFFS_FILEHDL_OFFSET -#define SPIFFS_FILEHDL_OFFSET 0 -#endif - -// Enable this to compile a read only version of spiffs. -// This will reduce binary size of spiffs. All code comprising modification -// of the file system will not be compiled. Some config will be ignored. -// HAL functions for erasing and writing to spi-flash may be null. Cache -// can be disabled for even further binary size reduction (and ram savings). -// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL. -// If the file system cannot be mounted due to aborted erase operation and -// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be -// returned. -// Might be useful for e.g. bootloaders and such. -#ifndef SPIFFS_READ_ONLY -#define SPIFFS_READ_ONLY 0 -#endif - -// Enable this to add a temporal file cache using the fd buffer. -// The effects of the cache is that SPIFFS_open will find the file faster in -// certain cases. It will make it a lot easier for spiffs to find files -// opened frequently, reducing number of readings from the spi flash for -// finding those files. -// This will grow each fd by 6 bytes. If your files are opened in patterns -// with a degree of temporal locality, the system is optimized. -// Examples can be letting spiffs serve web content, where one file is the css. -// The css is accessed for each html file that is opened, meaning it is -// accessed almost every second time a file is opened. Another example could be -// a log file that is often opened, written, and closed. -// The size of the cache is number of given file descriptors, as it piggybacks -// on the fd update mechanism. The cache lives in the closed file descriptors. -// When closed, the fd know the whereabouts of the file. Instead of forgetting -// this, the temporal cache will keep handling updates to that file even if the -// fd is closed. If the file is opened again, the location of the file is found -// directly. If all available descriptors become opened, all cache memory is -// lost. -#ifndef SPIFFS_TEMPORAL_FD_CACHE -#define SPIFFS_TEMPORAL_FD_CACHE 1 -#endif - -// Temporal file cache hit score. Each time a file is opened, all cached files -// will lose one point. If the opened file is found in cache, that entry will -// gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this -// value for the specific access patterns of the application. However, it must -// be between 1 (no gain for hitting a cached entry often) and 255. -#ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE -#define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4 -#endif - -// Enable to be able to map object indices to memory. -// This allows for faster and more deterministic reading if cases of reading -// large files and when changing file offset by seeking around a lot. -// When mapping a file's index, the file system will be scanned for index pages -// and the info will be put in memory provided by user. When reading, the -// memory map can be looked up instead of searching for index pages on the -// medium. This way, user can trade memory against performance. -// Whole, parts of, or future parts not being written yet can be mapped. The -// memory array will be owned by spiffs and updated accordingly during garbage -// collecting or when modifying the indices. The latter is invoked by when the -// file is modified in some way. The index buffer is tied to the file -// descriptor. -#ifndef SPIFFS_IX_MAP -#define SPIFFS_IX_MAP 1 -#endif - -// By default SPIFFS in some cases relies on the property of NOR flash that bits -// cannot be set from 0 to 1 by writing and that controllers will ignore such -// bit changes. This results in fewer reads as SPIFFS can in some cases perform -// blind writes, with all bits set to 1 and only those it needs reset set to 0. -// Most of the chips and controllers allow this behavior, so the default is to -// use this technique. If your controller is one of the rare ones that don't, -// turn this option on and SPIFFS will perform a read-modify-write instead. -#ifndef SPIFFS_NO_BLIND_WRITES -#define SPIFFS_NO_BLIND_WRITES 0 -#endif - -// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function -// in the api. This function will visualize all filesystem using given printf -// function. -#ifndef SPIFFS_TEST_VISUALISATION -#define SPIFFS_TEST_VISUALISATION 1 -#endif -#if SPIFFS_TEST_VISUALISATION -#ifndef spiffs_printf -#define spiffs_printf(...) printf(__VA_ARGS__) -#endif -// spiffs_printf argument for a free page -#ifndef SPIFFS_TEST_VIS_FREE_STR -#define SPIFFS_TEST_VIS_FREE_STR "_" -#endif -// spiffs_printf argument for a deleted page -#ifndef SPIFFS_TEST_VIS_DELE_STR -#define SPIFFS_TEST_VIS_DELE_STR "/" -#endif -// spiffs_printf argument for an index page for given object id -#ifndef SPIFFS_TEST_VIS_INDX_STR -#define SPIFFS_TEST_VIS_INDX_STR(id) "i" -#endif -// spiffs_printf argument for a data page for given object id -#ifndef SPIFFS_TEST_VIS_DATA_STR -#define SPIFFS_TEST_VIS_DATA_STR(id) "d" -#endif -#endif - -// Types depending on configuration such as the amount of flash bytes -// given to spiffs file system in total (spiffs_file_system_size), -// the logical block size (log_block_size), and the logical page size -// (log_page_size) - -// Block index type. Make sure the size of this type can hold -// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size -typedef u16_t spiffs_block_ix; -// Page index type. Make sure the size of this type can hold -// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size -typedef u16_t spiffs_page_ix; -// Object id type - most significant bit is reserved for index flag. Make sure the -// size of this type can hold the highest object id on a full system, -// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2 -typedef u16_t spiffs_obj_id; -// Object span index type. Make sure the size of this type can -// hold the largest possible span index on the system - -// i.e. (spiffs_file_system_size / log_page_size) - 1 -typedef u16_t spiffs_span_ix; - -#endif /* SPIFFS_CONFIG_H_ */ diff --git a/src/spiffs/spiffs.h b/src/spiffs/spiffs.h deleted file mode 100644 index 534c3df..0000000 --- a/src/spiffs/spiffs.h +++ /dev/null @@ -1,816 +0,0 @@ -/* - * spiffs.h - * - * Created on: May 26, 2013 - * Author: petera - */ - -#ifndef SPIFFS_H_ -#define SPIFFS_H_ -#if defined(__cplusplus) -extern "C" { -#endif - -#include "spiffs_config.h" - -#define SPIFFS_OK 0 -#define SPIFFS_ERR_NOT_MOUNTED -10000 -#define SPIFFS_ERR_FULL -10001 -#define SPIFFS_ERR_NOT_FOUND -10002 -#define SPIFFS_ERR_END_OF_OBJECT -10003 -#define SPIFFS_ERR_DELETED -10004 -#define SPIFFS_ERR_NOT_FINALIZED -10005 -#define SPIFFS_ERR_NOT_INDEX -10006 -#define SPIFFS_ERR_OUT_OF_FILE_DESCS -10007 -#define SPIFFS_ERR_FILE_CLOSED -10008 -#define SPIFFS_ERR_FILE_DELETED -10009 -#define SPIFFS_ERR_BAD_DESCRIPTOR -10010 -#define SPIFFS_ERR_IS_INDEX -10011 -#define SPIFFS_ERR_IS_FREE -10012 -#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10013 -#define SPIFFS_ERR_DATA_SPAN_MISMATCH -10014 -#define SPIFFS_ERR_INDEX_REF_FREE -10015 -#define SPIFFS_ERR_INDEX_REF_LU -10016 -#define SPIFFS_ERR_INDEX_REF_INVALID -10017 -#define SPIFFS_ERR_INDEX_FREE -10018 -#define SPIFFS_ERR_INDEX_LU -10019 -#define SPIFFS_ERR_INDEX_INVALID -10020 -#define SPIFFS_ERR_NOT_WRITABLE -10021 -#define SPIFFS_ERR_NOT_READABLE -10022 -#define SPIFFS_ERR_CONFLICTING_NAME -10023 -#define SPIFFS_ERR_NOT_CONFIGURED -10024 - -#define SPIFFS_ERR_NOT_A_FS -10025 -#define SPIFFS_ERR_MOUNTED -10026 -#define SPIFFS_ERR_ERASE_FAIL -10027 -#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028 - -#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029 - -#define SPIFFS_ERR_FILE_EXISTS -10030 - -#define SPIFFS_ERR_NOT_A_FILE -10031 -#define SPIFFS_ERR_RO_NOT_IMPL -10032 -#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033 -#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034 -#define SPIFFS_ERR_PROBE_NOT_A_FS -10035 -#define SPIFFS_ERR_NAME_TOO_LONG -10036 - -#define SPIFFS_ERR_IX_MAP_UNMAPPED -10037 -#define SPIFFS_ERR_IX_MAP_MAPPED -10038 -#define SPIFFS_ERR_IX_MAP_BAD_RANGE -10039 - -#define SPIFFS_ERR_SEEK_BOUNDS -10040 - - -#define SPIFFS_ERR_INTERNAL -10050 - -#define SPIFFS_ERR_TEST -10100 - - -// spiffs file descriptor index type. must be signed -typedef s16_t spiffs_file; -// spiffs file descriptor flags -typedef u16_t spiffs_flags; -// spiffs file mode -typedef u16_t spiffs_mode; -// object type -typedef u8_t spiffs_obj_type; - -struct spiffs_t; - -#if SPIFFS_HAL_CALLBACK_EXTRA - -/* spi read call function type */ -typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst); -/* spi write call function type */ -typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src); -/* spi erase call function type */ -typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size); - -#else // SPIFFS_HAL_CALLBACK_EXTRA - -/* spi read call function type */ -typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst); -/* spi write call function type */ -typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src); -/* spi erase call function type */ -typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size); -#endif // SPIFFS_HAL_CALLBACK_EXTRA - -/* file system check callback report operation */ -typedef enum { - SPIFFS_CHECK_LOOKUP = 0, - SPIFFS_CHECK_INDEX, - SPIFFS_CHECK_PAGE -} spiffs_check_type; - -/* file system check callback report type */ -typedef enum { - SPIFFS_CHECK_PROGRESS = 0, - SPIFFS_CHECK_ERROR, - SPIFFS_CHECK_FIX_INDEX, - SPIFFS_CHECK_FIX_LOOKUP, - SPIFFS_CHECK_DELETE_ORPHANED_INDEX, - SPIFFS_CHECK_DELETE_PAGE, - SPIFFS_CHECK_DELETE_BAD_FILE -} spiffs_check_report; - -/* file system check callback function */ -#if SPIFFS_HAL_CALLBACK_EXTRA -typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report, - u32_t arg1, u32_t arg2); -#else // SPIFFS_HAL_CALLBACK_EXTRA -typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, - u32_t arg1, u32_t arg2); -#endif // SPIFFS_HAL_CALLBACK_EXTRA - -/* file system listener callback operation */ -typedef enum { - /* the file has been created */ - SPIFFS_CB_CREATED = 0, - /* the file has been updated or moved to another page */ - SPIFFS_CB_UPDATED, - /* the file has been deleted */ - SPIFFS_CB_DELETED -} spiffs_fileop_type; - -/* file system listener callback function */ -typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix); - -#ifndef SPIFFS_DBG -#define SPIFFS_DBG(...) \ - printf(__VA_ARGS__) -#endif -#ifndef SPIFFS_GC_DBG -#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__) -#endif -#ifndef SPIFFS_CACHE_DBG -#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__) -#endif -#ifndef SPIFFS_CHECK_DBG -#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__) -#endif - -/* Any write to the filehandle is appended to end of the file */ -#define SPIFFS_APPEND (1<<0) -#define SPIFFS_O_APPEND SPIFFS_APPEND -/* If the opened file exists, it will be truncated to zero length before opened */ -#define SPIFFS_TRUNC (1<<1) -#define SPIFFS_O_TRUNC SPIFFS_TRUNC -/* If the opened file does not exist, it will be created before opened */ -#define SPIFFS_CREAT (1<<2) -#define SPIFFS_O_CREAT SPIFFS_CREAT -/* The opened file may only be read */ -#define SPIFFS_RDONLY (1<<3) -#define SPIFFS_O_RDONLY SPIFFS_RDONLY -/* The opened file may only be written */ -#define SPIFFS_WRONLY (1<<4) -#define SPIFFS_O_WRONLY SPIFFS_WRONLY -/* The opened file may be both read and written */ -#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY) -#define SPIFFS_O_RDWR SPIFFS_RDWR -/* Any writes to the filehandle will never be cached but flushed directly */ -#define SPIFFS_DIRECT (1<<5) -#define SPIFFS_O_DIRECT SPIFFS_DIRECT -/* If SPIFFS_O_CREAT and SPIFFS_O_EXCL are set, SPIFFS_open() shall fail if the file exists */ -#define SPIFFS_EXCL (1<<6) -#define SPIFFS_O_EXCL SPIFFS_EXCL - -#define SPIFFS_SEEK_SET (0) -#define SPIFFS_SEEK_CUR (1) -#define SPIFFS_SEEK_END (2) - -#define SPIFFS_TYPE_FILE (1) -#define SPIFFS_TYPE_DIR (2) -#define SPIFFS_TYPE_HARD_LINK (3) -#define SPIFFS_TYPE_SOFT_LINK (4) - -#ifndef SPIFFS_LOCK -#define SPIFFS_LOCK(fs) -#endif - -#ifndef SPIFFS_UNLOCK -#define SPIFFS_UNLOCK(fs) -#endif - -// phys structs - -// spiffs spi configuration struct -typedef struct { - // physical read function - spiffs_read hal_read_f; - // physical write function - spiffs_write hal_write_f; - // physical erase function - spiffs_erase hal_erase_f; -#if SPIFFS_SINGLETON == 0 - // physical size of the spi flash - u32_t phys_size; - // physical offset in spi flash used for spiffs, - // must be on block boundary - u32_t phys_addr; - // physical size when erasing a block - u32_t phys_erase_block; - - // logical size of a block, must be on physical - // block size boundary and must never be less than - // a physical block - u32_t log_block_size; - // logical size of a page, must be at least - // log_block_size / 8 - u32_t log_page_size; - -#endif -#if SPIFFS_FILEHDL_OFFSET - // an integer offset added to each file handle - u16_t fh_ix_offset; -#endif -} spiffs_config; - -typedef struct spiffs_t { - // file system configuration - spiffs_config cfg; - // number of logical blocks - u32_t block_count; - - // cursor for free blocks, block index - spiffs_block_ix free_cursor_block_ix; - // cursor for free blocks, entry index - int free_cursor_obj_lu_entry; - // cursor when searching, block index - spiffs_block_ix cursor_block_ix; - // cursor when searching, entry index - int cursor_obj_lu_entry; - - // primary work buffer, size of a logical page - u8_t *lu_work; - // secondary work buffer, size of a logical page - u8_t *work; - // file descriptor memory area - u8_t *fd_space; - // available file descriptors - u32_t fd_count; - - // last error - s32_t err_code; - - // current number of free blocks - u32_t free_blocks; - // current number of busy pages - u32_t stats_p_allocated; - // current number of deleted pages - u32_t stats_p_deleted; - // flag indicating that garbage collector is cleaning - u8_t cleaning; - // max erase count amongst all blocks - spiffs_obj_id max_erase_count; - -#if SPIFFS_GC_STATS - u32_t stats_gc_runs; -#endif - -#if SPIFFS_CACHE - // cache memory - void *cache; - // cache size - u32_t cache_size; -#if SPIFFS_CACHE_STATS - u32_t cache_hits; - u32_t cache_misses; -#endif -#endif - - // check callback function - spiffs_check_callback check_cb_f; - // file callback function - spiffs_file_callback file_cb_f; - // mounted flag - u8_t mounted; - // user data - void *user_data; - // config magic - u32_t config_magic; -} spiffs; - -/* spiffs file status struct */ -typedef struct { - spiffs_obj_id obj_id; - u32_t size; - spiffs_obj_type type; - spiffs_page_ix pix; - u8_t name[SPIFFS_OBJ_NAME_LEN]; -#if SPIFFS_OBJ_META_LEN - u8_t meta[SPIFFS_OBJ_META_LEN]; -#endif -} spiffs_stat; - -struct spiffs_dirent { - spiffs_obj_id obj_id; - u8_t name[SPIFFS_OBJ_NAME_LEN]; - spiffs_obj_type type; - u32_t size; - spiffs_page_ix pix; -#if SPIFFS_OBJ_META_LEN - u8_t meta[SPIFFS_OBJ_META_LEN]; -#endif -}; - -typedef struct { - spiffs *fs; - spiffs_block_ix block; - int entry; -} spiffs_DIR; - -#if SPIFFS_IX_MAP - -typedef struct { - // buffer with looked up data pixes - spiffs_page_ix *map_buf; - // precise file byte offset - u32_t offset; - // start data span index of lookup buffer - spiffs_span_ix start_spix; - // end data span index of lookup buffer - spiffs_span_ix end_spix; -} spiffs_ix_map; - -#endif - -// functions - -#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 -/** - * Special function. This takes a spiffs config struct and returns the number - * of blocks this file system was formatted with. This function relies on - * that following info is set correctly in given config struct: - * - * phys_addr, log_page_size, and log_block_size. - * - * Also, hal_read_f must be set in the config struct. - * - * One must be sure of the correct page size and that the physical address is - * correct in the probed file system when calling this function. It is not - * checked if the phys_addr actually points to the start of the file system, - * so one might get a false positive if entering a phys_addr somewhere in the - * middle of the file system at block boundary. In addition, it is not checked - * if the page size is actually correct. If it is not, weird file system sizes - * will be returned. - * - * If this function detects a file system it returns the assumed file system - * size, which can be used to set the phys_size. - * - * Otherwise, it returns an error indicating why it is not regarded as a file - * system. - * - * Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK - * macros. It returns the error code directly, instead of as read by - * SPIFFS_errno. - * - * @param config essential parts of the physical and logical - * configuration of the file system. - */ -s32_t SPIFFS_probe_fs(spiffs_config *config); -#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 - -/** - * Initializes the file system dynamic parameters and mounts the filesystem. - * If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS - * if the flash does not contain a recognizable file system. - * In this case, SPIFFS_format must be called prior to remounting. - * @param fs the file system struct - * @param config the physical and logical configuration of the file system - * @param work a memory work buffer comprising 2*config->log_page_size - * bytes used throughout all file system operations - * @param fd_space memory for file descriptors - * @param fd_space_size memory size of file descriptors - * @param cache memory for cache, may be null - * @param cache_size memory size of cache - * @param check_cb_f callback function for reporting during consistency checks - */ -s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, - u8_t *fd_space, u32_t fd_space_size, - void *cache, u32_t cache_size, - spiffs_check_callback check_cb_f); - -/** - * Unmounts the file system. All file handles will be flushed of any - * cached writes and closed. - * @param fs the file system struct - */ -void SPIFFS_unmount(spiffs *fs); - -/** - * Creates a new file. - * @param fs the file system struct - * @param path the path of the new file - * @param mode ignored, for posix compliance - */ -s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode); - -/** - * Opens/creates a file. - * @param fs the file system struct - * @param path the path of the new file - * @param flags the flags for the open command, can be combinations of - * SPIFFS_O_APPEND, SPIFFS_O_TRUNC, SPIFFS_O_CREAT, SPIFFS_O_RDONLY, - * SPIFFS_O_WRONLY, SPIFFS_O_RDWR, SPIFFS_O_DIRECT, SPIFFS_O_EXCL - * @param mode ignored, for posix compliance - */ -spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode); - -/** - * Opens a file by given dir entry. - * Optimization purposes, when traversing a file system with SPIFFS_readdir - * a normal SPIFFS_open would need to traverse the filesystem again to find - * the file, whilst SPIFFS_open_by_dirent already knows where the file resides. - * @param fs the file system struct - * @param e the dir entry to the file - * @param flags the flags for the open command, can be combinations of - * SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY, - * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT. - * SPIFFS_CREAT will have no effect in this case. - * @param mode ignored, for posix compliance - */ -spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode); - -/** - * Opens a file by given page index. - * Optimization purposes, opens a file by directly pointing to the page - * index in the spi flash. - * If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE - * is returned. - * @param fs the file system struct - * @param page_ix the page index - * @param flags the flags for the open command, can be combinations of - * SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY, - * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT. - * SPIFFS_CREAT will have no effect in this case. - * @param mode ignored, for posix compliance - */ -spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode); - -/** - * Reads from given filehandle. - * @param fs the file system struct - * @param fh the filehandle - * @param buf where to put read data - * @param len how much to read - * @returns number of bytes read, or -1 if error - */ -s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len); - -/** - * Writes to given filehandle. - * @param fs the file system struct - * @param fh the filehandle - * @param buf the data to write - * @param len how much to write - * @returns number of bytes written, or -1 if error - */ -s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len); - -/** - * Moves the read/write file offset. Resulting offset is returned or negative if error. - * lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset. - * @param fs the file system struct - * @param fh the filehandle - * @param offs how much/where to move the offset - * @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes - * if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset - * if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative - */ -s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence); - -/** - * Removes a file by path - * @param fs the file system struct - * @param path the path of the file to remove - */ -s32_t SPIFFS_remove(spiffs *fs, const char *path); - -/** - * Removes a file by filehandle - * @param fs the file system struct - * @param fh the filehandle of the file to remove - */ -s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh); - -/** - * Gets file status by path - * @param fs the file system struct - * @param path the path of the file to stat - * @param s the stat struct to populate - */ -s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s); - -/** - * Gets file status by filehandle - * @param fs the file system struct - * @param fh the filehandle of the file to stat - * @param s the stat struct to populate - */ -s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s); - -/** - * Flushes all pending write operations from cache for given file - * @param fs the file system struct - * @param fh the filehandle of the file to flush - */ -s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh); - -/** - * Closes a filehandle. If there are pending write operations, these are finalized before closing. - * @param fs the file system struct - * @param fh the filehandle of the file to close - */ -s32_t SPIFFS_close(spiffs *fs, spiffs_file fh); - -/** - * Renames a file - * @param fs the file system struct - * @param old path of file to rename - * @param newPath new path of file - */ -s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newPath); - -#if SPIFFS_OBJ_META_LEN -/** - * Updates file's metadata - * @param fs the file system struct - * @param path path to the file - * @param meta new metadata. must be SPIFFS_OBJ_META_LEN bytes long. - */ -s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta); - -/** - * Updates file's metadata - * @param fs the file system struct - * @param fh file handle of the file - * @param meta new metadata. must be SPIFFS_OBJ_META_LEN bytes long. - */ -s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta); -#endif - -/** - * Returns last error of last file operation. - * @param fs the file system struct - */ -s32_t SPIFFS_errno(spiffs *fs); - -/** - * Clears last error. - * @param fs the file system struct - */ -void SPIFFS_clearerr(spiffs *fs); - -/** - * Opens a directory stream corresponding to the given name. - * The stream is positioned at the first entry in the directory. - * On hydrogen builds the name argument is ignored as hydrogen builds always correspond - * to a flat file structure - no directories. - * @param fs the file system struct - * @param name the name of the directory - * @param d pointer the directory stream to be populated - */ -spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d); - -/** - * Closes a directory stream - * @param d the directory stream to close - */ -s32_t SPIFFS_closedir(spiffs_DIR *d); - -/** - * Reads a directory into given spifs_dirent struct. - * @param d pointer to the directory stream - * @param e the dirent struct to be populated - * @returns null if error or end of stream, else given dirent is returned - */ -struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e); - -/** - * Runs a consistency check on given filesystem. - * @param fs the file system struct - */ -s32_t SPIFFS_check(spiffs *fs); - -/** - * Returns number of total bytes available and number of used bytes. - * This is an estimation, and depends on if there a many files with little - * data or few files with much data. - * NB: If used number of bytes exceeds total bytes, a SPIFFS_check should - * run. This indicates a power loss in midst of things. In worst case - * (repeated powerlosses in mending or gc) you might have to delete some files. - * - * @param fs the file system struct - * @param total total number of bytes in filesystem - * @param used used number of bytes in filesystem - */ -s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used); - -/** - * Formats the entire file system. All data will be lost. - * The filesystem must not be mounted when calling this. - * - * NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount - * MUST be called prior to formatting in order to configure the filesystem. - * If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling - * SPIFFS_format. - * If SPIFFS_mount fails, SPIFFS_format can be called directly without calling - * SPIFFS_unmount first. - * - * @param fs the file system struct - */ -s32_t SPIFFS_format(spiffs *fs); - -/** - * Returns nonzero if spiffs is mounted, or zero if unmounted. - * @param fs the file system struct - */ -u8_t SPIFFS_mounted(spiffs *fs); - -/** - * Tries to find a block where most or all pages are deleted, and erase that - * block if found. Does not care for wear levelling. Will not move pages - * around. - * If parameter max_free_pages are set to 0, only blocks with only deleted - * pages will be selected. - * - * NB: the garbage collector is automatically called when spiffs needs free - * pages. The reason for this function is to give possibility to do background - * tidying when user knows the system is idle. - * - * Use with care. - * - * Setting max_free_pages to anything larger than zero will eventually wear - * flash more as a block containing free pages can be erased. - * - * Will set err_no to SPIFFS_OK if a block was found and erased, - * SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found, - * or other error. - * - * @param fs the file system struct - * @param max_free_pages maximum number allowed free pages in block - */ -s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages); - -/** - * Will try to make room for given amount of bytes in the filesystem by moving - * pages and erasing blocks. - * If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If - * there already is this amount (or more) of free space, SPIFFS_gc will - * silently return. It is recommended to call SPIFFS_info before invoking - * this method in order to determine what amount of bytes to give. - * - * NB: the garbage collector is automatically called when spiffs needs free - * pages. The reason for this function is to give possibility to do background - * tidying when user knows the system is idle. - * - * Use with care. - * - * @param fs the file system struct - * @param size amount of bytes that should be freed - */ -s32_t SPIFFS_gc(spiffs *fs, u32_t size); - -/** - * Check if EOF reached. - * @param fs the file system struct - * @param fh the filehandle of the file to check - */ -s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh); - -/** - * Get position in file. - * @param fs the file system struct - * @param fh the filehandle of the file to check - */ -s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh); - -/** - * Registers a callback function that keeps track on operations on file - * headers. Do note, that this callback is called from within internal spiffs - * mechanisms. Any operations on the actual file system being callbacked from - * in this callback will mess things up for sure - do not do this. - * This can be used to track where files are and move around during garbage - * collection, which in turn can be used to build location tables in ram. - * Used in conjuction with SPIFFS_open_by_page this may improve performance - * when opening a lot of files. - * Must be invoked after mount. - * - * @param fs the file system struct - * @param cb_func the callback on file operations - */ -s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func); - -#if SPIFFS_IX_MAP - -/** - * Maps the first level index lookup to a given memory map. - * This will make reading big files faster, as the memory map will be used for - * looking up data pages instead of searching for the indices on the physical - * medium. When mapping, all affected indicies are found and the information is - * copied to the array. - * Whole file or only parts of it may be mapped. The index map will cover file - * contents from argument offset until and including arguments (offset+len). - * It is valid to map a longer range than the current file size. The map will - * then be populated when the file grows. - * On garbage collections and file data page movements, the map array will be - * automatically updated. Do not tamper with the map array, as this contains - * the references to the data pages. Modifying it from outside will corrupt any - * future readings using this file descriptor. - * The map will no longer be used when the file descriptor closed or the file - * is unmapped. - * This can be useful to get faster and more deterministic timing when reading - * large files, or when seeking and reading a lot within a file. - * @param fs the file system struct - * @param fh the file handle of the file to map - * @param map a spiffs_ix_map struct, describing the index map - * @param offset absolute file offset where to start the index map - * @param len length of the mapping in actual file bytes - * @param map_buf the array buffer for the look up data - number of required - * elements in the array can be derived from function - * SPIFFS_bytes_to_ix_map_entries given the length - */ -s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map, - u32_t offset, u32_t len, spiffs_page_ix *map_buf); - -/** - * Unmaps the index lookup from this filehandle. All future readings will - * proceed as normal, requiring reading of the first level indices from - * physical media. - * The map and map buffer given in function SPIFFS_ix_map will no longer be - * referenced by spiffs. - * It is not strictly necessary to unmap a file before closing it, as closing - * a file will automatically unmap it. - * @param fs the file system struct - * @param fh the file handle of the file to unmap - */ -s32_t SPIFFS_ix_unmap(spiffs *fs, spiffs_file fh); - -/** - * Moves the offset for the index map given in function SPIFFS_ix_map. Parts or - * all of the map buffer will repopulated. - * @param fs the file system struct - * @param fh the mapped file handle of the file to remap - * @param offset new absolute file offset where to start the index map - */ -s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offs); - -/** - * Utility function to get number of spiffs_page_ix entries a map buffer must - * contain on order to map given amount of file data in bytes. - * See function SPIFFS_ix_map and SPIFFS_ix_map_entries_to_bytes. - * @param fs the file system struct - * @param bytes number of file data bytes to map - * @return needed number of elements in a spiffs_page_ix array needed to - * map given amount of bytes in a file - */ -s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes); - -/** - * Utility function to amount of file data bytes that can be mapped when - * mapping a file with buffer having given number of spiffs_page_ix entries. - * See function SPIFFS_ix_map and SPIFFS_bytes_to_ix_map_entries. - * @param fs the file system struct - * @param map_page_ix_entries number of entries in a spiffs_page_ix array - * @return amount of file data in bytes that can be mapped given a map - * buffer having given amount of spiffs_page_ix entries - */ -s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entries); - -#endif // SPIFFS_IX_MAP - - -#if SPIFFS_TEST_VISUALISATION -/** - * Prints out a visualization of the filesystem. - * @param fs the file system struct - */ -s32_t SPIFFS_vis(spiffs *fs); -#endif - -#if SPIFFS_BUFFER_HELP -/** - * Returns number of bytes needed for the filedescriptor buffer given - * amount of file descriptors. - */ -u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs); - -#if SPIFFS_CACHE -/** - * Returns number of bytes needed for the cache buffer given - * amount of cache pages. - */ -u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages); -#endif -#endif - -#if SPIFFS_CACHE -#endif -#if defined(__cplusplus) -} -#endif - -#endif /* SPIFFS_H_ */ diff --git a/src/spiffs/spiffs_cache.c b/src/spiffs/spiffs_cache.c deleted file mode 100644 index e7cd4b7..0000000 --- a/src/spiffs/spiffs_cache.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * spiffs_cache.c - * - * Created on: Jun 23, 2013 - * Author: petera - */ - -#include "spiffs.h" -#include "spiffs_nucleus.h" - -#if SPIFFS_CACHE - -// returns cached page for give page index, or null if no such cached page -static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) { - spiffs_cache *cache = spiffs_get_cache(fs); - if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0; - int i; - for (i = 0; i < cache->cpage_count; i++) { - spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); - if ((cache->cpage_use_map & (1<flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && - cp->pix == pix ) { - //SPIFFS_CACHE_DBG("CACHE_GET: have cache page "_SPIPRIi" for "_SPIPRIpg"\n", i, pix); - cp->last_access = cache->last_access; - return cp; - } - } - //SPIFFS_CACHE_DBG("CACHE_GET: no cache for "_SPIPRIpg"\n", pix); - return 0; -} - -// frees cached page -static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) { - s32_t res = SPIFFS_OK; - spiffs_cache *cache = spiffs_get_cache(fs); - spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix); - if (cache->cpage_use_map & (1<flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && - (cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) { - u8_t *mem = spiffs_get_cache_page(fs, cache, ix); - SPIFFS_CACHE_DBG("CACHE_FREE: write cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix); - res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem); - } - -#if SPIFFS_CACHE_WR - if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" objid "_SPIPRIid"\n", ix, cp->obj_id); - } else -#endif - { - SPIFFS_CACHE_DBG("CACHE_FREE: free cache page "_SPIPRIi" pix "_SPIPRIpg"\n", ix, cp->pix); - } - cache->cpage_use_map &= ~(1 << ix); - cp->flags = 0; - } - - return res; -} - -// removes the oldest accessed cached page -static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) { - s32_t res = SPIFFS_OK; - spiffs_cache *cache = spiffs_get_cache(fs); - - if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) { - // at least one free cpage - return SPIFFS_OK; - } - - // all busy, scan thru all to find the cpage which has oldest access - int i; - int cand_ix = -1; - u32_t oldest_val = 0; - for (i = 0; i < cache->cpage_count; i++) { - spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); - if ((cache->last_access - cp->last_access) > oldest_val && - (cp->flags & flag_mask) == flags) { - oldest_val = cache->last_access - cp->last_access; - cand_ix = i; - } - } - - if (cand_ix >= 0) { - res = spiffs_cache_page_free(fs, cand_ix, 1); - } - - return res; -} - -// allocates a new cached page and returns it, or null if all cache pages are busy -static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) { - spiffs_cache *cache = spiffs_get_cache(fs); - if (cache->cpage_use_map == 0xffffffff) { - // out of cache memory - return 0; - } - int i; - for (i = 0; i < cache->cpage_count; i++) { - if ((cache->cpage_use_map & (1<cpage_use_map |= (1<last_access = cache->last_access; - //SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi"\n", i); - return cp; - } - } - // out of cache entries - return 0; -} - -// drops the cache page for give page index -void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) { - spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix); - if (cp) { - spiffs_cache_page_free(fs, cp->ix, 0); - } -} - -// ------------------------------ - -// reads from spi flash or the cache -s32_t spiffs_phys_rd( - spiffs *fs, - u8_t op, - spiffs_file fh, - u32_t addr, - u32_t len, - u8_t *dst) { - (void)fh; - s32_t res = SPIFFS_OK; - spiffs_cache *cache = spiffs_get_cache(fs); - spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr)); - cache->last_access++; - if (cp) { - // we've already got one, you see -#if SPIFFS_CACHE_STATS - fs->cache_hits++; -#endif - cp->last_access = cache->last_access; - u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix); - _SPIFFS_MEMCPY(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len); - } else { - if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) { - // for second layer lookup functions, we do not cache in order to prevent shredding - return SPIFFS_HAL_READ(fs, addr, len, dst); - } -#if SPIFFS_CACHE_STATS - fs->cache_misses++; -#endif - // this operation will always free one cache page (unless all already free), - // the result code stems from the write operation of the possibly freed cache page - res = spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0); - - cp = spiffs_cache_page_allocate(fs); - if (cp) { - cp->flags = SPIFFS_CACHE_FLAG_WRTHRU; - cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr); - SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for pix "_SPIPRIpg "\n", cp->ix, cp->pix); - - s32_t res2 = SPIFFS_HAL_READ(fs, - addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr), - SPIFFS_CFG_LOG_PAGE_SZ(fs), - spiffs_get_cache_page(fs, cache, cp->ix)); - if (res2 != SPIFFS_OK) { - // honor read failure before possible write failure (bad idea?) - res = res2; - } - u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix); - _SPIFFS_MEMCPY(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len); - } else { - // this will never happen, last resort for sake of symmetry - s32_t res2 = SPIFFS_HAL_READ(fs, addr, len, dst); - if (res2 != SPIFFS_OK) { - // honor read failure before possible write failure (bad idea?) - res = res2; - } - } - } - return res; -} - -// writes to spi flash and/or the cache -s32_t spiffs_phys_wr( - spiffs *fs, - u8_t op, - spiffs_file fh, - u32_t addr, - u32_t len, - u8_t *src) { - (void)fh; - spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr); - spiffs_cache *cache = spiffs_get_cache(fs); - spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix); - - if (cp && (op & SPIFFS_OP_COM_MASK) != SPIFFS_OP_C_WRTHRU) { - // have a cache page - // copy in data to cache page - - if ((op & SPIFFS_OP_COM_MASK) == SPIFFS_OP_C_DELE && - (op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) { - // page is being deleted, wipe from cache - unless it is a lookup page - spiffs_cache_page_free(fs, cp->ix, 0); - return SPIFFS_HAL_WRITE(fs, addr, len, src); - } - - u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix); - _SPIFFS_MEMCPY(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len); - - cache->last_access++; - cp->last_access = cache->last_access; - - if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) { - // page is being updated, no write-cache, just pass thru - return SPIFFS_HAL_WRITE(fs, addr, len, src); - } else { - return SPIFFS_OK; - } - } else { - // no cache page, no write cache - just write thru - return SPIFFS_HAL_WRITE(fs, addr, len, src); - } -} - -#if SPIFFS_CACHE_WR -// returns the cache page that this fd refers, or null if no cache page -spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) { - spiffs_cache *cache = spiffs_get_cache(fs); - - if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) { - // all cpages free, no cpage cannot be assigned to obj_id - return 0; - } - - int i; - for (i = 0; i < cache->cpage_count; i++) { - spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i); - if ((cache->cpage_use_map & (1<flags & SPIFFS_CACHE_FLAG_TYPE_WR) && - cp->obj_id == fd->obj_id) { - return cp; - } - } - - return 0; -} - -// allocates a new cache page and refers this to given fd - flushes an old cache -// page if all cache is busy -spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_fd *fd) { - // before this function is called, it is ensured that there is no already existing - // cache page with same object id - spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0); - spiffs_cache_page *cp = spiffs_cache_page_allocate(fs); - if (cp == 0) { - // could not get cache page - return 0; - } - - cp->flags = SPIFFS_CACHE_FLAG_TYPE_WR; - cp->obj_id = fd->obj_id; - fd->cache_page = cp; - SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page "_SPIPRIi" for fd "_SPIPRIfd ":"_SPIPRIid "\n", cp->ix, fd->file_nbr, fd->obj_id); - return cp; -} - -// unrefers all fds that this cache page refers to and releases the cache page -void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) { - if (cp == 0) return; - 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->cache_page == cp) { - cur_fd->cache_page = 0; - } - } - spiffs_cache_page_free(fs, cp->ix, 0); - - cp->obj_id = 0; -} - -#endif - -// initializes the cache -void spiffs_cache_init(spiffs *fs) { - if (fs->cache == 0) return; - u32_t sz = fs->cache_size; - u32_t cache_mask = 0; - int i; - int cache_entries = - (sz - sizeof(spiffs_cache)) / (SPIFFS_CACHE_PAGE_SIZE(fs)); - if (cache_entries <= 0) return; - - for (i = 0; i < cache_entries; i++) { - cache_mask <<= 1; - cache_mask |= 1; - } - - spiffs_cache cache; - memset(&cache, 0, sizeof(spiffs_cache)); - cache.cpage_count = cache_entries; - cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache)); - - cache.cpage_use_map = 0xffffffff; - cache.cpage_use_mask = cache_mask; - _SPIFFS_MEMCPY(fs->cache, &cache, sizeof(spiffs_cache)); - - spiffs_cache *c = spiffs_get_cache(fs); - - memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs)); - - c->cpage_use_map &= ~(c->cpage_use_mask); - for (i = 0; i < cache.cpage_count; i++) { - spiffs_get_cache_page_hdr(fs, c, i)->ix = i; - } -} - -#endif // SPIFFS_CACHE diff --git a/src/spiffs/spiffs_check.c b/src/spiffs/spiffs_check.c deleted file mode 100644 index 0331fb1..0000000 --- a/src/spiffs/spiffs_check.c +++ /dev/null @@ -1,1008 +0,0 @@ -/* - * spiffs_check.c - * - * Contains functionality for checking file system consistency - * and mending problems. - * Three levels of consistency checks are implemented: - * - * Look up consistency - * Checks if indices in lookup pages are coherent with page headers - * Object index consistency - * Checks if there are any orphaned object indices (missing object index headers). - * If an object index is found but not its header, the object index is deleted. - * This is critical for the following page consistency check. - * Page consistency - * Checks for pages that ought to be indexed, ought not to be indexed, are multiple indexed - * - * - * Created on: Jul 7, 2013 - * Author: petera - */ - - -#include "spiffs.h" -#include "spiffs_nucleus.h" - -#if !SPIFFS_READ_ONLY - -#if SPIFFS_HAL_CALLBACK_EXTRA -#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \ - do { \ - if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \ - } while (0) -#else -#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \ - do { \ - if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \ - } while (0) -#endif - -//--------------------------------------- -// Look up consistency - -// searches in the object indices and returns the referenced page index given -// the object id and the data span index -// destroys fs->lu_work -static s32_t spiffs_object_get_data_page_index_reference( - spiffs *fs, - spiffs_obj_id obj_id, - spiffs_span_ix data_spix, - spiffs_page_ix *pix, - spiffs_page_ix *objix_pix) { - s32_t res; - - // calculate object index span index for given data page span index - spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix); - - // find obj index for obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, objix_pix); - SPIFFS_CHECK_RES(res); - - // load obj index entry - u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, *objix_pix); - if (objix_spix == 0) { - // get referenced page from object index header - addr += sizeof(spiffs_page_object_ix_header) + data_spix * sizeof(spiffs_page_ix); - } else { - // get referenced page from object index - addr += sizeof(spiffs_page_object_ix) + SPIFFS_OBJ_IX_ENTRY(fs, data_spix) * sizeof(spiffs_page_ix); - } - - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, 0, addr, sizeof(spiffs_page_ix), (u8_t *)pix); - - return res; -} - -// copies page contents to a new page -static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spiffs_page_header *p_hdr, spiffs_page_ix *new_pix) { - s32_t res; - res = spiffs_page_allocate_data(fs, p_hdr->obj_id, p_hdr, 0,0,0,0, new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_phys_cpy(fs, 0, - SPIFFS_PAGE_TO_PADDR(fs, *new_pix) + sizeof(spiffs_page_header), - SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), - SPIFFS_DATA_PAGE_SIZE(fs)); - SPIFFS_CHECK_RES(res); - return res; -} - -// rewrites the object index for given object id and replaces the -// data page index to a new page index -static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_ix data_spix, spiffs_page_ix new_data_pix, spiffs_page_ix objix_pix) { - s32_t res; - spiffs_block_ix bix; - int entry; - spiffs_page_ix free_pix; - 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); - free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry); - - // calculate object index span index for given data page span index - spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix); - if (objix_spix == 0) { - // calc index in index header - entry = data_spix; - } else { - // calc entry in index - entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix); - - } - // load index - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); - SPIFFS_CHECK_RES(res); - spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work; - - // be ultra safe, double check header against provided data - if (objix_p_hdr->obj_id != obj_id) { - spiffs_page_delete(fs, free_pix); - return SPIFFS_ERR_CHECK_OBJ_ID_MISM; - } - if (objix_p_hdr->span_ix != objix_spix) { - spiffs_page_delete(fs, free_pix); - return SPIFFS_ERR_CHECK_SPIX_MISM; - } - if ((objix_p_hdr->flags & (SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_INDEX | - SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) != - (SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_DELET)) { - spiffs_page_delete(fs, free_pix); - return SPIFFS_ERR_CHECK_FLAGS_BAD; - } - - // rewrite in mem - if (objix_spix == 0) { - ((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix; - } else { - ((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix; - } - - 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), fs->lu_work); - SPIFFS_CHECK_RES(res); - 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); - res = spiffs_page_delete(fs, objix_pix); - - return res; -} - -// deletes an object just by marking object index header as deleted -static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) { - spiffs_page_ix objix_hdr_pix; - s32_t res; - res = spiffs_obj_lu_find_id_and_span(fs, obj_id, 0, 0, &objix_hdr_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - return SPIFFS_OK; - } - SPIFFS_CHECK_RES(res); - u8_t flags = 0xff; -#if SPIFFS_NO_BLIND_WRITES - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags), - sizeof(flags), &flags); - SPIFFS_CHECK_RES(res); -#endif - flags &= ~SPIFFS_PH_FLAG_IXDELE; - res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT, - 0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags), - sizeof(flags), &flags); - return res; -} - -// validates the given look up entry -static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr, - spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) { - (void)cur_block; - (void)cur_entry; - u8_t delete_page = 0; - s32_t res = SPIFFS_OK; - spiffs_page_ix objix_pix; - spiffs_page_ix ref_pix; - // check validity, take actions - if (((lu_obj_id == SPIFFS_OBJ_ID_DELETED) && (p_hdr->flags & SPIFFS_PH_FLAG_DELET)) || - ((lu_obj_id == SPIFFS_OBJ_ID_FREE) && (p_hdr->flags & SPIFFS_PH_FLAG_USED) == 0)) { - // look up entry deleted / free but used in page header - SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" deleted/free in lu but not on page\n", cur_pix); - *reload_lu = 1; - delete_page = 1; - if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) { - // header says data page - // data page can be removed if not referenced by some object index - res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - // no object with this id, so remove page safely - res = SPIFFS_OK; - } else { - SPIFFS_CHECK_RES(res); - if (ref_pix == cur_pix) { - // data page referenced by object index but deleted in lu - // copy page to new place and re-write the object index to new place - spiffs_page_ix new_pix; - res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); - SPIFFS_CHECK_DBG("LU: FIXUP: data page not found elsewhere, rewriting "_SPIPRIpg" to new page "_SPIPRIpg"\n", cur_pix, new_pix); - SPIFFS_CHECK_RES(res); - *reload_lu = 1; - SPIFFS_CHECK_DBG("LU: FIXUP: "_SPIPRIpg" rewritten to "_SPIPRIpg", affected objix_pix "_SPIPRIpg"\n", cur_pix, new_pix, objix_pix); - res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); - if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { - // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("LU: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res); - res = spiffs_page_delete(fs, new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); - } else { - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix); - } - SPIFFS_CHECK_RES(res); - } - } - } else { - // header says index page - // index page can be removed if other index with same obj_id and spanix is found - res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, 0); - if (res == SPIFFS_ERR_NOT_FOUND) { - // no such index page found, check for a data page amongst page headers - // lu cannot be trusted - res = spiffs_obj_lu_find_id_and_span_by_phdr(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, 0); - if (res == SPIFFS_OK) { // ignore other errors - // got a data page also, assume lu corruption only, rewrite to new page - spiffs_page_ix new_pix; - res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); - SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting "_SPIPRIpg" to new page "_SPIPRIpg"\n", cur_pix, new_pix); - SPIFFS_CHECK_RES(res); - *reload_lu = 1; - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); - } - } else { - SPIFFS_CHECK_RES(res); - } - } - } - if (lu_obj_id != SPIFFS_OBJ_ID_FREE && lu_obj_id != SPIFFS_OBJ_ID_DELETED) { - // look up entry used - if ((p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG) != (lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG)) { - SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" differ in obj_id lu:"_SPIPRIid" ph:"_SPIPRIid"\n", cur_pix, lu_obj_id, p_hdr->obj_id); - delete_page = 1; - if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0 || - (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) || - (p_hdr->flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE)) == 0) { - // page deleted or not finalized, just remove it - } else { - if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) { - // if data page, check for reference to this page - res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - // no object with this id, so remove page safely - res = SPIFFS_OK; - } else { - SPIFFS_CHECK_RES(res); - // if found, rewrite page with object id, update index, and delete current - if (ref_pix == cur_pix) { - spiffs_page_ix new_pix; - res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); - if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { - // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("LU: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res); - res = spiffs_page_delete(fs, new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); - *reload_lu = 1; - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); - } - SPIFFS_CHECK_RES(res); - } - } - } else { - // else if index, check for other pages with both obj_id's and spanix - spiffs_page_ix objix_pix_lu, objix_pix_ph; - // see if other object index page exists for lookup obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_lu); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - objix_pix_lu = 0; - } - SPIFFS_CHECK_RES(res); - // see if other object index exists for page header obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_ph); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - objix_pix_ph = 0; - } - SPIFFS_CHECK_RES(res); - // if both obj_id's found, just delete current - if (objix_pix_ph == 0 || objix_pix_lu == 0) { - // otherwise try finding first corresponding data pages - spiffs_page_ix data_pix_lu, data_pix_ph; - // see if other data page exists for look up obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_lu); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - objix_pix_lu = 0; - } - SPIFFS_CHECK_RES(res); - // see if other data page exists for page header obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_ph); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - objix_pix_ph = 0; - } - SPIFFS_CHECK_RES(res); - - spiffs_page_header new_ph; - new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL); - new_ph.span_ix = p_hdr->span_ix; - spiffs_page_ix new_pix; - if ((objix_pix_lu && data_pix_lu && data_pix_ph && objix_pix_ph == 0) || - (objix_pix_lu == 0 && data_pix_ph && objix_pix_ph == 0)) { - // got a data page for page header obj id - // rewrite as obj_id_ph - new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG; - res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); - SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page "_SPIPRIpg" as "_SPIPRIid" to pix "_SPIPRIpg"\n", cur_pix, new_ph.obj_id, new_pix); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); - SPIFFS_CHECK_RES(res); - *reload_lu = 1; - } else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) || - (objix_pix_ph == 0 && data_pix_lu && objix_pix_lu == 0)) { - // got a data page for look up obj id - // rewrite as obj_id_lu - new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG; - SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page "_SPIPRIpg" as "_SPIPRIid"\n", cur_pix, new_ph.obj_id); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); - res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); - SPIFFS_CHECK_RES(res); - *reload_lu = 1; - } else { - // cannot safely do anything - SPIFFS_CHECK_DBG("LU: FIXUP: nothing to do, just delete\n"); - } - } - } - } - } else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) || - ((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) { - SPIFFS_CHECK_DBG("LU: "_SPIPRIpg" lu/page index marking differ\n", cur_pix); - spiffs_page_ix data_pix, objix_pix_d; - // see if other data page exists for given obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - data_pix = 0; - } - SPIFFS_CHECK_RES(res); - // see if other object index exists for given obj id and span index - res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix_d); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - objix_pix_d = 0; - } - SPIFFS_CHECK_RES(res); - - delete_page = 1; - // if other data page exists and object index exists, just delete page - if (data_pix && objix_pix_d) { - SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n"); - } else - // if only data page exists, make this page index - if (data_pix && objix_pix_d == 0) { - SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n"); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix); - spiffs_page_header new_ph; - spiffs_page_ix new_pix; - new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX); - new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG; - new_ph.span_ix = p_hdr->span_ix; - res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header), - SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), - SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header)); - SPIFFS_CHECK_RES(res); - } else - // if only index exists, make data page - if (data_pix == 0 && objix_pix_d) { - SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n"); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix); - spiffs_page_header new_ph; - spiffs_page_ix new_pix; - new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL); - new_ph.obj_id = lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; - new_ph.span_ix = p_hdr->span_ix; - res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header), - SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), - SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header)); - SPIFFS_CHECK_RES(res); - } else { - // if nothing exists, we cannot safely make a decision - delete - } - } - else if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0) { - SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" busy in lu but deleted on page\n", cur_pix); - delete_page = 1; - } else if ((p_hdr->flags & SPIFFS_PH_FLAG_FINAL)) { - SPIFFS_CHECK_DBG("LU: pix "_SPIPRIpg" busy but not final\n", cur_pix); - // page can be removed if not referenced by object index - *reload_lu = 1; - res = spiffs_object_get_data_page_index_reference(fs, lu_obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - // no object with this id, so remove page safely - res = SPIFFS_OK; - delete_page = 1; - } else { - SPIFFS_CHECK_RES(res); - if (ref_pix != cur_pix) { - SPIFFS_CHECK_DBG("LU: FIXUP: other finalized page is referred, just delete\n"); - delete_page = 1; - } else { - // page referenced by object index but not final - // just finalize - SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n"); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); - u8_t flags = 0xff; -#if SPIFFS_NO_BLIND_WRITES - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags), - sizeof(flags), &flags); - SPIFFS_CHECK_RES(res); -#endif - flags &= ~SPIFFS_PH_FLAG_FINAL; - res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags), - sizeof(flags), &flags); - } - } - } - } - - if (delete_page) { - SPIFFS_CHECK_DBG("LU: FIXUP: deleting page "_SPIPRIpg"\n", cur_pix); - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - } - - return res; -} - -static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry, - const void *user_const_p, void *user_var_p) { - (void)user_const_p; - (void)user_var_p; - s32_t res = SPIFFS_OK; - spiffs_page_header p_hdr; - spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry); - - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, - (cur_block * 256)/fs->block_count, 0); - - // load header - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - - int reload_lu = 0; - - res = spiffs_lookup_check_validate(fs, obj_id, &p_hdr, cur_pix, cur_block, cur_entry, &reload_lu); - SPIFFS_CHECK_RES(res); - - if (res == SPIFFS_OK) { - return reload_lu ? SPIFFS_VIS_COUNTINUE_RELOAD : SPIFFS_VIS_COUNTINUE; - } - return res; -} - - -// Scans all object look up. For each entry, corresponding page header is checked for validity. -// If an object index header page is found, this is also checked -s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) { - (void)check_all_objects; - s32_t res = SPIFFS_OK; - - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0); - - res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0); - - if (res == SPIFFS_VIS_END) { - res = SPIFFS_OK; - } - - if (res != SPIFFS_OK) { - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0); - } - - CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0); - - return res; -} - -//--------------------------------------- -// Page consistency - -// Scans all pages (except lu pages), reserves 4 bits in working memory for each page -// bit 0: 0 == FREE|DELETED, 1 == USED -// bit 1: 0 == UNREFERENCED, 1 == REFERENCED -// bit 2: 0 == NOT_INDEX, 1 == INDEX -// bit 3: unused -// A consistent file system will have only pages being -// * x000 free, unreferenced, not index -// * x011 used, referenced only once, not index -// * x101 used, unreferenced, index -// The working memory might not fit all pages so several scans might be needed -static s32_t spiffs_page_consistency_check_i(spiffs *fs) { - const u32_t bits = 4; - const spiffs_page_ix pages_per_scan = SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8 / bits; - - s32_t res = SPIFFS_OK; - spiffs_page_ix pix_offset = 0; - - // for each range of pages fitting into work memory - while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) { - // set this flag to abort all checks and rescan the page range - u8_t restart = 0; - memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); - - spiffs_block_ix cur_block = 0; - // build consistency bitmap for id range traversing all blocks - while (!restart && cur_block < fs->block_count) { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, - (pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) + - ((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count), - 0); - // traverse each page except for lookup pages - spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block; - while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) { - //if ((cur_pix & 0xff) == 0) - // SPIFFS_CHECK_DBG("PA: processing pix "_SPIPRIpg", block "_SPIPRIbl" of pix "_SPIPRIpg", block "_SPIPRIbl"\n", - // cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count); - - // read header - spiffs_page_header p_hdr; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - - u8_t within_range = (cur_pix >= pix_offset && cur_pix < pix_offset + pages_per_scan); - const u32_t pix_byte_ix = (cur_pix - pix_offset) / (8/bits); - const u8_t pix_bit_ix = (cur_pix & ((8/bits)-1)) * bits; - - if (within_range && - (p_hdr.flags & SPIFFS_PH_FLAG_DELET) && (p_hdr.flags & SPIFFS_PH_FLAG_USED) == 0) { - // used - fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 0)); - } - if ((p_hdr.flags & SPIFFS_PH_FLAG_DELET) && - (p_hdr.flags & SPIFFS_PH_FLAG_IXDELE) && - (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) == 0) { - // found non-deleted index - if (within_range) { - fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 2)); - } - - // load non-deleted index - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); - SPIFFS_CHECK_RES(res); - - // traverse index for referenced pages - spiffs_page_ix *object_page_index; - spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work; - - int entries; - int i; - spiffs_span_ix data_spix_offset; - if (p_hdr.span_ix == 0) { - // object header page index - entries = SPIFFS_OBJ_HDR_IX_LEN(fs); - data_spix_offset = 0; - object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header)); - } else { - // object page index - entries = SPIFFS_OBJ_IX_LEN(fs); - data_spix_offset = SPIFFS_OBJ_HDR_IX_LEN(fs) + SPIFFS_OBJ_IX_LEN(fs) * (p_hdr.span_ix - 1); - object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix)); - } - - // for all entries in index - for (i = 0; !restart && i < entries; i++) { - spiffs_page_ix rpix = object_page_index[i]; - u8_t rpix_within_range = rpix >= pix_offset && rpix < pix_offset + pages_per_scan; - - if ((rpix != (spiffs_page_ix)-1 && rpix > SPIFFS_MAX_PAGES(fs)) - || (rpix_within_range && SPIFFS_IS_LOOKUP_PAGE(fs, rpix))) { - - // bad reference - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg"x bad pix / LU referenced from page "_SPIPRIpg"\n", - rpix, cur_pix); - // check for data page elsewhere - spiffs_page_ix data_pix; - res = spiffs_obj_lu_find_id_and_span(fs, objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, - data_spix_offset + i, 0, &data_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - data_pix = 0; - } - SPIFFS_CHECK_RES(res); - if (data_pix == 0) { - // if not, allocate free page - spiffs_page_header new_ph; - new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL); - new_ph.obj_id = objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; - new_ph.span_ix = data_spix_offset + i; - res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &data_pix); - SPIFFS_CHECK_RES(res); - SPIFFS_CHECK_DBG("PA: FIXUP: found no existing data page, created new @ "_SPIPRIpg"\n", data_pix); - } - // remap index - SPIFFS_CHECK_DBG("PA: FIXUP: rewriting index pix "_SPIPRIpg"\n", cur_pix); - res = spiffs_rewrite_index(fs, objix_p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, - data_spix_offset + i, data_pix, cur_pix); - if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { - // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend - delete object\n", res); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0); - // delete file - res = spiffs_page_delete(fs, cur_pix); - } else { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix); - } - SPIFFS_CHECK_RES(res); - restart = 1; - - } else if (rpix_within_range) { - - // valid reference - // read referenced page header - spiffs_page_header rp_hdr; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr); - SPIFFS_CHECK_RES(res); - - // cross reference page header check - if (rp_hdr.obj_id != (p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) || - rp_hdr.span_ix != data_spix_offset + i || - (rp_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) != - (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX)) { - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" has inconsistent page header ix id/span:"_SPIPRIid"/"_SPIPRIsp", ref id/span:"_SPIPRIid"/"_SPIPRIsp" flags:"_SPIPRIfl"\n", - rpix, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, data_spix_offset + i, - rp_hdr.obj_id, rp_hdr.span_ix, rp_hdr.flags); - // try finding correct page - spiffs_page_ix data_pix; - res = spiffs_obj_lu_find_id_and_span(fs, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, - data_spix_offset + i, rpix, &data_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - data_pix = 0; - } - SPIFFS_CHECK_RES(res); - if (data_pix == 0) { - // not found, this index is badly borked - SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id "_SPIPRIid"\n", p_hdr.obj_id); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); - res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); - SPIFFS_CHECK_RES(res); - break; - } else { - // found it, so rewrite index - SPIFFS_CHECK_DBG("PA: FIXUP: found correct data pix "_SPIPRIpg", rewrite ix pix "_SPIPRIpg" id "_SPIPRIid"\n", - data_pix, cur_pix, p_hdr.obj_id); - res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix); - if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { - // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); - res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); - } else { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); - } - SPIFFS_CHECK_RES(res); - restart = 1; - } - } - else { - // mark rpix as referenced - const u32_t rpix_byte_ix = (rpix - pix_offset) / (8/bits); - const u8_t rpix_bit_ix = (rpix & ((8/bits)-1)) * bits; - if (fs->work[rpix_byte_ix] & (1<<(rpix_bit_ix + 1))) { - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" multiple referenced from page "_SPIPRIpg"\n", - rpix, cur_pix); - // Here, we should have fixed all broken references - getting this means there - // must be multiple files with same object id. Only solution is to delete - // the object which is referring to this page - SPIFFS_CHECK_DBG("PA: FIXUP: removing object "_SPIPRIid" and page "_SPIPRIpg"\n", - p_hdr.obj_id, cur_pix); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); - res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); - SPIFFS_CHECK_RES(res); - // extra precaution, delete this page also - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - restart = 1; - } - fs->work[rpix_byte_ix] |= (1<<(rpix_bit_ix + 1)); - } - } - } // for all index entries - } // found index - - // next page - cur_pix++; - } - // next block - cur_block++; - } - // check consistency bitmap - if (!restart) { - spiffs_page_ix objix_pix; - spiffs_page_ix rpix; - - u32_t byte_ix; - u8_t bit_ix; - for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) { - for (bit_ix = 0; !restart && bit_ix < 8/bits; bit_ix ++) { - u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7; - spiffs_page_ix cur_pix = pix_offset + byte_ix * (8/bits) + bit_ix; - - // 000 ok - free, unreferenced, not index - - if (bitmask == 0x1) { - - // 001 - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" USED, UNREFERENCED, not index\n", cur_pix); - - u8_t rewrite_ix_to_this = 0; - u8_t delete_page = 0; - // check corresponding object index entry - spiffs_page_header p_hdr; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - - res = spiffs_object_get_data_page_index_reference(fs, p_hdr.obj_id, p_hdr.span_ix, - &rpix, &objix_pix); - if (res == SPIFFS_OK) { - if (((rpix == (spiffs_page_ix)-1 || rpix > SPIFFS_MAX_PAGES(fs)) || (SPIFFS_IS_LOOKUP_PAGE(fs, rpix)))) { - // pointing to a bad page altogether, rewrite index to this - rewrite_ix_to_this = 1; - SPIFFS_CHECK_DBG("PA: corresponding ref is bad: "_SPIPRIpg", rewrite to this "_SPIPRIpg"\n", rpix, cur_pix); - } else { - // pointing to something else, check what - spiffs_page_header rp_hdr; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr); - SPIFFS_CHECK_RES(res); - if (((p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) == rp_hdr.obj_id) && - ((rp_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL)) == - (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET))) { - // pointing to something else valid, just delete this page then - SPIFFS_CHECK_DBG("PA: corresponding ref is good but different: "_SPIPRIpg", delete this "_SPIPRIpg"\n", rpix, cur_pix); - delete_page = 1; - } else { - // pointing to something weird, update index to point to this page instead - if (rpix != cur_pix) { - SPIFFS_CHECK_DBG("PA: corresponding ref is weird: "_SPIPRIpg" %s%s%s%s, rewrite this "_SPIPRIpg"\n", rpix, - (rp_hdr.flags & SPIFFS_PH_FLAG_INDEX) ? "" : "INDEX ", - (rp_hdr.flags & SPIFFS_PH_FLAG_DELET) ? "" : "DELETED ", - (rp_hdr.flags & SPIFFS_PH_FLAG_USED) ? "NOTUSED " : "", - (rp_hdr.flags & SPIFFS_PH_FLAG_FINAL) ? "NOTFINAL " : "", - cur_pix); - rewrite_ix_to_this = 1; - } else { - // should not happen, destined for fubar - } - } - } - } else if (res == SPIFFS_ERR_NOT_FOUND) { - SPIFFS_CHECK_DBG("PA: corresponding ref not found, delete "_SPIPRIpg"\n", cur_pix); - delete_page = 1; - res = SPIFFS_OK; - } - - if (rewrite_ix_to_this) { - // if pointing to invalid page, redirect index to this page - SPIFFS_CHECK_DBG("PA: FIXUP: rewrite index id "_SPIPRIid" data spix "_SPIPRIsp" to point to this pix: "_SPIPRIpg"\n", - p_hdr.obj_id, p_hdr.span_ix, cur_pix); - res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix); - if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { - // index bad also, cannot mend this file - SPIFFS_CHECK_DBG("PA: FIXUP: index bad "_SPIPRIi", cannot mend!\n", res); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); - } else { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); - } - SPIFFS_CHECK_RES(res); - restart = 1; - continue; - } else if (delete_page) { - SPIFFS_CHECK_DBG("PA: FIXUP: deleting page "_SPIPRIpg"\n", cur_pix); - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); - res = spiffs_page_delete(fs, cur_pix); - } - SPIFFS_CHECK_RES(res); - } - if (bitmask == 0x2) { - - // 010 - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, REFERENCED, not index\n", cur_pix); - - // no op, this should be taken care of when checking valid references - } - - // 011 ok - busy, referenced, not index - - if (bitmask == 0x4) { - - // 100 - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, unreferenced, INDEX\n", cur_pix); - - // this should never happen, major fubar - } - - // 101 ok - busy, unreferenced, index - - if (bitmask == 0x6) { - - // 110 - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" FREE, REFERENCED, INDEX\n", cur_pix); - - // no op, this should be taken care of when checking valid references - } - if (bitmask == 0x7) { - - // 111 - SPIFFS_CHECK_DBG("PA: pix "_SPIPRIpg" USED, REFERENCED, INDEX\n", cur_pix); - - // no op, this should be taken care of when checking valid references - } - } - } - } - - SPIFFS_CHECK_DBG("PA: processed "_SPIPRIpg", restart "_SPIPRIi"\n", pix_offset, restart); - // next page range - if (!restart) { - pix_offset += pages_per_scan; - } - } // while page range not reached end - return res; -} - -// Checks consistency amongst all pages and fixes irregularities -s32_t spiffs_page_consistency_check(spiffs *fs) { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0); - s32_t res = spiffs_page_consistency_check_i(fs); - if (res != SPIFFS_OK) { - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0); - } - CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0); - return res; -} - -//--------------------------------------- -// Object index consistency - -// searches for given object id in temporary object id index, -// returns the index or -1 -static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) { - u32_t i; - spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work; - obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG; - for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) { - if ((obj_table[i] & ~SPIFFS_OBJ_ID_IX_FLAG) == obj_id) { - return i; - } - } - return -1; -} - -static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, - int cur_entry, const void *user_const_p, void *user_var_p) { - (void)user_const_p; - s32_t res_c = SPIFFS_VIS_COUNTINUE; - s32_t res = SPIFFS_OK; - u32_t *log_ix = (u32_t*)user_var_p; - spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work; - - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, - (cur_block * 256)/fs->block_count, 0); - - if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) { - spiffs_page_header p_hdr; - spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry); - - // load header - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - - if (p_hdr.span_ix == 0 && - (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) == - (SPIFFS_PH_FLAG_DELET)) { - SPIFFS_CHECK_DBG("IX: pix "_SPIPRIpg", obj id:"_SPIPRIid" spix:"_SPIPRIsp" header not fully deleted - deleting\n", - cur_pix, obj_id, p_hdr.span_ix); - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id); - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - return res_c; - } - - if ((p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) == - (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) { - return res_c; - } - - if (p_hdr.span_ix == 0) { - // objix header page, register objid as reachable - int r = spiffs_object_index_search(fs, obj_id); - if (r == -1) { - // not registered, do it - obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; - (*log_ix)++; - if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) { - *log_ix = 0; - } - } - } else { // span index - // objix page, see if header can be found - int r = spiffs_object_index_search(fs, obj_id); - u8_t delete = 0; - if (r == -1) { - // not in temporary index, try finding it - spiffs_page_ix objix_hdr_pix; - res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &objix_hdr_pix); - res_c = SPIFFS_VIS_COUNTINUE_RELOAD; - if (res == SPIFFS_OK) { - // found, register as reachable - obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; - } else if (res == SPIFFS_ERR_NOT_FOUND) { - // not found, register as unreachable - delete = 1; - obj_table[*log_ix] = obj_id | SPIFFS_OBJ_ID_IX_FLAG; - } else { - SPIFFS_CHECK_RES(res); - } - (*log_ix)++; - if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) { - *log_ix = 0; - } - } else { - // in temporary index, check reachable flag - if ((obj_table[r] & SPIFFS_OBJ_ID_IX_FLAG)) { - // registered as unreachable - delete = 1; - } - } - - if (delete) { - SPIFFS_CHECK_DBG("IX: FIXUP: pix "_SPIPRIpg", obj id:"_SPIPRIid" spix:"_SPIPRIsp" is orphan index - deleting\n", - cur_pix, obj_id, p_hdr.span_ix); - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id); - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - } - } // span index - } // valid object index id - - return res_c; -} - -// Removes orphaned and partially deleted index pages. -// Scans for index pages. When an index page is found, corresponding index header is searched for. -// If no such page exists, the index page cannot be reached as no index header exists and must be -// deleted. -s32_t spiffs_object_index_consistency_check(spiffs *fs) { - s32_t res = SPIFFS_OK; - // impl note: - // fs->work is used for a temporary object index memory, listing found object ids and - // indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit. - // In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate - // a reachable/unreachable object id. - memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); - u32_t obj_id_log_ix = 0; - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0); - res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix, - 0, 0); - if (res == SPIFFS_VIS_END) { - res = SPIFFS_OK; - } - if (res != SPIFFS_OK) { - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0); - } - CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0); - return res; -} - -#endif // !SPIFFS_READ_ONLY diff --git a/src/spiffs/spiffs_config.h b/src/spiffs/spiffs_config.h deleted file mode 100644 index 6a89476..0000000 --- a/src/spiffs/spiffs_config.h +++ /dev/null @@ -1,369 +0,0 @@ -/* - * spiffs_config.h - * - * Created on: Jul 3, 2013 - * Author: petera - */ - -#ifndef SPIFFS_CONFIG_H_ -#define SPIFFS_CONFIG_H_ - -#include - -/* type definitions used in spiffs code */ -typedef int32_t s32_t; -typedef uint32_t u32_t; -typedef int16_t s16_t; -typedef uint16_t u16_t; -typedef int8_t s8_t; -typedef uint8_t u8_t; - -// compile time switches - -// Set generic spiffs debug output call. -#ifndef SPIFFS_DBG -#define SPIFFS_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for garbage collecting. -#ifndef SPIFFS_GC_DBG -#define SPIFFS_GC_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for caching. -#ifndef SPIFFS_CACHE_DBG -#define SPIFFS_CACHE_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for system consistency checks. -#ifndef SPIFFS_CHECK_DBG -#define SPIFFS_CHECK_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif -// Set spiffs debug output call for all api invocations. -#ifndef SPIFFS_API_DBG -#define SPIFFS_API_DBG(_f, ...) //printf(_f, ## __VA_ARGS__) -#endif - - - -// Defines spiffs debug print formatters -// some general signed number -#ifndef _SPIPRIi -#define _SPIPRIi "%d" -#endif -// address -#ifndef _SPIPRIad -#define _SPIPRIad "%08x" -#endif -// block -#ifndef _SPIPRIbl -#define _SPIPRIbl "%04x" -#endif -// page -#ifndef _SPIPRIpg -#define _SPIPRIpg "%04x" -#endif -// span index -#ifndef _SPIPRIsp -#define _SPIPRIsp "%04x" -#endif -// file descriptor -#ifndef _SPIPRIfd -#define _SPIPRIfd "%d" -#endif -// file object id -#ifndef _SPIPRIid -#define _SPIPRIid "%04x" -#endif -// file flags -#ifndef _SPIPRIfl -#define _SPIPRIfl "%02x" -#endif - - -// Enable/disable API functions to determine exact number of bytes -// for filedescriptor and cache buffers. Once decided for a configuration, -// this can be disabled to reduce flash. -#ifndef SPIFFS_BUFFER_HELP -#define SPIFFS_BUFFER_HELP 0 -#endif - -// Enables/disable memory read caching of nucleus file system operations. -// If enabled, memory area must be provided for cache in SPIFFS_mount. -#ifndef SPIFFS_CACHE -#define SPIFFS_CACHE 1 -#endif -#if SPIFFS_CACHE -// Enables memory write caching for file descriptors in hydrogen -#ifndef SPIFFS_CACHE_WR -#define SPIFFS_CACHE_WR 1 -#endif - -// Enable/disable statistics on caching. Debug/test purpose only. -#ifndef SPIFFS_CACHE_STATS -#define SPIFFS_CACHE_STATS 1 -#endif -#endif - -// Always check header of each accessed page to ensure consistent state. -// If enabled it will increase number of reads, will increase flash. -#ifndef SPIFFS_PAGE_CHECK -#define SPIFFS_PAGE_CHECK 1 -#endif - -// Define maximum number of gc runs to perform to reach desired free pages. -#ifndef SPIFFS_GC_MAX_RUNS -#define SPIFFS_GC_MAX_RUNS 5 -#endif - -// Enable/disable statistics on gc. Debug/test purpose only. -#ifndef SPIFFS_GC_STATS -#define SPIFFS_GC_STATS 1 -#endif - -// Garbage collecting examines all pages in a block which and sums up -// to a block score. Deleted pages normally gives positive score and -// used pages normally gives a negative score (as these must be moved). -// To have a fair wear-leveling, the erase age is also included in score, -// whose factor normally is the most positive. -// The larger the score, the more likely it is that the block will -// picked for garbage collection. - -// Garbage collecting heuristics - weight used for deleted pages. -#ifndef SPIFFS_GC_HEUR_W_DELET -#define SPIFFS_GC_HEUR_W_DELET (5) -#endif -// Garbage collecting heuristics - weight used for used pages. -#ifndef SPIFFS_GC_HEUR_W_USED -#define SPIFFS_GC_HEUR_W_USED (-1) -#endif -// Garbage collecting heuristics - weight used for time between -// last erased and erase of this block. -#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE -#define SPIFFS_GC_HEUR_W_ERASE_AGE (50) -#endif - -// Object name maximum length. Note that this length include the -// zero-termination character, meaning maximum string of characters -// can at most be SPIFFS_OBJ_NAME_LEN - 1. -#ifndef SPIFFS_OBJ_NAME_LEN -#define SPIFFS_OBJ_NAME_LEN (32) -#endif - -// Maximum length of the metadata associated with an object. -// Setting to non-zero value enables metadata-related API but also -// changes the on-disk format, so the change is not backward-compatible. -// -// Do note: the meta length must never exceed -// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64) -// -// This is derived from following: -// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) + -// spiffs_object_ix_header fields + at least some LUT entries) -#ifndef SPIFFS_OBJ_META_LEN -#define SPIFFS_OBJ_META_LEN (0) -#endif - -// Size of buffer allocated on stack used when copying data. -// Lower value generates more read/writes. No meaning having it bigger -// than logical page size. -#ifndef SPIFFS_COPY_BUFFER_STACK -#define SPIFFS_COPY_BUFFER_STACK (64) -#endif - -// Enable this to have an identifiable spiffs filesystem. This will look for -// a magic in all sectors to determine if this is a valid spiffs system or -// not on mount point. If not, SPIFFS_format must be called prior to mounting -// again. -#ifndef SPIFFS_USE_MAGIC -#define SPIFFS_USE_MAGIC (1) -#endif - -#if SPIFFS_USE_MAGIC -// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is -// enabled, the magic will also be dependent on the length of the filesystem. -// For example, a filesystem configured and formatted for 4 megabytes will not -// be accepted for mounting with a configuration defining the filesystem as 2 -// megabytes. -#ifndef SPIFFS_USE_MAGIC_LENGTH -#define SPIFFS_USE_MAGIC_LENGTH (0) -#endif -#endif - -// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level -// These should be defined on a multithreaded system - -// define this to enter a mutex if you're running on a multithreaded system -#ifndef SPIFFS_LOCK -#define SPIFFS_LOCK(fs) -#endif -// define this to exit a mutex if you're running on a multithreaded system -#ifndef SPIFFS_UNLOCK -#define SPIFFS_UNLOCK(fs) -#endif - -// Enable if only one spiffs instance with constant configuration will exist -// on the target. This will reduce calculations, flash and memory accesses. -// Parts of configuration must be defined below instead of at time of mount. -#ifndef SPIFFS_SINGLETON -#define SPIFFS_SINGLETON 0 -#endif - -#if SPIFFS_SINGLETON -// Instead of giving parameters in config struct, singleton build must -// give parameters in defines below. -#ifndef SPIFFS_CFG_PHYS_SZ -#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2) -#endif -#ifndef SPIFFS_CFG_PHYS_ERASE_SZ -#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536) -#endif -#ifndef SPIFFS_CFG_PHYS_ADDR -#define SPIFFS_CFG_PHYS_ADDR(ignore) (0) -#endif -#ifndef SPIFFS_CFG_LOG_PAGE_SZ -#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256) -#endif -#ifndef SPIFFS_CFG_LOG_BLOCK_SZ -#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536) -#endif -#endif - -// Enable this if your target needs aligned data for index tables -#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES -#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1 -#endif - -// Enable this if you want the HAL callbacks to be called with the spiffs struct -#ifndef SPIFFS_HAL_CALLBACK_EXTRA -#define SPIFFS_HAL_CALLBACK_EXTRA 0 -#endif - -// Enable this if you want to add an integer offset to all file handles -// (spiffs_file). This is useful if running multiple instances of spiffs on -// same target, in order to recognise to what spiffs instance a file handle -// belongs. -// NB: This adds config field fh_ix_offset in the configuration struct when -// mounting, which must be defined. -#ifndef SPIFFS_FILEHDL_OFFSET -#define SPIFFS_FILEHDL_OFFSET 0 -#endif - -// Enable this to compile a read only version of spiffs. -// This will reduce binary size of spiffs. All code comprising modification -// of the file system will not be compiled. Some config will be ignored. -// HAL functions for erasing and writing to spi-flash may be null. Cache -// can be disabled for even further binary size reduction (and ram savings). -// Functions modifying the fs will return SPIFFS_ERR_RO_NOT_IMPL. -// If the file system cannot be mounted due to aborted erase operation and -// SPIFFS_USE_MAGIC is enabled, SPIFFS_ERR_RO_ABORTED_OPERATION will be -// returned. -// Might be useful for e.g. bootloaders and such. -#ifndef SPIFFS_READ_ONLY -#define SPIFFS_READ_ONLY 0 -#endif - -// Enable this to add a temporal file cache using the fd buffer. -// The effects of the cache is that SPIFFS_open will find the file faster in -// certain cases. It will make it a lot easier for spiffs to find files -// opened frequently, reducing number of readings from the spi flash for -// finding those files. -// This will grow each fd by 6 bytes. If your files are opened in patterns -// with a degree of temporal locality, the system is optimized. -// Examples can be letting spiffs serve web content, where one file is the css. -// The css is accessed for each html file that is opened, meaning it is -// accessed almost every second time a file is opened. Another example could be -// a log file that is often opened, written, and closed. -// The size of the cache is number of given file descriptors, as it piggybacks -// on the fd update mechanism. The cache lives in the closed file descriptors. -// When closed, the fd know the whereabouts of the file. Instead of forgetting -// this, the temporal cache will keep handling updates to that file even if the -// fd is closed. If the file is opened again, the location of the file is found -// directly. If all available descriptors become opened, all cache memory is -// lost. -#ifndef SPIFFS_TEMPORAL_FD_CACHE -#define SPIFFS_TEMPORAL_FD_CACHE 1 -#endif - -// Temporal file cache hit score. Each time a file is opened, all cached files -// will lose one point. If the opened file is found in cache, that entry will -// gain SPIFFS_TEMPORAL_CACHE_HIT_SCORE points. One can experiment with this -// value for the specific access patterns of the application. However, it must -// be between 1 (no gain for hitting a cached entry often) and 255. -#ifndef SPIFFS_TEMPORAL_CACHE_HIT_SCORE -#define SPIFFS_TEMPORAL_CACHE_HIT_SCORE 4 -#endif - -// Enable to be able to map object indices to memory. -// This allows for faster and more deterministic reading if cases of reading -// large files and when changing file offset by seeking around a lot. -// When mapping a file's index, the file system will be scanned for index pages -// and the info will be put in memory provided by user. When reading, the -// memory map can be looked up instead of searching for index pages on the -// medium. This way, user can trade memory against performance. -// Whole, parts of, or future parts not being written yet can be mapped. The -// memory array will be owned by spiffs and updated accordingly during garbage -// collecting or when modifying the indices. The latter is invoked by when the -// file is modified in some way. The index buffer is tied to the file -// descriptor. -#ifndef SPIFFS_IX_MAP -#define SPIFFS_IX_MAP 1 -#endif - -// By default SPIFFS in some cases relies on the property of NOR flash that bits -// cannot be set from 0 to 1 by writing and that controllers will ignore such -// bit changes. This results in fewer reads as SPIFFS can in some cases perform -// blind writes, with all bits set to 1 and only those it needs reset set to 0. -// Most of the chips and controllers allow this behavior, so the default is to -// use this technique. If your controller is one of the rare ones that don't, -// turn this option on and SPIFFS will perform a read-modify-write instead. -#ifndef SPIFFS_NO_BLIND_WRITES -#define SPIFFS_NO_BLIND_WRITES 0 -#endif - -// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function -// in the api. This function will visualize all filesystem using given printf -// function. -#ifndef SPIFFS_TEST_VISUALISATION -#define SPIFFS_TEST_VISUALISATION 1 -#endif -#if SPIFFS_TEST_VISUALISATION -#ifndef spiffs_printf -#define spiffs_printf(...) printf(__VA_ARGS__) -#endif -// spiffs_printf argument for a free page -#ifndef SPIFFS_TEST_VIS_FREE_STR -#define SPIFFS_TEST_VIS_FREE_STR "_" -#endif -// spiffs_printf argument for a deleted page -#ifndef SPIFFS_TEST_VIS_DELE_STR -#define SPIFFS_TEST_VIS_DELE_STR "/" -#endif -// spiffs_printf argument for an index page for given object id -#ifndef SPIFFS_TEST_VIS_INDX_STR -#define SPIFFS_TEST_VIS_INDX_STR(id) "i" -#endif -// spiffs_printf argument for a data page for given object id -#ifndef SPIFFS_TEST_VIS_DATA_STR -#define SPIFFS_TEST_VIS_DATA_STR(id) "d" -#endif -#endif - -// Types depending on configuration such as the amount of flash bytes -// given to spiffs file system in total (spiffs_file_system_size), -// the logical block size (log_block_size), and the logical page size -// (log_page_size) - -// Block index type. Make sure the size of this type can hold -// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size -typedef u16_t spiffs_block_ix; -// Page index type. Make sure the size of this type can hold -// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size -typedef u16_t spiffs_page_ix; -// Object id type - most significant bit is reserved for index flag. Make sure the -// size of this type can hold the highest object id on a full system, -// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2 -typedef u16_t spiffs_obj_id; -// Object span index type. Make sure the size of this type can -// hold the largest possible span index on the system - -// i.e. (spiffs_file_system_size / log_page_size) - 1 -typedef u16_t spiffs_span_ix; - -#endif /* SPIFFS_CONFIG_H_ */ diff --git a/src/spiffs/spiffs_gc.c b/src/spiffs/spiffs_gc.c deleted file mode 100644 index db1af4c..0000000 --- a/src/spiffs/spiffs_gc.c +++ /dev/null @@ -1,606 +0,0 @@ -#include "spiffs.h" -#include "spiffs_nucleus.h" - -#if !SPIFFS_READ_ONLY - -// Erases a logical block and updates the erase counter. -// If cache is enabled, all pages that might be cached in this block -// is dropped. -static s32_t spiffs_gc_erase_block( - spiffs *fs, - spiffs_block_ix bix) { - s32_t res; - - SPIFFS_GC_DBG("gc: erase block "_SPIPRIbl"\n", bix); - res = spiffs_erase_block(fs, bix); - SPIFFS_CHECK_RES(res); - -#if SPIFFS_CACHE - { - u32_t i; - for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) { - spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i); - } - } -#endif - return res; -} - -// Searches for blocks where all entries are deleted - if one is found, -// the block is erased. Compared to the non-quick gc, the quick one ensures -// that no updates are needed on existing objects on pages that are erased. -s32_t spiffs_gc_quick( - spiffs *fs, u16_t max_free_pages) { - s32_t res = SPIFFS_OK; - u32_t blocks = fs->block_count; - spiffs_block_ix cur_block = 0; - u32_t cur_block_addr = 0; - int cur_entry = 0; - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - - SPIFFS_GC_DBG("gc_quick: running\n"); -#if SPIFFS_GC_STATS - fs->stats_gc_runs++; -#endif - - int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - - // find fully deleted blocks - // check each block - while (res == SPIFFS_OK && blocks--) { - u16_t deleted_pages_in_block = 0; - u16_t free_pages_in_block = 0; - - int obj_lookup_page = 0; - // 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 && - cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) { - spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset]; - if (obj_id == SPIFFS_OBJ_ID_DELETED) { - deleted_pages_in_block++; - } else if (obj_id == SPIFFS_OBJ_ID_FREE) { - // kill scan, go for next block - free_pages_in_block++; - if (free_pages_in_block > max_free_pages) { - obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs); - res = 1; // kill object lu loop - break; - } - } else { - // kill scan, go for next block - obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs); - res = 1; // kill object lu loop - break; - } - cur_entry++; - } // per entry - obj_lookup_page++; - } // per object lookup page - if (res == 1) res = SPIFFS_OK; - - if (res == SPIFFS_OK && - deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs) && - free_pages_in_block <= max_free_pages) { - // found a fully deleted block - fs->stats_p_deleted -= deleted_pages_in_block; - res = spiffs_gc_erase_block(fs, cur_block); - return res; - } - - cur_entry = 0; - cur_block++; - cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs); - } // per block - - if (res == SPIFFS_OK) { - res = SPIFFS_ERR_NO_DELETED_BLOCKS; - } - return res; -} - -// Checks if garbage collecting is necessary. If so a candidate block is found, -// cleansed and erased -s32_t spiffs_gc_check( - spiffs *fs, - u32_t len) { - s32_t res; - s32_t free_pages = - (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count-2) - - fs->stats_p_allocated - fs->stats_p_deleted; - int tries = 0; - - if (fs->free_blocks > 3 && - (s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) { - return SPIFFS_OK; - } - - u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs); -// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) { -// SPIFFS_GC_DBG("gc: full freeblk:"_SPIPRIi" needed:"_SPIPRIi" free:"_SPIPRIi" dele:"_SPIPRIi"\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); -// return SPIFFS_ERR_FULL; -// } - if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) { - SPIFFS_GC_DBG("gc_check: full freeblk:"_SPIPRIi" needed:"_SPIPRIi" free:"_SPIPRIi" dele:"_SPIPRIi"\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); - return SPIFFS_ERR_FULL; - } - - do { - SPIFFS_GC_DBG("\ngc_check #"_SPIPRIi": run gc free_blocks:"_SPIPRIi" pfree:"_SPIPRIi" pallo:"_SPIPRIi" pdele:"_SPIPRIi" ["_SPIPRIi"] len:"_SPIPRIi" of "_SPIPRIi"\n", - tries, - fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted), - len, (u32_t)(free_pages*SPIFFS_DATA_PAGE_SIZE(fs))); - - spiffs_block_ix *cands; - int count; - spiffs_block_ix cand; - s32_t prev_free_pages = free_pages; - // if the fs is crammed, ignore block age when selecting candidate - kind of a bad state - res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0); - SPIFFS_CHECK_RES(res); - if (count == 0) { - SPIFFS_GC_DBG("gc_check: no candidates, return\n"); - return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL; - } -#if SPIFFS_GC_STATS - fs->stats_gc_runs++; -#endif - cand = cands[0]; - fs->cleaning = 1; - //SPIFFS_GC_DBG("gcing: cleaning block "_SPIPRIi"\n", cand); - res = spiffs_gc_clean(fs, cand); - fs->cleaning = 0; - if (res < 0) { - SPIFFS_GC_DBG("gc_check: cleaning block "_SPIPRIi", result "_SPIPRIi"\n", cand, res); - } else { - SPIFFS_GC_DBG("gc_check: cleaning block "_SPIPRIi", result "_SPIPRIi"\n", cand, res); - } - SPIFFS_CHECK_RES(res); - - res = spiffs_gc_erase_page_stats(fs, cand); - SPIFFS_CHECK_RES(res); - - res = spiffs_gc_erase_block(fs, cand); - SPIFFS_CHECK_RES(res); - - free_pages = - (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2) - - fs->stats_p_allocated - fs->stats_p_deleted; - - if (prev_free_pages <= 0 && prev_free_pages == free_pages) { - // abort early to reduce wear, at least tried once - SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n"); - break; - } - - } while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 || - (s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs))); - - free_pages = - (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2) - - fs->stats_p_allocated - fs->stats_p_deleted; - if ((s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) { - res = SPIFFS_ERR_FULL; - } - - SPIFFS_GC_DBG("gc_check: finished, "_SPIPRIi" dirty, blocks "_SPIPRIi" free, "_SPIPRIi" pages free, "_SPIPRIi" tries, res "_SPIPRIi"\n", - fs->stats_p_allocated + fs->stats_p_deleted, - fs->free_blocks, free_pages, tries, res); - - return res; -} - -// Updates page statistics for a block that is about to be erased -s32_t spiffs_gc_erase_page_stats( - spiffs *fs, - spiffs_block_ix bix) { - s32_t res = SPIFFS_OK; - int obj_lookup_page = 0; - int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - int cur_entry = 0; - u32_t dele = 0; - u32_t allo = 0; - - // 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, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + 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 && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) { - spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset]; - if (obj_id == SPIFFS_OBJ_ID_FREE) { - } else if (obj_id == SPIFFS_OBJ_ID_DELETED) { - dele++; - } else { - allo++; - } - cur_entry++; - } // per entry - obj_lookup_page++; - } // per object lookup page - SPIFFS_GC_DBG("gc_check: wipe pallo:"_SPIPRIi" pdele:"_SPIPRIi"\n", allo, dele); - fs->stats_p_allocated -= allo; - fs->stats_p_deleted -= dele; - return res; -} - -// Finds block candidates to erase -s32_t spiffs_gc_find_candidate( - spiffs *fs, - spiffs_block_ix **block_candidates, - int *candidate_count, - char fs_crammed) { - s32_t res = SPIFFS_OK; - u32_t blocks = fs->block_count; - spiffs_block_ix cur_block = 0; - u32_t cur_block_addr = 0; - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - int cur_entry = 0; - - // using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score - int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t))); - *candidate_count = 0; - memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs)); - - // divide up work area into block indices and scores - spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work; - s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix)); - - // align cand_scores on s32_t boundary - cand_scores = (s32_t*)(((intptr_t)cand_scores + sizeof(intptr_t) - 1) & ~(sizeof(intptr_t) - 1)); - - *block_candidates = cand_blocks; - - int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - - // check each block - while (res == SPIFFS_OK && blocks--) { - u16_t deleted_pages_in_block = 0; - u16_t used_pages_in_block = 0; - - int obj_lookup_page = 0; - // 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 && - cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) { - spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset]; - if (obj_id == SPIFFS_OBJ_ID_FREE) { - // when a free entry is encountered, scan logic ensures that all following entries are free also - res = 1; // kill object lu loop - break; - } else if (obj_id == SPIFFS_OBJ_ID_DELETED) { - deleted_pages_in_block++; - } else { - used_pages_in_block++; - } - cur_entry++; - } // per entry - obj_lookup_page++; - } // per object lookup page - if (res == 1) res = SPIFFS_OK; - - // calculate score and insert into candidate table - // stoneage sort, but probably not so many blocks - if (res == SPIFFS_OK /*&& deleted_pages_in_block > 0*/) { - // read erase count - spiffs_obj_id erase_count; - res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0, - SPIFFS_ERASE_COUNT_PADDR(fs, cur_block), - sizeof(spiffs_obj_id), (u8_t *)&erase_count); - SPIFFS_CHECK_RES(res); - - spiffs_obj_id erase_age; - if (fs->max_erase_count > erase_count) { - erase_age = fs->max_erase_count - erase_count; - } else { - erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count); - } - - s32_t score = - deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET + - used_pages_in_block * SPIFFS_GC_HEUR_W_USED + - erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE); - int cand_ix = 0; - SPIFFS_GC_DBG("gc_check: bix:"_SPIPRIbl" del:"_SPIPRIi" use:"_SPIPRIi" score:"_SPIPRIi"\n", cur_block, deleted_pages_in_block, used_pages_in_block, score); - while (cand_ix < max_candidates) { - if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) { - cand_blocks[cand_ix] = cur_block; - cand_scores[cand_ix] = score; - break; - } else if (cand_scores[cand_ix] < score) { - int reorder_cand_ix = max_candidates - 2; - while (reorder_cand_ix >= cand_ix) { - cand_blocks[reorder_cand_ix + 1] = cand_blocks[reorder_cand_ix]; - cand_scores[reorder_cand_ix + 1] = cand_scores[reorder_cand_ix]; - reorder_cand_ix--; - } - cand_blocks[cand_ix] = cur_block; - cand_scores[cand_ix] = score; - break; - } - cand_ix++; - } - (*candidate_count)++; - } - - cur_entry = 0; - cur_block++; - cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs); - } // per block - - return res; -} - -typedef enum { - FIND_OBJ_DATA, - MOVE_OBJ_DATA, - MOVE_OBJ_IX, - FINISHED -} spiffs_gc_clean_state; - -typedef struct { - spiffs_gc_clean_state state; - spiffs_obj_id cur_obj_id; - spiffs_span_ix cur_objix_spix; - spiffs_page_ix cur_objix_pix; - spiffs_page_ix cur_data_pix; - int stored_scan_entry_index; - u8_t obj_id_found; -} spiffs_gc; - -// Empties given block by moving all data into free pages of another block -// Strategy: -// loop: -// scan object lookup for object data pages -// for first found id, check spix and load corresponding object index page to memory -// push object scan lookup entry index -// rescan object lookup, find data pages with same id and referenced by same object index -// move data page, update object index in memory -// when reached end of lookup, store updated object index -// pop object scan lookup entry index -// repeat loop until end of object lookup -// scan object lookup again for remaining object index pages, move to new page in other block -// -s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) { - s32_t res = SPIFFS_OK; - const int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - // this is the global localizer being pushed and popped - int cur_entry = 0; - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - spiffs_gc gc; // our stack frame/state - spiffs_page_ix cur_pix = 0; - 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_GC_DBG("gc_clean: cleaning block "_SPIPRIbl"\n", bix); - - memset(&gc, 0, sizeof(spiffs_gc)); - gc.state = FIND_OBJ_DATA; - - if (fs->free_cursor_block_ix == bix) { - // move free cursor to next block, cannot use free pages from the block we want to clean - fs->free_cursor_block_ix = (bix+1)%fs->block_count; - fs->free_cursor_obj_lu_entry = 0; - SPIFFS_GC_DBG("gc_clean: move free cursor to block "_SPIPRIbl"\n", fs->free_cursor_block_ix); - } - - while (res == SPIFFS_OK && gc.state != FINISHED) { - SPIFFS_GC_DBG("gc_clean: state = "_SPIPRIi" entry:"_SPIPRIi"\n", gc.state, cur_entry); - gc.obj_id_found = 0; // reset (to no found data page) - - // scan through lookup pages - int obj_lookup_page = cur_entry / entries_per_page; - u8_t scan = 1; - // check each object lookup page - while (scan && 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, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), - SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); - // check each object lookup entry - while (scan && res == SPIFFS_OK && - cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) { - spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset]; - cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry); - - // act upon object id depending on gc state - switch (gc.state) { - case FIND_OBJ_DATA: - // find a data page - if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE && - ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) { - // found a data page, stop scanning and handle in switch case below - SPIFFS_GC_DBG("gc_clean: FIND_DATA state:"_SPIPRIi" - found obj id "_SPIPRIid"\n", gc.state, obj_id); - gc.obj_id_found = 1; - gc.cur_obj_id = obj_id; - gc.cur_data_pix = cur_pix; - scan = 0; - } - break; - case MOVE_OBJ_DATA: - // evacuate found data pages for corresponding object index we have in memory, - // update memory representation - if (obj_id == gc.cur_obj_id) { - spiffs_page_header p_hdr; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page "_SPIPRIid":"_SPIPRIsp" @ "_SPIPRIpg"\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix); - if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) { - SPIFFS_GC_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n"); - } else { - spiffs_page_ix new_data_pix; - if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) { - // move page - res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix); - SPIFFS_GC_DBG("gc_clean: MOVE_DATA move objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg" to "_SPIPRIpg"\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix, new_data_pix); - SPIFFS_CHECK_RES(res); - // move wipes obj_lu, reload it - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, - 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), - SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); - SPIFFS_CHECK_RES(res); - } else { - // page is deleted but not deleted in lookup, scrap it - - // might seem unnecessary as we will erase this block, but - // we might get aborted - SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix); - res = spiffs_page_delete(fs, cur_pix); - SPIFFS_CHECK_RES(res); - new_data_pix = SPIFFS_OBJ_ID_FREE; - } - // update memory representation of object index page with new data page - if (gc.cur_objix_spix == 0) { - // update object index header page - ((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix; - SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)); - } else { - // update object index page - ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix; - SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)); - } - } - } - break; - case MOVE_OBJ_IX: - // find and evacuate object index pages - if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE && - (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) { - // found an index object id - spiffs_page_header p_hdr; - spiffs_page_ix new_pix; - // load header - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) { - // move page - res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix); - SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX move objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg" to "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix, new_pix); - SPIFFS_CHECK_RES(res); - spiffs_cb_object_event(fs, (spiffs_page_object_ix *)&p_hdr, - SPIFFS_EV_IX_MOV, obj_id, p_hdr.span_ix, new_pix, 0); - // move wipes obj_lu, reload it - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, - 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), - SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); - SPIFFS_CHECK_RES(res); - } else { - // page is deleted but not deleted in lookup, scrap it - - // might seem unnecessary as we will erase this block, but - // we might get aborted - SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix "_SPIPRIid":"_SPIPRIsp" page "_SPIPRIpg"\n", obj_id, p_hdr.span_ix, cur_pix); - res = spiffs_page_delete(fs, cur_pix); - if (res == SPIFFS_OK) { - spiffs_cb_object_event(fs, (spiffs_page_object_ix *)0, - SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0); - } - } - SPIFFS_CHECK_RES(res); - } - break; - default: - scan = 0; - break; - } // switch gc state - cur_entry++; - } // per entry - obj_lookup_page++; // no need to check scan variable here, obj_lookup_page is set in start of loop - } // per object lookup page - if (res != SPIFFS_OK) break; - - // state finalization and switch - switch (gc.state) { - case FIND_OBJ_DATA: - if (gc.obj_id_found) { - // handle found data page - - // find out corresponding obj ix page and load it to memory - spiffs_page_header p_hdr; - spiffs_page_ix objix_pix; - gc.stored_scan_entry_index = cur_entry; // push cursor - cur_entry = 0; // restart scan from start - gc.state = MOVE_OBJ_DATA; - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); - SPIFFS_CHECK_RES(res); - gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix); - SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:"_SPIPRIsp"\n", gc.cur_objix_spix); - res = spiffs_obj_lu_find_id_and_span(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, 0, &objix_pix); - if (res == SPIFFS_ERR_NOT_FOUND) { - // on borked systems we might get an ERR_NOT_FOUND here - - // this is handled by simply deleting the page as it is not referenced - // from anywhere - SPIFFS_GC_DBG("gc_clean: FIND_OBJ_DATA objix not found! Wipe page "_SPIPRIpg"\n", gc.cur_data_pix); - res = spiffs_page_delete(fs, gc.cur_data_pix); - SPIFFS_CHECK_RES(res); - // then we restore states and continue scanning for data pages - cur_entry = gc.stored_scan_entry_index; // pop cursor - gc.state = FIND_OBJ_DATA; - break; // done - } - SPIFFS_CHECK_RES(res); - SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page "_SPIPRIpg"\n", objix_pix); - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work); - SPIFFS_CHECK_RES(res); - // cannot allow a gc if the presumed index in fact is no index, a - // check must run or lot of data may be lost - SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix); - gc.cur_objix_pix = objix_pix; - } else { - // no more data pages found, passed thru all block, start evacuating object indices - gc.state = MOVE_OBJ_IX; - cur_entry = 0; // restart entry scan index - } - break; - case MOVE_OBJ_DATA: { - // store modified objix (hdr) page residing in memory now that all - // data pages belonging to this object index and residing in the block - // we want to evacuate - spiffs_page_ix new_objix_pix; - gc.state = FIND_OBJ_DATA; - cur_entry = gc.stored_scan_entry_index; // pop cursor - if (gc.cur_objix_spix == 0) { - // store object index header page - res = spiffs_object_update_index_hdr(fs, 0, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_pix, fs->work, 0, 0, 0, &new_objix_pix); - SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp"\n", new_objix_pix, 0); - SPIFFS_CHECK_RES(res); - } else { - // store object index page - res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix); - SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, "_SPIPRIpg":"_SPIPRIsp"\n", new_objix_pix, objix->p_hdr.span_ix); - SPIFFS_CHECK_RES(res); - spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work, - SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0); - } - } - break; - case MOVE_OBJ_IX: - // scanned thru all block, no more object indices found - our work here is done - gc.state = FINISHED; - break; - default: - cur_entry = 0; - break; - } // switch gc.state - SPIFFS_GC_DBG("gc_clean: state-> "_SPIPRIi"\n", gc.state); - } // while state != FINISHED - - - return res; -} - -#endif // !SPIFFS_READ_ONLY diff --git a/src/spiffs/spiffs_hydrogen.c b/src/spiffs/spiffs_hydrogen.c deleted file mode 100644 index 235aaaa..0000000 --- a/src/spiffs/spiffs_hydrogen.c +++ /dev/null @@ -1,1451 +0,0 @@ -/* - * spiffs_hydrogen.c - * - * Created on: Jun 16, 2013 - * Author: petera - */ - -#include "spiffs.h" -#include "spiffs_nucleus.h" - -#if SPIFFS_CACHE == 1 -static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh); -#endif - -#if SPIFFS_BUFFER_HELP -u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) { - return num_descs * sizeof(spiffs_fd); -} -#if SPIFFS_CACHE -u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) { - return sizeof(spiffs_cache) + num_pages * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs)); -} -#endif -#endif - -u8_t SPIFFS_mounted(spiffs *fs) { - return SPIFFS_CHECK_MOUNT(fs); -} - -s32_t SPIFFS_format(spiffs *fs) { -#if SPIFFS_READ_ONLY - (void)fs; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - if (SPIFFS_CHECK_MOUNT(fs)) { - fs->err_code = SPIFFS_ERR_MOUNTED; - return -1; - } - - s32_t res; - SPIFFS_LOCK(fs); - - spiffs_block_ix bix = 0; - while (bix < fs->block_count) { - fs->max_erase_count = 0; - res = spiffs_erase_block(fs, bix); - if (res != SPIFFS_OK) { - res = SPIFFS_ERR_ERASE_FAIL; - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - bix++; - } - - SPIFFS_UNLOCK(fs); - - return 0; -#endif // SPIFFS_READ_ONLY -} - -#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 - -s32_t SPIFFS_probe_fs(spiffs_config *config) { - SPIFFS_API_DBG("%s\n", __func__); - s32_t res = spiffs_probe(config); - return res; -} - -#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 - -s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, - u8_t *fd_space, u32_t fd_space_size, - void *cache, u32_t cache_size, - spiffs_check_callback check_cb_f) { - SPIFFS_API_DBG("%s " - " sz:"_SPIPRIi " logpgsz:"_SPIPRIi " logblksz:"_SPIPRIi " perasz:"_SPIPRIi - " addr:"_SPIPRIad - " fdsz:"_SPIPRIi " cachesz:"_SPIPRIi - "\n", - __func__, - SPIFFS_CFG_PHYS_SZ(fs), - SPIFFS_CFG_LOG_PAGE_SZ(fs), - SPIFFS_CFG_LOG_BLOCK_SZ(fs), - SPIFFS_CFG_PHYS_ERASE_SZ(fs), - SPIFFS_CFG_PHYS_ADDR(fs), - fd_space_size, cache_size); - void *user_data; - SPIFFS_LOCK(fs); - user_data = fs->user_data; - memset(fs, 0, sizeof(spiffs)); - _SPIFFS_MEMCPY(&fs->cfg, config, sizeof(spiffs_config)); - fs->user_data = user_data; - fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs); - fs->work = &work[0]; - fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)]; - memset(fd_space, 0, fd_space_size); - // align fd_space pointer to pointer size byte boundary - u8_t ptr_size = sizeof(void*); - u8_t addr_lsb = ((u8_t)(intptr_t)fd_space) & (ptr_size-1); - if (addr_lsb) { - fd_space += (ptr_size-addr_lsb); - fd_space_size -= (ptr_size-addr_lsb); - } - fs->fd_space = fd_space; - fs->fd_count = (fd_space_size/sizeof(spiffs_fd)); - - // align cache pointer to 4 byte boundary - addr_lsb = ((u8_t)(intptr_t)cache) & (ptr_size-1); - if (addr_lsb) { - u8_t *cache_8 = (u8_t *)cache; - cache_8 += (ptr_size-addr_lsb); - cache = cache_8; - cache_size -= (ptr_size-addr_lsb); - } - if (cache_size & (ptr_size-1)) { - cache_size -= (cache_size & (ptr_size-1)); - } - -#if SPIFFS_CACHE - fs->cache = cache; - fs->cache_size = (cache_size > (SPIFFS_CFG_LOG_PAGE_SZ(fs)*32)) ? SPIFFS_CFG_LOG_PAGE_SZ(fs)*32 : cache_size; - spiffs_cache_init(fs); -#endif - - s32_t res; - -#if SPIFFS_USE_MAGIC - res = SPIFFS_CHECK_MAGIC_POSSIBLE(fs) ? SPIFFS_OK : SPIFFS_ERR_MAGIC_NOT_POSSIBLE; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#endif - - fs->config_magic = SPIFFS_CONFIG_MAGIC; - - res = spiffs_obj_lu_scan(fs); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_DBG("page index byte len: "_SPIPRIi"\n", (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)); - SPIFFS_DBG("object lookup pages: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_LOOKUP_PAGES(fs)); - SPIFFS_DBG("page pages per block: "_SPIPRIi"\n", (u32_t)SPIFFS_PAGES_PER_BLOCK(fs)); - SPIFFS_DBG("page header length: "_SPIPRIi"\n", (u32_t)sizeof(spiffs_page_header)); - SPIFFS_DBG("object header index entries: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_HDR_IX_LEN(fs)); - SPIFFS_DBG("object index entries: "_SPIPRIi"\n", (u32_t)SPIFFS_OBJ_IX_LEN(fs)); - SPIFFS_DBG("available file descriptors: "_SPIPRIi"\n", (u32_t)fs->fd_count); - SPIFFS_DBG("free blocks: "_SPIPRIi"\n", (u32_t)fs->free_blocks); - - fs->check_cb_f = check_cb_f; - - fs->mounted = 1; - - SPIFFS_UNLOCK(fs); - - return 0; -} - -void SPIFFS_unmount(spiffs *fs) { - SPIFFS_API_DBG("%s\n", __func__); - if (!SPIFFS_CHECK_CFG(fs) || !SPIFFS_CHECK_MOUNT(fs)) return; - SPIFFS_LOCK(fs); - 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) { -#if SPIFFS_CACHE - (void)spiffs_fflush_cache(fs, cur_fd->file_nbr); -#endif - spiffs_fd_return(fs, cur_fd->file_nbr); - } - } - fs->mounted = 0; - - SPIFFS_UNLOCK(fs); -} - -s32_t SPIFFS_errno(spiffs *fs) { - return fs->err_code; -} - -void SPIFFS_clearerr(spiffs *fs) { - SPIFFS_API_DBG("%s\n", __func__); - fs->err_code = SPIFFS_OK; -} - -s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) { - SPIFFS_API_DBG("%s '%s'\n", __func__, path); -#if SPIFFS_READ_ONLY - (void)fs; (void)path; (void)mode; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - (void)mode; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) { - SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG); - } - SPIFFS_LOCK(fs); - spiffs_obj_id obj_id; - s32_t res; - - res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, (const u8_t*)path); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - res = spiffs_object_create(fs, obj_id, (const u8_t*)path, 0, SPIFFS_TYPE_FILE, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - SPIFFS_UNLOCK(fs); - return 0; -#endif // SPIFFS_READ_ONLY -} - -spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) { - SPIFFS_API_DBG("%s '%s' "_SPIPRIfl "\n", __func__, path, flags); - (void)mode; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) { - SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG); - } - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - spiffs_page_ix pix; - -#if SPIFFS_READ_ONLY - // not valid flags in read only mode - flags &= ~(SPIFFS_WRONLY | SPIFFS_CREAT | SPIFFS_TRUNC); -#endif // SPIFFS_READ_ONLY - - s32_t res = spiffs_fd_find_new(fs, &fd, path); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix); - if ((flags & SPIFFS_O_CREAT) == 0) { - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - if (res == SPIFFS_OK && - (flags & (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) == (SPIFFS_O_CREAT | SPIFFS_O_EXCL)) { - // creat and excl and file exists - fail - res = SPIFFS_ERR_FILE_EXISTS; - spiffs_fd_return(fs, fd->file_nbr); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - if ((flags & SPIFFS_O_CREAT) && res == SPIFFS_ERR_NOT_FOUND) { -#if !SPIFFS_READ_ONLY - spiffs_obj_id obj_id; - // no need to enter conflicting name here, already looked for it above - res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - res = spiffs_object_create(fs, obj_id, (const u8_t*)path, 0, SPIFFS_TYPE_FILE, &pix); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - flags &= ~SPIFFS_O_TRUNC; -#endif // !SPIFFS_READ_ONLY - } else { - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - res = spiffs_object_open_by_page(fs, pix, fd, flags, mode); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#if !SPIFFS_READ_ONLY - if (flags & SPIFFS_O_TRUNC) { - res = spiffs_object_truncate(fd, 0, 0); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } -#endif // !SPIFFS_READ_ONLY - - fd->fdoffset = 0; - - SPIFFS_UNLOCK(fs); - - return SPIFFS_FH_OFFS(fs, fd->file_nbr); -} - -spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) { - SPIFFS_API_DBG("%s '%s':"_SPIPRIid " "_SPIPRIfl "\n", __func__, e->name, e->obj_id, flags); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - - s32_t res = spiffs_fd_find_new(fs, &fd, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_open_by_page(fs, e->pix, fd, flags, mode); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#if !SPIFFS_READ_ONLY - if (flags & SPIFFS_O_TRUNC) { - res = spiffs_object_truncate(fd, 0, 0); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } -#endif // !SPIFFS_READ_ONLY - - fd->fdoffset = 0; - - SPIFFS_UNLOCK(fs); - - return SPIFFS_FH_OFFS(fs, fd->file_nbr); -} - -spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode) { - SPIFFS_API_DBG("%s "_SPIPRIpg " "_SPIPRIfl "\n", __func__, page_ix, flags); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - - s32_t res = spiffs_fd_find_new(fs, &fd, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if (SPIFFS_IS_LOOKUP_PAGE(fs, page_ix)) { - res = SPIFFS_ERR_NOT_A_FILE; - spiffs_fd_return(fs, fd->file_nbr); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - res = spiffs_object_open_by_page(fs, page_ix, fd, flags, mode); - if (res == SPIFFS_ERR_IS_FREE || - res == SPIFFS_ERR_DELETED || - res == SPIFFS_ERR_NOT_FINALIZED || - res == SPIFFS_ERR_NOT_INDEX || - res == SPIFFS_ERR_INDEX_SPAN_MISMATCH) { - res = SPIFFS_ERR_NOT_A_FILE; - } - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - -#if !SPIFFS_READ_ONLY - if (flags & SPIFFS_O_TRUNC) { - res = spiffs_object_truncate(fd, 0, 0); - if (res < SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } -#endif // !SPIFFS_READ_ONLY - - fd->fdoffset = 0; - - SPIFFS_UNLOCK(fs); - - return SPIFFS_FH_OFFS(fs, fd->file_nbr); -} - -static s32_t spiffs_hydro_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - s32_t res; - - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if ((fd->flags & SPIFFS_O_RDONLY) == 0) { - res = SPIFFS_ERR_NOT_READABLE; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - if (fd->size == SPIFFS_UNDEFINED_LEN && len > 0) { - // special case for zero sized files - res = SPIFFS_ERR_END_OF_OBJECT; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - -#if SPIFFS_CACHE_WR - spiffs_fflush_cache(fs, fh); -#endif - - if (fd->fdoffset + len >= fd->size) { - // reading beyond file size - s32_t avail = fd->size - fd->fdoffset; - if (avail <= 0) { - SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_END_OF_OBJECT); - } - res = spiffs_object_read(fd, fd->fdoffset, avail, (u8_t*)buf); - if (res == SPIFFS_ERR_END_OF_OBJECT) { - fd->fdoffset += avail; - SPIFFS_UNLOCK(fs); - return avail; - } else { - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - len = avail; - } - } else { - // reading within file size - res = spiffs_object_read(fd, fd->fdoffset, len, (u8_t*)buf); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - fd->fdoffset += len; - - SPIFFS_UNLOCK(fs); - - return len; -} - -s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { - SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, len); - s32_t res = spiffs_hydro_read(fs, fh, buf, len); - if (res == SPIFFS_ERR_END_OF_OBJECT) { - res = 0; - } - return res; -} - - -#if !SPIFFS_READ_ONLY -static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) { - (void)fs; - s32_t res = SPIFFS_OK; - s32_t remaining = len; - if (fd->size != SPIFFS_UNDEFINED_LEN && offset < fd->size) { - s32_t m_len = MIN((s32_t)(fd->size - offset), len); - res = spiffs_object_modify(fd, offset, (u8_t *)buf, m_len); - SPIFFS_CHECK_RES(res); - remaining -= m_len; - u8_t *buf_8 = (u8_t *)buf; - buf_8 += m_len; - buf = buf_8; - offset += m_len; - } - if (remaining > 0) { - res = spiffs_object_append(fd, offset, (u8_t *)buf, remaining); - SPIFFS_CHECK_RES(res); - } - return len; - -} -#endif // !SPIFFS_READ_ONLY - -s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) { - SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, len); -#if SPIFFS_READ_ONLY - (void)fs; (void)fh; (void)buf; (void)len; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - s32_t res; - u32_t offset; - - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if ((fd->flags & SPIFFS_O_WRONLY) == 0) { - res = SPIFFS_ERR_NOT_WRITABLE; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - if ((fd->flags & SPIFFS_O_APPEND)) { - fd->fdoffset = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size; - } - offset = fd->fdoffset; - -#if SPIFFS_CACHE_WR - if (fd->cache_page == 0) { - // see if object id is associated with cache already - fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd); - } -#endif - if (fd->flags & SPIFFS_O_APPEND) { - if (fd->size == SPIFFS_UNDEFINED_LEN) { - offset = 0; - } else { - offset = fd->size; - } -#if SPIFFS_CACHE_WR - if (fd->cache_page) { - offset = MAX(offset, fd->cache_page->offset + fd->cache_page->size); - } -#endif - } - -#if SPIFFS_CACHE_WR - if ((fd->flags & SPIFFS_O_DIRECT) == 0) { - if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) { - // small write, try to cache it - u8_t alloc_cpage = 1; - if (fd->cache_page) { - // have a cached page for this fd already, check cache page boundaries - if (offset < fd->cache_page->offset || // writing before cache - offset > fd->cache_page->offset + fd->cache_page->size || // writing after cache - offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page - { - // boundary violation, write back cache first and allocate new - SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", boundary viol, offs:"_SPIPRIi" size:"_SPIPRIi"\n", - fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size); - res = spiffs_hydro_write(fs, fd, - spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), - fd->cache_page->offset, fd->cache_page->size); - spiffs_cache_fd_release(fs, fd->cache_page); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } else { - // writing within cache - alloc_cpage = 0; - } - } - - if (alloc_cpage) { - fd->cache_page = spiffs_cache_page_allocate_by_fd(fs, fd); - if (fd->cache_page) { - fd->cache_page->offset = offset; - fd->cache_page->size = 0; - SPIFFS_CACHE_DBG("CACHE_WR_ALLO: allocating cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid"\n", - fd->cache_page->ix, fd->file_nbr, fd->obj_id); - } - } - - if (fd->cache_page) { - u32_t offset_in_cpage = offset - fd->cache_page->offset; - SPIFFS_CACHE_DBG("CACHE_WR_WRITE: storing to cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", offs "_SPIPRIi":"_SPIPRIi" len "_SPIPRIi"\n", - fd->cache_page->ix, fd->file_nbr, fd->obj_id, - offset, offset_in_cpage, len); - spiffs_cache *cache = spiffs_get_cache(fs); - u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix); -#ifdef _SPIFFS_TEST - { - intptr_t __a1 = (u8_t*)&cpage_data[offset_in_cpage]-(u8_t*)cache; - intptr_t __a2 = (u8_t*)&cpage_data[offset_in_cpage]+len-(u8_t*)cache; - intptr_t __b = sizeof(spiffs_cache) + cache->cpage_count * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs)); - if (__a1 > __b || __a2 > __b) { - printf("FATAL OOB: CACHE_WR: memcpy to cache buffer ixs:%4ld..%4ld of %4ld\n", __a1, __a2, __b); - ERREXIT(); - } - } -#endif - _SPIFFS_MEMCPY(&cpage_data[offset_in_cpage], buf, len); - fd->cache_page->size = MAX(fd->cache_page->size, offset_in_cpage + len); - fd->fdoffset += len; - SPIFFS_UNLOCK(fs); - return len; - } else { - res = spiffs_hydro_write(fs, fd, buf, offset, len); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - fd->fdoffset += len; - SPIFFS_UNLOCK(fs); - return res; - } - } else { - // big write, no need to cache it - but first check if there is a cached write already - if (fd->cache_page) { - // write back cache first - SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", big write, offs:"_SPIPRIi" size:"_SPIPRIi"\n", - fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size); - res = spiffs_hydro_write(fs, fd, - spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), - fd->cache_page->offset, fd->cache_page->size); - spiffs_cache_fd_release(fs, fd->cache_page); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - // data written below - } - } - } -#endif - - res = spiffs_hydro_write(fs, fd, buf, offset, len); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - fd->fdoffset += len; - - SPIFFS_UNLOCK(fs); - - return res; -#endif // SPIFFS_READ_ONLY -} - -s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) { - SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi " %s\n", __func__, fh, offs, (const char* []){"SET","CUR","END","???"}[MIN(whence,3)]); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - s32_t res; - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - -#if SPIFFS_CACHE_WR - spiffs_fflush_cache(fs, fh); -#endif - - s32_t file_size = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size; - - switch (whence) { - case SPIFFS_SEEK_CUR: - offs = fd->fdoffset+offs; - break; - case SPIFFS_SEEK_END: - offs = file_size + offs; - break; - } - if (offs < 0) { - SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_SEEK_BOUNDS); - } - if (offs > file_size) { - fd->fdoffset = file_size; - res = SPIFFS_ERR_END_OF_OBJECT; - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - spiffs_span_ix data_spix = (offs > 0 ? (offs-1) : 0) / SPIFFS_DATA_PAGE_SIZE(fs); - spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix); - if (fd->cursor_objix_spix != objix_spix) { - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span( - fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, &pix); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - fd->cursor_objix_spix = objix_spix; - fd->cursor_objix_pix = pix; - } - fd->fdoffset = offs; - - SPIFFS_UNLOCK(fs); - - return offs; -} - -s32_t SPIFFS_remove(spiffs *fs, const char *path) { - SPIFFS_API_DBG("%s '%s'\n", __func__, path); -#if SPIFFS_READ_ONLY - (void)fs; (void)path; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) { - SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG); - } - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - spiffs_page_ix pix; - s32_t res; - - res = spiffs_fd_find_new(fs, &fd, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix); - if (res != SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_open_by_page(fs, pix, fd, 0,0); - if (res != SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_truncate(fd, 0, 1); - if (res != SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - return 0; -#endif // SPIFFS_READ_ONLY -} - -s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); -#if SPIFFS_READ_ONLY - (void)fs; (void)fh; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - s32_t res; - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if ((fd->flags & SPIFFS_O_WRONLY) == 0) { - res = SPIFFS_ERR_NOT_WRITABLE; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - -#if SPIFFS_CACHE_WR - spiffs_cache_fd_release(fs, fd->cache_page); -#endif - - res = spiffs_object_truncate(fd, 0, 1); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - - return 0; -#endif // SPIFFS_READ_ONLY -} - -static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) { - (void)fh; - spiffs_page_object_ix_header objix_hdr; - spiffs_obj_id obj_id; - s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh, - SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr); - SPIFFS_API_CHECK_RES(fs, res); - - u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , pix)) + - SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_obj_id); - res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, fh, - obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id); - SPIFFS_API_CHECK_RES(fs, res); - - s->obj_id = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; - s->type = objix_hdr.type; - s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size; - s->pix = pix; - strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN); -#if SPIFFS_OBJ_META_LEN - _SPIFFS_MEMCPY(s->meta, objix_hdr.meta, SPIFFS_OBJ_META_LEN); -#endif - - return res; -} - -s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) { - SPIFFS_API_DBG("%s '%s'\n", __func__, path); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - if (strlen(path) > SPIFFS_OBJ_NAME_LEN - 1) { - SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG); - } - SPIFFS_LOCK(fs); - - s32_t res; - spiffs_page_ix pix; - - res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)path, &pix); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_stat_pix(fs, pix, 0, s); - - SPIFFS_UNLOCK(fs); - - return res; -} - -s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_fd *fd; - s32_t res; - - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - -#if SPIFFS_CACHE_WR - spiffs_fflush_cache(fs, fh); -#endif - - res = spiffs_stat_pix(fs, fd->objix_hdr_pix, fh, s); - - SPIFFS_UNLOCK(fs); - - return res; -} - -// Checks if there are any cached writes for the object id associated with -// given filehandle. If so, these writes are flushed. -#if SPIFFS_CACHE == 1 -static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { - (void)fs; - (void)fh; - s32_t res = SPIFFS_OK; -#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES(fs, res); - - if ((fd->flags & SPIFFS_O_DIRECT) == 0) { - if (fd->cache_page == 0) { - // see if object id is associated with cache already - fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd); - } - if (fd->cache_page) { - SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page "_SPIPRIi" for fd "_SPIPRIfd":"_SPIPRIid", flush, offs:"_SPIPRIi" size:"_SPIPRIi"\n", - fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size); - res = spiffs_hydro_write(fs, fd, - spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), - fd->cache_page->offset, fd->cache_page->size); - if (res < SPIFFS_OK) { - fs->err_code = res; - } - spiffs_cache_fd_release(fs, fd->cache_page); - } - } -#endif - - return res; -} -#endif - -s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - (void)fh; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - s32_t res = SPIFFS_OK; -#if !SPIFFS_READ_ONLY && SPIFFS_CACHE_WR - SPIFFS_LOCK(fs); - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fflush_cache(fs, fh); - SPIFFS_API_CHECK_RES_UNLOCK(fs,res); - SPIFFS_UNLOCK(fs); -#endif - - return res; -} - -s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - - s32_t res = SPIFFS_OK; - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); -#if SPIFFS_CACHE - res = spiffs_fflush_cache(fs, fh); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#endif - res = spiffs_fd_return(fs, fh); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - - return res; -} - -s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_path) { - SPIFFS_API_DBG("%s %s %s\n", __func__, old_path, new_path); -#if SPIFFS_READ_ONLY - (void)fs; (void)old_path; (void)new_path; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - if (strlen(new_path) > SPIFFS_OBJ_NAME_LEN - 1 || - strlen(old_path) > SPIFFS_OBJ_NAME_LEN - 1) { - SPIFFS_API_CHECK_RES(fs, SPIFFS_ERR_NAME_TOO_LONG); - } - SPIFFS_LOCK(fs); - - spiffs_page_ix pix_old, pix_dummy; - spiffs_fd *fd; - - s32_t res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)old_path, &pix_old); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)new_path, &pix_dummy); - if (res == SPIFFS_ERR_NOT_FOUND) { - res = SPIFFS_OK; - } else if (res == SPIFFS_OK) { - res = SPIFFS_ERR_CONFLICTING_NAME; - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_fd_find_new(fs, &fd, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_open_by_page(fs, pix_old, fd, 0, 0); - if (res != SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (const u8_t*)new_path, - 0, 0, &pix_dummy); -#if SPIFFS_TEMPORAL_FD_CACHE - if (res == SPIFFS_OK) { - spiffs_fd_temporal_cache_rehash(fs, old_path, new_path); - } -#endif - - spiffs_fd_return(fs, fd->file_nbr); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - - return res; -#endif // SPIFFS_READ_ONLY -} - -#if SPIFFS_OBJ_META_LEN -s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta) { -#if SPIFFS_READ_ONLY - (void)fs; (void)name; (void)meta; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - spiffs_page_ix pix, pix_dummy; - spiffs_fd *fd; - - s32_t res = spiffs_object_find_object_index_header_by_name(fs, (const u8_t*)name, &pix); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_fd_find_new(fs, &fd, 0); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_open_by_page(fs, pix, fd, 0, 0); - if (res != SPIFFS_OK) { - spiffs_fd_return(fs, fd->file_nbr); - } - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, 0, meta, - 0, &pix_dummy); - - spiffs_fd_return(fs, fd->file_nbr); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - - return res; -#endif // SPIFFS_READ_ONLY -} - -s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta) { -#if SPIFFS_READ_ONLY - (void)fs; (void)fh; (void)meta; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - s32_t res; - spiffs_fd *fd; - spiffs_page_ix pix_dummy; - - fh = SPIFFS_FH_UNOFFS(fs, fh); - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if ((fd->flags & SPIFFS_O_WRONLY) == 0) { - res = SPIFFS_ERR_NOT_WRITABLE; - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, 0, meta, - 0, &pix_dummy); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - - return res; -#endif // SPIFFS_READ_ONLY -} -#endif // SPIFFS_OBJ_META_LEN - -spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) { - SPIFFS_API_DBG("%s\n", __func__); - (void)name; - - if (!SPIFFS_CHECK_CFG((fs))) { - (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; - return 0; - } - - if (!SPIFFS_CHECK_MOUNT(fs)) { - fs->err_code = SPIFFS_ERR_NOT_MOUNTED; - return 0; - } - - d->fs = fs; - d->block = 0; - d->entry = 0; - return d; -} - -static s32_t spiffs_read_dir_v( - spiffs *fs, - spiffs_obj_id obj_id, - spiffs_block_ix bix, - int ix_entry, - const void *user_const_p, - void *user_var_p) { - (void)user_const_p; - s32_t res; - spiffs_page_object_ix_header objix_hdr; - 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; - } - - spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry); - 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); - if (res != SPIFFS_OK) return res; - if ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && - 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)) { - struct spiffs_dirent *e = (struct spiffs_dirent*)user_var_p; - e->obj_id = obj_id; - strcpy((char *)e->name, (char *)objix_hdr.name); - e->type = objix_hdr.type; - e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size; - e->pix = pix; -#if SPIFFS_OBJ_META_LEN - _SPIFFS_MEMCPY(e->meta, objix_hdr.meta, SPIFFS_OBJ_META_LEN); -#endif - return SPIFFS_OK; - } - return SPIFFS_VIS_COUNTINUE; -} - -struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) { - SPIFFS_API_DBG("%s\n", __func__); - if (!SPIFFS_CHECK_MOUNT(d->fs)) { - d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED; - return 0; - } - SPIFFS_LOCK(d->fs); - - spiffs_block_ix bix; - int entry; - s32_t res; - struct spiffs_dirent *ret = 0; - - res = spiffs_obj_lu_find_entry_visitor(d->fs, - d->block, - d->entry, - SPIFFS_VIS_NO_WRAP, - 0, - spiffs_read_dir_v, - 0, - e, - &bix, - &entry); - if (res == SPIFFS_OK) { - d->block = bix; - d->entry = entry + 1; - e->obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG; - ret = e; - } else { - d->fs->err_code = res; - } - SPIFFS_UNLOCK(d->fs); - return ret; -} - -s32_t SPIFFS_closedir(spiffs_DIR *d) { - SPIFFS_API_DBG("%s\n", __func__); - SPIFFS_API_CHECK_CFG(d->fs); - SPIFFS_API_CHECK_MOUNT(d->fs); - return 0; -} - -s32_t SPIFFS_check(spiffs *fs) { - SPIFFS_API_DBG("%s\n", __func__); -#if SPIFFS_READ_ONLY - (void)fs; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - res = spiffs_lookup_consistency_check(fs, 0); - - res = spiffs_object_index_consistency_check(fs); - - res = spiffs_page_consistency_check(fs); - - res = spiffs_obj_lu_scan(fs); - - SPIFFS_UNLOCK(fs); - return res; -#endif // SPIFFS_READ_ONLY -} - -s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) { - SPIFFS_API_DBG("%s\n", __func__); - s32_t res = SPIFFS_OK; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - u32_t pages_per_block = SPIFFS_PAGES_PER_BLOCK(fs); - u32_t blocks = fs->block_count; - u32_t obj_lu_pages = SPIFFS_OBJ_LOOKUP_PAGES(fs); - u32_t data_page_size = SPIFFS_DATA_PAGE_SIZE(fs); - u32_t total_data_pages = (blocks - 2) * (pages_per_block - obj_lu_pages) + 1; // -2 for spare blocks, +1 for emergency page - - if (total) { - *total = total_data_pages * data_page_size; - } - - if (used) { - *used = fs->stats_p_allocated * data_page_size; - } - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) { - SPIFFS_API_DBG("%s "_SPIPRIi "\n", __func__, max_free_pages); -#if SPIFFS_READ_ONLY - (void)fs; (void)max_free_pages; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - res = spiffs_gc_quick(fs, max_free_pages); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - SPIFFS_UNLOCK(fs); - return 0; -#endif // SPIFFS_READ_ONLY -} - - -s32_t SPIFFS_gc(spiffs *fs, u32_t size) { - SPIFFS_API_DBG("%s "_SPIPRIi "\n", __func__, size); -#if SPIFFS_READ_ONLY - (void)fs; (void)size; - return SPIFFS_ERR_RO_NOT_IMPL; -#else - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - res = spiffs_gc_check(fs, size); - - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - SPIFFS_UNLOCK(fs); - return 0; -#endif // SPIFFS_READ_ONLY -} - -s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - -#if SPIFFS_CACHE_WR - res = spiffs_fflush_cache(fs, fh); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#endif - - res = (fd->fdoffset >= (fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size)); - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - -#if SPIFFS_CACHE_WR - res = spiffs_fflush_cache(fs, fh); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); -#endif - - res = fd->fdoffset; - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func) { - SPIFFS_API_DBG("%s\n", __func__); - SPIFFS_LOCK(fs); - fs->file_cb_f = cb_func; - SPIFFS_UNLOCK(fs); - return 0; -} - -#if SPIFFS_IX_MAP - -s32_t SPIFFS_ix_map(spiffs *fs, spiffs_file fh, spiffs_ix_map *map, - u32_t offset, u32_t len, spiffs_page_ix *map_buf) { - SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi " "_SPIPRIi "\n", __func__, fh, offset, len); - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if (fd->ix_map) { - SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_MAPPED); - } - - 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)); - fd->ix_map = map; - - // scan for pixes - res = spiffs_populate_ix_map(fs, fd, 0, map->end_spix - map->start_spix + 1); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_ix_unmap(spiffs *fs, spiffs_file fh) { - SPIFFS_API_DBG("%s "_SPIPRIfd "\n", __func__, fh); - s32_t res; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if (fd->ix_map == 0) { - SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_UNMAPPED); - } - - fd->ix_map = 0; - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) { - SPIFFS_API_DBG("%s "_SPIPRIfd " "_SPIPRIi "\n", __func__, fh, offset); - s32_t res = SPIFFS_OK; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - fh = SPIFFS_FH_UNOFFS(fs, fh); - - spiffs_fd *fd; - res = spiffs_fd_get(fs, fh, &fd); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - - if (fd->ix_map == 0) { - SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_IX_MAP_UNMAPPED); - } - - spiffs_ix_map *map = fd->ix_map; - - s32_t spix_diff = offset / SPIFFS_DATA_PAGE_SIZE(fs) - map->start_spix; - map->offset = offset; - - // move existing pixes if within map offs - if (spix_diff != 0) { - // move vector - int i; - 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)); - // 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; i++) { - map->map_buf[i] = map->map_buf[i + spix_diff]; - } - // 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)); - // populate_ix_map is inclusive - res = spiffs_populate_ix_map(fs, fd, 0, -spix_diff - 1); - SPIFFS_API_CHECK_RES_UNLOCK(fs, res); - } - - } - - SPIFFS_UNLOCK(fs); - return res; -} - -s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) { - SPIFFS_API_CHECK_CFG(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) { - SPIFFS_API_CHECK_CFG(fs); - return map_page_ix_entries * SPIFFS_DATA_PAGE_SIZE(fs); -} - -#endif // SPIFFS_IX_MAP - -#if SPIFFS_TEST_VISUALISATION -s32_t SPIFFS_vis(spiffs *fs) { - s32_t res = SPIFFS_OK; - SPIFFS_API_CHECK_CFG(fs); - SPIFFS_API_CHECK_MOUNT(fs); - SPIFFS_LOCK(fs); - - int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - spiffs_block_ix bix = 0; - - while (bix < fs->block_count) { - // check each object lookup page - int obj_lookup_page = 0; - int cur_entry = 0; - - 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, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + 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 && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) { - spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset]; - if (cur_entry == 0) { - spiffs_printf(_SPIPRIbl" ", bix); - } else if ((cur_entry & 0x3f) == 0) { - spiffs_printf(" "); - } - if (obj_id == SPIFFS_OBJ_ID_FREE) { - spiffs_printf(SPIFFS_TEST_VIS_FREE_STR); - } else if (obj_id == SPIFFS_OBJ_ID_DELETED) { - spiffs_printf(SPIFFS_TEST_VIS_DELE_STR); - } else if (obj_id & SPIFFS_OBJ_ID_IX_FLAG){ - spiffs_printf(SPIFFS_TEST_VIS_INDX_STR(obj_id)); - } else { - spiffs_printf(SPIFFS_TEST_VIS_DATA_STR(obj_id)); - } - cur_entry++; - if ((cur_entry & 0x3f) == 0) { - spiffs_printf("\n"); - } - } // per entry - obj_lookup_page++; - } // per object lookup page - - spiffs_obj_id erase_count; - res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 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)-1) { - spiffs_printf("\tera_cnt: "_SPIPRIi"\n", erase_count); - } else { - spiffs_printf("\tera_cnt: N/A\n"); - } - - bix++; - } // per block - - spiffs_printf("era_cnt_max: "_SPIPRIi"\n", fs->max_erase_count); - spiffs_printf("last_errno: "_SPIPRIi"\n", fs->err_code); - spiffs_printf("blocks: "_SPIPRIi"\n", fs->block_count); - spiffs_printf("free_blocks: "_SPIPRIi"\n", fs->free_blocks); - spiffs_printf("page_alloc: "_SPIPRIi"\n", fs->stats_p_allocated); - spiffs_printf("page_delet: "_SPIPRIi"\n", fs->stats_p_deleted); - SPIFFS_UNLOCK(fs); - u32_t total, used; - SPIFFS_info(fs, &total, &used); - spiffs_printf("used: "_SPIPRIi" of "_SPIPRIi"\n", used, total); - return res; -} -#endif diff --git a/src/spiffs/spiffs_nucleus.c b/src/spiffs/spiffs_nucleus.c deleted file mode 100644 index 6b052b0..0000000 --- a/src/spiffs/spiffs_nucleus.c +++ /dev/null @@ -1,2364 +0,0 @@ -#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; -} - -#if !SPIFFS_READ_ONLY -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; -} -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_CACHE - -s32_t spiffs_phys_rd( - spiffs *fs, - u32_t addr, - u32_t len, - u8_t *dst) { - return SPIFFS_HAL_READ(fs, addr, len, dst); -} - -s32_t spiffs_phys_wr( - spiffs *fs, - u32_t addr, - u32_t len, - u8_t *src) { - return SPIFFS_HAL_WRITE(fs, addr, len, src); -} - -#endif - -#if !SPIFFS_READ_ONLY -s32_t spiffs_phys_cpy( - spiffs *fs, - spiffs_file fh, - u32_t dst, - u32_t src, - u32_t len) { - (void)fh; - 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; -} -#endif // !SPIFFS_READ_ONLY - -// 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_const_p any const pointer, passed to the callback visitor function -// @param user_var_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, - const void *user_const_p, - void *user_var_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_const_p, - user_var_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; -} - -#if !SPIFFS_READ_ONLY -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 "_SPIPRIad":"_SPIPRIi"\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); - SPIFFS_HAL_ERASE(fs, 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, bix); - 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; -} -#endif // !SPIFFS_READ_ONLY - -#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 -s32_t spiffs_probe( - spiffs_config *cfg) { - s32_t res; - u32_t paddr; - spiffs dummy_fs; // create a dummy fs struct just to be able to use macros - _SPIFFS_MEMCPY(&dummy_fs.cfg, cfg, sizeof(spiffs_config)); - dummy_fs.block_count = 0; - - // Read three magics, as one block may be in an aborted erase state. - // At least two of these must contain magic and be in decreasing order. - spiffs_obj_id magic[3]; - spiffs_obj_id bix_count[3]; - - spiffs_block_ix bix; - for (bix = 0; bix < 3; bix++) { - paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, bix); -#if SPIFFS_HAL_CALLBACK_EXTRA - // not any proper fs to report here, so callback with null - // (cross fingers that no-one gets angry) - res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]); -#else - res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic[bix]); -#endif - bix_count[bix] = magic[bix] ^ SPIFFS_MAGIC(&dummy_fs, 0); - SPIFFS_CHECK_RES(res); - } - - // check that we have sane number of blocks - if (bix_count[0] < 3) return SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS; - // check that the order is correct, take aborted erases in calculation - // first block aborted erase - if (magic[0] == (spiffs_obj_id)(-1) && bix_count[1] - bix_count[2] == 1) { - return (bix_count[1]+1) * cfg->log_block_size; - } - // second block aborted erase - if (magic[1] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[2] == 2) { - return bix_count[0] * cfg->log_block_size; - } - // third block aborted erase - if (magic[2] == (spiffs_obj_id)(-1) && bix_count[0] - bix_count[1] == 1) { - return bix_count[0] * cfg->log_block_size; - } - // no block has aborted erase - if (bix_count[0] - bix_count[1] == 1 && bix_count[1] - bix_count[2] == 1) { - return bix_count[0] * cfg->log_block_size; - } - - return SPIFFS_ERR_PROBE_NOT_A_FS; -} -#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0 - - -static s32_t spiffs_obj_lu_scan_v( - spiffs *fs, - spiffs_obj_id obj_id, - spiffs_block_ix bix, - int ix_entry, - const void *user_const_p, - void *user_var_p) { - (void)bix; - (void)user_const_p; - (void)user_var_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, bix)) { - 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 "_SPIPRIbl"\n", bix); -#if SPIFFS_READ_ONLY - res = SPIFFS_ERR_RO_ABORTED_OPERATION; -#else - res = spiffs_erase_block(fs, unerased_bix); -#endif // SPIFFS_READ_ONLY - 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; -} - -#if !SPIFFS_READ_ONLY -// 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) + 1; - if (*lu_entry == 0) { - fs->free_blocks--; - } - } - if (res == SPIFFS_ERR_FULL) { - SPIFFS_DBG("fs full\n"); - } - - return res; -} -#endif // !SPIFFS_READ_ONLY - -// 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, - const void *user_const_p, - void *user_var_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_var_p) && - (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_const_p == 0 || *((const spiffs_page_ix*)user_const_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, - exclusion_pix ? &exclusion_pix : 0, - &spix, - &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, - exclusion_pix ? &exclusion_pix : 0, - &spix, - &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; -} - -#if SPIFFS_IX_MAP - -// update index map of given fd with given object index data -static void spiffs_update_ix_map(spiffs *fs, - spiffs_fd *fd, spiffs_span_ix objix_spix, spiffs_page_object_ix *objix) { -#if SPIFFS_SINGLETON - (void)fs; -#endif - spiffs_ix_map *map = fd->ix_map; - spiffs_span_ix map_objix_start_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix); - spiffs_span_ix map_objix_end_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->end_spix); - - // check if updated ix is within map range - if (objix_spix < map_objix_start_spix || objix_spix > map_objix_end_spix) { - return; - } - - // update memory mapped page index buffer to new pages - - // get range of updated object index map data span indices - spiffs_span_ix objix_data_spix_start = - SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, objix_spix); - spiffs_span_ix objix_data_spix_end = objix_data_spix_start + - (objix_spix == 0 ? SPIFFS_OBJ_HDR_IX_LEN(fs) : SPIFFS_OBJ_IX_LEN(fs)); - - // calc union of object index range and index map range array - spiffs_span_ix map_spix = MAX(map->start_spix, objix_data_spix_start); - spiffs_span_ix map_spix_end = MIN(map->end_spix + 1, objix_data_spix_end); - - while (map_spix < map_spix_end) { - spiffs_page_ix objix_data_pix; - if (objix_spix == 0) { - // get data page from object index header page - objix_data_pix = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix_header)))[map_spix]; - } else { - // get data page from object index page - objix_data_pix = ((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, map_spix)]; - } - - if (objix_data_pix == (spiffs_page_ix)-1) { - // reached end of object, abort - break; - } - - map->map_buf[map_spix - map->start_spix] = objix_data_pix; - SPIFFS_DBG("map "_SPIPRIid":"_SPIPRIsp" ("_SPIPRIsp"--"_SPIPRIsp") objix.spix:"_SPIPRIsp" to pix "_SPIPRIpg"\n", - fd->obj_id, map_spix - map->start_spix, - map->start_spix, map->end_spix, - objix->p_hdr.span_ix, - objix_data_pix); - - map_spix++; - } -} - -typedef struct { - spiffs_fd *fd; - u32_t remaining_objix_pages_to_visit; - spiffs_span_ix map_objix_start_spix; - spiffs_span_ix map_objix_end_spix; -} spiffs_ix_map_populate_state; - -static s32_t spiffs_populate_ix_map_v( - spiffs *fs, - spiffs_obj_id obj_id, - spiffs_block_ix bix, - int ix_entry, - const void *user_const_p, - void *user_var_p) { - (void)user_const_p; - s32_t res; - spiffs_ix_map_populate_state *state = (spiffs_ix_map_populate_state *)user_var_p; - spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry); - - // load header to check it - spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work; - 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), (u8_t *)objix); - SPIFFS_CHECK_RES(res); - SPIFFS_VALIDATE_OBJIX(objix->p_hdr, obj_id, objix->p_hdr.span_ix); - - // check if hdr is ok, and if objix range overlap with ix map range - if ((objix->p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) == - (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE) && - objix->p_hdr.span_ix >= state->map_objix_start_spix && - objix->p_hdr.span_ix <= state->map_objix_end_spix) { - // ok, load rest of object index - 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), - SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix), - (u8_t *)objix + sizeof(spiffs_page_object_ix)); - SPIFFS_CHECK_RES(res); - - spiffs_update_ix_map(fs, state->fd, objix->p_hdr.span_ix, objix); - - state->remaining_objix_pages_to_visit--; - SPIFFS_DBG("map "_SPIPRIid" ("_SPIPRIsp"--"_SPIPRIsp") remaining objix pages "_SPIPRIi"\n", - state->fd->obj_id, - state->fd->ix_map->start_spix, state->fd->ix_map->end_spix, - state->remaining_objix_pages_to_visit); - } - - if (res == SPIFFS_OK) { - res = state->remaining_objix_pages_to_visit ? SPIFFS_VIS_COUNTINUE : SPIFFS_VIS_END; - } - 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; - spiffs_ix_map_populate_state state; - vec_entry_start = MIN((u32_t)(map->end_spix - map->start_spix), vec_entry_start); - vec_entry_end = MAX((u32_t)(map->end_spix - map->start_spix), vec_entry_end); - if (vec_entry_start > vec_entry_end) { - return SPIFFS_ERR_IX_MAP_BAD_RANGE; - } - state.map_objix_start_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix + vec_entry_start); - state.map_objix_end_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, map->start_spix + vec_entry_end); - state.remaining_objix_pages_to_visit = - state.map_objix_end_spix - state.map_objix_start_spix + 1; - state.fd = fd; - - res = spiffs_obj_lu_find_entry_visitor( - fs, - SPIFFS_BLOCK_FOR_PAGE(fs, fd->objix_hdr_pix), - SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, fd->objix_hdr_pix), - SPIFFS_VIS_CHECK_ID, - fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, - spiffs_populate_ix_map_v, - 0, - &state, - 0, - 0); - - if (res == SPIFFS_VIS_END) { - res = SPIFFS_OK; - } - - return res; -} - -#endif - - -#if !SPIFFS_READ_ONLY -// 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; -} -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_READ_ONLY -// 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; -} -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_READ_ONLY -// Deletes a page and removes it from object lookup. -s32_t spiffs_page_delete( - spiffs *fs, - spiffs_page_ix pix) { - s32_t res; - // 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 - u8_t flags = 0xff; -#if SPIFFS_NO_BLIND_WRITES - res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_READ, - 0, SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags), - sizeof(flags), &flags); - SPIFFS_CHECK_RES(res); -#endif - flags &= ~(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED); - 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(flags), &flags); - - return res; -} -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_READ_ONLY -// Create an object index header page with empty index and undefined length -s32_t spiffs_object_create( - spiffs *fs, - spiffs_obj_id obj_id, - const u8_t name[], - const u8_t meta[], - 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 @ "_SPIPRIpg" bix:"_SPIPRIbl" entry:"_SPIPRIsp"\n", (spiffs_page_ix)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, (const char*)name, SPIFFS_OBJ_NAME_LEN); -#if SPIFFS_OBJ_META_LEN - if (meta) { - _SPIFFS_MEMCPY(oix_hdr.meta, meta, SPIFFS_OBJ_META_LEN); - } else { - memset(oix_hdr.meta, 0xff, SPIFFS_OBJ_META_LEN); - } -#else - (void) meta; -#endif - - // 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, (spiffs_page_object_ix *)&oix_hdr, - 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; -} -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_READ_ONLY -// 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, - const u8_t name[], - const u8_t meta[], - 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, (const char*)name, SPIFFS_OBJ_NAME_LEN); - } -#if SPIFFS_OBJ_META_LEN - if (meta) { - _SPIFFS_MEMCPY(objix_hdr->meta, meta, SPIFFS_OBJ_META_LEN); - } -#else - (void) meta; -#endif - 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, (spiffs_page_object_ix *)objix_hdr, - new_objix_hdr_data ? SPIFFS_EV_IX_UPD : SPIFFS_EV_IX_UPD_HDR, - 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; -} -#endif // !SPIFFS_READ_ONLY - -void spiffs_cb_object_event( - spiffs *fs, - spiffs_page_object_ix *objix, - int ev, - spiffs_obj_id obj_id_raw, - spiffs_span_ix spix, - spiffs_page_ix new_pix, - u32_t new_size) { -#if SPIFFS_IX_MAP == 0 - (void)objix; -#endif - // update index caches in all file descriptors - spiffs_obj_id obj_id = obj_id_raw & ~SPIFFS_OBJ_ID_IX_FLAG; - u32_t i; - spiffs_fd *fds = (spiffs_fd *)fs->fd_space; - SPIFFS_DBG(" CALLBACK %s obj_id:"_SPIPRIid" spix:"_SPIPRIsp" npix:"_SPIPRIpg" nsz:"_SPIPRIi"\n", (const char *[]){"UPD", "NEW", "DEL", "MOV", "HUP","???"}[MIN(ev,5)], - obj_id_raw, spix, new_pix, new_size); - for (i = 0; i < fs->fd_count; i++) { - spiffs_fd *cur_fd = &fds[i]; - if ((cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue; // fd not related to updated file -#if !SPIFFS_TEMPORAL_FD_CACHE - if (cur_fd->file_nbr == 0) continue; // fd closed -#endif - if (spix == 0) { // object index header update - if (ev != SPIFFS_EV_IX_DEL) { -#if SPIFFS_TEMPORAL_FD_CACHE - if (cur_fd->score == 0) continue; // never used fd -#endif - SPIFFS_DBG(" callback: setting fd "_SPIPRIfd":"_SPIPRIid"(fdoffs:"_SPIPRIi" offs:"_SPIPRIi") objix_hdr_pix to "_SPIPRIpg", size:"_SPIPRIi"\n", - SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, cur_fd->fdoffset, cur_fd->offset, new_pix, new_size); - cur_fd->objix_hdr_pix = new_pix; - if (new_size != 0) { - // update size and offsets for fds to this file - cur_fd->size = new_size; - u32_t act_new_size = new_size == SPIFFS_UNDEFINED_LEN ? 0 : new_size; -#if SPIFFS_CACHE_WR - if (act_new_size > 0 && cur_fd->cache_page) { - act_new_size = MAX(act_new_size, cur_fd->cache_page->offset + cur_fd->cache_page->size); - } -#endif - if (cur_fd->offset > act_new_size) { - cur_fd->offset = act_new_size; - } - if (cur_fd->fdoffset > act_new_size) { - cur_fd->fdoffset = act_new_size; - } -#if SPIFFS_CACHE_WR - if (cur_fd->cache_page && cur_fd->cache_page->offset > act_new_size+1) { - SPIFFS_CACHE_DBG("CACHE_DROP: file trunced, dropping cache page "_SPIPRIi", no writeback\n", cur_fd->cache_page->ix); - spiffs_cache_fd_release(fs, cur_fd->cache_page); - } -#endif - } - } else { - // removing file -#if SPIFFS_CACHE_WR - if (cur_fd->file_nbr && cur_fd->cache_page) { - SPIFFS_CACHE_DBG("CACHE_DROP: file deleted, dropping cache page "_SPIPRIi", no writeback\n", cur_fd->cache_page->ix); - spiffs_cache_fd_release(fs, cur_fd->cache_page); - } -#endif - SPIFFS_DBG(" callback: release fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp" objix_pix to "_SPIPRIpg"\n", SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, spix, new_pix); - cur_fd->file_nbr = 0; - cur_fd->obj_id = SPIFFS_OBJ_ID_DELETED; - } - } // object index header update - if (cur_fd->cursor_objix_spix == spix) { - if (ev != SPIFFS_EV_IX_DEL) { - SPIFFS_DBG(" callback: setting fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp" objix_pix to "_SPIPRIpg"\n", SPIFFS_FH_OFFS(fs, 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; - } - } - } // fd update loop - -#if SPIFFS_IX_MAP - - // update index maps - if (ev == SPIFFS_EV_IX_UPD || ev == SPIFFS_EV_IX_NEW) { - for (i = 0; i < fs->fd_count; i++) { - spiffs_fd *cur_fd = &fds[i]; - // check fd opened, having ix map, match obj id - if (cur_fd->file_nbr == 0 || - cur_fd->ix_map == 0 || - (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue; - SPIFFS_DBG(" callback: map ix update fd "_SPIPRIfd":"_SPIPRIid" span:"_SPIPRIsp"\n", SPIFFS_FH_OFFS(fs, cur_fd->file_nbr), cur_fd->obj_id, spix); - spiffs_update_ix_map(fs, cur_fd, spix, objix); - } - } - -#endif - - // callback to user if object index header - if (fs->file_cb_f && spix == 0 && (obj_id_raw & SPIFFS_OBJ_ID_IX_FLAG)) { - spiffs_fileop_type op; - if (ev == SPIFFS_EV_IX_NEW) { - op = SPIFFS_CB_CREATED; - } else if (ev == SPIFFS_EV_IX_UPD || - ev == SPIFFS_EV_IX_MOV || - ev == SPIFFS_EV_IX_UPD_HDR) { - op = SPIFFS_CB_UPDATED; - } else if (ev == SPIFFS_EV_IX_DEL) { - op = SPIFFS_CB_DELETED; - } else { - SPIFFS_DBG(" callback: WARNING unknown callback event "_SPIPRIi"\n", ev); - return; // bail out - } - fs->file_cb_f(fs, op, obj_id, new_pix); - } -} - -// 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 "_SPIPRIfd" is obj id "_SPIPRIid"\n", SPIFFS_FH_OFFS(fs, fd->file_nbr), fd->obj_id); - - return res; -} - -#if !SPIFFS_READ_ONLY -// 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: "_SPIPRIi" bytes @ offs "_SPIPRIi" of size "_SPIPRIi"\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 "_SPIPRIi"\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: "_SPIPRIid" store objix "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, 0, offset+written, &new_objix_hdr_page); - SPIFFS_CHECK_RES(res); - SPIFFS_DBG("append: "_SPIPRIid" store new objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, (spiffs_page_object_ix *)fs->work, - 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, 0, offset+written, &new_objix_hdr_page); - SPIFFS_CHECK_RES(res); - SPIFFS_DBG("append: "_SPIPRIid" store new size I "_SPIPRIi" in objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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: "_SPIPRIid" load objixhdr page "_SPIPRIpg":"_SPIPRIsp"\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); - // quick "load" of new object index page - memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs)); - _SPIFFS_MEMCPY(fs->work, &p_hdr, sizeof(spiffs_page_header)); - spiffs_cb_object_event(fs, (spiffs_page_object_ix *)fs->work, - SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0); - SPIFFS_DBG("append: "_SPIPRIid" create objix page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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: "_SPIPRIid" find objix span_ix:"_SPIPRIsp"\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: "_SPIPRIid" found object index at page "_SPIPRIpg" [fd size "_SPIPRIi"]\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: "_SPIPRIid" store new data page, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\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: "_SPIPRIid" store to existing data page, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\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: "_SPIPRIid" wrote page "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" 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: "_SPIPRIid" wrote page "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", fd->obj_id - , data_page, (spiffs_span_ix)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: "_SPIPRIid" store objix page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, (spiffs_page_object_ix *)fs->work, - 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, 0, offset+written, &new_objix_hdr_page); - SPIFFS_DBG("append: "_SPIPRIid" store new size II "_SPIPRIi" in objix_hdr, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi", res "_SPIPRIi"\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: "_SPIPRIid" store fresh objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, (spiffs_page_object_ix *)fs->work, - SPIFFS_EV_IX_UPD_HDR, 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, 0, offset+written, &new_objix_hdr_page); - SPIFFS_DBG("append: "_SPIPRIid" store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", fd->obj_id - , new_objix_hdr_page, 0, written); - SPIFFS_CHECK_RES(res2); - } - } - - return res; -} // spiffs_object_append -#endif // !SPIFFS_READ_ONLY - -#if !SPIFFS_READ_ONLY -// 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, 0, &new_objix_hdr_pix); - SPIFFS_DBG("modify: store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, "_SPIPRIid":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_pix, objix->p_hdr.span_ix, written); - SPIFFS_CHECK_RES(res); - spiffs_cb_object_event(fs, (spiffs_page_object_ix *)objix, - 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 "_SPIPRIpg":"_SPIPRIsp"\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:"_SPIPRIsp"\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 "_SPIPRIpg"\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, "_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\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:"_SPIPRIpg", dst:"_SPIPRIpg":"_SPIPRIsp" offset:"_SPIPRIi", len "_SPIPRIi", written "_SPIPRIi"\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 "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" 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 "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", data_pix, (spiffs_span_ix)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, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\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, (spiffs_page_object_ix *)objix, - 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, 0, &new_objix_hdr_pix); - SPIFFS_DBG("modify: store modified objix_hdr page, "_SPIPRIpg":"_SPIPRIsp", written "_SPIPRIi"\n", new_objix_hdr_pix, 0, written); - SPIFFS_CHECK_RES(res2); - } - - return res; -} // spiffs_object_modify -#endif // !SPIFFS_READ_ONLY - -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, - const void *user_const_p, - void *user_var_p) { - (void)user_var_p; - 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 (strcmp((const char*)user_const_p, (char*)objix_hdr.name) == 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, - const 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, - name, - 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; -} - -#if !SPIFFS_READ_ONLY -// 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_full) { - s32_t res = SPIFFS_OK; - spiffs *fs = fd->fs; - - if ((fd->size == SPIFFS_UNDEFINED_LEN || fd->size == 0) && !remove_full) { - // no op - return res; - } - - // need 2 pages if not removing: object index page + possibly chopped data page - if (remove_full == 0) { - res = spiffs_gc_check(fs, SPIFFS_DATA_PAGE_SIZE(fs) * 2); - 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_full && 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 "_SPIPRIpg":"_SPIPRIsp"\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, (spiffs_page_object_ix *)0, - 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, unless we totally want to remove the file. - // If fully removing, we're not keeping consistency as good as when storing the header between chunks, - // would we be aborted. But when removing full files, a crammed system may otherwise - // report ERR_FULL a la windows. We cannot have that. - // Hence, take the risk - if aborted, a file check would free the lost pages and mend things - // as the file is marked as fully deleted in the beginning. - if (remove_full == 0) { - SPIFFS_DBG("truncate: update objix hdr page "_SPIPRIpg":"_SPIPRIsp" to size "_SPIPRIi"\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, 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 "_SPIPRIpg":"_SPIPRIsp" for data spix:"_SPIPRIsp"\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 "_SPIPRIpg"\n", data_pix); - - if (new_size == 0 || remove_full || cur_size - new_size >= SPIFFS_DATA_PAGE_SIZE(fs)) { - // 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 "_SPIPRIi"\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 "_SPIPRIi"\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 "_SPIPRIpg" for data spix:"_SPIPRIsp", cur_size:"_SPIPRIi"\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 "_SPIPRIi" bytes from data page "_SPIPRIpg" for data spix:"_SPIPRIsp", cur_size:"_SPIPRIi"\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 "_SPIPRIpg" to objix_hdr entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)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 "_SPIPRIpg" to objix entry "_SPIPRIsp" in mem\n", new_data_pix, (spiffs_span_ix)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_full) { - // remove object altogether - SPIFFS_DBG("truncate: remove object index header page "_SPIPRIpg"\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, (spiffs_page_object_ix *)0, - SPIFFS_EV_IX_DEL, fd->obj_id, 0, objix_pix, 0); - } else { - // make uninitialized object - SPIFFS_DBG("truncate: reset objix_hdr page "_SPIPRIpg"\n", objix_pix); - 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, 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, 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, (spiffs_page_object_ix *)objix_hdr, - SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0); - SPIFFS_DBG("truncate: store modified objix page, "_SPIPRIpg":"_SPIPRIsp"\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, 0, cur_size, &new_objix_hdr_pix); - SPIFFS_CHECK_RES(res); - } - fd->size = cur_size; - - return res; -} // spiffs_object_truncate -#endif // !SPIFFS_READ_ONLY - -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) { -#if SPIFFS_IX_MAP - // check if we have a memory, index map and if so, if we're within index map's range - // and if so, if the entry is populated - if (fd->ix_map && data_spix >= fd->ix_map->start_spix && data_spix <= fd->ix_map->end_spix - && fd->ix_map->map_buf[data_spix - fd->ix_map->start_spix]) { - data_pix = fd->ix_map->map_buf[data_spix - fd->ix_map->start_spix]; - } else { -#endif - 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 "_SPIPRIid":"_SPIPRIsp"\n", fd->obj_id, cur_objix_spix); - if (fd->cursor_objix_spix == cur_objix_spix) { - objix_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, &objix_pix); - SPIFFS_CHECK_RES(res); - } - } - SPIFFS_DBG("read: load objix page "_SPIPRIpg":"_SPIPRIsp" for data spix:"_SPIPRIsp"\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)]; - } -#if SPIFFS_IX_MAP - } -#endif - // 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:"_SPIPRIi" rd:"_SPIPRIi" data spix:"_SPIPRIsp" is data_pix:"_SPIPRIpg" addr:"_SPIPRIad"\n", cur_offset, len_to_read, data_spix, data_pix, - (u32_t)(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; -} - -#if !SPIFFS_READ_ONLY -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, - const void *user_const_p, void *user_var_p) { - if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) { - spiffs_obj_id min_obj_id = *((spiffs_obj_id*)user_var_p); - const u8_t *conflicting_name = (const u8_t*)user_const_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 (strcmp((const char*)user_const_p, (char*)objix_hdr.name) == 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<conflicting_name && strcmp((const char *)state->conflicting_name, (char *)objix_hdr.name) == 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 "_SPIPRIi" for id "_SPIPRIid" min"_SPIPRIid" max"_SPIPRIid" comp:"_SPIPRIi"\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 bitmask is searched for a free id -s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, const u8_t *conflicting_name) { - s32_t res = SPIFFS_OK; - u32_t max_objects = (fs->block_count * SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(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:"_SPIPRIid" max:"_SPIPRIid"\n", state.min_obj_id, state.max_obj_id); - - 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, - conflicting_name, &state.min_obj_id, 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<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:"_SPIPRIi" min_count:"_SPIPRIi" min:"_SPIPRIid" max:"_SPIPRIid" compact:"_SPIPRIi"\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:"_SPIPRIi" min:"_SPIPRIid" -> "_SPIPRIid"\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:"_SPIPRIid" max:"_SPIPRIid" compact:"_SPIPRIi"\n", state.min_obj_id, state.max_obj_id, state.compaction); - - 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, &state, 0, 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; -} -#endif // !SPIFFS_READ_ONLY - -#if SPIFFS_TEMPORAL_FD_CACHE -// djb2 hash -static u32_t spiffs_hash(spiffs *fs, const u8_t *name) { - (void)fs; - u32_t hash = 5381; - u8_t c; - int i = 0; - while ((c = name[i++]) && i < SPIFFS_OBJ_NAME_LEN) { - hash = (hash * 33) ^ c; - } - return hash; -} -#endif - -s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) { -#if SPIFFS_TEMPORAL_FD_CACHE - u32_t i; - u16_t min_score = 0xffff; - u32_t cand_ix = (u32_t)-1; - u32_t name_hash = name ? spiffs_hash(fs, (const u8_t *)name) : 0; - spiffs_fd *fds = (spiffs_fd *)fs->fd_space; - - if (name) { - // first, decrease score of all closed descriptors - for (i = 0; i < fs->fd_count; i++) { - spiffs_fd *cur_fd = &fds[i]; - if (cur_fd->file_nbr == 0) { - if (cur_fd->score > 1) { // score == 0 indicates never used fd - cur_fd->score--; - } - } - } - } - - // find the free fd with least score or name match - for (i = 0; i < fs->fd_count; i++) { - spiffs_fd *cur_fd = &fds[i]; - if (cur_fd->file_nbr == 0) { - if (name && cur_fd->name_hash == name_hash) { - cand_ix = i; - break; - } - if (cur_fd->score < min_score) { - min_score = cur_fd->score; - cand_ix = i; - } - } - } - - if (cand_ix != (u32_t)-1) { - spiffs_fd *cur_fd = &fds[cand_ix]; - if (name) { - if (cur_fd->name_hash == name_hash && cur_fd->score > 0) { - // opened an fd with same name hash, assume same file - // set search point to saved obj index page and hope we have a correct match directly - // when start searching - if not, we will just keep searching until it is found - fs->cursor_block_ix = SPIFFS_BLOCK_FOR_PAGE(fs, cur_fd->objix_hdr_pix); - fs->cursor_obj_lu_entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, cur_fd->objix_hdr_pix); - // update score - if (cur_fd->score < 0xffff-SPIFFS_TEMPORAL_CACHE_HIT_SCORE) { - cur_fd->score += SPIFFS_TEMPORAL_CACHE_HIT_SCORE; - } else { - cur_fd->score = 0xffff; - } - } else { - // no hash hit, restore this fd to initial state - cur_fd->score = SPIFFS_TEMPORAL_CACHE_HIT_SCORE; - cur_fd->name_hash = name_hash; - } - } - cur_fd->file_nbr = cand_ix+1; - *fd = cur_fd; - return SPIFFS_OK; - } else { - return SPIFFS_ERR_OUT_OF_FILE_DESCS; - } -#else - (void)name; - 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; -#endif -} - -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; -#if SPIFFS_IX_MAP - fd->ix_map = 0; -#endif - 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; -} - -#if SPIFFS_TEMPORAL_FD_CACHE -void spiffs_fd_temporal_cache_rehash( - spiffs *fs, - const char *old_path, - const char *new_path) { - u32_t i; - u32_t old_hash = spiffs_hash(fs, (const u8_t *)old_path); - u32_t new_hash = spiffs_hash(fs, (const u8_t *)new_path); - 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->score > 0 && cur_fd->name_hash == old_hash) { - cur_fd->name_hash = new_hash; - } - } -} -#endif diff --git a/src/spiffs/spiffs_nucleus.h b/src/spiffs/spiffs_nucleus.h deleted file mode 100644 index b6165c2..0000000 --- a/src/spiffs/spiffs_nucleus.h +++ /dev/null @@ -1,842 +0,0 @@ -/* - * spiffs_nucleus.h - * - * Created on: Jun 15, 2013 - * Author: petera - */ - -/* SPIFFS layout - * - * spiffs is designed for following spi flash characteristics: - * - only big areas of data (blocks) can be erased - * - erasing resets all bits in a block to ones - * - writing pulls ones to zeroes - * - zeroes cannot be pulled to ones, without erase - * - wear leveling - * - * spiffs is also meant to be run on embedded, memory constraint devices. - * - * Entire area is divided in blocks. Entire area is also divided in pages. - * Each block contains same number of pages. A page cannot be erased, but a - * block can be erased. - * - * Entire area must be block_size * x - * page_size must be block_size / (2^y) where y > 2 - * - * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes - * - * BLOCK 0 PAGE 0 object lookup 1 - * PAGE 1 object lookup 2 - * ... - * PAGE n-1 object lookup n - * PAGE n object data 1 - * PAGE n+1 object data 2 - * ... - * PAGE n+m-1 object data m - * - * BLOCK 1 PAGE n+m object lookup 1 - * PAGE n+m+1 object lookup 2 - * ... - * PAGE 2n+m-1 object lookup n - * PAGE 2n+m object data 1 - * PAGE 2n+m object data 2 - * ... - * PAGE 2n+2m-1 object data m - * ... - * - * n is number of object lookup pages, which is number of pages needed to index all pages - * in a block by object id - * : block_size / page_size * sizeof(obj_id) / page_size - * m is number data pages, which is number of pages in block minus number of lookup pages - * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size - * thus, n+m is total number of pages in a block - * : block_size / page_size - * - * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256 - * - * Object lookup pages contain object id entries. Each entry represent the corresponding - * data page. - * Assuming a 16 bit object id, an object id being 0xffff represents a free page. - * An object id being 0x0000 represents a deleted page. - * - * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff .. - * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff .. - * page 2 : data : data for object id 0008 - * page 3 : data : data for object id 0001 - * page 4 : data : data for object id 0aaa - * ... - * - * - * Object data pages can be either object index pages or object content. - * All object data pages contains a data page header, containing object id and span index. - * The span index denotes the object page ordering amongst data pages with same object id. - * This applies to both object index pages (when index spans more than one page of entries), - * and object data pages. - * An object index page contains page entries pointing to object content page. The entry index - * in a object index page correlates to the span index in the actual object data page. - * The first object index page (span index 0) is called object index header page, and also - * contains object flags (directory/file), size, object name etc. - * - * ex: - * BLOCK 1 - * PAGE 256: objectl lookup page 1 - * [*123] [ 123] [ 123] [ 123] - * [ 123] [*123] [ 123] [ 123] - * [free] [free] [free] [free] ... - * PAGE 257: objectl lookup page 2 - * [free] [free] [free] [free] ... - * PAGE 258: object index page (header) - * obj.id:0123 span.ix:0000 flags:INDEX - * size:1600 name:ex.txt type:file - * [259] [260] [261] [262] - * PAGE 259: object data page - * obj.id:0123 span.ix:0000 flags:DATA - * PAGE 260: object data page - * obj.id:0123 span.ix:0001 flags:DATA - * PAGE 261: object data page - * obj.id:0123 span.ix:0002 flags:DATA - * PAGE 262: object data page - * obj.id:0123 span.ix:0003 flags:DATA - * PAGE 263: object index page - * obj.id:0123 span.ix:0001 flags:INDEX - * [264] [265] [fre] [fre] - * [fre] [fre] [fre] [fre] - * PAGE 264: object data page - * obj.id:0123 span.ix:0004 flags:DATA - * PAGE 265: object data page - * obj.id:0123 span.ix:0005 flags:DATA - * - */ -#ifndef SPIFFS_NUCLEUS_H_ -#define SPIFFS_NUCLEUS_H_ - -#define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1) -#define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1) -#define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2) -#define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3) -#define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4) - -// visitor result, continue searching -#define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20) -// visitor result, continue searching after reloading lu buffer -#define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21) -// visitor result, stop searching -#define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22) - -// updating an object index contents -#define SPIFFS_EV_IX_UPD (0) -// creating a new object index -#define SPIFFS_EV_IX_NEW (1) -// deleting an object index -#define SPIFFS_EV_IX_DEL (2) -// moving an object index without updating contents -#define SPIFFS_EV_IX_MOV (3) -// updating an object index header data only, not the table itself -#define SPIFFS_EV_IX_UPD_HDR (4) - -#define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1))) - -#define SPIFFS_UNDEFINED_LEN (u32_t)(-1) - -#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0) -#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1) - - - -#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__) - /* For GCC, clang and TI compilers */ -#define SPIFFS_PACKED __attribute__((packed)) -#elif defined(__ICCARM__) || defined(__CC_ARM) - /* For IAR ARM and Keil MDK-ARM compilers */ -#define SPIFFS_PACKED - -#else - /* Unknown compiler */ -#define SPIFFS_PACKED -#endif - - - -#if SPIFFS_USE_MAGIC -#if !SPIFFS_USE_MAGIC_LENGTH -#define SPIFFS_MAGIC(fs, bix) \ - ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs))) -#else // SPIFFS_USE_MAGIC_LENGTH -#define SPIFFS_MAGIC(fs, bix) \ - ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix)))) -#endif // SPIFFS_USE_MAGIC_LENGTH -#endif // SPIFFS_USE_MAGIC - -#define SPIFFS_CONFIG_MAGIC (0x20090315) - -#if SPIFFS_SINGLETON == 0 -#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \ - ((fs)->cfg.log_page_size) -#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \ - ((fs)->cfg.log_block_size) -#define SPIFFS_CFG_PHYS_SZ(fs) \ - ((fs)->cfg.phys_size) -#define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \ - ((fs)->cfg.phys_erase_block) -#define SPIFFS_CFG_PHYS_ADDR(fs) \ - ((fs)->cfg.phys_addr) -#endif - -// total number of pages -#define SPIFFS_MAX_PAGES(fs) \ - ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// total number of pages per block, including object lookup pages -#define SPIFFS_PAGES_PER_BLOCK(fs) \ - ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// number of object lookup pages per block -#define SPIFFS_OBJ_LOOKUP_PAGES(fs) \ - (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) ) -// checks if page index belongs to object lookup -#define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \ - (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) -// number of object lookup entries in all object lookup pages -#define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \ - (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) -// converts a block to physical address -#define SPIFFS_BLOCK_TO_PADDR(fs, block) \ - ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) ) -// converts a object lookup entry to page index -#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \ - ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry)) -// converts a object lookup entry to physical address of corresponding page -#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \ - (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// converts a page to physical address -#define SPIFFS_PAGE_TO_PADDR(fs, page) \ - ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// converts a physical address to page -#define SPIFFS_PADDR_TO_PAGE(fs, addr) \ - ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// gives index in page for a physical address -#define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \ - ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) ) -// returns containing block for given page -#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \ - ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) ) -// returns starting page for block -#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \ - ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) ) -// converts page to entry in object lookup page -#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \ - ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) ) -// returns data size in a data page -#define SPIFFS_DATA_PAGE_SIZE(fs) \ - ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) ) -// returns physical address for block's erase count, -// always in the physical last entry of the last object lookup page -#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \ - ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) ) -// returns physical address for block's magic, -// always in the physical second last entry of the last object lookup page -#define SPIFFS_MAGIC_PADDR(fs, bix) \ - ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 ) -// checks if there is any room for magic in the object luts -#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \ - ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \ - <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) ) - -// define helpers object - -// entries in an object header page index -#define SPIFFS_OBJ_HDR_IX_LEN(fs) \ - ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix)) -// entries in an object page index -#define SPIFFS_OBJ_IX_LEN(fs) \ - ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix)) -// object index entry for given data span index -#define SPIFFS_OBJ_IX_ENTRY(fs, spix) \ - ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs))) -// object index span index number for given data span index or entry -#define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \ - ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs))) -// get data span index for object index span index -#define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \ - ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) ) - -#if SPIFFS_FILEHDL_OFFSET -#define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0) -#define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0) -#else -#define SPIFFS_FH_OFFS(fs, fh) (fh) -#define SPIFFS_FH_UNOFFS(fs, fh) (fh) -#endif - - -#define SPIFFS_OP_T_OBJ_LU (0<<0) -#define SPIFFS_OP_T_OBJ_LU2 (1<<0) -#define SPIFFS_OP_T_OBJ_IX (2<<0) -#define SPIFFS_OP_T_OBJ_DA (3<<0) -#define SPIFFS_OP_C_DELE (0<<2) -#define SPIFFS_OP_C_UPDT (1<<2) -#define SPIFFS_OP_C_MOVS (2<<2) -#define SPIFFS_OP_C_MOVD (3<<2) -#define SPIFFS_OP_C_FLSH (4<<2) -#define SPIFFS_OP_C_READ (5<<2) -#define SPIFFS_OP_C_WRTHRU (6<<2) - -#define SPIFFS_OP_TYPE_MASK (3<<0) -#define SPIFFS_OP_COM_MASK (7<<2) - - -// if 0, this page is written to, else clean -#define SPIFFS_PH_FLAG_USED (1<<0) -// if 0, writing is finalized, else under modification -#define SPIFFS_PH_FLAG_FINAL (1<<1) -// if 0, this is an index page, else a data page -#define SPIFFS_PH_FLAG_INDEX (1<<2) -// if 0, page is deleted, else valid -#define SPIFFS_PH_FLAG_DELET (1<<7) -// if 0, this index header is being deleted -#define SPIFFS_PH_FLAG_IXDELE (1<<6) - - -#define SPIFFS_CHECK_MOUNT(fs) \ - ((fs)->mounted != 0) - -#define SPIFFS_CHECK_CFG(fs) \ - ((fs)->config_magic == SPIFFS_CONFIG_MAGIC) - -#define SPIFFS_CHECK_RES(res) \ - do { \ - if ((res) < SPIFFS_OK) return (res); \ - } while (0); - -#define SPIFFS_API_CHECK_MOUNT(fs) \ - if (!SPIFFS_CHECK_MOUNT((fs))) { \ - (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \ - return SPIFFS_ERR_NOT_MOUNTED; \ - } - -#define SPIFFS_API_CHECK_CFG(fs) \ - if (!SPIFFS_CHECK_CFG((fs))) { \ - (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \ - return SPIFFS_ERR_NOT_CONFIGURED; \ - } - -#define SPIFFS_API_CHECK_RES(fs, res) \ - if ((res) < SPIFFS_OK) { \ - (fs)->err_code = (res); \ - return (res); \ - } - -#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \ - if ((res) < SPIFFS_OK) { \ - (fs)->err_code = (res); \ - SPIFFS_UNLOCK(fs); \ - return (res); \ - } - -#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \ - if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \ - if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \ - if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \ - if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \ - if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \ - if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH; - //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED; - -#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \ - if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \ - if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \ - if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \ - if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \ - if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \ - if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH; - - -// check id, only visit matching objec ids -#define SPIFFS_VIS_CHECK_ID (1<<0) -// report argument object id to visitor - else object lookup id is reported -#define SPIFFS_VIS_CHECK_PH (1<<1) -// stop searching at end of all look up pages -#define SPIFFS_VIS_NO_WRAP (1<<2) - -#if SPIFFS_HAL_CALLBACK_EXTRA - -#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \ - (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src)) -#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \ - (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst)) -#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \ - (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len)) - -#else // SPIFFS_HAL_CALLBACK_EXTRA - -#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \ - (_fs)->cfg.hal_write_f((_paddr), (_len), (_src)) -#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \ - (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst)) -#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \ - (_fs)->cfg.hal_erase_f((_paddr), (_len)) - -#endif // SPIFFS_HAL_CALLBACK_EXTRA - -#if SPIFFS_CACHE - -#define SPIFFS_CACHE_FLAG_DIRTY (1<<0) -#define SPIFFS_CACHE_FLAG_WRTHRU (1<<1) -#define SPIFFS_CACHE_FLAG_OBJLU (1<<2) -#define SPIFFS_CACHE_FLAG_OBJIX (1<<3) -#define SPIFFS_CACHE_FLAG_DATA (1<<4) -#define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7) - -#define SPIFFS_CACHE_PAGE_SIZE(fs) \ - (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs)) - -#define spiffs_get_cache(fs) \ - ((spiffs_cache *)((fs)->cache)) - -#define spiffs_get_cache_page_hdr(fs, c, ix) \ - ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)]))) - -#define spiffs_get_cache_page(fs, c, ix) \ - ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page)) - -// cache page struct -typedef struct { - // cache flags - u8_t flags; - // cache page index - u8_t ix; - // last access of this cache page - u32_t last_access; - union { - // type read cache - struct { - // read cache page index - spiffs_page_ix pix; - }; -#if SPIFFS_CACHE_WR - // type write cache - struct { - // write cache - spiffs_obj_id obj_id; - // offset in cache page - u32_t offset; - // size of cache page - u16_t size; - }; -#endif - }; -} spiffs_cache_page; - -// cache struct -typedef struct { - u8_t cpage_count; - u32_t last_access; - u32_t cpage_use_map; - u32_t cpage_use_mask; - u8_t *cpages; -} spiffs_cache; - -#endif - - -// spiffs nucleus file descriptor -typedef struct { - // the filesystem of this descriptor - spiffs *fs; - // number of file descriptor - if 0, the file descriptor is closed - spiffs_file file_nbr; - // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted - spiffs_obj_id obj_id; - // size of the file - u32_t size; - // cached object index header page index - spiffs_page_ix objix_hdr_pix; - // cached offset object index page index - spiffs_page_ix cursor_objix_pix; - // cached offset object index span index - spiffs_span_ix cursor_objix_spix; - // current absolute offset - u32_t offset; - // current file descriptor offset (cached) - u32_t fdoffset; - // fd flags - spiffs_flags flags; -#if SPIFFS_CACHE_WR - spiffs_cache_page *cache_page; -#endif -#if SPIFFS_TEMPORAL_FD_CACHE - // djb2 hash of filename - u32_t name_hash; - // hit score (score == 0 indicates never used fd) - u16_t score; -#endif -#if SPIFFS_IX_MAP - // spiffs index map, if 0 it means unmapped - spiffs_ix_map *ix_map; -#endif -} spiffs_fd; - - -// object structs - -// page header, part of each page except object lookup pages -// NB: this is always aligned when the data page is an object index, -// as in this case struct spiffs_page_object_ix is used -typedef struct SPIFFS_PACKED { - // object id - spiffs_obj_id obj_id; - // object span index - spiffs_span_ix span_ix; - // flags - u8_t flags; -} spiffs_page_header; - -// object index header page header -typedef struct SPIFFS_PACKED -#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES - __attribute(( aligned(sizeof(spiffs_page_ix)) )) -#endif -{ - // common page header - spiffs_page_header p_hdr; - // alignment - u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))]; - // size of object - u32_t size; - // type of object - spiffs_obj_type type; - // name of object - u8_t name[SPIFFS_OBJ_NAME_LEN]; -#if SPIFFS_OBJ_META_LEN - // metadata. not interpreted by SPIFFS in any way. - u8_t meta[SPIFFS_OBJ_META_LEN]; -#endif -} spiffs_page_object_ix_header; - -// object index page header -typedef struct SPIFFS_PACKED { - spiffs_page_header p_hdr; - u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))]; -} spiffs_page_object_ix; - -// callback func for object lookup visitor -typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry, - const void *user_const_p, void *user_var_p); - - -#if SPIFFS_CACHE -#define _spiffs_rd(fs, op, fh, addr, len, dst) \ - spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst)) -#define _spiffs_wr(fs, op, fh, addr, len, src) \ - spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src)) -#else -#define _spiffs_rd(fs, op, fh, addr, len, dst) \ - spiffs_phys_rd((fs), (addr), (len), (dst)) -#define _spiffs_wr(fs, op, fh, addr, len, src) \ - spiffs_phys_wr((fs), (addr), (len), (src)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -// --------------- - -s32_t spiffs_phys_rd( - spiffs *fs, -#if SPIFFS_CACHE - u8_t op, - spiffs_file fh, -#endif - u32_t addr, - u32_t len, - u8_t *dst); - -s32_t spiffs_phys_wr( - spiffs *fs, -#if SPIFFS_CACHE - u8_t op, - spiffs_file fh, -#endif - u32_t addr, - u32_t len, - u8_t *src); - -s32_t spiffs_phys_cpy( - spiffs *fs, - spiffs_file fh, - u32_t dst, - u32_t src, - u32_t len); - -s32_t spiffs_phys_count_free_blocks( - spiffs *fs); - -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, - const void *user_const_p, - void *user_var_p, - spiffs_block_ix *block_ix, - int *lu_entry); - -s32_t spiffs_erase_block( - spiffs *fs, - spiffs_block_ix bix); - -#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH -s32_t spiffs_probe( - spiffs_config *cfg); -#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH - -// --------------- - -s32_t spiffs_obj_lu_scan( - spiffs *fs); - -s32_t spiffs_obj_lu_find_free_obj_id( - spiffs *fs, - spiffs_obj_id *obj_id, - const u8_t *conflicting_name); - -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 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 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 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 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 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 spiffs_page_delete( - spiffs *fs, - spiffs_page_ix pix); - -// --------------- - -s32_t spiffs_object_create( - spiffs *fs, - spiffs_obj_id obj_id, - const u8_t name[], - const u8_t meta[], - spiffs_obj_type type, - spiffs_page_ix *objix_hdr_pix); - -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, - const u8_t name[], - const u8_t meta[], - u32_t size, - spiffs_page_ix *new_pix); - -#if SPIFFS_IX_MAP - -s32_t spiffs_populate_ix_map( - spiffs *fs, - spiffs_fd *fd, - u32_t vec_entry_start, - u32_t vec_entry_end); - -#endif - -void spiffs_cb_object_event( - spiffs *fs, - spiffs_page_object_ix *objix, - int ev, - spiffs_obj_id obj_id, - spiffs_span_ix spix, - spiffs_page_ix new_pix, - u32_t new_size); - -s32_t spiffs_object_open_by_id( - spiffs *fs, - spiffs_obj_id obj_id, - spiffs_fd *f, - spiffs_flags flags, - spiffs_mode mode); - -s32_t spiffs_object_open_by_page( - spiffs *fs, - spiffs_page_ix pix, - spiffs_fd *f, - spiffs_flags flags, - spiffs_mode mode); - -s32_t spiffs_object_append( - spiffs_fd *fd, - u32_t offset, - u8_t *data, - u32_t len); - -s32_t spiffs_object_modify( - spiffs_fd *fd, - u32_t offset, - u8_t *data, - u32_t len); - -s32_t spiffs_object_read( - spiffs_fd *fd, - u32_t offset, - u32_t len, - u8_t *dst); - -s32_t spiffs_object_truncate( - spiffs_fd *fd, - u32_t new_len, - u8_t remove_object); - -s32_t spiffs_object_find_object_index_header_by_name( - spiffs *fs, - const u8_t name[SPIFFS_OBJ_NAME_LEN], - spiffs_page_ix *pix); - -// --------------- - -s32_t spiffs_gc_check( - spiffs *fs, - u32_t len); - -s32_t spiffs_gc_erase_page_stats( - spiffs *fs, - spiffs_block_ix bix); - -s32_t spiffs_gc_find_candidate( - spiffs *fs, - spiffs_block_ix **block_candidate, - int *candidate_count, - char fs_crammed); - -s32_t spiffs_gc_clean( - spiffs *fs, - spiffs_block_ix bix); - -s32_t spiffs_gc_quick( - spiffs *fs, u16_t max_free_pages); - -// --------------- - -s32_t spiffs_fd_find_new( - spiffs *fs, - spiffs_fd **fd, - const char *name); - -s32_t spiffs_fd_return( - spiffs *fs, - spiffs_file f); - -s32_t spiffs_fd_get( - spiffs *fs, - spiffs_file f, - spiffs_fd **fd); - -#if SPIFFS_TEMPORAL_FD_CACHE -void spiffs_fd_temporal_cache_rehash( - spiffs *fs, - const char *old_path, - const char *new_path); -#endif - -#if SPIFFS_CACHE -void spiffs_cache_init( - spiffs *fs); - -void spiffs_cache_drop_page( - spiffs *fs, - spiffs_page_ix pix); - -#if SPIFFS_CACHE_WR -spiffs_cache_page *spiffs_cache_page_allocate_by_fd( - spiffs *fs, - spiffs_fd *fd); - -void spiffs_cache_fd_release( - spiffs *fs, - spiffs_cache_page *cp); - -spiffs_cache_page *spiffs_cache_page_get_by_fd( - spiffs *fs, - spiffs_fd *fd); -#endif -#endif - -s32_t spiffs_lookup_consistency_check( - spiffs *fs, - u8_t check_all_objects); - -s32_t spiffs_page_consistency_check( - spiffs *fs); - -s32_t spiffs_object_index_consistency_check( - spiffs *fs); - -// memcpy macro, -// checked in test builds, otherwise plain memcpy (unless already defined) -#ifdef _SPIFFS_TEST -#define _SPIFFS_MEMCPY(__d, __s, __l) do { \ - intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \ - intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \ - intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \ - intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \ - if (__a1 <= __b2 && __b1 <= __a2) { \ - printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \ - ERREXIT(); \ - } \ - memcpy((__d),(__s),(__l)); \ -} while (0) -#else -#ifndef _SPIFFS_MEMCPY -#define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0) -#endif -#endif //_SPIFFS_TEST - -#endif /* SPIFFS_NUCLEUS_H_ */ diff --git a/src/spiffs/test/main.c b/src/spiffs/test/main.c deleted file mode 100644 index 4d363d5..0000000 --- a/src/spiffs/test/main.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#ifndef NO_TEST -#include "testrunner.h" -#endif - -int main(int argc, char **args) { -#ifndef NO_TEST - run_tests(argc, args); -#endif - exit(EXIT_SUCCESS); -} diff --git a/src/spiffs/test/params_test.h b/src/spiffs/test/params_test.h deleted file mode 100644 index 74f553f..0000000 --- a/src/spiffs/test/params_test.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * params_test.h - * - * Created on: May 26, 2013 - * Author: petera - */ - -#ifndef PARAMS_TEST_H_ -#define PARAMS_TEST_H_ - -//////////////// TEST PARAMS //////////////// - -// default test total emulated spi flash size -#define PHYS_FLASH_SIZE (16*1024*1024) -// default test spiffs file system size -#define SPIFFS_FLASH_SIZE (2*1024*1024) -// default test spiffs file system offset in emulated spi flash -#define SPIFFS_PHYS_ADDR (4*1024*1024) -// default test sector size -#define SECTOR_SIZE 65536 -// default test logical block size -#define LOG_BLOCK (SECTOR_SIZE*2) -// default test logical page size -#define LOG_PAGE (SECTOR_SIZE/256) -// default test number of filedescs -#define DEFAULT_NUM_FD 16 -// default test number of cache pages -#define DEFAULT_NUM_CACHE_PAGES 8 - -// When testing, test bench create reference files for comparison on -// the actual hard drive. By default, put these on ram drive for speed. -#define TEST_PATH "/dev/shm/spiffs/test-data/" - -#define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__); -void real_assert(int c, const char *n, const char *file, int l); - -/////////// SPIFFS BUILD CONFIG //////////// - -// test using filesystem magic -#ifndef SPIFFS_USE_MAGIC -#define SPIFFS_USE_MAGIC 1 -#endif -// test using filesystem magic length -#ifndef SPIFFS_USE_MAGIC_LENGTH -#define SPIFFS_USE_MAGIC_LENGTH 1 -#endif -// test using extra param in callback -#ifndef SPIFFS_HAL_CALLBACK_EXTRA -#define SPIFFS_HAL_CALLBACK_EXTRA 1 -#endif -// test using filehandle offset -#ifndef SPIFFS_FILEHDL_OFFSET -#define SPIFFS_FILEHDL_OFFSET 1 -// use this offset -#define TEST_SPIFFS_FILEHDL_OFFSET 0x1000 -#endif - -#ifdef NO_TEST -#define SPIFFS_LOCK(fs) -#define SPIFFS_UNLOCK(fs) -#else -struct spiffs_t; -extern void test_lock(struct spiffs_t *fs); -extern void test_unlock(struct spiffs_t *fs); -#define SPIFFS_LOCK(fs) test_lock(fs) -#define SPIFFS_UNLOCK(fs) test_unlock(fs) -#endif - -// dbg output -#define SPIFFS_DBG(_f, ...) //printf("\x1b[32m" _f "\x1b[0m", ## __VA_ARGS__) -#define SPIFFS_API_DBG(_f, ...) //printf("\n\x1b[1m\x1b[7m" _f "\x1b[0m", ## __VA_ARGS__) -#define SPIFFS_GC_DBG(_f, ...) //printf("\x1b[36m" _f "\x1b[0m", ## __VA_ARGS__) -#define SPIFFS_CACHE_DBG(_f, ...) //printf("\x1b[33m" _f "\x1b[0m", ## __VA_ARGS__) -#define SPIFFS_CHECK_DBG(_f, ...) //printf("\x1b[31m" _f "\x1b[0m", ## __VA_ARGS__) - -// needed types -typedef signed int s32_t; -typedef unsigned int u32_t; -typedef signed short s16_t; -typedef unsigned short u16_t; -typedef signed char s8_t; -typedef unsigned char u8_t; - -#endif /* PARAMS_TEST_H_ */ diff --git a/src/spiffs/test/test_bugreports.c b/src/spiffs/test/test_bugreports.c deleted file mode 100644 index e9b59d1..0000000 --- a/src/spiffs/test/test_bugreports.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * test_bugreports.c - * - * Created on: Mar 8, 2015 - * Author: petera - */ - - - -#include "testrunner.h" -#include "test_spiffs.h" -#include "spiffs_nucleus.h" -#include "spiffs.h" -#include -#include -#include -#include -#include - -/* The follow defines control details of how the fuzzer can exercise the API. If you - * undef any of these, then the fuzzer is less brutal. FOr example, if you undef - * HAVE_REMOVE_OPEN, then the fuzzer will not attempt to remove (or rename) an open file - */ -#define HAVE_REMOVE_OPEN -#define HAVE_MULTIPLE_OPEN -#define NO_FORCE_CHECK - -SUITE(bug_tests) -static void setup() { - _setup_test_only(); -} -static void teardown() { - _teardown(); -} - -TEST(nodemcu_full_fs_1) { - fs_reset_specific(0, 0, 4096*20, 4096, 4096, 256); - - int res; - spiffs_file fd; - - printf(" fill up system by writing one byte a lot\n"); - fd = SPIFFS_open(FS, "test1.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - int i; - spiffs_stat s; - res = SPIFFS_OK; - for (i = 0; i < 100*1000; i++) { - u8_t buf = 'x'; - res = SPIFFS_write(FS, fd, &buf, 1); - } - - int errno = SPIFFS_errno(FS); - int res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 == SPIFFS_OK); - printf(" >>> file %s size: %i\n", s.name, s.size); - - TEST_CHECK(errno == SPIFFS_ERR_FULL); - SPIFFS_close(FS, fd); - - printf(" remove big file\n"); - res = SPIFFS_remove(FS, "test1.txt"); - - printf("res:%i errno:%i\n",res, SPIFFS_errno(FS)); - - TEST_CHECK(res == SPIFFS_OK); - res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res2 = SPIFFS_stat(FS, "test1.txt", &s); - TEST_CHECK(res2 < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_FOUND); - - printf(" create small file\n"); - fd = SPIFFS_open(FS, "test2.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_OK; - for (i = 0; res >= 0 && i < 1000; i++) { - u8_t buf = 'x'; - res = SPIFFS_write(FS, fd, &buf, 1); - } - TEST_CHECK(res >= SPIFFS_OK); - - res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 == SPIFFS_OK); - printf(" >>> file %s size: %i\n", s.name, s.size); - - TEST_CHECK(s.size == 1000); - SPIFFS_close(FS, fd); - - return TEST_RES_OK; - -} TEST_END - -TEST(nodemcu_full_fs_2) { - fs_reset_specific(0, 0, 4096*22, 4096, 4096, 256); - - int res; - spiffs_file fd; - - printf(" fill up system by writing one byte a lot\n"); - fd = SPIFFS_open(FS, "test1.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - int i; - spiffs_stat s; - res = SPIFFS_OK; - for (i = 0; i < 100*1000; i++) { - u8_t buf = 'x'; - res = SPIFFS_write(FS, fd, &buf, 1); - } - - int errno = SPIFFS_errno(FS); - int res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 == SPIFFS_OK); - printf(" >>> file %s size: %i\n", s.name, s.size); - - TEST_CHECK(errno == SPIFFS_ERR_FULL); - SPIFFS_close(FS, fd); - - res2 = SPIFFS_stat(FS, "test1.txt", &s); - TEST_CHECK(res2 == SPIFFS_OK); - - SPIFFS_clearerr(FS); - printf(" create small file\n"); - fd = SPIFFS_open(FS, "test2.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); -#if 0 - // before gc in v3.1 - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_OK); - TEST_CHECK(fd > 0); - - for (i = 0; i < 1000; i++) { - u8_t buf = 'x'; - res = SPIFFS_write(FS, fd, &buf, 1); - } - - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FULL); - res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 == SPIFFS_OK); - printf(" >>> file %s size: %i\n", s.name, s.size); - TEST_CHECK(s.size == 0); - SPIFFS_clearerr(FS); -#else - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FULL); - SPIFFS_clearerr(FS); -#endif - printf(" remove files\n"); - res = SPIFFS_remove(FS, "test1.txt"); - TEST_CHECK(res == SPIFFS_OK); -#if 0 - res = SPIFFS_remove(FS, "test2.txt"); - TEST_CHECK(res == SPIFFS_OK); -#endif - - printf(" create medium file\n"); - fd = SPIFFS_open(FS, "test3.txt", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_OK); - TEST_CHECK(fd > 0); - - for (i = 0; i < 20*1000; i++) { - u8_t buf = 'x'; - res = SPIFFS_write(FS, fd, &buf, 1); - } - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_OK); - - res2 = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res2 == SPIFFS_OK); - printf(" >>> file %s size: %i\n", s.name, s.size); - TEST_CHECK(s.size == 20*1000); - - return TEST_RES_OK; - -} TEST_END - -TEST(magic_test) { - // this test only works on default sizes - TEST_ASSERT(sizeof(spiffs_obj_id) == sizeof(u16_t)); - - // one obj lu page, not full - fs_reset_specific(0, 0, 4096*16, 4096, 4096*1, 128); - TEST_CHECK(SPIFFS_CHECK_MAGIC_POSSIBLE(FS)); - // one obj lu page, full - fs_reset_specific(0, 0, 4096*16, 4096, 4096*2, 128); - TEST_CHECK(!SPIFFS_CHECK_MAGIC_POSSIBLE(FS)); - // two obj lu pages, not full - fs_reset_specific(0, 0, 4096*16, 4096, 4096*4, 128); - TEST_CHECK(SPIFFS_CHECK_MAGIC_POSSIBLE(FS)); - - return TEST_RES_OK; - -} TEST_END - -TEST(nodemcu_309) { - fs_reset_specific(0, 0, 4096*20, 4096, 4096, 256); - - int res; - spiffs_file fd; - int j; - - for (j = 1; j <= 3; j++) { - char fname[32]; - sprintf(fname, "20K%i.txt", j); - fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_DIRECT, 0); - TEST_CHECK(fd > 0); - int i; - res = SPIFFS_OK; - u8_t err = 0; - for (i = 1; i <= 1280; i++) { - char *buf = "0123456789ABCDE\n"; - res = SPIFFS_write(FS, fd, buf, strlen(buf)); - if (!err && res < 0) { - printf("err @ %i,%i\n", i, j); - err = 1; - } - } - } - - int errno = SPIFFS_errno(FS); - TEST_CHECK(errno == SPIFFS_ERR_FULL); - - u32_t total; - u32_t used; - - SPIFFS_info(FS, &total, &used); - printf("total:%i\nused:%i\nremain:%i\nerrno:%i\n", total, used, total-used, errno); - //TEST_CHECK(total-used < 11000); // disabled, depends on too many variables - - spiffs_DIR d; - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - - SPIFFS_opendir(FS, "/", &d); - int spoon_guard = 0; - while ((pe = SPIFFS_readdir(&d, pe))) { - printf("%s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size); - TEST_CHECK(spoon_guard++ < 3); - } - TEST_CHECK(spoon_guard == 3); - SPIFFS_closedir(&d); - - return TEST_RES_OK; - -} TEST_END - - -TEST(robert) { - // create a clean file system starting at address 0, 2 megabytes big, - // sector size 65536, block size 65536, page size 256 - fs_reset_specific(0, 0, 1024*1024*2, 65536, 65536, 256); - - int res; - spiffs_file fd; - char fname[32]; - - sprintf(fname, "test.txt"); - fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_OK; - char buf[500]; - memset(buf, 0xaa, 500); - res = SPIFFS_write(FS, fd, buf, 500); - TEST_CHECK(res >= SPIFFS_OK); - SPIFFS_close(FS, fd); - - int errno = SPIFFS_errno(FS); - TEST_CHECK(errno == SPIFFS_OK); - - //SPIFFS_vis(FS); - // unmount - SPIFFS_unmount(FS); - - // remount - res = fs_mount_specific(0, 1024*1024*2, 65536, 65536, 256); - TEST_CHECK(res== SPIFFS_OK); - - //SPIFFS_vis(FS); - - spiffs_stat s; - TEST_CHECK(SPIFFS_stat(FS, fname, &s) == SPIFFS_OK); - printf("file %s stat size %i\n", s.name, s.size); - TEST_CHECK(s.size == 500); - - return TEST_RES_OK; - -} TEST_END - - -TEST(spiffs_12) { - fs_reset_specific(0x4024c000, 0x4024c000 + 0, 192*1024, 4096, 4096*2, 256); - - int res; - spiffs_file fd; - int j = 1; - - while (1) { - char fname[32]; - sprintf(fname, "file%i.txt", j); - fd = SPIFFS_open(FS, fname, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_DIRECT, 0); - if (fd <=0) break; - - int i; - res = SPIFFS_OK; - for (i = 1; i <= 100; i++) { - char *buf = "0123456789ABCDE\n"; - res = SPIFFS_write(FS, fd, buf, strlen(buf)); - if (res < 0) break; - } - SPIFFS_close(FS, fd); - j++; - } - - int errno = SPIFFS_errno(FS); - TEST_CHECK(errno == SPIFFS_ERR_FULL); - - u32_t total; - u32_t used; - - SPIFFS_info(FS, &total, &used); - printf("total:%i (%iK)\nused:%i (%iK)\nremain:%i (%iK)\nerrno:%i\n", total, total/1024, used, used/1024, total-used, (total-used)/1024, errno); - - spiffs_DIR d; - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - - SPIFFS_opendir(FS, "/", &d); - while ((pe = SPIFFS_readdir(&d, pe))) { - printf("%s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size); - } - SPIFFS_closedir(&d); - - //SPIFFS_vis(FS); - - //dump_page(FS, 0); - //dump_page(FS, 1); - - return TEST_RES_OK; - -} TEST_END - - -TEST(zero_sized_file_44) { - fs_reset(); - - spiffs_file fd = SPIFFS_open(FS, "zero", SPIFFS_RDWR | SPIFFS_CREAT, 0); - TEST_CHECK_GE(fd, 0); - - int res = SPIFFS_close(FS, fd); - TEST_CHECK_GE(res, 0); - - fd = SPIFFS_open(FS, "zero", SPIFFS_RDWR, 0); - TEST_CHECK_GE(fd, 0); - - u8_t buf[8]; - res = SPIFFS_read(FS, fd, buf, 8); - TEST_CHECK_EQ(res, 0); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_END_OF_OBJECT); - - res = SPIFFS_read(FS, fd, buf, 0); - TEST_CHECK_GE(res, 0); - - res = SPIFFS_read(FS, fd, buf, 0); - TEST_CHECK_GE(res, 0); - - buf[0] = 1; - buf[1] = 2; - - res = SPIFFS_write(FS, fd, buf, 2); - TEST_CHECK_EQ(res, 2); - - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_SET); - TEST_CHECK_GE(res, 0); - - u8_t b; - res = SPIFFS_read(FS, fd, &b, 1); - TEST_CHECK_EQ(res, 1); - TEST_CHECK_EQ(b, 1); - - res = SPIFFS_read(FS, fd, &b, 1); - TEST_CHECK_EQ(res, 1); - TEST_CHECK_EQ(b, 2); - - res = SPIFFS_read(FS, fd, buf, 8); - TEST_CHECK_EQ(res, 0); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_END_OF_OBJECT); - - return TEST_RES_OK; -} TEST_END - -#if !SPIFFS_READ_ONLY -TEST(truncate_48) { - fs_reset(); - - u32_t len = SPIFFS_DATA_PAGE_SIZE(FS)/2; - - s32_t res = test_create_and_write_file("small", len, len); - TEST_CHECK_GE(res, 0); - - spiffs_file fd = SPIFFS_open(FS, "small", SPIFFS_RDWR, 0); - TEST_CHECK_GE(fd, 0); - - spiffs_fd *desc; -#if SPIFFS_FILEHDL_OFFSET - res = spiffs_fd_get(FS, fd - TEST_SPIFFS_FILEHDL_OFFSET, &desc); -#else - res = spiffs_fd_get(FS, fd, &desc); -#endif - - TEST_CHECK_GE(res, 0); - - TEST_CHECK_EQ(desc->size, len); - - u32_t new_len = len/2; - res = spiffs_object_truncate(desc, new_len, 0); - TEST_CHECK_GE(res, 0); - - TEST_CHECK_EQ(desc->size, new_len); - - res = SPIFFS_close(FS, fd); - TEST_CHECK_GE(res, 0); - - spiffs_stat s; - res = SPIFFS_stat(FS, "small", &s); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(s.size, new_len); - - res = SPIFFS_remove(FS, "small"); - TEST_CHECK_GE(res, 0); - - fd = SPIFFS_open(FS, "small", SPIFFS_RDWR, 0); - TEST_CHECK_LT(fd, 0); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_FOUND); - - return TEST_RES_OK; -} TEST_END -#endif - -TEST(eof_tell_72) { - fs_reset(); - - s32_t res; - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_CREAT | SPIFFS_RDWR | SPIFFS_APPEND, 0); - TEST_CHECK_GT(fd, 0); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 0); - - res = SPIFFS_write(FS, fd, "test", 4); - TEST_CHECK_EQ(res, 4); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 4); - - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_EQ(res, SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 4); - - res = SPIFFS_lseek(FS, fd, 2, SPIFFS_SEEK_SET); - TEST_CHECK_EQ(res, 2); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 0); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 2); - - res = SPIFFS_write(FS, fd, "test", 4); - TEST_CHECK_EQ(res, 4); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 8); - - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_EQ(res, SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 8); - - res = SPIFFS_close(FS, fd); - TEST_CHECK_EQ(res, SPIFFS_OK); - TEST_CHECK_LT(SPIFFS_eof(FS, fd), SPIFFS_OK); - TEST_CHECK_LT(SPIFFS_tell(FS, fd), SPIFFS_OK); - - fd = SPIFFS_open(FS, "file", SPIFFS_RDWR, 0); - TEST_CHECK_GT(fd, 0); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 0); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 0); - - res = SPIFFS_lseek(FS, fd, 2, SPIFFS_SEEK_SET); - TEST_CHECK_EQ(res, 2); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 0); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 2); - - res = SPIFFS_write(FS, fd, "test", 4); - TEST_CHECK_EQ(res, 4); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 0); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 6); - - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_EQ(res, SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 0); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 6); - - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_END); - TEST_CHECK_EQ(res, 8); - TEST_CHECK_EQ(SPIFFS_eof(FS, fd), 1); - TEST_CHECK_EQ(SPIFFS_tell(FS, fd), 8); - - return TEST_RES_OK; -} TEST_END - -TEST(spiffs_dup_file_74) { - fs_reset_specific(0, 0, 64*1024, 4096, 4096*2, 256); - { - spiffs_file fd = SPIFFS_open(FS, "/config", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_WRONLY, 0); - TEST_CHECK(fd >= 0); - char buf[5]; - strncpy(buf, "test", sizeof(buf)); - SPIFFS_write(FS, fd, buf, 4); - SPIFFS_close(FS, fd); - } - { - spiffs_file fd = SPIFFS_open(FS, "/data", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_WRONLY, 0); - TEST_CHECK(fd >= 0); - SPIFFS_close(FS, fd); - } - { - spiffs_file fd = SPIFFS_open(FS, "/config", SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - char buf[5]; - int cb = SPIFFS_read(FS, fd, buf, sizeof(buf)); - TEST_CHECK(cb > 0 && cb < sizeof(buf)); - TEST_CHECK(strncmp("test", buf, cb) == 0); - SPIFFS_close(FS, fd); - } - { - spiffs_file fd = SPIFFS_open(FS, "/data", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_WRONLY, 0); - TEST_CHECK(fd >= 0); - spiffs_stat stat; - SPIFFS_fstat(FS, fd, &stat); - if (strcmp((const char*) stat.name, "/data") != 0) { - // oops! lets check the list of files... - spiffs_DIR dir; - SPIFFS_opendir(FS, "/", &dir); - struct spiffs_dirent dirent; - while (SPIFFS_readdir(&dir, &dirent)) { - printf("%s\n", dirent.name); - } - // this will print "/config" two times - TEST_CHECK(0); - } - SPIFFS_close(FS, fd); - } - return TEST_RES_OK; -} TEST_END - -TEST(temporal_fd_cache) { - fs_reset_specific(0, 0, 1024*1024, 4096, 2*4096, 256); - (FS)->fd_count = 4; - - char *fcss = "blaha.css"; - - char *fhtml[] = { - "index.html", "cykel.html", "bloja.html", "drivmedel.html", "smorgasbord.html", - "ombudsman.html", "fubbick.html", "paragrod.html" - }; - - const int hit_probabilities[] = { - 25, 20, 16, 12, 10, 8, 5, 4 - }; - - const int runs = 10000; - - // create our webserver files - TEST_CHECK_EQ(test_create_and_write_file(fcss, 2000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[0], 4000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[1], 3000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[2], 2000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[3], 1000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[4], 1500, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[5], 3000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[6], 2000, 256), SPIFFS_OK); - TEST_CHECK_EQ(test_create_and_write_file(fhtml[7], 3500, 256), SPIFFS_OK); - - clear_flash_ops_log(); - - int run = 0; - do { - // open & read an html - int dice = rand() % 100; - int probability = 0; - int html_ix = 0; - do { - probability += hit_probabilities[html_ix]; - if (dice <= probability) { - break; - } - html_ix++; - } while(probability < 100); - - TEST_CHECK_EQ(read_and_verify(fhtml[html_ix]), SPIFFS_OK); - - // open & read css - TEST_CHECK_EQ(read_and_verify(fcss), SPIFFS_OK); - } while (run ++ < runs); - - return TEST_RES_OK; -} TEST_END - -static int run_fuzz_test(FILE *f, int maxfds, int debuglog) { - // There are a bunch of arbitrary constants in this test case. Changing them will - // almost certainly change the effets of an input file. It *may* be worth - // making some of these constants to come from the input file. - int setup = fgetc(f); - - int page_size = 128 << (setup & 3); - setup >>= 2; - int erase_size = 4096 << (setup & 3); - setup >>= 2; - int block_size = erase_size << (setup & 1); - setup >>= 1; - int blocks = 4 + (setup & 7); - fs_reset_specific(0, 0, blocks * block_size, erase_size, block_size, page_size); - int res; - (FS)->fd_count = 4; - - int c; - - spiffs_file fd[4]; - memset(fd, -1, sizeof(fd)); - int openindex[4]; - memset(openindex, -1, sizeof(openindex)); - char *filename[8]; - - int i; - - for (i = 0; i < 8; i++) { - char buff[128]; - sprintf(buff, "%dfile%d.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxasdasdasdadxxxxxxxxxxxxxxxxxxx", i, i); - buff[9 + 2 * i] = 0; - filename[i] = strdup(buff); - } - - // The list of 8 modes that are chosen. SPIFFS_EXCL is not present -- it probably ought to be. - int modes[8] = {SPIFFS_RDONLY, SPIFFS_RDWR, SPIFFS_RDWR|SPIFFS_TRUNC, SPIFFS_RDWR|SPIFFS_CREAT, SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_TRUNC, - SPIFFS_WRONLY|SPIFFS_CREAT|SPIFFS_TRUNC, SPIFFS_RDWR|SPIFFS_CREAT|SPIFFS_TRUNC|SPIFFS_DIRECT, SPIFFS_WRONLY}; - - char buff[2048]; - for (i = 0; i < sizeof(buff); i++) { - buff[i] = i * 19; - } - -#define LOGOP if (debuglog) printf - - while ((c = fgetc(f)) >= 0) { - int add; - char rbuff[2048]; - if (c <= ' ') { - continue; - } - int arg = fgetc(f); - if (arg < 0) { - break; - } - int fdn = ((arg >> 6) & 3) % maxfds; - int rc; - switch(c) { - case 'O': - if (fd[fdn] >= 0) { - LOGOP(" close(%d)\n", fd[fdn]); - SPIFFS_close(FS, fd[fdn]); - openindex[fdn] = -1; - fd[fdn] = -1; - } -#ifndef HAVE_MULTIPLE_OPEN - { - int index = (arg >> 3) & 7; - for (i = 0; i < sizeof(openindex) / sizeof(openindex[0]); i++) { - if (openindex[i] == index) { - break; - } - } - if (i < sizeof(openindex) / sizeof(openindex[0])) { - break; - } - } -#endif - LOGOP(" open(\"%s\", 0x%x)", filename[(arg>>3) & 7], modes[arg & 7]); - fd[fdn] = SPIFFS_open(FS, filename[(arg>>3) & 7], modes[arg & 7], 0); - if (fd[fdn] >= 0) { - openindex[fdn] = (arg >> 3) & 7; - } - LOGOP(" -> %d\n", fd[fdn]); - break; - - case 'S': - if (fd[fdn] >= 0) { - int offset = (14 << (arg & 7)) + arg; - if (arg & 16) { - offset = -offset; - } - int whence = (arg & 63) % 3; - LOGOP(" lseek(%d, %d, %d)\n", fd[fdn], offset, whence); - SPIFFS_lseek(FS, fd[fdn], offset, whence); - } - break; - - case 'R': - if (fd[fdn] >= 0) { - LOGOP(" read(%d, , %d)", fd[fdn], (15 << (arg & 7)) + (arg & 127)); - int rlen = SPIFFS_read(FS, fd[fdn], rbuff, (15 << (arg & 7)) + (arg & 127)); - LOGOP(" -> %d\n", rlen); - } - break; - - case 'W': - if (fd[fdn] >= 0) { - LOGOP(" write(%d, , %d)", fd[fdn], (15 << (arg & 7)) + (arg & 127)); - rc = SPIFFS_write(FS, fd[fdn], buff, (15 << (arg & 7)) + (arg & 127)); - LOGOP(" -> %d\n", rc); - } - break; - - case 'C': - if (fd[fdn] >= 0) { - LOGOP(" close(%d)\n", fd[fdn]); - SPIFFS_close(FS, fd[fdn]); - } - fd[fdn] = -1; - openindex[fdn] = -1; - break; - - case 'b': - add = fgetc(f); - for (i = 0; i < sizeof(buff); i++) { - buff[i] = add + i * arg; - } - break; - - case 'f': - if (fd[fdn] >= 0) { - LOGOP(" fflush(%d)\n", fd[fdn]); - SPIFFS_fflush(FS, fd[fdn]); - } - break; - -#ifdef HAVE_REMOVE_OPEN - case 'D': - if (fd[fdn] >= 0) { - LOGOP(" fremove(%d)\n", fd[fdn]); - SPIFFS_fremove(FS, fd[fdn]); - } - break; -#endif - - case 'd': -#ifndef HAVE_REMOVE_OPEN - { - int index = arg & 7; - for (i = 0; i < sizeof(openindex) / sizeof(openindex[0]); i++) { - if (openindex[i] == index) { - break; - } - } - if (i < sizeof(openindex) / sizeof(openindex[0])) { - break; - } - } -#endif - LOGOP(" remove(\"%s\")", filename[arg & 7]); - rc = SPIFFS_remove(FS, filename[arg & 7]); - LOGOP(" -> %d\n", rc); - break; - - case 'r': -#ifndef HAVE_REMOVE_OPEN - { - int index = arg & 7; - for (i = 0; i < sizeof(openindex) / sizeof(openindex[0]); i++) { - if (openindex[i] == index) { - break; - } - } - if (i < sizeof(openindex) / sizeof(openindex[0])) { - break; - } - } -#endif - LOGOP(" rename(\"%s\", \"%s\")", filename[arg & 7], filename[(arg >> 3) & 7]); - rc = SPIFFS_rename(FS, filename[arg & 7], filename[(arg >> 3) & 7]); - LOGOP(" -> %d\n", rc); - break; - - case 'U': - ungetc(arg, f); - for (i = 0; i < 4; i++) { - fd[i] = -1; - } - { -#ifdef DO_UNMOUNT - LOGOP(" unmount\n"); - SPIFFS_unmount(FS); -#endif - char *tmpfile = strdup("/tmp/fsdump.XXXXXX"); - LOGOP(" cycle and remount\n"); - close(mkstemp(tmpfile)); - fs_store_dump(tmpfile); - fs_mount_dump(tmpfile, 0, 0, blocks * block_size, erase_size, block_size, page_size); - unlink(tmpfile); - free(tmpfile); -#ifndef NO_FORCE_CHECK - LOGOP(" forcecheck()"); - rc = SPIFFS_check(FS); - LOGOP(" -> %d\n", rc); -#endif - } - break; - - case 'c': - { - LOGOP(" check()"); - rc = SPIFFS_check(FS); - LOGOP(" -> %d\n", rc); - ungetc(arg, f); - break; - } - - default: - ungetc(arg, f); - break; - } - } - - for (i = 0; i < 4; i++) { - if (fd[i] >= 0) { - LOGOP(" close(%d)\n", fd[i]); - SPIFFS_close(FS, fd[i]); - } - } - - return TEST_RES_OK; -} - -#define FMEMARGS(x) x, sizeof(x) - 1 - -TEST(fuzzer_found_1) { - return run_fuzz_test(fmemopen(FMEMARGS("\021OlWkd5O4W4W0O5OlWkO5OlW0O5O4W0"), "r"), 4, 1); -} TEST_END - -TEST(fuzzer_found_2) { - return run_fuzz_test(fmemopen(FMEMARGS("bO4W6W0d\036O4W6"), "r"), 4, 1); -} TEST_END - -TEST(fuzzer_found_3) { - return run_fuzz_test(fmemopen(FMEMARGS("\264O4OqWeWWWWW@O4WWW\027"), "r"), 4, 1); -} TEST_END - -TEST(fuzzer_found_4) { - unsigned char smalltest[] = { - 0x62, 0x4f, 0x24, 0x57, 0x3f, 0x57, 0x3f, 0x57, 0x3f, 0x57, 0x3f, 0x57, - 0x3f, 0x4f, 0x34, 0x57, 0x3f, 0x55, 0x4f, 0x61, 0x57, 0x61, 0x4f, 0x61, - 0x57, 0x65, 0x43, 0x61, 0x4f, 0x24, 0x57, 0x30 - }; - unsigned int smalltest_len = 32; - - return run_fuzz_test(fmemopen(smalltest, smalltest_len, "r"), 4, 1); -} TEST_END - -TEST(fuzzer_found_single_1) { - return run_fuzz_test(fmemopen(FMEMARGS("\000O\004Odr4d\356Okr0WWUO;WWWWd\035W4"), "r"), 1, 1); -} TEST_END - -TEST(log_afl_test) { - u32_t old_val = set_abort_on_error(1); - int rc = run_fuzz_test(stdin, 4, 1); - set_abort_on_error(old_val); - return rc; -} TEST_END - -TEST(afl_test) { - u32_t old_val = set_abort_on_error(1); - int rc = run_fuzz_test(stdin, 4, 0); - set_abort_on_error(old_val); - return rc; -} TEST_END - -TEST(afl_single) { - u32_t old_val = set_abort_on_error(1); - int rc = run_fuzz_test(stdin, 1, 0); - set_abort_on_error(old_val); - return rc; -} TEST_END - -TEST(small_free_space) { - fs_reset_specific(0, 0, 400*1024, 4096, 2*4096, 256); - spiffs_file fd; - int res; - (FS)->fd_count = 4; - - int tfd = SPIFFS_open(FS, "testfile", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(tfd > 0); - char *tbuf = "some data"; - res = SPIFFS_write(FS, tfd, tbuf, strlen(tbuf)); - - TEST_CHECK(res == strlen(tbuf)); - - res = SPIFFS_fflush(FS, tfd); - TEST_CHECK(res >= SPIFFS_OK); - - SPIFFS_close(FS, tfd); - - const int runs = 1000; - - int fileCurrNumber = 0; - int fileDelNumber = 1; - - int run = 0; - do { - u8_t buf[1000]; - - sprintf(buf, "%d", fileCurrNumber); - int i; - for (i = 0; i < 100; i++) { - strcat(buf, " azzaaax"); - } - - int maxFileNr = 500; - char *filename = "awyn"; - char *fileext = ".dat"; - - u32_t total; - u32_t used; - - SPIFFS_info(FS, &total, &used); - - if (total - used < 20000) { - maxFileNr = 1; - } - - fileCurrNumber++; - int fileCntr = fileCurrNumber + 1 - fileDelNumber; - - char fileCurrName[64]; - sprintf(fileCurrName, "%s%d%s", filename, fileCurrNumber, fileext); - - fd = SPIFFS_open(FS, fileCurrName, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - - //printf("About to write to %s\n", fileCurrName); - res = SPIFFS_write(FS, fd, buf, strlen(buf)); - - TEST_CHECK(res == strlen(buf)); - - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_EQ(res, SPIFFS_OK); - - SPIFFS_close(FS, fd); - - if (fileCntr > maxFileNr) { - char fileDelName[64]; - sprintf(fileDelName, "%s%d%s", filename, fileDelNumber, fileext); - //printf("Deleting %s (free space %d)\n", fileDelName, total - used); - - res = SPIFFS_remove(FS, fileDelName); - - TEST_CHECK(res == SPIFFS_OK); - fileDelNumber++; - } - } while (run ++ < runs); - - tfd = SPIFFS_open(FS, "testfile", SPIFFS_RDONLY, 0); - TEST_CHECK(tfd > 0); - char rbuf[32]; - res = SPIFFS_read(FS, tfd, rbuf, sizeof(rbuf)); - - TEST_CHECK(res == strlen(tbuf)); - - SPIFFS_close(FS, tfd); - - TEST_CHECK(memcmp(rbuf, tbuf, strlen(tbuf)) == 0); - - return TEST_RES_OK; -} TEST_END - -TEST(lots_of_overwrite) { - fs_reset_specific(0, 0, 3000*1024, 4096, 2*4096, 256); - spiffs_file fd; - int res; - (FS)->fd_count = 4; - - int i; - - for (i = 0; i < 5; i++) { - - char filename[64]; - sprintf(filename, "%d-tstfile", i); - int tfd = SPIFFS_open(FS, filename, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(tfd > 0); - char tbuf[1024]; - memset(tbuf, 'a', 700); - tbuf[700] = 0; - res = SPIFFS_write(FS, tfd, tbuf, strlen(tbuf)); - - TEST_CHECK(res == strlen(tbuf)); - - res = SPIFFS_fflush(FS, tfd); - TEST_CHECK(res >= SPIFFS_OK); - - SPIFFS_close(FS, tfd); - } - - const int runs = 100000; - - int run = 0; - for (run = 0; run < runs; run++) { - u8_t buf[2000]; - - sprintf(buf, "%d", run); - int i; - for (i = 0; i < 100 + (run % 100); i++) { - strcat(buf, " azzaaax"); - } - - int tfd = SPIFFS_open(FS, "file.dat", SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(tfd > 0); - res = SPIFFS_write(FS, tfd, buf, strlen(buf)); - - TEST_CHECK(res == strlen(buf)); - - res = SPIFFS_fflush(FS, tfd); - TEST_CHECK(res >= SPIFFS_OK); - - SPIFFS_close(FS, tfd); - - tfd = SPIFFS_open(FS, "file.dat", SPIFFS_RDONLY, 0); - TEST_CHECK(tfd > 0); - char rbuf[2000]; - res = SPIFFS_read(FS, tfd, rbuf, sizeof(rbuf)); - - TEST_CHECK(res == strlen(buf)); - - SPIFFS_close(FS, tfd); - - TEST_CHECK(memcmp(rbuf, buf, strlen(buf)) == 0); - - char filename[64]; - sprintf(filename, "%d-tstfile", run % 5); - tfd = SPIFFS_open(FS, filename, SPIFFS_RDONLY, 0); - TEST_CHECK(tfd > 0); - char tbuf[1024]; - memset(tbuf, 'a', 700); - tbuf[700] = 0; - res = SPIFFS_read(FS, tfd, rbuf, sizeof(rbuf)); - - TEST_CHECK(res == strlen(tbuf)); - - SPIFFS_close(FS, tfd); - TEST_CHECK(memcmp(rbuf, tbuf, strlen(tbuf)) == 0); - } - - return TEST_RES_OK; -} TEST_END - - -#if 0 -TEST(spiffs_hidden_file_90) { - fs_mount_dump("imgs/90.hidden_file.spiffs", 0, 0, 1*1024*1024, 4096, 4096, 128); - - SPIFFS_vis(FS); - - dump_page(FS, 1); - dump_page(FS, 0x8fe); - dump_page(FS, 0x8ff); - - { - spiffs_DIR dir; - SPIFFS_opendir(FS, "/", &dir); - struct spiffs_dirent dirent; - while (SPIFFS_readdir(&dir, &dirent)) { - printf("%-32s sz:%-7i obj_id:%08x pix:%08x\n", dirent.name, dirent.size, dirent.obj_id, dirent.pix); - } - } - - printf("remove cli.bin res %i\n", SPIFFS_remove(FS, "cli.bin")); - - { - spiffs_DIR dir; - SPIFFS_opendir(FS, "/", &dir); - struct spiffs_dirent dirent; - while (SPIFFS_readdir(&dir, &dirent)) { - printf("%-32s sz:%-7i obj_id:%08x pix:%08x\n", dirent.name, dirent.size, dirent.obj_id, dirent.pix); - } - } - return TEST_RES_OK; - -} TEST_END -#endif -#if 0 -TEST(null_deref_check_93) { - fs_mount_dump("imgs/93.dump.bin", 0, 0, 2*1024*1024, 4096, 4096, 256); - - //int res = SPIFFS_open(FS, "d43.fw", SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_WRONLY, 0); - //TEST_CHECK_GE(res, SPIFFS_OK); - - SPIFFS_vis(FS); - - printf("\n\n-------------------------------------------------\n\n"); - - SPIFFS_check(FS); - //fs_store_dump("imgs/93.dump.checked.bin"); - - SPIFFS_vis(FS); - - printf("\n\n-------------------------------------------------\n\n"); - - SPIFFS_check(FS); - - SPIFFS_vis(FS); - printf("\n\n-------------------------------------------------\n\n"); - - - - return TEST_RES_OK; -} TEST_END -#endif - -TEST(spiffs_145) { - int res; - fs_reset_specific(0, 0, 1024*1024, 65536, 65536, 1024); - { - spiffs_file fd = SPIFFS_open(FS, "biggie", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_WRONLY, 0); - TEST_CHECK(fd >= 0); - char buf[1024*512]; - memset(buf, 0xee, sizeof(buf)); - TEST_CHECK_GT(SPIFFS_write(FS, fd, buf, sizeof(buf)), 0); - TEST_CHECK_EQ(SPIFFS_close(FS, fd), SPIFFS_OK); - } - const int runs = 1000; - int run = 0; - while (run++ < runs) { - spiffs_file fd = SPIFFS_open(FS, "clobber", SPIFFS_CREAT | SPIFFS_TRUNC | SPIFFS_WRONLY, 0); - TEST_CHECK(fd >= 0); - char buf[8192]; - memset(buf, 0xee, sizeof(buf)); - TEST_CHECK_GT(SPIFFS_write(FS, fd, buf, sizeof(buf)), 0); - TEST_CHECK_EQ(SPIFFS_close(FS, fd), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_remove(FS, "clobber"), SPIFFS_OK); - } - - // below stolen from SPIFFS_vis - spiffs *fs = FS; - int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); - spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work; - spiffs_block_ix bix = 0; - - while (bix < fs->block_count) { - // check each object lookup page - spiffs_obj_id erase_count; - TEST_CHECK_EQ(_spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0, - SPIFFS_ERASE_COUNT_PADDR(fs, bix), - sizeof(spiffs_obj_id), (u8_t *)&erase_count), SPIFFS_OK); - TEST_CHECK_NEQ(erase_count, (spiffs_obj_id)-1); - TEST_CHECK_NEQ(erase_count, 0); - bix++; - } // per block - - return TEST_RES_OK; -} TEST_END - - -TEST(seek_bug_148) { - int res; -#define MAGIC_SIZE_THAT_FAILS 26355 // happens to be SPIFFS_DATA_PAGE_SIZE(FS) * SPIFFS_OBJ_HDR_IX_LEN(FS) - fs_reset_specific(0, 0, 64*1024, 4096, 4096, 256); - u8_t buf[MAGIC_SIZE_THAT_FAILS]; - spiffs_file fd = SPIFFS_open(FS, "EVENT", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0); - TEST_CHECK_GT(fd, 0); - TEST_CHECK_EQ(SPIFFS_write(FS, fd, &buf, sizeof(buf)), sizeof(buf)); - TEST_CHECK_EQ(SPIFFS_close(FS, fd), SPIFFS_OK); - fd = SPIFFS_open(FS, "EVENT", SPIFFS_O_RDONLY, 0); - TEST_CHECK_GT(fd, 0); - TEST_CHECK_EQ(SPIFFS_lseek(FS, fd, 0, SEEK_END), MAGIC_SIZE_THAT_FAILS); - return TEST_RES_OK; -} TEST_END - - -TEST(remove_release_fd_152) { - int res; - fs_reset_specific(0, 0, 64*1024, 4096, 4096, 256); - u8_t buf[1024]; - memrand(buf, sizeof(buf)); - TEST_CHECK_EQ(count_taken_fds(FS), 0); - spiffs_file fd1 = SPIFFS_open(FS, "removemeandloseafd", SPIFFS_O_CREAT | SPIFFS_O_RDWR, 0); - TEST_CHECK_GT(fd1, 0); - TEST_CHECK_EQ(count_taken_fds(FS), 1); - TEST_CHECK_EQ(SPIFFS_write(FS, fd1, &buf, sizeof(buf)), sizeof(buf)); - TEST_CHECK_EQ(SPIFFS_close(FS, fd1), SPIFFS_OK); - TEST_CHECK_EQ(count_taken_fds(FS), 0); - spiffs_file fd2 = SPIFFS_open(FS, "removemeandloseafd", SPIFFS_O_RDWR, 0); - TEST_CHECK_GT(fd2, 0); - TEST_CHECK_EQ(count_taken_fds(FS), 1); - spiffs_file fd3 = SPIFFS_open(FS, "removemeandloseafd", SPIFFS_O_RDWR, 0); - TEST_CHECK_GT(fd3, 0); - TEST_CHECK_EQ(count_taken_fds(FS), 2); - TEST_CHECK_EQ(SPIFFS_remove(FS, "removemeandloseafd"), SPIFFS_OK); - TEST_CHECK_EQ(count_taken_fds(FS), 0); - return TEST_RES_OK; -} TEST_END - -TEST(certain_file_size_fail_165) { - fs_reset_specific(0, 0, 512*1024, 4*1024, 64*1024, 256); - const int NUM = 134; - const int SIZ = 200; - u8_t buf[SIZ]; - - TEST_CHECK_EQ(SPIFFS_creat(FS, "test", 0), SPIFFS_OK); - spiffs_file fd = SPIFFS_open(FS, "test", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd, 0); - - int i; - for (i = 0; i < NUM; i++) { - TEST_CHECK_EQ(SPIFFS_write(FS, fd, buf, SIZ), SIZ); - } - TEST_CHECK_EQ(SPIFFS_close(FS, fd), SPIFFS_OK); - fd = SPIFFS_open(FS, "test", SPIFFS_O_RDONLY, 0); - TEST_CHECK_GT(fd, 0); - - spiffs_stat s; - TEST_CHECK_EQ(SPIFFS_fstat(FS, fd, &s), SPIFFS_OK); - TEST_CHECK_EQ(s.size, NUM*SIZ); - - int size = 0; - for (i = 0; i < NUM; i++) { - size += SPIFFS_read(FS, fd, buf, SIZ); - } - TEST_CHECK_EQ(size, NUM*SIZ); - - return TEST_RES_OK; -} TEST_END - - -SUITE_TESTS(bug_tests) - ADD_TEST(nodemcu_full_fs_1) - ADD_TEST(nodemcu_full_fs_2) - ADD_TEST(magic_test) - ADD_TEST(nodemcu_309) - ADD_TEST(robert) - ADD_TEST(spiffs_12) - ADD_TEST(zero_sized_file_44) - ADD_TEST(truncate_48) - ADD_TEST(eof_tell_72) - ADD_TEST(spiffs_dup_file_74) - ADD_TEST(temporal_fd_cache) - ADD_TEST(spiffs_145) - ADD_TEST(seek_bug_148) - //ADD_TEST(small_free_space) - ADD_TEST(lots_of_overwrite) - ADD_TEST(fuzzer_found_1) - ADD_TEST(fuzzer_found_2) - ADD_TEST(fuzzer_found_3) - ADD_TEST(fuzzer_found_4) - ADD_TEST(remove_release_fd_152) - ADD_TEST(certain_file_size_fail_165) - ADD_TEST_NON_DEFAULT(fuzzer_found_single_1) - ADD_TEST_NON_DEFAULT(log_afl_test) - ADD_TEST_NON_DEFAULT(afl_test) - ADD_TEST_NON_DEFAULT(afl_single) -#if 0 - ADD_TEST(spiffs_hidden_file_90) -#endif -#if 0 - ADD_TEST(null_deref_check_93) -#endif -SUITE_END(bug_tests) diff --git a/src/spiffs/test/test_check.c b/src/spiffs/test/test_check.c deleted file mode 100644 index 15865c4..0000000 --- a/src/spiffs/test/test_check.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * test_dev.c - * - * Created on: Jul 14, 2013 - * Author: petera - */ - - -#include "testrunner.h" -#include "test_spiffs.h" -#include "spiffs_nucleus.h" -#include "spiffs.h" -#include -#include -#include -#include -#include - - -SUITE(check_tests) -static void setup() { - _setup(); -} -static void teardown() { - _teardown(); -} - -TEST(evil_write) { - fs_set_validate_flashing(0); - printf("writing corruption to block 1 data range (leaving lu intact)\n"); - u32_t data_range = SPIFFS_CFG_LOG_BLOCK_SZ(FS) - - SPIFFS_CFG_LOG_PAGE_SZ(FS) * (SPIFFS_OBJ_LOOKUP_PAGES(FS)); - u8_t *corruption = malloc(data_range); - memrand(corruption, data_range); - u32_t addr = 0 * SPIFFS_CFG_LOG_PAGE_SZ(FS) * SPIFFS_OBJ_LOOKUP_PAGES(FS); - area_write(addr, corruption, data_range); - free(corruption); - - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - - printf("CHECK1-----------------\n"); - SPIFFS_check(FS); - printf("CHECK2-----------------\n"); - SPIFFS_check(FS); - printf("CHECK3-----------------\n"); - SPIFFS_check(FS); - - res = test_create_and_write_file("file2", size, size); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(lu_check1) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify lu entry data page index 1 - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 1, 0, &pix); - TEST_CHECK(res >= 0); - - // reset lu entry to being erased, but keep page data - spiffs_obj_id obj_id = SPIFFS_OBJ_ID_DELETED; - spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(FS, pix); - int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(FS, pix); - u32_t addr = SPIFFS_BLOCK_TO_PADDR(FS, bix) + entry*sizeof(spiffs_obj_id); - - area_write(addr, (u8_t*)&obj_id, sizeof(spiffs_obj_id)); - -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - SPIFFS_check(FS); - - return TEST_RES_OK; -} TEST_END - - -TEST(page_cons1) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify object index, find object index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - // set object index entry 2 to a bad page - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + sizeof(spiffs_page_object_ix_header) + 0 * sizeof(spiffs_page_ix); - spiffs_page_ix bad_pix_ref = 0x55; - area_write(addr, (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - area_write(addr + sizeof(spiffs_page_ix), (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - - // delete all cache -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(page_cons2) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify object index, find object index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - // find data page span index 0 - spiffs_page_ix dpix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &dpix); - TEST_CHECK(res >= 0); - - // set object index entry 1+2 to a data page 0 - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + sizeof(spiffs_page_object_ix_header) + 1 * sizeof(spiffs_page_ix); - spiffs_page_ix bad_pix_ref = dpix; - area_write(addr, (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - area_write(addr+sizeof(spiffs_page_ix), (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - - // delete all cache -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - - -TEST(page_cons3) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify object index, find object index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - // set object index entry 1+2 lookup page - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + sizeof(spiffs_page_object_ix_header) + 1 * sizeof(spiffs_page_ix); - spiffs_page_ix bad_pix_ref = SPIFFS_PAGES_PER_BLOCK(FS) * (*FS.block_count - 2); - area_write(addr, (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - area_write(addr+sizeof(spiffs_page_ix), (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - - // delete all cache -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(page_cons_final) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify page header, make unfinalized - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 1, 0, &pix); - TEST_CHECK(res >= 0); - - // set page span ix 1 as unfinalized - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + offsetof(spiffs_page_header, flags); - u8_t flags; - area_read(addr, (u8_t*)&flags, 1); - flags |= SPIFFS_PH_FLAG_FINAL; - area_write(addr, (u8_t*)&flags, 1); - - // delete all cache -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(index_cons1) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*SPIFFS_PAGES_PER_BLOCK(FS); - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify lu entry data page index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - printf(" deleting lu entry pix %04x\n", pix); - // reset lu entry to being erased, but keep page data - spiffs_obj_id obj_id = SPIFFS_OBJ_ID_DELETED; - spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(FS, pix); - int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(FS, pix); - u32_t addr = SPIFFS_BLOCK_TO_PADDR(FS, bix) + entry * sizeof(spiffs_obj_id); - - area_write(addr, (u8_t*)&obj_id, sizeof(spiffs_obj_id)); - -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(index_cons2) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*SPIFFS_PAGES_PER_BLOCK(FS); - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify lu entry data page index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - printf(" writing lu entry for index page, ix %04x, as data page\n", pix); - spiffs_obj_id obj_id = 0x1234; - spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(FS, pix); - int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(FS, pix); - u32_t addr = SPIFFS_BLOCK_TO_PADDR(FS, bix) + entry * sizeof(spiffs_obj_id); - - area_write(addr, (u8_t*)&obj_id, sizeof(spiffs_obj_id)); - -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - - -TEST(index_cons3) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*SPIFFS_PAGES_PER_BLOCK(FS); - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify lu entry data page index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - printf(" setting lu entry pix %04x to another index page\n", pix); - // reset lu entry to being erased, but keep page data - spiffs_obj_id obj_id = 1234 | SPIFFS_OBJ_ID_IX_FLAG; - spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(FS, pix); - int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(FS, pix); - u32_t addr = SPIFFS_BLOCK_TO_PADDR(FS, bix) + entry * sizeof(spiffs_obj_id); - - area_write(addr, (u8_t*)&obj_id, sizeof(spiffs_obj_id)); - -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - SPIFFS_check(FS); - - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} TEST_END - -TEST(index_cons4) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*SPIFFS_PAGES_PER_BLOCK(FS); - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify lu entry data page index header, flags - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - printf(" cue objix hdr deletion in page %04x\n", pix); - // set flags as deleting ix header - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + offsetof(spiffs_page_header, flags); - u8_t flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE); - - area_write(addr, (u8_t*)&flags, 1); - -#if SPIFFS_CACHE - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - SPIFFS_check(FS); - - return TEST_RES_OK; -} TEST_END - -SUITE_TESTS(check_tests) - ADD_TEST(evil_write) - ADD_TEST(lu_check1) - ADD_TEST(page_cons1) - ADD_TEST(page_cons2) - ADD_TEST(page_cons3) - ADD_TEST(page_cons_final) - ADD_TEST(index_cons1) - ADD_TEST(index_cons2) - ADD_TEST(index_cons3) - ADD_TEST(index_cons4) -SUITE_END(check_tests) diff --git a/src/spiffs/test/test_dev.c b/src/spiffs/test/test_dev.c deleted file mode 100644 index 552e9d4..0000000 --- a/src/spiffs/test/test_dev.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * test_dev.c - * - * Created on: Jul 14, 2013 - * Author: petera - */ - - -#include "testrunner.h" -#include "test_spiffs.h" -#include "spiffs_nucleus.h" -#include "spiffs.h" -#include -#include -#include -#include -#include - - -SUITE(dev_tests) -static void setup() { - _setup(); -} -static void teardown() { - _teardown(); -} - -TEST(interrupted_write) { - char *name = "interrupt"; - char *name2 = "interrupt2"; - int res; - spiffs_file fd; - - const u32_t sz = SPIFFS_CFG_LOG_PAGE_SZ(FS)*8; - u8_t *buf = malloc(sz); - memrand(buf, sz); - - printf(" create reference file\n"); - fd = SPIFFS_open(FS, name, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - clear_flash_ops_log(); - res = SPIFFS_write(FS, fd, buf, sz); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - u32_t written = get_flash_ops_log_write_bytes(); - printf(" written bytes: %i\n", written); - - - printf(" create error file\n"); - fd = SPIFFS_open(FS, name2, SPIFFS_RDWR | SPIFFS_CREAT | SPIFFS_TRUNC, 0); - TEST_CHECK(fd > 0); - clear_flash_ops_log(); - invoke_error_after_write_bytes(written/2, 0); - res = SPIFFS_write(FS, fd, buf, sz); - SPIFFS_close(FS, fd); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_TEST); - - clear_flash_ops_log(); - -#if SPIFFS_CACHE - // delete all cache - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - - printf(" read error file\n"); - fd = SPIFFS_open(FS, name2, SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - printf(" file size: %i\n", s.size); - - if (s.size > 0) { - u8_t *buf2 = malloc(s.size); - res = SPIFFS_read(FS, fd, buf2, s.size); - TEST_CHECK(res >= 0); - - u32_t ix = 0; - for (ix = 0; ix < s.size; ix += 16) { - int i; - printf(" "); - for (i = 0; i < 16; i++) { - printf("%02x", buf[ix+i]); - } - printf(" "); - for (i = 0; i < 16; i++) { - printf("%02x", buf2[ix+i]); - } - printf("\n"); - } - free(buf2); - } - SPIFFS_close(FS, fd); - - - printf(" FS check\n"); - SPIFFS_check(FS); - - printf(" read error file again\n"); - fd = SPIFFS_open(FS, name2, SPIFFS_APPEND | SPIFFS_RDWR, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - printf(" file size: %i\n", s.size); - printf(" write file\n"); - res = SPIFFS_write(FS, fd, buf, sz); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - free(buf); - - return TEST_RES_OK; - -} TEST_END - -SUITE_TESTS(dev_tests) - ADD_TEST(interrupted_write) -SUITE_END(dev_tests) diff --git a/src/spiffs/test/test_hydrogen.c b/src/spiffs/test/test_hydrogen.c deleted file mode 100644 index 52126b2..0000000 --- a/src/spiffs/test/test_hydrogen.c +++ /dev/null @@ -1,2507 +0,0 @@ -/* - * test_suites.c - * - * Created on: Jun 19, 2013 - * Author: petera - */ - - -#include "testrunner.h" -#include "test_spiffs.h" -#include "spiffs_nucleus.h" -#include "spiffs.h" -#include -#include -#include -#include -#include - -SUITE(hydrogen_tests) -static void setup() { - _setup(); -} -static void teardown() { - _teardown(); -} - -TEST(info) -{ - u32_t used, total; - int res = SPIFFS_info(FS, &total, &used); - TEST_CHECK(res == SPIFFS_OK); - TEST_CHECK(used == 0); - TEST_CHECK(total < SPIFFS_CFG_PHYS_SZ(&__fs)); - return TEST_RES_OK; -} -TEST_END - -#if SPIFFS_USE_MAGIC -TEST(magic) -{ - fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); - SPIFFS_unmount(FS); - - TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK); - SPIFFS_unmount(FS); - - TEST_CHECK_NEQ(fs_mount_specific(0, 65536*16, 65536, 65536, 128), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - TEST_CHECK_NEQ(fs_mount_specific(4, 65536*16, 65536, 65536, 256), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - return TEST_RES_OK; -} -TEST_END - - -#if SPIFFS_USE_MAGIC_LENGTH -TEST(magic_length) -{ - fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); - SPIFFS_unmount(FS); - - TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK); - SPIFFS_unmount(FS); - - TEST_CHECK_NEQ(fs_mount_specific(0, 65536*8, 65536, 65536, 256), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - TEST_CHECK_NEQ(fs_mount_specific(0, 65536*15, 65536, 65536, 256), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - TEST_CHECK_NEQ(fs_mount_specific(0, 65536*17, 65536, 65536, 256), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - TEST_CHECK_NEQ(fs_mount_specific(0, 65536*256, 65536, 65536, 256), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); - - return TEST_RES_OK; -} -TEST_END - -#if SPIFFS_SINGLETON==0 -TEST(magic_length_probe) -{ - fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 65536*16); - - fs_reset_specific(0, 0, 65536*24, 65536, 65536, 256); - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 65536*24); - - fs_reset_specific(0, 0, 32768*16, 32768, 32768, 128); - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 32768*16); - - fs_reset_specific(0, 0, 16384*37, 16384, 16384, 128); - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 16384*37); - - fs_reset_specific(0, 0, 4096*11, 4096, 4096, 256); - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 4096*11); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - __fs.cfg.log_page_size = 128; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - __fs.cfg.log_page_size = 512; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - __fs.cfg.log_page_size = 256; - __fs.cfg.log_block_size = 8192; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - __fs.cfg.log_block_size = 2048; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - __fs.cfg.log_block_size = 4096; - __fs.cfg.phys_addr += 2; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - __fs.cfg.phys_addr += 4096*6; - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096); // "erase" block 0 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 4096*8); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096); // "erase" block 1 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 4096*8); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096); // "erase" block 2 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), 4096*8); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096*2); // "erase" block 0 & 1 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096*2); // "erase" block 0 - area_set(4096*0, 0xff, 4096); // "erase" block 2 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*1, 0xff, 4096*2); // "erase" block 1 & 2 - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xff, 4096*8); // "erase" all - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - fs_reset_specific(0, 0, 4096*8, 4096, 4096, 256); - area_set(4096*0, 0xdd, 4096*8); // garble all - TEST_CHECK_EQ(SPIFFS_probe_fs(&__fs.cfg), SPIFFS_ERR_PROBE_NOT_A_FS); - - return TEST_RES_OK; -} -TEST_END - -#endif // SPIFFS_SINGLETON==0 - -#endif // SPIFFS_USE_MAGIC_LENGTH - -#endif // SPIFFS_USE_MAGIC - -TEST(missing_file) -{ - spiffs_file fd = SPIFFS_open(FS, "this_wont_exist", SPIFFS_RDONLY, 0); - TEST_CHECK(fd < 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(bad_fd) -{ - int res; - spiffs_stat s; - spiffs_file fd = SPIFFS_open(FS, "this_wont_exist", SPIFFS_RDONLY, 0); - TEST_CHECK(fd < 0); - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_CUR); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); - res = SPIFFS_read(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); - res = SPIFFS_write(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); -#if SPIFFS_OBJ_META_LEN - u8_t new_meta[SPIFFS_OBJ_META_LEN] = {0}; - res = SPIFFS_fupdate_meta(FS, fd, new_meta); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_BAD_DESCRIPTOR); -#endif - return TEST_RES_OK; -} -TEST_END - - -TEST(closed_fd) -{ - int res; - spiffs_stat s; - res = test_create_file("file"); - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - SPIFFS_close(FS, fd); - - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_CUR); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_read(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_write(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); -#if SPIFFS_OBJ_META_LEN - u8_t new_meta[SPIFFS_OBJ_META_LEN] = {0}; - res = SPIFFS_fupdate_meta(FS, fd, new_meta); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); -#endif - return TEST_RES_OK; -} -TEST_END - - -TEST(deleted_same_fd) -{ - int res; - spiffs_stat s; - spiffs_file fd; - res = test_create_file("remove"); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res >= 0); - - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_CUR); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_read(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_write(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - - return TEST_RES_OK; -} -TEST_END - - -TEST(deleted_other_fd) -{ - int res; - spiffs_stat s; - spiffs_file fd, fd_orig; - res = test_create_file("remove"); - fd_orig = SPIFFS_open(FS, "remove", SPIFFS_RDWR, 0); - TEST_CHECK(fd_orig >= 0); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fremove(FS, fd_orig); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd_orig); - - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_CUR); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_read(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - res = SPIFFS_write(FS, fd, 0, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_CLOSED); - - return TEST_RES_OK; -} -TEST_END - - -TEST(file_by_open) -{ - int res; - spiffs_stat s; - spiffs_file fd = SPIFFS_open(FS, "filebopen", SPIFFS_CREAT, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - TEST_CHECK(strcmp((char*)s.name, "filebopen") == 0); - TEST_CHECK(s.size == 0); - SPIFFS_close(FS, fd); - - fd = SPIFFS_open(FS, "filebopen", SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - TEST_CHECK(strcmp((char*)s.name, "filebopen") == 0); - TEST_CHECK(s.size == 0); - SPIFFS_close(FS, fd); - return TEST_RES_OK; -} -TEST_END - - -TEST(file_by_creat) -{ - int res; - res = test_create_file("filebcreat"); - TEST_CHECK(res >= 0); - res = SPIFFS_creat(FS, "filebcreat", 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS)==SPIFFS_ERR_CONFLICTING_NAME); - return TEST_RES_OK; -} -TEST_END - -TEST(file_by_open_excl) -{ - int res; - spiffs_stat s; - spiffs_file fd = SPIFFS_open(FS, "filebexcl", SPIFFS_CREAT | SPIFFS_EXCL, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - TEST_CHECK(strcmp((char*)s.name, "filebexcl") == 0); - TEST_CHECK(s.size == 0); - SPIFFS_close(FS, fd); - - fd = SPIFFS_open(FS, "filebexcl", SPIFFS_CREAT | SPIFFS_EXCL, 0); - TEST_CHECK(fd < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_FILE_EXISTS); - - return TEST_RES_OK; -} -TEST_END - -#if SPIFFS_FILEHDL_OFFSET -TEST(open_fh_offs) -{ - spiffs_file fd1, fd2, fd3; - fd1 = SPIFFS_open(FS, "1", SPIFFS_CREAT | SPIFFS_EXCL, 0); - fd2 = SPIFFS_open(FS, "2", SPIFFS_CREAT | SPIFFS_EXCL, 0); - fd3 = SPIFFS_open(FS, "3", SPIFFS_CREAT | SPIFFS_EXCL, 0); - TEST_CHECK(fd1 >= TEST_SPIFFS_FILEHDL_OFFSET); - TEST_CHECK(fd2 >= TEST_SPIFFS_FILEHDL_OFFSET); - TEST_CHECK(fd3 >= TEST_SPIFFS_FILEHDL_OFFSET); - SPIFFS_close(FS, fd1); - fd1 = SPIFFS_open(FS, "2", SPIFFS_RDONLY, 0); - TEST_CHECK(fd1 >= TEST_SPIFFS_FILEHDL_OFFSET); - SPIFFS_close(FS, fd2); - fd2 = SPIFFS_open(FS, "3", SPIFFS_RDONLY, 0); - TEST_CHECK(fd2 >= TEST_SPIFFS_FILEHDL_OFFSET); - SPIFFS_close(FS, fd3); - fd3 = SPIFFS_open(FS, "1", SPIFFS_RDONLY, 0); - TEST_CHECK(fd3 >= TEST_SPIFFS_FILEHDL_OFFSET); - SPIFFS_close(FS, fd1); - SPIFFS_close(FS, fd2); - SPIFFS_close(FS, fd3); - fd1 = SPIFFS_open(FS, "3", SPIFFS_RDONLY, 0); - TEST_CHECK(fd1 >= TEST_SPIFFS_FILEHDL_OFFSET); - SPIFFS_close(FS, fd1); - fd1 = SPIFFS_open(FS, "foo", SPIFFS_RDONLY, 0); - TEST_CHECK(fd1 < TEST_SPIFFS_FILEHDL_OFFSET); - - return TEST_RES_OK; -} -TEST_END - -#endif //SPIFFS_FILEHDL_OFFSET - -TEST(list_dir) -{ - int res; - - char *files[4] = { - "file1", - "file2", - "file3", - "file4" - }; - int file_cnt = sizeof(files)/sizeof(char *); - - int i; - - for (i = 0; i < file_cnt; i++) { - res = test_create_file(files[i]); - TEST_CHECK(res >= 0); - } - - spiffs_DIR d; - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - - SPIFFS_opendir(FS, "/", &d); - int found = 0; - while ((pe = SPIFFS_readdir(&d, pe))) { - printf(" %s [%04x] size:%i\n", pe->name, pe->obj_id, pe->size); - for (i = 0; i < file_cnt; i++) { - if (strcmp(files[i], (char *)pe->name) == 0) { - found++; - break; - } - } - { - spiffs_stat s; - TEST_CHECK_EQ(SPIFFS_stat(FS, pe->name, &s), 0); - TEST_CHECK_EQ(pe->obj_id, s.obj_id); - TEST_CHECK_EQ(pe->size, s.size); - TEST_CHECK_EQ(pe->type, s.type); - TEST_CHECK_EQ(pe->pix, s.pix); -#if SPIFFS_OBJ_META_LEN - TEST_CHECK_EQ(memcmp(pe->meta, s.meta, SPIFFS_OBJ_META_LEN), 0); -#endif - } - } - SPIFFS_closedir(&d); - - TEST_CHECK(found == file_cnt); - - return TEST_RES_OK; -} -TEST_END - - -TEST(open_by_dirent) { - int res; - - char *files[4] = { - "file1", - "file2", - "file3", - "file4" - }; - int file_cnt = sizeof(files)/sizeof(char *); - - int i; - int size = SPIFFS_DATA_PAGE_SIZE(FS); - - for (i = 0; i < file_cnt; i++) { - res = test_create_and_write_file(files[i], size, size); - TEST_CHECK(res >= 0); - } - - spiffs_DIR d; - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - - int found = 0; - SPIFFS_opendir(FS, "/", &d); - while ((pe = SPIFFS_readdir(&d, pe))) { - spiffs_file fd = SPIFFS_open_by_dirent(FS, pe, SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = read_and_verify_fd(fd, (char *)pe->name); - TEST_CHECK(res == SPIFFS_OK); - fd = SPIFFS_open_by_dirent(FS, pe, SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res == SPIFFS_OK); - SPIFFS_close(FS, fd); - found++; - } - SPIFFS_closedir(&d); - - TEST_CHECK(found == file_cnt); - - found = 0; - SPIFFS_opendir(FS, "/", &d); - while ((pe = SPIFFS_readdir(&d, pe))) { - found++; - } - SPIFFS_closedir(&d); - - TEST_CHECK(found == 0); - - return TEST_RES_OK; - -} TEST_END - - -TEST(open_by_page) { - int res; - - char *files[4] = { - "file1", - "file2", - "file3", - "file4" - }; - int file_cnt = sizeof(files)/sizeof(char *); - - int i; - int size = SPIFFS_DATA_PAGE_SIZE(FS); - - for (i = 0; i < file_cnt; i++) { - res = test_create_and_write_file(files[i], size, size); - TEST_CHECK(res >= 0); - } - - spiffs_DIR d; - struct spiffs_dirent e; - struct spiffs_dirent *pe = &e; - - int found = 0; - SPIFFS_opendir(FS, "/", &d); - while ((pe = SPIFFS_readdir(&d, pe))) { - spiffs_file fd = SPIFFS_open_by_dirent(FS, pe, SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = read_and_verify_fd(fd, (char *)pe->name); - TEST_CHECK(res == SPIFFS_OK); - fd = SPIFFS_open_by_page(FS, pe->pix, SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res == SPIFFS_OK); - SPIFFS_close(FS, fd); - found++; - } - SPIFFS_closedir(&d); - - TEST_CHECK(found == file_cnt); - - found = 0; - SPIFFS_opendir(FS, "/", &d); - while ((pe = SPIFFS_readdir(&d, pe))) { - found++; - } - SPIFFS_closedir(&d); - - TEST_CHECK(found == 0); - - spiffs_file fd; - // test opening a lookup page - fd = SPIFFS_open_by_page(FS, 0, SPIFFS_RDWR, 0); - TEST_CHECK_LT(fd, 0); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FILE); - // test opening a proper page but not being object index - fd = SPIFFS_open_by_page(FS, SPIFFS_OBJ_LOOKUP_PAGES(FS)+1, SPIFFS_RDWR, 0); - TEST_CHECK_LT(fd, 0); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FILE); - - return TEST_RES_OK; -} TEST_END - - -static struct { - u32_t calls; - spiffs_fileop_type op; - spiffs_obj_id obj_id; - spiffs_page_ix pix; -} ucb; - -void test_cb(spiffs *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix) { - ucb.calls++; - ucb.op = op; - ucb.obj_id = obj_id; - ucb.pix = pix; - //printf("%4i op:%i objid:%04x pix:%04x\n", ucb.calls, ucb.op, ucb.obj_id, ucb.pix); -} - -TEST(user_callback_basic) { - SPIFFS_set_file_callback_func(FS, test_cb); - int res; - memset(&ucb, 0, sizeof(ucb)); - spiffs_file fd = SPIFFS_open(FS, "foo", SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_RDWR, 0); - TEST_CHECK_GE(fd, 0); - TEST_CHECK_EQ(ucb.calls, 1); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_CREATED); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - res = SPIFFS_write(FS, fd, "howdy partner", 14); - TEST_CHECK_GE(res, 0); - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.calls, 2); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - res = SPIFFS_fremove(FS, fd); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.calls, 3); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_DELETED); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - return TEST_RES_OK; -} TEST_END - - -TEST(user_callback_gc) { - SPIFFS_set_file_callback_func(FS, test_cb); - - char name[32]; - int f; - int size = SPIFFS_DATA_PAGE_SIZE(FS); - int pages_per_block = SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS); - int files = (pages_per_block-1)/2; - int res; - - // fill block with files - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = test_create_and_write_file(name, size, 1); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - // remove all files in block - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = SPIFFS_remove(FS, name); - TEST_CHECK(res >= 0); - } - - memset(&ucb, 0, sizeof(ucb)); - spiffs_file fd = SPIFFS_open(FS, "foo", SPIFFS_CREAT | SPIFFS_APPEND | SPIFFS_RDWR, 0); - TEST_CHECK_GE(fd, 0); - TEST_CHECK_EQ(ucb.calls, 1); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_CREATED); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - res = SPIFFS_write(FS, fd, "howdy partner", 14); - TEST_CHECK_GE(res, 0); - res = SPIFFS_fflush(FS, fd); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.calls, 2); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - u32_t tot, us; - SPIFFS_info(FS, &tot, &us); - - // do a hard gc, should move our file - res = SPIFFS_gc(FS, tot-us*2); - TEST_CHECK_GE(res, 0); - - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.calls, 3); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_UPDATED); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_NEQ(ucb.pix, s.pix); - - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.pix, s.pix); - - res = SPIFFS_fremove(FS, fd); - TEST_CHECK_GE(res, 0); - TEST_CHECK_EQ(ucb.calls, 4); - TEST_CHECK_EQ(ucb.op, SPIFFS_CB_DELETED); - TEST_CHECK_EQ(ucb.obj_id, s.obj_id); - TEST_CHECK_EQ(ucb.pix, s.pix); - - return TEST_RES_OK; -} TEST_END - - -TEST(name_too_long) { - char name[SPIFFS_OBJ_NAME_LEN*2]; - memset(name, 0, sizeof(name)); - int i; - for (i = 0; i < SPIFFS_OBJ_NAME_LEN; i++) { - name[i] = 'A'; - } - - TEST_CHECK_LT(SPIFFS_creat(FS, name, 0), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - TEST_CHECK_LT(SPIFFS_open(FS, name, SPIFFS_CREAT | SPIFFS_TRUNC, 0), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - TEST_CHECK_LT(SPIFFS_remove(FS, name), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - spiffs_stat s; - TEST_CHECK_LT(SPIFFS_stat(FS, name, &s), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - TEST_CHECK_LT(SPIFFS_rename(FS, name, "a"), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - TEST_CHECK_LT(SPIFFS_rename(FS, "a", name), SPIFFS_OK); - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NAME_TOO_LONG); - - return TEST_RES_OK; -} TEST_END - - -TEST(rename) { - int res; - - char *src_name = "baah"; - char *dst_name = "booh"; - char *dst_name2 = "beeh"; - int size = SPIFFS_DATA_PAGE_SIZE(FS); - - res = test_create_and_write_file(src_name, size, size); - TEST_CHECK(res >= 0); - - res = SPIFFS_rename(FS, src_name, dst_name); - TEST_CHECK(res >= 0); - - res = SPIFFS_rename(FS, dst_name, dst_name); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_CONFLICTING_NAME); - - res = SPIFFS_rename(FS, src_name, dst_name2); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_FOUND); - - return TEST_RES_OK; -} TEST_END - -#if SPIFFS_OBJ_META_LEN -TEST(update_meta) { - s32_t i, res, fd; - spiffs_stat s; - u8_t new_meta[SPIFFS_OBJ_META_LEN], new_meta2[SPIFFS_OBJ_META_LEN]; - - res = test_create_file("foo"); - TEST_CHECK(res >= 0); - - for (i = 0; i < SPIFFS_OBJ_META_LEN; i++) { - new_meta[i] = 0xaa; - } - res = SPIFFS_update_meta(FS, "foo", new_meta); - TEST_CHECK(res >= 0); - - res = SPIFFS_stat(FS, "foo", &s); - TEST_CHECK(res >= 0); - TEST_CHECK_EQ(memcmp(s.meta, new_meta, SPIFFS_OBJ_META_LEN), 0); - - for (i = 0; i < SPIFFS_OBJ_META_LEN; i++) { - new_meta2[i] = 0xbb; - } - - fd = SPIFFS_open(FS, "foo", SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fupdate_meta(FS, fd, new_meta2); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_WRITABLE); - SPIFFS_close(FS, fd); - - res = SPIFFS_stat(FS, "foo", &s); - TEST_CHECK(res >= 0); - TEST_CHECK_EQ(memcmp(s.meta, new_meta, SPIFFS_OBJ_META_LEN), 0); - - fd = SPIFFS_open(FS, "foo", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fupdate_meta(FS, fd, new_meta2); - TEST_CHECK_EQ(res, 0); - SPIFFS_close(FS, fd); - - res = SPIFFS_stat(FS, "foo", &s); - TEST_CHECK(res >= 0); - TEST_CHECK_EQ(memcmp(s.meta, new_meta2, SPIFFS_OBJ_META_LEN), 0); - - return TEST_RES_OK; -} TEST_END -#endif - -TEST(remove_single_by_path) -{ - int res; - spiffs_file fd; - res = test_create_file("remove"); - TEST_CHECK(res >= 0); - res = SPIFFS_remove(FS, "remove"); - TEST_CHECK(res >= 0); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDONLY, 0); - TEST_CHECK(fd < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_FOUND); - - return TEST_RES_OK; -} -TEST_END - - -TEST(remove_single_by_fd) -{ - int res; - spiffs_file fd; - res = test_create_file("remove"); - TEST_CHECK(res >= 0); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - fd = SPIFFS_open(FS, "remove", SPIFFS_RDONLY, 0); - TEST_CHECK(fd < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_FOUND); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_cache) -{ - int res; - spiffs_file fd; - u8_t buf[1024*8]; - u8_t fbuf[1024*8]; - res = test_create_file("f"); - TEST_CHECK(res >= 0); - fd = SPIFFS_open(FS, "f", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd, buf, SPIFFS_CFG_LOG_PAGE_SZ(FS)/2); - TEST_CHECK(res >= 0); - res = SPIFFS_write(FS, fd, buf, SPIFFS_CFG_LOG_PAGE_SZ(FS)*2); - TEST_CHECK(res >= 0); - res = SPIFFS_close(FS, fd); - TEST_CHECK(res >= 0); - - fd = SPIFFS_open(FS, "f", SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_read(FS, fd, fbuf, SPIFFS_CFG_LOG_PAGE_SZ(FS)/2 + SPIFFS_CFG_LOG_PAGE_SZ(FS)*2); - TEST_CHECK(res >= 0); - TEST_CHECK(0 == memcmp(&buf[0], &fbuf[0], SPIFFS_CFG_LOG_PAGE_SZ(FS)/2)); - TEST_CHECK(0 == memcmp(&buf[0], &fbuf[SPIFFS_CFG_LOG_PAGE_SZ(FS)/2], SPIFFS_CFG_LOG_PAGE_SZ(FS)*2)); - res = SPIFFS_close(FS, fd); - TEST_CHECK(res >= 0); - - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_OK); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_file_chunks_page) -{ - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100); - printf(" filesize %i\n", size); - int res = test_create_and_write_file("bigfile", size, SPIFFS_DATA_PAGE_SIZE(FS)); - TEST_CHECK(res >= 0); - res = read_and_verify("bigfile"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_files_chunks_page) -{ - char name[32]; - int f; - int files = 10; - int res; - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100)/files; - printf(" filesize %i\n", size); - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = test_create_and_write_file(name, size, SPIFFS_DATA_PAGE_SIZE(FS)); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_file_chunks_index) -{ - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100); - printf(" filesize %i\n", size); - int res = test_create_and_write_file("bigfile", size, SPIFFS_DATA_PAGE_SIZE(FS) * SPIFFS_OBJ_HDR_IX_LEN(FS)); - TEST_CHECK(res >= 0); - res = read_and_verify("bigfile"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_files_chunks_index) -{ - char name[32]; - int f; - int files = 10; - int res; - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100)/files; - printf(" filesize %i\n", size); - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = test_create_and_write_file(name, size, SPIFFS_DATA_PAGE_SIZE(FS) * SPIFFS_OBJ_HDR_IX_LEN(FS)); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_file_chunks_huge) -{ - int size = (FS_PURE_DATA_PAGES(FS) / 2) * SPIFFS_DATA_PAGE_SIZE(FS); - printf(" filesize %i\n", size); - int res = test_create_and_write_file("bigfile", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("bigfile"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_big_files_chunks_huge) -{ - char name[32]; - int f; - int files = 10; - int res; - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100)/files; - printf(" filesize %i\n", size); - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = test_create_and_write_file(name, size, size); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - - return TEST_RES_OK; -} -TEST_END - - -TEST(truncate_big_file) -{ - int size = (FS_PURE_DATA_PAGES(FS) / 2) * SPIFFS_DATA_PAGE_SIZE(FS); - printf(" filesize %i\n", size); - int res = test_create_and_write_file("bigfile", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("bigfile"); - TEST_CHECK(res >= 0); - spiffs_file fd = SPIFFS_open(FS, "bigfile", SPIFFS_RDWR, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_fremove(FS, fd); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - fd = SPIFFS_open(FS, "bigfile", SPIFFS_RDWR, 0); - TEST_CHECK(fd < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NOT_FOUND); - - return TEST_RES_OK; -} -TEST_END - - -TEST(simultaneous_write) { - int res = SPIFFS_creat(FS, "simul1", 0); - TEST_CHECK(res >= 0); - - spiffs_file fd1 = SPIFFS_open(FS, "simul1", SPIFFS_RDWR, 0); - TEST_CHECK(fd1 > 0); - spiffs_file fd2 = SPIFFS_open(FS, "simul1", SPIFFS_RDWR, 0); - TEST_CHECK(fd2 > 0); - spiffs_file fd3 = SPIFFS_open(FS, "simul1", SPIFFS_RDWR, 0); - TEST_CHECK(fd3 > 0); - - u8_t data1 = 1; - u8_t data2 = 2; - u8_t data3 = 3; - - res = SPIFFS_write(FS, fd1, &data1, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd1); - res = SPIFFS_write(FS, fd2, &data2, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd2); - res = SPIFFS_write(FS, fd3, &data3, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd3); - - spiffs_stat s; - res = SPIFFS_stat(FS, "simul1", &s); - TEST_CHECK(res >= 0); - - TEST_CHECK(s.size == 1); - - u8_t rdata; - spiffs_file fd = SPIFFS_open(FS, "simul1", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_read(FS, fd, &rdata, 1); - TEST_CHECK(res >= 0); - - TEST_CHECK(rdata == data3); - - return TEST_RES_OK; -} -TEST_END - - -TEST(simultaneous_write_append) { - int res = SPIFFS_creat(FS, "simul2", 0); - TEST_CHECK(res >= 0); - - spiffs_file fd1 = SPIFFS_open(FS, "simul2", SPIFFS_RDWR | SPIFFS_APPEND, 0); - TEST_CHECK(fd1 > 0); - spiffs_file fd2 = SPIFFS_open(FS, "simul2", SPIFFS_RDWR | SPIFFS_APPEND, 0); - TEST_CHECK(fd2 > 0); - spiffs_file fd3 = SPIFFS_open(FS, "simul2", SPIFFS_RDWR | SPIFFS_APPEND, 0); - TEST_CHECK(fd3 > 0); - - u8_t data1 = 1; - u8_t data2 = 2; - u8_t data3 = 3; - - res = SPIFFS_write(FS, fd1, &data1, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd1); - res = SPIFFS_write(FS, fd2, &data2, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd2); - res = SPIFFS_write(FS, fd3, &data3, 1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd3); - - spiffs_stat s; - res = SPIFFS_stat(FS, "simul2", &s); - TEST_CHECK(res >= 0); - - TEST_CHECK(s.size == 3); - - u8_t rdata[3]; - spiffs_file fd = SPIFFS_open(FS, "simul2", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - res = SPIFFS_read(FS, fd, &rdata, 3); - TEST_CHECK(res >= 0); - - TEST_CHECK(rdata[0] == data1); - TEST_CHECK(rdata[1] == data2); - TEST_CHECK(rdata[2] == data3); - - return TEST_RES_OK; -} -TEST_END - -TEST(file_uniqueness) -{ - int res; - spiffs_file fd; - char fname[32]; - int files = ((SPIFFS_CFG_PHYS_SZ(FS) * 75) / 100) / 2 / SPIFFS_CFG_LOG_PAGE_SZ(FS); - //(FS_PURE_DATA_PAGES(FS) / 2) - SPIFFS_PAGES_PER_BLOCK(FS)*8; - int i; - printf(" creating %i files\n", files); - for (i = 0; i < files; i++) { - char content[20]; - sprintf(fname, "file%i", i); - sprintf(content, "%i", i); - res = test_create_file(fname); - TEST_CHECK(res >= 0); - fd = SPIFFS_open(FS, fname, SPIFFS_APPEND | SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_write(FS, fd, content, strlen(content)+1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - } - printf(" checking %i files\n", files); - for (i = 0; i < files; i++) { - char content[20]; - char ref_content[20]; - sprintf(fname, "file%i", i); - sprintf(content, "%i", i); - fd = SPIFFS_open(FS, fname, SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_read(FS, fd, ref_content, strlen(content)+1); - TEST_CHECK(res >= 0); - TEST_CHECK(strcmp(ref_content, content) == 0); - SPIFFS_close(FS, fd); - } - printf(" removing %i files\n", files/2); - for (i = 0; i < files; i += 2) { - sprintf(fname, "file%i", i); - res = SPIFFS_remove(FS, fname); - TEST_CHECK(res >= 0); - } - printf(" creating %i files\n", files/2); - for (i = 0; i < files; i += 2) { - char content[20]; - sprintf(fname, "file%i", i); - sprintf(content, "new%i", i); - res = test_create_file(fname); - TEST_CHECK(res >= 0); - fd = SPIFFS_open(FS, fname, SPIFFS_APPEND | SPIFFS_RDWR, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_write(FS, fd, content, strlen(content)+1); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - } - printf(" checking %i files\n", files); - for (i = 0; i < files; i++) { - char content[20]; - char ref_content[20]; - sprintf(fname, "file%i", i); - if ((i & 1) == 0) { - sprintf(content, "new%i", i); - } else { - sprintf(content, "%i", i); - } - fd = SPIFFS_open(FS, fname, SPIFFS_RDONLY, 0); - TEST_CHECK(fd >= 0); - res = SPIFFS_read(FS, fd, ref_content, strlen(content)+1); - TEST_CHECK(res >= 0); - TEST_CHECK(strcmp(ref_content, content) == 0); - SPIFFS_close(FS, fd); - } - - return TEST_RES_OK; -} -TEST_END - -int create_and_read_back(int size, int chunk) { - char *name = "file"; - spiffs_file fd; - s32_t res; - - u8_t *buf = malloc(size); - memrand(buf, size); - - res = test_create_file(name); - CHECK(res >= 0); - fd = SPIFFS_open(FS, name, SPIFFS_APPEND | SPIFFS_RDWR, 0); - CHECK(fd >= 0); - res = SPIFFS_write(FS, fd, buf, size); - CHECK(res >= 0); - - spiffs_stat stat; - res = SPIFFS_fstat(FS, fd, &stat); - CHECK(res >= 0); - CHECK(stat.size == size); - - SPIFFS_close(FS, fd); - - fd = SPIFFS_open(FS, name, SPIFFS_RDONLY, 0); - CHECK(fd >= 0); - - u8_t *rbuf = malloc(size); - int offs = 0; - while (offs < size) { - int len = MIN(size - offs, chunk); - res = SPIFFS_read(FS, fd, &rbuf[offs], len); - CHECK(res >= 0); - CHECK(memcmp(&rbuf[offs], &buf[offs], len) == 0); - - offs += chunk; - } - - CHECK(memcmp(&rbuf[0], &buf[0], size) == 0); - - SPIFFS_close(FS, fd); - - free(rbuf); - free(buf); - - return 0; -} - -TEST(read_chunk_1) -{ - TEST_CHECK(create_and_read_back(SPIFFS_DATA_PAGE_SIZE(FS)*8, 1) == 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(read_chunk_page) -{ - TEST_CHECK(create_and_read_back(SPIFFS_DATA_PAGE_SIZE(FS)*(SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS))*2, - SPIFFS_DATA_PAGE_SIZE(FS)) == 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(read_chunk_index) -{ - TEST_CHECK(create_and_read_back(SPIFFS_DATA_PAGE_SIZE(FS)*(SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS))*4, - SPIFFS_DATA_PAGE_SIZE(FS)*(SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS))) == 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(read_chunk_huge) -{ - int sz = (2*SPIFFS_CFG_PHYS_SZ(FS))/3; - TEST_CHECK(create_and_read_back(sz, sz) == 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(read_beyond) -{ - char *name = "file"; - spiffs_file fd; - s32_t res; - u32_t size = SPIFFS_DATA_PAGE_SIZE(FS)*2; - - u8_t *buf = malloc(size); - memrand(buf, size); - - res = test_create_file(name); - CHECK(res >= 0); - fd = SPIFFS_open(FS, name, SPIFFS_APPEND | SPIFFS_RDWR, 0); - CHECK(fd >= 0); - res = SPIFFS_write(FS, fd, buf, size); - CHECK(res >= 0); - - spiffs_stat stat; - res = SPIFFS_fstat(FS, fd, &stat); - CHECK(res >= 0); - CHECK(stat.size == size); - - SPIFFS_close(FS, fd); - - fd = SPIFFS_open(FS, name, SPIFFS_RDONLY, 0); - CHECK(fd >= 0); - - u8_t *rbuf = malloc(size+10); - res = SPIFFS_read(FS, fd, rbuf, size+10); - - SPIFFS_close(FS, fd); - - free(rbuf); - free(buf); - - TEST_CHECK(res == size); - - return TEST_RES_OK; -} -TEST_END - -TEST(read_beyond2) -{ - char *name = "file"; - spiffs_file fd; - s32_t res; - const s32_t size = SPIFFS_DATA_PAGE_SIZE(FS); - - u8_t buf[size*2]; - memrand(buf, size); - - res = test_create_file(name); - CHECK(res >= 0); - fd = SPIFFS_open(FS, name, SPIFFS_APPEND | SPIFFS_RDWR, 0); - CHECK(fd >= 0); - res = SPIFFS_write(FS, fd, buf, size); - CHECK(res >= 0); - - spiffs_stat stat; - res = SPIFFS_fstat(FS, fd, &stat); - CHECK(res >= 0); - CHECK(stat.size == size); - - SPIFFS_close(FS, fd); - - int i,j; - for (j = 1; j <= size+1; j++) { - fd = SPIFFS_open(FS, name, SPIFFS_RDONLY, 0); - CHECK(fd >= 0); - SPIFFS_clearerr(FS); - for (i = 0; i < size * 2; i += j) { - u8_t dst; - res = SPIFFS_read(FS, fd, buf, j); - TEST_CHECK_EQ(SPIFFS_errno(FS), i < size ? SPIFFS_OK : SPIFFS_ERR_END_OF_OBJECT); - TEST_CHECK_EQ(res, MIN(j, MAX(0, size - (i + j) + j))); - } - SPIFFS_close(FS, fd); - } - - return TEST_RES_OK; -} -TEST_END - - -TEST(bad_index_1) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify object index, find object index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - // set object index entry 2 to a bad page, free - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + sizeof(spiffs_page_object_ix_header) + 2 * sizeof(spiffs_page_ix); - spiffs_page_ix bad_pix_ref = (spiffs_page_ix)-1; - area_write(addr, (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - -#if SPIFFS_CACHE - // delete all cache - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - res = read_and_verify("file"); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_INDEX_REF_FREE); - - return TEST_RES_OK; -} TEST_END - - -TEST(bad_index_2) { - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - int res = test_create_and_write_file("file", size, size); - TEST_CHECK(res >= 0); - res = read_and_verify("file"); - TEST_CHECK(res >= 0); - - spiffs_file fd = SPIFFS_open(FS, "file", SPIFFS_RDONLY, 0); - TEST_CHECK(fd > 0); - spiffs_stat s; - res = SPIFFS_fstat(FS, fd, &s); - TEST_CHECK(res >= 0); - SPIFFS_close(FS, fd); - - // modify object index, find object index header - spiffs_page_ix pix; - res = spiffs_obj_lu_find_id_and_span(FS, s.obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix); - TEST_CHECK(res >= 0); - - // set object index entry 2 to a bad page, lu - u32_t addr = SPIFFS_PAGE_TO_PADDR(FS, pix) + sizeof(spiffs_page_object_ix_header) + 2 * sizeof(spiffs_page_ix); - spiffs_page_ix bad_pix_ref = SPIFFS_OBJ_LOOKUP_PAGES(FS)-1; - area_write(addr, (u8_t*)&bad_pix_ref, sizeof(spiffs_page_ix)); - -#if SPIFFS_CACHE - // delete all cache - spiffs_cache *cache = spiffs_get_cache(FS); - cache->cpage_use_map = 0; -#endif - - res = read_and_verify("file"); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_INDEX_REF_LU); - - return TEST_RES_OK; -} TEST_END - - -TEST(lseek_simple_modification) { - int res; - spiffs_file fd; - char *fname = "seekfile"; - int len = 4096; - 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); - u8_t *buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - - res = SPIFFS_lseek(FS, fd, len/2, SPIFFS_SEEK_SET); - TEST_CHECK(res >= 0); - lseek(pfd, len/2, SEEK_SET); - len = len/4; - buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - - SPIFFS_close(FS, fd); - close(pfd); - - return TEST_RES_OK; -} -TEST_END - - -TEST(lseek_modification_append) { - int res; - spiffs_file fd; - char *fname = "seekfile"; - int len = 4096; - 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); - u8_t *buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - - res = SPIFFS_lseek(FS, fd, len/2, SPIFFS_SEEK_SET); - TEST_CHECK(res >= 0); - lseek(pfd, len/2, SEEK_SET); - - buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - - SPIFFS_close(FS, fd); - close(pfd); - - return TEST_RES_OK; -} -TEST_END - - -TEST(lseek_modification_append_multi) { - int res; - spiffs_file fd; - char *fname = "seekfile"; - int len = 1024; - int runs = (FS_PURE_DATA_PAGES(FS) / 2) * SPIFFS_DATA_PAGE_SIZE(FS) / (len/2); - - 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); - u8_t *buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - - while (runs--) { - res = SPIFFS_lseek(FS, fd, -len/2, SPIFFS_SEEK_END); - TEST_CHECK(res >= 0); - lseek(pfd, -len/2, SEEK_END); - - buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - TEST_CHECK(res >= 0); - write(pfd, buf, len); - free(buf); - - res = read_and_verify(fname); - TEST_CHECK(res >= 0); - } - - SPIFFS_close(FS, fd); - close(pfd); - - return TEST_RES_OK; -} -TEST_END - - -TEST(lseek_read) { - int res; - spiffs_file fd; - char *fname = "seekfile"; - int len = (FS_PURE_DATA_PAGES(FS) / 2) * SPIFFS_DATA_PAGE_SIZE(FS); - int runs = 100000; - - fd = SPIFFS_open(FS, fname, SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0); - TEST_CHECK(fd > 0); - u8_t *refbuf = malloc(len); - memrand(refbuf, len); - res = SPIFFS_write(FS, fd, refbuf, len); - TEST_CHECK(res >= 0); - - int offs = 0; - res = SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_SET); - TEST_CHECK(res >= 0); - - while (runs--) { - int i; - u8_t buf[64]; - if (offs + 41 + sizeof(buf) >= len) { - offs = (offs + 41 + sizeof(buf)) % len; - res = SPIFFS_lseek(FS, fd, offs, SPIFFS_SEEK_SET); - TEST_CHECK(res >= 0); - } - res = SPIFFS_lseek(FS, fd, 41, SPIFFS_SEEK_CUR); - TEST_CHECK(res >= 0); - offs += 41; - res = SPIFFS_read(FS, fd, buf, sizeof(buf)); - TEST_CHECK(res >= 0); - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != refbuf[offs+i]) { - printf(" mismatch at offs %i\n", offs); - } - TEST_CHECK(buf[i] == refbuf[offs+i]); - } - offs += sizeof(buf); - - res = SPIFFS_lseek(FS, fd, -((u32_t)sizeof(buf)+11), SPIFFS_SEEK_CUR); - TEST_CHECK(res >= 0); - offs -= (sizeof(buf)+11); - res = SPIFFS_read(FS, fd, buf, sizeof(buf)); - TEST_CHECK(res >= 0); - for (i = 0; i < sizeof(buf); i++) { - if (buf[i] != refbuf[offs+i]) { - printf(" mismatch at offs %i\n", offs); - } - TEST_CHECK(buf[i] == refbuf[offs+i]); - } - offs += sizeof(buf); - } - - free(refbuf); - SPIFFS_close(FS, fd); - - return TEST_RES_OK; -} -TEST_END - - - -TEST(lseek_oob) { - int res; - spiffs_file fd; - char *fname = "seekfile"; - int len = (FS_PURE_DATA_PAGES(FS) / 2) * SPIFFS_DATA_PAGE_SIZE(FS); - - fd = SPIFFS_open(FS, fname, SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0); - TEST_CHECK(fd > 0); - u8_t *refbuf = malloc(len); - memrand(refbuf, len); - res = SPIFFS_write(FS, fd, refbuf, len); - TEST_CHECK(res >= 0); - - int offs = 0; - res = SPIFFS_lseek(FS, fd, -1, SPIFFS_SEEK_SET); - TEST_CHECK_EQ(res, SPIFFS_ERR_SEEK_BOUNDS); - res = SPIFFS_lseek(FS, fd, len+1, SPIFFS_SEEK_SET); - TEST_CHECK_EQ(res, SPIFFS_ERR_END_OF_OBJECT); - free(refbuf); - SPIFFS_close(FS, fd); - - return TEST_RES_OK; -} -TEST_END - - -TEST(gc_quick) -{ - char name[32]; - int f; - int size = SPIFFS_DATA_PAGE_SIZE(FS); - int pages_per_block=SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS); - int files = (pages_per_block+1)/2; - int res; - - // negative, try quick gc on clean sys - res = SPIFFS_gc_quick(FS, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NO_DELETED_BLOCKS); - - // fill block with files - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = test_create_and_write_file(name, size, 1); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - // remove all files in block - for (f = 0; f < files; f++) { - sprintf(name, "file%i", f); - res = SPIFFS_remove(FS, name); - TEST_CHECK(res >= 0); - } - - // do a quick gc - res = SPIFFS_gc_quick(FS, 0); - TEST_CHECK(res >= 0); - - // fill another block with files but two pages - // We might have one deleted page left over from the previous gc, in case pages_per_block is odd. - int pages_already=2*files-pages_per_block; - int files2=(pages_per_block-pages_already+1)/2; - - for (f = 0; f < files2 - 1; f++) { - sprintf(name, "file%i", f); - res = test_create_and_write_file(name, size, 1); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files2 - 1; f++) { - sprintf(name, "file%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - // remove all files in block leaving two free pages in block - for (f = 0; f < files2 - 1; f++) { - sprintf(name, "file%i", f); - res = SPIFFS_remove(FS, name); - TEST_CHECK(res >= 0); - } - - // negative, try quick gc where no fully deleted blocks exist - res = SPIFFS_gc_quick(FS, 0); - TEST_CHECK(res < 0); - TEST_CHECK(SPIFFS_errno(FS) == SPIFFS_ERR_NO_DELETED_BLOCKS); - - // positive, try quick gc where allowing two free pages - res = SPIFFS_gc_quick(FS, 2); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_small_file_chunks_1) -{ - int res = test_create_and_write_file("smallfile", 256, 1); - TEST_CHECK(res >= 0); - res = read_and_verify("smallfile"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - - -TEST(write_small_files_chunks_1) -{ - char name[32]; - int f; - int size = 512; - int files = ((20*SPIFFS_CFG_PHYS_SZ(FS))/100)/size; - int res; - for (f = 0; f < files; f++) { - sprintf(name, "smallfile%i", f); - res = test_create_and_write_file(name, size, 1); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "smallfile%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - - return TEST_RES_OK; -} -TEST_END - -TEST(write_big_file_chunks_1) -{ - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100); - printf(" filesize %i\n", size); - int res = test_create_and_write_file("bigfile", size, 1); - TEST_CHECK(res >= 0); - res = read_and_verify("bigfile"); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - -TEST(write_big_files_chunks_1) -{ - char name[32]; - int f; - int files = 10; - int res; - int size = ((50*SPIFFS_CFG_PHYS_SZ(FS))/100)/files; - printf(" filesize %i\n", size); - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = test_create_and_write_file(name, size, 1); - TEST_CHECK(res >= 0); - } - for (f = 0; f < files; f++) { - sprintf(name, "bigfile%i", f); - res = read_and_verify(name); - TEST_CHECK(res >= 0); - } - - return TEST_RES_OK; -} -TEST_END - - -TEST(long_run_config_many_small_one_long) -{ - tfile_conf cfgs[] = { - { .tsize = LARGE, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = LONG - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = LONG - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = LONG - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = LONG - }, - }; - - int res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 206, 5, 0); - TEST_CHECK(res >= 0); - return TEST_RES_OK; -} -TEST_END - -TEST(long_run_config_many_medium) -{ - tfile_conf cfgs[] = { - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = LARGE, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = LARGE, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = LARGE, .ttype = MODIFIED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = LONG - }, - }; - - int res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 305, 5, 0); - TEST_CHECK(res >= 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(long_run_config_many_small) -{ - tfile_conf cfgs[] = { - { .tsize = SMALL, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = LONG - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = MODIFIED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = SHORT - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = UNTAMPERED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = APPENDED, .tlife = SHORT - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = NORMAL - }, - { .tsize = EMPTY, .ttype = UNTAMPERED, .tlife = SHORT - }, - }; - - int res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 115, 6, 0); - TEST_CHECK(res >= 0); - return TEST_RES_OK; -} -TEST_END - - -TEST(long_run) -{ - tfile_conf cfgs[] = { - { .tsize = EMPTY, .ttype = APPENDED, .tlife = NORMAL - }, - { .tsize = SMALL, .ttype = REWRITTEN, .tlife = SHORT - }, - { .tsize = MEDIUM, .ttype = MODIFIED, .tlife = SHORT - }, - { .tsize = MEDIUM, .ttype = APPENDED, .tlife = SHORT - }, - }; - - int macro_runs = 500; - printf(" "); - u32_t clob_size = SPIFFS_CFG_PHYS_SZ(FS)/4; - int res = test_create_and_write_file("long_clobber", clob_size, clob_size); - TEST_CHECK(res >= 0); - - res = read_and_verify("long_clobber"); - TEST_CHECK(res >= 0); - - while (macro_runs--) { - //printf(" ---- run %i ----\n", macro_runs); - if ((macro_runs % 20) == 0) { - printf("."); - fflush(stdout); - } - res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 20, 2, 0); - TEST_CHECK(res >= 0); - } - printf("\n"); - - res = read_and_verify("long_clobber"); - TEST_CHECK(res >= 0); - - res = SPIFFS_check(FS); - TEST_CHECK(res >= 0); - - return TEST_RES_OK; -} -TEST_END - -#if SPIFFS_IX_MAP -TEST(ix_map_basic) -{ - // create a scattered file - s32_t res; - spiffs_file fd1, fd2; - fd1 = SPIFFS_open(FS, "1", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd1, 0); - fd2 = SPIFFS_open(FS, "2", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd2, 0); - - u8_t buf[SPIFFS_DATA_PAGE_SIZE(FS)]; - int i; - for (i = 0; i < SPIFFS_CFG_PHYS_SZ(FS) / 4 / SPIFFS_DATA_PAGE_SIZE(FS); i++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd1, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd2, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - res = SPIFFS_close(FS, fd1); - TEST_CHECK_GE(res, SPIFFS_OK); - res = SPIFFS_close(FS, fd2); - TEST_CHECK_GE(res, SPIFFS_OK); - - res = SPIFFS_remove(FS, "2"); - TEST_CHECK_GE(res, SPIFFS_OK); - - spiffs_stat s; - res = SPIFFS_stat(FS, "1", &s); - TEST_CHECK_GE(res, SPIFFS_OK); - u32_t size = s.size; - - printf("file created, size: %i..\n", size); - - 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)); - - u8_t rd_buf[SPIFFS_CFG_LOG_PAGE_SZ(FS)]; - - fd1 = SPIFFS_open(FS, "1", SPIFFS_O_RDONLY, 0); - TEST_CHECK_GT(fd1, 0); - - clear_flash_ops_log(); - - printf("reading file without memory mapped index\n"); - while ((res = SPIFFS_read(FS, fd1, rd_buf, sizeof(rd_buf))) == sizeof(rd_buf)); - TEST_CHECK_GT(res, SPIFFS_OK); - - res = SPIFFS_OK; - - u32_t reads_without_ixmap = get_flash_ops_log_read_bytes(); - dump_flash_access_stats(); - - u32_t crc_non_map_ix = get_spiffs_file_crc_by_fd(fd1); - - TEST_CHECK_EQ(SPIFFS_close(FS, fd1), SPIFFS_OK); - - - printf("reading file with memory mapped index\n"); - spiffs_ix_map map; - spiffs_page_ix ixbuf[SPIFFS_bytes_to_ix_map_entries(FS, size)]; - - fd1 = SPIFFS_open(FS, "1", SPIFFS_O_RDONLY, 0); - TEST_CHECK_GT(fd1, 0); - - // map index to memory - res = SPIFFS_ix_map(FS, fd1, &map, 0, size, ixbuf); - TEST_CHECK_GE(res, SPIFFS_OK); - - clear_flash_ops_log(); - - while ((res = SPIFFS_read(FS, fd1, rd_buf, sizeof(rd_buf))) == sizeof(rd_buf)); - TEST_CHECK_GT(res, SPIFFS_OK); - u32_t reads_with_ixmap_pass1 = get_flash_ops_log_read_bytes(); - - dump_flash_access_stats(); - - u32_t crc_map_ix_pass1 = get_spiffs_file_crc_by_fd(fd1); - - TEST_CHECK_LT(reads_with_ixmap_pass1, reads_without_ixmap); - - TEST_CHECK_EQ(crc_non_map_ix, crc_map_ix_pass1); - - spiffs_page_ix ref_ixbuf[SPIFFS_bytes_to_ix_map_entries(FS, size)]; - memcpy(ref_ixbuf, ixbuf, sizeof(ixbuf)); - - // force a gc by creating small files until full, reordering the index - printf("forcing gc, error ERR_FULL %i expected\n", SPIFFS_ERR_FULL); - res = SPIFFS_OK; - u32_t ix = 10; - while (res == SPIFFS_OK) { - char name[32]; - sprintf(name, "%i", ix); - res = test_create_and_write_file(name, SPIFFS_CFG_LOG_BLOCK_SZ(FS), SPIFFS_CFG_LOG_BLOCK_SZ(FS)); - ix++; - } - - TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_FULL); - - // make sure the map array was altered - TEST_CHECK_NEQ(0, memcmp(ref_ixbuf, ixbuf, sizeof(ixbuf))); - - TEST_CHECK_GE(SPIFFS_lseek(FS, fd1, 0, SPIFFS_SEEK_SET), SPIFFS_OK); - - clear_flash_ops_log(); - while ((res = SPIFFS_read(FS, fd1, rd_buf, sizeof(rd_buf))) == sizeof(rd_buf)); - TEST_CHECK_GT(res, SPIFFS_OK); - u32_t reads_with_ixmap_pass2 = get_flash_ops_log_read_bytes(); - - TEST_CHECK_EQ(reads_with_ixmap_pass1, reads_with_ixmap_pass2); - - u32_t crc_map_ix_pass2 = get_spiffs_file_crc_by_fd(fd1); - - TEST_CHECK_EQ(crc_map_ix_pass1, crc_map_ix_pass2); - - TEST_CHECK_EQ(SPIFFS_close(FS, fd1), SPIFFS_OK); - - return TEST_RES_OK; -} -TEST_END - -TEST(ix_map_remap) -{ - // create a file, 10 data pages long - s32_t res; - spiffs_file fd1; - fd1 = SPIFFS_open(FS, "1", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd1, 0); - - const int size_pages = 10; - - u8_t buf[SPIFFS_DATA_PAGE_SIZE(FS)]; - int i; - for (i = 0; i < size_pages; i++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd1, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - res = SPIFFS_close(FS, fd1); - TEST_CHECK_GE(res, SPIFFS_OK); - - spiffs_stat s; - res = SPIFFS_stat(FS, "1", &s); - TEST_CHECK_GE(res, SPIFFS_OK); - u32_t size = s.size; - - printf("file created, size: %i..\n", size); - - 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) + 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; - // 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); - - 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(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); - 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++) { - if (ixbuf_ref[i] == ixbuf[i]) { - matches++; - } - } - } - TEST_CHECK_LE(matches, 1); - - return TEST_RES_OK; -} -TEST_END - -TEST(ix_map_partial) -{ - // create a file, 10 data pages long - s32_t res; - spiffs_file fd; - fd = SPIFFS_open(FS, "1", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd, 0); - - const int size_pages = 10; - - u8_t buf[SPIFFS_DATA_PAGE_SIZE(FS)]; - int i; - for (i = 0; i < size_pages; i++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - res = SPIFFS_close(FS, fd); - TEST_CHECK_GE(res, SPIFFS_OK); - - spiffs_stat s; - res = SPIFFS_stat(FS, "1", &s); - TEST_CHECK_GE(res, SPIFFS_OK); - u32_t size = s.size; - - printf("file created, size: %i..\n", size); - - const u32_t crc_unmapped = get_spiffs_file_crc("1"); - - fd = SPIFFS_open(FS, "1", SPIFFS_O_RDONLY, 0); - TEST_CHECK_GT(fd, 0); - - // map index to memory - const int entries = SPIFFS_bytes_to_ix_map_entries(FS, size/2); - spiffs_ix_map map; - spiffs_page_ix ixbuf[entries]; - - printf("map 0-50%%\n"); - res = SPIFFS_ix_map(FS, fd, &map, 0, size/2, ixbuf); - TEST_CHECK_GE(res, SPIFFS_OK); - - const u32_t crc_mapped_beginning = get_spiffs_file_crc_by_fd(fd); - TEST_CHECK_EQ(crc_mapped_beginning, crc_unmapped); - - printf("map 25-75%%\n"); - res = SPIFFS_ix_remap(FS, fd, size/4); - TEST_CHECK_GE(res, SPIFFS_OK); - - const u32_t crc_mapped_middle = get_spiffs_file_crc_by_fd(fd); - TEST_CHECK_EQ(crc_mapped_middle, crc_unmapped); - - printf("map 50-100%%\n"); - res = SPIFFS_ix_remap(FS, fd, size/2); - TEST_CHECK_GE(res, SPIFFS_OK); - - const u32_t crc_mapped_end = get_spiffs_file_crc_by_fd(fd); - TEST_CHECK_EQ(crc_mapped_end, crc_unmapped); - - return TEST_RES_OK; -} -TEST_END - -TEST(ix_map_beyond) -{ - // create a file, 10 data pages long - s32_t res; - spiffs_file fd; - fd = SPIFFS_open(FS, "1", SPIFFS_O_CREAT | SPIFFS_O_WRONLY, 0); - TEST_CHECK_GT(fd, 0); - - const int size_pages = 10; - - u8_t buf[SPIFFS_DATA_PAGE_SIZE(FS)]; - int i; - for (i = 0; i < size_pages; i++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - res = SPIFFS_close(FS, fd); - TEST_CHECK_GE(res, SPIFFS_OK); - - spiffs_stat s; - res = SPIFFS_stat(FS, "1", &s); - TEST_CHECK_GE(res, SPIFFS_OK); - u32_t size = s.size; - - printf("file created, size: %i..\n", size); - - // map index to memory - fd = SPIFFS_open(FS, "1", SPIFFS_O_RDWR | SPIFFS_O_APPEND, 0); - TEST_CHECK_GT(fd, 0); - - 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, ixbuf); - TEST_CHECK_GE(res, SPIFFS_OK); - - 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++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - TEST_CHECK_GE(SPIFFS_fflush(FS, fd), SPIFFS_OK); - - res = SPIFFS_stat(FS, "1", &s); - TEST_CHECK_GE(res, SPIFFS_OK); - size = s.size; - printf("file elongated, size: %i..\n", size); - - printf("make sure map is full but for one element\n"); - int zeroed = 0; - for (i = 0; i < entries; i++) { - 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); - - 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"); - - spiffs_file fd2 = SPIFFS_open(FS, "1", SPIFFS_O_WRONLY | SPIFFS_O_APPEND, 0); - TEST_CHECK_GT(fd2, 0); - - for (i = 0; i < size_pages; i++) { - memrand(buf, sizeof(buf)); - res = SPIFFS_write(FS, fd2, buf, sizeof(buf)); - TEST_CHECK_GE(res, SPIFFS_OK); - } - TEST_CHECK_GE(SPIFFS_close(FS, fd2), SPIFFS_OK); - - printf("make sure map is full but for one element\n"); - zeroed = 0; - for (i = 0; i < entries; i++) { - printf("%04x ", ixbuf[i]); - if (ixbuf[i] == 0) zeroed++; - } - printf("\n"); - TEST_CHECK_LE(zeroed, 1); - - return TEST_RES_OK; -} -TEST_END - -#endif // SPIFFS_IX_MAP - -SUITE_TESTS(hydrogen_tests) - ADD_TEST(info) -#if SPIFFS_USE_MAGIC - ADD_TEST(magic) -#if SPIFFS_USE_MAGIC_LENGTH - ADD_TEST(magic_length) -#if SPIFFS_SINGLETON==0 - ADD_TEST(magic_length_probe) -#endif -#endif -#endif - ADD_TEST(missing_file) - ADD_TEST(bad_fd) - ADD_TEST(closed_fd) - ADD_TEST(deleted_same_fd) - ADD_TEST(deleted_other_fd) - ADD_TEST(file_by_open) - ADD_TEST(file_by_creat) - ADD_TEST(file_by_open_excl) -#if SPIFFS_FILEHDL_OFFSET - ADD_TEST(open_fh_offs) -#endif - ADD_TEST(list_dir) - ADD_TEST(open_by_dirent) - ADD_TEST(open_by_page) - ADD_TEST(user_callback_basic) - ADD_TEST(user_callback_gc) - ADD_TEST(name_too_long) - ADD_TEST(rename) -#if SPIFFS_OBJ_META_LEN - ADD_TEST(update_meta) -#endif - ADD_TEST(remove_single_by_path) - ADD_TEST(remove_single_by_fd) - ADD_TEST(write_cache) - ADD_TEST(write_big_file_chunks_page) - ADD_TEST(write_big_files_chunks_page) - ADD_TEST(write_big_file_chunks_index) - ADD_TEST(write_big_files_chunks_index) - ADD_TEST(write_big_file_chunks_huge) - ADD_TEST(write_big_files_chunks_huge) - ADD_TEST(truncate_big_file) - ADD_TEST(simultaneous_write) - ADD_TEST(simultaneous_write_append) - ADD_TEST(file_uniqueness) - ADD_TEST(read_chunk_1) - ADD_TEST(read_chunk_page) - ADD_TEST(read_chunk_index) - ADD_TEST(read_chunk_huge) - ADD_TEST(read_beyond) - ADD_TEST(read_beyond2) - ADD_TEST(bad_index_1) - ADD_TEST(bad_index_2) - ADD_TEST(lseek_simple_modification) - ADD_TEST(lseek_modification_append) - ADD_TEST(lseek_modification_append_multi) - ADD_TEST(lseek_read) - ADD_TEST(lseek_oob) - ADD_TEST(gc_quick) - ADD_TEST(write_small_file_chunks_1) - ADD_TEST(write_small_files_chunks_1) - ADD_TEST(write_big_file_chunks_1) - ADD_TEST(write_big_files_chunks_1) - ADD_TEST(long_run_config_many_small_one_long) - ADD_TEST(long_run_config_many_medium) - ADD_TEST(long_run_config_many_small) - ADD_TEST(long_run) -#if SPIFFS_IX_MAP - ADD_TEST(ix_map_basic) - ADD_TEST(ix_map_remap) - ADD_TEST(ix_map_partial) - ADD_TEST(ix_map_beyond) -#endif - -SUITE_END(hydrogen_tests) - diff --git a/src/spiffs/test/test_spiffs.c b/src/spiffs/test/test_spiffs.c deleted file mode 100644 index 78ca447..0000000 --- a/src/spiffs/test/test_spiffs.c +++ /dev/null @@ -1,1114 +0,0 @@ -/* - * test_spiffs.c - * - * Created on: Jun 19, 2013 - * Author: petera - */ - - -#include -#include -#include - -#include "params_test.h" -#include "spiffs.h" -#include "spiffs_nucleus.h" - -#include "testrunner.h" - -#include "test_spiffs.h" - -#include -#include -#include -#include -#include -#include - -#define AREA(x) _area[(x) - addr_offset] - -static u32_t _area_sz; -static unsigned char *_area = NULL; -static u32_t addr_offset = 0; - -static int *_erases; -static char _path[256]; -static u32_t bytes_rd = 0; -static u32_t bytes_wr = 0; -static u32_t reads = 0; -static u32_t writes = 0; -static u32_t error_after_bytes_written = 0; -static u32_t error_after_bytes_read = 0; -static char error_after_bytes_written_once_only = 0; -static char error_after_bytes_read_once_only = 0; -static char log_flash_ops = 1; -static u32_t fs_check_fixes = 0; -static u32_t _fs_locks; - -spiffs __fs; -static u8_t *_work = NULL; -static u8_t *_fds = NULL; -static u32_t _fds_sz; -static u8_t *_cache = NULL; -static u32_t _cache_sz; - -static int check_valid_flash = 1; - -#ifndef TEST_PATH -#define TEST_PATH "/dev/shm/spiffs/test-data/" -#endif - -// taken from http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux -// thanks Jonathan Leffler - -static int do_mkdir(const char *path, mode_t mode) -{ - struct stat st; - int status = 0; - - if (stat(path, &st) != 0) { - /* Directory does not exist. EEXIST for race condition */ - if (mkdir(path, mode) != 0 && errno != EEXIST) { - status = -1; - } - } else if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - status = -1; - } - - return status; -} - -/** -** mkpath - ensure all directories in path exist -** Algorithm takes the pessimistic view and works top-down to ensure -** each directory in path exists, rather than optimistically creating -** the last element and working backwards. -*/ -static int mkpath(const char *path, mode_t mode) { - char *pp; - char *sp; - int status; - char *copypath = strdup(path); - - status = 0; - pp = copypath; - while (status == 0 && (sp = strchr(pp, '/')) != 0) { - if (sp != pp) { - /* Neither root nor double slash in path */ - *sp = '\0'; - status = do_mkdir(copypath, mode); - *sp = '/'; - } - pp = sp + 1; - } - if (status == 0) { - status = do_mkdir(path, mode); - } - free(copypath); - return status; -} - -// end take -// -// -char *make_test_fname(const char *name) { - sprintf(_path, "%s/%s", TEST_PATH, name); - return _path; -} - -void create_test_path(void) { - if (mkpath(TEST_PATH, 0755)) { - printf("could not create path %s\n", TEST_PATH); - exit(1); - } -} - -void clear_test_path() { - DIR *dp; - struct dirent *ep; - dp = opendir(TEST_PATH); - - if (dp != NULL) { - while ((ep = readdir(dp))) { - if (ep->d_name[0] != '.') { - sprintf(_path, "%s/%s", TEST_PATH, ep->d_name); - remove(_path); - } - } - closedir(dp); - } -} - -static s32_t _read( -#if SPIFFS_HAL_CALLBACK_EXTRA - spiffs *fs, -#endif - u32_t addr, u32_t size, u8_t *dst) { - //printf("rd @ addr %08x => %p\n", addr, &AREA(addr)); - if (log_flash_ops) { - bytes_rd += size; - reads++; - if (error_after_bytes_read > 0 && bytes_rd >= error_after_bytes_read) { - if (error_after_bytes_read_once_only) { - error_after_bytes_read = 0; - } - return SPIFFS_ERR_TEST; - } - } - if (addr < SPIFFS_CFG_PHYS_ADDR(&__fs)) { - printf("FATAL read addr too low %08x < %08x\n", addr, SPIFFS_PHYS_ADDR); - ERREXIT(); - return -1; - } - if (addr + size > SPIFFS_CFG_PHYS_ADDR(&__fs) + SPIFFS_CFG_PHYS_SZ(&__fs)) { - printf("FATAL read addr too high %08x + %08x > %08x\n", addr, size, SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE); - ERREXIT(); - return -1; - } - memcpy(dst, &AREA(addr), size); - return 0; -} - -static s32_t _write( -#if SPIFFS_HAL_CALLBACK_EXTRA - spiffs *fs, -#endif - u32_t addr, u32_t size, u8_t *src) { - int i; - //printf("wr %08x %i\n", addr, size); - if (log_flash_ops) { - bytes_wr += size; - writes++; - if (error_after_bytes_written > 0 && bytes_wr >= error_after_bytes_written) { - if (error_after_bytes_written_once_only) { - error_after_bytes_written = 0; - } - return SPIFFS_ERR_TEST; - } - } - - if (addr < SPIFFS_CFG_PHYS_ADDR(&__fs)) { - printf("FATAL write addr too low %08x < %08x\n", addr, SPIFFS_PHYS_ADDR); - ERREXIT(); - return -1; - } - if (addr + size > SPIFFS_CFG_PHYS_ADDR(&__fs) + SPIFFS_CFG_PHYS_SZ(&__fs)) { - printf("FATAL write addr too high %08x + %08x > %08x\n", addr, size, SPIFFS_PHYS_ADDR + SPIFFS_FLASH_SIZE); - ERREXIT(); - return -1; - } - - for (i = 0; i < size; i++) { -#if !SPIFFS_NO_BLIND_WRITES - if (((addr + i) & (SPIFFS_CFG_LOG_PAGE_SZ(&__fs)-1)) == offsetof(spiffs_page_header, flags)) { - /* Blind flag writes are allowed. */ - } else -#endif - if (check_valid_flash && ((AREA(addr + i) ^ src[i]) & src[i])) { - printf("trying to write %02x to %02x at addr %08x (as part of writing %d bytes to addr %08x)\n", src[i], AREA(addr + i), addr+i, size, addr); - spiffs_page_ix pix = (addr + i) / SPIFFS_CFG_LOG_PAGE_SZ(&__fs); - dump_page(&__fs, pix); - ERREXIT(); - return -1; - } - AREA(addr + i) &= src[i]; - } - return 0; -} -static s32_t _erase( -#if SPIFFS_HAL_CALLBACK_EXTRA - spiffs *fs, -#endif - u32_t addr, u32_t size) { - if (addr & (SPIFFS_CFG_PHYS_ERASE_SZ(&__fs)-1)) { - printf("trying to erase at addr %08x, out of boundary\n", addr); - ERREXIT(); - return -1; - } - if (size & (SPIFFS_CFG_PHYS_ERASE_SZ(&__fs)-1)) { - printf("trying to erase at with size %08x, out of boundary\n", size); - ERREXIT(); - return -1; - } - _erases[(addr-SPIFFS_CFG_PHYS_ADDR(&__fs))/SPIFFS_CFG_PHYS_ERASE_SZ(&__fs)]++; - memset(&AREA(addr), 0xff, size); - return 0; -} - -void hexdump_mem(u8_t *b, u32_t len) { - while (len--) { - if ((((intptr_t)b)&0x1f) == 0) { - printf("\n"); - } - printf("%02x", *b++); - } - printf("\n"); -} - -void hexdump(u32_t addr, u32_t len) { - int remainder = (addr % 32) == 0 ? 0 : 32 - (addr % 32); - u32_t a; - for (a = addr - remainder; a < addr+len; a++) { - if ((a & 0x1f) == 0) { - if (a != addr) { - printf(" "); - int j; - for (j = 0; j < 32; j++) { - if (a-32+j < addr) - printf(" "); - else { - printf("%c", (AREA(a-32+j) < 32 || AREA(a-32+j) >= 0x7f) ? '.' : AREA(a-32+j)); - } - } - } - printf("%s %08x: ", a<=addr ? "":"\n", a); - } - if (a < addr) { - printf(" "); - } else { - printf("%02x", AREA(a)); - } - } - int j; - printf(" "); - for (j = 0; j < 32; j++) { - if (a-32+j < addr) - printf(" "); - else { - printf("%c", (AREA(a-32+j) < 32 || AREA(a-32+j) >= 0x7f) ? '.' : AREA(a-32+j)); - } - } - printf("\n"); -} - -void dump_page(spiffs *fs, spiffs_page_ix p) { - printf("page %04x ", p); - u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, p); - if (p % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) { - // obj lu page - printf("OBJ_LU"); - } else { - u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , p)) + - SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, p) * sizeof(spiffs_obj_id); - spiffs_obj_id obj_id = *((spiffs_obj_id *)&AREA(obj_id_addr)); - // data page - spiffs_page_header *ph = (spiffs_page_header *)&AREA(addr); - printf("DATA %04x:%04x ", obj_id, ph->span_ix); - printf("%s", ((ph->flags & SPIFFS_PH_FLAG_FINAL) == 0) ? "FIN " : "fin "); - printf("%s", ((ph->flags & SPIFFS_PH_FLAG_DELET) == 0) ? "DEL " : "del "); - printf("%s", ((ph->flags & SPIFFS_PH_FLAG_INDEX) == 0) ? "IDX " : "idx "); - printf("%s", ((ph->flags & SPIFFS_PH_FLAG_USED) == 0) ? "USD " : "usd "); - printf("%s ", ((ph->flags & SPIFFS_PH_FLAG_IXDELE) == 0) ? "IDL " : "idl "); - if (obj_id & SPIFFS_OBJ_ID_IX_FLAG) { - // object index - printf("OBJ_IX"); - if (ph->span_ix == 0) { - printf("_HDR "); - spiffs_page_object_ix_header *oix_hdr = (spiffs_page_object_ix_header *)&AREA(addr); - printf("'%s' %i bytes type:%02x", oix_hdr->name, oix_hdr->size, oix_hdr->type); - } - } else { - // data page - printf("CONTENT"); - } - } - printf("\n"); - u32_t len = SPIFFS_CFG_LOG_PAGE_SZ(fs); - hexdump(addr, len); -} - -void area_write(u32_t addr, u8_t *buf, u32_t size) { - int i; - for (i = 0; i < size; i++) { - AREA(addr + i) = *buf++; - } -} - -void area_set(u32_t addr, u8_t d, u32_t size) { - int i; - for (i = 0; i < size; i++) { - AREA(addr + i) = d; - } -} - -void area_read(u32_t addr, u8_t *buf, u32_t size) { - int i; - for (i = 0; i < size; i++) { - *buf++ = AREA(addr + i); - } -} - -void dump_erase_counts(spiffs *fs) { - spiffs_block_ix bix; - spiffs_block_ix bix_offs; - printf(" BLOCK |\n"); - printf(" AGE COUNT|\n"); - for (bix_offs = 0; bix_offs < fs->block_count; bix_offs+=8) { - for (bix = bix_offs; bix < bix_offs+8 && bix < fs->block_count; bix++) { - printf("----%3i ----|", bix); - } - printf("\n"); - for (bix = bix_offs; bix < bix_offs+8 && bix < fs->block_count; bix++) { - spiffs_obj_id erase_mark; - _spiffs_rd(fs, 0, 0, SPIFFS_ERASE_COUNT_PADDR(fs, bix), sizeof(spiffs_obj_id), (u8_t *)&erase_mark); - if (_erases[bix] == 0) { - printf(" |"); - } else { - printf("%7i %4i|", (fs->max_erase_count - erase_mark), _erases[bix]); - } - } - printf("\n"); - } -} - -void dump_flash_access_stats() { - printf(" RD: %10i reads %10i bytes %10i avg bytes/read\n", reads, bytes_rd, reads == 0 ? 0 : (bytes_rd / reads)); - printf(" WR: %10i writes %10i bytes %10i avg bytes/write\n", writes, bytes_wr, writes == 0 ? 0 : (bytes_wr / writes)); -} - - -static int check_cb_count; -// static u32_t old_perc = 999; -static void spiffs_check_cb_f( -#if SPIFFS_HAL_CALLBACK_EXTRA - spiffs *fs, -#endif - spiffs_check_type type, spiffs_check_report report, - u32_t arg1, u32_t arg2) { -/* if (report == SPIFFS_CHECK_PROGRESS && old_perc != arg1) { - old_perc = arg1; - printf("CHECK REPORT: "); - switch(type) { - case SPIFFS_CHECK_LOOKUP: - printf("LU "); break; - case SPIFFS_CHECK_INDEX: - printf("IX "); break; - case SPIFFS_CHECK_PAGE: - printf("PA "); break; - } - printf("%i%%\n", arg1 * 100 / 256); - }*/ - if (report != SPIFFS_CHECK_PROGRESS) { - check_cb_count++; - if (report != SPIFFS_CHECK_ERROR) fs_check_fixes++; - printf(" check: "); - switch (type) { - case SPIFFS_CHECK_INDEX: - printf("INDEX "); break; - case SPIFFS_CHECK_LOOKUP: - printf("LOOKUP "); break; - case SPIFFS_CHECK_PAGE: - printf("PAGE "); break; - default: - printf("???? "); break; - } - if (report == SPIFFS_CHECK_ERROR) { - printf("ERROR %i", arg1); - } else if (report == SPIFFS_CHECK_DELETE_BAD_FILE) { - printf("DELETE BAD FILE %04x", arg1); - } else if (report == SPIFFS_CHECK_DELETE_ORPHANED_INDEX) { - printf("DELETE ORPHANED INDEX %04x", arg1); - } else if (report == SPIFFS_CHECK_DELETE_PAGE) { - printf("DELETE PAGE %04x", arg1); - } else if (report == SPIFFS_CHECK_FIX_INDEX) { - printf("FIX INDEX %04x:%04x", arg1, arg2); - } else if (report == SPIFFS_CHECK_FIX_LOOKUP) { - printf("FIX INDEX %04x:%04x", arg1, arg2); - } else { - printf("??"); - } - printf("\n"); - } -} - -void fs_set_addr_offset(u32_t offset) { - addr_offset = offset; -} - -void test_lock(spiffs *fs) { - if (_fs_locks != 0) { - printf("FATAL: reentrant locks. Abort.\n"); - ERREXIT(); - exit(-1); - } - _fs_locks++; -} - -void test_unlock(spiffs *fs) { - if (_fs_locks != 1) { - printf("FATAL: unlocking unlocked. Abort.\n"); - ERREXIT(); - exit(-1); - } - _fs_locks--; -} - -s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size) { - spiffs_config c; - c.hal_erase_f = _erase; - c.hal_read_f = _read; - c.hal_write_f = _write; -#if SPIFFS_SINGLETON == 0 - c.log_block_size = log_block_size; - c.log_page_size = log_page_size; - c.phys_addr = phys_addr; - c.phys_erase_block = phys_sector_size; - c.phys_size = phys_size; -#endif -#if SPIFFS_FILEHDL_OFFSET - c.fh_ix_offset = TEST_SPIFFS_FILEHDL_OFFSET; -#endif - return SPIFFS_mount(&__fs, &c, _work, _fds, _fds_sz, _cache, _cache_sz, spiffs_check_cb_f); -} - -static void fs_create(u32_t spiflash_size, - u32_t phys_sector_size, - u32_t log_page_size, - u32_t descriptors, u32_t cache_pages) { - _area_sz = spiflash_size; - _area = malloc(spiflash_size); - ASSERT(_area != NULL, "testbench area could not be malloced"); - - const u32_t erase_sz = sizeof(int) * (spiflash_size / phys_sector_size); - _erases = malloc(erase_sz); - ASSERT(_erases != NULL, "testbench erase log could not be malloced"); - memset(_erases, 0, erase_sz); - - _fds_sz = descriptors * sizeof(spiffs_fd); - _fds = malloc(_fds_sz); - ASSERT(_fds != NULL, "testbench fd buffer could not be malloced"); - memset(_fds, 0, _fds_sz); - -#if SPIFFS_CACHE - _cache_sz = sizeof(spiffs_cache) + cache_pages * (sizeof(spiffs_cache_page) + log_page_size); - _cache = malloc(_cache_sz); - ASSERT(_cache != NULL, "testbench cache could not be malloced"); - memset(_cache, 0, _cache_sz); -#endif - - const u32_t work_sz = log_page_size * 2; - _work = malloc(work_sz); - ASSERT(_work != NULL, "testbench work buffer could not be malloced"); - memset(_work, 0, work_sz); -} - -static void fs_free(void) { - if (_area) free(_area); - _area = NULL; - if (_erases) free(_erases); - _erases = NULL; - if (_fds) free(_fds); - _fds = NULL; - if (_cache) free(_cache); - _cache = NULL; - if (_work) free(_work); - _work = NULL; -} - -/** - * addr_offset - */ -void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size) { - fs_create(phys_size + phys_addr - addr_offset, - phys_sector_size, - log_page_size, - DEFAULT_NUM_FD, - DEFAULT_NUM_CACHE_PAGES); - fs_set_addr_offset(addr_offset); - memset(&AREA(addr_offset), 0xcc, _area_sz); - memset(&AREA(phys_addr), 0xff, phys_size); - memset(&__fs, 0, sizeof(__fs)); - - s32_t res = fs_mount_specific(phys_addr, phys_size, phys_sector_size, log_block_size, log_page_size); - -#if SPIFFS_USE_MAGIC - if (res == SPIFFS_OK) { - SPIFFS_unmount(&__fs); - } - res = SPIFFS_format(&__fs); - if (res != SPIFFS_OK) { - printf("format failed, %i\n", SPIFFS_errno(&__fs)); - } - res = fs_mount_specific(phys_addr, phys_size, phys_sector_size, log_block_size, log_page_size); - if (res != SPIFFS_OK) { - printf("mount failed, %i\n", SPIFFS_errno(&__fs)); - } -#endif - - clear_flash_ops_log(); - log_flash_ops = 1; - fs_check_fixes = 0; -} - -void fs_reset() { - fs_reset_specific(0, SPIFFS_PHYS_ADDR, SPIFFS_FLASH_SIZE, SECTOR_SIZE, LOG_BLOCK, LOG_PAGE); -} - -void fs_store_dump(char *fname) { - int pfd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - ASSERT(pfd > 0, "could not open dump file"); - write(pfd, _area, _area_sz); - close(pfd); -} - -void fs_load_dump(char *fname) { - int pfd = open(fname, O_RDONLY, S_IRUSR | S_IWUSR); - ASSERT(pfd > 0, "could not load dump"); - read(pfd, _area, _area_sz); - close(pfd); -} - -void fs_mount_dump(char *fname, - u32_t addr_offset, u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size) { - fs_create(phys_size + phys_addr - addr_offset, - phys_sector_size, - log_page_size, - DEFAULT_NUM_FD, - DEFAULT_NUM_CACHE_PAGES); - fs_set_addr_offset(addr_offset); - memset(&AREA(addr_offset), 0xcc, _area_sz); - memset(&AREA(phys_addr), 0xff, phys_size); - memset(&__fs, 0, sizeof(__fs)); - - fs_load_dump(fname); - - s32_t res = fs_mount_specific(phys_addr, phys_size, phys_sector_size, log_block_size, log_page_size); - - ASSERT(res == SPIFFS_OK, "failed mounting dump, check settings"); - - clear_flash_ops_log(); - log_flash_ops = 1; - fs_check_fixes = 0; -} - -void set_flash_ops_log(int enable) { - log_flash_ops = enable; -} - -void clear_flash_ops_log() { - bytes_rd = 0; - bytes_wr = 0; - reads = 0; - writes = 0; - error_after_bytes_read = 0; - error_after_bytes_written = 0; -} - -u32_t get_flash_ops_log_read_bytes() { - return bytes_rd; -} - -u32_t get_flash_ops_log_write_bytes() { - return bytes_wr; -} - -void invoke_error_after_read_bytes(u32_t b, char once_only) { - error_after_bytes_read = b; - error_after_bytes_read_once_only = once_only; -} -void invoke_error_after_write_bytes(u32_t b, char once_only) { - error_after_bytes_written = b; - error_after_bytes_written_once_only = once_only; -} - -void fs_set_validate_flashing(int i) { - check_valid_flash = i; -} - -void real_assert(int c, const char *n, const char *file, int l) { - if (c == 0) { - printf("ASSERT: %s %s @ %i\n", (n ? n : ""), file, l); - printf("fs errno:%i\n", __fs.err_code); - exit(0); - } -} - -int read_and_verify(char *name) { - int fd = SPIFFS_open(&__fs, name, SPIFFS_RDONLY, 0); - if (fd < 0) { - printf(" read_and_verify: could not open file %s\n", name); - return fd; - } - return read_and_verify_fd(fd, name); -} - -int read_and_verify_fd(spiffs_file fd, char *name) { - s32_t res; - int pfd = open(make_test_fname(name), O_RDONLY); - spiffs_stat s; - res = SPIFFS_fstat(&__fs, fd, &s); - if (res < 0) { - printf(" read_and_verify: could not stat file %s\n", name); - return res; - } - - off_t fsize = lseek(pfd, 0, SEEK_END); - if (s.size != fsize) { - printf(" read_and_verify: size differs, %s spiffs:%d!=fs:%ld\n", name, s.size, fsize); - return -1; - } - lseek(pfd, 0, SEEK_SET); - - if (s.size == 0) { - SPIFFS_close(&__fs, fd); - close(pfd); - return 0; - } - - //printf("verifying %s, len %i\n", name, s.size); - int offs = 0; - u8_t buf_d[256]; - u8_t buf_v[256]; - while (offs < s.size) { - int read_len = MIN(s.size - offs, sizeof(buf_d)); - res = SPIFFS_read(&__fs, fd, buf_d, read_len); - if (res < 0) { - printf(" read_and_verify: could not read file %s offs:%i len:%i filelen:%i\n", name, offs, read_len, s.size); - return res; - } - int pres = read(pfd, buf_v, read_len); - (void)pres; - //printf("reading offs:%i len:%i spiffs_res:%i posix_res:%i\n", offs, read_len, res, pres); - int i; - int veri_ok = 1; - for (i = 0; veri_ok && i < read_len; i++) { - if (buf_d[i] != buf_v[i]) { - printf("file verification mismatch @ %i, %02x %c != %02x %c\n", offs+i, buf_d[i], buf_d[i], buf_v[i], buf_v[i]); - int j = MAX(0, i-16); - int k = MIN(sizeof(buf_d), i+16); - k = MIN(s.size-offs, k); - int l; - for (l = j; l < k; l++) { - printf("%c", buf_d[l] > 31 ? buf_d[l] : '.'); - } - printf("\n"); - for (l = j; l < k; l++) { - printf("%c", buf_v[l] > 31 ? buf_v[l] : '.'); - } - printf("\n"); - veri_ok = 0; - } - } - if (!veri_ok) { - SPIFFS_close(&__fs, fd); - close(pfd); - printf("data mismatch\n"); - return -1; - } - - offs += read_len; - } - - SPIFFS_close(&__fs, fd); - close(pfd); - - return 0; -} - -static void test_on_stop(test *t) { - printf(" spiffs errno:%i\n", SPIFFS_errno(&__fs)); -#if SPIFFS_TEST_VISUALISATION - if (_area) SPIFFS_vis(FS); -#endif - -} - -void memrand(u8_t *b, int len) { - int i; - for (i = 0; i < len; i++) { - b[i] = rand(); - } -} - -int test_create_file(char *name) { - spiffs_stat s; - spiffs_file fd; - int res = SPIFFS_creat(FS, name, 0); - CHECK_RES(res); - fd = SPIFFS_open(FS, name, SPIFFS_RDONLY, 0); - CHECK(fd >= 0); - res = SPIFFS_fstat(FS, fd, &s); - CHECK_RES(res); - CHECK(strcmp((char*)s.name, name) == 0); - CHECK(s.size == 0); -#if SPIFFS_OBJ_META_LEN - { - int i; - for (i = 0; i < SPIFFS_OBJ_META_LEN; i++) { - CHECK(s.meta[i] == 0xff); - } - } -#endif - SPIFFS_close(FS, fd); - return 0; -} - -int test_create_and_write_file(char *name, int size, int chunk_size) { - int res; - spiffs_file fd; - printf(" create and write %s", name); - res = test_create_file(name); - if (res < 0) { - printf(" failed creation, %i\n",res); - } - CHECK(res >= 0); - fd = SPIFFS_open(FS, name, SPIFFS_APPEND | SPIFFS_RDWR, 0); - if (fd < 0) { - printf(" failed open, %i\n",res); - } - CHECK(fd >= 0); - int pfd = open(make_test_fname(name), O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - int offset = 0; - int mark = 0; - while (offset < size) { - int len = MIN(size-offset, chunk_size); - if (offset > mark) { - mark += size/16; - printf("."); - fflush(stdout); - } - u8_t *buf = malloc(len); - memrand(buf, len); - res = SPIFFS_write(FS, fd, buf, len); - write(pfd, buf, len); - free(buf); - if (res < 0) { - printf("\n error @ offset %i, res %i\n", offset, res); - } - offset += len; - CHECK(res >= 0); - } - printf("\n"); - close(pfd); - - spiffs_stat stat; - res = SPIFFS_fstat(FS, fd, &stat); - if (res < 0) { - printf(" failed fstat, %i\n",res); - } - CHECK(res >= 0); - if (stat.size != size) { - printf(" failed size, %i != %i\n", stat.size, size); - } - CHECK(stat.size == size); - - SPIFFS_close(FS, fd); - return 0; -} - -static u32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -static u32_t crc32(u32_t crc, const void *buf, size_t size) -{ - const u8_t *p; - - p = buf; - crc = crc ^ ~0U; - - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - - return crc ^ ~0U; -} - -u32_t get_spiffs_file_crc_by_fd(spiffs_file fd) { - s32_t res; - u32_t crc = 0; - u8_t buf[256]; - - ASSERT(SPIFFS_lseek(FS, fd, 0, SPIFFS_SEEK_SET) >= 0, "could not seek to start of file"); - - while ((res = SPIFFS_read(FS, fd, buf, sizeof(buf))) > SPIFFS_OK) { - crc = crc32(crc, buf, res); - } - ASSERT(SPIFFS_errno(FS) == SPIFFS_ERR_END_OF_OBJECT || SPIFFS_errno(FS) == SPIFFS_OK, "failed reading file"); - - return crc; -} - -u32_t get_spiffs_file_crc(char *name) { - s32_t res; - spiffs_file fd; - fd = SPIFFS_open(FS, name, SPIFFS_O_RDONLY, 0); - ASSERT(fd >= 0, "Could not open file"); - u32_t crc = get_spiffs_file_crc_by_fd(fd); - res = SPIFFS_close(FS, fd); - ASSERT(res >= SPIFFS_OK, "failing closing file"); - return crc; -} - -#if SPIFFS_CACHE -#if SPIFFS_CACHE_STATS -static u32_t chits_tot = 0; -static u32_t cmiss_tot = 0; -#endif -#endif - -void _setup_test_only() { - create_test_path(); - fs_set_validate_flashing(1); - test_init(test_on_stop); -} - -void _setup() { - _fs_locks = 0; - fs_reset(); - _setup_test_only(); -} - -void _teardown() { - printf(" free blocks : %i of %i\n", (FS)->free_blocks, (FS)->block_count); - printf(" pages allocated : %i\n", (FS)->stats_p_allocated); - printf(" pages deleted : %i\n", (FS)->stats_p_deleted); -#if SPIFFS_GC_STATS - printf(" gc runs : %i\n", (FS)->stats_gc_runs); -#endif -#if SPIFFS_CACHE -#if SPIFFS_CACHE_STATS - chits_tot += (FS)->cache_hits; - cmiss_tot += (FS)->cache_misses; - printf(" cache hits : %i (sum %i)\n", (FS)->cache_hits, chits_tot); - printf(" cache misses : %i (sum %i)\n", (FS)->cache_misses, cmiss_tot); - printf(" cache utiliz : %f\n", ((float)chits_tot/(float)(chits_tot + cmiss_tot))); - chits_tot = 0; - cmiss_tot = 0; -#endif -#endif - if (_area) { - dump_flash_access_stats(); - clear_flash_ops_log(); -#if SPIFFS_GC_STATS - if ((FS)->stats_gc_runs > 0) -#endif - dump_erase_counts(FS); - printf(" fs consistency check output begin\n"); - check_cb_count = 0; - SPIFFS_check(FS); - printf(" fs consistency check output end\n"); - if (check_cb_count) { - ERREXIT(); - } - } - clear_test_path(); - fs_free(); - printf(" locks : %i\n", _fs_locks); - if (_fs_locks != 0) { - printf("FATAL: lock asymmetry. Abort.\n"); - ERREXIT(); - exit(-1); - } -} - -u32_t tfile_get_size(tfile_size s) { - switch (s) { - case EMPTY: - return 0; - case SMALL: // half a data page - return SPIFFS_DATA_PAGE_SIZE(FS)/2; - case MEDIUM: // one block - return SPIFFS_DATA_PAGE_SIZE(FS) * (SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS)); - case LARGE: // third of fs - return SPIFFS_DATA_PAGE_SIZE(FS) * (SPIFFS_PAGES_PER_BLOCK(FS) - SPIFFS_OBJ_LOOKUP_PAGES(FS)) * (FS)->block_count/3; - } - return 0; -} - -int run_file_config(int cfg_count, tfile_conf* cfgs, int max_runs, int max_concurrent_files, int dbg) { - int res; - tfile *tfiles = malloc(sizeof(tfile) * max_concurrent_files); - memset(tfiles, 0, sizeof(tfile) * max_concurrent_files); - int run = 0; - int cur_config_ix = 0; - char name[32]; - while (run < max_runs) { - if (dbg) printf(" run %i/%i\n", run, max_runs); - int i; - for (i = 0; i < max_concurrent_files; i++) { - sprintf(name, "file%i_%i", (1+run), i); - tfile *tf = &tfiles[i]; - if (tf->state == 0 && cur_config_ix < cfg_count) { -// create a new file - strcpy(tf->name, name); - tf->state = 1; - tf->cfg = cfgs[cur_config_ix]; - int size = tfile_get_size(tf->cfg.tsize); - if (dbg) printf(" create new %s with cfg %i/%i, size %i\n", name, (1+cur_config_ix), cfg_count, size); - - if (tf->cfg.tsize == EMPTY) { - res = SPIFFS_creat(FS, name, 0); - CHECK_RES(res); - int pfd = open(make_test_fname(name), O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - close(pfd); - int extra_flags = tf->cfg.ttype == APPENDED ? SPIFFS_APPEND : 0; - spiffs_file fd = SPIFFS_open(FS, name, extra_flags | SPIFFS_RDWR, 0); - CHECK(fd > 0); - tf->fd = fd; - } else { - int extra_flags = tf->cfg.ttype == APPENDED ? SPIFFS_APPEND : 0; - spiffs_file fd = SPIFFS_open(FS, name, extra_flags | SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0); - CHECK(fd > 0); - extra_flags = tf->cfg.ttype == APPENDED ? O_APPEND : 0; - int pfd = open(make_test_fname(name), extra_flags | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - tf->fd = fd; - u8_t *buf = malloc(size); - memrand(buf, size); - res = SPIFFS_write(FS, fd, buf, size); - CHECK_RES(res); - write(pfd, buf, size); - close(pfd); - free(buf); - res = read_and_verify(name); - CHECK_RES(res); - } - - cur_config_ix++; - } else if (tf->state > 0) { -// hande file lifecycle - switch (tf->cfg.ttype) { - case UNTAMPERED: { - break; - } - case APPENDED: { - if (dbg) printf(" appending %s\n", tf->name); - int size = SPIFFS_DATA_PAGE_SIZE(FS)*3; - u8_t *buf = malloc(size); - memrand(buf, size); - res = SPIFFS_write(FS, tf->fd, buf, size); - CHECK_RES(res); - int pfd = open(make_test_fname(tf->name), O_APPEND | O_RDWR); - write(pfd, buf, size); - close(pfd); - free(buf); - res = read_and_verify(tf->name); - CHECK_RES(res); - break; - } - case MODIFIED: { - if (dbg) printf(" modify %s\n", tf->name); - spiffs_stat stat; - res = SPIFFS_fstat(FS, tf->fd, &stat); - CHECK_RES(res); - int size = stat.size / tf->cfg.tlife + SPIFFS_DATA_PAGE_SIZE(FS)/3; - int offs = (stat.size / tf->cfg.tlife) * tf->state; - res = SPIFFS_lseek(FS, tf->fd, offs, SPIFFS_SEEK_SET); - CHECK_RES(res); - u8_t *buf = malloc(size); - memrand(buf, size); - res = SPIFFS_write(FS, tf->fd, buf, size); - CHECK_RES(res); - int pfd = open(make_test_fname(tf->name), O_RDWR); - lseek(pfd, offs, SEEK_SET); - write(pfd, buf, size); - close(pfd); - free(buf); - res = read_and_verify(tf->name); - CHECK_RES(res); - break; - } - case REWRITTEN: { - if (tf->fd > 0) { - SPIFFS_close(FS, tf->fd); - } - if (dbg) printf(" rewriting %s\n", tf->name); - spiffs_file fd = SPIFFS_open(FS, tf->name, SPIFFS_TRUNC | SPIFFS_CREAT | SPIFFS_RDWR, 0); - CHECK(fd > 0); - int pfd = open(make_test_fname(tf->name), O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - tf->fd = fd; - int size = tfile_get_size(tf->cfg.tsize); - u8_t *buf = malloc(size); - memrand(buf, size); - res = SPIFFS_write(FS, fd, buf, size); - CHECK_RES(res); - write(pfd, buf, size); - close(pfd); - free(buf); - res = read_and_verify(tf->name); - CHECK_RES(res); - break; - } - } - tf->state++; - if (tf->state > tf->cfg.tlife) { -// file outlived its time, kill it - if (tf->fd > 0) { - SPIFFS_close(FS, tf->fd); - } - if (dbg) printf(" removing %s\n", tf->name); - res = read_and_verify(tf->name); - CHECK_RES(res); - res = SPIFFS_remove(FS, tf->name); - CHECK_RES(res); - remove(make_test_fname(tf->name)); - memset(tf, 0, sizeof(tfile)); - } - - } - } - - run++; - } - free(tfiles); - return 0; -} - -int count_taken_fds(spiffs *fs) { - int i; - spiffs_fd *fds = (spiffs_fd *)fs->fd_space; - int taken = 0; - for (i = 0; i < fs->fd_count; i++) { - spiffs_fd *cur_fd = &fds[i]; - if (cur_fd->file_nbr) taken++; - } - return taken; -} diff --git a/src/spiffs/test/test_spiffs.h b/src/spiffs/test/test_spiffs.h deleted file mode 100644 index 4c39bdb..0000000 --- a/src/spiffs/test/test_spiffs.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * test_spiffs.h - * - * Created on: Jun 19, 2013 - * Author: petera - */ - -#ifndef TEST_SPIFFS_H_ -#define TEST_SPIFFS_H_ - -#include "spiffs.h" - -#define FS &__fs - -extern spiffs __fs; - - -#define CHECK(r) if (!(r)) return -1; -#define CHECK_RES(r) if (r < 0) return -1; -#define FS_PURE_DATA_PAGES(fs) \ - (SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_PAGE_SZ(fs)- (fs)->block_count * SPIFFS_OBJ_LOOKUP_PAGES(fs)) -#define FS_PURE_DATA_SIZE(fs) \ - FS_PURE_DATA_PAGES(fs) * SPIFFS_DATA_PAGE_SIZE(fs) - -typedef enum { - EMPTY, - SMALL, - MEDIUM, - LARGE, -} tfile_size; - -typedef enum { - UNTAMPERED, - APPENDED, - MODIFIED, - REWRITTEN, -} tfile_type; - -typedef enum { - SHORT = 3, - NORMAL = 15, - LONG = 100, -} tfile_life; - -typedef struct { - tfile_size tsize; - tfile_type ttype; - tfile_life tlife; -} tfile_conf; - -typedef struct { - int state; - spiffs_file fd; - tfile_conf cfg; - char name[32]; -} tfile; - -void fs_reset(); -void fs_reset_specific(u32_t addr_offset, u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size); -s32_t fs_mount_specific(u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size); -void fs_mount_dump(char *fname, - u32_t addr_offset, u32_t phys_addr, u32_t phys_size, - u32_t phys_sector_size, - u32_t log_block_size, u32_t log_page_size); - -void fs_store_dump(char *fname); -void fs_load_dump(char *fname); - -void fs_set_addr_offset(u32_t offset); -int read_and_verify(char *name); -int read_and_verify_fd(spiffs_file fd, char *name); -void dump_page(spiffs *fs, spiffs_page_ix p); -void hexdump(u32_t addr, u32_t len); -char *make_test_fname(const char *name); -void clear_test_path(); -void area_write(u32_t addr, u8_t *buf, u32_t size); -void area_set(u32_t addr, u8_t d, u32_t size); -void area_read(u32_t addr, u8_t *buf, u32_t size); -void dump_erase_counts(spiffs *fs); -void dump_flash_access_stats(); -void set_flash_ops_log(int enable); -void clear_flash_ops_log(); -u32_t get_flash_ops_log_read_bytes(); -u32_t get_flash_ops_log_write_bytes(); -void invoke_error_after_read_bytes(u32_t b, char once_only); -void invoke_error_after_write_bytes(u32_t b, char once_only); -void fs_set_validate_flashing(int i); -int get_error_count(); -int count_taken_fds(spiffs *fs); - -void memrand(u8_t *b, int len); -int test_create_file(char *name); -int test_create_and_write_file(char *name, int size, int chunk_size); -u32_t get_spiffs_file_crc_by_fd(spiffs_file fd); -u32_t get_spiffs_file_crc(char *name); -void _setup(); -void _setup_test_only(); -void _teardown(); -u32_t tfile_get_size(tfile_size s); -int run_file_config(int cfg_count, tfile_conf* cfgs, int max_runs, int max_concurrent_files, int dbg); - -void test_lock(spiffs *fs); -void test_unlock(spiffs *fs); - -#endif /* TEST_SPIFFS_H_ */ diff --git a/src/spiffs/test/testrunner.c b/src/spiffs/test/testrunner.c deleted file mode 100644 index 27419d3..0000000 --- a/src/spiffs/test/testrunner.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * testrunner.c - * - * Created on: Jun 18, 2013 - * Author: petera - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "testrunner.h" - -static struct { - test *tests; - test *_last_test; - int test_count; - void (*on_stop)(test *t); - test_res *failed; - test_res *failed_last; - test_res *stopped; - test_res *stopped_last; - FILE *spec; - char incl_filter[256]; - char excl_filter[256]; -} test_main; - -void test_init(void (*on_stop)(test *t)) { - test_main.on_stop = on_stop; -} - -static int abort_on_error = 0; -static int error_count = 0; - -static char check_spec(char *name) { - if (test_main.spec) { - fseek(test_main.spec, 0, SEEK_SET); - char *line = NULL; - size_t sz; - ssize_t read; - while ((read = getline(&line, &sz, test_main.spec)) != -1) { - if (strncmp(line, name, strlen(line)-1) == 0) { - free(line); - return 1; - } - } - free(line); - return 0; - } else { - return 1; - } -} - -static char check_incl_filter(char *name) { - if (strlen(test_main.incl_filter)== 0) return 1; - return strstr(name, test_main.incl_filter) == 0 ? 0 : 2; -} - -static char check_excl_filter(char *name) { - if (strlen(test_main.excl_filter)== 0) return 1; - return strstr(name, test_main.excl_filter) == 0 ? 1 : 0; -} - -void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default) { - if (f == 0) return; - if (!check_spec(name)) return; - if (check_incl_filter(name) <= non_default) return; - if (!check_excl_filter(name)) return; - DBGT("adding test %s\n", name); - test *t = malloc(sizeof(test)); - memset(t, 0, sizeof(test)); - t->f = f; - strcpy(t->name, name); - t->setup = setup; - t->teardown = teardown; - if (test_main.tests == 0) { - test_main.tests = t; - } else { - test_main._last_test->_next = t; - } - test_main._last_test = t; - test_main.test_count++; -} - -static void add_res(test *t, test_res **head, test_res **last) { - test_res *tr = malloc(sizeof(test_res)); - memset(tr,0,sizeof(test_res)); - strcpy(tr->name, t->name); - if (*head == 0) { - *head = tr; - } else { - (*last)->_next = tr; - } - *last = tr; -} - -static void dump_res(test_res **head) { - test_res *tr = (*head); - while (tr) { - test_res *next_tr = tr->_next; - printf(" %s\n", tr->name); - free(tr); - tr = next_tr; - } -} - -int get_error_count(void) { - return error_count; -} - -void inc_error_count(void) { - error_count++; -} - -int set_abort_on_error(int val) { - int old_val = abort_on_error; - abort_on_error = val; - - return old_val; -} - -int get_abort_on_error(void) { - return abort_on_error; -} - -int run_tests(int argc, char **args) { - memset(&test_main, 0, sizeof(test_main)); - int arg; - int incl_filter = 0; - int excl_filter = 0; - for (arg = 1; arg < argc; arg++) { - if (strlen(args[arg]) == 0) continue; - if (0 == strcmp("-f", args[arg])) { - incl_filter = 1; - continue; - } - if (0 == strcmp("-e", args[arg])) { - excl_filter = 1; - continue; - } - if (incl_filter) { - strcpy(test_main.incl_filter, args[arg]); - incl_filter = 0; - } else if (excl_filter) { - strcpy(test_main.excl_filter, args[arg]); - excl_filter = 0; - } else { - printf("running tests from %s\n", args[arg]); - FILE *fd = fopen(args[1], "r"); - if (fd == NULL) { - printf("%s not found\n", args[arg]); - return -2; - } - test_main.spec = fd; - } - } - - DBGT("adding suites...\n"); - add_suites(); - DBGT("%i tests added\n", test_main.test_count); - if (test_main.spec) { - fclose(test_main.spec); - } - - if (test_main.test_count == 0) { - printf("No tests to run\n"); - return 0; - } - - int fd_success = open("_tests_ok", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - int fd_bad = open("_tests_fail", O_APPEND | O_TRUNC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - - DBGT("running tests...\n"); - int ok = 0; - int failed = 0; - int stopped = 0; - test *cur_t = test_main.tests; - int i = 1; - while (cur_t) { - cur_t->setup(cur_t); - test *next_test = cur_t->_next; - DBGT("TEST %i/%i : running test %s\n", i, test_main.test_count, cur_t->name); - i++; - int start_error_count = get_error_count(); - int res = cur_t->f(cur_t); - if (res == TEST_RES_OK && get_error_count() != start_error_count) { - res = TEST_RES_FAIL; - } - cur_t->test_result = res; - int fd = res == TEST_RES_OK ? fd_success : fd_bad; - write(fd, cur_t->name, strlen(cur_t->name)); - write(fd, "\n", 1); - switch (res) { - case TEST_RES_OK: - ok++; - printf(" .. ok\n"); - break; - case TEST_RES_FAIL: - failed++; - printf(" .. FAILED\n"); - if (test_main.on_stop) test_main.on_stop(cur_t); - add_res(cur_t, &test_main.failed, &test_main.failed_last); - break; - case TEST_RES_ASSERT: - stopped++; - printf(" .. ABORTED\n"); - if (test_main.on_stop) test_main.on_stop(cur_t); - add_res(cur_t, &test_main.stopped, &test_main.stopped_last); - break; - } - cur_t->teardown(cur_t); - free(cur_t); - cur_t = next_test; - } - close(fd_success); - close(fd_bad); - DBGT("ran %i tests\n", test_main.test_count); - printf("Test report, %i tests\n", test_main.test_count); - printf("%i succeeded\n", ok); - printf("%i failed\n", failed); - dump_res(&test_main.failed); - printf("%i stopped\n", stopped); - dump_res(&test_main.stopped); - if (ok < test_main.test_count) { - printf("\nFAILED\n"); - return -1; - } else { - printf("\nALL TESTS OK\n"); - return 0; - } -} diff --git a/src/spiffs/test/testrunner.h b/src/spiffs/test/testrunner.h deleted file mode 100644 index 697fb09..0000000 --- a/src/spiffs/test/testrunner.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * testrunner.h - * - * Created on: Jun 19, 2013 - * Author: petera - */ - -/* - -file mysuite.c: - -SUITE(mysuite) - -static void setup(test *t) {} - -static void teardown(test *t) {} - -TEST(mytest) { - printf("mytest runs now..\n"); - return 0; -} TEST_END - -SUITE_TESTS(mysuite) - ADD_TEST(mytest) -SUITE_END(mysuite) - - - -file mysuite2.c: - -SUITE(mysuite2) - -static void setup(test *t) {} - -static void teardown(test *t) {} - -TEST(mytest2a) { - printf("mytest2a runs now..\n"); - return 0; -} TEST_END - -TEST(mytest2b) { - printf("mytest2b runs now..\n"); - return 0; -} TEST_END - -SUITE_TESTS(mysuite2) - ADD_TEST(mytest2a) - ADD_TEST(mytest2b) -SUITE_END(mysuite2) - - -some other file.c: - -void add_suites() { - ADD_SUITE(mysuite); - ADD_SUITE(mysuite2); -} - */ - -#ifndef TESTRUNNER_H_ -#define TESTRUNNER_H_ - -#define TEST_RES_OK 0 -#define TEST_RES_FAIL -1 -#define TEST_RES_ASSERT -2 - -#define ERREXIT() if (get_abort_on_error()) abort(); else inc_error_count() - -struct test_s; - -typedef int (*test_f)(struct test_s *t); - -typedef struct test_s { - test_f f; - char name[256]; - void *data; - void (*setup)(struct test_s *t); - void (*teardown)(struct test_s *t); - struct test_s *_next; - unsigned char test_result; -} test; - -typedef struct test_res_s { - char name[256]; - struct test_res_s *_next; -} test_res; - -#define TEST_CHECK(x) if (!(x)) { \ - printf(" TEST FAIL %s:%d\n", __FILE__, __LINE__); \ - goto __fail_stop; \ -} -#define TEST_CHECK_EQ(x, y) if ((x) != (y)) { \ - printf(" TEST FAIL %s:%d, %d != %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_CHECK_NEQ(x, y) if ((x) == (y)) { \ - printf(" TEST FAIL %s:%d, %d == %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_CHECK_GT(x, y) if ((x) <= (y)) { \ - printf(" TEST FAIL %s:%d, %d <= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_CHECK_LT(x, y) if ((x) >= (y)) { \ - printf(" TEST FAIL %s:%d, %d >= %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_CHECK_GE(x, y) if ((x) < (y)) { \ - printf(" TEST FAIL %s:%d, %d < %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_CHECK_LE(x, y) if ((x) > (y)) { \ - printf(" TEST FAIL %s:%d, %d > %d\n", __FILE__, __LINE__, (int)(x), (int)(y)); \ - goto __fail_stop; \ -} -#define TEST_ASSERT(x) if (!(x)) { \ - printf(" TEST ASSERT %s:%d\n", __FILE__, __LINE__); \ - goto __fail_assert; \ -} - -#define DBGT(...) printf(__VA_ARGS__) - -#define str(s) #s - -#define SUITE(sui) - -#define SUITE_TESTS(sui) \ - void _add_suite_tests_##sui(void) { - -#define SUITE_END(sui) \ - } - -#define ADD_TEST(tf) \ - _add_test(__test_##tf, str(tf), setup, teardown, 0); - -#define ADD_TEST_NON_DEFAULT(tf) \ - _add_test(__test_##tf, str(tf), setup, teardown, 1); - -#define ADD_SUITE(sui) \ - extern void _add_suite_tests_##sui(void); \ - _add_suite_tests_##sui(); - -#define TEST(tf) \ - static int __test_##tf(struct test_s *t) { do - -#define TEST_END \ - while(0); \ - __fail_stop: return TEST_RES_FAIL; \ - __fail_assert: return TEST_RES_ASSERT; \ - } - -int set_abort_on_error(int val); -int get_abort_on_error(void); -int get_error_count(void); -void inc_error_count(void); - -void add_suites(void); -void test_init(void (*on_stop)(test *t)); -// returns 0 if all tests ok, -1 if any test failed, -2 on badness -int run_tests(int argc, char **args); -void _add_suite(const char *suite_name); -void _add_test(test_f f, char *name, void (*setup)(test *t), void (*teardown)(test *t), int non_default); - -#endif /* TESTRUNNER_H_ */ diff --git a/src/spiffs/test/testsuites.c b/src/spiffs/test/testsuites.c deleted file mode 100644 index cce5cd9..0000000 --- a/src/spiffs/test/testsuites.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * testsuites.c - * - * Created on: Jun 19, 2013 - * Author: petera - */ - -#include "testrunner.h" - -void add_suites(void) { - //ADD_SUITE(dev_tests); - ADD_SUITE(check_tests); - ADD_SUITE(hydrogen_tests); - ADD_SUITE(bug_tests); -}