Autor Thema: cdi.fs  (Gelesen 26144 mal)

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« am: 11. February 2008, 16:20 »
Viele kennen es schon, für die Restlichen: cdi.fs ist als Interface für Dateisystem-Treiber gedacht.
BTW: Ich habe in letzter Zeit etwas mit fuse gearbeitet. Man könnte sich ja etwas davon inspirieren lassen.

Die 1. drei Funktions-Deklarationen sollten klar sein. cdi_fs_seterror() ermöglicht dem FS-Treiber einen error zu setzen (siehe ferror). Aber eigentlich müsste man das anderst machen, da man ja für jeden Filehandle ferror() machen kann.
cdi_fs_read_data() und cdi_fs_write_data() sind da um dem FS-Treiber Zugriff auf das Speichermedium zu geben.

#ifndef _CDI_FS_H_
#define _CDI_FS_H_

#include "types.h"
#include "cdi.h"
#include "cdi/lists.h"

#define CDI_FS_META_NONE       0 /* -/- Invalid Meta read        */
#define CDI_FS_META_MODE       1 /* r/w Get/Set permissions      */
#define CDI_FS_META_OWNER      2 /* r/w Get/Set owner            */
#define CDI_FS_META_GROUP      3 /* r/w Get/Set owner group      */
#define CDI_FS_META_TYPE       4 /* r/- Get file type            */
#define CDI_FS_META_SIZE       5 /* r/- Get file size            */
#define CDI_FS_META_USEDBLOCKS 6 /* r/- Get how many blocks used */
#define CDI_FS_META_CREATETIME 7 /* r/- Get creation time        */
#define CDI_FS_META_ACCESSTIME 8 /* r/- Get time of last access  */
#define CDI_FS_META_CHANGETIME 9 /* r/- Get time if last change  */

#define CDI_FS_ERROR_NONE    0 /* No Error */
#define CDI_FS_ERROR_ONS     1 /* Operation not supported */
#define CDI_FS_ERROR_FNF     2 /* File not found */
#define CDI_FS_ERROR_EOF     3 /* End of file */
#define CDI_FS_ERROR_UNKNOWN 4 /* Unknown error */

typedef enum {
  CDI_FS_TYPE_NONE     = 0, // Invalid file type
  CDI_FS_TYPE_FILE     = 1, // normal file
  CDI_FS_TYPE_DIR      = 2, // Directory
  CDI_FS_TYPE_FIF0     = 3, // First-In-First-Out-Pipe
  CDI_FS_TYPE_LIFO     = 4, // Last-In-First-Out-Pipe (Stack)
  CDI_FS_TYPE_BLOCKDEV = 5, // Block device
  CDI_FS_TYPE_CHARDEV  = 6, // Character device
  CDI_FS_TYPE_SYMLINK  = 7, // Symbolic link, points to another file
  CDI_FS_TYPE_SOCKET   = 8, // Unix socket
  CDI_FS_TYPE_BUFFER   = 9 // Buffer (like file but stored in RAM and will get deleted when closed)
} cdi_filetype_t;

struct cdi_fs_driver {
  struct cdi_driver drv;
  /**
   * Opens a file/pipe/etc and returns file descriptor
   *  @param path Path to file
   *  @return File descriptor (negative = Failure)
   */
  int (*open)(const char *path);
  /**
   * Closes a file
   *  @param fildes File descriptor
   *  @return 0 = Success
   */
  int (*close)(int fildes);
  /**
   * Creates an file/dir/pipe/etc
   *  @param path Path to file
   *  @param type Whether it is a file/dir/etc
   *  @param mode Permissions
   *  @return 0 = Success
   */
  int (*create)(const char *path,int type,mode_t mode);
  /**
   * Removes a file/dir/pipe/etc
   *  @param path Path to dir
   *  @return 0 = Success
   */
  int (*remove)(const char *path);
  /**
   * Puts filenames of files from dir in list
   *  @param path Path to dir
   *  @param content List with filenames
   *  @return 0 = Success
   */
  int (*listdir)(const char *path,cdi_list_t content);
  /**
   * Sets meta data of a file/dir/pipe/etc
   *  @param path Path to file/dir/pipe/etc
   *  @param which Which meta information to set
   *  @param value Value to set as meta
   *  @return 0 = Success
   */
  void (*setmeta)(const char *path,int which,int value);
  /**
   * Gets meta data of a file/dir/pipe/etc
   *  @param path Path to file/dir/pipe/etc
   *  @param which Which meta information to get
   *  @return Meta data
   */
  int (*getmeta)(const char *path,int which);
  /**
   * Reads from an opened file
   *  @param fildes File descriptor of opened file
   *  @return Byte readed
   */
  u8 (*read)(int fildes);
  /**
   * Writes to an opened file
   *  @param fildes File descriptor of opened file
   *  @param byte Byte to write
   */
  void (*write)(int fildes,u8 byte);
  char *device; ///< @note meinOS specific
};

void cdi_fs_driver_init(struct cdi_fs_driver* driver);
void cdi_fs_driver_destroy(struct cdi_fs_driver* driver);
void cdi_fs_driver_register(struct cdi_fs_driver* driver);
void cdi_fs_seterror(struct cdi_fs_driver* driver,int error);
void cdi_fs_read_data(struct cdi_fs_driver* driver,void *buffer,size_t count);
void cdi_fs_write_data(struct cdi_fs_driver* driver,void *buffer,size_t count);

#endif

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 11. February 2008, 22:04 »
Die Idee mit den Meta-Konstanten gefällt mir schonmal.

Deine Dateitypen kommen mir aber etwas Unix-spezifisch vor. LOST kennt so ein Konzept beispielsweise nicht. Was du als Typ Verzeichnis ansiehst, ist in LOST einfach nur eine Datei mit dem Flag browsable.

Ansonsten sind die letzten paar Funktionen natürlich so gut wie gar nicht spezifiziert (ein Name sagt eben nicht alles) und manche andere Dinge sind stark unterspezifiziert (z.B. was passiert, wenn ich einen Symlink öffne). Außerdem fehlen noch ein paar allgemeinere Funktionen wie freier Platz auf dem Dateisystem oder sowas.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #2 am: 11. February 2008, 22:15 »
Die Idee mit get_meta und set_meta finde ich gut. Allerdings müsste man sich da überlegen, wie man Eigenschaften umsetzen möchte, die nich Integer sind. Also zum Beispiel Dateisysteme bei denen die Benutzer- und Gruppennamen als String gespeichert wird. (Zum Beispiel ACLs bei ext2)

Weiter finde ich die CDI_...._NONE Makros etwas seltsam. Das macht doch eigentlich nur bei der Fehlernummer sinn. Bei den anderen Kann man ja 0 einfach als ersten Wert benutzen.

Für die Verwaltung der Dateien möchte ich noch ein bisschen was ergänzen, denn es macht meiner Meinung nach nicht Sinn, in jedem Treiber den ganzen Code für die Verwaltung von Dateien und Verzeichnissen und das auflösen der Pfade neu zu schreiben. Abgsesehen davon müsste man sich ja damit fast auf ein Trennzeichen bei den Pfaden festlegen, und da wollen ja nicht alle das selbe.

Ich versuche mal, dafür noch ein bisschen was hin zu spinnen. ;-)

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. February 2008, 22:17 »
Abgsesehen davon müsste man sich ja damit fast auf ein Trennzeichen bei den Pfaden festlegen, und da wollen ja nicht alle das selbe.
Ein Trennzeichen ist sowieso zu wenig, wie wir wissen. Es gibt schließlich / und | und :/ ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #4 am: 11. February 2008, 22:18 »
Jo ist klar. Aber wenn ich einen definierbaren Trennstring vorgeschlagen hätte, wäre vielleicht noch jemand auf die Idee gekommen, das könnte genügen. ;-)

Edit:
Was fällt dir denn da als Flags im Stil von browsable noch so ein?
« Letzte Änderung: 11. February 2008, 22:45 von FreakyPenguin »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 11. February 2008, 22:51 »
Zitat von: FreakyPenguin link=topic=1939.msg22049#msg22049
 date=1202764710
Was fällt dir denn da als Flags im Stil von browsable noch so ein?
Hm, die standardmäßigen readable, writable, executable? Das sind ja eigentlich nicht nur Berechtigungen, sondern teilweise auch unveränderliche Eigenschaften. Resolvable für Symlinks oder sowas? Da kann man sich sicher noch ein paar Sachen für Spezialfälle ausdenken.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #6 am: 11. February 2008, 22:59 »
Hm, die standardmäßigen readable, writable, executable?

Stimmt, das wäre noch was.

Mir ist eben noch etwas eingefallen:
Wie könnten wir das mit dem Öffnen machen, damit man da zwischen den einzelnen Möglichkeiten, wie man auf ein Objek zugreifen kann, wechseln kann?
Irgendwie muss man ja angeben können, ob man jetzt den Pfad des Symlinks, die Untereinträge oder die Daten, die das Objekt als reguläre Datei beinhaltet haben will... Es macht ja auch nur bedingt sinn, diese alle gleich auszuwerten, denn die Verzeichniseinträge beispielsweise mit einem read() zu holen ist ja auch nicht speziell angenehm.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 11. February 2008, 23:17 »
Dafür gibt es natürlich eigene Funktionen, nicht wieder so komisches Zeug wie fopen(foo, "rd"). Eine Datei, die readable ist, unterstützt read(). Eine Datei die browsable ist, unterstützt browse(). Oder so ähnlich. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #8 am: 12. February 2008, 00:10 »
Jo das macht so eindeutig Sinn. *hust* ;-)

Vorhin ist mir auch noch eine Frage durch den Kopf gegangen:
Wie könnte man es ermöglichen, dass jemand, der zum Beispiel Gerätedateien in ext2 benutzen möchte, das tun kann?

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #9 am: 12. February 2008, 01:26 »
So, ich habe hier jetzt mal zusammengetragen, was mir so eingefallen ist. Ich hoffe ihr werdet davon nicht allzusehr erschlagen.
Mir ist bewusst, dass Funktionen zum Ändern der Berechtiungen noch fehlen. Aber dazu bin ich heute nicht mehr im Stande.  :roll:

#ifndef _CDI_FS_H_
#define _CDI_FS_H_

#include "types.h"
#include "cdi.h"
#include "cdi/lists.h"

// XXX Dateigroesse (Fuer mich stellt sich noch die Frage, ob sie wirklich zu
// den Meta-Informationen gehoert, oder ob wir sie nicht doch besser in die
// file-Struktur packen)
#define CDI_FS_META_SIZE        0
// Anzahl der Benutzten Dateisystemblocks (Irgendwo muesste man dann auch auf
// diese Blockgroesse zurgreiffen koennen)
#define CDI_FS_META_USEDBLOCKS  1
// Optimale Blockgroesse mit der man auf die Datei zugreiffen sollte
#define CDI_FS_META_BESTBLOCKSZ 2
// Zeitpunkt an dem das Objekt erstellt wurde
#define CDI_FS_META_CREATETIME  3
// Letzter Zugriff auf das Objekt, auch lesend
#define CDI_FS_META_ACCESSTIME  4
// Letzte Veraenderung des Objekts
#define CDI_FS_META_CHANGETIME  5


// XXX Bei den Fehlernummern weiss ich noch nicht wirklich, was da notwendig
// ist, deshalb lasse ich das mal so stehen.
#define CDI_FS_ERROR_NONE    0 /* No Error */
#define CDI_FS_ERROR_ONS     1 /* Operation not supported */
#define CDI_FS_ERROR_FNF     2 /* File not found */
#define CDI_FS_ERROR_EOF     3 /* End of file */
#define CDI_FS_ERROR_UNKNOWN 4 /* Unknown error */


struct cdi_fs_driver {
    struct cdi_driver drv;
}

struct cdi_fs_object;
/**
 * XXX Der Name Device ist hier unpassend, was besseres ist mir aber nicht
 * eingefallen.
 */
struct cdi_fs_device {
    // Wurzelobjekt fuer die Baumstruktur
    struct cdi_fs_object*   root_object;
   
    // Dieses Error-Flag sperrt den ganzen Mount fuer (Schreib?)Zugriffe
    int                     error;

    // Das Dateisystem darf nicht geschrieben werden. Damit schlaegt unter
    // anderem cdi_fs_write_data fehl.
    int                     read_only;

    // Hier sollte man wohl noch ein paar allgemeine Mount-Optionen oder
    // sonstige Flags die das ganze Dateisystem betreffen.
};

/**
 * Das Handle stellt die Verbindung zwischen Aufrufer und betroffenem
 * Dateisystemobjekt dar.
 */
struct cdi_fs_handle {
    // Betroffenes Dateisystemobjekt
    struct cdi_fs_object*   obj;

    // Fehlernummer
    int                     error;
};


/**
 * Diese Struktur hat eigentlich nicht viel mit Zugriffsrechten zu tun. Deshalb
 * ist der Name vielleicht etwas ungeschickt gewaehlt, aber was bessers ist mir
 * nicht eingefallen.
 * Sie stellt allgemein die Moeglichkeiten, die an einem Objekt zur verfuegung
 * stehen dar.
 */
struct cdi_fs_obj_permissions {
    // Objekt loeschen
    int                 remove;
    // Objekt umbenennen
    int                 rename;
    // Objekt verschieben
    int                 move;
    // Lesender Zugriff gestattet
    int                 read;
    // Schreibender Zugriff gestattet
    int                 write;
    // Ausfuehren gestattet
    int                 execute;
    // Auflisten der Verzeichniseintraege gestattet
    int                 browse;
    // Aufloesen des Links
    int                 read_link;
    // Aendern des Links
    int                 write_link;
};


struct cdi_fs_obj_file;
struct cdi_fs_obj_dir;
struct cdi_fs_obj_link;
/**
 * Das Dateisystem wird hier nur mit abstrakten Strukturen vom Typ
 * cdi_fs_object dargestellt. Diese können beispielsweise sowohl regulaere
 * Datei als auch Verzeichnis gleichzeitig darstellen.
 */
struct cdi_fs_object {
    // Name des Objektes
    char*                   name;

    // Verweis auf das Elternobjekt
    struct cdi_fs_object*   parent;
    // Liste mit allfaelligen Kindobjekten
    cdi_list_t              children;

    // Link-Pfad
    char*                   link_path;

    // ACL; siehe Unten
    cdi_list_t              acl;
    // Flags
    struct cdi_fs_obj_permissions flags;

    // Einzelne Klassen, zu denen das Objekt gehoeren kann, oder Null falls es
    // zu einer Bestimmten Klasse nicht gehoert.
    struct cdi_fs_obj_file* file;
    struct cdi_fs_obj_dir*  dir;
    struct cdi_fs_obj_link* link;
};



/**
 * Diese Dateisystemobjekte werden in Klassen eingeteilt, die das eigentliche
 * "Verhalten" der Objekte steuern. Diese Klassen beinhalten die moeglichen
 * Operationen und auch die Eigenschaften, die fuer die Objekte gelten, denen
 * diese Klassen zugeordnet sind.
 * Das Definieren der einzelnen Klassen uebernehmen dann die einzelnen Treiber.
 *
 * Die Flags koennen vom Objekt ueberschrieben werden. Es duerfen allerdings
 * nur Flags deaktiviert werden, die in der Klasse gesetzt sind und nicht
 * umgekehrt.
 */

/**
 * Diese Klasse gilt unabhaengig von den andern, also egal welche anderen
 * Klassen angegeben sind, diese muss angegeben werden.
 */
struct cdi_fs_obj_obj {
    /**
     * Objekt entfernen
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     *
     * @return Falls das Objekt erfolgreich geloescht wurde 1, sonst 0
     */
    int remove(struct cdi_fs_handle* handle);

    /**
     * Objekt umbenennen
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     * @param name Neuer Name
     *
     * @return Falls das Objekt erfolgreich umbenennt wurde 1, sonst 0
     */
    int rename(struct cdi_fs_handle* handle, const char* name);

    /**
     * Objekt verschieben
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     * @param dest Pointer auf das Objekt, in das verschoben werden soll
     *
     * @return Falls das Objekt erfolgreich verschoben wurde 1, sonst 0
     */
    int move(struct cdi_fs_handle* handle, struct cdi_fs_object* dest);
}

struct cdi_fs_obj_file {
    // XXX (Aber wie geht das, wenn eine Datei nicht lesbar, aber ausfuehrbar
    // sein soll?)
    int                     executable;
   
    /**
     * Daten aus dieser Datei lesen. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     * @param start Position von der an gelesen werden soll
     * @param size Groesse der zu lesenden Daten
     * @param buffer Puffer in den die Daten gelsen werden sollen
     *
     * @return Gelesene Bytes, oder 0 im Fehlerfall
     */
    size_t read(struct cdi_fs_handle* handle, uint64_t start, size_t size,
        void* buffer);

    /**
     * Daten in diese Datei schreiben. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     * @param start Position an die geschrieben werden soll
     * @param size Groesse der zu schreibenden Daten
     * @param buffer Puffer aus dem die Daten gelesen werden sollen
     *
     * @return Geschriebene Bytes oder 0 im Fehlerfall
     */
    size_t write(struct cdi_fs_handle* handle, uint64_t start, size_t size,
        void* buffer);
};

struct cdi_fs_obj_dir {
    // XXX Ein browsable Flag koennen wir vermutlich hier eindeutig welgassen,
    // waere ja irgenwie witzlos. ;-)
   
    /**
     * Diese Funktion gibt einen Pointer auf die Liste mit den Eintraegen
     * zurueck. Hier wird nicht einfach fix der Pointer in fs_obj genommen,
     * damit dort auch "versteckte" Eintraege vorhanden sein koennten. (Ich
     * meine hier nicht irgend ein versteckt-Flag dass die Dateien vor dem
     * Benutzer Verstecken soll, sondern eher von fuer den Internen gebrauch
     * angelegten Eintraegen.
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     *
     * @return Pointer auf eine Liste mit den Untereintraegen.
     */
     cdi_list_t* list(struct cdi_fs_handle* handle);
};

struct cdi_fs_obj_link {
    // XXX Ich glaube auch hier brauchen wir kein resolvable-Flag

    /**
     * Diese Funktion liest den Pfad aus, auf den der Link zeigt
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     *
     * @return Pointer auf einen Ouffer der den Pfad beinhaltet. Dieses Puffer
     *         darf vom Aufrufer nicht veraendert werden.
     */
    const char* read_link(struct cdi_fs_handle* handle);

    /**
     * Aendert den Pfad auf den der Link zeigt
     *
     * @param handle Handle fuer die Verbindung zwischen Aufrufer und Objekt
     * @param path Neuer Pfad
     *
     * XXX Hm ist diese Funktion so vielleicht noch ein bisschen zu
     * optimistisch?
     */
    void write_link(struct cdi_fs_handle* handle);
};


/**
 * Die Berechtigunen werden mit Access controll lists, kurz ACLs verwaltet.
 * Diese werden in Form von Listen gespeichert. Diese Listen enthalten
 * eintraege von verschiedenen Typen.
 */
/// Eine UID
#define  CDI_FS_ACL_USER_NUMERIC,
/// Ein Benutzername als String
#define CDI_FS_ACL_USER_STRING,
/// Eine GID
#define CDI_FS_ACL_GROUP_NUMERIC,
/// Ein Gruppenname als String
#define CDI_FS_ACL_GROUP_STRING

/**
 * Der Basiseintrag in einer ACL, von dem die anderen Typen der Eintraege
 * abgeleitet sind.
 */
struct cdi_fs_acl_entry {
    // Typ des Eintrages, eine der obigen Konstanten
    int                     type;
   
    // Flags
    struct cdi_fs_obj_permissions flags;
};

/**
 * Eintraege fuer die einzelnen Typen
 */
struct cdi_fs_acl_entry_usr_num {
    struct cdi_fs_acl_entry entry;
   
    // Benutzer-ID
    uid_t                   user_id;
}

struct cdi_fs_acl_entry_usr_str {
    struct cdi_fs_acl_entry entry;
   
    // Benutzername
    char*                   user_name;
}

struct cdi_fs_acl_entry_grp_num {
    struct cdi_fs_acl_entry entry;
   
    // Gruppen-ID
    gid_t                   group_id;
}

struct cdi_fs_acl_entry_usr_str {
    struct cdi_fs_acl_entry entry;
   
    // Gruppenname
    char*                   group_name;
}



void cdi_fs_driver_init(struct cdi_fs_driver* driver);
void cdi_fs_driver_destroy(struct cdi_fs_driver* driver);
void cdi_fs_driver_register(struct cdi_fs_driver* driver);


/**
 * Quelldateien fuer ein Dateisystem lesen
 * XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
 *
 * @param device Pointer auf die Device-Struktur des Dateisystems
 * @param start Position von der an gelesen werden soll
 * @param size Groesse des zu lesenden Datenblocks
 * @param buffer Puffer in dem die Daten abgelegt werden sollen
 *
 * @return die Anzahl der gelesenen Bytes
 */
size_t cdi_fs_data_read(struct cdi_fs_device* device, uint64_t start,
    size_t size, void* buffer);

/**
 * Quellmedium eines Dateisystems beschreiben
 * XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
 *
 * @param device Pointer auf die Device-Struktur des Dateisystems
 * @param start Position an die geschrieben werden soll
 * @param size Groesse des zu schreibenden Datenblocks
 * @param buffer Puffer aus dem die Daten gelesen werden sollen
 *
 * @return die Anzahl der geschriebenen Bytes
 */
