📄 backupfile.c
字号:
if (i>=447&&i<=449) /*start CHS*/
{
diskInfo.byteVals[count]=byteVal;
count++;
}
if (i>=451&&i<=453) /*end CHS*/
{
diskInfo.byteVals[count]=byteVal;
count++;
}
if (i>=458&&i<=461) /*current size */
{
diskInfo.byteVals[count]=byteVal;
count++;
}
if (i>=462&&i<=465) /*is next driver?*/
diskInfo.isNext=diskInfo.isNext+byteVal;
}
rewind(fp);
return diskInfo;
}
/*显示驱动器基本信息*/
void DisDiskInfo(DINFO diskInfo)
{
CHS staCHS,endCHS;
unsigned int dSize[4],i;
if(diskInfo.isActive)
printf("\n\nThe disk is Active!\n");
staCHS=RetCHS(diskInfo.byteVals[0],diskInfo.byteVals[1],diskInfo.byteVals[2]);
endCHS=RetCHS(diskInfo.byteVals[3],diskInfo.byteVals[4],diskInfo.byteVals[5]);
printf("The start CHS:%d,%d,%d\n",staCHS.cyl,staCHS.head,staCHS.sec);
printf("The end CHS:%d,%d,%d\n",endCHS.cyl,endCHS.head,endCHS.sec);
if(diskInfo.fileSysType==0x0b||diskInfo.fileSysType==0x0c)
printf("The file system is : FAT32\n");
if(diskInfo.fileSysType==0x86||diskInfo.fileSysType==0x87)
printf("The file system is : NTFS\n");
for (i=0;i<4;i++)
dSize[i]=diskInfo.byteVals[6+i];
printf("This driver size is: %.4f M\n",((float)Size(dSize,4)*SECBYTE/1024/1024));
// printf("\n%ld\n",diskInfo.isNext);
/* if(diskInfo.isNext)
printf("It has next driver.\n");
else
printf("It's the last driver.\n");
*/
getch();
}
/*一下是读取扇区信息并保存的的代码*/
BINFO RetBpbInfo(FILE *fp)
{
int i,count;
char arrBPBInfo[512]; /*用整型还是用字符型?*/
BINFO bpbInfo;
/*用char的时候一不注意就会出现一些诡异的问题*/
/* for (i=0,count=0;i<512;i++)
arrBPBInfo[i]=fgetc(fp);*/
fread(arrBPBInfo,512,1,fp);/*用fread()时数组必须用字符型*/
for(count=0,i=11;count<2;count++,i++)
bpbInfo.secSize[count]=arrBPBInfo[i];
bpbInfo.cluSize=arrBPBInfo[13];
for(count=0,i=14;count<2;count++,i++)
bpbInfo.keepSize[count]=arrBPBInfo[i];
bpbInfo.fatNum=arrBPBInfo[16];
for(count=0,i=24;count<2;count++,i++)
bpbInfo.secNum[count]=arrBPBInfo[i];
for(count=0,i=26;count<2;count++,i++)
bpbInfo.headNum[count]=arrBPBInfo[i];
for(count=0,i=28;count<4;count++,i++)
bpbInfo.hiddenSize[count]=arrBPBInfo[i];
for(count=0,i=32;count<4;count++,i++)
bpbInfo.driverSize[count]=arrBPBInfo[i];
for(count=0,i=36;count<4;count++,i++)
bpbInfo.fatSize[count]=arrBPBInfo[i];
for(count=0,i=44;count<4;count++,i++)
bpbInfo.rootStart[count]=arrBPBInfo[i];
rewind(fp);
return bpbInfo;
}
long RetFDTLBA(BINFO bpbInfo)
{
/* long keepSize,hiddenSize,fatSize,startClu;
keepSize=Size(bpbInfo.keepSize,2);
hiddenSize=Size(bpbInfo.hiddenSize,2);
fatSize=bpbInfo.fatNum*Size(bpbInfo.fatSize,4);
startClu=(Size(bpbInfo.rootStart,4)-2)*bpbInfo.cluSize;
return (keepSize+hiddenSize+fatSize+startClu); */
return (Size(bpbInfo.keepSize,2)+Size(bpbInfo.hiddenSize,2)+bpbInfo.fatNum*Size(bpbInfo.fatSize,4)+(Size(bpbInfo.rootStart,4)-2)*bpbInfo.cluSize);
}
/*逻辑地址转换为物理地址*/
CHS LBAToCHS(long LBA)
{
CHS fdtAdd;
fdtAdd.cyl=LBA/(255*63);
fdtAdd.head=(LBA/63)%255;
fdtAdd.sec=LBA%63+1;
return fdtAdd;
}
/*读取扇区数据*/
void ReadSector(FILE *fp,int cyl,int head,int sec,int len)
{
char buffer[512*16]={NULL};
// int i=0;
biosdisk(0x02,0x80,head,cyl,sec,len,buffer);
// for(i=0;i<512*len;i++)
// fputc(buffer[i],fp);
fwrite(buffer,512,len,fp);
rewind(fp);
// memset(buffer,0,512*16);
}
/*保存扇区数据*/
void SaveSecData(FILE *fpmbr,FILE *fpdbr,FILE *fpfdt)
{
CHS fdtadd;
BINFO bpbInfo;
long LBA;
// DINFO diskInfo;
ReadSector(fpmbr,0,0,1,1);
ReadSector(fpdbr,0,1,1,1);
// diskInfo=RetDiskData(fpmbr);
bpbInfo=RetBpbInfo(fpdbr); //获取分区的BPB信息
LBA=RetFDTLBA(bpbInfo);
rewind(fpdbr);
fdtadd=LBAToCHS(LBA);
// printf("FDT start:%d,%d,%d\n",fdtadd.cyl,fdtadd.head,fdtadd.sec);
ReadSector(fpfdt,fdtadd.cyl,fdtadd.head,fdtadd.sec,bpbInfo.cluSize);
rewind(fpfdt);
}
//簇链寻址
void FindClu(FILE *fpdbr,FILE *fpbk,FDT fdtInfo,unsigned int temp[4])
{
int i,count;
unsigned int buff[512];
CHS bkSec,tmSec;
long tmpLBA1,tmpLBA2,fatStart;
BINFO bpbInfo=RetBpbInfo(fpdbr);
fatStart=Size(bpbInfo.keepSize,2)+Size(bpbInfo.hiddenSize,4);
tmpLBA1=(((StartAdd(fdtInfo))*4/Size(bpbInfo.secSize,2))+fatStart);//记录的是簇号所在的FAT扇区逻辑地址
tmSec=LBAToCHS(tmpLBA1); /*找到簇号所在的fat扇区,保留扇区数+隐藏扇区数=fat入口*/
for(i=(int)((StartAdd(fdtInfo))*4%Size(bpbInfo.secSize,2)),count=0;count<4;count++,i++)/*取得表示文件下一簇的簇号*/
temp[count]=buff[i];
for(;temp[1]+temp[2]+temp[3]+temp[0]!=780;) /*temp[1]+temp[2]+temp[3]+temp[0]!=780||0xff+0xff+0xff+0x0f==780*/
{ //判断是否是结束标志
bkSec=LBAToCHS((Size(temp,4)-2)*bpbInfo.cluSize+RetFDTLBA(bpbInfo));/*获得下一个要备份的簇*/
fseek(fpbk,0,SEEK_END);//
ReadSector(fpbk,bkSec.cyl,bkSec.head,bkSec.sec,bpbInfo.cluSize); /*备份第二簇*/
tmpLBA2=(Size(temp,4)*4/Size(bpbInfo.secSize,2))+fatStart;
if(tmpLBA1!=tmpLBA2)//判断簇号是否在一个扇区
{
tmpLBA1=tmpLBA2;
tmSec=LBAToCHS(tmpLBA2);
biosdisk(0x02,0x80,tmSec.head,tmSec.cyl,tmSec.sec,1,buff);
}
for(i=(int)((Size(temp,4))*4%Size(bpbInfo.secSize,2)),count=0;count<4;count++,i++)
temp[count]=buff[i];
}
}
//备份根目录下的文件
void BackupFile(FILE *fpfdt,FILE *fpdbr,FILE *fpbk,SqStack *S)
{
FDT fdtInfo; //记录文件的目录登记项
CHS bkSec,tmSec,subFdtSec; //tmSec记录的是表示占用情况的FAT扇区
FILE *fpSubFdt[StackSize]; //
BINFO bpbInfo; //记录分区的各个信息
int i=0,catNum=0,count;
unsigned int temp[4]={0}; //记录簇链中的簇号
unsigned char buff[512]; //
long tmpLBA1,tmpLBA2,fatStart;
long j=0;
int fpcount=-1; //记录目录登记项的个数
bpbInfo=RetBpbInfo(fpdbr); //获取分区的BPB信息
fatStart=Size(bpbInfo.keepSize,2)+Size(bpbInfo.hiddenSize,4);//获取FAT的其始地址
for(catNum=0;catNum<CATNUM;catNum++) //遍历整个FDT
{
//printf("catNum=%d\n",catNum);
fdtInfo=RetCatalog(catNum*32,fpfdt); //提取文件目录项
if(fdtInfo.isEOF==0)
break;
if(fdtInfo.fProperty==0x0f||fdtInfo.fName[0]==0xe5||fdtInfo.fName[0]==0x2e)
continue; //,结束本次循环,不处理长文件名和已经删去的文件(夹)
//暂时只备份根目录下的文件
if (StartAdd(fdtInfo)!=0) //不备份文件(夹)||IsFolder(fdtInfo.fProperty)==0
{//&&fdtInfo.fName[0]!=0xe5
for(i=0;i<8;i++) //打印文件名
printf("%c",fdtInfo.fName[i]);
if(IsFolder(fdtInfo.fProperty)==0) //文件夹无扩展名,不打印"."
printf(".");
else
{
printf("<DIR");
// fpSubFdt=fopen("SubDirFdt.dat","wb+");
fpSubFdt[++fpcount]=tmpfile();
}
for(i=0;i<3;i++) //文件扩展名或者文件夹名
printf("%c",fdtInfo.extName[i]);
//printf("%ld \n",StartAdd(fdtInfo));
bkSec=LBAToCHS(((StartAdd(fdtInfo)-2)*bpbInfo.cluSize)+RetFDTLBA(bpbInfo));//取得文件第一簇地址
// printf("%ld:",(((StartAdd(fdtInfo)-2)*bpbInfo.cluSize)+RetFDTLBA(bpbInfo)));
fseek(fpbk,0,SEEK_END); //文件指针指向文件尾,由于函数ReadSector执行完要把文件指针指向文件头
ReadSector(fpbk,bkSec.cyl,bkSec.head,bkSec.sec,bpbInfo.cluSize); //备份文件第一簇
if(IsFolder(fdtInfo.fProperty)==1)
{
fseek(fpSubFdt[fpcount],0,SEEK_END);
ReadSector(fpSubFdt[fpcount],bkSec.cyl,bkSec.head,bkSec.sec,bpbInfo.cluSize);
}
//((StartAdd(fdtInfo))*4/Size(bpbInfo.secSize,2))计算的是FAT的某个扇区地址,这个扇区记录了此簇的占用情况
//fseek(fpbk,0,SEEK_END);
//ReadSector(fpbk,2,9,43,bpbInfo.cluSize); //备份第二簇
//fclose(fpbk);
//printf("%d ",Size(bpbInfo.secSize,2));
tmpLBA1=(((StartAdd(fdtInfo))*4/Size(bpbInfo.secSize,2))+fatStart);//记录的是簇号所在的FAT扇区逻辑地址
//printf("%ld,",tmpLBA1);
tmSec=LBAToCHS(tmpLBA1);//找到簇号所在的fat扇区,保留扇区数+隐藏扇区数=fat入口
biosdisk(0x02,0x80,tmSec.head,tmSec.cyl,tmSec.sec,1,buff); //读一个簇链所在FAT扇区的内容到数组
//printf("%d ",((StartAdd(fdtInfo))*4%Size(bpbInfo.secSize,2)));
for(i=(int)((StartAdd(fdtInfo))*4%Size(bpbInfo.secSize,2)),count=0;count<4;count++,i++)/*取得表示文件下一簇的簇号*/
//{
temp[count]=buff[i];
//printf("%2x,",temp[count]);
//}
//检查fat链中是否是0xff+0xff+0xff+0x0f
//for(count=0;count<4;count++)
// printf("%2x,",temp[count])
//printf("%ld ",((Size(temp,4)-2)*bpbInfo.cluSize+RetFDTLBA(bpbInfo)));
//printf("%ld ",(Size(temp,4)-2));
//printf("%2x ",temp[0]);
for(;temp[1]+temp[2]+temp[3]+temp[0]!=780;) //temp[1]+temp[2]+temp[3]+temp[0]!=780||0xff+0xff+0xff+0x0f==780
{ //判断是否是结束标志
//for(count=0;count<4;count++)
// printf("%2x,",temp[count]);
//printf("\n");
// printf("\n%ld",++j);
bkSec=LBAToCHS((Size(temp,4)-2)*bpbInfo.cluSize+RetFDTLBA(bpbInfo));//获得下一个要备份的簇
//printf("%ld\n",((Size(temp,4)-2)*bpbInfo.cluSize+RetFDTLBA(bpbInfo)));
fseek(fpbk,0,SEEK_END);//
ReadSector(fpbk,bkSec.cyl,bkSec.head,bkSec.sec,bpbInfo.cluSize); /*备份第二簇*/
if(IsFolder(fdtInfo.fProperty)==1)
{
fseek(fpSubFdt[fpcount],0,SEEK_END);
ReadSector(fpSubFdt[fpcount],bkSec.cyl,bkSec.head,bkSec.sec,bpbInfo.cluSize);
}
//fclose(fpbk);
tmpLBA2=(Size(temp,4)*4/Size(bpbInfo.secSize,2))+fatStart;
// printf("=%ld=\n",tmpLBA2);
if(tmpLBA1!=tmpLBA2)//判断簇号是否在一个扇区
{
tmpLBA1=tmpLBA2;
//printf("%ld ",tmpLBA2);
tmSec=LBAToCHS(tmpLBA2);
//获取表示第二簇占用情况的FAT扇区
biosdisk(0x02,0x80,tmSec.head,tmSec.cyl,tmSec.sec,1,buff);
}
// printf("%ld ",((Size(temp,4))*4%Size(bpbInfo.secSize,2)));
for(i=(int)((Size(temp,4))*4%Size(bpbInfo.secSize,2)),count=0;count<4;count++,i++)
{
temp[count]=buff[i];
// printf("%2x,",temp[count]);
}
// printf("\n");
//if(catNum%10==0)
//getch();
//printf("%d\n",((Size(temp,4)-2)*4%Size(bpbInfo.secSize,2)));
}
if(temp[1]+temp[2]+temp[3]+temp[0]==780)
printf(" %2d file has been saved!\n",++j);
}
// else
// continue;
//递归遍历子目录
if(fdtInfo.fName[0]!=0xe5&&IsFolder(fdtInfo.fProperty)==1)
{
printf("Test FDT!\n");
getch();
// rewind(fpSubFdt[fpcount]);
if(S->top==-1)
{
push(S,fpfdt);
printf("\nfdt\n");
getch();
}
else
{
printf("\nIt's subFdt\n");
getch();
push(S,fpSubFdt[fpcount]);
}
BackupFile(fpSubFdt[fpcount],fpdbr,fpbk,S);
//为什么程序进入子目录后无法返回上级目录
}
//本目录登记项遍历完毕后,返回上一级目录
else if(fdtInfo.isEOF==0)//目录登记项遍历完毕可能还有另外一个条件:目录登记项没有全零的项
{
fpfdt=pop(S);
if(StackEmpty(S))
exit(-1);
BackupFile(fpfdt,fpdbr,fpbk,S);
}
}
// printf("catNum=%d ",catNum);
// fclose(fptmp);
fclose(fpbk);
rewind(fpfdt);
rewind(fpdbr);
// fclose(fpSubFdt);
getch();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -