mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +00:00
parent
c72ea84bcd
commit
cec2dd3b3f
@ -314,7 +314,7 @@ void rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t off,
|
||||
Packet *p = backend()->alloc();
|
||||
|
||||
if (verbose)
|
||||
PDBG("fd: %d op: %d len: %zu off: %lx p %p bio %p sync %u", fd, op, dlen, off,
|
||||
PDBG("fd: %d op: %d len: %zu off: %lx p %p bio %p sync %u", fd, op, dlen, (unsigned long)off,
|
||||
p, donearg, !!(op & RUMPUSER_BIO_SYNC));
|
||||
|
||||
p->opcode= op & RUMPUSER_BIO_WRITE ? Block::Packet_descriptor::WRITE :
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
#include <file_system/util.h>
|
||||
|
||||
|
||||
/**
|
||||
@ -40,18 +41,6 @@ static inline bool is_basename(char const *path)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if null-terminated string 'substr' occurs in null-terminated
|
||||
* string 'str'
|
||||
@ -85,9 +74,9 @@ static inline bool valid_filename(char const *str)
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '/') ||
|
||||
File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -105,8 +94,8 @@ static inline bool valid_path(char const *str)
|
||||
return false;
|
||||
|
||||
/* must not contain '\' or ':' */
|
||||
if (string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
/* must not contain "/../" */
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
#include <file_system/util.h>
|
||||
|
||||
|
||||
/**
|
||||
@ -40,18 +41,6 @@ static inline bool is_basename(char const *path)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if null-terminated string 'substr' occurs in null-terminated
|
||||
* string 'str'
|
||||
@ -85,9 +74,9 @@ static inline bool valid_filename(char const *str)
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '/') ||
|
||||
File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -105,8 +94,8 @@ static inline bool valid_path(char const *str)
|
||||
return false;
|
||||
|
||||
/* must not contain '\' or ':' */
|
||||
if (string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
/* must not contain "/../" */
|
||||
|
@ -7,57 +7,237 @@
|
||||
#ifndef _FILE_SYSTEM__UTIL_H_
|
||||
#define _FILE_SYSTEM__UTIL_H_
|
||||
|
||||
/**
|
||||
* Return base-name portion of null-terminated path string
|
||||
*/
|
||||
static inline char const *basename(char const *path)
|
||||
{
|
||||
char const *start = path;
|
||||
#include <file_system_session/file_system_session.h>
|
||||
#include <os/path.h>
|
||||
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
start = path + 1;
|
||||
namespace File_system {
|
||||
|
||||
return start;
|
||||
}
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return base-name portion of null-terminated path string
|
||||
*/
|
||||
static inline char const *basename(char const *path)
|
||||
{
|
||||
char const *start = path;
|
||||
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
start = path + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if specified path is a base name (contains no path delimiters)
|
||||
*/
|
||||
static inline bool is_basename(char const *path)
|
||||
{
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
return false;
|
||||
/**
|
||||
* Return true if specified path is a base name (contains no path delimiters)
|
||||
*/
|
||||
static inline bool is_basename(char const *path)
|
||||
{
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Return true if 'str' is a valid node name
|
||||
*/
|
||||
static inline bool valid_name(char const *str)
|
||||
{
|
||||
if (string_contains(str, '/')) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid node name
|
||||
*/
|
||||
static inline bool valid_name(char const *str)
|
||||
{
|
||||
if (string_contains(str, '/')) return false;
|
||||
/**
|
||||
* Open a directory, ensuring all parent directories exists.
|
||||
*/
|
||||
static inline Dir_handle ensure_dir(Session &fs, char const *path)
|
||||
{
|
||||
try {
|
||||
return fs.dir(path, false);
|
||||
} catch (Lookup_failed) {
|
||||
try {
|
||||
return fs.dir(path, true);
|
||||
} catch (Lookup_failed) {
|
||||
Genode::Path<MAX_PATH_LEN> target(path);
|
||||
target.strip_last_element();
|
||||
target.remove_trailing('/');
|
||||
fs.close(ensure_dir(fs, target.base()));
|
||||
}
|
||||
}
|
||||
return fs.dir(path, true);
|
||||
}
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
return true;
|
||||
/**
|
||||
* Collect pending packet acknowledgements, freeing the space occupied
|
||||
* by the packet in the bulk buffer
|
||||
*
|
||||
* This function should be called prior enqueing new packets into the
|
||||
* packet stream to free up space in the bulk buffer.
|
||||
*/
|
||||
static void collect_acknowledgements(Session::Tx::Source &source)
|
||||
{
|
||||
while (source.ack_avail())
|
||||
source.release_packet(source.get_acked_packet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*/
|
||||
static inline size_t read(Session &fs, File_handle const &file_handle,
|
||||
void *dst, size_t count, seek_off_t seek_offset = 0)
|
||||
{
|
||||
bool success = true;
|
||||
Session::Tx::Source &source = *fs.tx();
|
||||
|
||||
size_t const max_packet_size = source.bulk_buffer_size() / 2;
|
||||
|
||||
size_t remaining_count = count;
|
||||
|
||||
while (remaining_count && success) {
|
||||
|
||||
collect_acknowledgements(source);
|
||||
|
||||
size_t const curr_packet_size = min(remaining_count, max_packet_size);
|
||||
|
||||
Packet_descriptor
|
||||
packet(source.alloc_packet(curr_packet_size),
|
||||
0,
|
||||
file_handle,
|
||||
File_system::Packet_descriptor::READ,
|
||||
curr_packet_size,
|
||||
seek_offset);
|
||||
|
||||
/* pass packet to server side */
|
||||
source.submit_packet(packet);
|
||||
|
||||
packet = source.get_acked_packet();
|
||||
success = packet.succeeded();
|
||||
|
||||
size_t const read_num_bytes = min(packet.length(), curr_packet_size);
|
||||
|
||||
/* copy-out payload into destination buffer */
|
||||
memcpy(dst, source.packet_content(packet), read_num_bytes);
|
||||
|
||||
source.release_packet(packet);
|
||||
|
||||
/* prepare next iteration */
|
||||
seek_offset += read_num_bytes;
|
||||
dst = (void *)((Genode::addr_t)dst + read_num_bytes);
|
||||
remaining_count -= read_num_bytes;
|
||||
|
||||
/*
|
||||
* If we received less bytes than requested, we reached the end
|
||||
* of the file.
|
||||
*/
|
||||
if (read_num_bytes < curr_packet_size)
|
||||
break;
|
||||
}
|
||||
|
||||
return count - remaining_count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write file content
|
||||
*/
|
||||
static inline size_t write(Session &fs, File_handle const &file_handle,
|
||||
void const *src, size_t count, seek_off_t seek_offset = 0)
|
||||
{
|
||||
bool success = true;
|
||||
Session::Tx::Source &source = *fs.tx();
|
||||
|
||||
size_t const max_packet_size = source.bulk_buffer_size() / 2;
|
||||
|
||||
size_t remaining_count = count;
|
||||
|
||||
while (remaining_count && success) {
|
||||
|
||||
collect_acknowledgements(source);
|
||||
|
||||
size_t const curr_packet_size = min(remaining_count, max_packet_size);
|
||||
|
||||
Packet_descriptor
|
||||
packet(source.alloc_packet(curr_packet_size),
|
||||
0,
|
||||
file_handle,
|
||||
File_system::Packet_descriptor::WRITE,
|
||||
curr_packet_size,
|
||||
seek_offset);
|
||||
|
||||
/* copy-out source buffer into payload */
|
||||
memcpy(source.packet_content(packet), src, curr_packet_size);
|
||||
|
||||
/* pass packet to server side */
|
||||
source.submit_packet(packet);
|
||||
|
||||
packet = source.get_acked_packet();;
|
||||
success = packet.succeeded();
|
||||
source.release_packet(packet);
|
||||
|
||||
/* prepare next iteration */
|
||||
seek_offset += curr_packet_size;
|
||||
src = (void *)((Genode::addr_t)src + curr_packet_size);
|
||||
remaining_count -= curr_packet_size;
|
||||
}
|
||||
|
||||
return count - remaining_count;
|
||||
}
|
||||
|
||||
|
||||
class Handle_guard
|
||||
{
|
||||
private:
|
||||
|
||||
Session &_session;
|
||||
Node_handle _handle;
|
||||
|
||||
public:
|
||||
|
||||
Handle_guard(Session &session, Node_handle handle)
|
||||
: _session(session), _handle(handle) { }
|
||||
|
||||
~Handle_guard() { _session.close(_handle); }
|
||||
};
|
||||
|
||||
class Packet_guard
|
||||
{
|
||||
private:
|
||||
|
||||
Session::Tx::Source &_source;
|
||||
File_system::Packet_descriptor _packet;
|
||||
|
||||
public:
|
||||
|
||||
Packet_guard(Session::Tx::Source &source,
|
||||
File_system::Packet_descriptor packet)
|
||||
: _source(source), _packet(packet) { }
|
||||
|
||||
~Packet_guard()
|
||||
{
|
||||
_source.release_packet(_packet);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* _FILE_SYSTEM__UTIL_H_ */
|
||||
|
@ -82,6 +82,10 @@ struct File_system::Node_handle
|
||||
Node_handle(int v) : value(v) { }
|
||||
|
||||
bool valid() const { return value != -1; }
|
||||
|
||||
bool operator == (Node_handle const &other) const { return other.value == value; }
|
||||
bool operator != (Node_handle const &other) const { return other.value != value; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <root/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <file_system_session/connection.h>
|
||||
#include <file_system/util.h>
|
||||
#include <util/arg_string.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/env.h>
|
||||
@ -23,104 +24,6 @@
|
||||
#include <os/path.h>
|
||||
|
||||
|
||||
/*********************************************
|
||||
** Utilities for accessing the file system **
|
||||
*********************************************/
|
||||
|
||||
/*
|
||||
* XXX The following generic utilities should be moved to a public place.
|
||||
* They are based on those found in the 'libc_fs' plugin. We should
|
||||
* unify them.
|
||||
*/
|
||||
|
||||
namespace File_system {
|
||||
|
||||
/**
|
||||
* Collect pending packet acknowledgements, freeing the space occupied
|
||||
* by the packet in the bulk buffer
|
||||
*
|
||||
* This function should be called prior enqueing new packets into the
|
||||
* packet stream to free up space in the bulk buffer.
|
||||
*/
|
||||
static void collect_acknowledgements(Session::Tx::Source &source)
|
||||
{
|
||||
while (source.ack_avail())
|
||||
source.release_packet(source.get_acked_packet());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read file content
|
||||
*/
|
||||
static inline size_t read(Session &fs, File_handle const &file_handle,
|
||||
void *dst, size_t count, off_t seek_offset = 0)
|
||||
{
|
||||
Session::Tx::Source &source = *fs.tx();
|
||||
|
||||
size_t const max_packet_size = source.bulk_buffer_size() / 2;
|
||||
|
||||
size_t remaining_count = count;
|
||||
|
||||
while (remaining_count) {
|
||||
|
||||
collect_acknowledgements(source);
|
||||
|
||||
size_t const curr_packet_size = min(remaining_count, max_packet_size);
|
||||
|
||||
Packet_descriptor
|
||||
packet(source.alloc_packet(curr_packet_size),
|
||||
0,
|
||||
file_handle,
|
||||
File_system::Packet_descriptor::READ,
|
||||
curr_packet_size,
|
||||
seek_offset);
|
||||
|
||||
/* pass packet to server side */
|
||||
source.submit_packet(packet);
|
||||
|
||||
packet = source.get_acked_packet();
|
||||
|
||||
size_t const read_num_bytes = min(packet.length(), curr_packet_size);
|
||||
|
||||
/* copy-out payload into destination buffer */
|
||||
memcpy(dst, source.packet_content(packet), read_num_bytes);
|
||||
|
||||
source.release_packet(packet);
|
||||
|
||||
/* prepare next iteration */
|
||||
seek_offset += read_num_bytes;
|
||||
dst = (void *)((Genode::addr_t)dst + read_num_bytes);
|
||||
remaining_count -= read_num_bytes;
|
||||
|
||||
/*
|
||||
* If we received less bytes than requested, we reached the end
|
||||
* of the file.
|
||||
*/
|
||||
if (read_num_bytes < curr_packet_size)
|
||||
break;
|
||||
}
|
||||
|
||||
return count - remaining_count;
|
||||
}
|
||||
|
||||
|
||||
struct Handle_guard
|
||||
{
|
||||
private:
|
||||
|
||||
Session &_session;
|
||||
Node_handle _handle;
|
||||
|
||||
public:
|
||||
|
||||
Handle_guard(Session &session, Node_handle handle)
|
||||
: _session(session), _handle(handle) { }
|
||||
|
||||
~Handle_guard() { _session.close(_handle); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** ROM service **
|
||||
*****************/
|
||||
|
@ -17,18 +17,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
#include <file_system/util.h>
|
||||
|
||||
|
||||
/**
|
||||
@ -64,9 +53,9 @@ static inline bool valid_filename(char const *str)
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '/') ||
|
||||
File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -85,8 +74,8 @@ static inline bool valid_path(char const *str)
|
||||
return false;
|
||||
|
||||
/* must not contain '\' or ':' */
|
||||
if (string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
/* must not contain "/../" */
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <util/list.h>
|
||||
#include <util/string.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <file_system/util.h>
|
||||
|
||||
/* local includes */
|
||||
#include <buffer.h>
|
||||
@ -47,9 +48,9 @@ static inline bool valid_filename(char const *str)
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
if (File_system::string_contains(str, '/') ||
|
||||
File_system::string_contains(str, '\\') ||
|
||||
File_system::string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user