2013年6月18日 星期二

Mounting a hard disk image including partitions using Linux


Mounting a hard disk image including partitions using Linux


A while ago I thought it would be a good idea to make a backup of my Linux server by just dumping the complete disk to a file. In retrospect, it would have been much easier had I just dumped the individual filesystems.
When I finally got around to using this backup, long after the 10GB disk had perished I realized that to use the loopback device to mount a filesystem it actually needs a filesystem to mount. What I had was a disk image, including partition table and individual partitions. To further complicate matters the data partition was also not the first partition inside this image.
For reference, I created this image using the Unix ‘dd’ tool:
# dd if=/dev/hda of=hda.img
30544113+0 records in
30544113+0 records out
# ls -lh
-rw-r--r-- 1 root    root  9.6G 2008-01-22 14:12 hda.img
I followed the instructions on http://www.trekweb.com/~jasonb/articles/linux_loopback.html to try and mount the partitions inside the disk image, but ran into two problems.
To mount a partition inside the disk image you need to calculate the offset of where the partition starts. You can use fdisk to show this information to you, but you need to specify the number of cylinders if you are using a disk image.
You then also need to multiply the start and end numbers with the calculated sectors to get a byte offset.
I found another tool more useful for this task, called parted. If you are using Ubuntu, you can install it with ‘apt-get install parted’
# parted hda.img
GNU Parted 1.7.1
Using /data/rabbit/disk_image/test2
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit
Unit?  [compact]? B
(parted) print
Disk /data/rabbit/disk_image/test2: 10262568959B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number  Start        End           Size         Type     File system  Flags
1      32256B       106928639B    106896384B   primary  ext3         boot
2      106928640B   1184440319B   1077511680B  primary  linux-swap
3      1184440320B  10256924159B  9072483840B  primary  ext3
(parted) quit
Now we have the offsets and we can use those to mount the filesystems using the loopback device:
#mount -o loop,ro,offset=32256 hda.img /mnt/rabbit
That mounted the first partition, the ‘boot’ partition, but this didn’t have the data on it that I was looking for. Lets try to mount partition number 3.
#umount /mnt/rabbit
#mount -o loop,ro,offset=1184440320 test2 /mnt/rabbit
#mount: wrong fs type, bad option, bad superblock on /dev/loop0,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail  or so
Oops, that doesn’t look right. According the article referred to above if you are using a util-linux below v2.12b then you cannot specify an offset higher than 32bits. I’m using util-inux 2.13 which shouldn’t have that problem, and besides, my offset is well below the 32bit limit.
The article also offers an alternative loopback implementation that supports mounting partitions within an image, but that requires patching and recompiling your kernel which I would rather not do.
Instead I decided to extra ct the filesystem from the image which would then allow me to mount it without specifying an offset.
Doing this is quite straightforward with ‘dd’. You need to give ‘dd’ a skip count, or, how far into the source to start copying, and a count, how much to copy.
Here you can either use the single byte offsets retrieved with parted or divide them by 512 and let ‘dd’ use 512 byte blocks. Copying just one byte at a time takes a very long time, so I suggest using a larger block size.
Here is the command I used to extract my filesystem. Skip is 2313360 (1184440320/512) and Count is 17719695 (9072483840/4)
#dd if=hda.img of=hda3.img bs=512 skip=2313360 count=17719695
17719695+0 records in
17719695+0 records out
9072483840 bytes (9.1 GB) copied, 485.679 seconds, 18.7 MB/s
After extracting the filesystem I was able to mount it without any problems.
# mount -o loop hda3.img /mnt/rabbit/
# df -h /mnt/rabbit
Filesystem            Size  Used Avail Use% Mounted on
/data/rabbit/image/hda3.img
8.4G  6.3G  1.7G  80% /mnt/rabbit

Loop-mounting partitions from a disk image

Loop-mounting partitions from a disk image
Update: it seems that kpartx pretty much does all of the below. Thanks to Faidon Liambotis for the pointer.
Every now and then, I have a disk image (as produced by catpv, or dd) and I need to access separate partitions. Unfortunately, the patch allowing partitions on loop devices to be accessed via their own device nodes does not appear to be in the latest (Debian) 2.6.18 kernels — the loop module does not have a max_part parameter, according to modinfo.
So this time I sat down to come up with a recipe on how to access the partitions, and after some arithmetic and much swearing at disk manufacturers, and especially the designers of the msdos partition table type, I think I have found the solution, and the urge to document it for posterity.
It's all about the -o parameter to losetup, which specifies how many bytes into the disk a given partition starts. Getting this number isn't straight forward. Well, it is, if you know how, which is why I am writing this.
Let's take a look at a partition table, with sectors as units:
$ /sbin/fdisk -lu disk.img
You must set cylinders.
You can do this from the extra functions menu.

Disk disk.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes

      Device Boot      Start         End      Blocks   Id  System
disk.imgp1   *          63       96389       48163+  83  Linux
disk.imgp2           96390     2056319      979965   82  Linux swap / Solaris
disk.imgp3         2056320    78140159    38041920    5  Extended
disk.imgp5         2056383     3052349      497983+  83  Linux
disk.imgp6         3052413    10859939     3903763+  83  Linux
disk.imgp7        10860003    68372639    28756318+  83  Linux
disk.imgp8        68372703    76180229     3903763+  83  Linux
disk.imgp9        76180293    78140159      979933+  83  Linux

The first few lines is fdisk complaining not being able to extract the number of cylinders, since it has to operate on a file which does not provide an ioctl interface.
The first important data are the units, which are stated to be 512 bytes per sector. We take note of this value as the factor for use in the next operation.
Let's say we want to access the 7th partition, which is 10860003 sectors into the disk, according to the fdisk output. We know that each sector is 512 bytes, so:
10860003 * 512 = 5560321536

Passing this number to losetup produces the desired result:
# losetup /dev/loop0 disk.img -o $((10860003 * 512))
# file -s /dev/loop0
/dev/loop0: Linux rev 1.0 ext3 filesystem data
# mount /dev/loop0 /mnt
[...]
# umount /mnt
# losetup -d /dev/loop0

If the partition really holds a normal filesystem, you can also let mount set up the loop device, and manage it automatically:
# mount -o loop,offset=$((10860003 * 512)) disk.img /mnt
[...]
# umount /mnt

And since there's aparently no means to automate the whole process for an entire disk, I hacked up plosetup. Enjoy:
# plosetup lapse.hda .
I: partition 1 of lapse.hda will become ./lapse.hda_p1 (/dev/loop0)...
I: plosetup: skipping partition 2 of type 82...
I: plosetup: skipping partition 3 of type 5...
I: partition 5 of lapse.hda will become ./lapse.hda_p5 (/dev/loop1)...
I: partition 6 of lapse.hda will become ./lapse.hda_p6 (/dev/loop2)...
I: partition 7 of lapse.hda will become ./lapse.hda_p7 (/dev/loop3)...
I: partition 8 of lapse.hda will become ./lapse.hda_p8 (/dev/loop4)...
I: partition 9 of lapse.hda will become ./lapse.hda_p9 (/dev/loop5)...
# ls -l
total 0
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p1 -> /dev/loop0
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p5 -> /dev/loop1
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p6 -> /dev/loop2
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p7 -> /dev/loop3
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p8 -> /dev/loop4
lrwxrwxrwx 1 root root 10 2006-10-20 13:25 lapse.hda_p9 -> /dev/loop5
# plosetup -c .
# ls -l
total 0

(this post is dedicated to Penny for no other reason than the tunes I am listening to right now)
NP: Fly My Pretties / The Return of Fly My Pretties
Update: Be careful about the $((...)) style arithmetic. dash manages to overflow at 32bit. zsh and bash seem to get it right. If in doubt, use perl or a calculator.

[GPO] 在Microsoft Active Directory (AD) 網域環境,新增Microsoft Edge群組原則管理

[GPO]  在 Microsoft Active Directory (AD) 網域環境, 新增Microsoft Edge群組原則管理 在還沒有被微軟強迫使用Edge前,對於一些老舊的網站,還可以使用IE。 因此在公司環境,之前有為IE和google chrome,寫入配合的...