size_t cdi_fs_data_write(struct cdi_fs_device* device, uint64_t start,
    size_t size, void* buffer);


#endif

Edit:
Mir ist gerade eingefallen, dass das mit den Klassen ja beim Lesen so funktionieren kann... Aber wie sieht das beim schreiben aus? Woher soll der Treiber wissen, welche file-Klasse da benutzt werden soll?
Der Gedanke war eigentlich, dass sich beispielsweise eine Blockdatei oder ein FIFO von aussen gesehen auch nicht anders verhalten als eine reguläre Datei. Aber der Dateisystemtreiber ist dafür wohl schon eine Schicht zu tief, um das zu verhalten. Aber für mich stellt sich jetzt noch die Frage, wie mit den Spezialdateien umgegangen werden soll...
« Letzte Änderung: 12. February 2008, 10:54 von FreakyPenguin »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 12. February 2008, 11:15 »
// XXX Dateigroesse (Fuer mich stellt sich noch die Frage, ob sie wirklich zu
// den Meta-Informationen gehoert, oder ob wir sie nicht doch besser in die
// file-Struktur packen)
#define CDI_FS_META_SIZE        0
Eigentlich stellt sich die Frage nicht, denn sowas haben nur Dateien, aber nicht Verzeichnisse, Links...

/**
 * XXX Der Name Device ist hier unpassend, was besseres ist mir aber nicht
 * eingefallen.
 */
struct cdi_fs_device {
Wie wäre es mit cdi_fs_filesystem?
    // Wurzelobjekt fuer die Baumstruktur
    struct cdi_fs_object*   root_object;
   
    // Dieses Error-Flag sperrt den ganzen Mount fuer (Schreib?)Zugriffe
    int                     error;

    // Das Dateisystem darf nicht geschrieben werden. Damit schlaegt unter
    // anderem cdi_fs_write_data fehl.
    int                     read_only;
Was ist jetzt der Unterschied zwischen error und read_only, außer daß ersteres durch einen Fehler erzeugt wird?

/**
 * Das Handle stellt die Verbindung zwischen Aufrufer und betroffenem
 * Dateisystemobjekt dar.
 */
struct cdi_fs_handle {
    // Betroffenes Dateisystemobjekt
    struct cdi_fs_object*   obj;

    // Fehlernummer
    int                     error;
};
Zumindest in LOST-Terminologie hatten wir uns mal darauf geeinigt, von den "Objekten" als Ressourcen und geöffneten Ressourcen als Streams zu reden. Ich halte das für günstigere Bezeichnungen.

/**
 * Diese Struktur hat eigentlich nicht viel mit Zugriffsrechten zu tun. Deshalb
 * ist der Name vielleicht etwas ungeschickt gewaehlt, aber was bessers ist mir
 * nicht eingefallen.
 * Sie stellt allgemein die Moeglichkeiten, die an einem Objekt zur verfuegung
 * stehen dar.
 */
struct cdi_fs_obj_permissions {
cdi_fs_res_flags?
    // Objekt loeschen
    int                 remove;
    // Objekt umbenennen
    int                 rename;
    // Objekt verschieben
    int                 move;
    // Lesender Zugriff gestattet
    int                 read;
    // Schreibender Zugriff gestattet
    int                 write;
    // Ausfuehren gestattet
    int                 execute;
    // Auflisten der Verzeichniseintraege gestattet
    int                 browse;
    // Aufloesen des Links
    int                 read_link;
    // Aendern des Links
    int                 write_link;
};
create_child oder sowas fehlt noch. Ist rename lokal zum Verzeichnis, zum Dateisystem, oder global? (Letzteres macht keinen Sinn, da es noch move gibt)

struct cdi_fs_obj_file;
struct cdi_fs_obj_dir;
struct cdi_fs_obj_link;
/**
 * Das Dateisystem wird hier nur mit abstrakten Strukturen vom Typ
 * cdi_fs_object dargestellt. Diese können beispielsweise sowohl regulaere
 * Datei als auch Verzeichnis gleichzeitig darstellen.
 */
struct cdi_fs_object {
    // Name des Objektes
    char*                   name;

    // Verweis auf das Elternobjekt
    struct cdi_fs_object*   parent;
    // Liste mit allfaelligen Kindobjekten
    cdi_list_t              children;

    // Link-Pfad
    char*                   link_path;

    // ACL; siehe Unten
    cdi_list_t              acl;
    // Flags
    struct cdi_fs_obj_permissions flags;
Ah, du hast die Bezeichnung also selbst noch gefunden. ;)

    // Einzelne Klassen, zu denen das Objekt gehoeren kann, oder Null falls es
    // zu einer Bestimmten Klasse nicht gehoert.
    struct cdi_fs_obj_file* file;
    struct cdi_fs_obj_dir*  dir;
    struct cdi_fs_obj_link* link;
};
Ich mag die Idee.

Zitat
Mir ist gerade eingefallen, dass das mit den Klassen ja beim Lesen so funktionieren kann... Aber wie sieht das beim schreiben aus? Woher soll der Treiber wissen, welche file-Klasse da benutzt werden soll?
Gehört nicht jede Operation eindeutig zu einer Klasse?

Zitat
Aber für mich stellt sich jetzt noch die Frage, wie mit den Spezialdateien umgegangen werden soll...
Ich bin vermutlich von LostIO verdorben, aber was ändert sich mit Spezialdateien?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #11 am: 12. February 2008, 12:35 »
// XXX Dateigroesse (Fuer mich stellt sich noch die Frage, ob sie wirklich zu
// den Meta-Informationen gehoert, oder ob wir sie nicht doch besser in die
// file-Struktur packen)
#define CDI_FS_META_SIZE        0
Eigentlich stellt sich die Frage nicht, denn sowas haben nur Dateien, aber nicht Verzeichnisse, Links...
Hm, eigentlich hast du recht... ;-)

/**
 * XXX Der Name Device ist hier unpassend, was besseres ist mir aber nicht
 * eingefallen.
 */
struct cdi_fs_device {
Wie wäre es mit cdi_fs_filesystem?
Daran habe ich auch schon gedacht, aber das sah irgendwie auch 0xd00f aus. Aber vom Sinn her ist es wohl gescheiter.

    // Wurzelobjekt fuer die Baumstruktur
    struct cdi_fs_object*   root_object;
   
    // Dieses Error-Flag sperrt den ganzen Mount fuer (Schreib?)Zugriffe
    int                     error;

    // Das Dateisystem darf nicht geschrieben werden. Damit schlaegt unter
    // anderem cdi_fs_write_data fehl.
    int                     read_only;
Was ist jetzt der Unterschied zwischen error und read_only, außer daß ersteres durch einen Fehler erzeugt wird?

Die Überlegung dahinter war, dass man auch erkennen kann, warum das Dateisystem jetzt gesperrt ist. Das Dateisystem kann ja auch read_only sein, ohne dass ein Fehler aufgetreten ist. Flag ist da natürlich auch der Falsche Ausdruck. Da würde man wohl besser eine Fehlernummer nehmen.

create_child oder sowas fehlt noch. Ist rename lokal zum Verzeichnis, zum Dateisystem, oder global? (Letzteres macht keinen Sinn, da es noch move gibt)
Jo das fehlt noch. Ich wusste noch nicht, wie ich das am dümmsten anstellen könnte. ;-) Unter anderem auch im Zusammenhang mit den Spezialdateien, aber dazu kommen wir ja weiter unten gleich.
rename ist lokal, also kein verschieben. Ich habe die getrennt, da das ja auch aus sicht vom Treiber unterschiedliche Aktionen sind.

Zitat
Mir ist gerade eingefallen, dass das mit den Klassen ja beim Lesen so funktionieren kann... Aber wie sieht das beim schreiben aus? Woher soll der Treiber wissen, welche file-Klasse da benutzt werden soll?
Gehört nicht jede Operation eindeutig zu einer Klasse?
Wie sieht es denn mit dem neu erstellen aus? Das ist eigentlich das was ich gemeint, aber selbstveständlich nicht hingeschrieben habe. ;-)

Edit:
Vielleicht könnte man da vom eigentlichen Erstellen wegkommen und eher was in Richtung Klasse zuordnen oder so machen...

Zitat
Aber für mich stellt sich jetzt noch die Frage, wie mit den Spezialdateien umgegangen werden soll...
Ich bin vermutlich von LostIO verdorben, aber was ändert sich mit Spezialdateien?
Und ich soll davon nicht verdorben sein? ;-)

Die Spezialdateien haben keine Nutzdaten auf der Platte. Sie beinhalten (in linux) lediglich 2 Zahlen im Inode, damit sie vom Kernel identifiziert werden koennen, wenn darauf zugegriffen wird, aber mit dem eigentlichen Zugriff hat der Dateisystemtreiber nichts mehr zu tun. Das wird dann vom Kernel an irgendwelche Treiber delegiert.
« Letzte Änderung: 12. February 2008, 12:38 von FreakyPenguin »

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 12. February 2008, 13:17 »
Zitat
rename ist lokal, also kein verschieben. Ich habe die getrennt, da das ja auch aus sicht vom Treiber unterschiedliche Aktionen sind.
Lokal relativ wozu? Verzeichnis oder Dateisystem? Verschieben auf ein anderes FS ist sowieso keine eigenständige Aktion, sondern ein Kopieren und Löschen.

Zitat
Wie sieht es denn mit dem neu erstellen aus? Das ist eigentlich das was ich gemeint, aber selbstveständlich nicht hingeschrieben habe. ;-)

Edit:
Vielleicht könnte man da vom eigentlichen Erstellen wegkommen und eher was in Richtung Klasse zuordnen oder so machen...
Hm, gute Frage. Das Erstellen würde dann nur eine Ressource ohne Klasse erstellen und hinterher ordnet man die Klassen einzeln zu? Könnte funktionieren.

Zitat
Die Spezialdateien haben keine Nutzdaten auf der Platte. Sie beinhalten (in linux) lediglich 2 Zahlen im Inode, damit sie vom Kernel identifiziert werden koennen, wenn darauf zugegriffen wird, aber mit dem eigentlichen Zugriff hat der Dateisystemtreiber nichts mehr zu tun. Das wird dann vom Kernel an irgendwelche Treiber delegiert.
Was auf der Platte steht, ist wurscht. Wir reden gerade über das Interface. Das kann, muß aber nicht dasselbe sein. Aber eine eigene Klasse dafür mit read/write_major/minor sollte es doch tun?
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #13 am: 12. February 2008, 13:32 »
Zitat
rename ist lokal, also kein verschieben. Ich habe die getrennt, da das ja auch aus sicht vom Treiber unterschiedliche Aktionen sind.
Lokal relativ wozu? Verzeichnis oder Dateisystem? Verschieben auf ein anderes FS ist sowieso keine eigenständige Aktion, sondern ein Kopieren und Löschen.
Relativ zum Verzeichnis. Verschieben ist relativ zum Dateisystem

Zitat
Wie sieht es denn mit dem neu erstellen aus? Das ist eigentlich das was ich gemeint, aber selbstveständlich nicht hingeschrieben habe. ;-)

Edit:
Vielleicht könnte man da vom eigentlichen Erstellen wegkommen und eher was in Richtung Klasse zuordnen oder so machen...
Hm, gute Frage. Das Erstellen würde dann nur eine Ressource ohne Klasse erstellen und hinterher ordnet man die Klassen einzeln zu? Könnte funktionieren.
Jo das wäre vermutlich die beste Variante... Das geht aber nur solange, wie der Treiber nicht wissen muss, zu welchen Klassen die Ressource gehört, um sie erstellen zu können. Ok ein Treiber der das Braucht kann ja die "nackte" Ressource auch nur einfach mal im Speicher liegen lassen.

Zitat
Die Spezialdateien haben keine Nutzdaten auf der Platte. Sie beinhalten (in linux) lediglich 2 Zahlen im Inode, damit sie vom Kernel identifiziert werden koennen, wenn darauf zugegriffen wird, aber mit dem eigentlichen Zugriff hat der Dateisystemtreiber nichts mehr zu tun. Das wird dann vom Kernel an irgendwelche Treiber delegiert.
Was auf der Platte steht, ist wurscht. Wir reden gerade über das Interface. Das kann, muß aber nicht dasselbe sein. Aber eine eigene Klasse dafür mit read/write_major/minor sollte es doch tun?
Es geht mir ja auch um das Interface... Wenn das so ausreicht mit den 4 Funktionen ist das ja kein Problem. Dann würdest du einfach eine klasse fuer die Spezialfunktion machen, egal ob FIFO oder Block Datei?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 12. February 2008, 13:46 »
Relativ zum Verzeichnis. Verschieben ist relativ zum Dateisystem
Ok. Dokumentieren. ;)

Zitat
Jo das wäre vermutlich die beste Variante... Das geht aber nur solange, wie der Treiber nicht wissen muss, zu welchen Klassen die Ressource gehört, um sie erstellen zu können. Ok ein Treiber der das Braucht kann ja die "nackte" Ressource auch nur einfach mal im Speicher liegen lassen.
Ich denke, das wäre sowieso eine sinnvolle Definition, daß eine Ressource ohne Klasse grundsätzlich nicht persistent ist.

Zitat
Es geht mir ja auch um das Interface... Wenn das so ausreicht mit den 4 Funktionen ist das ja kein Problem. Dann würdest du einfach eine klasse fuer die Spezialfunktion machen, egal ob FIFO oder Block Datei?
Wahrscheinlich das geschickteste, einfach ein type-Feld dazupacken. Ansonsten hat man dreimal (block/char/pipe) dasselbe unter jeweils verschiedenem Namen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #15 am: 12. February 2008, 13:54 »
Ok das übernehme ich so mal.

Wahrscheinlich das geschickteste, einfach ein type-Feld dazupacken. Ansonsten hat man dreimal (block/char/pipe) dasselbe unter jeweils verschiedenem Namen.
Du meinst so, dass eine Ressource nur einen solchen Spezialtyp habe kann?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 12. February 2008, 14:32 »
Wozu braucht man bitte gleichzeitig block, char und pipe? Okay, außer für lange Dateinamen natürlich... :-D
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #17 am: 12. February 2008, 18:10 »
Hier die überarbeitete Version. Die besprochenen Änderungen sind gemacht und ein paar kleine Dinge die mir noch so eingefallen sind, habe ich auch noch ergänzt:

