home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / win95 / ext2tool.exe / EXT2FS / INIT.C < prev    next >
C/C++ Source or Header  |  1995-05-10  |  7KB  |  233 lines

  1. /*
  2.  * initialize.c --- initialize a filesystem handle given superblock
  3.  *     parameters.  Used by mke2fs when initializing a filesystem.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include <fcntl.h>
  11. #include <time.h>
  12. #include <sys/stat.h>
  13. #include <sys/types.h>
  14. #include <errno.h>
  15.  
  16. #include <linux/ext2_fs.h>
  17.  
  18. #include "ext2fs.h"
  19.  
  20. errcode_t ext2fs_initialize(const char *name, int flags,
  21.                 struct ext2_super_block *param,
  22.                 io_manager manager, ext2_filsys *ret_fs)
  23. {
  24.     ext2_filsys    fs;
  25.     errcode_t    retval;
  26.     struct ext2_super_block *super;
  27.     int        frags_per_block;
  28.     int        rem;
  29.     int        overhead = 0;
  30.     blk_t        group_block;
  31.     int        i, j;
  32.     int        numblocks;
  33.     char        *buf;
  34.  
  35.     if (!param || !param->s_blocks_count)
  36.         return EINVAL;
  37.     
  38.     fs = (ext2_filsys) malloc(sizeof(struct struct_ext2_filsys));
  39.     if (!fs)
  40.         return ENOMEM;
  41.     
  42.     memset(fs, 0, sizeof(struct struct_ext2_filsys));
  43.     fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS;
  44.     fs->flags = flags | EXT2_FLAG_RW;
  45.     retval = manager->open(name, IO_FLAG_RW, &fs->io);
  46.     if (retval)
  47.         goto cleanup;
  48.     fs->device_name = malloc(strlen(name)+1);
  49.     if (!fs->device_name) {
  50.         retval = ENOMEM;
  51.         goto cleanup;
  52.     }
  53.     strcpy(fs->device_name, name);
  54.     fs->super = super = malloc(SUPERBLOCK_SIZE);
  55.     if (!super) {
  56.         retval = ENOMEM;
  57.         goto cleanup;
  58.     }
  59.     memset(super, 0, SUPERBLOCK_SIZE);
  60.  
  61. #define set_field(field, default) (super->field = param->field ? \
  62.                    param->field : (default))
  63.  
  64.     super->s_magic = EXT2_SUPER_MAGIC;
  65.     super->s_state = EXT2_VALID_FS;
  66.  
  67.     set_field(s_log_block_size, 0);    /* default blocksize: 1024 bytes */
  68.     set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */
  69.     set_field(s_first_data_block, super->s_log_block_size ? 0 : 1);
  70.     set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT);
  71.     set_field(s_errors, EXT2_ERRORS_DEFAULT);
  72.  
  73.     set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL);
  74.     super->s_lastcheck = time(NULL);
  75.  
  76. #ifdef    EXT2_OS_LINUX
  77.     super->s_creator_os = EXT2_OS_LINUX;
  78. #endif
  79.  
  80.     fs->blocksize = EXT2_BLOCK_SIZE(super);
  81.     fs->fragsize = EXT2_FRAG_SIZE(super);
  82.     frags_per_block = fs->blocksize / fs->fragsize;
  83.     
  84.     set_field(s_blocks_per_group, 8192); /* default: 8192 blocks/group */
  85.     super->s_frags_per_group = super->s_blocks_per_group * frags_per_block;
  86.     
  87.     super->s_blocks_count = param->s_blocks_count;
  88.     super->s_r_blocks_count = param->s_r_blocks_count;
  89.     if (super->s_r_blocks_count >= param->s_blocks_count) {
  90.         retval = EINVAL;
  91.         goto cleanup;
  92.     }
  93.  
  94. retry:
  95.     fs->group_desc_count = (super->s_blocks_count -
  96.                 super->s_first_data_block +
  97.                 EXT2_BLOCKS_PER_GROUP(super) - 1)
  98.         / EXT2_BLOCKS_PER_GROUP(super);
  99.     fs->desc_blocks = (fs->group_desc_count +
  100.                EXT2_DESC_PER_BLOCK(super) - 1)
  101.         / EXT2_DESC_PER_BLOCK(super);
  102.  
  103.     set_field(s_inodes_count, (super->s_blocks_count*fs->blocksize)/4096);
  104.  
  105.     /*
  106.      * There should be at least as many inodes as the user
  107.      * requested.  Figure out how many inodes per group that
  108.      * should be.
  109.      */
  110.     super->s_inodes_per_group = (super->s_inodes_count +
  111.                      fs->group_desc_count - 1) /
  112.                          fs->group_desc_count;
  113.     
  114.     /*
  115.      * Make sure the number of inodes per group completely fills
  116.      * the inode table blocks in the descriptor.  If not, add some
  117.      * additional inodes/group.  Waste not, want not...
  118.      */
  119.     fs->inode_blocks_per_group = (super->s_inodes_per_group +
  120.                       EXT2_INODES_PER_BLOCK(super) - 1) /
  121.                           EXT2_INODES_PER_BLOCK(super);
  122.     super->s_inodes_per_group = fs->inode_blocks_per_group *
  123.         EXT2_INODES_PER_BLOCK(super);
  124.         
  125.     /*
  126.      * adjust inode count to reflect the adjusted inodes_per_group
  127.      */
  128.     super->s_inodes_count = super->s_inodes_per_group *
  129.         fs->group_desc_count;
  130.     super->s_free_inodes_count = super->s_inodes_count;
  131.  
  132.     /*
  133.      * Overhead is the number of bookkeeping blocks per group.  It
  134.      * includes the superblock backup, the group descriptor
  135.      * backups, the inode bitmap, the block bitmap, and the inode
  136.      * table.
  137.      */
  138.     overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group;
  139.     super->s_free_blocks_count = super->s_blocks_count -
  140.         super->s_first_data_block - (overhead*fs->group_desc_count);
  141.     
  142.     /*
  143.      * See if the last group is big enough to support the
  144.      * necessary data structures.  If not, we need to get rid of
  145.      * it.
  146.      */
  147.     rem = (super->s_blocks_count - super->s_first_data_block) %
  148.         super->s_blocks_per_group;
  149.     if ((fs->group_desc_count == 1) && rem && (rem < overhead))
  150.         return EXT2_ET_TOOSMALL;
  151.     if (rem && (rem < overhead+50)) {
  152.         super->s_blocks_count -= rem;
  153.         goto retry;
  154.     }
  155.  
  156.     /*
  157.      * At this point we know how big the filesystem will be.  So
  158.      * we can do any and all allocations that depend on the block
  159.      * count.
  160.      */
  161.  
  162.     buf = malloc(strlen(fs->device_name) + 80);
  163.     if (!buf) {
  164.         retval = ENOMEM;
  165.         goto cleanup;
  166.     }
  167.     
  168.     sprintf(buf, "block bitmap for %s", fs->device_name);
  169.     retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map);
  170.     if (retval)
  171.         goto cleanup;
  172.     
  173.     sprintf(buf, "inode bitmap for %s", fs->device_name);
  174.     retval = ext2fs_allocate_inode_bitmap(fs, 0, &fs->inode_map);
  175.     if (retval)
  176.         goto cleanup;
  177.  
  178.     free(buf);
  179.  
  180.     fs->group_desc = malloc(fs->desc_blocks * fs->blocksize);
  181.     if (!fs->group_desc) {
  182.         retval = ENOMEM;
  183.         goto cleanup;
  184.     }
  185.     memset(fs->group_desc, 0, fs->desc_blocks * fs->blocksize);
  186.  
  187.     /*
  188.      * Reserve the superblock and group descriptors for each
  189.      * group, and fill in the correct group statistics for group.
  190.      * Note that although the block bitmap, inode bitmap, and
  191.      * inode table have not been allocated (and in fact won't be
  192.      * by this routine), they are accounted for nevertheless.
  193.      */
  194.     group_block = super->s_first_data_block;
  195.     for (i = 0; i < fs->group_desc_count; i++) {
  196.         for (j=0; j < fs->desc_blocks+1; j++)
  197.             ext2fs_mark_block_bitmap(fs->block_map,
  198.                          group_block + j);
  199.  
  200.         if (i == fs->group_desc_count-1) {
  201.             numblocks = (fs->super->s_blocks_count -
  202.                      fs->super->s_first_data_block) %
  203.                          fs->super->s_blocks_per_group;
  204.             if (!numblocks)
  205.                 numblocks = fs->super->s_blocks_per_group;
  206.         } else
  207.             numblocks = fs->super->s_blocks_per_group;
  208.         numblocks -= 3 + fs->desc_blocks + fs->inode_blocks_per_group;
  209.         
  210.         fs->group_desc[i].bg_free_blocks_count = numblocks;
  211.         fs->group_desc[i].bg_free_inodes_count =
  212.             fs->super->s_inodes_per_group;
  213.         fs->group_desc[i].bg_used_dirs_count = 0;
  214.         
  215.         group_block += super->s_blocks_per_group;
  216.     }
  217.     
  218.     ext2fs_mark_super_dirty(fs);
  219.     ext2fs_mark_bb_dirty(fs);
  220.     ext2fs_mark_ib_dirty(fs);
  221.     
  222.     io_channel_set_blksize(fs->io, fs->blocksize);
  223.  
  224.     *ret_fs = fs;
  225.     return 0;
  226. cleanup:
  227.     ext2fs_free(fs);
  228.     return retval;
  229. }
  230.     
  231.  
  232.  
  233.