[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [RFC PATCH 2/5] kernel2: Zentrale LIOv2-Clientfunktionen
+ kernel2: Alles, was ein Client so mit Ressourcen und Streams anstellen
kann, ausgenommen die Ressource erstmal zu bekommen.
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
src/kernel2/include/lostio/client.h | 188 ++++++++++
src/kernel2/src/lostio/client.c | 531 +++++++++++++++++++++++++++
src/kernel2/src/lostio/include/lostio_int.h | 91 +++++
3 files changed, 810 insertions(+), 0 deletions(-)
create mode 100644 src/kernel2/include/lostio/client.h
create mode 100644 src/kernel2/src/lostio/client.c
diff --git a/src/kernel2/include/lostio/client.h b/src/kernel2/include/lostio/client.h
new file mode 100644
index 0000000..d3490f0
--- /dev/null
+++ b/src/kernel2/include/lostio/client.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2008 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the tyndur Project
+ * and its contributors.
+ * 4. Neither the name of the tyndur Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LOSTIO_CLIENT_H_
+#define _LOSTIO_CLIENT_H_
+
+#include "lostio/core.h"
+
+struct lio_dir_entry {
+ struct lio_resource* resource;
+ char name[LIO_MAX_FNLEN + 1];
+ struct lio_stat stat;
+};
+
+/**
+ * Loest einen Pfad zu einer Ressource auf
+ *
+ * @return Die zum Pfad gehoerende Ressource oder NULL, wenn der Pfad keine
+ * existierende Ressource beschreibt.
+ */
+struct lio_resource* lio_get_resource(const char* path, int follow_symlinks);
+
+/**
+ * Oeffnet einen Stream zu einer Ressource
+ *
+ * @param flags Bitmaske für den Modus, in dem der Stream arbeiten soll (siehe
+ * enum lio_flags)
+ *
+ * @return Stream zur Ressource oder NULL, wenn die Ressource nicht erfolgreich
+ * geoeffnet werden konnte.
+ */
+struct lio_stream* lio_open(struct lio_resource* res, int flags);
+
+/**
+ * Liest aus einem Stream aus.
+ *
+ * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_read(struct lio_stream* s, size_t bytes, void* buf);
+
+/**
+ * Liest aus einem Stream aus, ohne die Position des streams zu benutzen oder
+ * zu veraendern.
+ *
+ * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_pread(struct lio_stream* s, uint64_t offset, size_t bytes,
+ void* buf);
+
+/**
+ * Schreibt in einen Stream
+ *
+ * @return Anzahl der geschriebenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_write(struct lio_stream* s, size_t bytes, const void* buf);
+
+/**
+ * Schreibt in einen Stream, ohne dabei die Position des Streams zu benutzen
+ * oder zu veraendern.
+ *
+ * @return Anzahl der geschriebenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_pwrite(struct lio_stream* s, uint64_t offset, size_t bytes,
+ const void* buf);
+
+/**
+ * Position veraendern. Funktioniert nur, wenn die Ressource seekable ist, und
+ * es sich um keine Pipe handelt.
+ *
+ * @param offset Offset um den die Position angepasst werden soll. Wie sie genau
+ * angepasst wird, haengt vom Parameter whence ab.
+ * @param whence Einer der drei Werte aus enum lio_seek_whence.
+ * - LIO_SEEK_SET: Position auf den angegebenen Wert setzen.
+ * - LIO_SEEK_CUR: Angegebenen Wert zur aktuellen Position
+ * dazu addieren.
+ * - LIO_SEEK_END: Position auf das Dateiende setzen.
+ *
+ * @return Neue Position oder < 0 im Fehlerfall.
+ */
+int64_t lio_seek(struct lio_stream* s, int64_t offset, int whence);
+
+/**
+ * Schreibt Aenderungen, die bisher nur im Cache sind, zurueck. Dabei werden
+ * nur die Cluster beruecksichtigt, die im angegebenen Bereich liegen.
+ *
+ * @param s Stream, dessen Aendungen geschrieben werden sollen
+ * @param offset Start des zurueckzuschreibenden Bereichs (in Bytes)
+ * @param bytes Laenge des zurueckzuschreibenden Bereichs (in Bytes) oder 0,
+ * falls die gesamte Datei zurueckgeschrieben werden soll
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ *
+ * @attention Diese Funktion ist unterbrechbar
+ */
+int lio_sync_blocks(struct lio_resource* res, uint64_t offset, size_t bytes);
+
+/**
+ * Schreibt alle zum Zeitpunkt des Aufrufs der Funktion vorhandenen
+ * Aenderungen, die bisher nur im Cache sind, zurueck
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ * @attention Diese Funktion ist unterbrechbar
+ */
+int lio_sync(struct lio_stream* s);
+
+/**
+ * Alle veraenderten Blocks im Cache rausschreiben
+ *
+ * @param soft Wenn true, wird nicht blockiert, wenn ein Cluster nicht gesynct
+ * werden kann. Es wird auch kein Fehler zurückgegeben. (Ziel ist es, einfach
+ * irgendwelche Dirty-Cluster loszuwerden)
+ *
+ * @return 0 bei Erfolg, -errno im Fehlerfall
+ */
+int lio_sync_all(bool soft);
+
+/**
+ * Aendert die Dateigroesse
+ *
+ * @param size Neue Dateigroesse
+ * @return 0 bei Erfolg, negativ im Fehlerfall
+ */
+int lio_truncate(struct lio_stream* s, uint64_t size);
+
+/**
+ * Schliesst einen Stream
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ */
+int lio_close(struct lio_stream* s);
+
+/**
+ * Inhalt eines Verzeichnisses auslesen
+ */
+ssize_t lio_read_dir(struct lio_resource* dir, size_t start, size_t num,
+ struct lio_dir_entry* buf);
+
+/** Erstellt eine neue Datei */
+struct lio_resource* lio_mkfile(struct lio_resource* parent, const char* name);
+
+/** Erstellt ein neues Verzeichnis */
+struct lio_resource* lio_mkdir(struct lio_resource* parent, const char* name);
+
+/** Erstellt einen neuen Symlink */
+struct lio_resource* lio_mksymlink(struct lio_resource* parent,
+ const char* name, const char* target);
+
+/**
+ * Gibt Informationen zu einer Ressource zurueck
+ */
+int lio_stat(struct lio_resource* resource, struct lio_stat* sbuf);
+
+/** Verzeichniseintrag loeschen */
+int lio_unlink(struct lio_resource* parent, const char* name);
+
+#endif
diff --git a/src/kernel2/src/lostio/client.c b/src/kernel2/src/lostio/client.c
new file mode 100644
index 0000000..f87c6fa
--- /dev/null
+++ b/src/kernel2/src/lostio/client.c
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2009 The tyndur Project. All rights reserved.
+ *
+ * This code is derived from software contributed to the tyndur Project
+ * by Kevin Wolf.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the tyndur Project
+ * and its contributors.
+ * 4. Neither the name of the tyndur Project nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "kernel.h"
+#include "kprintf.h"
+
+#include "lostio/client.h"
+#include "lostio_int.h"
+
+/**
+ * Loest einen Pfad zu einer Ressource auf
+ *
+ * @return Die zum Pfad gehoerende Ressource oder NULL, wenn der Pfad keine
+ * existierende Ressource beschreibt.
+ */
+struct lio_resource* lio_get_resource(const char* path, int follow_symlinks)
+{
+ /* TODO */
+ return NULL;
+}
+
+/**
+ * Oeffnet einen Stream zu einer Ressource
+ *
+ * @param flags Bitmaske für den Modus, in dem der Stream arbeiten soll (siehe
+ * enum lio_flags)
+ *
+ * @return Stream zur Ressource oder NULL, wenn die Ressource nicht erfolgreich
+ * geoeffnet werden konnte.
+ */
+struct lio_stream* lio_open(struct lio_resource* res, int flags)
+{
+ struct lio_stream* s;
+
+ if (res == NULL) {
+ return NULL;
+ }
+
+ // Nur lesbare Ressourcen duerfen mit dem LIO_READ-Flag geoeffnet werden,
+ // und nur Schreibbare mit LIO_WRITE oder LIO_TRUNC.
+ bool symlink = !!(flags & LIO_SYMLINK);
+ if (((flags & LIO_READ) && !res->readable && !symlink) ||
+ ((flags & (LIO_WRITE | LIO_TRUNC) && !res->writable && !symlink)) ||
+ ((flags & LIO_READ) && !res->resolvable && symlink) ||
+ ((flags & (LIO_WRITE | LIO_TRUNC) && !res->retargetable && symlink)))
+ {
+ return NULL;
+ }
+
+ // Symlinks duerfen nur als solche geoeffnet werden
+ if (res->resolvable && !(flags & LIO_SYMLINK)) {
+ return NULL;
+ }
+
+ // Stream anlegen und initialisieren
+ s = calloc(1, sizeof(*s));
+ s->res = s->res_read = s->res_write = res;
+ s->flags = flags;
+ s->eof = false;
+
+ if (res->tree->service->lio_ops.preopen &&
+ res->tree->service->lio_ops.preopen(s))
+ {
+ goto fail;
+ }
+
+
+ // Datei leeren, wenn LIO_TRUNC gesetzt ist
+ if (flags & LIO_TRUNC) {
+ if (lio_truncate(s, 0) < 0) {
+ goto fail;
+ }
+ }
+
+ return s;
+
+fail:
+ free(s);
+ return NULL;
+}
+
+/**
+ * Liest aus einem Stream aus.
+ *
+ * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_read(struct lio_stream* s, size_t bytes, void* buf)
+{
+ ssize_t result;
+
+ result = lio_pread(s, s->pos_read, bytes, buf);
+ if (result > 0) {
+ s->pos_read += result;
+ }
+
+ return result;
+}
+
+/**
+ * Liest aus einem Stream aus, ohne die Position des streams zu benutzen oder
+ * zu veraendern.
+ *
+ * @return Anzahl der gelesenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_pread(struct lio_stream* s, uint64_t offset, size_t bytes,
+ void* buf)
+{
+ ssize_t ret = 0;
+ struct lio_resource* res;
+
+ // Stream muss existieren und zum Lesen geoeffnet sein
+ if (!s || (s->flags & LIO_READ) == 0) {
+ return -EBADF;
+ }
+
+ res = s->res_read;
+
+ // Position pruefen
+ if (offset >= res->size) {
+ if (res->moredata) {
+ return -EAGAIN;
+ }
+ return 0;
+ }
+
+ // Abschneiden, wenn ueber das Dateiende hinausgelesen wird
+ if (offset + bytes > res->size) {
+ bytes = res->size - offset;
+ }
+
+ // Daten einlesen
+ uint64_t offset_aligned = ROUND_TO_BLOCK_DOWN(offset, res->blocksize);
+ size_t bytes_aligned = ROUND_TO_NEXT_BLOCK(
+ bytes + (offset - offset_aligned), res->blocksize);
+
+ struct lio_driver* drv = &res->tree->service->lio_ops;
+ uint8_t* bounce = malloc(bytes_aligned);
+ uint8_t* p = bounce;
+ uint64_t curoffset = offset_aligned;
+
+ ret = drv->read(res, curoffset, bytes_aligned, p);
+ if (ret >= 0) {
+ ret = bytes;
+ memcpy(buf, bounce + (offset - offset_aligned), ret);
+ }
+
+ free(bounce);
+
+ return ret;
+}
+
+/**
+ * Schreibt in einen Stream
+ *
+ * @return Anzahl der geschriebenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_write(struct lio_stream* s, size_t bytes, const void* buf)
+{
+ ssize_t result;
+ uint64_t pos;
+
+ pos = ((s->res_read == s->res_write) ? s->pos_read : s->pos_write);
+
+ result = lio_pwrite(s, pos, bytes, buf);
+ if (result > 0) {
+ if (s->res_read == s->res_write) {
+ s->pos_read += result;
+ } else {
+ s->pos_write += result;
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Schreibt in einen Stream, ohne dabei die Position des Streams zu benutzen
+ * oder zu veraendern.
+ *
+ * @return Anzahl der geschriebenen Bytes oder negativ im Fehlerfall
+ */
+ssize_t lio_pwrite(struct lio_stream* s, uint64_t offset, size_t bytes,
+ const void* buf)
+{
+ ssize_t ret;
+ struct lio_resource* res;
+
+ // Stream muss existieren und zum Schreiben geoeffnet sein
+ if (!s || (s->flags & LIO_WRITE) == 0) {
+ return -EBADF;
+ }
+
+ res = s->res_write;
+ if (!res->writable && (!(s->flags & LIO_SYMLINK) || !res->retargetable)) {
+ return -EBADF;
+ }
+
+ // Falls noetig Ressource vergroessern
+ if ((offset + bytes) > res->size) {
+ ret = lio_truncate(s, offset + bytes);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ // Daten einlesen
+ uint64_t offset_aligned = ROUND_TO_BLOCK_DOWN(offset, res->blocksize);
+ size_t bytes_aligned = ROUND_TO_NEXT_BLOCK(
+ bytes + (offset - offset_aligned), res->blocksize);
+
+ struct lio_driver* drv = &res->tree->service->lio_ops;
+ uint8_t* bounce = calloc(1, bytes_aligned);
+ uint8_t* p = bounce;
+ uint64_t curoffset = offset_aligned;
+ int old_flags;
+
+ old_flags = s->flags;
+ s->flags |= LIO_READ;
+ ret = lio_pread(s, offset_aligned, bytes_aligned, bounce);
+ s->flags = old_flags;
+
+ if (ret < 0) {
+ goto out;
+ }
+ memcpy(bounce + (offset - offset_aligned), buf, bytes);
+
+ ret = drv->write(res, curoffset, bytes_aligned, p);
+ if (ret >= 0) {
+ ret = bytes;
+ }
+
+ // Offset zeigt jetzt auf das erste Byte nach dem letzten geschriebenen
+ if (ret > 0){
+ if (res->size < offset) {
+ res->size = offset;
+ }
+ }
+
+out:
+ free(bounce);
+ return ret;
+}
+
+/**
+ * Position veraendern. Funktioniert nur, wenn die Ressource seekable ist, und
+ * es sich um keine Pipe handelt.
+ *
+ * @param offset Offset um den die Position angepasst werden soll. Wie sie genau
+ * angepasst wird, haengt vom Parameter whence ab.
+ * @param whence Einer der drei Werte aus enum lio_seek_whence.
+ * - LIO_SEEK_SET: Position auf den angegebenen Wert setzen.
+ * - LIO_SEEK_CUR: Angegebenen Wert zur aktuellen Position
+ * dazu addieren.
+ * - LIO_SEEK_END: Position auf das Dateiende setzen.
+ *
+ * @return Neue Position oder < 0 im Fehlerfall.
+ */
+int64_t lio_seek(struct lio_stream* s, int64_t offset, int whence)
+{
+ if ((s->res_read != s->res_write) || !s->res_read->seekable) {
+ return -EINVAL;
+ }
+
+ switch (whence) {
+ case LIO_SEEK_SET:
+ if (offset < 0) {
+ return -EINVAL;
+ } else {
+ s->pos_read = offset;
+ }
+ break;
+
+ case LIO_SEEK_CUR:
+ if ((int64_t)(s->pos_read + offset) < 0) {
+ return -EINVAL;
+ } else {
+ s->pos_read += offset;
+ }
+ break;
+
+ case LIO_SEEK_END:
+ if ((int64_t)(s->res_read->size + offset) < 0) {
+ return -EINVAL;
+ } else {
+ s->pos_read = s->res_read->size + offset;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return s->pos_read;
+}
+
+/**
+ * Schreibt Aenderungen, die bisher nur im Cache sind, zurueck. Dabei werden
+ * nur die Cluster beruecksichtigt, die im angegebenen Bereich liegen.
+ *
+ * @param s Stream, dessen Aendungen geschrieben werden sollen
+ * @param offset Start des zurueckzuschreibenden Bereichs (in Bytes)
+ * @param bytes Laenge des zurueckzuschreibenden Bereichs (in Bytes) oder 0,
+ * falls die gesamte Datei zurueckgeschrieben werden soll
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ *
+ * @attention Diese Funktion ist unterbrechbar
+ */
+int lio_sync_blocks(struct lio_resource* res, uint64_t offset, size_t bytes)
+{
+ return 0;
+}
+
+/**
+ * Schreibt alle zum Zeitpunkt des Aufrufs der Funktion vorhandenen
+ * Aenderungen, die bisher nur im Cache sind, zurueck
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ * @attention Diese Funktion ist unterbrechbar
+ */
+int lio_sync(struct lio_stream* s)
+{
+ struct lio_resource* res = s->res_write;
+ struct lio_driver* drv = &res->tree->service->lio_ops;
+
+ /*
+ * TODO Muss z.B. ata nochmal gesynct werden, nachdem ext2 dran war? Ist es
+ * Aufgabe des Treibers oder von LIO?
+ */
+ if (drv->sync) {
+ drv->sync(res);
+ }
+
+ return 0;
+}
+
+/**
+ * Alle veraenderten Blocks im Cache rausschreiben
+ *
+ * @param soft Wenn true, wird nicht blockiert, wenn ein Cluster nicht gesynct
+ * werden kann. Es wird auch kein Fehler zurückgegeben. (Ziel ist es, einfach
+ * irgendwelche Dirty-Cluster loszuwerden)
+ *
+ * @return 0 bei Erfolg, -errno im Fehlerfall
+ */
+int lio_sync_all(bool soft)
+{
+ return 0;
+}
+
+/**
+ * Aendert die Dateigroesse
+ *
+ * @param size Neue Dateigroesse
+ * @return 0 bei Erfolg, negativ im Fehlerfall
+ */
+int lio_truncate(struct lio_stream* s, uint64_t size)
+{
+ struct lio_resource* res = s->res_write;
+ struct lio_driver* drv = &res->tree->service->lio_ops;
+
+ /* Zunaechst den Treiber informieren */
+ if (drv->truncate) {
+ int ret = drv->truncate(res, size);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+
+ /* Anschliessend die Ressourcengroesse anpassen (drv->truncate kann das
+ * u.U. auch schon gemacht haben) */
+ res->size = size;
+
+ return 0;
+}
+
+/**
+ * Schliesst einen Stream
+ *
+ * @return 0 bei Erfolg, ungleich 0 im Fehlerfall
+ */
+int lio_close(struct lio_stream* s)
+{
+ if (s->res->tree->service->lio_ops.close) {
+ s->res->tree->service->lio_ops.close(s);
+ }
+
+ free(s);
+ return 0;
+}
+
+/**
+ * Inhalt eines Verzeichnisses auslesen
+ */
+ssize_t lio_read_dir(struct lio_resource* dir, size_t start, size_t num,
+ struct lio_dir_entry* buf)
+{
+ struct lio_node* node;
+ size_t cnt = 0;
+
+ /* Die Ressource muss auch wirklich ein Verzeichnis sein */
+ if (!dir->browsable) {
+ return -EBADF;
+ }
+
+ /* Wenn der Aufrufer keine Eintraege will, sind wir fertig */
+ if (!num) {
+ return 0;
+ }
+
+ /* Zunaechst kommt der Eintrag fuer . */
+ if (start == 0) {
+ strcpy(buf[0].name, ".");
+ buf[0].resource = dir;
+ lio_stat(dir, &buf[0].stat);
+ cnt++;
+ }
+
+ /* Und dann der ganzer Rest */
+ if (!dir->children) {
+ dir->tree->service->lio_ops.load_children(dir);
+ }
+
+ for (; (cnt < num) &&
+ (node = list_get_element_at(dir->children, start - 1 + cnt));)
+ {
+ buf[cnt].resource = node->res;
+ strncpy(buf[cnt].name, node->name, LIO_MAX_FNLEN);
+ buf[cnt].name[LIO_MAX_FNLEN] = 0;
+ lio_stat(node->res, &buf[cnt].stat);
+ cnt++;
+ }
+
+ return cnt;
+}
+
+/** Erstellt eine neue Datei */
+struct lio_resource* lio_mkfile(struct lio_resource* parent, const char* name)
+{
+ if (!parent->tree->service->lio_ops.make_file || !parent->changeable) {
+ return NULL;
+ }
+
+ return parent->tree->service->lio_ops.make_file(parent, name);
+}
+
+/** Erstellt ein neues Verzeichnis */
+struct lio_resource* lio_mkdir(struct lio_resource* parent, const char* name)
+{
+ if (!parent->tree->service->lio_ops.make_dir || !parent->changeable) {
+ return NULL;
+ }
+
+ return parent->tree->service->lio_ops.make_dir(parent, name);
+}
+
+/** Erstellt einen neuen Symlink */
+struct lio_resource* lio_mksymlink(struct lio_resource* parent,
+ const char* name, const char* target)
+{
+ if (!parent->tree->service->lio_ops.make_symlink || !parent->changeable) {
+ return NULL;
+ }
+
+ return parent->tree->service->lio_ops.make_symlink(parent, name, target);
+}
+
+/**
+ * Gibt Informationen zu einer Ressource zurueck
+ */
+int lio_stat(struct lio_resource* resource, struct lio_stat* sbuf)
+{
+ memset(sbuf, 0, sizeof(*sbuf));
+ sbuf->size = resource->size;
+
+ sbuf->flags = (resource->readable ? LIO_FLAG_READABLE : 0) |
+ (resource->writable ? LIO_FLAG_WRITABLE : 0) |
+ (resource->browsable ? LIO_FLAG_BROWSABLE : 0) |
+ (resource->changeable ? LIO_FLAG_CHANGEABLE : 0) |
+ (resource->resolvable ? LIO_FLAG_RESOLVABLE : 0) |
+ (resource->retargetable ? LIO_FLAG_RETARGETABLE : 0) |
+ (resource->seekable ? LIO_FLAG_SEEKABLE : 0) |
+ (resource->ispipe ? LIO_FLAG_PIPE : 0);
+ return 0;
+}
+
+/** Verzeichniseintrag loeschen */
+int lio_unlink(struct lio_resource* parent, const char* name)
+{
+ if (!parent->tree->service->lio_ops.unlink) {
+ return -EINVAL;
+ }
+
+ return parent->tree->service->lio_ops.unlink(parent, name);
+}
+
diff --git a/src/kernel2/src/lostio/include/lostio_int.h b/src/kernel2/src/lostio/include/lostio_int.h
index 45630bc..c7a511f 100644
--- a/src/kernel2/src/lostio/include/lostio_int.h
+++ b/src/kernel2/src/lostio/include/lostio_int.h
@@ -42,7 +42,98 @@
#include "lostio/core.h"
#include "tasks.h"
+#define ROUND_TO_NEXT_BLOCK(bytes, blocksize) \
+ ((bytes) + (blocksize) - 1) & ~((blocksize) - 1)
+#define ROUND_TO_BLOCK_DOWN(bytes, blocksize) \
+ ((bytes)) & ~((blocksize) - 1)
+
struct lio_service;
+struct lio_driver {
+ /**
+ * Laedt alle Kindknoten nach res->children
+ */
+ int (*load_children)(struct lio_resource* res);
+
+ /**
+ * Wird aufgerufen wenn eine Ressource geoeffnet wird.
+ *
+ * @return 0 bei Erfolg, negativ bei Fehlern. Bei einem Fehler wird das
+ * Oeffnen abgebrochen.
+ */
+ int (*preopen)(struct lio_stream* stream);
+
+ /** Stream wird geschlossen */
+ void (*close)(struct lio_stream* stream);
+
+ /** Erstellt eine neue Datei */
+ struct lio_resource* (*make_file)(struct lio_resource* parent,
+ const char* name);
+
+ /** Erstellt ein neues Verzeichnis */
+ struct lio_resource* (*make_dir)(struct lio_resource* parent,
+ const char* name);
+
+ /** Erstellt einen neuen Symlink */
+ struct lio_resource* (*make_symlink)(struct lio_resource* parent,
+ const char* name, const char* target);
+
+ /** Verzeichniseintrag loeschen */
+ int (*unlink)(struct lio_resource* parent, const char* name);
+
+ /**
+ * Laedt Daten vom Service in den Cache.
+ * offset und bytes muessen auf die Blockgroesse ausgerichtet sein.
+ *
+ * @return 0 bei Erfolg (Puffer ist komplett gelesen), negativ im
+ * Fehlerfall.
+ *
+ * TODO iovec statt bytes/buf
+ */
+ int (*read)(struct lio_resource* res, uint64_t offset,
+ size_t bytes, void* buf);
+
+ /**
+ * Schreibt Daten aus dem Cache in den Service zurueck
+ * offset und bytes muessen auf die Blockgroesse ausgerichtet sein.
+ *
+ * @return 0 bei Erfolg (Puffer ist komplett geschrieben), negativ im
+ * Fehlerfall.
+ *
+ * TODO iovec statt bytes/buf
+ */
+ int (*write)(struct lio_resource* res, uint64_t offset,
+ size_t bytes, void* buf);
+
+ /** Schreibt eventuelle im Treiber gecachte Daten zurueck */
+ int (*sync)(struct lio_resource* res);
+
+ /**
+ * Setzt die Dateigroesse.
+ *
+ * Diese Funktion wird auch aufgerufen, bevor eine Datei durch einen
+ * Schreibzugriff vergroessert wird. Ein Service kann write()-Aufrufe
+ * hinter dem Dateiende verwerfen.
+ */
+ int (*truncate)(struct lio_resource* res, uint64_t size);
+
+};
+
+
+/**
+ * Beschreibt einen LostIO-Service.
+ */
+struct lio_service {
+ /** Eindeutiger Name des Service */
+ char* name;
+
+ /** Funktionspointer, die den eigentlichen Treiber implementieren */
+ struct lio_driver lio_ops;
+
+ /** Private Daten des Services */
+ void* opaque;
+};
+
+
/**
* Beschreibt eine von LostIO verwaltete Ressource (d.h. in der Regel eine
--
1.6.0.2