📄 fat_write.c
字号:
for (i= 2; i < entryCount; i++) { //first two records should be '.' & '..'
if ((entry[i] & 0x03) != 0) {
XPRINTF("I: directory not empty!\n");
return 0;
}
}
XPRINTF("I: directory is empty.\n");
return 1;
}
/*
Remove the name (direntries of the file or directory) from the directory space.
lname - long name (without the path)
directory - 0->delete file 1-delete directory
startCluster - start cluster of the directory space
*/
int fat_clearDirSpace(fat_bpb* bpb, unsigned char* lname, char directory, unsigned int* startCluster) {
int ret;
int i;
unsigned char sname[12]; //short name 8+3 + terminator
unsigned int dirCluster;
unsigned int theSector;
int entryCount;
int entryIndex;
int direntrySize;
fat_direntry_sfn* dsfn;
unsigned int sfnSector;
int sfnOffset;
unsigned char entry[DIRENTRY_COUNT];
memset(entry, 0, DIRENTRY_COUNT);
sname[0] = 0;
dirCluster = *startCluster;
//get information about existing direntries (palcement of the empty/reusable direntries)
//and find the lname in the directory
//also fill up the dsSec and dsOfs information
ret = fat_fillDirentryInfo(bpb, lname, sname, directory, startCluster, entry, DIRENTRY_COUNT, &sfnSector, &sfnOffset);
if (ret != 0) {
XPRINTF("E: direntry not found!\n");
return -ENOENT;
}
XPRINTF("clear dir space: dir found at cluster=%d \n ", *startCluster);
//Check wether any file or directory exist in te target directory space.
//We should not delete the directory if files/directories exist
//because just clearing the dir doesn't free the fat clusters
//occupied by files.
if (directory) {
//check wether sub-directory is empty
//startCluster now points to subdirectory start cluster
ret = checkDirspaceEmpty(bpb, *startCluster, entry);
if (ret == 0) { //directorty contains some files
return -ENOTEMPTY;
}
//read the direntry info again, because we lost it during subdir check
*startCluster = dirCluster;
memset(entry, 0, DIRENTRY_COUNT);
ret = fat_fillDirentryInfo(bpb, lname, sname, directory, startCluster, entry, DIRENTRY_COUNT, &sfnSector, &sfnOffset);
if (ret != 0) {
XPRINTF("E: direntry not found!\n");
return -ENOENT;
}
}
#ifdef DEBUG
for (i = 0; i < deIdx; i++) {
printf("Sector=%d (%d) Offset=%d (%d) \n",
deSec[i], deSec[i]*bpb->sectorSize,
deOfs[i], deSec[i]*bpb->sectorSize + deOfs[i]);
}
#endif
//now mark direntries as deleted
theSector = 0;
for (i = 0; i < deIdx; i++) {
if (deSec[i] != theSector) {
if (theSector > 0) {
ret = WRITE_SECTOR(theSector);
if (ret < 0) {
printf("FAT writer: write directory sector failed ! sector=%i\n", theSector);
return -EIO;
}
}
theSector = deSec[i];
ret = READ_SECTOR(theSector, sbuf);
if (ret < 0) {
printf("FAT writer: read directory sector failed ! sector=%i\n", theSector);
return -EIO;
}
}
sbuf[deOfs[i]] = 0xE5; //delete marker
}
if (theSector > 0) {
ret = WRITE_SECTOR(theSector);
if (ret < 0) {
printf("FAT writer: write directory sector failed ! sector=%i\n", theSector);
return -EIO;
}
}
//now delete whole cluster chain starting at the file's first cluster
ret = fat_deleteClusterChain(bpb, *startCluster);
if (ret < 0) {
XPRINTF("E: delete cluster chain failed!\n");
return ret;
}
FLUSH_SECTORS();
return 1;
}
/* ===================================================================== */
/*
cluster - start cluster of the file
sfnSector - short filename entry sector
sfnOffset - short filename entry offset from the sector start
*/
int fat_truncateFile(fat_bpb* bpb, unsigned int cluster, unsigned int sfnSector, int sfnOffset ) {
int ret;
fat_direntry_sfn* dsfn;
if (cluster == 0 || sfnSector == 0) {
return -EFAULT;
}
//now delete whole cluster chain starting at the file's first cluster
ret = fat_deleteClusterChain(bpb, cluster);
if (ret < 0) {
XPRINTF("E: delete cluster chain failed!\n");
return ret;
}
//terminate cluster
ret = fat_createClusterChain(bpb, cluster);
if (ret < 0) {
XPRINTF("E: truncate cluster chain failed!\n");
return ret;
}
ret = READ_SECTOR(sfnSector, sbuf);
if (ret < 0) {
printf("FAT writer: read direntry sector failed ! sector=%i\n", sfnSector);
return -EIO;
}
dsfn = (fat_direntry_sfn*) (sbuf + sfnOffset);
dsfn->size[0] = 0;
dsfn->size[1] = 0;
dsfn->size[2] = 0;
dsfn->size[3] = 0;
ret = WRITE_SECTOR(sfnSector);
if (ret < 0) {
printf("FAT writer: write directory sector failed ! sector=%i\n", sfnSector);
return -EIO;
}
return 1;
}
/*
Update size of the SFN entry
cluster - start cluster of the file
sfnSector - short filename entry sector
sfnOffset - short filename entry offset from the sector start
*/
int fat_updateSfn(int size, unsigned int sfnSector, int sfnOffset ) {
int ret;
fat_direntry_sfn* dsfn;
if (sfnSector == 0) {
return -EFAULT;
}
ret = READ_SECTOR(sfnSector, sbuf);
if (ret < 0) {
printf("FAT writer: read direntry sector failed ! sector=%i\n", sfnSector);
return -EIO;
}
dsfn = (fat_direntry_sfn*) (sbuf + sfnOffset);
dsfn->size[0] = size & 0xFF;
dsfn->size[1] = (size & 0xFF00) >> 8;
dsfn->size[2] = (size & 0xFF0000) >> 16;
dsfn->size[3] = (size & 0xFF000000) >> 24;
setSfnDate(dsfn, DATE_MODIFY);
ret = WRITE_SECTOR(sfnSector);
if (ret < 0) {
printf("FAT writer: write directory sector failed ! sector=%i\n", sfnSector);
return -EIO;
}
XPRINTF("I: sfn updated, file size=%d \n", size);
return 1;
}
/*
create file or directory
fname - path and filename
directory - set to 0 to create file, 1 to create directory
escapeNotExist - set to 1 if you want to report error if file not exist.
Otherwise set to 0 and file/dir will be created.
cluster - start cluster of the directory space - default is 0 -> root directory
sfnSector - sector of the SFN entry (output) - helps to modify direntry (size, date, time)
sfnOffset - offset (in bytes) of the SFN entry (output)
*/
int fat_createFile(fat_bpb* bpb, const char* fname, char directory, char escapeNotExist, unsigned int* cluster, unsigned int* sfnSector, int* sfnOffset) {
int ret;
unsigned int startCluster;
unsigned char path[FAT_MAX_PATH];
unsigned char lname[FAT_MAX_NAME];
ret = separatePathAndName(fname, path, lname);
if (lname[0] == 0 || lname[0]=='.' || ret < 0) {
XPRINTF("E: file name not exist or not valid!");
return -ENOENT;
}
//get start cluster of the last sub-directory of the path
startCluster = 0;
ret = fat_getFileStartCluster(bpb, (const char*)path, &startCluster, NULL);
if (ret > 0) {
XPRINTF("directory=%s name=%s cluster=%d \n", path, lname, startCluster);
}else {
XPRINTF("E: directory not found! \n");
return -ENOENT;
}
//modify directory space of the path (cread direntries)
//and/or create new (empty) directory space if directory creation requested
ret = fat_modifyDirSpace(bpb, lname, directory, escapeNotExist, &startCluster, sfnSector, sfnOffset);
if (ret < 0) {
XPRINTF("E: modifyDirSpace failed!\n");
return ret;
}
XPRINTF("I: SFN info: sector=%d (%d) offset=%d (%d) startCluster=%d\n", *sfnSector, *sfnSector * bpb->sectorSize, *sfnOffset, *sfnOffset + (*sfnSector * bpb->sectorSize), startCluster);
*cluster = startCluster;
if (ret == 0) {
XPRINTF("I: file already exists at cluster=%d\n", startCluster);
return 2;
}
return 1;
}
int fat_deleteFile(fat_bpb* bpb, const char* fname, char directory) {
int ret;
unsigned int startCluster;
unsigned int directoryCluster;
unsigned char path[FAT_MAX_PATH];
unsigned char lname[FAT_MAX_NAME];
ret = separatePathAndName(fname, path, lname);
if (lname[0] == 0 || lname[0]=='.' || ret < 0) {
XPRINTF("E: file name not exist or not valid!");
return -ENOENT;
}
//get start cluster of the last sub-directory of the path
startCluster = 0;
ret = fat_getFileStartCluster(bpb, (const char*)path, &startCluster, NULL);
if (ret > 0) {
XPRINTF("directory=%s name=%s cluster=%d \n", path, lname, startCluster);
}else {
XPRINTF("E: directory not found! \n");
return -ENOENT;
}
//delete direntries and modify fat
directoryCluster = startCluster;
ret = fat_clearDirSpace(bpb, lname, directory, &startCluster);
if (ret < 0) {
XPRINTF("E: cleanDirSpace failed!\n");
return ret;
}
if (startCluster != directoryCluster) {
XPRINTF("I: file/dir removed from cluster=%d\n", startCluster);
}
return 1;
}
int fat_writeFile(fat_bpb* bpb, fat_dir* fatDir, int* updateClusterIndices, unsigned int filePos, unsigned char* buffer, int size) {
int ret;
int i,j;
int chainSize;
int nextChain;
int startSector;
int bufSize;
int sectorSkip;
int clusterSkip;
int dataSkip;
unsigned int bufferPos;
unsigned int fileCluster;
unsigned int clusterPos;
unsigned int endPosFile;
unsigned int endPosCluster;
unsigned int lastCluster;
int clusterChainStart;
//check wether we have enough clusters allocated
i = bpb->clusterSize * bpb->sectorSize; //the size (in bytes) of the one cluster
j = fatDir->size / i;
if (fatDir->size % i) {
j++;
}
if (j == 0) j = 1; //the file have allways at least one cluster allocated
endPosCluster = j * i;
endPosFile = filePos + size;
*updateClusterIndices = 0;
//allocate additional cluster(s)
if (endPosFile > endPosCluster) {
ret = endPosFile - endPosCluster; //additional space needed in bytes
j = ret / i; //additional space needed (given in number of clusters)
if (ret % i) {
j++;
}
lastCluster = fatDir->lastCluster;
XPRINTF("I: writeFile: last cluster= %d \n", lastCluster);
if (lastCluster == 0) return -ENOSPC; // no more free clusters or data invalid
for (i = 0; i < j; i++) {
lastCluster = fat_getFreeCluster(bpb, lastCluster);
if (lastCluster == 0) return -ENOSPC; // no more free clusters
}
fatDir->lastCluster = lastCluster;
*updateClusterIndices = j;
fat_invalidateLastChainResult(); //prevent to misuse current (now deleted) cbuf
XPRINTF("I: writeFile: new clusters allocated = %d new lastCluster=%d \n", j, lastCluster);
}
XPRINTF("I: write file: filePos=%d dataSize=%d \n", filePos, size);
fat_getClusterAtFilePos(bpb, fatDir, filePos, &fileCluster, &clusterPos);
sectorSkip = (filePos - clusterPos) / bpb->sectorSize;
clusterSkip = sectorSkip / bpb->clusterSize;
sectorSkip %= bpb->clusterSize;
dataSkip = filePos % bpb->sectorSize;
bufferPos = 0;
XPRINTF("fileCluster = %i, clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i \n",
fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip);
if (fileCluster < 2) {
return -EFAULT;
}
bufSize = SECTOR_SIZE;
nextChain = 1;
clusterChainStart = 1;
while (nextChain && size > 0 ) {
chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart);
clusterChainStart = 0;
if (chainSize == 0) { //the chain is full, but more chain parts exist
chainSize = MAX_DIR_CLUSTER;
fileCluster = cbuf[MAX_DIR_CLUSTER - 1];
}else { //chain fits in the chain buffer completely - no next chain needed
nextChain = 0;
}
while (clusterSkip >= MAX_DIR_CLUSTER) {
chainSize = fat_getClusterChain(bpb, fileCluster, cbuf, MAX_DIR_CLUSTER, clusterChainStart);
clusterChainStart = 0;
if (chainSize == 0) { //the chain is full, but more chain parts exist
chainSize = MAX_DIR_CLUSTER;
fileCluster = cbuf[MAX_DIR_CLUSTER - 1];
}else { //chain fits in the chain buffer completely - no next chain needed
nextChain = 0;
}
clusterSkip -= MAX_DIR_CLUSTER;
}
#ifdef DEBUG
fat_dumpClusterChain(cbuf, chainSize, clusterSkip);
fat_dumpClusterChain(cbuf, chainSize, 0);
printf("fileCluster = %i, clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i filePos=%i \n",
fileCluster, clusterPos, clusterSkip, sectorSkip, dataSkip, filePos);
#endif
//process the cluster chain (cbuf) and skip leading clusters if needed
for (i = 0 + clusterSkip; i < chainSize && size > 0; i++) {
//read cluster and save cluster content
startSector = fat_cluster2sector(bpb, cbuf[i]);
//process all sectors of the cluster (and skip leading sectors if needed)
for (j = 0 + sectorSkip; j < bpb->clusterSize && size > 0; j++) {
//TODO - do not read when writing to unallocated sectors
ret = READ_SECTOR(startSector + j, sbuf);
if (ret < 0) {
printf("Read sector failed ! sector=%i\n", sta
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -