VHD


VHD

VHD 结构是一种虚拟磁盘的实现方式,即通过文件来模拟物理磁盘的方式来存储数据。

VHD结构有2种实现方式:固定方式和动态方式。本文只讨论固定方式。

固定方式就是用真实大小的文件模拟同样大小的一个虚拟磁盘。

VHD 头部

VHD和其他文件不同,VHD其信息放在尾部,也就是最后一个扇区中。我们应当首先读取最后一个扇区的内容。

字段字节数说明
cookie8标识,应为conectix,用于判断VHD是否有效
features40: HD_NO_FEATURES
1: HD_TEMPORARY
2: HD_RESERVED
ff_version4VHD版本
data_offset8固定磁盘,总是0xFFFFFFFF。
timestamp4VHD的创建时间,指2000年1月1日00:00:00至今的秒数
crtr_app4创建者
crtr_ver4创建版本
crtr_os4创建者系统
orig_size8创建的虚拟磁盘大小,这个大小指虚拟出来的磁盘的可用寻址空间。
curr_size8用于vhd在线扩容后的最后大小表述,如果没有扩容,和orig_size相同。
geometry4VHD的C/H/S结构参数
柱面数2字节,磁头数1字节,扇区数1字节
type40: HD_TYPE_NONE
2: HD_TYPE_FIXED 固定磁盘
3: HD_TYPE_DYNAMIC 动态磁盘
4: HD_TYPE_DIFF 差异磁盘
checksum4本扇区的校验和
uuid16磁盘标识,在差异磁盘中,决定了VHD间的主从关系。
saved1是否在保存状态
hidden1VDI是否隐藏

VHD 写入

VHD文件规定读写需要针对磁道,读写必须要在某个磁道的开头处,然后读取n个磁道(n*512字节)。如果你的数据不够512的倍数,那么写入的时候需要将数据凑到512字节的倍数,不够的部分补0。

import datetime
import logging


class Vhd:
    def __init__(self, file_name):
        self.head = {}
        self.file_name = file_name
        self.f = open(self.file_name, 'rb+')
        self.head_info()

    def head_info(self):
        self.f.seek(-512, 2)
        self.head["cookie"] = self.f.read(8).decode()
        self.head["features"] = self.f.read(4)
        self.head["ff_version"] = self.f.read(4)
        self.head["data_offset"] = self.f.read(8)
        t = int.from_bytes(self.f.read(4))
        t = datetime.datetime(2000, 1, 1, 8) + datetime.timedelta(seconds=t)
        self.head["timestamp"] = t.strftime("%Y-%m-%d %H:%M:%S")
        self.head["crtr_app"] = self.f.read(4).decode()
        self.head["crtr_ver"] = self.f.read(4)
        self.head["crtr_os"] = self.f.read(4)
        self.head["orig_size"] = int.from_bytes(self.f.read(8))
        self.head["curr_size"] = int.from_bytes(self.f.read(8))
        cylinder = int.from_bytes(self.f.read(2))
        head = int.from_bytes(self.f.read(1))
        sector = int.from_bytes(self.f.read(1))
        self.head["geometry"] = (cylinder, head, sector)
        type_ = int.from_bytes(self.f.read(4))
        if type_ == 0:
            type_ = "HD_TYPE_NONE"
        elif type_ == 2:
            type_ = "HD_TYPE_FIXED"
        elif type_ == 3:
            type_ = "HD_TYPE_DYNAMIC"
        elif type_ == 4:
            type_ = "HD_TYPE_DIFF"
        self.head["type"] = type_
        self.head["checksum"] = self.f.read(4)
        self.head["uuid"] = self.f.read(16)
        self.head["saved"] = bool(int.from_bytes(self.f.read(1)))
        self.head["hidden"] = bool(int.from_bytes(self.f.read(1)))

    def __str__(self):
        return str(self.head)

    def write(self, bin_file, *, lba=None, cylinder=None, head=None, sector=None):
        if lba is None:
            lba = cylinder * self.head['geometry'][1] * self.head['geometry'][2] + head * self.head['geometry'][
                2] + sector - 1
        start_pos = lba * 512
        with open(bin_file, 'rb') as f:
            self.f.seek(-512, 2)
            safe = self.f.tell()
            f.seek(0, 2)
            write_file_length = f.tell()
            if start_pos + write_file_length > safe:
                raise Exception('No Enough Space')
            self.f.seek(start_pos, 0)
            f.seek(0, 0)
            while True:
                data = f.read(512)
                if not data:
                    break
                self.f.write(data)
        logging.info(f'file write successfully')

    def __del__(self):
        self.f.close()



声明:Hello World|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - VHD


我的朋友,理论是灰色的,而生活之树是常青的!