Large files on NTFS on FreeBSD.
Well, it seems its crappy software week all over again.
While trying to find out how to burn an .iso image on a DVD using only free(as in beer) software, I had interesting experiences with CD Burner XP on Windows, which simply ruined an empty disk in 37 seconds without even trying to write the actual data onto the disk, and some (patched) windows-cdrecord which spewed interesting error messages, and astonished me by interpreting the speed=
command line in a creative way (so 1 means 4, 10 means 8 and 16 means 17? interesting ;) - but at least it didn't ruin another blank disk.
Then I tried using FreeBSD. cdrecord from the ports tells me that the Author has completely lost it which means I would have to jump some hoops before I could have the holy grail of DVD support.
Well. Some more digging led me to growisofs from the dvd+rw-tools package which, despite its name, is able to just burn an iso image with the following easy command line
growisofs -dvd-compat -Z /dev/cd0=image.iso
It does however require device atapicam in your kernel config (see here in the FreeBSD Handbook for details).
This is where we finally touch the subject. Large Files on NTFS. The image was on my NTFS partition. And I was just assuming I could burn it directly. Well, I was wrong and so spent another blank disk on learning that the NTFS driver is not 64 bit clean. You just get the filesize modulo 4G. And yes, the problem is known but they didn't even bother to document it somewhere.
Well, some more searching led me to dimitry who tried to tackle that issue but got no help at all.
I updated the patch he wrote for FreeBSD-6_STABLE (had to fix one simple reject), but be warned, as he notes using mmap on such large files will lead to a panic (I didn't test that ;-). So just to be safe, I copied the file with
dd if=/dos/.../image.img bs=4M of=/home/sec/image.img
Because dd is guaranteed not to use mmap ;)
If you want/need to use the patch, here is how to you do it:
cd
fetch http://blogmal.42.org/patches/freebsd-ntfs-largefile/FreeBSD-6-ntfs-largefile.patch
cd /usr/src
parch ~/FreeBSD-6-ntfs-largfile.patch
cd sys/modules/ntfs
make
If you already used ntfs, be sure to unmount all ntfs volumes, and kldunload ntfs.ko before the final step:
kldload ./ntfs.ko
mount -t ntfs /dev/ad0s1 /dos
Happy large filing…
– Sec
P.S.: There relevant bug report kern/73514 indicates that a fix for this was committed to FreeBSD-current in November. Yay! I do hope it gets merged to -STABLE soon.
posted at: 05:02
| Category:
/patches
|
permanent link to this entry
|
1 comment
(
trackback)
Probleme mit Cryptoloop und Suse
Eigentlich gehört das in die Kategorie Das glaubt mir doch eh keiner
.
Gestern hat ein Kollege hier seinen Laptop unvorsichtigerweise lang genug ohne Strom stehen lassen, und plötzlich war er aus. Nunja, ärgerlich weil vermeidbar, aber an sich kein Problem, man hat ja schliesslich ein journaling Filesystem.
Denkste.
Beim Booten weigert sich das Teil hartnäckig die Filesysteme wieder zu mounten. Die erste Befürchtung, daß er die Passphrase vergessen hat, läßt sich noch recht einfach zerstreuen:
kiste:~# losetup -e twofish256 /dev/loop0 /data/crypt5
Password:
kiste:~# file -s /dev/loop0
/dev/sda2: Linux rev 1.0 ext3 filesystem data (needs journal recovery)
Lang hält die Freude nicht an, denn mounten lässt es sich nicht. Das Journal hat irgendwelche interessanten Fehler…
kiste:~# fsck /dev/loop0
fsck 1.34 (25-Jul-2003)
e2fsck 1.34 (25-Jul-2003)
Superblock has a bad ext3 journal (inode 8).
Clear<y>? yes
*** ext3 journal has been deleted - filesystem is now ext2 only ***
Superblock doesn't have has_journal flag, but has ext3 journal inode.
Clear<y>? yes
Und fährt dann dann fort, das FS komplett zu schreddern. Nicht gut.
Und wenn man es als ext2fs mounten will, bekommt man das im syslog:
Jan 17 15:13:30 kiste kernel: EXT2-fs: loop(7,0): \
couldn't mount because of unsupported optional features (4).
(Was ist denn das für eine Schizophrenie? Entweder optional, oder nicht!)
Unter FreeBSD hab ich dem ext2fs-kernelmodul mal zum Testen so gepatcht, daß es das Mounten trotzdem erlaubt, und siehe da, man sah einen Grossteil der Files. Leider konnte man aber nur einen kleinen Teil davon lesen…
Nun, mit debugfs kann man das journal zwar löschen, aber mounten kann mans nachher immer noch nicht. Damn. - Schauen wir uns nochmal genauer an, was fsck noch so alles sagt:
Inode count in superblock is 640002, should be 640000.
Fix<y>? yes
Hm. Strange. Ein Offset von 2 Inodes? Keine Ahnung wie sowas passieren kann…
/dev/loop0 was not cleanly unmounted, check forced.
Pass 1: Checking inodes, blocks, and sizes
Group 0's block bitmap at 10 conflicts with some other fs block.
Relocate<y>?
Irgendwie klingt das ungesund. Was ist da wohl passiert?
Naja, nachdem auch schon der inode count kaputt ist, habe ich mir mal den Superblock-Inhalt angeschaut:
kiste:~# debugfs /dev/loop0
debugfs 1.34 (25-Jul-2003)
debugfs: stats
[...]
Die Werte sahen eigentlich alle gut aus… bis auf das da:
Group 0: block bitmap at 10, inode bitmap at 3, inode table at 4
4 free blocks, 15959 free inodes, 2 used directories
Die block bitmap (ja, die über die der fsck meckert) ist at 10
. In den anderen Groups siehts so aus:
Group 1: block bitmap at 32770, inode bitmap at 32771, inode table at 32772
0 free blocks, 15793 free inodes, 85 used directories
Group 2: block bitmap at 65536, inode bitmap at 65537, inode table at 65538
0 free blocks, 15323 free inodes, 92 used directories
Da ist sie also genau immer eins vor der inode bitmap.
Da mir so langsam die Ideen ausgegangen sind, hab' ich mal ein bisschen in einem Hexdump des Filesystems rumgesucht:
kiste:~# dd if=/dev/loop0 bs=512 count=20 of=t
kiste:~# xxd <t >t.xxd
kiste:~# vim t.xxd
<such such, fündig bei 0×1000>
0001000: 0a00 0000 0300 0000 0400 0000 0400 573e ...........…W>
genau die 3 Zahlen der Group 0
von oben. Machen wir also aus dem 0a ein 02, und schreiben es zurück:
kiste:~# xxd -r <t.xxd >t.neu
kiste:~# dd if=t.neu bs=512 of=/dev/loop0 conv=notrunc
und schmeissen den fsck nochmal an. Der sagt jetzt:
Group 16's block bitmap at 524297 conflicts with some other fs block.
Relocate<y>?
Hm. debugfs sagt uns wieder:
Group 16: block bitmap at 524297, inode bitmap at 524289, inode table at 524290
10275 free blocks, 15858 free inodes, 6 used directories
dumpe2fs hat die gleiche Information, nur für unseren Fall schöner aufbereitet:
Group 16: (Blocks 524288-557055)
Block bitmap at 524297 (+9), Inode bitmap at 524289 (+1)
Inode table at 524290-524789 (+2)
beim Durchsehen, fällt einem nochmal das gleiche Problem in Group 32 auf:
Group 32: (Blocks 1048576-1081343)
Block bitmap at 1048586 (+10), Inode bitmap at 1048577 (+1)
Inode table at 1048578-1049077 (+2)
Ok, gleich nochmal in t.xxd rumspielen.
0001200: 0900 0800 0100 0800 0200 0800 2328 f23d ............#(.=
machen wir aus dem 09 ein 00 und
0001400: 0a00 1000 0100 1000 0200 1000 0000 363e ...........…6>
ändern wir das 0a in ein 00. Dann schreiben wir es (wie oben) zurück:
kiste:~# xxd -r <t.xxd >t.neu
kiste:~# dd if=t.neu bs=512 of=/dev/loop0 conv=notrunc
Aber leider selbst jetzt ist das Filesystem noch recht kaputt. Der Versuch mit debugfs rdump
Daten rauszukopieren erzeugt immernoch recht viele Fehler ;-/
Aber!
Ist euch was aufgefallen? Ja?
Die drei Stellen an denen wir was editiert haben sind 0×1000, 0×1200, 0×1400 - verdammt regelmässig, oder?
Schauen wir nochmal genauer auf die Änderungen:
War Soll
0×1000 0A 02
0×1200 09 00
0×1400 0A 00
Hm. Der Unterschied ist in allen drei Fällen ungefähr gleich groß. Schauen wir uns das binär an:
War Soll War XOR Soll
0×1000 1010b 0010b 1000b
0×1200 1001b 0000b 1001b
0×1400 1010b 0000b 1010b
He. Das sieht aus wie ein Zähler. Und 0×200 (512) ist genau eine übliche Blockgröße.
Ein paar prüfende Blicke in den Hexdump zeigen, daß in allen Blöcken die nur aus 0-Bytes bestehen, am Anfang genau die Blocknummer drinsteht. Dieser Verdacht reicht für einen Test. Schnell ein C-Programm zusammengehackt, das ein File in 512-Byte-Blöcken kopiert, und immer vorne die Blocknummer reinXORt.
Gut, ein kurzer Dämpfer, weil fread() auf dem Linux hier coredumpt weil das File größer als 2G ist, aber das läßt sich mit den passenden #defines hinbiegen.
Schnell den Ursprungszustand wieder herstellen:
kiste:~# dd if=t bs=512 of=/dev/loop0 conv=notrunc
kiste:~# losetup -d /dev/loop0
Das Programm mal drüberlaufen lassen:
kiste:~# gcc -o xorme -Wall xorme.c
kiste:~# ./xorme crypt5 crypt5.out
sector: 9c4000: err(eof?) while reading
Und sehen was rauskommt:
kiste:~# losetup /dev/loop0 crypt5.out
kiste:~# fsck /dev/loop0
fsck 1.34 (25-Jul-2003)
e2fsck 1.34 (25-Jul-2003)
/dev/loop0: recovering journal
/dev/loop0: clean, 18990/640000 files, 1205770/1280000 blocks
Yay!
Ein Test mit mount liefert auch das befriedigende Ergebniss, daß alle Dateien wieder vorhanden, und auch lesbar sind. Das macht einen glücklichen Kollegen, ein paar Tafeln Schokolade für mich, und wieder was über die Interna von ext2fs/ext3fs gelernt.
Bleibt eigentlich nur noch die Frage, wie das passieren konnte. Der aktuelle Verdacht ist, daß durch irgendein SuSe-Update sich was an dem crypto-loop Treiber geändert hat und das erst durch den Reboot (und damit verbundene reattach/remount) aufgefallen ist. Wenn irgendeiner der Leser da mehr Ahnung hat, wäre ich für einen Hinweis natürlich dankbar.
– Sec
Update: Das Problem ist SuSE bekannt und dort beschrieben. (Dank an Nick)
Seufz
posted at: 10:48
| Category:
/rev-eng
|
permanent link to this entry
|
1 comment
(
trackback)