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

📄 fatvol.cpp

📁 Jazmyn is a 32-bit, protected mode, multitasking OS which runs on i386 & above CPU`s. Its complete
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                        if(*temp == '.')
                        {
                                if(f == 0)
                                {
                                        f = 1;
                                        name[i++] = *temp;
                                }
                        }
                        else name[i++] = *temp;
                }
                temp++;
        }
        name[i] = '\0';
        delete temp;
        return strrev(name);	
}

char* FATvolume::gen_basis_name(char *name)
{

        if(strcmp(name,".") == 0)
        {
                memset(name,' ',11);
                name[0] = '.';
                name[11] = '\0';
                return name;
        }
        if(strcmp(name,"..") == 0)
        {
                memset(name,' ',11);
                name[0] = '.';
                name[1] = '.';
                name[11] = '\0';
                return name;
        }
        name = strupr(name);
        name = strip(name);
        char* t1 = new char[strlen(name)+1];
        char* t2 = new char[strlen(name)+1];
        strcpy(t2,name);
        strcpy(t1,name);
        memset(name,' ',11);
        
        int t = 0;
        while(*t2 && *t2!='.' && t<8)
        {
                name[t] = *t2;
                t2++;
                t++;
        }
        int _d = 0;
        int i;
        for(i=strlen(t1)-1;i>=0;i--)
        {
                if(t1[i] == '.')
                {
                        _d=1;
                        break;
                }
        }
        t = 0;
        int ext = 8;
        if(_d)
        {
                t1 = t1 + i + 1;
                while(*t1 && t<3)
                {
                        name[ext] = *t1;
                        t1++;
                        t++;
                        ext++;
                }
        }
        name[11]='\0';
        delete t1;
        delete t2;
        return name;	
}

int FATvolume::is_8_3(char *name)
{

        if(!strcmp(name,".") || !strcmp(name,".."))
        return 1;

 	int i = strlen(name);
        if(i > 12) return 0;
        int b=0,e=0,f=0;
        while(*name)
        {
                if(*name == '.') f += 1;
                (f) ? e++ : b++;
                name++;
        }
        return (b<=8 && e<=4 && f<=1) ? 1 : 0;
}

byte* FATvolume::get_unicode(char* name,uint &num)
{
	int len = strlen(name);
	num = len/13;
	if(len % 13) num++;
	short *unicode = new short[num*13];	
	int i=0;
	while(*name)
	{
		unicode[i++] = *name;
		name++;
	}
	int rem = num*13 - i;
	if(rem) unicode[i++] = 0,rem--;
	while(rem) unicode[i++] = 0xFFFF,rem--;
	return (byte*)unicode;
}

int FATvolume::is_dot_dotdot(char* name)
{
	if(!strncmp(name,".",1) || !strncmp(name,"..",2))
	return 1;
	return 0;
}

int FATvolume::get_nfe(char* name)
{
	if(is_dot_dotdot(name)) return 1;
	int len = strlen(name);
	uint num = len / 13;
	if(len %13) num++;
	return ++num;
}

uint FATvolume::get_start_clus(fdir *dir)
{
	if(is_equal(*dir,root)) return 2;
	ushort clus_lo = dir->dir_fst_clusLO;
	ushort clus_hi = dir->dir_fst_clusHI;
	return (clus_hi<<16) | clus_lo;
}

 
uint FATvolume::get_next_clus(uint start,uint &clus_nr,fdir *dir)
{
	/*
	 *Requires access to FAT.
	 *look at FAT[start], if it is EOC, then set a flag
	 *if(flag) return 0 else return FAT[start];
	 */
        if(gnflag)
	{
                gnflag = 0;
                return -1;
	}
	clus_nr = start;
	if(dir)
        {
                if(read_clus(clus_nr,dir) < 0) return -1;
        }
	uint temp = get_FAT_entry(start);
        if(temp == EOC)
        {
                gnflag = 1;
        }
	return temp;
}

int FATvolume::write_clus(uint clus_nr,void *buf)
{
	disk_req req;
        _CR(req,DISK_WRITE,dev,_pi.start_sec+FSOC(clus_nr),_bpb.spc,buf);
	if(_dev_mgr.driver_tab[slot].main(&req) < 0) return -1;
	return 0;
}

int FATvolume::read_clus(uint clus_nr,void *buf)
{
	disk_req req;
        _CR(req,DISK_READ,dev,_pi.start_sec+FSOC(clus_nr),_bpb.spc,buf);
	if(_dev_mgr.driver_tab[slot].main(&req) < 0) return -1;
	return 0;
}

uint FATvolume::expand_clus(uint clus_nr)
{
	uint entry = get_FAT_entry(clus_nr);
	if(entry != EOC) return 0;
	uint free_clus = get_free_clus();
	put_FAT_entry(clus_nr,free_clus);
	put_FAT_entry(free_clus,EOC);
	return free_clus;
}

uint FATvolume::contract_clus(uint clus_nr)
{
        uint start = get_start_clus(&pwd);
	uint entry = get_FAT_entry(clus_nr);
	if(entry != EOC) return 0;
	uint clus = 0;
	while(start = get_next_clus(start,clus,NULL) != 0xFFFFFFFF)
	{
		if(get_FAT_entry(clus) == clus_nr);
		break;
	}
	put_FAT_entry(clus_nr,0);
	put_FAT_entry(clus,EOC);
	return clus;
}

uint FATvolume::alloc_first_clus(char *name,byte attr)
{
	/*
	 *if name = "." return pwd`s start cluster
	 *if name = ".." return pwds parent dirs starts cluster
	 *if attr = file, return 0
	 *if attr = dir && name !="." || ".." return get_free_clus()
	 */
        if(!strncmp(name,".",1)) return get_start_clus(&pwd);
        if(!strncmp(name,"..",2)) return get_start_clus(&ppwd);
	if(attr & ATTR_DIRECTORY) return get_free_clus();
	return 0;
}

