예제 #1
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFileSystem == null)
            {
                throw new ArgumentNullException("aFileSystem");
            }

            if (aName == null)
            {
                throw new ArgumentNullException("aName");
            }

            if (aFirstCluster < 2)
            {
                throw new ArgumentOutOfRangeException("aFirstCluster");
            }

            mFileSystem = aFileSystem;
            mParent = aParent;
            mFirstClusterNum = aFirstCluster;
            mEntryHeaderDataOffset = 0;

            //FatHelpers.Debug(
            //    "-- FatDirectoryEntry.ctor : " + "aParent.Name = " + aParent?.mName + ", aName = " + aName
            //    + ", aFirstCluster = " + aFirstCluster + " --");
        }
예제 #2
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFileSystem == null)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aFileSystem is null.");
                throw new ArgumentNullException(nameof(aFileSystem));
            }

            if (aName == null)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aName is null.");
                throw new ArgumentNullException(nameof(aName));
            }

            if (aFirstCluster < 2)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aParent.Name = {aParent?.mName}, aName = {aName}, aFirstCluster = {aFirstCluster}");

            mFileSystem            = aFileSystem;
            mParent                = aParent;
            mFirstClusterNum       = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #3
0
        public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType)
        {
            Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.AddDirectoryEntry --");
            Global.mFileSystemDebugger.SendInternal("aName =");
            Global.mFileSystemDebugger.SendInternal(aName);
            Global.mFileSystemDebugger.SendInternal("aType =");
            Global.mFileSystemDebugger.SendInternal((uint)aType);

            if ((aType == DirectoryEntryTypeEnum.Directory) || (aType == DirectoryEntryTypeEnum.File))
            {
                string xFullPath              = Path.Combine(mFullPath, aName);
                uint   xFirstCluster          = ((FatFileSystem)mFileSystem).GetFat(0).GetNextUnallocatedFatEntry();
                uint   xEntryHeaderDataOffset = GetNextUnallocatedDirectoryEntry();
                Global.mFileSystemDebugger.SendInternal("xFullPath =");
                Global.mFileSystemDebugger.SendInternal(xFullPath);
                Global.mFileSystemDebugger.SendInternal("xFirstCluster =");
                Global.mFileSystemDebugger.SendInternal(xFirstCluster);
                Global.mFileSystemDebugger.SendInternal("xEntryHeaderDataOffset =");
                Global.mFileSystemDebugger.SendInternal(xEntryHeaderDataOffset);

                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.");
        }
예제 #4
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFileSystem == null)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aFileSystem is null.");
                throw new ArgumentNullException(nameof(aFileSystem));
            }

            if (aName == null)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aName is null.");
                throw new ArgumentNullException(nameof(aName));
            }

            if (aFirstCluster < 2)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aParent.Name =", aParent?.mName, ", aName =", aName, ", aFirstCluster =", aFirstCluster);

            mFileSystem = aFileSystem;
            mParent = aParent;
            mFirstClusterNum = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #5
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFileSystem == null)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aFileSystem is null.");
                throw new ArgumentNullException(nameof(aFileSystem));
            }

            if (aName == null)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aName is null.");
                throw new ArgumentNullException(nameof(aName));
            }

            if (aFirstCluster < 2)
            {
                FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            FileSystemHelpers.Debug("FatDirectoryEntry.ctor", "aParent.Name =", aParent?.mName, ", aName =", aName, ", aFirstCluster =", aFirstCluster);

            mFileSystem            = aFileSystem;
            mParent                = aParent;
            mFirstClusterNum       = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #6
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFileSystem == null)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aFileSystem is null.");
                throw new ArgumentNullException(nameof(aFileSystem));
            }

            if (aName == null)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aName is null.");
                throw new ArgumentNullException(nameof(aName));
            }

            if (aFirstCluster < 2)
            {
                Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.ctor : aParent.Name = {aParent?.mName}, aName = {aName}, aFirstCluster = {aFirstCluster}");

            mFileSystem = aFileSystem;
            mParent = aParent;
            mFirstClusterNum = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #7
0
 // Size is UInt32 because FAT doesn't support bigger.
 // Don't change to UInt64
 public FatDirectoryEntry(FatFileSystem aFileSystem, FatDirectoryEntry aParent, string aName, uint aSize, ulong aFirstClusterNum, uint aEntryHeaderDataOffset, DirectoryEntryTypeEnum aEntryType)
     : base(aFileSystem, aParent, aName, aSize, aEntryType)
 {
     FileSystem = aFileSystem;
     Parent = aParent;
     FirstClusterNum = aFirstClusterNum;
     EntryHeaderDataOffset = aEntryHeaderDataOffset;
 }
예제 #8
0
파일: FatStream.cs 프로젝트: rebizu/Cosmos
 public FatStream(FatDirectoryEntry aEntry)
 {
     mDirectoryEntry = aEntry;
     mFS = mDirectoryEntry.GetFileSystem();
     mSize = mDirectoryEntry.mSize;
     if (mDirectoryEntry.mSize > 0)
     {
         mFatTable = mDirectoryEntry.GetFatTable();
     }
 }
예제 #9
0
파일: FatStream.cs 프로젝트: SUTD/Cosmos
        public FatStream(FatDirectoryEntry aFile)
        {
            mDirectoryEntry = aFile;
            mFS = mDirectoryEntry.FileSystem;
            mReadBuffer = mDirectoryEntry.FileSystem.NewClusterArray();

            mSize = this.mDirectoryEntry.Size;
            if (mDirectoryEntry.Size > 0)
            {
                mFatTable = mDirectoryEntry.GetFatTable();
            }
        }
예제 #10
0
파일: FatStream.cs 프로젝트: Orvid/Cosmos
        public FatStream(FatDirectoryEntry aEntry)
        {
            Global.mFileSystemDebugger.SendInternal("FatStream with entry " + aEntry);

            mDirectoryEntry = aEntry;
            mFS = mDirectoryEntry.GetFileSystem();
            mSize = mDirectoryEntry.mSize;
            if (mDirectoryEntry.mSize > 0)
            {
                mFatTable = mDirectoryEntry.GetFatTable();
            }
        }
예제 #11
0
 public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType)
 {
     Global.mFileSystemDebugger.SendInternal($"FatDirectoryEntry.AddDirectoryEntry : aName = {aName}, aType = {aType}");
     if ((aType == DirectoryEntryTypeEnum.Directory) || (aType == DirectoryEntryTypeEnum.File))
     {
         uint xFirstCluster          = mFileSystem.GetFat(0).GetNextUnallocatedFatEntry();
         uint xEntryHeaderDataOffset = GetNextUnallocatedEntry();
         var  xNewEntry = new FatDirectoryEntry(mFileSystem, this, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aType);
         xNewEntry.AllocateDirectoryEntry();
         return(xNewEntry);
     }
     throw new ArgumentOutOfRangeException("aType", "Unknown directory entry type.");
 }
예제 #12
0
        public FatDirectoryEntry FindVolumeId()
        {
            if (!IsRootDirectory())
            {
                throw new Exception("VolumeId can be found only in Root Directory");
            }

            Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.FindVolumeId --");

            var xData = GetDirectoryEntryData();
            FatDirectoryEntry xParent = this;

            FatDirectoryEntry xResult = null;

            for (uint i = 0; i < xData.Length; i = i + 32)
            {
                byte xAttrib = xData[i + 11];

                //if ((xAttrib & FatDirectoryEntryAttributeConsts.VolumeID) != FatDirectoryEntryAttributeConsts.VolumeID)
                if (xAttrib != FatDirectoryEntryAttributeConsts.VolumeID)
                {
                    continue;
                }

                Global.mFileSystemDebugger.SendInternal("VolumeID Found");
                /* The Label in FAT could be only a shortName (limited to 11 characters) so it is more easy */
                string xName = Encoding.ASCII.GetString(xData, (int)i, 11);
                xName = xName.TrimEnd();

                string xFullPath = Path.Combine(mFullPath, xName);
                /* Probably can be OK to hardcode 0 here */
                uint xSize = BitConverter.ToUInt32(xData, (int)i + 28);
                //uint xFirstCluster = (uint)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26));
                uint xFirstCluster = xParent.mFirstClusterNum;

                Global.mFileSystemDebugger.SendInternal($"VolumeID Found xName {xName} xFullPath {xFullPath} xSize {xSize} xFirstCluster {xFirstCluster}");

                xResult = new FatDirectoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
                break;
            }

            if (xResult == null)
            {
                Global.mFileSystemDebugger.SendInternal($"VolumeID not found, returning null");
            }

            return(xResult);
        }
예제 #13
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aFullPath,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aFullPath, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            if (aFirstCluster < aFileSystem.RootCluster)
            {
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            mFirstClusterNum = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #14
0
        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;
        }
예제 #15
0
        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.");
            }
        }
예제 #16
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aFullPath,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aFullPath, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            Global.mFileSystemDebugger.SendInternal("FatDirectoryEntry.ctor");

            if (aFirstCluster < 2)
            {
                Global.mFileSystemDebugger.SendInternal("aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            mFirstClusterNum       = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #17
0
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aFullPath,
            string aName,
            ulong aFirstCluster)
            : base(aFileSystem, aParent, aFullPath, aName, 0, DirectoryEntryTypeEnum.Directory)
        {
            Global.mFileSystemDebugger.SendInternal("FatDirectoryEntry.ctor");

            if (aFirstCluster < 2)
            {
                Global.mFileSystemDebugger.SendInternal("aFirstCluster is out of range.");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            mFirstClusterNum = aFirstCluster;
            mEntryHeaderDataOffset = 0;
        }
예제 #18
0
        public FatStream(FatDirectoryEntry aEntry)
        {
            Global.mFileSystemDebugger.SendInternal($"FatStream with entry {aEntry}");

            mDirectoryEntry = aEntry;
            mFS = mDirectoryEntry.GetFileSystem();
            mSize = mDirectoryEntry.mSize;

            Global.mFileSystemDebugger.SendInternal("FatStream with mSize {mSize}");

            Global.mFileSystemDebugger.SendInternal("Getting FatTable");
            // We get always the FatTable if the file is empty too
                mFatTable = mDirectoryEntry.GetFatTable();
            // What to do if this should happen? Throw exception?
            if (mFatTable == null)
            {
                Global.mFileSystemDebugger.SendInternal("FatTable got but it is null!");
            }
        }
예제 #19
0
        // Size is UInt32 because FAT doesn't support bigger.
        // Don't change to UInt64
        public FatDirectoryEntry(
            FatFileSystem aFileSystem,
            FatDirectoryEntry aParent,
            string aFullPath,
            string aName,
            long aSize,
            uint aFirstCluster,
            uint aEntryHeaderDataOffset,
            DirectoryEntryTypeEnum aEntryType)
            : base(aFileSystem, aParent, aFullPath, aName, aSize, aEntryType)
        {
            if (aFirstCluster < aFileSystem.RootCluster)
            {
                Global.mFileSystemDebugger.SendInternal($"aFirstCluster {aFirstCluster} < aFileSystem.RootCluster {aFileSystem.RootCluster}");
                throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
            }

            mFirstClusterNum       = aFirstCluster;
            mEntryHeaderDataOffset = aEntryHeaderDataOffset;
        }
예제 #20
0
        public List<FatDirectoryEntry> ReadDirectoryContents()
        {
            Global.mFileSystemDebugger.SendInternal("-- 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];
                    byte xOrd = xData[i];
                    if (xOrd == 0xE5)
                    {
                        Global.mFileSystemDebugger.SendInternal("<DELETED> : Attrib = " + xAttrib + ", Status = " + xStatus);
                        continue;
                    }
                    if (xType == 0)
                    {
                        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;
                        xLongPart = null;
                        //TODO: LDIR_Chksum
                    }
                }
                else
                {
                    xName = xLongName;
                    if (xStatus == 0x00)
                    {
                        Global.mFileSystemDebugger.SendInternal("<EOF> : Attrib = " + xAttrib + ", Status = " + xStatus);
                        break;
                    }
                    switch (xStatus)
                    {
                        case 0x05:
                            // Japanese characters - We dont handle these
                            break;
                        case 0xE5:
                            // Empty slot, skip it
                            break;
                        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);
                    Global.mFileSystemDebugger.SendInternal(xEntry.mName + " - " + xEntry.mSize + " bytes");
                }
                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);
                    Global.mFileSystemDebugger.SendInternal(xEntry.mName + " <DIR> " + xEntry.mSize + " bytes : Attrib = " + xAttrib + ", Status = " + xStatus);
                    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;
        }
예제 #21
0
        public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType)
        {
            Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.AddDirectoryEntry --");
            Global.mFileSystemDebugger.SendInternal("aName =");
            Global.mFileSystemDebugger.SendInternal(aName);
            Global.mFileSystemDebugger.SendInternal("aType =");
            Global.mFileSystemDebugger.SendInternal((uint)aType);

            if ((aType == DirectoryEntryTypeEnum.Directory) || (aType == DirectoryEntryTypeEnum.File))
            {
                string xFullPath = Path.Combine(mFullPath, aName);
                uint xFirstCluster = ((FatFileSystem)mFileSystem).GetFat(0).GetNextUnallocatedFatEntry();
                uint xEntryHeaderDataOffset = GetNextUnallocatedDirectoryEntry();
                Global.mFileSystemDebugger.SendInternal("xFullPath =");
                Global.mFileSystemDebugger.SendInternal(xFullPath);
                Global.mFileSystemDebugger.SendInternal("xFirstCluster =");
                Global.mFileSystemDebugger.SendInternal(xFirstCluster);
                Global.mFileSystemDebugger.SendInternal("xEntryHeaderDataOffset =");
                Global.mFileSystemDebugger.SendInternal(xEntryHeaderDataOffset);

                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.");
        }
예제 #22
0
        /// <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(bool aReturnShortFilenames = false)
        {
            Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.ReadDirectoryContents --");

            var xData = GetDirectoryEntryData();
            var xResult = new List<FatDirectoryEntry>();
            FatDirectoryEntry xParent = this;

            //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 (aReturnShortFilenames)
                    {
                        continue;
                    }

                    if (xStatus == FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry)
                    {
                        Global.mFileSystemDebugger.SendInternal("<DELETED> : Attrib = " + xAttrib + ", Status = " + xStatus);
                        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)
                    {
                        Global.mFileSystemDebugger.SendInternal("<EOF> : Attrib = " + xAttrib + ", Status = " + xStatus);
                        break;
                    }

                    switch (xStatus)
                    {
                        case 0x05:
                            // Japanese characters - We dont handle these
                            break;
                        case 0x2E:
                            // Dot entry
                            continue;
                        case FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry:
                            // Empty slot, skip it
                            continue;
                        default:
                            int xTest = xAttrib & (FatDirectoryEntryAttributeConsts.Directory | FatDirectoryEntryAttributeConsts.VolumeID);

                            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
                                {
                                    if (xTest == 0)
                                    {
                                        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;
                                        }
                                    }
                                    else
                                    {
                                        xName = xData.GetAsciiString(i, 11).TrimEnd();
                                    }
                                }
                            }

                            uint xFirstCluster = (uint)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26));

                            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);
                                Global.mFileSystemDebugger.SendInternal(xEntry.mName + " - " + xEntry.mSize + " bytes");
                            }
                            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);
                                Global.mFileSystemDebugger.SendInternal(xEntry.mName + " <DIR> " + xEntry.mSize + " bytes : Attrib = " + xAttrib + ", Status = " + xStatus);
                                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);
                            }
                            break;
                    }
                }
            }

            return xResult;
        }
예제 #23
0
        public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aEntryType)
        {
            Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.AddDirectoryEntry --");
            Global.mFileSystemDebugger.SendInternal("aName =");
            Global.mFileSystemDebugger.SendInternal(aName);
            Global.mFileSystemDebugger.SendInternal("aEntryType =");
            Global.mFileSystemDebugger.SendInternal((uint)aEntryType);

            if ((aEntryType == DirectoryEntryTypeEnum.Directory) || (aEntryType == DirectoryEntryTypeEnum.File))
            {
                string xShortName = aName;
                uint[] xDirectoryEntriesToAllocate = null;

                //Stack corruption, just delete everything from this until commented if when it's fixed
                var x1 = aEntryType == DirectoryEntryTypeEnum.File;
                var x2 = aName.Contains(".");
                var x3 = x2 ? aName.Substring(0, aName.LastIndexOf('.')).Contains(".") : false;
                var x4 = x2 ? aName.Substring(0, aName.IndexOf('.')).Length > 8 : false;
                var x5 = x2 ? aName.Substring(aName.IndexOf('.') + 1).Length > 3 : false;
                var x6 = aEntryType == DirectoryEntryTypeEnum.Directory;
                var x7 = aName.Length > 11;

                var x8 = (x3 || (x4 || x5));
                var x9 = (x2 && x8);

                var x10 = (x1 && x9) || (x6 && x7);

                //if ((aEntryType == DirectoryEntryTypeEnum.File && (aName.Contains(".") && (aName.Substring(0, aName.LastIndexOf('.')).Contains(".") || (aName.Substring(0, aName.IndexOf('.')).Length > 8 || aName.Substring(aName.IndexOf('.') + 1).Length > 3)))) ||
                //    (aEntryType == DirectoryEntryTypeEnum.Directory && aName.Length > 11))
                if (x10)
                {
                    string xLongName = aName;

                    char[] xInvalidShortNameChars = new char[] { '"', '*', '+', ',', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '|' };

                    int xLastPeriodPosition = aName.LastIndexOf('.');

                    string xExt = "";

                    if (xLastPeriodPosition + 1 > 0 && xLastPeriodPosition + 1 < aName.Length)
                    {
                        xExt = xShortName.Substring(xLastPeriodPosition + 1);
                    }

                    for (int i = xShortName.Length - 1; i > 0; i--)
                    {
                        char xChar = xShortName[i];

                        if (char.IsWhiteSpace(xChar) || (xChar == '.' && i != xLastPeriodPosition))
                        {
                            xShortName.Remove(i, 1);
                        }
                    }

                    foreach (char xInvalidChar in xInvalidShortNameChars)
                    {
                        xShortName.Replace(xInvalidChar, '_');
                    }

                    int n = 1;
                    List<FatDirectoryEntry> xDirectoryEntries = ReadDirectoryContents(true);
                    string[] xShortFilenames = new string[xDirectoryEntries.Count];

                    for (int i = 0; i < xDirectoryEntries.Count; i++)
                    {
                        xShortFilenames[i] = xDirectoryEntries[i].mName;
                    }

                    string xNameTry = "";

                    bool xTest = false;

                    do
                    {
                        xNameTry = (xShortName.Substring(0, 7 - n.ToString().Length) + "~" + n).ToUpperInvariant();

                        if (!string.IsNullOrEmpty(xExt))
                        {
                            xNameTry += '.' + xExt.ToUpperInvariant();
                        }

                        n++;

                        xTest = false;

                        foreach (string name in xShortFilenames)
                        {
                            if (name == xNameTry)
                            {
                                xTest = true;
                                break;
                            }
                        }
                    }
                    //TODO: Array.TrySZIndexOf plug is not being recognized; to use the generic version of IndexOf, just remove the cast to Array
                    //while (Array.IndexOf((Array)xShortFilenames, xNameTry) != -1);
                    while (xTest);

                    xShortName = xNameTry;

                    uint xChecksum = CalculateChecksum(GetShortName(xShortName));

                    int xNumEntries = (int)Math.Ceiling((double)xLongName.Length / (double)13);

                    char[] xLongNameWithPad = new char[xNumEntries * 13];

                    xLongNameWithPad[xLongNameWithPad.Length - 1] = (char)0xFFFF;
                    Array.Copy(xLongName.ToCharArray(), xLongNameWithPad, xLongName.Length);

                    xDirectoryEntriesToAllocate = GetNextUnallocatedDirectoryEntries(xNumEntries + 1);

                    for (int i = xNumEntries - 1; i >= 0; i--)
                    {
                        uint xEntry = xDirectoryEntriesToAllocate[xNumEntries - i - 1];

                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.SequenceNumberAndAllocationStatus, (i + 1) | (i == xNumEntries - 1 ? (1 << 6) : 0));
                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.Attributes, FatDirectoryEntryAttributeConsts.LongName);
                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.Checksum, xChecksum);

                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.LongName1, new string(xLongNameWithPad, i * 13, 5));
                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.LongName2, new string(xLongNameWithPad, i * 13 + 5, 6));
                        SetLongFilenameEntryMetadataValue(xEntry, FatDirectoryEntryMetadata.LongFilenameEntryMetadata.LongName3, new string(xLongNameWithPad, i * 13 + 11, 2));
                    }
                }

                string xFullPath = Path.Combine(mFullPath, aName);
                uint xFirstCluster = ((FatFileSystem)mFileSystem).GetFat(0).GetNextUnallocatedFatEntry();
                uint xEntryHeaderDataOffset = xDirectoryEntriesToAllocate == null ? GetNextUnallocatedDirectoryEntry() : xDirectoryEntriesToAllocate[xDirectoryEntriesToAllocate.Length - 1];

                Global.mFileSystemDebugger.SendInternal("xFullPath =");
                Global.mFileSystemDebugger.SendInternal(xFullPath);
                Global.mFileSystemDebugger.SendInternal("xFirstCluster =");
                Global.mFileSystemDebugger.SendInternal(xFirstCluster);
                Global.mFileSystemDebugger.SendInternal("xEntryHeaderDataOffset =");
                Global.mFileSystemDebugger.SendInternal(xEntryHeaderDataOffset);

                var xNewEntry = new FatDirectoryEntry((FatFileSystem)mFileSystem, this, xFullPath, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aEntryType);

                xNewEntry.AllocateDirectoryEntry(xShortName);

                return xNewEntry;
            }

            throw new ArgumentOutOfRangeException(nameof(aEntryType), "Unknown directory entry type.");
        }
