aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Foiani <mfoiani@cs.brown.edu>2024-05-15 17:38:07 -0400
committerMichael Foiani <mfoiani@cs.brown.edu>2024-05-15 17:38:07 -0400
commit77408081bd2622c50d9acbcec18f1c598738fdaa (patch)
tree0a8ddd8e4d32c15b689b55bc3b575a979e2aee15
parent919b7f666b9c85699d8d38d3957f9f4a8ebfedc9 (diff)
final submission
-rw-r--r--kernel/fs/s5fs/s5fs.c93
1 files changed, 92 insertions, 1 deletions
diff --git a/kernel/fs/s5fs/s5fs.c b/kernel/fs/s5fs/s5fs.c
index 6da57d4..fc327bb 100644
--- a/kernel/fs/s5fs/s5fs.c
+++ b/kernel/fs/s5fs/s5fs.c
@@ -657,7 +657,98 @@ static long s5fs_rename(vnode_t *olddir, const char *oldname, size_t oldnamelen,
size_t newnamelen)
{
// NOT_YET_IMPLEMENTED("S5FS: s5fs_rename");
- return -1;
+
+ // Check if the new name is too long
+ if (newnamelen >= NAME_LEN)
+ {
+ return -ENAMETOOLONG;
+ }
+
+ // Find the old directory entry
+ s5_node_t *s5_node = VNODE_TO_S5NODE(olddir);
+ size_t filepos;
+ long ino = s5_find_dirent(s5_node, oldname, oldnamelen, &filepos);
+ // Check if the directory entry was not found
+ if (ino < 0)
+ {
+ return ino;
+ }
+
+ // Get the found vnode
+ vnode_t *child = vget_locked(VNODE_TO_S5FS(olddir)->s5f_fs, ino);
+
+ // Check if the new directory is not a directory
+ if (!S_ISDIR(newdir->vn_mode))
+ {
+ vput_locked(&child);
+ return -ENOTDIR;
+ }
+
+ // Check if the new name is a directory
+ if (S_ISDIR(child->vn_mode))
+ {
+ vput_locked(&child);
+ return -EISDIR;
+ }
+
+ // Find the new directory entry
+ size_t filepos2;
+ long ino2 = s5_find_dirent(VNODE_TO_S5NODE(newdir), newname, newnamelen, &filepos2);
+ // Check if the directory entry was found
+ if (ino2 >= 0)
+ {
+ // Check if the old name and new name refer to the same inode
+ if (ino == ino2)
+ {
+ vput_locked(&child);
+ return 0;
+ }
+
+ // Get the found vnode
+ vnode_t *child2 = vget_locked(VNODE_TO_S5FS(newdir)->s5f_fs, ino2);
+ // Check if the new name is a directory
+ if (S_ISDIR(child2->vn_mode))
+ {
+ vput_locked(&child);
+ vput_locked(&child2);
+ return -EISDIR;
+ }
+
+ // Remove the previously existing entry for the new name
+ s5_remove_dirent(VNODE_TO_S5NODE(newdir), newname, newnamelen, VNODE_TO_S5NODE(child2));
+ // Check if this failed (TODO: ask in hours)
+
+ // Link the new directory
+ long link = s5_link(VNODE_TO_S5NODE(newdir), newname, newnamelen, VNODE_TO_S5NODE(child));
+ // Check if the link operation failed
+ if (link < 0)
+ {
+ vput_locked(&child);
+ vput_locked(&child2);
+ return link;
+ }
+
+ // Release the vnodes
+ vput_locked(&child);
+ vput_locked(&child2);
+ return 0;
+ }
+
+ // Link the new directory
+ long link = s5_link(VNODE_TO_S5NODE(newdir), newname, newnamelen, VNODE_TO_S5NODE(child));
+ // Check if the link operation failed
+ if (link < 0)
+ {
+ vput_locked(&child);
+ return link;
+ }
+
+ // Remove the old directory entry
+ s5_remove_dirent(s5_node, oldname, oldnamelen, VNODE_TO_S5NODE(child));
+
+ // Release the vnode
+ vput_locked(&child);
+ return 0;
}
/* Create a directory.