通过布尔 OR 合并两个二进制图像文件(ddrescue 输出文件名错误)

通过布尔 OR 合并两个二进制图像文件(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 的一个很好的第一个练习,我从来没有抽出时间来学习它!尽管如此,如果已经存在某些东西,就不要特别想重新发明轮子。不太注重性能。

更新:(如果这是回复答案的错误位置,我深表歉意。“评论”选项似乎允许的字符太少,所以我在这里回复!)

我还尝试过使用 '--fill-mode=?' 进行 ddrescue作为上述问题的解决方案,但没有成功。这就是我所做的:

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  |................|
*
...

我在 IDTa.img 中查找了 001da800:

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
)

(我使用了子 shell,因此变量会随之消失,而主 shell 不受影响。)

现在让该工具分析您的第一张图像并找出哪些扇区可能未获救:

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.isoIDTa.img.相反,如果您有一个块设备,那么您工作之前的“随机”内容ddrescue会干扰并破坏结果(因此,首先解决不同大小的潜在问题是没有意义的,这truncate没有帮助)。
  • 我在尝试拯救一个人时复制了你的错误后测试了该程序片状装置

相关内容