int FATvolume::is_empty(fdir &dir)
{
	uint start = get_start_clus(&dir);
	uint size;
        fdir *rdir = (fdir*)read_clus_chain(start,size);
        if(rdir[2].dir_name[0] == 0x00) {delete rdir;return 1;}
        delete rdir;
	return 0;
}

void* FATvolume::read_clus_chain(uint start,uint &size)
{
	void *buf = new byte[CLUSTER_SZ];
        void *oldbuf = buf;
        byte *temp = new byte[CLUSTER_SZ];
	int i = 2;
	size = 0;
        uint clus_nr;
        while((start = get_next_clus(start,clus_nr,(fdir*)temp)) != 0xFFFFFFFF)
	{
		memcpy(buf,temp,CLUSTER_SZ);
		size += CLUSTER_SZ;
		if(start != EOC)
		{
                        if(!(buf = _heap_obj.realloc(oldbuf,CLUSTER_SZ*i)))
                        {
                                delete buf;
                                return NULL;
                        }
			i++;
                        oldbuf = buf;
                        buf = (char*)buf + CLUSTER_SZ;
		}
	}
        delete temp;
        return oldbuf;
}

int FATvolume::write_clus_chain(uint start,void *buf,uint size)
{
	/*
	 *if the size of the buf is same as original, then no need to expand or contract
	 *the cluster chain.if size exceeds original by one or more clusters,we need to expand 
	 *cluster chain else if the size is less than the original size by one or more 
	 *clusters,the cluster chain need to be contracted.
	 */
	
	uint num_clus = size / CLUSTER_SZ;
        uint last_clus,clus_nr;
	while((start = get_next_clus(start,clus_nr,NULL)) != 0xFFFFFFFF)
	{
		if(write_clus(clus_nr,buf) < 0) return -1;
		num_clus--;
		if(num_clus == 0) break;
                buf = (char*)buf +  CLUSTER_SZ;
	}
	last_clus = clus_nr;

	/*This means that the new buf is same or changed with in the last cluster*/
	if(start == -1 && num_clus == 0) return 0;
	
	/*
	 *This means the buf is larger than the original by num_clus, so expand the cluster
	 *chain until all the remaining buf is written.
	 */
 
	if(num_clus > 0)
	{
		while(num_clus > 0)
		{
			uint new_clus = expand_clus(clus_nr);
			if(write_clus(new_clus,buf) < 0) return -1;
                        buf = (char*)buf + CLUSTER_SZ;
			num_clus--;
			clus_nr = new_clus;
		}
		return 0;
	}
	
	/*
	 *This means that the buffer is lesser than the original by one or more clusters
	 *so, contract the cluster chain.
	 */
	
	while(start = get_next_clus(start,clus_nr,NULL) != 0xFFFFFFFF);	
	while(clus_nr != last_clus)
	{
                if(!(clus_nr = contract_clus(clus_nr))) return -1;
	}
	return 0;
}

