#include <stdio.h>

#include "types.h"
#include "stat.h"
#include "filesys.h"
#include "dir.h"


/* This makes a filesystem */

int dev;

_main(argc,argv)
int argc;
char *argv[];
{
    uint16 fsize, isize;

    if (argc != 4)
    {
	printf("Usage: mkfs device isize fsize\n");
	exit(-1);
    }

    dev = open(argv[1],2);
    isize = (uint16)atoi(argv[2]);
    fsize = (uint16)atoi(argv[3]);

    if (dev < 0)
    {
	printf("Cant open device\n");
	exit(-1);
    }

    if (fsize < 3 || isize < 2 || isize >= fsize)
    {
	printf("Bad parameter values\n");
	exit(-1);
    }


    printf("Making filesystem on device %s with isize %u fsize %u. Confirm? ",
	    argv[1],isize,fsize);
    if (!yes())
	exit(-1);

    mkfs(fsize,isize);
    exit(0);
}




static struct dinode inode[8];
struct direct dirbuf[32] = { ROOTINODE,".",ROOTINODE,".." };
static struct filesys filsys;
static char zerobuf[512];

mkfs(fsize, isize)
uint16 fsize, isize;
{
    uint16 j;

    /* Zero out the blocks */

#ifdef vax
    for (j=0; j < fsize; ++j)
	dwrite(j,zerobuf);
#else
    for (j=0; j < isize; ++j)   /* Don't waste time in CPM */
	dwrite(j,zerobuf);
#endif

    /* Initialize the super-block */

    filsys.s_mounted = SMOUNTED; /* Magic number */
    filsys.s_isize =  isize;
    filsys.s_fsize =  fsize;
    filsys.s_nfree =  1;
    filsys.s_free[0] =  0;
    filsys.s_tfree =  0;
    filsys.s_ninode = 0;
    filsys.s_tinode =  8 * (isize-2) - 2;

    /* Free each block, building the free list */

    for (j= fsize-1; j >= isize+1; --j)
    {
	if (filsys.s_nfree == 50)
	{
	    dwrite(j, (char *)&filsys.s_nfree);
	    filsys.s_nfree = 0;
	}

	++filsys.s_tfree;
	filsys.s_free[(filsys.s_nfree)++] = j;
    }

    /* The inodes are already zeroed out */
    /* create the root dir */


    inode[ROOTINODE].i_mode = F_DIR | (0777 & MODE_MASK);
    inode[ROOTINODE].i_nlink = 3;
    inode[ROOTINODE].i_size.o_blkno = 0;
    inode[ROOTINODE].i_size.o_offset = 32;
    inode[ROOTINODE].i_addr[0] = isize;

    /* Reserve reserved inode */
    inode[0].i_nlink = 1;
    inode[0].i_mode = ~0;

    dwrite(2,(char *)inode);

    dwrite(isize,(char *)dirbuf);

    /* Write out super block */
    dwrite(1,(char *)&filsys);
}


dwrite(blk, addr)
uint16 blk;
char *addr;
{
    
    if (seek(dev,blk,3) == -1 || write(dev,addr,512) != 512)
    {
        fprintf(stderr,"Write of block %d failed.\n",blk);
        abort();
    }
}
    

yes()
{
    char line[20];

    if (!fgets(line,sizeof(line),stdin) || (*line != 'y' && *line != 'Y'))
	return(0);

    return(1);
}


/* This prints an error message and dies. */

panic(s)
char *s;
{
    fprintf(stderr,"PANIC: %s\n",s);
    abort();
}


#ifdef vax

int seek(fd, offset, mode)
int fd, mode;
int offset;
{
    long lseek();
    long stat;

    if (mode > 2)
    {
	mode -= 3;
	offset *= 512;
    }
    stat = lseek(fd, (long)offset, mode);

    return ( stat== -1 ? -1 : 0);
}

#endif


abort()
{
#asm 8080
	DI
	JMP	$
#endasm
}
