Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > DoxygenMke2fs.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: Mke2fs 00003 * FILE: Disk.c 00004 * PROGRAMMER: Matt Wu <mattwu@163.com> 00005 * HOMEPAGE: http://ext2.yeah.net 00006 */ 00007 00008 /* INCLUDES **************************************************************/ 00009 00010 #include "Mke2fs.h" 00011 #include <debug.h> 00012 00013 /* GLOBALS ***************************************************************/ 00014 00015 int inode_ratio = 4096; 00016 00017 BOOLEAN bLocked = FALSE; 00018 00019 /* This is needed for the ext2fs driver to mount the volume */ 00020 #define ZAP_BOOTBLOCK 00021 00022 /* FUNCTIONS *************************************************************/ 00023 00024 int int_log2(int arg) 00025 { 00026 int l = 0; 00027 00028 arg >>= 1; 00029 00030 while (arg) 00031 { 00032 l++; 00033 arg >>= 1; 00034 } 00035 00036 return l; 00037 } 00038 00039 int int_log10(unsigned int arg) 00040 { 00041 int l; 00042 00043 for (l=0; arg ; l++) 00044 arg = arg / 10; 00045 00046 return l; 00047 } 00048 00049 00050 static char default_str[] = "default"; 00051 00052 struct mke2fs_defaults { 00053 const char *type; 00054 int size; 00055 int blocksize; 00056 int inode_ratio; 00057 } settings[] = { 00058 { default_str, 0, 4096, 8192 }, 00059 { default_str, 512, 1024, 4096 }, 00060 { default_str, 3, 1024, 8192 }, 00061 { "journal", 0, 4096, 8192 }, 00062 { "news", 0, 4096, 4096 }, 00063 { "largefile", 0, 4096, 1024 * 1024 }, 00064 { "largefile4", 0, 4096, 4096 * 1024 }, 00065 { 0, 0, 0, 0}, 00066 }; 00067 00068 void set_fs_defaults(const char *fs_type, 00069 PEXT2_SUPER_BLOCK super, 00070 int blocksize, int *inode_ratio) 00071 { 00072 int megs; 00073 int ratio = 0; 00074 struct mke2fs_defaults *p; 00075 00076 megs = (super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024); 00077 00078 if (inode_ratio) 00079 ratio = *inode_ratio; 00080 00081 if (!fs_type) 00082 fs_type = default_str; 00083 00084 for (p = settings; p->type; p++) 00085 { 00086 if ((strcmp(p->type, fs_type) != 0) && 00087 (strcmp(p->type, default_str) != 0)) 00088 continue; 00089 00090 if ((p->size != 0) && 00091 (megs > p->size)) 00092 continue; 00093 00094 if (ratio == 0) 00095 *inode_ratio = p->inode_ratio; 00096 00097 if (blocksize == 0) 00098 { 00099 super->s_log_frag_size = super->s_log_block_size = 00100 int_log2(p->blocksize >> EXT2_MIN_BLOCK_LOG_SIZE); 00101 } 00102 } 00103 00104 if (blocksize == 0) 00105 { 00106 super->s_blocks_count /= EXT2_BLOCK_SIZE(super) / 1024; 00107 } 00108 } 00109 00110 /* 00111 * Helper function which zeros out _num_ blocks starting at _blk_. In 00112 * case of an error, the details of the error is returned via _ret_blk_ 00113 * and _ret_count_ if they are non-NULL pointers. Returns 0 on 00114 * success, and an error code on an error. 00115 * 00116 * As a special case, if the first argument is NULL, then it will 00117 * attempt to free the static zeroizing buffer. (This is to keep 00118 * programs that check for memory leaks happy.) 00119 */ 00120 bool zero_blocks(PEXT2_FILESYS fs, ULONG blk, ULONG num, 00121 ULONG *ret_blk, ULONG *ret_count) 00122 { 00123 ULONG j, count, next_update, next_update_incr; 00124 static unsigned char *buf; 00125 bool retval; 00126 00127 /* If fs is null, clean up the static buffer and return */ 00128 if (!fs) 00129 { 00130 if (buf) 00131 { 00132 RtlFreeHeap(RtlGetProcessHeap(), 0, buf); 00133 buf = 0; 00134 } 00135 return true; 00136 } 00137 00138 #define STRIDE_LENGTH 8 00139 00140 /* Allocate the zeroizing buffer if necessary */ 00141 if (!buf) 00142 { 00143 buf = (unsigned char *) 00144 RtlAllocateHeap(RtlGetProcessHeap(), 0, fs->blocksize * STRIDE_LENGTH); 00145 if (!buf) 00146 { 00147 DPRINT1("Mke2fs: while allocating zeroizing buffer"); 00148 if (ret_blk) 00149 *ret_blk = blk; 00150 return false; 00151 } 00152 memset(buf, 0, fs->blocksize * STRIDE_LENGTH); 00153 } 00154 00155 /* OK, do the write loop */ 00156 next_update = 0; 00157 next_update_incr = num / 100; 00158 if (next_update_incr < 1) 00159 next_update_incr = 1; 00160 00161 for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) 00162 { 00163 if (num-j > STRIDE_LENGTH) 00164 count = STRIDE_LENGTH; 00165 else 00166 count = num - j; 00167 00168 retval = NT_SUCCESS(Ext2WriteDisk( 00169 fs, 00170 ((ULONGLONG)blk * fs->blocksize), 00171 count * fs->blocksize, 00172 buf)); 00173 00174 if (!retval) 00175 { 00176 if (ret_count) 00177 *ret_count = count; 00178 00179 if (ret_blk) 00180 *ret_blk = blk; 00181 00182 return retval; 00183 } 00184 } 00185 00186 return true; 00187 } 00188 00189 00190 bool zap_sector(PEXT2_FILESYS Ext2Sys, int sect, int nsect) 00191 { 00192 unsigned char *buf; 00193 ULONG *magic; 00194 00195 buf = (unsigned char *) 00196 RtlAllocateHeap(RtlGetProcessHeap(), 0, SECTOR_SIZE*nsect); 00197 if (!buf) 00198 { 00199 DPRINT1("Mke2fs: Out of memory erasing sectors %d-%d\n", 00200 sect, sect + nsect - 1); 00201 return false; 00202 } 00203 00204 #define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */ 00205 #define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */ 00206 #define BSD_LABEL_OFFSET 64 00207 00208 if (sect == 0) 00209 { 00210 Ext2ReadDisk( 00211 Ext2Sys, 00212 (LONGLONG)(sect * SECTOR_SIZE), 00213 SECTOR_SIZE, buf); 00214 00215 // Check for a BSD disklabel, and don't erase it if so 00216 magic = (ULONG *) (buf + BSD_LABEL_OFFSET); 00217 if ((*magic == BSD_DISKMAGIC) || (*magic == BSD_MAGICDISK)) 00218 goto clean_up; 00219 } 00220 00221 memset(buf, 0, (ULONG)nsect * SECTOR_SIZE); 00222 00223 // Write buf to disk 00224 Ext2WriteDisk( Ext2Sys, 00225 (LONGLONG)(sect * SECTOR_SIZE), 00226 (ULONG)nsect * SECTOR_SIZE, 00227 buf ); 00228 00229 clean_up: 00230 00231 RtlFreeHeap(RtlGetProcessHeap(), 0, buf); 00232 00233 return true; 00234 } 00235 00236 bool ext2_mkdir( PEXT2_FILESYS fs, 00237 ULONG parent, 00238 ULONG inum, 00239 char *name, 00240 ULONG *no, 00241 PEXT2_INODE pid ) 00242 { 00243 bool retval; 00244 EXT2_INODE parent_inode, inode; 00245 ULONG ino = inum; 00246 //ULONG scratch_ino; 00247 ULONG blk; 00248 char *block = 0; 00249 int filetype = 0; 00250 00251 LARGE_INTEGER SysTime; 00252 00253 NtQuerySystemTime(&SysTime); 00254 00255 /* 00256 * Allocate an inode, if necessary 00257 */ 00258 if (!ino) 00259 { 00260 retval = ext2_new_inode(fs, parent, LINUX_S_IFDIR | 0755, 0, &ino); 00261 if (!retval) 00262 goto cleanup; 00263 } 00264 00265 if (no) 00266 *no = ino; 00267 00268 /* 00269 * Allocate a data block for the directory 00270 */ 00271 retval = ext2_new_block(fs, 0, 0, &blk); 00272 if (!retval) 00273 goto cleanup; 00274 00275 /* 00276 * Create a scratch template for the directory 00277 */ 00278 retval = ext2_new_dir_block(fs, ino, parent, &block); 00279 if (!retval) 00280 goto cleanup; 00281 00282 /* 00283 * Get the parent's inode, if necessary 00284 */ 00285 if (parent != ino) 00286 { 00287 retval = ext2_load_inode(fs, parent, &parent_inode); 00288 if (!retval) 00289 goto cleanup; 00290 } 00291 else 00292 { 00293 memset(&parent_inode, 0, sizeof(parent_inode)); 00294 } 00295 00296 /* 00297 * Create the inode structure.... 00298 */ 00299 memset(&inode, 0, sizeof(EXT2_INODE)); 00300 inode.i_mode = (USHORT)(LINUX_S_IFDIR | (0777 & ~fs->umask)); 00301 inode.i_uid = inode.i_gid = 0; 00302 inode.i_blocks = fs->blocksize / 512; 00303 inode.i_block[0] = blk; 00304 inode.i_links_count = 2; 00305 RtlTimeToSecondsSince1970(&SysTime, &inode.i_mtime); 00306 inode.i_ctime = inode.i_atime = inode.i_mtime; 00307 inode.i_size = fs->blocksize; 00308 00309 /* 00310 * Write out the inode and inode data block 00311 */ 00312 retval = ext2_write_block(fs, blk, block); 00313 if (!retval) 00314 goto cleanup; 00315 00316 retval = ext2_save_inode(fs, ino, &inode); 00317 if (!retval) 00318 goto cleanup; 00319 00320 if (pid) 00321 { 00322 *pid = inode; 00323 } 00324 00325 if (parent != ino) 00326 { 00327 /* 00328 * Add entry for this inode to parent dir 's block 00329 */ 00330 00331 if (fs->ext2_sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE) 00332 filetype = EXT2_FT_DIR; 00333 00334 retval = ext2_add_entry(fs, parent, ino, filetype, name); 00335 00336 if (!retval) 00337 goto cleanup; 00338 00339 /* 00340 * Update parent inode's counts 00341 */ 00342 00343 parent_inode.i_links_count++; 00344 retval = ext2_save_inode(fs, parent, &parent_inode); 00345 if (!retval) 00346 goto cleanup; 00347 00348 } 00349 00350 /* 00351 * Update accounting.... 00352 */ 00353 ext2_block_alloc_stats(fs, blk, +1); 00354 ext2_inode_alloc_stats2(fs, ino, +1, 1); 00355 00356 cleanup: 00357 00358 if (block) 00359 { 00360 RtlFreeHeap(RtlGetProcessHeap(), 0, block); 00361 block = NULL; 00362 } 00363 00364 return retval; 00365 } 00366 00367 bool create_root_dir(PEXT2_FILESYS fs) 00368 { 00369 bool retval; 00370 EXT2_INODE inode; 00371 00372 retval = ext2_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0, NULL, &inode); 00373 00374 if (!retval) 00375 { 00376 DPRINT1("Mke2fs: while creating root dir"); 00377 return false; 00378 } 00379 00380 { 00381 inode.i_uid = 0; 00382 inode.i_gid = 0; 00383 00384 retval = ext2_save_inode(fs, EXT2_ROOT_INO, &inode); 00385 if (!retval) 00386 { 00387 DPRINT1("Mke2fs: while setting root inode ownership"); 00388 return false; 00389 } 00390 } 00391 00392 return true; 00393 } 00394 00395 bool create_lost_and_found(PEXT2_FILESYS Ext2Sys) 00396 { 00397 bool retval; 00398 ULONG ino; 00399 char *name = "lost+found"; 00400 int lpf_size = 0; 00401 EXT2_INODE inode; 00402 ULONG dwBlk = 0; 00403 BOOLEAN bExt= TRUE; 00404 00405 PEXT2_DIR_ENTRY dir; 00406 00407 char * buf; 00408 00409 buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, Ext2Sys->blocksize); 00410 if (!buf) 00411 { 00412 bExt = FALSE; 00413 } 00414 else 00415 { 00416 memset(buf, 0, Ext2Sys->blocksize); 00417 00418 dir = (PEXT2_DIR_ENTRY) buf; 00419 dir->rec_len = Ext2Sys->blocksize; 00420 } 00421 00422 Ext2Sys->umask = 077; 00423 retval = ext2_mkdir(Ext2Sys, EXT2_ROOT_INO, 0, name, &ino, &inode); 00424 00425 if (!retval) 00426 { 00427 DPRINT1("Mke2fs: while creating /lost+found.\n"); 00428 return false; 00429 } 00430 00431 if (!bExt) 00432 goto errorout; 00433 00434 lpf_size = inode.i_size; 00435 00436 while(TRUE) 00437 { 00438 if (lpf_size >= 16*1024) 00439 break; 00440 00441 retval = ext2_alloc_block(Ext2Sys, 0, &dwBlk); 00442 00443 if (! retval) 00444 { 00445 DPRINT1("Mke2fs: create_lost_and_found: error alloc block.\n"); 00446 break; 00447 } 00448 00449 retval = ext2_expand_inode(Ext2Sys, &inode, dwBlk); 00450 if (!retval) 00451 { 00452 DPRINT1("Mke2fs: errors when expanding /lost+found.\n"); 00453 break; 00454 } 00455 00456 ext2_write_block(Ext2Sys, dwBlk, buf); 00457 00458 inode.i_blocks += (Ext2Sys->blocksize/SECTOR_SIZE); 00459 lpf_size += Ext2Sys->blocksize; 00460 } 00461 00462 { 00463 inode.i_size = lpf_size; 00464 00465 ASSERT( (inode.i_size/Ext2Sys->blocksize) == 00466 Ext2DataBlocks(Ext2Sys, inode.i_blocks/(Ext2Sys->blocksize/SECTOR_SIZE))); 00467 00468 ASSERT( (inode.i_blocks/(Ext2Sys->blocksize/SECTOR_SIZE)) == 00469 Ext2TotalBlocks(Ext2Sys, inode.i_size/Ext2Sys->blocksize)); 00470 00471 } 00472 00473 ext2_save_inode(Ext2Sys, ino, &inode); 00474 00475 errorout: 00476 00477 if (buf) 00478 { 00479 RtlFreeHeap(RtlGetProcessHeap(), 0, buf); 00480 } 00481 00482 return true; 00483 } 00484 00485 /* 00486 * This function forces out the primary superblock. We need to only 00487 * write out those fields which we have changed, since if the 00488 * filesystem is mounted, it may have changed some of the other 00489 * fields. 00490 * 00491 * It takes as input a superblock which has already been byte swapped 00492 * (if necessary). 00493 */ 00494 00495 bool write_primary_superblock(PEXT2_FILESYS Ext2Sys, PEXT2_SUPER_BLOCK super) 00496 { 00497 bool bRet; 00498 00499 bRet = NT_SUCCESS(Ext2WriteDisk( 00500 Ext2Sys, 00501 ((LONGLONG)SUPERBLOCK_OFFSET), 00502 SUPERBLOCK_SIZE, (PUCHAR)super)); 00503 00504 00505 00506 return bRet; 00507 } 00508 00509 00510 /* 00511 * Updates the revision to EXT2_DYNAMIC_REV 00512 */ 00513 void ext2_update_dynamic_rev(PEXT2_FILESYS fs) 00514 { 00515 PEXT2_SUPER_BLOCK sb = fs->ext2_sb; 00516 00517 if (sb->s_rev_level > EXT2_GOOD_OLD_REV) 00518 return; 00519 00520 sb->s_rev_level = EXT2_DYNAMIC_REV; 00521 sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO; 00522 sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE; 00523 /* s_uuid is handled by e2fsck already */ 00524 /* other fields should be left alone */ 00525 } 00526 00527 00528 bool ext2_flush(PEXT2_FILESYS fs) 00529 { 00530 ULONG i,j,maxgroup,sgrp; 00531 ULONG group_block; 00532 bool retval; 00533 char *group_ptr; 00534 unsigned long fs_state; 00535 PEXT2_SUPER_BLOCK super_shadow = 0; 00536 PEXT2_GROUP_DESC group_shadow = 0; 00537 00538 LARGE_INTEGER SysTime; 00539 00540 NtQuerySystemTime(&SysTime); 00541 00542 fs_state = fs->ext2_sb->s_state; 00543 00544 RtlTimeToSecondsSince1970(&SysTime, &fs->ext2_sb->s_wtime); 00545 fs->ext2_sb->s_block_group_nr = 0; 00546 00547 super_shadow = fs->ext2_sb; 00548 group_shadow = fs->group_desc; 00549 00550 /* 00551 * Write out master superblock. This has to be done 00552 * separately, since it is located at a fixed location 00553 * (SUPERBLOCK_OFFSET). 00554 */ 00555 retval = write_primary_superblock(fs, super_shadow); 00556 if (!retval) 00557 goto errout; 00558 00559 /* 00560 * If this is an external journal device, don't write out the 00561 * block group descriptors or any of the backup superblocks 00562 */ 00563 if (fs->ext2_sb->s_feature_incompat & 00564 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 00565 { 00566 retval = false; 00567 goto errout; 00568 } 00569 00570 /* 00571 * Set the state of the FS to be non-valid. (The state has 00572 * already been backed up earlier, and will be restored when 00573 * we exit.) 00574 */ 00575 fs->ext2_sb->s_state &= ~EXT2_VALID_FS; 00576 00577 /* 00578 * Write out the master group descriptors, and the backup 00579 * superblocks and group descriptors. 00580 */ 00581 group_block = fs->ext2_sb->s_first_data_block; 00582 maxgroup = fs->group_desc_count; 00583 00584 for (i = 0; i < maxgroup; i++) 00585 { 00586 if (!ext2_bg_has_super(fs->ext2_sb, i)) 00587 goto next_group; 00588 00589 sgrp = i; 00590 if (sgrp > ((1 << 16) - 1)) 00591 sgrp = (1 << 16) - 1; 00592 00593 fs->ext2_sb->s_block_group_nr = (USHORT) sgrp; 00594 00595 if (i !=0 ) 00596 { 00597 retval = NT_SUCCESS(Ext2WriteDisk( 00598 fs, 00599 ((ULONGLONG)group_block * fs->blocksize), 00600 SUPERBLOCK_SIZE, (PUCHAR)super_shadow)); 00601 00602 if (!retval) 00603 { 00604 goto errout; 00605 } 00606 } 00607 00608 group_ptr = (char *) group_shadow; 00609 00610 for (j=0; j < fs->desc_blocks; j++) 00611 { 00612 00613 retval = NT_SUCCESS(Ext2WriteDisk( 00614 fs, 00615 ((ULONGLONG)(group_block+1+j) * fs->blocksize), 00616 fs->blocksize, (PUCHAR) group_ptr)); 00617 00618 if (!retval) 00619 { 00620 goto errout; 00621 } 00622 00623 group_ptr += fs->blocksize; 00624 } 00625 00626 next_group: 00627 group_block += EXT2_BLOCKS_PER_GROUP(fs->ext2_sb); 00628 00629 } 00630 00631 fs->ext2_sb->s_block_group_nr = 0; 00632 00633 /* 00634 * If the write_bitmaps() function is present, call it to 00635 * flush the bitmaps. This is done this way so that a simple 00636 * program that doesn't mess with the bitmaps doesn't need to 00637 * drag in the bitmaps.c code. 00638 */ 00639 retval = ext2_write_bitmaps(fs); 00640 if (!retval) 00641 goto errout; 00642 00643 /* 00644 * Flush the blocks out to disk 00645 */ 00646 00647 // retval = io_channel_flush(fs->io); 00648 00649 errout: 00650 00651 fs->ext2_sb->s_state = (USHORT) fs_state; 00652 00653 return retval; 00654 } 00655 00656 00657 bool create_journal_dev(PEXT2_FILESYS fs) 00658 { 00659 bool retval = false; 00660 char *buf = NULL; 00661 ULONG blk; 00662 ULONG count; 00663 00664 if (!retval) 00665 { 00666 DPRINT1("Mke2fs: ext2_create_journal_dev: while initializing journal superblock.\n"); 00667 return false; 00668 } 00669 00670 DPRINT("Mke2fs: Zeroing journal device: \n"); 00671 00672 retval = zero_blocks(fs, 0, fs->ext2_sb->s_blocks_count, 00673 &blk, &count); 00674 00675 zero_blocks(0, 0, 0, 0, 0); 00676 00677 if (!retval) 00678 { 00679 DPRINT1("Mke2fs: create_journal_dev: while zeroing journal device (block %lu, count %lu).\n", 00680 blk, count); 00681 return false; 00682 } 00683 00684 retval = NT_SUCCESS(Ext2WriteDisk( 00685 fs, 00686 ((ULONGLONG)blk * (fs->ext2_sb->s_first_data_block+1)), 00687 fs->blocksize, (unsigned char *)buf)); 00688 00689 if (!retval) 00690 { 00691 DPRINT1("Mke2fs: create_journal_dev: while writing journal superblock.\n"); 00692 return false; 00693 } 00694 00695 return true; 00696 } 00697 00698 #define BLOCK_BITS (Ext2Sys->ext2_sb->s_log_block_size + 10) 00699 00700 ULONG 00701 Ext2DataBlocks(PEXT2_FILESYS Ext2Sys, ULONG TotalBlocks) 00702 { 00703 ULONG dwData[4] = {1, 1, 1, 1}; 00704 ULONG dwMeta[4] = {0, 0, 0, 0}; 00705 ULONG DataBlocks = 0; 00706 ULONG i, j; 00707 00708 if (TotalBlocks <= EXT2_NDIR_BLOCKS) 00709 { 00710 return TotalBlocks; 00711 } 00712 00713 TotalBlocks -= EXT2_NDIR_BLOCKS; 00714 00715 for (i = 0; i < 4; i++) 00716 { 00717 dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i); 00718 00719 if (i > 0) 00720 { 00721 dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2)); 00722 } 00723 } 00724 00725 for( i=1; (i < 4) && (TotalBlocks > 0); i++) 00726 { 00727 if (TotalBlocks >= (dwData[i] + dwMeta[i])) 00728 { 00729 TotalBlocks -= (dwData[i] + dwMeta[i]); 00730 DataBlocks += dwData[i]; 00731 } 00732 else 00733 { 00734 ULONG dwDivide = 0; 00735 ULONG dwRemain = 0; 00736 00737 for (j=i; (j > 0) && (TotalBlocks > 0); j--) 00738 { 00739 dwDivide = (TotalBlocks - 1) / (dwData[j-1] + dwMeta[j-1]); 00740 dwRemain = (TotalBlocks - 1) % (dwData[j-1] + dwMeta[j-1]); 00741 00742 DataBlocks += (dwDivide * dwData[j-1]); 00743 TotalBlocks = dwRemain; 00744 } 00745 } 00746 } 00747 00748 return (DataBlocks + EXT2_NDIR_BLOCKS); 00749 } 00750 00751 00752 ULONG 00753 Ext2TotalBlocks(PEXT2_FILESYS Ext2Sys, ULONG DataBlocks) 00754 { 00755 ULONG dwData[4] = {1, 1, 1, 1}; 00756 ULONG dwMeta[4] = {0, 0, 0, 0}; 00757 ULONG TotalBlocks = 0; 00758 ULONG i, j; 00759 00760 if (DataBlocks <= EXT2_NDIR_BLOCKS) 00761 { 00762 return DataBlocks; 00763 } 00764 00765 DataBlocks -= EXT2_NDIR_BLOCKS; 00766 00767 for (i = 0; i < 4; i++) 00768 { 00769 dwData[i] = dwData[i] << ((BLOCK_BITS - 2) * i); 00770 00771 if (i > 0) 00772 { 00773 dwMeta[i] = 1 + (dwMeta[i - 1] << (BLOCK_BITS - 2)); 00774 } 00775 } 00776 00777 for( i=1; (i < 4) && (DataBlocks > 0); i++) 00778 { 00779 if (DataBlocks >= dwData[i]) 00780 { 00781 DataBlocks -= dwData[i]; 00782 TotalBlocks += (dwData[i] + dwMeta[i]); 00783 } 00784 else 00785 { 00786 ULONG dwDivide = 0; 00787 ULONG dwRemain = 0; 00788 00789 for (j=i; (j > 0) && (DataBlocks > 0); j--) 00790 { 00791 dwDivide = (DataBlocks) / (dwData[j-1]); 00792 dwRemain = (DataBlocks) % (dwData[j-1]); 00793 00794 TotalBlocks += (dwDivide * (dwData[j-1] + dwMeta[j-1]) + 1); 00795 DataBlocks = dwRemain; 00796 } 00797 } 00798 } 00799 00800 return (TotalBlocks + EXT2_NDIR_BLOCKS); 00801 } 00802 00803 00804 NTSTATUS 00805 NTAPI 00806 Ext2Format(IN PUNICODE_STRING DriveRoot, 00807 IN FMIFS_MEDIA_FLAG MediaFlag, 00808 IN PUNICODE_STRING Label, 00809 IN BOOLEAN QuickFormat, 00810 IN ULONG ClusterSize, 00811 IN PFMIFSCALLBACK Callback) 00812 { 00813 BOOLEAN bRet = FALSE; 00814 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00815 /* Super Block: 1024 bytes long */ 00816 EXT2_SUPER_BLOCK Ext2Sb; 00817 /* File Sys Structure */ 00818 EXT2_FILESYS FileSys; 00819 ULONG Percent; 00820 ULONG rsv; 00821 ULONG blocks; 00822 ULONG start; 00823 ULONG ret_blk; 00824 00825 00826 if (Callback != NULL) 00827 { 00828 Callback(PROGRESS, 0, (PVOID)&Percent); 00829 } 00830 00831 00832 RtlZeroMemory(&Ext2Sb, sizeof(EXT2_SUPER_BLOCK)); 00833 RtlZeroMemory(&FileSys, sizeof(EXT2_FILESYS)); 00834 FileSys.ext2_sb = &Ext2Sb; 00835 00836 00837 if (!NT_SUCCESS(Ext2OpenDevice(&FileSys, DriveRoot))) 00838 { 00839 DPRINT1("Mke2fs: Volume %wZ does not exist, ...\n", DriveRoot); 00840 goto clean_up; 00841 } 00842 00843 00844 if (!NT_SUCCESS(Ext2GetMediaInfo(&FileSys))) 00845 { 00846 DPRINT1("Mke2fs: Can't get media information\n"); 00847 goto clean_up; 00848 } 00849 00850 set_fs_defaults(NULL, &Ext2Sb, ClusterSize, &inode_ratio); 00851 00852 Ext2Sb.s_blocks_count = FileSys.PartInfo.PartitionLength.QuadPart / 00853 EXT2_BLOCK_SIZE(&Ext2Sb); 00854 00855 00856 /* 00857 * Calculate number of inodes based on the inode ratio 00858 */ 00859 Ext2Sb.s_inodes_count = 00860 (ULONG)(((LONGLONG) Ext2Sb.s_blocks_count * EXT2_BLOCK_SIZE(&Ext2Sb)) / inode_ratio); 00861 00862 /* 00863 * Calculate number of blocks to reserve 00864 */ 00865 Ext2Sb.s_r_blocks_count = (Ext2Sb.s_blocks_count * 5) / 100; 00866 00867 00868 Status = Ext2LockVolume(&FileSys); 00869 if (NT_SUCCESS(Status)) 00870 { 00871 bLocked = TRUE; 00872 } 00873 00874 00875 // Initialize 00876 if (!ext2_initialize_sb(&FileSys)) 00877 { 00878 DPRINT1("Mke2fs: error...\n"); 00879 goto clean_up; 00880 } 00881 00882 00883 zap_sector(&FileSys, 2, 6); 00884 00885 /* 00886 * Generate a UUID for it... 00887 */ 00888 { 00889 __u8 uuid[16]; 00890 uuid_generate(&uuid[0]); 00891 memcpy(&Ext2Sb.s_uuid[0], &uuid[0], 16); 00892 } 00893 00894 /* 00895 * Add "jitter" to the superblock's check interval so that we 00896 * don't check all the filesystems at the same time. We use a 00897 * kludgy hack of using the UUID to derive a random jitter value. 00898 */ 00899 { 00900 ULONG i, val; 00901 00902 for (i = 0, val = 0 ; i < sizeof(Ext2Sb.s_uuid); i++) 00903 val += Ext2Sb.s_uuid[i]; 00904 00905 Ext2Sb.s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT; 00906 } 00907 00908 /* 00909 * Set the volume label... 00910 */ 00911 if (Label) 00912 { 00913 ANSI_STRING ansi_label; 00914 ansi_label.MaximumLength = sizeof(Ext2Sb.s_volume_name); 00915 ansi_label.Length = 0; 00916 ansi_label.Buffer = Ext2Sb.s_volume_name; 00917 RtlUnicodeStringToAnsiString(&ansi_label, Label, FALSE); 00918 } 00919 00920 ext2_print_super(&Ext2Sb); 00921 00922 bRet = ext2_allocate_tables(&FileSys); 00923 00924 if (!bRet) 00925 { 00926 goto clean_up; 00927 } 00928 00929 /* rsv must be a power of two (64kB is MD RAID sb alignment) */ 00930 rsv = 65536 / FileSys.blocksize; 00931 blocks = Ext2Sb.s_blocks_count; 00932 00933 #ifdef ZAP_BOOTBLOCK 00934 DPRINT1("Mke2fs: zeroing volume boot record\n"); 00935 zap_sector(&FileSys, 0, 2); 00936 #endif 00937 00938 /* 00939 * Wipe out any old MD RAID (or other) metadata at the end 00940 * of the device. This will also verify that the device is 00941 * as large as we think. Be careful with very small devices. 00942 */ 00943 00944 start = (blocks & ~(rsv - 1)); 00945 if (start > rsv) 00946 start -= rsv; 00947 00948 if (start > 0) 00949 bRet = zero_blocks(&FileSys, start, blocks - start, &ret_blk, NULL); 00950 00951 if (!bRet) 00952 { 00953 DPRINT1("Mke2fs: zeroing block %lu at end of filesystem", ret_blk); 00954 goto clean_up; 00955 } 00956 00957 write_inode_tables(&FileSys); 00958 00959 create_root_dir(&FileSys); 00960 create_lost_and_found(&FileSys); 00961 00962 ext2_reserve_inodes(&FileSys); 00963 00964 create_bad_block_inode(&FileSys, NULL); 00965 00966 DPRINT("Mke2fs: Writing superblocks and filesystem accounting information ... \n"); 00967 00968 if (!QuickFormat) 00969 { 00970 DPRINT1("Mke2fs: Slow format not supported yet\n"); 00971 } 00972 00973 if (!ext2_flush(&FileSys)) 00974 { 00975 bRet = false; 00976 DPRINT1("Mke2fs: Warning, had trouble writing out superblocks.\n"); 00977 goto clean_up; 00978 } 00979 00980 DPRINT("Mke2fs: Writing superblocks and filesystem accounting information done!\n"); 00981 00982 bRet = true; 00983 Status = STATUS_SUCCESS; 00984 00985 clean_up: 00986 00987 // Clean up ... 00988 ext2_free_group_desc(&FileSys); 00989 00990 ext2_free_block_bitmap(&FileSys); 00991 ext2_free_inode_bitmap(&FileSys); 00992 00993 if (!bRet) 00994 { 00995 Ext2DisMountVolume(&FileSys); 00996 } 00997 else 00998 { 00999 if(bLocked) 01000 { 01001 Ext2UnLockVolume(&FileSys); 01002 } 01003 } 01004 01005 Ext2CloseDevice(&FileSys); 01006 01007 if (Callback != NULL) 01008 { 01009 Callback(DONE, 0, (PVOID)&bRet); 01010 } 01011 01012 return Status; 01013 } 01014 01015 NTSTATUS 01016 WINAPI 01017 Ext2Chkdsk(IN PUNICODE_STRING DriveRoot, 01018 IN BOOLEAN FixErrors, 01019 IN BOOLEAN Verbose, 01020 IN BOOLEAN CheckOnlyIfDirty, 01021 IN BOOLEAN ScanDrive, 01022 IN PFMIFSCALLBACK Callback) 01023 { 01024 UNIMPLEMENTED; 01025 return STATUS_SUCCESS; 01026 } Generated on Sat May 26 2012 04:35:04 for ReactOS by
1.7.6.1
|