int FATvolume::free_clus_chain(uint start)
{
	uint clus_nr;
	while((start = get_next_clus(start,clus_nr,NULL)) != 0xFFFFFFFF)
	{
		put_FAT_entry(clus_nr,0);
	}
	return 0;
}

int FATvolume::is_directory(fdir &dir)
{
        return dir.dir_attr & ATTR_DIRECTORY;
}

char* FATvolume::gen_tail(char* name)
{
        int start = get_start_clus(&pwd);
	fdir *dir;
	uint size;
	uint num_entries = size / sizeof(fdir);
        int n,num;
        if(!(dir = (fdir*)read_clus_chain(start,size))) return NULL;
	
	/*code to generate tail*/
	int i = 0,max_num = 0;
	char *temp = name;
	while(*temp && *temp != ' ') i++,temp++;
	for(int j=0;j<num_entries;j++)
	{
		if(dir[j].dir_name[0] == 0x00) break;
		if(dir[j].dir_name[0] != 0xE5)
		{
			char tmp[8];
			if(get_behind(dir[j].dir_name,tmp,n,num))
			{
				if(!strncmp(name,tmp,n)) 
				{
					if(num > max_num)
					max_num = num;
				}
			}
		}
	}
	if(max_num == 0)
	{
		name[i++] = '~';
		name[i] = '1';
		return name;
	}
	char *s = new char[8];
	strcpy(s,"~");
        char ch[10];
        strcat(s,itoa(num,ch,10));
	int taillen = strlen(s);
	int p = 7;
	if(taillen > (8-i))
                while(taillen) name[p++] = s[taillen--];
	else
	{
		p = 0;
		while(i<8) name[i++] = s[p++];
	}
	return name;
}

int FATvolume::get_behind(byte *str,char *ret,int &n,int &num)
{
        int i;
        for(i=0;i<8;i++)
	if(str[i] == '~') break;
	if(i==8) return 0;
        strncpy(ret,(char*)str,i);
	n=i;
        num = atoin((char*)str+i+1,8-(i+1)); 
}

int FATvolume::set_root()
{
	if(read_root(root) < 0) return -1;
	pwd = root;
	return 0;
}

void FATvolume::save_root(fdir &r)
{
	r = root;
}

void FATvolume::restore_root(fdir &r)
{
	root = r;
}

int FATvolume::chdir(char *path)
{
        if(!strcmp(path,""))
        {
                return 0;
        }
	if(!strcmp(path,"\\"))
	{
                pwd = root;
		return 0;
	}
	char *temp = path;
	char name[255];
	uint n,clus_nr,index;
	fdir *dir;
	if(*temp == '\\') pwd = root;
	while(temp = get_next_name(temp,name))
	{
                if(dir = get_dir_entry(name,n,clus_nr,index))
		{
			pwd = dir[index];
			delete dir;
		}
                else
                {
                        cout<<"in chdir, get dir ent failed\n";
                        getch();
                        return -1;
                }
	}
	return 0;
}	

int FATvolume::read_root(fdir &r)
{
	fdir *dir = new fdir[NUM_ENTRIES];
        if(read_clus(2,dir) < 0) {delete dir;return -1;}
	r = dir[0];
	delete dir;
	return 0;
}