#ifndef _CDI_FS_H_
#define _CDI_FS_H_

#include "types.h"
#include "cdi.h"
#include "cdi/lists.h"


struct cdi_fs_driver {
    struct cdi_driver drv;
}

struct cdi_fs_object;
/**
 * Diese Struktur wird fuer jedes eingebundene Dateisystem einmal erstellt.
 */
struct cdi_fs_filesystem {
    // Wurzelobjekt fuer die Baumstruktur
    struct cdi_fs_object*   root_object;
   
    // Falls ein gravierender Fehler auftritt, wird diese Fehlernummer gesetzt.
    // Wenn sie != 0 ist wird das Dateisystem fuer Schreibzugriffe gesperrt.
    int                     error;

    // Das Dateisystem darf nicht geschrieben werden. Damit schlaegt unter
    // anderem cdi_fs_write_data fehl.
    int                     read_only;

    // Hier sollte man wohl noch ein paar allgemeine Mount-Optionen oder
    // sonstige Flags die das ganze Dateisystem betreffen.
};


// XXX Bei den Fehlernummern weiss ich noch nicht wirklich, was da notwendig
// ist, deshalb lasse ich das mal so stehen.
typedef enum {
    CDI_FS_ERROR_NONE = 0,
    // Operation nicht unterstuetzt
    CDI_FS_ERROR_ONS,
    // Ressource nicht gefunden
    CDI_FS_ERROR_RNF,
    // Beim lesen einer Datei wurde das Ende erreicht
    CDI_FS_ERROR_EOF,
    // Interner Fehler
    CDI_FS_ERROR_INTERNAL,
    // Unbekannter Fehler
    CDI_FS_ERROR_UNKNOWN
} cdi_fs_error_t;

/**
 * Der Stream stellt die Verbindung zwischen Aufrufer und Ressource dar.
 */
struct cdi_fs_stream {
    // Betroffene Ressource
    struct cdi_fs_resource* res;

    // Fehlernummer
    cdi_fs_error_t          error;
};


/**
 * Metaeigenschaften, die Ressourcen haben koennen
 */
typedef enum {
    // R  Groesse der Datei auslesen
    CDI_FS_META_SIZE,
    // R  Anzahl der Benutzten Dateisystemblocks (Irgendwo muesste man dann
    //    auch auf diese Blockgroesse zurgreiffen koennen)
    CDI_FS_META_USEDBLOCKS,
    // R  Optimale Blockgroesse mit der man auf die Datei zugreiffen sollte
    CDI_FS_META_BESTBLOCKSZ,
    // R  Zeitpunkt an dem die Ressource erstellt wurde
    CDI_FS_META_CREATETIME,
    // RW Letzter Zugriff auf die Ressource, auch lesend
    CDI_FS_META_ACCESSTIME,
    // RW Letzte Veraenderung der Ressource
    CDI_FS_META_CHANGETIME
} cdi_fs_meta_t;


/**
 * Siese Struktur stellt die Moeglichkeiten, die an einer Ressource zur
 * Verfuegung stehen, dar.
 */
struct cdi_fs_res_flags {
    // Ressource loeschen
    int                 remove;
    // Ressource umbenennen
    int                 rename;
    // Ressource verschieben
    int                 move;
    // Lesender Zugriff gestattet
    int                 read;
    // Schreibender Zugriff gestattet
    int                 write;
    // Ausfuehren gestattet
    int                 execute;
    // Auflisten der Verzeichniseintraege gestattet
    int                 browse;
    // Aufloesen des Links
    int                 read_link;
    // Aendern des Links
    int                 write_link;
    // Anlegen eines Untereintrags
    int                 create_child;
};


struct cdi_fs_res_file;
struct cdi_fs_res_dir;
struct cdi_fs_res_link;
struct cdi_fs_res_special;

/**
 * Typ der eine Ressource, die zu der Klasse der Spezialdateien gehoert noch
 * genauer beschreibt
 */
typedef enum {
    CDI_FS_BLOCK,
    CDI_FS_CHAR,
    CDI_FS_FIFO,
    CDI_FS_SOCKET
} cdi_fs_res_type_t;

/**
 * Konstanten fuer die einzelnen Klassen, um sie beim Funktionsaufruf zum
 * zuweisen einer Klasse, identifizieren zu koennen.
 */
typedef enum {
    CDI_FS_CLASS_FILE,
    CDI_FS_CLASS_DIR,
    CDI_FS_CLASS_LINK,
    CDI_FS_CLASS_SPECIAL
} cdi_fs_res_class_t;

/**
 * Dieser Typ dient dazu Ressourcen ganz oder teilweise zu sperren
 */
typedef enum {
    CDI_FS_LOCK_NONE,
    CDI_FS_LOCK_WRITE,
    CDI_FS_LOCK_ALL
} cdi_fs_lock_t;

/**
 * Das Dateisystem wird hier nur mit abstrakten Strukturen vom Typ
 * cdi_fs_resource dargestellt. Diese können beispielsweise sowohl regulaere
 * Datei als auch Verzeichnis gleichzeitig darstellen.
 *
 * Weiter gilt, dass Ressourcen, die zu keiner Klasse gehoeren, nicht
 * persistent sind.
 */
struct cdi_fs_resource {
    // Name der Ressource
    char*                   name;
   
    // Lock fuer diese Ressource
    cdi_fs_lock_t           lock;

    // Verweis auf das Elternobjekt
    struct cdi_fs_object*   parent;
    // Liste mit allfaelligen Kindobjekten
    cdi_list_t              children;

    // Link-Pfad
    char*                   link_path;

    // ACL; siehe Unten
    cdi_list_t              acl;
    // Flags
    struct cdi_fs_obj_flags flags;

    // Einzelne Klassen, zu denen die Ressourcen gehoeren kann, oder Null falls
    // es zu einer Bestimmten Klasse nicht gehoert.
    struct cdi_fs_res_file* file;
    struct cdi_fs_res_dir*  dir;
    struct cdi_fs_res_link* link;
    struct cdi_fs_res_special special;

    // Falls die Ressource zu einer Spezialklasse gehoert, wird hier angegeben,
    // um welchen Typ von Spezialressource sie gehoert.
    cdi_fs_res_type_t       type;
};



/**
 * Diese Dateisystemobjekte werden in Klassen eingeteilt, die das eigentliche
 * "Verhalten" der Ressourcen steuern. Diese Klassen beinhalten die moeglichen
 * Operationen und auch die Eigenschaften, die fuer die Ressourcen gelten,
 * denen diese Klassen zugeordnet sind.
 * Das Definieren der einzelnen Klassen uebernehmen dann die einzelnen Treiber.
 *
 * Die Flags koennen von der Ressource ueberschrieben werden. Es koennen
 * allerdings nur Flags deaktiviert werden, die in der Klasse gesetzt sind un
 * nicht umgekehrt.
 * Das Selbe gilt auch fuer Klassen bei denen NULL-Pointer fuer Operationen
 * eingetragen sind. Wenn zum Beispiel fuer write NULL eingetragen wird, dann
 * bringt ein gesetztes write-Flag nichts.
 */

/**
 * Diese Klasse gilt unabhaengig von den andern, also egal welche anderen
 * Klassen angegeben sind, diese muss angegeben werden.
 */
