Changeset 1226


Ignore:
Timestamp:
09/30/09 02:40:17 (5 years ago)
Author:
lowjoel
Message:

-Abstract the FatDirectory? class to a FatDirectoryBase? class which contains interfaces to parse the given FatDirectory? list, but no capability to read/write from disk since the Root directory in FAT12 and FAT16 are different from the Root directory in FAT32.
-Rename ::FatDirectory? to ::FatDirectoryEntry? since that's what it really is.

Location:
trunk/eraser6/Eraser.Util.FileSystem
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser6/Eraser.Util.FileSystem/Fat.h

    r1225 r1226  
    8989 
    9090/// Represents a short (8.3) directory entry. 
    91 struct FatDirectoryEntry 
     91struct Fat8Dot3DirectoryEntry 
    9292{ 
    9393    /// Base name. If Name[0] is: 
     
    189189 
    190190/// The collection of Fat Directory entries. 
    191 union FatDirectory 
     191union FatDirectoryEntry 
    192192{ 
    193     FatDirectoryEntry Short; 
     193    Fat8Dot3DirectoryEntry Short; 
    194194    FatLfnDirectoryEntry LongFileName; 
    195195}; 
    196196 
    197 typedef FatDirectory* FatDirectoryFile; 
     197typedef FatDirectoryEntry* FatDirectory; 
    198198 
    199199#pragma pack(pop) 
  • trunk/eraser6/Eraser.Util.FileSystem/Fat12Or16Api.cpp

    r1225 r1226  
    2121 
    2222#include <stdafx.h> 
    23 #include <windows.h> 
    24 #include <atlstr.h> 
    25  
    2623#include "FatApi.h" 
    2724 
     
    5855    } 
    5956 
    60     FatDirectory^ Fat12Or16Api::LoadDirectory(unsigned cluster, String^ name, FatDirectory^ parent) 
     57    FatDirectoryBase^ Fat12Or16Api::LoadDirectory(unsigned cluster, String^ name, 
     58        FatDirectoryBase^ parent) 
    6159    { 
    6260        return gcnew Directory(name, parent, cluster, this); 
     
    6563    long long Fat12Or16Api::ClusterToOffset(unsigned cluster) 
    6664    { 
    67         unsigned long long sector = BootSector->ReservedSectorCount +                                       //Reserved area 
    68             BootSector->FatCount * BootSector->SectorsPerFat +                                              //FAT area 
    69             (BootSector->RootDirectoryEntryCount * sizeof(::FatDirectory) / (ClusterSize / SectorSize)) +   //Root directory area 
     65        unsigned long long sector = BootSector->ReservedSectorCount +                                           //Reserved area 
     66            BootSector->FatCount * BootSector->SectorsPerFat +                                                  //FAT area 
     67            (BootSector->RootDirectoryEntryCount * sizeof(::FatDirectoryEntry) / (ClusterSize / SectorSize)) +  //Root directory area 
    7068            (static_cast<unsigned long long>(cluster) - 2) * (ClusterSize / SectorSize); 
    7169        return SectorToOffset(sector); 
     
    8280            BootSector->SectorCount32 : BootSector->SectorCount16); 
    8381        unsigned long long availableSectors = numberOfSectors - ( 
    84             BootSector->ReservedSectorCount +                                                           //Reserved area 
    85             BootSector->FatCount * BootSector->SectorsPerFat +                                          //FAT area 
    86             (BootSector->RootDirectoryEntryCount * sizeof(::FatDirectory) / (ClusterSize / SectorSize)) //Root directory area 
     82            BootSector->ReservedSectorCount +                                                               //Reserved area 
     83            BootSector->FatCount * BootSector->SectorsPerFat +                                              //FAT area 
     84            (BootSector->RootDirectoryEntryCount * sizeof(::FatDirectoryEntry) / (ClusterSize / SectorSize))    //Root directory area 
    8785        ); 
    8886        unsigned long long numberOfClusters = availableSectors / (ClusterSize / SectorSize); 
     
    9189    } 
    9290 
    93     Fat12Or16Api::Directory::Directory(String^ name, FatDirectory^ parent, unsigned cluster, 
     91    Fat12Or16Api::Directory::Directory(String^ name, FatDirectoryBase^ parent, unsigned cluster, 
    9492        Fat12Or16Api^ api) : FatDirectory(name, parent, cluster, api) 
    9593    { 
    9694    } 
    9795 
    98     unsigned Fat12Or16Api::Directory::GetStartCluster(::FatDirectory& directory) 
     96    unsigned Fat12Or16Api::Directory::GetStartCluster(::FatDirectoryEntry& directory) 
    9997    { 
    10098        if (directory.Short.Attributes == 0x0F) 
  • trunk/eraser6/Eraser.Util.FileSystem/Fat16Api.cpp

    r1225 r1226  
    2121 
    2222#include <stdafx.h> 
    23 #include <windows.h> 
    24 #include <atlstr.h> 
    25  
    2623#include "FatApi.h" 
    2724 
  • trunk/eraser6/Eraser.Util.FileSystem/Fat32Api.cpp

    r1222 r1226  
    2121 
    2222#include <stdafx.h> 
    23 #include <windows.h> 
    24 #include <atlstr.h> 
    25  
    2623#include "FatApi.h" 
    2724 
     
    5047 
    5148        //Seek to the FAT 
    52         VolumeStream->Seek(SectorSizeToSize(BootSector->ReservedSectorCount), SeekOrigin::Begin); 
     49        VolumeStream->Seek(SectorToOffset(BootSector->ReservedSectorCount), SeekOrigin::Begin); 
    5350 
    5451        //Read the FAT 
     
    5855    } 
    5956 
    60     FatDirectory^ Fat32Api::LoadDirectory(unsigned cluster, String^ name, FatDirectory^ parent) 
     57    FatDirectoryBase^ Fat32Api::LoadDirectory(unsigned cluster, String^ name, 
     58        FatDirectoryBase^ parent) 
    6159    { 
    6260        return gcnew Directory(name, parent, cluster, this); 
     
    126124        //Traverse the directories until we get the cluster we want. 
    127125        unsigned cluster = BootSector->Fat32ParameterBlock.RootDirectoryCluster; 
    128         FatDirectory^ parentDir = nullptr; 
     126        FatDirectoryBase^ parentDir = nullptr; 
    129127        for each (String^ component in components) 
    130128        { 
     
    140138    } 
    141139 
    142     Fat32Api::Directory::Directory(String^ name, FatDirectory^ parent, unsigned cluster, Fat32Api^ api) 
     140    Fat32Api::Directory::Directory(String^ name, FatDirectoryBase^ parent, unsigned cluster, Fat32Api^ api) 
    143141        : FatDirectory(name, parent, cluster, api) 
    144142    { 
    145143    } 
    146144 
    147     unsigned Fat32Api::Directory::GetStartCluster(::FatDirectory& directory) 
     145    unsigned Fat32Api::Directory::GetStartCluster(::FatDirectoryEntry& directory) 
    148146    { 
    149147        if (directory.Short.Attributes == 0x0F) 
  • trunk/eraser6/Eraser.Util.FileSystem/FatApi.cpp

    r1222 r1226  
    2222#include <stdafx.h> 
    2323#include <windows.h> 
    24 #include <atlstr.h> 
    2524 
    2625#include "FatApi.h" 
     
    4241 
    4342        //Open the handle to the drive 
    44         CString volumeName(info->VolumeId); 
    45         volumeName.Truncate(volumeName.GetLength() - 1); 
    4643        VolumeStream = info->Open(FileAccess::Read); 
    4744 
     
    7875    } 
    7976 
    80     FatDirectory^ FatApi::LoadDirectory(String^ directory) 
     77    FatDirectoryBase^ FatApi::LoadDirectory(String^ directory) 
    8178    { 
    8279        //Return the root directory if nothing is specified 
     
    152149    } 
    153150 
    154     FatDirectoryEntry::FatDirectoryEntry(String^ name, FatDirectory^ parent, 
     151    FatDirectoryEntry::FatDirectoryEntry(String^ name, FatDirectoryBase^ parent, 
    155152        FatDirectoryEntryTypes type, unsigned cluster) 
    156153    { 
     
    175172    } 
    176173 
    177     FatDirectory::FatDirectory(String^ name, FatDirectory^ parent, unsigned cluster, FatApi^ api) 
     174    FatDirectoryBase::FatDirectoryBase(String^ name, FatDirectoryBase^ parent, unsigned cluster) 
    178175        : FatDirectoryEntry(name, parent, FatDirectoryEntryTypes::Directory, cluster) 
    179176    { 
    180         System::Diagnostics::Debug::Print(FullName); 
    181177        Entries = gcnew Dictionary<String^, FatDirectoryEntry^>(); 
    182         Api = api; 
    183  
    184         //Get the size of the directory list and read it to memory 
    185         std::vector<char> dir = api->GetFileContents(cluster); 
    186         const size_t dirCount = dir.size() / sizeof(::FatDirectory); 
    187         Directory = new ::FatDirectory[dirCount]; 
    188         memcpy(Directory, &dir.front(), dir.size()); 
     178        ReadDirectory(); 
     179    } 
     180 
     181    void FatDirectoryBase::ClearDeletedEntries() 
     182    { 
     183        std::vector<::FatDirectoryEntry> validEntries; 
    189184 
    190185        //Parse the directory structures 
    191         for (::FatDirectory* i = Directory; i != Directory + dirCount; ++i) 
     186        for (::FatDirectoryEntry* i = Directory; i != Directory + DirectorySize; ++i) 
     187        { 
     188            //Check if we have checked the last valid entry 
     189            if (i->Short.Name[0] == 0x00) 
     190                break; 
     191 
     192            //Skip deleted entries. 
     193            if (static_cast<unsigned char>(i->Short.Name[0]) == 0xE5) 
     194                continue; 
     195 
     196            if (i->Short.Attributes == 0x0F) 
     197            { 
     198                //This is a long file name. 
     199                ::FatDirectoryEntry* longFileNameBegin = i; 
     200                for (unsigned char sequence = 0; i->Short.Attributes == 0x0F; ++i) 
     201                { 
     202                    if (!(i->LongFileName.Sequence & 0x40)) //Second entry onwards 
     203                    { 
     204                        //Check that the checksum of the file name is the same as the previous 
     205                        //long file name entry, to ensure no corruption has taken place 
     206                        if ((i - 1)->LongFileName.Checksum != i->LongFileName.Checksum) 
     207                            continue; 
     208 
     209                        //Check that the sequence is one less than the previous one. 
     210                        if (sequence != i->LongFileName.Sequence + 1) 
     211                            throw gcnew ArgumentException(L"Invalid directory entry."); 
     212                    } 
     213                     
     214                    sequence = i->LongFileName.Sequence & ~0x40; 
     215                } 
     216 
     217                //Checksum the string 
     218                unsigned char sum = 0; 
     219                char* shortFileName = i->Short.Name; 
     220                for (int j = 11; j; --j) 
     221                    sum = ((sum & 1) << 7) + (sum >> 1) + *shortFileName++; 
     222 
     223                if (sum == (i - 1)->LongFileName.Checksum) 
     224                { 
     225                    //The previous few entries contained the correct file name. Save these entries 
     226                    validEntries.insert(validEntries.end(), longFileNameBegin, i); 
     227                } 
     228            } 
     229 
     230            validEntries.push_back(*i); 
     231        } 
     232 
     233        //validEntries now contains the compacted list of directory entries. Zero 
     234        //the memory used. 
     235        memset(Directory, 0, DirectorySize * sizeof(::FatDirectoryEntry)); 
     236        memcpy(Directory, &validEntries.front(), validEntries.size() * sizeof(::FatDirectory)); 
     237 
     238        //Write the entries to disk 
     239        WriteDirectory(); 
     240    } 
     241 
     242    void FatDirectoryBase::ParseDirectory() 
     243    { 
     244        //Clear the list of entries 
     245        Entries->Clear(); 
     246 
     247        //Parse the directory structures 
     248        for (::FatDirectoryEntry* i = Directory; i != Directory + DirectorySize; ++i) 
    192249        { 
    193250            //Check if we have checked the last valid entry 
     
    275332    } 
    276333 
    277     void FatDirectory::ClearDeletedEntries() 
    278     { 
    279         std::vector<::FatDirectory> validEntries; 
    280         size_t entryCount = Api->FileSize(Cluster) / sizeof(::FatDirectory); 
    281  
    282         //Parse the directory structures 
    283         for (::FatDirectory* i = Directory; i != Directory + entryCount; ++i) 
    284         { 
    285             //Check if we have checked the last valid entry 
    286             if (i->Short.Name[0] == 0x00) 
    287                 break; 
    288  
    289             //Skip deleted entries. 
    290             if (static_cast<unsigned char>(i->Short.Name[0]) == 0xE5) 
    291                 continue; 
    292  
    293             if (i->Short.Attributes == 0x0F) 
    294             { 
    295                 //This is a long file name. 
    296                 ::FatDirectory* longFileNameBegin = i; 
    297                 for (unsigned char sequence = 0; i->Short.Attributes == 0x0F; ++i) 
    298                 { 
    299                     if (!(i->LongFileName.Sequence & 0x40)) //Second entry onwards 
    300                     { 
    301                         //Check that the checksum of the file name is the same as the previous 
    302                         //long file name entry, to ensure no corruption has taken place 
    303                         if ((i - 1)->LongFileName.Checksum != i->LongFileName.Checksum) 
    304                             continue; 
    305  
    306                         //Check that the sequence is one less than the previous one. 
    307                         if (sequence != i->LongFileName.Sequence + 1) 
    308                             throw gcnew ArgumentException(L"Invalid directory entry."); 
    309                     } 
    310                      
    311                     sequence = i->LongFileName.Sequence & ~0x40; 
    312                 } 
    313  
    314                 //Checksum the string 
    315                 unsigned char sum = 0; 
    316                 char* shortFileName = i->Short.Name; 
    317                 for (int j = 11; j; --j) 
    318                     sum = ((sum & 1) << 7) + (sum >> 1) + *shortFileName++; 
    319  
    320                 if (sum == (i - 1)->LongFileName.Checksum) 
    321                 { 
    322                     //The previous few entries contained the correct file name. Save these entries 
    323                     validEntries.insert(validEntries.end(), longFileNameBegin, i); 
    324                 } 
    325             } 
    326  
    327             validEntries.push_back(*i); 
    328         } 
    329  
    330         //validEntries now contains the compacted list of directory entries. Zero 
    331         //the memory used. 
    332         memset(Directory, 0, Api->FileSize(Cluster)); 
    333         memcpy(Directory, &validEntries.front(), validEntries.size() * sizeof(::FatDirectory)); 
    334  
    335         //Write the entries to disk 
     334    FatDirectory::FatDirectory(String^ name, FatDirectoryBase^ parent, unsigned cluster, FatApi^ api) 
     335        : Api(api), 
     336          FatDirectoryBase(name, parent, cluster) 
     337    { 
     338    } 
     339 
     340    void FatDirectory::ReadDirectory() 
     341    { 
     342        std::vector<char> dir = Api->GetFileContents(Cluster); 
     343        DirectorySize = dir.size() / sizeof(::FatDirectoryEntry); 
     344        Directory = new ::FatDirectoryEntry[DirectorySize]; 
     345        memcpy(Directory, &dir.front(), dir.size()); 
     346 
     347        ParseDirectory(); 
     348    } 
     349 
     350    void FatDirectory::WriteDirectory() 
     351    { 
    336352        Api->SetFileContents(Directory, Api->FileSize(Cluster), Cluster); 
    337353    } 
  • trunk/eraser6/Eraser.Util.FileSystem/FatApi.h

    r1225 r1226  
    2929namespace Eraser { 
    3030namespace Util { 
    31     ref class FatDirectory; 
     31    ref class FatDirectoryBase; 
     32 
     33    /// Represents an abstract API to interface with FAT file systems. 
    3234    public ref class FatApi abstract 
    3335    { 
     
    4951        virtual void LoadFat() = 0; 
    5052         
    51         /// Loads the directory structure representing the directory with the given 
    52         /// volume-relative path. 
    53         FatDirectory^ LoadDirectory(String^ directory); 
     53        /// Helper function to loads the directory structure representing the 
     54        /// directory with the given volume-relative path. 
     55        /// 
     56        /// \overload LoadDirectory 
     57        FatDirectoryBase^ LoadDirectory(String^ directory); 
    5458 
    5559        /// Loads the directory structure at the given cluster. 
    56         virtual FatDirectory^ LoadDirectory(unsigned cluster, String^ name, FatDirectory^ parent) = 0; 
     60        virtual FatDirectoryBase^ LoadDirectory(unsigned cluster, String^ name, 
     61            FatDirectoryBase^ parent) = 0; 
    5762 
    5863    internal: 
     
    143148 
    144149        /// Gets the parent directory of this entry. 
    145         property FatDirectory^ Parent 
    146         { 
    147             FatDirectory^ get() { return parent; } 
     150        property FatDirectoryBase^ Parent 
     151        { 
     152            FatDirectoryBase^ get() { return parent; } 
    148153        private: 
    149             void set(FatDirectory^ value) { parent = value; } 
     154            void set(FatDirectoryBase^ value) { parent = value; } 
    150155        } 
    151156 
     
    173178        /// \param[in] type    The type of this entry. 
    174179        /// \param[in] cluster The first cluster of the file. 
    175         FatDirectoryEntry(String^ name, FatDirectory^ parent, FatDirectoryEntryTypes type, 
     180        FatDirectoryEntry(String^ name, FatDirectoryBase^ parent, FatDirectoryEntryTypes type, 
    176181            unsigned cluster); 
    177182 
    178183    private: 
    179184        String^ name; 
    180         FatDirectory^ parent; 
     185        FatDirectoryBase^ parent; 
    181186        FatDirectoryEntryTypes type; 
    182187        unsigned cluster; 
    183188    }; 
    184189 
    185     /// Represents a FAT directory list. 
    186     public ref class FatDirectory abstract : FatDirectoryEntry 
     190    /// Represents an abstract FAT directory (can also represent the root directory of 
     191    /// FAT12 and FAT16 volumes.) 
     192    public ref class FatDirectoryBase abstract : FatDirectoryEntry 
     193    { 
     194    public: 
     195        /// Constructor. 
     196        ///  
     197        /// \param[in] name    The name of the current directory. 
     198        /// \param[in] parent  The parent directory containing this directory. 
     199        /// \param[in] cluster The cluster at which the directory list starts. 
     200        FatDirectoryBase(String^ name, FatDirectoryBase^ parent, unsigned cluster); 
     201 
     202        /// Compacts the directory structure, updating the structure on-disk as well. 
     203        void ClearDeletedEntries(); 
     204 
     205        /// The list of files and subfolders in this directory. 
     206        property Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ Items 
     207        { 
     208            Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ get() 
     209            { 
     210                return Entries; 
     211            } 
     212        } 
     213 
     214    protected: 
     215        /// Reads the directory structures from disk. 
     216        ///  
     217        /// \remarks This function must set the \see Directory instance as well as the 
     218        ///          \see DirectorySize fields. Furthermore, call the \see ParseDirectory 
     219        ///          function to initialise the directory entries on-disk. 
     220        virtual void ReadDirectory() = 0; 
     221 
     222        /// Writes the directory to disk. 
     223        virtual void WriteDirectory() = 0; 
     224 
     225        /// This function reads the raw directory structures in \see Directory and 
     226        /// sets the \see Entries field for easier access to the directory entries. 
     227        void ParseDirectory(); 
     228 
     229        /// Gets the start cluster from the given directory entry. 
     230        virtual unsigned GetStartCluster(::FatDirectoryEntry& directory) = 0; 
     231 
     232    protected: 
     233        /// A pointer to the directory structure. 
     234        ::FatDirectory Directory; 
     235 
     236        /// The number of entries in the directory 
     237        size_t DirectorySize; 
     238 
     239    private: 
     240        /// The list of parsed entries in the folder. 
     241        Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ Entries; 
     242    }; 
     243 
     244    /// Represents a FAT directory file. 
     245    public ref class FatDirectory abstract : FatDirectoryBase 
    187246    { 
    188247    public: 
     
    193252        /// \param[in] cluster The cluster at which the directory list starts. 
    194253        /// \param[in] api     The FAT API object which is creating this object. 
    195         FatDirectory(String^ name, FatDirectory^ parent, unsigned cluster, FatApi^ api); 
    196  
    197         /// Compacts the directory structure. 
    198         void ClearDeletedEntries(); 
    199  
    200         /// The list of files and subfolders in this directory. 
    201         property Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ Items 
    202         { 
    203             Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ get() 
    204             { 
    205                 return Entries; 
    206             } 
    207         } 
    208  
    209     protected: 
    210         /// Gets the start cluster from the given directory entry. 
    211         virtual unsigned GetStartCluster(::FatDirectory& directory) = 0; 
     254        FatDirectory(String^ name, FatDirectoryBase^ parent, unsigned cluster, FatApi^ api); 
     255 
     256    protected: 
     257        virtual void ReadDirectory() override; 
     258        virtual void WriteDirectory() override; 
    212259 
    213260    private: 
    214         FatDirectoryFile Directory; 
    215         Collections::Generic::Dictionary<String^, FatDirectoryEntry^>^ Entries; 
    216  
    217261        FatApi^ Api; 
    218262    }; 
     
    225269 
    226270        virtual void LoadFat() override; 
    227         virtual FatDirectory^ LoadDirectory(unsigned cluster, String^ name, FatDirectory^ parent) override; 
     271        virtual FatDirectoryBase^ LoadDirectory(unsigned cluster, String^ name, 
     272            FatDirectoryBase^ parent) override; 
    228273 
    229274    internal: 
     
    235280        { 
    236281        public: 
    237             Directory(String^ name, FatDirectory^ parent, unsigned cluster, Fat12Or16Api^ api); 
     282            Directory(String^ name, FatDirectoryBase^ parent, unsigned cluster, Fat12Or16Api^ api); 
    238283 
    239284        protected: 
    240             virtual unsigned GetStartCluster(::FatDirectory& directory) override; 
     285            virtual unsigned GetStartCluster(::FatDirectoryEntry& directory) override; 
    241286        }; 
    242287 
     
    265310    public: 
    266311        virtual void LoadFat() override; 
    267         virtual FatDirectory^ LoadDirectory(unsigned cluster, String^ name, FatDirectory^ parent) override; 
     312        virtual FatDirectoryBase^ LoadDirectory(unsigned cluster, String^ name, 
     313            FatDirectoryBase^ parent) override; 
    268314 
    269315    internal: 
     
    278324        { 
    279325        public: 
    280             Directory(String^ name, FatDirectory^ parent, unsigned cluster, Fat32Api^ api); 
     326            Directory(String^ name, FatDirectoryBase^ parent, unsigned cluster, Fat32Api^ api); 
    281327 
    282328        protected: 
    283             virtual unsigned GetStartCluster(::FatDirectory& directory) override; 
     329            virtual unsigned GetStartCluster(::FatDirectoryEntry& directory) override; 
    284330        }; 
    285331    }; 
  • trunk/eraser6/Eraser.Util.FileSystem/Stdafx.h

    r1206 r1226  
    2222#pragma once 
    2323#include <windows.h> 
    24 #include <atlstr.h> 
Note: See TracChangeset for help on using the changeset viewer.