PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit FUSE



schoppenhauer
09-04-2007, 00:14
Hallo.

Nachdem es ja scheinbar keine gescheite Doku der FUSE-API gibt, hab ich mir ein bissel versucht, das Ganze aus den Fingern zu saugen... Und vor allem viel Zeugs aus irgendwelchen Halbwahren Tutorials.

Was ich eigentlich erreichen wollte, war, ein Dateiensystem zu schreiben, sodass ich bei "cat hallo" ein "h" ausgegeben bekomme. Ein Anfang... Drum lass ich die meisten Sachen nicht ausführen.

Jedenfalls... Ich habs jetzt endlich soweit, dass ich compilieren und mounten kann... Allerdings weiß ich nicht, wie man wieder unmountet.

Der Sourcecode (in der Datei "test.c") ist Folgender:


#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

#define FUSE_USE_VERSION 25
#define _FILE_OFFSET_BITS 64
#include <fuse.h>

int m_getattr (const char * a, struct stat * b) {
return ENOSYS;
}
int m_readlink (const char * a, char * b, size_t c) {
return ENOSYS;
}
int m_getdir (const char * a, fuse_dirh_t b, fuse_dirfil_t c) {
return EPERM;
}
int m_mknod (const char * a, mode_t b, dev_t c) {
return EPERM;
}
int m_mkdir (const char * a, mode_t b) {
return EPERM;
}
int m_rmdir (const char * a) {
return EPERM;
}
int m_unlink (const char * a) {
return EPERM;
}
int m_rename (const char * a, const char * b) {
return EPERM;
}
int m_symlink (const char * a, const char * b) {
return EPERM;
}
int m_link (const char * a, const char * b) {
return EPERM;
}
int m_chmod (const char * a, mode_t b) {
return EPERM;
}
int m_chown (const char * a, uid_t b, gid_t c) {
return EPERM;
}
int m_truncate (const char * a, off_t b) {
return ENOSYS;
}
int m_utime (const char *a, struct utimbuf *b) {
return ENOSYS;
}

int m_open (const char *a, struct fuse_file_info *b) {
if (strcmp (a, "/hallo") == 0) {
return 0;
} else {
return EPERM;
}
}

int m_read (const char *file, char *ret, size_t size, off_t offset, struct fuse_file_info *ffi) {
if (strcmp (file, "/hallo") == 0) {
if (offset == 0) {
if (size > 0) {
ret[0] = 'h';
size_t i;
for (i = 1; i < size; i++) {
ret[i] = 0x00;
}
return 1;
} else {
return 0;
}
} else {
size_t i;
for (i = 0; i < size; i++) {
ret[i] = 0x00;
}
return EOF;
}
} else {
return EPERM;
}
}

int m_write (const char *a, const char *b, size_t c, off_t d, struct fuse_file_info *e) {
return EPERM;
}


int main (int argc, char* argv[]) {
struct fuse_operations fop;
fop.getattr = m_getattr;
fop.readlink = m_readlink;
fop.getdir = m_getdir;
fop.mknod = m_mknod;
fop.mkdir = m_mkdir;
fop.rmdir = m_rmdir;
fop.unlink = m_unlink;
fop.rename = m_rename;
fop.symlink = m_symlink;
fop.link = m_link;
fop.chmod = m_chmod;
fop.chown = m_chown;
fop.truncate = m_truncate;
fop.utime = m_utime;
fop.open = m_open;
fop.read = m_read;
fop.write = m_write;
return fuse_main(argc, argv, &fop);
}Jut... Soweit alles Klar... mittels
$ gcc -o test test.c -lfuselässt sich die ganze Pampe dann auch compilieren. Dann mach ich
$ mkdir mountpoint
$ ./test mountpoint
$ cd mountpoint/Soweit alles klar. Wenn ich jetzt "ls" eingebe erwarte ich eigentlich - entsprechend des Rückgabewertes ENOSYS - dass irgendwas passiert von wegen "Nicht unterstützt" oder so. Was ich stattdessen bekomme:
$ ls
ls: .: Das numerische Ergebnis ist außerhalb des gültigen Bereiches
Außerdem
$ cat hallo
cat: hallo: Das numerische Ergebnis ist außerhalb des gültigen Bereiches
Ich kann mir vorstellen, dass der Fehler ein ziemlich dummer Fehler ist, aber ich hab keine Ahnung, wo er liegt. Wie gesagt, ich hab bisher keine gescheite Doku dazu gefunden (wenn jemand eine kennt, her damit!) und hab also wenig Ahnung, und die Kommentare in den Includefiles sind auch nur begrenzt aufschlussreich.
Kann mir jemand sagen, was ich falsch mache?

