mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
Libc plugin for using file I/O on ROM dataspaces
This commit is contained in:
parent
dc4f6871c3
commit
54cb49583b
6
libports/lib/mk/libc_rom.mk
Normal file
6
libports/lib/mk/libc_rom.mk
Normal file
@ -0,0 +1,6 @@
|
||||
SRC_CC = plugin.cc
|
||||
LIBS += libc
|
||||
|
||||
vpath plugin.cc $(REP_DIR)/src/lib/libc_rom
|
||||
|
||||
SHARED_LIB = yes
|
5
libports/src/lib/libc_rom/README
Normal file
5
libports/src/lib/libc_rom/README
Normal file
@ -0,0 +1,5 @@
|
||||
The 'libc_rom' plugin allows the use of Genode's ROM-session interface via file
|
||||
operations of the C library.
|
||||
|
||||
This implementation is very preliminary. It supports no file operations other
|
||||
than open and read.
|
172
libports/src/lib/libc_rom/plugin.cc
Normal file
172
libports/src/lib/libc_rom/plugin.cc
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* \brief Libc plugin that uses Genode's ROM session
|
||||
* \author Norman Feske
|
||||
* \date 2012-01-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* libc plugin interface */
|
||||
#include <libc-plugin/plugin.h>
|
||||
#include <libc-plugin/fd_alloc.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/env.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* An open file descriptor for this plugin corresponds to a ROM connection
|
||||
*
|
||||
* The connection is created along with the context.
|
||||
*/
|
||||
struct Plugin_context : Libc::Plugin_context, Genode::Attached_rom_dataspace
|
||||
{
|
||||
Genode::off_t read_offset;
|
||||
|
||||
Plugin_context(char const *filename)
|
||||
: Genode::Attached_rom_dataspace(filename), read_offset(0) { }
|
||||
};
|
||||
|
||||
|
||||
static inline Plugin_context *context(Libc::File_descriptor *fd)
|
||||
{
|
||||
return static_cast<Plugin_context *>(fd->context);
|
||||
}
|
||||
|
||||
|
||||
class Plugin : public Libc::Plugin
|
||||
{
|
||||
private:
|
||||
|
||||
bool _probe_rom(char const *filename)
|
||||
{
|
||||
try {
|
||||
/*
|
||||
* Create ROM connection as local variable. The connection
|
||||
* gets closed automatically when leaving the scope of this
|
||||
* function.
|
||||
*/
|
||||
Genode::Rom_connection rom(filename);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Plugin()
|
||||
{ }
|
||||
|
||||
bool supports_open(const char *path, int flags)
|
||||
{
|
||||
return _probe_rom(path);
|
||||
}
|
||||
|
||||
Libc::File_descriptor *open(const char *pathname, int flags)
|
||||
{
|
||||
Plugin_context *context = new (Genode::env()->heap())
|
||||
Plugin_context(pathname);
|
||||
return Libc::file_descriptor_allocator()->alloc(this, context);
|
||||
}
|
||||
|
||||
int close(Libc::File_descriptor *fd)
|
||||
{
|
||||
Genode::destroy(Genode::env()->heap(), context(fd));
|
||||
Libc::file_descriptor_allocator()->free(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t read(Libc::File_descriptor *fd, void *buf, ::size_t count)
|
||||
{
|
||||
Plugin_context *rom = context(fd);
|
||||
|
||||
/* file read limit is the size of data space */
|
||||
Genode::size_t const max_size = rom->size();
|
||||
|
||||
/* shortcut to current read offset */
|
||||
Genode::off_t &read_offset = rom->read_offset;
|
||||
|
||||
/* maximum read offset, clamped to dataspace size */
|
||||
Genode::off_t const end_offset = Genode::min(count + read_offset, max_size);
|
||||
|
||||
/* source address within the dataspace */
|
||||
char const *src = rom->local_addr<char>() + read_offset;
|
||||
|
||||
/* check if end of file is reached */
|
||||
if (read_offset >= end_offset)
|
||||
return 0;
|
||||
|
||||
/* copy-out bytes from ROM dataspace */
|
||||
Genode::off_t num_bytes = end_offset - read_offset;
|
||||
memcpy(buf, src, num_bytes);
|
||||
|
||||
/* advance read offset */
|
||||
read_offset += num_bytes;
|
||||
|
||||
return num_bytes;
|
||||
}
|
||||
|
||||
::off_t lseek(Libc::File_descriptor *fd, ::off_t offset, int whence)
|
||||
{
|
||||
Plugin_context *rom = context(fd);
|
||||
|
||||
switch (whence) {
|
||||
|
||||
case SEEK_CUR:
|
||||
|
||||
offset += rom->read_offset;
|
||||
|
||||
/*
|
||||
* falling through...
|
||||
*/
|
||||
|
||||
case SEEK_SET:
|
||||
|
||||
if (offset > rom->size()) {
|
||||
errno = EINVAL;
|
||||
return (::off_t)(-1);
|
||||
}
|
||||
|
||||
rom->read_offset = offset;
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
|
||||
rom->read_offset = rom->size();
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
return (::off_t)(-1);
|
||||
}
|
||||
|
||||
return rom->read_offset;
|
||||
}
|
||||
};
|
||||
|
||||
} /* unnamed namespace */
|
||||
|
||||
|
||||
void __attribute__((constructor)) init_libc_rom(void)
|
||||
{
|
||||
static Plugin plugin;
|
||||
}
|
Loading…
Reference in New Issue
Block a user