Anu*_*nul 5 filesystems btrfs disk-image
我在 10G 图像文件中有一个大约 7G 的 btrfs 文件系统img.btrfs
(我使用 缩小了它btrfs fi resize -3G /mnt
)。如何找到文件系统的总大小(结束字节偏移量),以便缩小图像大小?即找出$SIZE
了
truncate -s $SIZE img.btrfs
Run Code Online (Sandbox Code Playgroud)
适用于图像文件内的任何其他文件系统的机制将是一个加分项。
注意:有一点做的工作是:
INITIAL=$(stat -c %s img.btrfs)
mount img.btrfs /mnt
btrfs fi resize -$NBYTES /mnt
umount /mnt
truncate -s $((INITIAL - NBYTES + 1024*1024)) img.btrfs
mount /img.btrfs /mnt
btrfs fi resize max /mnt
Run Code Online (Sandbox Code Playgroud)
即缩小 btrfs,将图像缩小一点(留下 1M 的开销),然后将 btrfs 增大到缩小图像所提供的最大值。
Annoyingly, btrfs filesystem show
returns an approximate value if the size isn't a multiple of 1MB. It also requires a loop device, btrfs filesystem show img.btrfs
doesn't work (as of Debian jessie). I can't find another btrfs
subcommand that would help.
But file img.btrfs
helpfully returns the desired size.
$ truncate -s 16684k /tmp/img.btrfs $ /sbin/mkfs.btrfs /tmp/img.btrfs SMALL VOLUME: forcing mixed metadata/data groups Btrfs v3.17 See http://btrfs.wiki.kernel.org for more information. Turning ON incompat feature 'mixed-bg': mixed data and metadata block groups Turning ON incompat feature 'extref': increased hardlink limit per file to 65536 Created a data/metadata chunk of size 1703936 failed to open /dev/btrfs-control skipping device registration: Permission denied fs created label (null) on /tmp/img.btrfs nodesize 4096 leafsize 4096 sectorsize 4096 size 16.29MiB $ truncate -s 32m /tmp/img.btrfs $ file /tmp/img.btrfs /tmp/img.btrfs: BTRFS Filesystem sectorsize 4096, nodesize 4096, leafsize 4096, UUID=61297945-d399-4fdc-ba9f-750ef9f9dfdb, 28672/17084416 bytes used, 1 devices
It directly reads the 8-byte little-endian value at offset 0x10070. If you don't want to parse the output of file
, you can extract it. The following POSIX snippet does the job¹:
size_hex=$(cat /tmp/img.btrfs | dd ibs=8 skip=8206 count=1 2>/dev/null | od -tx8 -An | tr abcdef ABCDEF | tr -dc 0-9ABCDEF)
[ ${#size_hex} -eq 16 ] &&
{ echo "ibase=16; $size_hex"; } | bc
Run Code Online (Sandbox Code Playgroud)
or in Perl:
</tmp/btrfs.img perl -e 'seek(STDIN, 0x10070, 0) or sysread(STDIN, $_, 0x10070) == 0x10070 or die "seek"; sysread(STDIN, $_, 8) == 8 or die "read"; print unpack("Q<", $_), "\n"'
Run Code Online (Sandbox Code Playgroud)
file
works for some other filesystem types, but that doesn't help much for scripts because the output isn't standardized. I can't think of a generic utility with a standard interface for all common filesystems, maybe some virtualization or forensics tool.
¹ Exercise: why is this a useful use of cat
?