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.
33 #define SECTORSIZE 2048
35 static ULONG IsoRootSector
; // Starting sector of the root directory
36 static ULONG IsoRootLength
; // Length of the root directory
38 ULONG IsoDriveNumber
= 0;
41 BOOL
IsoOpenVolume(ULONG DriveNumber
)
43 PPVD Pvd
= (PPVD
)DISKREADBUFFER
;
45 DbgPrint((DPRINT_FILESYSTEM
, "IsoOpenVolume() DriveNumber = 0x%x VolumeStartSector = 16\n", DriveNumber
));
47 // Store the drive number
48 IsoDriveNumber
= DriveNumber
;
53 if (!MachDiskReadLogicalSectors(DriveNumber
, 16, 1, Pvd
))
55 FileSystemError("Failed to read the PVD.");
59 IsoRootSector
= Pvd
->RootDirRecord
.ExtentLocationL
;
60 IsoRootLength
= Pvd
->RootDirRecord
.DataLengthL
;
62 DbgPrint((DPRINT_FILESYSTEM
, "IsoRootSector = %u IsoRootLegth = %u\n", IsoRootSector
, IsoRootLength
));
68 static BOOL
IsoSearchDirectoryBufferForFile(PVOID DirectoryBuffer
, ULONG DirectoryLength
, PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
75 DbgPrint((DPRINT_FILESYSTEM
, "IsoSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectoryLength = %d FileName = %s\n", DirectoryBuffer
, DirectoryLength
, FileName
));
77 RtlZeroMemory(Name
, 32 * sizeof(UCHAR
));
80 Record
= (PDIR_RECORD
)DirectoryBuffer
;
83 Offset
= Offset
+ Record
->RecordLength
;
84 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
86 if (Record
->RecordLength
== 0)
88 Offset
= ROUND_UP(Offset
, SECTORSIZE
);
89 Record
= (PDIR_RECORD
)(DirectoryBuffer
+ Offset
);
92 if (Offset
>= DirectoryLength
)
95 if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 0)
97 DbgPrint((DPRINT_FILESYSTEM
, "Name '.'\n"));
99 else if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 1)
101 DbgPrint((DPRINT_FILESYSTEM
, "Name '..'\n"));
105 for (i
= 0; i
< Record
->FileIdLength
&& Record
->FileId
[i
] != ';'; i
++)
106 Name
[i
] = Record
->FileId
[i
];
108 DbgPrint((DPRINT_FILESYSTEM
, "Name '%s'\n", Name
));
110 if (strlen(FileName
) == strlen(Name
) && stricmp(FileName
, Name
) == 0)
112 IsoFileInfoPointer
->FileStart
= Record
->ExtentLocationL
;
113 IsoFileInfoPointer
->FileSize
= Record
->DataLengthL
;
114 IsoFileInfoPointer
->FilePointer
= 0;
115 IsoFileInfoPointer
->Directory
= (Record
->FileFlags
& 0x02)?TRUE
:FALSE
;
122 RtlZeroMemory(Name
, 32 * sizeof(UCHAR
));
130 * IsoBufferDirectory()
131 * This function allocates a buffer, reads the specified directory
132 * and returns a pointer to that buffer. The function returns NULL
133 * if allocation or read fails. The directory is specified by its
134 * starting sector and length.
136 static PVOID
IsoBufferDirectory(ULONG DirectoryStartSector
, ULONG DirectoryLength
)
138 PVOID DirectoryBuffer
;
143 DbgPrint((DPRINT_FILESYSTEM
, "IsoBufferDirectory() DirectoryStartSector = %d DirectoryLength = %d\n", DirectoryStartSector
, DirectoryLength
));
145 SectorCount
= ROUND_UP(DirectoryLength
, SECTORSIZE
) / SECTORSIZE
;
146 DbgPrint((DPRINT_FILESYSTEM
, "Trying to read (DirectoryCount) %d sectors.\n", SectorCount
));
149 // Attempt to allocate memory for directory buffer
151 DbgPrint((DPRINT_FILESYSTEM
, "Trying to allocate (DirectoryLength) %d bytes.\n", DirectoryLength
));
152 DirectoryBuffer
= MmAllocateMemory(DirectoryLength
);
154 if (DirectoryBuffer
== NULL
)
160 // Now read directory contents into DirectoryBuffer
162 for (i
= 0, Ptr
= DirectoryBuffer
; i
< SectorCount
; i
++, Ptr
+= SECTORSIZE
)
164 if (!MachDiskReadLogicalSectors(IsoDriveNumber
, DirectoryStartSector
+ i
, 1, (PVOID
)DISKREADBUFFER
))
166 MmFreeMemory(DirectoryBuffer
);
169 RtlCopyMemory(Ptr
, (PVOID
)DISKREADBUFFER
, SECTORSIZE
);
172 return DirectoryBuffer
;
178 * This function searches the file system for the
179 * specified filename and fills in an ISO_FILE_INFO structure
180 * with info describing the file, etc. returns true
181 * if the file exists or false otherwise
183 static BOOL
IsoLookupFile(PUCHAR FileName
, PISO_FILE_INFO IsoFileInfoPointer
)
186 ULONG NumberOfPathParts
;
188 PVOID DirectoryBuffer
;
189 ULONG DirectorySector
;
190 ULONG DirectoryLength
;
191 ISO_FILE_INFO IsoFileInfo
;
193 DbgPrint((DPRINT_FILESYSTEM
, "IsoLookupFile() FileName = %s\n", FileName
));
195 RtlZeroMemory(IsoFileInfoPointer
, sizeof(ISO_FILE_INFO
));
198 // Figure out how many sub-directories we are nested in
200 NumberOfPathParts
= FsGetNumPathParts(FileName
);
202 DirectorySector
= IsoRootSector
;
203 DirectoryLength
= IsoRootLength
;
206 // Loop once for each part
208 for (i
=0; i
<NumberOfPathParts
; i
++)
211 // Get first path part
213 FsGetFirstNameFromPath(PathPart
, FileName
);
216 // Advance to the next part of the path
218 for (; (*FileName
!= '\\') && (*FileName
!= '/') && (*FileName
!= '\0'); FileName
++)
224 // Buffer the directory contents
226 DirectoryBuffer
= IsoBufferDirectory(DirectorySector
, DirectoryLength
);
227 if (DirectoryBuffer
== NULL
)
233 // Search for file name in directory
235 if (!IsoSearchDirectoryBufferForFile(DirectoryBuffer
, DirectoryLength
, PathPart
, &IsoFileInfo
))
237 MmFreeMemory(DirectoryBuffer
);
241 MmFreeMemory(DirectoryBuffer
);
244 // If we have another sub-directory to go then
245 // grab the start sector and file size
247 if ((i
+1) < NumberOfPathParts
)
249 DirectorySector
= IsoFileInfo
.FileStart
;
250 DirectoryLength
= IsoFileInfo
.FileSize
;
255 RtlCopyMemory(IsoFileInfoPointer
, &IsoFileInfo
, sizeof(ISO_FILE_INFO
));
263 * Tries to open the file 'name' and returns true or false
264 * for success and failure respectively
266 FILE* IsoOpenFile(PUCHAR FileName
)
268 ISO_FILE_INFO TempFileInfo
;
269 PISO_FILE_INFO FileHandle
;
271 DbgPrint((DPRINT_FILESYSTEM
, "IsoOpenFile() FileName = %s\n", FileName
));
273 if (!IsoLookupFile(FileName
, &TempFileInfo
))
278 FileHandle
= MmAllocateMemory(sizeof(ISO_FILE_INFO
));
280 if (FileHandle
== NULL
)
285 RtlCopyMemory(FileHandle
, &TempFileInfo
, sizeof(ISO_FILE_INFO
));
287 return (FILE*)FileHandle
;
293 * Reads BytesToRead from open file and
294 * returns the number of bytes read in BytesRead
296 BOOL
IsoReadFile(FILE *FileHandle
, ULONG BytesToRead
, ULONG
* BytesRead
, PVOID Buffer
)
298 PISO_FILE_INFO IsoFileInfo
= (PISO_FILE_INFO
)FileHandle
;
300 ULONG OffsetInSector
;
301 ULONG LengthInSector
;
302 ULONG NumberOfSectors
;
305 DbgPrint((DPRINT_FILESYSTEM
, "IsoReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead
, Buffer
));
307 if (BytesRead
!= NULL
)
313 // If they are trying to read past the
314 // end of the file then return success
315 // with BytesRead == 0
317 if (IsoFileInfo
->FilePointer
>= IsoFileInfo
->FileSize
)
323 // If they are trying to read more than there is to read
324 // then adjust the amount to read
326 if ((IsoFileInfo
->FilePointer
+ BytesToRead
) > IsoFileInfo
->FileSize
)
328 BytesToRead
= (IsoFileInfo
->FileSize
- IsoFileInfo
->FilePointer
);
332 // Ok, now we have to perform at most 3 calculations
333 // I'll draw you a picture (using nifty ASCII art):
335 // CurrentFilePointer -+
337 // +----------------+
339 // +-----------+-----------+-----------+-----------+
340 // | Sector 1 | Sector 2 | Sector 3 | Sector 4 |
341 // +-----------+-----------+-----------+-----------+
343 // +---------------+--------------------+
345 // BytesToRead -------+
347 // 1 - The first calculation (and read) will align
348 // the file pointer with the next sector
349 // boundary (if we are supposed to read that much)
350 // 2 - The next calculation (and read) will read
351 // in all the full sectors that the requested
352 // amount of data would cover (in this case
354 // 3 - The last calculation (and read) would read
355 // in the remainder of the data requested out of
361 // Only do the first read if we
362 // aren't aligned on a cluster boundary
364 if (IsoFileInfo
->FilePointer
% SECTORSIZE
)
367 // Do the math for our first read
369 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
370 OffsetInSector
= IsoFileInfo
->FilePointer
% SECTORSIZE
;
371 LengthInSector
= (BytesToRead
> (SECTORSIZE
- OffsetInSector
)) ? (SECTORSIZE
- OffsetInSector
) : BytesToRead
;
374 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
376 if (!MachDiskReadLogicalSectors(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
380 RtlCopyMemory(Buffer
, ((PVOID
)DISKREADBUFFER
+ OffsetInSector
), LengthInSector
);
381 if (BytesRead
!= NULL
)
383 *BytesRead
+= LengthInSector
;
385 BytesToRead
-= LengthInSector
;
386 IsoFileInfo
->FilePointer
+= LengthInSector
;
387 Buffer
+= LengthInSector
;
391 // Do the math for our second read (if any data left)
396 // Determine how many full clusters we need to read
398 NumberOfSectors
= (BytesToRead
/ SECTORSIZE
);
400 for (i
= 0; i
< NumberOfSectors
; i
++)
402 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
405 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
407 if (!MachDiskReadLogicalSectors(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
412 RtlCopyMemory(Buffer
, (PVOID
)DISKREADBUFFER
, SECTORSIZE
);
414 if (BytesRead
!= NULL
)
416 *BytesRead
+= SECTORSIZE
;
418 BytesToRead
-= SECTORSIZE
;
419 IsoFileInfo
->FilePointer
+= SECTORSIZE
;
420 Buffer
+= SECTORSIZE
;
425 // Do the math for our third read (if any data left)
429 SectorNumber
= IsoFileInfo
->FileStart
+ (IsoFileInfo
->FilePointer
/ SECTORSIZE
);
432 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
434 if (!MachDiskReadLogicalSectors(IsoDriveNumber
, SectorNumber
, 1, (PVOID
)DISKREADBUFFER
))
438 RtlCopyMemory(Buffer
, (PVOID
)DISKREADBUFFER
, BytesToRead
);
439 if (BytesRead
!= NULL
)
441 *BytesRead
+= BytesToRead
;
443 IsoFileInfo
->FilePointer
+= BytesToRead
;
444 BytesToRead
-= BytesToRead
;
445 Buffer
+= BytesToRead
;
448 DbgPrint((DPRINT_FILESYSTEM
, "IsoReadFile() done\n"));
454 ULONG
IsoGetFileSize(FILE *FileHandle
)
456 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
458 DbgPrint((DPRINT_FILESYSTEM
, "IsoGetFileSize() FileSize = %d\n", IsoFileHandle
->FileSize
));
460 return IsoFileHandle
->FileSize
;
463 VOID
IsoSetFilePointer(FILE *FileHandle
, ULONG NewFilePointer
)
465 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
467 DbgPrint((DPRINT_FILESYSTEM
, "IsoSetFilePointer() NewFilePointer = %d\n", NewFilePointer
));
469 IsoFileHandle
->FilePointer
= NewFilePointer
;
472 ULONG
IsoGetFilePointer(FILE *FileHandle
)
474 PISO_FILE_INFO IsoFileHandle
= (PISO_FILE_INFO
)FileHandle
;
476 DbgPrint((DPRINT_FILESYSTEM
, "IsoGetFilePointer() FilePointer = %d\n", IsoFileHandle
->FilePointer
));
478 return IsoFileHandle
->FilePointer
;