-
-
Notifications
You must be signed in to change notification settings - Fork 542
fix(radio): exFat directory handling #7484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -467,14 +467,18 @@ void RadioSdManagerPage::fileAction(const char* path, const char* name, | |||||||||||
| } | ||||||||||||
| menu->addLine(STR_COPY_FILE, [=]() { | ||||||||||||
| clipboard.type = CLIPBOARD_TYPE_SD_FILE; | ||||||||||||
| f_getcwd(clipboard.data.sd.directory, CLIPBOARD_PATH_LEN); | ||||||||||||
| // f_getcwd() is a no-op on exFAT; use the tracked path. | ||||||||||||
| strncpy(clipboard.data.sd.directory, path, CLIPBOARD_PATH_LEN - 1); | ||||||||||||
| clipboard.data.sd.directory[CLIPBOARD_PATH_LEN - 1] = '\0'; | ||||||||||||
| strncpy(clipboard.data.sd.filename, name, CLIPBOARD_PATH_LEN - 1); | ||||||||||||
| }); | ||||||||||||
|
Comment on lines
473
to
474
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Ensure clipboard filename is always NUL-terminated. At Line 473, Suggested fix strncpy(clipboard.data.sd.filename, name, CLIPBOARD_PATH_LEN - 1);
+ clipboard.data.sd.filename[CLIPBOARD_PATH_LEN - 1] = '\0';📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||
| if (clipboard.type == CLIPBOARD_TYPE_SD_FILE) { | ||||||||||||
| menu->addLine(STR_PASTE, [=]() { | ||||||||||||
| static char lfn[FF_MAX_LFN + 1]; // TODO optimize that! | ||||||||||||
| char destFileName[2 * CLIPBOARD_PATH_LEN + 1]; | ||||||||||||
| f_getcwd((TCHAR*)lfn, FF_MAX_LFN); | ||||||||||||
| // f_getcwd() is a no-op on exFAT; use the tracked path. | ||||||||||||
| strncpy(lfn, path, FF_MAX_LFN); | ||||||||||||
| lfn[FF_MAX_LFN] = '\0'; | ||||||||||||
| // prevent copying to the same directory with the same name | ||||||||||||
| char* destNamePtr = clipboard.data.sd.filename; | ||||||||||||
| if (!strcmp(clipboard.data.sd.directory, lfn)) { | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -61,9 +61,27 @@ inline bool isFilenameLower(bool isfile, const char * fn, const char * line) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return (!isfile && IS_FILE(line)) || (isfile==IS_FILE(line) && strcasecmp(fn, line) < 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Current dir, tracked explicitly: on exFAT f_getcwd() and f_chdir("..") are no-ops. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static char sdManagerPath[FF_MAX_LFN + 1] = "/"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| static void sdManagerChdir(const char* name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!strcmp(name, "..")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // go up: drop the last path segment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| char* sep = strrchr(sdManagerPath, '/'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (sep == sdManagerPath) sep[1] = '\0'; // parent is the root | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if (sep) *sep = '\0'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // descend into 'name' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (sdManagerPath[1] != '\0') strcat(sdManagerPath, "/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcat(sdManagerPath, name); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_chdir(sdManagerPath); // absolute path: resolves on FAT and exFAT alike | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+67
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify sizes and all C-string writes touching sdManagerPath / clipboard paths.
set -euo pipefail
fd -a "radio_sdmanager.cpp" radio/src | sort
echo "---- constants ----"
rg -n "FF_MAX_LFN|CLIPBOARD_PATH_LEN|sdManagerPath" radio/src/gui/common/stdlcd/radio_sdmanager.cpp radio/src/gui/colorlcd/radio/radio_sdmanager.cpp
echo "---- risky concatenations/copies ----"
rg -n "strcat\\(|strcpy\\(|strncpy\\(" radio/src/gui/common/stdlcd/radio_sdmanager.cpp radio/src/gui/colorlcd/radio/radio_sdmanager.cppRepository: EdgeTX/edgetx Length of output: 5644 🏁 Script executed: # Verify getSelectionFullPath and the strncpy at line 144
sed -n '82,87p' radio/src/gui/common/stdlcd/radio_sdmanager.cpp
echo "---"
sed -n '140,146p' radio/src/gui/common/stdlcd/radio_sdmanager.cpp
echo "---"
# Find FF_MAX_LFN definition
rg -n "define FF_MAX_LFN" radio/src/Repository: EdgeTX/edgetx Length of output: 754 🏁 Script executed: # Check if there's NUL termination after line 144
sed -n '144,146p' radio/src/gui/common/stdlcd/radio_sdmanager.cppRepository: EdgeTX/edgetx Length of output: 258
Use bounded operations, validate before writing, and only update Suggested fix static void sdManagerChdir(const char* name)
{
+ char candidate[FF_MAX_LFN + 1];
+ strncpy(candidate, sdManagerPath, FF_MAX_LFN);
+ candidate[FF_MAX_LFN] = '\0';
+
if (!strcmp(name, "..")) {
// go up: drop the last path segment
- char* sep = strrchr(sdManagerPath, '/');
- if (sep == sdManagerPath) sep[1] = '\0'; // parent is the root
- else if (sep) *sep = '\0';
+ char* sep = strrchr(candidate, '/');
+ if (sep == candidate) sep[1] = '\0'; // parent is the root
+ else if (sep) *sep = '\0';
} else {
// descend into 'name'
- if (sdManagerPath[1] != '\0') strcat(sdManagerPath, "/");
- strcat(sdManagerPath, name);
+ size_t used = strlen(candidate);
+ if (candidate[1] != '\0') {
+ if (used + 1 >= sizeof(candidate)) return;
+ candidate[used++] = '/';
+ candidate[used] = '\0';
+ }
+ size_t remain = sizeof(candidate) - used - 1;
+ if (strlen(name) > remain) return;
+ strcat(candidate, name);
}
- f_chdir(sdManagerPath); // absolute path: resolves on FAT and exFAT alike
+ if (f_chdir(candidate) == FR_OK) {
+ strncpy(sdManagerPath, candidate, FF_MAX_LFN);
+ sdManagerPath[FF_MAX_LFN] = '\0';
+ }
}Add NUL termination at line 145 and apply bounds checking to 📝 Committable suggestion
Suggested change
🧰 Tools🪛 ast-grep (0.44.0)[error] 75-75: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf). (dangerous-buffer-functions-cpp) [error] 76-76: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf). (dangerous-buffer-functions-cpp) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| void getSelectionFullPath(char * lfn) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_getcwd(lfn, FF_MAX_LFN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcpy(lfn, sdManagerPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcat(lfn, "/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcat(lfn, reusableBuffer.sdManager.lines[menuVerticalPosition - HEADER_LINE - menuVerticalOffset]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
82
to
87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major 🧩 Analysis chain🏁 Script executed: find . -type f -name "radio_sdmanager.cpp" | head -5Repository: EdgeTX/edgetx Length of output: 252 🏁 Script executed: fd "radio_sdmanager" --type fRepository: EdgeTX/edgetx Length of output: 295 🏁 Script executed: rg "FF_MAX_LFN" --type cpp --type c -A 2 -B 2Repository: EdgeTX/edgetx Length of output: 151 🏁 Script executed: rg "getSelectionFullPath" --type cpp --type c -B 5 -A 10Repository: EdgeTX/edgetx Length of output: 151 🏁 Script executed: cat -n radio/src/gui/common/stdlcd/radio_sdmanager.cpp | sed -n '75,95p'Repository: EdgeTX/edgetx Length of output: 825 🏁 Script executed: rg "MAX_LFN|LFN_MAX|FF_LFN" --type cpp --type c --type h | head -20Repository: EdgeTX/edgetx Length of output: 151 🏁 Script executed: rg "sdManagerPath" --type cpp --type c --type h -B 2 -A 2 | head -30Repository: EdgeTX/edgetx Length of output: 151 🏁 Script executed: grep -r "FF_MAX_LFN\|LFN_MAX\|MAX_LFN" --include="*.h" --include="*.cpp" --include="*.c" | head -20Repository: EdgeTX/edgetx Length of output: 2133 🏁 Script executed: rg "define FF_MAX_LFN|FF_MAX_LFN\s*=" --type h --type hpp | head -10Repository: EdgeTX/edgetx Length of output: 179 🏁 Script executed: find . -type f -name "*.h" -o -name "*.hpp" | xargs grep -l "FF_MAX_LFN" | head -10Repository: EdgeTX/edgetx Length of output: 219 🏁 Script executed: rg "getSelectionFullPath\(" --type cpp --type c -B 2 -A 2Repository: EdgeTX/edgetx Length of output: 151 🏁 Script executed: cat -n radio/src/gui/common/stdlcd/radio_sdmanager.cpp | head -50Repository: EdgeTX/edgetx Length of output: 2142 🏁 Script executed: rg "FF_MAX_LFN" radio/src/thirdparty/FatFs/ffconf.h -A 2 -B 2Repository: EdgeTX/edgetx Length of output: 885 🏁 Script executed: rg "sdManagerPath\s*\[|char.*sdManagerPath" radio/src/gui/common/stdlcd/radio_sdmanager.cppRepository: EdgeTX/edgetx Length of output: 307 🏁 Script executed: cat -n radio/src/gui/common/stdlcd/radio_sdmanager.cpp | grep -A 5 -B 5 "getSelectionFullPath"Repository: EdgeTX/edgetx Length of output: 6173 🏁 Script executed: rg "getSelectionFullPath" radio/src/gui/common/stdlcd/ radio/src/gui/colorlcd/ -B 3 -A 3Repository: EdgeTX/edgetx Length of output: 9870 Use The Suggested fix void getSelectionFullPath(char * lfn)
{
- strcpy(lfn, sdManagerPath);
- strcat(lfn, "/");
- strcat(lfn, reusableBuffer.sdManager.lines[menuVerticalPosition - HEADER_LINE - menuVerticalOffset]);
+ snprintf(lfn, FF_MAX_LFN + 1, "%s/%s",
+ sdManagerPath,
+ reusableBuffer.sdManager.lines[menuVerticalPosition - HEADER_LINE - menuVerticalOffset]);
}🧰 Tools🪛 ast-grep (0.44.0)[error] 83-83: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf). (dangerous-buffer-functions-cpp) [error] 84-84: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf). (dangerous-buffer-functions-cpp) [error] 85-85: Use of an unbounded buffer function that can overflow the destination; use a size-bounded equivalent (fgets, strncpy/strlcpy, strncat/strlcat, snprintf). (dangerous-buffer-functions-cpp) 🤖 Prompt for AI AgentsSource: Linters/SAST tools
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. valid concern, but the suggested direction would break a caller Not a regression. The original code keyed off CWD too (isCwdAtRoot() → f_getcwd()), so my fs->cdir version had the same CWD-coupling — just made to work on exFAT. So nothing got worse. Their implied fix (key off the opened dir, sclust) would actually break theme_manager. It opens /THEMES (no chdir) and calls scanThemeFolder(fno.fname) for every AM_DIR entry (theme_manager.cpp:330). If ".." were injected there, it'd recurse into the parent. With a pure opened-dir check, /THEMES is non-root → ".." always injected → broken. filechoice is immune regardless — it continues on every AM_DIR (filechoice.cpp:135). The actually-correct rule Fake ".." only when we're browsing the current dir itself and it isn't root: if (firstTime && dir->obj.fs->cdir != 0 && dir->obj.sclust == dir->obj.fs->cdir) {
So the fix now works on exFAT and removes the latent CWD-coupling the reviewer flagged. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -121,12 +139,13 @@ void onSdManagerMenu(const char * result) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if (result == STR_COPY_FILE) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clipboard.type = CLIPBOARD_TYPE_SD_FILE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_getcwd(clipboard.data.sd.directory, CLIPBOARD_PATH_LEN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strncpy(clipboard.data.sd.directory, sdManagerPath, CLIPBOARD_PATH_LEN - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| clipboard.data.sd.directory[CLIPBOARD_PATH_LEN - 1] = '\0'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strncpy(clipboard.data.sd.filename, line, CLIPBOARD_PATH_LEN-1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
144
to
145
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Mirror directory handling: NUL-terminate copied filename. At Line 144, Suggested fix strncpy(clipboard.data.sd.filename, line, CLIPBOARD_PATH_LEN-1);
+ clipboard.data.sd.filename[CLIPBOARD_PATH_LEN - 1] = '\0';🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else if (result == STR_PASTE) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| char destFileName[2 * CLIPBOARD_PATH_LEN + 1]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_getcwd(lfn, FF_MAX_LFN); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcpy(lfn, sdManagerPath); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // if destination is dir, copy into that dir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (IS_DIRECTORY(line)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcat(lfn, "/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -279,6 +298,7 @@ void menuRadioSdManager(event_t _event) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (_event == EVT_ENTRY) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_chdir(ROOT_PATH); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| strcpy(sdManagerPath, ROOT_PATH); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if LCD_DEPTH > 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lastPos = -1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -325,7 +345,7 @@ void menuRadioSdManager(event_t _event) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (IS_DIRECTORY(reusableBuffer.sdManager.lines[index])) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f_chdir(reusableBuffer.sdManager.lines[index]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sdManagerChdir(reusableBuffer.sdManager.lines[index]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| menuVerticalOffset = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| menuVerticalPosition = HEADER_LINE; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| REFRESH_FILES(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Handle
f_chdirfailures before committing tracked path changes.Line 136 and Line 256 ignore
f_chdirresults. On failure,currentPathcan drift from FatFs CWD, causing later callbacks/actions to target the wrong directory.Suggested fix
FileBrowser::FileBrowser(Window* parent, const rect_t& rect, const char* dir) : TableField(parent, rect), currentPath((dir && dir[0]) ? dir : "/") { - f_chdir(currentPath.c_str()); + if (f_chdir(currentPath.c_str()) != FR_OK) { + currentPath = "/"; + f_chdir(currentPath.c_str()); + } setAutoEdit();void FileBrowser::onPress(const char* name, bool is_dir) { if (is_dir) { + std::string nextPath = currentPath; if (strcmp(name, "..") == 0) { // Go up: trim last segment (f_chdir("..") / f_getcwd are no-ops on exFAT). - auto pos = currentPath.find_last_of('/'); - currentPath = (pos == 0 || pos == std::string::npos) ? "/" - : currentPath.substr(0, pos); + auto pos = nextPath.find_last_of('/'); + nextPath = (pos == 0 || pos == std::string::npos) ? "/" + : nextPath.substr(0, pos); } else { setFullPath(name); - currentPath = fullPathBuf; + nextPath = fullPathBuf; } - f_chdir(currentPath.c_str()); + if (f_chdir(nextPath.c_str()) != FR_OK) { + return; + } + currentPath = nextPath; if (fileSelected) fileSelected(nullptr, nullptr, nullptr, is_dir); selected = nullptr; refresh(); return; }Also applies to: 246-257
🤖 Prompt for AI Agents