2014-04-11 21:14:10 +02:00
|
|
|
/*
|
2017-02-01 11:28:15 +01:00
|
|
|
* \brief Libc plugin for using a process-local virtual file system
|
|
|
|
* \author Norman Feske
|
|
|
|
* \author Christian Helmuth
|
|
|
|
* \author Emery Hemingway
|
|
|
|
* \date 2014-04-09
|
2014-04-11 21:14:10 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-01 11:28:15 +01:00
|
|
|
* Copyright (C) 2014-2017 Genode Labs GmbH
|
2014-04-11 21:14:10 +02:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2014-04-11 21:14:10 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/env.h>
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/log.h>
|
2014-04-11 21:14:10 +02:00
|
|
|
#include <vfs/dir_file_system.h>
|
|
|
|
|
|
|
|
/* libc includes */
|
|
|
|
#include <errno.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/disk.h>
|
2014-08-19 17:21:10 +02:00
|
|
|
#include <dlfcn.h>
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
/* libc plugin interface */
|
|
|
|
#include <libc-plugin/plugin.h>
|
|
|
|
|
|
|
|
/* libc-internal includes */
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
#include <internal/vfs_plugin.h>
|
|
|
|
#include <internal/mem_alloc.h>
|
|
|
|
#include <internal/errno.h>
|
|
|
|
#include <internal/init.h>
|
|
|
|
#include <internal/legacy.h>
|
|
|
|
#include <internal/suspend.h>
|
|
|
|
|
|
|
|
|
|
|
|
static Libc::Suspend *_suspend_ptr;
|
|
|
|
|
|
|
|
|
|
|
|
void Libc::init_vfs_plugin(Suspend &suspend)
|
|
|
|
{
|
|
|
|
_suspend_ptr = &suspend;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void suspend(Libc::Suspend_functor &check)
|
|
|
|
{
|
|
|
|
struct Missing_call_of_init_vfs_plugin : Genode::Exception { };
|
|
|
|
if (!_suspend_ptr)
|
|
|
|
throw Missing_call_of_init_vfs_plugin();
|
|
|
|
|
|
|
|
_suspend_ptr->suspend(check);
|
|
|
|
};
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
static Genode::Lock &vfs_lock()
|
|
|
|
{
|
|
|
|
static Genode::Lock _vfs_lock;
|
|
|
|
return _vfs_lock;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define VFS_THREAD_SAFE(code) ({ \
|
|
|
|
Genode::Lock::Guard g(vfs_lock()); \
|
|
|
|
code; \
|
|
|
|
})
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
static Vfs::Vfs_handle *vfs_handle(Libc::File_descriptor *fd)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<Vfs::Vfs_handle *>(fd->context);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Libc::Plugin_context *vfs_context(Vfs::Vfs_handle *vfs_handle)
|
|
|
|
{
|
|
|
|
return reinterpret_cast<Libc::Plugin_context *>(vfs_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Utility to convert VFS stat struct to the libc stat struct
|
|
|
|
*
|
|
|
|
* Code shared between 'stat' and 'fstat'.
|
|
|
|
*/
|
|
|
|
static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src,
|
|
|
|
struct stat *dst)
|
|
|
|
{
|
2018-03-29 14:38:44 +02:00
|
|
|
enum { FS_BLOCK_SIZE = 4096 };
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
Genode::memset(dst, 0, sizeof(*dst));
|
|
|
|
|
|
|
|
dst->st_uid = src.uid;
|
|
|
|
dst->st_gid = src.gid;
|
|
|
|
dst->st_mode = src.mode;
|
|
|
|
dst->st_size = src.size;
|
|
|
|
dst->st_blksize = FS_BLOCK_SIZE;
|
|
|
|
dst->st_blocks = (dst->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
|
|
|
|
dst->st_ino = src.inode;
|
|
|
|
dst->st_dev = src.device;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-22 14:42:20 +01:00
|
|
|
static Genode::Xml_node *_config_node;
|
|
|
|
|
2018-05-25 22:22:12 +02:00
|
|
|
char const *libc_resolv_path;
|
2017-02-22 14:42:20 +01:00
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2018-05-25 22:22:12 +02:00
|
|
|
namespace Libc {
|
2017-02-22 14:42:20 +01:00
|
|
|
|
2014-05-06 11:49:56 +02:00
|
|
|
Genode::Xml_node config() __attribute__((weak));
|
|
|
|
Genode::Xml_node config()
|
2014-04-24 12:40:18 +02:00
|
|
|
{
|
2017-03-14 13:19:02 +01:00
|
|
|
if (!_config_node) {
|
|
|
|
error("libc config not initialized - aborting");
|
|
|
|
exit(1);
|
|
|
|
}
|
2017-03-03 10:56:05 +01:00
|
|
|
return *_config_node;
|
2014-04-24 12:40:18 +02:00
|
|
|
}
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2014-04-24 12:40:18 +02:00
|
|
|
class Config_attr
|
|
|
|
{
|
|
|
|
private:
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2019-01-21 15:59:00 +01:00
|
|
|
typedef String<Vfs::MAX_PATH_LEN> Value;
|
|
|
|
Value const _value;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2014-04-24 12:40:18 +02:00
|
|
|
public:
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2014-04-24 12:40:18 +02:00
|
|
|
Config_attr(char const *attr_name, char const *default_value)
|
2019-01-21 15:59:00 +01:00
|
|
|
:
|
|
|
|
_value(Libc::config().attribute_value(attr_name,
|
|
|
|
Value(default_value)))
|
|
|
|
{ }
|
|
|
|
|
|
|
|
char const *string() const { return _value.string(); }
|
2014-04-24 12:40:18 +02:00
|
|
|
};
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
char const *config_rng() __attribute__((weak));
|
|
|
|
char const *config_rng()
|
|
|
|
{
|
|
|
|
static Config_attr rng("rng", "");
|
|
|
|
return rng.string();
|
|
|
|
}
|
|
|
|
|
2017-02-12 10:59:37 +01:00
|
|
|
char const *config_socket() __attribute__((weak));
|
|
|
|
char const *config_socket()
|
|
|
|
{
|
|
|
|
static Config_attr socket("socket", "");
|
|
|
|
return socket.string();
|
|
|
|
}
|
2017-04-07 14:02:40 +02:00
|
|
|
|
2018-05-25 22:22:12 +02:00
|
|
|
char const *config_nameserver_file() __attribute__((weak));
|
|
|
|
char const *config_nameserver_file()
|
|
|
|
{
|
|
|
|
static Config_attr ns_file("nameserver_file",
|
|
|
|
"/socket/nameserver");
|
|
|
|
return ns_file.string();
|
|
|
|
}
|
|
|
|
|
|
|
|
void libc_config_init(Genode::Xml_node node)
|
|
|
|
{
|
|
|
|
static Genode::Xml_node config = node;
|
|
|
|
_config_node = &config;
|
|
|
|
|
|
|
|
libc_resolv_path = config_nameserver_file();
|
|
|
|
}
|
|
|
|
|
2017-04-07 14:02:40 +02:00
|
|
|
void notify_read_ready(Vfs::Vfs_handle *handle)
|
|
|
|
{
|
2018-09-07 19:01:48 +02:00
|
|
|
/*
|
|
|
|
* If this call fails, the VFS plugin is expected to call the IO
|
|
|
|
* handler when the notification request can be processed. The
|
|
|
|
* libc IO handler will then call 'notify_read_ready()' again
|
|
|
|
* via 'select_notify()'.
|
|
|
|
*/
|
|
|
|
VFS_THREAD_SAFE(handle->fs().notify_read_ready(handle));
|
2017-04-07 14:02:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool read_ready(Libc::File_descriptor *fd)
|
|
|
|
{
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
|
|
|
if (!handle) return false;
|
|
|
|
|
|
|
|
notify_read_ready(handle);
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
return VFS_THREAD_SAFE(handle->fs().read_ready(handle));
|
2017-04-07 14:02:40 +02:00
|
|
|
}
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
2015-09-20 11:47:17 +02:00
|
|
|
int Libc::Vfs_plugin::access(const char *path, int amode)
|
|
|
|
{
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.leaf_path(path)))
|
2015-09-20 11:47:17 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
errno = ENOENT;
|
|
|
|
return -1;
|
|
|
|
}
|
2015-09-18 11:10:29 +02:00
|
|
|
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags,
|
|
|
|
int libc_fd)
|
|
|
|
{
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.directory(path))) {
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
if (((flags & O_ACCMODE) != O_RDONLY)) {
|
2018-02-13 16:37:05 +01:00
|
|
|
errno = EISDIR;
|
2017-08-15 20:51:53 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-02-13 16:37:05 +01:00
|
|
|
flags |= O_DIRECTORY;
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *handle = 0;
|
|
|
|
|
|
|
|
typedef Vfs::Directory_service::Opendir_result Opendir_result;
|
|
|
|
|
2018-07-09 11:21:00 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.opendir(path, false, &handle, _alloc))) {
|
2017-08-15 20:51:53 +02:00
|
|
|
case Opendir_result::OPENDIR_OK: break;
|
|
|
|
case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED: errno = ENOENT; return nullptr;
|
|
|
|
case Opendir_result::OPENDIR_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return nullptr;
|
|
|
|
case Opendir_result::OPENDIR_ERR_NODE_ALREADY_EXISTS: errno = EEXIST; return nullptr;
|
|
|
|
case Opendir_result::OPENDIR_ERR_NO_SPACE: errno = ENOSPC; return nullptr;
|
|
|
|
case Opendir_result::OPENDIR_ERR_OUT_OF_RAM:
|
|
|
|
case Opendir_result::OPENDIR_ERR_OUT_OF_CAPS:
|
|
|
|
case Opendir_result::OPENDIR_ERR_PERMISSION_DENIED: errno = EPERM; return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the directory was successfully opened */
|
|
|
|
|
|
|
|
Libc::File_descriptor *fd =
|
|
|
|
Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd);
|
|
|
|
|
|
|
|
/* FIXME error cleanup code leaks resources! */
|
|
|
|
|
|
|
|
if (!fd) {
|
2019-06-06 12:27:46 +02:00
|
|
|
VFS_THREAD_SAFE(handle->close());
|
2017-08-15 20:51:53 +02:00
|
|
|
errno = EMFILE;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-03-25 15:41:43 +01:00
|
|
|
handle->handler(&_response_handler);
|
2017-08-15 20:51:53 +02:00
|
|
|
fd->flags = flags & O_ACCMODE;
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2018-02-13 16:37:05 +01:00
|
|
|
if (flags & O_DIRECTORY) {
|
|
|
|
errno = ENOTDIR;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
typedef Vfs::Directory_service::Open_result Result;
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = 0;
|
|
|
|
|
2019-06-11 09:45:41 +02:00
|
|
|
while (handle == nullptr) {
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.open(path, flags, &handle, _alloc))) {
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
case Result::OPEN_OK:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Result::OPEN_ERR_UNACCESSIBLE:
|
|
|
|
{
|
|
|
|
if (!(flags & O_CREAT)) {
|
2017-07-04 21:11:57 +02:00
|
|
|
if (flags & O_NOFOLLOW) {
|
|
|
|
errno = ELOOP;
|
|
|
|
return 0;
|
|
|
|
}
|
2014-04-11 21:14:10 +02:00
|
|
|
errno = ENOENT;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* O_CREAT is set, so try to create the file */
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.open(path, flags | O_EXCL, &handle, _alloc))) {
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
case Result::OPEN_OK:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Result::OPEN_ERR_EXISTS:
|
|
|
|
|
|
|
|
/* file has been created by someone else in the meantime */
|
2017-07-03 00:31:24 +02:00
|
|
|
if (flags & O_NOFOLLOW) {
|
|
|
|
errno = ELOOP;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
errno = EEXIST;
|
|
|
|
return 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2015-10-01 11:53:00 +02:00
|
|
|
case Result::OPEN_ERR_NO_PERM: errno = EPERM; return 0;
|
|
|
|
case Result::OPEN_ERR_UNACCESSIBLE: errno = ENOENT; return 0;
|
|
|
|
case Result::OPEN_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return 0;
|
|
|
|
case Result::OPEN_ERR_NO_SPACE: errno = ENOSPC; return 0;
|
2017-08-15 20:51:53 +02:00
|
|
|
case Result::OPEN_ERR_OUT_OF_RAM: errno = ENOSPC; return 0;
|
|
|
|
case Result::OPEN_ERR_OUT_OF_CAPS: errno = ENOSPC; return 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-10-01 11:53:00 +02:00
|
|
|
case Result::OPEN_ERR_NO_PERM: errno = EPERM; return 0;
|
|
|
|
case Result::OPEN_ERR_EXISTS: errno = EEXIST; return 0;
|
|
|
|
case Result::OPEN_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return 0;
|
|
|
|
case Result::OPEN_ERR_NO_SPACE: errno = ENOSPC; return 0;
|
2017-08-15 20:51:53 +02:00
|
|
|
case Result::OPEN_ERR_OUT_OF_RAM: errno = ENOSPC; return 0;
|
|
|
|
case Result::OPEN_ERR_OUT_OF_CAPS: errno = ENOSPC; return 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the file was successfully opened */
|
|
|
|
|
|
|
|
Libc::File_descriptor *fd =
|
|
|
|
Libc::file_descriptor_allocator()->alloc(this, vfs_context(handle), libc_fd);
|
|
|
|
|
2017-06-09 16:02:57 +02:00
|
|
|
/* FIXME error cleanup code leaks resources! */
|
|
|
|
|
|
|
|
if (!fd) {
|
2019-06-06 12:27:46 +02:00
|
|
|
VFS_THREAD_SAFE(handle->close());
|
2017-06-09 16:02:57 +02:00
|
|
|
errno = EMFILE;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-03-25 15:41:43 +01:00
|
|
|
handle->handler(&_response_handler);
|
2017-06-24 23:42:30 +02:00
|
|
|
fd->flags = flags & (O_ACCMODE|O_NONBLOCK|O_APPEND);
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) {
|
2019-06-06 12:27:46 +02:00
|
|
|
VFS_THREAD_SAFE(handle->close());
|
2017-06-09 16:02:57 +02:00
|
|
|
errno = EINVAL; /* XXX which error code fits best ? */
|
|
|
|
return nullptr;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-06-06 12:27:46 +02:00
|
|
|
int Libc::Vfs_plugin::_vfs_sync(Vfs::Vfs_handle &vfs_handle)
|
|
|
|
{
|
|
|
|
typedef Vfs::File_io_service::Sync_result Result;
|
|
|
|
Result result = Result::SYNC_QUEUED;
|
|
|
|
|
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle &vfs_handle;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle &vfs_handle)
|
|
|
|
: vfs_handle(vfs_handle) { }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
|
|
|
retry = !VFS_THREAD_SAFE(vfs_handle.fs().queue_sync(&vfs_handle));
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(vfs_handle);
|
|
|
|
|
|
|
|
/*
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
* Cannot call suspend() immediately, because the Libc kernel
|
2019-06-06 12:27:46 +02:00
|
|
|
* might not be running yet.
|
|
|
|
*/
|
|
|
|
if (!VFS_THREAD_SAFE(vfs_handle.fs().queue_sync(&vfs_handle))) {
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2019-06-06 12:27:46 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle &vfs_handle;
|
|
|
|
Result &result;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle &vfs_handle, Result &result)
|
|
|
|
: vfs_handle(vfs_handle), result(result) { }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
|
|
|
result = VFS_THREAD_SAFE(vfs_handle.fs().complete_sync(&vfs_handle));
|
|
|
|
retry = result == Vfs::File_io_service::SYNC_QUEUED;
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(vfs_handle, result);
|
|
|
|
|
|
|
|
/*
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
* Cannot call suspend() immediately, because the Libc kernel
|
2019-06-06 12:27:46 +02:00
|
|
|
* might not be running yet.
|
|
|
|
*/
|
|
|
|
result = VFS_THREAD_SAFE(vfs_handle.fs().complete_sync(&vfs_handle));
|
|
|
|
if (result == Result::SYNC_QUEUED) {
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2019-06-06 12:27:46 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result == Result::SYNC_OK ? 0 : Libc::Errno(EIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
int Libc::Vfs_plugin::close(Libc::File_descriptor *fd)
|
|
|
|
{
|
2016-03-30 15:24:19 +02:00
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
2019-03-25 15:41:43 +01:00
|
|
|
/* XXX: mark the handle as requiring sync or not */
|
2019-06-06 12:27:46 +02:00
|
|
|
_vfs_sync(*handle);
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->close());
|
2014-04-11 21:14:10 +02:00
|
|
|
Libc::file_descriptor_allocator()->free(fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::dup2(Libc::File_descriptor *fd,
|
|
|
|
Libc::File_descriptor *new_fd)
|
|
|
|
{
|
|
|
|
new_fd->context = fd->context;
|
|
|
|
return new_fd->libc_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::fstat(Libc::File_descriptor *fd, struct stat *buf)
|
|
|
|
{
|
2018-02-27 14:07:51 +01:00
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
2019-06-06 12:27:46 +02:00
|
|
|
_vfs_sync(*handle);
|
2014-04-11 21:14:10 +02:00
|
|
|
return stat(fd->fd_path, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-06-15 18:39:11 +02:00
|
|
|
int Libc::Vfs_plugin::fstatfs(Libc::File_descriptor *fd, struct statfs *buf)
|
2014-04-11 21:14:10 +02:00
|
|
|
{
|
2016-06-15 18:39:11 +02:00
|
|
|
if (!fd || !buf)
|
|
|
|
return Libc::Errno(EFAULT);
|
|
|
|
|
|
|
|
Genode::memset(buf, 0, sizeof(*buf));
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
buf->f_flags = MNT_UNION;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::mkdir(const char *path, mode_t mode)
|
|
|
|
{
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *dir_handle { 0 };
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
typedef Vfs::Directory_service::Opendir_result Opendir_result;
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.opendir(path, true, &dir_handle, _alloc))) {
|
2017-08-15 20:51:53 +02:00
|
|
|
case Opendir_result::OPENDIR_OK:
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(dir_handle->close());
|
2017-08-15 20:51:53 +02:00
|
|
|
break;
|
|
|
|
case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED:
|
|
|
|
return Errno(ENOENT);
|
|
|
|
case Opendir_result::OPENDIR_ERR_NAME_TOO_LONG:
|
|
|
|
return Errno(ENAMETOOLONG);
|
|
|
|
case Opendir_result::OPENDIR_ERR_NODE_ALREADY_EXISTS:
|
|
|
|
return Errno(EEXIST);
|
|
|
|
case Opendir_result::OPENDIR_ERR_NO_SPACE:
|
|
|
|
return Errno(ENOSPC);
|
|
|
|
case Opendir_result::OPENDIR_ERR_OUT_OF_RAM:
|
|
|
|
case Opendir_result::OPENDIR_ERR_OUT_OF_CAPS:
|
|
|
|
case Opendir_result::OPENDIR_ERR_PERMISSION_DENIED:
|
|
|
|
return Errno(EPERM);
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
2017-08-15 20:51:53 +02:00
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::stat(char const *path, struct stat *buf)
|
|
|
|
{
|
|
|
|
if (!path or !buf) {
|
|
|
|
errno = EFAULT;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef Vfs::Directory_service::Stat_result Result;
|
|
|
|
|
|
|
|
Vfs::Directory_service::Stat stat;
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.stat(path, stat))) {
|
2014-04-11 21:14:10 +02:00
|
|
|
case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
2016-04-01 11:42:31 +02:00
|
|
|
case Result::STAT_ERR_NO_PERM: errno = EACCES; return -1;
|
2014-10-15 16:09:45 +02:00
|
|
|
case Result::STAT_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
vfs_stat_to_libc_stat_struct(stat, buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
|
|
|
|
::size_t count)
|
|
|
|
{
|
|
|
|
typedef Vfs::File_io_service::Write_result Result;
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::file_size out_count = 0;
|
|
|
|
Result out_result = Result::WRITE_OK;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
if (fd->flags & O_NONBLOCK) {
|
|
|
|
|
|
|
|
try {
|
2017-10-19 14:08:30 +02:00
|
|
|
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf, count, out_count));
|
2018-07-04 14:09:01 +02:00
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
} catch (Vfs::File_io_service::Insufficient_buffer) { }
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle;
|
|
|
|
void const *buf;
|
|
|
|
::size_t count;
|
|
|
|
Vfs::file_size &out_count;
|
|
|
|
Result &out_result;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *handle, void const *buf,
|
|
|
|
::size_t count, Vfs::file_size &out_count,
|
|
|
|
Result &out_result)
|
|
|
|
: handle(handle), buf(buf), count(count), out_count(out_count),
|
|
|
|
out_result(out_result)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
|
|
|
try {
|
2017-10-19 14:08:30 +02:00
|
|
|
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf,
|
|
|
|
count, out_count));
|
2017-08-15 20:51:53 +02:00
|
|
|
retry = false;
|
|
|
|
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
|
|
|
retry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(handle, buf, count, out_count, out_result);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
switch (out_result) {
|
|
|
|
case Result::WRITE_ERR_AGAIN: return Errno(EAGAIN);
|
|
|
|
case Result::WRITE_ERR_WOULD_BLOCK: return Errno(EWOULDBLOCK);
|
|
|
|
case Result::WRITE_ERR_INVALID: return Errno(EINVAL);
|
|
|
|
case Result::WRITE_ERR_IO: return Errno(EIO);
|
|
|
|
case Result::WRITE_ERR_INTERRUPT: return Errno(EINTR);
|
|
|
|
case Result::WRITE_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->advance_seek(out_count));
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
return out_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf,
|
|
|
|
::size_t count)
|
|
|
|
{
|
2017-05-18 16:04:21 +02:00
|
|
|
Libc::dispatch_pending_io_signals();
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
typedef Vfs::File_io_service::Read_result Result;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
2017-01-31 16:38:23 +01:00
|
|
|
|
2018-02-13 16:37:05 +01:00
|
|
|
if (fd->flags & O_DIRECTORY)
|
|
|
|
return Errno(EISDIR);
|
|
|
|
|
2017-04-07 14:02:40 +02:00
|
|
|
if (fd->flags & O_NONBLOCK && !Libc::read_ready(fd))
|
|
|
|
return Errno(EAGAIN);
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle;
|
|
|
|
::size_t count;
|
2017-02-20 13:30:36 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Check(Vfs::Vfs_handle *handle, ::size_t count)
|
|
|
|
: handle(handle), count(count) { }
|
2017-02-20 13:30:36 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
bool suspend() override
|
|
|
|
{
|
2017-10-19 14:08:30 +02:00
|
|
|
retry = !VFS_THREAD_SAFE(handle->fs().queue_read(handle, count));
|
2017-08-15 20:51:53 +02:00
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check ( handle, count);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
2017-02-20 13:30:36 +01:00
|
|
|
}
|
2017-01-31 16:38:23 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::file_size out_count = 0;
|
|
|
|
Result out_result;
|
2017-02-20 13:30:36 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
2017-02-20 13:30:36 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *handle;
|
|
|
|
void *buf;
|
|
|
|
::size_t count;
|
|
|
|
Vfs::file_size &out_count;
|
|
|
|
Result &out_result;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *handle, void *buf, ::size_t count,
|
|
|
|
Vfs::file_size &out_count, Result &out_result)
|
|
|
|
: handle(handle), buf(buf), count(count), out_count(out_count),
|
|
|
|
out_result(out_result)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
2017-10-19 14:08:30 +02:00
|
|
|
out_result = VFS_THREAD_SAFE(handle->fs().complete_read(handle, (char *)buf,
|
|
|
|
count, out_count));
|
2017-02-20 13:30:36 +01:00
|
|
|
/* suspend me if read is still queued */
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
retry = (out_result == Result::READ_QUEUED);
|
|
|
|
|
|
|
|
return retry;
|
2017-02-20 13:30:36 +01:00
|
|
|
}
|
2017-08-15 20:51:53 +02:00
|
|
|
} check ( handle, buf, count, out_count, out_result);
|
2017-02-20 13:30:36 +01:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
2017-01-31 16:38:23 +01:00
|
|
|
}
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2017-01-31 16:38:23 +01:00
|
|
|
switch (out_result) {
|
|
|
|
case Result::READ_ERR_AGAIN: return Errno(EAGAIN);
|
|
|
|
case Result::READ_ERR_WOULD_BLOCK: return Errno(EWOULDBLOCK);
|
|
|
|
case Result::READ_ERR_INVALID: return Errno(EINVAL);
|
|
|
|
case Result::READ_ERR_IO: return Errno(EIO);
|
|
|
|
case Result::READ_ERR_INTERRUPT: return Errno(EINTR);
|
|
|
|
case Result::READ_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-01-31 16:38:23 +01:00
|
|
|
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->advance_seek(out_count));
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
return out_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf,
|
|
|
|
::size_t nbytes, ::off_t *basep)
|
|
|
|
{
|
|
|
|
if (nbytes < sizeof(struct dirent)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("getdirentries: buffer too small");
|
2014-04-11 21:14:10 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
typedef Vfs::File_io_service::Read_result Result;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
typedef Vfs::Directory_service::Dirent Dirent;
|
|
|
|
|
|
|
|
Dirent dirent_out;
|
|
|
|
|
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
Check(Vfs::Vfs_handle *handle)
|
|
|
|
: handle(handle) { }
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
bool suspend() override
|
|
|
|
{
|
2018-07-09 11:21:00 +02:00
|
|
|
retry = !VFS_THREAD_SAFE(handle->fs().queue_read(handle, sizeof(Dirent)));
|
2017-08-15 20:51:53 +02:00
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(handle);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
|
|
|
|
Result out_result;
|
|
|
|
Vfs::file_size out_count;
|
|
|
|
|
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle;
|
|
|
|
Dirent &dirent_out;
|
|
|
|
Vfs::file_size &out_count;
|
|
|
|
Result &out_result;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *handle, Dirent &dirent_out,
|
|
|
|
Vfs::file_size &out_count, Result &out_result)
|
|
|
|
: handle(handle), dirent_out(dirent_out), out_count(out_count),
|
|
|
|
out_result(out_result) { }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
2017-10-19 14:08:30 +02:00
|
|
|
out_result = VFS_THREAD_SAFE(handle->fs().complete_read(handle,
|
|
|
|
(char*)&dirent_out,
|
|
|
|
sizeof(Dirent),
|
|
|
|
out_count));
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
/* suspend me if read is still queued */
|
|
|
|
|
|
|
|
retry = (out_result == Result::READ_QUEUED);
|
|
|
|
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(handle, dirent_out, out_count, out_result);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
if ((out_result != Result::READ_OK) ||
|
|
|
|
(out_count < sizeof(Dirent))) {
|
|
|
|
return 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert dirent structure from VFS to libc
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct dirent *dirent = (struct dirent *)buf;
|
|
|
|
Genode::memset(dirent, 0, sizeof(struct dirent));
|
|
|
|
|
|
|
|
switch (dirent_out.type) {
|
|
|
|
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY: dirent->d_type = DT_DIR; break;
|
|
|
|
case Vfs::Directory_service::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break;
|
|
|
|
case Vfs::Directory_service::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break;
|
|
|
|
case Vfs::Directory_service::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break;
|
2014-04-14 11:57:22 +02:00
|
|
|
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;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
dirent->d_fileno = dirent_out.fileno;
|
|
|
|
dirent->d_reclen = sizeof(struct dirent);
|
|
|
|
|
|
|
|
Genode::strncpy(dirent->d_name, dirent_out.name, sizeof(dirent->d_name));
|
|
|
|
|
|
|
|
dirent->d_namlen = Genode::strlen(dirent->d_name);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Keep track of VFS seek pointer and user-supplied basep.
|
|
|
|
*/
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->advance_seek(sizeof(Vfs::Directory_service::Dirent)));
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
*basep += sizeof(struct dirent);
|
|
|
|
|
|
|
|
return sizeof(struct dirent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp)
|
|
|
|
{
|
|
|
|
using ::off_t;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Marshal ioctl arguments
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef Vfs::File_io_service::Ioctl_opcode Opcode;
|
|
|
|
|
|
|
|
Opcode opcode = Opcode::IOCTL_OP_UNDEFINED;
|
|
|
|
|
|
|
|
Vfs::File_io_service::Ioctl_arg arg = 0;
|
|
|
|
|
|
|
|
switch (request) {
|
|
|
|
|
|
|
|
case TIOCGWINSZ:
|
2018-10-26 11:31:31 +02:00
|
|
|
{
|
|
|
|
if (!argp) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
opcode = Opcode::IOCTL_OP_TIOCGWINSZ;
|
|
|
|
break;
|
|
|
|
}
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
case TIOCGETA:
|
|
|
|
{
|
|
|
|
::termios *termios = (::termios *)argp;
|
|
|
|
|
|
|
|
termios->c_iflag = 0;
|
|
|
|
termios->c_oflag = 0;
|
|
|
|
termios->c_cflag = 0;
|
|
|
|
/*
|
|
|
|
* Set 'ECHO' flag, needed by libreadline. Otherwise, echoing
|
|
|
|
* user input doesn't work in bash.
|
|
|
|
*/
|
|
|
|
termios->c_lflag = ECHO;
|
|
|
|
::memset(termios->c_cc, _POSIX_VDISABLE, sizeof(termios->c_cc));
|
|
|
|
termios->c_ispeed = 0;
|
|
|
|
termios->c_ospeed = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TIOCSETAF:
|
|
|
|
{
|
|
|
|
opcode = Opcode::IOCTL_OP_TIOCSETAF;
|
|
|
|
|
|
|
|
::termios *termios = (::termios *)argp;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For now only enabling/disabling of ECHO is supported
|
|
|
|
*/
|
|
|
|
if (termios->c_lflag & (ECHO | ECHONL)) {
|
|
|
|
arg = (Vfs::File_io_service::IOCTL_VAL_ECHO |
|
|
|
|
Vfs::File_io_service::IOCTL_VAL_ECHONL);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
arg = Vfs::File_io_service::IOCTL_VAL_NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case TIOCSETAW:
|
|
|
|
{
|
|
|
|
opcode = Opcode::IOCTL_OP_TIOCSETAW;
|
|
|
|
arg = argp ? *(int*)argp : 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case FIONBIO:
|
|
|
|
{
|
|
|
|
opcode = Opcode::IOCTL_OP_FIONBIO;
|
|
|
|
arg = argp ? *(int*)argp : 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case DIOCGMEDIASIZE:
|
|
|
|
{
|
2017-10-26 14:57:47 +02:00
|
|
|
if (!argp) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
opcode = Opcode::IOCTL_OP_DIOCGMEDIASIZE;
|
|
|
|
arg = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("unsupported ioctl (request=", Genode::Hex(request), ")");
|
2014-04-11 21:14:10 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opcode == Opcode::IOCTL_OP_UNDEFINED) {
|
|
|
|
errno = ENOTTY;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef Vfs::File_io_service::Ioctl_result Result;
|
2015-05-13 18:20:39 +02:00
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
Vfs::File_io_service::Ioctl_out out;
|
|
|
|
Genode::memset(&out, 0, sizeof(out));
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
|
|
|
|
2018-07-09 11:21:00 +02:00
|
|
|
switch (VFS_THREAD_SAFE(handle->fs().ioctl(handle, opcode, arg, out))) {
|
2015-05-13 18:20:39 +02:00
|
|
|
case Result::IOCTL_ERR_INVALID: errno = EINVAL; return -1;
|
|
|
|
case Result::IOCTL_ERR_NOTTY: errno = ENOTTY; return -1;
|
|
|
|
case Result::IOCTL_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Unmarshal ioctl results
|
|
|
|
*/
|
|
|
|
switch (request) {
|
|
|
|
|
|
|
|
case TIOCGWINSZ:
|
|
|
|
{
|
2018-10-26 11:31:31 +02:00
|
|
|
::winsize *winsize = (::winsize *)argp;
|
2014-04-11 21:14:10 +02:00
|
|
|
winsize->ws_row = out.tiocgwinsz.rows;
|
|
|
|
winsize->ws_col = out.tiocgwinsz.columns;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case TIOCSETAF:
|
|
|
|
case TIOCSETAW:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case FIONBIO:
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case DIOCGMEDIASIZE:
|
|
|
|
{
|
|
|
|
/* resolve ambiguity with libc type */
|
|
|
|
using Genode::int64_t;
|
|
|
|
|
2017-10-26 14:57:47 +02:00
|
|
|
int64_t *disk_size = (int64_t*)argp;
|
2014-04-11 21:14:10 +02:00
|
|
|
*disk_size = out.diocgmediasize.size;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::off_t Libc::Vfs_plugin::lseek(Libc::File_descriptor *fd, ::off_t offset, int whence)
|
|
|
|
{
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
|
|
|
|
|
|
|
switch (whence) {
|
|
|
|
case SEEK_SET: handle->seek(offset); break;
|
|
|
|
case SEEK_CUR: handle->advance_seek(offset); break;
|
|
|
|
case SEEK_END:
|
|
|
|
{
|
|
|
|
struct stat stat;
|
|
|
|
::memset(&stat, 0, sizeof(stat));
|
|
|
|
fstat(fd, &stat);
|
|
|
|
handle->seek(stat.st_size + offset);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return handle->seek();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length)
|
|
|
|
{
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
2019-06-06 12:27:46 +02:00
|
|
|
_vfs_sync(*handle);
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
typedef Vfs::File_io_service::Ftruncate_result Result;
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(handle->fs().ftruncate(handle, length))) {
|
2015-10-01 11:53:00 +02:00
|
|
|
case Result::FTRUNCATE_ERR_NO_PERM: errno = EPERM; return -1;
|
|
|
|
case Result::FTRUNCATE_ERR_INTERRUPT: errno = EINTR; return -1;
|
|
|
|
case Result::FTRUNCATE_ERR_NO_SPACE: errno = ENOSPC; return -1;
|
|
|
|
case Result::FTRUNCATE_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
2019-04-26 12:47:33 +02:00
|
|
|
case F_DUPFD_CLOEXEC:
|
2014-04-11 21:14:10 +02:00
|
|
|
case F_DUPFD:
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Allocate free file descriptor locally.
|
|
|
|
*/
|
|
|
|
Libc::File_descriptor *new_fd =
|
|
|
|
Libc::file_descriptor_allocator()->alloc(this, 0);
|
2017-06-09 16:02:57 +02:00
|
|
|
if (!new_fd) return Errno(EMFILE);
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
new_fd->path(fd->fd_path);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use new allocated number as name of file descriptor
|
|
|
|
* duplicate.
|
|
|
|
*/
|
|
|
|
if (dup2(fd, new_fd) == -1) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("Plugin::fcntl: dup2 unexpectedly failed");
|
2017-06-09 16:02:57 +02:00
|
|
|
return Errno(EINVAL);
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return new_fd->libc_fd;
|
|
|
|
}
|
2017-03-12 18:05:38 +01:00
|
|
|
case F_GETFD: return fd->cloexec ? FD_CLOEXEC : 0;
|
|
|
|
case F_SETFD: fd->cloexec = arg == FD_CLOEXEC; return 0;
|
|
|
|
|
|
|
|
case F_GETFL: return fd->flags;
|
|
|
|
case F_SETFL: fd->flags = arg; return 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("fcntl(): command ", cmd, " not supported - vfs");
|
2017-06-09 16:02:57 +02:00
|
|
|
return Errno(EINVAL);
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::fsync(Libc::File_descriptor *fd)
|
|
|
|
{
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
2019-06-06 12:27:46 +02:00
|
|
|
return _vfs_sync(*handle);
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath)
|
|
|
|
{
|
2017-08-15 20:51:53 +02:00
|
|
|
typedef Vfs::Directory_service::Openlink_result Openlink_result;
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle { 0 };
|
|
|
|
|
|
|
|
Openlink_result openlink_result =
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(_root_dir.openlink(newpath, true, &handle, _alloc));
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
switch (openlink_result) {
|
|
|
|
case Openlink_result::OPENLINK_OK:
|
|
|
|
break;
|
|
|
|
case Openlink_result::OPENLINK_ERR_LOOKUP_FAILED:
|
|
|
|
return Errno(ENOENT);
|
|
|
|
case Openlink_result::OPENLINK_ERR_NAME_TOO_LONG:
|
|
|
|
return Errno(ENAMETOOLONG);
|
|
|
|
case Openlink_result::OPENLINK_ERR_NODE_ALREADY_EXISTS:
|
|
|
|
return Errno(EEXIST);
|
|
|
|
case Openlink_result::OPENLINK_ERR_NO_SPACE:
|
|
|
|
return Errno(ENOSPC);
|
|
|
|
case Openlink_result::OPENLINK_ERR_OUT_OF_RAM:
|
|
|
|
return Errno(ENOSPC);
|
|
|
|
case Openlink_result::OPENLINK_ERR_OUT_OF_CAPS:
|
|
|
|
return Errno(ENOSPC);
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_PERMISSION_DENIED:
|
|
|
|
return Errno(EPERM);
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
Vfs::file_size count = ::strlen(oldpath) + 1;
|
|
|
|
Vfs::file_size out_count = 0;
|
|
|
|
|
2019-03-25 15:41:43 +01:00
|
|
|
handle->handler(&_response_handler);
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle;
|
|
|
|
void const *buf;
|
|
|
|
::size_t count;
|
|
|
|
Vfs::file_size &out_count;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *handle, void const *buf,
|
|
|
|
::size_t count, Vfs::file_size &out_count)
|
|
|
|
: handle(handle), buf(buf), count(count), out_count(out_count)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
|
|
|
try {
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf,
|
|
|
|
count, out_count));
|
2017-08-15 20:51:53 +02:00
|
|
|
retry = false;
|
|
|
|
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
|
|
|
retry = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check ( handle, oldpath, count, out_count);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2019-06-06 12:27:46 +02:00
|
|
|
_vfs_sync(*handle);
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(handle->close());
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
if (out_count != count)
|
|
|
|
return Errno(ENAMETOOLONG);
|
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-09-15 14:40:37 +02:00
|
|
|
ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_size)
|
2014-04-11 21:14:10 +02:00
|
|
|
{
|
2017-08-15 20:51:53 +02:00
|
|
|
Vfs::Vfs_handle *symlink_handle { 0 };
|
|
|
|
|
|
|
|
Vfs::Directory_service::Openlink_result openlink_result =
|
2018-07-09 11:21:00 +02:00
|
|
|
VFS_THREAD_SAFE(_root_dir.openlink(path, false, &symlink_handle, _alloc));
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
switch (openlink_result) {
|
|
|
|
case Vfs::Directory_service::OPENLINK_OK:
|
|
|
|
break;
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_LOOKUP_FAILED:
|
|
|
|
return Errno(ENOENT);
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_NAME_TOO_LONG:
|
|
|
|
/* should not happen */
|
|
|
|
return Errno(ENAMETOOLONG);
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_NODE_ALREADY_EXISTS:
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_NO_SPACE:
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_OUT_OF_RAM:
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_OUT_OF_CAPS:
|
|
|
|
case Vfs::Directory_service::OPENLINK_ERR_PERMISSION_DENIED:
|
|
|
|
return Errno(EACCES);
|
|
|
|
}
|
|
|
|
|
2019-03-25 15:41:43 +01:00
|
|
|
symlink_handle->handler(&_response_handler);
|
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *symlink_handle;
|
|
|
|
::size_t const buf_size;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *symlink_handle,
|
|
|
|
::size_t const buf_size)
|
|
|
|
: symlink_handle(symlink_handle), buf_size(buf_size) { }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
|
|
|
retry =
|
2018-07-09 11:21:00 +02:00
|
|
|
!VFS_THREAD_SAFE(symlink_handle->fs().queue_read(symlink_handle, buf_size));
|
2017-08-15 20:51:53 +02:00
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(symlink_handle, buf_size);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef Vfs::File_io_service::Read_result Result;
|
|
|
|
|
|
|
|
Result out_result;
|
2014-09-09 14:32:31 +02:00
|
|
|
Vfs::file_size out_len = 0;
|
2014-04-11 21:14:10 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
{
|
|
|
|
struct Check : Libc::Suspend_functor
|
|
|
|
{
|
|
|
|
bool retry { false };
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *symlink_handle;
|
|
|
|
char *buf;
|
|
|
|
::size_t const buf_size;
|
|
|
|
Vfs::file_size &out_len;
|
|
|
|
Result &out_result;
|
|
|
|
|
|
|
|
Check(Vfs::Vfs_handle *symlink_handle,
|
|
|
|
char *buf,
|
|
|
|
::size_t const buf_size,
|
|
|
|
Vfs::file_size &out_len,
|
|
|
|
Result &out_result)
|
|
|
|
: symlink_handle(symlink_handle), buf(buf), buf_size(buf_size),
|
|
|
|
out_len(out_len), out_result(out_result) { }
|
|
|
|
|
|
|
|
bool suspend() override
|
|
|
|
{
|
2017-10-19 14:08:30 +02:00
|
|
|
out_result = VFS_THREAD_SAFE(symlink_handle->fs().complete_read(symlink_handle, buf, buf_size, out_len));
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
/* suspend me if read is still queued */
|
|
|
|
|
|
|
|
retry = (out_result == Result::READ_QUEUED);
|
|
|
|
|
|
|
|
return retry;
|
|
|
|
}
|
|
|
|
} check(symlink_handle, buf, buf_size, out_len, out_result);
|
|
|
|
|
|
|
|
do {
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
suspend(check);
|
2017-08-15 20:51:53 +02:00
|
|
|
} while (check.retry);
|
|
|
|
}
|
|
|
|
|
libc: split task.cc into multiple files
This patch is the first step of re-organizing the internal structure of
the libc. The original version involved many direct calls of global
functions (often with side effects) across compilation units, which
made the control flow (e.g., the initialization sequence) hard to
follow.
The new version replaces those ad-hoc interactions with dedicated
interfaces (like suspend.h, resume.h, select.h, current_time.h). The
underlying facilities are provided by the central Libc::Kernel and
selectively propagated to the various compilation units. The latter is
done by a sequence of 'init_*' calls, which eventually will be replaced
by constructor calls.
The addition of new headers increases the chance for name clashes with
existing (public) headers. To disambiguate libc-internal header files
from public headers, this patch moves the former into a new 'internal/'
subdirectory. This makes the include directives easier to follow and the
libc's source-tree structure more tidy.
There are still a few legacies left, which cannot easily be removed
right now (e.g., because noux relies on them). However, the patch moves
those bad apples to legacy.h and legacy.cc, which highlights the
deprecation of those functions.
Issue #3497
2019-09-18 20:19:10 +02:00
|
|
|
Plugin::resume_all();
|
2018-07-04 14:09:01 +02:00
|
|
|
|
2017-08-15 20:51:53 +02:00
|
|
|
switch (out_result) {
|
|
|
|
case Result::READ_ERR_AGAIN: return Errno(EAGAIN);
|
|
|
|
case Result::READ_ERR_WOULD_BLOCK: return Errno(EWOULDBLOCK);
|
|
|
|
case Result::READ_ERR_INVALID: return Errno(EINVAL);
|
|
|
|
case Result::READ_ERR_IO: return Errno(EIO);
|
|
|
|
case Result::READ_ERR_INTERRUPT: return Errno(EINTR);
|
|
|
|
case Result::READ_OK: break;
|
|
|
|
|
|
|
|
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
2014-04-11 21:14:10 +02:00
|
|
|
};
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
VFS_THREAD_SAFE(symlink_handle->close());
|
2017-08-15 20:51:53 +02:00
|
|
|
|
2014-04-11 21:14:10 +02:00
|
|
|
return out_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::rmdir(char const *path)
|
|
|
|
{
|
|
|
|
return unlink(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::unlink(char const *path)
|
|
|
|
{
|
|
|
|
typedef Vfs::Directory_service::Unlink_result Result;
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.unlink(path))) {
|
2015-10-30 12:33:26 +01:00
|
|
|
case Result::UNLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
|
|
|
case Result::UNLINK_ERR_NO_PERM: errno = EPERM; return -1;
|
|
|
|
case Result::UNLINK_ERR_NOT_EMPTY: errno = ENOTEMPTY; return -1;
|
|
|
|
case Result::UNLINK_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::rename(char const *from_path, char const *to_path)
|
|
|
|
{
|
|
|
|
typedef Vfs::Directory_service::Rename_result Result;
|
|
|
|
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.leaf_path(to_path))) {
|
2016-03-02 14:32:43 +01:00
|
|
|
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.directory(to_path))) {
|
|
|
|
if (!VFS_THREAD_SAFE(_root_dir.directory(from_path))) {
|
2016-03-02 14:32:43 +01:00
|
|
|
errno = EISDIR; return -1;
|
|
|
|
}
|
|
|
|
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.num_dirent(to_path))) {
|
2016-03-02 14:32:43 +01:00
|
|
|
errno = ENOTEMPTY; return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2018-07-09 11:21:00 +02:00
|
|
|
if (VFS_THREAD_SAFE(_root_dir.directory(from_path))) {
|
2016-03-02 14:32:43 +01:00
|
|
|
errno = ENOTDIR; return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-19 14:08:30 +02:00
|
|
|
switch (VFS_THREAD_SAFE(_root_dir.rename(from_path, to_path))) {
|
2014-04-11 21:14:10 +02:00
|
|
|
case Result::RENAME_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
|
|
|
case Result::RENAME_ERR_CROSS_FS: errno = EXDEV; return -1;
|
|
|
|
case Result::RENAME_ERR_NO_PERM: errno = EPERM; return -1;
|
2014-10-15 16:09:45 +02:00
|
|
|
case Result::RENAME_OK: break;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *Libc::Vfs_plugin::mmap(void *addr_in, ::size_t length, int prot, int flags,
|
|
|
|
Libc::File_descriptor *fd, ::off_t offset)
|
|
|
|
{
|
2019-08-21 09:34:35 +02:00
|
|
|
if (prot != PROT_READ && !(prot == (PROT_READ | PROT_WRITE) && flags == MAP_PRIVATE)) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("mmap for prot=", Genode::Hex(prot), " not supported");
|
2014-04-11 21:14:10 +02:00
|
|
|
errno = EACCES;
|
|
|
|
return (void *)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr_in != 0) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("mmap for predefined address not supported");
|
2014-04-11 21:14:10 +02:00
|
|
|
errno = EINVAL;
|
|
|
|
return (void *)-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX attempt to obtain memory mapping via
|
|
|
|
* 'Vfs::Directory_service::dataspace'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void *addr = Libc::mem_alloc()->alloc(length, PAGE_SHIFT);
|
|
|
|
if (addr == (void *)-1) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
return (void *)-1;
|
|
|
|
}
|
|
|
|
|
2018-10-29 02:35:05 +01:00
|
|
|
/* copy variables for complete read */
|
|
|
|
size_t read_remain = length;
|
|
|
|
size_t read_offset = offset;
|
|
|
|
char *read_addr = (char *)addr;
|
|
|
|
|
|
|
|
while (read_remain > 0) {
|
|
|
|
ssize_t length_read = ::pread(fd->libc_fd, read_addr, read_remain, read_offset);
|
|
|
|
if (length_read < 0) { /* error */
|
|
|
|
Genode::error("mmap could not obtain file content");
|
|
|
|
::munmap(addr, length);
|
|
|
|
errno = EACCES;
|
|
|
|
return (void *)-1;
|
|
|
|
} else if (length_read == 0) /* EOF */
|
|
|
|
break; /* done (length can legally be greater than the file length) */
|
|
|
|
read_remain -= length_read;
|
|
|
|
read_offset += length_read;
|
|
|
|
read_addr += length_read;
|
2014-04-11 21:14:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::munmap(void *addr, ::size_t)
|
|
|
|
{
|
|
|
|
Libc::mem_alloc()->free(addr);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-02-01 11:28:15 +01:00
|
|
|
|
|
|
|
|
2019-04-26 12:47:33 +02:00
|
|
|
bool Libc::Vfs_plugin::poll(File_descriptor &fd, struct pollfd &pfd)
|
|
|
|
{
|
|
|
|
if (fd.plugin != this) return false;
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(&fd);
|
|
|
|
if (!handle) {
|
|
|
|
pfd.revents |= POLLNVAL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
POLLIN_MASK = POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI,
|
|
|
|
POLLOUT_MASK = POLLOUT | POLLWRNORM | POLLWRBAND,
|
|
|
|
};
|
|
|
|
|
|
|
|
bool res { false };
|
|
|
|
|
|
|
|
if ((pfd.events & POLLIN_MASK)
|
|
|
|
&& VFS_THREAD_SAFE(handle->fs().read_ready(handle)))
|
|
|
|
{
|
|
|
|
pfd.revents |= pfd.events & POLLIN_MASK;
|
|
|
|
res = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((pfd.events & POLLOUT_MASK) /* XXX always writeable */)
|
|
|
|
{
|
|
|
|
pfd.revents |= pfd.events & POLLOUT_MASK;
|
|
|
|
res = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-01 11:28:15 +01:00
|
|
|
bool Libc::Vfs_plugin::supports_select(int nfds,
|
|
|
|
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
struct timeval *timeout)
|
|
|
|
{
|
|
|
|
/* return true if any file descriptor (which is set) belongs to the VFS */
|
|
|
|
for (int fd = 0; fd < nfds; ++fd) {
|
|
|
|
|
|
|
|
if (FD_ISSET(fd, readfds) || FD_ISSET(fd, writefds) || FD_ISSET(fd, exceptfds)) {
|
|
|
|
|
|
|
|
Libc::File_descriptor *fdo =
|
|
|
|
Libc::file_descriptor_allocator()->find_by_libc_fd(fd);
|
|
|
|
|
|
|
|
if (fdo && (fdo->plugin == this))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Libc::Vfs_plugin::select(int nfds,
|
|
|
|
fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
|
|
|
struct timeval *timeout)
|
|
|
|
{
|
|
|
|
int nready = 0;
|
|
|
|
|
|
|
|
fd_set const in_readfds = *readfds;
|
|
|
|
fd_set const in_writefds = *writefds;
|
|
|
|
/* XXX exceptfds not supported */
|
|
|
|
|
|
|
|
/* clear fd sets */
|
|
|
|
FD_ZERO(readfds);
|
|
|
|
FD_ZERO(writefds);
|
|
|
|
FD_ZERO(exceptfds);
|
|
|
|
|
|
|
|
for (int fd = 0; fd < nfds; ++fd) {
|
|
|
|
|
|
|
|
Libc::File_descriptor *fdo =
|
|
|
|
Libc::file_descriptor_allocator()->find_by_libc_fd(fd);
|
|
|
|
|
|
|
|
/* handle only fds that belong to this plugin */
|
|
|
|
if (!fdo || (fdo->plugin != this))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
Vfs::Vfs_handle *handle = vfs_handle(fdo);
|
|
|
|
if (!handle) continue;
|
|
|
|
|
|
|
|
if (FD_ISSET(fd, &in_readfds)) {
|
2017-10-19 14:08:30 +02:00
|
|
|
if (VFS_THREAD_SAFE(handle->fs().read_ready(handle))) {
|
2017-02-01 11:28:15 +01:00
|
|
|
FD_SET(fd, readfds);
|
|
|
|
++nready;
|
|
|
|
} else {
|
2017-04-07 14:02:40 +02:00
|
|
|
Libc::notify_read_ready(handle);
|
2017-02-01 11:28:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FD_ISSET(fd, &in_writefds)) {
|
|
|
|
if (true /* XXX always writeable */) {
|
|
|
|
FD_SET(fd, writefds);
|
|
|
|
++nready;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX exceptfds not supported */
|
|
|
|
}
|
|
|
|
return nready;
|
|
|
|
}
|