Create a place for work on creating a bootloader capable of booting Windows NT (from...
[reactos.git] / fs / fs.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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
20 #include <freeldr.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 /////////////////////////////////////////////////////////////////////////////////////////////
26 // DATA
27 /////////////////////////////////////////////////////////////////////////////////////////////
28
29 ULONG FsType = 0; // Type of filesystem on boot device, set by FsOpenVolume()
30
31 /////////////////////////////////////////////////////////////////////////////////////////////
32 // FUNCTIONS
33 /////////////////////////////////////////////////////////////////////////////////////////////
34
35 VOID FileSystemError(PCSTR ErrorString)
36 {
37 DbgPrint((DPRINT_FILESYSTEM, "%s\n", ErrorString));
38
39 UiMessageBox(ErrorString);
40 }
41
42 /*
43 *
44 * BOOLEAN FsOpenVolume(ULONG DriveNumber, ULONGLONG StartSector, ULONGLONG SectorCount, int Type);
45 *
46 * This function is called to open a disk volume for file access.
47 * It must be called before any of the file functions will work.
48 *
49 */
50 static BOOLEAN FsOpenVolume(ULONG DriveNumber, ULONGLONG StartSector, ULONGLONG SectorCount, int Type)
51 {
52 CHAR ErrorText[80];
53
54 FsType = Type;
55
56 switch (FsType)
57 {
58 case FS_FAT:
59 return FatOpenVolume(DriveNumber, StartSector, SectorCount);
60 case FS_EXT2:
61 return Ext2OpenVolume(DriveNumber, StartSector);
62 case FS_NTFS:
63 return NtfsOpenVolume(DriveNumber, StartSector);
64 case FS_ISO9660:
65 return IsoOpenVolume(DriveNumber);
66 default:
67 FsType = 0;
68 sprintf(ErrorText, "Unsupported file system. Type: 0x%x", Type);
69 FileSystemError(ErrorText);
70 }
71
72 return FALSE;
73 }
74 /*
75 *
76 * BOOLEAN FsOpenBootVolume()
77 *
78 * This function is called to open the boot disk volume for file access.
79 * It must be called before any of the file functions will work.
80 */
81 BOOLEAN FsOpenBootVolume()
82 {
83 ULONG DriveNumber;
84 ULONGLONG StartSector;
85 ULONGLONG SectorCount;
86 int Type;
87
88 if (! MachDiskGetBootVolume(&DriveNumber, &StartSector, &SectorCount, &Type))
89 {
90 FileSystemError("Unable to locate boot partition\n");
91 return FALSE;
92 }
93
94 return FsOpenVolume(DriveNumber, StartSector, SectorCount, Type);
95 }
96
97 BOOLEAN FsOpenSystemVolume(char *SystemPath, char *RemainingPath, PULONG Device)
98 {
99 ULONG DriveNumber;
100 ULONGLONG StartSector;
101 ULONGLONG SectorCount;
102 int Type;
103
104 if (! MachDiskGetSystemVolume(SystemPath, RemainingPath, Device,
105 &DriveNumber, &StartSector, &SectorCount,
106 &Type))
107 {
108 FileSystemError("Unable to locate system partition\n");
109 return FALSE;
110 }
111
112 return FsOpenVolume(DriveNumber, StartSector, SectorCount, Type);
113 }
114
115
116 PFILE FsOpenFile(PCSTR FileName)
117 {
118 PFILE FileHandle = NULL;
119
120 //
121 // Print status message
122 //
123 DbgPrint((DPRINT_FILESYSTEM, "Opening file '%s'...\n", FileName));
124
125 //
126 // Check and see if the first character is '\' or '/' and remove it if so
127 //
128 while ((*FileName == '\\') || (*FileName == '/'))
129 {
130 FileName++;
131 }
132
133 //
134 // Check file system type and pass off to appropriate handler
135 //
136 switch (FsType)
137 {
138 case FS_FAT:
139 FileHandle = FatOpenFile(FileName);
140 break;
141 case FS_ISO9660:
142 FileHandle = IsoOpenFile(FileName);
143 break;
144 case FS_EXT2:
145 FileHandle = Ext2OpenFile(FileName);
146 break;
147 case FS_NTFS:
148 FileHandle = NtfsOpenFile(FileName);
149 break;
150 default:
151 FileSystemError("Error: Unknown filesystem.");
152 break;
153 }
154
155 #ifdef DEBUG
156 //
157 // Check return value
158 //
159 if (FileHandle != NULL)
160 {
161 DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
162 }
163 else
164 {
165 DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() failed.\n"));
166 }
167 #endif // defined DEBUG
168
169 return FileHandle;
170 }
171
172 VOID FsCloseFile(PFILE FileHandle)
173 {
174 switch (FsType)
175 {
176 case FS_FAT:
177 case FS_ISO9660:
178 case FS_EXT2:
179 break;
180 case FS_NTFS:
181 NtfsCloseFile(FileHandle);
182 break;
183 default:
184 FileSystemError("Error: Unknown filesystem.");
185 break;
186 }
187 }
188
189 /*
190 * ReadFile()
191 * returns number of bytes read or EOF
192 */
193 BOOLEAN FsReadFile(PFILE FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
194 {
195 ULONGLONG BytesReadBig;
196 BOOLEAN Success;
197
198 //
199 // Set the number of bytes read equal to zero
200 //
201 if (BytesRead != NULL)
202 {
203 *BytesRead = 0;
204 }
205
206 switch (FsType)
207 {
208 case FS_FAT:
209
210 return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
211
212 case FS_ISO9660:
213
214 return IsoReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
215
216 case FS_EXT2:
217
218 //return Ext2ReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
219 Success = Ext2ReadFile(FileHandle, BytesToRead, &BytesReadBig, Buffer);
220 *BytesRead = (ULONG)BytesReadBig;
221 return Success;
222
223 case FS_NTFS:
224
225 return NtfsReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
226
227 default:
228
229 FileSystemError("Unknown file system.");
230 return FALSE;
231 }
232
233 return FALSE;
234 }
235
236 ULONG FsGetFileSize(PFILE FileHandle)
237 {
238 switch (FsType)
239 {
240 case FS_FAT:
241
242 return FatGetFileSize(FileHandle);
243
244 case FS_ISO9660:
245
246 return IsoGetFileSize(FileHandle);
247
248 case FS_EXT2:
249
250 return Ext2GetFileSize(FileHandle);
251
252 case FS_NTFS:
253
254 return NtfsGetFileSize(FileHandle);
255
256 default:
257 FileSystemError("Unknown file system.");
258 break;
259 }
260
261 return 0;
262 }
263
264 VOID FsSetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
265 {
266 switch (FsType)
267 {
268 case FS_FAT:
269
270 FatSetFilePointer(FileHandle, NewFilePointer);
271 break;
272
273 case FS_ISO9660:
274
275 IsoSetFilePointer(FileHandle, NewFilePointer);
276 break;
277
278 case FS_EXT2:
279
280 Ext2SetFilePointer(FileHandle, NewFilePointer);
281 break;
282
283 case FS_NTFS:
284
285 NtfsSetFilePointer(FileHandle, NewFilePointer);
286 break;
287
288 default:
289 FileSystemError("Unknown file system.");
290 break;
291 }
292 }
293
294 ULONG FsGetFilePointer(PFILE FileHandle)
295 {
296 switch (FsType)
297 {
298 case FS_FAT:
299
300 return FatGetFilePointer(FileHandle);
301 break;
302
303 case FS_ISO9660:
304
305 return IsoGetFilePointer(FileHandle);
306 break;
307
308 case FS_EXT2:
309
310 return Ext2GetFilePointer(FileHandle);
311 break;
312
313 case FS_NTFS:
314
315 return NtfsGetFilePointer(FileHandle);
316 break;
317
318 default:
319 FileSystemError("Unknown file system.");
320 break;
321 }
322
323 return 0;
324 }
325
326 BOOLEAN FsIsEndOfFile(PFILE FileHandle)
327 {
328 if (FsGetFilePointer(FileHandle) >= FsGetFileSize(FileHandle))
329 {
330 return TRUE;
331 }
332 else
333 {
334 return FALSE;
335 }
336 }
337
338 /*
339 * FsGetNumPathParts()
340 * This function parses a path in the form of dir1\dir2\file1.ext
341 * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
342 */
343 ULONG FsGetNumPathParts(PCSTR Path)
344 {
345 size_t i;
346 ULONG num;
347
348 for (i=0,num=0; i<strlen(Path); i++)
349 {
350 if ((Path[i] == '\\') || (Path[i] == '/'))
351 {
352 num++;
353 }
354 }
355 num++;
356
357 DbgPrint((DPRINT_FILESYSTEM, "FatGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num));
358
359 return num;
360 }
361
362 /*
363 * FsGetFirstNameFromPath()
364 * This function parses a path in the form of dir1\dir2\file1.ext
365 * and puts the first name of the path (e.g. "dir1") in buffer
366 * compatible with the MSDOS directory structure
367 */
368 VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
369 {
370 size_t i;
371
372 // Copy all the characters up to the end of the
373 // string or until we hit a '\' character
374 // and put them in Buffer
375 for (i=0; i<strlen(Path); i++)
376 {
377 if ((Path[i] == '\\') || (Path[i] == '/'))
378 {
379 break;
380 }
381 else
382 {
383 Buffer[i] = Path[i];
384 }
385 }
386
387 Buffer[i] = 0;
388
389 DbgPrint((DPRINT_FILESYSTEM, "FatGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer));
390 }