static int32 _initialize_file( IN tffs_t * ptffs, IN tdir_t * pdir, IN tdir_entry_t * pdir_entry, OUT tfile_t * pfile) { int32 ret; pfile->ptffs = ptffs; pfile->pdir = pdir; pfile->pdir_entry = pdir_entry; ret = FILE_OK; pfile->start_clus = dirent_get_clus(pdir_entry); pfile->file_size = dirent_get_file_size(pdir_entry); pfile->cur_clus = pfile->start_clus; pfile->cur_sec = 0; pfile->cur_sec_offset = 0; pfile->cur_fp_offset = 0; if (pfile->open_mode == OPENMODE_APPEND) { pfile->cur_fp_offset = dirent_get_file_size(pdir_entry); _file_seek(pfile, pfile->cur_fp_offset); if (pfile->cur_clus != 0) { if (cache_readsector(ptffs->pcache, clus2sec(ptffs, pfile->cur_clus) + pfile->cur_sec, pfile->secbuf) != CACHE_OK) { ret = ERR_TFFS_DEVICE_FAIL; } } } else if (pfile->open_mode == OPENMODE_WRITE) { if (pfile->start_clus != 0) { if (fat_free_clus(ptffs->pfat, pfile->start_clus) != FAT_OK) { ERR("%s(): %d fat_free_clus failed.\n", __FUNCTION__, __LINE__); ret = ERR_TFFS_FAT; } } dirent_set_file_size(pdir_entry , 0); dirent_set_clus(pdir_entry, 0); pfile->file_size = 0; pfile->cur_clus = 0; pfile->cur_sec = 0; pfile->cur_sec_offset = 0; pfile->cur_fp_offset = 0; } else { if (pfile->cur_clus != 0) { if (cache_readsector(ptffs->pcache, clus2sec(ptffs, pfile->cur_clus) + pfile->cur_sec, pfile->secbuf) != CACHE_OK) { ret = ERR_TFFS_DEVICE_FAIL; } } } return ret; }
int32 file_read_sector( IN tfile_t * pfile) { int32 ret; tffs_t * ptffs = pfile->ptffs; if (pfile->cur_clus == 0) { ret = ERR_FILE_EOF; } else { if (fat_get_next_sec(ptffs->pfat, &pfile->cur_clus, &pfile->cur_sec)) { if (cache_readsector(ptffs->pcache, clus2sec(ptffs, pfile->cur_clus) + pfile->cur_sec, pfile->secbuf) == CACHE_OK) { ret = FILE_OK; } else { ret = ERR_FILE_DEVICE_FAIL; } } else { ret = ERR_FILE_EOF; } } return ret; }
static void clearclus(u32 clus) { u16 sect; tzmemclr(filesectbuf, 512); for (sect = 0; sect < fpm.spc; sect++) writesec(clus2sec(clus) + sect); }
uint appendBuf(uint clus, void *buf, int size, int curWSize) { uint expandClusNo = -1; // 下一个簇号 uchar nextClus[4]; // 下一个簇号 uint clusBytes = SECPERCLUS * SECSIZE; // 单个簇字节数 uint curClus = clus; // 需要向curClus簇内写入内容 uint offSec = (curWSize % clusBytes) / SECSIZE; // 取值范围:[0,1...SECPERCLUS) uint curSec = clus2sec(curClus) + offSec; uint hasWBytes = (curWSize % clusBytes) % SECSIZE; uint leaveBytes = SECSIZE - hasWBytes; // 该扇区剩余的空闲字节数 char fileEnd[4] = {0xff,0xff,0xff,0xff}; // -1 uint shouldWrite = min(size, leaveBytes); uint res = clus; // priority 1: 是否需要扩展簇? if((size + (curWSize % clusBytes) > clusBytes) || (curWSize > 0 && curWSize % clusBytes == 0)) { while(expandClusNo == -1){ expandClusNo = cnallloc(); } nextClus[0] = expandClusNo; nextClus[1] = expandClusNo >> 8; nextClus[2] = expandClusNo >> 16; nextClus[3] = expandClusNo >> 24; wsect4bytes(fatFstSec, curClus, nextClus); wsect4bytes(fatFstSec, expandClusNo, fileEnd); res = expandClusNo; } if(curWSize > 0 && curWSize % clusBytes == 0) { curClus = expandClusNo; curSec = clus2sec(curClus); } // 向簇中写入buf while(size > 0) { wsectnbytes(curSec, hasWBytes, buf, shouldWrite); buf += shouldWrite; size -= shouldWrite; leaveBytes -= shouldWrite; hasWBytes = (hasWBytes + shouldWrite) % SECSIZE; if (leaveBytes == 0) { curSec = (offSec + 1 >= SECPERCLUS) ? (clus2sec(expandClusNo)) : (curSec + 1); offSec = (offSec + 1 >= SECPERCLUS) ? (0) : (offSec + 1); hasWBytes = 0; leaveBytes = SECPERCLUS; } shouldWrite = min(size, leaveBytes); } return res; }
void czero(uint clus) { uint sec = clus2sec(clus); uint end = sec + SECPERCLUS; for(; sec < end; sec++) { szero(sec); } }
int32 file_write_sector( IN tfile_t * pfile) { int32 ret; tffs_t * ptffs = pfile->ptffs; tdir_entry_t * pdir_entry = pfile->pdir_entry; uint32 new_clus; ret = FILE_OK; if (pfile->cur_clus == 0) { int32 fatret; if ((fatret = fat_malloc_clus(ptffs->pfat, FAT_INVALID_CLUS, &new_clus)) == FAT_OK) { DBG("%s: new_clus = %d\n", __FUNCTION__, new_clus); dirent_set_clus(pdir_entry, new_clus); pfile->cur_clus = new_clus; pfile->cur_sec = 0; } else if (fatret == ERR_FAT_NO_FREE_CLUSTER) { ret = ERR_FILE_NO_FREE_CLUSTER; } else { ret = ERR_FILE_DEVICE_FAIL; } } if (ret == FILE_OK) { if (cache_writesector(ptffs->pcache, clus2sec(ptffs, pfile->cur_clus) + pfile->cur_sec, pfile->secbuf) != CACHE_OK) { ret = ERR_FILE_DEVICE_FAIL; } } return ret; }