⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatvol.cpp

📁 Jazmyn is a 32-bit, protected mode, multitasking OS which runs on i386 & above CPU`s. Its complete
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) 2004, Thejesh AP. All rights reserved.
 */

#include <sys\types.h>
#include <null.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <mm\new.h>
#include <drivers\drvreq.h>
#include <drivers\console.h>
#include <drivers\keyboard.h>
#include <fs\devmgr.h>
#include <mm\heap.h>
#include <fs\fatbuffer.h>
#include <fs\fatvol.h>

extern heap _heap_obj;

//#define __FATVOLUME_DEBUG


#define NUM_ENTRIES	((_bpb.spc * _bpb.bps) / sizeof(fdir))
#define CLUSTER_SZ	(_bpb.spc * _bpb.bps)
#define FSOC(N)		(((N - 2) * _bpb.spc) + fds)
#define LLE             0x40

fdir            FATvolume::root = {0,0,0,0,0,0,0,0,0,0,0,0};
fdir		FATvolume::pwd = {0,0,0,0,0,0,0,0,0,0,0,0};
fdir		FATvolume::ppwd = {0,0,0,0,0,0,0,0,0,0,0,0};
uint            FATvolume::totsz = 0;
fatbuffer       FATvolume::_fb;

extern device_manager _dev_mgr;
int gnflag = 0;

FATvolume::FATvolume()
{

}

FATvolume::~FATvolume()
{
	if(mounted) mounted = FALSE;
}

void FATvolume::init_volume(uint start,uint end,char drv,int slt_nr,int dv_nr)
{
	mounted = FALSE;
	drive = drv;
	_pi.start_sec = start;
	_pi.end_sec = end;
	slot = slt_nr;
	dev = dv_nr;
	disk_req req;
	byte buf[512];

        _CR(req,DISK_READ,dev,start,1,buf);
        if(_dev_mgr.driver_tab[slot].main(&req) < 0) return;
	
        strncpy((char*)_bpb.OEMname,(char*)&buf[3],8);
	_bpb.bps = *(ushort*)&buf[11];
	_bpb.spc = buf[13];
	_bpb.rsc = *(ushort*)&buf[14];
	_bpb.numFATs = buf[16];
	_bpb.rec = *(ushort*)&buf[17];
	_bpb.totsec16 = *(ushort*)&buf[19];
	_bpb.media = buf[21];
	_bpb.FATsz16 = *(ushort*)&buf[22];
	_bpb.spt = *(ushort*)&buf[24];
	_bpb.numheads = *(ushort*)&buf[26];
	_bpb.totsec32 = *(uint*)&buf[32];
	_bpb.FATsz32 = *(uint*)&buf[36];
	
	#ifdef __FATVOLUME_DEBUG
		cout<<"OEM name      :";
                for(int i=0;i<8;i++)
                        cout<<(char)_bpb.OEMname[i];
		cout<<endl;  
                cout<<"Bytes per sec :"<<_bpb.bps<<endl;
                cout<<"Sec per clus  :"<<(int)_bpb.spc<<endl;
                cout<<"Res sec cnt   :"<<_bpb.rsc<<endl;
                cout<<"Num FATs      :"<<(int)_bpb.numFATs<<endl;
		cout<<"Root ent cnt  :"<<_bpb.rec<<endl;
     		cout<<"Total sec16   :"<<_bpb.totsec16<<endl;
                cout<<"Media ID      :"<<(int)_bpb.media<<endl;
                cout<<"FAT sz16      :"<<_bpb.FATsz16<<endl;
                cout<<"Sec per track :"<<_bpb.spt<<endl;
                cout<<"Num heads     :"<<_bpb.numheads<<endl;
                cout<<"Tot sec32     :"<<_bpb.totsec32<<endl;
                cout<<"FAT sz32      :"<<_bpb.FATsz32<<endl;
	#endif


	if(is_FAT())
	{
		mounted = TRUE;
		rds = ((_bpb.rec * 32) + (_bpb.bps - 1)) / _bpb.bps;
		FATstart = _bpb.rsc;
		FATsz = (_bpb.FATsz16) ? _bpb.FATsz16 : _bpb.FATsz32;
                fds = _bpb.rsc + (_bpb.numFATs * FATsz) + rds;
		totsec = (_bpb.totsec16) ? _bpb.totsec16 : _bpb.totsec32;
		datasec = totsec - (_bpb.rsc + (_bpb.numFATs * FATsz) + rds);
		coc = datasec / _bpb.spc;
		if(coc < 4085) FATtype = FAT12;
		else if(coc < 65525) FATtype = FAT16;
		else FATtype = FAT32;

                /* only for testing delete me*/
                FATtype = FAT32;

                totsz += FATsz * _bpb.bps;

		#ifdef __FATVOLUME_DEBUG
			cout<<"Root dir secs :"<<rds<<endl;
			cout<<"FAT start     :"<<FATstart<<endl;
			cout<<"FATsz in sec  :"<<FATsz<<endl;
			cout<<"First data sec:"<<fds<<endl;
			cout<<"Total sec     :"<<totsec<<endl;
			cout<<"Data sec      :"<<datasec<<endl;
			cout<<"Count of clus :"<<coc<<endl;
			cout<<"FAT type      :"<<FATtype<<endl;
		#endif    
	}
}

int FATvolume::is_FAT()
{
	/* This is wrong. the condition should be changed */	
/*        if(
           (strncmp("MSWIN4.1",(char*)_bpb.OEMname,8) == 0) ||
           (strncmp("MSDOS5.0",(char*)_bpb.OEMname,8) == 0) ||
           (strncmp("MKDOSFS",(char*)_bpb.OEMname,7) == 0)
          )*/
	return 1;
//        return 0;
}

int FATvolume::mount()
{
	if(mounted) return -1;
	disk_req req;
	byte buf[512];	
        _CR(req,DISK_READ,dev,_pi.start_sec,1,buf);
        if(_dev_mgr.driver_tab[slot].main(&req) < 0) return -1;
	_bpb = *(BPB*)buf;
	if(is_FAT())
	{
		mounted = TRUE;
		rds = ((_bpb.rec * 32) + (_bpb.bps - 1)) / _bpb.bps;
		FATstart = _bpb.rsc;
		FATsz = (_bpb.FATsz16) ? _bpb.FATsz16 : _bpb.FATsz32;
                fds = _bpb.rsc + (_bpb.numFATs * FATsz) + rds;
		totsec = (_bpb.totsec16) ? _bpb.totsec16 : _bpb.totsec32;
		datasec = totsec - (_bpb.rsc + (_bpb.numFATs * FATsz) + rds);
		coc = datasec / _bpb.spc;
		if(coc < 4085) FATtype = FAT12;
		else if(coc < 65525) FATtype = FAT16;
		else FATtype = FAT32;
	}
	return 0;
}	

int FATvolume::unmount()
{
	if(!mounted) return -1;
	mounted = FALSE;
	return 0;
}

char* FATvolume::get_next_name(char* path,char* pname)
{
        static int rf = 0;
        if(rf)
        {
                rf=0;
                return NULL;
        }
	int i = 0;
	if(*path == '\\') path++;
	while(*path && *path !='\\') pname[i++] = *path++;
	pname[i] = '\0';
        if(*path == '\0')
        {
                rf=1;
                return path;
        }
	return ++path;
}
	
fdir* FATvolume::get_dir_entry(char *name,uint &n,uint &clus_nr,uint &index)
{
	/* the search is always in pwd except */


        fdir *dir = new fdir[NUM_ENTRIES];

        char org[255];
        char cname[255];
	strcpy(org,name);
	uint start,buf_size;
        start = get_start_clus(&pwd);

	int present = FALSE;
        uint num;
	clus_nr = 0;
        uint i;
        if(!(name = gen_basis_name(name))) return NULL;
        strcpy(cname,name);

	while((start = get_next_clus(start,clus_nr,dir))!=0xFFFFFFFF)
	{
                if(is_8_3(org))
		{
                        for(i=0;i<NUM_ENTRIES;i++)
			{
                                if(strncmp((char*)dir[i].dir_name,cname,11) == 0)
				{
                                	present = TRUE;
                                        gnflag = 0;
                                        goto success;
				}
			}
		}
		else
		{
                        char *uni = (char*)get_unicode(name,num);
                        fldir *ldir = (fldir*)dir;
			/* should be improved */
			for(int i=num-1;i<NUM_ENTRIES;i++)
			{
				int ord = 1;
                                int k;
                                for(k=i;k>i-num;k--)
				{
					
                                        if(
                                        (strncmp((char*)ldir[k].ldir_name1,uni,10) == 0) &&
                                        (strncmp((char*)ldir[k].ldir_name2,uni+=10,12) == 0) &&
                                        (strncmp((char*)ldir[k].ldir_name3,uni+=12,4) == 0) &&
                                        (ldir[k].ldir_ord & ord == ord)
					  )
					 ord++;
				}
				if(ord == num+1 && (ldir[k+1].ldir_ord & LLE))
				{	
					i++;
					present = TRUE;
                                        gnflag = 0;
                                        goto success;
				}
			}
		}
	}
success:
	if(!present)
	{
		/* 
		*the dir entry is not present & the start clus of parent dir is in
		*'start' & the read_buffer is in 'dir','last_dir' contains the parent
		*dir entry.
		*/
		return NULL;
	}
	if(!is_dot_dotdot(name))
                n = (is_8_3(org)) ? 2 : num + 1;
	else
		n = 1;
	index = i;

        return dir;
}

int FATvolume::put_dir_entry(char *name,byte attr,uint fsize)
{
	if(!mounted) return -1;
        uint t1,t2,t3;
	if(get_dir_entry(name,t1,t2,t3)) return -1;
        uint start = get_start_clus(&pwd);
	int nfe = get_nfe(name);
	fdir *dir = new fdir[NUM_ENTRIES];
	uint clus_nr = 0;
	while((start = get_next_clus(start,clus_nr,dir))!=0xFFFFFFFF)
	{
		int flag = 0;
		/* should be improved */
                int i;
                for(i=0;i<(NUM_ENTRIES-nfe)+1;i++)
		{
			if(dir[i].dir_name[0] = 0x00)
			{
				flag = 1;
				break;
			}
			for(int j=i;j<i+nfe;j++)
			flag = (dir[j].dir_name[0] == 0xE5) ? 1 : 0;
			if(flag) break;
		}
		if(flag)
		{
                        /* dir[i]..dir[i+nfe-1] is avaiable*/
                        if(creat_dir_entry(name,dir,i,nfe,attr,fsize) < 0)
                        {
                                delete dir;
                                return -1;
                        }
                        if(write_clus(clus_nr,dir) < 0)
                        {
                                delete dir;
                                return -1;
                        }
			return 0;
		}
	}
        if(start == -1)
        {
                delete dir;
                return -1;
        }
	/* No room in cluster chain, so expand cluster chain.last_clus = eoc in chain*/		
	uint new_clus;
        if(!(new_clus = expand_clus(clus_nr)))
        {
                delete dir;
                return -1;
        }
        memset(dir,0,NUM_ENTRIES*sizeof(fdir));
        if(creat_dir_entry(name,dir,0,nfe,attr,fsize) < 0)
        {
                delete dir;
                return -1;
        }
        if(write_clus(new_clus,dir) < 0)
        {
                delete dir;
                return -1;
        }
	return 0;
}

int FATvolume::creat_dir_entry(char *name,fdir *dir,uint start,uint nfe,byte attr,uint fsize)
{
        int b = start+nfe-1;
        uint num;
        char *uni = (char*)get_unicode(name,num);
	if(!(name = gen_basis_name(name))) return -1;
        if(!is_8_3(name)) 
	if(!(name = gen_tail(name))) return -1;
	
        strncpy((char*)dir[b].dir_name,name,11);
	dir[b].dir_attr = attr;
	dir[b].dir_NTres = 0;
	dir[b].crt_time_tenth = 0;
	dir[b].dir_crt_time = get_FAT_time();
	dir[b].dir_crt_date = get_FAT_date();
	dir[b].dir_lst_acc_date = dir[b].dir_crt_date;
	uint fc = alloc_first_clus(name,attr);
	dir[b].dir_fst_clusHI = (fc>>16)&0xFFFF;
	dir[b].dir_wrt_time = dir[b].dir_crt_time;
	dir[b].dir_wrt_date = dir[b].dir_crt_date;
	dir[b].dir_fst_clusLO = fc & 0xFFFF;
	dir[b].dir_file_size = fsize;
	b--;	
	uint ord = 1;
        fldir *ldir;
        while(b >= start)
	{
                ldir = (fldir*)&dir[b];
		ldir->ldir_ord = ord;
                strncpy((char*)ldir->ldir_name1,uni,10);
		ldir->ldir_attr = ATTR_LONG_NAME;
		ldir->ldir_type = 0;
		ldir->ldir_chksum = chksum(name);
                strncpy((char*)ldir->ldir_name2,uni+=10,12);
		ldir->ldir_fst_clusLO = 0;
                strncpy((char*)ldir->ldir_name3,uni+=12,4);
		b--;
		ord++;
	}
	if(!is_dot_dotdot(name))
	{
		ldir->ldir_ord = ldir->ldir_ord | LLE;
		if(fc) write_clus(fc,NULL);
	}
	return 0;
}

byte FATvolume::chksum(char *name)
{
        short len;
        byte sum = 0;
        for(len=11;len!=0;len--)
        {
                sum = ((sum & 1) ? 0x80 : 0) + (sum>>1) + *name++;
        }
        return sum;
}
        
int FATvolume::del_dir_entry(char *name)
{
	/*
	 *if name is a filename, simply delete the entry. if name is a dirname check if the dir
	 *is empty or not.if it is empty then delete it. if possible contract the cluster chain.
         */         
        
	fdir *dir;
        uint n,clus_nr,index;
	if(!(dir = get_dir_entry(name,n,clus_nr,index))) return -1;

        /*
         *dir[index]...dir[(index-n)+1] contain dir entry
	 *dir[index] = short dir entry,
         *dir[index-1]...dir[(index-n)+1] = long dir entry
	 *clus_nr = clus_nr where this entry is found
	 */


        if(is_directory(dir[index]))
	{
                if(!is_empty(dir[index]))
                {
                        delete dir;
                        return -1;
                }
                if( write_clus(get_start_clus(&dir[index]),NULL) < 0)
                {
                        delete dir;
                        return -1;
                }
	}
	
	byte flag = 0;
	if(index+1 == NUM_ENTRIES || dir[index+1].dir_name[0] == 0x00)
	flag = 1;
	for(int i=index;i>=n-index-1;i--)
	dir[i].dir_name[0] = (flag) ? 0x00 : 0xE5;
	if((n-index)-1 == 0) 
	{
		if(dir[index+1].dir_name[0] = 0x00)
		{
                        if(!contract_clus(clus_nr))
                        {
                                delete dir;
                                return -1;
                        }
		}
	}
        if(write_clus(clus_nr,dir) < 0)
        {
                delete dir;
                return -1;
        }
	delete dir;
	return 0;
}
		
void* FATvolume::read_file(char *name,uint &size)
{
        fdir *dir;
	uint n,clus_nr,index;
        uint start;

        if(!strcmp(name,".") && is_equal(pwd,root))
        {
                start = get_start_clus(&pwd);
        }
        else
        {
                if(!(dir = get_dir_entry(name,n,clus_nr,index)))
                {
                        delete dir;
                        return NULL;
                }
                start = get_start_clus(&dir[index]);
        }

	void *buf;
        if(!(buf = read_clus_chain(start,size)))
        {
                delete dir;
                return NULL;
        }
        delete dir;
        return buf;
}

int FATvolume::write_file(char *name,void *buf,uint size)
{
	fdir *dir;
	uint n,clus_nr,index;
        uint start;

        if(!strcmp(name,".") && is_equal(pwd,root))
        {
                cout<<". & root\n";
                start = get_start_clus(&pwd);
        }
        else
        {
                if(!(dir = get_dir_entry(name,n,clus_nr,index)))
                {
                        delete dir;
                        return -1;
                }
                start = get_start_clus(&dir[index]);
        }

        if(write_clus_chain(start,buf,size) < 0)
        {
                delete dir;
                return -1;
        }
	delete dir;
	return 0;
}

int FATvolume::delete_file(char *name)
{
	fdir *dir;
	uint n,clus_nr,index;
        if(!(dir = get_dir_entry(name,n,clus_nr,index)))
        {
                delete dir;
                return -1;
        }
        uint start = get_start_clus(&dir[index]);
        if(free_clus_chain(start) < 0) {delete dir;return -1;}

	/*free the directory entry in pwd*/
        if(del_dir_entry(name) < 0) return -1;
	delete dir;
	return 0;
}


int FATvolume::get_short_dir_entry(char *name,fdir &d)
{
	int __ret = -1;
	fdir *dir;
	uint n,clus_nr,index;
	if(dir = get_dir_entry(name,n,clus_nr,index))
	{
                d = dir[index];
		delete dir;
		__ret = 0;
	}
	return __ret;
}
	
char* FATvolume::strip(char *name)
{
        char *temp = new char[strlen(name)+1];
        strcpy(temp,name);
        strrev(temp);
        int i=0,f=0;
        while(*temp)
        {
                if(*temp != ' ')
                {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -