fixed some signed/unsigned comparison warnings with -Wsign-compare
[reactos.git] / reactos / drivers / fs / ntfs / mft.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/fs/ntfs/mft.c
24 * PURPOSE: NTFS filesystem driver
25 * PROGRAMMER: Eric Kohl
26 * Updated by Valentin Verkhovsky 2003/09/12
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ddk/ntddk.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36 #include "ntfs.h"
37
38
39 //#define __min(a,b) (((a) < (b)) ? (a) : (b))
40
41
42 /* FUNCTIONS ****************************************************************/
43
44
45 NTSTATUS
46 NtfsOpenMft (PDEVICE_EXTENSION Vcb)
47 {
48 // PVOID Bitmap;
49 PFILE_RECORD_HEADER MftRecord;
50 PFILE_RECORD_HEADER FileRecord;
51 // PATTRIBUTE Attribute;
52 // PATTRIBUTE AttrData;
53 // PRESIDENT_ATTRIBUTE ResAttr;
54
55 NTSTATUS Status;
56 ULONG BytesPerFileRecord;
57 ULONG n;
58 ULONG i;
59
60 DPRINT1("NtfsOpenMft() called\n");
61
62 BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
63
64 MftRecord = ExAllocatePool(NonPagedPool,
65 BytesPerFileRecord);
66 if (MftRecord == NULL)
67 {
68 return STATUS_INSUFFICIENT_RESOURCES;
69 }
70
71 Status = NtfsReadSectors(Vcb->StorageDevice,
72 Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
73 BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector,
74 Vcb->NtfsInfo.BytesPerSector,
75 (PVOID)MftRecord,
76 FALSE);
77 if (!NT_SUCCESS(Status))
78 {
79 ExFreePool(MftRecord);
80 return Status;
81 }
82
83
84 FixupUpdateSequenceArray(MftRecord);
85
86 // Attribute = FindAttribute(MftRecord, AttributeBitmap, 0);
87
88 /* Get number of file records*/
89 n = AttributeDataLength (FindAttribute (MftRecord, AttributeData, 0))
90 / BytesPerFileRecord;
91
92 FileRecord = ExAllocatePool(NonPagedPool, BytesPerFileRecord);
93 if (FileRecord == NULL)
94 {
95 ExFreePool(MftRecord);
96 return(STATUS_INSUFFICIENT_RESOURCES);
97 }
98
99 /* Enumerate MFT Records */
100 DPRINT("Enumerate MFT records\n");
101 for ( i=0; i < n; i++)
102 {
103 ReadFileRecord(Vcb, i, FileRecord, MftRecord);
104
105 if (FileRecord->Ntfs.Type == NRH_FILE_TYPE && (FileRecord->Flags & FRH_IN_USE))
106 {
107 DPRINT("\nFile %lu\n\n", i);
108
109 /* Enumerate attributtes */
110 NtfsDumpFileAttributes (FileRecord);
111 DbgPrint("\n\n");
112 }
113 }
114
115 ExFreePool(FileRecord);
116 ExFreePool(MftRecord);
117
118 return Status;
119 }
120
121
122 PATTRIBUTE
123 FindAttribute (PFILE_RECORD_HEADER FileRecord,
124 ATTRIBUTE_TYPE Type,
125 PWSTR name)
126 {
127 PATTRIBUTE Attribute;
128
129 Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
130 while (Attribute < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
131 Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
132 {
133 if (Attribute->AttributeType == Type)
134 {
135 return Attribute;
136 }
137
138 Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
139 }
140
141 return NULL;
142 }
143
144
145 ULONG
146 AttributeAllocatedLength (PATTRIBUTE Attribute)
147 {
148 if (Attribute->Nonresident)
149 {
150 return ((PNONRESIDENT_ATTRIBUTE)Attribute)->AllocatedSize;
151 }
152
153 return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
154 }
155
156
157 ULONG
158 AttributeDataLength (PATTRIBUTE Attribute)
159 {
160 if (Attribute->Nonresident)
161 {
162 return ((PNONRESIDENT_ATTRIBUTE)Attribute)->DataSize;
163 }
164
165 return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
166 }
167
168
169 VOID
170 ReadAttribute (PATTRIBUTE attr,
171 PVOID buffer,
172 PDEVICE_EXTENSION Vcb,
173 PDEVICE_OBJECT DeviceObject)
174 {
175 if (attr->Nonresident == FALSE)
176 {
177 memcpy (buffer,
178 (PVOID)((ULONG_PTR)attr + ((PRESIDENT_ATTRIBUTE)attr)->ValueOffset),
179 ((PRESIDENT_ATTRIBUTE)attr)->ValueLength);
180 }
181
182 PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
183 ReadExternalAttribute(Vcb, NresAttr, 0, (ULONG)(NresAttr->LastVcn) + 1,
184 buffer);
185 }
186
187
188
189
190
191 NTSTATUS
192 ReadFileRecord (PDEVICE_EXTENSION Vcb,
193 ULONG index,
194 PFILE_RECORD_HEADER file,
195 PFILE_RECORD_HEADER Mft)
196 {
197 PVOID p;
198 ULONG BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
199 ULONG clusters = max(BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster, 1);
200
201 p = ExAllocatePool(NonPagedPool, clusters * Vcb->NtfsInfo.BytesPerCluster);
202
203 ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster;
204
205 ReadVCN (Vcb, Mft, AttributeData, vcn, clusters, p);
206
207 LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1;
208
209 ULONG n = m > 0 ? (index & m) : 0;
210
211 memcpy(file, (PVOID)((ULONG_PTR)p + n * BytesPerFileRecord), BytesPerFileRecord);
212
213 ExFreePool(p);
214
215 FixupUpdateSequenceArray(file);
216
217 return STATUS_SUCCESS;
218 }
219
220
221
222 VOID
223 ReadExternalAttribute (PDEVICE_EXTENSION Vcb,
224 PNONRESIDENT_ATTRIBUTE NresAttr,
225 ULONGLONG vcn,
226 ULONG count,
227 PVOID buffer)
228 {
229 ULONGLONG lcn;
230 ULONGLONG runcount;
231 ULONG readcount;
232 ULONG left;
233
234 PUCHAR bytes = (PUCHAR)buffer;
235
236 for (left = count; left>0; left -=readcount)
237 {
238 FindRun(NresAttr, vcn, &lcn, &runcount);
239
240 // readcount = (ULONG)(__min(runcount, left));
241 readcount = (ULONG)min (runcount, left);
242
243
244 ULONG n = readcount * Vcb->NtfsInfo.BytesPerCluster;
245
246 if (lcn == 0)
247 memset(bytes, 0, n);
248 else
249 ReadLCN(Vcb, lcn, readcount, bytes);
250
251 vcn += readcount;
252 bytes += n;
253
254
255 }
256 }
257
258
259 VOID
260 ReadVCN (PDEVICE_EXTENSION Vcb,
261 PFILE_RECORD_HEADER file,
262 ATTRIBUTE_TYPE type,
263 ULONGLONG vcn,
264 ULONG count,
265 PVOID buffer)
266 {
267 PNONRESIDENT_ATTRIBUTE NresAttr;
268 PATTRIBUTE attr;
269
270 attr = FindAttribute(file, type, 0);
271
272 NresAttr = (PNONRESIDENT_ATTRIBUTE) attr;
273
274 if (NresAttr == 0 || (vcn < NresAttr->StartVcn ||vcn > NresAttr->LastVcn))
275 {
276 // PATTRIBUTE attrList = FindAttribute(file,AttributeAttributeList,0);
277 DbgPrint("Exeption \n");
278 // KeDebugCheck(0);
279 }
280
281 ReadExternalAttribute(Vcb, NresAttr, vcn, count, buffer);
282 }
283
284
285 BOOL bitset(PUCHAR bitmap, ULONG i)
286 {
287 return (bitmap[i>>3] & (1 << (i & 7))) !=0;
288 }
289
290
291 VOID FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)
292 {
293 PUSHORT usa = (PUSHORT)((ULONG_PTR)file + file->Ntfs.UsaOffset);
294 PUSHORT sector = (PUSHORT)file;
295 ULONG i;
296
297 for( i =1; i < file->Ntfs.UsaCount; i++)
298 {
299 sector[255] = usa[i];
300 sector += 256;
301
302 }
303
304 }
305
306
307 NTSTATUS
308 ReadLCN (PDEVICE_EXTENSION Vcb,
309 ULONGLONG lcn,
310 ULONG count,
311 PVOID buffer)
312 {
313 LARGE_INTEGER DiskSector;
314
315 DiskSector.QuadPart = lcn;
316
317 return NtfsReadSectors (Vcb->StorageDevice,
318 DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
319 count * Vcb->NtfsInfo.SectorsPerCluster,
320 Vcb->NtfsInfo.BytesPerSector,
321 buffer,
322 FALSE);
323 }
324
325 /* EOF */