/*
 * mkfs.c
 *
 * Copyright 2003, Minoru Murashima. All rights reserved.
 * Distributed under the terms of the BSD License.
 *
 * オリジナルファイルシステムを構築する。
 */


#include"types.h"
#include"lib.h"
#include"mm.h"
#include"fs.h"
#include"device.h"
#include"orig_fs.h"


/*
 * parameters : device path
 * return : 0 or error=-1
 */
int mk_orig_fs(const char *dev_path)
{
	void *dbuf;
	int fd;
	int din;
	SUPER_BLOCK *sbuf;
	ENPTY_BLOCK *ebuf=NULL;
	DEV_STAT dev_stat;
	int i,j,last,emp_num,index;


	/* Device open */
	if((fd=sys_open(dev_path,0))==-1)return -1;
	if((din=get_inode(fd))==-1)return -1;

	/* パーティションタイプの確認。 */
	if(get_dev_stat(din,&dev_stat)==-1)return -1;
	if(dev_stat.prt_type!=PT_TYPE_ORIG)return -1;

	/* スーパーブロックの設定。 */
	if((sbuf=(SUPER_BLOCK*)kmalloc(sizeof(SUPER_BLOCK)))==NULL)return -1;
	sbuf->secters=BLOCK_SIZE/dev_stat.sect_size;
	sbuf->all_blk=dev_stat.all_sect/sbuf->secters;
	sbuf->magic_number=SBLOCK_MAGIC;
	sbuf->useable_blk=(dev_stat.all_sect-SBLOCK_SECTER)/sbuf->secters-1;

	/* root directory の設定 */
	sbuf->root_blk=SBLOCK_SECTER+sbuf->secters;
	if((dbuf=kmalloc(BLOCK_SIZE))==NULL)goto ERR;
	make_dir(dbuf,sbuf->root_blk);
	if(write_direct(din,dbuf,sbuf->secters,sbuf->root_blk)!=sbuf->secters)goto ERR;
	kfree(dbuf);

	/* 空きブロックインデックスの設定。 */
	if((ebuf=(ENPTY_BLOCK*)kmalloc(BLOCK_SIZE))==NULL)goto ERR;
	emp_num=(BLOCK_SIZE-sizeof(ENPTY_BLOCK))/sizeof(uint);
	last=dev_stat.all_sect-sbuf->secters;
	index=sbuf->root_blk+sbuf->secters;
	j=0;
	for(i=index;i<last;i+=sbuf->secters)
	{
		ebuf->empty[j++]=i;
		
		if(j>=emp_num)
		{
			ebuf->current=0;
			if(write_direct(din,ebuf,sbuf->secters,index)!=sbuf->secters)goto ERR;
			index=i;
			j=0;
			printk("Init empty index %d%%\r",i/(dev_stat.all_sect/100));		/* 進行状況表示。 */
		}
	}
	ebuf->empty[j]=0;
	if(write_direct(din,ebuf,sbuf->secters,index)!=sbuf->secters)goto ERR;
	printk("Init empty index 100%%\n");				/* 進行状況表示。 */
	kfree(ebuf);

	sbuf->empty_blk=sbuf->root_blk+sbuf->secters;
	
	/* スーパーブロックを書き込む。 */
	write_direct(din,sbuf,(sizeof(SUPER_BLOCK)+dev_stat.sect_size-1)/dev_stat.sect_size,SBLOCK_SECTER);
	kfree(sbuf);

	/* device close */
	return sys_close(fd);

ERR:
	kfree(ebuf);
	kfree(sbuf);
	sys_close(fd);

	return -1;
}
