/*
* file_system.c
*
* Created on: 2009-5-28
* Author: liyi
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "file_global.h"
#define RevByte(low,high) ((high)<<8|(low))
#define RevWord(lowest,lower,higher,highest) ((highest)<<24|(higher)<<16|(lower)<<8|lowest)
/*
* 读fat表的信息,存入fatbuf[]中
*/
int readFat()
{
if(lseek(fd,FAT_ONE_OFFSET,SEEK_SET)<0)
{
perror("lseek failed");
return -1;
}
if(read(fd,fatbuf,FAT_SIZE)<0)
{
perror("read failed");
return -1;
}
return 1;
}
/*
* 将改变的fat表值写回fat表
*/
int writeFat()
{
if(lseek(fd,FAT_ONE_OFFSET,SEEK_SET)<0)
{
perror("lseek failed");
return -1;
}
if(write(fd,fatbuf,FAT_SIZE)<0)
{
perror("read failed");
return -1;
}
if(lseek(fd,FAT_TWO_OFFSET,SEEK_SET)<0)
{
perror("lseek failed");
return -1;
}
if((write(fd,fatbuf,FAT_SIZE))<0)
{
perror("read failed");
return -1;
}
return 1;
}
/*打印启动项记录*/
void scanBootSector()
{
unsigned char buf[SECTOR_SIZE];
int ret,i;
if((ret=read(fd,buf,SECTOR_SIZE))<0)
perror("read boot sector failed");
for(i=0;i<8;i++)
bdptor.Oem_name[i]=buf[i+0x03];
bdptor.Oem_name[i]='\0';
bdptor.BytesPerSector=RevByte(buf[0x0b],buf[0x0c]);
bdptor.SectorsPerCluster=buf[0x0d];
bdptor.ReservedSectors=RevByte(buf[0x0e],buf[0x0f]);
bdptor.FATs=buf[0x10];
bdptor.RootDirEntries=RevByte(buf[0x11],buf[0x12]);
bdptor.LogicSectors=RevByte(buf[0x13],buf[0x14]);
bdptor.MediaType=buf[0x15];
bdptor.SectorsPerFAT=RevByte( buf[0x16],buf[0x17]);
bdptor.SectorsPerTrack=RevByte(buf[0x18],buf[0x19]);
bdptor.Heads=RevByte(buf[0x1a],buf[0x1b]);
bdptor.HiddenSectors=RevByte(buf[0x1c],buf[0x1d]);
printf("Oem_name \t\t%s\n"
"BytesPerSector \t\t%d\n"
"SectorsPerCluster \t%d\n"
"ReservedSector \t\t%d\n"
"FATs \t\t\t%d\n"
"RootDirEntries \t\t%d\n"
"LogicSectors \t\t%d\n"
"MediaType \t\t%d\n"
"SectorPerFAT \t\t%d\n"
"SectorPerTrack \t\t%d\n"
"Heads \t\t\t%d\n"
"HiddenSectors \t\t%d\n",
bdptor.Oem_name,
bdptor.BytesPerSector,
bdptor.SectorsPerCluster,
bdptor.ReservedSectors,
bdptor.FATs,
bdptor.RootDirEntries,
bdptor.LogicSectors,
bdptor.MediaType,
bdptor.SectorsPerFAT,
bdptor.SectorsPerTrack,
bdptor.Heads,
bdptor.HiddenSectors);
}
/*
* 参数:entryname 类型:char
* pentry 类型:Entry *
* mode 类型:int,mode=1,为目录表项;mode=0,为文件
* 返回值:偏移值大于0,则成功;-1,则失败
* 功能:搜索当前目录,查找文件或目录项
*/
int scanEntry(char *entryname,Entry *pentry,int mode)
{
int ret,offset,i;
int cluster_addr;
char uppername[80];
for(i=0;i<strlen(entryname);i++)
uppername[i]=toupper(entryname[i]);
uppername[i]='\0';
if(curdir==NULL) //扫描根目录
{
if((ret=lseek(fd,ROOTDIR_OFFSET,SEEK_SET))<0)
perror("lseek ROOTDIR_OFFSET failed");
offset=ROOTDIR_OFFSET;
while(offset<DATA_OFFSET)
{
ret=getEntry(pentry);
offset+=abs(ret);
if(pentry->subdir==mode&&strcmp((char *)pentry->short_name,uppername)==0)
return offset;
}
}
else //扫描子目录
{
cluster_addr=DATA_OFFSET+(curdir->FirstCluster-2)*CLUSTER_SIZE;
if((ret=lseek(fd,cluster_addr,SEEK_SET))<0)
perror("lseek cluster_addr failed");
offset=cluster_addr;
while(offset<cluster_addr+CLUSTER_SIZE)
{
ret=getEntry(pentry);
offset+=abs(ret);
if(pentry->subdir==mode&&strcmp((char *)pentry->short_name,uppername)==0)
return offset;
}
}
return -1;
}
/*
* 参数:entry,类型:Entry *
* 返回值:成功,则返回偏移值;失败:返回负值
* 功能:从根目录或文件簇中得到文件表项
*/
int getEntry(Entry *pentry)
{
int ret,i;
int count=0;
unsigned char buf[DIR_ENTRY_SIZE],info[2];
/*读一个目录表项,即32字节*/
if((ret=read(fd,buf,DIR_ENTRY_SIZE))<0)
perror("read entry failed");
count+=ret;
if(buf[0]==0xe5||buf[0]==0x00)
return -1*count;
else
{
/*长文件名,忽略掉*/
while(buf[11]==0x0f)
{
if((ret=read(fd,buf,DIR_ENTRY_SIZE))<0)
perror("read root dir failed");
count+=ret;
}
/*命名格式化,注意结尾的'\0'*/
for (i=0;i<=10;i++)
pentry->short_name[i]=buf[i];
pentry->short_name[i]='\0';
formatFileName(pentry->short_name);
info[0]=buf[22];
info[1]=buf[23];
findTime(&(pentry->hour),&(pentry->minute),&(pentry->second),info);
info[0]=buf[24];
info[1]=buf[25];
findDate(&(pentry->year),&(pentry->month),&(pentry->day),info);
pentry->FirstCluster=RevByte(buf[26],buf[27]);
pentry->size=RevWord(buf[28],buf[29],buf[30],buf[31]);
pentry->readonly=(buf[11]&ATTR_READONLY)?1:0;
pentry->hidden=(buf[11]&ATTR_HIDDEN)?1:0;
pentry->system=(buf[11]&ATTR_SYSTEM)?1:0;
pentry->vlabel=(buf[11]&ATTR_VLABEL)?1:0;
pentry->subdir=(buf[11]&ATTR_SUBDIR)?1:0;
pentry->archive=(buf[11]&ATTR_ARCHIVE)?1:0;
return count;
}
}
/*日期*/
void findDate(unsigned short *year,unsigned short *month,unsigned short *day,unsigned char info[2])
{
int date;
date=RevByte(info[0],info[1]);
*year=((date&MASK_YEAR)>>9)+1980;
*month=((date&MASK_MONTH)>>5);
*day=(date&MASK_DAY);
}
/*时间*/
void findTime(unsigned short *hour,unsigned short *min,unsigned short *sec,unsigned char info[2])
{
int time;
time=RevByte(info[0],info[1]);
*hour=((time&MASK_HOUR)>>11);
*min=(time&MASK_MIN)>>5;
*sec=(time&MASK_SEC)*2;
}
/*文件名格式化,便于比较*/
void formatFileName(unsigned char *name)
{
unsigned char *p=name;
while(*p!='\0')
p++;
p--;
while(*p==' ')
p--;
p++;
*p='\0';
}
/*
* 参数:prev,类型:unsigned char
* 返回值:下一簇
* 功能:在fat表中获得下一簇的位置
*/
unsigned short getFatCluster(unsigned short prev)
{
unsigned short next;
int index;
index=prev*2;
next=RevByte(fatbuf[index],fatbuf[index+1]);
return next;
}
/*
* 参数:cluster,类型:unsigned short
* 返回值:void
* 功能:清除fat表中的簇信息
*/
void clearFatCluster(unsigned short cluster)
{
int index;
index=cluster*2;
fatbuf[index]=0x00;
fatbuf[index+1]=0x00;
}
/*
* 参数:mode,类型:int
* 返回值:1,成功;-1,失败
* 功能:显示所要查看目录下的内容。
* 说明:mode值为0时,查看当前目录信息;mode值为1时,查看所有的非根目录信息
*/
int ud_ls(int mode)
{
int ret,offset,cluster_addr;
int i;
Entry entry;
unsigned char buf[DIR_ENTRY_SIZE];
if((ret=read(fd,buf,DIR_ENTRY_SIZE))<0)
perror("read entry failed");
if(mode==1)
{
printf("All_Non-Root_dir\n");
printf("\tname\t\tdate\t\ttime\t\tcluster\tsize\tattr\n");
for(i=0;i<100;i++)
{
cluster_addr=DATA_OFFSET+i*CLUSTER_SIZE;
if((ret=lseek(fd,cluster_addr,SEEK_SET))<0)
perror("lseek cluster_addr failed");
offset=cluster_addr;
/*只读一簇的内容*/
while(offset<cluster_addr+CLUSTER_SIZE)
{
ret=getEntry(&entry);
offset+=abs(ret);
if(ret>0)
{
printf("%16s\t"
"%d-%d-%d\t"
"%d:%d:%d \t"
"%d\t"
"%d\t"
"%s\n",
entry.short_name,
entry.year,entry.month,entry.day,
entry.hour,entry.minute,entry.second,
entry.FirstCluster,
entry.size,
(entry.subdir)?"dir":"file");
}
}
}
return 1;
}
if(curdir==NULL)
printf("Root_dir\n");
else
printf("%s_dir\n",curdir->short_name);
printf("\tname\t\tdate\t\ttime\t\tcluster\tsize\tattr\n");
if(curdir==NULL) //显示根目录区
{
/*将fd定位到根目录区的起始地址*/
if((ret=lseek(fd,ROOTDIR_OFFSET,SEEK_SET))<0)
perror("lseek ROOTDIR_OFFSET failed");
offset=ROOTDIR_OFFSET;
/*从根目录区开始遍历,直到数据区起始地址*/
while(offset<DATA_OFFSET)
{
ret=getEntry(&entry);
offset+=abs(ret);
if(ret>0)
{
printf("%16s\t"
"%d-%d-%d\t"
"%d:%d:%d \t"
"%d\t"
"%d\t"
"%s\n",
entry.short_name,
entry.year,entry.month,entry.day,
entry.hour,entry.minute,entry.second,
entry.FirstCluster,
entry.size,
(entry.subdir)?"dir":"file");
}
}
}
else //显示子目录
{
cluster_addr=DATA_OFFSET+(curdir->FirstCluster-2)*CLUSTER_SIZE;
if((ret=lseek(fd,cluster_addr,SEEK_SET)