public FatDirectoryEntry( FatFileSystem aFileSystem, FatDirectoryEntry aParent, string aFullPath, string aName, uint aFirstCluster) : base(aFileSystem, aParent, aFullPath, aName, 0, DirectoryEntryTypeEnum.Directory) { if (aFirstCluster < aFileSystem.RootCluster) { throw new ArgumentOutOfRangeException(nameof(aFirstCluster)); } mFirstClusterNum = aFirstCluster; mEntryHeaderDataOffset = 0; }
public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType) { if ((aType == DirectoryEntryTypeEnum.Directory) || (aType == DirectoryEntryTypeEnum.File)) { string xFullPath = Path.Combine(mFullPath, aName); uint xFirstCluster = ((FatFileSystem)mFileSystem).GetFat(0).GetNextUnallocatedFatEntry(); uint xEntryHeaderDataOffset = GetNextUnallocatedDirectoryEntry(); var xNewEntry = new FatDirectoryEntry((FatFileSystem)mFileSystem, this, xFullPath, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aType); xNewEntry.AllocateDirectoryEntry(); return(xNewEntry); } throw new ArgumentOutOfRangeException(nameof(aType), "Unknown directory entry type."); }
public FatStream(FatDirectoryEntry aEntry) { if (aEntry == null) { throw new ArgumentNullException(nameof(aEntry)); } mDirectoryEntry = aEntry; mFS = aEntry.GetFileSystem(); mFatTable = aEntry.GetFatTable(); mSize = aEntry.mSize; if (mFatTable == null) { throw new Exception("The fat chain returned for the directory entry was null."); } }
/// <summary> /// Retrieves a <see cref="List{T}"/> of <see cref="FatDirectoryEntry"/> objects that represent the Directory Entries inside this Directory /// </summary> /// <returns>Returns a <see cref="List{T}"/> of the Directory Entries inside this Directory</returns> public List <FatDirectoryEntry> ReadDirectoryContents() { var xData = GetDirectoryEntryData(); var xResult = new List <FatDirectoryEntry>(); FatDirectoryEntry xParent = (FatDirectoryEntry)(mParent ?? mFileSystem.GetRootDirectory()); //TODO: Change xLongName to StringBuilder string xLongName = ""; string xName = ""; for (uint i = 0; i < xData.Length; i = i + 32) { byte xAttrib = xData[i + 11]; byte xStatus = xData[i]; if (xAttrib == FatDirectoryEntryAttributeConsts.LongName) { byte xType = xData[i + 12]; if (xStatus == FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry) { continue; } if (xType == 0) { if ((xStatus & 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; xLongPart = null; //TODO: LDIR_Chksum } } else { xName = xLongName; if (xStatus == 0x00) { break; } switch (xStatus) { case 0x05: // Japanese characters - We dont handle these break; case FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry: // Empty slot, skip it continue; default: if (xStatus >= 0x20) { 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); } xLongName = ""; } 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; } } } break; } } uint xFirstCluster = (uint)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26)); int xTest = xAttrib & (FatDirectoryEntryAttributeConsts.Directory | FatDirectoryEntryAttributeConsts.VolumeID); if (xAttrib == FatDirectoryEntryAttributeConsts.LongName) { // skip adding, as it's a LongFileName entry, meaning the next normal entry is the item with the name. ////Global.mFileSystemDebugger.SendInternal($"Entry was a Long FileName entry. Current LongName = '{xLongName}'"); } else if (xTest == 0) { uint xSize = xData.ToUInt32(i + 28); if (xSize == 0 && xName.Length == 0) { continue; } string xFullPath = Path.Combine(mFullPath, xName); var xEntry = new FatDirectoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File); xResult.Add(xEntry); } else if (xTest == FatDirectoryEntryAttributeConsts.Directory) { string xFullPath = Path.Combine(mFullPath, xName); uint xSize = xData.ToUInt32(i + 28); var xEntry = new FatDirectoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.Directory); xResult.Add(xEntry); } else if (xTest == FatDirectoryEntryAttributeConsts.VolumeID) { ////Global.mFileSystemDebugger.SendInternal("<VOLUME ID> : Attrib = " + xAttrib + ", Status = " + xStatus); } else { ////Global.mFileSystemDebugger.SendInternal("<INVALID ENTRY> : Attrib = " + xAttrib + ", Status = " + xStatus); } } return(xResult); }
public override DirectoryEntry GetRootDirectory() { var xRootEntry = new FatDirectoryEntry(this, null, mRootPath, mRootPath, RootCluster); return(xRootEntry); }