mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-10 22:44:30 +00:00
libc, vfs: rename improvements
Perform POSIX rename checks at the libc VFS plugin. Clarify rename at VFS fs, ram, single, and tar file systems. Issue #1900 Fixes #1782
This commit is contained in:
parent
d0735b1734
commit
23c1d4c66d
@ -775,6 +775,24 @@ int Libc::Vfs_plugin::rename(char const *from_path, char const *to_path)
|
||||
{
|
||||
typedef Vfs::Directory_service::Rename_result Result;
|
||||
|
||||
if (_root_dir.leaf_path(to_path)) {
|
||||
|
||||
if (_root_dir.is_directory(to_path)) {
|
||||
if (!_root_dir.is_directory(from_path)) {
|
||||
errno = EISDIR; return -1;
|
||||
}
|
||||
|
||||
if (_root_dir.num_dirent(to_path)) {
|
||||
errno = ENOTEMPTY; return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (_root_dir.is_directory(from_path)) {
|
||||
errno = ENOTDIR; return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (_root_dir.rename(from_path, to_path)) {
|
||||
case Result::RENAME_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
||||
case Result::RENAME_ERR_CROSS_FS: errno = EXDEV; return -1;
|
||||
|
@ -387,6 +387,9 @@ class Vfs::Fs_file_system : public File_system
|
||||
|
||||
Rename_result rename(char const *from_path, char const *to_path) override
|
||||
{
|
||||
if ((strcmp(from_path, to_path) == 0) && leaf_path(from_path))
|
||||
return RENAME_OK;
|
||||
|
||||
Absolute_path from_dir_path(from_path);
|
||||
from_dir_path.strip_last_element();
|
||||
from_dir_path.remove_trailing('/');
|
||||
|
@ -353,7 +353,7 @@ class Vfs::Ram_file_system : public Vfs::File_system
|
||||
Directory *dir = &_root;
|
||||
|
||||
char *name = &buf[0];
|
||||
for (size_t i = 0; i < MAX_NAME_LEN; ++i) {
|
||||
for (size_t i = 0; i < MAX_PATH_LEN; ++i) {
|
||||
if (buf[i] == '/') {
|
||||
buf[i] = '\0';
|
||||
|
||||
@ -498,6 +498,7 @@ class Vfs::Ram_file_system : public Vfs::File_system
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
/* this should never happen */
|
||||
return STAT_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
@ -575,6 +576,9 @@ class Vfs::Ram_file_system : public Vfs::File_system
|
||||
{
|
||||
using namespace Vfs_ram;
|
||||
|
||||
if ((strcmp(from, to) == 0) && lookup(from))
|
||||
return RENAME_OK;
|
||||
|
||||
char const *new_name = basename(to);
|
||||
if (strlen(new_name) >= MAX_NAME_LEN)
|
||||
return RENAME_ERR_NO_PERM;
|
||||
@ -586,28 +590,32 @@ class Vfs::Ram_file_system : public Vfs::File_system
|
||||
Directory *to_dir = lookup_parent(to);
|
||||
if (!to_dir) return RENAME_ERR_NO_ENTRY;
|
||||
|
||||
if (from_dir == to_dir) {
|
||||
/* unlock the node so a second guard can be constructed */
|
||||
if (from_dir == to_dir)
|
||||
from_dir->unlock();
|
||||
|
||||
Node *node = from_dir->child(basename(from));
|
||||
if (!node) return RENAME_ERR_NO_ENTRY;
|
||||
Node::Guard guard(node);
|
||||
Node::Guard to_guard(to_dir);
|
||||
|
||||
if (from_dir->child(new_name)) return RENAME_ERR_NO_PERM;
|
||||
node->name(new_name);
|
||||
Node *from_node = from_dir->child(basename(from));
|
||||
if (!from_node) return RENAME_ERR_NO_ENTRY;
|
||||
Node::Guard guard(from_node);
|
||||
|
||||
} else {
|
||||
Node *to_node = to_dir->child(new_name);
|
||||
if (to_node) {
|
||||
to_node->lock();
|
||||
|
||||
Node::Guard toguard(to_dir);
|
||||
if (Directory *dir = dynamic_cast<Directory*>(to_node))
|
||||
if (dir->length() || (!dynamic_cast<Directory*>(from_node)))
|
||||
return RENAME_ERR_NO_PERM;
|
||||
|
||||
if (to_dir->child(new_name)) return RENAME_ERR_NO_PERM;
|
||||
|
||||
Node *node = from_dir->child(basename(from));
|
||||
if (!node) return RENAME_ERR_NO_ENTRY;
|
||||
|
||||
node->name(new_name);
|
||||
to_dir->adopt(node);
|
||||
from_dir->release(node);
|
||||
to_dir->release(to_node);
|
||||
destroy(_alloc, to_node);
|
||||
}
|
||||
|
||||
from_dir->release(from_node);
|
||||
from_node->name(new_name);
|
||||
to_dir->adopt(from_node);
|
||||
|
||||
return RENAME_OK;
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ class Vfs::Single_file_system : public File_system
|
||||
|
||||
char const *leaf_path(char const *path) override
|
||||
{
|
||||
return path;
|
||||
return _is_single_file(path) ? path : 0;
|
||||
}
|
||||
|
||||
Open_result open(char const *path, unsigned,
|
||||
@ -148,9 +148,11 @@ class Vfs::Single_file_system : public File_system
|
||||
return READLINK_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
Rename_result rename(char const *, char const *) override
|
||||
Rename_result rename(char const *from, char const *to) override
|
||||
{
|
||||
return RENAME_ERR_NO_PERM;
|
||||
if (_is_single_file(from) || _is_single_file(to))
|
||||
return RENAME_ERR_NO_PERM;
|
||||
return RENAME_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
Mkdir_result mkdir(char const *, unsigned) override
|
||||
|
@ -138,8 +138,12 @@ class Vfs::Symlink_file_system : public File_system
|
||||
Unlink_result unlink(char const *) override {
|
||||
return UNLINK_ERR_NO_PERM; }
|
||||
|
||||
Rename_result rename(char const *, char const *) override {
|
||||
return RENAME_ERR_NO_PERM; }
|
||||
Rename_result rename(char const *from, char const *to) override
|
||||
{
|
||||
if (_is_single_file(from) || _is_single_file(to))
|
||||
return RENAME_ERR_NO_PERM;
|
||||
return RENAME_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
Mkdir_result mkdir(char const *, unsigned) override {
|
||||
return MKDIR_ERR_NO_PERM; }
|
||||
|
@ -528,9 +528,11 @@ class Vfs::Tar_file_system : public File_system
|
||||
return READLINK_OK;
|
||||
}
|
||||
|
||||
Rename_result rename(char const *, char const *) override
|
||||
Rename_result rename(char const *from, char const *to) override
|
||||
{
|
||||
return RENAME_ERR_NO_PERM;
|
||||
if (_root_node.lookup(from) || _root_node.lookup(to))
|
||||
return RENAME_ERR_NO_PERM;
|
||||
return RENAME_ERR_NO_ENTRY;
|
||||
}
|
||||
|
||||
Mkdir_result mkdir(char const *, unsigned) override
|
||||
|
Loading…
x
Reference in New Issue
Block a user