Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Как узнать, какому файлу принадлежит сектор диска?

#linux #ntfs #поиск_программ #ddrescue


При помощи ddrescue создан образ диска. К нему есть карта, что не удалось скопировать.
Начинается вот так:

# Rescue Logfile. Created by GNU ddrescue version 1.17
# Command line: ddrescue -v -d --max-retries=1 --cluster-size=3 /dev/sdb2 d.img d.log
# current_pos  current_status
0xA7459CBA00     +
#      pos        size  status
0x00000000  0x52C15CAC00  +
0x52C15CAC00  0x00000400  -
0x52C15CB000  0x00011600  +


Насколько я понимаю, это означает, что 0x400 байт начиная с 0x52C15CAC00 не удалось
прочитать. Как понять, какие именно файлы повреждены? Файловая система NTFS.
    


Ответы

Ответ 1



как пишут здесь, нужно разделить номер блока на размер кластера, используемого данной файловой системой, и перевести результат в десятичную систему счисления. размер кластера: $ sudo ntfsinfo -m раздел | grep -i 'cluster size' Cluster Size: 4096 в шестнадцатиричной это будет: $ echo 'obase=16;4096' | bc 1000 делим номер из вопроса (0x52C15CAC00) на 1000 и получаем результат в десятичной системе счисления: $ echo 'ibase=16;52C15CAC00/1000' | bc 86775242 узнаём, что за файл(ы) располагаются в этом кластере (пример вывода команды взят из вышеупомянутой инструкции): $ sudo ntfscluster -c 86775242 раздел Searching for cluster 9369 Inode 89381 /Windows/System32/atidxx64.dll/$DATA

Ответ 2