Edit: Ok... Zwei fehler hab ich gefunden: Ich muss -ENOSYS und -EPERM returnen... was auch immer das für einen Sinn machen mag, nicht gleich die Konstanten korrekt zu definieren...
Weiterhin hab ich die Funktion m_getattr wie folgt geändert:
int m_getattr (const char * a, struct stat * b) {
if (strcmp(a, "/")) {
b->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
} else { /* rootdir */
b->st_mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH;
}
return 0;
}Irgendwie denkt FUSE jetzt aber scheinbar, alle Dateien seien Sockets... Ich bekomme Fehlermeldungen wie "ls: .: Das Programm verursachte den Abbruch der Verbindung" und "cat: a: Der Socket ist nicht verbunden". Aber ich hab doch den Socket-Flag garnicht gesetzt...

panzi
09-04-2007, 22:28
Ich weiß nicht aber eventuell hilft dieser dieser BspCode. Ist zwar Python und nicht C, aber IMHO ist python eh einfach(er) zu verstehn. Und wie geil ist das bitt? Ein filesystem in einer Skriptsprache wie python implementiert!! Suckt sicher, aber zum herumspieln/testen reichts. Oder für ein Object-Filesystem in dem Python Objekte als Dateine/Verzeichnisse dargestellt werden.

http://codespeak.net/svn/user/arigo/hack/pyfuse/test.py
http://codespeak.net/svn/user/arigo/hack/pyfuse/

schoppenhauer
09-04-2007, 23:02
Ich weiß nicht aber eventuell hilft dieser dieser BspCode.Naja, danke auf jeden Fall. Besser als nichts. Wobei ich daraus nur begrenzt schlau werde.
Hat jemand ggf. noch was anderes? Oder weiß vor allem Konkret was ich in meinem noch relativ bescheidenen Vorhaben falsch mache?


Ist zwar Python und nicht C, aber IMHO ist python eh einfach(er) zu verstehn.Also ne... Ich persönlich konnt mich nie mit Python anfreunden. Ein bissel PERL hab ich mal gecoded... Ein bissel PHP (aber das ist ja für andere Zwecke gedacht)... Python gefiel mir nie (ist aber Ansichtssache). Ich mag so Scriptsprachen generell weniger... Mal abgesehen ggf. von Bash - die aber nen anderen Einsatzzweck hat, aber recht praktisch ist für kleinere Sachen.


Und wie geil ist das bitt? Ein filesystem in einer Skriptsprache wie python implementiert!! Suckt sicher, aber zum herumspieln/testen reichts.Jup. Sehr viele auf FUSE basierende Filesysteme sind in Scriptsprachen geschrieben, leider meistens in Python. Das ist nichts verwerfliches, und auch nichts schlechtes, finde ich. Und GMailFS hab ich auch mal z.B. probiert (liebes G00gle, hab bitte Nachsicht - ich wollt nur mal wissen, ob es auch geht, mehr nicht, und ich benutz es auch nicht weiter - alleine schon, weil ich keinen produktiven Einsatzzweck hätte :D ) - eigentlich das einzige FUSE-System, das ich bisher ausprobiert habe. Und das ist afaik in python geschrieben. Läuft aber scheinbar recht stabil.

Um den Scripting-Wahnsinn bis Ultimo zu treiben, gibt es sogar ein Projekt, das Bindings für Bash bereitstellen wird, hab ich gelesen... Wobei ich mir nicht ganz vorstellen kann, wie das funktionieren soll. Wie dem auch sei...
Es gibt so viel von dem Zeugs... Aber keine gescheite oder wenigstens annehmbare Doku, die sich finden lässt.