示例#1
0
        /// <summary>
        /// Create FS node
        /// </summary>
        /// <param name="dirEntry">Direntry</param>
        /// <param name="cluster">Directory cluster</param>
        /// <param name="num">Direnty number</param>
        /// <returns></returns>
        public Node CreateNode(FatDirEntry *dirEntry, uint cluster, uint num)
        {
            Node node = new Node();

            node.Size = dirEntry->Size;

            Fat16Cookie cookie = new Fat16Cookie();

            cookie.DirEntry = dirEntry;
            cookie.Cluster  = cluster;
            cookie.Num      = num;
            cookie.FAT16    = this;

            node.Cookie = cookie;

            /**
             * Is it a directory?
             */
            if ((dirEntry->Attribs & ATTRIB_SUBDIR) == ATTRIB_SUBDIR)
            {
                node.ReadDir = readDirImpl;
                node.FindDir = findDirImpl;
                node.Flags   = NodeFlags.DIRECTORY;
            }
            else
            {
                node.Read     = readImpl;
                node.Write    = writeImpl;
                node.Truncate = truncateImpl;
                node.Flags    = NodeFlags.FILE;
            }

            return(node);
        }
示例#2
0
        /// <summary>
        /// Parse direntries
        /// </summary>
        private unsafe void parseBoot()
        {
            /**
             * Calculate first data start LBA
             */
            m_clusterBeginLBA = m_beginLBA + m_bpb->ReservedSectors + (m_bpb->NumFats * (int)m_bpb->SectorsPerFat16);

            // Fetch root directory from memory
            byte[] buffer = new byte[m_bpb->NumDirEntries * sizeof(FatDirEntry)];

            m_dirEntries = (FatDirEntry *)Util.ObjectToVoidPtr(buffer);


            uint sectorSize = (uint)m_bpb->NumDirEntries / 16;

            // Do we have a spare sector?
            if (sectorSize * 16 != m_bpb->NumDirEntries)
            {
                sectorSize++;
            }

            _Device.Read(_Device, (uint)(m_clusterBeginLBA), sectorSize * 512, buffer);

            m_numDirEntries = m_bpb->NumDirEntries;
            m_beginDataLBA  = m_clusterBeginLBA + ((m_bpb->NumDirEntries * 32) / m_bpb->BytesPerSector);
        }
示例#3
0
        /// <summary>
        /// Filesystem truncate implementation
        /// </summary>
        /// <param name="node"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private static uint truncateImpl(Node node, uint size)
        {
            /**
             * Get directory entry from cookie "cache"
             */
            Fat16Cookie  cookie = (Fat16Cookie)node.Cookie;
            FatDirEntry *entry  = cookie.DirEntry;
            Fat16        fat    = cookie.FAT16;

            if (entry == null)
            {
                return(0);
            }

            /**
             * Empty file not supported
             */
            if (size == 0)
            {
                return(0);
            }

            /**
             * Resize file
             */
            return(fat.ResizeFile(entry, cookie.Cluster, cookie.Num, size));
        }
示例#4
0
        /// <summary>
        /// Filesystem write implementation
        /// </summary>
        /// <param name="node"></param>
        /// <param name="offset"></param>
        /// <param name="size"></param>
        /// <param name="buffer"></param>
        /// <returns></returns>
        private static uint writeImpl(Node node, uint offset, uint size, byte[] buffer)
        {
            /**
             * Get directory entry from cookie "cache"
             */
            Fat16Cookie  cookie = (Fat16Cookie)node.Cookie;
            Fat16        fat    = cookie.FAT16;
            FatDirEntry *entry  = cookie.DirEntry;

            uint totalSize = size + offset;

            /**
             * Do we need to resize the file?
             */
            if (entry->Size < totalSize)
            {
                if (fat.ResizeFile(entry, cookie.Cluster, cookie.Num, totalSize) == 0)
                {
                    return(0);
                }
            }

            /**
             * Handle file writing
             */
            return(fat.writeFile(entry->ClusterNumberLo, offset, size, buffer));
        }
