Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmetadata.c
Go to the documentation of this file.
00001 /************************************************************************* 00002 * 00003 * File: metadata.c 00004 * 00005 * Module: Ext2 File System Driver (Kernel mode execution only) 00006 * 00007 * Description: 00008 * Should contain code to handle Ext2 Metadata. 00009 * 00010 * Author: Manoj Paul Joseph 00011 * 00012 * 00013 *************************************************************************/ 00014 00015 #include "ext2fsd.h" 00016 00017 #define EXT2_BUG_CHECK_ID EXT2_FILE_METADATA_IO 00018 00019 #define DEBUG_LEVEL ( DEBUG_TRACE_METADATA ) 00020 00021 extern Ext2Data Ext2GlobalData; 00022 00023 /************************************************************************* 00024 * 00025 * Function: Ext2ReadInode() 00026 * 00027 * Description: 00028 * 00029 * The functions will read in the specifiec inode and return it in a buffer 00030 * 00031 * 00032 * Expected Interrupt Level (for execution) : 00033 * 00034 * IRQL_PASSIVE_LEVEL 00035 * 00036 * 00037 * Arguements: 00038 * 00039 * 00040 * 00041 * Return Value: The Status of the Read IO 00042 * 00043 *************************************************************************/ 00044 00045 NTSTATUS NTAPI Ext2ReadInode ( 00046 PtrExt2VCB PtrVcb, // the Volume Control Block 00047 uint32 InodeNo, // The Inode no 00048 PEXT2_INODE PtrInode // The Inode Buffer 00049 ) 00050 { 00051 // The Status to be returned... 00052 NTSTATUS RC = STATUS_SUCCESS; 00053 00054 // The Read Buffer Pointer 00055 BYTE * PtrPinnedReadBuffer = NULL; 00056 00057 PEXT2_INODE PtrTempInode; 00058 00059 // Buffer Control Block 00060 PBCB PtrBCB = NULL; 00061 00062 LARGE_INTEGER VolumeByteOffset, TempOffset; 00063 00064 ULONG LogicalBlockSize = 0; 00065 00066 ULONG NumberOfBytesToRead = 0; 00067 ULONG Difference = 0; 00068 00069 ULONG GroupNo; 00070 int Index; 00071 00072 try 00073 { 00074 ASSERT(PtrVcb); 00075 ASSERT(PtrVcb->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB); 00076 00077 // Inode numbers start at 1 and not from 0 00078 // Hence 1 is subtracted from InodeNo to get a zero based index... 00079 GroupNo = ( InodeNo - 1 ) / PtrVcb->InodesPerGroup; 00080 00081 if( GroupNo >= PtrVcb->NoOfGroups ) 00082 { 00083 DebugTrace(DEBUG_TRACE_MISC, "&&&&&& Invalid Inode no. Group no %d - too big", GroupNo ); 00084 DebugTrace(DEBUG_TRACE_MISC, "Only %d groups available on disk", PtrVcb->NoOfGroups ); 00085 RC = STATUS_UNSUCCESSFUL; 00086 try_return(); 00087 } 00088 00089 //if( PtrVcb->InodeTableBlock[ GroupNo ] == 0 ) 00090 if( PtrVcb->PtrGroupDescriptors[ GroupNo ].InodeTablesBlock == 0 ) 00091 { 00092 DebugTrace(DEBUG_TRACE_MISC, "&&&&&& Inode Table Group Invalid - Group no %d ", GroupNo ); 00093 RC = STATUS_UNSUCCESSFUL; 00094 try_return(); 00095 } 00096 00097 // Inode numbers start at 1 and not from 0 00098 // Hence 1 is subtracted from InodeNo to get a zero based index... 00099 Index = ( InodeNo - 1 ) - ( GroupNo * PtrVcb->InodesPerGroup ); 00100 00101 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVcb->LogBlockSize; 00102 NumberOfBytesToRead = sizeof(EXT2_INODE); // LogicalBlockSize; 00103 00104 VolumeByteOffset.QuadPart = PtrVcb->PtrGroupDescriptors[ GroupNo ].InodeTablesBlock 00105 * LogicalBlockSize + Index * PtrVcb->InodeSize; 00106 //VolumeByteOffset.QuadPart = PtrVcb->InodeTableBlock[ GroupNo ] * LogicalBlockSize + 00107 // Index * PtrVcb->InodeSize; 00108 00109 TempOffset.QuadPart = Ext2Align64( VolumeByteOffset.QuadPart, LogicalBlockSize ); 00110 if( TempOffset.QuadPart != VolumeByteOffset.QuadPart ) 00111 { 00112 // TempOffset.QuadPart -= LogicalBlockSize; 00113 Difference = (LONG) (VolumeByteOffset.QuadPart - TempOffset.QuadPart + LogicalBlockSize ); 00114 VolumeByteOffset.QuadPart -= Difference; 00115 NumberOfBytesToRead += Difference; 00116 } 00117 00118 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 00119 00120 if( NumberOfBytesToRead > LogicalBlockSize ) 00121 { 00122 // Multiple blocks being read in... 00123 // Can cause overlap 00124 // Watch out!!!! 00125 Ext2BreakPoint(); 00126 } 00127 00128 00129 00130 if (!CcMapData( PtrVcb->PtrStreamFileObject, 00131 &VolumeByteOffset, 00132 NumberOfBytesToRead, 00133 TRUE, 00134 &PtrBCB, 00135 (PVOID*)&PtrPinnedReadBuffer )) 00136 { 00137 RC = STATUS_UNSUCCESSFUL; 00138 try_return(); 00139 } 00140 else 00141 { 00142 PtrTempInode = (PEXT2_INODE) ( PtrPinnedReadBuffer + Difference ); 00143 RtlCopyMemory( PtrInode, PtrTempInode , sizeof(EXT2_INODE) ); 00144 } 00145 00146 try_exit: NOTHING; 00147 } 00148 finally 00149 { 00150 if( PtrBCB ) 00151 { 00152 CcUnpinData( PtrBCB ); 00153 PtrBCB = NULL; 00154 } 00155 00156 } 00157 return RC; 00158 } 00159 00160 /************************************************************************* 00161 * 00162 * Function: Ext2InitializeFCBInodeInfo() 00163 * 00164 * Description: 00165 * The functions will initialize the FCB with its i-node info 00166 * provided it hasn't been initialized as yet... 00167 * 00168 * Expected Interrupt Level (for execution) : 00169 * IRQL_PASSIVE_LEVEL 00170 * 00171 * Arguements: 00172 * Pointer to FCB 00173 * 00174 * Return Value: None 00175 * 00176 *************************************************************************/ 00177 void NTAPI Ext2InitializeFCBInodeInfo ( 00178 PtrExt2FCB PtrFCB ) 00179 { 00180 PtrExt2VCB PtrVCB = NULL; 00181 EXT2_INODE Inode; 00182 int i; 00183 ULONG LogicalBlockSize; 00184 00185 PtrVCB = PtrFCB->PtrVCB; 00186 00187 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 00188 00189 if( !Ext2IsFlagOn( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED ) ) 00190 { 00191 DebugTrace(DEBUG_TRACE_MISC, "Reading in the i-node no %d", PtrFCB->INodeNo ); 00192 00193 Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ); 00194 00195 for( i = 0; i < EXT2_N_BLOCKS ; i++ ) 00196 { 00197 PtrFCB->IBlock[i] = Inode.i_block[ i ]; 00198 } 00199 00200 PtrFCB->CreationTime.QuadPart = ( __int64 )Inode.i_ctime * 10000000; 00201 PtrFCB->CreationTime.QuadPart += Ext2GlobalData.TimeDiff.QuadPart; 00202 PtrFCB->LastAccessTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) Inode.i_atime * 10000000); 00203 PtrFCB->LastWriteTime.QuadPart = Ext2GlobalData.TimeDiff.QuadPart + ( ( __int64 ) Inode.i_mtime * 10000000); 00204 00205 00206 PtrFCB->LinkCount = Inode.i_links_count; 00207 00208 // Getting the file type... 00209 if( ! Ext2IsModeRegularFile( Inode.i_mode ) ) 00210 { 00211 // Not a reqular file... 00212 if( Ext2IsModeDirectory( Inode.i_mode) ) 00213 { 00214 // Directory... 00215 Ext2SetFlag( PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY ); 00216 } 00217 else 00218 { 00219 // Special File... 00220 // Treated with respect... ;) 00221 // 00222 Ext2SetFlag( PtrFCB->FCBFlags, EXT2_FCB_SPECIAL_FILE ); 00223 } 00224 00225 } 00226 if( Ext2IsModeHidden( Inode.i_mode ) ) 00227 { 00228 Ext2SetFlag( PtrFCB->FCBFlags, EXT2_FCB_HIDDEN_FILE ); 00229 } 00230 if( Ext2IsModeReadOnly( Inode.i_mode ) ) 00231 { 00232 Ext2SetFlag( PtrFCB->FCBFlags, EXT2_FCB_READ_ONLY ); 00233 } 00234 00235 00236 PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart = Inode.i_size; 00237 Ext2SetFlag( PtrFCB->FCBFlags, EXT2_FCB_BLOCKS_INITIALIZED ); 00238 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart = Inode.i_blocks * 512; 00239 00240 if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] ) 00241 { 00242 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart -= LogicalBlockSize / 512; 00243 } 00244 DebugTrace( DEBUG_TRACE_FREE, "Freeing = %lX [metadata]", Inode ); 00245 } 00246 } 00247 00248 /************************************************************************* 00249 * 00250 * Function: Ext2AllocInode() 00251 * 00252 * Description: 00253 * The functions will allocate a new on-disk i-node 00254 * 00255 * Expected Interrupt Level (for execution) : 00256 * IRQL_PASSIVE_LEVEL 00257 * 00258 * 00259 * Arguements: 00260 * Parent Inode no 00261 * 00262 * Return Value: The new i-node no or zero 00263 * 00264 *************************************************************************/ 00265 ULONG NTAPI Ext2AllocInode( 00266 PtrExt2IrpContext PtrIrpContext, 00267 PtrExt2VCB PtrVCB, 00268 ULONG ParentINodeNo ) 00269 { 00270 ULONG InodeNo = 0; 00271 00272 // Buffer Control Block 00273 PBCB PtrBitmapBCB = NULL; 00274 BYTE * PtrBitmapBuffer = NULL; 00275 00276 LARGE_INTEGER VolumeByteOffset; 00277 ULONG LogicalBlockSize = 0; 00278 ULONG NumberOfBytesToRead = 0; 00279 00280 if( PtrVCB->FreeInodesCount == 0) 00281 { 00282 // 00283 // No Free Inodes left... 00284 // Fail request... 00285 // 00286 return 0; 00287 } 00288 00289 try 00290 { 00291 // unsigned int DescIndex ; 00292 BOOLEAN Found = FALSE; 00293 ULONG Block; 00294 ULONG GroupNo; 00295 00296 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 00297 00298 for( GroupNo = 0; PtrVCB->NoOfGroups; GroupNo++ ) 00299 { 00300 if( PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeInodesCount ) 00301 break; 00302 } 00303 00304 VolumeByteOffset.QuadPart = 00305 PtrVCB->PtrGroupDescriptors[ GroupNo ].InodeBitmapBlock * LogicalBlockSize; 00306 00307 NumberOfBytesToRead = PtrVCB->InodesCount / PtrVCB->NoOfGroups; 00308 00309 if( NumberOfBytesToRead % 8 ) 00310 { 00311 NumberOfBytesToRead = ( NumberOfBytesToRead / 8 ) + 1; 00312 } 00313 else 00314 { 00315 NumberOfBytesToRead = ( NumberOfBytesToRead / 8 ) ; 00316 } 00317 00318 for( Block = 0; !Found && Block < Ext2Align( NumberOfBytesToRead , LogicalBlockSize ); 00319 Block += LogicalBlockSize, VolumeByteOffset.QuadPart += LogicalBlockSize) 00320 { 00321 // 00322 // Read in the bitmap block... 00323 // 00324 ULONG i, j; 00325 BYTE Bitmap; 00326 00327 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 00328 &VolumeByteOffset, 00329 LogicalBlockSize, //NumberOfBytesToRead, 00330 TRUE, 00331 &PtrBitmapBCB, 00332 (PVOID*)&PtrBitmapBuffer ) ) 00333 { 00334 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 00335 return 0; 00336 } 00337 00338 // 00339 // Is there a free inode... 00340 // 00341 for( i = 0; !Found && i < LogicalBlockSize && 00342 i + (Block * LogicalBlockSize) < NumberOfBytesToRead; i++ ) 00343 { 00344 Bitmap = PtrBitmapBuffer[i]; 00345 if( Bitmap != 0xff ) 00346 { 00347 // 00348 // Found a free inode... 00349 for( j = 0; !Found && j < 8; j++ ) 00350 { 00351 if( ( Bitmap & 0x01 ) == 0 ) 00352 { 00353 // 00354 // Found... 00355 Found = TRUE; 00356 00357 // Inode numbers start at 1 and not from 0 00358 // Hence 1 is addded to j 00359 InodeNo = ( ( ( Block * LogicalBlockSize) + i ) * 8) + j + 1 + 00360 ( GroupNo * PtrVCB->InodesPerGroup ); 00361 00362 // Update the inode on the disk... 00363 Bitmap = 1 << j; 00364 PtrBitmapBuffer[i] |= Bitmap; 00365 00366 CcSetDirtyPinnedData( PtrBitmapBCB, NULL ); 00367 Ext2SaveBCB( PtrIrpContext, PtrBitmapBCB, PtrVCB->PtrStreamFileObject ); 00368 00369 // 00370 // Should update the bitmaps in the other groups too... 00371 // 00372 break; 00373 } 00374 Bitmap = Bitmap >> 1; 00375 } 00376 } 00377 } 00378 // 00379 // Unpin the BCB... 00380 // 00381 if( PtrBitmapBCB ) 00382 { 00383 CcUnpinData( PtrBitmapBCB ); 00384 PtrBitmapBCB = NULL; 00385 } 00386 } 00387 00388 { 00389 // 00390 // Updating the Inode count in the Group Descriptor... 00391 // 00392 PBCB PtrDescriptorBCB = NULL; 00393 PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL; 00394 00395 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeInodesCount--; 00396 00397 if( PtrVCB->LogBlockSize ) 00398 { 00399 // First block contains the descriptors... 00400 VolumeByteOffset.QuadPart = LogicalBlockSize; 00401 } 00402 else 00403 { 00404 // Second block contains the descriptors... 00405 VolumeByteOffset.QuadPart = LogicalBlockSize * 2; 00406 } 00407 NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc ); 00408 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 00409 00410 if (!CcPinRead( PtrVCB->PtrStreamFileObject, 00411 &VolumeByteOffset, 00412 NumberOfBytesToRead, 00413 TRUE, 00414 &PtrDescriptorBCB , 00415 (PVOID*)&PtrGroupDescriptor )) 00416 { 00417 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 00418 // 00419 // Ignore this error... 00420 // Not fatal... 00421 } 00422 else 00423 { 00424 PtrGroupDescriptor[ GroupNo ].bg_free_inodes_count = 00425 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeInodesCount; 00426 // 00427 // Not synchronously flushing this information... 00428 // Lazy writing will do... 00429 // 00430 CcSetDirtyPinnedData( PtrDescriptorBCB, NULL ); 00431 CcUnpinData( PtrDescriptorBCB ); 00432 PtrDescriptorBCB = NULL; 00433 } 00434 } 00435 00436 00437 // 00438 // Update the Inode count... 00439 // in the Super Block... 00440 // 00441 { 00442 // Ext2 Super Block information... 00443 PEXT2_SUPER_BLOCK PtrSuperBlock = NULL; 00444 PBCB PtrSuperBlockBCB = NULL; 00445 00446 PtrVCB->FreeInodesCount--; 00447 // Reading in the super block... 00448 VolumeByteOffset.QuadPart = 1024; 00449 00450 // THis shouldn't be more than a block in size... 00451 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize ); 00452 00453 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 00454 &VolumeByteOffset, 00455 NumberOfBytesToRead, 00456 TRUE, 00457 &PtrSuperBlockBCB, 00458 (PVOID*)&PtrSuperBlock ) ) 00459 { 00460 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 00461 } 00462 else 00463 { 00464 PtrSuperBlock->s_free_inodes_count = PtrVCB->FreeInodesCount; 00465 CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL ); 00466 Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject ); 00467 if( PtrSuperBlockBCB ) 00468 { 00469 CcUnpinData( PtrSuperBlockBCB ); 00470 PtrSuperBlockBCB = NULL; 00471 } 00472 00473 } 00474 } 00475 } 00476 finally 00477 { 00478 if( PtrBitmapBCB ) 00479 { 00480 CcUnpinData( PtrBitmapBCB ); 00481 PtrBitmapBCB = NULL; 00482 } 00483 } 00484 DebugTrace( DEBUG_TRACE_SPECIAL, " Allocating an inode - I-Node no : %ld", InodeNo ); 00485 00486 return InodeNo; 00487 00488 } 00489 00490 /************************************************************************* 00491 * 00492 * Function: Ext2DeallocInode() 00493 * 00494 * Description: 00495 * The functions will deallocate an i-node 00496 * 00497 * Expected Interrupt Level (for execution) : 00498 * IRQL_PASSIVE_LEVEL 00499 * 00500 * Return Value: Success / Failure... 00501 * 00502 *************************************************************************/ 00503 BOOLEAN NTAPI Ext2DeallocInode( 00504 PtrExt2IrpContext PtrIrpContext, 00505 PtrExt2VCB PtrVCB, 00506 ULONG INodeNo ) 00507 { 00508 BOOLEAN RC = TRUE; 00509 00510 // Buffer Control Block 00511 PBCB PtrBitmapBCB = NULL; 00512 BYTE * PtrBitmapBuffer = NULL; 00513 00514 LARGE_INTEGER VolumeByteOffset; 00515 ULONG LogicalBlockSize = 0; 00516 00517 DebugTrace( DEBUG_TRACE_SPECIAL, " Deallocating an inode - I-Node no : %ld", INodeNo ); 00518 00519 try 00520 { 00521 ULONG BlockIndex ; 00522 ULONG BitmapIndex; 00523 ULONG GroupNo; 00524 BYTE Bitmap; 00525 00526 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 00527 00528 GroupNo = INodeNo / PtrVCB->InodesPerGroup; 00529 INodeNo = INodeNo % PtrVCB->InodesPerGroup; 00530 00531 BitmapIndex = (INodeNo-1) / 8; 00532 Bitmap = 1 << ( (INodeNo-1) % 8 ); 00533 BlockIndex = BitmapIndex / LogicalBlockSize; 00534 // Adjusting to index into the Logical block that contains the bitmap 00535 BitmapIndex = BitmapIndex - ( BlockIndex * LogicalBlockSize ); 00536 00537 VolumeByteOffset.QuadPart = 00538 ( PtrVCB->PtrGroupDescriptors[ GroupNo ].InodeBitmapBlock + BlockIndex ) 00539 * LogicalBlockSize; 00540 00541 // 00542 // Read in the bitmap block... 00543 // 00544 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 00545 &VolumeByteOffset, 00546 LogicalBlockSize, // Just the block that contains the bitmap will do... 00547 TRUE, // Can Wait... 00548 &PtrBitmapBCB, 00549 (PVOID*)&PtrBitmapBuffer ) ) 00550 { 00551 // Unable to Pin the data into the cache... 00552 try_return (RC = FALSE); 00553 } 00554 00555 // 00556 // Locate the inode... 00557 // This inode is in the byte PtrBitmapBuffer[ BitmapIndex ] 00558 if( ( PtrBitmapBuffer[ BitmapIndex ] & Bitmap ) == 0) 00559 { 00560 // This shouldn't have been so... 00561 // The inode was never allocated! 00562 // How to deallocate something that hasn't been allocated? 00563 // Hmmm... ;) 00564 // Ignore this error... 00565 try_return (RC = TRUE); 00566 } 00567 00568 00569 // Setting the bit for the inode... 00570 PtrBitmapBuffer[ BitmapIndex ] &= (~Bitmap); 00571 00572 // Update the cache... 00573 CcSetDirtyPinnedData( PtrBitmapBCB, NULL ); 00574 00575 // Save up the BCB for forcing a synchronous write... 00576 // Before completing the IRP... 00577 Ext2SaveBCB( PtrIrpContext, PtrBitmapBCB, PtrVCB->PtrStreamFileObject ); 00578 00579 00580 if( PtrBitmapBCB ) 00581 { 00582 CcUnpinData( PtrBitmapBCB ); 00583 PtrBitmapBCB = NULL; 00584 } 00585 00586 { 00587 // 00588 // Updating the Inode count in the Group Descriptor... 00589 // 00590 PBCB PtrDescriptorBCB = NULL; 00591 PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL; 00592 ULONG NumberOfBytesToRead = 0; 00593 00594 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeInodesCount++; 00595 00596 if( PtrVCB->LogBlockSize ) 00597 { 00598 // First block contains the descriptors... 00599 VolumeByteOffset.QuadPart = LogicalBlockSize; 00600 } 00601 else 00602 { 00603 // Second block contains the descriptors... 00604 VolumeByteOffset.QuadPart = LogicalBlockSize * 2; 00605 } 00606 NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc ); 00607 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 00608 00609 if (!CcPinRead( PtrVCB->PtrStreamFileObject, 00610 &VolumeByteOffset, 00611 NumberOfBytesToRead, 00612 TRUE, 00613 &PtrDescriptorBCB , 00614 (PVOID*)&PtrGroupDescriptor )) 00615 { 00616 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 00617 // 00618 // Ignore this error... 00619 // Not fatal... 00620 } 00621 else 00622 { 00623 PtrGroupDescriptor[ GroupNo ].bg_free_inodes_count = 00624 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeInodesCount; 00625 // 00626 // Not synchronously flushing this information... 00627 // Lazy writing will do... 00628 // 00629 CcSetDirtyPinnedData( PtrDescriptorBCB, NULL ); 00630 CcUnpinData( PtrDescriptorBCB ); 00631 PtrDescriptorBCB = NULL; 00632 } 00633 } 00634 00635 00636 // 00637 // Update the Inode count... 00638 // in the Super Block 00639 // and in the VCB 00640 // 00641 { 00642 // Ext2 Super Block information... 00643 PEXT2_SUPER_BLOCK PtrSuperBlock = NULL; 00644 PBCB PtrSuperBlockBCB = NULL; 00645 ULONG NumberOfBytesToRead = 0; 00646 00647 PtrVCB->FreeInodesCount++; 00648 00649 // Reading in the super block... 00650 VolumeByteOffset.QuadPart = 1024; 00651 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize ); 00652 00653 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 00654 &VolumeByteOffset, 00655 NumberOfBytesToRead, 00656 TRUE, 00657 &PtrSuperBlockBCB, 00658 (PVOID*)&PtrSuperBlock ) ) 00659 { 00660 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 00661 } 00662 else 00663 { 00664 PtrSuperBlock->s_free_inodes_count = PtrVCB->FreeInodesCount; 00665 CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL ); 00666 Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject ); 00667 if( PtrSuperBlockBCB ) 00668 { 00669 CcUnpinData( PtrSuperBlockBCB ); 00670 PtrSuperBlockBCB = NULL; 00671 } 00672 00673 } 00674 } 00675 try_exit: NOTHING; 00676 } 00677 finally 00678 { 00679 if( PtrBitmapBCB ) 00680 { 00681 CcUnpinData( PtrBitmapBCB ); 00682 PtrBitmapBCB = NULL; 00683 } 00684 } 00685 return RC; 00686 } 00687 00688 /************************************************************************* 00689 * 00690 * Function: Ext2WriteInode() 00691 * 00692 * Description: 00693 * The functions will write an i-node to disk 00694 * 00695 * Expected Interrupt Level (for execution) : 00696 * IRQL_PASSIVE_LEVEL 00697 * 00698 * 00699 * Return Value: Success / Failure... 00700 * 00701 *************************************************************************/ 00702 NTSTATUS NTAPI Ext2WriteInode( 00703 PtrExt2IrpContext PtrIrpContext, 00704 PtrExt2VCB PtrVcb, // the Volume Control Block 00705 uint32 InodeNo, // The Inode no 00706 PEXT2_INODE PtrInode // The Inode Buffer 00707 ) 00708 { 00709 // The Status to be returned... 00710 NTSTATUS RC = STATUS_SUCCESS; 00711 00712 // The Read Buffer Pointer 00713 BYTE * PtrPinnedBuffer = NULL; 00714 00715 // Buffer Control Block 00716 PBCB PtrBCB = NULL; 00717 00718 LARGE_INTEGER VolumeByteOffset, TempOffset; 00719 00720 ULONG LogicalBlockSize = 0; 00721 ULONG NumberOfBytesToRead = 0; 00722 ULONG Difference = 0; 00723 ULONG GroupNo; 00724 int Index; 00725 00726 try 00727 { 00728 DebugTrace( DEBUG_TRACE_SPECIAL, "Writing and updating an inode - I-Node no : %ld", InodeNo ); 00729 00730 ASSERT(PtrVcb); 00731 ASSERT(PtrVcb->NodeIdentifier.NodeType == EXT2_NODE_TYPE_VCB); 00732 GroupNo = InodeNo / PtrVcb->InodesPerGroup; 00733 00734 if( GroupNo >= PtrVcb->NoOfGroups ) 00735 { 00736 DebugTrace(DEBUG_TRACE_MISC, "&&&&&& Invalid Inode no. Group no %d - too big", GroupNo ); 00737 DebugTrace(DEBUG_TRACE_MISC, "Only %d groups available on disk", PtrVcb->NoOfGroups ); 00738 RC = STATUS_UNSUCCESSFUL; 00739 try_return(); 00740 } 00741 00742 if( PtrVcb->PtrGroupDescriptors[ GroupNo ].InodeTablesBlock == 0 ) 00743 { 00744 DebugTrace(DEBUG_TRACE_MISC, "&&&&&& Inode Table Group Invalid - Group no %d ", GroupNo ); 00745 RC = STATUS_UNSUCCESSFUL; 00746 try_return(); 00747 } 00748 00749 Index = ( InodeNo - 1 ) - ( GroupNo * PtrVcb->InodesPerGroup ); 00750 00751 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVcb->LogBlockSize; 00752 NumberOfBytesToRead = sizeof(EXT2_INODE); 00753 00754 VolumeByteOffset.QuadPart = PtrVcb->PtrGroupDescriptors[ GroupNo ].InodeTablesBlock 00755 * LogicalBlockSize + Index * PtrVcb->InodeSize; 00756 00757 TempOffset.QuadPart = Ext2Align64( VolumeByteOffset.QuadPart, LogicalBlockSize ); 00758 if( TempOffset.QuadPart != VolumeByteOffset.QuadPart ) 00759 { 00760 // TempOffset.QuadPart -= LogicalBlockSize; 00761 Difference = (LONG) (VolumeByteOffset.QuadPart - TempOffset.QuadPart + LogicalBlockSize ); 00762 VolumeByteOffset.QuadPart -= Difference; 00763 NumberOfBytesToRead += Difference; 00764 } 00765 00766 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 00767 00768 if( NumberOfBytesToRead > LogicalBlockSize ) 00769 { 00770 // Multiple blocks being read in... 00771 // Can cause overlap 00772 // Watch out!!!! 00773 Ext2BreakPoint(); 00774 } 00775 00776 if( !CcPinRead( PtrVcb->PtrStreamFileObject, 00777 &VolumeByteOffset, 00778 NumberOfBytesToRead, 00779 TRUE, // Can Wait... 00780 &PtrBCB, 00781 (PVOID*)&PtrPinnedBuffer ) ) 00782 { 00783 RC = STATUS_UNSUCCESSFUL; 00784 try_return(); 00785 } 00786 else 00787 { 00788 RtlCopyMemory( PtrPinnedBuffer + Difference, PtrInode, sizeof(EXT2_INODE) ); 00789 CcSetDirtyPinnedData( PtrBCB, NULL ); 00790 Ext2SaveBCB( PtrIrpContext, PtrBCB, PtrVcb->PtrStreamFileObject ); 00791 } 00792 00793 try_exit: NOTHING; 00794 } 00795 finally 00796 { 00797 if( PtrBCB ) 00798 { 00799 CcUnpinData( PtrBCB ); 00800 PtrBCB = NULL; 00801 } 00802 00803 } 00804 return RC; 00805 } 00806 00807 00808 /************************************************************************* 00809 * 00810 * Function: Ext2MakeNewDirectoryEntry() 00811 * 00812 * Description: 00813 * The functions will make a new directory entry in a directory file... 00814 * 00815 * Expected Interrupt Level (for execution) : 00816 * IRQL_PASSIVE_LEVEL 00817 * 00818 * 00819 * Return Value: Success / Failure... 00820 * 00821 *************************************************************************/ 00822 BOOLEAN NTAPI Ext2MakeNewDirectoryEntry( 00823 PtrExt2IrpContext PtrIrpContext, // The Irp context 00824 PtrExt2FCB PtrParentFCB, // Parent Folder FCB 00825 PFILE_OBJECT PtrFileObject, // Parent Folder Object 00826 PUNICODE_STRING PtrName, // New entry's name 00827 ULONG Type, // The type of the new entry 00828 ULONG NewInodeNo) // The inode no of the new entry... 00829 { 00830 PBCB PtrLastBlockBCB = NULL; 00831 BYTE * PtrLastBlock = NULL; 00832 EXT2_DIR_ENTRY DirEntry; 00833 PEXT2_DIR_ENTRY PtrTempDirEntry; 00834 00835 ULONG BlockNo = 0; 00836 ULONG i; 00837 PtrExt2VCB PtrVCB; 00838 LARGE_INTEGER VolumeByteOffset; 00839 unsigned long LogicalBlockSize = 0; 00840 BOOLEAN RC = FALSE; 00841 00842 USHORT HeaderLength = sizeof( EXT2_DIR_ENTRY ); 00843 USHORT NewEntryLength = 0; 00844 USHORT MinLength = 0; 00845 #define ActualLength (PtrTempDirEntry->rec_len) 00846 #define NameLength (PtrTempDirEntry->name_len) 00847 00848 try 00849 { 00850 ASSERT( PtrFileObject ); 00851 00852 DebugTrace( DEBUG_TRACE_SPECIAL, "Making directory entry: %S", PtrName->Buffer ); 00853 00854 PtrVCB = PtrParentFCB->PtrVCB; 00855 AssertVCB( PtrVCB); 00856 00857 HeaderLength = sizeof( EXT2_DIR_ENTRY ) - 00858 (sizeof( char ) * EXT2_NAME_LEN); 00859 // 1. Setting up the entry... 00860 NewEntryLength = sizeof( EXT2_DIR_ENTRY ) - ( sizeof( char ) * ( EXT2_NAME_LEN - (PtrName->Length / 2) ) ); 00861 // Length should be a multiplicant of 4 00862 NewEntryLength = ((NewEntryLength + 3 ) & 0xfffffffc); 00863 00864 RtlZeroMemory( &DirEntry, sizeof( EXT2_DIR_ENTRY ) ); 00865 00866 DirEntry.file_type = (BYTE) Type; 00867 DirEntry.inode = NewInodeNo; 00868 DirEntry.name_len = (BYTE)(PtrName->Length / 2 ); // Does not include a NULL 00869 00870 // DirEntry.rec_len = (USHORT) NewEntryLength; 00871 00872 for( i = 0; ; i++ ) 00873 { 00874 if( i < (ULONG)( PtrName->Length / 2 ) ) 00875 { 00876 DirEntry.name[i] = (CHAR) PtrName->Buffer[i]; 00877 } 00878 else 00879 { 00880 //DirEntry.name[i] = 0; // Entry need not be zero terminated... 00881 break; 00882 } 00883 } 00884 00885 // 00886 // 2. Read the block in the directory... 00887 // Initiate Caching... 00888 if ( PtrFileObject->PrivateCacheMap == NULL ) 00889 { 00890 CcInitializeCacheMap( 00891 PtrFileObject, 00892 (PCC_FILE_SIZES)(&(PtrParentFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)), 00893 TRUE, // We utilize pin access for directories 00894 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks 00895 PtrParentFCB ); // The context used in callbacks 00896 } 00897 00898 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 00899 if( PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart > 0 ) 00900 { 00901 BlockNo = (ULONG) ( (PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) / LogicalBlockSize) ; 00902 } 00903 else 00904 { 00905 // This directory doesn't have any data blocks... 00906 // Allocate a new block... 00907 if( !Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrParentFCB, PtrFileObject, TRUE ) ) 00908 { 00909 try_return( RC = FALSE ); 00910 } 00911 else 00912 { 00913 // Bring in the newly allocated block to the cache... 00914 VolumeByteOffset.QuadPart = 0; 00915 00916 if( !CcPreparePinWrite( 00917 PtrFileObject, 00918 &VolumeByteOffset, 00919 LogicalBlockSize, 00920 TRUE, // Zero out the block... 00921 TRUE, // Can Wait... 00922 &PtrLastBlockBCB, 00923 (PVOID*)&PtrLastBlock ) ) 00924 { 00925 try_return( RC = FALSE ); 00926 } 00927 00928 DirEntry.rec_len = (USHORT)LogicalBlockSize; 00929 RtlCopyBytes( PtrLastBlock, &DirEntry, NewEntryLength); 00930 CcSetDirtyPinnedData( PtrLastBlockBCB, NULL ); 00931 Ext2SaveBCB( PtrIrpContext, PtrLastBlockBCB, PtrFileObject ); 00932 try_return( RC = TRUE ); 00933 } 00934 } 00935 00936 VolumeByteOffset.QuadPart = BlockNo * LogicalBlockSize; 00937 CcMapData( PtrFileObject, 00938 &VolumeByteOffset, 00939 LogicalBlockSize, 00940 TRUE, 00941 &PtrLastBlockBCB, 00942 (PVOID*)&PtrLastBlock ); 00943 00944 for( i = 0 ; i < LogicalBlockSize; ) 00945 { 00946 PtrTempDirEntry = (PEXT2_DIR_ENTRY) &PtrLastBlock[ i ]; 00947 00948 MinLength = HeaderLength + NameLength; 00949 MinLength = ( HeaderLength + NameLength + 3 ) & 0xfffffffc; 00950 00951 00952 if( PtrTempDirEntry->rec_len == 0 ) 00953 { 00954 if( i == 0 ) 00955 { 00956 // Must be an empty Block... 00957 // Insert here... 00958 // ---------------->>> 00959 00960 CcPinMappedData( PtrFileObject, 00961 &VolumeByteOffset, 00962 LogicalBlockSize, 00963 TRUE, 00964 &PtrLastBlockBCB ); 00965 00966 DirEntry.rec_len = (USHORT)LogicalBlockSize; 00967 00968 RtlCopyBytes( PtrLastBlock, &DirEntry, NewEntryLength); 00969 CcSetDirtyPinnedData( PtrLastBlockBCB, NULL ); 00970 Ext2SaveBCB( PtrIrpContext, PtrLastBlockBCB, PtrFileObject ); 00971 try_return( RC = TRUE ); 00972 } 00973 else 00974 { 00975 // This shouldn't be so... 00976 // Something is wrong... 00977 // Fail this request... 00978 try_return( RC = FALSE ); 00979 } 00980 } 00981 if( ActualLength - MinLength >= NewEntryLength ) 00982 { 00983 // Insert here... 00984 // ----------------> 00985 00986 // Getting ready for updation... 00987 CcPinMappedData( PtrFileObject, 00988 &VolumeByteOffset, 00989 LogicalBlockSize, 00990 TRUE, 00991 &PtrLastBlockBCB ); 00992 00993 00994 DirEntry.rec_len = ActualLength - MinLength; 00995 00996 // Updating the current last entry 00997 PtrTempDirEntry->rec_len = MinLength; 00998 i += PtrTempDirEntry->rec_len; 00999 01000 // Making the new entry... 01001 RtlCopyBytes( (PtrLastBlock + i) , &DirEntry, NewEntryLength); 01002 CcSetDirtyPinnedData( PtrLastBlockBCB, NULL ); 01003 Ext2SaveBCB( PtrIrpContext, PtrLastBlockBCB, PtrFileObject ); 01004 try_return( RC = TRUE ); 01005 01006 } 01007 i += PtrTempDirEntry->rec_len; 01008 } 01009 01010 // Will have to allocate a new block... 01011 // Old block does not have enough space.. 01012 if( !Ext2AddBlockToFile( PtrIrpContext, PtrVCB, PtrParentFCB, PtrFileObject, TRUE ) ) 01013 { 01014 try_return( RC = FALSE ); 01015 } 01016 else 01017 { 01018 // unpin the previously pinned block 01019 CcUnpinData( PtrLastBlockBCB ); 01020 PtrLastBlockBCB = NULL; 01021 01022 // Bring in the newly allocated block to the cache... 01023 VolumeByteOffset.QuadPart += LogicalBlockSize; 01024 if( !CcPreparePinWrite( 01025 PtrFileObject, 01026 &VolumeByteOffset, 01027 LogicalBlockSize, 01028 TRUE, // Zero out the block... 01029 TRUE, // Can Wait... 01030 &PtrLastBlockBCB, 01031 (PVOID*)&PtrLastBlock ) ) 01032 { 01033 try_return( RC = FALSE ); 01034 } 01035 01036 DirEntry.rec_len = (USHORT)LogicalBlockSize; 01037 RtlCopyBytes( PtrLastBlock, &DirEntry, NewEntryLength); 01038 CcSetDirtyPinnedData( PtrLastBlockBCB, NULL ); 01039 Ext2SaveBCB( PtrIrpContext, PtrLastBlockBCB, PtrFileObject ); 01040 try_return( RC = TRUE ); 01041 } 01042 try_exit: NOTHING; 01043 } 01044 finally 01045 { 01046 if( PtrLastBlockBCB ) 01047 { 01048 CcUnpinData( PtrLastBlockBCB ); 01049 PtrLastBlockBCB = NULL; 01050 } 01051 } 01052 if( RC == FALSE ) 01053 { 01054 DebugTrace( DEBUG_TRACE_ERROR, "Failed to making directory entry: %S", PtrName->Buffer ); 01055 } 01056 return RC; 01057 } 01058 01059 01060 BOOLEAN NTAPI Ext2FreeDirectoryEntry( 01061 PtrExt2IrpContext PtrIrpContext, 01062 PtrExt2FCB PtrParentFCB, 01063 PUNICODE_STRING PtrName) 01064 { 01065 01066 PBCB PtrDataBlockBCB = NULL; 01067 BYTE * PtrDataBlock = NULL; 01068 PFILE_OBJECT PtrFileObject = NULL; 01069 LONGLONG ByteOffset = 0; 01070 PtrExt2VCB PtrVCB; 01071 LARGE_INTEGER VolumeByteOffset; 01072 unsigned long LogicalBlockSize = 0; 01073 BOOLEAN RC = FALSE; 01074 01075 01076 try 01077 { 01078 DebugTrace( DEBUG_TRACE_SPECIAL, "Freeing directory entry: %S", PtrName->Buffer ); 01079 01080 PtrVCB = PtrParentFCB->PtrVCB; 01081 AssertVCB( PtrVCB); 01082 01083 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 01084 01085 PtrFileObject = PtrParentFCB->DcbFcb.Dcb.PtrDirFileObject; 01086 if( PtrFileObject == NULL ) 01087 { 01088 return FALSE; 01089 } 01090 01091 01092 // 01093 // 1. Read the block in the directory... 01094 // Initiate Caching... 01095 if ( PtrFileObject->PrivateCacheMap == NULL ) 01096 { 01097 CcInitializeCacheMap( 01098 PtrFileObject, 01099 (PCC_FILE_SIZES)(&(PtrParentFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)), 01100 TRUE, // We utilize pin access for directories 01101 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks 01102 PtrParentFCB ); // The context used in callbacks 01103 } 01104 01105 for( ByteOffset = 0; 01106 ByteOffset < PtrParentFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart; 01107 ByteOffset += LogicalBlockSize ) 01108 { 01109 ULONG Index = 0; 01110 PEXT2_DIR_ENTRY PtrDirEntry = NULL; 01111 01112 01113 VolumeByteOffset.QuadPart = ByteOffset; 01114 01115 CcPinRead( PtrFileObject, 01116 &VolumeByteOffset, 01117 LogicalBlockSize, 01118 TRUE, 01119 &PtrDataBlockBCB, 01120 (PVOID*)&PtrDataBlock ); 01121 while( Index < LogicalBlockSize ) 01122 { 01123 ULONG i; 01124 // Parse... 01125 PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrDataBlock[ Index ]; 01126 Index += PtrDirEntry->rec_len; 01127 01128 if( PtrDirEntry->inode == 0 ) 01129 { 01130 // This is a deleted entry... 01131 continue; 01132 } 01133 if( ( PtrName->Length/2 ) != PtrDirEntry->name_len ) 01134 continue; 01135 for( i = 0; ; i++ ) 01136 { 01137 if( PtrDirEntry->name_len == i ) 01138 { 01139 // Remove the entry by setting the inode no to zero 01140 PtrDirEntry->inode = 0; 01141 01142 // Update the disk 01143 CcSetDirtyPinnedData( PtrDataBlockBCB , NULL ); 01144 Ext2SaveBCB( PtrIrpContext, PtrDataBlockBCB, PtrFileObject ); 01145 CcUnpinData( PtrDataBlockBCB ); 01146 PtrDataBlockBCB = NULL; 01147 01148 // Return to caller... 01149 try_return( RC = TRUE ); 01150 } 01151 if( PtrName->Buffer[i] != PtrDirEntry->name[i] ) 01152 { 01153 break; 01154 } 01155 } 01156 } 01157 CcUnpinData( PtrDataBlockBCB ); 01158 PtrDataBlockBCB = NULL; 01159 } 01160 try_return( RC = FALSE ); 01161 01162 try_exit: NOTHING; 01163 } 01164 finally 01165 { 01166 if( PtrDataBlockBCB ) 01167 { 01168 CcUnpinData( PtrDataBlockBCB ); 01169 PtrDataBlockBCB = NULL; 01170 } 01171 } 01172 return RC; 01173 } 01174 01175 /************************************************************************* 01176 * 01177 * Function: Ext2AddBlockToFile() 01178 * 01179 * Description: 01180 * The functions will add a block to a file... 01181 * It will update the allocation size but not the file size... 01182 * 01183 * Expected Interrupt Level (for execution) : 01184 * IRQL_PASSIVE_LEVEL 01185 * 01186 * 01187 * Return Value: Success / Failure... 01188 * 01189 *************************************************************************/ 01190 BOOLEAN NTAPI Ext2AddBlockToFile( 01191 PtrExt2IrpContext PtrIrpContext, 01192 PtrExt2VCB PtrVCB, 01193 PtrExt2FCB PtrFCB, 01194 PFILE_OBJECT PtrFileObject, 01195 BOOLEAN UpdateFileSize) 01196 { 01197 BOOLEAN RC = TRUE; 01198 01199 ULONG NewBlockNo = 0; 01200 LARGE_INTEGER VolumeByteOffset; 01201 ULONG LogicalBlockSize = 0; 01202 ULONG NoOfBlocks = 0; 01203 EXT2_INODE Inode; 01204 01205 ULONG DirectBlocks = 0; 01206 ULONG SingleIndirectBlocks = 0; 01207 ULONG DoubleIndirectBlocks = 0; 01208 ULONG TripleIndirectBlocks = 0; 01209 01210 ULONG *PtrSIBBuffer = NULL; 01211 PBCB PtrSIBBCB = NULL; 01212 ULONG *PtrDIBBuffer = NULL; 01213 PBCB PtrDIBBCB = NULL; 01214 01215 01216 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 01217 DirectBlocks = EXT2_NDIR_BLOCKS ; 01218 SingleIndirectBlocks = LogicalBlockSize / sizeof( ULONG ); 01219 DoubleIndirectBlocks = SingleIndirectBlocks * LogicalBlockSize / sizeof( ULONG ); 01220 TripleIndirectBlocks = DoubleIndirectBlocks * LogicalBlockSize / sizeof( ULONG ); 01221 01222 try 01223 { 01224 if( PtrFCB && PtrFCB->FCBName->ObjectName.Length ) 01225 { 01226 DebugTrace( DEBUG_TRACE_SPECIAL, "Adding Blocks to file %S", PtrFCB->FCBName->ObjectName.Buffer ); 01227 } 01228 01229 Ext2InitializeFCBInodeInfo( PtrFCB ); 01230 01231 // Allocate a block... 01232 NewBlockNo = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01233 01234 if( NewBlockNo == 0 ) 01235 { 01236 try_return (RC = FALSE ); 01237 } 01238 01239 // No of blocks CURRENTLY allocated... 01240 NoOfBlocks = (ULONG) PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart / LogicalBlockSize; 01241 01242 01243 if( NoOfBlocks < EXT2_NDIR_BLOCKS ) 01244 { 01245 // 01246 // A direct data block will do... 01247 // 01248 01249 PtrFCB->IBlock[ NoOfBlocks ] = NewBlockNo; 01250 01251 // Update the inode... 01252 Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ); 01253 Inode.i_block[ NoOfBlocks ] = NewBlockNo; 01254 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01255 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize; 01256 if( UpdateFileSize ) 01257 { 01258 Inode.i_size += LogicalBlockSize; 01259 PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize; 01260 } 01261 01262 01263 if( PtrFileObject->PrivateCacheMap != NULL) 01264 { 01265 // 01266 // Caching has been initiated... 01267 // Let the Cache manager in on these changes... 01268 // 01269 CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)); 01270 } 01271 01272 01273 // Updating the inode... 01274 if( NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 01275 { 01276 try_return (RC = TRUE); 01277 } 01278 else 01279 { 01280 try_return (RC = FALSE ); 01281 } 01282 01283 } 01284 else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks) ) 01285 { 01286 // 01287 // A single indirect data block will do... 01288 Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ); 01289 01290 if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] == 0 ) 01291 { 01292 // A Single Indirect block should be allocated as well!! 01293 PtrFCB->IBlock[ EXT2_IND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01294 if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] == 0 ) 01295 { 01296 try_return (RC = FALSE ); 01297 } 01298 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01299 01300 // Bring in the new block to the cache 01301 // Zero it out 01302 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize; 01303 01304 if( !CcPreparePinWrite( 01305 PtrVCB->PtrStreamFileObject, 01306 &VolumeByteOffset, 01307 LogicalBlockSize, 01308 TRUE, // Zero out the block... 01309 TRUE, // Can Wait... 01310 &PtrSIBBCB, 01311 (PVOID*)&PtrSIBBuffer ) ) 01312 { 01313 try_return( RC = FALSE ); 01314 } 01315 } 01316 else 01317 { 01318 // Just bring in the SIB to the cache 01319 01320 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize; 01321 01322 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01323 &VolumeByteOffset, 01324 LogicalBlockSize, 01325 TRUE, // Can Wait... 01326 &PtrSIBBCB, 01327 (PVOID*)&PtrSIBBuffer ) ) 01328 { 01329 try_return( RC = FALSE ); 01330 } 01331 } 01332 01333 // Update the inode... 01334 01335 Inode.i_block[ EXT2_IND_BLOCK ] = PtrFCB->IBlock[ EXT2_IND_BLOCK ]; 01336 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01337 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize; 01338 if( UpdateFileSize ) 01339 { 01340 Inode.i_size += LogicalBlockSize; 01341 PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize; 01342 } 01343 if( PtrFileObject->PrivateCacheMap != NULL) 01344 { 01345 // 01346 // Caching has been initiated... 01347 // Let the Cache manager in on these changes... 01348 // 01349 CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)); 01350 } 01351 01352 if( !NT_SUCCESS( Ext2WriteInode( 01353 PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 01354 { 01355 try_return (RC = FALSE ); 01356 } 01357 01358 01359 // Update the SIB... 01360 PtrSIBBuffer[ NoOfBlocks - DirectBlocks ] = NewBlockNo; 01361 CcSetDirtyPinnedData( PtrSIBBCB, NULL ); 01362 Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject ); 01363 01364 try_return (RC = TRUE); 01365 01366 } 01367 else if( NoOfBlocks < (DirectBlocks + SingleIndirectBlocks + DoubleIndirectBlocks ) ) 01368 { 01369 // 01370 // A double indirect block will do... 01371 // 01372 ULONG SBlockNo; 01373 ULONG BlockNo; 01374 01375 Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ); 01376 01377 if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 ) 01378 { 01379 // A double indirect pointer block should be allocated as well!! 01380 PtrFCB->IBlock[ EXT2_DIND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01381 if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 ) 01382 { 01383 try_return (RC = FALSE ); 01384 } 01385 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01386 01387 // Bring in the new block to the cache 01388 // Zero it out 01389 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize; 01390 01391 if( !CcPreparePinWrite( 01392 PtrVCB->PtrStreamFileObject, 01393 &VolumeByteOffset, 01394 LogicalBlockSize, 01395 TRUE, // Zero out the block... 01396 TRUE, // Can Wait... 01397 &PtrDIBBCB, 01398 (PVOID*)&PtrDIBBuffer ) ) 01399 { 01400 try_return( RC = FALSE ); 01401 } 01402 } 01403 else 01404 { 01405 // Just bring in the DIB to the cache 01406 01407 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize; 01408 01409 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01410 &VolumeByteOffset, 01411 LogicalBlockSize, 01412 TRUE, // Can Wait... 01413 &PtrDIBBCB, 01414 (PVOID*)&PtrDIBBuffer ) ) 01415 { 01416 try_return( RC = FALSE ); 01417 } 01418 } 01419 01420 // See if a single indirect 'pointer' block 01421 // should also be allocated... 01422 BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks ); 01423 SBlockNo = BlockNo / SingleIndirectBlocks; 01424 if( BlockNo % SingleIndirectBlocks ) 01425 { 01426 // A single indirect 'pointer' block 01427 // should also be allocated... 01428 PtrDIBBuffer[SBlockNo] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01429 CcSetDirtyPinnedData( PtrDIBBCB, NULL ); 01430 VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize; 01431 01432 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01433 01434 if( !CcPreparePinWrite( 01435 PtrVCB->PtrStreamFileObject, 01436 &VolumeByteOffset, 01437 LogicalBlockSize, 01438 TRUE, // Zero out the block... 01439 TRUE, // Can Wait... 01440 &PtrSIBBCB, 01441 (PVOID*)&PtrSIBBuffer ) ) 01442 { 01443 try_return( RC = FALSE ); 01444 } 01445 } 01446 else 01447 { 01448 VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize; 01449 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01450 &VolumeByteOffset, 01451 LogicalBlockSize, 01452 TRUE, // Can Wait... 01453 &PtrSIBBCB, 01454 (PVOID*)&PtrSIBBuffer ) ) 01455 { 01456 try_return( RC = FALSE ); 01457 } 01458 } 01459 BlockNo = BlockNo % SingleIndirectBlocks; 01460 01461 // Update the inode... 01462 01463 Inode.i_block[ EXT2_DIND_BLOCK ] = PtrFCB->IBlock[ EXT2_DIND_BLOCK ]; 01464 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01465 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize; 01466 if( UpdateFileSize ) 01467 { 01468 Inode.i_size += LogicalBlockSize; 01469 PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize; 01470 } 01471 if( PtrFileObject->PrivateCacheMap != NULL) 01472 { 01473 // 01474 // Caching has been initiated... 01475 // Let the Cache manager in on these changes... 01476 // 01477 CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)); 01478 } 01479 01480 if( !NT_SUCCESS( Ext2WriteInode( 01481 PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 01482 { 01483 try_return (RC = FALSE ); 01484 } 01485 01486 01487 // Update the SIB... 01488 PtrSIBBuffer[ BlockNo ] = NewBlockNo; 01489 CcSetDirtyPinnedData( PtrSIBBCB, NULL ); 01490 Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject ); 01491 Ext2SaveBCB( PtrIrpContext, PtrDIBBCB, PtrVCB->PtrStreamFileObject ); 01492 01493 try_return (RC = TRUE); 01494 01495 } 01496 else 01497 { 01498 // 01499 // A Triple Indirect block is required 01500 // 01501 ULONG SBlockNo; 01502 ULONG BlockNo; 01503 01504 // This is not supported as yet... 01505 try_return (RC = FALSE); 01506 01507 Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ); 01508 01509 if( PtrFCB->IBlock[ EXT2_TIND_BLOCK ] == 0 ) 01510 { 01511 // A double indirect pointer block should be allocated as well!! 01512 PtrFCB->IBlock[ EXT2_DIND_BLOCK ] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01513 if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] == 0 ) 01514 { 01515 try_return (RC = FALSE ); 01516 } 01517 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01518 01519 // Bring in the new block to the cache 01520 // Zero it out 01521 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize; 01522 01523 if( !CcPreparePinWrite( 01524 PtrVCB->PtrStreamFileObject, 01525 &VolumeByteOffset, 01526 LogicalBlockSize, 01527 TRUE, // Zero out the block... 01528 TRUE, // Can Wait... 01529 &PtrDIBBCB, 01530 (PVOID*)&PtrDIBBuffer ) ) 01531 { 01532 try_return( RC = FALSE ); 01533 } 01534 } 01535 else 01536 { 01537 // Just bring in the DIB to the cache 01538 01539 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize; 01540 01541 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01542 &VolumeByteOffset, 01543 LogicalBlockSize, 01544 TRUE, // Can Wait... 01545 &PtrDIBBCB, 01546 (PVOID*)&PtrDIBBuffer ) ) 01547 { 01548 try_return( RC = FALSE ); 01549 } 01550 } 01551 01552 // See if a single indirect 'pointer' block 01553 // should also be allocated... 01554 BlockNo = ( NoOfBlocks - DirectBlocks - SingleIndirectBlocks ); 01555 SBlockNo = BlockNo / SingleIndirectBlocks; 01556 if( BlockNo % SingleIndirectBlocks ) 01557 { 01558 // A single indirect 'pointer' block 01559 // should also be allocated... 01560 PtrDIBBuffer[SBlockNo] = Ext2AllocBlock( PtrIrpContext, PtrVCB, 1 ); 01561 CcSetDirtyPinnedData( PtrDIBBCB, NULL ); 01562 VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize; 01563 01564 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01565 01566 if( !CcPreparePinWrite( 01567 PtrVCB->PtrStreamFileObject, 01568 &VolumeByteOffset, 01569 LogicalBlockSize, 01570 TRUE, // Zero out the block... 01571 TRUE, // Can Wait... 01572 &PtrSIBBCB, 01573 (PVOID*)&PtrSIBBuffer ) ) 01574 { 01575 try_return( RC = FALSE ); 01576 } 01577 } 01578 else 01579 { 01580 VolumeByteOffset.QuadPart = PtrDIBBuffer[SBlockNo] * LogicalBlockSize; 01581 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01582 &VolumeByteOffset, 01583 LogicalBlockSize, 01584 TRUE, // Can Wait... 01585 &PtrSIBBCB, 01586 (PVOID*)&PtrSIBBuffer ) ) 01587 { 01588 try_return( RC = FALSE ); 01589 } 01590 } 01591 BlockNo = BlockNo % SingleIndirectBlocks; 01592 01593 // Update the inode... 01594 01595 Inode.i_block[ EXT2_DIND_BLOCK ] = PtrFCB->IBlock[ EXT2_DIND_BLOCK ]; 01596 Inode.i_blocks += ( LogicalBlockSize / 512 ); 01597 PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize.QuadPart += LogicalBlockSize; 01598 if( UpdateFileSize ) 01599 { 01600 Inode.i_size += LogicalBlockSize; 01601 PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart += LogicalBlockSize; 01602 } 01603 if( PtrFileObject->PrivateCacheMap != NULL) 01604 { 01605 // 01606 // Caching has been initiated... 01607 // Let the Cache manager in on these changes... 01608 // 01609 CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)); 01610 } 01611 01612 if( !NT_SUCCESS( Ext2WriteInode( 01613 PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 01614 { 01615 try_return (RC = FALSE ); 01616 } 01617 01618 01619 // Update the SIB... 01620 PtrSIBBuffer[ BlockNo ] = NewBlockNo; 01621 CcSetDirtyPinnedData( PtrSIBBCB, NULL ); 01622 Ext2SaveBCB( PtrIrpContext, PtrSIBBCB, PtrVCB->PtrStreamFileObject ); 01623 Ext2SaveBCB( PtrIrpContext, PtrDIBBCB, PtrVCB->PtrStreamFileObject ); 01624 01625 try_return (RC = TRUE); 01626 01627 } 01628 01629 try_exit: NOTHING; 01630 } 01631 finally 01632 { 01633 if( PtrSIBBCB ) 01634 { 01635 CcUnpinData( PtrSIBBCB ); 01636 PtrSIBBCB = NULL; 01637 } 01638 if( PtrDIBBCB ) 01639 { 01640 CcUnpinData( PtrDIBBCB ); 01641 PtrDIBBCB = NULL; 01642 } 01643 } 01644 return RC; 01645 } 01646 01647 /************************************************************************* 01648 * 01649 * Function: Ext2AllocBlock() 01650 * 01651 * Description: 01652 * The functions will allocate a new block 01653 * 01654 * Expected Interrupt Level (for execution) : 01655 * IRQL_PASSIVE_LEVEL 01656 * 01657 * 01658 * Return Value: Success / Failure... 01659 * 01660 *************************************************************************/ 01661 ULONG NTAPI Ext2AllocBlock( 01662 PtrExt2IrpContext PtrIrpContext, 01663 PtrExt2VCB PtrVCB, 01664 ULONG Count) 01665 { 01666 // Buffer Control Block 01667 PBCB PtrBitmapBCB = NULL; 01668 BYTE * PtrBitmapBuffer = NULL; 01669 ULONG BlockNo = 0; 01670 LARGE_INTEGER VolumeByteOffset; 01671 ULONG LogicalBlockSize = 0; 01672 ULONG NumberOfBytesToRead = 0; 01673 01674 if( PtrVCB->FreeBlocksCount == 0 ) 01675 { 01676 // 01677 // No Free Block left... 01678 // Fail request... 01679 // 01680 return 0; 01681 } 01682 01683 try 01684 { 01685 BOOLEAN Found = FALSE; 01686 ULONG Block; 01687 ULONG GroupNo; 01688 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 01689 01690 for( GroupNo = 0; PtrVCB->NoOfGroups; GroupNo++ ) 01691 { 01692 if( PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeBlocksCount ) 01693 break; 01694 } 01695 01696 VolumeByteOffset.QuadPart = 01697 PtrVCB->PtrGroupDescriptors[ GroupNo ].BlockBitmapBlock * LogicalBlockSize; 01698 01699 NumberOfBytesToRead = PtrVCB->BlocksCount / PtrVCB->NoOfGroups; 01700 01701 if( NumberOfBytesToRead % 8 ) 01702 { 01703 NumberOfBytesToRead = ( NumberOfBytesToRead / 8 ) + 1; 01704 } 01705 else 01706 { 01707 NumberOfBytesToRead = ( NumberOfBytesToRead / 8 ) ; 01708 } 01709 01710 01711 for( Block = 0; !Found && Block < Ext2Align( NumberOfBytesToRead , LogicalBlockSize ); 01712 Block += LogicalBlockSize, VolumeByteOffset.QuadPart += LogicalBlockSize) 01713 { 01714 // 01715 // Read in the block bitmap block... 01716 ULONG i, j; 01717 BYTE Bitmap; 01718 01719 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01720 &VolumeByteOffset, 01721 LogicalBlockSize, // NumberOfBytesToRead, 01722 TRUE, 01723 &PtrBitmapBCB, 01724 (PVOID*)&PtrBitmapBuffer ) ) 01725 { 01726 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 01727 try_return( BlockNo = 0 ); 01728 } 01729 01730 // 01731 // Is there a free block... 01732 // 01733 for( i = 0; !Found && i < LogicalBlockSize && 01734 i + (Block * LogicalBlockSize) < NumberOfBytesToRead; i++ ) 01735 { 01736 Bitmap = PtrBitmapBuffer[i]; 01737 if( Bitmap != 0xff ) 01738 { 01739 // 01740 // Found a free block... 01741 for( j = 0; !Found && j < 8; j++ ) 01742 { 01743 if( ( Bitmap & 0x01 ) == 0 ) 01744 { 01745 // 01746 // Found... 01747 Found = TRUE; 01748 BlockNo = ( ( ( Block * LogicalBlockSize) + i ) * 8) + j + 1 01749 + ( GroupNo * PtrVCB->BlocksPerGroup ); 01750 01751 Bitmap = 1 << j; 01752 PtrBitmapBuffer[i] |= Bitmap; 01753 01754 CcSetDirtyPinnedData( PtrBitmapBCB, NULL ); 01755 Ext2SaveBCB( PtrIrpContext, PtrBitmapBCB, PtrVCB->PtrStreamFileObject ); 01756 // 01757 // Should update the bitmaps in the other groups too... 01758 // 01759 break; 01760 } 01761 Bitmap = Bitmap >> 1; 01762 } 01763 } 01764 } 01765 // 01766 // Unpin the BCB... 01767 // 01768 if( PtrBitmapBCB ) 01769 { 01770 CcUnpinData( PtrBitmapBCB ); 01771 PtrBitmapBCB = NULL; 01772 } 01773 01774 } 01775 01776 // 01777 // Updating the Free Block count in the Group Descriptor... 01778 // 01779 01780 { 01781 PBCB PtrDescriptorBCB = NULL; 01782 PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL; 01783 // 01784 // Updating the Free Blocks count in the Group Descriptor... 01785 // 01786 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeBlocksCount--; 01787 01788 if( PtrVCB->LogBlockSize ) 01789 { 01790 // First block contains the descriptors... 01791 VolumeByteOffset.QuadPart = LogicalBlockSize; 01792 } 01793 else 01794 { 01795 // Second block contains the descriptors... 01796 VolumeByteOffset.QuadPart = LogicalBlockSize * 2; 01797 } 01798 NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc ); 01799 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 01800 01801 if (!CcPinRead( PtrVCB->PtrStreamFileObject, 01802 &VolumeByteOffset, 01803 NumberOfBytesToRead, 01804 TRUE, 01805 &PtrDescriptorBCB , 01806 (PVOID*)&PtrGroupDescriptor )) 01807 { 01808 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 01809 // 01810 // Ignore this error... 01811 // Not fatal... 01812 } 01813 else 01814 { 01815 PtrGroupDescriptor[ GroupNo ].bg_free_blocks_count= 01816 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeBlocksCount; 01817 01818 // 01819 // Not synchronously flushing this information... 01820 // Lazy writing will do... 01821 // 01822 CcSetDirtyPinnedData( PtrDescriptorBCB, NULL ); 01823 CcUnpinData( PtrDescriptorBCB ); 01824 PtrDescriptorBCB = NULL; 01825 } 01826 } 01827 01828 // 01829 // Update the Block count 01830 // in the super block and in the VCB 01831 // 01832 { 01833 // Ext2 Super Block information... 01834 PEXT2_SUPER_BLOCK PtrSuperBlock = NULL; 01835 PBCB PtrSuperBlockBCB = NULL; 01836 01837 PtrVCB->FreeBlocksCount--; 01838 01839 // Reading in the super block... 01840 VolumeByteOffset.QuadPart = 1024; 01841 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize ); 01842 01843 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01844 &VolumeByteOffset, 01845 NumberOfBytesToRead, 01846 TRUE, 01847 &PtrSuperBlockBCB, 01848 (PVOID*)&PtrSuperBlock ) ) 01849 { 01850 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 01851 } 01852 else 01853 { 01854 PtrSuperBlock->s_free_blocks_count = PtrVCB->FreeBlocksCount; 01855 CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL ); 01856 Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject ); 01857 if( PtrSuperBlockBCB ) 01858 { 01859 CcUnpinData( PtrSuperBlockBCB ); 01860 PtrSuperBlockBCB = NULL; 01861 } 01862 } 01863 } 01864 01865 try_exit: NOTHING; 01866 } 01867 finally 01868 { 01869 if( PtrBitmapBCB ) 01870 { 01871 CcUnpinData( PtrBitmapBCB ); 01872 PtrBitmapBCB = NULL; 01873 } 01874 DebugTrace( DEBUG_TRACE_SPECIAL, " Allocating a block - Block no : %ld", BlockNo ); 01875 } 01876 return BlockNo; 01877 } 01878 01879 /************************************************************************* 01880 * 01881 * Function: Ext2DeallocBlock() 01882 * 01883 * Description: 01884 * The functions will deallocate a data block 01885 * 01886 * Expected Interrupt Level (for execution) : 01887 * IRQL_PASSIVE_LEVEL 01888 * 01889 * Return Value: Success / Failure... 01890 * 01891 *************************************************************************/ 01892 BOOLEAN NTAPI Ext2DeallocBlock( 01893 PtrExt2IrpContext PtrIrpContext, 01894 PtrExt2VCB PtrVCB, 01895 ULONG BlockNo ) 01896 { 01897 // Buffer Control Block 01898 PBCB PtrBitmapBCB = NULL; 01899 BYTE * PtrBitmapBuffer = NULL; 01900 BOOLEAN RC = TRUE; 01901 LARGE_INTEGER VolumeByteOffset; 01902 ULONG LogicalBlockSize = 0; 01903 // ULONG NumberOfBytesToRead = 0; 01904 01905 DebugTrace( DEBUG_TRACE_SPECIAL, " Deallocating a block - Block no : %ld", BlockNo ); 01906 01907 try 01908 { 01909 ULONG GroupNo; 01910 ULONG BlockIndex; 01911 ULONG BitmapIndex; 01912 BYTE Bitmap; 01913 01914 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 01915 01916 GroupNo = BlockNo / PtrVCB->BlocksPerGroup; 01917 BlockNo = BlockNo % PtrVCB->BlocksPerGroup; 01918 01919 Bitmap = 1 << ( (BlockNo-1) % 8 ); 01920 BitmapIndex = (BlockNo-1) / 8; 01921 BlockIndex = BitmapIndex / LogicalBlockSize; 01922 // Adjusting to index into the Logical block that contains the bitmap 01923 BitmapIndex = BitmapIndex - ( BlockIndex * LogicalBlockSize ); 01924 01925 VolumeByteOffset.QuadPart = 01926 ( PtrVCB->PtrGroupDescriptors[ GroupNo ].BlockBitmapBlock + BlockIndex ) 01927 * LogicalBlockSize; 01928 01929 // 01930 // Read in the bitmap block... 01931 // 01932 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 01933 &VolumeByteOffset, 01934 LogicalBlockSize, 01935 TRUE, // Can Wait... 01936 &PtrBitmapBCB, 01937 (PVOID*)&PtrBitmapBuffer ) ) 01938 { 01939 // Unable to Pin the data into the cache... 01940 try_return (RC = FALSE); 01941 } 01942 01943 // 01944 // Locate the block 'bit'... 01945 // This block 'bit' is in the byte PtrBitmapBuffer[ BitmapIndex ] 01946 if( ( PtrBitmapBuffer[ BitmapIndex ] & Bitmap ) == 0) 01947 { 01948 // This shouldn't have been so... 01949 // The block was never allocated! 01950 // How to deallocate something that hasn't been allocated? 01951 // Hmmm... ;) 01952 // Ignore this error... 01953 try_return (RC = TRUE); 01954 } 01955 01956 // Setting the bit for the inode... 01957 PtrBitmapBuffer[ BitmapIndex ] &= (~Bitmap); 01958 01959 // Update the cache... 01960 CcSetDirtyPinnedData( PtrBitmapBCB, NULL ); 01961 01962 // Save up the BCB for forcing a synchronous write... 01963 // Before completing the IRP... 01964 Ext2SaveBCB( PtrIrpContext, PtrBitmapBCB, PtrVCB->PtrStreamFileObject ); 01965 01966 01967 if( PtrBitmapBCB ) 01968 { 01969 CcUnpinData( PtrBitmapBCB ); 01970 PtrBitmapBCB = NULL; 01971 } 01972 01973 // 01974 // Updating the Block count in the Group Descriptor... 01975 // 01976 01977 { 01978 PBCB PtrDescriptorBCB = NULL; 01979 PEXT2_GROUP_DESCRIPTOR PtrGroupDescriptor = NULL; 01980 ULONG NumberOfBytesToRead = 0; 01981 // 01982 // Updating the Free Blocks count in the Group Descriptor... 01983 // 01984 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeBlocksCount++; 01985 01986 if( PtrVCB->LogBlockSize ) 01987 { 01988 // First block contains the descriptors... 01989 VolumeByteOffset.QuadPart = LogicalBlockSize; 01990 } 01991 else 01992 { 01993 // Second block contains the descriptors... 01994 VolumeByteOffset.QuadPart = LogicalBlockSize * 2; 01995 } 01996 NumberOfBytesToRead = PtrVCB->NoOfGroups * sizeof( struct ext2_group_desc ); 01997 NumberOfBytesToRead = Ext2Align( NumberOfBytesToRead, LogicalBlockSize ); 01998 01999 if (!CcPinRead( PtrVCB->PtrStreamFileObject, 02000 &VolumeByteOffset, 02001 NumberOfBytesToRead, 02002 TRUE, 02003 &PtrDescriptorBCB , 02004 (PVOID*)&PtrGroupDescriptor )) 02005 { 02006 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 02007 // 02008 // Ignore this error... 02009 // Not fatal... 02010 } 02011 else 02012 { 02013 PtrGroupDescriptor[ GroupNo ].bg_free_blocks_count= 02014 PtrVCB->PtrGroupDescriptors[ GroupNo ].FreeBlocksCount; 02015 02016 // 02017 // Not synchronously flushing this information... 02018 // Lazy writing will do... 02019 // 02020 CcSetDirtyPinnedData( PtrDescriptorBCB, NULL ); 02021 CcUnpinData( PtrDescriptorBCB ); 02022 PtrDescriptorBCB = NULL; 02023 } 02024 } 02025 02026 // 02027 // Update the Block count 02028 // in the super block and in the VCB 02029 // 02030 { 02031 // Ext2 Super Block information... 02032 PEXT2_SUPER_BLOCK PtrSuperBlock = NULL; 02033 PBCB PtrSuperBlockBCB = NULL; 02034 ULONG NumberOfBytesToRead = 0; 02035 02036 PtrVCB->FreeBlocksCount++; 02037 02038 // Reading in the super block... 02039 VolumeByteOffset.QuadPart = 1024; 02040 NumberOfBytesToRead = Ext2Align( sizeof( EXT2_SUPER_BLOCK ), LogicalBlockSize ); 02041 02042 if( !CcPinRead( PtrVCB->PtrStreamFileObject, 02043 &VolumeByteOffset, 02044 NumberOfBytesToRead, 02045 TRUE, 02046 &PtrSuperBlockBCB, 02047 (PVOID*)&PtrSuperBlock ) ) 02048 { 02049 DebugTrace(DEBUG_TRACE_ERROR, "Cache read failiure while reading in volume meta data", 0); 02050 } 02051 else 02052 { 02053 PtrSuperBlock->s_free_blocks_count = PtrVCB->FreeBlocksCount; 02054 CcSetDirtyPinnedData( PtrSuperBlockBCB, NULL ); 02055 Ext2SaveBCB( PtrIrpContext, PtrSuperBlockBCB, PtrVCB->PtrStreamFileObject ); 02056 CcUnpinData( PtrSuperBlockBCB ); 02057 PtrSuperBlockBCB = NULL; 02058 } 02059 } 02060 try_exit: NOTHING; 02061 } 02062 finally 02063 { 02064 if( PtrBitmapBCB ) 02065 { 02066 CcUnpinData( PtrBitmapBCB ); 02067 PtrBitmapBCB = NULL; 02068 } 02069 } 02070 return RC; 02071 } 02072 02073 BOOLEAN NTAPI Ext2UpdateFileSize( 02074 PtrExt2IrpContext PtrIrpContext, 02075 PFILE_OBJECT PtrFileObject, 02076 PtrExt2FCB PtrFCB) 02077 { 02078 EXT2_INODE Inode; 02079 PtrExt2VCB PtrVCB = PtrFCB->PtrVCB; 02080 02081 if( PtrFileObject->PrivateCacheMap ) 02082 { 02083 CcSetFileSizes( PtrFileObject, (PCC_FILE_SIZES)&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)); 02084 } 02085 // Now update the size on the disk... 02086 // Read in the inode... 02087 if( ! NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 02088 { 02089 return FALSE; 02090 } 02091 02092 Inode.i_size = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart; 02093 // Update time also??? 02094 02095 // Updating the inode... 02096 if( NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 02097 { 02098 return TRUE; 02099 } 02100 else 02101 { 02102 return FALSE; 02103 } 02104 } 02105 02106 /************************************************************************* 02107 * 02108 * Function: Ext2DeleteFile() 02109 * 02110 * Description: 02111 * The functions will delete a file 02112 * 02113 * Expected Interrupt Level (for execution) : 02114 * IRQL_PASSIVE_LEVEL 02115 * 02116 * Return Value: Success / Failure... 02117 * 02118 *************************************************************************/ 02119 BOOLEAN NTAPI Ext2DeleteFile( 02120 PtrExt2FCB PtrFCB, 02121 PtrExt2IrpContext PtrIrpContext) 02122 { 02123 EXT2_INODE Inode; 02124 PtrExt2FCB PtrParentFCB = NULL; 02125 PtrExt2VCB PtrVCB = PtrFCB->PtrVCB; 02126 02127 // 02128 // Get the Parent Directory... 02129 PtrParentFCB = Ext2LocateFCBInCore( PtrVCB, PtrFCB->ParentINodeNo ); 02130 Ext2InitializeFCBInodeInfo( PtrFCB ); 02131 02132 // 1. 02133 // Free up the directory entry... 02134 if( !Ext2FreeDirectoryEntry( PtrIrpContext, 02135 PtrParentFCB, &PtrFCB->FCBName->ObjectName ) ) 02136 { 02137 return FALSE; 02138 } 02139 02140 // 2. 02141 // Decrement Link count... 02142 if( !NT_SUCCESS( Ext2ReadInode( PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 02143 { 02144 return FALSE; 02145 } 02146 02147 ASSERT( Inode.i_links_count == PtrFCB->LinkCount ); 02148 02149 Inode.i_links_count--; 02150 PtrFCB->LinkCount = Inode.i_links_count; 02151 02152 if( !Inode.i_links_count ) 02153 { 02154 // 02155 // Setting the deletion time field in the inode... 02156 // 02157 ULONG Time; 02158 Time = Ext2GetCurrentTime(); 02159 Inode.i_dtime = Time ; 02160 } 02161 02162 // 3. 02163 // Updating the inode... 02164 02165 if( NT_SUCCESS( Ext2WriteInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo, &Inode ) ) ) 02166 { 02167 if( Inode.i_links_count ) 02168 { 02169 // Some more links to the same file are available... 02170 // So we won't deallocate the data blocks... 02171 return TRUE; 02172 } 02173 } 02174 else 02175 { 02176 return FALSE; 02177 } 02178 02179 // 4. 02180 // Free up the inode... 02181 Ext2DeallocInode( PtrIrpContext, PtrVCB, PtrFCB->INodeNo ); 02182 02183 // 5. 02184 // Release the data blocks... 02185 Ext2ReleaseDataBlocks( PtrFCB, PtrIrpContext); 02186 02187 return TRUE; 02188 } 02189 02190 02191 /************************************************************************* 02192 * 02193 * Function: Ext2ReleaseDataBlocks() 02194 * 02195 * Description: 02196 * The functions will release all the data blocks in a file 02197 * It does NOT update the file inode... 02198 * 02199 * Expected Interrupt Level (for execution) : 02200 * IRQL_PASSIVE_LEVEL 02201 * 02202 * Return Value: Success / Failure... 02203 * 02204 *************************************************************************/ 02205 BOOLEAN NTAPI Ext2ReleaseDataBlocks( 02206 PtrExt2FCB PtrFCB, 02207 PtrExt2IrpContext PtrIrpContext) 02208 { 02209 PtrExt2VCB PtrVCB = PtrFCB->PtrVCB; 02210 ULONG LogicalBlockSize; 02211 ULONG i; 02212 02213 02214 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 02215 02216 // Release the data blocks... 02217 02218 // 1. 02219 // Free up the triple indirect blocks... 02220 if( PtrFCB->IBlock[ EXT2_TIND_BLOCK ] ) 02221 { 02222 02223 PBCB PtrSIBCB = NULL; 02224 PBCB PtrDIBCB = NULL; 02225 PBCB PtrTIBCB = NULL; 02226 02227 ULONG * PtrPinnedSIndirectBlock = NULL; 02228 ULONG * PtrPinnedDIndirectBlock = NULL; 02229 ULONG * PtrPinnedTIndirectBlock = NULL; 02230 02231 LARGE_INTEGER VolumeByteOffset; 02232 ULONG TIndex, DIndex, SIndex; 02233 02234 // Pin the Double Indirect Pointer Block... 02235 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_TIND_BLOCK ] * LogicalBlockSize; 02236 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02237 &VolumeByteOffset, 02238 LogicalBlockSize, 02239 TRUE, 02240 &PtrTIBCB, 02241 (PVOID*)&PtrPinnedTIndirectBlock )) 02242 { 02243 return FALSE; 02244 } 02245 02246 // Read the Block numbers off the Triple Indirect Pointer Block... 02247 for( TIndex = 0; TIndex < (LogicalBlockSize/sizeof(ULONG)); TIndex++ ) 02248 { 02249 if( PtrPinnedTIndirectBlock[ TIndex ] ) 02250 { 02251 VolumeByteOffset.QuadPart = PtrPinnedTIndirectBlock[TIndex] * LogicalBlockSize; 02252 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02253 &VolumeByteOffset, 02254 LogicalBlockSize, 02255 TRUE, 02256 &PtrDIBCB, 02257 (PVOID*)&PtrPinnedDIndirectBlock )) 02258 { 02259 return FALSE; 02260 } 02261 02262 // Read the Block numbers off the Double Indirect Pointer Blocks... 02263 for( DIndex = 0; DIndex < (LogicalBlockSize/sizeof(ULONG)); DIndex++ ) 02264 { 02265 if( PtrPinnedDIndirectBlock[DIndex] ) 02266 { 02267 VolumeByteOffset.QuadPart = PtrPinnedDIndirectBlock[DIndex] * LogicalBlockSize; 02268 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02269 &VolumeByteOffset, 02270 LogicalBlockSize, 02271 TRUE, 02272 &PtrSIBCB, 02273 (PVOID*)&PtrPinnedSIndirectBlock )) 02274 { 02275 return FALSE; 02276 } 02277 02278 // Read the Block numbers off the Single Indirect Pointer Blocks and 02279 // free the data blocks 02280 for( SIndex = 0; SIndex < (LogicalBlockSize/sizeof(ULONG)); SIndex++ ) 02281 { 02282 if( PtrPinnedSIndirectBlock[ SIndex ] ) 02283 { 02284 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedSIndirectBlock[SIndex] ); 02285 } 02286 else 02287 { 02288 break; 02289 } 02290 } 02291 CcUnpinData( PtrSIBCB ); 02292 02293 // Deallocating 02294 // Single Indirect Pointer Block 02295 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedDIndirectBlock[DIndex] ); 02296 } 02297 else 02298 { 02299 break; 02300 } 02301 } 02302 } 02303 else 02304 { 02305 break; 02306 } 02307 } 02308 CcUnpinData( PtrTIBCB ); 02309 // Deallocating Triple Indirect Pointer Blocks 02310 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ EXT2_TIND_BLOCK ] ); 02311 } 02312 02313 // 2. 02314 // Free up the double indirect blocks... 02315 if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] ) 02316 { 02317 PBCB PtrDIBCB = NULL; 02318 PBCB PtrSIBCB = NULL; 02319 ULONG * PtrPinnedSIndirectBlock = NULL; 02320 ULONG * PtrPinnedDIndirectBlock = NULL; 02321 02322 LARGE_INTEGER VolumeByteOffset; 02323 ULONG DIndex, SIndex; 02324 02325 // Pin the Double Indirect Pointer Block... 02326 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_DIND_BLOCK ] * LogicalBlockSize; 02327 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02328 &VolumeByteOffset, 02329 LogicalBlockSize, 02330 TRUE, 02331 &PtrDIBCB, 02332 (PVOID*)&PtrPinnedDIndirectBlock )) 02333 { 02334 return FALSE; 02335 } 02336 02337 // Read the Block numbers off the Double Indirect Pointer Block... 02338 for( DIndex = 0; DIndex < (LogicalBlockSize/sizeof(ULONG)); DIndex++ ) 02339 { 02340 if( PtrPinnedDIndirectBlock[DIndex] ) 02341 { 02342 VolumeByteOffset.QuadPart = PtrPinnedDIndirectBlock[DIndex] * LogicalBlockSize; 02343 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02344 &VolumeByteOffset, 02345 LogicalBlockSize, 02346 TRUE, 02347 &PtrSIBCB, 02348 (PVOID*)&PtrPinnedSIndirectBlock )) 02349 { 02350 return FALSE; 02351 } 02352 02353 // Read the Block numbers off the Single Indirect Pointer Blocks and 02354 // free the data blocks 02355 for( SIndex = 0; SIndex < (LogicalBlockSize/sizeof(ULONG)); SIndex++ ) 02356 { 02357 if( PtrPinnedSIndirectBlock[ SIndex ] ) 02358 { 02359 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedSIndirectBlock[SIndex] ); 02360 } 02361 else 02362 { 02363 break; 02364 } 02365 } 02366 CcUnpinData( PtrSIBCB ); 02367 02368 // Deallocating 02369 // Single Indirect Pointer Block 02370 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedDIndirectBlock[DIndex] ); 02371 } 02372 else 02373 { 02374 break; 02375 } 02376 } 02377 CcUnpinData( PtrDIBCB ); 02378 // Deallocating Double Indirect Pointer Blocks 02379 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ EXT2_DIND_BLOCK ] ); 02380 } 02381 02382 // 3. 02383 // Free up the single indirect blocks... 02384 if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] ) 02385 { 02386 PBCB PtrBCB = NULL; 02387 ULONG * PtrPinnedSIndirectBlock = NULL; 02388 LARGE_INTEGER VolumeByteOffset; 02389 ULONG Index; 02390 02391 // Pin the Single Indirect Pointer Block... 02392 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize; 02393 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02394 &VolumeByteOffset, 02395 LogicalBlockSize, 02396 TRUE, 02397 &PtrBCB, 02398 (PVOID*)&PtrPinnedSIndirectBlock )) 02399 { 02400 return FALSE; 02401 } 02402 02403 // Read the Block numbers off the Indirect Pointer Block and 02404 // free the data blocks 02405 for( Index = 0; Index < (LogicalBlockSize/sizeof(ULONG)); Index++ ) 02406 { 02407 if( PtrPinnedSIndirectBlock[Index] ) 02408 { 02409 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedSIndirectBlock[Index] ); 02410 } 02411 else 02412 { 02413 break; 02414 } 02415 } 02416 CcUnpinData( PtrBCB ); 02417 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ EXT2_IND_BLOCK ] ); 02418 } 02419 02420 // 4. 02421 // Free up the direct blocks... 02422 for( i = 0; i < EXT2_NDIR_BLOCKS; i++ ) 02423 { 02424 if( PtrFCB->IBlock[ i ] ) 02425 { 02426 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ i ] ); 02427 } 02428 else 02429 { 02430 break; 02431 } 02432 } 02433 return TRUE; 02434 } 02435 02436 02437 BOOLEAN NTAPI Ext2TruncateFileAllocationSize( 02438 PtrExt2IrpContext PtrIrpContext, 02439 PtrExt2FCB PtrFCB, 02440 PFILE_OBJECT PtrFileObject, 02441 PLARGE_INTEGER PtrAllocationSize ) 02442 { 02443 PtrExt2VCB PtrVCB = PtrFCB->PtrVCB; 02444 ULONG LogicalBlockSize; 02445 ULONG i; 02446 02447 ULONG NoOfBlocksToBeLeft= 0; 02448 ULONG CurrentBlockNo = 0; 02449 02450 // 02451 // This function has not been tested... 02452 // 02453 Ext2BreakPoint(); 02454 02455 LogicalBlockSize = EXT2_MIN_BLOCK_SIZE << PtrVCB->LogBlockSize; 02456 NoOfBlocksToBeLeft = (ULONG) (PtrAllocationSize->QuadPart / LogicalBlockSize); 02457 02458 02459 02460 // Release the data blocks... 02461 02462 // 1. 02463 // Free up the direct blocks... 02464 for( i = NoOfBlocksToBeLeft; i < EXT2_NDIR_BLOCKS; i++ ) 02465 { 02466 if( PtrFCB->IBlock[ i ] ) 02467 { 02468 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ i ] ); 02469 PtrFCB->IBlock[ i ] = 0; 02470 } 02471 else 02472 { 02473 break; 02474 } 02475 } 02476 02477 // 2. 02478 // Free up the single indirect blocks... 02479 CurrentBlockNo = EXT2_NDIR_BLOCKS; 02480 02481 if( PtrFCB->IBlock[ EXT2_IND_BLOCK ] ) 02482 { 02483 PBCB PtrBCB = NULL; 02484 ULONG * PtrPinnedSIndirectBlock = NULL; 02485 LARGE_INTEGER VolumeByteOffset; 02486 ULONG Index; 02487 02488 // Pin the Single Indirect Pointer Block... 02489 VolumeByteOffset.QuadPart = PtrFCB->IBlock[ EXT2_IND_BLOCK ] * LogicalBlockSize; 02490 if (!CcMapData( PtrVCB->PtrStreamFileObject, 02491 &VolumeByteOffset, 02492 LogicalBlockSize, 02493 TRUE, 02494 &PtrBCB, 02495 (PVOID*)&PtrPinnedSIndirectBlock )) 02496 { 02497 return FALSE; 02498 } 02499 02500 // Read the Block numbers off the Indirect Pointer Block and 02501 // free the data blocks 02502 for( Index = 0; Index < (LogicalBlockSize/sizeof(ULONG)); 02503 Index++, CurrentBlockNo++ ) 02504 { 02505 if( CurrentBlockNo >= NoOfBlocksToBeLeft ) 02506 { 02507 if( PtrPinnedSIndirectBlock[Index] ) 02508 { 02509 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrPinnedSIndirectBlock[Index] ); 02510 } 02511 else 02512 { 02513 break; 02514 } 02515 } 02516 else if( !PtrPinnedSIndirectBlock[Index] ) 02517 { 02518 break; 02519 } 02520 } 02521 if( NoOfBlocksToBeLeft <= EXT2_NDIR_BLOCKS ) 02522 { 02523 Ext2DeallocBlock( PtrIrpContext, PtrVCB, PtrFCB->IBlock[ EXT2_IND_BLOCK ] ); 02524 PtrFCB->IBlock[ EXT2_IND_BLOCK ] = 0; 02525 } 02526 02527 CcUnpinData( PtrBCB ); 02528 } 02529 02530 // 3. 02531 // Free up the double indirect blocks... 02532 if( PtrFCB->IBlock[ EXT2_DIND_BLOCK ] ) 02533 { 02534 02535 } 02536 02537 // 4. 02538 // Free up the triple indirect blocks... 02539 if( PtrFCB->IBlock[ EXT2_TIND_BLOCK ] ) 02540 { 02541 02542 } 02543 02544 return TRUE; 02545 } 02546 02547 BOOLEAN NTAPI Ext2IsDirectoryEmpty( 02548 PtrExt2FCB PtrFCB, 02549 PtrExt2CCB PtrCCB, 02550 PtrExt2IrpContext PtrIrpContext) 02551 { 02552 02553 PFILE_OBJECT PtrFileObject = NULL; 02554 02555 if( !Ext2IsFlagOn(PtrFCB->FCBFlags, EXT2_FCB_DIRECTORY) ) 02556 { 02557 return FALSE; 02558 } 02559 02560 // 1. 02561 // Initialize the Blocks in the FCB... 02562 // 02563 Ext2InitializeFCBInodeInfo( PtrFCB ); 02564 02565 02566 // 2. 02567 // Get hold of the file object... 02568 // 02569 PtrFileObject = PtrCCB->PtrFileObject; 02570 02571 02572 // 3. 02573 // Now initiating Caching, pinned access to be precise ... 02574 // 02575 if (PtrFileObject->PrivateCacheMap == NULL) 02576 { 02577 CcInitializeCacheMap(PtrFileObject, (PCC_FILE_SIZES)(&(PtrFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)), 02578 TRUE, // We utilize pin access for directories 02579 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks 02580 PtrFCB ); // The context used in callbacks 02581 } 02582 02583 // 4. 02584 // Getting down to the real business now... ;) 02585 // Read in the directory contents and do a search 02586 // 02587 { 02588 LARGE_INTEGER StartBufferOffset; 02589 ULONG PinBufferLength; 02590 ULONG BufferIndex; 02591 PBCB PtrBCB = NULL; 02592 BYTE * PtrPinnedBlockBuffer = NULL; 02593 PEXT2_DIR_ENTRY PtrDirEntry = NULL; 02594 BOOLEAN Found = FALSE; 02595 02596 StartBufferOffset.QuadPart = 0; 02597 02598 // 02599 // Read in the whole directory 02600 // **Bad programming** 02601 // Will do for now. 02602 // 02603 PinBufferLength = PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart; 02604 if (!CcMapData( PtrFileObject, 02605 &StartBufferOffset, 02606 PinBufferLength, 02607 TRUE, 02608 &PtrBCB, 02609 (PVOID*)&PtrPinnedBlockBuffer ) ) 02610 { 02611 return FALSE; 02612 } 02613 02614 // 02615 // Walking through now... 02616 // 02617 for( BufferIndex = 0, Found = FALSE; !Found && BufferIndex < ( PtrFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; BufferIndex += PtrDirEntry->rec_len ) 02618 { 02619 PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ BufferIndex ]; 02620 if( PtrDirEntry->inode == 0) 02621 { 02622 // Deleted entry... 02623 // Ignore... 02624 continue; 02625 } 02626 if( PtrDirEntry->name[0] == '.' ) 02627 { 02628 if( PtrDirEntry->name_len == 1 || 02629 ( PtrDirEntry->name_len == 2 && PtrDirEntry->name[1] == '.' ) ) 02630 { 02631 continue; 02632 } 02633 } 02634 Found = TRUE; 02635 } 02636 CcUnpinData( PtrBCB ); 02637 PtrBCB = NULL; 02638 02639 return !Found; 02640 } 02641 } 02642 02643 02644 NTSTATUS NTAPI Ext2RenameOrLinkFile( 02645 PtrExt2FCB PtrSourceFCB, 02646 PFILE_OBJECT PtrSourceFileObject, 02647 PtrExt2IrpContext PtrIrpContext, 02648 PIRP PtrIrp, 02649 PFILE_RENAME_INFORMATION PtrRenameInfo) 02650 { 02651 PtrExt2FCB PtrParentFCB = NULL; 02652 PtrExt2VCB PtrSourceVCB = PtrSourceFCB->PtrVCB; 02653 02654 PtrExt2FCB PtrTargetFCB = NULL; 02655 PtrExt2CCB PtrTargetCCB = NULL; 02656 PtrExt2VCB PtrTargetVCB = NULL; 02657 02658 02659 FILE_INFORMATION_CLASS FunctionalityRequested; 02660 PIO_STACK_LOCATION PtrIoStackLocation = NULL; 02661 PFILE_OBJECT TargetFileObject = NULL; 02662 BOOLEAN ReplaceExistingFile = FALSE; 02663 BOOLEAN Found = FALSE; 02664 02665 PtrIoStackLocation = IoGetCurrentIrpStackLocation(PtrIrp); 02666 FunctionalityRequested = PtrIoStackLocation->Parameters.SetFile.FileInformationClass; 02667 TargetFileObject = PtrIoStackLocation->Parameters.SetFile.FileObject; 02668 ReplaceExistingFile = PtrIoStackLocation->Parameters.SetFile.ReplaceIfExists; 02669 02670 // Get the FCB and CCB pointers 02671 Ext2GetFCB_CCB_VCB_FromFileObject ( 02672 TargetFileObject , &PtrTargetFCB, &PtrTargetCCB, &PtrTargetVCB); 02673 02674 if( !PtrTargetCCB ) 02675 { 02676 return STATUS_ACCESS_DENIED; 02677 } 02678 if( PtrTargetVCB != PtrSourceVCB ) 02679 { 02680 // Cannot rename across volumes... 02681 return STATUS_ACCESS_DENIED; 02682 } 02683 if ( !Ext2IsFlagOn( PtrTargetFCB->FCBFlags, EXT2_FCB_DIRECTORY ) ) 02684 { 02685 // Target has to be a folder... 02686 return STATUS_ACCESS_DENIED; 02687 } 02688 02689 // 1. 02690 // Open the parent folder... 02691 PtrParentFCB = Ext2LocateFCBInCore( PtrSourceVCB, PtrSourceFCB->ParentINodeNo ); 02692 if( !PtrParentFCB ) 02693 { 02694 // Get the folder from the disk 02695 // Use the inode no PtrSourceFCB->ParentINodeNo 02696 // 02697 // For now... 02698 return STATUS_ACCESS_DENIED; 02699 } 02700 02701 // 2. 02702 // Check if the file exists in the TargetFolder... 02703 { 02704 LARGE_INTEGER StartBufferOffset; 02705 ULONG PinBufferLength; 02706 ULONG BufferIndex; 02707 PBCB PtrBCB = NULL; 02708 BYTE * PtrPinnedBlockBuffer = NULL; 02709 PEXT2_DIR_ENTRY PtrDirEntry = NULL; 02710 int i; 02711 02712 StartBufferOffset.QuadPart = 0; 02713 02714 // 02715 // Read in the whole directory 02716 // 02717 if ( TargetFileObject->PrivateCacheMap == NULL ) 02718 { 02719 CcInitializeCacheMap( 02720 TargetFileObject, 02721 (PCC_FILE_SIZES)(&(PtrTargetFCB->NTRequiredFCB.CommonFCBHeader.AllocationSize)), 02722 TRUE, // We utilize pin access for directories 02723 &(Ext2GlobalData.CacheMgrCallBacks), // callbacks 02724 PtrTargetCCB ); // The context used in callbacks 02725 } 02726 02727 PinBufferLength = PtrTargetFCB->NTRequiredFCB.CommonFCBHeader.FileSize.LowPart; 02728 if (!CcMapData( TargetFileObject, 02729 &StartBufferOffset, 02730 PinBufferLength, 02731 TRUE, 02732 &PtrBCB, 02733 (PVOID*)&PtrPinnedBlockBuffer ) ) 02734 { 02735 return FALSE; 02736 } 02737 02738 // 02739 // Walking through now... 02740 // 02741 for( BufferIndex = 0, Found = FALSE; !Found && BufferIndex < ( PtrTargetFCB->NTRequiredFCB.CommonFCBHeader.FileSize.QuadPart - 1) ; BufferIndex += PtrDirEntry->rec_len ) 02742 { 02743 PtrDirEntry = (PEXT2_DIR_ENTRY) &PtrPinnedBlockBuffer[ BufferIndex ]; 02744 if( PtrDirEntry->inode == 0) 02745 { 02746 // Deleted entry... 02747 // Ignore... 02748 continue; 02749 } 02750 if( PtrDirEntry->name_len == (PtrTargetCCB->RenameLinkTargetFileName.Length/2) ) 02751 { 02752 Found = TRUE; 02753 for( i =0; i < PtrDirEntry->name_len ; i++ ) 02754 { 02755 if( PtrDirEntry->name[i] != PtrTargetCCB->RenameLinkTargetFileName.Buffer[i] ) 02756 { 02757 Found = FALSE; 02758 break; 02759 } 02760 } 02761 } 02762 } 02763 CcUnpinData( PtrBCB ); 02764 PtrBCB = NULL; 02765 } 02766 02767 // 3. 02768 // If the file exists, delete it if requested.. 02769 if( Found ) 02770 { 02771 if( !ReplaceExistingFile ) 02772 { 02773 return STATUS_OBJECT_NAME_COLLISION; 02774 } 02775 // Delete the file... 02776 // Reject this for now... 02777 return STATUS_ACCESS_DENIED; 02778 } 02779 02780 02781 { 02782 ULONG Type = EXT2_FT_REG_FILE; 02783 if( Ext2IsFlagOn( PtrSourceFCB->FCBFlags, EXT2_FCB_DIRECTORY ) ) 02784 { 02785 Type = EXT2_FT_DIR; 02786 } 02787 02788 ASSERT( TargetFileObject ); 02789 02790 // 4. 02791 // Remove the old entry... 02792 Ext2FreeDirectoryEntry( PtrIrpContext, PtrParentFCB, 02793 &PtrSourceFCB->FCBName->ObjectName); 02794 02795 // 5. 02796 // Create a new entry... 02797 Ext2MakeNewDirectoryEntry( 02798 PtrIrpContext, // This IRP Context 02799 PtrTargetFCB, // Parent Folder FCB 02800 TargetFileObject, // Parent Folder Object 02801 &PtrTargetCCB->RenameLinkTargetFileName, // New entry's name 02802 Type, // The type of the new entry 02803 PtrSourceFCB->INodeNo ); // The inode no of the new entry... 02804 02805 } 02806 02807 // 6. 02808 // Update the PtrSourceFCB... 02809 { 02810 02811 PtrExt2ObjectName PtrObjectName; 02812 if( PtrSourceFCB->FCBName ) 02813 { 02814 Ext2ReleaseObjectName( PtrSourceFCB->FCBName ); 02815 } 02816 PtrObjectName = Ext2AllocateObjectName(); 02817 Ext2CopyUnicodeString( &PtrObjectName->ObjectName, &PtrTargetCCB->RenameLinkTargetFileName ); 02818 PtrSourceFCB->FCBName = PtrObjectName; 02819 PtrSourceFCB->ParentINodeNo = PtrTargetFCB->INodeNo; 02820 } 02821 02822 if( PtrTargetCCB->RenameLinkTargetFileName.Length ) 02823 { 02824 Ext2DeallocateUnicodeString( &PtrTargetCCB->RenameLinkTargetFileName ); 02825 } 02826 02827 return STATUS_SUCCESS; 02828 } Generated on Sun May 27 2012 04:24:48 for ReactOS by
1.7.6.1
|