Объединить два двоичных файла образа с помощью логического ИЛИ (ошибка имени выходного файла ddrescue)

Объединить два двоичных файла образа с помощью логического ИЛИ (ошибка имени выходного файла ddrescue)

Я допустил глупую ошибку, указав неправильное имя выходного файла при возобновлении работы ddrescue. Вот что произошло:

ddrescue -b 2048 -d -v /dev/sr1 IDTa.img IDTa.ddrescue.log 

Затем компьютер завис, и я по ошибке продолжил работу со следующим текстом:

ddrescue -b 2048 -d -v /dev/sr1 IDTa.iso IDTa.ddrescue.log

Я так понимаю, что оба файла изображений изначально будут обнулены, поэтому предполагаю, что если бы я выполнил логическое ИЛИ для обоих файлов, то результат был бы таким, какой вывел бы ddrescue, если бы я не допустил ошибку?

Файлы не являются продолжением друг друга (какКак объединить два образа ddrescue?), поскольку я уже запускал его ddrescue -nранее, что завершилось успешно. т. е. IDTa.img содержит большую часть данных, IDTa.iso содержит разбросанные блоки со всего изображения (и эти блоки будут равны нулю в IDTa.img).

Есть ли простой способ CLI сделать это? Я, вероятно, мог бы сделать это на C, но я очень заржавел! Также это может быть хорошим первым упражнением в Python, который я так и не изучил! Тем не менее, не особо хочу изобретать велосипед, если что-то уже существует. Не слишком заморачиваюсь по поводу производительности.

Обновлять:(извините, если это не то место, где можно разместить ответ на ответ. Похоже, опция «комментарий» допускает слишком мало символов, поэтому я отвечу здесь!)

Я также пробовал ddrescue с '--fill-mode=?' как решение вышеизложенного, но это не сработало. Вот что я сделал:

ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img IDTa.img.log
cp IDTa.img IDTa.img.backup
ddrescue '--fill-mode=?' -b 2048 -v IDTa.iso IDTa.img IDTa.img.log 

Для проверки я нашел первую позицию, в которой есть данные IDTa.iso:

hexdump -C IDTa.iso |less

результат был следующим:

00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001da800  00 00 01 ba 21 00 79 f3  09 80 10 69 00 00 01 e0  |....!.y....i....|
...
001db000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
...

Я посмотрел 001da800 в IDTa.img:

hexdump -C IDTa.img |less
/001da800

Выход:

001da800  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
001db000  00 00 01 ba 21 00 7b 00  bf 80 10 69 00 00 01 e0  |....!.{....i....|
...

Итак, данные в позиции 001da800 не скопировались из файла IDTa.iso в IDTa.img?

Проверка IDTa.img.log:

# Mapfile. Created by GNU ddrescue version 1.22
# Command line: ddrescue --fill-mode=? -b 2048 -v IDTa.iso IDTa.img IDTa.img.log
# Start time:   2021-06-28 13:52:39
# Current time: 2021-06-28 13:52:46
# Finished
# current_pos  current_status  current_pass
0x299F2000     +               1
#      pos        size  status
0x00000000  0x00008000  ?
0x00008000  0x001D2800  +
0x001DA800  0x00000800  ?
0x001DB000  0x00049000  +
...

и проверка реальности:

diff -q IDTa.img IDTa.img.backup

не возвращает никакой разницы.

Обновление 2:

@Kamil отредактировал решение (см. ниже), удалив --fill-mode=?аргумент. Кажется, работает!

решение1

Я думаю, это можно сделать с ddrescueсамим собой. Вам нужно --generate-mode.

При ddrescueвызове с опцией --generate-modeон работает в "режиме генерации", который отличается от "режима спасения" по умолчанию. То есть в "режиме генерации" ddrescueничего не спасает. Он только пытается сгенерировать mapfileдля последующего использования.

[…]

ddrescueможет в некоторых случаях генерировать приблизительный mapfile, из infileи (частичную) копию в outfile, которая почти так же хороша, как точная mapfile. Это делается просто путем предположения, что сектора, содержащие все нули, не были спасены.

[…]

ddrescue --generate-mode infile outfile mapfile

(источник)

Сделайте копии двух образов, на всякий случай. Если ваша файловая система поддерживает CoW-copy, то используйте cp --reflink=alwaysдля каждого образа, чтобы сделать копии практически мгновенно.

Вам нужно убедиться, что оба изображения имеют одинаковый размер. Если одно из них меньше, то его следует увеличить, т.е. добавить нули (возможно, редкие нули). Этот код сделает это автоматически ( truncateобязательно):

( f1=IDTa.img
  f2=IDTa.iso
  s1="$(wc -c <"$f1")"
  s2="$(wc -c <"$f2")"
  if [ "$s2" -gt "$s1" ]; then
    truncate -s "$s2" "$f1"
  else
    truncate -s "$s1" "$f2"
  fi
)

(Я использовал подоболочку, поэтому переменные исчезают вместе с ней, а основная оболочка остается нетронутой.)

Теперь позвольте инструменту проанализировать ваше первое изображение и выяснить, какие сектора, вероятно, не были восстановлены:

ddrescue --generate-mode -b 2048 -v /dev/sr1 IDTa.img new_mapfile

Обратите внимание new_mapfile, что это новый файл,нетваш IDTa.ddrescue.log. Не трогай IDTa.ddrescue.log.

После new_mapfileгенерации строки в нем должны показывать статус +или ?, в зависимости от того, считался ли соответствующий фрагмент «спасенным» или «неиспытанным».

Теперь вы хотите заполнить якобы "непроверенный" блок IDTa.imgданными из IDTa.iso. Следующая команда изменит IDTa.img.

Спасите якобы «неиспытанный» блок, IDTa.imgпрочитав данные из IDTa.iso:

ddrescue -b 2048 -v IDTa.iso IDTa.img new_mapfile

Теперь измененное IDTa.imgвместе с нетронутым IDTa.ddrescue.logдолжно быть так же хорошо, как если бы вы не совершили ошибку.

Примечания:

  • Может случиться так, что некоторые сектора, содержащие все нули, были фактически спасены. --generate-modeклассифицирует их как ?. Они будут заполнены данными, взятыми из IDTa.iso"напрасно". Это не имеет значения для конечного результата, потому что они все нули и в этом другом файле.
  • Результат должен быть таким же, если вы поменяете местами IDTa.isoи IDTa.imgво всей процедуре (но имейте в виду, если вы сделаете это, то результат будет в IDTa.iso). Так что есть выбор. С --generate-modeя бы использовал файл, от которого ожидаю меньше секторов, содержащих все нули, потому что это должно минимизировать объем работы для последней команды.
  • Метод работает для обычных файлов IDTa.isoи IDTa.img. Если вместо любого из них у вас было блочное устройство, его «случайное» содержимое, оставшееся до начала работы, ddrescueбудет мешать и портить результат (поэтому нет смысла решать потенциальную проблему с разными размерами изначально, где truncateэто не помогает).
  • Я проверил процедуру, повторив вашу ошибку при попытке спастиненадежное устройство.

Связанный контент