Changeset 1228


Ignore:
Timestamp:
9/30/2009 3:22:33 AM (5 years ago)
Author:
lowjoel
Message:

Treat the FAT12/FAT16 root directory specially as it is part of the reserved area.

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

Legend:

Unmodified
Added
Removed
  • trunk/eraser6/Eraser.Util.FileSystem/Fat12Or16Api.cpp

    r1226 r1228  
    3131    { 
    3232        //Sanity checks: check that this volume is FAT12 or FAT16! 
    33         if (info->VolumeFormat != L"FAT") 
     33        if (info->VolumeFormat != L"FAT12" && info->VolumeFormat != "FAT16") 
    3434            throw gcnew ArgumentException(L"The volume provided is not a FAT12 or FAT16 volume."); 
    3535    } 
     
    3838    { 
    3939        //Sanity checks: check that this volume is FAT12 or FAT16! 
    40         if (info->VolumeFormat != L"FAT") 
     40        if (info->VolumeFormat != L"FAT12" && info->VolumeFormat != "FAT16") 
    4141            throw gcnew ArgumentException(L"The volume provided is not a FAT12 or FAT16 volume."); 
    4242    } 
     
    5858        FatDirectoryBase^ parent) 
    5959    { 
     60        //Return the root directory if we get cluster 0, name is blank and the parent is null 
     61        if (cluster == 0 && name == String::Empty && parent == nullptr) 
     62            return gcnew RootDirectory(this); 
    6063        return gcnew Directory(name, parent, cluster, this); 
    6164    } 
     
    7275    unsigned Fat12Or16Api::DirectoryToCluster(String^ path) 
    7376    { 
    74         throw gcnew NotImplementedException(); 
     77        //The path must start with a backslash as it must be volume-relative. 
     78        if (path->Length != 0 && path[0] != L'\\') 
     79            throw gcnew ArgumentException(L"The path provided is not volume relative. " + 
     80                gcnew String(L"Volume relative paths must begin with a backslash.")); 
     81 
     82        //Chop the path into it's constituent directory components 
     83        array<String^>^ components = path->Split(Path::DirectorySeparatorChar, 
     84            Path::AltDirectorySeparatorChar); 
     85 
     86        //Traverse the directories until we get the cluster we want. 
     87        unsigned cluster = 0; 
     88        FatDirectoryBase^ parentDir = gcnew RootDirectory(this); 
     89        for each (String^ component in components) 
     90        { 
     91            if (component == String::Empty) 
     92                break; 
     93 
     94            parentDir = LoadDirectory(cluster, parentDir == nullptr ? nullptr : parentDir->Name, 
     95                parentDir); 
     96            cluster = parentDir->Items[component]->Cluster; 
     97        } 
     98 
     99        return cluster; 
    75100    } 
    76101 
     
    80105            BootSector->SectorCount32 : BootSector->SectorCount16); 
    81106        unsigned long long availableSectors = numberOfSectors - ( 
    82             BootSector->ReservedSectorCount +                                                               //Reserved area 
    83             BootSector->FatCount * BootSector->SectorsPerFat +                                              //FAT area 
     107            BootSector->ReservedSectorCount +                                                                   //Reserved area 
     108            BootSector->FatCount * BootSector->SectorsPerFat +                                                  //FAT area 
    84109            (BootSector->RootDirectoryEntryCount * sizeof(::FatDirectoryEntry) / (ClusterSize / SectorSize))    //Root directory area 
    85110        ); 
     
    87112 
    88113        return numberOfClusters < 0xFF0; 
     114    } 
     115 
     116    Fat12Or16Api::RootDirectory::RootDirectory(Fat12Or16Api^ api) 
     117        : Api(api), 
     118          FatDirectoryBase(String::Empty, nullptr, 0) 
     119    { 
     120    } 
     121 
     122    void Fat12Or16Api::RootDirectory::ReadDirectory() 
     123    { 
     124        //Calculate the starting sector of the root directory 
     125        unsigned long long startPos = Api->SectorToOffset(Api->BootSector->ReservedSectorCount + 
     126            Api->BootSector->FatCount * Api->BootSector->SectorsPerFat); 
     127        int directoryLength = Api->BootSector->RootDirectoryEntryCount * 
     128            sizeof(::FatDirectoryEntry); 
     129 
     130        array<Byte>^ buffer = gcnew array<Byte>(directoryLength); 
     131        Api->VolumeStream->Seek(startPos, SeekOrigin::Begin); 
     132        Api->VolumeStream->Read(buffer, 0, directoryLength); 
     133 
     134        DirectorySize = Api->BootSector->RootDirectoryEntryCount; 
     135        Directory = new ::FatDirectoryEntry[DirectorySize]; 
     136        Marshal::Copy(buffer, 0, static_cast<IntPtr>(Directory), directoryLength); 
     137 
     138        ParseDirectory(); 
     139    } 
     140 
     141    void Fat12Or16Api::RootDirectory::WriteDirectory() 
     142    { 
     143        //Calculate the starting sector of the root directory 
     144        unsigned long long startPos = Api->SectorToOffset(Api->BootSector->ReservedSectorCount + 
     145            Api->BootSector->FatCount * Api->BootSector->SectorsPerFat); 
     146        int directoryLength = Api->BootSector->RootDirectoryEntryCount * 
     147            sizeof(::FatDirectoryEntry); 
     148 
     149        array<Byte>^ buffer = gcnew array<Byte>(directoryLength); 
     150        Marshal::Copy(static_cast<IntPtr>(Directory), buffer, 0, directoryLength); 
     151        Api->VolumeStream->Seek(startPos, SeekOrigin::Begin); 
     152        Api->VolumeStream->Write(buffer, 0, directoryLength); 
     153    } 
     154 
     155    unsigned Fat12Or16Api::RootDirectory::GetStartCluster(::FatDirectoryEntry& directory) 
     156    { 
     157        if (directory.Short.Attributes == 0x0F) 
     158            throw gcnew ArgumentException(L"The provided directory is a long file name."); 
     159        return directory.Short.StartClusterLow; 
    89160    } 
    90161 
  • trunk/eraser6/Eraser.Util.FileSystem/FatApi.h

    r1226 r1228  
    277277 
    278278    protected: 
     279        ref class RootDirectory : FatDirectoryBase 
     280        { 
     281        public: 
     282            RootDirectory(Fat12Or16Api^ api); 
     283 
     284        protected: 
     285            virtual void ReadDirectory() override; 
     286            virtual void WriteDirectory() override; 
     287            virtual unsigned GetStartCluster(::FatDirectoryEntry& directory) override; 
     288 
     289        private: 
     290            Fat12Or16Api^ Api; 
     291        }; 
     292 
    279293        ref class Directory : FatDirectory 
    280294        { 
Note: See TracChangeset for help on using the changeset viewer.