diff options
author | Michael Foiani <mfoiani@cs.brown.edu> | 2024-05-15 17:38:07 -0400 |
---|---|---|
committer | Michael Foiani <mfoiani@cs.brown.edu> | 2024-05-15 17:38:07 -0400 |
commit | 77408081bd2622c50d9acbcec18f1c598738fdaa (patch) | |
tree | 0a8ddd8e4d32c15b689b55bc3b575a979e2aee15 | |
parent | 919b7f666b9c85699d8d38d3957f9f4a8ebfedc9 (diff) |
final submission
-rw-r--r-- | kernel/fs/s5fs/s5fs.c | 93 |
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. |