/// <summary> /// Initializes a new FAT directory. /// </summary> /// <param name="aFileSystem">The FAT file system to which the directory belongs.</param> /// <param name="parent">The FAT directory which is the parent of the directory. Null for the root directory.</param> /// <param name="aName">The name of the directory.</param> /// <param name="aFirstCluster">The first cluster number of the directory.</param> public FATDirectory(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aFirstCluster) : base(aFileSystem, parent, aName) { _theFile = new FATFile(aFileSystem, parent, Name, 0, aFirstCluster) { IsDirectoryFile = true }; }
/// <summary> /// Initializes a new FAT file. /// </summary> /// <param name="aFileSystem">The FAT file system to which the file belongs.</param> /// <param name="parent">The parent directory of the file.</param> /// <param name="aName">The name of the file.</param> /// <param name="aSize">The size of the file.</param> /// <param name="aFirstCluster">The first cluster number of the file.</param> /// <remarks> /// Size is UInt32 because FAT doesn't support bigger. Don't change to UInt64. /// </remarks> public FATFile(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aSize, UInt32 aFirstCluster) : base(aFileSystem, parent, aName, aSize) { TheFATFileSystem = aFileSystem; FirstClusterNum = aFirstCluster; }
/// <summary> /// Parses the specified directory file data for its listings. /// </summary> /// <param name="xData">The directory data.</param> /// <param name="xDataLength">The directory data length.</param> /// <param name="thisDir"> /// The FAT directory the FAT data is from. /// Used when creating listings as the parent directory. /// </param> /// <returns>The directory listings.</returns> public List ParseDirectoryTable(byte[] xData, int xDataLength, FATDirectory thisDir) { List xResult = new List(); //BasicConsole.WriteLine("Parsing listings..."); FOS_System.String xLongName = ""; for (UInt32 i = 0; i < xDataLength; i = i + 32) { byte xAttrib = xData[i + 11]; if (xAttrib == ListingAttribs.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. FOS_System.String xLongPart = ByteConverter.GetASCIIStringFromUTF16(xData, i + 1, 5); //BasicConsole.WriteLine("xLongPart1: " + xLongPart); // 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 determine // this by also looking at the length. Since we short circuit the or, the length // is rarely evaluated. if (xLongPart.length == 5) { xLongPart = xLongPart + ByteConverter.GetASCIIStringFromUTF16(xData, i + 14, 6); //BasicConsole.WriteLine("xLongPart2: " + xLongPart); if (xLongPart.length == 11) { xLongPart = xLongPart + ByteConverter.GetASCIIStringFromUTF16(xData, i + 28, 2); //BasicConsole.WriteLine("xLongPart3: " + xLongPart); } } xLongName = xLongPart + xLongName; //BasicConsole.WriteLine("xLongName: " + 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) { FOS_System.String xName; int xTest = xAttrib & (ListingAttribs.Directory | ListingAttribs.VolumeID); 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. xName = xLongName.Trim(); // As per spec, ignore trailing periods //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 > -1; nameIndex--) { if (xName[nameIndex] != '.') { break; } } //Substring to remove the periods xName = xName.Substring(0, nameIndex + 1); } } else { FOS_System.String xEntry = ByteConverter.GetASCIIStringFromASCII(xData, i, 11); //Volume ID does not have same format as file-name. if (xTest == ListingAttribs.VolumeID) { xName = xEntry; } else { //Attempt to apply original spec: // - 8 chars for filename // - 3 chars for extension if (xEntry.length >= 8) { xName = xEntry.Substring(0, 8).TrimEnd(); if (xEntry.length >= 11) { FOS_System.String xExt = xEntry.Substring(8, 3).TrimEnd(); if (xExt.length > 0) { xName += "." + xExt; } } } else { xName = xEntry; } } } UInt32 xFirstCluster = (UInt32)(ByteConverter.ToUInt16(xData, i + 20) << 16 | ByteConverter.ToUInt16(xData, i + 26)); xName = xName.ToUpper(); //TODO: Store attributes in the listings if (xTest == 0) { if (xName[xName.length - 1] != '~') { UInt32 xSize = ByteConverter.ToUInt32(xData, i + 28); xResult.Add(new FATFile(this, thisDir, xName, xSize, xFirstCluster)); } else { //BasicConsole.WriteLine("Ignoring file: " + xName); } } else if (xTest == ListingAttribs.VolumeID) { thePartition.VolumeID = xName; } else if (xTest == ListingAttribs.Directory) { xResult.Add(new FATDirectory(this, thisDir, xName, xFirstCluster)); } xLongName = ""; } } } return xResult; }
/// <summary> /// Gets the root directory listings in the FAT file system. /// </summary> /// <returns>The root directory listings.</returns> public List GetRootDirectoryListings() { if (FATType == FATTypeEnum.FAT32) { if (_rootDirectoryFAT32 == null) { _rootDirectoryFAT32 = new FATDirectory(this, null, "ROOT", RootCluster); } return _rootDirectoryFAT32.GetListings(); } else { if (_rootDirectoryListings == null) { byte[] xData = thePartition.TheDiskDevice.NewBlockArray(RootSectorCount); thePartition.ReadBlock(RootSector, RootSectorCount, xData); _rootDirectoryListings = ParseDirectoryTable(xData, xData.Length, null); } return _rootDirectoryListings; } }
/// <summary> /// Creates a new directory within the file system. /// </summary> /// <param name="name">The name of the directory to create.</param> /// <param name="parent">The parent directory of the new directory.</param> /// <returns>The new directory listing.</returns> public override Directory NewDirectory(String name, Directory parent) { if (FATType != FATTypeEnum.FAT32) { ExceptionMethods.Throw(new Exceptions.NotSupportedException("FATFileSystem.NewDirectory for non-FAT32 not supported!")); } if (parent == null) { ExceptionMethods.Throw(new Exceptions.NullReferenceException()); } if (!(parent is FATDirectory)) { ExceptionMethods.Throw(new Exceptions.NotSupportedException("FATFileSystem.NewDirectory parent directory must be of type FATDirectory!")); } //BasicConsole.WriteLine("Getting listings..."); List listings = parent.GetListings(); //BasicConsole.WriteLine("Got listings. Converting name to upper..."); name = name.ToUpper(); //BasicConsole.WriteLine("Name converted. Checking listing exists..."); bool exists = Directory.ListingExists(name, listings); //BasicConsole.WriteLine("Checked."); if (!exists) { //BasicConsole.WriteLine("Getting next free cluster..."); UInt32 freeCluster = GetNextFreeCluster(2); //BasicConsole.WriteLine("Got next free. Clearing cluster..."); WriteCluster(freeCluster, null); //BasicConsole.WriteLine("Cleared. Setting FAT entry..."); SetFATEntryAndSave(freeCluster, GetFATEntryEOFValue(FATType)); //BasicConsole.WriteLine("Set FAT entry. Creating new directory..."); FATDirectory newDir = new FATDirectory(this, (FATDirectory)parent, name, freeCluster); //BasicConsole.WriteLine("Adding listing to parent..."); parent.AddListing(newDir); //BasicConsole.WriteLine("Added listing. Writing listings..."); parent.WriteListings(); //BasicConsole.WriteLine("Written listings."); return newDir; } else { ExceptionMethods.Throw(new IOException("Listing (directory/file) with specified name already exists!")); } return null; }
/// <summary> /// Initializes a new FAT file. /// </summary> /// <param name="aFileSystem">The FAT file system to which the file belongs.</param> /// <param name="parent">The parent directory of the file.</param> /// <param name="aName">The name of the file.</param> /// <param name="aSize">The size of the file.</param> /// <param name="aFirstCluster">The first cluster number of the file.</param> /// <remarks> /// Size is UInt32 because FAT doesn't support bigger. Don't change to UInt64. /// </remarks> public FATFile(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aSize, UInt32 aFirstCluster) : base(aFileSystem, parent, aName, aSize) { TheFATFileSystem = aFileSystem; FirstClusterNum = aFirstCluster; }
/// <summary> /// Initializes a new FAT directory. /// </summary> /// <param name="aFileSystem">The FAT file system to which the directory belongs.</param> /// <param name="parent">The FAT directory which is the parent of the directory. Null for the root directory.</param> /// <param name="aName">The name of the directory.</param> /// <param name="aFirstCluster">The first cluster number of the directory.</param> public FATDirectory(FATFileSystem aFileSystem, FATDirectory parent, FOS_System.String aName, UInt32 aFirstCluster) : base(aFileSystem, parent, aName) { _theFile = new FATFile(aFileSystem, parent, Name, 0, aFirstCluster) { IsDirectoryFile = true }; }