unify file system utilities to os/include/file_system

Fixes #1564
This commit is contained in:
Emery Hemingway 2015-06-04 08:59:40 -04:00 committed by Christian Helmuth
parent c72ea84bcd
commit cec2dd3b3f
8 changed files with 248 additions and 193 deletions

View File

@ -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 :

View File

@ -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 "/../" */

View File

@ -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 "/../" */

View File

@ -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_ */

View File

@ -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; }
};

View File

@ -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 **
*****************/

View File

@ -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 "/../" */

View File

@ -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;