/// <summary> /// /// </summary> /// <param name="volumeName"></param> /// <param name="fileName"></param> /// <param name="nodeNumber"></param> /// <returns></returns> internal static Node Get(string volumeName, string fileName, uint nodeNumber) { VolumeHeader volHeader = VolumeHeader.Get(volumeName); Node headerNode = null; switch (fileName) { case "Catalog": headerNode = CatalogFile.GetHeaderNode(volumeName); break; case "Attributes": headerNode = AttributesFile.GetHeaderNode(volumeName); break; case "ExtentsOverflow": headerNode = ExtentsOverflowFile.GetHeaderNode(volumeName); break; } HeaderRecord headerRecord = headerNode.Records[0] as HeaderRecord; return(Get(GetBytes(volumeName, fileName, nodeNumber), volumeName, fileName, nodeNumber)); }
/// <summary> /// /// </summary> /// <param name="volumeName"></param> /// <param name="fileName"></param> /// <returns></returns> private static byte[] GetHeaderBytes(string volumeName, string fileName) { VolumeHeader volHeader = VolumeHeader.Get(volumeName); ExtentDescriptor extent = null; switch (fileName) { case "Catalog": extent = volHeader.CatalogFile.Extents[0]; break; case "Attributes": extent = volHeader.AttributesFile.Extents[0]; break; case "ExtentsOverflow": extent = volHeader.ExtentsOverflowFile.Extents[0]; break; } // Read the smallest possible amount of bytes byte[] firstSectorBytes = Helper.readDrive(volumeName, extent.StartBlock * volHeader.BlockSize, 0x200); // Parse HeaderRecord to determine NodeSize HeaderRecord headerRecord = HeaderRecord.Get(firstSectorBytes, 0x0E, volumeName, fileName); // Read the full Header Node return(Helper.readDrive(volumeName, extent.StartBlock * volHeader.BlockSize, headerRecord.NodeSize)); }
/// <summary> /// /// </summary> /// <param name="volumeName"></param> /// <param name="fileName"></param> /// <param name="nodeNumber"></param> /// <returns></returns> internal static byte[] GetBytes(string volumeName, string fileName, uint nodeNumber) { VolumeHeader volHeader = VolumeHeader.Get(volumeName); ExtentDescriptor[] extents = null; switch (fileName) { case "Catalog": extents = volHeader.CatalogFile.Extents; break; case "Attributes": extents = volHeader.AttributesFile.Extents; break; case "ExtentsOverflow": extents = volHeader.ExtentsOverflowFile.Extents; break; } Node headerNode = GetHeaderNode(volumeName, fileName); HeaderRecord headerRecord = headerNode.Records[0] as HeaderRecord; // Determine which blocks contain desired node's bytes uint blockNumber = nodeNumber * (headerRecord.NodeSize / volHeader.BlockSize); // Starting Position within the extents uint extentPosition = 0; // Iterate through extents to determine which extent conatians the Node foreach (ExtentDescriptor extent in extents) { uint relBlock = blockNumber - extentPosition; if (relBlock < extent.BlockCount) { return(Helper.readDrive(volumeName, (long)(extent.StartBlock + relBlock) * volHeader.BlockSize, headerRecord.NodeSize)); } else { extentPosition += extent.BlockCount; } } // Need to throw an "Invalid Node Number" error return(null); }
/// <summary> /// /// </summary> /// <param name="volumeName"></param> /// <param name="blockNumber"></param> /// <returns></returns> public static bool IsAllocationBlockUsed(string volumeName, uint blockNumber) { // Get VolumeHeader VolumeHeader volHeader = VolumeHeader.Get(volumeName); // Detemine which byte to look at uint bytePosition = blockNumber / 0x8; // Determine which of AllocationFile's blocks the byte belongs to uint fileBlock = bytePosition / volHeader.BlockSize; uint relativeBlock = 0; byte[] blockBytes = null; foreach (ExtentDescriptor extent in volHeader.AllocationFile.Extents) { if (fileBlock < relativeBlock + extent.BlockCount) { uint blockToRead = fileBlock - relativeBlock + extent.StartBlock; blockBytes = Helper.readDrive(volumeName, (blockToRead * volHeader.BlockSize), volHeader.BlockSize); break; } else { relativeBlock += extent.BlockCount; } } // Pick the right byte from the Sector byte byteToCheck = blockBytes[(blockNumber / 8) % volHeader.BlockSize]; byte position = (byte)(blockNumber % 8); // Need to come back and ensure this is correct (it appears to be opposite of what i'd expect) return((byteToCheck & (1 >> (position))) != 0); }