Quantcast
Channel: User Kamil Maciorowski - Super User
Viewing all articles
Browse latest Browse all 656

Answer by Kamil Maciorowski for How can I efficiently use ddrescue to read NTFS partition from hard drive with damaged GPT?

$
0
0

Preliminary notes

  • If you just want to mount the filesystem directly from the disk then see that other answer of mine. If you want to ddrescue the filesystem then keep reading.
  • Most commands in this answer need to be run as root. For brevity I don't add sudo everywhere.
  • ddru_ntfsbitmap creates few files and uses them when you start it again in the same directory (see info ddrutility -n ddru_ntfsbitmap). Make sure you don't start ddru_ntfsbitmap with old files present, especially if you change the device you want to rescue data from (like when switching from the "simplest way" to the "better way" described below). When in doubt, start anew in an empty directory.
  • If you want to copy to a regular file, it's best to create and keep the file in a filesystem that supports sparse files.

Simplest way

The simplest (although IMO not the best) way is to use the --inputoffset option of ddru_ntfsbitmap:

-i, --inputoffset <bytes>
Set input offset (partition offset)

(source)

To get the offset in bytes you need to multiply the logical sector size by the number of the start sector of the partition. You mentioned testdisk and I assume it can show you the start sector (I think old versions were crazy and showed CHS, not LBA; I guess fdisk or gdisk may help, if the backup GPT is fine).

E.g. if the logical sector size is 512 bytes and the partition starts at the sector number 24680, then the command shall be:

ddru_ntfsbitmap --inputoffset "$((512*24680))" /dev/sdx domain_mapfile

And later you use the domain_mapfile with ddrescue:

ddrescue --domain-mapfile domain_mapfile /dev/sdx image rescue_mapfile

You can write to a block device instead of to image. In any case there are disadvantages and caveats:

  1. The domain_mapfile describes positions inside the whole device /dev/sdx, not inside the partition (nor the filesystem). This is fine, since we need ddrescue to read from /dev/sdx anyway (because this is the only special file we have, there are no /dev/sdx1, /dev/sdx2; if they were there, then there would be no problem in the first place, right?). But this also means that the image will be a (partial) image of the whole device, so the filesystem will be there with the offset.

    • If you write to a block device, the device shall be large enough to hold the filesystem that starts at the original offset. E.g. if originally the filesystem is 2 GiB, but it starts at the offset of 1800 GiB, then you need a block device with at least 1802 GiB.
  2. It wouldn't be that bad if the information about the offset was inside the image itself. Well, ddru_ntfsbitmap is smart enough to create domain_mapfile that makes the later ddrescue try to recover not only the desired filesystem, but also the partition table. In the best case the partition table would be copied into the image. In your case the partition table is (partially) unreadable and you know it, so straining the hardware by trying to read it is not the best idea.

    • If you write to a block device, its old partition table may remain if the partition table of the source device cannot be read.
  3. In general the partition table might be copied into the image. In general the logical sector size might be 4096 bytes and the partition table would use such sectors in this case. The OS gets the information about the logical sector size via ioctl from the hardware, this information does not belong to the content you can read by ddrescue (to be clear: the actual partition table does belong). Our image will not contain this information.

    In general tools you may want to use later to get data from the image may assume logical sector size of 512 bytes, they may use some heuristics or they may allow you to specify it. It may happen the wrong value is used and thus the partition table is misinterpreted (or not found).

    • If you write to a block device then its logical sector size will matter. In case of mismatch you will need to rebuild the partition table. If the logical sector size of the source is 512 and the logical sector size of destination is 4096 and the original start sector is unfortunate (not divisible by 8) then you won't be able to build a partition table that matches the actual location of the filesystem.

For these reasons it's better to copy only the partition (or rather the filesystem; these are different concepts) to a regular file (like our image) or to a block device, so the filesystem starts without any offset in the file or the device.


Better way

If the partition table was fine, you would have /dev/sdx1, /dev/sdx2 etc. You would use ddru_ntfsbitmap and ddrescue on one of these files to get an image of the right partition, not of the whole device. Your partition table is not fine and thus you don't have the special files associated with the partitions. Here I will show you how to "extract" a partition anyway.

We will need the number of the start sector of the partition and (optionally) the number of sectors in the partition. If you know the start and the end sector then you can calculate the number of sectors as end-start+1. The tool we will use expects values in bytes, to we need to multiply by the logical sector size.

E.g. if the logical sector size is 512 bytes and the partition starts at the sector number 24680 and the partition ends at the sector number 18245847, then it takes 18221168 sectors and you can use this:

losetup --read-only --find --show --offset "$((512*24680))" --sizelimit "$((512*18221168))" /dev/sdx

The command, if successful, will print you the pathname of a loop device, e.g. /dev/loop91. The loop device is the partition. Confirm there is NTFS there (file -skr /dev/loop91) and copy the loop device with ddru_ntfsbitmap and ddrescue, as if you were copying /dev/sdx2 or so.

I suppose we could omit --sizelimit and its option-argument, the procedure would work anyway. This is because the filesystem knows its size, ddru_ntfsbitmap would not let ddrescue read beyond the filesystem anyway.

ddru_ntfsbitmap /dev/loop91 domain_mapfile \&& ddrescue --domain-mapfile domain_mapfile /dev/loop91 image rescue_mapfile

You can write to a block device instead of image. If to a block device then it's advised to use a partition rather than a whole device (you need to create a partition beforehand, it should be large enough to hold the filesystem).

When you no longer need the loop device, remove it:

losetup --detach /dev/loop91

Now, unless there have been read errors that severely crippled the copy, you are almost ready to even mount the filesystem stored inside the image without any offset. The following command may succeed or it may fail:

mount -o ro image /some/mountpoint

It may fail with an error message like Failed to read last sector (18221151).

  • If you write to a block device (partition) instead of to image, and if the block device was large enough in the first place then there should be no such error.

If mount does fail with such error, it means the tail of the filesystem was not used (in terms of the NTFS bitmap file), ddru_ntfsbitmap allowed ddrescue to skip it, the image is too small. You should correct the size of the image, using the number the error message gave you plus one (because sectors are numbered from zero):

truncate --size="$((512*18221152))" image

I guess the number in the error message always refers to 512-byte sectors, but I'm not sure. Another way to get the right number is to use file image to see how big the filesystem actually is. When in doubt, use the size of the partition we have read the filesystem from (18221168 512-byte sectors in our example). The partition may be bigger than the filesystem (usually only slightly bigger), the point is in a sane setup it's not smaller, so we can safely use its size for our image.

Hopefully the filesystem in which you store the image supports sparse files and thus the file does not take space in vain.

The image is ready. You can mount it or whatever.

# mounting read-onlymount -o ro image /some/mountpoint

Viewing all articles
Browse latest Browse all 656

Trending Articles