Strip trailing slashes from dir-path constants

PATH_CONTACTS / PATH_MESSAGES / SD_PATH_CONTACTS / SD_PATH_MESSAGES
all ended in '/'. The FATFS layer used by the SD library and LittleFS
won't reliably enumerate when given a path ending in slash — opendir
returns a valid handle but readdir yields nothing. Direct file reads
(SD.open with FILE_READ for a known path) still work, which is why
settings/identity persisted but contacts and conversations vanished
on reboot.

Drop the trailing slash from the constants and add explicit "/" at
all concat sites: saveContact, removeContact, conversationDir,
sdConversationDir, and the migrateTruncatedDirs path builders.
This commit is contained in:
drkhsh
2026-04-26 02:50:54 +02:00
parent 9cb5a4f3db
commit 3d135ceca1
3 changed files with 15 additions and 12 deletions
+7 -4
View File
@@ -30,14 +30,17 @@
#define PATH_IDENTITY_BAK "/identity/identity.key.bak"
#define PATH_PATHS "/transport/paths.msgpack"
#define PATH_USER_CONFIG "/config/user.json"
#define PATH_CONTACTS "/contacts/"
#define PATH_MESSAGES "/messages/"
// Directory paths intentionally have NO trailing slash — some FATFS/VFS
// readdir paths fail to enumerate when given a path ending in '/'.
// Concat sites must add their own '/' before the basename.
#define PATH_CONTACTS "/contacts"
#define PATH_MESSAGES "/messages"
// --- SD Card Paths ---
#define SD_PATH_CONFIG_DIR "/ratdeck/config"
#define SD_PATH_USER_CONFIG "/ratdeck/config/user.json"
#define SD_PATH_MESSAGES "/ratdeck/messages/"
#define SD_PATH_CONTACTS "/ratdeck/contacts/"
#define SD_PATH_MESSAGES "/ratdeck/messages"
#define SD_PATH_CONTACTS "/ratdeck/contacts"
#define SD_PATH_IDENTITY "/ratdeck/identity/identity.key"
// --- TCP Client ---
+4 -4
View File
@@ -349,15 +349,15 @@ void AnnounceManager::saveContact(const DiscoveredNode& node) {
serializeJson(doc, json);
String filename = hexHash.substr(0, 16).c_str();
filename += ".json";
if (_sd && _sd->isReady()) { _sd->writeString((String(SD_PATH_CONTACTS) + filename).c_str(), json); }
if (_flash) { _flash->writeString((String(PATH_CONTACTS) + filename).c_str(), json); }
if (_sd && _sd->isReady()) { _sd->writeString((String(SD_PATH_CONTACTS) + "/" + filename).c_str(), json); }
if (_flash) { _flash->writeString((String(PATH_CONTACTS) + "/" + filename).c_str(), json); }
}
void AnnounceManager::removeContact(const std::string& hexHash) {
String filename = hexHash.substr(0, 16).c_str();
filename += ".json";
if (_sd && _sd->isReady()) { _sd->remove((String(SD_PATH_CONTACTS) + filename).c_str()); }
if (_flash) { _flash->remove((String(PATH_CONTACTS) + filename).c_str()); }
if (_sd && _sd->isReady()) { _sd->remove((String(SD_PATH_CONTACTS) + "/" + filename).c_str()); }
if (_flash) { _flash->remove((String(PATH_CONTACTS) + "/" + filename).c_str()); }
}
bool AnnounceManager::deleteContact(int nodeIdx) {
+4 -4
View File
@@ -146,7 +146,7 @@ void MessageStore::migrateTruncatedDirs() {
// Old dirs are exactly 16 hex chars; new ones are 32
if (dirName.length() == 16) {
// Read first JSON file inside to get the full hash
String oldDir = String(basePath) + dirName.c_str();
String oldDir = String(basePath) + "/" + dirName.c_str();
File inner = openFn(oldDir.c_str());
if (inner && inner.isDirectory()) {
File jsonFile = inner.openNextFile();
@@ -176,7 +176,7 @@ void MessageStore::migrateTruncatedDirs() {
inner.close();
if (!fullHash.empty() && fullHash.substr(0, 16) == dirName) {
String newDir = String(basePath) + fullHash.c_str();
String newDir = String(basePath) + "/" + fullHash.c_str();
renames.push_back({oldDir, newDir});
}
}
@@ -738,11 +738,11 @@ int MessageStore::totalUnreadCount() const {
}
String MessageStore::conversationDir(const std::string& peerHex) const {
return String(PATH_MESSAGES) + peerHex.c_str();
return String(PATH_MESSAGES) + "/" + peerHex.c_str();
}
String MessageStore::sdConversationDir(const std::string& peerHex) const {
return String(SD_PATH_MESSAGES) + peerHex.c_str();
return String(SD_PATH_MESSAGES) + "/" + peerHex.c_str();
}
void MessageStore::enforceFlashLimit(const std::string& peerHex) {