lib/vfs: deduplicate symlink and single_file

Issue #1891
This commit is contained in:
Emery Hemingway 2016-06-27 10:47:23 +02:00 committed by Christian Helmuth
parent ddf3716cff
commit bae4ce5360
2 changed files with 27 additions and 109 deletions

View File

@ -24,7 +24,10 @@ class Vfs::Single_file_system : public File_system
{ {
public: public:
enum Node_type { NODE_TYPE_FILE, NODE_TYPE_CHAR_DEVICE, NODE_TYPE_BLOCK_DEVICE }; enum Node_type {
NODE_TYPE_FILE, NODE_TYPE_SYMLINK,
NODE_TYPE_CHAR_DEVICE, NODE_TYPE_BLOCK_DEVICE
};
private: private:
@ -33,6 +36,8 @@ class Vfs::Single_file_system : public File_system
enum { FILENAME_MAX_LEN = 64 }; enum { FILENAME_MAX_LEN = 64 };
char _filename[FILENAME_MAX_LEN]; char _filename[FILENAME_MAX_LEN];
protected:
bool _root(const char *path) bool _root(const char *path)
{ {
return (strcmp(path, "") == 0) || (strcmp(path, "/") == 0); return (strcmp(path, "") == 0) || (strcmp(path, "/") == 0);
@ -79,6 +84,7 @@ class Vfs::Single_file_system : public File_system
} else if (_single_file(path)) { } else if (_single_file(path)) {
switch (_node_type) { switch (_node_type) {
case NODE_TYPE_FILE: out.mode = STAT_MODE_FILE; break; case NODE_TYPE_FILE: out.mode = STAT_MODE_FILE; break;
case NODE_TYPE_SYMLINK: out.mode = STAT_MODE_SYMLINK; break;
case NODE_TYPE_CHAR_DEVICE: out.mode = STAT_MODE_CHARDEV; break; case NODE_TYPE_CHAR_DEVICE: out.mode = STAT_MODE_CHARDEV; break;
case NODE_TYPE_BLOCK_DEVICE: out.mode = STAT_MODE_BLOCKDEV; break; case NODE_TYPE_BLOCK_DEVICE: out.mode = STAT_MODE_BLOCKDEV; break;
} }
@ -98,6 +104,7 @@ class Vfs::Single_file_system : public File_system
out.fileno = (Genode::addr_t)this; out.fileno = (Genode::addr_t)this;
switch (_node_type) { switch (_node_type) {
case NODE_TYPE_FILE: out.type = DIRENT_TYPE_FILE; break; case NODE_TYPE_FILE: out.type = DIRENT_TYPE_FILE; break;
case NODE_TYPE_SYMLINK: out.type = DIRENT_TYPE_SYMLINK; break;
case NODE_TYPE_CHAR_DEVICE: out.type = DIRENT_TYPE_CHARDEV; break; case NODE_TYPE_CHAR_DEVICE: out.type = DIRENT_TYPE_CHARDEV; break;
case NODE_TYPE_BLOCK_DEVICE: out.type = DIRENT_TYPE_BLOCKDEV; break; case NODE_TYPE_BLOCK_DEVICE: out.type = DIRENT_TYPE_BLOCKDEV; break;
} }

View File

@ -15,42 +15,29 @@
#ifndef _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ #ifndef _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_
#define _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ #define _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_
#include <vfs/file_system.h> #include <vfs/single_file_system.h>
namespace Vfs { class Symlink_file_system; } namespace Vfs { class Symlink_file_system; }
class Vfs::Symlink_file_system : public File_system class Vfs::Symlink_file_system : public Single_file_system
{ {
private: private:
enum { FILENAME_MAX_LEN = 64 }; enum { FILENAME_MAX_LEN = 64 };
typedef Genode::String<MAX_PATH_LEN> Target;
char _target[MAX_PATH_LEN]; Target const _target;
char _filename[FILENAME_MAX_LEN];
bool _root(const char *path)
{
return (strcmp(path, "") == 0) || (strcmp(path, "/") == 0);
}
bool _single_file(const char *path)
{
return (strlen(path) == (strlen(_filename) + 1)) &&
(strcmp(&path[1], _filename) == 0);
}
public: public:
Symlink_file_system(Genode::Env&, Symlink_file_system(Genode::Env&,
Genode::Allocator&, Genode::Allocator&,
Genode::Xml_node config) Genode::Xml_node config)
{ :
try { Single_file_system(NODE_TYPE_SYMLINK, "symlink", config),
config.attribute("name").value(_filename, sizeof(_filename)); _target(config.attribute_value("target", Target()))
config.attribute("target").value(_target, sizeof(_target)); { }
} catch (...) { }
}
static char const *name() { return "symlink"; } static char const *name() { return "symlink"; }
@ -64,114 +51,38 @@ class Vfs::Symlink_file_system : public File_system
Readlink_result readlink(char const *path, Readlink_result readlink(char const *path,
char *buf, char *buf,
file_size buf_size, file_size buf_len,
file_size &out_len) override file_size &out_len) override
{ {
if (!_single_file(path)) if (!_single_file(path))
return READLINK_ERR_NO_ENTRY; return READLINK_ERR_NO_ENTRY;
out_len = min(buf_size, file_size(sizeof(_target))); out_len = min(buf_len, (file_size)_target.length()-1);
strncpy(buf, _target, out_len); memcpy(buf, _target.string(), out_len);
if (out_len < buf_len)
buf[out_len] = '\0';
return READLINK_OK; return READLINK_OK;
} }
Stat_result stat(char const *path, Stat &out) override
{
out = Stat();
out.device = (Genode::addr_t)this;
if (_root(path)) {
out.mode = STAT_MODE_DIRECTORY;
} else if (_single_file(path)) {
out.mode = STAT_MODE_SYMLINK;
out.inode = 1;
} else {
return STAT_ERR_NO_ENTRY;
}
return STAT_OK;
}
file_size num_dirent(char const *path) override
{
if (_root(path))
return 1;
else
return 0;
}
bool directory(char const *path) override
{
if (_root(path))
return true;
return false;
}
char const *leaf_path(char const *path) override
{
return _single_file(path) ? path : 0;
}
Dirent_result dirent(char const *path, file_offset index, Dirent &out) override
{
if (!_root(path))
return DIRENT_ERR_INVALID_PATH;
if (index == 0) {
out.fileno = (Genode::addr_t)this;
out.type = DIRENT_TYPE_SYMLINK;
strncpy(out.name, _filename, sizeof(out.name));
} else {
out.type = DIRENT_TYPE_END;
}
return DIRENT_OK;
}
Dataspace_capability dataspace(char const *path) override {
return Dataspace_capability(); }
void release(char const *path, Dataspace_capability ds_cap) override { }
Open_result open(char const *, unsigned, Vfs_handle **out_handle, Open_result open(char const *, unsigned, Vfs_handle **out_handle,
Allocator&) override { Allocator&) override {
return OPEN_ERR_UNACCESSIBLE; } return OPEN_ERR_UNACCESSIBLE; }
void close(Vfs_handle *) override { } void close(Vfs_handle *) override { }
Unlink_result unlink(char const *) override {
return UNLINK_ERR_NO_PERM; }
Rename_result rename(char const *from, char const *to) override
{
if (_single_file(from) || _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; }
/******************************** /********************************
** File I/O service interface ** ** File I/O service interface **
********************************/ ********************************/
Write_result write(Vfs_handle *handle, char const *, file_size, Write_result write(Vfs_handle *handle, char const *, file_size,
file_size &) override file_size &) override {
{ return WRITE_ERR_INVALID; }
return WRITE_ERR_INVALID;
}
Read_result read(Vfs_handle *, char *, file_size, file_size &) override Read_result read(Vfs_handle *, char *, file_size, file_size &) override {
{ return READ_ERR_INVALID; }
return READ_ERR_INVALID;
}
Ftruncate_result ftruncate(Vfs_handle *, file_size) override
{
return FTRUNCATE_ERR_NO_PERM;
}
Ftruncate_result ftruncate(Vfs_handle *, file_size) override {
return FTRUNCATE_ERR_NO_PERM; }
}; };
#endif /* _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ */ #endif /* _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ */