📄 vdiskplain.cpp
字号:
/* VDiskPlain.cpp Plain disk class Copyright (c) 2003 Ken Kato*/#include "vdkbase.h"#include "vdkutil.h"#include "cowdisk.h"#include "VDiskPlain.h"#include "VDiskExtRaw.h"#include "VDiskUtil.h"#include "VDiskFile.h"//// Constructor -- set default members//VDiskPlain::VDiskPlain(){ m_nVMwareVer = 2; m_nHardwareVer = COWD_HARDWARE_VMWARE2;}//// Destructor//VDiskPlain::~VDiskPlain(){}//// Initialize instance from a VMware 2.x plain disk descriptor file//VDKSTAT VDiskPlain::Initialize(PCHAR pPath){ VDiskFile file; CHAR buf[MAX_PATH + 40]; CHAR path[MAX_PATH]; PCHAR current; VDKSTAT ret; PVOID cbparams[2]; // // parameter check // if (!pPath || !*pPath) { return VDK_PARAM; } // // store path // if ((ret = StorePath(pPath)) != VDK_OK) { return ret; } // // open file // if ((ret = file.Open(pPath)) != VDK_OK) { return ret; } // // initialize members // ClrFlag(VDISK_FLAG_CHILD); cbparams[0] = pPath; while ((ret = file.ReadText(buf, sizeof(buf), NULL)) == VDK_OK) { // // replace tabs with blanks // current = buf; while (*current) { if (*current == '\t' || *current == '\n') { *current = ' '; } current++; } // // remove trailing blanks // while (current > buf && *(--current) == ' ') { *current = '\0'; } // // skip leading blanks // current = buf; while (*current == ' ') { current++; } // // blank line? // if (!*current) { continue; } cbparams[1] = current; // // start parsing // if (!VdkCmpNoCaseN(current, "ACCESS ", 7)) { VDiskExtRaw *ext; PCHAR top, tail; ULONG capacity; ULONG offset; CHAR delim; HANDLE hFile; // // search path field // top = current + 7; while (*top == ' ') { top++; } if (*top == '\"') { delim = '\"'; top++; } else { delim = ' '; } tail = top; while (*tail && *tail != delim) { tail++; } if (!*tail || tail - top >= MAX_PATH) { if (!VDiskCallBack(VDISK_CB_DESC_BADENTRY, cbparams)) { return VDK_CANCEL; } SetFlag(VDISK_FLAG_DIRTY); continue; } if ((isalpha(*top) && *(top + 1) == ':') || *top == PATH_SEPARATOR_CHAR || *top == ALT_SEPARATOR_CHAR) { SetFlag(VDISK_FLAG_ABSPATH); } else { ClrFlag(VDISK_FLAG_ABSPATH); } VdkCopyMem(path, top, tail - top); path[tail - top] = '\0'; // // search offset field // top = tail + 1; while (*top == ' ') { top++; } if (isdigit(*top)) { offset = atol(top); } else { offset = VDiskCallBack( VDISK_CB_DESC_OFFSET, cbparams); if (offset == (ULONG)-1) { return VDK_DATA; } SetFlag(VDISK_FLAG_DIRTY); } // // search capacity field // while (isdigit(*top)) { top++; } while (*top == ' ') { top++; } capacity = atol(top); if (!capacity) { capacity = VDiskCallBack( VDISK_CB_DESC_CAPACITY, cbparams); if (!capacity) { return VDK_DATA; } SetFlag(VDISK_FLAG_DIRTY); } // // create an extent object // ext = new VDiskExtRaw; if (ext == NULL) { return VdkLastError(); } ret = AddExtent(ext); if (ret != VDK_OK) { delete ext; return ret; } ret = VDiskSearchFile(&hFile, path, m_pPath); if (ret != VDK_OK) { return ret; } ret = ext->SetPath(path); if (ret != VDK_OK) { return ret; } ret = ext->Load(hFile); VdkCloseFile(hFile); if (ret != VDK_OK) { return ret; } ext->SetCapacity(capacity); ext->SetStartOffset(offset); } else if (!VdkCmpNoCaseN(current, "CYLINDERS ", 10)) { m_nCylinders = atol(current + 10); if (!m_nCylinders) { m_nCylinders = VDiskCallBack( VDISK_CB_DESC_GEOMETRY, cbparams); if (!m_nCylinders) { return VDK_DATA; } SetFlag(VDISK_FLAG_DIRTY); } } else if (!VdkCmpNoCaseN(current, "HEADS ", 6)) { m_nTracks = atol(current + 6); if (!m_nTracks) { m_nTracks = VDiskCallBack( VDISK_CB_DESC_GEOMETRY, cbparams); if (!m_nTracks) { return VDK_DATA; } SetFlag(VDISK_FLAG_DIRTY); } } else if (!VdkCmpNoCaseN(current, "SECTORS ", 8)) { m_nSectors = atol(current + 8); if (!m_nSectors) { m_nSectors = VDiskCallBack( VDISK_CB_DESC_GEOMETRY, cbparams); if (!m_nSectors) { return VDK_DATA; } SetFlag(VDISK_FLAG_DIRTY); } } else if (!VdkCmpNoCaseN(current, "DRIVETYPE ", 10)) { PCHAR p = current + 10; while (*p == ' ') { p++; } if (!VdkCmpNoCase(p, "scsi")) { m_nController = VDISK_CONTROLLER_SCSI; } else if (!VdkCmpNoCase(p, "ide")) { m_nController = VDISK_CONTROLLER_IDE; } else { m_nController = VDiskCallBack( VDISK_CB_CONTROLLER, cbparams); if (m_nController != VDISK_CONTROLLER_SCSI && m_nController != VDISK_CONTROLLER_IDE) { return VDK_CANCEL; } SetFlag(VDISK_FLAG_DIRTY); } } else if (!VdkCmpNoCaseN(current, "#vm|TOOLSVERSION ", 17)) { m_nVMwareVer = 3; m_nToolsFlag = atol(current + 17); } else if (!VdkCmpNoCaseN(current, "#vm|VERSION ", 12)) { m_nVMwareVer = 3; m_nHardwareVer = atol(current + 12); if (m_nHardwareVer != COWD_HARDWARE_VMWARE2 && m_nHardwareVer != COWD_HARDWARE_VMWARE3 && m_nHardwareVer != COWD_HARDWARE_VMWARE4) { m_nHardwareVer = VDiskCallBack( VDISK_CB_HARDWAREVER, cbparams); if (m_nHardwareVer != COWD_HARDWARE_VMWARE2 && m_nHardwareVer != COWD_HARDWARE_VMWARE3 && m_nHardwareVer != COWD_HARDWARE_VMWARE4) { return VDK_CANCEL; } SetFlag(VDISK_FLAG_DIRTY); } } else if (*current != '#') { if (!VDiskCallBack(VDISK_CB_DESC_BADENTRY, cbparams)) { return VDK_CANCEL; } SetFlag(VDISK_FLAG_DIRTY); } } file.Close(); if (ret == VDK_EOF) { ret = Check(); } return ret;}//// Initialize as a child disk//VDKSTAT VDiskPlain::InitChild( ULONG flags, PCHAR pPath, ULONG version, VDisk *parent){ UNREFERENCED_PARAMETER(flags); UNREFERENCED_PARAMETER(pPath); UNREFERENCED_PARAMETER(version); UNREFERENCED_PARAMETER(parent); // // Plain Disk cannot be a child // return VDK_FUNCTION;}//// Check paramters//VDKSTAT VDiskPlain::Check(){ CHAR path[MAX_PATH]; PVOID cbparams[3]; ULONG idx; VDKSTAT ret; FullPath(path); // // At least one extent must be present // if (!m_nExtents) { cbparams[0] = path; VDiskCallBack(VDISK_CB_EMPTY_IMAGE, cbparams); return VDK_DATA; } // // Check extent offset // m_nCapacity = 0; for (idx = 0; idx < m_nExtents; idx++) { VDiskExtRaw *ext = (VDiskExtRaw *)m_ppExtents[idx]; if (ext->GetStartOffset() != m_nCapacity) { cbparams[0] = ext->GetFullPath(); cbparams[1] = (PVOID)ext->GetStartOffset(); cbparams[2] = (PVOID)m_nCapacity; // // file range conflict or there is a hole // if (!VDiskCallBack(VDISK_CB_EXT_OFFSET, cbparams)) { return VDK_CANCEL; } ext->SetStartOffset(m_nCapacity); SetFlag(VDISK_FLAG_DIRTY); } if ((ret = ext->Check()) != VDK_OK) { return ret; } if (ext->IsModified()) { SetFlag(VDISK_FLAG_DIRTY); } m_nCapacity += ext->GetCapacity(); } cbparams[0] = path; // // Check geometry // /* if (m_nCylinders * m_nTracks * m_nSectors != m_nCapacity) { cbparams[1] = (PVOID)m_nCapacity; cbparams[2] = (PVOID)total_size; if (!VDiskCallBack(VDISK_CB_EXT_CAPACITY, cbparams)) { return VDK_DATA; } m_nCapacity = total_size; SetGeometry(); SetFlag(VDISK_FLAG_DIRTY); for (idx = 0; idx < m_nExtents; idx++) { if (total_size < m_ppExtents[idx]->GetCapacity()) { m_ppExtents[idx]->SetCapacity(total_size); total_size = 0; } else { total_size -= m_ppExtents[idx]->GetCapacity(); } } } */ // // Any bad parameter? // if (m_nFlags & VDISK_FLAG_DIRTY) { if (VDiskCallBack(VDISK_CB_CONFIRM_FIX, cbparams)) { ret = WriteDescriptor(FALSE, FALSE); if (ret != VDK_OK) { return ret; } for (idx = 0; idx < m_nExtents; idx++) { ret = m_ppExtents[idx]->Update(); if (ret != VDK_OK) { return ret; } } } ClrFlag(VDISK_FLAG_DIRTY); } return VDK_OK;}//// create plain disk descriptor file and extent files//VDKSTAT VDiskPlain::Create(ULONG flags){ ULONG idx; VDKSTAT ret; if (!m_nExtents || !m_ppExtents || !m_ppExtents[0]) { return VDK_FUNCTION; } // // create each extent file // for (idx = 0; idx < m_nExtents; idx++) { ret = m_ppExtents[idx]->Create(flags); if (ret != VDK_OK) { return ret; } } // // create the description file // ret = WriteDescriptor(TRUE, (flags & VDISK_CREATE_FORCE)); return ret;}//// Write plain disk descriptor file//VDKSTAT VDiskPlain::WriteDescriptor(BOOL create, BOOL force){ CHAR buf[MAX_PATH + 30]; ULONG idx; ULONG path_len; HANDLE hFile = INVALID_HANDLE_VALUE; VDKSTAT ret = VDK_OK; // // create/open the description file // FullPath(buf); if (create) { ret = VdkCreateFile(&hFile, buf, force); } else { ret = VdkOpenFile(&hFile, buf, strlen(buf), FALSE); } if (ret != VDK_OK) { return ret; } // // create header entries // buf[0] = '\0'; if (m_nVMwareVer == 3) { // // additional entry for VMware 3.x // sprintf(buf, "#vm|TOOLSVERSION %lu\n" "#vm|VERSION %lu\n", m_nToolsFlag, m_nHardwareVer); } sprintf(buf + strlen(buf), "DRIVETYPE %s\n" "CYLINDERS %6lu\n" "HEADS %6lu\n" "SECTORS %6lu\n", m_nController == VDISK_CONTROLLER_IDE ? "ide" : "scsi", m_nCylinders, m_nTracks, m_nSectors); ret = VdkWriteFileAt(hFile, -1, buf, strlen(buf), NULL); if (ret != VDK_OK) { goto cleanup; } // // create each extent entry // path_len = strlen(m_pPath); for (idx = 0; idx < m_nExtents; idx++) { VDiskExtRaw *ext; PCHAR path; ext = (VDiskExtRaw *)m_ppExtents[idx]; path = ext->GetFullPath(); if (!(m_nFlags & VDISK_FLAG_ABSPATH) && !VdkCmpNoCaseN(m_pPath, path, path_len)) { path = ext->GetFileName(); } sprintf(buf, "ACCESS \"%s\" %lu %lu\n", path, ext->GetStartOffset(), ext->GetCapacity()); ret = VdkWriteFileAt(hFile, -1, buf, strlen(buf), NULL); if (ret != VDK_OK) { goto cleanup; } }cleanup: if (hFile != INVALID_HANDLE_VALUE) { VdkCloseFile(hFile); } return ret;}//// Create a new extent object for this instance//VDiskExt *VDiskPlain::NewExtent(){ return new VDiskExtRaw;}//// Get path for each extent files//void VDiskPlain::GetExtentPath( PCHAR pPath, ULONG nSeq){ sprintf(pPath, "%s" PATH_SEPARATOR_STR "%s%lu.dat", m_pPath, m_pBody, nSeq + 1);}//// Set default geometry values//void VDiskPlain::SetGeometry(){ if (m_nController == VDISK_CONTROLLER_IDE) { m_nTracks = COWD1_TRACKS_IDE_PLAIN; m_nSectors = COWD1_SECTORS_IDE_PLAIN; } else { if (m_nCapacity <= COWD_SECTORS_SCSI_1023M * COWD_TRACKS_SCSI_1023M * 1023) { m_nSectors = COWD_SECTORS_SCSI_1023M; m_nTracks = COWD_TRACKS_SCSI_1023M; } else if (m_nCapacity <= COWD_SECTORS_SCSI_2046M * COWD_TRACKS_SCSI_2046M * 1023) { m_nSectors = COWD_SECTORS_SCSI_2046M; m_nTracks = COWD_TRACKS_SCSI_2046M; } else { m_nSectors = COWD_SECTORS_SCSI_LARGE; m_nTracks = COWD_TRACKS_SCSI_LARGE; } } m_nCylinders = m_nCapacity / (m_nSectors * m_nTracks);}//// Returns default extent size//ULONG VDiskPlain::DefaultExtSize(){ ULONG ext_size = COWD1_MAX_EXTENT_PLAIN; if (m_nCapacity > ext_size) { // // In VMware 2.x plain disks, all extents are the same size // ULONG extents = (m_nCapacity + ext_size - 1) / ext_size; ext_size = (m_nCapacity + extents - 1) / extents; } return ext_size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -