File: disk.c | Size: 4,308 bytes | Download file | Back to directory listing | BWPOW's homepage
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ext2sim.h"
 
FILE *fs_file;
char fs_state;
 
extern S_SUPERBLOCK superblock;
extern FS_INFO info;
extern char *block_bitmap;
extern char *inode_bitmap;
extern S_GROUP_DESCRIPTOR group_desc[MAX_GROUPS];
 
int mount_fs(char *fname,char state)
{
  int block_size;
  if(fs_state!=FS_STATE_NOT_MOUNTED) return -1;
 
  if(state==FS_STATE_MOUNTED_RW){
    fs_file=fopen(fname,"rb+");
    if(fs_file==0){
      fs_file=fopen(fname,"wb");
      if(fs_file==0) return -3;
    }
  }
  if(state==FS_STATE_MOUNTED_RO){
    fs_file=fopen(fname,"rb");
    if(fs_file==0) return -2;
  }
  fs_state=state;
 
  if(fs_state!=FS_STATE_MOUNTED_RW&&fs_state!=FS_STATE_MOUNTED_RO) return -5;
  if(fs_file==0) return -6;
 
  if(read_superblock()!=0){
    printf("UNKNOWN/EMPTY FS!\n");
    deinitialise_bitmaps();
  }
  else{
    printf("EXT2FS:\n");
    block_size=1024<<superblock.s_log_block_size;
    info.block_size=block_size;
    info.sektors_per_block=block_size/512;
    info.group_desc_start=superblock.s_first_data_block+1;
    info.first_group_start=info.group_desc_start+info.sektors_per_block;
    info.group_size=2+superblock.s_blocks_per_group+ceil((double)superblock.s_inodes_per_group*128/1024);
 
    info.group_count=ceil((double)superblock.s_inodes_count/(double)superblock.s_inodes_per_group);
 
    initialise_bitmaps();
 
    if(read_group_descriptor()!=0){
      printf("Can't read group descriptor!\n");
    }
    else{
      if(check()==0){
        printf("Block size = %d bytes, %d groups\n",block_size,info.group_count);
        printf("%d free inodes (%d inodes total)\n",superblock.s_free_inodes_count,superblock.s_inodes_count);
        printf("%d free blocks (%d blocks total)\n",superblock.s_free_blocks_count,superblock.s_block_count);
        printf("%d free kbytes (%d kbytes total)\n",superblock.s_free_blocks_count*block_size/1024,superblock.s_block_count*block_size/1024);
      }
    }
 
  }
 
  return 0;
}
 
int umount_fs(void)
{
  if(fs_state==FS_STATE_NOT_MOUNTED) return -1;
  fclose(fs_file);
  fs_state=FS_STATE_NOT_MOUNTED;
  return 0;
}
 
int read_sector(int num,unsigned char buf[512])
{
  if(fs_state==FS_STATE_NOT_MOUNTED) return -1;
  fseek(fs_file,num*512,SEEK_SET);
  if(ftell(fs_file)!=num*512) return -2;
  if(fread(buf,1,512,fs_file)!=512) return -3;
  return 0;
}
 
int write_sector(int num,unsigned char buf[512])
{
  if(fs_state!=FS_STATE_MOUNTED_RW) return -1;
  fseek(fs_file,num*512,SEEK_SET);
  if(ftell(fs_file)!=num*512) return -2;
  if(fwrite(buf,1,512,fs_file)!=512) return -3;
  return 0;
}
 
int write_block(int num,int l,unsigned char *buf)
{
  if(fs_state!=FS_STATE_MOUNTED_RW) return -1;
  fseek(fs_file,num*info.block_size,SEEK_SET);
  if(ftell(fs_file)!=num*info.block_size) return -2;
//  if(l>info.block_size) l=info.block_size;
  if(fwrite(buf,1,l,fs_file)!=l) return -3;
  return 0;
}
 
int read_block(int num,int l,unsigned char *buf)
{
  if(fs_state==FS_STATE_NOT_MOUNTED) return -1;
  fseek(fs_file,num*info.block_size,SEEK_SET);
  if(ftell(fs_file)!=num*info.block_size) return -2;
//  if(l>info.block_size) l=info.block_size;
  if(fread(buf,1,l,fs_file)!=l) return -3;
  return 0;
}
 
int create_disk(int num)
{
  unsigned char buf[512];
  int i;
 
  if(fs_state!=FS_STATE_MOUNTED_RW) return -1;
 
  fseek(fs_file,0,SEEK_SET);
 
  for(i=0;i<512;i++) buf[i]=0;
  for(i=0;i<num;i++){
    if(fwrite(buf,1,512,fs_file)!=512) return -2;
  }
 
  return 0;
}
 
int read_inode(int num,S_INODE *inode)
{
  int bl,s,i;
  unsigned char *buf;
  num--;
  if(num<0||num>=superblock.s_inodes_count) return -1;
  bl=num/superblock.s_inodes_per_group;
 
  s=128*superblock.s_inodes_per_group;
  buf=(unsigned char *) malloc(s);
  if(buf==0) return -2;
  if(read_block(group_desc[bl].bg_inode_table,s,buf)!=0){
    free(buf);
    return -3;
  }
 
  bl=(num%superblock.s_inodes_per_group)*128;
  memcpy((unsigned char *)inode,buf+bl,128);
  free(buf);
  return 0;
}
 
int read_blocks(unsigned int i_block[15],int l,unsigned char *buf)
{
  int i=0,pos=0,r;
  while(l>0){
    if(i<12){
      if(l>info.block_size) r=info.block_size;
      else r=l;
      if(read_block(i_block[i],r,buf+pos)!=0) return -1;
      pos+=info.block_size;
      l-=info.block_size;
    }
    else return -1;
    i++;
  }
  return 0;
}