Code: Select all
#include <FS.h>
#include <SD.h>
#include <errno.h>
/*----------------------------------------------------------------
* source : http://man7.org/linux/man-pages/man3/fopen.3.html
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is
positioned at the beginning of the file.
a Open for appending (writing at end of file). The file is
created if it does not exist. The stream is positioned at the
end of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. Output is always
appended to the end of the file. POSIX is silent on what the
initial read position is when using this mode. For glibc, the
initial file position for reading is at the beginning of the
file, but for Android/BSD/MacOS, the initial file position for
reading is at the end of the file.
from : https://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html
r or rb
Open file for reading.
w or wb
Truncate to zero length or create file for writing.
a or ab
Append; open or create file for writing at end-of-file.
r+ or rb+ or r+b
Open file for update (reading and writing).
w+ or wb+ or w+b
Truncate to zero length or create file for update.
a+ or ab+ or a+b
Append; open or create file for update, writing at end-of-file.
*/
//----------------------------------------------------------------
#define _BUFFERMAX 128
static char _Buffer[_BUFFERMAX]="";
void sprintln ( const char * format, ... )
{
va_list args;
va_start (args, format);
vsnprintf (_Buffer, _BUFFERMAX, format, (va_list)args);
Serial.println (_Buffer);
va_end (args);
}
void sprint ( const char * format, ... )
{
va_list args;
va_start (args, format);
vsnprintf (_Buffer, _BUFFERMAX, format, (va_list)args);
Serial.print (_Buffer);
va_end (args);
}
enum testtype {NEF, EEF, ENF};
char *testname[] = {"non existing", "existing empty", "existing non empty", NULL};
enum fstype {IsSD, IsSPIFFS};
int fsmounted[] = { 0, 0};
char *fsname[] = {"SD card", "SPIFFS", NULL};
char *NoYes[] = {"no", "yes"};
char *RES[] = {"OK", "NOK"};
char c15[] = "0123456789ABCDF";
char CFilename[] = "/TesT.txt";
struct Res_t {
int open;
size_t siz;
size_t pos;
int ava;
size_t sizw;
size_t posw;
int avaw;
} *Rest;
#define L strlen(c15)
#define D 2*strlen(c15)
struct Test_t {
const char *Mode;
struct Res_t Exp[3]; // [NEF, EEF, ENF]
struct Res_t Res[2][3]; // [SD, SPIFFS][NEF, EEF, ENF]
} Tests[] = {
// O S P A S P A
{"r", {{0,0,0,0,0,0,0},
{1,0,0,0,0,0,0},
{1,L,0,L,L,L,0}}},
{"a", {{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0},
{1,L,L,0,D,D,0}}},
{"w", {{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0}}},
{"r+", {{0,0,0,0,0,0,0},
{1,0,0,0,L,L,0},
{1,L,L,0,D,D,0}}},
{"a+", {{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0},
{1,L,L,L,D,D,0}}},
{"w+", {{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0},
{1,0,0,0,L,L,0}}},
{NULL}
};
File CFile;
//===========================================================
void RunTest(int FST, int Test, int Mode) {
struct Res_t *Res;
// if file exist erase it
if (FST == IsSD)
if (SD.exists(CFilename)) SD.remove(CFilename);
else
if (SPIFFS.exists(CFilename)) SPIFFS.remove(CFilename);
// if file should exist create it
if ( Test == EEF || Test == ENF ) {
if (FST == IsSD)
CFile = SD.open(CFilename, "w");
else
CFile = SPIFFS.open(CFilename, "w");
// if file should not be empty
if ( Test == ENF)
CFile.write((const uint8_t*)c15, L);
CFile.flush();
CFile.close();
}
if (FST == IsSD)
CFile = SD.open(CFilename, Tests[Mode].Mode);
else
CFile = SPIFFS.open(CFilename, Tests[Mode].Mode);
Res = &Tests[Mode].Res[FST][Test];
Res->open = CFile;
if (!Res->open)
return;
Res->siz = CFile.size();
Res->pos = CFile.position();
Res->ava = CFile.available();
CFile.write((const uint8_t*)c15, L);
CFile.flush();
Res->sizw = CFile.size();
Res->posw = CFile.position();
Res->avaw = CFile.available();
CFile.close();
}
void setup() {
Serial.begin(9600);
while (!Serial) {}
Serial.println("Initializing ...");
delay(3000);
Serial.println("Initializing SD card");
if (!SD.begin(5)) {
Serial.print("Error mounting SD card");
Serial.println(strerror(errno));
} else
fsmounted[IsSD] = 1;
Serial.println("Initializing SPIFF");
if(!SPIFFS.begin(true)){
Serial.println("Error mounting SPIFFS");
}else
fsmounted[IsSPIFFS] = 1;
Serial.println("Initializations done");
sprintln("----");
int t=0,f=0,m=0;
while (testname[t]) {
sprintln("Running tests with a %s file on :", testname[t]);
f=0;
while (fsname[f]) {
sprint(" %s : ", fsname[f]);
if (fsmounted[f]) {
m=0;
while(Tests[m].Mode) {
sprint(" %s", Tests[m].Mode);
RunTest(f, t, m); //Tests[m].Mode, &Tests[m].Res[f][t]);
m++;
}
sprintln("");
} else
sprintln("not mounted");
f++;
}
t++;
}
sprintln("----");
t=0,f=0,m=0;
while (testname[t]) {
sprintln("-------------");
sprintln("With a file : %s", testname[t]);
f=0;
sprintln("%-7s %-4s %4s %28s %28s", "", "", "", "Just after open ", "After first write ");
sprintln("%-7s %-4s %4s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
m=0;
while(Tests[m].Mode) {
sprint("%-7s %-4s ", "Posix", Tests[m].Mode);
Rest = &Tests[m].Exp[t];
sprintln("%4x %8x %8x %10d %8x %8x %10d", Rest->open, Rest->siz, Rest->pos, Rest->ava, Rest->sizw, Rest->posw, Rest->avaw);
m++;
}
while (fsname[f]) {
if (fsmounted[f]) {
m=0;
while(Tests[m].Mode) {
sprint("%-7s %-4s ", fsname[f], Tests[m].Mode);
Rest = &Tests[m].Res[f][t];
sprintln("%4x %8x %8x %10d %8x %8x %10d", Rest->open, Rest->siz, Rest->pos, Rest->ava, Rest->sizw, Rest->posw, Rest->avaw);
m++;
}
} else
sprintln("not mounted");
f++;
}
t++;
}
/*
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
while (ExNEF[i].Mode) {
RunNEF(IsSD, ExNEF[i].Mode, &Tests[i]. );
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s",
fsname[Tests[i].FS], Tests[i].Mode,
(Tests[i].result.open == Tests[i].expect.open? RES[0] : RES[1]),
(Tests[i].result.siz == Tests[i].expect.siz? RES[0] : RES[1]),
(Tests[i].result.pos == Tests[i].expect.pos? RES[0] : RES[1]),
(Tests[i].result.ava == Tests[i].expect.ava? RES[0] : RES[1]),
(Tests[i].result.sizw == Tests[i].expect.sizw? RES[0] : RES[1]),
(Tests[i].result.posw == Tests[i].expect.posw? RES[0] : RES[1]),
(Tests[i].result.avaw == Tests[i].expect.avaw? RES[0] : RES[1]));
Serial.println("Raw results :");
i=0;
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
while (Tests[i].Mode) {
CreateFile(&Tests[i]);
sprintln("%-8s %-8s %-8x %8x %8x %10d %8x %8x %10d",
fsname[Tests[i].FS], Tests[i].Mode,
Tests[i].result.open,
Tests[i].result.siz, Tests[i].result.pos, Tests[i].result.ava,
Tests[i].result.sizw, Tests[i].result.posw, Tests[i].result.avaw);
i++;
}
Serial.println("Expected results :");
i=0;
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
while (Tests[i].Mode) {
CreateFile(&Tests[i]);
sprintln("%-8s %-8s %-8x %8x %8x %10d %8x %8x %10d",
fsname[Tests[i].FS], Tests[i].Mode,
Tests[i].expect.open,
Tests[i].expect.siz, Tests[i].expect.pos, Tests[i].expect.ava,
Tests[i].expect.sizw, Tests[i].expect.posw, Tests[i].expect.avaw);
i++;
}
Serial.println("----------------------------------------------");
Serial.println("Work with a pre-existing empty file on the FS :");
Serial.println("----------------------------------------------");
Serial.println("Raw results :");
i=0;
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
while (ETests[i].Mode) {
ExistingFile(&ETests[i]);
sprintln("%-8s %-8s %-8x %8x %8x %10d %8x %8x %10d",
fsname[ETests[i].FS], ETests[i].Mode,
ETests[i].result.open,
ETests[i].result.siz, ETests[i].result.pos, ETests[i].result.ava,
ETests[i].result.sizw, ETests[i].result.posw, ETests[i].result.avaw);
i++;
}
Serial.println("--------------------------------------------------");
Serial.println("Work with a pre-existing non-empty file on the FS :");
Serial.println("--------------------------------------------------");
Serial.println("Raw results :");
i=0;
sprintln("%-8s %-8s %-8s %8s %8s %10s %8s %8s %10s", "Support", "Mode", "Open", "Size", "Position", "Available", "Size", "Position", "Available");
while (EnTests[i].Mode) {
ExistingNeFile(&EnTests[i]);
sprintln("%-8s %-8s %-8x %8x %8x %10d %8x %8x %10d",
fsname[EnTests[i].FS], EnTests[i].Mode,
EnTests[i].result.open,
EnTests[i].result.siz, EnTests[i].result.pos, EnTests[i].result.ava,
EnTests[i].result.sizw, EnTests[i].result.posw, EnTests[i].result.avaw);
i++;
}
*/
}
void loop() {
}