source: trunk/eraser6/Eraser.Util.FileSystem/Fat32Api.cpp @ 1239

Revision 1239, 5.2 KB checked in by lowjoel, 5 years ago (diff)

Got rid of the SectorSize? and ClusterSize? fields in the FatApi? class, replacing them with the values straight from the BootSector? field. For the rest of the protected fields, place them into properties to allow ABI compatibility.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2009 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22#include <stdafx.h>
23#include "FatApi.h"
24
25using namespace System::IO;
26using namespace System::Runtime::InteropServices;
27
28namespace Eraser {
29namespace Util {
30    Fat32Api::Fat32Api(VolumeInfo^ info) : FatApi(info)
31    {
32        //Sanity checks: check that this volume is FAT32!
33        if (info->VolumeFormat != L"FAT32")
34            throw gcnew ArgumentException(L"The volume provided is not a FAT32 volume.");
35    }
36
37    Fat32Api::Fat32Api(VolumeInfo^ info, Stream^ stream) : FatApi(info, stream)
38    {
39        //Sanity checks: check that this volume is FAT32!
40        if (info->VolumeFormat != L"FAT32")
41            throw gcnew ArgumentException(L"The volume provided is not a FAT32 volume.");
42    }
43
44    void Fat32Api::LoadFat()
45    {
46        Fat = new char[SectorSizeToSize(BootSector->Fat32ParameterBlock.SectorsPerFat)];
47
48        //Seek to the FAT
49        VolumeStream->Seek(SectorToOffset(BootSector->ReservedSectorCount), SeekOrigin::Begin);
50
51        //Read the FAT
52        array<Byte>^ buffer = gcnew array<Byte>(SectorSizeToSize(BootSector->Fat32ParameterBlock.SectorsPerFat));
53        VolumeStream->Read(buffer, 0, SectorSizeToSize(BootSector->Fat32ParameterBlock.SectorsPerFat));
54        Marshal::Copy(buffer, 0, static_cast<IntPtr>(Fat), buffer->Length);
55    }
56
57    FatDirectoryBase^ Fat32Api::LoadDirectory(unsigned cluster, String^ name,
58        FatDirectoryBase^ parent)
59    {
60        return gcnew Directory(name, parent, cluster, this);
61    }
62
63    long long Fat32Api::ClusterToOffset(unsigned cluster)
64    {
65        unsigned long long sector = BootSector->ReservedSectorCount +               //Reserved area
66            BootSector->FatCount * BootSector->Fat32ParameterBlock.SectorsPerFat +  //FAT area
67            (static_cast<unsigned long long>(cluster) - 2) *  BootSector->SectorsPerCluster;
68        return SectorToOffset(sector);
69    }
70
71    bool Fat32Api::IsClusterAllocated(unsigned cluster)
72    {
73        unsigned* fatPtr = reinterpret_cast<unsigned*>(Fat);
74        if (
75            fatPtr[cluster] <= 0x00000001 ||
76            (fatPtr[cluster] >= 0x0FFFFFF0 && fatPtr[cluster] <= 0x0FFFFFF6) ||
77            fatPtr[cluster] == 0x0FFFFFF7
78        )
79            return false;
80
81        return true;
82    }
83
84    unsigned Fat32Api::GetNextCluster(unsigned cluster)
85    {
86        unsigned* fatPtr = reinterpret_cast<unsigned*>(Fat);
87        if (fatPtr[cluster] <= 0x00000001 || (fatPtr[cluster] >= 0x0FFFFFF0 && fatPtr[cluster] <= 0x0FFFFFF6))
88            throw gcnew ArgumentException(L"Invalid FAT cluster: cluster is marked free.");
89        else if (fatPtr[cluster] == 0x0FFFFFF7)
90            throw gcnew ArgumentException(L"Invalid FAT cluster: cluster is marked bad.");
91        else if (fatPtr[cluster] >= 0x0FFFFFF8)
92            return 0xFFFFFFFF;
93        else
94            return fatPtr[cluster];
95    }
96
97    unsigned Fat32Api::FileSize(unsigned cluster)
98    {
99        unsigned* fatPtr = reinterpret_cast<unsigned*>(Fat);
100        for (unsigned result = 1; ; ++result)
101        {
102            if (fatPtr[cluster] <= 0x00000001 || (fatPtr[cluster] >= 0x0FFFFFF0 && fatPtr[cluster] <= 0x0FFFFFF6))
103                throw gcnew ArgumentException(L"Invalid FAT cluster: cluster is marked free.");
104            else if (fatPtr[cluster] == 0x0FFFFFF7)
105                throw gcnew ArgumentException(L"Invalid FAT cluster: cluster is marked bad.");
106            else if (fatPtr[cluster] >= 0x0FFFFFF8)
107                return ClusterSizeToSize(result);
108            else
109                cluster = fatPtr[cluster];
110        }
111    }
112
113    unsigned Fat32Api::DirectoryToCluster(String^ path)
114    {
115        //The path must start with a backslash as it must be volume-relative.
116        if (path->Length != 0)
117        {
118            if (path[0] != L'\\')
119                throw gcnew ArgumentException(L"The path provided is not volume relative. " +
120                    gcnew String(L"Volume relative paths must begin with a backslash."));
121            path = path->Remove(0, 1);
122        }
123
124        //Chop the path into it's constituent directory components
125        array<String^>^ components = path->Split(Path::DirectorySeparatorChar,
126            Path::AltDirectorySeparatorChar);
127
128        //Traverse the directories until we get the cluster we want.
129        unsigned cluster = BootSector->Fat32ParameterBlock.RootDirectoryCluster;
130        FatDirectoryBase^ parentDir = nullptr;
131        for each (String^ component in components)
132        {
133            if (String::IsNullOrEmpty(component))
134                break;
135
136            parentDir = LoadDirectory(cluster, parentDir == nullptr ? String::Empty : parentDir->Name,
137                parentDir);
138            cluster = parentDir->Items[component]->Cluster;
139        }
140
141        return cluster;
142    }
143
144    Fat32Api::Directory::Directory(String^ name, FatDirectoryBase^ parent, unsigned cluster, Fat32Api^ api)
145        : FatDirectory(name, parent, cluster, api)
146    {
147    }
148
149    unsigned Fat32Api::Directory::GetStartCluster(::FatDirectoryEntry& directory)
150    {
151        if (directory.Short.Attributes == 0x0F)
152            throw gcnew ArgumentException(L"The provided directory is a long file name.");
153        return directory.Short.StartClusterLow | (unsigned(directory.Short.StartClusterHigh) << 16);
154    }
155}
156}
Note: See TracBrowser for help on using the repository browser.