void* FATvolume::get_FAT_ent_addr(uint N)
{
	/*should contain FAT12/16/32 specific code*/
	uint FAToffset;
        switch(FATtype)
	{
		case FAT12 : FAToffset = N + (N / 2);break;
                case FAT16 : FAToffset = N * 2;break;
                case FAT32 : FAToffset = N * 4;
                break;
		default: return 0;
	}
	uint ThisFATsecnum = _bpb.rsc + (FAToffset / _bpb.bps);
	uint ThisFATentoff = FAToffset % _bpb.bps;
	void *FATentaddr = mem_FAT + ((ThisFATsecnum - _bpb.rsc)*512 + ThisFATentoff);
	return FATentaddr;
}

uint FATvolume::get_FAT_entry(uint N)
{
	/*
	 *should contain FAT12/16/32 specific code
	 *should return FAT[N];
	 */
	void *FATentaddr = get_FAT_ent_addr(N);
	uint FATclusentval;
	if(FATtype == FAT16)
		FATclusentval = *(WORD*)FATentaddr;
	else if(FATtype == FAT32)
		FATclusentval = *(DWORD*)FATentaddr;
	else if(FATtype == FAT12)
	{
		/*
		 *FAT12 code is written according to Microsoft document. Never went into
		 *details of this mathematics.
		 */
		
		FATclusentval = *(WORD*)FATentaddr;
		if(N &  0x0001) FATclusentval = FATclusentval >> 4;
		else	FATclusentval = FATclusentval & 0x0FFF;
	}
	else FATclusentval = 0;
	return FATclusentval;
}

void FATvolume::put_FAT_entry(uint N,uint value)
{
	/*
	 *should contain FAT12/16/32 specific code
	 *should set FAT[N] = value;
	 */

	void *FATentaddr = get_FAT_ent_addr(N);
	if(FATtype == FAT16)
		*(WORD*)FATentaddr = value;
	else if(FATtype == FAT32)
	{
		value = value & 0x0FFFFFFF;
		*(DWORD*)FATentaddr = (*(DWORD*)FATentaddr) & 0xF0000000;
		*(DWORD*)FATentaddr = (*(DWORD*)FATentaddr) | value;
	}
	else if(FATtype == FAT12)
	{
		/*I hope this code works*/
		if(N & 0x0001)
		{
			value = value << 4;
			*(WORD*)FATentaddr = (*(WORD*)FATentaddr) & 0x000F;
		}
		else
		{
			value = value & 0x0FFF;
			*(WORD*)FATentaddr = (*(WORD*)FATentaddr) & 0xF000;
		}
		*(WORD*)FATentaddr = (*(WORD*)FATentaddr) | value;
	}
}		

uint FATvolume::get_free_clus()
{
        uint entry;
        for(uint i=2;i<coc;i++)
        {
                entry = get_FAT_entry(i);
                if(entry == FREE_CLUS)
                return i;
        }
        return 0;
}

int is_equal(fdir &d1,fdir &d2)
{
               if( (!strncmp((char*)d1.dir_name,(char*)d2.dir_name,11)) &&
                    (d1.dir_attr == d2.dir_attr) &&
                    (d1.dir_NTres == d2.dir_NTres) &&
                    (d1.crt_time_tenth == d2.crt_time_tenth) &&
                    (d1.dir_crt_time == d2. dir_crt_time) &&
                    (d1.dir_crt_date == d2.dir_crt_date) &&
                    (d1.dir_lst_acc_date == d2.dir_lst_acc_date) &&
                    (d1.dir_fst_clusHI == d2.dir_fst_clusHI) &&
                    (d1.dir_wrt_time == d2.dir_wrt_time) &&
                    (d1.dir_wrt_date == d2.dir_wrt_date) &&
                    (d1.dir_fst_clusLO == d2.dir_fst_clusLO) &&
                    (d1.dir_file_size == d2.dir_file_size)
                  )
                  return 1;
                  return 0;
}

⌨️ 快捷键说明

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