struct cdi_fs_obj_obj {
    /**
     * Ressource entfernen
     *
     * @param stream Stream
     *
     * @return Falls die Ressource erfolgreich geloescht wurde 1, sonst 0
     */
    int (*remove)(struct cdi_fs_stream* stream);

    /**
     * Namen einer Ressource aendern. Der Parameter name ist nur der
     * Resourcennamen ohne Pfad. Zum verschieben wird move() benutzt.
     *
     * @param stream Stream
     * @param name Neuer Name
     *
     * @return Falls die Ressource erfolgreich umbenennt wurde 1, sonst 0
     */
    int (*rename)(struct cdi_fs_stream* stream, const char* name);

    /**
     * Ressource innerhalb des Dateisystems verschieben. Das Verschieben ueber
     * Dateisystemgrenzen hinweg wird per kopieren und loeschen durchgefuehrt.
     *
     * @param stream Stream
     * @param dest Pointer auf die Ressource, in die die Ressource verschoben
     *             werden soll
     *
     * @return Falls die Ressource erfolgreich verschoben wurde 1, sonst 0
     */
    int (*move)(struct cdi_fs_stream* stream, struct cdi_fs_resource* dest);

    /**
     * Neue Ressource in der Aktuellen erstellen. Diese wird erstmal noch
     * keiner Klasse zugewiesen. Diese Funktion wird mit einem NULL-Pointer als
     * Ressource im Stream aufgerufen. Dieser NULL-Pointer muss bei
     * Erfolgreichem Beenden durch einen Pointer auf die neue Ressource ersetzt
     * worden sein.
     *
     * @param stream Mit NULL-Pointer als Ressource
     * @param parent Ressource, der die neue Ressource als Kindressource
     *               zugeordnet werden soll.
     *
     * @return Falls die Ressource erfolgreich erstellt wurde 1, sonst 0
     */
    int (*create_child)(struct cdi_fs_stream* stream,
        struct cdi_fs_resource* parent);

    /**
     * Diese Ressource einer neuen Klasse zuweisen. Dieser Aufruf schlaegt
     * fehl, wenn die Ressource dieser Klasse schon zugewiesen ist.
     *
     * @param stream Stream
     * @param class Konstante fuer den Typ der klasse, der die Ressource
     *              zugewiesen werden soll.
     *
     * @return 1 falls die Ressource erfolgreich der Klasse zugewiesen wurde, 0
     *         sonst
     */
     int (*assign_class)(struct cdi_fs_stream* stream,
        cdi_fs_res_class_t class);

    /**
     * Metaeigenschaft lesen
     *
     * @param stream Stream
     * @param meta Konstante fuer die gewuenschte Metaeigenschaft
     *
     * @return Wert der Metaeigenschaft
     */
    int64_t (*meta_read)(struct cdi_fs_stream* stream, cdi_fs_meta_t meta);

    /**
     * Metaeigenschaft schreiben
     *
     * @param stream Stream
     * @param meta Konstante fuer die gewuenschte Metaeigenschaft
     * @param value Neuen Wert fuer die Metaeigenschaft
     *
     * @return Falls die Metaeigenschaft erfolgreich geaendert wurde 1, sonst 0
     */
    int64_t (*meta_write)(struct cdi_fs_stream* stream, cdi_fs_meta_t meta,
        int64_t value);

}

struct cdi_fs_obj_file {
    // XXX (Aber wie geht das, wenn eine Datei nicht lesbar, aber ausfuehrbar
    // sein soll?)
    int                     executable;
   
    /**
     * Daten aus dieser Datei lesen. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param stream Stream
     * @param start Position von der an gelesen werden soll
     * @param size Groesse der zu lesenden Daten
     * @param buffer Puffer in den die Daten gelsen werden sollen
     *
     * @return Gelesene Bytes, oder 0 im Fehlerfall
     */
    size_t (*read)(struct cdi_fs_stream* stream, uint64_t start, size_t size,
        void* buffer);

    /**
     * Daten in diese Datei schreiben. Wird nur aufgerufen, wenn es durch die
     * Flags oder Berechtigungen nicht verhindert wird.
     *
     * Im Fehlerfall wird je nach Fehler die Fehlernummer im Handle und die im
     * Device gesetzt.
     *
     * @param stream Stream
     * @param start Position an die geschrieben werden soll
     * @param size Groesse der zu schreibenden Daten
     * @param buffer Puffer aus dem die Daten gelesen werden sollen
     *
     * @return Geschriebene Bytes oder 0 im Fehlerfall
     */
    size_t (*write)(struct cdi_fs_stream* stream, uint64_t start, size_t size,
        void* buffer);
};

struct cdi_fs_obj_dir {
    // XXX Ein browsable Flag koennen wir vermutlich hier eindeutig welgassen,
    // waere ja irgenwie witzlos. ;-)
   
    /**
     * Diese Funktion gibt einen Pointer auf die Liste mit den Eintraegen
     * zurueck. Hier wird nicht einfach fix der Pointer in fs_obj genommen,
     * damit dort auch "versteckte" Eintraege vorhanden sein koennten. (Ich
     * meine hier nicht irgend ein versteckt-Flag dass die Dateien vor dem
     * Benutzer Verstecken soll, sondern eher von fuer den Internen gebrauch
     * angelegten Eintraegen.
     *
     * @param stream Stream
     *
     * @return Pointer auf eine Liste mit den Untereintraegen.
     */
     cdi_list_t* (*list)(struct cdi_fs_stream* stream);
};

struct cdi_fs_obj_link {
    // XXX Ich glaube auch hier brauchen wir kein resolvable-Flag

    /**
     * Diese Funktion liest den Pfad aus, auf den der Link zeigt
     *
     * @param stream Stream
     *
     * @return Pointer auf einen Ouffer der den Pfad beinhaltet. Dieses Puffer
     *         darf vom Aufrufer nicht veraendert werden.
     */
    const char* (*read_link)(struct cdi_fs_stream* stream);

    /**
     * Aendert den Pfad auf den der Link zeigt
     *
     * @param stream Stream
     * @param path Neuer Pfad
     *
     * XXX Hm ist diese Funktion so vielleicht noch ein bisschen zu
     * optimistisch?
     */
    void (*write_link)(struct cdi_fs_stream* stream);
};

struct cdi_fs_res_special {
    // XXX Reicht das so?

    /**
     * Geraeteadresse der Spezialdatei Lesen
     *
     * @param stream Stream
     * @param dev Pointer auf die Variable in der die Geraeteadresse
     *            gespeichert werden soll.
     *
     * @return Falls die Geraeteadresse erfolgreich gelesen wurde 1, sonst 0
     */
    int (*dev_read)(struct cdi_fs_stream* stream, dev_t* dev);

    /**
     * Geraeteadresse der Spezialdatei Aendern
     *
     * @param stream Stream
     * @param dev Die neue Geraeteadresse
     *
     * @return Falls die Geraeteadresse erfolgreich geaendert wurde 1, sonst 0
     */
    int (*dev_write)(struct cdi_fs_stream* stream, dev_t dev);
}



/**
 * Die Berechtigunen werden mit Access controll lists, kurz ACLs verwaltet.
 * Diese werden in Form von Listen gespeichert. Diese Listen enthalten
 * eintraege von verschiedenen Typen.
 */
/// Eine UID
#define  CDI_FS_ACL_USER_NUMERIC,
/// Ein Benutzername als String
#define CDI_FS_ACL_USER_STRING,
/// Eine GID
#define CDI_FS_ACL_GROUP_NUMERIC,
/// Ein Gruppenname als String
#define CDI_FS_ACL_GROUP_STRING

/**
 * Der Basiseintrag in einer ACL, von dem die anderen Typen der Eintraege
 * abgeleitet sind.
 */
struct cdi_fs_acl_entry {
    // Typ des Eintrages, eine der obigen Konstanten
    int                     type;
   
    // Flags
    struct cdi_fs_obj_flags flags;
};

/**
 * Eintraege fuer die einzelnen Typen
 */
struct cdi_fs_acl_entry_usr_num {
    struct cdi_fs_acl_entry entry;
   
    // Benutzer-ID
    uid_t                   user_id;
}

struct cdi_fs_acl_entry_usr_str {
    struct cdi_fs_acl_entry entry;
   
    // Benutzername
    char*                   user_name;
}

struct cdi_fs_acl_entry_grp_num {
    struct cdi_fs_acl_entry entry;
   
    // Gruppen-ID
    gid_t                   group_id;
}

struct cdi_fs_acl_entry_usr_str {
    struct cdi_fs_acl_entry entry;
   
    // Gruppenname
    char*                   group_name;
}



void cdi_fs_driver_init(struct cdi_fs_driver* driver);
void cdi_fs_driver_destroy(struct cdi_fs_driver* driver);
void cdi_fs_driver_register(struct cdi_fs_driver* driver);


/**
 * Quelldateien fuer ein Dateisystem lesen
 * XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
 *
 * @param device Pointer auf die Device-Struktur des Dateisystems
 * @param start Position von der an gelesen werden soll
 * @param size Groesse des zu lesenden Datenblocks
 * @param buffer Puffer in dem die Daten abgelegt werden sollen
 *
 * @return die Anzahl der gelesenen Bytes
 */
size_t cdi_fs_data_read(struct cdi_fs_device* device, uint64_t start,
    size_t size, void* buffer);

/**
 * Quellmedium eines Dateisystems beschreiben
 * XXX Brauchen wir hier auch noch irgendwas errno-Maessiges?
 *
 * @param device Pointer auf die Device-Struktur des Dateisystems
 * @param start Position an die geschrieben werden soll
 * @param size Groesse des zu schreibenden Datenblocks
 * @param buffer Puffer aus dem die Daten gelesen werden sollen
 *
 * @return die Anzahl der geschriebenen Bytes
 */
size_t cdi_fs_data_write(struct cdi_fs_device* device, uint64_t start,
    size_t size, void* buffer);


#endif

jgraef

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 17. February 2008, 14:05 »
Ich hab hier mal ein paar Fehlercodes hinzugefügt.

    // Keine Zugriffsrechte
    CDI_FS_ERROR_NOPERM,
    // Invalider Dateideskriptor
    CDI_FS_ERROR_BADFD,
    // Datei existiert
    CDI_FS_ERROR_FEXISTS,
    // Datei zu groß
    CDI_FS_ERROR_FBIG,
    // Ist ein Verzeichnis
    CDI_FS_ERROR_ISDIR,
    // Zu viele Levels symbolischer Links
    CDI_FS_ERROR_LOOP,
    // Zu viele geöffnete Dateien
    CDI_FS_ERROR_MFILES,
    // Zu viele Links
    CDI_FS_ERROR_MLINKS,
    // Dateiname zu lang
    CDI_FS_ERROR_FNTOOLONG,
    // Nicht genügend Speicher
    CDI_FS_ERROR_NOMEM,
    // Kein Verzeichnis
    CDI_FS_ERROR_NODIR,
    // Kein Socket
    CDI_FS_ERROR_NOSOCK,
    // Verzeichnis nicht leer
    CDI_FS_ERROR_DIRNEMPTY,
    // Kaputte Pipe
    CDI_FS_ERROR_BRKPIPE,
    // Read-only Dateisystem
    CDI_FS_ERROR_ROFS,
    // Ungültiger Seek
    CDI_FS_ERROR_BADSEEK

FreakyPenguin

  • Administrator
  • Beiträge: 301
    • Profil anzeigen
    • toni.famkaufmann.info
Gespeichert
« Antwort #19 am: 17. February 2008, 14:37 »
Zitat
Ich hab hier mal ein paar Fehlercodes hinzugefügt.

    // Keine Zugriffsrechte
    CDI_FS_ERROR_NOPERM,
Das gehört meiner Meinung nach nicht zu CDI. So wie ich mir das vorstelle, füllt der Treiber nur die ACLs, ausgewertet werden die von der OS-abhängigen Implementation.

Zitat
    // Invalider Dateideskriptor
    CDI_FS_ERROR_BADFD,
Auch das Verwalten der Dateideskriptoren, bei uns hier jetzt Streams genannt, gehört nicht in die Treiber.
Zitat
    // Datei existiert
    CDI_FS_ERROR_FEXISTS,
    // Datei zu groß
    CDI_FS_ERROR_FBIG,
    // Ist ein Verzeichnis
    CDI_FS_ERROR_ISDIR,
Das kann in der Implementation doch nicht passieren. Datei-Funktionen können aus sicht des Treibers auf eine Ressource nur angewendet werden, wenn sie zu einer entsprechenden Klasse gehören.
Zitat
    // Zu viele Levels symbolischer Links
    CDI_FS_ERROR_LOOP,
    // Zu viele geöffnete Dateien
    CDI_FS_ERROR_MFILES,
Auch diese 2 kommen von der Implementation

Zitat
    // Zu viele Links
    CDI_FS_ERROR_MLINKS,
    // Dateiname zu lang
    CDI_FS_ERROR_FNTOOLONG,
    // Nicht genügend Speicher
    CDI_FS_ERROR_NOMEM,
    // Kein Verzeichnis
    CDI_FS_ERROR_NODIR,
Dieser auch wieder, oder verstehe ich die Bedeutung falsch? Dieser Fehler kommt doch, wenn eine Komponente in einem Pfad kein Verzeichnis oder nicht vorhanden ist?
Zitat
    // Kein Socket
    CDI_FS_ERROR_NOSOCK,
    // Verzeichnis nicht leer
    CDI_FS_ERROR_DIRNEMPTY,
    // Kaputte Pipe
    CDI_FS_ERROR_BRKPIPE,
    // Read-only Dateisystem
    CDI_FS_ERROR_ROFS,
    // Ungültiger Seek
    CDI_FS_ERROR_BADSEEK
Für CDI_FS_ERROR_NOSOCK, CDI_FS_ERROR_BRKPIPE, CDI_FS_ERROR_BADSEEK gilt wieder, dass das in die Implementation gehört.

Und zu CDI_FS_ERROR_DIRNEMPTY,  CDI_FS_ERROR_ROFS stelle ich mir grad die Frage, ob wir nicht definieren sollen, dass von der Implementation garantiert werden muss, dass keine schreibenden Operationen ausgeführt werden, wenn read only aktiviert ist, und dass nicht versucht wird, ein volles verzeichnis zu löschen.

 

Einloggen