示例#5
0
        /// <summary>
        /// Filesystem read implementation
        /// </summary>
        /// <param name="node"></param>
        /// <param name="offset"></param>
        /// <param name="size"></param>
        /// <param name="buffer"></param>
        /// <returns></returns>
        private static uint readImpl(Node node, uint offset, uint size, byte[] buffer)
        {
            /**
             * Get directory entry from cookie "cache"
             */
            Fat16Cookie  cookie = (Fat16Cookie)node.Cookie;
            Fat16        fat    = cookie.FAT16;
            FatDirEntry *entry  = cookie.DirEntry;

            /*
             * If the offset is behind the size, stop here
             */
            if (offset > entry->Size)
            {
                return(0);
            }

            /*
             * If bytes to read is bigger than the file size, set the size to the file size minus offset
             */
            if (offset + size > entry->Size)
            {
                size = entry->Size - offset;
            }

            //Util.PrintStackTrace(6);

            uint read = fat.readFile(entry->ClusterNumberLo, offset, size, buffer);

            return(read);
        }
示例#6
0
        /// <summary>
        /// Read directory
        /// </summary>
        /// <param name="cluster"></param>
        /// <returns></returns>
        public SubDirectory readDirectory(uint cluster)
        {
            SubDirectory outDir = new SubDirectory();

            if (cluster == 0xFFFFFFFF)
            {
                outDir.Length     = m_numDirEntries;
                outDir.DirEntries = m_dirEntries;
            }
            else
            {
                byte[] buffer = new byte[m_bpb->NumDirEntries * sizeof(FatDirEntry)];

                // To-do why does this read that mutch?
                readFile(cluster, 0, (uint)(m_bpb->NumDirEntries * sizeof(FatDirEntry)), buffer);

                FatDirEntry *entries = (FatDirEntry *)Heap.Alloc(m_bpb->NumDirEntries * sizeof(FatDirEntry));

                FatDirEntry *curBufPtr = (FatDirEntry *)Util.ObjectToVoidPtr(buffer);

                int length = 0;
                for (int i = 0; i < m_bpb->NumDirEntries; i++)
                {
                    entries[i] = curBufPtr[i];

                    if (curBufPtr[i].Name[0] == 0x00)
                    {
                        break;
                    }

                    length++;
                }

                outDir.DirEntries = entries;
                outDir.Length     = (uint)length;
            }

            return(outDir);
        }
示例#7
0
        /// <summary>
        /// Find node in directory
        /// </summary>
        /// <param name="cluster">Cluster number</param>
        /// <param name="testFor">Compare string</param>
        /// <returns></returns>
        public Node FindFileInDirectory(uint cluster, char *testFor)
        {
            SubDirectory dir = readDirectory(cluster);

            for (int i = 0; i < dir.Length; i++)
            {
                FatDirEntry entry = dir.DirEntries[i];

                if (entry.Name[0] == 0 || entry.Name[0] == 0xE5 || entry.Attribs == 0xF || (entry.Attribs & 0x08) > 0)
                {
                    continue;
                }

                if (Memory.Compare(testFor, entry.Name, 11))
                {
                    FatDirEntry *entr = (FatDirEntry *)Heap.Alloc(sizeof(FatDirEntry));
                    Memory.Memcpy(entr, dir.DirEntries + i, sizeof(FatDirEntry));
                    return(CreateNode(entr, cluster, (uint)i));
                }
            }

            return(null);
        }
示例#8
0
        /// <summary>
        /// Set file size in Direntries
        /// </summary>
        /// <param name="cluster">Start cluster</param>
        /// <param name="num">Direnty location</param>
        /// <param name="size">Size</param>
        private void SetFileSize(uint cluster, uint num, uint size)
        {
            uint offset = num * (uint)sizeof(FatDirEntry);

            uint offsetSector = offset / 512;

            offset -= offsetSector * 512;

            // Read dir entry part
            uint realOffset = 0;

            if (cluster == 0xFFFFFFFF)
            {
                realOffset = (uint)(m_clusterBeginLBA + offsetSector);
            }
            else
            {
                realOffset = Data_clust_to_lba(cluster) + offsetSector;
            }

            byte[] buf = new byte[512];
            _Device.Read(_Device, realOffset, 512, buf);


            byte *       bufPtr = (byte *)Util.ObjectToVoidPtr(buf);
            FatDirEntry *entry  = (FatDirEntry *)(bufPtr + offset);

            entry->Size = size;

            _Device.Write(_Device, realOffset, 512, buf);

            // Update dir entry if needed
            if (cluster == 0xFFFFFFFF)
            {
                m_dirEntries[num].Size = size;
            }
        }
示例#9
0
        /// <summary>
        /// Filesystem read directory implementation
        /// </summary>
        /// <param name="node"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        private static DirEntry *readDirImpl(Node node, uint index)
        {
            int j = 0;

            /**
             * Find cluster number if not root directory
             */
            uint cluster = 0xFFFFFFFF;

            Fat16Cookie cookie = (Fat16Cookie)node.Cookie;
            Fat16       fat    = cookie.FAT16;

            if (cookie.DirEntry != null)
            {
                FatDirEntry *entry = cookie.DirEntry;
                cluster = entry->ClusterNumberLo;
            }

            /**
             * Read directory entries
             */
            SubDirectory dir = fat.readDirectory(cluster);

            for (int i = 0; i < dir.Length; i++)
            {
                FatDirEntry entry = dir.DirEntries[i];

                /**
                 * Correct attributes?
                 */
                if (entry.Name[0] == 0 || entry.Name[0] == (char)0xE5 || entry.Attribs == 0xF || (entry.Attribs & 0x08) > 0)
                {
                    continue;
                }

                /**
                 * Do we need to search further?
                 */
                if (j >= index)
                {
                    DirEntry *outDir = (DirEntry *)Heap.Alloc(sizeof(DirEntry));
                    outDir->Reclen = (ushort)sizeof(DirEntry);

                    GetName(dir, i, outDir->Name);


                    /**
                     * Directory or file?
                     */
                    if ((dir.DirEntries[i].Attribs & ATTRIB_SUBDIR) == 0)
                    {
                        outDir->Type = (byte)DT_Type.DT_REG;
                    }
                    else
                    {
                        outDir->Type = (byte)DT_Type.DT_DIR;
                    }


                    return(outDir);
                }

                j++;
            }

            return(null);
        }
示例#10
0
        /// <summary>
        /// Find directory implementation
        /// </summary>
        /// <param name="node">FS Node</param>
        /// <param name="name">Filename</param>
        /// <returns></returns>
        private static Node findDirImpl(Node node, string name)
        {
            Fat16Cookie cookie = (Fat16Cookie)node.Cookie;
            Fat16       fat16  = cookie.FAT16;

            /**
             * Calculate lengths (and check if no LFN)
             */
            int length = name.Length;

            if (length > 12)
            {
                return(null);
            }

            int dot = name.IndexOf('.');

            if (dot > 8)
            {
                return(null);
            }

            /**
             * Prepare test memory block
             */
            char *testFor = (char *)Heap.Alloc(11);

            Memory.Memset(testFor, ' ', 11);

            int min = (dot == -1) ? Math.Min(length, 8) : Math.Min(dot, 8);
            int i   = 0;

            for (; i < min; i++)
            {
                testFor[i] = String.ToUpper(name[i]);
            }

            if (dot != -1)
            {
                int lengthExt = length - dot - 1;
                min = Math.Min(3, lengthExt);

                i++;
                for (int j = 0; j < min; j++)
                {
                    testFor[j + 8] = String.ToUpper(name[i + j]);
                }
            }

            /**
             * Find cluster number
             */
            uint cluster = 0xFFFFFFFF;

            if (cookie.DirEntry != null)
            {
                FatDirEntry *entry = cookie.DirEntry;
                cluster = entry->ClusterNumberLo;
            }

            /**
             * Find file in cluster (directory)
             */
            Node nd = fat16.FindFileInDirectory(cluster, testFor);

            Heap.Free(testFor);

            return(nd);
        }
示例#11
0
        /// <summary>
        /// Resize file
        ///
        /// @TODO: Allow cluster allocation and removal
        ///
        /// /// </summary>
        /// <param name="direntry">Current direntry</param>
        /// <param name="cluster">Cluster number for writing</param>
        /// <param name="num">Direntry number in cluster</param>
        /// <param name="size">File size</param>
        /// <returns>Changed size (=0 when error)</returns>
        private uint ResizeFile(FatDirEntry *direntry, uint cluster, uint num, uint size)
        {
            uint realsize = size;

            int bytesPerCluster = m_bpb->SectorsPerCluster * m_bpb->BytesPerSector;

            uint readSizeNew = size - 1;
            uint readSizeOld = direntry->Size - 1;

            /**
             * Calculate sectors and clusters
             */
            uint sectorsNew  = (uint)Math.Ceil((double)readSizeNew / (double)m_bpb->BytesPerSector);
            uint clustersNew = (uint)Math.Ceil((double)sectorsNew / (double)m_bpb->SectorsPerCluster);

            if (readSizeNew == bytesPerCluster)
            {
                clustersNew++;
            }

            uint sectorsOld  = (uint)Math.Ceil((double)(readSizeOld) / (double)m_bpb->BytesPerSector);
            uint clustersOld = (uint)Math.Ceil((double)sectorsOld / (double)m_bpb->SectorsPerCluster);

            if (readSizeOld == bytesPerCluster)
            {
                clustersOld++;
            }

            /**
             * Calculate difference
             */
            int clusterDiff = (int)clustersNew - (int)clustersOld;

            /**
             * @TODO: Test this! (lightly tested, looks like is that it is working)
             */
            if (clusterDiff != 0)
            {
                /**
                 * Increase or decrease
                 */
                if (clusterDiff < 0)
                {
                    clusterDiff = Math.Abs(clusterDiff);

                    ushort currentLastCluster = findLastCluster((ushort)cluster);
                    ushort newLastCluster     = findLastCluster((ushort)cluster, 1);

                    /**
                     * Removing clusters
                     */
                    for (int i = 0; i < clusterDiff; i++)
                    {
                        /**
                         * Change cluster table values
                         */
                        changeClusterValue(currentLastCluster, 0x0000);
                        changeClusterValue(newLastCluster, 0xFFFF);

                        currentLastCluster = findLastCluster((ushort)cluster);
                        newLastCluster     = findLastCluster((ushort)cluster, 1);
                    }
                }
                else
                {
                    ushort currentCluster = findLastCluster((ushort)cluster);


                    byte[] buf = new byte[m_bpb->BytesPerSector];
                    Memory.Memclear(Util.ObjectToVoidPtr(buf), m_bpb->BytesPerSector);

                    /**
                     * Allocating clusters
                     */
                    for (int i = 0; i < clusterDiff; i++)
                    {
                        ushort freeCluster = findNextFreeCluster();

                        /**
                         * Change cluster table values
                         */
                        changeClusterValue(currentCluster, freeCluster);
                        changeClusterValue(freeCluster, 0xFFFF);

                        currentCluster = freeCluster;

                        /**
                         * Free cluster
                         */
                        uint toFreeLBA = Data_clust_to_lba(currentCluster);

                        for (uint x = 0; x < m_bpb->SectorsPerCluster; x++)
                        {
                            _Device.Write(_Device, toFreeLBA + x, m_bpb->BytesPerSector, buf);
                        }
                    }

                    Heap.Free(buf);
                }
            }

            /**
             * CLEAR EMPTY SPACE
             *
             * Calculate startpoint and offsets
             */
            uint startPoint   = (uint)(size > direntry->Size ? direntry->Size : size);
            uint offsetSector = startPoint / 512;
            uint offset       = startPoint - (offsetSector * 512);

            /**
             * Get starting position on FS
             */
            uint lba = Data_clust_to_lba(direntry->ClusterNumberLo);

            byte[] writeSec = new byte[m_bpb->BytesPerSector];
            byte[] readSec  = new byte[m_bpb->BytesPerSector];

            /**
             * Free cluster
             */
            for (uint i = offsetSector; i < m_bpb->SectorsPerCluster; i++)
            {
                /**
                 * Do we have an offset to use?
                 */
                if (offset != 0)
                {
                    _Device.Read(_Device, lba + i, 512, readSec);
                    Memory.Memcpy(Util.ObjectToVoidPtr(writeSec), Util.ObjectToVoidPtr(readSec), (int)offset);
                    Memory.Memclear((byte *)Util.ObjectToVoidPtr(writeSec) + offset, (int)(512 - offset));
                }
                else
                {
                    Memory.Memclear(Util.ObjectToVoidPtr(writeSec), 512);
                }

                offset = 0;
                _Device.Write(_Device, lba + i, 512, writeSec);
            }

            /**
             * Free objects
             */
            Heap.Free(Util.ObjectToVoidPtr(writeSec));
            Heap.Free(Util.ObjectToVoidPtr(readSec));

            /**
             * Finally update node!
             */
            SetFileSize(cluster, num, realsize);

            direntry->Size = realsize;

            return(realsize);
        }