Cosmos/source/Cosmos.System/FileSystem/FAT/FatFileSystem.cs
2014-12-04 21:11:46 -08:00

349 lines
No EOL
14 KiB
C#

//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Cosmos.Common.Extensions;
//using Cosmos.HAL.BlockDevice;
//namespace Cosmos.System.FileSystem.FAT
//{
// public class FatFileSystem : FileSystem
// {
// readonly public UInt32 BytesPerSector;
// readonly public UInt32 SectorsPerCluster;
// readonly public UInt32 BytesPerCluster;
// readonly public UInt32 ReservedSectorCount;
// readonly public UInt32 TotalSectorCount;
// readonly public UInt32 ClusterCount;
// readonly public UInt32 NumberOfFATs;
// readonly public UInt32 FatSectorCount;
// readonly public UInt32 RootSector = 0; // FAT12/16
// readonly public UInt32 RootSectorCount = 0; // FAT12/16, FAT32 remains 0
// readonly public UInt32 RootCluster; // FAT32
// readonly public UInt32 RootEntryCount;
// readonly public UInt32 DataSector; // First Data Sector
// readonly public UInt32 DataSectorCount;
// public static class Attribs
// {
// public const int Test = 0x01;
// public const int Hidden = 0x02;
// public const int System = 0x04;
// public const int VolumeID = 0x08;
// public const int Directory = 0x10;
// public const int Archive = 0x20;
// // LongName was created after and is a combination of other attribs. Its "special".
// public const int LongName = 0x0F;
// }
// public enum FatTypeEnum { Unknown, Fat12, Fat16, Fat32 }
// readonly public FatTypeEnum FatType = FatTypeEnum.Unknown;
// Cosmos.HAL.BlockDevice.BlockDevice mDevice;
// public void ReadFatTableSector(UInt64 xSectorNum, byte[] aData)
// {
// mDevice.ReadBlock(ReservedSectorCount + xSectorNum, 1, aData);
// }
// public bool FatEntryIsEOF(UInt64 aValue)
// {
// if (FatType == FatTypeEnum.Fat12)
// {
// return aValue >= 0x0FF8;
// }
// else if (FatType == FatTypeEnum.Fat16)
// {
// return aValue >= 0xFFF8;
// }
// else
// {
// return aValue >= 0x0FFFFFF8;
// }
// }
// public UInt64 GetFatEntry(byte[] aSector, UInt64 aClusterNum, UInt64 aOffset)
// {
// if (FatType == FatTypeEnum.Fat12)
// {
// if (aOffset == (BytesPerSector - 1))
// {
// throw new Exception("TODO: Sector Span");
// /* This cluster access spans a sector boundary in the FAT */
// /* There are a number of strategies to handling this. The */
// /* easiest is to always load FAT sectors into memory */
// /* in pairs if the volume is FAT12 (if you want to load */
// /* FAT sector N, you also load FAT sector N+1 immediately */
// /* following it in memory unless sector N is the last FAT */
// /* sector). It is assumed that this is the strategy used here */
// /* which makes this if test for a sector boundary span */
// /* unnecessary. */
// }
// // We now access the FAT entry as a WORD just as we do for FAT16, but if the cluster number is
// // EVEN, we only want the low 12-bits of the 16-bits we fetch. If the cluster number is ODD
// // we want the high 12-bits of the 16-bits we fetch.
// UInt32 xResult = aSector.ToUInt16(aOffset);
// if ((aClusterNum & 0x01) == 0)
// { // Even
// return xResult & 0x0FFF;
// }
// else
// { // Odd
// return xResult >> 4;
// }
// }
// else if (FatType == FatTypeEnum.Fat16)
// {
// return aSector.ToUInt16(aOffset);
// }
// else
// {
// return aSector.ToUInt32(aOffset) & 0x0FFFFFFF;
// }
// }
// public FatFileSystem(Cosmos.HAL.BlockDevice.BlockDevice aDevice)
// {
// mDevice = aDevice;
// byte[] xBPB = mDevice.NewBlockArray(1);
// mDevice.ReadBlock(0UL, 1U, xBPB);
// UInt16 xSig = xBPB.ToUInt16(510);
// if (xSig != 0xAA55)
// {
// throw new Exception("FAT signature not found.");
// }
// BytesPerSector = xBPB.ToUInt16(11);
// SectorsPerCluster = xBPB[13];
// BytesPerCluster = BytesPerSector * SectorsPerCluster;
// ReservedSectorCount = xBPB.ToUInt16(14);
// NumberOfFATs = xBPB[16];
// RootEntryCount = xBPB.ToUInt16(17);
// TotalSectorCount = xBPB.ToUInt16(19);
// if (TotalSectorCount == 0)
// {
// TotalSectorCount = xBPB.ToUInt32(32);
// }
// // FATSz
// FatSectorCount = xBPB.ToUInt16(22);
// if (FatSectorCount == 0)
// {
// FatSectorCount = xBPB.ToUInt32(36);
// }
// //Global.Dbg.Send("FAT Sector Count: " + FatSectorCount);
// DataSectorCount = TotalSectorCount - (ReservedSectorCount + (NumberOfFATs * FatSectorCount) + ReservedSectorCount);
// // Computation rounds down.
// ClusterCount = DataSectorCount / SectorsPerCluster;
// // Determine the FAT type. Do not use another method - this IS the official and
// // proper way to determine FAT type.
// // Comparisons are purposefully < and not <=
// // FAT16 starts at 4085, FAT32 starts at 65525
// if (ClusterCount < 4085)
// {
// FatType = FatTypeEnum.Fat12;
// }
// else if (ClusterCount < 65525)
// {
// FatType = FatTypeEnum.Fat16;
// }
// else
// {
// FatType = FatTypeEnum.Fat32;
// }
// if (FatType == FatTypeEnum.Fat32)
// {
// RootCluster = xBPB.ToUInt32(44);
// }
// else
// {
// RootSector = ReservedSectorCount + (NumberOfFATs * FatSectorCount);
// RootSectorCount = (RootEntryCount * 32 + (BytesPerSector - 1)) / BytesPerSector;
// }
// DataSector = ReservedSectorCount + (NumberOfFATs * FatSectorCount) + RootSectorCount;
// }
// public byte[] NewClusterArray()
// {
// return new byte[BytesPerCluster];
// }
// public void ReadCluster(UInt64 aCluster, byte[] aData)
// {
// UInt64 xSector = DataSector + ((aCluster - 2) * SectorsPerCluster);
// mDevice.ReadBlock(xSector, SectorsPerCluster, aData);
// }
// public void GetFatTableSector(UInt64 aClusterNum, out UInt32 oSector, out UInt32 oOffset)
// {
// UInt64 xOffset = 0;
// if (FatType == FatTypeEnum.Fat12)
// {
// // Multiply by 1.5 without using floating point, the divide by 2 rounds DOWN
// xOffset = aClusterNum + (aClusterNum / 2);
// }
// else if (FatType == FatTypeEnum.Fat16)
// {
// xOffset = aClusterNum * 2;
// }
// else if (FatType == FatTypeEnum.Fat32)
// {
// xOffset = aClusterNum * 4;
// }
// oSector = (UInt32)(xOffset / BytesPerSector);
// oOffset = (UInt32)(xOffset % BytesPerSector);
// }
// public List<Cosmos.System.FileSystem.Listing.Base> GetRoot()
// {
// var xResult = new List<Cosmos.System.FileSystem.Listing.Base>();
// byte[] xData;
// if (FatType == FatTypeEnum.Fat32)
// {
// xData = NewClusterArray();
// ReadCluster(RootCluster, xData);
// }
// else
// {
// xData = mDevice.NewBlockArray(RootSectorCount);
// mDevice.ReadBlock(RootSector, RootSectorCount, xData);
// }
// //TODO: Change xLongName to StringBuilder
// string xLongName = "";
// for (UInt32 i = 0; i < xData.Length; i = i + 32)
// {
// byte xAttrib = xData[i + 11];
// if (xAttrib == Attribs.LongName)
// {
// byte xType = xData[i + 12];
// if (xType == 0)
// {
// byte xOrd = xData[i];
// if ((xOrd & 0x40) > 0)
// {
// xLongName = "";
// }
// //TODO: Check LDIR_Ord for ordering and throw exception
// // if entries are found out of order.
// // Also save buffer and only copy name if a end Ord marker is found.
// string xLongPart = xData.GetUtf16String(i + 1, 5);
// // We have to check the length because 0xFFFF is a valid Unicode codepoint.
// // So we only want to stop if the 0xFFFF is AFTER a 0x0000. We can determin
// // this by also looking at the length. Since we short circuit the or, the length
// // is rarely evaluated.
// if (xData.ToUInt16(i + 14) != 0xFFFF || xLongPart.Length == 5)
// {
// xLongPart = xLongPart + xData.GetUtf16String(i + 14, 6);
// if (xData.ToUInt16(i + 28) != 0xFFFF || xLongPart.Length == 11)
// {
// xLongPart = xLongPart + xData.GetUtf16String(i + 28, 2);
// }
// }
// xLongName = xLongPart + xLongName;
// //TODO: LDIR_Chksum
// }
// }
// else
// {
// byte xStatus = xData[i];
// if (xStatus == 0x00)
// {
// // Empty slot, and no more entries after this
// break;
// }
// else if (xStatus == 0x05)
// {
// // Japanese characters - We dont handle these
// }
// else if (xStatus == 0xE5)
// {
// // Empty slot, skip it
// }
// else if (xStatus >= 0x20)
// {
// string xName;
// if (xLongName.Length > 0)
// {
// // Leading and trailing spaces are to be ignored according to spec.
// // Many programs (including Windows) pad trailing spaces although it
// // it is not required for long names.
// // As per spec, ignore trailing periods
// xName = xLongName.Trim();
// //If there are trailing periods
// int nameIndex = xName.Length - 1;
// if (xName[nameIndex] == '.')
// {
// //Search backwards till we find the first non-period character
// for (; nameIndex > 0; nameIndex--)
// {
// if (xName[nameIndex] != '.')
// {
// break;
// }
// }
// //Substring to remove the periods
// xName = xName.Substring(0, nameIndex + 1);
// }
// }
// else
// {
// string xEntry = xData.GetAsciiString(i, 11);
// xName = xEntry.Substring(0, 8).TrimEnd();
// string xExt = xEntry.Substring(8, 3).TrimEnd();
// if (xExt.Length > 0)
// {
// xName = xName + "." + xExt;
// }
// }
// UInt32 xFirstCluster = (UInt32)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26));
// var xTest = xAttrib & (Attribs.Directory | Attribs.VolumeID);
// if (xTest == 0)
// {
// UInt32 xSize = xData.ToUInt32(i + 28);
// xResult.Add(new Listing.FatFile(this, xName, xSize, xFirstCluster));
// }
// else if (xTest == Attribs.VolumeID)
// {
// //
// }
// else if (xTest == Attribs.Directory)
// {
// xResult.Add(new Listing.FatDirectory(this, xName));
// }
// xLongName = "";
// }
// }
// }
// return xResult;
// }
// public static bool IsDeviceFAT(Partition aDevice)
// {
// byte[] xBPB = aDevice.NewBlockArray(1);
// aDevice.ReadBlock(0UL, 1U, xBPB);
// UInt16 xSig = xBPB.ToUInt16(510);
// if (xSig != 0xAA55)
// {
// return false;
// }
// return true;
// }
// }
//}