Preliminary notes
- If you just want to
mount
the filesystem directly from the disk then see that other answer of mine. If you want toddrescue
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 (seeinfo ddrutility -n ddru_ntfsbitmap
). Make sure you don't startddru_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:
The
domain_mapfile
describes positions inside the whole device/dev/sdx
, not inside the partition (nor the filesystem). This is fine, since we needddrescue
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 theimage
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.
It wouldn't be that bad if the information about the offset was inside the
image
itself. Well,ddru_ntfsbitmap
is smart enough to createdomain_mapfile
that makes the laterddrescue
try to recover not only the desired filesystem, but also the partition table. In the best case the partition table would be copied into theimage
. 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.
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 byddrescue
(to be clear: the actual partition table does belong). Ourimage
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