ReactOS 0.4.16-dev-1946-g52006dd
ext.c File Reference
#include <freeldr.h>
#include "fs/stat.h"
#include <debug.h>
Include dependency graph for ext.c:

Go to the source code of this file.

Classes

struct  _EXT_VOLUME_INFO
 

Macros

#define TAG_EXT_BLOCK_LIST   'LtxE'
 
#define TAG_EXT_FILE   'FtxE'
 
#define TAG_EXT_BUFFER   'BtxE'
 
#define TAG_EXT_SUPER_BLOCK   'StxE'
 
#define TAG_EXT_GROUP_DESC   'GtxE'
 
#define TAG_EXT_VOLUME   'VtxE'
 

Typedefs

typedef struct _EXT_VOLUME_INFO EXT_VOLUME_INFO
 

Functions

 DBG_DEFAULT_CHANNEL (FILESYSTEM)
 
BOOLEAN ExtOpenVolume (PEXT_VOLUME_INFO Volume)
 
PEXT_FILE_INFO ExtOpenFile (PEXT_VOLUME_INFO Volume, PCSTR FileName)
 
BOOLEAN ExtLookupFile (PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO ExtFileInfo)
 
BOOLEAN ExtSearchDirectoryBufferForFile (PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT_DIR_ENTRY DirectoryEntry)
 
BOOLEAN ExtReadVolumeSectors (PEXT_VOLUME_INFO Volume, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
 
BOOLEAN ExtReadFileBig (PEXT_FILE_INFO ExtFileInfo, ULONGLONG BytesToRead, ULONGLONG *BytesRead, PVOID Buffer)
 
BOOLEAN ExtReadSuperBlock (PEXT_VOLUME_INFO Volume)
 
BOOLEAN ExtReadGroupDescriptors (PEXT_VOLUME_INFO Volume)
 
BOOLEAN ExtReadDirectory (PEXT_VOLUME_INFO Volume, ULONG Inode, PVOID *DirectoryBuffer, PEXT_INODE InodePointer)
 
BOOLEAN ExtReadBlock (PEXT_VOLUME_INFO Volume, ULONG BlockNumber, PVOID Buffer)
 
BOOLEAN ExtReadPartialBlock (PEXT_VOLUME_INFO Volume, ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
 
BOOLEAN ExtReadInode (PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffer)
 
BOOLEAN ExtReadGroupDescriptor (PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_DESC GroupBuffer)
 
ULONGExtReadBlockPointerList (PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
 
ULONGLONG ExtGetInodeFileSize (PEXT_INODE Inode)
 
BOOLEAN ExtCopyBlockPointersByExtents (PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader)
 
BOOLEAN ExtCopyIndirectBlockPointers (PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
 
BOOLEAN ExtCopyDoubleIndirectBlockPointers (PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
 
BOOLEAN ExtCopyTripleIndirectBlockPointers (PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
 
ULONG ExtGetInodeGroupNumber (PEXT_VOLUME_INFO Volume, ULONG Inode)
 
ULONG ExtGetInodeBlockNumber (PEXT_VOLUME_INFO Volume, ULONG Inode)
 
ULONG ExtGetInodeOffsetInBlock (PEXT_VOLUME_INFO Volume, ULONG Inode)
 
ARC_STATUS ExtClose (ULONG FileId)
 
ARC_STATUS ExtGetFileInformation (ULONG FileId, FILEINFORMATION *Information)
 
ARC_STATUS ExtOpen (CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
 
ARC_STATUS ExtRead (ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
 
ARC_STATUS ExtSeek (ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
 
ULONGLONG ExtGetVolumeSize (_In_ ULONG DeviceId)
 Returns the size of the EXT2/3/4 volume laid on the storage media device opened via DeviceId.
 
const DEVVTBLExtMount (ULONG DeviceId)
 

Variables

PEXT_VOLUME_INFO ExtVolumes [MAX_FDS]
 
const DEVVTBL ExtFuncTable
 

Macro Definition Documentation

◆ TAG_EXT_BLOCK_LIST

#define TAG_EXT_BLOCK_LIST   'LtxE'

Definition at line 72 of file ext.c.

◆ TAG_EXT_BUFFER

#define TAG_EXT_BUFFER   'BtxE'

Definition at line 74 of file ext.c.

◆ TAG_EXT_FILE

#define TAG_EXT_FILE   'FtxE'

Definition at line 73 of file ext.c.

◆ TAG_EXT_GROUP_DESC

#define TAG_EXT_GROUP_DESC   'GtxE'

Definition at line 76 of file ext.c.

◆ TAG_EXT_SUPER_BLOCK

#define TAG_EXT_SUPER_BLOCK   'StxE'

Definition at line 75 of file ext.c.

◆ TAG_EXT_VOLUME

#define TAG_EXT_VOLUME   'VtxE'

Definition at line 77 of file ext.c.

Typedef Documentation

◆ EXT_VOLUME_INFO

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( FILESYSTEM  )

◆ ExtClose()

ARC_STATUS ExtClose ( ULONG  FileId)

Definition at line 1302 of file ext.c.

1303{
1306 return ESUCCESS;
1307}
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:709
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
#define TAG_EXT_FILE
Definition: ext.c:73
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ ESUCCESS
Definition: arc.h:32

◆ ExtCopyBlockPointersByExtents()

BOOLEAN ExtCopyBlockPointersByExtents ( PEXT_VOLUME_INFO  Volume,
ULONG BlockList,
ULONG CurrentBlockInList,
ULONG  BlockCount,
PEXT4_EXTENT_HEADER  ExtentHeader 
)

Definition at line 1134 of file ext.c.

1135{
1136 TRACE("ExtCopyBlockPointersByExtents() BlockCount = 0x%p\n", BlockCount);
1137
1138 if (ExtentHeader->Magic != EXT4_EXTENT_HEADER_MAGIC ||
1139 ExtentHeader->Depth > EXT4_EXTENT_MAX_LEVEL)
1140 return FALSE;
1141
1142 ULONG Level = ExtentHeader->Depth;
1143 ULONG Entries = ExtentHeader->Entries;
1144
1145 TRACE("Level: %d\n", Level);
1146 TRACE("Entries: %d\n", Entries);
1147
1148 // If the level is 0, we have a direct extent block mapping
1149 if (!Level)
1150 {
1151 PEXT4_EXTENT Extent = (PVOID)&ExtentHeader[1];
1152
1153 while ((*CurrentBlockInList) < BlockCount && Entries--)
1154 {
1155 BOOLEAN SparseExtent = (Extent->Length > EXT4_EXTENT_MAX_LENGTH);
1156 ULONG Length = SparseExtent ? (Extent->Length - EXT4_EXTENT_MAX_LENGTH) : Extent->Length;
1157 ULONG CurrentBlock = SparseExtent ? 0 : Extent->Start;
1158
1159 // Copy the pointers to the block list
1160 while ((*CurrentBlockInList) < BlockCount && Length--)
1161 {
1162 BlockList[(*CurrentBlockInList)++] = CurrentBlock;
1163
1164 if (!SparseExtent)
1165 CurrentBlock++;
1166 }
1167
1168 Extent++;
1169 }
1170 }
1171 else
1172 {
1173 PEXT4_EXTENT_IDX Extent = (PVOID)&ExtentHeader[1];
1174
1175 PEXT4_EXTENT_HEADER BlockBuffer = FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
1176 if (!BlockBuffer)
1177 {
1178 return FALSE;
1179 }
1180
1181 // Recursively copy the pointers to the block list
1182 while ((*CurrentBlockInList) < BlockCount && Entries--)
1183 {
1184 if (!(ExtReadBlock(Volume, Extent->Leaf, BlockBuffer) &&
1185 ExtCopyBlockPointersByExtents(Volume, BlockList, CurrentBlockInList, BlockCount, BlockBuffer)))
1186 {
1187 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1188 return FALSE;
1189 }
1190
1191 Extent++;
1192 }
1193
1194 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1195 }
1196
1197 return TRUE;
1198}
unsigned char BOOLEAN
#define EXT4_EXTENT_MAX_LEVEL
Definition: ext.h:218
#define EXT4_EXTENT_HEADER_MAGIC
Definition: ext.h:215
#define EXT4_EXTENT_MAX_LENGTH
Definition: ext.h:221
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader)
Definition: ext.c:1134
BOOLEAN ExtReadBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, PVOID Buffer)
Definition: ext.c:873
#define TAG_EXT_BUFFER
Definition: ext.c:74
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UNICODE_STRING Volume
Definition: fltkernel.h:1172
static const ENTRY Entries[]
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define TRACE(s)
Definition: solgame.cpp:4
uint64 Length
Definition: DriveVolume.h:48
USHORT Magic
Definition: ext.h:130
USHORT Depth
Definition: ext.h:133
USHORT Entries
Definition: ext.h:131
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG
Definition: typedefs.h:59
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56

Referenced by ExtCopyBlockPointersByExtents(), and ExtReadBlockPointerList().

◆ ExtCopyDoubleIndirectBlockPointers()

BOOLEAN ExtCopyDoubleIndirectBlockPointers ( PEXT_VOLUME_INFO  Volume,
ULONG BlockList,
ULONG CurrentBlockInList,
ULONG  BlockCount,
ULONG  DoubleIndirectBlock 
)

Definition at line 1232 of file ext.c.

1233{
1234 ULONG* BlockBuffer;
1235 ULONG CurrentBlock;
1236 ULONG BlockPointersPerBlock;
1237
1238 TRACE("ExtCopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1239
1240 BlockPointersPerBlock = Volume->BlockSizeInBytes / sizeof(ULONG);
1241
1242 BlockBuffer = (ULONG*)FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
1243 if (BlockBuffer == NULL)
1244 {
1245 return FALSE;
1246 }
1247
1248 if (!ExtReadBlock(Volume, DoubleIndirectBlock, BlockBuffer))
1249 {
1250 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1251 return FALSE;
1252 }
1253
1254 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1255 {
1256 if (!ExtCopyIndirectBlockPointers(Volume, BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
1257 {
1258 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1259 return FALSE;
1260 }
1261 }
1262
1263 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1264 return TRUE;
1265}
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
Definition: ext.c:1200
#define NULL
Definition: types.h:112

Referenced by ExtCopyTripleIndirectBlockPointers(), and ExtReadBlockPointerList().

◆ ExtCopyIndirectBlockPointers()

BOOLEAN ExtCopyIndirectBlockPointers ( PEXT_VOLUME_INFO  Volume,
ULONG BlockList,
ULONG CurrentBlockInList,
ULONG  BlockCount,
ULONG  IndirectBlock 
)

Definition at line 1200 of file ext.c.

1201{
1202 ULONG* BlockBuffer;
1203 ULONG CurrentBlock;
1204 ULONG BlockPointersPerBlock;
1205
1206 TRACE("ExtCopyIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1207
1208 BlockPointersPerBlock = Volume->BlockSizeInBytes / sizeof(ULONG);
1209
1210 BlockBuffer = FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
1211 if (!BlockBuffer)
1212 {
1213 return FALSE;
1214 }
1215
1216 if (!ExtReadBlock(Volume, IndirectBlock, BlockBuffer))
1217 {
1218 return FALSE;
1219 }
1220
1221 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1222 {
1223 BlockList[(*CurrentBlockInList)] = BlockBuffer[CurrentBlock];
1224 (*CurrentBlockInList)++;
1225 }
1226
1227 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1228
1229 return TRUE;
1230}

Referenced by ExtCopyDoubleIndirectBlockPointers(), and ExtReadBlockPointerList().

◆ ExtCopyTripleIndirectBlockPointers()

BOOLEAN ExtCopyTripleIndirectBlockPointers ( PEXT_VOLUME_INFO  Volume,
ULONG BlockList,
ULONG CurrentBlockInList,
ULONG  BlockCount,
ULONG  TripleIndirectBlock 
)

Definition at line 1267 of file ext.c.

1268{
1269 ULONG* BlockBuffer;
1270 ULONG CurrentBlock;
1271 ULONG BlockPointersPerBlock;
1272
1273 TRACE("ExtCopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1274
1275 BlockPointersPerBlock = Volume->BlockSizeInBytes / sizeof(ULONG);
1276
1277 BlockBuffer = (ULONG*)FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
1278 if (BlockBuffer == NULL)
1279 {
1280 return FALSE;
1281 }
1282
1283 if (!ExtReadBlock(Volume, TripleIndirectBlock, BlockBuffer))
1284 {
1285 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1286 return FALSE;
1287 }
1288
1289 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1290 {
1291 if (!ExtCopyDoubleIndirectBlockPointers(Volume, BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
1292 {
1293 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1294 return FALSE;
1295 }
1296 }
1297
1298 FrLdrTempFree(BlockBuffer, TAG_EXT_BUFFER);
1299 return TRUE;
1300}
BOOLEAN ExtCopyDoubleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
Definition: ext.c:1232

Referenced by ExtReadBlockPointerList().

◆ ExtGetFileInformation()

ARC_STATUS ExtGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)

Definition at line 1309 of file ext.c.

1310{
1312
1314 Information->EndingAddress.QuadPart = FileHandle->FileSize;
1315 Information->CurrentAddress.QuadPart = FileHandle->FilePointer;
1316
1317 /* Set the ARC file attributes */
1318 Information->Attributes = FileHandle->Attributes;
1319
1320 /* Copy the file name, perhaps truncated, and NUL-terminated */
1321 Information->FileNameLength = min(FileHandle->FileNameLength, sizeof(Information->FileName) - 1);
1322 RtlCopyMemory(Information->FileName, FileHandle->FileName, Information->FileNameLength);
1323 Information->FileName[Information->FileNameLength] = ANSI_NULL;
1324
1325 TRACE("ExtGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
1326 FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
1327
1328 return ESUCCESS;
1329}
#define min(a, b)
Definition: monoChain.cc:55
#define ANSI_NULL
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049

◆ ExtGetInodeBlockNumber()

ULONG ExtGetInodeBlockNumber ( PEXT_VOLUME_INFO  Volume,
ULONG  Inode 
)

Definition at line 930 of file ext.c.

931{
932 return (((Inode - 1) % Volume->SuperBlock->InodesPerGroup) / Volume->InodesPerBlock);
933}

Referenced by ExtReadInode().

◆ ExtGetInodeFileSize()

ULONGLONG ExtGetInodeFileSize ( PEXT_INODE  Inode)

Definition at line 1126 of file ext.c.

1127{
1128 if (_S_ISDIR(Inode->Mode))
1129 return (ULONGLONG)(Inode->Size);
1130 else
1131 return ((ULONGLONG)(Inode->Size) | ((ULONGLONG)(Inode->DirACL) << 32));
1132}
#define _S_ISDIR(m)
Definition: stat.h:46
ULONG DirACL
Definition: ext.h:181
USHORT Mode
Definition: ext.h:155
ULONG Size
Definition: ext.h:157
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by ExtLookupFile(), ExtReadBlockPointerList(), and ExtReadDirectory().

◆ ExtGetInodeGroupNumber()

ULONG ExtGetInodeGroupNumber ( PEXT_VOLUME_INFO  Volume,
ULONG  Inode 
)

Definition at line 925 of file ext.c.

926{
927 return ((Inode - 1) / Volume->SuperBlock->InodesPerGroup);
928}

Referenced by ExtReadInode().

◆ ExtGetInodeOffsetInBlock()

ULONG ExtGetInodeOffsetInBlock ( PEXT_VOLUME_INFO  Volume,
ULONG  Inode 
)

Definition at line 935 of file ext.c.

936{
937 return (((Inode - 1) % Volume->SuperBlock->InodesPerGroup) % Volume->InodesPerBlock);
938}

Referenced by ExtReadInode().

◆ ExtGetVolumeSize()

ULONGLONG ExtGetVolumeSize ( _In_ ULONG  DeviceId)

Returns the size of the EXT2/3/4 volume laid on the storage media device opened via DeviceId.

Definition at line 1404 of file ext.c.

1406{
1408 ULARGE_INTEGER BlocksCount;
1409
1410 Volume = ExtVolumes[DeviceId];
1411 ASSERT(Volume);
1412
1413 BlocksCount.LowPart = Volume->SuperBlock->BlocksCountLo;
1414 BlocksCount.HighPart = Volume->SuperBlock->BlocksCountHi;
1415
1416 /* NOTE: Volume->BlockSizeInBytes == Volume->BlockSizeInSectors * Volume->BytesPerSector */
1417 return BlocksCount.QuadPart * Volume->BlockSizeInBytes;
1418}
PEXT_VOLUME_INFO ExtVolumes[MAX_FDS]
Definition: ext.c:70
#define ASSERT(a)
Definition: mode.c:44
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:582

Referenced by FsGetVolumeSize().

◆ ExtLookupFile()

BOOLEAN ExtLookupFile ( PEXT_VOLUME_INFO  Volume,
PCSTR  FileName,
PEXT_FILE_INFO  ExtFileInfo 
)

Definition at line 210 of file ext.c.

211{
212 ULONG NumberOfPathParts;
213 ULONG i;
214 CHAR PathPart[261];
215 PVOID DirectoryBuffer;
216 ULONG DirectoryInode = EXT_ROOT_INODE;
217 EXT_INODE InodeData;
218 EXT_DIR_ENTRY DirectoryEntry;
219
220 TRACE("ExtLookupFile() FileName = \"%s\"\n", FileName);
221
222 RtlZeroMemory(ExtFileInfo, sizeof(EXT_FILE_INFO));
223
224 /* Skip leading path separator, if any */
225 if (*FileName == '\\' || *FileName == '/')
226 ++FileName;
227 //
228 // Figure out how many sub-directories we are nested in
229 //
230 NumberOfPathParts = FsGetNumPathParts(FileName);
231
232 //
233 // Loop once for each part
234 //
235 for (i=0; i<NumberOfPathParts; i++)
236 {
237 //
238 // Get first path part
239 //
241
242 //
243 // Advance to the next part of the path
244 //
245 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
246 {
247 }
248 FileName++;
249
250 //
251 // Buffer the directory contents
252 //
253 if (!ExtReadDirectory(Volume, DirectoryInode, &DirectoryBuffer, &InodeData))
254 {
255 return FALSE;
256 }
257
258 //
259 // Search for file name in directory
260 //
261 if (!ExtSearchDirectoryBufferForFile(DirectoryBuffer, (ULONG)ExtGetInodeFileSize(&InodeData), PathPart, &DirectoryEntry))
262 {
263 FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
264 return FALSE;
265 }
266
267 FrLdrTempFree(DirectoryBuffer, TAG_EXT_BUFFER);
268
269 DirectoryInode = DirectoryEntry.Inode;
270 }
271
272 if (!ExtReadInode(Volume, DirectoryInode, &InodeData))
273 {
274 return FALSE;
275 }
276
277 if (!_S_ISREG(InodeData.Mode) && !_S_ISLNK(InodeData.Mode))
278 {
279 FileSystemError("Inode is not a regular file or symbolic link.");
280 return FALSE;
281 }
282
283 // Set the associated volume
284 ExtFileInfo->Volume = Volume;
285
286 // If it's a regular file or a regular symbolic link
287 // then get the block pointer list otherwise it must
288 // be a fast symbolic link which doesn't have a block list
289 if (_S_ISREG(InodeData.Mode) ||
290 (_S_ISLNK(InodeData.Mode) && InodeData.Size > FAST_SYMLINK_MAX_NAME_SIZE))
291 {
292 ExtFileInfo->FileBlockList = ExtReadBlockPointerList(Volume, &InodeData);
293 if (ExtFileInfo->FileBlockList == NULL)
294 {
295 return FALSE;
296 }
297 }
298 else
299 {
300 ExtFileInfo->FileBlockList = NULL;
301 }
302
303 ExtFileInfo->FilePointer = 0;
304 ExtFileInfo->FileSize = ExtGetInodeFileSize(&InodeData);
305 RtlCopyMemory(&ExtFileInfo->Inode, &InodeData, sizeof(InodeData));
306
307 /* Map the attributes to ARC file attributes */
308 ExtFileInfo->Attributes = 0;
309 if (!(InodeData.Mode & (_S_IWUSR | _S_IWGRP | _S_IWOTH)))
310 ExtFileInfo->Attributes |= ReadOnlyFile;
311 if (_S_ISDIR(InodeData.Mode))
312 ExtFileInfo->Attributes |= DirectoryFile;
313
314 /* Set hidden attribute for all entries starting with '.' */
315 if ((DirectoryEntry.NameLen >= 2 && DirectoryEntry.Name[0] == '.') &&
316 ((DirectoryEntry.NameLen == 2 && DirectoryEntry.Name[1] != '.') ||
317 DirectoryEntry.NameLen >= 3))
318 {
319 ExtFileInfo->Attributes |= HiddenFile;
320 }
321
322 /* Copy the file name, perhaps truncated */
323 ExtFileInfo->FileNameLength = DirectoryEntry.NameLen; // (ULONG)strlen(PathPart);
324 ExtFileInfo->FileNameLength = min(ExtFileInfo->FileNameLength, sizeof(ExtFileInfo->FileName) - 1);
325 RtlCopyMemory(ExtFileInfo->FileName, DirectoryEntry.Name /*PathPart*/, ExtFileInfo->FileNameLength);
326
327 return TRUE;
328}
#define FAST_SYMLINK_MAX_NAME_SIZE
Definition: ext.h:229
#define EXT_ROOT_INODE
Definition: ext.h:198
#define _S_ISLNK(m)
Definition: stat.h:56
#define _S_IWOTH
Definition: stat.h:99
#define _S_IWUSR
Definition: stat.h:89
#define _S_ISREG(m)
Definition: stat.h:50
#define _S_IWGRP
Definition: stat.h:94
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:617
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:471
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:645
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
Definition: ext.c:1126
BOOLEAN ExtReadDirectory(PEXT_VOLUME_INFO Volume, ULONG Inode, PVOID *DirectoryBuffer, PEXT_INODE InodePointer)
Definition: ext.c:813
BOOLEAN ExtSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT_DIR_ENTRY DirectoryEntry)
Definition: ext.c:330
BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffer)
Definition: ext.c:940
ULONG * ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
Definition: ext.c:1041
@ DirectoryFile
Definition: fatprocs.h:1047
struct _FileName FileName
Definition: fatprocs.h:897
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
@ ReadOnlyFile
Definition: arc.h:78
@ HiddenFile
Definition: arc.h:79
EXT_INODE Inode
Definition: ext.h:237
PEXT_VOLUME_INFO Volume
Definition: ext.h:235
UCHAR Attributes
Definition: ext.h:241
PULONG FileBlockList
Definition: ext.h:236
CHAR FileName[RTL_FIELD_SIZE(FILEINFORMATION, FileName)]
Definition: ext.h:242
ULONG FileNameLength
Definition: ext.h:240
ULONGLONG FilePointer
Definition: ext.h:239
ULONGLONG FileSize
Definition: ext.h:238
ULONG Inode
Definition: ext.h:188
CHAR Name[EXT_DIR_ENTRY_MAX_NAME_LENGTH]
Definition: ext.h:192
UCHAR NameLen
Definition: ext.h:190
Definition: ext.h:154
char CHAR
Definition: xmlstorage.h:175

Referenced by ExtOpenFile().

◆ ExtMount()

const DEVVTBL * ExtMount ( ULONG  DeviceId)

Definition at line 1431 of file ext.c.

1432{
1434 EXT_SUPER_BLOCK SuperBlock;
1436 ULONG Count;
1438
1439 TRACE("Enter ExtMount(%lu)\n", DeviceId);
1440
1441 /* Allocate data for volume information */
1443 if (!Volume)
1444 return NULL;
1446
1447 /* Read the SuperBlock */
1448 Position.QuadPart = 2 * 512;
1449 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1450 if (Status != ESUCCESS)
1451 {
1453 return NULL;
1454 }
1455 Status = ArcRead(DeviceId, &SuperBlock, sizeof(SuperBlock), &Count);
1456 if (Status != ESUCCESS || Count != sizeof(SuperBlock))
1457 {
1459 return NULL;
1460 }
1461
1462 /* Check if SuperBlock is valid. If yes, return Ext function table. */
1463 if (SuperBlock.Magic != EXT_SUPERBLOCK_MAGIC)
1464 {
1466 return NULL;
1467 }
1468
1469 Volume->DeviceId = DeviceId;
1470
1471 /* Really open the volume */
1472 if (!ExtOpenVolume(Volume))
1473 {
1475 return NULL;
1476 }
1477
1478 /* Remember EXT volume information */
1479 ExtVolumes[DeviceId] = Volume;
1480
1481 /* Return success */
1482 TRACE("ExtMount(%lu) success\n", DeviceId);
1483 return &ExtFuncTable;
1484}
#define EXT_SUPERBLOCK_MAGIC
Definition: ext.h:45
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
#define TAG_EXT_VOLUME
Definition: ext.c:77
const DEVVTBL ExtFuncTable
Definition: ext.c:1421
BOOLEAN ExtOpenVolume(PEXT_VOLUME_INFO Volume)
Definition: ext.c:79
Status
Definition: gdiplustypes.h:25
int Count
Definition: noreturn.cpp:7
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
USHORT Magic
Definition: ext.h:70
static COORD Position
Definition: mouse.c:34

◆ ExtOpen()

ARC_STATUS ExtOpen ( CHAR Path,
OPENMODE  OpenMode,
ULONG FileId 
)

Definition at line 1331 of file ext.c.

1332{
1335 ULONG DeviceId;
1336
1337 /* Check parameters */
1338 if (OpenMode != OpenReadOnly)
1339 return EACCES;
1340
1341 /* Get underlying device */
1342 DeviceId = FsGetDeviceId(*FileId);
1343 Volume = ExtVolumes[DeviceId];
1344
1345 TRACE("ExtOpen() FileName = \"%s\"\n", Path);
1346
1347 /* Call the internal open method */
1348 // Status = ExtOpenFile(Volume, Path, &FileHandle);
1350 if (!FileHandle)
1351 return ENOENT;
1352
1353 /* Success, remember the handle */
1355 return ESUCCESS;
1356}
PRTL_UNICODE_STRING_BUFFER Path
#define ENOENT
Definition: acclib.h:79
#define EACCES
Definition: acclib.h:85
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:702
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:716
PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
Definition: ext.c:108
@ OpenReadOnly
Definition: arc.h:65

◆ ExtOpenFile()

PEXT_FILE_INFO ExtOpenFile ( PEXT_VOLUME_INFO  Volume,
PCSTR  FileName 
)

Definition at line 108 of file ext.c.

109{
110 EXT_FILE_INFO TempExtFileInfo;
115
116 TRACE("ExtOpenFile() FileName = \"%s\"\n", FileName);
117
118 RtlZeroMemory(SymLinkPath, sizeof(SymLinkPath));
119
120 // Lookup the file in the file system
121 if (!ExtLookupFile(Volume, FileName, &TempExtFileInfo))
122 {
123 return NULL;
124 }
125
126 // If we got a symbolic link then fix up the path
127 // and re-call this function
128 if (_S_ISLNK(TempExtFileInfo.Inode.Mode))
129 {
130 TRACE("File is a symbolic link\n");
131
132 // Now read in the symbolic link path
133 if (!ExtReadFileBig(&TempExtFileInfo, TempExtFileInfo.FileSize, NULL, SymLinkPath))
134 {
135 if (TempExtFileInfo.FileBlockList != NULL)
136 {
138 }
139
140 return NULL;
141 }
142
143 TRACE("Symbolic link path = \"%s\"\n", SymLinkPath);
144
145 // Get the full path
146 if (SymLinkPath[0] == '/' || SymLinkPath[0] == '\\')
147 {
148 // Symbolic link is an absolute path
149 // So copy it to FullPath, but skip over
150 // the '/' character at the beginning
151 strcpy(FullPath, &SymLinkPath[1]);
152 }
153 else
154 {
155 // Symbolic link is a relative path
156 // Copy the first part of the path
157 strcpy(FullPath, FileName);
158
159 // Remove the last part of the path
160 for (Index=strlen(FullPath); Index>0; )
161 {
162 Index--;
163 if (FullPath[Index] == '/' || FullPath[Index] == '\\')
164 {
165 break;
166 }
167 }
168 FullPath[Index] = '\0';
169
170 // Concatenate the symbolic link
171 strcat(FullPath, Index == 0 ? "" : "/");
172 strcat(FullPath, SymLinkPath);
173 }
174
175 TRACE("Full file path = \"%s\"\n", FullPath);
176
177 if (TempExtFileInfo.FileBlockList != NULL)
178 {
180 }
181
182 return ExtOpenFile(Volume, FullPath);
183 }
184 else
185 {
187 if (FileHandle == NULL)
188 {
189 if (TempExtFileInfo.FileBlockList != NULL)
190 {
192 }
193
194 return NULL;
195 }
196
197 RtlCopyMemory(FileHandle, &TempExtFileInfo, sizeof(EXT_FILE_INFO));
198
199 return FileHandle;
200 }
201}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define EXT_DIR_ENTRY_MAX_NAME_LENGTH
Definition: ext.h:50
#define TAG_EXT_BLOCK_LIST
Definition: ext.c:72
BOOLEAN ExtReadFileBig(PEXT_FILE_INFO ExtFileInfo, ULONGLONG BytesToRead, ULONGLONG *BytesRead, PVOID Buffer)
Definition: ext.c:387
BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO ExtFileInfo)
Definition: ext.c:210
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_In_ WDFCOLLECTION _In_ ULONG Index

Referenced by ExtOpen(), and ExtOpenFile().

◆ ExtOpenVolume()

BOOLEAN ExtOpenVolume ( PEXT_VOLUME_INFO  Volume)

Definition at line 79 of file ext.c.

80{
81 TRACE("ExtOpenVolume() DeviceId = %d\n", Volume->DeviceId);
82
83#if 0
84 /* Initialize the disk cache for this drive */
85 if (!CacheInitializeDrive(DriveNumber))
86 {
87 return FALSE;
88 }
89#endif
90 Volume->BytesPerSector = SECTOR_SIZE;
91
92 /* Read in the super block */
94 return FALSE;
95
96 /* Read in the group descriptors */
98 return FALSE;
99
100 return TRUE;
101}
BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
Definition: cache.c:37
#define SECTOR_SIZE
Definition: fs.h:22
BOOLEAN ExtReadSuperBlock(PEXT_VOLUME_INFO Volume)
Definition: ext.c:600
BOOLEAN ExtReadGroupDescriptors(PEXT_VOLUME_INFO Volume)
Definition: ext.c:771

Referenced by ExtMount().

◆ ExtRead()

ARC_STATUS ExtRead ( ULONG  FileId,
VOID Buffer,
ULONG  N,
ULONG Count 
)

Definition at line 1358 of file ext.c.

1359{
1361 ULONGLONG BytesReadBig;
1363
1364 /* Read data */
1365 Success = ExtReadFileBig(FileHandle, N, &BytesReadBig, Buffer);
1366 *Count = (ULONG)BytesReadBig;
1367 if (Success)
1368 return ESUCCESS;
1369 else
1370 return EIO;
1371}
#define N
Definition: crc32.c:57
#define EIO
Definition: acclib.h:81
Definition: bufpool.h:45
@ Success
Definition: eventcreate.c:712

◆ ExtReadBlock()

BOOLEAN ExtReadBlock ( PEXT_VOLUME_INFO  Volume,
ULONG  BlockNumber,
PVOID  Buffer 
)

Definition at line 873 of file ext.c.

874{
875 CHAR ErrorString[80];
876
877 TRACE("ExtReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer);
878
879 // Make sure its a valid block
880 if (BlockNumber > Volume->SuperBlock->BlocksCountLo)
881 {
882 sprintf(ErrorString, "Error reading block %d - block out of range.", (int) BlockNumber);
883 FileSystemError(ErrorString);
884 return FALSE;
885 }
886
887 // Check to see if this is a sparse block
888 if (BlockNumber == 0)
889 {
890 TRACE("Block is part of a sparse file. Zeroing input buffer.\n");
891
892 RtlZeroMemory(Buffer, Volume->BlockSizeInBytes);
893
894 return TRUE;
895 }
896
897 return ExtReadVolumeSectors(Volume, (ULONGLONG)BlockNumber * Volume->BlockSizeInSectors, Volume->BlockSizeInSectors, Buffer);
898}
BOOLEAN ExtReadVolumeSectors(PEXT_VOLUME_INFO Volume, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: ext.c:569
#define sprintf
Definition: sprintf.c:45

Referenced by ExtCopyBlockPointersByExtents(), ExtCopyDoubleIndirectBlockPointers(), ExtCopyIndirectBlockPointers(), ExtCopyTripleIndirectBlockPointers(), ExtReadFileBig(), ExtReadGroupDescriptor(), ExtReadGroupDescriptors(), and ExtReadPartialBlock().

◆ ExtReadBlockPointerList()

ULONG * ExtReadBlockPointerList ( PEXT_VOLUME_INFO  Volume,
PEXT_INODE  Inode 
)

Definition at line 1041 of file ext.c.

1042{
1044 ULONG BlockCount;
1045 ULONG* BlockList;
1046 ULONG CurrentBlockInList;
1047 ULONG CurrentBlock;
1048
1049 TRACE("ExtReadBlockPointerList()\n");
1050
1051 // Get the number of blocks this file occupies
1052 // I would just use Inode->i_blocks but it
1053 // doesn't seem to be the number of blocks
1054 // the file size corresponds to, but instead
1055 // it is much bigger.
1056 //BlockCount = Inode->i_blocks;
1058 FileSize = ROUND_UP(FileSize, Volume->BlockSizeInBytes);
1059 BlockCount = (ULONG)(FileSize / Volume->BlockSizeInBytes);
1060
1061 // Allocate the memory for the block list
1062 BlockList = FrLdrTempAlloc(BlockCount * sizeof(ULONG), TAG_EXT_BLOCK_LIST);
1063 if (BlockList == NULL)
1064 {
1065 return NULL;
1066 }
1067
1068 RtlZeroMemory(BlockList, BlockCount * sizeof(ULONG));
1069
1070 // If the file is stored in extents, copy the block pointers by reading the
1071 // extent entries.
1072 if (Inode->Flags & EXT4_INODE_FLAG_EXTENTS)
1073 {
1074 CurrentBlockInList = 0;
1075
1076 if (!ExtCopyBlockPointersByExtents(Volume, BlockList, &CurrentBlockInList, BlockCount, &Inode->ExtentHeader))
1077 {
1079 return NULL;
1080 }
1081
1082 return BlockList;
1083 }
1084
1085 // Copy the direct block pointers
1086 for (CurrentBlockInList = CurrentBlock = 0;
1087 CurrentBlockInList < BlockCount && CurrentBlock < sizeof(Inode->Blocks.DirectBlocks) / sizeof(*Inode->Blocks.DirectBlocks);
1088 CurrentBlock++, CurrentBlockInList++)
1089 {
1090 BlockList[CurrentBlockInList] = Inode->Blocks.DirectBlocks[CurrentBlock];
1091 }
1092
1093 // Copy the indirect block pointers
1094 if (CurrentBlockInList < BlockCount)
1095 {
1096 if (!ExtCopyIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.IndirectBlock))
1097 {
1099 return NULL;
1100 }
1101 }
1102
1103 // Copy the double indirect block pointers
1104 if (CurrentBlockInList < BlockCount)
1105 {
1106 if (!ExtCopyDoubleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.DoubleIndirectBlock))
1107 {
1109 return NULL;
1110 }
1111 }
1112
1113 // Copy the triple indirect block pointers
1114 if (CurrentBlockInList < BlockCount)
1115 {
1116 if (!ExtCopyTripleIndirectBlockPointers(Volume, BlockList, &CurrentBlockInList, BlockCount, Inode->Blocks.TripleIndirectBlock))
1117 {
1119 return NULL;
1120 }
1121 }
1122
1123 return BlockList;
1124}
#define EXT4_INODE_FLAG_EXTENTS
Definition: ext.h:212
BOOLEAN ExtCopyTripleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
Definition: ext.c:1267
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
Definition: fsrtlfuncs.h:108
struct _ExtInode::@203::@205 Blocks
EXT4_EXTENT_HEADER ExtentHeader
Definition: ext.h:177
ULONG Flags
Definition: ext.h:165

Referenced by ExtLookupFile(), and ExtReadDirectory().

◆ ExtReadDirectory()

BOOLEAN ExtReadDirectory ( PEXT_VOLUME_INFO  Volume,
ULONG  Inode,
PVOID DirectoryBuffer,
PEXT_INODE  InodePointer 
)

Definition at line 813 of file ext.c.

814{
815 EXT_FILE_INFO DirectoryFileInfo;
816
817 TRACE("ExtReadDirectory() Inode = %d\n", Inode);
818
819 // Read the directory inode
820 if (!ExtReadInode(Volume, Inode, InodePointer))
821 {
822 return FALSE;
823 }
824
825 // Make sure it is a directory inode
826 if (!_S_ISDIR(InodePointer->Mode))
827 {
828 FileSystemError("Inode is not a directory.");
829 return FALSE;
830 }
831
832 // Fill in file info struct so we can call ExtReadFileBig()
833 RtlZeroMemory(&DirectoryFileInfo, sizeof(EXT_FILE_INFO));
834 DirectoryFileInfo.Volume = Volume;
835 DirectoryFileInfo.FileBlockList = ExtReadBlockPointerList(Volume, InodePointer);
836 DirectoryFileInfo.FilePointer = 0;
837 DirectoryFileInfo.FileSize = ExtGetInodeFileSize(InodePointer);
838
839 if (DirectoryFileInfo.FileBlockList == NULL)
840 {
841 return FALSE;
842 }
843
844 //
845 // Now allocate the memory to hold the group descriptors
846 //
847 ASSERT(DirectoryFileInfo.FileSize <= 0xFFFFFFFF);
848 *DirectoryBuffer = (PEXT_DIR_ENTRY)FrLdrTempAlloc((ULONG)DirectoryFileInfo.FileSize, TAG_EXT_BUFFER);
849
850 //
851 // Make sure we got the memory
852 //
853 if (*DirectoryBuffer == NULL)
854 {
856 FileSystemError("Out of memory.");
857 return FALSE;
858 }
859
860 // Now read the root directory data
861 if (!ExtReadFileBig(&DirectoryFileInfo, DirectoryFileInfo.FileSize, NULL, *DirectoryBuffer))
862 {
863 FrLdrTempFree(*DirectoryBuffer, TAG_EXT_BUFFER);
864 *DirectoryBuffer = NULL;
866 return FALSE;
867 }
868
870 return TRUE;
871}
struct _ExtDirEntry * PEXT_DIR_ENTRY

Referenced by ExtLookupFile().

◆ ExtReadFileBig()

BOOLEAN ExtReadFileBig ( PEXT_FILE_INFO  ExtFileInfo,
ULONGLONG  BytesToRead,
ULONGLONG BytesRead,
PVOID  Buffer 
)

Definition at line 387 of file ext.c.

388{
389 PEXT_VOLUME_INFO Volume = ExtFileInfo->Volume;
390 ULONG BlockNumber;
391 ULONG BlockNumberIndex;
392 ULONG OffsetInBlock;
393 ULONG LengthInBlock;
394 ULONG NumberOfBlocks;
395
396 TRACE("ExtReadFileBig() BytesToRead = %d Buffer = 0x%x\n", (ULONG)BytesToRead, Buffer);
397
398 if (BytesRead != NULL)
399 {
400 *BytesRead = 0;
401 }
402
403 // Make sure we have the block pointer list if we need it
404 if (ExtFileInfo->FileBlockList == NULL)
405 {
406 // Block pointer list is NULL
407 // so this better be a fast symbolic link or else
408 if (!_S_ISLNK(ExtFileInfo->Inode.Mode) ||
409 (ExtFileInfo->FileSize > FAST_SYMLINK_MAX_NAME_SIZE))
410 {
411 FileSystemError("Block pointer list is NULL and file is not a fast symbolic link.");
412 return FALSE;
413 }
414 }
415
416 //
417 // If the user is trying to read past the end of
418 // the file then return success with BytesRead == 0.
419 //
420 if (ExtFileInfo->FilePointer >= ExtFileInfo->FileSize)
421 {
422 return TRUE;
423 }
424
425 //
426 // If the user is trying to read more than there is to read
427 // then adjust the amount to read.
428 //
429 if ((ExtFileInfo->FilePointer + BytesToRead) > ExtFileInfo->FileSize)
430 {
431 BytesToRead = (ExtFileInfo->FileSize - ExtFileInfo->FilePointer);
432 }
433
434 // Check if this is a fast symbolic link
435 // if so then the read is easy
436 if (_S_ISLNK(ExtFileInfo->Inode.Mode) &&
437 (ExtFileInfo->FileSize <= FAST_SYMLINK_MAX_NAME_SIZE))
438 {
439 TRACE("Reading fast symbolic link data\n");
440
441 // Copy the data from the link
442 RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)ExtFileInfo->FilePointer + ExtFileInfo->Inode.SymLink), (ULONG)BytesToRead);
443
444 if (BytesRead != NULL)
445 {
446 *BytesRead = BytesToRead;
447 }
448 // ExtFileInfo->FilePointer += BytesToRead;
449
450 return TRUE;
451 }
452
453 //
454 // Ok, now we have to perform at most 3 calculations
455 // I'll draw you a picture (using nifty ASCII art):
456 //
457 // CurrentFilePointer -+
458 // |
459 // +----------------+
460 // |
461 // +-----------+-----------+-----------+-----------+
462 // | Block 1 | Block 2 | Block 3 | Block 4 |
463 // +-----------+-----------+-----------+-----------+
464 // | |
465 // +---------------+--------------------+
466 // |
467 // BytesToRead -------+
468 //
469 // 1 - The first calculation (and read) will align
470 // the file pointer with the next block.
471 // boundary (if we are supposed to read that much)
472 // 2 - The next calculation (and read) will read
473 // in all the full blocks that the requested
474 // amount of data would cover (in this case
475 // blocks 2 & 3).
476 // 3 - The last calculation (and read) would read
477 // in the remainder of the data requested out of
478 // the last block.
479 //
480
481 //
482 // Only do the first read if we
483 // aren't aligned on a block boundary
484 //
485 if (ExtFileInfo->FilePointer % Volume->BlockSizeInBytes)
486 {
487 //
488 // Do the math for our first read
489 //
490 BlockNumberIndex = (ULONG)(ExtFileInfo->FilePointer / Volume->BlockSizeInBytes);
491 BlockNumber = ExtFileInfo->FileBlockList[BlockNumberIndex];
492 OffsetInBlock = (ExtFileInfo->FilePointer % Volume->BlockSizeInBytes);
493 LengthInBlock = (ULONG)((BytesToRead > (Volume->BlockSizeInBytes - OffsetInBlock)) ? (Volume->BlockSizeInBytes - OffsetInBlock) : BytesToRead);
494
495 //
496 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
497 //
498 if (!ExtReadPartialBlock(Volume, BlockNumber, OffsetInBlock, LengthInBlock, Buffer))
499 {
500 return FALSE;
501 }
502 if (BytesRead != NULL)
503 {
504 *BytesRead += LengthInBlock;
505 }
506 BytesToRead -= LengthInBlock;
507 ExtFileInfo->FilePointer += LengthInBlock;
508 Buffer = (PVOID)((ULONG_PTR)Buffer + LengthInBlock);
509 }
510
511 //
512 // Do the math for our second read (if any data left)
513 //
514 if (BytesToRead > 0)
515 {
516 //
517 // Determine how many full clusters we need to read
518 //
519 NumberOfBlocks = (ULONG)(BytesToRead / Volume->BlockSizeInBytes);
520
521 while (NumberOfBlocks > 0)
522 {
523 BlockNumberIndex = (ULONG)(ExtFileInfo->FilePointer / Volume->BlockSizeInBytes);
524 BlockNumber = ExtFileInfo->FileBlockList[BlockNumberIndex];
525
526 //
527 // Now do the read and update BytesRead, BytesToRead, FilePointer, & Buffer
528 //
529 if (!ExtReadBlock(Volume, BlockNumber, Buffer))
530 {
531 return FALSE;
532 }
533 if (BytesRead != NULL)
534 {
535 *BytesRead += Volume->BlockSizeInBytes;
536 }
537 BytesToRead -= Volume->BlockSizeInBytes;
538 ExtFileInfo->FilePointer += Volume->BlockSizeInBytes;
539 Buffer = (PVOID)((ULONG_PTR)Buffer + Volume->BlockSizeInBytes);
540 NumberOfBlocks--;
541 }
542 }
543
544 //
545 // Do the math for our third read (if any data left)
546 //
547 if (BytesToRead > 0)
548 {
549 BlockNumberIndex = (ULONG)(ExtFileInfo->FilePointer / Volume->BlockSizeInBytes);
550 BlockNumber = ExtFileInfo->FileBlockList[BlockNumberIndex];
551
552 //
553 // Now do the read and update BytesRead & FilePointer
554 //
555 if (!ExtReadPartialBlock(Volume, BlockNumber, 0, (ULONG)BytesToRead, Buffer))
556 {
557 return FALSE;
558 }
559 if (BytesRead != NULL)
560 {
561 *BytesRead += BytesToRead;
562 }
563 ExtFileInfo->FilePointer += BytesToRead;
564 }
565
566 return TRUE;
567}
BOOLEAN ExtReadPartialBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
Definition: ext.c:904
CHAR SymLink[60]
Definition: ext.h:169
uint32_t ULONG_PTR
Definition: typedefs.h:65
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870

Referenced by ExtOpenFile(), ExtRead(), and ExtReadDirectory().

◆ ExtReadGroupDescriptor()

BOOLEAN ExtReadGroupDescriptor ( PEXT_VOLUME_INFO  Volume,
ULONG  Group,
PEXT_GROUP_DESC  GroupBuffer 
)

Definition at line 1016 of file ext.c.

1017{
1018 TRACE("ExtReadGroupDescriptor()\n");
1019
1020#if 0
1021 if (!ExtReadBlock(Volume, ExtGetGroupDescBlockNumber(Volume, Group), (PVOID)FILESYSBUFFER))
1022 {
1023 return FALSE;
1024 }
1025 RtlCopyMemory(GroupBuffer, (PVOID)(FILESYSBUFFER + ExtGetGroupDescOffsetInBlock(Volume, Group)), sizeof(EXT_GROUP_DESC));
1026#endif
1027
1028 RtlCopyMemory(GroupBuffer, &((PUCHAR)Volume->GroupDescriptors)[Volume->GroupDescSizeInBytes * Group], sizeof(EXT_GROUP_DESC));
1029
1030 TRACE("Dumping group descriptor:\n");
1031 TRACE("BlockBitmap = %d\n", GroupBuffer->BlockBitmap);
1032 TRACE("InodeBitmap = %d\n", GroupBuffer->InodeBitmap);
1033 TRACE("InodeTable = %d\n", GroupBuffer->InodeTable);
1034 TRACE("FreeBlocksCount = %d\n", GroupBuffer->FreeBlocksCount);
1035 TRACE("FreeInodesCount = %d\n", GroupBuffer->FreeInodesCount);
1036 TRACE("UsedDirsCount = %d\n", GroupBuffer->UsedDirsCount);
1037
1038 return TRUE;
1039}
@ Group
Definition: help.c:22
USHORT FreeBlocksCount
Definition: ext.h:123
ULONG InodeBitmap
Definition: ext.h:121
ULONG InodeTable
Definition: ext.h:122
ULONG BlockBitmap
Definition: ext.h:120
USHORT FreeInodesCount
Definition: ext.h:124
USHORT UsedDirsCount
Definition: ext.h:125
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by ExtReadInode().

◆ ExtReadGroupDescriptors()

BOOLEAN ExtReadGroupDescriptors ( PEXT_VOLUME_INFO  Volume)

Definition at line 771 of file ext.c.

772{
773 ULONG GroupDescBlockCount;
774 ULONG BlockNumber;
775 PUCHAR CurrentGroupDescBlock;
776
777 TRACE("ExtReadGroupDescriptors()\n");
778
779 /* Free any memory previously allocated */
780 if (Volume->GroupDescriptors != NULL)
781 {
782 FrLdrTempFree(Volume->GroupDescriptors, TAG_EXT_GROUP_DESC);
783 Volume->GroupDescriptors = NULL;
784 }
785
786 /* Now allocate the memory to hold the group descriptors */
787 GroupDescBlockCount = ROUND_UP(Volume->GroupCount, Volume->GroupDescPerBlock) / Volume->GroupDescPerBlock;
788 Volume->GroupDescriptors = (PEXT_GROUP_DESC)FrLdrTempAlloc(GroupDescBlockCount * Volume->BlockSizeInBytes, TAG_EXT_GROUP_DESC);
789 if (Volume->GroupDescriptors == NULL)
790 {
791 FileSystemError("Out of memory.");
792 return FALSE;
793 }
794
795 // Now read the group descriptors
796 CurrentGroupDescBlock = (PUCHAR)Volume->GroupDescriptors;
797 BlockNumber = Volume->SuperBlock->FirstDataBlock + 1;
798
799 while (GroupDescBlockCount--)
800 {
801 if (!ExtReadBlock(Volume, BlockNumber, CurrentGroupDescBlock))
802 {
803 return FALSE;
804 }
805
806 BlockNumber++;
807 CurrentGroupDescBlock += Volume->BlockSizeInBytes;
808 }
809
810 return TRUE;
811}
struct _ExtGroupDescriptor * PEXT_GROUP_DESC
#define TAG_EXT_GROUP_DESC
Definition: ext.c:76

Referenced by ExtOpenVolume().

◆ ExtReadInode()

BOOLEAN ExtReadInode ( PEXT_VOLUME_INFO  Volume,
ULONG  Inode,
PEXT_INODE  InodeBuffer 
)

Definition at line 940 of file ext.c.

941{
942 ULONG InodeGroupNumber;
943 ULONG InodeBlockNumber;
944 ULONG InodeOffsetInBlock;
945 CHAR ErrorString[80];
946 EXT_GROUP_DESC GroupDescriptor;
947
948 TRACE("ExtReadInode() Inode = %d\n", Inode);
949
950 // Make sure its a valid inode
951 if ((Inode < 1) || (Inode > Volume->SuperBlock->InodesCount))
952 {
953 sprintf(ErrorString, "Error reading inode %ld - inode out of range.", Inode);
954 FileSystemError(ErrorString);
955 return FALSE;
956 }
957
958 // Get inode group & block number and offset in block
959 InodeGroupNumber = ExtGetInodeGroupNumber(Volume, Inode);
960 InodeBlockNumber = ExtGetInodeBlockNumber(Volume, Inode);
961 InodeOffsetInBlock = ExtGetInodeOffsetInBlock(Volume, Inode);
962 TRACE("InodeGroupNumber = %d\n", InodeGroupNumber);
963 TRACE("InodeBlockNumber = %d\n", InodeBlockNumber);
964 TRACE("InodeOffsetInBlock = %d\n", InodeOffsetInBlock);
965
966 // Read the group descriptor
967 if (!ExtReadGroupDescriptor(Volume, InodeGroupNumber, &GroupDescriptor))
968 {
969 return FALSE;
970 }
971
972 // Add the start block of the inode table to the inode block number
973 InodeBlockNumber += GroupDescriptor.InodeTable;
974 TRACE("InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber);
975
976 // Read the block
978 InodeBlockNumber,
979 (InodeOffsetInBlock * Volume->InodeSizeInBytes),
980 sizeof(EXT_INODE),
981 InodeBuffer))
982 {
983 return FALSE;
984 }
985
986 TRACE("Dumping inode information:\n");
987 TRACE("Mode = 0x%x\n", InodeBuffer->Mode);
988 TRACE("UID = %d\n", InodeBuffer->UID);
989 TRACE("Size = %d\n", InodeBuffer->Size);
990 TRACE("Atime = %d\n", InodeBuffer->Atime);
991 TRACE("Ctime = %d\n", InodeBuffer->Ctime);
992 TRACE("Mtime = %d\n", InodeBuffer->Mtime);
993 TRACE("Dtime = %d\n", InodeBuffer->Dtime);
994 TRACE("GID = %d\n", InodeBuffer->GID);
995 TRACE("LinksCount = %d\n", InodeBuffer->LinksCount);
996 TRACE("Blocks = %d\n", InodeBuffer->Blocks);
997 TRACE("Flags = 0x%x\n", InodeBuffer->Flags);
998 TRACE("OSD1 = 0x%x\n", InodeBuffer->OSD1);
999 TRACE("DirectBlocks = { %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u }\n",
1000 InodeBuffer->Blocks.DirectBlocks[0], InodeBuffer->Blocks.DirectBlocks[1], InodeBuffer->Blocks.DirectBlocks[2], InodeBuffer->Blocks.DirectBlocks[3],
1001 InodeBuffer->Blocks.DirectBlocks[4], InodeBuffer->Blocks.DirectBlocks[5], InodeBuffer->Blocks.DirectBlocks[6], InodeBuffer->Blocks.DirectBlocks[7],
1002 InodeBuffer->Blocks.DirectBlocks[8], InodeBuffer->Blocks.DirectBlocks[9], InodeBuffer->Blocks.DirectBlocks[10], InodeBuffer->Blocks.DirectBlocks[11]);
1003 TRACE("IndirectBlock = %u\n", InodeBuffer->Blocks.IndirectBlock);
1004 TRACE("DoubleIndirectBlock = %u\n", InodeBuffer->Blocks.DoubleIndirectBlock);
1005 TRACE("TripleIndirectBlock = %u\n", InodeBuffer->Blocks.TripleIndirectBlock);
1006 TRACE("Generation = %d\n", InodeBuffer->Generation);
1007 TRACE("FileACL = %d\n", InodeBuffer->FileACL);
1008 TRACE("DirACL = %d\n", InodeBuffer->DirACL);
1009 TRACE("FragAddress = %d\n", InodeBuffer->FragAddress);
1010 TRACE("OSD2 = { %d, %d, %d }\n",
1011 InodeBuffer->OSD2[0], InodeBuffer->OSD2[1], InodeBuffer->OSD2[2]);
1012
1013 return TRUE;
1014}
ULONG ExtGetInodeGroupNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
Definition: ext.c:925
BOOLEAN ExtReadGroupDescriptor(PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_DESC GroupBuffer)
Definition: ext.c:1016
ULONG ExtGetInodeBlockNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
Definition: ext.c:930
ULONG ExtGetInodeOffsetInBlock(PEXT_VOLUME_INFO Volume, ULONG Inode)
Definition: ext.c:935
ULONG Dtime
Definition: ext.h:161
USHORT LinksCount
Definition: ext.h:163
ULONG FragAddress
Definition: ext.h:182
USHORT GID
Definition: ext.h:162
ULONG Generation
Definition: ext.h:179
ULONG Ctime
Definition: ext.h:159
USHORT UID
Definition: ext.h:156
ULONG OSD1
Definition: ext.h:166
ULONG FileACL
Definition: ext.h:180
ULONG Mtime
Definition: ext.h:160
ULONG OSD2[3]
Definition: ext.h:183
ULONG Atime
Definition: ext.h:158

Referenced by ExtLookupFile(), and ExtReadDirectory().

◆ ExtReadPartialBlock()

BOOLEAN ExtReadPartialBlock ( PEXT_VOLUME_INFO  Volume,
ULONG  BlockNumber,
ULONG  StartingOffset,
ULONG  Length,
PVOID  Buffer 
)

Definition at line 904 of file ext.c.

905{
906 PVOID TempBuffer;
907
908 TRACE("ExtReadPartialBlock() BlockNumber = %d StartingOffset = %d Length = %d Buffer = 0x%x\n", BlockNumber, StartingOffset, Length, Buffer);
909
910 TempBuffer = FrLdrTempAlloc(Volume->BlockSizeInBytes, TAG_EXT_BUFFER);
911
912 if (!ExtReadBlock(Volume, BlockNumber, TempBuffer))
913 {
914 FrLdrTempFree(TempBuffer, TAG_EXT_BUFFER);
915 return FALSE;
916 }
917
919
920 FrLdrTempFree(TempBuffer, TAG_EXT_BUFFER);
921
922 return TRUE;
923}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291

Referenced by ExtReadFileBig(), and ExtReadInode().

◆ ExtReadSuperBlock()

BOOLEAN ExtReadSuperBlock ( PEXT_VOLUME_INFO  Volume)

Definition at line 600 of file ext.c.

601{
602 PEXT_SUPER_BLOCK SuperBlock = Volume->SuperBlock;
604 ULONG Count;
606
607 TRACE("ExtReadSuperBlock()\n");
608
609#if 0
610 /* Free any memory previously allocated */
611 if (SuperBlock != NULL)
612 {
614 SuperBlock = NULL;
615 }
616#endif
617
618 /* Allocate the memory to hold the super block if needed */
619 if (SuperBlock == NULL)
620 {
622 if (SuperBlock == NULL)
623 {
624 FileSystemError("Out of memory.");
625 return FALSE;
626 }
627 }
628 Volume->SuperBlock = SuperBlock;
629
630 /* Reset its contents */
631 RtlZeroMemory(SuperBlock, 1024);
632
633 /* Read the SuperBlock */
634 Position.QuadPart = 2 * 512;
635 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
636 if (Status != ESUCCESS)
637 return FALSE;
638 Status = ArcRead(Volume->DeviceId, SuperBlock, 2 * 512, &Count);
639 if (Status != ESUCCESS || Count != 2 * 512)
640 return FALSE;
641
642 TRACE("Dumping super block:\n");
643 TRACE("InodesCount: %d\n", SuperBlock->InodesCount);
644 TRACE("BlocksCountLo: %d\n", SuperBlock->BlocksCountLo);
645 TRACE("RBlocksCountLo: %d\n", SuperBlock->RBlocksCountLo);
646 TRACE("FreeBlocksCountLo: %d\n", SuperBlock->FreeBlocksCountLo);
647 TRACE("FreeInodesCount: %d\n", SuperBlock->FreeInodesCount);
648 TRACE("FirstDataBlock: %d\n", SuperBlock->FirstDataBlock);
649 TRACE("LogBlockSize: %d\n", SuperBlock->LogBlockSize);
650 TRACE("LogFragSize: %d\n", SuperBlock->LogFragSize);
651 TRACE("BlocksPerGroup: %d\n", SuperBlock->BlocksPerGroup);
652 TRACE("FragsPerGroup: %d\n", SuperBlock->FragsPerGroup);
653 TRACE("InodesPerGroup: %d\n", SuperBlock->InodesPerGroup);
654 TRACE("MTime: %d\n", SuperBlock->MTime);
655 TRACE("WTime: %d\n", SuperBlock->WTime);
656 TRACE("MntCount: %d\n", SuperBlock->MntCount);
657 TRACE("MaxMntCount: %d\n", SuperBlock->MaxMntCount);
658 TRACE("Magic: 0x%x\n", SuperBlock->Magic);
659 TRACE("State: 0x%x\n", SuperBlock->State);
660 TRACE("Errors: 0x%x\n", SuperBlock->Errors);
661 TRACE("MinorRevisionLevel: %d\n", SuperBlock->MinorRevisionLevel);
662 TRACE("LastCheck: %d\n", SuperBlock->LastCheck);
663 TRACE("CheckInterval: %d\n", SuperBlock->CheckInterval);
664 TRACE("CreatorOS: %d\n", SuperBlock->CreatorOS);
665 TRACE("RevisionLevel: %d\n", SuperBlock->RevisionLevel);
666 TRACE("DefResUID: %d\n", SuperBlock->DefResUID);
667 TRACE("DefResGID: %d\n", SuperBlock->DefResGID);
668 TRACE("FirstInode: %d\n", SuperBlock->FirstInode);
669 TRACE("InodeSize: %d\n", SuperBlock->InodeSize);
670 TRACE("BlockGroupNr: %d\n", SuperBlock->BlockGroupNr);
671 TRACE("FeatureCompat: 0x%x\n", SuperBlock->FeatureCompat);
672 TRACE("FeatureIncompat: 0x%x\n", SuperBlock->FeatureIncompat);
673 TRACE("FeatureROCompat: 0x%x\n", SuperBlock->FeatureROCompat);
674 TRACE("UUID: { ");
675 for (ULONG i = 0; i < sizeof(SuperBlock->UUID); i++)
676 {
677 TRACE("0x%02x", SuperBlock->UUID[i]);
678 if (i < sizeof(SuperBlock->UUID) - 1)
679 TRACE(", ");
680 }
681 TRACE(" }\n");
682 TRACE("VolumeName: \"%s\"\n", SuperBlock->VolumeName);
683 TRACE("LastMounted: \"%s\"\n", SuperBlock->LastMounted);
684 TRACE("AlgorithmUsageBitmap: 0x%x\n", SuperBlock->AlgorithmUsageBitmap);
685 TRACE("PreallocBlocks: %d\n", SuperBlock->PreallocBlocks);
686 TRACE("PreallocDirBlocks: %d\n", SuperBlock->PreallocDirBlocks);
687 TRACE("ReservedGdtBlocks: %d\n", SuperBlock->ReservedGdtBlocks);
688 TRACE("JournalUUID: { ");
689 for (ULONG i = 0; i < sizeof(SuperBlock->JournalUUID); i++)
690 {
691 TRACE("0x%02x", SuperBlock->JournalUUID[i]);
692 if (i < sizeof(SuperBlock->JournalUUID) - 1)
693 TRACE(", ");
694 }
695 TRACE(" }\n");
696 TRACE("JournalInum: %d\n", SuperBlock->JournalInum);
697 TRACE("JournalDev: %d\n", SuperBlock->JournalDev);
698 TRACE("LastOrphan: %d\n", SuperBlock->LastOrphan);
699 TRACE("HashSeed: { 0x%02x, 0x%02x, 0x%02x, 0x%02x }\n",
700 SuperBlock->HashSeed[0], SuperBlock->HashSeed[1],
701 SuperBlock->HashSeed[2], SuperBlock->HashSeed[3]);
702 TRACE("DefHashVersion: %d\n", SuperBlock->DefHashVersion);
703 TRACE("JournalBackupType: %d\n", SuperBlock->JournalBackupType);
704 TRACE("GroupDescSize: %d\n", SuperBlock->GroupDescSize);
705 TRACE("DefaultMountOpts: %d\n", SuperBlock->DefaultMountOpts);
706 TRACE("FirstMetaBg: %d\n", SuperBlock->FirstMetaBg);
707 TRACE("MkfsTime: %d\n", SuperBlock->MkfsTime);
708 // ULONG JnlBlocks[17];
709 TRACE("BlocksCountHi: %d\n", SuperBlock->BlocksCountHi);
710 TRACE("RBlocksCountHi: %d\n", SuperBlock->RBlocksCountHi);
711 TRACE("FreeBlocksCountHi: %d\n", SuperBlock->FreeBlocksCountHi);
712
713 //
714 // Check the super block magic
715 //
716 if (SuperBlock->Magic != EXT_SUPERBLOCK_MAGIC)
717 {
718 FileSystemError("Invalid super block magic (0xef53)");
719 return FALSE;
720 }
721
722 // Calculate the group count
723 Volume->GroupCount = (SuperBlock->BlocksCountLo - SuperBlock->FirstDataBlock + SuperBlock->BlocksPerGroup - 1) / SuperBlock->BlocksPerGroup;
724 TRACE("ExtGroupCount: %d\n", Volume->GroupCount);
725
726 // Calculate the block size
727 Volume->BlockSizeInBytes = 1024 << SuperBlock->LogBlockSize;
728 Volume->BlockSizeInSectors = Volume->BlockSizeInBytes / Volume->BytesPerSector;
729 TRACE("ExtBlockSizeInBytes: %d\n", Volume->BlockSizeInBytes);
730 TRACE("ExtBlockSizeInSectors: %d\n", Volume->BlockSizeInSectors);
731
732 // Calculate the fragment size
733 if (SuperBlock->LogFragSize >= 0)
734 {
735 Volume->FragmentSizeInBytes = 1024 << SuperBlock->LogFragSize;
736 }
737 else
738 {
739 Volume->FragmentSizeInBytes = 1024 >> -(SuperBlock->LogFragSize);
740 }
741 Volume->FragmentSizeInSectors = Volume->FragmentSizeInBytes / Volume->BytesPerSector;
742 TRACE("ExtFragmentSizeInBytes: %d\n", Volume->FragmentSizeInBytes);
743 TRACE("ExtFragmentSizeInSectors: %d\n", Volume->FragmentSizeInSectors);
744
745 // Verify that the fragment size and the block size are equal
746 if (Volume->BlockSizeInBytes != Volume->FragmentSizeInBytes)
747 {
748 FileSystemError("The fragment size must be equal to the block size.");
749 return FALSE;
750 }
751
752 // Set the volume inode size in bytes
753 Volume->InodeSizeInBytes = EXT_INODE_SIZE(SuperBlock);
754 TRACE("InodeSizeInBytes: %d\n", Volume->InodeSizeInBytes);
755
756 // Set the volume group descriptor size in bytes
757 Volume->GroupDescSizeInBytes = EXT_GROUP_DESC_SIZE(SuperBlock);
758 TRACE("GroupDescSizeInBytes: %d\n", Volume->GroupDescSizeInBytes);
759
760 // Calculate the number of inodes in one block
761 Volume->InodesPerBlock = Volume->BlockSizeInBytes / Volume->InodeSizeInBytes;
762 TRACE("ExtInodesPerBlock: %d\n", Volume->InodesPerBlock);
763
764 // Calculate the number of group descriptors in one block
765 Volume->GroupDescPerBlock = Volume->BlockSizeInBytes / Volume->GroupDescSizeInBytes;
766 TRACE("ExtGroupDescPerBlock: %d\n", Volume->GroupDescPerBlock);
767
768 return TRUE;
769}
#define EXT_GROUP_DESC_SIZE(sb)
Definition: ext.h:208
struct _ExtSuperBlock * PEXT_SUPER_BLOCK
#define EXT_INODE_SIZE(sb)
Definition: ext.h:204
#define TAG_EXT_SUPER_BLOCK
Definition: ext.c:75
ULONG DefaultMountOpts
Definition: ext.h:104
ULONG FreeBlocksCountHi
Definition: ext.h:112
USHORT GroupDescSize
Definition: ext.h:102
ULONG FreeInodesCount
Definition: ext.h:59
UCHAR PreallocDirBlocks
Definition: ext.h:93
ULONG FeatureCompat
Definition: ext.h:85
UCHAR UUID[16]
Definition: ext.h:88
ULONG HashSeed[4]
Definition: ext.h:99
ULONG MkfsTime
Definition: ext.h:106
ULONG FirstMetaBg
Definition: ext.h:105
ULONG FeatureIncompat
Definition: ext.h:86
UCHAR DefHashVersion
Definition: ext.h:100
ULONG InodesCount
Definition: ext.h:55
UCHAR JournalBackupType
Definition: ext.h:101
ULONG BlocksCountLo
Definition: ext.h:56
USHORT MaxMntCount
Definition: ext.h:69
USHORT DefResUID
Definition: ext.h:78
ULONG InodesPerGroup
Definition: ext.h:65
ULONG MTime
Definition: ext.h:66
ULONG CreatorOS
Definition: ext.h:76
ULONG LogBlockSize
Definition: ext.h:61
ULONG LastCheck
Definition: ext.h:74
ULONG RevisionLevel
Definition: ext.h:77
USHORT BlockGroupNr
Definition: ext.h:84
ULONG CheckInterval
Definition: ext.h:75
ULONG AlgorithmUsageBitmap
Definition: ext.h:91
LONG LogFragSize
Definition: ext.h:62
ULONG FragsPerGroup
Definition: ext.h:64
USHORT DefResGID
Definition: ext.h:79
CHAR VolumeName[16]
Definition: ext.h:89
ULONG BlocksPerGroup
Definition: ext.h:63
ULONG FirstInode
Definition: ext.h:82
ULONG BlocksCountHi
Definition: ext.h:110
ULONG RBlocksCountHi
Definition: ext.h:111
ULONG WTime
Definition: ext.h:67
ULONG LastOrphan
Definition: ext.h:98
ULONG RBlocksCountLo
Definition: ext.h:57
ULONG FeatureROCompat
Definition: ext.h:87
USHORT MntCount
Definition: ext.h:68
USHORT InodeSize
Definition: ext.h:83
USHORT State
Definition: ext.h:71
UCHAR JournalUUID[16]
Definition: ext.h:95
CHAR LastMounted[64]
Definition: ext.h:90
USHORT Errors
Definition: ext.h:72
ULONG FreeBlocksCountLo
Definition: ext.h:58
USHORT ReservedGdtBlocks
Definition: ext.h:94
USHORT MinorRevisionLevel
Definition: ext.h:73
ULONG FirstDataBlock
Definition: ext.h:60
UCHAR PreallocBlocks
Definition: ext.h:92
ULONG JournalDev
Definition: ext.h:97
ULONG JournalInum
Definition: ext.h:96

Referenced by ExtOpenVolume().

◆ ExtReadVolumeSectors()

BOOLEAN ExtReadVolumeSectors ( PEXT_VOLUME_INFO  Volume,
ULONGLONG  SectorNumber,
ULONG  SectorCount,
PVOID  Buffer 
)

Definition at line 569 of file ext.c.

570{
571#if 0
572 return CacheReadDiskSectors(DriveNumber, SectorNumber + ExtVolumeStartSector, SectorCount, Buffer);
573#endif
574
576 ULONG Count;
578
579 /* Seek to right position */
580 Position.QuadPart = (ULONGLONG)SectorNumber * 512;
581 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
582 if (Status != ESUCCESS)
583 {
584 TRACE("ExtReadVolumeSectors() Failed to seek\n");
585 return FALSE;
586 }
587
588 /* Read data */
589 Status = ArcRead(Volume->DeviceId, Buffer, SectorCount * 512, &Count);
590 if (Status != ESUCCESS || Count != SectorCount * 512)
591 {
592 TRACE("ExtReadVolumeSectors() Failed to read\n");
593 return FALSE;
594 }
595
596 /* Return success */
597 return TRUE;
598}
BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
Definition: cache.c:113
ULONG SectorCount
Definition: part_xbox.c:31

Referenced by ExtReadBlock().

◆ ExtSearchDirectoryBufferForFile()

BOOLEAN ExtSearchDirectoryBufferForFile ( PVOID  DirectoryBuffer,
ULONG  DirectorySize,
PCHAR  FileName,
PEXT_DIR_ENTRY  DirectoryEntry 
)

Definition at line 330 of file ext.c.

331{
332 PEXT_DIR_ENTRY CurrentDirectoryEntry;
333 ULONG CurrentOffset = 0;
335
336 TRACE("ExtSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = \"%s\"\n", DirectoryBuffer, DirectorySize, FileName);
337
339
340 while (CurrentOffset < DirectorySize)
341 {
342 CurrentDirectoryEntry = (PEXT_DIR_ENTRY)((ULONG_PTR)DirectoryBuffer + CurrentOffset);
343
344 if (!CurrentDirectoryEntry->EntryLen)
345 break;
346
347 if ((CurrentDirectoryEntry->EntryLen + CurrentOffset) > DirectorySize)
348 {
349 FileSystemError("Directory entry extends past end of directory file.");
350 return FALSE;
351 }
352
353 if (!CurrentDirectoryEntry->Inode)
354 goto NextDirectoryEntry;
355
356 TRACE("EXT Directory Entry:\n");
357 TRACE("Inode = %d\n", CurrentDirectoryEntry->Inode);
358 TRACE("EntryLen = %d\n", CurrentDirectoryEntry->EntryLen);
359 TRACE("NameLen = %d\n", CurrentDirectoryEntry->NameLen);
360 TRACE("FileType = %d\n", CurrentDirectoryEntry->FileType);
361 TRACE("Name = \"");
362 for (ULONG NameOffset = 0; NameOffset < CurrentDirectoryEntry->NameLen; NameOffset++)
363 {
364 TRACE("%c", CurrentDirectoryEntry->Name[NameOffset]);
365 }
366 TRACE("\"\n\n");
367
368 if ((FileNameLen == CurrentDirectoryEntry->NameLen) &&
369 (_strnicmp(FileName, CurrentDirectoryEntry->Name, FileNameLen) == 0))
370 {
371 RtlCopyMemory(DirectoryEntry, CurrentDirectoryEntry, sizeof(EXT_DIR_ENTRY));
372 return TRUE;
373 }
374
375NextDirectoryEntry:
376 CurrentOffset += CurrentDirectoryEntry->EntryLen;
377 }
378
379 return FALSE;
380}
Dirent FileNameLen
Definition: dirsup.c:506
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
USHORT EntryLen
Definition: ext.h:189
UCHAR FileType
Definition: ext.h:191

Referenced by ExtLookupFile().

◆ ExtSeek()

ARC_STATUS ExtSeek ( ULONG  FileId,
LARGE_INTEGER Position,
SEEKMODE  SeekMode 
)

Definition at line 1373 of file ext.c.

1374{
1376 LARGE_INTEGER NewPosition = *Position;
1377
1378 switch (SeekMode)
1379 {
1380 case SeekAbsolute:
1381 break;
1382 case SeekRelative:
1383 NewPosition.QuadPart += FileHandle->FilePointer;
1384 break;
1385 default:
1386 ASSERT(FALSE);
1387 return EINVAL;
1388 }
1389
1390 if (NewPosition.QuadPart >= FileHandle->FileSize)
1391 return EINVAL;
1392
1393 FileHandle->FilePointer = NewPosition.QuadPart;
1394 return ESUCCESS;
1395}
#define EINVAL
Definition: acclib.h:90
@ SeekRelative
Definition: arc.h:60
LONGLONG QuadPart
Definition: typedefs.h:114

Variable Documentation

◆ ExtFuncTable

const DEVVTBL ExtFuncTable
Initial value:
=
{
L"ext2fs",
}
ARC_STATUS ExtGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ext.c:1309
ARC_STATUS ExtSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ext.c:1373
ARC_STATUS ExtRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ext.c:1358
ARC_STATUS ExtClose(ULONG FileId)
Definition: ext.c:1302
ARC_STATUS ExtOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ext.c:1331
#define L(x)
Definition: resources.c:13

Definition at line 1421 of file ext.c.

Referenced by ExtMount().

◆ ExtVolumes

Definition at line 70 of file ext.c.

Referenced by ExtGetVolumeSize(), ExtMount(), and ExtOpen().