Fix diveToFile with open Dir object (#19539)

* Fix CardReader diveToFile
* Add CardReader::fileExists
This commit is contained in:
Scott Lahteine 2020-09-28 15:46:12 -05:00
parent 04a712dacc
commit 806c908091
2 changed files with 46 additions and 23 deletions

View File

@ -571,11 +571,11 @@ void CardReader::openFileRead(char * const path, const uint8_t subcall_type/*=0*
endFilePrint(); endFilePrint();
SdFile *curDir; SdFile *diveDir;
const char * const fname = diveToFile(true, curDir, path); const char * const fname = diveToFile(true, diveDir, path);
if (!fname) return; if (!fname) return;
if (file.open(curDir, fname, O_READ)) { if (file.open(diveDir, fname, O_READ)) {
filesize = file.fileSize(); filesize = file.fileSize();
sdpos = 0; sdpos = 0;
@ -606,14 +606,14 @@ void CardReader::openFileWrite(char * const path) {
endFilePrint(); endFilePrint();
SdFile *curDir; SdFile *diveDir;
const char * const fname = diveToFile(false, curDir, path); const char * const fname = diveToFile(false, diveDir, path);
if (!fname) return; if (!fname) return;
#if ENABLED(SDCARD_READONLY) #if ENABLED(SDCARD_READONLY)
openFailed(fname); openFailed(fname);
#else #else
if (file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) { if (file.open(diveDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
flag.saving = true; flag.saving = true;
selectFileByName(fname); selectFileByName(fname);
TERN_(EMERGENCY_PARSER, emergency_parser.disable()); TERN_(EMERGENCY_PARSER, emergency_parser.disable());
@ -625,6 +625,16 @@ void CardReader::openFileWrite(char * const path) {
#endif #endif
} }
//
// Check if a file exists by absolute or workDir-relative path
//
bool CardReader::fileExists(const char * const path) {
if (!isMounted()) return false;
SdFile *diveDir = nullptr;
const char * const fname = diveToFile(false, diveDir, path);
return fname != nullptr;
}
// //
// Delete a file by name in the working directory // Delete a file by name in the working directory
// //
@ -770,13 +780,15 @@ uint16_t CardReader::countFilesInWorkDir() {
/** /**
* Dive to the given DOS 8.3 file path, with optional echo of the dive paths. * Dive to the given DOS 8.3 file path, with optional echo of the dive paths.
* *
* On exit, curDir contains an SdFile reference to the file's directory. * On exit:
* - Your curDir pointer contains an SdFile reference to the file's directory.
* - If update_cwd was 'true' the workDir now points to the file's directory.
* *
* Returns a pointer to the last segment (filename) of the given DOS 8.3 path. * Returns a pointer to the last segment (filename) of the given DOS 8.3 path.
* *
* A nullptr result indicates an unrecoverable error. * A nullptr result indicates an unrecoverable error.
*/ */
const char* CardReader::diveToFile(const bool update_cwd, SdFile*& curDir, const char * const path, const bool echo/*=false*/) { const char* CardReader::diveToFile(const bool update_cwd, SdFile*& diveDir, const char * const path, const bool echo/*=false*/) {
// Track both parent and subfolder // Track both parent and subfolder
static SdFile newDir1, newDir2; static SdFile newDir1, newDir2;
SdFile *sub = &newDir1, *startDir; SdFile *sub = &newDir1, *startDir;
@ -785,14 +797,15 @@ const char* CardReader::diveToFile(const bool update_cwd, SdFile*& curDir, const
const char *item_name_adr = path; const char *item_name_adr = path;
if (path[0] == '/') { // Starting at the root directory? if (path[0] == '/') { // Starting at the root directory?
curDir = &root; diveDir = &root;
if (update_cwd) workDirDepth = 0; // The cwd can be updated for the benefit of sub-programs
item_name_adr++; item_name_adr++;
if (update_cwd) workDirDepth = 0; // The cwd can be updated for the benefit of sub-programs
} }
else else
curDir = &workDir; // Dive from workDir (as set by the UI) diveDir = &workDir; // Dive from workDir (as set by the UI)
startDir = diveDir;
startDir = curDir;
while (item_name_adr) { while (item_name_adr) {
// Find next subdirectory delimiter // Find next subdirectory delimiter
char * const name_end = strchr(item_name_adr, '/'); char * const name_end = strchr(item_name_adr, '/');
@ -808,30 +821,39 @@ const char* CardReader::diveToFile(const bool update_cwd, SdFile*& curDir, const
if (echo) SERIAL_ECHOLN(dosSubdirname); if (echo) SERIAL_ECHOLN(dosSubdirname);
// Open curDir // Open diveDir (closing first)
if (!sub->open(curDir, dosSubdirname, O_READ)) { sub->close();
if (!sub->open(diveDir, dosSubdirname, O_READ)) {
openFailed(dosSubdirname); openFailed(dosSubdirname);
return nullptr; item_name_adr = nullptr;
break;
} }
// Close curDir if not at starting-point // Close diveDir if not at starting-point
if (curDir != startDir) curDir->close(); if (diveDir != startDir) diveDir->close();
// curDir now subDir // diveDir now subDir
curDir = sub; diveDir = sub;
// Update workDirParents, workDirDepth, and workDir // Update workDirParents and workDirDepth
if (update_cwd) { if (update_cwd) {
if (workDirDepth < MAX_DIR_DEPTH) workDirParents[workDirDepth++] = *curDir; if (workDirDepth < MAX_DIR_DEPTH)
workDir = *curDir; workDirParents[workDirDepth++] = *diveDir;
} }
// Point sub at the other scratch object // Point sub at the other scratch object
sub = (curDir != &newDir1) ? &newDir1 : &newDir2; sub = (diveDir != &newDir1) ? &newDir1 : &newDir2;
// Next path atom address // Next path atom address
item_name_adr = name_end + 1; item_name_adr = name_end + 1;
} }
if (update_cwd) {
workDir = *diveDir;
flag.workDirIsRoot = (workDirDepth == 0);
TERN_(SDCARD_SORT_ALPHA, presort());
}
return item_name_adr; return item_name_adr;
} }

View File

@ -99,6 +99,7 @@ public:
static void openFileRead(char * const path, const uint8_t subcall=0); static void openFileRead(char * const path, const uint8_t subcall=0);
static void openFileWrite(char * const path); static void openFileWrite(char * const path);
static void closefile(const bool store_location=false); static void closefile(const bool store_location=false);
static bool fileExists(const char * const name);
static void removeFile(const char * const name); static void removeFile(const char * const name);
static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; } static inline char* longest_filename() { return longFilename[0] ? longFilename : filename; }