mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-30 02:28:54 +00:00
parent
ec559b85e2
commit
baea48fbec
@ -343,10 +343,6 @@ Separate components
|
||||
Provides each file contained in a tar file obtained via Genode's ROM session
|
||||
as separate ROM session.
|
||||
|
||||
:_os/src/server/iso9660/_:
|
||||
Provides each file of an ISO9660 file system accessed via a block session as
|
||||
separate ROM session.
|
||||
|
||||
:_os/src/server/lx_fs/_:
|
||||
A file system server that makes the file system of a Linux base platform
|
||||
available to Genode.
|
||||
|
@ -1,27 +0,0 @@
|
||||
This directory contains an implementation of an ISO 9660 file system.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
At the moment, the only file-name format supported is the Rock Ridge extension.
|
||||
The ISO specified 8.3 upper-case-file names are not supported, as well as Joliet.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The server requires an ATAPI-block device as back-end. Please have a look at
|
||||
'os/src/drivers/atapi'. The front-end of the server is implemented as a ROM
|
||||
session server. In order to access this server from your application, you need
|
||||
to route the ROM session to the ISO-ROM-session server in Genode's configuration
|
||||
file:
|
||||
|
||||
!<start name="test-iso">
|
||||
! <resource name="RAM" quantum="10M" />
|
||||
! <route>
|
||||
! <service name="ROM"><child name="iso9660"/></service>
|
||||
! </route>
|
||||
!</start>
|
||||
|
||||
Currently, the RAM quota necessary to obtain a file from the ISO file system
|
||||
is allocated on behalf of the ISO server. Please make sure to provide
|
||||
sufficient RAM quota to the ISO server.
|
@ -1,476 +0,0 @@
|
||||
/*
|
||||
* \brief ISO 9660 file system support
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2010-07-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/exception.h>
|
||||
#include <base/log.h>
|
||||
#include <base/stdint.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <util/token.h>
|
||||
|
||||
#include "iso9660.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Iso {
|
||||
class Sector;
|
||||
class Rock_ridge;
|
||||
class Iso_base;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sector reads one or more packets from the block interface
|
||||
*/
|
||||
class Iso::Sector {
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
MAX_SECTORS = 32, /* max. number sectors that can be read in one
|
||||
transaction */
|
||||
BLOCK_SIZE = 2048,
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Block::Session::Tx::Source &_source;
|
||||
Block::Packet_descriptor _p { };
|
||||
|
||||
public:
|
||||
|
||||
Sector(Block::Connection<> &block,
|
||||
unsigned long blk_nr, unsigned long count)
|
||||
: _source(*block.tx())
|
||||
{
|
||||
try {
|
||||
_p = Block::Packet_descriptor(
|
||||
block.alloc_packet(blk_size() * count),
|
||||
Block::Packet_descriptor::READ,
|
||||
blk_nr * ((float)blk_size() / BLOCK_SIZE),
|
||||
count * ((float)blk_size() / BLOCK_SIZE));
|
||||
|
||||
_source.submit_packet(_p);
|
||||
_p = _source.get_acked_packet();
|
||||
|
||||
if (!_p.succeeded()) {
|
||||
Genode::error("Could not read block ", blk_nr);
|
||||
throw Io_error();
|
||||
}
|
||||
|
||||
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
Genode::error("packet overrun!");
|
||||
_p = _source.get_acked_packet();
|
||||
throw Io_error();
|
||||
}
|
||||
}
|
||||
|
||||
~Sector() {
|
||||
_source.release_packet(_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return address of packet content
|
||||
*/
|
||||
template <typename T>
|
||||
T addr() { return reinterpret_cast<T>(_source.packet_content(_p)); }
|
||||
|
||||
static size_t blk_size() { return BLOCK_SIZE; }
|
||||
|
||||
static unsigned long to_blk(unsigned long bytes) {
|
||||
return ((bytes + blk_size() - 1) & ~(blk_size() - 1)) / blk_size(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rock ridge extension (see IEEE P1282)
|
||||
*/
|
||||
class Iso::Rock_ridge
|
||||
{
|
||||
public:
|
||||
|
||||
enum {
|
||||
NM = 0x4d4e, /* POSIX name system use entry (little endian) */
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
uint16_t _signature;
|
||||
uint8_t _length;
|
||||
uint8_t _version;
|
||||
uint8_t _flags;
|
||||
char _name;
|
||||
|
||||
public:
|
||||
|
||||
char *name() { return &_name; }
|
||||
uint8_t length() { return _length - 5; }
|
||||
|
||||
static Rock_ridge* scan_name(uint8_t *ptr, uint8_t size)
|
||||
{
|
||||
Rock_ridge *rr = (Rock_ridge *)ptr;
|
||||
|
||||
while (rr->_length && ((uint8_t *)rr < ptr + size - 4)) {
|
||||
if (rr->_signature == NM)
|
||||
return rr;
|
||||
rr = rr->next();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Rock_ridge *next() { return (Rock_ridge *)((uint8_t *)this + _length); }
|
||||
};
|
||||
|
||||
|
||||
/*********************
|
||||
** ISO9660 classes **
|
||||
*********************/
|
||||
|
||||
/**
|
||||
* Access memory using offsets
|
||||
*/
|
||||
class Iso::Iso_base
|
||||
{
|
||||
protected:
|
||||
|
||||
template <typename T>
|
||||
T value(int offset) { return *((T *)(this + offset)); }
|
||||
|
||||
template <typename T>
|
||||
T ptr(int offset) { return (T)(this + offset); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class representing a directory descriptions (see ECMA 119)
|
||||
*/
|
||||
class Directory_record : public Iso::Iso_base
|
||||
{
|
||||
enum {
|
||||
TABLE_LENGTH = 33, /* fixed length of directory record */
|
||||
|
||||
ROOT_DIR = 0x0, /* special names of root and parent directories */
|
||||
PARENT_DIR = 0x1,
|
||||
|
||||
DIR_FLAG = 0x2, /* directory flag in attributes */
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/* total length of this record */
|
||||
uint8_t record_length() { return value<uint8_t>(0); }
|
||||
|
||||
/* starting block of extent */
|
||||
uint32_t blk_nr() { return value<uint32_t>(2); }
|
||||
|
||||
/* length in bytes of extent */
|
||||
uint32_t data_length() { return value<uint32_t>(10); }
|
||||
|
||||
/* attributes */
|
||||
uint8_t file_flags() { return value<uint8_t>(25); }
|
||||
|
||||
/* length of file name */
|
||||
uint8_t file_name_length() { return value<uint8_t>(32); }
|
||||
|
||||
/* retrieve the file name */
|
||||
void file_name(char *buf)
|
||||
{
|
||||
buf[0] = 0;
|
||||
|
||||
/* try Rock Ridge name */
|
||||
Iso::Rock_ridge *rr = Iso::Rock_ridge::scan_name(system_use(),
|
||||
system_use_size());
|
||||
|
||||
if (rr) {
|
||||
memcpy(buf, rr->name(), rr->length());
|
||||
buf[rr->length()] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* retrieve iso name */
|
||||
char *name = ptr<char*>(33);
|
||||
|
||||
/*
|
||||
* Check for root and parent directory names and modify them
|
||||
* to '.' and '..' respectively.
|
||||
*/
|
||||
if (file_name_length() == 1)
|
||||
|
||||
switch (name[0]) {
|
||||
|
||||
case PARENT_DIR:
|
||||
|
||||
buf[2] = 0;
|
||||
buf[1] = '.';
|
||||
buf[0] = '.';
|
||||
return;
|
||||
|
||||
case ROOT_DIR:
|
||||
|
||||
buf[1] = 0;
|
||||
buf[0] = '.';
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buf, name, file_name_length());
|
||||
buf[file_name_length()] = 0;
|
||||
}
|
||||
|
||||
/* pad byte after file name (if file name length is even, only) */
|
||||
uint8_t pad_byte() { return !(file_name_length() % 2) ? 1 : 0; }
|
||||
|
||||
/* system use area */
|
||||
uint8_t *system_use()
|
||||
{
|
||||
return (uint8_t*)this + TABLE_LENGTH
|
||||
+ file_name_length() + pad_byte();
|
||||
}
|
||||
|
||||
/* length in bytes of system use area */
|
||||
uint8_t system_use_size()
|
||||
{
|
||||
return record_length() - file_name_length()
|
||||
- TABLE_LENGTH - pad_byte();
|
||||
}
|
||||
|
||||
/* retrieve next record */
|
||||
Directory_record *next()
|
||||
{
|
||||
Directory_record *_next = this + record_length();
|
||||
|
||||
if (_next->record_length())
|
||||
return _next;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find a directory record with file name matching 'level' */
|
||||
Directory_record *locate(char const *level)
|
||||
{
|
||||
Directory_record *dir = this;
|
||||
|
||||
while (dir) {
|
||||
|
||||
char name[Iso::LEVEL_LENGTH];
|
||||
dir->file_name(name);
|
||||
|
||||
if (!strcmp(name, level))
|
||||
return dir;
|
||||
|
||||
dir = dir->next();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* describes this record a directory */
|
||||
bool directory() { return file_flags() & DIR_FLAG; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Volume descriptor (see ECMA 119)
|
||||
*/
|
||||
class Volume_descriptor : public Iso::Iso_base
|
||||
{
|
||||
enum {
|
||||
/* volume types */
|
||||
PRIMARY = 0x01, /* type of primary volume descriptor */
|
||||
TERMINATOR = 0xff, /* type of terminating descriptor */
|
||||
|
||||
/* constants */
|
||||
ROOT_SIZE = 34, /* the root directory record has a fixed length */
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/* descriptor type */
|
||||
uint8_t type() { return value<uint8_t>(0); }
|
||||
|
||||
/* root directory record */
|
||||
Directory_record * root_record() { return ptr<Directory_record *>(156); }
|
||||
|
||||
/* check for primary descriptor */
|
||||
bool primary() { return type() == PRIMARY; }
|
||||
|
||||
/* check for terminating descriptor */
|
||||
bool terminator() { return type() == TERMINATOR; }
|
||||
|
||||
/* copy the root record */
|
||||
Directory_record *copy_root_record(Genode::Allocator &alloc)
|
||||
{
|
||||
return alloc.try_alloc(ROOT_SIZE).convert<Directory_record *>(
|
||||
|
||||
[&] (void *ptr) -> Directory_record * {
|
||||
memcpy(ptr, root_record(), ROOT_SIZE);
|
||||
return (Directory_record *)ptr; },
|
||||
|
||||
[&] (Allocator::Alloc_error e) -> Directory_record * {
|
||||
Allocator::throw_alloc_error(e); }
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Locate the root-directory record in the primary volume descriptor
|
||||
*/
|
||||
static Directory_record *locate_root(Genode::Allocator &alloc,
|
||||
Block::Connection<> &block)
|
||||
{
|
||||
/* volume descriptors in ISO9660 start at block 16 */
|
||||
for (unsigned long blk_nr = 16;; blk_nr++) {
|
||||
Iso::Sector sec(block, blk_nr, 1);
|
||||
Volume_descriptor *vol = sec.addr<Volume_descriptor *>();
|
||||
|
||||
if (vol->primary())
|
||||
return vol->copy_root_record(alloc);
|
||||
|
||||
if (vol->terminator())
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return root directory record
|
||||
*/
|
||||
static Directory_record *root_dir(Genode::Allocator &alloc,
|
||||
Block::Connection<> &block)
|
||||
{
|
||||
Directory_record *root = locate_root(alloc, block);
|
||||
|
||||
if (!root) { throw Iso::Non_data_disc(); }
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
** Iso interface **
|
||||
*******************/
|
||||
|
||||
static Directory_record *_root_dir;
|
||||
|
||||
|
||||
Iso::File_info *Iso::file_info(Genode::Allocator &alloc,
|
||||
Block::Connection<> &block, char const *path)
|
||||
{
|
||||
char level[PATH_LENGTH];
|
||||
|
||||
struct Scanner_policy_file
|
||||
{
|
||||
static bool identifier_char(char c, unsigned /* i */)
|
||||
{
|
||||
return c != '/' && c != 0;
|
||||
}
|
||||
};
|
||||
typedef ::Genode::Token<Scanner_policy_file> Token;
|
||||
|
||||
Token t(path);
|
||||
|
||||
if (!_root_dir) {
|
||||
_root_dir = root_dir(alloc, block);
|
||||
}
|
||||
|
||||
Directory_record *dir = _root_dir;
|
||||
uint32_t blk_nr = 0, data_length = 0;
|
||||
|
||||
/* determine block nr and file length on disk, parse directory records */
|
||||
while (t) {
|
||||
|
||||
if (t.type() != Token::IDENT) {
|
||||
t = t.next();
|
||||
continue;
|
||||
}
|
||||
|
||||
t.string(level, PATH_LENGTH);
|
||||
|
||||
/*
|
||||
* Save current block number in a variable because successive
|
||||
* iterations might override the memory location where dir points
|
||||
* to when a directory entry spans several sectors.
|
||||
*/
|
||||
uint32_t current_blk_nr = dir->blk_nr();
|
||||
|
||||
/* load extent of directory record and search for level */
|
||||
for (unsigned long i = 0; i < Sector::to_blk(dir->data_length()); i++) {
|
||||
Sector sec(block, current_blk_nr + i, 1);
|
||||
Directory_record *tmp = sec.addr<Directory_record *>()->locate(level);
|
||||
|
||||
if (!tmp && i == Sector::to_blk(dir->data_length()) - 1) {
|
||||
Genode::error("file not found: ", Genode::Cstring(path));
|
||||
throw File_not_found();
|
||||
}
|
||||
|
||||
if (!tmp) continue;
|
||||
|
||||
dir = tmp;
|
||||
current_blk_nr = dir->blk_nr();
|
||||
|
||||
if (!dir->directory()) {
|
||||
blk_nr = current_blk_nr;
|
||||
data_length = dir->data_length();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
t = t.next();
|
||||
}
|
||||
|
||||
/* Warning: Don't access 'dir' after this point, since the sector is gone */
|
||||
|
||||
if (!blk_nr && !data_length) {
|
||||
Genode::error("file not found: ", Genode::Cstring(path));
|
||||
throw File_not_found();
|
||||
}
|
||||
|
||||
return new (alloc) File_info(blk_nr, data_length);
|
||||
}
|
||||
|
||||
|
||||
unsigned long Iso::read_file(Block::Connection<> &block, File_info *info,
|
||||
off_t file_offset, uint32_t length, void *buf_ptr)
|
||||
{
|
||||
uint8_t *buf = (uint8_t *)buf_ptr;
|
||||
if (info->size() <= (size_t)(length + file_offset))
|
||||
length = info->size() - file_offset - 1;
|
||||
|
||||
unsigned long total_blk_count = ((length + (Sector::blk_size() - 1)) &
|
||||
~((Sector::blk_size()) - 1)) / Sector::blk_size();
|
||||
unsigned long ret = total_blk_count;
|
||||
unsigned long blk_count;
|
||||
unsigned long blk_nr = info->blk_nr() + (file_offset / Sector::blk_size());
|
||||
|
||||
while ((blk_count = min<unsigned long>(Sector::MAX_SECTORS, total_blk_count))) {
|
||||
Sector sec(block, blk_nr, blk_count);
|
||||
|
||||
total_blk_count -= blk_count;
|
||||
blk_nr += blk_count;
|
||||
|
||||
unsigned long copy_length = blk_count * Sector::blk_size();
|
||||
memcpy(buf, sec.addr<void *>(), copy_length);
|
||||
|
||||
length -= copy_length;
|
||||
buf += copy_length;
|
||||
|
||||
/* zero out rest of page */
|
||||
if (!total_blk_count && (blk_count % 2))
|
||||
memset(buf, 0, Sector::blk_size());
|
||||
}
|
||||
|
||||
return ret * Sector::blk_size();
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* \brief ISO interface to session server
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/stdint.h>
|
||||
#include <block_session/connection.h>
|
||||
|
||||
namespace Iso {
|
||||
|
||||
/*
|
||||
* Exceptions
|
||||
*/
|
||||
class Io_error : public Genode::Exception { };
|
||||
class Non_data_disc : public Genode::Exception { };
|
||||
class File_not_found : public Genode::Exception { };
|
||||
|
||||
/* enable/disable debugging output */
|
||||
const int verbose = 0;
|
||||
|
||||
enum {
|
||||
PATH_LENGTH = 128, /* max. length of a path */
|
||||
LEVEL_LENGTH = 32, /* max. length of a level of a path */
|
||||
PAGE_SIZE = 4096,
|
||||
};
|
||||
|
||||
|
||||
class File_info
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::uint32_t _blk_nr;
|
||||
Genode::size_t _size;
|
||||
|
||||
public:
|
||||
|
||||
File_info(Genode::uint32_t blk_nr, Genode::size_t size)
|
||||
: _blk_nr(blk_nr), _size(size) {}
|
||||
|
||||
Genode::uint32_t blk_nr() { return _blk_nr; }
|
||||
Genode::size_t size() { return _size; }
|
||||
Genode::size_t page_sized() { return (_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); }
|
||||
};
|
||||
|
||||
|
||||
/*******************
|
||||
** Iso interface **
|
||||
*******************/
|
||||
|
||||
/**
|
||||
* Retrieve file information
|
||||
*
|
||||
* \param alloc allocator used for File_info object
|
||||
* \param block Block session used to read sectors from ISO
|
||||
* \param path absolute path of the file (slash separated)
|
||||
*
|
||||
* \throw File_not_found
|
||||
* \throw Io_error
|
||||
* \throw Non_data_disc
|
||||
*
|
||||
* \return Pointer to File_info class
|
||||
*/
|
||||
File_info *file_info(Genode::Allocator &alloc, Block::Connection<> &block, char const *path);
|
||||
|
||||
/**
|
||||
* Read data from ISO
|
||||
*
|
||||
* \param block Block session used to read sectors from ISO
|
||||
* \param info File Info of file to read the data from
|
||||
* \param file_offset Offset in file
|
||||
* \param length Number of bytes to read
|
||||
* \param buf Output buffer
|
||||
*
|
||||
* \throw Io_error
|
||||
*
|
||||
* \return Number of bytes read
|
||||
*/
|
||||
unsigned long read_file(Block::Connection<> &block, File_info *info, Genode::off_t file_offset,
|
||||
Genode::uint32_t length, void *buf);
|
||||
} /* namespace Iso */
|
@ -1,197 +0,0 @@
|
||||
/*
|
||||
* \brief Rom-session server for ISO file systems
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \date 2010-07-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <root/component.h>
|
||||
#include <util/avl_string.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/session_label.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <rom_session/rom_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include "iso9660.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/*****************
|
||||
** ROM service **
|
||||
*****************/
|
||||
|
||||
namespace Iso {
|
||||
|
||||
typedef Avl_string<PATH_LENGTH> File_base;
|
||||
typedef Avl_tree<Avl_string_base> File_cache;
|
||||
|
||||
class File;
|
||||
class Rom_component;
|
||||
|
||||
typedef Genode::Root_component<Rom_component> Root_component;
|
||||
|
||||
|
||||
class Root;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* File abstraction
|
||||
*/
|
||||
class Iso::File : public File_base
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
File(File const &);
|
||||
File &operator = (File const &);
|
||||
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
File_info *_info;
|
||||
Attached_ram_dataspace _ds;
|
||||
|
||||
public:
|
||||
|
||||
File(Genode::Env &env, Genode::Allocator &alloc,
|
||||
Block::Connection<> &block, char const *path)
|
||||
:
|
||||
File_base(path), _alloc(alloc),
|
||||
_info(Iso::file_info(_alloc, block, path)),
|
||||
_ds(env.ram(), env.rm(), align_addr(_info->page_sized(), 12))
|
||||
{
|
||||
Iso::read_file(block, _info, 0, _ds.size(), _ds.local_addr<void>());
|
||||
}
|
||||
|
||||
~File() { destroy(_alloc, _info); }
|
||||
|
||||
Dataspace_capability dataspace() { return _ds.cap(); }
|
||||
};
|
||||
|
||||
|
||||
class Iso::Rom_component : public Genode::Rpc_object<Rom_session>
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Rom_component(Rom_component const &);
|
||||
Rom_component &operator = (Rom_component const &);
|
||||
|
||||
File *_file = nullptr;
|
||||
|
||||
File *_lookup(File_cache &cache, char const *path)
|
||||
{
|
||||
return static_cast<File *>(cache.first() ?
|
||||
cache.first()->find_by_name(path) :
|
||||
0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Rom_dataspace_capability dataspace() override {
|
||||
return static_cap_cast<Rom_dataspace>(_file->dataspace()); }
|
||||
|
||||
void sigh(Signal_context_capability) override { }
|
||||
|
||||
Rom_component(Genode::Env &env, Genode::Allocator &alloc,
|
||||
File_cache &cache, Block::Connection<> &block,
|
||||
char const *path)
|
||||
{
|
||||
if ((_file = _lookup(cache, path))) {
|
||||
Genode::log("cache hit for file ", Genode::Cstring(path));
|
||||
return;
|
||||
}
|
||||
|
||||
_file = new (alloc) File(env, alloc, block, path);
|
||||
Genode::log("request for file ", Genode::Cstring(path));
|
||||
|
||||
cache.insert(_file);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Iso::Root : public Iso::Root_component
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Allocator &_alloc;
|
||||
|
||||
Allocator_avl _block_alloc { &_alloc };
|
||||
Block::Connection<> _block { _env, &_block_alloc };
|
||||
|
||||
/*
|
||||
* Entries in the cache are never freed, even if the ROM session
|
||||
* gets destroyed.
|
||||
*/
|
||||
File_cache _cache { };
|
||||
|
||||
char _path[PATH_LENGTH];
|
||||
|
||||
protected:
|
||||
|
||||
Rom_component *_create_session(const char *args) override
|
||||
{
|
||||
size_t ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
size_t session_size = sizeof(Rom_component) + sizeof(File_info);
|
||||
if (ram_quota < session_size)
|
||||
throw Insufficient_ram_quota();
|
||||
|
||||
Session_label const label = label_from_args(args);
|
||||
copy_cstring(_path, label.last_element().string(), sizeof(_path));
|
||||
|
||||
if (verbose)
|
||||
Genode::log("Request for file ", Cstring(_path), " len ", strlen(_path));
|
||||
|
||||
try {
|
||||
return new (_alloc) Rom_component(_env, _alloc, _cache, _block, _path);
|
||||
}
|
||||
catch (Io_error) { throw Service_denied(); }
|
||||
catch (Non_data_disc) { throw Service_denied(); }
|
||||
catch (File_not_found) { throw Service_denied(); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Env &env, Allocator &alloc)
|
||||
:
|
||||
Root_component(&env.ep().rpc_ep(), &alloc),
|
||||
_env(env), _alloc(alloc)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Genode::Env &_env;
|
||||
Genode::Heap _heap { _env.ram(), _env.rm() };
|
||||
|
||||
Iso::Root _root { _env, _heap };
|
||||
|
||||
Main(Genode::Env &env) : _env(env)
|
||||
{
|
||||
_env.parent().announce(_env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Main main(env); }
|
@ -1,5 +0,0 @@
|
||||
TARGET = iso9660
|
||||
SRC_CC = main.cc iso9660.cc
|
||||
LIBS = base
|
||||
|
||||
CC_CXX_WARN_STRICT_CONVERSION =
|
Loading…
Reference in New Issue
Block a user