From 4f32738cd6a861e9c3f077e86349f0c28ae5f589 Mon Sep 17 00:00:00 2001
From: Tom Szilagyi <tom.szilagyi@altmail.se>
Date: Wed, 3 Jan 2024 16:13:31 +0100
Subject: [PATCH 1/2] Fix return value of lfs_rename()

When lfs_rename() is called trying to rename (move) a file to an
existing directory, LFS_ERR_ISDIR is (correctly) returned. However, in
the opposite case, if one tries to rename (move) a directory to a path
currently occupied by a regular file, LFS_ERR_NOTDIR should be
returned (since the error is that the destination is NOT a directory),
but in reality, LFS_ERR_ISDIR is returned in this case as well.

This commit fixes the code so that in the latter case, LFS_ERR_NOTDIR
is returned.
---
 lfs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lfs.c b/lfs.c
index a152687f..c7dc3eba 100644
--- a/lfs.c
+++ b/lfs.c
@@ -3940,7 +3940,9 @@ static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
             newoldid += 1;
         }
     } else if (lfs_tag_type3(prevtag) != lfs_tag_type3(oldtag)) {
-        return LFS_ERR_ISDIR;
+        return (lfs_tag_type3(prevtag) == LFS_TYPE_DIR)
+                ? LFS_ERR_ISDIR
+                : LFS_ERR_NOTDIR;
     } else if (samepair && newid == newoldid) {
         // we're renaming to ourselves??
         return 0;

From f522ed907af5de03f13487d3e75704ecf1557733 Mon Sep 17 00:00:00 2001
From: Christopher Haster <geky@geky.net>
Date: Wed, 17 Jan 2024 00:10:30 -0600
Subject: [PATCH 2/2] Added tests over rename type errors

---
 tests/test_dirs.toml | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/tests/test_dirs.toml b/tests/test_dirs.toml
index 4262a1aa..181dd6ad 100644
--- a/tests/test_dirs.toml
+++ b/tests/test_dirs.toml
@@ -747,6 +747,11 @@ code = '''
     lfs_file_open(&lfs, &file, "potato",
             LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
 
+    lfs_file_open(&lfs, &file, "tacoto", LFS_O_WRONLY | LFS_O_CREAT) => 0;
+    lfs_file_close(&lfs, &file) => 0;
+    lfs_rename(&lfs, "tacoto", "potato") => LFS_ERR_ISDIR;
+    lfs_rename(&lfs, "potato", "tacoto") => LFS_ERR_NOTDIR;
+
     lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
     lfs_file_open(&lfs, &file, "/",
             LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
@@ -770,6 +775,10 @@ code = '''
     lfs_dir_read(&lfs, &dir, &info) => 1;
     assert(info.type == LFS_TYPE_DIR);
     assert(strcmp(info.name, "potato") == 0);
+    lfs_dir_read(&lfs, &dir, &info) => 1;
+    assert(info.type == LFS_TYPE_REG);
+    assert(strcmp(info.name, "tacoto") == 0);
+    assert(info.size == 0);
     lfs_dir_read(&lfs, &dir, &info) => 0;
     lfs_dir_close(&lfs, &dir) => 0;
 
@@ -790,6 +799,10 @@ code = '''
     lfs_dir_read(&lfs, &dir, &info) => 1;
     assert(info.type == LFS_TYPE_DIR);
     assert(strcmp(info.name, "potato") == 0);
+    lfs_dir_read(&lfs, &dir, &info) => 1;
+    assert(info.type == LFS_TYPE_REG);
+    assert(strcmp(info.name, "tacoto") == 0);
+    assert(info.size == 0);
     lfs_dir_read(&lfs, &dir, &info) => 0;
     lfs_dir_close(&lfs, &dir) => 0;
     lfs_unmount(&lfs) => 0;