3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
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.
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.
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.
32 #define SECTORSIZE 2048
34 static ULONG IsoRootSector
; // Starting sector of the root directory
35 static ULONG IsoRootLength
; // Length of the root directory
37 ULONG IsoDriveNumber
= 0;
40 BOOL
IsoOpenVolume(ULONG DriveNumber
)
44 // DbgPrint((DPRINT_FILESYSTEM, "IsoOpenVolume() DriveNumber = 0x%x VolumeStartSector = 16\n", DriveNumber));
45 printf("IsoOpenVolume() DriveNumber = 0x%x\n", DriveNumber
);
47 // Store the drive number
48 IsoDriveNumber
= DriveNumber
;
53 Pvd
= AllocateMemory(SECTORSIZE
);
55 if (!BiosInt13ReadExtended(DriveNumber
, 16, 1, Pvd
))
57 FileSystemError("Failed to read the PVD.");
62 IsoRootSector
= Pvd
->RootDirRecord
.ExtentLocationL
;
63 IsoRootLength
= Pvd
->RootDirRecord
.DataLengthL
;
67 // DbgPrint((DPRINT_FILESYSTEM, "IsoRootSector = %u IsoRootLegth = %u\n", IsoRootSector, IsoRootLength));
68 printf("IsoRootSector = %u IsoRootLegth = %u\n", IsoRootSector
, IsoRootLength
);
74 static BOOL
IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer
, UINT32 DirectoryLength
, PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
81 // DbgPrint((DPRINT_FILESYSTEM, "IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer, DirectoryLength, FileName));
82 printf("IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer
, DirectoryLength
, FileName
);
84 memset(Name
, 0, 32 * sizeof(UCHAR
));
87 Record
= (PDIR_RECORD
)DirectoryBuffer
;
90 Offset
= Offset
+ Record
->RecordLength
;
91 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
93 if (Record
->RecordLength
== 0)
95 Offset
= ROUND_UP(Offset
, SECTORSIZE
);
96 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
99 if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 0)
101 // DbgPrint((DPRINT_FILESYSTEM, "Name '.'\n"));
102 printf("Name '.'\n");
104 else if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 1)
106 // DbgPrint((DPRINT_FILESYSTEM, "Name '..'\n"));
107 printf("Name '..'\n");
111 for (i
= 0; i
< Record
->FileIdLength
&& Record
->FileId
[i
] != ';'; i
++)
112 Name
[i
] = Record
->FileId
[i
];
114 // DbgPrint((DPRINT_FILESYSTEM, "Name '%s'\n", Name));
115 printf("Name '%s'\n", Name
);
117 if (strlen(FileName
) == strlen(Name
) && stricmp(FileName
, Name
) == 0)
119 IsoFileInfoPointer
->FileStart
= Record
->ExtentLocationL
;
120 IsoFileInfoPointer
->FileSize
= Record
->DataLengthL
;
121 IsoFileInfoPointer
->FilePointer
= 0;
122 IsoFileInfoPointer
->Directory
= (Record
->FileFlags
& 0x02)?TRUE
:FALSE
;
129 if (Offset
>= DirectoryLength
)
132 memset(Name
, 0, 32 * sizeof(UCHAR
));
140 static PVOID
IsoBufferDirectory(UINT32 DirectoryStartSector
, UINT32 DirectoryLength
)
142 PVOID DirectoryBuffer
;
145 // DbgPrint((DPRINT_FILESYSTEM, "IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector, DirectoryLength));
146 printf("IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector
, DirectoryLength
);
149 // Attempt to allocate memory for directory buffer
151 // DbgPrint((DPRINT_FILESYSTEM, "Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength));
152 printf("Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength
);
153 DirectoryBuffer
= AllocateMemory(DirectoryLength
);
155 if (DirectoryBuffer
== NULL
)
160 SectorCount
= ROUND_UP(DirectoryLength
, SECTORSIZE
) / SECTORSIZE
;
161 // DbgPrint((DPRINT_FILESYSTEM, "Trying to read (DirectoryCount) %d sectors.\n", SectorCount));
162 printf("Trying to read (DirectoryCount) %d sectors.\n", SectorCount
);
165 // Now read directory contents into DirectoryBuffer
167 if (!BiosInt13ReadExtended(IsoDriveNumber
, DirectoryStartSector
, SectorCount
, DirectoryBuffer
))
169 FreeMemory(DirectoryBuffer
);
173 return DirectoryBuffer
;
178 * IsoGetNumPathParts()
179 * This function parses a path in the form of dir1\dir2\file1.ext
180 * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
182 static ULONG
IsoGetNumPathParts(PUCHAR Path
)
187 for (i
=0,num
=0; i
<(int)strlen(Path
); i
++)
196 // DbgPrint((DPRINT_FILESYSTEM, "IsoGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num));
197 printf("IsoGetNumPathParts() Path = %s NumPathParts = %d\n", Path
, num
);
204 * IsoGetFirstNameFromPath()
205 * This function parses a path in the form of dir1\dir2\file1.ext
206 * and puts the first name of the path (e.g. "dir1") in buffer
207 * compatible with the MSDOS directory structure
209 static VOID
IsoGetFirstNameFromPath(PUCHAR Buffer
, PUCHAR Path
)
213 // Copy all the characters up to the end of the
214 // string or until we hit a '\' character
215 // and put them in Buffer
216 for (i
=0; i
<(int)strlen(Path
); i
++)
230 // DbgPrint((DPRINT_FILESYSTEM, "IsoGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer));
231 printf("IsoGetFirstNameFromPath() Path = %s FirstName = %s\n", Path
, Buffer
);
237 * This function searches the file system for the
238 * specified filename and fills in an ISO_FILE_INFO structure
239 * with info describing the file, etc. returns true
240 * if the file exists or false otherwise
242 static BOOL
IsoLookupFile(PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
245 ULONG NumberOfPathParts
;
247 PVOID DirectoryBuffer
;
248 UINT32 DirectorySector
;
249 UINT32 DirectoryLength
;
250 ISO_FILE_INFO IsoFileInfo
;
252 // DbgPrint((DPRINT_FILESYSTEM, "IsoLookupFile() FileName = %s\n", FileName));
253 printf("IsoLookupFile() FileName = %s\n", FileName
);
255 memset(IsoFileInfoPointer
, 0, sizeof(ISO_FILE_INFO
));
258 // Check and see if the first character is '\' and remove it if so
260 while (*FileName
== '\\')
266 // Figure out how many sub-directories we are nested in
268 NumberOfPathParts
= IsoGetNumPathParts(FileName
);
270 DirectorySector
= IsoRootSector
;
271 DirectoryLength
= IsoRootLength
;
274 // Loop once for each part
276 for (i
=0; i
<NumberOfPathParts
; i
++)
279 // Get first path part
281 IsoGetFirstNameFromPath(PathPart
, FileName
);
284 // Advance to the next part of the path
286 for (; (*FileName
!= '\\') && (*FileName
!= '\0'); FileName
++)
292 // Buffer the directory contents
294 DirectoryBuffer
= IsoBufferDirectory(DirectorySector
, DirectoryLength
);
295 if (DirectoryBuffer
== NULL
)
301 // Search for file name in directory
303 if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer
, DirectoryLength
, PathPart
, &IsoFileInfo
))
305 FreeMemory(DirectoryBuffer
);
309 FreeMemory(DirectoryBuffer
);
312 // If we have another sub-directory to go then
313 // grab the start sector and file size
315 if ((i
+1) < NumberOfPathParts
)
317 DirectorySector
= IsoFileInfo
.FileStart
;
318 DirectoryLength
= IsoFileInfo
.FileSize
;
323 memcpy(IsoFileInfoPointer
, &IsoFileInfo
, sizeof(ISO_FILE_INFO
));
331 * Tries to open the file 'name' and returns true or false
332 * for success and failure respectively
334 FILE* IsoOpenFile(PUCHAR FileName
)
336 ISO_FILE_INFO TempFileInfo
;
337 PISO_FILE_INFO FileHandle
;
339 // DbgPrint((DPRINT_FILESYSTEM, "IsoOpenFile() FileName = %s\n", FileName));
340 printf("IsoOpenFile() FileName = %s\n", FileName
);
342 if (!IsoLookupFile(FileName
, &TempFileInfo
))
347 FileHandle
= AllocateMemory(sizeof(ISO_FILE_INFO
));
349 if (FileHandle
== NULL
)
354 memcpy(FileHandle
, &TempFileInfo
, sizeof(ISO_FILE_INFO
));
356 return (FILE*)FileHandle
;
361 * IsoReadPartialSector()
362 * Reads part of a cluster into memory
364 static BOOL
IsoReadPartialSector(ULONG SectorNumber
, ULONG StartingOffset
, ULONG Length
, PVOID Buffer
)
368 // DbgPrint((DPRINT_FILESYSTEM, "IsoReadPartialSector() SectorNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", SectorNumber, StartingOffset, Length, Buffer));
369 printf("IsoReadPartialSector() SectorNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", SectorNumber
, StartingOffset
, Length
, Buffer
);
371 SectorBuffer
= AllocateMemory(SECTORSIZE
);
372 if (SectorBuffer
== NULL
)
377 if (!BiosInt13ReadExtended(IsoDriveNumber
, SectorNumber
, 1, SectorBuffer
))
379 FreeMemory(SectorBuffer
);
383 memcpy(Buffer
, ((PVOID
)SectorBuffer
+ StartingOffset
), Length
);
385 FreeMemory(SectorBuffer
);
393 * Reads BytesToRead from open file and
394 * returns the number of bytes read in BytesRead
396 BOOL
IsoReadFile(FILE *FileHandle
, ULONG BytesToRead
, PULONG BytesRead
, PVOID Buffer
)
398 PISO_FILE_INFO IsoFileInfo
= (PISO_FILE_INFO
)FileHandle
;
400 UINT32 OffsetInSector
;
401 UINT32 LengthInSector
;
402 UINT32 NumberOfSectors
;
404 // DbgPrint((DPRINT_FILESYSTEM, "IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer));
405 printf("IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead
, Buffer
);
407 if (BytesRead
!= NULL
)
413 // If they are trying to read past the
414 // end of the file then return success
415 // with BytesRead == 0
417 if (IsoFileInfo
->FilePointer
>= IsoFileInfo
->FileSize
)
423 // If they are trying to read more than there is to read
424 // then adjust the amount to read
426 if ((IsoFileInfo
->FilePointer
+ BytesToRead
) > IsoFileInfo
->FileSize
)
428 BytesToRead
= (IsoFileInfo
->FileSize
- IsoFileInfo
->FilePointer
);
432 // Ok, now we have to perform at most 3 calculations
433 // I'll draw you a picture (using nifty ASCII art):
435 // CurrentFilePointer -+
437 // +----------------+
439 // +-----------+-----------+-----------+-----------+
440 // | Sector 1 | Sector 2 | Sector 3 | Sector 4 |
441 // +-----------+-----------+-----------+-----------+
443 // +---------------+--------------------+
445 // BytesToRead -------+
447 // 1 - The first calculation (and read) will align
448 // the file pointer with the next sector
449 // boundary (if we are supposed to read that much)
450 // 2 - The next calculation (and read) will read
451 // in all the full sectors that the requested
452 // amount of data would cover (in this case
454 // 3 - The last calculation (and read) would read
455 // in the remainder of the data requested out of
461 // Only do the first read if we
462 // aren't aligned on a cluster boundary
464 if (IsoFileInfo
->FilePointer
% SECTORSIZE
)
467 // Do the math for our first read
469 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
470 OffsetInSector
= IsoFileInfo
->FilePointer
% SECTORSIZE
;
471 LengthInSector
= (BytesToRead
> (SECTORSIZE
- OffsetInSector
)) ? (SECTORSIZE
- OffsetInSector
) : BytesToRead
;
474 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
476 if (!IsoReadPartialSector(SectorNumber
, OffsetInSector
, LengthInSector
, Buffer
))
480 if (BytesRead
!= NULL
)
482 *BytesRead
+= LengthInSector
;
484 BytesToRead
-= LengthInSector
;
485 IsoFileInfo
->FilePointer
+= LengthInSector
;
486 Buffer
+= LengthInSector
;
490 // Do the math for our second read (if any data left)
495 // Determine how many full clusters we need to read
497 NumberOfSectors
= (BytesToRead
/ SECTORSIZE
);
499 if (NumberOfSectors
> 0)
501 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
504 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
506 if (!BiosInt13ReadExtended(IsoDriveNumber
, SectorNumber
, NumberOfSectors
, Buffer
))
510 if (BytesRead
!= NULL
)
512 *BytesRead
+= (NumberOfSectors
* SECTORSIZE
);
514 BytesToRead
-= (NumberOfSectors
* SECTORSIZE
);
515 IsoFileInfo
->FilePointer
+= (NumberOfSectors
* SECTORSIZE
);
516 Buffer
+= (NumberOfSectors
* SECTORSIZE
);
521 // Do the math for our third read (if any data left)
525 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
528 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
530 if (!IsoReadPartialSector(SectorNumber
, 0, BytesToRead
, Buffer
))
534 if (BytesRead
!= NULL
)
536 *BytesRead
+= BytesToRead
;
538 BytesToRead
-= BytesToRead
;
539 IsoFileInfo
->FilePointer
+= BytesToRead
;
540 Buffer
+= BytesToRead
;
543 printf("IsoReadFile() done\n");
549 ULONG
IsoGetFileSize(FILE *FileHandle
)
551 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
553 // DbgPrint((DPRINT_FILESYSTEM, "IsoGetFileSize() FileSize = %d\n", IsoFileHandle->FileSize));
554 printf("IsoGetFileSize() FileSize = %d\n", IsoFileHandle
->FileSize
);
556 return IsoFileHandle
->FileSize
;
559 VOID
IsoSetFilePointer(FILE *FileHandle
, ULONG NewFilePointer
)
561 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
563 // DbgPrint((DPRINT_FILESYSTEM, "IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer));
564 printf("IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer
);
566 IsoFileHandle
->FilePointer
= NewFilePointer
;
569 ULONG
IsoGetFilePointer(FILE *FileHandle
)
571 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
573 // DbgPrint((DPRINT_FILESYSTEM, "IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle->FilePointer));
574 printf("IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle
->FilePointer
);
576 return IsoFileHandle
->FilePointer
;