Итак.
Внезапно...
Внезапно система, на которой была спасена не одна дюжина миров и собрана дюжина Миров споткнулась на ровном месте, дёрнула 250Гным винтом и ушла в ребут, утянув вместе с собой в небытие UFS раздел с сорцами и торрентами.
Ступор... Single mode...
Беглый осмотр места проишествия показал: тип раздела не определяется как UFS, хотя тень раздела в виде метки /dev/gpt/work присутсутствует.
Хватаю первый попавшийся под руку микроскоп:
Код: Выделить всё
# fdisk -p ad2
# /dev/ad2
g c484518 h16 s63
p 1 0xee 1 488395054
Всё в порядке и соответствует спецификации.
Следующая тулза, которая первой приходит на ум - Testdisk. Проверяю:
Код: Выделить всё
# testdisk -> No Log -> Disk /dev/ad2 -> [EFI GPT] -> [Analyse]
TestDisk 6.11, Data Recovery Utility, April 2009
Christophe GRENIER <grenier@cgsecurity.org>
http://www.cgsecurity.org
Disk /dev/ad2 - 250 GB / 232 GiB - CHS 484518 16 63
Partition Start End Size in sectors
P Solaris /home 66 488395053 488394988

ЗЫ: если testdisk сообщает про "write protected disk", значит нужно вколоть стимулятор:
Код: Выделить всё
# sysctl kern.geom.label.debug=16
Перво-наперво надо потренироваться на кошках:
Код: Выделить всё
dd if=/dev/zero of=/flash/d64m.raw bs=1M count=64
mdconfig -a -t vnode -f /home/pablo/flash/d64m.raw -o async -u 0
gpart create -s gpt md0
gpart add -t freebsd md0
gpart modify -i 1 -l test md0
newfs -o time /dev/md0s1
mount /dev/gpt/test /mnt/tmp/
Код: Выделить всё
# portinstall sysutils/scan_ffs
Код: Выделить всё
$ scan_ffs -vs /dev/md0s1
block 128 id 4c34a367,be2d1218 size 32751
block 160 id 4c34a367,be2d1218 size 32751
ufs2 at 0 size 32751 mount /mnt/tmp time Wed Jul 7 22:55:19 2010
Код: Выделить всё
$ scan_ffs -vs /dev/md0
block 162 id 4c34a367,be2d1218 size 32751 <== адреса блоков смещены на 34 блока. Superblock по адресу 0x14400
block 194 id 4c34a367,be2d1218 size 32751 <== хвост Суперблока по адресу 0x18400
ufs2 at 34 size 32751 mount /mnt/tmp time Wed Jul 7 22:55:19 2010 <== UFS2 находится со смещеним 34 от начала диска
Код: Выделить всё
$ scan_ffs -vs /dev/ad0
block 290 id 4b3a8ba7,7d0b56cf size 262144 <== superblock /, смещён на 128 блоков от начала диска, на размер boot-part'а
block 322 id 4b3a8ba7,7d0b56cf size 262144 <== magic
ufs2 at 162 size 262144 mount / time Wed Dec 30 05:07:19 2009
Запускаю, медитирую:
Код: Выделить всё
> scan_ffs -v -l /dev/ad2
block 160 id 4a8f5548,f603e83e size 122098747 <== а вот нужное, с id=4a8f5548,f603e83e и size=122098747
block 162 id 0,0 size 122098747 <== здесь должен быть superblock
block 194 id 4a8f5548,f603e83e size 122098747 <== magic для UFS2 = 19 01 54 19
X: 488394988 34 4.2BSD 2048 16384 0 # <== строка для bsdlabel, которую подсказывает scan_ffs. Пока форматить повременю...
block 12098 id 0,0 size 122098747 <== тоже непонятно-что
block 239602 id 4b08bce0,6b8b4567 size 901552 <== какой-то старый хвост
block 376546 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 1 (если я не путаю нумерацию)
block 752898 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 2
block 1129250 id 4a8f5548,f603e83e size 122098747 <== Cylinder Group 3
... <scipped>
Код: Выделить всё
> scan_ffs -v -b 0 -e 163 /dev/ad2
block 160 id 4a8f5548,f603e83e size 122098747 <== правильная запись в неправильном месте
block 162 id 0,0 size 122098747 <== неправильная запись в правильном месте
block 194 id 4a8f5548,f603e83e size 122098747 <== magic
ufs2 at 34 size 122098747 mount time Sat Aug 22 09:17:44 2009 <== точка последнего монтирования не определилась
Если считать от начала диска, то надо прибавить, соответственно, 0x4400 (34 blocks): адрес суперблока=0x14400, адрес корня файловой системы=0xA4400
Диагноз: в конкретном моём случае всё указывало на то, что суперблок (живой и здоровый) находится не на своём месте (testdisk всё-таки сумел записать на диск правильный superblock в неправильное место).
Небольшое отступление: здесь можно было выбрать иной путь: взять backup GPT header из последнего блока диска
Код: Выделить всё
# dd if=/dev/ad2 of=ad2_lbaB bs=512 count=1 iseek=488395054; chexedit ad2_lbaB
00000000 45 46 49 20 50 41 52 54 00 00 01 00 5C 00 00 00 6F DD A8 4B 00 00 00 00 2E 51 1C 1D EFI PART....\...o..K.....Q..
0000001C 00 00 00 00 01 00 00 00 00 00 00 00 22 00 00 00 00 00 00 00 0D 51 1C 1D 00 00 00 00 ............"........Q......
00000038 EE 23 D1 D7 89 FB 43 CF AC 3D 3F 7C E8 1D 4A 53 0E 51 1C 1D 00 00 00 00 80 00 00 00 .#....C..=?|..JS.Q..........
00000054 80 00 00 00 22 F8 63 99 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ....".c.....................
и вписать во 2-ой блок диска, но... Это было слишком сложно для меня и я поступил просто, но решительно:
Код: Выделить всё
# gpart destroy ad2 <== мёртвой водой
# gpart create -s GPT ad2 <== живой водой
# gpart add -t freebsd-ufs ad2 <== определил
# gpart modify -i 1 -l work ad2 <== пометил
Код: Выделить всё
# gpart show -l ad2
=> 34 488394988 ad2 GPT (233G)
34 488394988 1 work (233G)
Код: Выделить всё
# dd if=/dev/ad2 of=ad2_superblock skip=194 bs=512 count=4
# dd if=/dev/zero of=/dev/ad2 bs=512 count=6 oseek=160
# dd if=ad2_superblock of=/dev/ad2 bs=512 count=4 oseek=162
Код: Выделить всё
# scan_ffs /dev/ad2
ufs2 at 34 size 122098747 mount time Sat Aug 22 09:17:44 2009
Код: Выделить всё
# fsdb -d /dev/gpt/work
** /dev/gpt/work
Editing file system `/dev/gpt/work'
Last Mounted on
current inode: directory
I=2 MODE=40755 SIZE=512
BTIME=Aug 22 09:17:44 2009 [0 nsec]
MTIME=Dec 11 22:05:25 2009 [0 nsec]
CTIME=Dec 11 22:05:25 2009 [0 nsec]
ATIME=Jun 13 00:26:01 2010 [0 nsec]
OWNER=root GRP=wheel LINKCNT=8 FLAGS=0 BLKCNT=4 GEN=206f2c6
fsdb (inum: 2)> ls
command `ls
'
slot 0 ino 2 reclen 12: directory, `.'
slot 1 ino 2 reclen 12: directory, `..'
slot 2 ino 3 reclen 16: directory, `.snap'
slot 3 ino 24541184 reclen 16: directory, `backup'
slot 4 ino 6571008 reclen 16: directory, `torrent'
slot 5 ino 21879808 reclen 16: directory, `public'
slot 6 ino 21903360 reclen 20: directory, `lost+found'
slot 7 ino 17805312 reclen 404: directory, `conf'
fsdb (inum: 2)> quit
Код: Выделить всё
# diff <(ffsinfo -g 0 -i 2 -l 0x1 /dev/gpt/work) <(ffsinfo -g -1 -i 2 -l 0x1 /dev/gpt/work)
Затаив дыхание, запустил:
Код: Выделить всё
# fsck -y -t ufs /dev/gpt/work

Отступать некуда, монтирую:
Код: Выделить всё
# mount -o noatime /dev/gpt/work /work/
# ll /work
total 32
drwxr-xr-x 8 root wheel - 512 11 дек 2009 ./
drwxr-xr-x 23 root wheel - 512 15 июл 12:02 ../
drwxrwx--- 2 root operator - 512 18 сен 2009 .snap/
drwxr-xr-x 8 root wheel - 512 12 июн 21:28 backup/
drwxr-xr-x 3 root wheel - 512 14 дек 2009 conf/
drwx------ 6 root wheel - 16896 22 авг 2009 lost+found/
drwxrwxr-x 2 pablo pablo - 512 14 июн 13:37 public/
drwxr-xr-x 9 pablo pablo - 512 28 фев 13:39 torrent/

И последнее наведение гламурного глянца - зачистка хвостов NTFS, boot record которой начинается с адреса 0x7E00(=32256) и тянется примерно до 0x8B75(=40448), т.е., общим размером 8192:
Код: Выделить всё
# dd if=/dev/zero of=/dev/ad2 oseek=63 bs=512 count=16
Радостный возглас !$@#
Холодный Guiness 1,2,3...
Занавес...
Небольшой ИТОГО:
- Для более-менее надёжной очистки диска от предыдущих разделов, надо обнулять 65,5 Кбайт в начале и в конце диска. Потом будет проще выковыривать.
- Сохранять расклад. Сохранять тем же dd'ом те же самые 65,5 Кбайт начала и конца диска. Чтоб было от чего плясать, в случае чего.
- GUID для Unix File System (UFS) partition вот такой 516E7CB6-6ECF-11D6-8FF8-00022D09712B, но первые три группы цифр идут в обратном порядке,
поэтому на диске они видятся вот так:
Код: Выделить всё
B6 7C 6E 51 CF 6E D6 11 8F F8 00 02 2D 09 71 2B
Использованные программы: c dd_rescue и ddrescue лично у меня не срослось. Пытался сделать образ диска, но скорость копирования была менее 1 Мб/с.
С dd тоже не срослось - образ писал на внешний USB, смонтированный fusefs-ntfs'ом и система не справлялась. Пока сижу смотрю, копируется. Ушёл спать - всё терминулось. Больше 92 Гб не смог скопировать - бросил эту затею.
Sleuthkit - могутный пакет, в пару к нему идёт Autopsy, перловый Веб-ГУЙ, особенно хорош для начинающих. Одно "НО" - работает только с образами диском (в моём случае не стали работать с /dev/ad2p1).
С ним у меня тоже не срослось, ввиду отсутствия полноценного образа. Хотя образ можно разбивать на части и грузить списком.
HEX-редакторы: lfhex - требует что-то из QT4, ghex - требует Gnoma, судя по всему, всё и сразу. Поскольку я сижу под XFCE4, ни QT4 ни Gnome у меня нет, поэтому отказался. Для любителей VI могу порекомендовать bvi (binary vi), полный аналог vi.
hexedit, chexedit - простые консольные, работают на ncurses, примерно одинаково функциональны. Я остановился на chexedit.
Пришлось много конвертировать hex-dec. Не придумал ничего лучшего, кроме пары алиасов:
Код: Выделить всё
alias dec='printf "%d\n" $1'
alias hex='printf "0x%x\n" $1'