📄 volume.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// Volume.cpp
//
// Implementation of class Volume.
//////////////////////////////////////////////////////////////////////////////
// $Id: Volume.cpp,v 1.5 1999/02/13 04:24:35 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#include <vtoolscp.h>
#include "Required.h"
#include "UtilityFunctions.h"
#include "CPGPdiskDrv.h"
#include "Globals.h"
#include "Volume.h"
///////////////////////////////////////
// Class Volume public member functions
///////////////////////////////////////
// The Class Volume constructor.
Volume::Volume()
{
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = kInvalidDrive;
mAttachedToLocalVol = FALSE;
mBBlock = NULL;
mPDcb = NULL;
mVolumeReq.isInUse = FALSE;
}
// The Volume destructor unmounted the volume if was mounted by us.
Volume::~Volume()
{
DualErr derr;
if (Mounted())
{
if (AttachedToLocalVolume())
{
DetachLocalVolume();
}
else
{
derr = Unmount();
pgpAssert(derr.IsntError());
}
}
}
// Mounted returns TRUE if the volume is mounted, FALSE if not.
PGPBoolean
Volume::Mounted()
{
return (mMountState == kVol_Mounted);
}
// Unmounted returns TRUE if the volume is unmounted, FALSE if not.
PGPBoolean
Volume::Unmounted()
{
return (mMountState == kVol_Unmounted);
}
// HasOpenFiles returns TRUE if the volume has open files, FALSE otherwise.
PGPBoolean
Volume::HasOpenFiles()
{
DualErr derr;
PGPBoolean hasOpenFiles;
pgpAssert(Mounted());
derr = Driver->HasOpenFiles(mDrive, &hasOpenFiles);
if (derr.IsntError())
return hasOpenFiles;
else
return TRUE;
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// read/write access, FALSE otherwise.
PGPBoolean
Volume::LockedForReadWrite()
{
return (Mounted() && (mLockState == kLock_ReadWrite));
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// format access, FALSE otherwise.
PGPBoolean
Volume::LockedForFormat()
{
return (Mounted() && (mLockState == kLock_Format));
}
// AttachedToLocalVolume returns TRUE if the Volume object is attached to a
// local volume, FALSE if not.
PGPBoolean
Volume::AttachedToLocalVolume()
{
return mAttachedToLocalVol;
}
// GetDrive returns the drive number of the volume.
PGPUInt8
Volume::GetDrive()
{
pgpAssert(Mounted());
return mDrive;
}
// GetBlockSize returns the block size of the volume.
PGPUInt16
Volume::GetBlockSize()
{
pgpAssert(Mounted());
pgpAssertAddrValid(mPDcb, DCB);
return ExtractBlockSize(mPDcb);
}
// GetTotalBlocks returns the total number of blocks on the volume.
PGPUInt64
Volume::GetTotalBlocks()
{
pgpAssert(Mounted());
pgpAssertAddrValid(mPDcb, DCB);
return MakeQWord(mPDcb->DCB_actual_sector_cnt[0],
mPDcb->DCB_actual_sector_cnt[0]);
}
// GetDcb returns a pointer to the DCB.
PDCB
Volume::GetDcb()
{
pgpAssert(Mounted());
pgpAssertAddrValid(mPDcb, DCB);
return mPDcb;
}
// GetDevParams16 will fill out the elements of DevParams16 structure for the
// mounted Volume by reading directly from the boot block.
DualErr
Volume::GetDevParams16(DevParams16 *dp16)
{
DualErr derr;
PBootSector16 pBS16;
pgpAssertAddrValid(dp16, DevParams16);
pgpAssertAddrValid(mBBlock, PGPUInt8);
pgpAssert(Mounted());
derr = Read(mBBlock, 0, 1);
pBS16 = (PBootSector16) mBBlock;
if (derr.IsntError())
{
pgpClearMemory(dp16, sizeof(DevParams16));
dp16->dpDevType = 0x05; // we are a hard disk
dp16->dpDevAttr = 1; // we are not removable
dp16->dpCylinders = (PGPUInt16) mPDcb->DCB_actual_cyl_cnt;
dp16->dpMediaType = pBS16->bsMedia;
dp16->dpBytesPerSec = pBS16->bsBytesPerSec;
dp16->dpSecPerClust = pBS16->bsSecPerClust;
dp16->dpResSectors = pBS16->bsResSectors;
dp16->dpFats = pBS16->bsFats;
dp16->dpRootDirEnts = pBS16->bsRootDirEnts;
dp16->dpSectors = pBS16->bsSectors;
dp16->dpMedia = pBS16->bsMedia;
dp16->dpFatSecs = pBS16->bsFatSecs;
dp16->dpSecPerTrack = pBS16->bsSecPerTrack;
dp16->dpHeads = pBS16->bsHeads;
dp16->dpHiddenSecs = pBS16->bsHiddenSecs;
dp16->dpHugeSectors = pBS16->bsHugeSectors;
}
return derr;
}
// GetDevParams32 will fill out the elements of DevParams32 structure for the
// mounted Volume by reading directly from the boot block.
DualErr
Volume::GetDevParams32(DevParams32 *dp32)
{
DualErr derr;
PBootSector32 pBS32;
pgpAssert(Mounted());
pgpAssertAddrValid(dp32, DevParams32);
pgpAssertAddrValid(mBBlock, PGPUInt8);
derr = Read(mBBlock, 0, 1);
pBS32 = (PBootSector32) mBBlock;
if (derr.IsntError())
{
pgpClearMemory(dp32, sizeof(DevParams32));
dp32->dpDevType = 0x05; // we are a hard disk
dp32->dpDevAttr = 1; // we are not removable
dp32->dpCylinders = (PGPUInt16) mPDcb->DCB_actual_cyl_cnt;
dp32->dpMediaType = pBS32->bsMedia;
dp32->dpBytesPerSector = pBS32->bsBytesPerSec;
dp32->dpSectorsPerClust = pBS32->bsSecPerClust;
dp32->dpReservedSectors = pBS32->bsResSectors;
dp32->dpNumberOfFats = pBS32->bsFats;
dp32->dpRootEntries = pBS32->bsRootDirEnts;
dp32->dpTotalSectors = pBS32->bsSectors;
dp32->dpMediaDescriptor = pBS32->bsMedia;
dp32->dpSectorsPerFat = pBS32->bsFatSecs;
dp32->dpSectorsPerTrack = pBS32->bsSecPerTrack;
dp32->dpHeads = pBS32->bsHeads;
dp32->dpHiddenSectors = pBS32->bsHiddenSecs;
dp32->dpBigTotalSectors = pBS32->bsHugeSectors;
dp32->dpBigSectorsPerFat = pBS32->bsBigSectorsPerFat;
dp32->dpExtFlags = pBS32->bsExtFlags;
dp32->dpFS_Version = pBS32->bsFS_Version;
dp32->dpRootDirStrtClus = pBS32->bsRootDirStrtClus;
dp32->dpFsInfoSec = pBS32->bsFsInfoSec;
dp32->dpBkUpBootSec = pBS32->bsBkUpBootSec;
}
return derr;
}
// GetMediaId fills in a MID structure with information about the volume.
DualErr
Volume::GetMediaId(MID *pMid)
{
DualErr derr;
PGPBoolean foundRecognizedFileSys = FALSE;
pgpAssertAddrValid(pMid, MID);
pgpAssert(Mounted());
pgpAssertAddrValid(mBBlock, PGPUInt8);
derr = Read(mBBlock, 0, 1);
if (derr.IsntError())
{
LPSTR fsStr;
pMid->midInfoLevel = 0;
fsStr = (LPSTR) mBBlock + kFat12Offset;
if (!strncmp(fsStr, "FAT12", 5)) // is it a FAT12 drive?
{
PBootSector12 pBS12 = (PBootSector12) mBBlock;
foundRecognizedFileSys = TRUE;
pMid->midSerialNum = pBS12->bsVolumeId;
strncpy((char *) pMid->midVolLabel, pBS12->bsVolumeLabel, 11);
strncpy((char *) pMid->midFileSysType, pBS12->bsFileSysType, 8);
}
fsStr = (LPSTR) mBBlock + kFat16Offset;
if (!strncmp(fsStr, "FAT16", 5)) // is it a FAT16 drive?
{
PBootSector16 pBS16 = (PBootSector16) mBBlock;
foundRecognizedFileSys = TRUE;
pMid->midSerialNum = pBS16->bsVolumeId;
strncpy((char *) pMid->midVolLabel, pBS16->bsVolumeLabel, 11);
strncpy((char *) pMid->midFileSysType, pBS16->bsFileSysType, 8);
}
fsStr = (LPSTR) mBBlock + kFat32Offset;
if (!strncmp(fsStr, "FAT32", 5)) // is it a FAT32 drive?
{
PBootSector32 pBS32 = (PBootSector32) mBBlock;
foundRecognizedFileSys = TRUE;
pMid->midSerialNum = pBS32->bsVolumeId;
strncpy((char *) pMid->midVolLabel, pBS32->bsVolumeLabel, 11);
strncpy((char *) pMid->midFileSysType, pBS32->bsFileSysType, 8);
}
// Special case for incorrectly formatted floppy drives. If the
// filesystem is unknown but the media is a floppy, assume FAT12.
if (!foundRecognizedFileSys)
{
PBootSector12 pBS12 = (PBootSector12) mBBlock;
if (pBS12->bsMedia == kFloppyMediaId)
{
pMid->midSerialNum = pBS12->bsVolumeId;
strncpy((char *) pMid->midVolLabel, pBS12->bsVolumeLabel, 11);
strncpy((char *) pMid->midFileSysType, "FAT12 ", 8);
}
}
}
return derr;
}
// GetFsId returns the ID of the filesystem of the mounted volume by reading
// the volume's bootsector and then seeing if it can find an identifier
// describing a known filesystem.
DualErr
Volume::GetFsId(FileSysId *fsId)
{
DualErr derr;
MID mid;
pgpAssertAddrValid(fsId, FileSysId);
pgpAssert(Mounted());
pgpAssertAddrValid(mBBlock, PGPUInt8);
(* fsId) = kFS_Unknown;
derr = GetMediaId(&mid);
if (derr.IsntError())
{
LPSTR fsStr = (char *) mid.midFileSysType;
if (!strncmp(fsStr, "FAT12", 5)) // is it a FAT12 drive?
(* fsId) = kFS_FAT12;
if (!strncmp(fsStr, "FAT16", 5)) // is it a FAT16 drive?
(* fsId) = kFS_FAT16;
if (!strncmp(fsStr, "FAT32", 5)) // is it a FAT32 drive?
(* fsId) = kFS_FAT32;
}
return derr;
}
// AttachLocalVolume initializes this Volume object for access to an already
// mounted volume on the local computer.
DualErr
Volume::AttachLocalVolume(PGPUInt8 drive)
{
DualErr derr;
PDCB pDcb;
pgpAssert(IsLegalDriveNumber(drive));
pgpAssert(Unmounted());
pgpAssert(!AttachedToLocalVolume());
// Find the DCB by making a system call.
if (!(pDcb = IspGetDcb(drive)))
derr = DualErr(kPGDMinorError_IspGetDcbFailed);
if (derr.IsntError())
{
derr = InitMountedVars(drive, pDcb);
mAttachedToLocalVol = derr.IsntError();
}
return derr;
}
// DetachLocalVolume marks this Volume object as no longer being associated
// with a local volume.
void
Volume::DetachLocalVolume()
{
pgpAssert(Mounted());
pgpAssert(AttachedToLocalVolume());
mAttachedToLocalVol = FALSE;
CleanUpMountedVars();
}
// Mount() mounts the volume on the specified drive letter using the
// specified DCB.
DualErr
Volume::Mount(PDCB pDcb, PGPUInt8 drive)
{
DualErr derr;
PGPBoolean assocedDcb = FALSE;
pgpAssertAddrValid(pDcb, DCB);
pgpAssert(Unmounted());
pgpAssert(!AttachedToLocalVolume());
// If no preferred drive letter is specified, or if the drive is in use,
// we make a system call to get the next free drive letter.
if ((drive < 2) || (drive >= kMaxDrives) || (IsntNull(IspGetDcb(drive))))
{
drive = pDcb->DCB_cmn.DCB_drive_lttr_equiv =
IspDriveLetterPick(mPDcb, NULL);
if (drive == kInvalidDrive)
derr = DualErr(kPGDMinorError_IspDriveLetterPickFailed);
}
// Then we make another call to associate this driver letter with our
// DCB, thereby mounting the volume.
if (derr.IsntError())
{
if (!IspAssociateDcb(pDcb, drive, NULL))
derr = DualErr(kPGDMinorError_IspAssociateDcbFailed);
assocedDcb = derr.IsntError();
}
// Initialize some variables for mounted drives.
if (derr.IsntError())
{
derr = InitMountedVars(drive, pDcb);
}
// Clean up in case of error.
if (derr.IsError())
{
if (assocedDcb)
IspDisassociateDcb(drive);
}
return derr;
}
// Unmount unmounts a mounted Volume.
DualErr
Volume::Unmount(PGPBoolean isThisEmergency)
{
DualErr derr;
LockLevel oldLock;
PGPBoolean hasOpenFiles, lockedDown;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -