How can I copy three partitions of my disk with a specific beginning and ending using dd?
first of all, here's how:
First do almost as you did before, but no subtraction - and add one to the count.
dd count=132552704 </dev/sda >img
Next print the partition table at a
sed
process which can screen out the ones which you're removing.sed
will write ad
elete command to a secondfdisk
which has opened yourimg
file for every partition from sda4 and on.fdisk -l img | sed -e'/sda4 /,$id' -e'g;$aw' | fdisk img
There is no 3. You're done.
secondly, here's why:
A Partial Success...
I'm pretty sure your command almost worked, but I'm willing to bet that it worked better than you think.
I expect that when you say it copied all of sda you believe that because an
fdisk -l
of that image indicated all of the partitions were included within. Based on thedd
command in your question, though, provided/dev/sda
's sector size is the fairly standard 512 bytes (and therefore identical todd
's default blocksize) then you should have copied everything from byte 0 of/dev/sda
only through to all but the last 2k sectors of/dev/sda3
.
About Sectors...
You can see below where the
fdisk
output reports on Units. That is the size of each sector thatfdisk
reports on. A disk sector might be 4096-bytes - if it is a very recently manufactured disk and handles the Advanced Format sector-size - otherwise it is very rare to find a disk not partitioned on a standard logical 512-byte sector-size.This is how
fdisk
'sman
page puts it:-u
,--units[=unit]
- When listing partition tables, show sizes in sectors or in cylinders. The default is to show sizes in sectors. For backward compatibility, it is possible to use the option without the unit argument - then the default is used. Note that the optional unit argument cannot be separated from the
-u
option by a space, the correct form is for example-u=cylinders
.
- When listing partition tables, show sizes in sectors or in cylinders. The default is to show sizes in sectors. For backward compatibility, it is possible to use the option without the unit argument - then the default is used. Note that the optional unit argument cannot be separated from the
There's more on this here.
And something about
dd
, too...dd
cannot silently lose data. In fact, if a short read occurs,dd
is specified to be very vocal about it:A partial input block is one for which
read()
returned less than the input block size. A partial output block is one that was written with fewer bytes than specified by the output block size......when there is at least one truncated block, the number of truncated blocks shall be written to standard error...
"%u truncated %s\n"
,<number of truncated blocks>
,"record[s]"
Block i/o...
- But anyway, that actually can't happen with block-device i/o. It's what makes a block-device a block-device - there's an extra layer (sometimes several) of buffered protection for block-devices as opposed to character devices. It is this distinction which enables POSIX to guarantee
lseek()
for files existing on block-devices - it's a very basic principle of blocked i/o.
- But anyway, that actually can't happen with block-device i/o. It's what makes a block-device a block-device - there's an extra layer (sometimes several) of buffered protection for block-devices as opposed to character devices. It is this distinction which enables POSIX to guarantee
To sum up...
- And so you have copied all of your device up to the point you specified, but the thing is, the first 2k sectors of
/dev/sda
will contain its entire partition table, and as such you would have copied said partition table to your image, and so anfdisk -l
of your image would report for all partitions of/dev/sda
, whether or not the data for those partitions actually resides within that image-file. You can, instead, of course, justcat
the separate data partitions separately into separate image files if you like - but in that case you lose the partition table entirely. All you really have to do is delete the partitions which you did not copy, and make sure you copy all of those you do.
- And so you have copied all of your device up to the point you specified, but the thing is, the first 2k sectors of
third, here's how I know:
This will create an 4G
./img
file full of NULs.</dev/zero >./img \ dd ibs=8k obs=8kx1b count=1kx1b
524288+0 records in 1024+0 records out 4294967296 bytes (4.3 GB) copied, 3.53287 s, 1.2 GB/s
This will partition
./img
to match your disk up to the first three partitions but on a 1/16th scale:(set "$((p=0))" 28266495 27 \ 28268544 28473343 2\\n7 \ 28473344 132552703 3\\n7 while [ "$#" -ge "$((p+=1))" ] do printf "n\np\n$p\n%.0d\n%d\nt\n%b\n" \ "$(($1/16))" "$(($2/16))" "$3" shift 3 done; echo w )| fdisk ./img >/dev/null
And so now we can look at it.
fdisk -l ./img
Disk ./img: 4 GiB, 4294967296 bytes, 8388608 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x5659b81c Device Boot Start End Sectors Size Id Type ./img1 2048 1766655 1764608 861.6M 27 Hidden NTFS WinRE ./img2 1766784 1779583 12800 6.3M 7 HPFS/NTFS/exFAT ./img3 1779584 8284543 6504960 3.1G 7 HPFS/NTFS/exFAT
I'll also put some actual filesystems and files on the three partitions.
sudo sh -c ' trap "$1" 0 cd /tmp; mkdir -p mnt for p in "$(losetup --show -Pf "$0")p"* do mkfs.vfat "$p" mount "$p" mnt echo "my part# is ${p##*p}" \ >./mnt/"part${p##*p}" sync; umount mnt done' "$PWD/img" 'losetup -D'
Here are the byte offsets for where it all wound up...
grep -Ebao '(my[^0-9]*|PART)[123]' <./img
2826272:PART1 2830336:my part# is 1 904606240:PART2 904624640:my part# is 2 917656608:PART3 917660672:my part# is 3
But did you notice that fdisk
was perfectly happy to report on the partitions' sizes before ever we formatted them with filesystems? This is because the partition table lies at the very head of the disk - it's only a layout and nothing more. None of the partitions need actually exist to be reported. They're only logically mapped out within the first 1M of ./img
. Watch:
Let's try getting only the first two partitions off of
./img
...<./img >./img2 dd count=1779583
1779583+0 records in 1779583+0 records out 911146496 bytes (911 MB) copied, 1.84985 s, 493 MB/s
We'll
grep
it again...grep -Ebao '(my[^0-9]*|PART)[123]' <./img2
2826272:PART1 2830336:my part# is 1 904606240:PART2 904624640:my part# is 2
And get an
fdisk
report...fdisk -l ./img2
Disk ./img2: 869 MiB, 911146496 bytes, 1779583 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xcbcab4d8 Device Boot Start End Sectors Size Id Type ./img2p1 2048 1766655 1764608 861.6M 27 Hidden NTFS WinRE ./img2p2 1766784 1779583 12800 6.3M 7 HPFS/NTFS/exFAT ./img2p3 1779584 8284543 6504960 3.1G 7 HPFS/NTFS/exFAT
Now that is curious. fdisk
still seems to believe there's a third partition extending as far out as 4G for a disk which it also seems to believe is only 869M in size!
Probably we should remove that third partition from the partition table.
printf %s\\n d 3 w | fdisk ./img2 >/dev/null
And now lets see if we can mount the partitions we copied and if our files remain in tact...
sudo sh -c ' trap "$1" 0 cd /tmp; mkdir -p mnt for p in "$(losetup --show -Pf "$0")p"* do mount "$p" mnt grep . /dev/null ./mnt/* umount mnt done' "$PWD/img2" 'losetup -D'
./mnt/part1:my part# is 1 ./mnt/part2:my part# is 2
Apparently it's not impossible.