예제 #24
0
 public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType)
 {
     FileSystemHelpers.Debug("FatDirectoryEntry.AddDirectoryEntry", "aName =", aName, ", aType =", aType.ToString());
     if (aType == DirectoryEntryTypeEnum.Directory)
     {
         uint xFirstCluster = mFileSystem.GetFat(0).GetNextUnallocatedFatEntry();
         uint xEntryHeaderDataOffset = GetNextUnallocatedEntry();
         var xNewEntry = new FatDirectoryEntry(
             mFileSystem,
             this,
             aName,
             0,
             xFirstCluster,
             xEntryHeaderDataOffset,
             aType);
         xNewEntry.AllocateDirectoryEntry();
         return xNewEntry;
     }
     if (aType == DirectoryEntryTypeEnum.File)
     {
         throw new NotImplementedException("Creating new files is currently not implemented.");
     }
     throw new ArgumentOutOfRangeException("aType", "Unknown directory entry type.");
 }
예제 #25
0
        private void SetDirectoryEntryData(FatDirectoryEntry aDirectoryEntry, byte[] aData)
        {
            if (aDirectoryEntry == null)
            {
                throw new ArgumentNullException("aDirectoryEntry");
            }

            if (aData == null)
            {
                throw new ArgumentNullException("aData");
            }

            if (aData.Length == 0)
            {
                FatHelpers.Debug("SetDirectoryEntryData: No data to write.");
                return;
            }

            FatHelpers.Debug("SetDirectoryEntryData: Name = " + aDirectoryEntry.Name);
            FatHelpers.Debug("SetDirectoryEntryData: Size = " + aDirectoryEntry.Size);
            FatHelpers.Debug("SetDirectoryEntryData: FirstClusterNum = " + aDirectoryEntry.FirstClusterNum);
            FatHelpers.Debug("SetDirectoryEntryData: aData.Length = " + aData.Length);

            if (aDirectoryEntry.EntryType != DirectoryEntryTypeEnum.Unknown)
            {
                if (mFatType == FatTypeEnum.Fat32)
                {
                    WriteCluster(aDirectoryEntry.FirstClusterNum, aData);
                }
                else
                {
                    mDevice.WriteBlock(aDirectoryEntry.FirstClusterNum, RootSectorCount, aData);
                }
            }
            else
            {
                throw new Exception("Invalid directory entry type");
            }
        }
