Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / lib / ext2fs / initialize.c
index 4349244..1537968 100644 (file)
@@ -4,13 +4,17 @@
  * 
  * Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
  * 
+ * %Begin-Header%
  * This file may be redistributed under the terms of the GNU Public
  * License.
+ * %End-Header%
  */
 
 #include <stdio.h>
 #include <string.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <stdlib.h>
 #include <fcntl.h>
 #include <time.h>
@@ -47,7 +51,7 @@
 #ifdef EXT2_DFL_CHECKINTERVAL
 #undef EXT2_DFL_CHECKINTERVAL
 #endif
-#define EXT2_DFL_CHECKINTERVAL (86400 * 180)
+#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
 
 errcode_t ext2fs_initialize(const char *name, int flags,
                            struct ext2_super_block *param,
@@ -61,7 +65,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        int             overhead = 0;
        blk_t           group_block;
        int             i, j;
-       int             numblocks;
+       blk_t           numblocks;
        char            *buf;
 
        if (!param || !param->s_blocks_count)
@@ -77,6 +81,7 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        retval = manager->open(name, IO_FLAG_RW, &fs->io);
        if (retval)
                goto cleanup;
+       fs->io->app_data = fs;
        fs->device_name = malloc(strlen(name)+1);
        if (!fs->device_name) {
                retval = ENOMEM;
@@ -101,9 +106,15 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
        set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
        set_field(s_errors, EXT2_ERRORS_DEFAULT);
-
-
 #ifdef EXT2_DYNAMIC_REV
+       set_field(s_feature_compat, 0);
+       set_field(s_feature_incompat, 0);
+       set_field(s_feature_ro_compat, 0);
+       if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)
+               return EXT2_ET_UNSUPP_FEATURE;
+       if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)
+               return EXT2_ET_RO_UNSUPP_FEATURE;
+
        set_field(s_rev_level, EXT2_GOOD_OLD_REV);
        if (super->s_rev_level >= EXT2_DYNAMIC_REV) {
                set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO);
@@ -120,7 +131,8 @@ errcode_t ext2fs_initialize(const char *name, int flags,
        fs->fragsize = EXT2_FRAG_SIZE(super);
        frags_per_block = fs->blocksize / fs->fragsize;
        
-       set_field(s_blocks_per_group, 8192); /* default: 8192 blocks/group */
+       /* default: (fs->blocksize*8) blocks/group */
+       set_field(s_blocks_per_group, fs->blocksize*8); 
        super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
        
        super->s_blocks_count = param->s_blocks_count;
@@ -190,18 +202,19 @@ retry:
         * includes the superblock backup, the group descriptor
         * backups, the inode bitmap, the block bitmap, and the inode
         * table.
+        *
+        * XXX Not all block groups need the descriptor blocks, but
+        * being clever is tricky...
         */
-       overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
-       super->s_free_blocks_count = super->s_blocks_count -
-               super->s_first_data_block - (overhead*fs->group_desc_count);
+       overhead = (int) (3 + fs->desc_blocks + fs->inode_blocks_per_group);
        
        /*
         * See if the last group is big enough to support the
         * necessary data structures.  If not, we need to get rid of
         * it.
         */
-       rem = (super->s_blocks_count - super->s_first_data_block) %
-               super->s_blocks_per_group;
+       rem = (int) ((super->s_blocks_count - super->s_first_data_block) %
+                    super->s_blocks_per_group);
        if ((fs->group_desc_count == 1) && rem && (rem < overhead))
                return EXT2_ET_TOOSMALL;
        if (rem && (rem < overhead+50)) {
@@ -233,12 +246,12 @@ retry:
 
        free(buf);
 
-       fs->group_desc = malloc(fs->desc_blocks * fs->blocksize);
+       fs->group_desc = malloc((size_t) fs->desc_blocks * fs->blocksize);
        if (!fs->group_desc) {
                retval = ENOMEM;
                goto cleanup;
        }
-       memset(fs->group_desc, 0, fs->desc_blocks * fs->blocksize);
+       memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize);
 
        /*
         * Reserve the superblock and group descriptors for each
@@ -248,11 +261,8 @@ retry:
         * by this routine), they are accounted for nevertheless.
         */
        group_block = super->s_first_data_block;
+       super->s_free_blocks_count = 0;
        for (i = 0; i < fs->group_desc_count; i++) {
-               for (j=0; j < fs->desc_blocks+1; j++)
-                       ext2fs_mark_block_bitmap(fs->block_map,
-                                                group_block + j);
-
                if (i == fs->group_desc_count-1) {
                        numblocks = (fs->super->s_blocks_count -
                                     fs->super->s_first_data_block) %
@@ -261,8 +271,17 @@ retry:
                                numblocks = fs->super->s_blocks_per_group;
                } else
                        numblocks = fs->super->s_blocks_per_group;
-               numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group;
+
+               if (ext2fs_bg_has_super(fs, i)) {
+                       for (j=0; j < fs->desc_blocks+1; j++)
+                               ext2fs_mark_block_bitmap(fs->block_map,
+                                                        group_block + j);
+                       numblocks -= 1 + fs->desc_blocks;
+               }
+               
+               numblocks -= 2 + fs->inode_blocks_per_group;
                
+               super->s_free_blocks_count += numblocks;
                fs->group_desc[i].bg_free_blocks_count = numblocks;
                fs->group_desc[i].bg_free_inodes_count =
                        fs->super->s_inodes_per_group;