file system: enhanced file status info
This patch extends the 'File_system::Status', 'File_system::Directory_entry', and the related 'Vfs' types with the following additional information: - Distinction between continuous and transactional files (Node_type) (issue #3507) - Readable, writeable, and executable attributes (Node_rwx), replacing the former 'mode' bits (issue #3030) The types 'Node_rwx', 'Node_type' are defined twice, once for the VFS (vfs/types.h) and once for the 'File_system' session (file_system_session/file_system_session.h). Similarly, there is a direct correspondance between 'Vfs::Directory_service::Dirent' and 'File_system::Directory_entry'. This duplication of types follows the existing pattern of keeping the VFS and file-system session independent from each other.
This commit is contained in:
parent
1297a8fb57
commit
5ab1505d43
|
@ -1107,11 +1107,7 @@ class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir
|
|||
|
||||
Vfs::file_size index = seek_offset / sizeof(Dirent);
|
||||
|
||||
Dirent *out = (Dirent*)dst;
|
||||
|
||||
out->fileno = index+1;
|
||||
out->type = Directory_service::DIRENT_TYPE_END;
|
||||
out->name[0] = '\0';
|
||||
Dirent &out = *(Dirent*)dst;
|
||||
|
||||
Vfs::Node *node = nullptr;
|
||||
for (Vfs::File *n : _files) {
|
||||
|
@ -1123,11 +1119,21 @@ class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir
|
|||
--index;
|
||||
}
|
||||
}
|
||||
if (!node) return -1;
|
||||
if (!node) {
|
||||
out = {
|
||||
.fileno = index + 1,
|
||||
.type = Directory_service::Dirent_type::END,
|
||||
.rwx = { },
|
||||
.name = { } };
|
||||
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(out->name, node->name(), sizeof(out->name));
|
||||
out = {
|
||||
.fileno = index + 1,
|
||||
.type = Directory_service::Dirent_type::TRANSACTIONAL_FILE,
|
||||
.rwx = Node_rwx::rw(),
|
||||
.name = { node->name() } };
|
||||
|
||||
return sizeof(Dirent);
|
||||
}
|
||||
|
@ -1435,11 +1441,7 @@ class Lxip::Protocol_dir_impl : public Protocol_dir
|
|||
|
||||
Vfs::file_size index = seek_offset / sizeof(Dirent);
|
||||
|
||||
Dirent *out = (Dirent*)dst;
|
||||
|
||||
out->fileno = index+1;
|
||||
out->type = Vfs::Directory_service::DIRENT_TYPE_END;
|
||||
out->name[0] = '\0';
|
||||
Dirent &out = *(Dirent*)dst;
|
||||
|
||||
Vfs::Node *node = nullptr;
|
||||
for (Vfs::Node *n : _nodes) {
|
||||
|
@ -1451,15 +1453,32 @@ class Lxip::Protocol_dir_impl : public Protocol_dir
|
|||
--index;
|
||||
}
|
||||
}
|
||||
if (!node) return -1;
|
||||
if (!node) {
|
||||
out = {
|
||||
.fileno = index + 1,
|
||||
.type = Vfs::Directory_service::Dirent_type::END,
|
||||
.rwx = { },
|
||||
.name = { } };
|
||||
|
||||
if (dynamic_cast<Vfs::Directory*>(node))
|
||||
out->type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dynamic_cast<Vfs::File*>(node))
|
||||
out->type = Vfs::Directory_service::DIRENT_TYPE_FILE;
|
||||
typedef Vfs::Directory_service::Dirent_type Dirent_type;
|
||||
|
||||
Genode::strncpy(out->name, node->name(), sizeof(out->name));
|
||||
Dirent_type const type =
|
||||
dynamic_cast<Vfs::Directory*>(node) ? Dirent_type::DIRECTORY :
|
||||
dynamic_cast<Vfs::File *>(node) ? Dirent_type::TRANSACTIONAL_FILE
|
||||
: Dirent_type::END;
|
||||
|
||||
Vfs::Node_rwx const rwx = (type == Dirent_type::DIRECTORY)
|
||||
? Vfs::Node_rwx::rwx()
|
||||
: Vfs::Node_rwx::rw();
|
||||
|
||||
out = {
|
||||
.fileno = index + 1,
|
||||
.type = type,
|
||||
.rwx = rwx,
|
||||
.name = { node->name() } };
|
||||
|
||||
return sizeof(Dirent);
|
||||
}
|
||||
|
@ -1692,44 +1711,38 @@ class Vfs::Lxip_file_system : public Vfs::File_system,
|
|||
if (len < sizeof(Dirent))
|
||||
return -1;
|
||||
|
||||
file_size index = seek_offset / sizeof(Dirent);
|
||||
file_size const index = seek_offset / sizeof(Dirent);
|
||||
|
||||
Dirent *out = (Dirent*)dst;
|
||||
struct Entry
|
||||
{
|
||||
void const *fileno;
|
||||
Dirent_type type;
|
||||
char const *name;
|
||||
};
|
||||
|
||||
if (index == 0) {
|
||||
out->fileno = (Genode::addr_t)&_tcp_dir;
|
||||
out->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
||||
Genode::strncpy(out->name, "tcp", sizeof(out->name));
|
||||
} else if (index == 1) {
|
||||
out->fileno = (Genode::addr_t)&_udp_dir;
|
||||
out->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
||||
Genode::strncpy(out->name, "udp", sizeof(out->name));
|
||||
} else if (index == 2) {
|
||||
out->fileno = (Genode::addr_t)&_address;
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(out->name, "address", sizeof(out->name));
|
||||
} else if (index == 3) {
|
||||
out->fileno = (Genode::addr_t)&_netmask;
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(out->name, "netmask", sizeof(out->name));
|
||||
} else if (index == 4) {
|
||||
out->fileno = (Genode::addr_t)&_gateway;
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(out->name, "gateway", sizeof(out->name));
|
||||
} else if (index == 5) {
|
||||
out->fileno = (Genode::addr_t)&_nameserver;
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(out->name, "nameserver", sizeof(out->name));
|
||||
} else if (index == 6) {
|
||||
out->fileno = (Genode::addr_t)&_link_state;
|
||||
out->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(out->name, "link_state", sizeof(out->name));
|
||||
} else {
|
||||
out->fileno = 0;
|
||||
out->type = Directory_service::DIRENT_TYPE_END;
|
||||
out->name[0] = '\0';
|
||||
}
|
||||
enum { NUM_ENTRIES = 8U };
|
||||
static Entry const entries[NUM_ENTRIES] = {
|
||||
{ &_tcp_dir, Dirent_type::DIRECTORY, "tcp" },
|
||||
{ &_udp_dir, Dirent_type::DIRECTORY, "udp" },
|
||||
{ &_address, Dirent_type::TRANSACTIONAL_FILE, "address" },
|
||||
{ &_netmask, Dirent_type::TRANSACTIONAL_FILE, "netmask" },
|
||||
{ &_gateway, Dirent_type::TRANSACTIONAL_FILE, "gateway" },
|
||||
{ &_nameserver, Dirent_type::TRANSACTIONAL_FILE, "nameserver" },
|
||||
{ &_link_state, Dirent_type::TRANSACTIONAL_FILE, "link_state" },
|
||||
{ nullptr, Dirent_type::END, "" }
|
||||
};
|
||||
|
||||
Entry const &entry = entries[min(index, NUM_ENTRIES - 1U)];
|
||||
|
||||
Dirent &out = *(Dirent*)dst;
|
||||
|
||||
out = {
|
||||
.fileno = (Genode::addr_t)entry.fileno,
|
||||
.type = entry.type,
|
||||
.rwx = entry.type == Dirent_type::DIRECTORY
|
||||
? Node_rwx::rwx() : Node_rwx::rw(),
|
||||
.name = { entry.name }
|
||||
};
|
||||
return sizeof(Dirent);
|
||||
}
|
||||
|
||||
|
@ -1746,23 +1759,27 @@ class Vfs::Lxip_file_system : public Vfs::File_system,
|
|||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Vfs::Node *node = _lookup(path);
|
||||
Node *node = _lookup(path);
|
||||
if (!node) return STAT_ERR_NO_ENTRY;
|
||||
|
||||
Vfs::Directory *dir = dynamic_cast<Vfs::Directory*>(node);
|
||||
if (dir) {
|
||||
out.mode = STAT_MODE_DIRECTORY | 0777;
|
||||
out = { };
|
||||
|
||||
if (dynamic_cast<Vfs::Directory*>(node)) {
|
||||
out.type = Node_type::DIRECTORY;
|
||||
out.rwx = Node_rwx::rwx();
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
if (dynamic_cast<Lxip_file*>(node)) {
|
||||
out.mode = STAT_MODE_FILE | 0666;
|
||||
out.type = Node_type::TRANSACTIONAL_FILE;
|
||||
out.rwx = Node_rwx::rw();
|
||||
out.size = 0;
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
if (dynamic_cast<Vfs::File*>(node)) {
|
||||
out.mode = STAT_MODE_FILE | 0666;
|
||||
out.type = Node_type::TRANSACTIONAL_FILE;
|
||||
out.rwx = Node_rwx::rw();
|
||||
out.size = 0x1000; /* there may be something to read */
|
||||
return STAT_OK;
|
||||
}
|
||||
|
|
|
@ -197,25 +197,28 @@ class Vfs::Rump_file_system : public File_system
|
|||
struct stat s;
|
||||
rump_sys_lstat(path, &s);
|
||||
|
||||
vfs_dir.fileno = s.st_ino;
|
||||
auto dirent_type = [] (unsigned mode)
|
||||
{
|
||||
if (S_ISREG (mode)) return Dirent_type::CONTINUOUS_FILE;
|
||||
if (S_ISDIR (mode)) return Dirent_type::DIRECTORY;
|
||||
if (S_ISLNK (mode)) return Dirent_type::SYMLINK;
|
||||
if (S_ISBLK (mode)) return Dirent_type::CONTINUOUS_FILE;
|
||||
if (S_ISCHR (mode)) return Dirent_type::CONTINUOUS_FILE;
|
||||
if (S_ISFIFO(mode)) return Dirent_type::CONTINUOUS_FILE;
|
||||
|
||||
if (S_ISREG(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE;
|
||||
else if (S_ISDIR(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_DIRECTORY;
|
||||
else if (S_ISLNK(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_SYMLINK;
|
||||
else if (S_ISBLK(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_BLOCKDEV;
|
||||
else if (S_ISCHR(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_CHARDEV;
|
||||
else if (S_ISFIFO(s.st_mode))
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_FIFO;
|
||||
else
|
||||
vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE;
|
||||
return Dirent_type::END;
|
||||
};
|
||||
|
||||
strncpy(vfs_dir.name, dent->d_name, sizeof(Dirent::name));
|
||||
Node_rwx const rwx { .readable = (s.st_mode & S_IRUSR),
|
||||
.writeable = (s.st_mode & S_IWUSR),
|
||||
.executable = (s.st_mode & S_IXUSR) };
|
||||
|
||||
vfs_dir = {
|
||||
.fileno = s.st_ino,
|
||||
.type = dirent_type(s.st_mode),
|
||||
.rwx = rwx,
|
||||
.name = { dent->d_name }
|
||||
};
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
|
@ -699,12 +702,25 @@ class Vfs::Rump_file_system : public File_system
|
|||
struct stat sb;
|
||||
if (rump_sys_lstat(path, &sb) != 0) return STAT_ERR_NO_ENTRY;
|
||||
|
||||
stat.size = sb.st_size;
|
||||
stat.mode = sb.st_mode;
|
||||
stat.uid = sb.st_uid;
|
||||
stat.gid = sb.st_gid;
|
||||
stat.inode = sb.st_ino;
|
||||
stat.device = sb.st_dev;
|
||||
auto type = [] (unsigned mode)
|
||||
{
|
||||
if (S_ISDIR(mode)) return Node_type::DIRECTORY;
|
||||
if (S_ISLNK(mode)) return Node_type::SYMLINK;
|
||||
|
||||
return Node_type::CONTINUOUS_FILE;
|
||||
};
|
||||
|
||||
stat = {
|
||||
.size = (file_size)sb.st_size,
|
||||
.type = type(sb.st_mode),
|
||||
.rwx = { .readable = (sb.st_mode & S_IRUSR),
|
||||
.writeable = (sb.st_mode & S_IWUSR),
|
||||
.executable = (sb.st_mode & S_IXUSR) },
|
||||
.inode = sb.st_ino,
|
||||
.device = sb.st_dev,
|
||||
|
||||
.modification_time = { 0 }
|
||||
};
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
|
|
@ -218,18 +218,26 @@ class Rump_fs::Directory : public Node
|
|||
struct stat s;
|
||||
rump_sys_lstat(path, &s);
|
||||
|
||||
Directory_entry *e = (Directory_entry *)(dst);
|
||||
if (S_ISDIR(s.st_mode))
|
||||
e->type = Directory_entry::TYPE_DIRECTORY;
|
||||
else if (S_ISREG(s.st_mode))
|
||||
e->type = Directory_entry::TYPE_FILE;
|
||||
else if (S_ISLNK(s.st_mode))
|
||||
e->type = Directory_entry::TYPE_SYMLINK;
|
||||
else
|
||||
return 0;
|
||||
auto type = [] (unsigned mode)
|
||||
{
|
||||
if (S_ISDIR(mode)) return Node_type::DIRECTORY;
|
||||
else if (S_ISREG(mode)) return Node_type::CONTINUOUS_FILE;
|
||||
else if (S_ISLNK(mode)) return Node_type::SYMLINK;
|
||||
else return Node_type::CONTINUOUS_FILE;
|
||||
};
|
||||
|
||||
Node_rwx const rwx { .readable = (s.st_mode & S_IRUSR),
|
||||
.writeable = (s.st_mode & S_IWUSR),
|
||||
.executable = (s.st_mode & S_IXUSR) };
|
||||
|
||||
Directory_entry &e = *(Directory_entry *)(dst);
|
||||
e = {
|
||||
.inode = s.st_ino,
|
||||
.type = type(s.st_mode),
|
||||
.rwx = rwx,
|
||||
.name = { dent->d_name }
|
||||
};
|
||||
|
||||
e->inode = s.st_ino;
|
||||
strncpy(e->name, dent->d_name, dent->d_namlen + 1);
|
||||
return sizeof(Directory_entry);
|
||||
}
|
||||
|
||||
|
@ -245,13 +253,15 @@ class Rump_fs::Directory : public Node
|
|||
if (rump_sys_fstat(_fd, &st) < 0)
|
||||
st.st_mtime = 0;
|
||||
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = num_entries() * sizeof (Directory_entry);
|
||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
||||
s.modification_time = { (int64_t)st.st_mtime };
|
||||
|
||||
return s;
|
||||
return {
|
||||
.size = num_entries() * sizeof (Directory_entry),
|
||||
.type = File_system::Node_type::DIRECTORY,
|
||||
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||
.writeable = (st.st_mode & S_IWUSR),
|
||||
.executable = (st.st_mode & S_IXUSR) },
|
||||
.inode = inode(),
|
||||
.modification_time = { (int64_t)st.st_mtime }
|
||||
};
|
||||
}
|
||||
|
||||
size_t num_entries() const
|
||||
|
|
|
@ -153,20 +153,21 @@ class Rump_fs::File : public Node
|
|||
|
||||
virtual Status status() override
|
||||
{
|
||||
struct stat st;
|
||||
struct stat st { };
|
||||
if (rump_sys_fstat(_fd, &st) < 0) {
|
||||
st.st_size = 0;
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
Status s;
|
||||
|
||||
s.inode = inode();
|
||||
s.size = st.st_size;
|
||||
s.mode = File_system::Status::MODE_FILE;
|
||||
s.modification_time = { (int64_t)st.st_mtime };
|
||||
|
||||
return s;
|
||||
return {
|
||||
.size = (file_size_t)st.st_size,
|
||||
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||
.writeable = (st.st_mode & S_IWUSR),
|
||||
.executable = (st.st_mode & S_IXUSR) },
|
||||
.inode = inode(),
|
||||
.modification_time = { (int64_t)st.st_mtime }
|
||||
};
|
||||
}
|
||||
|
||||
void truncate(file_size_t size) override
|
||||
|
|
|
@ -78,13 +78,15 @@ class Rump_fs::Symlink : public Node
|
|||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = length();
|
||||
s.mode = File_system::Status::MODE_SYMLINK;
|
||||
s.modification_time = { (int64_t)st.st_mtime };
|
||||
|
||||
return s;
|
||||
return {
|
||||
.size = length(),
|
||||
.type = File_system::Node_type::SYMLINK,
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.inode = inode(),
|
||||
.modification_time = { (int64_t)st.st_mtime }
|
||||
};
|
||||
}
|
||||
|
||||
file_size_t length()
|
||||
|
|
|
@ -56,20 +56,22 @@ struct Genode::Directory : Noncopyable, Interface
|
|||
{
|
||||
using Genode::print;
|
||||
using Vfs::Directory_service;
|
||||
using Dirent_type = Directory_service::Dirent_type;
|
||||
|
||||
print(out, _dirent.name, " (");
|
||||
print(out, _dirent.name.buf, " (");
|
||||
switch (_dirent.type) {
|
||||
case Directory_service::DIRENT_TYPE_FILE: print(out, "file"); break;
|
||||
case Directory_service::DIRENT_TYPE_DIRECTORY: print(out, "dir"); break;
|
||||
case Directory_service::DIRENT_TYPE_SYMLINK: print(out, "symlink"); break;
|
||||
default: print(out, "other"); break;
|
||||
case Dirent_type::TRANSACTIONAL_FILE: print(out, "file"); break;
|
||||
case Dirent_type::CONTINUOUS_FILE: print(out, "file"); break;
|
||||
case Dirent_type::DIRECTORY: print(out, "dir"); break;
|
||||
case Dirent_type::SYMLINK: print(out, "symlink"); break;
|
||||
default: print(out, "other"); break;
|
||||
}
|
||||
print(out, ")");
|
||||
}
|
||||
|
||||
typedef String<Vfs::Directory_service::DIRENT_MAX_NAME_LEN> Name;
|
||||
typedef String<Vfs::Directory_service::Dirent::Name::MAX_LEN> Name;
|
||||
|
||||
Name name() const { return Name(Cstring(_dirent.name)); }
|
||||
Name name() const { return Name(Cstring(_dirent.name.buf)); }
|
||||
|
||||
Vfs::Directory_service::Dirent_type type() const { return _dirent.type; }
|
||||
};
|
||||
|
@ -118,16 +120,10 @@ struct Genode::Directory : Noncopyable, Interface
|
|||
return const_cast<Vfs::File_system &>(_fs);
|
||||
}
|
||||
|
||||
Vfs::Directory_service::Stat _stat(Path const &rel_path) const
|
||||
Vfs::Directory_service::Stat_result _stat(Path const &rel_path,
|
||||
Vfs::Directory_service::Stat &out) const
|
||||
{
|
||||
Vfs::Directory_service::Stat stat;
|
||||
|
||||
/*
|
||||
* Ignore return value as the validity of the result is can be
|
||||
* checked by the caller via 'stat.mode != 0'.
|
||||
*/
|
||||
_nonconst_fs().stat(join(_path, rel_path).string(), stat);
|
||||
return stat;
|
||||
return _nonconst_fs().stat(join(_path, rel_path).string(), out);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -199,7 +195,7 @@ struct Genode::Directory : Noncopyable, Interface
|
|||
throw Read_dir_failed();
|
||||
}
|
||||
|
||||
if (entry._dirent.type == Vfs::Directory_service::DIRENT_TYPE_END)
|
||||
if (entry._dirent.type == Vfs::Directory_service::Dirent_type::END)
|
||||
return;
|
||||
|
||||
fn(entry);
|
||||
|
@ -215,12 +211,23 @@ struct Genode::Directory : Noncopyable, Interface
|
|||
|
||||
bool file_exists(Path const &rel_path) const
|
||||
{
|
||||
return _stat(rel_path).mode & Vfs::Directory_service::STAT_MODE_FILE;
|
||||
Vfs::Directory_service::Stat stat { };
|
||||
|
||||
if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK)
|
||||
return false;
|
||||
|
||||
return stat.type == Vfs::Node_type::TRANSACTIONAL_FILE
|
||||
|| stat.type == Vfs::Node_type::CONTINUOUS_FILE;
|
||||
}
|
||||
|
||||
bool directory_exists(Path const &rel_path) const
|
||||
{
|
||||
return _stat(rel_path).mode & Vfs::Directory_service::STAT_MODE_DIRECTORY;
|
||||
Vfs::Directory_service::Stat stat { };
|
||||
|
||||
if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK)
|
||||
return false;
|
||||
|
||||
return stat.type == Vfs::Node_type::DIRECTORY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -232,11 +239,16 @@ struct Genode::Directory : Noncopyable, Interface
|
|||
*/
|
||||
Vfs::file_size file_size(Path const &rel_path) const
|
||||
{
|
||||
Vfs::Directory_service::Stat stat = _stat(rel_path);
|
||||
Vfs::Directory_service::Stat stat { };
|
||||
|
||||
if (!(stat.mode & Vfs::Directory_service::STAT_MODE_FILE))
|
||||
if (_stat(rel_path, stat) != Vfs::Directory_service::STAT_OK)
|
||||
throw Nonexistent_file();
|
||||
return stat.size;
|
||||
|
||||
if (stat.type == Vfs::Node_type::TRANSACTIONAL_FILE
|
||||
|| stat.type == Vfs::Node_type::CONTINUOUS_FILE)
|
||||
return stat.size;
|
||||
|
||||
throw Nonexistent_file();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,7 +104,11 @@ struct Fs_query::Watched_directory
|
|||
_dir(other, rel_path), _watcher(other, rel_path, handler)
|
||||
{
|
||||
_dir.for_each_entry([&] (Directory::Entry const &entry) {
|
||||
if (entry.type() == Vfs::Directory_service::DIRENT_TYPE_FILE) {
|
||||
|
||||
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||
bool const file = (entry.type() == Dirent_type::CONTINUOUS_FILE)
|
||||
|| (entry.type() == Dirent_type::TRANSACTIONAL_FILE);
|
||||
if (file) {
|
||||
try {
|
||||
new (_alloc) Registered<Watched_file>(_files, _dir, entry.name(), handler);
|
||||
} catch (...) { }
|
||||
|
|
|
@ -189,19 +189,20 @@ class Vfs_import::File_system : public Vfs::File_system
|
|||
dir.for_each_entry([&] (Directory::Entry const &e) {
|
||||
auto entry_path = Directory::join(path, e.name());
|
||||
switch (e.type()) {
|
||||
case DIRENT_TYPE_FILE:
|
||||
case Dirent_type::TRANSACTIONAL_FILE:
|
||||
case Dirent_type::CONTINUOUS_FILE:
|
||||
copy_file(env, src, entry_path, alloc, overwrite);
|
||||
break;
|
||||
case DIRENT_TYPE_DIRECTORY:
|
||||
return;
|
||||
case Dirent_type::DIRECTORY:
|
||||
copy_dir(env, src, entry_path, alloc, overwrite);
|
||||
break;
|
||||
case DIRENT_TYPE_SYMLINK:
|
||||
return;
|
||||
case Dirent_type::SYMLINK:
|
||||
copy_symlink(env, src, entry_path, alloc, overwrite);
|
||||
break;
|
||||
default:
|
||||
Genode::warning("skipping copy of ", e);
|
||||
break;
|
||||
return;
|
||||
case Dirent_type::END:
|
||||
return;
|
||||
}
|
||||
Genode::warning("skipping copy of ", e);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -128,8 +128,8 @@ class Vfs::Value_file_system : public Vfs::Single_file_system
|
|||
|
||||
Value_file_system(Name const &name, Buffer const &initial_value)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, type(),
|
||||
Xml_node(_config(name).string())),
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type(),
|
||||
Node_rwx::rw(), Xml_node(_config(name).string())),
|
||||
_file_name(name)
|
||||
{
|
||||
value(initial_value);
|
||||
|
@ -196,7 +196,6 @@ class Vfs::Value_file_system : public Vfs::Single_file_system
|
|||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Stat_result result = Single_file_system::stat(path, out);
|
||||
out.mode |= 0666;
|
||||
out.size = BUF_SIZE + 1;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -155,8 +155,8 @@ class Vfs_trace::Trace_buffer_file_system : public Single_file_system
|
|||
Trace::Connection &trace,
|
||||
Trace::Policy_id policy,
|
||||
Trace::Subject_id id)
|
||||
: Single_file_system(NODE_TYPE_CHAR_DEVICE,
|
||||
type_name(), Xml_node(_config().string())),
|
||||
: Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node(_config().string())),
|
||||
_env(env), _trace(trace), _policy(policy), _id(id)
|
||||
{ }
|
||||
|
||||
|
|
|
@ -113,7 +113,8 @@ class Vfs::Glyphs_file_system : public Vfs::Single_file_system
|
|||
|
||||
Glyphs_file_system(Font const &font)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, type(), Xml_node("<glyphs/>")),
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type(),
|
||||
Node_rwx::ro(), Xml_node("<glyphs/>")),
|
||||
_font(font)
|
||||
{ }
|
||||
|
||||
|
@ -145,7 +146,6 @@ class Vfs::Glyphs_file_system : public Vfs::Single_file_system
|
|||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Stat_result result = Single_file_system::stat(path, out);
|
||||
out.mode |= 0444;
|
||||
out.size = FILE_SIZE;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -98,11 +98,29 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src
|
|||
{
|
||||
enum { FS_BLOCK_SIZE = 4096 };
|
||||
|
||||
Genode::memset(dst, 0, sizeof(*dst));
|
||||
unsigned const readable_bits = S_IRUSR,
|
||||
writeable_bits = S_IWUSR,
|
||||
executable_bits = S_IXUSR;
|
||||
|
||||
dst->st_uid = src.uid;
|
||||
dst->st_gid = src.gid;
|
||||
dst->st_mode = src.mode;
|
||||
auto type = [] (Vfs::Node_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Vfs::Node_type::DIRECTORY: return S_IFDIR;
|
||||
case Vfs::Node_type::CONTINUOUS_FILE: return S_IFREG;
|
||||
case Vfs::Node_type::TRANSACTIONAL_FILE: return S_IFSOCK;
|
||||
case Vfs::Node_type::SYMLINK: return S_IFLNK;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
*dst = { };
|
||||
|
||||
dst->st_uid = 0;
|
||||
dst->st_gid = 0;
|
||||
dst->st_mode = (src.rwx.readable ? readable_bits : 0)
|
||||
| (src.rwx.writeable ? writeable_bits : 0)
|
||||
| (src.rwx.executable ? executable_bits : 0)
|
||||
| type(src.type);
|
||||
dst->st_size = src.size;
|
||||
dst->st_blksize = FS_BLOCK_SIZE;
|
||||
dst->st_blocks = (dst->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
|
||||
|
@ -525,7 +543,18 @@ int Libc::Vfs_plugin::fstat(File_descriptor *fd, struct stat *buf)
|
|||
_vfs_sync(*handle);
|
||||
fd->modified = false;
|
||||
}
|
||||
return stat(fd->fd_path, buf);
|
||||
|
||||
int const result = stat(fd->fd_path, buf);
|
||||
|
||||
/*
|
||||
* The libc expects stdout to be a character device.
|
||||
* If 'st_mode' is set to 'S_IFREG', 'printf' does not work.
|
||||
*/
|
||||
if (fd->libc_fd == 1) {
|
||||
buf->st_mode &= ~S_IFMT;
|
||||
buf->st_mode |= S_IFCHR;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -830,6 +859,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(File_descriptor *fd, char *buf,
|
|||
(char*)&dirent_out,
|
||||
sizeof(Dirent),
|
||||
out_count));
|
||||
dirent_out.sanitize();
|
||||
|
||||
/* suspend me if read is still queued */
|
||||
|
||||
|
@ -851,29 +881,37 @@ ssize_t Libc::Vfs_plugin::getdirentries(File_descriptor *fd, char *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||
|
||||
if (dirent_out.type == Dirent_type::END)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Convert dirent structure from VFS to libc
|
||||
*/
|
||||
|
||||
struct dirent *dirent = (struct dirent *)buf;
|
||||
Genode::memset(dirent, 0, sizeof(struct dirent));
|
||||
auto dirent_type = [] (Dirent_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Dirent_type::DIRECTORY: return DT_DIR;
|
||||
case Dirent_type::CONTINUOUS_FILE: return DT_REG;
|
||||
case Dirent_type::TRANSACTIONAL_FILE: return DT_SOCK;
|
||||
case Dirent_type::SYMLINK: return DT_LNK;
|
||||
case Dirent_type::END: return DT_UNKNOWN;
|
||||
}
|
||||
return DT_UNKNOWN;
|
||||
};
|
||||
|
||||
switch (dirent_out.type) {
|
||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_CHARDEV: dirent->d_type = DT_CHR; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_BLOCKDEV: dirent->d_type = DT_BLK; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_END: return 0;
|
||||
}
|
||||
dirent &dirent = *(struct dirent *)buf;
|
||||
dirent = { };
|
||||
|
||||
dirent->d_fileno = dirent_out.fileno;
|
||||
dirent->d_reclen = sizeof(struct dirent);
|
||||
dirent.d_type = dirent_type(dirent_out.type);
|
||||
dirent.d_fileno = dirent_out.fileno;
|
||||
dirent.d_reclen = sizeof(struct dirent);
|
||||
|
||||
Genode::strncpy(dirent->d_name, dirent_out.name, sizeof(dirent->d_name));
|
||||
Genode::strncpy(dirent.d_name, dirent_out.name.buf, sizeof(dirent.d_name));
|
||||
|
||||
dirent->d_namlen = Genode::strlen(dirent->d_name);
|
||||
dirent.d_namlen = Genode::strlen(dirent.d_name);
|
||||
|
||||
/*
|
||||
* Keep track of VFS seek pointer and user-supplied basep.
|
||||
|
|
|
@ -181,30 +181,39 @@ class Fatfs::File_system : public Vfs::File_system
|
|||
cur_index = 0;
|
||||
}
|
||||
|
||||
Dirent *vfs_dir = (Dirent*)buf;
|
||||
Dirent &vfs_dirent = *(Dirent*)buf;
|
||||
|
||||
FILINFO info;
|
||||
FRESULT res;
|
||||
vfs_dir->fileno = 1; /* inode 0 is a pending unlink */
|
||||
|
||||
unsigned const fileno = 1; /* inode 0 is a pending unlink */
|
||||
|
||||
while (cur_index <= dir_index) {
|
||||
res = f_readdir (&dir, &info);
|
||||
if ((res != FR_OK) || (!info.fname[0])) {
|
||||
f_readdir(&dir, nullptr);
|
||||
cur_index = 0;
|
||||
vfs_dir->type = DIRENT_TYPE_END;
|
||||
vfs_dir->name[0] = '\0';
|
||||
|
||||
vfs_dirent = {
|
||||
.fileno = fileno,
|
||||
.type = Dirent_type::END,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.name = { }
|
||||
};
|
||||
out_count = sizeof(Dirent);
|
||||
return READ_OK;
|
||||
}
|
||||
cur_index++;
|
||||
}
|
||||
|
||||
vfs_dir->type = (info.fattrib & AM_DIR) ?
|
||||
DIRENT_TYPE_DIRECTORY : DIRENT_TYPE_FILE;
|
||||
Genode::strncpy(vfs_dir->name, (const char*)info.fname,
|
||||
sizeof(vfs_dir->name));
|
||||
|
||||
vfs_dirent = {
|
||||
.fileno = fileno,
|
||||
.type = (info.fattrib & AM_DIR)
|
||||
? Dirent_type::DIRECTORY
|
||||
: Dirent_type::CONTINUOUS_FILE,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.name = { (char const *)info.fname }
|
||||
};
|
||||
out_count = sizeof(Dirent);
|
||||
return READ_OK;
|
||||
}
|
||||
|
@ -607,19 +616,22 @@ class Fatfs::File_system : public Vfs::File_system
|
|||
|
||||
Stat_result stat(char const *path, Stat &stat) override
|
||||
{
|
||||
stat = Stat();
|
||||
stat = Stat { };
|
||||
|
||||
FILINFO info;
|
||||
|
||||
FRESULT const err = f_stat((const TCHAR*)path, &info);
|
||||
switch (err) {
|
||||
case FR_OK:
|
||||
stat.inode = 1;
|
||||
stat.inode = 1;
|
||||
stat.device = (Genode::addr_t)this;
|
||||
stat.mode = (info.fattrib & AM_DIR) ?
|
||||
STAT_MODE_DIRECTORY : STAT_MODE_FILE;
|
||||
stat.type = (info.fattrib & AM_DIR)
|
||||
? Vfs::Node_type::DIRECTORY
|
||||
: Vfs::Node_type::CONTINUOUS_FILE;
|
||||
stat.rwx = Vfs::Node_rwx::rwx();
|
||||
|
||||
/* XXX: size in f_stat is always zero */
|
||||
if ((stat.mode == STAT_MODE_FILE) && (info.fsize == 0)) {
|
||||
if ((stat.type == Vfs::Node_type::CONTINUOUS_FILE) && (info.fsize == 0)) {
|
||||
File *file = _opened_file(path);
|
||||
if (file) {
|
||||
stat.size = f_size(&file->fil);
|
||||
|
|
|
@ -102,7 +102,8 @@ class Jitterentropy_file_system : public Vfs::Single_file_system
|
|||
Jitterentropy_file_system(Genode::Allocator &alloc,
|
||||
Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
|
||||
Single_file_system(Vfs::Node_type::CONTINUOUS_FILE, name(),
|
||||
Vfs::Node_rwx::ro(), config),
|
||||
_ec_stir(0),
|
||||
_initialized(_init_jitterentropy(alloc))
|
||||
{ }
|
||||
|
|
|
@ -603,35 +603,51 @@ class Lwip::Protocol_dir_impl final : public Protocol_dir
|
|||
Path subpath(path);
|
||||
|
||||
if (subpath == "/") {
|
||||
st.size = 1;
|
||||
st.mode = Directory_service::STAT_MODE_DIRECTORY;
|
||||
st.inode = (Genode::addr_t)this;
|
||||
st = { .size = 1,
|
||||
.type = Node_type::DIRECTORY,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.inode = (Genode::addr_t)this,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return Directory_service::STAT_OK;
|
||||
}
|
||||
|
||||
if (subpath == "/new_socket") {
|
||||
st.size = 1;
|
||||
st.mode = Directory_service::STAT_MODE_FILE | 0777;
|
||||
st.inode = ((Genode::addr_t)this)+1;
|
||||
st = { .size = 1,
|
||||
.type = Node_type::TRANSACTIONAL_FILE,
|
||||
.rwx = Node_rwx::rw(),
|
||||
.inode = (Genode::addr_t)this + 1,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return Directory_service::STAT_OK;
|
||||
}
|
||||
|
||||
if (!subpath.has_single_element())
|
||||
subpath.strip_last_element();
|
||||
|
||||
if (SOCKET_DIR *dir = lookup(subpath.string())) {
|
||||
Path filename(path);
|
||||
filename.keep_only_last_element();
|
||||
if (filename == subpath.base()) {
|
||||
st.size = Lwip_file_handle::INVALID;
|
||||
st.mode = Directory_service::STAT_MODE_DIRECTORY;
|
||||
st.inode = (Genode::addr_t)dir;
|
||||
st = { .size = 0,
|
||||
.type = Node_type::DIRECTORY,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.inode = (Genode::addr_t)dir,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return Directory_service::STAT_OK;
|
||||
}
|
||||
|
||||
Lwip_file_handle::Kind k = Lwip_file_handle::kind_from_name(filename);
|
||||
if (k != Lwip_file_handle::INVALID) {
|
||||
st.mode = Directory_service::STAT_MODE_CHARDEV;
|
||||
st.inode = ((Genode::addr_t)dir)+k;
|
||||
st = { .size = 0,
|
||||
.type = (filename == "/data")
|
||||
? Node_type::CONTINUOUS_FILE
|
||||
: Node_type::TRANSACTIONAL_FILE,
|
||||
.rwx = Node_rwx::rw(),
|
||||
.inode = (Genode::addr_t)dir + k,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return Directory_service::STAT_OK;
|
||||
}
|
||||
}
|
||||
|
@ -1795,18 +1811,26 @@ class Lwip::File_system final : public Vfs::File_system, public Lwip::Directory
|
|||
Stat_result stat(char const *path, Stat &st) override
|
||||
{
|
||||
if (*path == '/') ++path;
|
||||
st = Stat();
|
||||
st = Stat { };
|
||||
st.device = (Genode::addr_t)this;
|
||||
|
||||
if (match_address(path) || match_netmask(path)) {
|
||||
st.size = ADDRESS_FILE_SIZE;
|
||||
st.mode = STAT_MODE_FILE;
|
||||
st = { .size = ADDRESS_FILE_SIZE,
|
||||
.type = Node_type::TRANSACTIONAL_FILE,
|
||||
.rwx = Node_rwx::rw(),
|
||||
.inode = (Genode::addr_t)this,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
if (match_nameserver(path)) {
|
||||
st.size = IPADDR_STRLEN_MAX;
|
||||
st.mode = STAT_MODE_FILE;
|
||||
st = { .size = IPADDR_STRLEN_MAX,
|
||||
.type = Node_type::TRANSACTIONAL_FILE,
|
||||
.rwx = Node_rwx::rw(),
|
||||
.inode = 0,
|
||||
.device = 0,
|
||||
.modification_time = { 0 } };
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,8 +56,6 @@ class Fatfs_fs::Directory : public Node
|
|||
return 0;
|
||||
}
|
||||
|
||||
Directory_entry *e = (Directory_entry *)(dst);
|
||||
|
||||
using namespace Fatfs;
|
||||
|
||||
FILINFO fatfs_file_info;
|
||||
|
@ -99,12 +97,17 @@ class Fatfs_fs::Directory : public Node
|
|||
return 0;
|
||||
}
|
||||
|
||||
strncpy(e->name, fatfs_file_info.fname, sizeof(e->name));
|
||||
|
||||
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
|
||||
e->type = Directory_entry::TYPE_DIRECTORY;
|
||||
else
|
||||
e->type = Directory_entry::TYPE_FILE;
|
||||
Directory_entry &e = *(Directory_entry *)(dst);
|
||||
e = {
|
||||
.inode = 0,
|
||||
.type = ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
|
||||
? Node_type::DIRECTORY
|
||||
: Node_type::CONTINUOUS_FILE,
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.name = { fatfs_file_info.fname }
|
||||
};
|
||||
|
||||
return sizeof(Directory_entry);
|
||||
}
|
||||
|
|
|
@ -133,6 +133,10 @@ class Fatfs_fs::Session_component : public Session_rpc_object
|
|||
succeeded = true;
|
||||
/* not supported */
|
||||
break;
|
||||
|
||||
case Packet_descriptor::WRITE_TIMESTAMP:
|
||||
succeeded = false;
|
||||
break;
|
||||
}
|
||||
|
||||
packet.length(res_length);
|
||||
|
@ -537,8 +541,9 @@ class Fatfs_fs::Session_component : public Session_rpc_object
|
|||
Status status;
|
||||
status.inode = 1;
|
||||
status.size = 0;
|
||||
status.mode = 0;
|
||||
|
||||
status.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true };
|
||||
Node &node = open_node.node();
|
||||
|
||||
using namespace Fatfs;
|
||||
|
@ -587,17 +592,17 @@ class Fatfs_fs::Session_component : public Session_rpc_object
|
|||
}
|
||||
|
||||
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) {
|
||||
status.mode = File_system::Status::MODE_DIRECTORY; }
|
||||
status.type = File_system::Node_type::DIRECTORY; }
|
||||
else {
|
||||
status.mode = File_system::Status::MODE_FILE;
|
||||
status.type = File_system::Node_type::CONTINUOUS_FILE;
|
||||
status.size = fatfs_file_info.fsize;
|
||||
}
|
||||
|
||||
} else {
|
||||
status.mode = File_system::Status::MODE_DIRECTORY;
|
||||
status.type = File_system::Node_type::DIRECTORY;
|
||||
}
|
||||
|
||||
if (status.mode == File_system::Status::MODE_DIRECTORY) {
|
||||
if (status.type == File_system::Node_type::DIRECTORY) {
|
||||
|
||||
/* determine the number of directory entries */
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_
|
||||
#define _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_
|
||||
|
||||
#include <util/string.h>
|
||||
#include <base/exception.h>
|
||||
#include <os/packet_stream.h>
|
||||
#include <packet_stream_tx/packet_stream_tx.h>
|
||||
|
@ -66,6 +67,20 @@ namespace File_system {
|
|||
typedef Symlink::Id Symlink_handle;
|
||||
typedef Watch::Id Watch_handle;
|
||||
|
||||
enum class Node_type {
|
||||
DIRECTORY,
|
||||
SYMLINK,
|
||||
CONTINUOUS_FILE,
|
||||
TRANSACTIONAL_FILE
|
||||
};
|
||||
|
||||
struct Node_rwx
|
||||
{
|
||||
bool readable;
|
||||
bool writeable;
|
||||
bool executable;
|
||||
};
|
||||
|
||||
using Genode::size_t;
|
||||
|
||||
typedef Genode::uint64_t seek_off_t;
|
||||
|
@ -250,30 +265,21 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
|
|||
|
||||
struct File_system::Status
|
||||
{
|
||||
enum {
|
||||
MODE_SYMLINK = 0020000,
|
||||
MODE_FILE = 0100000,
|
||||
MODE_DIRECTORY = 0040000,
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX add executable bit
|
||||
*/
|
||||
|
||||
file_size_t size;
|
||||
unsigned mode;
|
||||
Node_type type;
|
||||
Node_rwx rwx;
|
||||
unsigned long inode;
|
||||
Timestamp modification_time;
|
||||
|
||||
/**
|
||||
* Return true if node is a directory
|
||||
*/
|
||||
bool directory() const { return mode & MODE_DIRECTORY; }
|
||||
bool directory() const { return type == Node_type::DIRECTORY; }
|
||||
|
||||
/**
|
||||
* Return true if node is a symbolic link
|
||||
*/
|
||||
bool symlink() const { return mode & MODE_SYMLINK; }
|
||||
bool symlink() const { return type == Node_type::SYMLINK; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -285,11 +291,27 @@ struct File_system::Control { /* to manipulate the executable bit */ };
|
|||
*/
|
||||
struct File_system::Directory_entry
|
||||
{
|
||||
enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK };
|
||||
struct Name
|
||||
{
|
||||
char buf[MAX_NAME_LEN] { };
|
||||
|
||||
Name() { };
|
||||
Name(char const *name) { Genode::strncpy(buf, name, sizeof(buf)); }
|
||||
};
|
||||
|
||||
unsigned long inode;
|
||||
Type type;
|
||||
char name[MAX_NAME_LEN];
|
||||
Node_type type;
|
||||
Node_rwx rwx;
|
||||
Name name;
|
||||
|
||||
/**
|
||||
* Sanitize object received from a file-system server as plain bytes
|
||||
*/
|
||||
void sanitize()
|
||||
{
|
||||
/* enforce null termination */
|
||||
name.buf[MAX_NAME_LEN - 1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -343,8 +343,8 @@ class Vfs::Dir_file_system : public File_system
|
|||
if (count < sizeof(Dirent))
|
||||
return READ_ERR_INVALID;
|
||||
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
*dirent = Dirent();
|
||||
Dirent &dirent = *(Dirent*)dst;
|
||||
dirent = Dirent { };
|
||||
|
||||
out_count = sizeof(Dirent);
|
||||
|
||||
|
@ -456,13 +456,14 @@ class Vfs::Dir_file_system : public File_system
|
|||
* current directory.
|
||||
*/
|
||||
if (strlen(path) == 0 || _top_dir(path)) {
|
||||
out.size = 0;
|
||||
out.mode = STAT_MODE_DIRECTORY | 0755;
|
||||
out.uid = 0;
|
||||
out.gid = 0;
|
||||
out.inode = 1;
|
||||
out.device = (Genode::addr_t)this;
|
||||
out.modification_time = { Vfs::Timestamp::INVALID };
|
||||
out = {
|
||||
.size = 0,
|
||||
.type = Node_type::DIRECTORY,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.inode = 1,
|
||||
.device = (Genode::addr_t)this,
|
||||
.modification_time = { Vfs::Timestamp::INVALID },
|
||||
};
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
@ -903,16 +904,28 @@ class Vfs::Dir_file_system : public File_system
|
|||
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
||||
|
||||
if (_top_dir(dir_vfs_handle->path.base())) {
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
file_offset index = vfs_handle->seek() / sizeof(Dirent);
|
||||
|
||||
Dirent &dirent = *(Dirent*)dst;
|
||||
|
||||
file_offset const index = vfs_handle->seek() / sizeof(Dirent);
|
||||
|
||||
if (index == 0) {
|
||||
strncpy(dirent->name, _name.string(), sizeof(dirent->name));
|
||||
|
||||
dirent->type = DIRENT_TYPE_DIRECTORY;
|
||||
dirent->fileno = 1;
|
||||
dirent = {
|
||||
.fileno = 1,
|
||||
.type = Dirent_type::DIRECTORY,
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.name = { _name.string() }
|
||||
};
|
||||
|
||||
} else {
|
||||
dirent->type = DIRENT_TYPE_END;
|
||||
|
||||
dirent = {
|
||||
.fileno = 0,
|
||||
.type = Dirent_type::END,
|
||||
.rwx = { },
|
||||
.name = { }
|
||||
};
|
||||
}
|
||||
|
||||
out_count = sizeof(Dirent);
|
||||
|
|
|
@ -141,26 +141,14 @@ struct Vfs::Directory_service : Interface
|
|||
** Stat **
|
||||
**********/
|
||||
|
||||
/**
|
||||
* These values are the same as in the FreeBSD libc
|
||||
*/
|
||||
enum {
|
||||
STAT_MODE_SYMLINK = 0120000,
|
||||
STAT_MODE_FILE = 0100000,
|
||||
STAT_MODE_DIRECTORY = 0040000,
|
||||
STAT_MODE_CHARDEV = 0020000,
|
||||
STAT_MODE_BLOCKDEV = 0060000,
|
||||
};
|
||||
|
||||
struct Stat
|
||||
{
|
||||
file_size size = 0;
|
||||
unsigned mode = 0;
|
||||
unsigned uid = 0;
|
||||
unsigned gid = 0;
|
||||
unsigned long inode = 0;
|
||||
unsigned long device = 0;
|
||||
Timestamp modification_time { Timestamp::INVALID };
|
||||
file_size size;
|
||||
Node_type type;
|
||||
Node_rwx rwx;
|
||||
unsigned long inode;
|
||||
unsigned long device;
|
||||
Timestamp modification_time;
|
||||
};
|
||||
|
||||
enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS,
|
||||
|
@ -177,23 +165,42 @@ struct Vfs::Directory_service : Interface
|
|||
** Dirent **
|
||||
************/
|
||||
|
||||
enum { DIRENT_MAX_NAME_LEN = 128 };
|
||||
|
||||
enum Dirent_type {
|
||||
DIRENT_TYPE_FILE,
|
||||
DIRENT_TYPE_DIRECTORY,
|
||||
DIRENT_TYPE_FIFO,
|
||||
DIRENT_TYPE_CHARDEV,
|
||||
DIRENT_TYPE_BLOCKDEV,
|
||||
DIRENT_TYPE_SYMLINK,
|
||||
DIRENT_TYPE_END
|
||||
enum class Dirent_type
|
||||
{
|
||||
END,
|
||||
DIRECTORY,
|
||||
SYMLINK,
|
||||
CONTINUOUS_FILE,
|
||||
TRANSACTIONAL_FILE,
|
||||
};
|
||||
|
||||
struct Dirent
|
||||
{
|
||||
unsigned long fileno = 0;
|
||||
Dirent_type type = DIRENT_TYPE_END;
|
||||
char name[DIRENT_MAX_NAME_LEN] = { 0 };
|
||||
struct Name
|
||||
{
|
||||
enum { MAX_LEN = 128 };
|
||||
char buf[MAX_LEN] { };
|
||||
|
||||
Name() { };
|
||||
Name(char const *name) { strncpy(buf, name, sizeof(buf)); }
|
||||
};
|
||||
|
||||
unsigned long fileno;
|
||||
Dirent_type type;
|
||||
Node_rwx rwx;
|
||||
Name name;
|
||||
|
||||
/**
|
||||
* Sanitize dirent members
|
||||
*
|
||||
* This method must be called after receiving a 'Dirent' as
|
||||
* a plain data copy.
|
||||
*/
|
||||
void sanitize()
|
||||
{
|
||||
/* enforce null termination */
|
||||
name.buf[Name::MAX_LEN - 1] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system
|
|||
|
||||
Readonly_value_file_system(Name const &name, T const &initial_value)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, type(),
|
||||
Xml_node(_config(name).string())),
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type(),
|
||||
Node_rwx::ro(), Xml_node(_config(name).string())),
|
||||
_file_name(name)
|
||||
{
|
||||
value(initial_value);
|
||||
|
@ -131,7 +131,6 @@ class Vfs::Readonly_value_file_system : public Vfs::Single_file_system
|
|||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Stat_result result = Single_file_system::stat(path, out);
|
||||
out.mode |= 0444;
|
||||
out.size = _buffer.length();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,16 +22,10 @@ namespace Vfs { class Single_file_system; }
|
|||
|
||||
class Vfs::Single_file_system : public File_system
|
||||
{
|
||||
public:
|
||||
|
||||
enum Node_type {
|
||||
NODE_TYPE_FILE, NODE_TYPE_SYMLINK,
|
||||
NODE_TYPE_CHAR_DEVICE, NODE_TYPE_BLOCK_DEVICE
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Node_type const _node_type;
|
||||
Node_type const _type;
|
||||
Node_rwx const _rwx;
|
||||
|
||||
typedef String<64> Filename;
|
||||
|
||||
|
@ -61,8 +55,10 @@ class Vfs::Single_file_system : public File_system
|
|||
{
|
||||
private:
|
||||
|
||||
Node_type _node_type;
|
||||
char const *_filename;
|
||||
Node_type const _type;
|
||||
Node_rwx const _rwx;
|
||||
|
||||
Filename const &_filename;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
|
@ -75,12 +71,12 @@ class Vfs::Single_file_system : public File_system
|
|||
Single_vfs_dir_handle(Directory_service &ds,
|
||||
File_io_service &fs,
|
||||
Genode::Allocator &alloc,
|
||||
Node_type node_type,
|
||||
char const *filename)
|
||||
Node_type type,
|
||||
Node_rwx rwx,
|
||||
Filename const &filename)
|
||||
:
|
||||
Single_vfs_handle(ds, fs, alloc, 0),
|
||||
_node_type(node_type),
|
||||
_filename(filename)
|
||||
_type(type), _rwx(rwx), _filename(filename)
|
||||
{ }
|
||||
|
||||
Read_result read(char *dst, file_size count,
|
||||
|
@ -93,19 +89,33 @@ class Vfs::Single_file_system : public File_system
|
|||
|
||||
file_size index = seek() / sizeof(Dirent);
|
||||
|
||||
Dirent *out = (Dirent*)dst;
|
||||
Dirent &out = *(Dirent*)dst;
|
||||
|
||||
auto dirent_type = [&] ()
|
||||
{
|
||||
switch (_type) {
|
||||
case Node_type::DIRECTORY: return Dirent_type::DIRECTORY;
|
||||
case Node_type::SYMLINK: return Dirent_type::SYMLINK;
|
||||
case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE;
|
||||
case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE;
|
||||
}
|
||||
return Dirent_type::END;
|
||||
};
|
||||
|
||||
if (index == 0) {
|
||||
out->fileno = (Genode::addr_t)this;
|
||||
switch (_node_type) {
|
||||
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_BLOCK_DEVICE: out->type = DIRENT_TYPE_BLOCKDEV; break;
|
||||
}
|
||||
strncpy(out->name, _filename, sizeof(out->name));
|
||||
out = {
|
||||
.fileno = (Genode::addr_t)this,
|
||||
.type = dirent_type(),
|
||||
.rwx = _rwx,
|
||||
.name = { _filename.string() }
|
||||
};
|
||||
} else {
|
||||
out->type = DIRENT_TYPE_END;
|
||||
out = {
|
||||
.fileno = (Genode::addr_t)this,
|
||||
.type = Dirent_type::END,
|
||||
.rwx = { },
|
||||
.name = { }
|
||||
};
|
||||
}
|
||||
|
||||
out_count = sizeof(Dirent);
|
||||
|
@ -134,9 +144,12 @@ class Vfs::Single_file_system : public File_system
|
|||
|
||||
public:
|
||||
|
||||
Single_file_system(Node_type node_type, char const *type_name, Xml_node config)
|
||||
Single_file_system(Node_type node_type,
|
||||
char const *type_name,
|
||||
Node_rwx rwx,
|
||||
Xml_node config)
|
||||
:
|
||||
_node_type(node_type),
|
||||
_type(node_type), _rwx(rwx),
|
||||
_filename(config.attribute_value("name", Filename(type_name)))
|
||||
{ }
|
||||
|
||||
|
@ -154,19 +167,15 @@ class Vfs::Single_file_system : public File_system
|
|||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
out = Stat();
|
||||
out = Stat { };
|
||||
out.device = (Genode::addr_t)this;
|
||||
|
||||
if (_root(path)) {
|
||||
out.mode = STAT_MODE_DIRECTORY;
|
||||
out.type = Node_type::DIRECTORY;
|
||||
|
||||
} else if (_single_file(path)) {
|
||||
switch (_node_type) {
|
||||
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_BLOCK_DEVICE: out.mode = STAT_MODE_BLOCKDEV; break;
|
||||
}
|
||||
out.type = _type;
|
||||
out.rwx = _rwx;
|
||||
out.inode = 1;
|
||||
} else {
|
||||
return STAT_ERR_NO_ENTRY;
|
||||
|
@ -208,7 +217,7 @@ class Vfs::Single_file_system : public File_system
|
|||
try {
|
||||
*out_handle = new (alloc)
|
||||
Single_vfs_dir_handle(*this, *this, alloc,
|
||||
_node_type, _filename.string());
|
||||
_type, _rwx, _filename);
|
||||
return OPENDIR_OK;
|
||||
}
|
||||
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
|
||||
|
|
|
@ -55,6 +55,36 @@ namespace Vfs {
|
|||
long long value;
|
||||
};
|
||||
|
||||
enum class Node_type {
|
||||
DIRECTORY,
|
||||
SYMLINK,
|
||||
CONTINUOUS_FILE,
|
||||
TRANSACTIONAL_FILE
|
||||
};
|
||||
|
||||
struct Node_rwx
|
||||
{
|
||||
bool readable;
|
||||
bool writeable;
|
||||
bool executable;
|
||||
|
||||
static Node_rwx ro() { return { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = false }; }
|
||||
|
||||
static Node_rwx rw() { return { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = false }; }
|
||||
|
||||
static Node_rwx rx() { return { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = true }; }
|
||||
|
||||
static Node_rwx rwx() { return { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = true }; }
|
||||
};
|
||||
|
||||
typedef Genode::Path<MAX_PATH_LEN> Absolute_path;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ class Cli_monitor::Subsystem_config_registry
|
|||
unsigned _subsystem_suffix(Vfs::Directory_service::Dirent const &dirent)
|
||||
{
|
||||
unsigned found = 0;
|
||||
for (unsigned i = 0; i < sizeof(dirent.name) && dirent.name[i]; i++)
|
||||
if (Genode::strcmp(_subsystem_suffix(), &dirent.name[i]) == 0)
|
||||
for (unsigned i = 0; i < sizeof(dirent.name.buf) && dirent.name.buf[i]; i++)
|
||||
if (Genode::strcmp(_subsystem_suffix(), &dirent.name.buf[i]) == 0)
|
||||
found = i;
|
||||
|
||||
return found;
|
||||
|
@ -155,7 +155,7 @@ class Cli_monitor::Subsystem_config_registry
|
|||
/* iterate over the directory entries */
|
||||
for (unsigned i = 0;; i++) {
|
||||
|
||||
Vfs::Directory_service::Dirent dirent;
|
||||
Vfs::Directory_service::Dirent dirent { };
|
||||
|
||||
dir_handle->seek(i * sizeof(dirent));
|
||||
dir_handle->fs().queue_read(dir_handle, sizeof(dirent));
|
||||
|
@ -168,7 +168,7 @@ class Cli_monitor::Subsystem_config_registry
|
|||
Vfs::File_io_service::READ_QUEUED)
|
||||
_ep.wait_and_dispatch_one_io_signal();
|
||||
|
||||
if (dirent.type == Vfs::Directory_service::DIRENT_TYPE_END) {
|
||||
if (dirent.type == Vfs::Directory_service::Dirent_type::END) {
|
||||
_fs.close(dir_handle);
|
||||
return;
|
||||
}
|
||||
|
@ -179,8 +179,8 @@ class Cli_monitor::Subsystem_config_registry
|
|||
if (subsystem_suffix) {
|
||||
|
||||
/* subsystem name is file name without the suffix */
|
||||
char name[sizeof(dirent.name)];
|
||||
Genode::strncpy(name, dirent.name, subsystem_suffix + 1);
|
||||
char name[sizeof(dirent.name.buf)];
|
||||
Genode::strncpy(name, dirent.name.buf, subsystem_suffix + 1);
|
||||
|
||||
try {
|
||||
for_config(name, fn);
|
||||
|
|
|
@ -326,7 +326,8 @@ class Vfs::Block_file_system : public Single_file_system
|
|||
|
||||
Block_file_system(Vfs::Env &env, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_BLOCK_DEVICE, name(), config),
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::rw(), config),
|
||||
_env(env),
|
||||
_label(config.attribute_value("label", Label())),
|
||||
_block_buffer(0),
|
||||
|
|
|
@ -69,6 +69,50 @@ class Vfs::Fs_file_system : public File_system
|
|||
struct Fs_vfs_handle;
|
||||
typedef Genode::Fifo<Fs_vfs_handle> Fs_vfs_handle_queue;
|
||||
|
||||
/**
|
||||
* Convert 'File_system::Node_type' to 'Dirent_type'
|
||||
*/
|
||||
static Dirent_type _dirent_type(::File_system::Node_type type)
|
||||
{
|
||||
using ::File_system::Node_type;
|
||||
|
||||
switch (type) {
|
||||
case Node_type::DIRECTORY: return Dirent_type::DIRECTORY;
|
||||
case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE;
|
||||
case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE;
|
||||
case Node_type::SYMLINK: return Dirent_type::SYMLINK;
|
||||
}
|
||||
return Dirent_type::END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert 'File_system::Node_type' to 'Vfs::Node_type'
|
||||
*/
|
||||
static Node_type _node_type(::File_system::Node_type type)
|
||||
{
|
||||
using Type = ::File_system::Node_type;
|
||||
|
||||
switch (type) {
|
||||
case Type::DIRECTORY: return Node_type::DIRECTORY;
|
||||
case Type::CONTINUOUS_FILE: return Node_type::CONTINUOUS_FILE;
|
||||
case Type::TRANSACTIONAL_FILE: return Node_type::TRANSACTIONAL_FILE;
|
||||
case Type::SYMLINK: return Node_type::SYMLINK;
|
||||
}
|
||||
|
||||
Genode::error("invalid File_system::Node_type");
|
||||
return Node_type::CONTINUOUS_FILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert 'File_system::Node_rwx' to 'Vfs::Node_rwx'
|
||||
*/
|
||||
static Node_rwx _node_rwx(::File_system::Node_rwx rwx)
|
||||
{
|
||||
return { .readable = rwx.readable,
|
||||
.writeable = rwx.writeable,
|
||||
.executable = rwx.executable };
|
||||
}
|
||||
|
||||
struct Fs_vfs_handle : Vfs_handle,
|
||||
private ::File_system::Node,
|
||||
private Handle_space::Element,
|
||||
|
@ -295,41 +339,38 @@ class Vfs::Fs_file_system : public File_system
|
|||
|
||||
using ::File_system::Directory_entry;
|
||||
|
||||
Directory_entry entry;
|
||||
file_size entry_out_count;
|
||||
Directory_entry entry { };
|
||||
file_size entry_out_count = 0;
|
||||
|
||||
Read_result read_result =
|
||||
Read_result const read_result =
|
||||
_complete_read(&entry, DIRENT_SIZE, entry_out_count);
|
||||
|
||||
if (read_result != READ_OK)
|
||||
return read_result;
|
||||
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
entry.sanitize();
|
||||
|
||||
Dirent &dirent = *(Dirent*)dst;
|
||||
|
||||
if (entry_out_count < DIRENT_SIZE) {
|
||||
|
||||
/* no entry found for the given index, or error */
|
||||
*dirent = Dirent();
|
||||
dirent = Dirent {
|
||||
.fileno = 0,
|
||||
.type = Dirent_type::END,
|
||||
.rwx = { },
|
||||
.name = { }
|
||||
};
|
||||
out_count = sizeof(Dirent);
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* The default value has no meaning because the switch below
|
||||
* assigns a value in each possible branch. But it is needed to
|
||||
* keep the compiler happy.
|
||||
*/
|
||||
Dirent_type type = DIRENT_TYPE_END;
|
||||
|
||||
/* copy-out payload into destination buffer */
|
||||
switch (entry.type) {
|
||||
case Directory_entry::TYPE_DIRECTORY: type = DIRENT_TYPE_DIRECTORY; break;
|
||||
case Directory_entry::TYPE_FILE: type = DIRENT_TYPE_FILE; break;
|
||||
case Directory_entry::TYPE_SYMLINK: type = DIRENT_TYPE_SYMLINK; break;
|
||||
}
|
||||
|
||||
dirent->fileno = entry.inode;
|
||||
dirent->type = type;
|
||||
strncpy(dirent->name, entry.name, sizeof(dirent->name));
|
||||
dirent = Dirent {
|
||||
.fileno = entry.inode,
|
||||
.type = _dirent_type(entry.type),
|
||||
.rwx = _node_rwx(entry.rwx),
|
||||
.name = { entry.name.buf }
|
||||
};
|
||||
|
||||
out_count = sizeof(Dirent);
|
||||
|
||||
|
@ -646,20 +687,13 @@ class Vfs::Fs_file_system : public File_system
|
|||
|
||||
out = Stat();
|
||||
|
||||
out.size = status.size;
|
||||
out.mode = STAT_MODE_FILE | 0777;
|
||||
|
||||
if (status.symlink())
|
||||
out.mode = STAT_MODE_SYMLINK | 0777;
|
||||
|
||||
if (status.directory())
|
||||
out.mode = STAT_MODE_DIRECTORY | 0777;
|
||||
|
||||
out.uid = 0;
|
||||
out.gid = 0;
|
||||
out.inode = status.inode;
|
||||
out.size = status.size;
|
||||
out.type = _node_type(status.type);
|
||||
out.rwx = _node_rwx(status.rwx);
|
||||
out.inode = status.inode;
|
||||
out.device = (Genode::addr_t)this;
|
||||
out.modification_time.value = status.modification_time.value;
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,9 @@ class Vfs::Inline_file_system : public Single_file_system
|
|||
*/
|
||||
Inline_file_system(Vfs::Env&, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_FILE, name(), config), _node(config)
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::rx(), config),
|
||||
_node(config)
|
||||
{ }
|
||||
|
||||
static char const *name() { return "inline"; }
|
||||
|
@ -140,9 +142,11 @@ class Vfs::Inline_file_system : public Single_file_system
|
|||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Stat_result result = Single_file_system::stat(path, out);
|
||||
Stat_result const result = Single_file_system::stat(path, out);
|
||||
|
||||
_node.with_raw_content([&] (char const *, Genode::size_t size) {
|
||||
out.size = size; });
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -141,7 +141,8 @@ class Vfs::Log_file_system : public Single_file_system
|
|||
Log_file_system(Vfs::Env &env,
|
||||
Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::ro(), config),
|
||||
_label(config.attribute_value("label", Label())),
|
||||
_log(_log_session(env.env()))
|
||||
{ }
|
||||
|
|
|
@ -24,7 +24,8 @@ struct Vfs::Null_file_system : Single_file_system
|
|||
{
|
||||
Null_file_system(Vfs::Env&, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config)
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::rw(), config)
|
||||
{ }
|
||||
|
||||
static char const *name() { return "null"; }
|
||||
|
|
|
@ -169,6 +169,13 @@ class Vfs_ram::Node : private Genode::Avl_node<Node>, private Genode::Lock
|
|||
|
||||
Vfs::Timestamp modification_time() const { return _modification_time; }
|
||||
|
||||
Vfs::Node_rwx rwx() const
|
||||
{
|
||||
return { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true };
|
||||
}
|
||||
|
||||
virtual size_t read(char*, size_t, file_size)
|
||||
{
|
||||
Genode::error("Vfs_ram::Node::read() called");
|
||||
|
@ -450,39 +457,43 @@ class Vfs_ram::Directory : public Vfs_ram::Node
|
|||
|
||||
file_offset index = seek_offset / sizeof(Dirent);
|
||||
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
*dirent = Dirent();
|
||||
Dirent &dirent = *(Dirent*)dst;
|
||||
|
||||
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||
|
||||
out_count = sizeof(Dirent);
|
||||
|
||||
Node *node = _entries.first();
|
||||
if (node) node = node->index(index);
|
||||
if (!node) {
|
||||
dirent->type = Directory_service::DIRENT_TYPE_END;
|
||||
Node *node_ptr = _entries.first();
|
||||
if (node_ptr) node_ptr = node_ptr->index(index);
|
||||
if (!node_ptr) {
|
||||
dirent.type = Dirent_type::END;
|
||||
return Vfs::File_io_service::READ_OK;
|
||||
}
|
||||
|
||||
dirent->fileno = node->inode;
|
||||
strncpy(dirent->name, node->name(), sizeof(dirent->name));
|
||||
Node &node = *node_ptr;
|
||||
|
||||
File *file = dynamic_cast<File *>(node);
|
||||
if (file) {
|
||||
dirent->type = Directory_service::DIRENT_TYPE_FILE;
|
||||
return Vfs::File_io_service::READ_OK;
|
||||
}
|
||||
auto dirent_type = [&] ()
|
||||
{
|
||||
if (dynamic_cast<File *>(node_ptr)) return Dirent_type::CONTINUOUS_FILE;
|
||||
if (dynamic_cast<Directory *>(node_ptr)) return Dirent_type::DIRECTORY;
|
||||
if (dynamic_cast<Symlink *>(node_ptr)) return Dirent_type::SYMLINK;
|
||||
|
||||
Directory *dir = dynamic_cast<Directory *>(node);
|
||||
if (dir) {
|
||||
dirent->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
||||
return Vfs::File_io_service::READ_OK;
|
||||
}
|
||||
return Dirent_type::END;
|
||||
};
|
||||
|
||||
Symlink *symlink = dynamic_cast<Symlink *>(node);
|
||||
if (symlink) {
|
||||
dirent->type = Directory_service::DIRENT_TYPE_SYMLINK;
|
||||
return Vfs::File_io_service::READ_OK;
|
||||
}
|
||||
Dirent_type const type = dirent_type();
|
||||
|
||||
return Vfs::File_io_service::READ_ERR_INVALID;
|
||||
if (type == Dirent_type::END)
|
||||
return Vfs::File_io_service::READ_ERR_INVALID;
|
||||
|
||||
dirent = {
|
||||
.fileno = node.inode,
|
||||
.type = type,
|
||||
.rwx = node.rwx(),
|
||||
.name = { node.name() }
|
||||
};
|
||||
|
||||
return Vfs::File_io_service::READ_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -780,35 +791,31 @@ class Vfs::Ram_file_system : public Vfs::File_system
|
|||
{
|
||||
using namespace Vfs_ram;
|
||||
|
||||
Node *node = lookup(path);
|
||||
if (!node) return STAT_ERR_NO_ENTRY;
|
||||
Node::Guard guard(node);
|
||||
Node *node_ptr = lookup(path);
|
||||
if (!node_ptr) return STAT_ERR_NO_ENTRY;
|
||||
|
||||
stat.size = node->length();
|
||||
stat.inode = node->inode;
|
||||
stat.device = (Genode::addr_t)this;
|
||||
stat.modification_time = node->modification_time();
|
||||
Node::Guard guard(node_ptr);
|
||||
|
||||
File *file = dynamic_cast<File *>(node);
|
||||
if (file) {
|
||||
stat.mode = STAT_MODE_FILE | 0777;
|
||||
return STAT_OK;
|
||||
}
|
||||
Node &node = *node_ptr;
|
||||
|
||||
Directory *dir = dynamic_cast<Directory *>(node);
|
||||
if (dir) {
|
||||
stat.mode = STAT_MODE_DIRECTORY | 0777;
|
||||
return STAT_OK;
|
||||
}
|
||||
auto node_type = [&] ()
|
||||
{
|
||||
if (dynamic_cast<Directory *>(node_ptr)) return Node_type::DIRECTORY;
|
||||
if (dynamic_cast<Symlink *>(node_ptr)) return Node_type::SYMLINK;
|
||||
|
||||
Symlink *symlink = dynamic_cast<Symlink *>(node);
|
||||
if (symlink) {
|
||||
stat.mode = STAT_MODE_SYMLINK | 0777;
|
||||
return STAT_OK;
|
||||
}
|
||||
return Node_type::CONTINUOUS_FILE;
|
||||
};
|
||||
|
||||
/* this should never happen */
|
||||
return STAT_ERR_NO_ENTRY;
|
||||
stat = {
|
||||
.size = node.length(),
|
||||
.type = node_type(),
|
||||
.rwx = node.rwx(),
|
||||
.inode = node.inode,
|
||||
.device = (Genode::addr_t)this,
|
||||
.modification_time = node.modification_time()
|
||||
};
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
Rename_result rename(char const *from, char const *to) override
|
||||
|
|
|
@ -107,7 +107,8 @@ class Vfs::Rom_file_system : public Single_file_system
|
|||
Rom_file_system(Vfs::Env &env,
|
||||
Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_FILE, name(), config),
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::ro(), config),
|
||||
|
||||
/* use 'label' attribute if present, fall back to 'name' if not */
|
||||
_label(config.attribute_value("label",
|
||||
|
@ -161,10 +162,12 @@ class Vfs::Rom_file_system : public Single_file_system
|
|||
* found a file), obtain the size of the most current ROM module
|
||||
* version.
|
||||
*/
|
||||
if (out.mode == STAT_MODE_FILE) {
|
||||
if (out.type == Node_type::CONTINUOUS_FILE) {
|
||||
_rom.update();
|
||||
out.size = _rom.valid() ? _rom.size() : 0;
|
||||
out.mode |= 0555;
|
||||
out.rwx = { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = true };
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -103,7 +103,8 @@ class Vfs::Rtc_file_system : public Single_file_system
|
|||
|
||||
Rtc_file_system(Vfs::Env &env, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, name(),
|
||||
Node_rwx::ro(), config),
|
||||
_rtc(env.env()),
|
||||
_set_signal_handler(env.env().ep(), *this,
|
||||
&Rtc_file_system::_handle_set_signal)
|
||||
|
@ -136,10 +137,7 @@ class Vfs::Rtc_file_system : public Single_file_system
|
|||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
Stat_result result = Single_file_system::stat(path, out);
|
||||
out.mode |= 0444;
|
||||
|
||||
return result;
|
||||
return Single_file_system::stat(path, out);
|
||||
}
|
||||
|
||||
Watch_result watch(char const *path,
|
||||
|
|
|
@ -60,7 +60,8 @@ class Vfs::Symlink_file_system : public Single_file_system
|
|||
|
||||
Symlink_file_system(Vfs::Env&, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_SYMLINK, "symlink", config),
|
||||
Single_file_system(Node_type::SYMLINK, "symlink",
|
||||
Node_rwx::rw(), config),
|
||||
_target(config.attribute_value("target", Target()))
|
||||
{ }
|
||||
|
||||
|
|
|
@ -110,12 +110,22 @@ class Vfs::Tar_file_system : public File_system
|
|||
TYPE_LONG_LINK = 75, TYPE_LONG_NAME = 76
|
||||
};
|
||||
|
||||
file_size size() const { return _long_name() ? _next()->size() : _read(_size); }
|
||||
unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); }
|
||||
unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); }
|
||||
unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); }
|
||||
unsigned type() const { return _long_name() ? _next()->type() : _read(_type); }
|
||||
void *data() const { return _long_name() ? _next()->data() : (void *)_data_begin(); }
|
||||
file_size size() const { return _long_name() ? _next()->size() : _read(_size); }
|
||||
long long mtime() const { return _long_name() ? _next()->mtime() : _read(_mtime); }
|
||||
unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); }
|
||||
unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); }
|
||||
unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); }
|
||||
unsigned type() const { return _long_name() ? _next()->type() : _read(_type); }
|
||||
void *data() const { return _long_name() ? _next()->data() : (void *)_data_begin(); }
|
||||
|
||||
Node_rwx rwx() const
|
||||
{
|
||||
unsigned const mode_bits = mode();
|
||||
|
||||
return { .readable = (mode_bits & 0400) != 0,
|
||||
.writeable = (mode_bits & 0200) != 0,
|
||||
.executable = (mode_bits & 0100) != 0 };
|
||||
}
|
||||
|
||||
char const *name() const { return _long_name() ? _data_begin() : _name; }
|
||||
unsigned max_name_len() const { return _long_name() ? MAX_PATH_LEN : 100; }
|
||||
|
@ -193,50 +203,67 @@ class Vfs::Tar_file_system : public File_system
|
|||
if (count < sizeof(Dirent))
|
||||
return READ_ERR_INVALID;
|
||||
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
Dirent &dirent = *(Dirent*)dst;
|
||||
|
||||
/* initialize */
|
||||
*dirent = Dirent();
|
||||
file_offset const index = seek() / sizeof(Dirent);
|
||||
|
||||
file_offset index = seek() / sizeof(Dirent);
|
||||
Node const *node_ptr = _node->lookup_child(index);
|
||||
|
||||
Node const *node = _node->lookup_child(index);
|
||||
|
||||
if (!node)
|
||||
if (!node_ptr) {
|
||||
dirent = Dirent { };
|
||||
out_count = 0;
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
dirent->fileno = (Genode::addr_t)node;
|
||||
Node const &node = *node_ptr;
|
||||
|
||||
Record const *record = node->record;
|
||||
Record const *record_ptr = node.record;
|
||||
|
||||
while (record && (record->type() == Record::TYPE_HARDLINK)) {
|
||||
while (record_ptr && (record_ptr->type() == Record::TYPE_HARDLINK)) {
|
||||
Tar_file_system &tar_fs = static_cast<Tar_file_system&>(fs());
|
||||
Node const *target = tar_fs.dereference(record->linked_name());
|
||||
record = target ? target->record : 0;
|
||||
Node const *target = tar_fs.dereference(record_ptr->linked_name());
|
||||
record_ptr = target ? target->record : 0;
|
||||
}
|
||||
|
||||
if (record) {
|
||||
switch (record->type()) {
|
||||
case Record::TYPE_FILE:
|
||||
dirent->type = DIRENT_TYPE_FILE; break;
|
||||
case Record::TYPE_SYMLINK:
|
||||
dirent->type = DIRENT_TYPE_SYMLINK; break;
|
||||
case Record::TYPE_DIR:
|
||||
dirent->type = DIRENT_TYPE_DIRECTORY; break;
|
||||
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||
|
||||
default:
|
||||
Genode::error("unhandled record type ", record->type(), " "
|
||||
"for ", node->name);
|
||||
}
|
||||
} else {
|
||||
/* If no record exists, assume it is a directory */
|
||||
dirent->type = DIRENT_TYPE_DIRECTORY;
|
||||
/* if no record exists, assume it is a directory */
|
||||
if (!record_ptr) {
|
||||
dirent = {
|
||||
.fileno = (Genode::addr_t)node_ptr,
|
||||
.type = Dirent_type::DIRECTORY,
|
||||
.rwx = Node_rwx::rx(),
|
||||
.name = { node.name }
|
||||
};
|
||||
out_count = sizeof(Dirent);
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
strncpy(dirent->name, node->name, sizeof(dirent->name));
|
||||
Record const &record = *record_ptr;
|
||||
|
||||
auto node_type = [&] ()
|
||||
{
|
||||
switch (record.type()) {
|
||||
case Record::TYPE_FILE: return Dirent_type::CONTINUOUS_FILE;
|
||||
case Record::TYPE_SYMLINK: return Dirent_type::SYMLINK;
|
||||
case Record::TYPE_DIR: return Dirent_type::DIRECTORY;
|
||||
};
|
||||
|
||||
Genode::warning("unhandled record type ", record.type(), " "
|
||||
"for ", node.name);
|
||||
|
||||
return Dirent_type::END;
|
||||
};
|
||||
|
||||
dirent = {
|
||||
.fileno = (Genode::addr_t)node_ptr,
|
||||
.type = node_type(),
|
||||
.rwx = { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = record.rwx().executable },
|
||||
.name = { node.name }
|
||||
};
|
||||
out_count = sizeof(Dirent);
|
||||
|
||||
return READ_OK;
|
||||
}
|
||||
};
|
||||
|
@ -576,35 +603,40 @@ class Vfs::Tar_file_system : public File_system
|
|||
|
||||
Stat_result stat(char const *path, Stat &out) override
|
||||
{
|
||||
out = Stat();
|
||||
out = Stat { };
|
||||
|
||||
Node const *node = dereference(path);
|
||||
if (!node)
|
||||
Node const *node_ptr = dereference(path);
|
||||
if (!node_ptr)
|
||||
return STAT_ERR_NO_ENTRY;
|
||||
|
||||
if (!node->record) {
|
||||
out.mode = STAT_MODE_DIRECTORY;
|
||||
if (!node_ptr->record) {
|
||||
out.type = Node_type::DIRECTORY;
|
||||
out.rwx = Node_rwx::rx();
|
||||
return STAT_OK;
|
||||
}
|
||||
|
||||
Record const *record = node->record;
|
||||
Record const &record = *node_ptr->record;
|
||||
|
||||
/* convert TAR record modes to stat modes */
|
||||
unsigned mode = record->mode();
|
||||
switch (record->type()) {
|
||||
case Record::TYPE_FILE: mode |= STAT_MODE_FILE; break;
|
||||
case Record::TYPE_SYMLINK: mode |= STAT_MODE_SYMLINK; break;
|
||||
case Record::TYPE_DIR: mode |= STAT_MODE_DIRECTORY; break;
|
||||
auto node_type = [&] ()
|
||||
{
|
||||
switch (record.type()) {
|
||||
case Record::TYPE_FILE: return Node_type::CONTINUOUS_FILE;
|
||||
case Record::TYPE_SYMLINK: return Node_type::SYMLINK;
|
||||
case Record::TYPE_DIR: return Node_type::DIRECTORY;
|
||||
};
|
||||
return Node_type::DIRECTORY;
|
||||
};
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
out.mode = mode;
|
||||
out.size = record->size();
|
||||
out.uid = record->uid();
|
||||
out.gid = record->gid();
|
||||
out.inode = (Genode::addr_t)node;
|
||||
out.device = (Genode::addr_t)this;
|
||||
out = {
|
||||
.size = record.size(),
|
||||
.type = node_type(),
|
||||
.rwx = { .readable = true,
|
||||
.writeable = false,
|
||||
.executable = record.rwx().executable },
|
||||
.inode = (Genode::addr_t)node_ptr,
|
||||
.device = (Genode::addr_t)this,
|
||||
.modification_time = { record.mtime() }
|
||||
};
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,8 @@ class Vfs::Terminal_file_system : public Single_file_system
|
|||
|
||||
Terminal_file_system(Vfs::Env &env, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, name(),
|
||||
Node_rwx::rw(), config),
|
||||
_label(config.attribute_value("label", Label())),
|
||||
_env(env.env())
|
||||
{
|
||||
|
|
|
@ -24,7 +24,8 @@ struct Vfs::Zero_file_system : Single_file_system
|
|||
{
|
||||
Zero_file_system(Vfs::Env&, Genode::Xml_node config)
|
||||
:
|
||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config)
|
||||
Single_file_system(Node_type::CONTINUOUS_FILE, name(),
|
||||
Node_rwx::rw(), config)
|
||||
{ }
|
||||
|
||||
static char const *name() { return "zero"; }
|
||||
|
|
|
@ -69,7 +69,7 @@ class Lx_fs::Directory : public Node
|
|||
}
|
||||
}
|
||||
|
||||
struct stat s;
|
||||
struct stat s { };
|
||||
|
||||
ret = lstat(path, &s);
|
||||
if (ret == -1)
|
||||
|
@ -203,19 +203,30 @@ class Lx_fs::Directory : public Node
|
|||
if (!dent)
|
||||
return 0;
|
||||
|
||||
Directory_entry *e = (Directory_entry *)(dst);
|
||||
Path dent_path(dent->d_name, _path.base());
|
||||
|
||||
switch (dent->d_type) {
|
||||
case DT_REG: e->type = Directory_entry::TYPE_FILE; break;
|
||||
case DT_DIR: e->type = Directory_entry::TYPE_DIRECTORY; break;
|
||||
case DT_LNK: e->type = Directory_entry::TYPE_SYMLINK; break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
struct stat st { };
|
||||
lstat(dent_path.base(), &st);
|
||||
|
||||
e->inode = dent->d_ino;
|
||||
auto type = [] (unsigned char type)
|
||||
{
|
||||
switch (type) {
|
||||
case DT_REG: return Node_type::CONTINUOUS_FILE;
|
||||
case DT_DIR: return Node_type::DIRECTORY;
|
||||
case DT_LNK: return Node_type::SYMLINK;
|
||||
default: return Node_type::CONTINUOUS_FILE;
|
||||
}
|
||||
};
|
||||
|
||||
strncpy(e->name, dent->d_name, sizeof(e->name));
|
||||
Directory_entry &e = *(Directory_entry *)(dst);
|
||||
e = {
|
||||
.inode = (unsigned long)dent->d_ino,
|
||||
.type = type(dent->d_type),
|
||||
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||
.writeable = (st.st_mode & S_IWUSR),
|
||||
.executable = (st.st_mode & S_IXUSR) },
|
||||
.name = { dent->d_name }
|
||||
};
|
||||
|
||||
return sizeof(Directory_entry);
|
||||
}
|
||||
|
@ -228,18 +239,21 @@ class Lx_fs::Directory : public Node
|
|||
|
||||
Status status() override
|
||||
{
|
||||
struct stat st;
|
||||
struct stat st { };
|
||||
|
||||
int fd = dirfd(_fd);
|
||||
if (fd == -1 || fstat(fd, &st) < 0)
|
||||
st.st_mtime = 0;
|
||||
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = _num_entries() * sizeof(File_system::Directory_entry);
|
||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
||||
s.modification_time = { st.st_mtime };
|
||||
return s;
|
||||
return {
|
||||
.size = _num_entries() * sizeof(File_system::Directory_entry),
|
||||
.type = Node_type::DIRECTORY,
|
||||
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||
.writeable = (st.st_mode & S_IWUSR),
|
||||
.executable = (st.st_mode & S_IXUSR) },
|
||||
.inode = inode(),
|
||||
.modification_time = { st.st_mtime }
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -143,19 +143,22 @@ class Lx_fs::File : public Node
|
|||
|
||||
Status status() override
|
||||
{
|
||||
struct stat st;
|
||||
struct stat st { };
|
||||
|
||||
if (fstat(_fd, &st) < 0) {
|
||||
st.st_size = 0;
|
||||
st.st_mtime = 0;
|
||||
}
|
||||
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = st.st_size;
|
||||
s.mode = File_system::Status::MODE_FILE;
|
||||
s.modification_time = { st.st_mtime };
|
||||
return s;
|
||||
return {
|
||||
.size = (file_size_t)st.st_size,
|
||||
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||
.writeable = (st.st_mode & S_IWUSR),
|
||||
.executable = (st.st_mode & S_IXUSR) },
|
||||
.inode = inode(),
|
||||
.modification_time = { st.st_mtime }
|
||||
};
|
||||
}
|
||||
|
||||
void truncate(file_size_t size) override
|
||||
|
|
|
@ -203,15 +203,25 @@ class Ram_fs::Directory : public Node
|
|||
if (!node)
|
||||
return 0;
|
||||
|
||||
Directory_entry *e = (Directory_entry *)(dst);
|
||||
auto type = [&] ()
|
||||
{
|
||||
using Node_type = File_system::Node_type;
|
||||
|
||||
e->inode = node->inode();
|
||||
if (dynamic_cast<Directory *>(node)) return Node_type::DIRECTORY;
|
||||
if (dynamic_cast<Symlink *>(node)) return Node_type::SYMLINK;
|
||||
return Node_type::CONTINUOUS_FILE;
|
||||
};
|
||||
|
||||
if (dynamic_cast<File *>(node)) e->type = Directory_entry::TYPE_FILE;
|
||||
if (dynamic_cast<Directory *>(node)) e->type = Directory_entry::TYPE_DIRECTORY;
|
||||
if (dynamic_cast<Symlink *>(node)) e->type = Directory_entry::TYPE_SYMLINK;
|
||||
Directory_entry &e = *(Directory_entry *)(dst);
|
||||
|
||||
strncpy(e->name, node->name(), sizeof(e->name));
|
||||
e = {
|
||||
.inode = node->inode(),
|
||||
.type = type(),
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.name = { node->name() }
|
||||
};
|
||||
|
||||
return sizeof(Directory_entry);
|
||||
}
|
||||
|
@ -224,12 +234,15 @@ class Ram_fs::Directory : public Node
|
|||
|
||||
Status status() override
|
||||
{
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = _num_entries * sizeof(File_system::Directory_entry);
|
||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
||||
s.modification_time = modification_time();
|
||||
return s;
|
||||
return {
|
||||
.size = _num_entries * sizeof(File_system::Directory_entry),
|
||||
.type = File_system::Node_type::DIRECTORY,
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.inode = inode(),
|
||||
.modification_time = modification_time()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -112,12 +112,15 @@ class Ram_fs::File : public Node
|
|||
|
||||
Status status() override
|
||||
{
|
||||
Status s { };
|
||||
s.inode = inode();
|
||||
s.size = _length;
|
||||
s.mode = File_system::Status::MODE_FILE;
|
||||
s.modification_time = modification_time();
|
||||
return s;
|
||||
return {
|
||||
.size = _length,
|
||||
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.inode = inode(),
|
||||
.modification_time = modification_time()
|
||||
};
|
||||
}
|
||||
|
||||
void truncate(file_size_t size) override
|
||||
|
|
|
@ -67,12 +67,15 @@ class Ram_fs::Symlink : public Node
|
|||
|
||||
Status status() override
|
||||
{
|
||||
Status s;
|
||||
s.inode = inode();
|
||||
s.size = _len;
|
||||
s.mode = File_system::Status::MODE_SYMLINK;
|
||||
s.modification_time = modification_time();
|
||||
return s;
|
||||
return {
|
||||
.size = _len,
|
||||
.type = File_system::Node_type::SYMLINK,
|
||||
.rwx = { .readable = true,
|
||||
.writeable = true,
|
||||
.executable = true },
|
||||
.inode = inode(),
|
||||
.modification_time = modification_time()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -485,35 +485,54 @@ class Vfs_server::Session_component : private Session_resources,
|
|||
::File_system::Status fs_stat;
|
||||
|
||||
_apply_node(node_handle, [&] (Node &node) {
|
||||
|
||||
Directory_service::Stat vfs_stat;
|
||||
|
||||
if (_vfs.stat(node.path(), vfs_stat) != Directory_service::STAT_OK)
|
||||
throw Invalid_handle();
|
||||
|
||||
fs_stat.inode = vfs_stat.inode;
|
||||
auto fs_node_type = [&] (Vfs::Node_type type)
|
||||
{
|
||||
using To = ::File_system::Node_type;
|
||||
|
||||
switch (vfs_stat.mode & (
|
||||
Directory_service::STAT_MODE_DIRECTORY |
|
||||
Directory_service::STAT_MODE_SYMLINK |
|
||||
::File_system::Status::MODE_FILE)) {
|
||||
switch (type) {
|
||||
case Vfs::Node_type::DIRECTORY: return To::DIRECTORY;
|
||||
case Vfs::Node_type::SYMLINK: return To::SYMLINK;
|
||||
case Vfs::Node_type::CONTINUOUS_FILE: return To::CONTINUOUS_FILE;
|
||||
case Vfs::Node_type::TRANSACTIONAL_FILE: return To::TRANSACTIONAL_FILE;
|
||||
};
|
||||
return To::CONTINUOUS_FILE;
|
||||
};
|
||||
|
||||
case Directory_service::STAT_MODE_DIRECTORY:
|
||||
fs_stat.mode = ::File_system::Status::MODE_DIRECTORY;
|
||||
fs_stat.size = _vfs.num_dirent(node.path()) * sizeof(Directory_entry);
|
||||
return;
|
||||
auto fs_node_size = [&] (Vfs::Directory_service::Stat const &vfs_stat)
|
||||
{
|
||||
switch (vfs_stat.type) {
|
||||
case Vfs::Node_type::DIRECTORY:
|
||||
return _vfs.num_dirent(node.path()) * sizeof(Directory_entry);
|
||||
|
||||
case Directory_service::STAT_MODE_SYMLINK:
|
||||
fs_stat.mode = ::File_system::Status::MODE_SYMLINK;
|
||||
break;
|
||||
case Vfs::Node_type::SYMLINK:
|
||||
return 0ULL;
|
||||
|
||||
default: /* Directory_service::STAT_MODE_FILE */
|
||||
fs_stat.mode = ::File_system::Status::MODE_FILE;
|
||||
break;
|
||||
}
|
||||
case Vfs::Node_type::CONTINUOUS_FILE:
|
||||
case Vfs::Node_type::TRANSACTIONAL_FILE:
|
||||
return vfs_stat.size;
|
||||
};
|
||||
return 0ULL;
|
||||
};
|
||||
|
||||
fs_stat.size = vfs_stat.size;
|
||||
fs_stat.modification_time.value = vfs_stat.modification_time.value;
|
||||
fs_stat = ::File_system::Status {
|
||||
.size = fs_node_size(vfs_stat),
|
||||
.type = fs_node_type(vfs_stat.type),
|
||||
.rwx = {
|
||||
.readable = vfs_stat.rwx.readable,
|
||||
.writeable = vfs_stat.rwx.writeable,
|
||||
.executable = vfs_stat.rwx.executable },
|
||||
|
||||
.inode = vfs_stat.inode,
|
||||
.modification_time = { vfs_stat.modification_time.value }
|
||||
};
|
||||
});
|
||||
|
||||
return fs_stat;
|
||||
}
|
||||
|
||||
|
|
|
@ -726,17 +726,21 @@ struct Vfs_server::Directory : Io_node
|
|||
return true;
|
||||
}
|
||||
|
||||
seek_off_t seek_offset = _packet.position();
|
||||
seek_off_t const seek_offset = _packet.position();
|
||||
|
||||
Directory_service::Dirent vfs_dirent;
|
||||
size_t blocksize = sizeof(::File_system::Directory_entry);
|
||||
size_t const blocksize = sizeof(::File_system::Directory_entry);
|
||||
|
||||
unsigned index = (seek_offset / blocksize);
|
||||
unsigned const index = (seek_offset / blocksize);
|
||||
|
||||
file_size out_count = 0;
|
||||
bool result = _vfs_read(
|
||||
(char*)&vfs_dirent, sizeof(vfs_dirent),
|
||||
index * sizeof(vfs_dirent), out_count);
|
||||
|
||||
Directory_service::Dirent vfs_dirent { };
|
||||
|
||||
bool const result = _vfs_read((char*)&vfs_dirent,
|
||||
sizeof(vfs_dirent),
|
||||
index * sizeof(vfs_dirent),
|
||||
out_count);
|
||||
vfs_dirent.sanitize();
|
||||
|
||||
if (result) {
|
||||
if (out_count != sizeof(vfs_dirent)) {
|
||||
|
@ -744,30 +748,47 @@ struct Vfs_server::Directory : Io_node
|
|||
return true;
|
||||
}
|
||||
|
||||
::File_system::Directory_entry *fs_dirent =
|
||||
(Directory_entry *)_stream.packet_content(_packet);
|
||||
fs_dirent->inode = vfs_dirent.fileno;
|
||||
auto fs_dirent_type = [&] (Vfs::Directory_service::Dirent_type type)
|
||||
{
|
||||
using From = Vfs::Directory_service::Dirent_type;
|
||||
using To = ::File_system::Node_type;
|
||||
|
||||
switch (vfs_dirent.type) {
|
||||
case Vfs::Directory_service::DIRENT_TYPE_END:
|
||||
/*
|
||||
* This should never be taken because 'END' is checked as a
|
||||
* precondition prior the call to of this function.
|
||||
*/
|
||||
To const default_result = To::CONTINUOUS_FILE;
|
||||
|
||||
switch (type) {
|
||||
case From::END: return default_result;
|
||||
case From::DIRECTORY: return To::DIRECTORY;
|
||||
case From::SYMLINK: return To::SYMLINK;
|
||||
case From::CONTINUOUS_FILE: return To::CONTINUOUS_FILE;
|
||||
case From::TRANSACTIONAL_FILE: return To::TRANSACTIONAL_FILE;
|
||||
}
|
||||
return default_result;
|
||||
};
|
||||
|
||||
if (vfs_dirent.type == Vfs::Directory_service::Dirent_type::END) {
|
||||
_ack_packet(0);
|
||||
return true;
|
||||
|
||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY:
|
||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_DIRECTORY;
|
||||
break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_SYMLINK:
|
||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_SYMLINK;
|
||||
break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_FILE:
|
||||
default:
|
||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_FILE;
|
||||
break;
|
||||
} else {
|
||||
|
||||
::File_system::Directory_entry &fs_dirent =
|
||||
*(Directory_entry *)_stream.packet_content(_packet);
|
||||
|
||||
fs_dirent = {
|
||||
.inode = vfs_dirent.fileno,
|
||||
.type = fs_dirent_type(vfs_dirent.type),
|
||||
.rwx = {
|
||||
.readable = vfs_dirent.rwx.readable,
|
||||
.writeable = vfs_dirent.rwx.writeable,
|
||||
.executable = vfs_dirent.rwx.executable },
|
||||
.name = { vfs_dirent.name.buf }
|
||||
};
|
||||
|
||||
_ack_packet(sizeof(Directory_entry));
|
||||
}
|
||||
|
||||
strncpy(fs_dirent->name, vfs_dirent.name, MAX_NAME_LEN);
|
||||
|
||||
_ack_packet(sizeof(Directory_entry));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -442,7 +442,7 @@ struct Unlink_test : public Stress_test
|
|||
Vfs::Vfs_handle *dir_handle;
|
||||
assert_opendir(vfs.opendir(path, false, &dir_handle, alloc));
|
||||
|
||||
Vfs::Directory_service::Dirent dirent;
|
||||
Vfs::Directory_service::Dirent dirent { };
|
||||
for (Vfs::file_size i = vfs.num_dirent(path); i;) {
|
||||
dir_handle->seek(--i * sizeof(dirent));
|
||||
dir_handle->fs().queue_read(dir_handle, sizeof(dirent));
|
||||
|
@ -453,13 +453,13 @@ struct Unlink_test : public Stress_test
|
|||
Vfs::File_io_service::READ_QUEUED)
|
||||
_ep.wait_and_dispatch_one_io_signal();
|
||||
|
||||
subpath.append(dirent.name);
|
||||
subpath.append(dirent.name.buf);
|
||||
switch (dirent.type) {
|
||||
case Vfs::Directory_service::DIRENT_TYPE_END:
|
||||
case Vfs::Directory_service::Dirent_type::END:
|
||||
error("reached the end prematurely");
|
||||
throw Exception();
|
||||
|
||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY:
|
||||
case Vfs::Directory_service::Dirent_type::DIRECTORY:
|
||||
empty_dir(subpath.base());
|
||||
|
||||
default:
|
||||
|
|
|
@ -74,43 +74,7 @@ struct Noux::Sysio
|
|||
OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */
|
||||
};
|
||||
|
||||
/**
|
||||
* These values are the same as in the FreeBSD libc
|
||||
*/
|
||||
enum {
|
||||
STAT_MODE_SYMLINK = 0120000,
|
||||
STAT_MODE_FILE = 0100000,
|
||||
STAT_MODE_DIRECTORY = 0040000,
|
||||
STAT_MODE_CHARDEV = 0020000,
|
||||
STAT_MODE_BLOCKDEV = 0060000,
|
||||
};
|
||||
|
||||
/*
|
||||
* Must be POD (in contrast to the VFS type) because it's used in a union
|
||||
*/
|
||||
struct Stat
|
||||
{
|
||||
Vfs::file_size size;
|
||||
unsigned mode;
|
||||
unsigned uid;
|
||||
unsigned gid;
|
||||
unsigned long inode;
|
||||
unsigned long device;
|
||||
long long mtime;
|
||||
|
||||
Stat & operator= (Vfs::Directory_service::Stat const &stat)
|
||||
{
|
||||
size = stat.size;
|
||||
mode = stat.mode;
|
||||
uid = stat.uid;
|
||||
gid = stat.gid;
|
||||
inode = stat.inode;
|
||||
device = stat.device;
|
||||
mtime = stat.modification_time.value;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
typedef Vfs::Directory_service::Stat Stat;
|
||||
|
||||
/**
|
||||
* Argument structure used for ioctl syscall
|
||||
|
@ -132,7 +96,7 @@ struct Noux::Sysio
|
|||
|
||||
enum Lseek_whence { LSEEK_SET, LSEEK_CUR, LSEEK_END };
|
||||
|
||||
enum { DIRENT_MAX_NAME_LEN = Vfs::Directory_service::DIRENT_MAX_NAME_LEN };
|
||||
enum { DIRENT_MAX_NAME_LEN = Vfs::Directory_service::Dirent::Name::MAX_LEN };
|
||||
|
||||
typedef Vfs::Directory_service::Dirent_type Dirent_type;
|
||||
|
||||
|
@ -149,7 +113,7 @@ struct Noux::Sysio
|
|||
{
|
||||
fileno = dirent.fileno;
|
||||
type = dirent.type;
|
||||
memcpy(name, dirent.name, DIRENT_MAX_NAME_LEN);
|
||||
memcpy(name, dirent.name.buf, DIRENT_MAX_NAME_LEN);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
b82025f7f85938ce713b6c442c693afe465dd83a
|
||||
8eddf0d249a22993e57b3242112fb62f503101c9
|
||||
|
|
|
@ -388,18 +388,39 @@ extern "C" int getrlimit(int resource, struct rlimit *rlim)
|
|||
*/
|
||||
static void _sysio_to_stat_struct(Noux::Sysio const *sysio, struct stat *buf)
|
||||
{
|
||||
Genode::memset(buf, 0, sizeof(*buf));
|
||||
buf->st_uid = sysio->stat_out.st.uid;
|
||||
buf->st_gid = sysio->stat_out.st.gid;
|
||||
buf->st_mode = sysio->stat_out.st.mode;
|
||||
buf->st_size = sysio->stat_out.st.size;
|
||||
buf->st_blksize = FS_BLOCK_SIZE;
|
||||
buf->st_blocks = (buf->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
|
||||
buf->st_ino = sysio->stat_out.st.inode;
|
||||
buf->st_dev = sysio->stat_out.st.device;
|
||||
unsigned const readable_bits = S_IRUSR,
|
||||
writeable_bits = S_IWUSR,
|
||||
executable_bits = S_IXUSR;
|
||||
|
||||
if (sysio->stat_out.st.mtime >= 0)
|
||||
buf->st_mtime = sysio->stat_out.st.mtime;
|
||||
auto type = [] (Vfs::Node_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case Vfs::Node_type::DIRECTORY: return S_IFDIR;
|
||||
case Vfs::Node_type::CONTINUOUS_FILE: return S_IFREG;
|
||||
case Vfs::Node_type::TRANSACTIONAL_FILE: return S_IFSOCK;
|
||||
case Vfs::Node_type::SYMLINK: return S_IFLNK;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
Vfs::Directory_service::Stat const &src = sysio->stat_out.st;
|
||||
|
||||
*buf = { };
|
||||
|
||||
buf->st_uid = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_mode = (src.rwx.readable ? readable_bits : 0)
|
||||
| (src.rwx.writeable ? writeable_bits : 0)
|
||||
| (src.rwx.executable ? executable_bits : 0)
|
||||
| type(src.type);
|
||||
buf->st_size = src.size;
|
||||
buf->st_blksize = FS_BLOCK_SIZE;
|
||||
buf->st_blocks = (src.size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
|
||||
buf->st_ino = src.inode;
|
||||
buf->st_dev = src.device;
|
||||
|
||||
if (src.modification_time.value >= 0)
|
||||
buf->st_mtime = src.modification_time.value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1693,9 +1714,6 @@ namespace {
|
|||
|
||||
sysio()->dirent_in.fd = noux_fd(fd->context);
|
||||
|
||||
struct dirent *dirent = (struct dirent *)buf;
|
||||
Genode::memset(dirent, 0, sizeof(struct dirent));
|
||||
|
||||
if (!noux_syscall(Noux::Session::SYSCALL_DIRENT)) {
|
||||
switch (sysio()->error.general) {
|
||||
|
||||
|
@ -1708,23 +1726,35 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
switch (sysio()->dirent_out.entry.type) {
|
||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_CHARDEV: dirent->d_type = DT_CHR; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_BLOCKDEV: dirent->d_type = DT_BLK; break;
|
||||
case Vfs::Directory_service::DIRENT_TYPE_END: return 0;
|
||||
}
|
||||
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||
|
||||
dirent->d_fileno = sysio()->dirent_out.entry.fileno;
|
||||
dirent->d_reclen = sizeof(struct dirent);
|
||||
if (sysio()->dirent_out.entry.type == Dirent_type::END)
|
||||
return 0;
|
||||
|
||||
Genode::strncpy(dirent->d_name, sysio()->dirent_out.entry.name,
|
||||
sizeof(dirent->d_name));
|
||||
auto d_type = [] (Dirent_type const &type)
|
||||
{
|
||||
switch (sysio()->dirent_out.entry.type) {
|
||||
case Dirent_type::DIRECTORY: return DT_DIR;
|
||||
case Dirent_type::CONTINUOUS_FILE: return DT_REG;
|
||||
case Dirent_type::TRANSACTIONAL_FILE: return DT_REG;
|
||||
case Dirent_type::SYMLINK: return DT_LNK;
|
||||
case Dirent_type::END: return 0;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
dirent->d_namlen = Genode::strlen(dirent->d_name);
|
||||
struct dirent &dirent = *(struct dirent *)buf;
|
||||
|
||||
dirent = { };
|
||||
|
||||
dirent.d_type = d_type(sysio()->dirent_out.entry.type);
|
||||
dirent.d_fileno = sysio()->dirent_out.entry.fileno;
|
||||
dirent.d_reclen = sizeof(struct dirent);
|
||||
|
||||
Genode::strncpy(dirent.d_name, sysio()->dirent_out.entry.name,
|
||||
sizeof(dirent.d_name));
|
||||
|
||||
dirent.d_namlen = Genode::strlen(dirent.d_name);
|
||||
|
||||
*basep += sizeof(struct dirent);
|
||||
return sizeof(struct dirent);
|
||||
|
|
|
@ -14,14 +14,14 @@ From: Christian Prochaska <christian.prochaska@genode-labs.com>
|
|||
gdb/gdbserver/linux-x86-low.c | 111 +++++++++++++++++++-
|
||||
gdb/gdbserver/linux-x86-tdesc-selftest.c | 31 ++++++
|
||||
gdb/gdbserver/linux-x86-tdesc.c | 8 +
|
||||
gdb/gdbserver/remote-utils.c | 11 ++
|
||||
gdb/gdbserver/remote-utils.c | 15 +++
|
||||
gdb/gdbserver/server.c | 36 ++++++
|
||||
gdb/gdbserver/server.h | 4 +
|
||||
gdb/nat/fork-inferior.c | 4 -
|
||||
gdb/nat/gdb_ptrace.h | 2
|
||||
gdb/nat/linux-ptrace.c | 17 +++
|
||||
gdb/nat/linux-ptrace.h | 4 +
|
||||
17 files changed, 418 insertions(+), 15 deletions(-)
|
||||
17 files changed, 422 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h
|
||||
index eb0ec21..4dc07ce 100644
|
||||
|
@ -1071,7 +1071,7 @@ index c3aa20c..e5a57c0 100644
|
|||
init_target_desc (*tdesc, amd64_expedite_regs);
|
||||
}
|
||||
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
|
||||
index 45d5c8d..7b6b1be 100644
|
||||
index 45d5c8d..b246402 100644
|
||||
--- a/gdb/gdbserver/remote-utils.c
|
||||
+++ b/gdb/gdbserver/remote-utils.c
|
||||
@@ -27,6 +27,12 @@
|
||||
|
@ -1099,6 +1099,18 @@ index 45d5c8d..7b6b1be 100644
|
|||
static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
|
||||
|
||||
/* FIXME headerize? */
|
||||
@@ -312,7 +321,11 @@ remote_open (const char *name)
|
||||
struct stat statbuf;
|
||||
|
||||
if (stat (name, &statbuf) == 0
|
||||
+#ifndef __GENODE__
|
||||
&& (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode)))
|
||||
+#else
|
||||
+ )
|
||||
+#endif
|
||||
remote_desc = open (name, O_RDWR);
|
||||
else
|
||||
{
|
||||
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
|
||||
index bf6302b..b6a9494 100644
|
||||
--- a/gdb/gdbserver/server.c
|
||||
|
|
|
@ -271,7 +271,7 @@ class Noux::Pipe_sink_io_channel : public Io_channel
|
|||
|
||||
bool fstat(Sysio &sysio) override
|
||||
{
|
||||
sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
|
||||
sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -345,7 +345,7 @@ class Noux::Pipe_source_io_channel : public Io_channel
|
|||
|
||||
bool fstat(Sysio &sysio) override
|
||||
{
|
||||
sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
|
||||
sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -121,9 +121,6 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
|||
* we use the ones specificed in the config.
|
||||
*/
|
||||
if (result) {
|
||||
stat_out.uid = _user_info.uid();
|
||||
stat_out.gid = _user_info.gid();
|
||||
|
||||
stat_out.inode = path_hash;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,12 +151,7 @@ struct Noux::Terminal_io_channel : Io_channel
|
|||
|
||||
bool fstat(Sysio &sysio) override
|
||||
{
|
||||
/*
|
||||
* Supply stat values such that libc is happy. I.e., the libc
|
||||
* is checking for the file descriptor 1 being a character
|
||||
* device.
|
||||
*/
|
||||
sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
|
||||
sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ struct Noux::Vfs_io_channel : Io_channel
|
|||
*/
|
||||
unsigned const index = _fh.seek() / sizeof(Sysio::Dirent);
|
||||
if (index < 2) {
|
||||
sysio.dirent_out.entry.type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY;
|
||||
sysio.dirent_out.entry.type = Vfs::Directory_service::Dirent_type::DIRECTORY;
|
||||
strncpy(sysio.dirent_out.entry.name,
|
||||
index ? ".." : ".",
|
||||
sizeof(sysio.dirent_out.entry.name));
|
||||
|
@ -284,12 +284,10 @@ struct Noux::Vfs_io_channel : Io_channel
|
|||
* Align index range to zero when calling the directory service.
|
||||
*/
|
||||
|
||||
Vfs::Directory_service::Dirent dirent;
|
||||
|
||||
Vfs::file_size noux_dirent_seek = _fh.seek();
|
||||
_fh.seek((index - 2) * sizeof(dirent));
|
||||
_fh.seek((index - 2) * sizeof(Vfs::Directory_service::Dirent));
|
||||
|
||||
Vfs::file_size const count = sizeof(dirent);
|
||||
Vfs::file_size const count = sizeof(Vfs::Directory_service::Dirent);
|
||||
|
||||
Registered_no_delete<Vfs_io_waiter>
|
||||
vfs_io_waiter(_vfs_io_waiter_registry);
|
||||
|
@ -298,10 +296,10 @@ struct Noux::Vfs_io_channel : Io_channel
|
|||
vfs_io_waiter.wait_for_io();
|
||||
|
||||
Vfs::File_io_service::Read_result read_result;
|
||||
Vfs::file_size out_count = 0;
|
||||
Vfs::file_size out_count = 0;
|
||||
Vfs::Directory_service::Dirent dirent { };
|
||||
|
||||
for (;;) {
|
||||
|
||||
read_result = _fh.fs().complete_read(&_fh, (char*)&dirent,
|
||||
count, out_count);
|
||||
|
||||
|
@ -318,7 +316,7 @@ struct Noux::Vfs_io_channel : Io_channel
|
|||
|
||||
if ((read_result != Vfs::File_io_service::READ_OK) ||
|
||||
(out_count != sizeof(dirent))) {
|
||||
dirent = Vfs::Directory_service::Dirent();
|
||||
dirent = { };
|
||||
}
|
||||
|
||||
_fh.seek(noux_dirent_seek);
|
||||
|
|
Loading…
Reference in New Issue