예제 #26
0
 public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aType)
 {
     FileSystemHelpers.Debug("FatDirectoryEntry.AddDirectoryEntry");
     if ((aType == DirectoryEntryTypeEnum.Directory) || (aType == DirectoryEntryTypeEnum.File))
     {
         uint xFirstCluster = mFileSystem.GetFat(0).GetNextUnallocatedFatEntry();
         uint xEntryHeaderDataOffset = GetNextUnallocatedEntry();
         var xNewEntry = new FatDirectoryEntry(mFileSystem, this, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aType);
         xNewEntry.AllocateDirectoryEntry();
         return xNewEntry;
     }
     throw new ArgumentOutOfRangeException("aType", "Unknown directory entry type.");
 }
예제 #27
0
 public override DirectoryEntry GetRootDirectory()
 {
     FileSystemHelpers.Debug("FatFileSystem.GetRootDirectory", "RootCluster =" + RootCluster);
     var xRootEntry = new FatDirectoryEntry(this, null, mRootPath, RootCluster);
     return xRootEntry;
 }
예제 #28
0
        private List<FatDirectoryEntry> ReadDirectoryContents(byte[] xData, FatDirectoryEntry aDirectory)
        {
            var xResult = new List<FatDirectoryEntry>();
            //TODO: Change xLongName to StringBuilder
            string xLongName = "";
            string xName = "";
            for (uint i = 0; i < xData.Length; i = i + 32)
            {
                FatHelpers.Debug("-------------------------------------------------");
                byte xAttrib = xData[i + 11];
                byte xStatus = xData[i];

                FatHelpers.Debug("Attrib = " + xAttrib + ", Status = " + xStatus);
                if (xAttrib == FatDirectoryEntryAttributeConsts.LongName)
                {
                    byte xType = xData[i + 12];
                    byte xOrd = xData[i];
                    FatHelpers.Debug("Reading LFN with Seqnr " + xOrd + ", Type = " + xType);
                    if (xOrd == 0xE5)
                    {
                        FatHelpers.Debug("Skipping deleted entry");
                        continue;
                    }
                    if (xType == 0)
                    {
                        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;
                        xLongPart = null;
                        //TODO: LDIR_Chksum
                    }
                }
                else
                {
                    xName = xLongName;
                    if (xStatus == 0x00)
                    {
                        FatHelpers.Debug("End of directory");
                        break;
                    }
                    switch (xStatus)
                    {
                        case 0x05:
                            // Japanese characters - We dont handle these
                            break;
                        case 0xE5:
                            // Empty slot, skip it
                            break;
                        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));

                var 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.
                    FatHelpers.Debug("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;
                    }
                    var xEntry = new FatDirectoryEntry(this, aDirectory, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
                    xResult.Add(xEntry);
                    FatHelpers.Debug("Returning file '" + xEntry.Name + "', FirstCluster = " + xEntry.FirstClusterNum +
                                     ", Size = " + xEntry.Size);
                }
                else if (xTest == FatDirectoryEntryAttributeConsts.Directory)
                {
                    uint xSize = xData.ToUInt32(i + 28);
                    var xEntry = new FatDirectoryEntry(this, aDirectory, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.Directory);
                    FatHelpers.Debug("Returning directory '" + xEntry.Name + "', FirstCluster = " +
                                     xEntry.FirstClusterNum + ", Size = " + xEntry.Size);
                    xResult.Add(xEntry);
                }
                else if (xTest == FatDirectoryEntryAttributeConsts.VolumeID)
                {
                    FatHelpers.Debug("Directory entry is VolumeID");
                }
                else
                {
                    FatHelpers.Debug("Not sure what to do!");
                }
            }

            return xResult;
        }
예제 #29
0
        private List<FatDirectoryEntry> GetDirectoryContents(FatDirectoryEntry directory)
        {
            if (directory == null)
            {
                throw new ArgumentNullException("directory");
            }

            byte[] xData = GetDirectoryEntryData(directory);
            // todo: what about larger directories?

            return ReadDirectoryContents(xData, directory);
        }
예제 #30
0
        internal void SetDirectoryEntryMetadataValue(FatDirectoryEntry aDirectoryEntry, FatDirectoryEntryMetadata aEntryMetadata, string aValue)
        {
            var xData = GetDirectoryEntryData(aDirectoryEntry.Parent);
            if (xData.Length > 0)
            {
                byte[] xValue = new byte[aEntryMetadata.DataLength];
                xValue = aValue.ToString().GetUtf8Bytes(0, aEntryMetadata.DataLength);

                uint offset = aDirectoryEntry.EntryHeaderDataOffset + aEntryMetadata.DataOffset;

                Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);

                FatHelpers.Debug("SetDirectoryEntryMetadataValue: DataLength = " + aEntryMetadata.DataLength);
                FatHelpers.Debug("SetDirectoryEntryMetadataValue: DataOffset = " + aEntryMetadata.DataOffset);
                FatHelpers.Debug("SetDirectoryEntryMetadataValue: EntryHeaderDataOffset = " + aDirectoryEntry.EntryHeaderDataOffset);
                FatHelpers.Debug("SetDirectoryEntryMetadataValue: TotalOffset = " + offset);
                FatHelpers.Debug("SetDirectoryEntryMetadataValue: aValue = " + aValue);

                for (int i = 0; i < xValue.Length; i++)
                {
                    FatHelpers.DebugNumber(xValue[i]);
                }

                SetDirectoryEntryData(aDirectoryEntry.Parent, xData);
            }
        }
예제 #31
0
        public override DirectoryEntry GetRootDirectory()
        {
            Global.mFileSystemDebugger.SendInternal("-- FatFileSystem.GetRootDirectory --");

            var xRootEntry = new FatDirectoryEntry(this, null, mRootPath, mRootPath, RootCluster);
            return xRootEntry;
        }
예제 #32
0
        public List <FatDirectoryEntry> ReadDirectoryContents()
        {
            FileSystemHelpers.Debug("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)
            {
                FileSystemHelpers.Debug("-------------------------------------------------");
                byte xAttrib = xData[i + 11];
                byte xStatus = xData[i];

                FileSystemHelpers.Debug("Attrib =", xAttrib, ", Status =", xStatus);
                if (xAttrib == FatDirectoryEntryAttributeConsts.LongName)
                {
                    byte xType = xData[i + 12];
                    byte xOrd  = xData[i];
                    FileSystemHelpers.Debug("Reading LFN with Seqnr " + xOrd, ", Type =", xType);
                    if (xOrd == 0xE5)
                    {
                        FileSystemHelpers.Debug("<DELETED>", "Attrib =", xAttrib, ", Status =", xStatus);
                        continue;
                    }
                    if (xType == 0)
                    {
                        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;
                        xLongPart = null;
                        //TODO: LDIR_Chksum
                    }
                }
                else
                {
                    xName = xLongName;
                    if (xStatus == 0x00)
                    {
                        FileSystemHelpers.Debug("<EOF>", "Attrib =", xAttrib, ", Status =", xStatus);
                        break;
                    }
                    switch (xStatus)
                    {
                    case 0x05:
                        // Japanese characters - We dont handle these
                        break;

                    case 0xE5:
                        // Empty slot, skip it
                        break;

                    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.
                    FileSystemHelpers.Debug("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;
                    }
                    var xEntry = new FatDirectoryEntry(mFileSystem, xParent, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
                    xResult.Add(xEntry);
                    FileSystemHelpers.Debug(xEntry.mName + " -" + xEntry.mSize + " bytes");
                }
                else if (xTest == FatDirectoryEntryAttributeConsts.Directory)
                {
                    uint xSize  = xData.ToUInt32(i + 28);
                    var  xEntry = new FatDirectoryEntry(mFileSystem, xParent, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.Directory);
                    FileSystemHelpers.Debug(xEntry.mName + " <DIR> " + xEntry.mSize + " bytes", "Attrib =", xAttrib, ", Status =", xStatus);
                    xResult.Add(xEntry);
                }
                else if (xTest == FatDirectoryEntryAttributeConsts.VolumeID)
                {
                    FileSystemHelpers.Debug("<VOLUME ID>", "Attrib =", xAttrib, ", Status =", xStatus);
                }
                else
                {
                    FileSystemHelpers.Debug("<INVALID ENTRY>", "Attrib =", xAttrib, ", Status =", xStatus);
                }
            }

            return(xResult);
        }
예제 #33
0
 private byte[] GetDirectoryEntryData(FatDirectoryEntry aDirectoryEntry)
 {
     byte[] xData;
     if (mFatType == FatTypeEnum.Fat32)
     {
         if (aDirectoryEntry.EntryType != DirectoryEntryTypeEnum.Unknown)
         {
             xData = NewClusterArray();
             ReadCluster(aDirectoryEntry.FirstClusterNum, xData);
         }
         else
         {
             throw new Exception("Invalid directory entry type");
         }
     }
     else
     {
         if (aDirectoryEntry.EntryType != DirectoryEntryTypeEnum.Unknown)
         {
             xData = mDevice.NewBlockArray(1);
             mDevice.ReadBlock(aDirectoryEntry.FirstClusterNum, RootSectorCount, xData);
         }
         else
         {
             throw new Exception("Invalid directory entry type");
         }
     }
     return xData;
 }