diff --git a/source/fs.c b/source/fs.c index 4587f51..8a9bca3 100644 --- a/source/fs.c +++ b/source/fs.c @@ -124,6 +124,21 @@ u32 GetWritePermissions() { return write_permission_level; } +bool GetTempFileName(char* path) { + // this assumes path is initialized with enough room + char* tempname = strrchr(path, '/'); + if (!tempname) return false; + tempname++; + strncpy(tempname, "AAAAAAAA.TMP", 255 - (tempname - path)); + char* cc = tempname; + // this does not try all permutations + for (; (*cc <= 'Z') && (cc - tempname < 8); (*cc)++) { + if (f_stat(path, NULL) != FR_OK) break; + if (*cc == 'Z') cc++; + } + return (cc - tempname < 8) ? true : false; +} + bool FileCreateData(const char* path, u8* data, size_t size) { FIL file; UINT bytes_written = 0; @@ -463,12 +478,26 @@ bool PathDelete(const char* path) { bool PathRename(const char* path, const char* newname) { char npath[256]; // 256 is the maximum length of a full path char* oldname = strrchr(path, '/'); + if (!CheckWritePermissions(path)) return false; if (!oldname) return false; oldname++; strncpy(npath, path, oldname - path); - strncpy(npath + (oldname - path), newname, strnlen(newname, 255 - (oldname - path))); - return (f_rename(path, npath) == FR_OK); + strncpy(npath + (oldname - path), newname, 255 - (oldname - path)); + + FRESULT res = f_rename(path, npath); + if (res == FR_EXIST) { // new path already exists (possible LFN/case issue) + char temp[256]; + strncpy(temp, path, oldname - path); + if (!GetTempFileName(temp)) return false; + if (f_rename(path, temp) == FR_OK) { + if ((f_stat(npath, NULL) == FR_OK) || (f_rename(temp, npath) != FR_OK)) { + ShowPrompt(false, "Destination exists in folder"); + f_rename(temp, path); // something went wrong - try renaming back + return false; + } else return true; + } else return false; + } else return (res == FR_OK) ? true : false; } bool DirCreate(const char* cpath, const char* dirname) {