ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

Mke2fs.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.