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

📄 backupfile.c

📁 自己写的磁盘备份小工具,能显示MBR,DBR信息以及8.4G以下的小硬盘备份恢复
💻 C
📖 第 1 页 / 共 3 页
字号:
        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 + -