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);
|
Vfs::file_size index = seek_offset / sizeof(Dirent);
|
||||||
|
|
||||||
Dirent *out = (Dirent*)dst;
|
Dirent &out = *(Dirent*)dst;
|
||||||
|
|
||||||
out->fileno = index+1;
|
|
||||||
out->type = Directory_service::DIRENT_TYPE_END;
|
|
||||||
out->name[0] = '\0';
|
|
||||||
|
|
||||||
Vfs::Node *node = nullptr;
|
Vfs::Node *node = nullptr;
|
||||||
for (Vfs::File *n : _files) {
|
for (Vfs::File *n : _files) {
|
||||||
|
@ -1123,11 +1119,21 @@ class Vfs::Lxip_socket_dir final : public Lxip::Socket_dir
|
||||||
--index;
|
--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);
|
return sizeof(Dirent);
|
||||||
}
|
}
|
||||||
|
@ -1435,11 +1441,7 @@ class Lxip::Protocol_dir_impl : public Protocol_dir
|
||||||
|
|
||||||
Vfs::file_size index = seek_offset / sizeof(Dirent);
|
Vfs::file_size index = seek_offset / sizeof(Dirent);
|
||||||
|
|
||||||
Dirent *out = (Dirent*)dst;
|
Dirent &out = *(Dirent*)dst;
|
||||||
|
|
||||||
out->fileno = index+1;
|
|
||||||
out->type = Vfs::Directory_service::DIRENT_TYPE_END;
|
|
||||||
out->name[0] = '\0';
|
|
||||||
|
|
||||||
Vfs::Node *node = nullptr;
|
Vfs::Node *node = nullptr;
|
||||||
for (Vfs::Node *n : _nodes) {
|
for (Vfs::Node *n : _nodes) {
|
||||||
|
@ -1451,15 +1453,32 @@ class Lxip::Protocol_dir_impl : public Protocol_dir
|
||||||
--index;
|
--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))
|
return -1;
|
||||||
out->type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY;
|
}
|
||||||
|
|
||||||
if (dynamic_cast<Vfs::File*>(node))
|
typedef Vfs::Directory_service::Dirent_type Dirent_type;
|
||||||
out->type = Vfs::Directory_service::DIRENT_TYPE_FILE;
|
|
||||||
|
|
||||||
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);
|
return sizeof(Dirent);
|
||||||
}
|
}
|
||||||
|
@ -1692,44 +1711,38 @@ class Vfs::Lxip_file_system : public Vfs::File_system,
|
||||||
if (len < sizeof(Dirent))
|
if (len < sizeof(Dirent))
|
||||||
return -1;
|
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) {
|
enum { NUM_ENTRIES = 8U };
|
||||||
out->fileno = (Genode::addr_t)&_tcp_dir;
|
static Entry const entries[NUM_ENTRIES] = {
|
||||||
out->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
{ &_tcp_dir, Dirent_type::DIRECTORY, "tcp" },
|
||||||
Genode::strncpy(out->name, "tcp", sizeof(out->name));
|
{ &_udp_dir, Dirent_type::DIRECTORY, "udp" },
|
||||||
} else if (index == 1) {
|
{ &_address, Dirent_type::TRANSACTIONAL_FILE, "address" },
|
||||||
out->fileno = (Genode::addr_t)&_udp_dir;
|
{ &_netmask, Dirent_type::TRANSACTIONAL_FILE, "netmask" },
|
||||||
out->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
{ &_gateway, Dirent_type::TRANSACTIONAL_FILE, "gateway" },
|
||||||
Genode::strncpy(out->name, "udp", sizeof(out->name));
|
{ &_nameserver, Dirent_type::TRANSACTIONAL_FILE, "nameserver" },
|
||||||
} else if (index == 2) {
|
{ &_link_state, Dirent_type::TRANSACTIONAL_FILE, "link_state" },
|
||||||
out->fileno = (Genode::addr_t)&_address;
|
{ nullptr, Dirent_type::END, "" }
|
||||||
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';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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);
|
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
|
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;
|
if (!node) return STAT_ERR_NO_ENTRY;
|
||||||
|
|
||||||
Vfs::Directory *dir = dynamic_cast<Vfs::Directory*>(node);
|
out = { };
|
||||||
if (dir) {
|
|
||||||
out.mode = STAT_MODE_DIRECTORY | 0777;
|
if (dynamic_cast<Vfs::Directory*>(node)) {
|
||||||
|
out.type = Node_type::DIRECTORY;
|
||||||
|
out.rwx = Node_rwx::rwx();
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_cast<Lxip_file*>(node)) {
|
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;
|
out.size = 0;
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_cast<Vfs::File*>(node)) {
|
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 */
|
out.size = 0x1000; /* there may be something to read */
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,25 +197,28 @@ class Vfs::Rump_file_system : public File_system
|
||||||
struct stat s;
|
struct stat s;
|
||||||
rump_sys_lstat(path, &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))
|
return Dirent_type::END;
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
return READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,12 +702,25 @@ class Vfs::Rump_file_system : public File_system
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (rump_sys_lstat(path, &sb) != 0) return STAT_ERR_NO_ENTRY;
|
if (rump_sys_lstat(path, &sb) != 0) return STAT_ERR_NO_ENTRY;
|
||||||
|
|
||||||
stat.size = sb.st_size;
|
auto type = [] (unsigned mode)
|
||||||
stat.mode = sb.st_mode;
|
{
|
||||||
stat.uid = sb.st_uid;
|
if (S_ISDIR(mode)) return Node_type::DIRECTORY;
|
||||||
stat.gid = sb.st_gid;
|
if (S_ISLNK(mode)) return Node_type::SYMLINK;
|
||||||
stat.inode = sb.st_ino;
|
|
||||||
stat.device = sb.st_dev;
|
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;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,18 +218,26 @@ class Rump_fs::Directory : public Node
|
||||||
struct stat s;
|
struct stat s;
|
||||||
rump_sys_lstat(path, &s);
|
rump_sys_lstat(path, &s);
|
||||||
|
|
||||||
Directory_entry *e = (Directory_entry *)(dst);
|
auto type = [] (unsigned mode)
|
||||||
if (S_ISDIR(s.st_mode))
|
{
|
||||||
e->type = Directory_entry::TYPE_DIRECTORY;
|
if (S_ISDIR(mode)) return Node_type::DIRECTORY;
|
||||||
else if (S_ISREG(s.st_mode))
|
else if (S_ISREG(mode)) return Node_type::CONTINUOUS_FILE;
|
||||||
e->type = Directory_entry::TYPE_FILE;
|
else if (S_ISLNK(mode)) return Node_type::SYMLINK;
|
||||||
else if (S_ISLNK(s.st_mode))
|
else return Node_type::CONTINUOUS_FILE;
|
||||||
e->type = Directory_entry::TYPE_SYMLINK;
|
};
|
||||||
else
|
|
||||||
return 0;
|
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);
|
return sizeof(Directory_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,13 +253,15 @@ class Rump_fs::Directory : public Node
|
||||||
if (rump_sys_fstat(_fd, &st) < 0)
|
if (rump_sys_fstat(_fd, &st) < 0)
|
||||||
st.st_mtime = 0;
|
st.st_mtime = 0;
|
||||||
|
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = num_entries() * sizeof (Directory_entry),
|
||||||
s.size = num_entries() * sizeof (Directory_entry);
|
.type = File_system::Node_type::DIRECTORY,
|
||||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||||
s.modification_time = { (int64_t)st.st_mtime };
|
.writeable = (st.st_mode & S_IWUSR),
|
||||||
|
.executable = (st.st_mode & S_IXUSR) },
|
||||||
return s;
|
.inode = inode(),
|
||||||
|
.modification_time = { (int64_t)st.st_mtime }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t num_entries() const
|
size_t num_entries() const
|
||||||
|
|
|
@ -153,20 +153,21 @@ class Rump_fs::File : public Node
|
||||||
|
|
||||||
virtual Status status() override
|
virtual Status status() override
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st { };
|
||||||
if (rump_sys_fstat(_fd, &st) < 0) {
|
if (rump_sys_fstat(_fd, &st) < 0) {
|
||||||
st.st_size = 0;
|
st.st_size = 0;
|
||||||
st.st_mtime = 0;
|
st.st_mtime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status s;
|
return {
|
||||||
|
.size = (file_size_t)st.st_size,
|
||||||
s.inode = inode();
|
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||||
s.size = st.st_size;
|
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||||
s.mode = File_system::Status::MODE_FILE;
|
.writeable = (st.st_mode & S_IWUSR),
|
||||||
s.modification_time = { (int64_t)st.st_mtime };
|
.executable = (st.st_mode & S_IXUSR) },
|
||||||
|
.inode = inode(),
|
||||||
return s;
|
.modification_time = { (int64_t)st.st_mtime }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void truncate(file_size_t size) override
|
void truncate(file_size_t size) override
|
||||||
|
|
|
@ -78,13 +78,15 @@ class Rump_fs::Symlink : public Node
|
||||||
st.st_mtime = 0;
|
st.st_mtime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = length(),
|
||||||
s.size = length();
|
.type = File_system::Node_type::SYMLINK,
|
||||||
s.mode = File_system::Status::MODE_SYMLINK;
|
.rwx = { .readable = true,
|
||||||
s.modification_time = { (int64_t)st.st_mtime };
|
.writeable = true,
|
||||||
|
.executable = true },
|
||||||
return s;
|
.inode = inode(),
|
||||||
|
.modification_time = { (int64_t)st.st_mtime }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
file_size_t length()
|
file_size_t length()
|
||||||
|
|
|
@ -56,20 +56,22 @@ struct Genode::Directory : Noncopyable, Interface
|
||||||
{
|
{
|
||||||
using Genode::print;
|
using Genode::print;
|
||||||
using Vfs::Directory_service;
|
using Vfs::Directory_service;
|
||||||
|
using Dirent_type = Directory_service::Dirent_type;
|
||||||
|
|
||||||
print(out, _dirent.name, " (");
|
print(out, _dirent.name.buf, " (");
|
||||||
switch (_dirent.type) {
|
switch (_dirent.type) {
|
||||||
case Directory_service::DIRENT_TYPE_FILE: print(out, "file"); break;
|
case Dirent_type::TRANSACTIONAL_FILE: print(out, "file"); break;
|
||||||
case Directory_service::DIRENT_TYPE_DIRECTORY: print(out, "dir"); break;
|
case Dirent_type::CONTINUOUS_FILE: print(out, "file"); break;
|
||||||
case Directory_service::DIRENT_TYPE_SYMLINK: print(out, "symlink"); break;
|
case Dirent_type::DIRECTORY: print(out, "dir"); break;
|
||||||
default: print(out, "other"); break;
|
case Dirent_type::SYMLINK: print(out, "symlink"); break;
|
||||||
|
default: print(out, "other"); break;
|
||||||
}
|
}
|
||||||
print(out, ")");
|
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; }
|
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);
|
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;
|
return _nonconst_fs().stat(join(_path, rel_path).string(), out);
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -199,7 +195,7 @@ struct Genode::Directory : Noncopyable, Interface
|
||||||
throw Read_dir_failed();
|
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;
|
return;
|
||||||
|
|
||||||
fn(entry);
|
fn(entry);
|
||||||
|
@ -215,12 +211,23 @@ struct Genode::Directory : Noncopyable, Interface
|
||||||
|
|
||||||
bool file_exists(Path const &rel_path) const
|
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
|
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::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();
|
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(other, rel_path), _watcher(other, rel_path, handler)
|
||||||
{
|
{
|
||||||
_dir.for_each_entry([&] (Directory::Entry const &entry) {
|
_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 {
|
try {
|
||||||
new (_alloc) Registered<Watched_file>(_files, _dir, entry.name(), handler);
|
new (_alloc) Registered<Watched_file>(_files, _dir, entry.name(), handler);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
|
@ -189,19 +189,20 @@ class Vfs_import::File_system : public Vfs::File_system
|
||||||
dir.for_each_entry([&] (Directory::Entry const &e) {
|
dir.for_each_entry([&] (Directory::Entry const &e) {
|
||||||
auto entry_path = Directory::join(path, e.name());
|
auto entry_path = Directory::join(path, e.name());
|
||||||
switch (e.type()) {
|
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);
|
copy_file(env, src, entry_path, alloc, overwrite);
|
||||||
break;
|
return;
|
||||||
case DIRENT_TYPE_DIRECTORY:
|
case Dirent_type::DIRECTORY:
|
||||||
copy_dir(env, src, entry_path, alloc, overwrite);
|
copy_dir(env, src, entry_path, alloc, overwrite);
|
||||||
break;
|
return;
|
||||||
case DIRENT_TYPE_SYMLINK:
|
case Dirent_type::SYMLINK:
|
||||||
copy_symlink(env, src, entry_path, alloc, overwrite);
|
copy_symlink(env, src, entry_path, alloc, overwrite);
|
||||||
break;
|
return;
|
||||||
default:
|
case Dirent_type::END:
|
||||||
Genode::warning("skipping copy of ", e);
|
return;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
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)
|
Value_file_system(Name const &name, Buffer const &initial_value)
|
||||||
:
|
:
|
||||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, type(),
|
Single_file_system(Node_type::TRANSACTIONAL_FILE, type(),
|
||||||
Xml_node(_config(name).string())),
|
Node_rwx::rw(), Xml_node(_config(name).string())),
|
||||||
_file_name(name)
|
_file_name(name)
|
||||||
{
|
{
|
||||||
value(initial_value);
|
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 stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
Stat_result result = Single_file_system::stat(path, out);
|
Stat_result result = Single_file_system::stat(path, out);
|
||||||
out.mode |= 0666;
|
|
||||||
out.size = BUF_SIZE + 1;
|
out.size = BUF_SIZE + 1;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,8 +155,8 @@ class Vfs_trace::Trace_buffer_file_system : public Single_file_system
|
||||||
Trace::Connection &trace,
|
Trace::Connection &trace,
|
||||||
Trace::Policy_id policy,
|
Trace::Policy_id policy,
|
||||||
Trace::Subject_id id)
|
Trace::Subject_id id)
|
||||||
: Single_file_system(NODE_TYPE_CHAR_DEVICE,
|
: Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||||
type_name(), Xml_node(_config().string())),
|
Node_rwx::rw(), Xml_node(_config().string())),
|
||||||
_env(env), _trace(trace), _policy(policy), _id(id)
|
_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)
|
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)
|
_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 stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
Stat_result result = Single_file_system::stat(path, out);
|
Stat_result result = Single_file_system::stat(path, out);
|
||||||
out.mode |= 0444;
|
|
||||||
out.size = FILE_SIZE;
|
out.size = FILE_SIZE;
|
||||||
return result;
|
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 };
|
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;
|
auto type = [] (Vfs::Node_type type)
|
||||||
dst->st_gid = src.gid;
|
{
|
||||||
dst->st_mode = src.mode;
|
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_size = src.size;
|
||||||
dst->st_blksize = FS_BLOCK_SIZE;
|
dst->st_blksize = FS_BLOCK_SIZE;
|
||||||
dst->st_blocks = (dst->st_size + FS_BLOCK_SIZE - 1) / 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);
|
_vfs_sync(*handle);
|
||||||
fd->modified = false;
|
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,
|
(char*)&dirent_out,
|
||||||
sizeof(Dirent),
|
sizeof(Dirent),
|
||||||
out_count));
|
out_count));
|
||||||
|
dirent_out.sanitize();
|
||||||
|
|
||||||
/* suspend me if read is still queued */
|
/* suspend me if read is still queued */
|
||||||
|
|
||||||
|
@ -851,29 +881,37 @@ ssize_t Libc::Vfs_plugin::getdirentries(File_descriptor *fd, char *buf,
|
||||||
return 0;
|
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
|
* Convert dirent structure from VFS to libc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dirent *dirent = (struct dirent *)buf;
|
auto dirent_type = [] (Dirent_type type)
|
||||||
Genode::memset(dirent, 0, sizeof(struct dirent));
|
{
|
||||||
|
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) {
|
dirent &dirent = *(struct dirent *)buf;
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break;
|
dirent = { };
|
||||||
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->d_fileno = dirent_out.fileno;
|
dirent.d_type = dirent_type(dirent_out.type);
|
||||||
dirent->d_reclen = sizeof(struct dirent);
|
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.
|
* 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;
|
cur_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirent *vfs_dir = (Dirent*)buf;
|
Dirent &vfs_dirent = *(Dirent*)buf;
|
||||||
|
|
||||||
FILINFO info;
|
FILINFO info;
|
||||||
FRESULT res;
|
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) {
|
while (cur_index <= dir_index) {
|
||||||
res = f_readdir (&dir, &info);
|
res = f_readdir (&dir, &info);
|
||||||
if ((res != FR_OK) || (!info.fname[0])) {
|
if ((res != FR_OK) || (!info.fname[0])) {
|
||||||
f_readdir(&dir, nullptr);
|
f_readdir(&dir, nullptr);
|
||||||
cur_index = 0;
|
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);
|
out_count = sizeof(Dirent);
|
||||||
return READ_OK;
|
return READ_OK;
|
||||||
}
|
}
|
||||||
cur_index++;
|
cur_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
vfs_dir->type = (info.fattrib & AM_DIR) ?
|
vfs_dirent = {
|
||||||
DIRENT_TYPE_DIRECTORY : DIRENT_TYPE_FILE;
|
.fileno = fileno,
|
||||||
Genode::strncpy(vfs_dir->name, (const char*)info.fname,
|
.type = (info.fattrib & AM_DIR)
|
||||||
sizeof(vfs_dir->name));
|
? Dirent_type::DIRECTORY
|
||||||
|
: Dirent_type::CONTINUOUS_FILE,
|
||||||
|
.rwx = Node_rwx::rwx(),
|
||||||
|
.name = { (char const *)info.fname }
|
||||||
|
};
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
return READ_OK;
|
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_result stat(char const *path, Stat &stat) override
|
||||||
{
|
{
|
||||||
stat = Stat();
|
stat = Stat { };
|
||||||
|
|
||||||
FILINFO info;
|
FILINFO info;
|
||||||
|
|
||||||
FRESULT const err = f_stat((const TCHAR*)path, &info);
|
FRESULT const err = f_stat((const TCHAR*)path, &info);
|
||||||
switch (err) {
|
switch (err) {
|
||||||
case FR_OK:
|
case FR_OK:
|
||||||
stat.inode = 1;
|
stat.inode = 1;
|
||||||
stat.device = (Genode::addr_t)this;
|
stat.device = (Genode::addr_t)this;
|
||||||
stat.mode = (info.fattrib & AM_DIR) ?
|
stat.type = (info.fattrib & AM_DIR)
|
||||||
STAT_MODE_DIRECTORY : STAT_MODE_FILE;
|
? Vfs::Node_type::DIRECTORY
|
||||||
|
: Vfs::Node_type::CONTINUOUS_FILE;
|
||||||
|
stat.rwx = Vfs::Node_rwx::rwx();
|
||||||
|
|
||||||
/* XXX: size in f_stat is always zero */
|
/* 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);
|
File *file = _opened_file(path);
|
||||||
if (file) {
|
if (file) {
|
||||||
stat.size = f_size(&file->fil);
|
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,
|
Jitterentropy_file_system(Genode::Allocator &alloc,
|
||||||
Genode::Xml_node config)
|
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),
|
_ec_stir(0),
|
||||||
_initialized(_init_jitterentropy(alloc))
|
_initialized(_init_jitterentropy(alloc))
|
||||||
{ }
|
{ }
|
||||||
|
|
|
@ -603,35 +603,51 @@ class Lwip::Protocol_dir_impl final : public Protocol_dir
|
||||||
Path subpath(path);
|
Path subpath(path);
|
||||||
|
|
||||||
if (subpath == "/") {
|
if (subpath == "/") {
|
||||||
st.size = 1;
|
st = { .size = 1,
|
||||||
st.mode = Directory_service::STAT_MODE_DIRECTORY;
|
.type = Node_type::DIRECTORY,
|
||||||
st.inode = (Genode::addr_t)this;
|
.rwx = Node_rwx::rwx(),
|
||||||
|
.inode = (Genode::addr_t)this,
|
||||||
|
.device = 0,
|
||||||
|
.modification_time = { 0 } };
|
||||||
return Directory_service::STAT_OK;
|
return Directory_service::STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subpath == "/new_socket") {
|
if (subpath == "/new_socket") {
|
||||||
st.size = 1;
|
st = { .size = 1,
|
||||||
st.mode = Directory_service::STAT_MODE_FILE | 0777;
|
.type = Node_type::TRANSACTIONAL_FILE,
|
||||||
st.inode = ((Genode::addr_t)this)+1;
|
.rwx = Node_rwx::rw(),
|
||||||
|
.inode = (Genode::addr_t)this + 1,
|
||||||
|
.device = 0,
|
||||||
|
.modification_time = { 0 } };
|
||||||
return Directory_service::STAT_OK;
|
return Directory_service::STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subpath.has_single_element())
|
if (!subpath.has_single_element())
|
||||||
subpath.strip_last_element();
|
subpath.strip_last_element();
|
||||||
|
|
||||||
if (SOCKET_DIR *dir = lookup(subpath.string())) {
|
if (SOCKET_DIR *dir = lookup(subpath.string())) {
|
||||||
Path filename(path);
|
Path filename(path);
|
||||||
filename.keep_only_last_element();
|
filename.keep_only_last_element();
|
||||||
if (filename == subpath.base()) {
|
if (filename == subpath.base()) {
|
||||||
st.size = Lwip_file_handle::INVALID;
|
st = { .size = 0,
|
||||||
st.mode = Directory_service::STAT_MODE_DIRECTORY;
|
.type = Node_type::DIRECTORY,
|
||||||
st.inode = (Genode::addr_t)dir;
|
.rwx = Node_rwx::rwx(),
|
||||||
|
.inode = (Genode::addr_t)dir,
|
||||||
|
.device = 0,
|
||||||
|
.modification_time = { 0 } };
|
||||||
return Directory_service::STAT_OK;
|
return Directory_service::STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lwip_file_handle::Kind k = Lwip_file_handle::kind_from_name(filename);
|
Lwip_file_handle::Kind k = Lwip_file_handle::kind_from_name(filename);
|
||||||
if (k != Lwip_file_handle::INVALID) {
|
if (k != Lwip_file_handle::INVALID) {
|
||||||
st.mode = Directory_service::STAT_MODE_CHARDEV;
|
st = { .size = 0,
|
||||||
st.inode = ((Genode::addr_t)dir)+k;
|
.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;
|
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
|
Stat_result stat(char const *path, Stat &st) override
|
||||||
{
|
{
|
||||||
if (*path == '/') ++path;
|
if (*path == '/') ++path;
|
||||||
st = Stat();
|
st = Stat { };
|
||||||
st.device = (Genode::addr_t)this;
|
st.device = (Genode::addr_t)this;
|
||||||
|
|
||||||
if (match_address(path) || match_netmask(path)) {
|
if (match_address(path) || match_netmask(path)) {
|
||||||
st.size = ADDRESS_FILE_SIZE;
|
st = { .size = ADDRESS_FILE_SIZE,
|
||||||
st.mode = STAT_MODE_FILE;
|
.type = Node_type::TRANSACTIONAL_FILE,
|
||||||
|
.rwx = Node_rwx::rw(),
|
||||||
|
.inode = (Genode::addr_t)this,
|
||||||
|
.device = 0,
|
||||||
|
.modification_time = { 0 } };
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_nameserver(path)) {
|
if (match_nameserver(path)) {
|
||||||
st.size = IPADDR_STRLEN_MAX;
|
st = { .size = IPADDR_STRLEN_MAX,
|
||||||
st.mode = STAT_MODE_FILE;
|
.type = Node_type::TRANSACTIONAL_FILE,
|
||||||
|
.rwx = Node_rwx::rw(),
|
||||||
|
.inode = 0,
|
||||||
|
.device = 0,
|
||||||
|
.modification_time = { 0 } };
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,6 @@ class Fatfs_fs::Directory : public Node
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory_entry *e = (Directory_entry *)(dst);
|
|
||||||
|
|
||||||
using namespace Fatfs;
|
using namespace Fatfs;
|
||||||
|
|
||||||
FILINFO fatfs_file_info;
|
FILINFO fatfs_file_info;
|
||||||
|
@ -99,12 +97,17 @@ class Fatfs_fs::Directory : public Node
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(e->name, fatfs_file_info.fname, sizeof(e->name));
|
Directory_entry &e = *(Directory_entry *)(dst);
|
||||||
|
e = {
|
||||||
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
|
.inode = 0,
|
||||||
e->type = Directory_entry::TYPE_DIRECTORY;
|
.type = ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR)
|
||||||
else
|
? Node_type::DIRECTORY
|
||||||
e->type = Directory_entry::TYPE_FILE;
|
: Node_type::CONTINUOUS_FILE,
|
||||||
|
.rwx = { .readable = true,
|
||||||
|
.writeable = true,
|
||||||
|
.executable = true },
|
||||||
|
.name = { fatfs_file_info.fname }
|
||||||
|
};
|
||||||
|
|
||||||
return sizeof(Directory_entry);
|
return sizeof(Directory_entry);
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,6 +133,10 @@ class Fatfs_fs::Session_component : public Session_rpc_object
|
||||||
succeeded = true;
|
succeeded = true;
|
||||||
/* not supported */
|
/* not supported */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Packet_descriptor::WRITE_TIMESTAMP:
|
||||||
|
succeeded = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.length(res_length);
|
packet.length(res_length);
|
||||||
|
@ -537,8 +541,9 @@ class Fatfs_fs::Session_component : public Session_rpc_object
|
||||||
Status status;
|
Status status;
|
||||||
status.inode = 1;
|
status.inode = 1;
|
||||||
status.size = 0;
|
status.size = 0;
|
||||||
status.mode = 0;
|
status.rwx = { .readable = true,
|
||||||
|
.writeable = true,
|
||||||
|
.executable = true };
|
||||||
Node &node = open_node.node();
|
Node &node = open_node.node();
|
||||||
|
|
||||||
using namespace Fatfs;
|
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) {
|
if ((fatfs_file_info.fattrib & AM_DIR) == AM_DIR) {
|
||||||
status.mode = File_system::Status::MODE_DIRECTORY; }
|
status.type = File_system::Node_type::DIRECTORY; }
|
||||||
else {
|
else {
|
||||||
status.mode = File_system::Status::MODE_FILE;
|
status.type = File_system::Node_type::CONTINUOUS_FILE;
|
||||||
status.size = fatfs_file_info.fsize;
|
status.size = fatfs_file_info.fsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} 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 */
|
/* determine the number of directory entries */
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#ifndef _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_
|
#ifndef _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_
|
||||||
#define _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 <base/exception.h>
|
||||||
#include <os/packet_stream.h>
|
#include <os/packet_stream.h>
|
||||||
#include <packet_stream_tx/packet_stream_tx.h>
|
#include <packet_stream_tx/packet_stream_tx.h>
|
||||||
|
@ -66,6 +67,20 @@ namespace File_system {
|
||||||
typedef Symlink::Id Symlink_handle;
|
typedef Symlink::Id Symlink_handle;
|
||||||
typedef Watch::Id Watch_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;
|
using Genode::size_t;
|
||||||
|
|
||||||
typedef Genode::uint64_t seek_off_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
|
struct File_system::Status
|
||||||
{
|
{
|
||||||
enum {
|
|
||||||
MODE_SYMLINK = 0020000,
|
|
||||||
MODE_FILE = 0100000,
|
|
||||||
MODE_DIRECTORY = 0040000,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX add executable bit
|
|
||||||
*/
|
|
||||||
|
|
||||||
file_size_t size;
|
file_size_t size;
|
||||||
unsigned mode;
|
Node_type type;
|
||||||
|
Node_rwx rwx;
|
||||||
unsigned long inode;
|
unsigned long inode;
|
||||||
Timestamp modification_time;
|
Timestamp modification_time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if node is a directory
|
* 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
|
* 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
|
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;
|
unsigned long inode;
|
||||||
Type type;
|
Node_type type;
|
||||||
char name[MAX_NAME_LEN];
|
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))
|
if (count < sizeof(Dirent))
|
||||||
return READ_ERR_INVALID;
|
return READ_ERR_INVALID;
|
||||||
|
|
||||||
Dirent *dirent = (Dirent*)dst;
|
Dirent &dirent = *(Dirent*)dst;
|
||||||
*dirent = Dirent();
|
dirent = Dirent { };
|
||||||
|
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
|
|
||||||
|
@ -456,13 +456,14 @@ class Vfs::Dir_file_system : public File_system
|
||||||
* current directory.
|
* current directory.
|
||||||
*/
|
*/
|
||||||
if (strlen(path) == 0 || _top_dir(path)) {
|
if (strlen(path) == 0 || _top_dir(path)) {
|
||||||
out.size = 0;
|
out = {
|
||||||
out.mode = STAT_MODE_DIRECTORY | 0755;
|
.size = 0,
|
||||||
out.uid = 0;
|
.type = Node_type::DIRECTORY,
|
||||||
out.gid = 0;
|
.rwx = Node_rwx::rwx(),
|
||||||
out.inode = 1;
|
.inode = 1,
|
||||||
out.device = (Genode::addr_t)this;
|
.device = (Genode::addr_t)this,
|
||||||
out.modification_time = { Vfs::Timestamp::INVALID };
|
.modification_time = { Vfs::Timestamp::INVALID },
|
||||||
|
};
|
||||||
return STAT_OK;
|
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);
|
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
||||||
|
|
||||||
if (_top_dir(dir_vfs_handle->path.base())) {
|
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) {
|
if (index == 0) {
|
||||||
strncpy(dirent->name, _name.string(), sizeof(dirent->name));
|
|
||||||
|
|
||||||
dirent->type = DIRENT_TYPE_DIRECTORY;
|
dirent = {
|
||||||
dirent->fileno = 1;
|
.fileno = 1,
|
||||||
|
.type = Dirent_type::DIRECTORY,
|
||||||
|
.rwx = Node_rwx::rwx(),
|
||||||
|
.name = { _name.string() }
|
||||||
|
};
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dirent->type = DIRENT_TYPE_END;
|
|
||||||
|
dirent = {
|
||||||
|
.fileno = 0,
|
||||||
|
.type = Dirent_type::END,
|
||||||
|
.rwx = { },
|
||||||
|
.name = { }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
|
|
|
@ -141,26 +141,14 @@ struct Vfs::Directory_service : Interface
|
||||||
** Stat **
|
** 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
|
struct Stat
|
||||||
{
|
{
|
||||||
file_size size = 0;
|
file_size size;
|
||||||
unsigned mode = 0;
|
Node_type type;
|
||||||
unsigned uid = 0;
|
Node_rwx rwx;
|
||||||
unsigned gid = 0;
|
unsigned long inode;
|
||||||
unsigned long inode = 0;
|
unsigned long device;
|
||||||
unsigned long device = 0;
|
Timestamp modification_time;
|
||||||
Timestamp modification_time { Timestamp::INVALID };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS,
|
enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS,
|
||||||
|
@ -177,23 +165,42 @@ struct Vfs::Directory_service : Interface
|
||||||
** Dirent **
|
** Dirent **
|
||||||
************/
|
************/
|
||||||
|
|
||||||
enum { DIRENT_MAX_NAME_LEN = 128 };
|
enum class Dirent_type
|
||||||
|
{
|
||||||
enum Dirent_type {
|
END,
|
||||||
DIRENT_TYPE_FILE,
|
DIRECTORY,
|
||||||
DIRENT_TYPE_DIRECTORY,
|
SYMLINK,
|
||||||
DIRENT_TYPE_FIFO,
|
CONTINUOUS_FILE,
|
||||||
DIRENT_TYPE_CHARDEV,
|
TRANSACTIONAL_FILE,
|
||||||
DIRENT_TYPE_BLOCKDEV,
|
|
||||||
DIRENT_TYPE_SYMLINK,
|
|
||||||
DIRENT_TYPE_END
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Dirent
|
struct Dirent
|
||||||
{
|
{
|
||||||
unsigned long fileno = 0;
|
struct Name
|
||||||
Dirent_type type = DIRENT_TYPE_END;
|
{
|
||||||
char name[DIRENT_MAX_NAME_LEN] = { 0 };
|
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)
|
Readonly_value_file_system(Name const &name, T const &initial_value)
|
||||||
:
|
:
|
||||||
Single_file_system(NODE_TYPE_CHAR_DEVICE, type(),
|
Single_file_system(Node_type::TRANSACTIONAL_FILE, type(),
|
||||||
Xml_node(_config(name).string())),
|
Node_rwx::ro(), Xml_node(_config(name).string())),
|
||||||
_file_name(name)
|
_file_name(name)
|
||||||
{
|
{
|
||||||
value(initial_value);
|
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 stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
Stat_result result = Single_file_system::stat(path, out);
|
Stat_result result = Single_file_system::stat(path, out);
|
||||||
out.mode |= 0444;
|
|
||||||
out.size = _buffer.length();
|
out.size = _buffer.length();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,10 @@ namespace Vfs { class Single_file_system; }
|
||||||
|
|
||||||
class Vfs::Single_file_system : public 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:
|
private:
|
||||||
|
|
||||||
Node_type const _node_type;
|
Node_type const _type;
|
||||||
|
Node_rwx const _rwx;
|
||||||
|
|
||||||
typedef String<64> Filename;
|
typedef String<64> Filename;
|
||||||
|
|
||||||
|
@ -61,8 +55,10 @@ class Vfs::Single_file_system : public File_system
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Node_type _node_type;
|
Node_type const _type;
|
||||||
char const *_filename;
|
Node_rwx const _rwx;
|
||||||
|
|
||||||
|
Filename const &_filename;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Noncopyable
|
* Noncopyable
|
||||||
|
@ -75,12 +71,12 @@ class Vfs::Single_file_system : public File_system
|
||||||
Single_vfs_dir_handle(Directory_service &ds,
|
Single_vfs_dir_handle(Directory_service &ds,
|
||||||
File_io_service &fs,
|
File_io_service &fs,
|
||||||
Genode::Allocator &alloc,
|
Genode::Allocator &alloc,
|
||||||
Node_type node_type,
|
Node_type type,
|
||||||
char const *filename)
|
Node_rwx rwx,
|
||||||
|
Filename const &filename)
|
||||||
:
|
:
|
||||||
Single_vfs_handle(ds, fs, alloc, 0),
|
Single_vfs_handle(ds, fs, alloc, 0),
|
||||||
_node_type(node_type),
|
_type(type), _rwx(rwx), _filename(filename)
|
||||||
_filename(filename)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Read_result read(char *dst, file_size count,
|
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);
|
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) {
|
if (index == 0) {
|
||||||
out->fileno = (Genode::addr_t)this;
|
out = {
|
||||||
switch (_node_type) {
|
.fileno = (Genode::addr_t)this,
|
||||||
case NODE_TYPE_FILE: out->type = DIRENT_TYPE_FILE; break;
|
.type = dirent_type(),
|
||||||
case NODE_TYPE_SYMLINK: out->type = DIRENT_TYPE_SYMLINK; break;
|
.rwx = _rwx,
|
||||||
case NODE_TYPE_CHAR_DEVICE: out->type = DIRENT_TYPE_CHARDEV; break;
|
.name = { _filename.string() }
|
||||||
case NODE_TYPE_BLOCK_DEVICE: out->type = DIRENT_TYPE_BLOCKDEV; break;
|
};
|
||||||
}
|
|
||||||
strncpy(out->name, _filename, sizeof(out->name));
|
|
||||||
} else {
|
} else {
|
||||||
out->type = DIRENT_TYPE_END;
|
out = {
|
||||||
|
.fileno = (Genode::addr_t)this,
|
||||||
|
.type = Dirent_type::END,
|
||||||
|
.rwx = { },
|
||||||
|
.name = { }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
|
@ -134,9 +144,12 @@ class Vfs::Single_file_system : public File_system
|
||||||
|
|
||||||
public:
|
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)))
|
_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
|
Stat_result stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
out = Stat();
|
out = Stat { };
|
||||||
out.device = (Genode::addr_t)this;
|
out.device = (Genode::addr_t)this;
|
||||||
|
|
||||||
if (_root(path)) {
|
if (_root(path)) {
|
||||||
out.mode = STAT_MODE_DIRECTORY;
|
out.type = Node_type::DIRECTORY;
|
||||||
|
|
||||||
} else if (_single_file(path)) {
|
} else if (_single_file(path)) {
|
||||||
switch (_node_type) {
|
out.type = _type;
|
||||||
case NODE_TYPE_FILE: out.mode = STAT_MODE_FILE; break;
|
out.rwx = _rwx;
|
||||||
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.inode = 1;
|
out.inode = 1;
|
||||||
} else {
|
} else {
|
||||||
return STAT_ERR_NO_ENTRY;
|
return STAT_ERR_NO_ENTRY;
|
||||||
|
@ -208,7 +217,7 @@ class Vfs::Single_file_system : public File_system
|
||||||
try {
|
try {
|
||||||
*out_handle = new (alloc)
|
*out_handle = new (alloc)
|
||||||
Single_vfs_dir_handle(*this, *this, alloc,
|
Single_vfs_dir_handle(*this, *this, alloc,
|
||||||
_node_type, _filename.string());
|
_type, _rwx, _filename);
|
||||||
return OPENDIR_OK;
|
return OPENDIR_OK;
|
||||||
}
|
}
|
||||||
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
|
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
|
||||||
|
|
|
@ -55,6 +55,36 @@ namespace Vfs {
|
||||||
long long value;
|
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;
|
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 _subsystem_suffix(Vfs::Directory_service::Dirent const &dirent)
|
||||||
{
|
{
|
||||||
unsigned found = 0;
|
unsigned found = 0;
|
||||||
for (unsigned i = 0; i < sizeof(dirent.name) && dirent.name[i]; i++)
|
for (unsigned i = 0; i < sizeof(dirent.name.buf) && dirent.name.buf[i]; i++)
|
||||||
if (Genode::strcmp(_subsystem_suffix(), &dirent.name[i]) == 0)
|
if (Genode::strcmp(_subsystem_suffix(), &dirent.name.buf[i]) == 0)
|
||||||
found = i;
|
found = i;
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
@ -155,7 +155,7 @@ class Cli_monitor::Subsystem_config_registry
|
||||||
/* iterate over the directory entries */
|
/* iterate over the directory entries */
|
||||||
for (unsigned i = 0;; i++) {
|
for (unsigned i = 0;; i++) {
|
||||||
|
|
||||||
Vfs::Directory_service::Dirent dirent;
|
Vfs::Directory_service::Dirent dirent { };
|
||||||
|
|
||||||
dir_handle->seek(i * sizeof(dirent));
|
dir_handle->seek(i * sizeof(dirent));
|
||||||
dir_handle->fs().queue_read(dir_handle, 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)
|
Vfs::File_io_service::READ_QUEUED)
|
||||||
_ep.wait_and_dispatch_one_io_signal();
|
_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);
|
_fs.close(dir_handle);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -179,8 +179,8 @@ class Cli_monitor::Subsystem_config_registry
|
||||||
if (subsystem_suffix) {
|
if (subsystem_suffix) {
|
||||||
|
|
||||||
/* subsystem name is file name without the suffix */
|
/* subsystem name is file name without the suffix */
|
||||||
char name[sizeof(dirent.name)];
|
char name[sizeof(dirent.name.buf)];
|
||||||
Genode::strncpy(name, dirent.name, subsystem_suffix + 1);
|
Genode::strncpy(name, dirent.name.buf, subsystem_suffix + 1);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for_config(name, fn);
|
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)
|
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),
|
_env(env),
|
||||||
_label(config.attribute_value("label", Label())),
|
_label(config.attribute_value("label", Label())),
|
||||||
_block_buffer(0),
|
_block_buffer(0),
|
||||||
|
|
|
@ -69,6 +69,50 @@ class Vfs::Fs_file_system : public File_system
|
||||||
struct Fs_vfs_handle;
|
struct Fs_vfs_handle;
|
||||||
typedef Genode::Fifo<Fs_vfs_handle> Fs_vfs_handle_queue;
|
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,
|
struct Fs_vfs_handle : Vfs_handle,
|
||||||
private ::File_system::Node,
|
private ::File_system::Node,
|
||||||
private Handle_space::Element,
|
private Handle_space::Element,
|
||||||
|
@ -295,41 +339,38 @@ class Vfs::Fs_file_system : public File_system
|
||||||
|
|
||||||
using ::File_system::Directory_entry;
|
using ::File_system::Directory_entry;
|
||||||
|
|
||||||
Directory_entry entry;
|
Directory_entry entry { };
|
||||||
file_size entry_out_count;
|
file_size entry_out_count = 0;
|
||||||
|
|
||||||
Read_result read_result =
|
Read_result const read_result =
|
||||||
_complete_read(&entry, DIRENT_SIZE, entry_out_count);
|
_complete_read(&entry, DIRENT_SIZE, entry_out_count);
|
||||||
|
|
||||||
if (read_result != READ_OK)
|
if (read_result != READ_OK)
|
||||||
return read_result;
|
return read_result;
|
||||||
|
|
||||||
Dirent *dirent = (Dirent*)dst;
|
entry.sanitize();
|
||||||
|
|
||||||
|
Dirent &dirent = *(Dirent*)dst;
|
||||||
|
|
||||||
if (entry_out_count < DIRENT_SIZE) {
|
if (entry_out_count < DIRENT_SIZE) {
|
||||||
|
|
||||||
/* no entry found for the given index, or error */
|
/* 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);
|
out_count = sizeof(Dirent);
|
||||||
return READ_OK;
|
return READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
dirent = Dirent {
|
||||||
* The default value has no meaning because the switch below
|
.fileno = entry.inode,
|
||||||
* assigns a value in each possible branch. But it is needed to
|
.type = _dirent_type(entry.type),
|
||||||
* keep the compiler happy.
|
.rwx = _node_rwx(entry.rwx),
|
||||||
*/
|
.name = { entry.name.buf }
|
||||||
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));
|
|
||||||
|
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
|
|
||||||
|
@ -646,20 +687,13 @@ class Vfs::Fs_file_system : public File_system
|
||||||
|
|
||||||
out = Stat();
|
out = Stat();
|
||||||
|
|
||||||
out.size = status.size;
|
out.size = status.size;
|
||||||
out.mode = STAT_MODE_FILE | 0777;
|
out.type = _node_type(status.type);
|
||||||
|
out.rwx = _node_rwx(status.rwx);
|
||||||
if (status.symlink())
|
out.inode = status.inode;
|
||||||
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.device = (Genode::addr_t)this;
|
out.device = (Genode::addr_t)this;
|
||||||
out.modification_time.value = status.modification_time.value;
|
out.modification_time.value = status.modification_time.value;
|
||||||
|
|
||||||
return STAT_OK;
|
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)
|
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"; }
|
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 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) {
|
_node.with_raw_content([&] (char const *, Genode::size_t size) {
|
||||||
out.size = size; });
|
out.size = size; });
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -141,7 +141,8 @@ class Vfs::Log_file_system : public Single_file_system
|
||||||
Log_file_system(Vfs::Env &env,
|
Log_file_system(Vfs::Env &env,
|
||||||
Genode::Xml_node config)
|
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())),
|
_label(config.attribute_value("label", Label())),
|
||||||
_log(_log_session(env.env()))
|
_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)
|
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"; }
|
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::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)
|
virtual size_t read(char*, size_t, file_size)
|
||||||
{
|
{
|
||||||
Genode::error("Vfs_ram::Node::read() called");
|
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);
|
file_offset index = seek_offset / sizeof(Dirent);
|
||||||
|
|
||||||
Dirent *dirent = (Dirent*)dst;
|
Dirent &dirent = *(Dirent*)dst;
|
||||||
*dirent = Dirent();
|
|
||||||
|
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||||
|
|
||||||
out_count = sizeof(Dirent);
|
out_count = sizeof(Dirent);
|
||||||
|
|
||||||
Node *node = _entries.first();
|
Node *node_ptr = _entries.first();
|
||||||
if (node) node = node->index(index);
|
if (node_ptr) node_ptr = node_ptr->index(index);
|
||||||
if (!node) {
|
if (!node_ptr) {
|
||||||
dirent->type = Directory_service::DIRENT_TYPE_END;
|
dirent.type = Dirent_type::END;
|
||||||
return Vfs::File_io_service::READ_OK;
|
return Vfs::File_io_service::READ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirent->fileno = node->inode;
|
Node &node = *node_ptr;
|
||||||
strncpy(dirent->name, node->name(), sizeof(dirent->name));
|
|
||||||
|
|
||||||
File *file = dynamic_cast<File *>(node);
|
auto dirent_type = [&] ()
|
||||||
if (file) {
|
{
|
||||||
dirent->type = Directory_service::DIRENT_TYPE_FILE;
|
if (dynamic_cast<File *>(node_ptr)) return Dirent_type::CONTINUOUS_FILE;
|
||||||
return Vfs::File_io_service::READ_OK;
|
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);
|
return Dirent_type::END;
|
||||||
if (dir) {
|
};
|
||||||
dirent->type = Directory_service::DIRENT_TYPE_DIRECTORY;
|
|
||||||
return Vfs::File_io_service::READ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Symlink *symlink = dynamic_cast<Symlink *>(node);
|
Dirent_type const type = dirent_type();
|
||||||
if (symlink) {
|
|
||||||
dirent->type = Directory_service::DIRENT_TYPE_SYMLINK;
|
|
||||||
return Vfs::File_io_service::READ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
using namespace Vfs_ram;
|
||||||
|
|
||||||
Node *node = lookup(path);
|
Node *node_ptr = lookup(path);
|
||||||
if (!node) return STAT_ERR_NO_ENTRY;
|
if (!node_ptr) return STAT_ERR_NO_ENTRY;
|
||||||
Node::Guard guard(node);
|
|
||||||
|
|
||||||
stat.size = node->length();
|
Node::Guard guard(node_ptr);
|
||||||
stat.inode = node->inode;
|
|
||||||
stat.device = (Genode::addr_t)this;
|
|
||||||
stat.modification_time = node->modification_time();
|
|
||||||
|
|
||||||
File *file = dynamic_cast<File *>(node);
|
Node &node = *node_ptr;
|
||||||
if (file) {
|
|
||||||
stat.mode = STAT_MODE_FILE | 0777;
|
|
||||||
return STAT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory *dir = dynamic_cast<Directory *>(node);
|
auto node_type = [&] ()
|
||||||
if (dir) {
|
{
|
||||||
stat.mode = STAT_MODE_DIRECTORY | 0777;
|
if (dynamic_cast<Directory *>(node_ptr)) return Node_type::DIRECTORY;
|
||||||
return STAT_OK;
|
if (dynamic_cast<Symlink *>(node_ptr)) return Node_type::SYMLINK;
|
||||||
}
|
|
||||||
|
|
||||||
Symlink *symlink = dynamic_cast<Symlink *>(node);
|
return Node_type::CONTINUOUS_FILE;
|
||||||
if (symlink) {
|
};
|
||||||
stat.mode = STAT_MODE_SYMLINK | 0777;
|
|
||||||
return STAT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this should never happen */
|
stat = {
|
||||||
return STAT_ERR_NO_ENTRY;
|
.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
|
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,
|
Rom_file_system(Vfs::Env &env,
|
||||||
Genode::Xml_node config)
|
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 */
|
/* use 'label' attribute if present, fall back to 'name' if not */
|
||||||
_label(config.attribute_value("label",
|
_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
|
* found a file), obtain the size of the most current ROM module
|
||||||
* version.
|
* version.
|
||||||
*/
|
*/
|
||||||
if (out.mode == STAT_MODE_FILE) {
|
if (out.type == Node_type::CONTINUOUS_FILE) {
|
||||||
_rom.update();
|
_rom.update();
|
||||||
out.size = _rom.valid() ? _rom.size() : 0;
|
out.size = _rom.valid() ? _rom.size() : 0;
|
||||||
out.mode |= 0555;
|
out.rwx = { .readable = true,
|
||||||
|
.writeable = false,
|
||||||
|
.executable = true };
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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)
|
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()),
|
_rtc(env.env()),
|
||||||
_set_signal_handler(env.env().ep(), *this,
|
_set_signal_handler(env.env().ep(), *this,
|
||||||
&Rtc_file_system::_handle_set_signal)
|
&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 stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
Stat_result result = Single_file_system::stat(path, out);
|
return Single_file_system::stat(path, out);
|
||||||
out.mode |= 0444;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Watch_result watch(char const *path,
|
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)
|
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()))
|
_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
|
TYPE_LONG_LINK = 75, TYPE_LONG_NAME = 76
|
||||||
};
|
};
|
||||||
|
|
||||||
file_size size() const { return _long_name() ? _next()->size() : _read(_size); }
|
file_size size() const { return _long_name() ? _next()->size() : _read(_size); }
|
||||||
unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); }
|
long long mtime() const { return _long_name() ? _next()->mtime() : _read(_mtime); }
|
||||||
unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); }
|
unsigned uid() const { return _long_name() ? _next()->uid() : _read(_uid); }
|
||||||
unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); }
|
unsigned gid() const { return _long_name() ? _next()->gid() : _read(_gid); }
|
||||||
unsigned type() const { return _long_name() ? _next()->type() : _read(_type); }
|
unsigned mode() const { return _long_name() ? _next()->mode() : _read(_mode); }
|
||||||
void *data() const { return _long_name() ? _next()->data() : (void *)_data_begin(); }
|
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; }
|
char const *name() const { return _long_name() ? _data_begin() : _name; }
|
||||||
unsigned max_name_len() const { return _long_name() ? MAX_PATH_LEN : 100; }
|
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))
|
if (count < sizeof(Dirent))
|
||||||
return READ_ERR_INVALID;
|
return READ_ERR_INVALID;
|
||||||
|
|
||||||
Dirent *dirent = (Dirent*)dst;
|
Dirent &dirent = *(Dirent*)dst;
|
||||||
|
|
||||||
/* initialize */
|
file_offset const index = seek() / sizeof(Dirent);
|
||||||
*dirent = Dirent();
|
|
||||||
|
|
||||||
file_offset index = seek() / sizeof(Dirent);
|
Node const *node_ptr = _node->lookup_child(index);
|
||||||
|
|
||||||
Node const *node = _node->lookup_child(index);
|
if (!node_ptr) {
|
||||||
|
dirent = Dirent { };
|
||||||
if (!node)
|
out_count = 0;
|
||||||
return READ_OK;
|
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());
|
Tar_file_system &tar_fs = static_cast<Tar_file_system&>(fs());
|
||||||
Node const *target = tar_fs.dereference(record->linked_name());
|
Node const *target = tar_fs.dereference(record_ptr->linked_name());
|
||||||
record = target ? target->record : 0;
|
record_ptr = target ? target->record : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record) {
|
using Dirent_type = Vfs::Directory_service::Dirent_type;
|
||||||
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;
|
|
||||||
|
|
||||||
default:
|
/* if no record exists, assume it is a directory */
|
||||||
Genode::error("unhandled record type ", record->type(), " "
|
if (!record_ptr) {
|
||||||
"for ", node->name);
|
dirent = {
|
||||||
}
|
.fileno = (Genode::addr_t)node_ptr,
|
||||||
} else {
|
.type = Dirent_type::DIRECTORY,
|
||||||
/* If no record exists, assume it is a directory */
|
.rwx = Node_rwx::rx(),
|
||||||
dirent->type = DIRENT_TYPE_DIRECTORY;
|
.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);
|
out_count = sizeof(Dirent);
|
||||||
|
|
||||||
return READ_OK;
|
return READ_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -576,35 +603,40 @@ class Vfs::Tar_file_system : public File_system
|
||||||
|
|
||||||
Stat_result stat(char const *path, Stat &out) override
|
Stat_result stat(char const *path, Stat &out) override
|
||||||
{
|
{
|
||||||
out = Stat();
|
out = Stat { };
|
||||||
|
|
||||||
Node const *node = dereference(path);
|
Node const *node_ptr = dereference(path);
|
||||||
if (!node)
|
if (!node_ptr)
|
||||||
return STAT_ERR_NO_ENTRY;
|
return STAT_ERR_NO_ENTRY;
|
||||||
|
|
||||||
if (!node->record) {
|
if (!node_ptr->record) {
|
||||||
out.mode = STAT_MODE_DIRECTORY;
|
out.type = Node_type::DIRECTORY;
|
||||||
|
out.rwx = Node_rwx::rx();
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Record const *record = node->record;
|
Record const &record = *node_ptr->record;
|
||||||
|
|
||||||
/* convert TAR record modes to stat modes */
|
auto node_type = [&] ()
|
||||||
unsigned mode = record->mode();
|
{
|
||||||
switch (record->type()) {
|
switch (record.type()) {
|
||||||
case Record::TYPE_FILE: mode |= STAT_MODE_FILE; break;
|
case Record::TYPE_FILE: return Node_type::CONTINUOUS_FILE;
|
||||||
case Record::TYPE_SYMLINK: mode |= STAT_MODE_SYMLINK; break;
|
case Record::TYPE_SYMLINK: return Node_type::SYMLINK;
|
||||||
case Record::TYPE_DIR: mode |= STAT_MODE_DIRECTORY; break;
|
case Record::TYPE_DIR: return Node_type::DIRECTORY;
|
||||||
|
};
|
||||||
|
return Node_type::DIRECTORY;
|
||||||
|
};
|
||||||
|
|
||||||
default: break;
|
out = {
|
||||||
}
|
.size = record.size(),
|
||||||
|
.type = node_type(),
|
||||||
out.mode = mode;
|
.rwx = { .readable = true,
|
||||||
out.size = record->size();
|
.writeable = false,
|
||||||
out.uid = record->uid();
|
.executable = record.rwx().executable },
|
||||||
out.gid = record->gid();
|
.inode = (Genode::addr_t)node_ptr,
|
||||||
out.inode = (Genode::addr_t)node;
|
.device = (Genode::addr_t)this,
|
||||||
out.device = (Genode::addr_t)this;
|
.modification_time = { record.mtime() }
|
||||||
|
};
|
||||||
|
|
||||||
return STAT_OK;
|
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)
|
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())),
|
_label(config.attribute_value("label", Label())),
|
||||||
_env(env.env())
|
_env(env.env())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,8 @@ struct Vfs::Zero_file_system : Single_file_system
|
||||||
{
|
{
|
||||||
Zero_file_system(Vfs::Env&, Genode::Xml_node config)
|
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"; }
|
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);
|
ret = lstat(path, &s);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
|
@ -203,19 +203,30 @@ class Lx_fs::Directory : public Node
|
||||||
if (!dent)
|
if (!dent)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Directory_entry *e = (Directory_entry *)(dst);
|
Path dent_path(dent->d_name, _path.base());
|
||||||
|
|
||||||
switch (dent->d_type) {
|
struct stat st { };
|
||||||
case DT_REG: e->type = Directory_entry::TYPE_FILE; break;
|
lstat(dent_path.base(), &st);
|
||||||
case DT_DIR: e->type = Directory_entry::TYPE_DIRECTORY; break;
|
|
||||||
case DT_LNK: e->type = Directory_entry::TYPE_SYMLINK; break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
return sizeof(Directory_entry);
|
||||||
}
|
}
|
||||||
|
@ -228,18 +239,21 @@ class Lx_fs::Directory : public Node
|
||||||
|
|
||||||
Status status() override
|
Status status() override
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st { };
|
||||||
|
|
||||||
int fd = dirfd(_fd);
|
int fd = dirfd(_fd);
|
||||||
if (fd == -1 || fstat(fd, &st) < 0)
|
if (fd == -1 || fstat(fd, &st) < 0)
|
||||||
st.st_mtime = 0;
|
st.st_mtime = 0;
|
||||||
|
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = _num_entries() * sizeof(File_system::Directory_entry),
|
||||||
s.size = _num_entries() * sizeof(File_system::Directory_entry);
|
.type = Node_type::DIRECTORY,
|
||||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||||
s.modification_time = { st.st_mtime };
|
.writeable = (st.st_mode & S_IWUSR),
|
||||||
return s;
|
.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
|
Status status() override
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st { };
|
||||||
|
|
||||||
if (fstat(_fd, &st) < 0) {
|
if (fstat(_fd, &st) < 0) {
|
||||||
st.st_size = 0;
|
st.st_size = 0;
|
||||||
st.st_mtime = 0;
|
st.st_mtime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = (file_size_t)st.st_size,
|
||||||
s.size = st.st_size;
|
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||||
s.mode = File_system::Status::MODE_FILE;
|
.rwx = { .readable = (st.st_mode & S_IRUSR),
|
||||||
s.modification_time = { st.st_mtime };
|
.writeable = (st.st_mode & S_IWUSR),
|
||||||
return s;
|
.executable = (st.st_mode & S_IXUSR) },
|
||||||
|
.inode = inode(),
|
||||||
|
.modification_time = { st.st_mtime }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void truncate(file_size_t size) override
|
void truncate(file_size_t size) override
|
||||||
|
|
|
@ -203,15 +203,25 @@ class Ram_fs::Directory : public Node
|
||||||
if (!node)
|
if (!node)
|
||||||
return 0;
|
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;
|
Directory_entry &e = *(Directory_entry *)(dst);
|
||||||
if (dynamic_cast<Directory *>(node)) e->type = Directory_entry::TYPE_DIRECTORY;
|
|
||||||
if (dynamic_cast<Symlink *>(node)) e->type = Directory_entry::TYPE_SYMLINK;
|
|
||||||
|
|
||||||
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);
|
return sizeof(Directory_entry);
|
||||||
}
|
}
|
||||||
|
@ -224,12 +234,15 @@ class Ram_fs::Directory : public Node
|
||||||
|
|
||||||
Status status() override
|
Status status() override
|
||||||
{
|
{
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = _num_entries * sizeof(File_system::Directory_entry),
|
||||||
s.size = _num_entries * sizeof(File_system::Directory_entry);
|
.type = File_system::Node_type::DIRECTORY,
|
||||||
s.mode = File_system::Status::MODE_DIRECTORY;
|
.rwx = { .readable = true,
|
||||||
s.modification_time = modification_time();
|
.writeable = true,
|
||||||
return s;
|
.executable = true },
|
||||||
|
.inode = inode(),
|
||||||
|
.modification_time = modification_time()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -112,12 +112,15 @@ class Ram_fs::File : public Node
|
||||||
|
|
||||||
Status status() override
|
Status status() override
|
||||||
{
|
{
|
||||||
Status s { };
|
return {
|
||||||
s.inode = inode();
|
.size = _length,
|
||||||
s.size = _length;
|
.type = File_system::Node_type::CONTINUOUS_FILE,
|
||||||
s.mode = File_system::Status::MODE_FILE;
|
.rwx = { .readable = true,
|
||||||
s.modification_time = modification_time();
|
.writeable = true,
|
||||||
return s;
|
.executable = true },
|
||||||
|
.inode = inode(),
|
||||||
|
.modification_time = modification_time()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void truncate(file_size_t size) override
|
void truncate(file_size_t size) override
|
||||||
|
|
|
@ -67,12 +67,15 @@ class Ram_fs::Symlink : public Node
|
||||||
|
|
||||||
Status status() override
|
Status status() override
|
||||||
{
|
{
|
||||||
Status s;
|
return {
|
||||||
s.inode = inode();
|
.size = _len,
|
||||||
s.size = _len;
|
.type = File_system::Node_type::SYMLINK,
|
||||||
s.mode = File_system::Status::MODE_SYMLINK;
|
.rwx = { .readable = true,
|
||||||
s.modification_time = modification_time();
|
.writeable = true,
|
||||||
return s;
|
.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;
|
::File_system::Status fs_stat;
|
||||||
|
|
||||||
_apply_node(node_handle, [&] (Node &node) {
|
_apply_node(node_handle, [&] (Node &node) {
|
||||||
|
|
||||||
Directory_service::Stat vfs_stat;
|
Directory_service::Stat vfs_stat;
|
||||||
|
|
||||||
if (_vfs.stat(node.path(), vfs_stat) != Directory_service::STAT_OK)
|
if (_vfs.stat(node.path(), vfs_stat) != Directory_service::STAT_OK)
|
||||||
throw Invalid_handle();
|
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 & (
|
switch (type) {
|
||||||
Directory_service::STAT_MODE_DIRECTORY |
|
case Vfs::Node_type::DIRECTORY: return To::DIRECTORY;
|
||||||
Directory_service::STAT_MODE_SYMLINK |
|
case Vfs::Node_type::SYMLINK: return To::SYMLINK;
|
||||||
::File_system::Status::MODE_FILE)) {
|
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:
|
auto fs_node_size = [&] (Vfs::Directory_service::Stat const &vfs_stat)
|
||||||
fs_stat.mode = ::File_system::Status::MODE_DIRECTORY;
|
{
|
||||||
fs_stat.size = _vfs.num_dirent(node.path()) * sizeof(Directory_entry);
|
switch (vfs_stat.type) {
|
||||||
return;
|
case Vfs::Node_type::DIRECTORY:
|
||||||
|
return _vfs.num_dirent(node.path()) * sizeof(Directory_entry);
|
||||||
|
|
||||||
case Directory_service::STAT_MODE_SYMLINK:
|
case Vfs::Node_type::SYMLINK:
|
||||||
fs_stat.mode = ::File_system::Status::MODE_SYMLINK;
|
return 0ULL;
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* Directory_service::STAT_MODE_FILE */
|
case Vfs::Node_type::CONTINUOUS_FILE:
|
||||||
fs_stat.mode = ::File_system::Status::MODE_FILE;
|
case Vfs::Node_type::TRANSACTIONAL_FILE:
|
||||||
break;
|
return vfs_stat.size;
|
||||||
}
|
};
|
||||||
|
return 0ULL;
|
||||||
|
};
|
||||||
|
|
||||||
fs_stat.size = vfs_stat.size;
|
fs_stat = ::File_system::Status {
|
||||||
fs_stat.modification_time.value = vfs_stat.modification_time.value;
|
.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;
|
return fs_stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -726,17 +726,21 @@ struct Vfs_server::Directory : Io_node
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
seek_off_t seek_offset = _packet.position();
|
seek_off_t const seek_offset = _packet.position();
|
||||||
|
|
||||||
Directory_service::Dirent vfs_dirent;
|
size_t const blocksize = sizeof(::File_system::Directory_entry);
|
||||||
size_t blocksize = sizeof(::File_system::Directory_entry);
|
|
||||||
|
|
||||||
unsigned index = (seek_offset / blocksize);
|
unsigned const index = (seek_offset / blocksize);
|
||||||
|
|
||||||
file_size out_count = 0;
|
file_size out_count = 0;
|
||||||
bool result = _vfs_read(
|
|
||||||
(char*)&vfs_dirent, sizeof(vfs_dirent),
|
Directory_service::Dirent vfs_dirent { };
|
||||||
index * sizeof(vfs_dirent), out_count);
|
|
||||||
|
bool const result = _vfs_read((char*)&vfs_dirent,
|
||||||
|
sizeof(vfs_dirent),
|
||||||
|
index * sizeof(vfs_dirent),
|
||||||
|
out_count);
|
||||||
|
vfs_dirent.sanitize();
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
if (out_count != sizeof(vfs_dirent)) {
|
if (out_count != sizeof(vfs_dirent)) {
|
||||||
|
@ -744,30 +748,47 @@ struct Vfs_server::Directory : Io_node
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
::File_system::Directory_entry *fs_dirent =
|
auto fs_dirent_type = [&] (Vfs::Directory_service::Dirent_type type)
|
||||||
(Directory_entry *)_stream.packet_content(_packet);
|
{
|
||||||
fs_dirent->inode = vfs_dirent.fileno;
|
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);
|
_ack_packet(0);
|
||||||
return true;
|
|
||||||
|
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY:
|
} else {
|
||||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_DIRECTORY;
|
|
||||||
break;
|
::File_system::Directory_entry &fs_dirent =
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_SYMLINK:
|
*(Directory_entry *)_stream.packet_content(_packet);
|
||||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_SYMLINK;
|
|
||||||
break;
|
fs_dirent = {
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_FILE:
|
.inode = vfs_dirent.fileno,
|
||||||
default:
|
.type = fs_dirent_type(vfs_dirent.type),
|
||||||
fs_dirent->type = ::File_system::Directory_entry::TYPE_FILE;
|
.rwx = {
|
||||||
break;
|
.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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -442,7 +442,7 @@ struct Unlink_test : public Stress_test
|
||||||
Vfs::Vfs_handle *dir_handle;
|
Vfs::Vfs_handle *dir_handle;
|
||||||
assert_opendir(vfs.opendir(path, false, &dir_handle, alloc));
|
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;) {
|
for (Vfs::file_size i = vfs.num_dirent(path); i;) {
|
||||||
dir_handle->seek(--i * sizeof(dirent));
|
dir_handle->seek(--i * sizeof(dirent));
|
||||||
dir_handle->fs().queue_read(dir_handle, 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)
|
Vfs::File_io_service::READ_QUEUED)
|
||||||
_ep.wait_and_dispatch_one_io_signal();
|
_ep.wait_and_dispatch_one_io_signal();
|
||||||
|
|
||||||
subpath.append(dirent.name);
|
subpath.append(dirent.name.buf);
|
||||||
switch (dirent.type) {
|
switch (dirent.type) {
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_END:
|
case Vfs::Directory_service::Dirent_type::END:
|
||||||
error("reached the end prematurely");
|
error("reached the end prematurely");
|
||||||
throw Exception();
|
throw Exception();
|
||||||
|
|
||||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY:
|
case Vfs::Directory_service::Dirent_type::DIRECTORY:
|
||||||
empty_dir(subpath.base());
|
empty_dir(subpath.base());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -74,43 +74,7 @@ struct Noux::Sysio
|
||||||
OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */
|
OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
typedef Vfs::Directory_service::Stat 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,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Argument structure used for ioctl syscall
|
* Argument structure used for ioctl syscall
|
||||||
|
@ -132,7 +96,7 @@ struct Noux::Sysio
|
||||||
|
|
||||||
enum Lseek_whence { LSEEK_SET, LSEEK_CUR, LSEEK_END };
|
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;
|
typedef Vfs::Directory_service::Dirent_type Dirent_type;
|
||||||
|
|
||||||
|
@ -149,7 +113,7 @@ struct Noux::Sysio
|
||||||
{
|
{
|
||||||
fileno = dirent.fileno;
|
fileno = dirent.fileno;
|
||||||
type = dirent.type;
|
type = dirent.type;
|
||||||
memcpy(name, dirent.name, DIRENT_MAX_NAME_LEN);
|
memcpy(name, dirent.name.buf, DIRENT_MAX_NAME_LEN);
|
||||||
|
|
||||||
return *this;
|
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)
|
static void _sysio_to_stat_struct(Noux::Sysio const *sysio, struct stat *buf)
|
||||||
{
|
{
|
||||||
Genode::memset(buf, 0, sizeof(*buf));
|
unsigned const readable_bits = S_IRUSR,
|
||||||
buf->st_uid = sysio->stat_out.st.uid;
|
writeable_bits = S_IWUSR,
|
||||||
buf->st_gid = sysio->stat_out.st.gid;
|
executable_bits = S_IXUSR;
|
||||||
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;
|
|
||||||
|
|
||||||
if (sysio->stat_out.st.mtime >= 0)
|
auto type = [] (Vfs::Node_type type)
|
||||||
buf->st_mtime = sysio->stat_out.st.mtime;
|
{
|
||||||
|
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);
|
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)) {
|
if (!noux_syscall(Noux::Session::SYSCALL_DIRENT)) {
|
||||||
switch (sysio()->error.general) {
|
switch (sysio()->error.general) {
|
||||||
|
|
||||||
|
@ -1708,23 +1726,35 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (sysio()->dirent_out.entry.type) {
|
using Dirent_type = Vfs::Directory_service::Dirent_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->d_fileno = sysio()->dirent_out.entry.fileno;
|
if (sysio()->dirent_out.entry.type == Dirent_type::END)
|
||||||
dirent->d_reclen = sizeof(struct dirent);
|
return 0;
|
||||||
|
|
||||||
Genode::strncpy(dirent->d_name, sysio()->dirent_out.entry.name,
|
auto d_type = [] (Dirent_type const &type)
|
||||||
sizeof(dirent->d_name));
|
{
|
||||||
|
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);
|
*basep += sizeof(struct dirent);
|
||||||
return 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-low.c | 111 +++++++++++++++++++-
|
||||||
gdb/gdbserver/linux-x86-tdesc-selftest.c | 31 ++++++
|
gdb/gdbserver/linux-x86-tdesc-selftest.c | 31 ++++++
|
||||||
gdb/gdbserver/linux-x86-tdesc.c | 8 +
|
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.c | 36 ++++++
|
||||||
gdb/gdbserver/server.h | 4 +
|
gdb/gdbserver/server.h | 4 +
|
||||||
gdb/nat/fork-inferior.c | 4 -
|
gdb/nat/fork-inferior.c | 4 -
|
||||||
gdb/nat/gdb_ptrace.h | 2
|
gdb/nat/gdb_ptrace.h | 2
|
||||||
gdb/nat/linux-ptrace.c | 17 +++
|
gdb/nat/linux-ptrace.c | 17 +++
|
||||||
gdb/nat/linux-ptrace.h | 4 +
|
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
|
diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h
|
||||||
index eb0ec21..4dc07ce 100644
|
index eb0ec21..4dc07ce 100644
|
||||||
|
@ -1071,7 +1071,7 @@ index c3aa20c..e5a57c0 100644
|
||||||
init_target_desc (*tdesc, amd64_expedite_regs);
|
init_target_desc (*tdesc, amd64_expedite_regs);
|
||||||
}
|
}
|
||||||
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
|
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
|
--- a/gdb/gdbserver/remote-utils.c
|
||||||
+++ b/gdb/gdbserver/remote-utils.c
|
+++ b/gdb/gdbserver/remote-utils.c
|
||||||
@@ -27,6 +27,12 @@
|
@@ -27,6 +27,12 @@
|
||||||
|
@ -1099,6 +1099,18 @@ index 45d5c8d..7b6b1be 100644
|
||||||
static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
|
static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
|
||||||
|
|
||||||
/* FIXME headerize? */
|
/* 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
|
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
|
||||||
index bf6302b..b6a9494 100644
|
index bf6302b..b6a9494 100644
|
||||||
--- a/gdb/gdbserver/server.c
|
--- a/gdb/gdbserver/server.c
|
||||||
|
|
|
@ -271,7 +271,7 @@ class Noux::Pipe_sink_io_channel : public Io_channel
|
||||||
|
|
||||||
bool fstat(Sysio &sysio) override
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -345,7 +345,7 @@ class Noux::Pipe_source_io_channel : public Io_channel
|
||||||
|
|
||||||
bool fstat(Sysio &sysio) override
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,9 +121,6 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
* we use the ones specificed in the config.
|
* we use the ones specificed in the config.
|
||||||
*/
|
*/
|
||||||
if (result) {
|
if (result) {
|
||||||
stat_out.uid = _user_info.uid();
|
|
||||||
stat_out.gid = _user_info.gid();
|
|
||||||
|
|
||||||
stat_out.inode = path_hash;
|
stat_out.inode = path_hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,12 +151,7 @@ struct Noux::Terminal_io_channel : Io_channel
|
||||||
|
|
||||||
bool fstat(Sysio &sysio) override
|
bool fstat(Sysio &sysio) override
|
||||||
{
|
{
|
||||||
/*
|
sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE;
|
||||||
* 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;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,7 @@ struct Noux::Vfs_io_channel : Io_channel
|
||||||
*/
|
*/
|
||||||
unsigned const index = _fh.seek() / sizeof(Sysio::Dirent);
|
unsigned const index = _fh.seek() / sizeof(Sysio::Dirent);
|
||||||
if (index < 2) {
|
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,
|
strncpy(sysio.dirent_out.entry.name,
|
||||||
index ? ".." : ".",
|
index ? ".." : ".",
|
||||||
sizeof(sysio.dirent_out.entry.name));
|
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.
|
* Align index range to zero when calling the directory service.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Vfs::Directory_service::Dirent dirent;
|
|
||||||
|
|
||||||
Vfs::file_size noux_dirent_seek = _fh.seek();
|
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>
|
Registered_no_delete<Vfs_io_waiter>
|
||||||
vfs_io_waiter(_vfs_io_waiter_registry);
|
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_io_waiter.wait_for_io();
|
||||||
|
|
||||||
Vfs::File_io_service::Read_result read_result;
|
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 (;;) {
|
for (;;) {
|
||||||
|
|
||||||
read_result = _fh.fs().complete_read(&_fh, (char*)&dirent,
|
read_result = _fh.fs().complete_read(&_fh, (char*)&dirent,
|
||||||
count, out_count);
|
count, out_count);
|
||||||
|
|
||||||
|
@ -318,7 +316,7 @@ struct Noux::Vfs_io_channel : Io_channel
|
||||||
|
|
||||||
if ((read_result != Vfs::File_io_service::READ_OK) ||
|
if ((read_result != Vfs::File_io_service::READ_OK) ||
|
||||||
(out_count != sizeof(dirent))) {
|
(out_count != sizeof(dirent))) {
|
||||||
dirent = Vfs::Directory_service::Dirent();
|
dirent = { };
|
||||||
}
|
}
|
||||||
|
|
||||||
_fh.seek(noux_dirent_seek);
|
_fh.seek(noux_dirent_seek);
|
||||||
|
|
Loading…
Reference in New Issue