3 * Copyright (C) 1998-2003 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 U32 IsoRootSector
; // Starting sector of the root directory
35 static U32 IsoRootLength
; // Length of the root directory
37 U32 IsoDriveNumber
= 0;
40 BOOL
IsoOpenVolume(U32 DriveNumber
)
42 PPVD Pvd
= (PPVD
)DISKREADBUFFER
;
44 DbgPrint((DPRINT_FILESYSTEM
, "IsoOpenVolume() DriveNumber = 0x%x VolumeStartSector = 16\n", DriveNumber
));
46 // Store the drive number
47 IsoDriveNumber
= DriveNumber
;
52 if (!DiskReadLogicalSectors(DriveNumber
, 16, 1, Pvd
))
54 FileSystemError("Failed to read the PVD.");
58 IsoRootSector
= Pvd
->RootDirRecord
.ExtentLocationL
;
59 IsoRootLength
= Pvd
->RootDirRecord
.DataLengthL
;
61 DbgPrint((DPRINT_FILESYSTEM
, "IsoRootSector = %u IsoRootLegth = %u\n", IsoRootSector
, IsoRootLength
));
67 static BOOL
IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer
, U32 DirectoryLength
, PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
74 DbgPrint((DPRINT_FILESYSTEM
, "IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer
, DirectoryLength
, FileName
));
76 RtlZeroMemory(Name
, 32 * sizeof(UCHAR
));
79 Record
= (PDIR_RECORD
)DirectoryBuffer
;
82 Offset
= Offset
+ Record
->RecordLength
;
83 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
85 if (Record
->RecordLength
== 0)
87 Offset
= ROUND_UP(Offset
, SECTORSIZE
);
88 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
91 if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 0)
93 DbgPrint((DPRINT_FILESYSTEM
, "Name '.'\n"));
95 else if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 1)
97 DbgPrint((DPRINT_FILESYSTEM
, "Name '..'\n"));
101 for (i
= 0; i
< Record
->FileIdLength
&& Record
->FileId
[i
] != ';'; i
++)
102 Name
[i
] = Record
->FileId
[i
];
104 DbgPrint((DPRINT_FILESYSTEM
, "Name '%s'\n", Name
));
106 if (strlen(FileName
) == strlen(Name
) && stricmp(FileName
, Name
) == 0)
108 IsoFileInfoPointer
->FileStart
= Record
->ExtentLocationL
;
109 IsoFileInfoPointer
->FileSize
= Record
->DataLengthL
;
110 IsoFileInfoPointer
->FilePointer
= 0;
111 IsoFileInfoPointer
->Directory
= (Record
->FileFlags
& 0x02)?TRUE
:FALSE
;
118 if (Offset
>= DirectoryLength
)
121 RtlZeroMemory(Name
, 32 * sizeof(UCHAR
));
129 * IsoBufferDirectory()
130 * This function allocates a buffer, reads the specified directory
131 * and returns a pointer to that buffer. The function returns NULL
132 * if allocation or read fails. The directory is specified by its
133 * starting sector and length.
135 static PVOID
IsoBufferDirectory(U32 DirectoryStartSector
, U32 DirectoryLength
)
137 PVOID DirectoryBuffer
;
142 DbgPrint((DPRINT_FILESYSTEM
, "IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector
, DirectoryLength
));
144 SectorCount
= ROUND_UP(DirectoryLength
, SECTORSIZE
) / SECTORSIZE
;
145 DbgPrint((DPRINT_FILESYSTEM
, "Trying to read (DirectoryCount) %d sectors.\n", SectorCount
));
148 // Attempt to allocate memory for directory buffer
150 DbgPrint((DPRINT_FILESYSTEM
, "Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength
));
151 DirectoryBuffer
= MmAllocateMemory(DirectoryLength
);
153 if (DirectoryBuffer
== NULL
)
159 // Now read directory contents into DirectoryBuffer
161 for (i
= 0, Ptr
= DirectoryBuffer
; i
< SectorCount
; i
++, Ptr
+= SECTORSIZE
)
163 if (!DiskReadLogicalSectors(IsoDriveNumber
, DirectoryStartSector
+ i
, 1, (PVOID
)DISKREADBUFFER
))
165 MmFreeMemory(DirectoryBuffer
);
168 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, SECTORSIZE
);
171 return DirectoryBuffer
;
177 * This function searches the file system for the
178 * specified filename and fills in an ISO_FILE_INFO structure
179 * with info describing the file, etc. returns true
180 * if the file exists or false otherwise
182 static BOOL
IsoLookupFile(PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
185 U32 NumberOfPathParts
;
187 PVOID DirectoryBuffer
;
190 ISO_FILE_INFO IsoFileInfo
;
192 DbgPrint((DPRINT_FILESYSTEM
, "IsoLookupFile() FileName = %s\n", FileName
));
194 RtlZeroMemory(IsoFileInfoPointer
, sizeof(ISO_FILE_INFO
));
197 // Figure out how many sub-directories we are nested in
199 NumberOfPathParts
= FsGetNumPathParts(FileName
);
201 DirectorySector
= IsoRootSector
;
202 DirectoryLength
= IsoRootLength
;
205 // Loop once for each part
207 for (i
=0; i
<NumberOfPathParts
; i
++)
210 // Get first path part
212 FsGetFirstNameFromPath(PathPart
, FileName
);
215 // Advance to the next part of the path
217 for (; (*FileName
!= '\\') && (*FileName
!= '/') && (*FileName
!= '\0'); FileName
++)
223 // Buffer the directory contents
225 DirectoryBuffer
= IsoBufferDirectory(DirectorySector
, DirectoryLength
);
226 if (DirectoryBuffer
== NULL
)
232 // Search for file name in directory
234 if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer
, DirectoryLength
, PathPart
, &IsoFileInfo
))
236 MmFreeMemory(DirectoryBuffer
);
240 MmFreeMemory(DirectoryBuffer
);
243 // If we have another sub-directory to go then
244 // grab the start sector and file size
246 if ((i
+1) < NumberOfPathParts
)
248 DirectorySector
= IsoFileInfo
.FileStart
;
249 DirectoryLength
= IsoFileInfo
.FileSize
;
254 RtlCopyMemory(IsoFileInfoPointer
, &IsoFileInfo
, sizeof(ISO_FILE_INFO
));
262 * Tries to open the file 'name' and returns true or false
263 * for success and failure respectively
265 FILE* IsoOpenFile(PUCHAR FileName
)
267 ISO_FILE_INFO TempFileInfo
;
268 PISO_FILE_INFO FileHandle
;
270 DbgPrint((DPRINT_FILESYSTEM
, "IsoOpenFile() FileName = %s\n", FileName
));
272 if (!IsoLookupFile(FileName
, &TempFileInfo
))
277 FileHandle
= MmAllocateMemory(sizeof(ISO_FILE_INFO
));
279 if (FileHandle
== NULL
)
284 RtlCopyMemory(FileHandle
, &TempFileInfo
, sizeof(ISO_FILE_INFO
));
286 return (FILE*)FileHandle
;
292 * Reads BytesToRead from open file and
293 * returns the number of bytes read in BytesRead
295 BOOL
IsoReadFile(FILE *FileHandle
, U32 BytesToRead
, U32
* BytesRead
, PVOID Buffer
)
297 PISO_FILE_INFO IsoFileInfo
= (PISO_FILE_INFO
)FileHandle
;
304 DbgPrint((DPRINT_FILESYSTEM
, "IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead
, Buffer
));
306 if (BytesRead
!= NULL
)
312 // If they are trying to read past the
313 // end of the file then return success
314 // with BytesRead == 0
316 if (IsoFileInfo
->FilePointer
>= IsoFileInfo
->FileSize
)
322 // If they are trying to read more than there is to read
323 // then adjust the amount to read
325 if ((IsoFileInfo
->FilePointer
+ BytesToRead
) > IsoFileInfo
->FileSize
)
327 BytesToRead
= (IsoFileInfo
->FileSize
- IsoFileInfo
->FilePointer
);
331 // Ok, now we have to perform at most 3 calculations
332 // I'll draw you a picture (using nifty ASCII art):
334 // CurrentFilePointer -+
336 // +----------------+
338 // +-----------+-----------+-----------+-----------+
339 // | Sector 1 | Sector 2 | Sector 3 | Sector 4 |
340 // +-----------+-----------+-----------+-----------+
342 // +---------------+--------------------+
344 // BytesToRead -------+
346 // 1 - The first calculation (and read) will align
347 // the file pointer with the next sector
348 // boundary (if we are supposed to read that much)
349 // 2 - The next calculation (and read) will read
350 // in all the full sectors that the requested
351 // amount of data would cover (in this case
353 // 3 - The last calculation (and read) would read
354 // in the remainder of the data requested out of
360 // Only do the first read if we
361 // aren't aligned on a cluster boundary
363 if (IsoFileInfo
->FilePointer
% SECTORSIZE
)
366 // Do the math for our first read
368 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
369 OffsetInSector
= IsoFileInfo
->FilePointer
% SECTORSIZE
;
370 LengthInSector
= (BytesToRead
> (SECTORSIZE
- OffsetInSector
)) ? (SECTORSIZE
- OffsetInSector
) : BytesToRead
;
373 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
375 if (!DiskReadLogicalSectors(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
379 RtlCopyMemory(Buffer
, ((PVOID
)DISKREADBUFFER
+ OffsetInSector
), LengthInSector
);
380 if (BytesRead
!= NULL
)
382 *BytesRead
+= LengthInSector
;
384 BytesToRead
-= LengthInSector
;
385 IsoFileInfo
->FilePointer
+= LengthInSector
;
386 Buffer
+= LengthInSector
;
390 // Do the math for our second read (if any data left)
395 // Determine how many full clusters we need to read
397 NumberOfSectors
= (BytesToRead
/ SECTORSIZE
);
399 for (i
= 0; i
< NumberOfSectors
; i
++)
401 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
404 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
406 if (!DiskReadLogicalSectorsLBA(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
411 RtlCopyMemory(Buffer
, (PVOID
)DISKREADBUFFER
, SECTORSIZE
);
413 if (BytesRead
!= NULL
)
415 *BytesRead
+= SECTORSIZE
;
417 BytesToRead
-= SECTORSIZE
;
418 IsoFileInfo
->FilePointer
+= SECTORSIZE
;
419 Buffer
+= SECTORSIZE
;
424 // Do the math for our third read (if any data left)
428 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
431 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
433 if (!DiskReadLogicalSectorsLBA(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
437 RtlCopyMemory(Buffer
, (PVOID
)DISKREADBUFFER
, BytesToRead
);
438 if (BytesRead
!= NULL
)
440 *BytesRead
+= BytesToRead
;
442 IsoFileInfo
->FilePointer
+= BytesToRead
;
443 BytesToRead
-= BytesToRead
;
444 Buffer
+= BytesToRead
;
447 DbgPrint((DPRINT_FILESYSTEM
, "IsoReadFile() done\n"));
453 U32
IsoGetFileSize(FILE *FileHandle
)
455 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
457 DbgPrint((DPRINT_FILESYSTEM
, "IsoGetFileSize() FileSize = %d\n", IsoFileHandle
->FileSize
));
459 return IsoFileHandle
->FileSize
;
462 VOID
IsoSetFilePointer(FILE *FileHandle
, U32 NewFilePointer
)
464 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
466 DbgPrint((DPRINT_FILESYSTEM
, "IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer
));
468 IsoFileHandle
->FilePointer
= NewFilePointer
;
471 U32
IsoGetFilePointer(FILE *FileHandle
)
473 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
475 DbgPrint((DPRINT_FILESYSTEM
, "IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle
->FilePointer
));
477 return IsoFileHandle
->FilePointer
;