ReactOS  0.4.13-dev-563-g0561610
ext2.c
Go to the documentation of this file.
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 along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef _M_ARM
21 #include <freeldr.h>
22 #include <debug.h>
23 
24 DBG_DEFAULT_CHANNEL(FILESYSTEM);
25 
26 BOOLEAN Ext2OpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG PartitionSectorCount);
29 BOOLEAN Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry);
31 
35 BOOLEAN Ext2ReadDirectory(ULONG Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer);
36 BOOLEAN Ext2ReadBlock(ULONG BlockNumber, PVOID Buffer);
43 BOOLEAN Ext2ReadInode(ULONG Inode, PEXT2_INODE InodeBuffer);
47 BOOLEAN Ext2CopyIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock);
48 BOOLEAN Ext2CopyDoubleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock);
49 BOOLEAN Ext2CopyTripleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock);
50 
51 GEOMETRY Ext2DiskGeometry; // Ext2 file system disk geometry
52 
53 PEXT2_SUPER_BLOCK Ext2SuperBlock = NULL; // Ext2 file system super block
54 PEXT2_GROUP_DESC Ext2GroupDescriptors = NULL; // Ext2 file system group descriptors
55 
56 UCHAR Ext2DriveNumber = 0; // Ext2 file system drive number
57 ULONGLONG Ext2VolumeStartSector = 0; // Ext2 file system starting sector
58 ULONG Ext2BlockSizeInBytes = 0; // Block size in bytes
59 ULONG Ext2BlockSizeInSectors = 0; // Block size in sectors
60 ULONG Ext2FragmentSizeInBytes = 0; // Fragment size in bytes
61 ULONG Ext2FragmentSizeInSectors = 0; // Fragment size in sectors
62 ULONG Ext2GroupCount = 0; // Number of groups in this file system
63 ULONG Ext2InodesPerBlock = 0; // Number of inodes in one block
64 ULONG Ext2GroupDescPerBlock = 0; // Number of group descriptors in one block
65 
66 #define TAG_EXT_BLOCK_LIST 'LtxE'
67 #define TAG_EXT_FILE 'FtxE'
68 #define TAG_EXT_BUFFER 'BtxE'
69 #define TAG_EXT_SUPER_BLOCK 'StxE'
70 #define TAG_EXT_GROUP_DESC 'GtxE'
71 
72 BOOLEAN DiskGetBootVolume(PUCHAR DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType)
73 {
74  *DriveNumber = 0;
75  *StartSector = 0;
76  *SectorCount = 0;
77  *FsType = 0;
78  return FALSE;
79 }
80 
82 {
83 
84  TRACE("Ext2OpenVolume() DriveNumber = 0x%x VolumeStartSector = %d\n", DriveNumber, VolumeStartSector);
85 
86  // Store the drive number and start sector
87  Ext2DriveNumber = DriveNumber;
88  Ext2VolumeStartSector = VolumeStartSector;
89 
90  if (!MachDiskGetDriveGeometry(DriveNumber, &Ext2DiskGeometry))
91  {
92  return FALSE;
93  }
94 
95  //
96  // Initialize the disk cache for this drive
97  //
98  if (!CacheInitializeDrive(DriveNumber))
99  {
100  return FALSE;
101  }
102 
103  // Read in the super block
104  if (!Ext2ReadSuperBlock())
105  {
106  return FALSE;
107  }
108 
109  // Read in the group descriptors
111  {
112  return FALSE;
113  }
114 
115  return TRUE;
116 }
117 
118 /*
119  * Ext2OpenFile()
120  * Tries to open the file 'name' and returns true or false
121  * for success and failure respectively
122  */
124 {
125  EXT2_FILE_INFO TempExt2FileInfo;
127  CHAR SymLinkPath[EXT2_NAME_LEN];
128  CHAR FullPath[EXT2_NAME_LEN * 2];
130 
131  TRACE("Ext2OpenFile() FileName = %s\n", FileName);
132 
133  RtlZeroMemory(SymLinkPath, sizeof(SymLinkPath));
134 
135  // Lookup the file in the file system
136  if (!Ext2LookupFile(FileName, &TempExt2FileInfo))
137  {
138  return NULL;
139  }
140 
141  // If we got a symbolic link then fix up the path
142  // and re-call this function
143  if ((TempExt2FileInfo.Inode.mode & EXT2_S_IFMT) == EXT2_S_IFLNK)
144  {
145  TRACE("File is a symbolic link\n");
146 
147  // Now read in the symbolic link path
148  if (!Ext2ReadFileBig(&TempExt2FileInfo, TempExt2FileInfo.FileSize, NULL, SymLinkPath))
149  {
150  if (TempExt2FileInfo.FileBlockList != NULL)
151  {
153  }
154 
155  return NULL;
156  }
157 
158  TRACE("Symbolic link path = %s\n", SymLinkPath);
159 
160  // Get the full path
161  if (SymLinkPath[0] == '/' || SymLinkPath[0] == '\\')
162  {
163  // Symbolic link is an absolute path
164  // So copy it to FullPath, but skip over
165  // the '/' char at the beginning
166  strcpy(FullPath, &SymLinkPath[1]);
167  }
168  else
169  {
170  // Symbolic link is a relative path
171  // Copy the first part of the path
172  strcpy(FullPath, FileName);
173 
174  // Remove the last part of the path
175  for (Index=strlen(FullPath); Index>0; )
176  {
177  Index--;
178  if (FullPath[Index] == '/' || FullPath[Index] == '\\')
179  {
180  break;
181  }
182  }
183  FullPath[Index] = '\0';
184 
185  // Concatenate the symbolic link
186  strcat(FullPath, Index == 0 ? "" : "/");
187  strcat(FullPath, SymLinkPath);
188  }
189 
190  TRACE("Full file path = %s\n", FullPath);
191 
192  if (TempExt2FileInfo.FileBlockList != NULL)
193  {
195  }
196 
197  return Ext2OpenFile(FullPath);
198  }
199  else
200  {
202 
203  if (FileHandle == NULL)
204  {
205  if (TempExt2FileInfo.FileBlockList != NULL)
206  {
208  }
209 
210  return NULL;
211  }
212 
213  RtlCopyMemory(FileHandle, &TempExt2FileInfo, sizeof(EXT2_FILE_INFO));
214 
215  return FileHandle;
216  }
217 }
218 
219 /*
220  * Ext2LookupFile()
221  * This function searches the file system for the
222  * specified filename and fills in a EXT2_FILE_INFO structure
223  * with info describing the file, etc. returns true
224  * if the file exists or false otherwise
225  */
227 {
228  UINT32 i;
229  ULONG NumberOfPathParts;
230  CHAR PathPart[261];
231  PVOID DirectoryBuffer;
232  ULONG DirectoryInode = EXT2_ROOT_INO;
233  EXT2_INODE InodeData;
234  EXT2_DIR_ENTRY DirectoryEntry;
235 
236  TRACE("Ext2LookupFile() FileName = %s\n", FileName);
237 
238  RtlZeroMemory(Ext2FileInfoPointer, sizeof(EXT2_FILE_INFO));
239 
240  //
241  // Figure out how many sub-directories we are nested in
242  //
243  NumberOfPathParts = FsGetNumPathParts(FileName);
244 
245  //
246  // Loop once for each part
247  //
248  for (i=0; i<NumberOfPathParts; i++)
249  {
250  //
251  // Get first path part
252  //
253  FsGetFirstNameFromPath(PathPart, FileName);
254 
255  //
256  // Advance to the next part of the path
257  //
258  for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
259  {
260  }
261  FileName++;
262 
263  //
264  // Buffer the directory contents
265  //
266  if (!Ext2ReadDirectory(DirectoryInode, &DirectoryBuffer, &InodeData))
267  {
268  return FALSE;
269  }
270 
271  //
272  // Search for file name in directory
273  //
274  if (!Ext2SearchDirectoryBufferForFile(DirectoryBuffer, (ULONG)Ext2GetInodeFileSize(&InodeData), PathPart, &DirectoryEntry))
275  {
276  FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
277  return FALSE;
278  }
279 
280  FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
281 
282  DirectoryInode = DirectoryEntry.inode;
283  }
284 
285  if (!Ext2ReadInode(DirectoryInode, &InodeData))
286  {
287  return FALSE;
288  }
289 
290  if (((InodeData.mode & EXT2_S_IFMT) != EXT2_S_IFREG) &&
291  ((InodeData.mode & EXT2_S_IFMT) != EXT2_S_IFLNK))
292  {
293  FileSystemError("Inode is not a regular file or symbolic link.");
294  return FALSE;
295  }
296 
297  // Set the drive number
298  Ext2FileInfoPointer->DriveNumber = Ext2DriveNumber;
299 
300  // If it's a regular file or a regular symbolic link
301  // then get the block pointer list otherwise it must
302  // be a fast symbolic link which doesn't have a block list
303  if (((InodeData.mode & EXT2_S_IFMT) == EXT2_S_IFREG) ||
304  ((InodeData.mode & EXT2_S_IFMT) == EXT2_S_IFLNK && InodeData.size > FAST_SYMLINK_MAX_NAME_SIZE))
305  {
306  Ext2FileInfoPointer->FileBlockList = Ext2ReadBlockPointerList(&InodeData);
307 
308  if (Ext2FileInfoPointer->FileBlockList == NULL)
309  {
310  return FALSE;
311  }
312  }
313  else
314  {
315  Ext2FileInfoPointer->FileBlockList = NULL;
316  }
317 
318  Ext2FileInfoPointer->FilePointer = 0;
319  Ext2FileInfoPointer->FileSize = Ext2GetInodeFileSize(&InodeData);
320  RtlCopyMemory(&Ext2FileInfoPointer->Inode, &InodeData, sizeof(EXT2_INODE));
321 
322  return TRUE;
323 }
324 
325 BOOLEAN Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry)
326 {
327  ULONG CurrentOffset;
328  PEXT2_DIR_ENTRY CurrentDirectoryEntry;
329 
330  TRACE("Ext2SearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = %s\n", DirectoryBuffer, DirectorySize, FileName);
331 
332  for (CurrentOffset=0; CurrentOffset<DirectorySize; )
333  {
334  CurrentDirectoryEntry = (PEXT2_DIR_ENTRY)((ULONG_PTR)DirectoryBuffer + CurrentOffset);
335 
336  if (CurrentDirectoryEntry->direntlen == 0)
337  {
338  break;
339  }
340 
341  if ((CurrentDirectoryEntry->direntlen + CurrentOffset) > DirectorySize)
342  {
343  FileSystemError("Directory entry extends past end of directory file.");
344  return FALSE;
345  }
346 
347  TRACE("Dumping directory entry at offset %d:\n", CurrentOffset);
348  DbgDumpBuffer(DPRINT_FILESYSTEM, CurrentDirectoryEntry, CurrentDirectoryEntry->direntlen);
349 
350  if ((_strnicmp(FileName, CurrentDirectoryEntry->name, CurrentDirectoryEntry->namelen) == 0) &&
351  (strlen(FileName) == CurrentDirectoryEntry->namelen))
352  {
353  RtlCopyMemory(DirectoryEntry, CurrentDirectoryEntry, sizeof(EXT2_DIR_ENTRY));
354 
355  TRACE("EXT2 Directory Entry:\n");
356  TRACE("inode = %d\n", DirectoryEntry->inode);
357  TRACE("direntlen = %d\n", DirectoryEntry->direntlen);
358  TRACE("namelen = %d\n", DirectoryEntry->namelen);
359  TRACE("filetype = %d\n", DirectoryEntry->filetype);
360  TRACE("name = ");
361  for (CurrentOffset=0; CurrentOffset<DirectoryEntry->namelen; CurrentOffset++)
362  {
363  TRACE("%c", DirectoryEntry->name[CurrentOffset]);
364  }
365  TRACE("\n");
366 
367  return TRUE;
368  }
369 
370  CurrentOffset += CurrentDirectoryEntry->direntlen;
371  }
372 
373  return FALSE;
374 }
375 
376 /*
377  * Ext2ReadFileBig()
378  * Reads BytesToRead from open file and
379  * returns the number of bytes read in BytesRead
380  */
382 {
383  ULONG BlockNumber;
384  ULONG BlockNumberIndex;
385  ULONG OffsetInBlock;
386  ULONG LengthInBlock;
387  ULONG NumberOfBlocks;
388 
389  TRACE("Ext2ReadFileBig() BytesToRead = %d Buffer = 0x%x\n", (ULONG)BytesToRead, Buffer);
390 
391  if (BytesRead != NULL)
392  {
393  *BytesRead = 0;
394  }
395 
396  // Make sure we have the block pointer list if we need it
397  if (Ext2FileInfo->FileBlockList == NULL)
398  {
399  // Block pointer list is NULL
400  // so this better be a fast symbolic link or else
401  if (((Ext2FileInfo->Inode.mode & EXT2_S_IFMT) != EXT2_S_IFLNK) ||
402  (Ext2FileInfo->FileSize > FAST_SYMLINK_MAX_NAME_SIZE))
403  {
404  FileSystemError("Block pointer list is NULL and file is not a fast symbolic link.");
405  return FALSE;
406  }
407  }
408 
409  //
410  // If they are trying to read past the
411  // end of the file then return success
412  // with BytesRead == 0
413  //
414  if (Ext2FileInfo->FilePointer >= Ext2FileInfo->FileSize)
415  {
416  return TRUE;
417  }
418 
419  //
420  // If they are trying to read more than there is to read
421  // then adjust the amount to read
422  //
423  if ((Ext2FileInfo->FilePointer + BytesToRead) > Ext2FileInfo->FileSize)
424  {
425  BytesToRead = (Ext2FileInfo->FileSize - Ext2FileInfo->FilePointer);
426  }
427 
428  // Check if this is a fast symbolic link
429  // if so then the read is easy
430  if (((Ext2FileInfo->Inode.mode & EXT2_S_IFMT) == EXT2_S_IFLNK) &&
431  (Ext2FileInfo->FileSize <= FAST_SYMLINK_MAX_NAME_SIZE))
432  {
433  TRACE("Reading fast symbolic link data\n");
434 
435  // Copy the data from the link
436  RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Ext2FileInfo->FilePointer + Ext2FileInfo->Inode.symlink), (ULONG)BytesToRead);
437 
438  if (BytesRead != NULL)
439  {
440  *BytesRead = BytesToRead;
441  }
442 
443  return TRUE;
444  }
445 
446  //
447  // Ok, now we have to perform at most 3 calculations
448  // I'll draw you a picture (using nifty ASCII art):
449  //
450  // CurrentFilePointer -+
451  // |
452  // +----------------+
453  // |
454  // +-----------+-----------+-----------+-----------+
455  // | Block 1 | Block 2 | Block 3 | Block 4 |
456  // +-----------+-----------+-----------+-----------+
457  // | |
458  // +---------------+--------------------+
459  // |
460  // BytesToRead -------+
461  //
462  // 1 - The first calculation (and read) will align
463  // the file pointer with the next block.
464  // boundary (if we are supposed to read that much)
465  // 2 - The next calculation (and read) will read
466  // in all the full blocks that the requested
467  // amount of data would cover (in this case
468  // blocks 2 & 3).
469  // 3 - The last calculation (and read) would read
470  // in the remainder of the data requested out of
471  // the last block.
472  //
473 
474  //
475  // Only do the first read if we
476  // aren't aligned on a block boundary
477  //
478  if (Ext2FileInfo->FilePointer % Ext2BlockSizeInBytes)
479  {
480  //
481  // Do the math for our first read
482  //
483  BlockNumberIndex = (ULONG)(Ext2FileInfo->FilePointer / Ext2BlockSizeInBytes);
484  BlockNumber = Ext2FileInfo->FileBlockList[BlockNumberIndex];
485  OffsetInBlock = (Ext2FileInfo->FilePointer % Ext2BlockSizeInBytes);
486  LengthInBlock = (ULONG)((BytesToRead > (Ext2BlockSizeInBytes - OffsetInBlock)) ? (Ext2BlockSizeInBytes - OffsetInBlock) : BytesToRead);
487 
488  //
489  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
490  //
491  if (!Ext2ReadPartialBlock(BlockNumber, OffsetInBlock, LengthInBlock, Buffer))
492  {
493  return FALSE;
494  }
495  if (BytesRead != NULL)
496  {
497  *BytesRead += LengthInBlock;
498  }
499  BytesToRead -= LengthInBlock;
500  Ext2FileInfo->FilePointer += LengthInBlock;
501  Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInBlock);
502  }
503 
504  //
505  // Do the math for our second read (if any data left)
506  //
507  if (BytesToRead > 0)
508  {
509  //
510  // Determine how many full clusters we need to read
511  //
512  NumberOfBlocks = (ULONG)(BytesToRead / Ext2BlockSizeInBytes);
513 
514  while (NumberOfBlocks > 0)
515  {
516  BlockNumberIndex = (ULONG)(Ext2FileInfo->FilePointer / Ext2BlockSizeInBytes);
517  BlockNumber = Ext2FileInfo->FileBlockList[BlockNumberIndex];
518 
519  //
520  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
521  //
522  if (!Ext2ReadBlock(BlockNumber, Buffer))
523  {
524  return FALSE;
525  }
526  if (BytesRead != NULL)
527  {
529  }
530  BytesToRead -= Ext2BlockSizeInBytes;
531  Ext2FileInfo->FilePointer += Ext2BlockSizeInBytes;
533  NumberOfBlocks--;
534  }
535  }
536 
537  //
538  // Do the math for our third read (if any data left)
539  //
540  if (BytesToRead > 0)
541  {
542  BlockNumberIndex = (ULONG)(Ext2FileInfo->FilePointer / Ext2BlockSizeInBytes);
543  BlockNumber = Ext2FileInfo->FileBlockList[BlockNumberIndex];
544 
545  //
546  // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
547  //
548  if (!Ext2ReadPartialBlock(BlockNumber, 0, (ULONG)BytesToRead, Buffer))
549  {
550  return FALSE;
551  }
552  if (BytesRead != NULL)
553  {
554  *BytesRead += BytesToRead;
555  }
556  Ext2FileInfo->FilePointer += BytesToRead;
557  BytesToRead -= BytesToRead;
558  Buffer = (PVOID)((ULONG_PTR)Buffer + (ULONG_PTR)BytesToRead);
559  }
560 
561  return TRUE;
562 }
563 
565 {
566  //GEOMETRY DiskGeometry;
567  //BOOLEAN ReturnValue;
568  //if (!DiskGetDriveGeometry(DriveNumber, &DiskGeometry))
569  //{
570  // return FALSE;
571  //}
572  //ReturnValue = MachDiskReadLogicalSectors(DriveNumber, SectorNumber + Ext2VolumeStartSector, SectorCount, DiskReadBuffer);
573  //RtlCopyMemory(Buffer, DiskReadBuffer, SectorCount * DiskGeometry.BytesPerSector);
574  //return ReturnValue;
575 
576  return CacheReadDiskSectors(DriveNumber, SectorNumber + Ext2VolumeStartSector, SectorCount, Buffer);
577 }
578 
580 {
581 
582  TRACE("Ext2ReadSuperBlock()\n");
583 
584  //
585  // Free any memory previously allocated
586  //
587  if (Ext2SuperBlock != NULL)
588  {
590 
592  }
593 
594  //
595  // Now allocate the memory to hold the super block
596  //
598 
599  //
600  // Make sure we got the memory
601  //
602  if (Ext2SuperBlock == NULL)
603  {
604  FileSystemError("Out of memory.");
605  return FALSE;
606  }
607 
608  // Now try to read the super block
609  // If this fails then abort
611  {
612  return FALSE;
613  }
615 
616  TRACE("Dumping super block:\n");
617  TRACE("total_inodes: %d\n", Ext2SuperBlock->total_inodes);
618  TRACE("total_blocks: %d\n", Ext2SuperBlock->total_blocks);
619  TRACE("reserved_blocks: %d\n", Ext2SuperBlock->reserved_blocks);
620  TRACE("free_blocks: %d\n", Ext2SuperBlock->free_blocks);
621  TRACE("free_inodes: %d\n", Ext2SuperBlock->free_inodes);
622  TRACE("first_data_block: %d\n", Ext2SuperBlock->first_data_block);
623  TRACE("log2_block_size: %d\n", Ext2SuperBlock->log2_block_size);
624  TRACE("log2_fragment_size: %d\n", Ext2SuperBlock->log2_fragment_size);
625  TRACE("blocks_per_group: %d\n", Ext2SuperBlock->blocks_per_group);
626  TRACE("fragments_per_group: %d\n", Ext2SuperBlock->fragments_per_group);
627  TRACE("inodes_per_group: %d\n", Ext2SuperBlock->inodes_per_group);
628  TRACE("mtime: %d\n", Ext2SuperBlock->mtime);
629  TRACE("utime: %d\n", Ext2SuperBlock->utime);
630  TRACE("mnt_count: %d\n", Ext2SuperBlock->mnt_count);
631  TRACE("max_mnt_count: %d\n", Ext2SuperBlock->max_mnt_count);
632  TRACE("magic: 0x%x\n", Ext2SuperBlock->magic);
633  TRACE("fs_state: %d\n", Ext2SuperBlock->fs_state);
634  TRACE("error_handling: %d\n", Ext2SuperBlock->error_handling);
635  TRACE("minor_revision_level: %d\n", Ext2SuperBlock->minor_revision_level);
636  TRACE("lastcheck: %d\n", Ext2SuperBlock->lastcheck);
637  TRACE("checkinterval: %d\n", Ext2SuperBlock->checkinterval);
638  TRACE("creator_os: %d\n", Ext2SuperBlock->creator_os);
639  TRACE("revision_level: %d\n", Ext2SuperBlock->revision_level);
640  TRACE("uid_reserved: %d\n", Ext2SuperBlock->uid_reserved);
641  TRACE("gid_reserved: %d\n", Ext2SuperBlock->gid_reserved);
642  TRACE("first_inode: %d\n", Ext2SuperBlock->first_inode);
643  TRACE("inode_size: %d\n", Ext2SuperBlock->inode_size);
644  TRACE("block_group_number: %d\n", Ext2SuperBlock->block_group_number);
645  TRACE("feature_compatibility: 0x%x\n", Ext2SuperBlock->feature_compatibility);
646  TRACE("feature_incompat: 0x%x\n", Ext2SuperBlock->feature_incompat);
647  TRACE("feature_ro_compat: 0x%x\n", Ext2SuperBlock->feature_ro_compat);
648  TRACE("unique_id = { 0x%x, 0x%x, 0x%x, 0x%x }\n",
650  TRACE("volume_name = '%.16s'\n", Ext2SuperBlock->volume_name);
651  TRACE("last_mounted_on = '%.64s'\n", Ext2SuperBlock->last_mounted_on);
652  TRACE("compression_info = 0x%x\n", Ext2SuperBlock->compression_info);
653 
654  //
655  // Check the super block magic
656  //
658  {
659  FileSystemError("Invalid super block magic (0xef53)");
660  return FALSE;
661  }
662 
663  //
664  // Check the revision level
665  //
667  {
668  FileSystemError("FreeLoader does not understand the revision of this EXT2/EXT3 filesystem.\nPlease update FreeLoader.");
669  return FALSE;
670  }
671 
672  //
673  // Check the feature set
674  // Don't need to check the compatible or read-only compatible features
675  // because we only mount the filesystem as read-only
676  //
678  (/*((Ext2SuperBlock->s_feature_compat & ~EXT3_FEATURE_COMPAT_SUPP) != 0) ||*/
679  /*((Ext2SuperBlock->s_feature_ro_compat & ~EXT3_FEATURE_RO_COMPAT_SUPP) != 0) ||*/
681  {
682  FileSystemError("FreeLoader does not understand features of this EXT2/EXT3 filesystem.\nPlease update FreeLoader.");
683  return FALSE;
684  }
685 
686  // Calculate the group count
688  TRACE("Ext2GroupCount: %d\n", Ext2GroupCount);
689 
690  // Calculate the block size
693  TRACE("Ext2BlockSizeInBytes: %d\n", Ext2BlockSizeInBytes);
694  TRACE("Ext2BlockSizeInSectors: %d\n", Ext2BlockSizeInSectors);
695 
696  // Calculate the fragment size
698  {
700  }
701  else
702  {
704  }
706  TRACE("Ext2FragmentSizeInBytes: %d\n", Ext2FragmentSizeInBytes);
707  TRACE("Ext2FragmentSizeInSectors: %d\n", Ext2FragmentSizeInSectors);
708 
709  // Verify that the fragment size and the block size are equal
711  {
712  FileSystemError("The fragment size must be equal to the block size.");
713  return FALSE;
714  }
715 
716  // Calculate the number of inodes in one block
718  TRACE("Ext2InodesPerBlock: %d\n", Ext2InodesPerBlock);
719 
720  // Calculate the number of group descriptors in one block
722  TRACE("Ext2GroupDescPerBlock: %d\n", Ext2GroupDescPerBlock);
723 
724  return TRUE;
725 }
726 
728 {
729  ULONG GroupDescBlockCount;
730  ULONG BlockNumber;
731  PUCHAR CurrentGroupDescBlock;
732 
733  TRACE("Ext2ReadGroupDescriptors()\n");
734 
735  //
736  // Free any memory previously allocated
737  //
738  if (Ext2GroupDescriptors != NULL)
739  {
741 
743  }
744 
745  //
746  // Now allocate the memory to hold the group descriptors
747  //
750 
751  //
752  // Make sure we got the memory
753  //
754  if (Ext2GroupDescriptors == NULL)
755  {
756  FileSystemError("Out of memory.");
757  return FALSE;
758  }
759 
760  // Now read the group descriptors
761  CurrentGroupDescBlock = (PUCHAR)Ext2GroupDescriptors;
762  BlockNumber = Ext2SuperBlock->first_data_block + 1;
763 
764  while (GroupDescBlockCount--)
765  {
766  if (!Ext2ReadBlock(BlockNumber, CurrentGroupDescBlock))
767  {
768  return FALSE;
769  }
770 
771  BlockNumber++;
772  CurrentGroupDescBlock += Ext2BlockSizeInBytes;
773  }
774 
775  return TRUE;
776 }
777 
778 BOOLEAN Ext2ReadDirectory(ULONG Inode, PVOID* DirectoryBuffer, PEXT2_INODE InodePointer)
779 {
780  EXT2_FILE_INFO DirectoryFileInfo;
781 
782  TRACE("Ext2ReadDirectory() Inode = %d\n", Inode);
783 
784  // Read the directory inode
785  if (!Ext2ReadInode(Inode, InodePointer))
786  {
787  return FALSE;
788  }
789 
790  // Make sure it is a directory inode
791  if ((InodePointer->mode & EXT2_S_IFMT) != EXT2_S_IFDIR)
792  {
793  FileSystemError("Inode is not a directory.");
794  return FALSE;
795  }
796 
797  // Fill in file info struct so we can call Ext2ReadFileBig()
798  RtlZeroMemory(&DirectoryFileInfo, sizeof(EXT2_FILE_INFO));
799  DirectoryFileInfo.DriveNumber = Ext2DriveNumber;
800  DirectoryFileInfo.FileBlockList = Ext2ReadBlockPointerList(InodePointer);
801  DirectoryFileInfo.FilePointer = 0;
802  DirectoryFileInfo.FileSize = Ext2GetInodeFileSize(InodePointer);
803 
804  if (DirectoryFileInfo.FileBlockList == NULL)
805  {
806  return FALSE;
807  }
808 
809  //
810  // Now allocate the memory to hold the group descriptors
811  //
812  ASSERT(DirectoryFileInfo.FileSize <= 0xFFFFFFFF);
813  *DirectoryBuffer = (PEXT2_DIR_ENTRY)FrLdrTempAlloc((ULONG)DirectoryFileInfo.FileSize, TAG_EXT_BUFFER);
814 
815  //
816  // Make sure we got the memory
817  //
818  if (*DirectoryBuffer == NULL)
819  {
820  FrLdrTempFree(DirectoryFileInfo.FileBlockList, TAG_EXT_BLOCK_LIST);
821  FileSystemError("Out of memory.");
822  return FALSE;
823  }
824 
825  // Now read the root directory data
826  if (!Ext2ReadFileBig(&DirectoryFileInfo, DirectoryFileInfo.FileSize, NULL, *DirectoryBuffer))
827  {
828  FrLdrTempFree(*DirectoryBuffer, TAG_EXT_BUFFER);
829  *DirectoryBuffer = NULL;
830  FrLdrTempFree(DirectoryFileInfo.FileBlockList, TAG_EXT_BLOCK_LIST);
831  return FALSE;
832  }
833 
834  FrLdrTempFree(DirectoryFileInfo.FileBlockList, TAG_EXT_BLOCK_LIST);
835  return TRUE;
836 }
837 
839 {
840  CHAR ErrorString[80];
841 
842  TRACE("Ext2ReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer);
843 
844  // Make sure its a valid block
845  if (BlockNumber > Ext2SuperBlock->total_blocks)
846  {
847  sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
848  FileSystemError(ErrorString);
849  return FALSE;
850  }
851 
852  // Check to see if this is a sparse block
853  if (BlockNumber == 0)
854  {
855  TRACE("Block is part of a sparse file. Zeroing input buffer.\n");
856 
858 
859  return TRUE;
860  }
861 
863 }
864 
865 /*
866  * Ext2ReadPartialBlock()
867  * Reads part of a block into memory
868  */
870 {
871  PVOID TempBuffer;
872 
873  TRACE("Ext2ReadPartialBlock() BlockNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", BlockNumber, StartingOffset, Length, Buffer);
874 
876 
877  if (!Ext2ReadBlock(BlockNumber, TempBuffer))
878  {
879  return FALSE;
880  }
881 
882  memcpy(Buffer, ((PUCHAR)TempBuffer + StartingOffset), Length);
883 
884  FrLdrTempFree(TempBuffer, TAG_EXT_BUFFER);
885 
886  return TRUE;
887 }
888 
890 {
892 }
893 
895 {
896  return ((Group * sizeof(EXT2_GROUP_DESC)) % Ext2GroupDescPerBlock);
897 }
898 
900 {
901  return ((Inode - 1) / Ext2SuperBlock->inodes_per_group);
902 }
903 
905 {
906  return (((Inode - 1) % Ext2SuperBlock->inodes_per_group) / Ext2InodesPerBlock);
907 }
908 
910 {
911  return (((Inode - 1) % Ext2SuperBlock->inodes_per_group) % Ext2InodesPerBlock);
912 }
913 
915 {
916  ULONG InodeGroupNumber;
917  ULONG InodeBlockNumber;
918  ULONG InodeOffsetInBlock;
919  CHAR ErrorString[80];
920  EXT2_GROUP_DESC GroupDescriptor;
921 
922  TRACE("Ext2ReadInode() Inode = %d\n", Inode);
923 
924  // Make sure its a valid inode
925  if ((Inode < 1) || (Inode > Ext2SuperBlock->total_inodes))
926  {
927  sprintf(ErrorString, "Error reading inode %ld - inode out of range.", Inode);
928  FileSystemError(ErrorString);
929  return FALSE;
930  }
931 
932  // Get inode group & block number and offset in block
933  InodeGroupNumber = Ext2GetInodeGroupNumber(Inode);
934  InodeBlockNumber = Ext2GetInodeBlockNumber(Inode);
935  InodeOffsetInBlock = Ext2GetInodeOffsetInBlock(Inode);
936  TRACE("InodeGroupNumber = %d\n", InodeGroupNumber);
937  TRACE("InodeBlockNumber = %d\n", InodeBlockNumber);
938  TRACE("InodeOffsetInBlock = %d\n", InodeOffsetInBlock);
939 
940  // Read the group descriptor
941  if (!Ext2ReadGroupDescriptor(InodeGroupNumber, &GroupDescriptor))
942  {
943  return FALSE;
944  }
945 
946  // Add the start block of the inode table to the inode block number
947  InodeBlockNumber += GroupDescriptor.inode_table_id;
948  TRACE("InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber);
949 
950  // Read the block
951  if (!Ext2ReadPartialBlock(InodeBlockNumber,
952  (InodeOffsetInBlock * EXT2_INODE_SIZE(Ext2SuperBlock)),
953  sizeof(EXT2_INODE),
954  InodeBuffer))
955  {
956  return FALSE;
957  }
958 
959  TRACE("Dumping inode information:\n");
960  TRACE("mode = 0x%x\n", InodeBuffer->mode);
961  TRACE("uid = %d\n", InodeBuffer->uid);
962  TRACE("size = %d\n", InodeBuffer->size);
963  TRACE("atime = %d\n", InodeBuffer->atime);
964  TRACE("ctime = %d\n", InodeBuffer->ctime);
965  TRACE("mtime = %d\n", InodeBuffer->mtime);
966  TRACE("dtime = %d\n", InodeBuffer->dtime);
967  TRACE("gid = %d\n", InodeBuffer->gid);
968  TRACE("nlinks = %d\n", InodeBuffer->nlinks);
969  TRACE("blockcnt = %d\n", InodeBuffer->blockcnt);
970  TRACE("flags = 0x%x\n", InodeBuffer->flags);
971  TRACE("osd1 = 0x%x\n", InodeBuffer->osd1);
972  TRACE("dir_blocks = { %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u }\n",
973  InodeBuffer->blocks.dir_blocks[0], InodeBuffer->blocks.dir_blocks[1], InodeBuffer->blocks.dir_blocks[ 2], InodeBuffer->blocks.dir_blocks[ 3],
974  InodeBuffer->blocks.dir_blocks[4], InodeBuffer->blocks.dir_blocks[5], InodeBuffer->blocks.dir_blocks[ 6], InodeBuffer->blocks.dir_blocks[ 7],
975  InodeBuffer->blocks.dir_blocks[8], InodeBuffer->blocks.dir_blocks[9], InodeBuffer->blocks.dir_blocks[10], InodeBuffer->blocks.dir_blocks[11]);
976  TRACE("indir_block = %u\n", InodeBuffer->blocks.indir_block);
977  TRACE("double_indir_block = %u\n", InodeBuffer->blocks.double_indir_block);
978  TRACE("tripple_indir_block = %u\n", InodeBuffer->blocks.tripple_indir_block);
979  TRACE("version = %d\n", InodeBuffer->version);
980  TRACE("acl = %d\n", InodeBuffer->acl);
981  TRACE("dir_acl = %d\n", InodeBuffer->dir_acl);
982  TRACE("fragment_addr = %d\n", InodeBuffer->fragment_addr);
983  TRACE("osd2 = { %d, %d, %d }\n",
984  InodeBuffer->osd2[0], InodeBuffer->osd2[1], InodeBuffer->osd2[2]);
985 
986  return TRUE;
987 }
988 
990 {
991  TRACE("Ext2ReadGroupDescriptor()\n");
992 
993  /*if (!Ext2ReadBlock(Ext2GetGroupDescBlockNumber(Group), (PVOID)FILESYSBUFFER))
994  {
995  return FALSE;
996  }
997 
998  RtlCopyMemory(GroupBuffer, (PVOID)(FILESYSBUFFER + Ext2GetGroupDescOffsetInBlock(Group)), sizeof(EXT2_GROUP_DESC));*/
999 
1000  RtlCopyMemory(GroupBuffer, &Ext2GroupDescriptors[Group], sizeof(EXT2_GROUP_DESC));
1001 
1002  TRACE("Dumping group descriptor:\n");
1003  TRACE("block_id = %d\n", GroupBuffer->block_id);
1004  TRACE("inode_id = %d\n", GroupBuffer->inode_id);
1005  TRACE("inode_table_id = %d\n", GroupBuffer->inode_table_id);
1006  TRACE("free_blocks = %d\n", GroupBuffer->free_blocks);
1007  TRACE("free_inodes = %d\n", GroupBuffer->free_inodes);
1008  TRACE("used_dirs = %d\n", GroupBuffer->used_dirs);
1009 
1010  return TRUE;
1011 }
1012 
1014 {
1016  ULONG BlockCount;
1017  ULONG* BlockList;
1018  ULONG CurrentBlockInList;
1019  ULONG CurrentBlock;
1020 
1021  TRACE("Ext2ReadBlockPointerList()\n");
1022 
1023  // Get the number of blocks this file occupies
1024  // I would just use Inode->i_blocks but it
1025  // doesn't seem to be the number of blocks
1026  // the file size corresponds to, but instead
1027  // it is much bigger.
1028  //BlockCount = Inode->i_blocks;
1029  FileSize = Ext2GetInodeFileSize(Inode);
1031  BlockCount = (ULONG)(FileSize / Ext2BlockSizeInBytes);
1032 
1033  // Allocate the memory for the block list
1034  BlockList = FrLdrTempAlloc(BlockCount * sizeof(ULONG), TAG_EXT_BLOCK_LIST);
1035  if (BlockList == NULL)
1036  {
1037  return NULL;
1038  }
1039 
1040  RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG));
1041 
1042  // Copy the direct block pointers
1043  for (CurrentBlockInList = CurrentBlock = 0;
1044  CurrentBlockInList < BlockCount && CurrentBlock < INDIRECT_BLOCKS;
1045  CurrentBlock++, CurrentBlockInList++)
1046  {
1047  BlockList[CurrentBlockInList] = Inode->blocks.dir_blocks[CurrentBlock];
1048  }
1049 
1050  // Copy the indirect block pointers
1051  if (CurrentBlockInList < BlockCount)
1052  {
1053  if (!Ext2CopyIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.indir_block))
1054  {
1055  FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
1056  return NULL;
1057  }
1058  }
1059 
1060  // Copy the double indirect block pointers
1061  if (CurrentBlockInList < BlockCount)
1062  {
1063  if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.double_indir_block))
1064  {
1065  FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
1066  return NULL;
1067  }
1068  }
1069 
1070  // Copy the triple indirect block pointers
1071  if (CurrentBlockInList < BlockCount)
1072  {
1073  if (!Ext2CopyTripleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->blocks.tripple_indir_block))
1074  {
1075  FrLdrTempFree(BlockList, TAG_EXT_BLOCK_LIST);
1076  return NULL;
1077  }
1078  }
1079 
1080  return BlockList;
1081 }
1082 
1084 {
1085  if ((Inode->mode & EXT2_S_IFMT) == EXT2_S_IFDIR)
1086  {
1087  return (ULONGLONG)(Inode->size);
1088  }
1089  else
1090  {
1091  return ((ULONGLONG)(Inode->size) | ((ULONGLONG)(Inode->dir_acl) << 32));
1092  }
1093 }
1094 
1095 BOOLEAN Ext2CopyIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
1096 {
1097  ULONG* BlockBuffer;
1098  ULONG CurrentBlock;
1099  ULONG BlockPointersPerBlock;
1100 
1101  TRACE("Ext2CopyIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1102 
1103  BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
1104 
1106  if (!BlockBuffer)
1107  {
1108  return FALSE;
1109  }
1110 
1111  if (!Ext2ReadBlock(IndirectBlock, BlockBuffer))
1112  {
1113  return FALSE;
1114  }
1115 
1116  for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1117  {
1118  BlockList[(*CurrentBlockInList)] = BlockBuffer[CurrentBlock];
1119  (*CurrentBlockInList)++;
1120  }
1121 
1122  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1123 
1124  return TRUE;
1125 }
1126 
1127 BOOLEAN Ext2CopyDoubleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
1128 {
1129  ULONG* BlockBuffer;
1130  ULONG CurrentBlock;
1131  ULONG BlockPointersPerBlock;
1132 
1133  TRACE("Ext2CopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1134 
1135  BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
1136 
1138  if (BlockBuffer == NULL)
1139  {
1140  return FALSE;
1141  }
1142 
1143  if (!Ext2ReadBlock(DoubleIndirectBlock, BlockBuffer))
1144  {
1145  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1146  return FALSE;
1147  }
1148 
1149  for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1150  {
1151  if (!Ext2CopyIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
1152  {
1153  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1154  return FALSE;
1155  }
1156  }
1157 
1158  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1159  return TRUE;
1160 }
1161 
1162 BOOLEAN Ext2CopyTripleIndirectBlockPointers(ULONG* BlockList, ULONG* CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
1163 {
1164  ULONG* BlockBuffer;
1165  ULONG CurrentBlock;
1166  ULONG BlockPointersPerBlock;
1167 
1168  TRACE("Ext2CopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1169 
1170  BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(ULONG);
1171 
1173  if (BlockBuffer == NULL)
1174  {
1175  return FALSE;
1176  }
1177 
1178  if (!Ext2ReadBlock(TripleIndirectBlock, BlockBuffer))
1179  {
1180  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1181  return FALSE;
1182  }
1183 
1184  for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1185  {
1186  if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
1187  {
1188  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1189  return FALSE;
1190  }
1191  }
1192 
1193  FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1194  return TRUE;
1195 }
1196 
1198 {
1200 
1202 
1203  return ESUCCESS;
1204 }
1205 
1207 {
1209 
1211  Information->EndingAddress.QuadPart = FileHandle->FileSize;
1212  Information->CurrentAddress.QuadPart = FileHandle->FilePointer;
1213 
1214  TRACE("Ext2GetFileInformation() FileSize = %d\n",
1215  Information->EndingAddress.LowPart);
1216  TRACE("Ext2GetFileInformation() FilePointer = %d\n",
1217  Information->CurrentAddress.LowPart);
1218 
1219  return ESUCCESS;
1220 }
1221 
1223 {
1225  //ULONG DeviceId;
1226 
1227  if (OpenMode != OpenReadOnly)
1228  return EACCES;
1229 
1230  //DeviceId = FsGetDeviceId(*FileId);
1231 
1232  TRACE("Ext2Open() FileName = %s\n", Path);
1233 
1234  //
1235  // Call old open method
1236  //
1238 
1239  //
1240  // Check for error
1241  //
1242  if (!FileHandle)
1243  return ENOENT;
1244 
1245  //
1246  // Success. Remember the handle
1247  //
1248  FsSetDeviceSpecific(*FileId, FileHandle);
1249  return ESUCCESS;
1250 }
1251 
1253 {
1255  ULONGLONG BytesReadBig;
1256  BOOLEAN Success;
1257 
1258  //
1259  // Read data
1260  //
1261  Success = Ext2ReadFileBig(FileHandle, N, &BytesReadBig, Buffer);
1262  *Count = (ULONG)BytesReadBig;
1263 
1264  //
1265  // Check for success
1266  //
1267  if (Success)
1268  return ESUCCESS;
1269  else
1270  return EIO;
1271 }
1272 
1274 {
1276 
1277  TRACE("Ext2Seek() NewFilePointer = %lu\n", Position->LowPart);
1278 
1279  if (SeekMode != SeekAbsolute)
1280  return EINVAL;
1281  if (Position->HighPart != 0)
1282  return EINVAL;
1283  if (Position->LowPart >= FileHandle->FileSize)
1284  return EINVAL;
1285 
1286  FileHandle->FilePointer = Position->LowPart;
1287  return ESUCCESS;
1288 }
1289 
1291 {
1292  Ext2Close,
1294  Ext2Open,
1295  Ext2Read,
1296  Ext2Seek,
1297  L"ext2fs",
1298 };
1299 
1300 const DEVVTBL* Ext2Mount(ULONG DeviceId)
1301 {
1302  EXT2_SUPER_BLOCK SuperBlock;
1304  ULONG Count;
1306 
1307  //
1308  // Read the SuperBlock
1309  //
1310  Position.HighPart = 0;
1311  Position.LowPart = 2 * 512;
1312  Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1313  if (Status != ESUCCESS)
1314  return NULL;
1315  Status = ArcRead(DeviceId, &SuperBlock, sizeof(SuperBlock), &Count);
1316  if (Status != ESUCCESS || Count != sizeof(SuperBlock))
1317  return NULL;
1318 
1319  //
1320  // Check if SuperBlock is valid. If yes, return Ext2 function table
1321  //
1322  if (SuperBlock.magic == EXT2_MAGIC)
1323  {
1324  //
1325  // Compatibility hack as long as FS is not using underlying device DeviceId
1326  //
1327  UCHAR DriveNumber;
1328  ULONGLONG StartSector;
1330  int Type;
1331  if (!DiskGetBootVolume(&DriveNumber, &StartSector, &SectorCount, &Type))
1332  return NULL;
1333  Ext2OpenVolume(DriveNumber, StartSector, SectorCount);
1334  return &Ext2FuncTable;
1335  }
1336  else
1337  return NULL;
1338 }
1339 
1340 #endif
1341 
ULONGLONG Ext2VolumeStartSector
Definition: ext2.c:57
ULONG PartitionSectorCount
Definition: xboxdisk.c:39
signed char * PCHAR
Definition: retypes.h:7
UCHAR filetype
Definition: ext2.h:163
ULONGLONG FilePointer
Definition: ext2.h:232
ULONG feature_incompat
Definition: ext2.h:100
#define MachDiskReadLogicalSectors(Drive, Start, Count, Buf)
Definition: machine.h:120
ULONG free_blocks
Definition: ext2.h:74
ULONG Ext2FragmentSizeInSectors
Definition: ext2.c:61
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
BOOLEAN Ext2ReadDirectory(ULONG Inode, PVOID *DirectoryBuffer, PEXT2_INODE InodePointer)
Definition: ext2.c:778
ULONG Ext2GetInodeGroupNumber(ULONG Inode)
Definition: ext2.c:899
ULONG * FileBlockList
Definition: ext2.h:233
USHORT uid_reserved
Definition: ext2.h:94
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
USHORT inode_size
Definition: ext2.h:97
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:414
Type
Definition: Type.h:6
BOOLEAN Ext2ReadFileBig(PEXT2_FILE_INFO Ext2FileInfo, ULONGLONG BytesToRead, ULONGLONG *BytesRead, PVOID Buffer)
Definition: ext2.c:381
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
ULONG mtime
Definition: ext2.h:130
ULONG first_inode
Definition: ext2.h:96
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define EXT2_S_IFLNK
Definition: ext2.h:224
USHORT fs_state
Definition: ext2.h:87
ULONG atime
Definition: ext2.h:128
ULONG checkinterval
Definition: ext2.h:91
ULONG block_id
Definition: ext2.h:112
ULONG inode_id
Definition: ext2.h:113
Definition: arc.h:32
ULONG Ext2GetInodeOffsetInBlock(ULONG Inode)
Definition: ext2.c:909
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
ULONG Ext2InodesPerBlock
Definition: ext2.c:63
struct ext2_sblock * PEXT2_SUPER_BLOCK
Definition: ext2.h:171
USHORT free_inodes
Definition: ext2.h:116
ULONG fragment_addr
Definition: ext2.h:151
Definition: arc.h:39
ULONG dtime
Definition: ext2.h:131
#define EXT3_FEATURE_INCOMPAT_SUPP
Definition: ext2.h:180
_In_opt_ PSID Group
Definition: rtlfuncs.h:1606
static COORD Position
Definition: mouse.c:34
#define DiskReadBuffer
Definition: hardware.h:33
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
ULONGLONG Ext2GetInodeFileSize(PEXT2_INODE Inode)
Definition: ext2.c:1083
ULONG feature_ro_compat
Definition: ext2.h:101
UCHAR namelen
Definition: ext2.h:162
Definition: fs.h:22
struct ext2_block_group * PEXT2_GROUP_DESC
Definition: ext2.h:173
EXT2_INODE Inode
Definition: ext2.h:235
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:386
BOOLEAN DiskGetBootVolume(PUCHAR DriveNumber, PULONGLONG StartSector, PULONGLONG SectorCount, int *FsType)
Definition: ext2.c:72
#define TAG_EXT_BUFFER
Definition: ext2.c:68
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
BOOLEAN Ext2ReadSuperBlock(VOID)
Definition: ext2.c:579
ULONG inode
Definition: ext2.h:160
ULONG ARC_STATUS
Definition: arc.h:4
#define INDIRECT_BLOCKS
Definition: ext2.h:45
ULONG Ext2GetGroupDescBlockNumber(ULONG Group)
Definition: ext2.c:889
#define FAST_SYMLINK_MAX_NAME_SIZE
Definition: ext2.h:227
ULONG dir_acl
Definition: ext2.h:150
USHORT uid
Definition: ext2.h:126
USHORT max_mnt_count
Definition: ext2.h:85
ULONG free_inodes
Definition: ext2.h:75
ULONG unique_id[4]
Definition: ext2.h:102
ULONG total_inodes
Definition: ext2.h:71
ULONG mtime
Definition: ext2.h:82
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:474
ULONG feature_compatibility
Definition: ext2.h:99
ULONG acl
Definition: ext2.h:149
char volume_name[16]
Definition: ext2.h:103
BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
Definition: cache.c:37
GEOMETRY Ext2DiskGeometry
Definition: ext2.c:51
ULONG Ext2GetGroupDescOffsetInBlock(ULONG Group)
Definition: ext2.c:894
uint32_t ULONG_PTR
Definition: typedefs.h:63
BOOLEAN Ext2OpenVolume(UCHAR DriveNumber, ULONGLONG VolumeStartSector, ULONGLONG PartitionSectorCount)
Definition: ext2.c:81
ULONG ctime
Definition: ext2.h:129
#define EXT2_MAGIC
Definition: ext2.h:43
ULONG Ext2GroupCount
Definition: ext2.c:62
BOOLEAN Ext2ReadGroupDescriptor(ULONG Group, PEXT2_GROUP_DESC GroupBuffer)
Definition: ext2.c:989
#define sprintf(buf, format,...)
Definition: sprintf.c:55
BOOLEAN Ext2ReadPartialBlock(ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
Definition: ext2.c:869
USHORT gid
Definition: ext2.h:132
HANDLE FileHandle
Definition: stats.c:38
ULONG size
Definition: ext2.h:127
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOLEAN Ext2ReadInode(ULONG Inode, PEXT2_INODE InodeBuffer)
Definition: ext2.c:914
ULONG reserved_blocks
Definition: ext2.h:73
unsigned int UINT32
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:260
ULONG Ext2GetInodeBlockNumber(ULONG Inode)
Definition: ext2.c:904
ULONG compression_info
Definition: ext2.h:105
BOOLEAN Ext2LookupFile(PCSTR FileName, PEXT2_FILE_INFO Ext2FileInfoPointer)
Definition: ext2.c:226
ARC_STATUS Ext2GetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ext2.c:1206
ULONGLONG FileSize
Definition: ext2.h:231
_Check_return_ _CRTIMP int __cdecl _strnicmp(_In_reads_or_z_(_MaxCount) const char *_Str1, _In_reads_or_z_(_MaxCount) const char *_Str2, _In_ size_t _MaxCount)
ULONG version
Definition: ext2.h:148
BOOLEAN Ext2SearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT2_DIR_ENTRY DirectoryEntry)
Definition: ext2.c:325
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
unsigned char BOOLEAN
USHORT direntlen
Definition: ext2.h:161
ULONG utime
Definition: ext2.h:83
smooth NULL
Definition: ftsmooth.c:416
enum _SEEKMODE SEEKMODE
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
USHORT magic
Definition: ext2.h:86
ULONG flags
Definition: ext2.h:135
#define MachDiskGetDriveGeometry(Drive, Geom)
Definition: machine.h:122
DBG_DEFAULT_CHANNEL(FILESYSTEM)
ULONG log2_block_size
Definition: ext2.h:77
#define EXT2_ROOT_INO
Definition: ext2.h:177
BOOLEAN Ext2ReadGroupDescriptors(VOID)
Definition: ext2.c:727
USHORT mnt_count
Definition: ext2.h:84
#define EXT2_S_IFDIR
Definition: ext2.h:221
ULONG blockcnt
Definition: ext2.h:134
PEXT2_GROUP_DESC Ext2GroupDescriptors
Definition: ext2.c:54
#define EXT2_INODE_SIZE(sb)
Definition: ext2.h:192
ULONG inode_table_id
Definition: ext2.h:114
#define TRACE(s)
Definition: solgame.cpp:4
ULONG revision_level
Definition: ext2.h:93
#define TAG_EXT_BLOCK_LIST
Definition: ext2.c:66
uint64_t ULONGLONG
Definition: typedefs.h:65
#define EXT2_S_IFMT
Definition: ext2.h:218
struct ext2_dirent * PEXT2_DIR_ENTRY
Definition: ext2.h:174
ULONG Ext2BlockSizeInSectors
Definition: ext2.c:59
static const UCHAR Index[8]
Definition: usbohci.c:18
BOOLEAN Ext2CopyDoubleIndirectBlockPointers(ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
Definition: ext2.c:1127
ARC_STATUS Ext2Close(ULONG FileId)
Definition: ext2.c:1197
VOID FsSetDeviceSpecific(ULONG FileId, VOID *Specific)
Definition: fs.c:467
ULONG osd2[3]
Definition: ext2.h:152
#define DPRINT_FILESYSTEM
Definition: debug.h:26
ULONG first_data_block
Definition: ext2.h:76
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
BOOLEAN Ext2CopyTripleIndirectBlockPointers(ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
Definition: ext2.c:1162
USHORT gid_reserved
Definition: ext2.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:237
#define EXT2_DESC_PER_BLOCK(s)
Definition: ext2.h:196
unsigned char UCHAR
Definition: xmlstorage.h:181
Definition: arc.h:34
ULONG blocks_per_group
Definition: ext2.h:79
static const WCHAR L[]
Definition: oid.c:1250
#define EXT2_NAME_LEN
Definition: ext2.h:156
UCHAR DriveNumber
Definition: ext2.h:234
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:244
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
USHORT free_blocks
Definition: ext2.h:115
char last_mounted_on[64]
Definition: ext2.h:104
ARC_STATUS Ext2Open(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ext2.c:1222
ULONG SectorCount
Definition: part_xbox.c:32
#define EXT2_S_IFREG
Definition: ext2.h:223
ULONG Ext2FragmentSizeInBytes
Definition: ext2.c:60
Status
Definition: gdiplustypes.h:24
ULONG Ext2BlockSizeInBytes
Definition: ext2.c:58
ARC_STATUS Ext2Seek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ext2.c:1273
ULONG BytesPerSector
Definition: disk.h:29
ULONG * Ext2ReadBlockPointerList(PEXT2_INODE Inode)
Definition: ext2.c:1013
PRTL_UNICODE_STRING_BUFFER Path
ARC_STATUS Ext2Read(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ext2.c:1252
#define TAG_EXT_FILE
Definition: ext2.c:67
ULONG total_blocks
Definition: ext2.h:72
PEXT2_SUPER_BLOCK Ext2SuperBlock
Definition: ext2.c:53
USHORT nlinks
Definition: ext2.h:133
const DEVVTBL * Ext2Mount(ULONG DeviceId)
Definition: ext2.c:1300
char symlink[60]
Definition: ext2.h:146
Definition: disk.h:24
#define DbgDumpBuffer(mask, buf, len)
Definition: debug.h:118
#define TAG_EXT_SUPER_BLOCK
Definition: ext2.c:69
Definition: arc.h:46
CHAR name[EXT2_NAME_LEN]
Definition: ext2.h:164
USHORT mode
Definition: ext2.h:125
Definition: arc.h:40
ULONG osd1
Definition: ext2.h:136
#define EXT2_DYNAMIC_REVISION
Definition: ext2.h:53
BOOLEAN Ext2CopyIndirectBlockPointers(ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
Definition: ext2.c:1095
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
USHORT used_dirs
Definition: ext2.h:117
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
UCHAR Ext2DriveNumber
Definition: ext2.c:56
ULONG lastcheck
Definition: ext2.h:90
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
struct ext2_inode::@162::datablocks blocks
const char * PCSTR
Definition: typedefs.h:51
const DEVVTBL Ext2FuncTable
Definition: ext2.c:1290
ULONG Ext2GroupDescPerBlock
Definition: ext2.c:64
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
ULONG inodes_per_group
Definition: ext2.h:81
PEXT2_FILE_INFO Ext2OpenFile(PCSTR FileName)
Definition: ext2.c:123
ULONG creator_os
Definition: ext2.h:92
enum _OPENMODE OPENMODE
BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
Definition: cache.c:116
LONG log2_fragment_size
Definition: ext2.h:78
BOOLEAN Ext2ReadVolumeSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: ext2.c:564
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255
ULONG fragments_per_group
Definition: ext2.h:80
USHORT block_group_number
Definition: ext2.h:98
USHORT error_handling
Definition: ext2.h:88
Iosb Information
Definition: create.c:4377
USHORT minor_revision_level
Definition: ext2.h:89
BOOLEAN Ext2ReadBlock(ULONG BlockNumber, PVOID Buffer)
Definition: ext2.c:838
#define TAG_EXT_GROUP_DESC
Definition: ext2.c:70
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186