Was mich wundert, daß nach dem mount (vdrnfofs ....) ein "df" kein fuse- oder sonstwie gemountetes Verzeichnis zeigt.
vdrnfofs mit Python 3
-
-
ASCII-Zeichen und Quotes in Dateinamen sollten eigentlich kein Problem machen, bei Unicode muss man ggf. aufpassen (das kann ich aus dem Code nicht abschätzen, ob es da ein Problem geben kann, weil ich das fuse-Modul nicht besonders gut kenne) - kannst du mal bitte eine vollständige Ausgabe des Verzeichnis-Inhalts anhängen, dann kann ich mal versuchen das nachzustellen. Asterix_+_Obelix_-_Im_Auftrag_Ihrer_Majestät_-_Astérix_et_Obélix_Au_service_de_Sa_Majesté wäre z.B. eine Aufnahme, die Unicode-Zeichen im Pfad hat.
Du könntest auch mal versuchen pydb anzuwerfen, eventuell sieht man damit mehr:
python3 -m pdb $(which vdrnfofs) /mnt/vdrnfofs -d -o video=/srv/vdr/video,allow_other -o loglevel=debug
Wenn der pdb-Prompt angezeigt wird, das Skript mit c (gefolgt von der Eingabetaste) laufen lassen und dann versuchen den Crash zu provozieren.
-
Nochmal danke für Deine Arbeit!
Im Anhang das Listing mit default (de_AT.UTF8) und auch mit LANG=C
Mit pydb sieht es auch nicht viel anders aus:
Code
Alles anzeigen# python3 -m pdb $(which vdrnfofs) /mnt/vdrnfofs -d -o video=/srv/vdr/video,allow_other -o loglevel=debug > /usr/local/bin/vdrnfofs(3)<module>() -> __requires__ = 'vdrnfofs==1.0' (Pdb) c INFO:root:Starting vdrnfofs FUSE library version: 2.9.9 nullpath_ok: 0 nopath: 0 utime_omit_ok: 0 unique: 2, opcode: INIT (26), nodeid: 0, insize: 56, pid: 0 INIT: 7.32 flags=0x03fffffb max_readahead=0x00020000 INIT: 7.19 flags=0x00000011 max_readahead=0x00020000 max_write=0x00020000 max_background=0 congestion_threshold=0 unique: 2, success, outsize: 40 unique: 4, opcode: GETATTR (3), nodeid: 1, insize: 56, pid: 2027623 getattr / unique: 4, success, outsize: 120 unique: 6, opcode: STATFS (17), nodeid: 1, insize: 40, pid: 2027623 unique: 6, success, outsize: 96 ### da stoppt die Ausgabe erstmal, erst mit "ls /mnt/vdrnfofs" der Fehler unique: 8, opcode: GETATTR (3), nodeid: 1, insize: 56, pid: 2032611 getattr / unique: 8, success, outsize: 120 unique: 10, opcode: OPENDIR (27), nodeid: 1, insize: 48, pid: 2032611 unique: 10, success, outsize: 32 unique: 12, opcode: READDIR (28), nodeid: 1, insize: 80, pid: 2032611 readdir[0] from 0 Speicherzugriffsfehler (Speicherabzug geschrieben)
-
Also eine wilde Mischung von Encodings in den Verzeichnisnamen - mit deiner Liste an Verzeichnisnamen kann ich den Crash schon mal reproduzieren, jetzt muss ich nur noch herausfinden, wo genau und warum es knallt...
Edit: es knallt laut gdb in der libfuse.so.2, also geht da vermutlich bei der Übergabe des Dateinamens an die Bibliothek etwas schief.
-
Das sieht für mich nach einem Fehler im C-Code in den Python-Bindings für die libfuse aus (https://github.com/libfuse/pyt…eparts/_fusemodule.c#L401 ff. (wobei PyString_AsString per Macro zu PyUnicode_AsUTF8 wird, wenn für Python3 kompiliert wird) - die nutzen also PyUnicode_AsUTF8 statt dem - wenn ich das richtig verstehe - dafür unter Python >= 3.2 vorgesehenen mit PyUnicode_EncodeFSDefault, das ein PyBytesObject zurückgibt, dessen Inhalt man dann mittels PyBytes_AsString als char* bekommt. Da PyUnicode_AsUTF8 immer mit 'strict' statt mit konvertiert, liefert die Funktion bei nicht UTF-8 konformen Zeichen einen leeren String zurück, was in keinem Fall ein gültiger Dateiname ist.
Vielleicht mag jemand den Patch ausprobieren:
Diff: fix_readdir_encoding_crash.patch
Alles anzeigenIndex: python-fuse-1.0.0/fuseparts/_fusemodule.c =================================================================== --- python-fuse-1.0.0.orig/fuseparts/_fusemodule.c 2019-07-19 06:56:12.000000000 +0200 +++ python-fuse-1.0.0/fuseparts/_fusemodule.c 2021-01-14 11:31:06.093972812 +0100 @@ -83,7 +83,15 @@ #define PyInt_AsLong PyLong_AsLong #define PyInt_Check PyLong_Check #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask +#if PY_MINOR_VERSION >= 2 + char* MyString_AsUnicodePath(PyObject *unicode) { + return PyBytes_AsString(PyUnicode_EncodeFSDefault(unicode)); + } +// use appropriate utf-8 conversion + #define PyString_AsString MyString_AsUnicodePath +#else #define PyString_AsString PyUnicode_AsUTF8 +#endif #define PyString_Check PyUnicode_Check #define PyString_Size PyUnicode_GET_SIZE #endif
Wer Ubuntu 20.04 nutzt, kann mal probieren die angehängte Datei zu entpacken und mit der darin enthaltenen Shared Library die vorhandene /usr/lib/python3/dist-packages/fuseparts/_fuse.cpython-38-x86_64-linux-gnu.so zu ersetzen.
Das Escaping in der Shell sieht dann nicht besonders schön aus, aber er crasht nicht mehr (daher würde ich mir überlegen, ob man Dateinamen mit kaputtem Encoding in vdrnfofs aufräumt oder mit (c)chardet versucht das korrekte Encoding zu erkennen und dann einen "hübschen" Pfad präsentiert - das geht dann natürlich zu Lasten der Performance):
'Mord_im_Spiegel_-_The_Mirror_Crack--'$'\231''d_2020-01-04.20.15.1-0.rec.mpg'
Edit: und leider kann man auf die Datei auch nicht zugreifen, weil der Pfad nicht korrekt aufgelöst wird.
-
Interessant. Erstmal danke für die ausführliche Analyse des Problems. Bekommst du das hin das eines der einfachen Beispiele, das bei python-fuse dabei ist, auch crasht? Wäre damit wohl einfacher ein Issue eröffnen zu können. Letztlich muss das zugrundeliegende Problem erstmal im Python-Modul gelöst werden. Als Python-Programmierer erwarte ich Exceptions aber keine Segfaults.
Weil solche Fehler im EPG ja nicht so unwahrscheinlich sind wird man aber um ein kreatives "Fixen" von kaputtem Encoding auf Dauer kaum rumkommen.
-
Sehe gerade: Ganz so einfach ist das nicht mit dem "beliebigen Umkodieren". Man muss ja immer den Pfad halten der zur "echten" Datei führt. Aktuell wird dafür der tatsächliche Pfad im Fuse-Dateisystem genutzt.
Eigentlich müsste das Fuse-Modul die "vergurkten" Pfade einfach durchreichen. Sieht dann komisch aus, aber besser als nichts.
-
Bekommst du das hin das eines der einfachen Beispiele, das bei python-fuse dabei ist, auch crasht?
Ja, es genügt, wenn man in https://github.com/libfuse/pyt…ster/example/hello.py#L24 einen nicht einfach mit errors='strict' in UTF-8 enkodierbaren Pfad bzw. Dateinamen setzt (also z.B. hello_path = b'/hello\x99'.decode('utf-8', errors='surrogateescape')) und sich den Inhalt des Wurzelverzeichnis des fuse-Dateisystems mit ls anzeigen lässt.
Letztlich muss das zugrundeliegende Problem erstmal im Python-Modul gelöst werden.
Fürs Listen von Dateien ist das ja wie oben gezeigt nicht schlimm - da sorgt man halt dafür, dass die Enkodierung mit passenden Escape-Zeichen für nicht UTF-8 konforme Zeichen passiert.
Wenn ich das richtig aus der Dokumentation der Python C-API herauslese, wird das eklig das korrekte Lesen von Pfaden mit nicht UTF-8 Zeichen im C-Code zu fixen - da muss man überall, wo das fuse-Modul einen char* mit den Bytes für den Pfad durch den UTF-8 Decoder schickt, um einen Python-String draus zu machen einen Custom Converter einbauen, damit er die Umwandlung mit 'surrogateescape' Error-Handler macht - das wären über 60 Stellen im Code und da man dann das korrekte "s" im Format-String durch ein "O&" ersetzen und die Convertermethode als zusätzlichen Parameter nach dem path angeben muss, ist das nicht mit suchen und ersetzen getan, gerade wenn man das noch "schön" kapseln will, so dass es die Abwärtskompatibilität zu alten Python- und FUSE-Versionen nicht kaputt macht...
-
Abwärtskompatibilität zu Python 2 kann man, seit Python 2 offiziell abgekündigt ist, eigentlich eh vergessen.
Sieht aber auch nicht so aus als würden die Python-Bindings auf libfuse sonderlich üppig gepflegt. Als Issue würde ich das aber trotzdem aufmachen. Segfaults darf es mit Python nie geben. Wenn stattdessen eine Exception geworfen wird wäre ich ja schon zufrieden.
In einem Test hatte ich gerade schon eine Art "Übersetzungstabelle" für Datei-Pfade laufen. Allerdings eher als Hack. Ich muss mich da nochmal etwas ausführlicher mit befassen. Es gibt in vdrnfofs zig verschiedenen "Caches". Keine Ahnung welcher da für was gut ist und vor allem ob die überhaupt alle sinnvoll sind.
-
Heureka
Wer Ubuntu 20.04 nutzt, kann mal probieren die angehängte Datei zu entpacken und mit der darin enthaltenen Shared Library die vorhandene /usr/lib/python3/dist-packages/fuseparts/_fuse.cpython-38-x86_64-linux-gnu.so zu ersetzen.
Danke herzlichst, ja, mit der modifizierten library stürzt vdrnfofs nicht mehr ab.
-
Möglicher Fix ist im GIT. Testen mit einer gepatchten Library bringt aber natürlich jetzt nicht viel
Mit der Anpassung hat man prinzipiell freie Wahl wie die Aufnahmen benannt werden. Der Name der Aufnahme ist nicht mehr an ihren echten Pfad im Dateisystem gebunden.
Das klappt nicht mit kaputten Zeichen in einem echten Unterordner. Die bitte sauber halten. Sonst wird es echt zu komplex.
-
Hier ist noch der vollständige Patch für python-fuse, der sowohl das De- als auch das Encoding von Pfaden gerade zieht, die nicht-UTF8 Zeichen enthalten (die Python C-API ist hübsch-hässlich): fix_readdir_encoding_crash.patch
Und für die Ubuntu 20.04 Nutzer das damit erstellte Modul: _fuse.cpython-38-x86_64-linux-gnu.zip
-
Wow. Doch ein ziemlicher Aufwand. Gute Arbeit!
Kannst du das als Pull-Request für python-fuse einstellen? Für Arch will ich auf keinen Fall ein Paket selber pflegen das schon in einem offiziellen Repo verfügbar ist. Einzige Chance es da rein zu bekommen wäre, wenn die eine Version mit dem Fix erstellen. Dann könnte ich "out of date" markieren um den Fix ins offizielle Paket zu bekommen.
-
Das kann ich am Wochenende machen - mir wäre es lieb, wenn das vorher noch ein paar Leute ausprobieren würden - ich habe schon ein Paket mit dem Patch in ppa:yavdr/experimental-main bauen lassen, damit das bequemer geht.
-
Hab den Hack mal im "master" Branch wieder rausgehauen und in einen Unter-Branch "unicode-crashfix" verschoben.
Aus diesem Branch habe ich dann eine Version 0.10.0 getaggt, die ich jetzt für vdr4arch paketiere. Ist für mich erstmal der einfachste Weg um das für Arch hinzubiegen.
Ich muss am Wochenende mal schauen ob ich dazu komme den Patch von oben zu testen. Sollte eigentlich kein allzu großer Aufwand sein das PKGBUILD anzupassen um den Patch einzubauen und einen "crashenden Fall" habe ich hier lokal sowieso schon erzeugt.
-
Die Ubuntu-Version läuft hier jedenfalls - nochmal herzlichsten Dank, Seahawk!
-
Anbei mal ein PKGBUILD für Arch zum einfachen Testen. Wenn ich das gepatchte Modul installiert habe, dann läuft vdrnfofs so wie ich es erwarten würde. Also das kaputte Encoding wird durchgereicht und im File-Manager wird auch die übliche "Invalid Encoding"-Warnung beim Dateinamen angezeigt. Abspielen läuft trotzdem.
-
Jetzt sieht das aber deutlich besser aus
-
-
Mount-Parameter solltest du in der fstab nach Belieben setzen können.
Selbst wenn man das beim manuellen Skriptaufruf hinbekommt: Ich will zumindest Löschen evtl. noch nachrüsten und ab dann wäre ein erzwungenes "ro" hinderlich.
Jetzt mitmachen!
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!