В линуксе можно использовать следующее решение: filename=d.img logname=d.log clsz=$(sudo ntfsinfo -m -f $filename 2>/dev/null | grep 'Cluster Size' | \ sed -r "s/.*:/obase=16;/" | bc) for r in $(cat $logname | grep '-' | grep -v 'ddrescue' | \ sed -r "s/0x(\w+)\s+0x(\w+)\s+.*/\1\/$clsz; (\1+\2)\/$clsz/;1s/^/ibase=16\n" | \ bc | tr '\n' '-' | sed -r 's/(\w+-\w+)-/\1\n/g' | uniq | tr '\n' ' ' | \ sed -r 's/-(\w+) \1\b//g' | sed -r 's/ /\n/g' | \ sed -r 's/(\w+)-(\w+)/\1;\2;\2+1;/' | bc | tr '\n' '-' | \ sed -r 's/(\w+-\w+-\w+)-/\1 /g' | sed -r 's/-\w+-(\w+) \1//g' | \ sed -r 's/(-\w+)-\w+/\1/g'); \ do sudo ntfscluster -f -c $r $filename 2>/dev/null; done Замечу, что надо предварительно выполнить любую команду sudo, чтобы последняя команда не съелась в качестве пароля. Тогда на остальные команды пароль запрашиваться не будет и всё будет работать. Существенный минус этого решения - то, что для каждого диапазона кластеров снова сканируется файловая система, т. е. работает очень медленно. Теперь поясню, что же здесь происходит. Сначала определим размер кластера Информацию о диске можно получить при помощи ntfsinfo. Опция -f нужна чтобы образ не ставился на проверку с просьбой перезагрузиться дважды. Перенаправление ошибок в /dev/null чтобы избавиться от WARNING: Dirty volume mount was forced by the 'force' mount option. sudo ntfsinfo -m -f d.img 2>/dev/null Выберем отсюда строку с информацией о размере кластера: ... | grep 'Cluster Size' Достанем из неё число и переведём в 16ричную систему счисления: ... | sed -r "s/.*:/obase=16;/" | bc Сохраним в переменную: clsz=$(...) Команда целиком: clsz=$(sudo ntfsinfo -m -f d.img 2>/dev/null | grep 'Cluster Size' | \ sed -r "s/.*:/obase=16;/" | bc) Вероятно, получится значение 1000. Теперь определим диапазоны кластеров Выберем из карты все плохие куски (содержат - и не являются строкой с самой командой): cat d.log | grep '-' | grep -v 'ddrescue' Получится нечто такое: 0x52C15CAC00 0x00000400 - 0x52C15DC600 0x00000200 - 0xA74593D600 0x00000200 - 0xA74593DA00 0x00000600 - 0xA74593E600 0x00000200 - 0xA745945000 0x00000400 - 0xA745945600 0x00000200 - 0xA745945C00 0x00000400 - 0xA745947600 0x00000200 - 0xA7459C3200 0x00000C00 - 0xA7459CB000 0x00000200 - 0xA7459CB400 0x00000200 - 0xA7459CB800 0x00000400 - Преобразуем в формулы для вычисления номеров кластеров в 16ричной системе счисления: ... | sed -r "s/0x(\w+)\s+0x(\w+)\s+.*/\1\/$clsz; (\1+\2)\/$clsz/;1s/^/ibase=16\n/" ibase=16; 52C15CAC00/1000; (52C15CAC00+00000400)/1000; ibase=A; ibase=16; 52C15DC600/1000; (52C15DC600+00000200)/1000; ibase=A; ibase=16; A74593D600/1000; (A74593D600+00000200)/1000; ibase=A; ibase=16; A74593DA00/1000; (A74593DA00+00000600)/1000; ibase=A; ibase=16; A74593E600/1000; (A74593E600+00000200)/1000; ibase=A; ibase=16; A745945000/1000; (A745945000+00000400)/1000; ibase=A; ibase=16; A745945600/1000; (A745945600+00000200)/1000; ibase=A; ibase=16; A745945C00/1000; (A745945C00+00000400)/1000; ibase=A; ibase=16; A745947600/1000; (A745947600+00000200)/1000; ibase=A; ibase=16; A7459C3200/1000; (A7459C3200+00000C00)/1000; ibase=A; ibase=16; A7459CB000/1000; (A7459CB000+00000200)/1000; ibase=A; ibase=16; A7459CB400/1000; (A7459CB400+00000200)/1000; ibase=A; ibase=16; A7459CB800/1000; (A7459CB800+00000400)/1000; ibase=A; И вычислим ... | bc 86775242 86775243 86775260 86775260 175397181 175397181 175397181 175397182 175397182 175397182 175397189 175397189 175397189 175397189 175397189 175397190 175397191 175397191 175397315 175397315 175397323 175397323 175397323 175397323 175397323 175397323 К сожалению, числа получились на разных строках - объединяем их через дефис, затем каждый второй дефис заменяем переводом строки, затем уберём дубликаты строк: ... | tr '\n' '-' | sed -r 's/(\w+-\w+)-/\1\n/g' | uniq 86775242-86775243 86775260-86775260 175397181-175397181 175397181-175397182 175397182-175397182 175397189-175397189 175397189-175397190 175397191-175397191 175397315-175397315 175397323-175397323 Объединим последовательные цепочки, если конечный кластер первой совпадает с начальным следующей. Для этого объединим строки через пробел и поудаляем -число такое-же-число\b. У меня sed не съел \d, поэтому я использовал \w. После замены вернём на место переводы строк. ... | tr '\n' ' ' | sed -r 's/-(\w+) \1\b//g' | sed -r 's/ /\n/g' 86775242-86775243 86775260-86775260 175397181-175397182 175397189-175397190 175397191-175397191 175397315-175397315 175397323-175397323 Приготовимся посчитать номер следующего за концом кластера: ... | sed -r 's/(\w+)-(\w+)/\1;\2;\2+1;/' 86775242;86775243;86775243+1; 86775260;86775260;86775260+1; 175397181;175397182;175397182+1; 175397189;175397190;175397190+1; 175397191;175397191;175397191+1; 175397315;175397315;175397315+1; 175397323;175397323;175397323+1; И вычислим это: ... | bc 86775242 86775243 86775244 86775260 86775260 86775261 175397181 175397182 175397183 175397189 175397190 175397191 175397191 175397191 175397192 175397315 175397315 175397316 175397323 175397323 175397324 По аналогии с прошлым разом, объединяем строки через дефис, а каждый третий дефоис заменяем пробелом: ... | tr '\n' '-' | sed -r 's/(\w+-\w+-\w+)-/\1 /g' Объединяем цепочки, где начальный кластер следующий совпадает со следующим за конечным кластером предыдущей: ... | sed -r 's/-\w+-(\w+) \1//g' 86775242-86775243-86775244 86775260-86775260-86775261 175397181-175397182-175397183 175397189-175397191-175397192 175397315-175397315-175397316 175397323-175397323-175397324 Убираем лишнюю информацию о следующем кластере: ... | sed -r 's/(-\w+)-\w+/\1/g' 86775242-86775243 86775260-86775260 175397181-175397182 175397189-175397191 175397315-175397315 175397323-175397323 Команда целиком: cat d.log | grep '-' | grep -v 'ddrescue' | \ sed -r "s/0x(\w+)\s+0x(\w+)\s+.*/\1\/$clsz; (\1+\2)\/$clsz/;1s/^ibase=16\n/" | \ bc | tr '\n' '-' | sed -r 's/(\w+-\w+)-/\1\n/g' | uniq | tr '\n' ' ' | \ sed -r 's/-(\w+) \1\b//g' | sed -r 's/ /\n/g' | \ sed -r 's/(\w+)-(\w+)/\1;\2;\2+1;/' | bc | tr '\n' '-' | \ sed -r 's/(\w+-\w+-\w+)-/\1 /g' | sed -r 's/-\w+-(\w+) \1//g' | \ sed -r 's/(-\w+)-\w+/\1/g' Используем список для поиска файлов: Оборачиваем получившуюся выше конструкцию в качестве набора для цикла for: for r in $(...); do echo $r; done Ну и наконец меняем echo $r на нечто полезное: sudo ntfscluster -f -c $r d.img 2>/dev/null В итоге получается интересующий нас список файлов вместе с указанием кластеров.

Комментариев нет:

Отправить комментарий