|
@@ -32,6 +32,7 @@ CardReader::CardReader()
|
|
|
workDirDepth = 0;
|
|
|
file_subcall_ctr=0;
|
|
|
memset(workDirParents, 0, sizeof(workDirParents));
|
|
|
+ presort_flag = false;
|
|
|
|
|
|
autostart_stilltocheck=true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
|
|
|
lastnr=0;
|
|
@@ -69,12 +70,23 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
|
|
|
+*/
|
|
|
|
|
|
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
|
|
|
+ static uint8_t recursionCnt = 0;
|
|
|
+ // RAII incrementer for the recursionCnt
|
|
|
+ class _incrementer
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ _incrementer() {recursionCnt++;}
|
|
|
+ ~_incrementer() {recursionCnt--;}
|
|
|
+ } recursionCntIncrementer;
|
|
|
+
|
|
|
dir_t p;
|
|
|
uint8_t cnt = 0;
|
|
|
// Read the next entry from a directory
|
|
|
while (parent.readDir(p, longFilename) > 0) {
|
|
|
- // If the entry is a directory and the action is LS_SerialPrint
|
|
|
- if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
|
|
|
+ if (recursionCnt > MAX_DIR_DEPTH)
|
|
|
+ return;
|
|
|
+ else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint
|
|
|
+
|
|
|
// Get the short name for the item, which we know is a folder
|
|
|
char lfilename[FILENAME_LENGTH];
|
|
|
createFilename(lfilename, p);
|
|
@@ -241,18 +253,18 @@ void CardReader::initsd()
|
|
|
|
|
|
}
|
|
|
|
|
|
-void CardReader::setroot()
|
|
|
+void CardReader::setroot(bool doPresort)
|
|
|
{
|
|
|
- /*if(!workDir.openRoot(&volume))
|
|
|
- {
|
|
|
- SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
|
|
|
- }*/
|
|
|
workDir=root;
|
|
|
+ workDirDepth = 0;
|
|
|
|
|
|
curDir=&workDir;
|
|
|
- #ifdef SDCARD_SORT_ALPHA
|
|
|
- presort();
|
|
|
- #endif
|
|
|
+#ifdef SDCARD_SORT_ALPHA
|
|
|
+ if (doPresort)
|
|
|
+ presort();
|
|
|
+ else
|
|
|
+ presort_flag = true;
|
|
|
+#endif
|
|
|
}
|
|
|
void CardReader::release()
|
|
|
{
|
|
@@ -304,6 +316,18 @@ void CardReader::getAbsFilename(char *t)
|
|
|
else
|
|
|
t[0]=0;
|
|
|
}
|
|
|
+
|
|
|
+void CardReader::printAbsFilenameFast()
|
|
|
+{
|
|
|
+ SERIAL_PROTOCOL('/');
|
|
|
+ for (uint8_t i = 0; i < getWorkDirDepth(); i++)
|
|
|
+ {
|
|
|
+ SERIAL_PROTOCOL(dir_names[i]);
|
|
|
+ SERIAL_PROTOCOL('/');
|
|
|
+ }
|
|
|
+ SERIAL_PROTOCOL(LONGEST_FILENAME);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* @brief Dive into subfolder
|
|
|
*
|
|
@@ -317,19 +341,17 @@ void CardReader::getAbsFilename(char *t)
|
|
|
* @param[in,out] fileName
|
|
|
* expects file name including path
|
|
|
* in case of absolute path, file name without path is returned
|
|
|
- * @param[in,out] dir SdFile object to operate with,
|
|
|
- * in case of absolute path, curDir is modified to point to dir,
|
|
|
- * so it is not possible to create on stack inside this function,
|
|
|
- * as curDir would point to destroyed object.
|
|
|
*/
|
|
|
-void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
|
|
|
+bool CardReader::diveSubfolder (const char *&fileName)
|
|
|
{
|
|
|
curDir=&root;
|
|
|
- if (!fileName) return;
|
|
|
+ if (!fileName)
|
|
|
+ return 1;
|
|
|
|
|
|
const char *dirname_start, *dirname_end;
|
|
|
if (fileName[0] == '/') // absolute path
|
|
|
{
|
|
|
+ setroot(false);
|
|
|
dirname_start = fileName + 1;
|
|
|
while (*dirname_start)
|
|
|
{
|
|
@@ -340,23 +362,13 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
|
|
|
{
|
|
|
const size_t maxLen = 12;
|
|
|
char subdirname[maxLen+1];
|
|
|
- subdirname[maxLen] = 0;
|
|
|
const size_t len = ((static_cast<size_t>(dirname_end-dirname_start))>maxLen) ? maxLen : (dirname_end-dirname_start);
|
|
|
strncpy(subdirname, dirname_start, len);
|
|
|
- SERIAL_ECHOLN(subdirname);
|
|
|
- if (!dir.open(curDir, subdirname, O_READ))
|
|
|
- {
|
|
|
- SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
|
|
|
- SERIAL_PROTOCOL(subdirname);
|
|
|
- SERIAL_PROTOCOLLN('.');
|
|
|
- return;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- //SERIAL_ECHOLN("dive ok");
|
|
|
- }
|
|
|
-
|
|
|
- curDir = &dir;
|
|
|
+ subdirname[len] = 0;
|
|
|
+ if (!chdir(subdirname, false))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ curDir = &workDir;
|
|
|
dirname_start = dirname_end + 1;
|
|
|
}
|
|
|
else // the reminder after all /fsa/fdsa/ is the filename
|
|
@@ -373,6 +385,7 @@ void CardReader::diveSubfolder (const char *fileName, SdFile& dir)
|
|
|
{
|
|
|
curDir = &workDir;
|
|
|
}
|
|
|
+ return 1;
|
|
|
}
|
|
|
|
|
|
void CardReader::openFile(const char* name,bool read, bool replace_current/*=true*/)
|
|
@@ -423,25 +436,24 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru
|
|
|
}
|
|
|
sdprinting = false;
|
|
|
|
|
|
- SdFile myDir;
|
|
|
const char *fname=name;
|
|
|
- diveSubfolder(fname,myDir);
|
|
|
+ if (!diveSubfolder(fname))
|
|
|
+ return;
|
|
|
|
|
|
if(read)
|
|
|
{
|
|
|
if (file.open(curDir, fname, O_READ))
|
|
|
{
|
|
|
+ getfilename(0, fname);
|
|
|
filesize = file.fileSize();
|
|
|
SERIAL_PROTOCOLRPGM(_N("File opened: "));////MSG_SD_FILE_OPENED
|
|
|
- SERIAL_PROTOCOL(fname);
|
|
|
+ printAbsFilenameFast();
|
|
|
SERIAL_PROTOCOLRPGM(_n(" Size: "));////MSG_SD_SIZE
|
|
|
SERIAL_PROTOCOLLN(filesize);
|
|
|
sdpos = 0;
|
|
|
|
|
|
- SERIAL_PROTOCOLLNRPGM(_N("File selected"));////MSG_SD_FILE_SELECTED
|
|
|
- getfilename(0, fname);
|
|
|
- lcd_setstatus(longFilename[0] ? longFilename : fname);
|
|
|
- lcd_setstatuspgm(PSTR("SD-PRINTING"));
|
|
|
+ SERIAL_PROTOCOLLNRPGM(MSG_FILE_SELECTED);
|
|
|
+ lcd_setstatuspgm(MSG_FILE_SELECTED);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -475,9 +487,9 @@ void CardReader::removeFile(const char* name)
|
|
|
file.close();
|
|
|
sdprinting = false;
|
|
|
|
|
|
- SdFile myDir;
|
|
|
const char *fname=name;
|
|
|
- diveSubfolder(fname,myDir);
|
|
|
+ if (!diveSubfolder(fname))
|
|
|
+ return;
|
|
|
|
|
|
if (file.remove(curDir, fname))
|
|
|
{
|
|
@@ -515,10 +527,8 @@ void CardReader::getStatus(bool arg_P)
|
|
|
{
|
|
|
if (arg_P)
|
|
|
{
|
|
|
- SERIAL_PROTOCOL('/');
|
|
|
- for (uint8_t i = 0; i < getWorkDirDepth(); i++)
|
|
|
- printf_P(PSTR("%s/"), dir_names[i]);
|
|
|
- puts(filename);
|
|
|
+ printAbsFilenameFast();
|
|
|
+ SERIAL_PROTOCOLLN();
|
|
|
}
|
|
|
else
|
|
|
SERIAL_PROTOCOLLN(LONGEST_FILENAME);
|
|
@@ -670,7 +680,7 @@ uint16_t CardReader::getnrfilenames()
|
|
|
return nrFiles;
|
|
|
}
|
|
|
|
|
|
-void CardReader::chdir(const char * relpath)
|
|
|
+bool CardReader::chdir(const char * relpath, bool doPresort)
|
|
|
{
|
|
|
SdFile newfile;
|
|
|
SdFile *parent=&root;
|
|
@@ -678,23 +688,32 @@ void CardReader::chdir(const char * relpath)
|
|
|
if(workDir.isOpen())
|
|
|
parent=&workDir;
|
|
|
|
|
|
- if(!newfile.open(*parent,relpath, O_READ))
|
|
|
+ if(!newfile.open(*parent,relpath, O_READ) || ((workDirDepth + 1) >= MAX_DIR_DEPTH))
|
|
|
{
|
|
|
SERIAL_ECHO_START;
|
|
|
SERIAL_ECHORPGM(_n("Cannot enter subdir: "));////MSG_SD_CANT_ENTER_SUBDIR
|
|
|
SERIAL_ECHOLN(relpath);
|
|
|
+ return 0;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
+ strcpy(dir_names[workDirDepth], relpath);
|
|
|
+ puts(relpath);
|
|
|
+
|
|
|
if (workDirDepth < MAX_DIR_DEPTH) {
|
|
|
for (int d = ++workDirDepth; d--;)
|
|
|
workDirParents[d+1] = workDirParents[d];
|
|
|
workDirParents[0]=*parent;
|
|
|
}
|
|
|
workDir=newfile;
|
|
|
- #ifdef SDCARD_SORT_ALPHA
|
|
|
+
|
|
|
+#ifdef SDCARD_SORT_ALPHA
|
|
|
+ if (doPresort)
|
|
|
presort();
|
|
|
- #endif
|
|
|
+ else
|
|
|
+ presort_flag = true;
|
|
|
+#endif
|
|
|
+ return 1;
|
|
|
}
|
|
|
}
|
|
|
|