📄 fatfs.c
字号:
// 如果文件大小被修改,将文件信息回写
if(f->Flags & F_SZCHG) {
DRIVE *d;
DIRENTRY *pe;
UCHAR *tmpbuf;
ULONG tm;
LockDrive(d);
d = f->Drive;
tmpbuf = d->tmpbuf;
pe = (DIRENTRY *)(tmpbuf + f->DEOffst);
if((*d->ReadSector)(d, f->DESt, tmpbuf)) {
tm = GetTm();
pe->Size = f->Size;
pe->TimeInTenths = 0x57;
pe->CreateTime = tm & 0xFFFF;
pe->CreateDate = tm >> 16;
pe->LastAccessDate = 0x3475;
pe->Date = 0x3475;
pe->Time = 0x7c11;
(*d->WriteSector)(d, f->DESt, tmpbuf);
}
UnlockDrive(d);
}
if(f->Buffer) {
kfree(f->Buffer);
f->Buffer = 0;
}
if(f->Clus) {
kfree(f->Clus);
f->Clus = 0;
}
sm_delete(f->sm);
f->Drive->Ref--;
f->Drive = 0;
}
}
//
// 如果文件内容被修改,将缓冲区内容回写
//
static int
FlushBuffer(FATFILE *f) {
DRIVE *drv;
FATFILE *raw;
ULONG offst;
CHECK_PTR(f);
CHECK_PTR(f->Drive);
drv = f->Drive;
if(!(drv->Flags & DRIVE_MOUNT))
return -1;
//DBG("FlushBuffer...\n");
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
f->Flags &= ~F_MODIF;
if(f->Blk == raw->Blk)
raw->Flags &= ~F_MODIF;
offst = Clus2Sect(drv, raw->Clus[f->Blk]);
if(!WriteCluster(drv, offst, f->Buffer))
return -1;
//LockDrive(drv);
(*drv->Sync2)(drv, offst);
//UnlockDrive(drv);
// WriteFileCallback((int)(f - Files), f->Pos);
return 0;
}
//
// 扩充文件大小
//
static int
ExtendFile(FATFILE *f) {
CLNO cl;
CLNO *ca;
DRIVE *drv;
FATFILE *raw;
CHECK_PTR(f);
CHECK_PTR(f->Drive);
drv = f->Drive;
if(!(drv->Flags & DRIVE_MOUNT))
return FALSE;
//DBG("ExtendFile...\n");
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
//DBG("Allocate Cluster... ");
// 申请一个簇
if(!AllocCluster(drv, 1, &cl)) {
DBG("DISK FULL!\n");
return FALSE;
}
//DBG1("%u\n", cl);
ca = (CLNO *)kmalloc((raw->Blks + 1) * sizeof(CLNO));
Memcpy(ca, raw->Clus, raw->Blks * sizeof(CLNO));
kfree(raw->Clus);
// 连接簇
ca[raw->Blks++] = cl;
raw->Clus = ca;
SetNextCluster(drv, ca[raw->Blks - 2], ca[raw->Blks - 1]);
SetNextCluster(drv, ca[raw->Blks - 1], drv->FatEnd + 1); // FAT_EOF
f->Flags &= ~F_EOF;
raw->Flags &= ~F_EOF;
return TRUE;
}
//
// 将文件当前簇的内容导入缓冲区
//
static int
FillBuffer(FATFILE *f, UINT lblk, int New) {
UINT csz;
DRIVE * drv;
UCHAR * buf;
//UCHAR * acc;
FATFILE *raw;
CHECK_PTR(f);
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
if(f->Blk >= raw->Blks)
DbgOut("f->Blk = %u, raw->Blks = %u\n", f->Blk, raw->Blks);
ASSERT(f->Blk < raw->Blks);
if(lblk > raw->Blks)
DbgOut("lblk = %u, f->Blks = %u\n", lblk, raw->Blks);
ASSERT(lblk <= raw->Blks);
if(lblk == f->Blk)
return TRUE;
if(lblk >= raw->Blks) {
f->Flags |= F_EOF;
return FALSE;
}
drv = f->Drive;
if(!(drv->Flags & DRIVE_MOUNT))
return FALSE;
csz = drv->ClusterSize;
buf = f->Buffer;
// 申请缓冲区空间
if(!buf) {
f->Buffer = buf = (UCHAR *)kmalloc(csz);
}
// 当前缓冲区内容被修改,回写它
if(f->Flags & F_MODIF)
FlushBuffer(f);
// 如果是新建的文件,清空缓冲区
if(New) {
Memset(f->Buffer, 0, csz);
}
else {
if(!ReadCluster(drv, Clus2Sect(drv, raw->Clus[lblk]), f->Buffer))
return FALSE;
}
f->Blk = lblk; // Logic block
return TRUE;
}
//
// 读文件
// fd: 文件号
// buf:数据指针
// sz: 字节数
//
ULONG
ReadFile(int fd, void *buf, ULONG sz) {
ULONG offst, brd;
UINT bsz, csz;
FATFILE *f, *raw;
ASSERT((UINT)fd < FILE_MAX);
CHECK_PTR(buf);
ASSERT(Files[fd].Flags & F_OPEN);
f = &Files[fd];
brd = 0;
if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
goto ret;
ASSERT(f->Magic == FILE_MAGIC);
if(!(f->Drive->Flags & DRIVE_MOUNT))
goto ret;
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
//sm_p(raw->sm, FOREVER);
csz = f->Drive->ClusterSize;
offst = f->Pos;
if(offst + sz > raw->Size)
sz = raw->Size - offst;
while(sz != 0 && !(f->Flags & F_EOF)) {
// 调入当前簇
if(!FillBuffer(f, offst / csz, FALSE))
break;
bsz = csz - (offst & (csz - 1));
if(bsz > sz)
bsz = sz;
Memcpy(buf, f->Buffer + (offst & (csz - 1)), bsz);
// 移动数据指针
sz -= bsz;
brd += bsz;
offst += bsz;
buf = (UCHAR *)buf + bsz;
}
if(offst >= raw->Size)
f->Flags |= F_EOF;
f->Pos = offst;
//sm_v(raw->sm);
ret:
return brd;
}
//
// 写文件
// fd: 文件号
// buf:数据指针
// sz: 字节数
//
ULONG
WriteFile(int fd, void *buf, ULONG sz) {
ULONG offst, bwr;
UINT bsz, csz;
FATFILE *f, *raw;
ASSERT((UINT)fd < FILE_MAX);
CHECK_PTR(buf);
ASSERT(Files[fd].Flags & F_OPEN);
f = &Files[fd];
bwr = 0;
if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
goto ret;
ASSERT(f->Magic == FILE_MAGIC);
if(!(f->Drive->Flags & DRIVE_MOUNT))
return 0;
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
//if(f->Drive->ms != NULL)
// DBG3("WriteFile(%d, %08X, %u)\n", fd, buf, sz);
//sm_p(raw->sm, FOREVER);
csz = f->Drive->ClusterSize;
offst = f->Pos;
while(sz != 0) {
// 调入当前簇
if(!FillBuffer(f, offst / csz, FALSE)) {
// 扩充文件大小
if(!ExtendFile(f))
break;
// 再次调入新簇
if(!FillBuffer(f, offst / csz, TRUE))
break; // ???
}
bsz = csz - (offst & (csz - 1));
if(bsz > sz)
bsz = sz;
Memcpy(f->Buffer + (offst & (csz - 1)), buf, bsz);
// 移动数据指针
f->Flags |= F_MODIF;
sz -= bsz;
bwr += bsz;
offst += bsz;
buf = (UCHAR *)buf + bsz;
}
if(offst > raw->Size) {
// 文件大小被修改
f->Flags |= F_EOF | F_SZCHG;
raw->Size = offst;
}
f->Pos = offst;
//sm_v(raw->sm);
ret:
return bwr;
}
//
// 移动文件访问指针
//
// fd: 文件号
// offst: 偏移
// orig: 移动方式
//
ULONG
SeekFile(int fd, long offst, int orig) {
long pos;
FATFILE *f, *raw;
ASSERT((UINT)fd < FILE_MAX);
ASSERT(orig == 0 || orig == 1 || orig == 2);
ASSERT(Files[fd].Flags & F_OPEN);
f = &Files[fd];
if((UINT)fd >= FILE_MAX || !(f->Flags & F_OPEN))
return -1;
ASSERT(f->Magic == FILE_MAGIC);
if(!(f->Drive->Flags & DRIVE_MOUNT))
return 0;
raw = (f->Flags & F_SHARE) ? f->sf : f;
ASSERT(raw != NULL);
sm_p(raw->sm, FOREVER);
pos = f->Pos;
switch(orig) {
case FILE_BEGIN: pos = offst; break; // 从文件头开始
case FILE_CUR: pos += offst; break; // 从当前位置开始
case FILE_END: pos = (long)raw->Size - offst; break; // 从文件尾开始
}
if(pos < 0) pos = 0;
if(pos >= (long)raw->Size) {
pos = (long)raw->Size;
f->Flags |= F_EOF; // 文件结束标志
}
f->Pos = pos;
sm_v(raw->sm);
return pos;
}
//
// 卸载驱动器
//
int
FatUnmount(DRIVE *d) {
CHECK_PTR(d);
CHECK_PTR(d->sm);
ASSERT(d->Flags & DRIVE_MOUNT);
d->Flags = 0;
sm_delete(d->sm);
d->sm = 0;
return 0;
}
//
// 挂载驱动器
//
// d: 驱动器
// Name: 驱动器名称
//
int
FatMount(DRIVE *d, const char *Name) {
MBR *mbr;
BOOTSECTOR *bs;
int i, ismbr;
UCHAR *tmpbuf;
ASSERT(d);
DBG1("Mount %s... ", Name);
// 读入FAT12/16/32文件系统结构
tmpbuf = d->tmpbuf;
if(!(*d->ReadSector)(d, 0, tmpbuf)) {
err: DBG("FAILURE!\n");
return FALSE;
}
// 判读文件系统的有效性
mbr = (MBR *)tmpbuf;
if(mbr->BootSectorMagic[0] != 0x55 || mbr->BootSectorMagic[1] != 0xaa)
goto err;
// 有的U盘有分区表
ismbr = TRUE;
for(i = 0; i < 4; i++)
if(mbr->List[i].BootIndicator != 0x80 &&
mbr->List[i].BootIndicator != 0x00)
ismbr = FALSE;
bs = (BOOTSECTOR *)mbr;
if((bs->BytesPerSector % 512) || bs->NumberOfFats > 2)
ismbr = TRUE;
if(!ismbr) {
d->Fat32 = bs->TotalSectors == 0 && bs->SectorsPerFat == 0;
} else {
ULONG st;
// 查找分区表中的FAT12/16/32分区
for(i = 0; i < 4; i++) {
if(mbr->List[i].SystemIndicator == 0x4 ||
mbr->List[i].SystemIndicator == 0x6 ||
mbr->List[i].SystemIndicator == 0xe) {
d->Fat32 = FALSE;
break;
}
if(mbr->List[i].SystemIndicator == 0xB ||
mbr->List[i].SystemIndicator == 0xC) {
d->Fat32 = TRUE;
break;
}
}
if(i == 4)
return FALSE;
// 读入真正的FAT12/16/32文件系统结构
st = mbr->List[i].SectorCountBeforePartition;
if(!(*d->ReadSector)(d, st, (void *)bs))
goto err;
if(bs->BootSectorMagic[0] != 0x55 || bs->BootSectorMagic[1] != 0xaa)
goto err;
}
//if(d->Fat32)
// DBG("File system: FAT32\n");
//else
// DBG("File system: FAT16\n");
// 获取文件系统信息
d->BytesPerSector = bs->BytesPerSector;
d->BytesPerSectorShift = mylog2(d->BytesPerSector);
d->SectorsPerCluster = bs->SectorsPerCluster;
d->SectorsPerClusterShift = mylog2(d->SectorsPerCluster);
d->ClusterSizeShift = mylog2(d->ClusterSize =
bs->BytesPerSector << d->SectorsPerClusterShift);
d->NumSectors = bs->TotalSectors ? bs->TotalSectors : bs->TotalSectorsBig;
d->NumClusters = d->NumSectors >> d->SectorsPerClusterShift;
d->Fat2 = 0;
d->FatStart = bs->ReservedSectors + bs->HiddenSectors;
d->FatLength = bs->SectorsPerFat ? bs->SectorsPerFat : bs->SectorsPerFatBig;
if(d->Fat32) {
d->DataStart = d->FatStart + bs->NumberOfFats * bs->SectorsPerFatBig;
d->RootStart = bs->RootDirStartCluster;
d->FatEnd = 0x0FFFFFF7;
}
else {
d->RootEntries = bs->RootDirEntries;
d->RootStart = d->FatStart + bs->NumberOfFats * d->FatLength;
d->DataStart = d->RootStart + ((d->RootEntries * 32) >> d->BytesPerSectorShift);
d->FatEnd = 0xFFF7;
}
d->Fat1 = d->FatStart;
if(bs->NumberOfFats > 1)
d->Fat2 = d->FatStart + d->FatLength;
d->Ref = 0;
d->fatst = -3;
d->Flags = DRIVE_MOUNT;
d->fatgoal = 2;
sm_create(Name, 1, 0, &d->sm);
ASSERT((d->BytesPerSector % 512) == 0);
ASSERT((d->SectorsPerCluster % 2) == 0);
DBG("OK!\n");
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -