📄 fatvol.cpp
字号:
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 + -