📄 fat_write.c
字号:
unsigned int fatSector;
ret = -1;
//indexCount is numer of cluster indices per sector
indexCount = bpb->sectorSize / 2; //FAT16->2, FAT32->4
//save both fat tables
for (fatNumber = 0; fatNumber < bpb->fatCount; fatNumber++) {
fatSector = bpb->partStart + bpb->resSectors + (fatNumber * bpb->fatSize);
fatSector += currentCluster / indexCount;
ret = READ_SECTOR(fatSector, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat16 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
i = currentCluster % indexCount;
i*=2; //fat16
sbuf[i++] = value & 0xFF;
sbuf[i] = ((value & 0xFF00) >> 8);
ret = WRITE_SECTOR(fatSector);
if (ret < 0) {
printf("FAT driver:Writed fat16 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
}
return ret;
}
/*
save value at the cluster record in FAT 16
*/
int fat_saveClusterRecord32(fat_bpb* bpb, unsigned int currentCluster, unsigned int value) {
int i;
int ret;
int indexCount;
int fatNumber;
unsigned int fatSector;
ret = -1;
//indexCount is numer of cluster indices per sector
indexCount = bpb->sectorSize / 4; //FAT16->2, FAT32->4
//save both fat tables
for (fatNumber = 0; fatNumber < bpb->fatCount; fatNumber++) {
fatSector = bpb->partStart + bpb->resSectors + (fatNumber * bpb->fatSize);
fatSector += currentCluster / indexCount;
ret = READ_SECTOR(fatSector, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat32 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
i = currentCluster % indexCount;
i*=4; //fat32
sbuf[i++] = value & 0xFF;
sbuf[i++] = ((value & 0xFF00) >> 8);
sbuf[i++] = ((value & 0xFF0000) >> 16);
sbuf[i] = (sbuf[i] &0xF0) + ((value >> 24) & 0x0F); //preserve the highest nibble intact
ret = WRITE_SECTOR(fatSector);
if (ret < 0) {
printf("FAT driver:Writed fat32 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
}
return ret;
}
/*
Append (and write) cluster chain to the FAT table.
currentCluster - current end cluster record.
endCluster - new end cluster record.
Note: there is no checking wether the currentCluster holds the EOF marker!
Example
current FAT:
index 09 10 11 12
+-----+-----+-----+-----+
value + 10 | EOF | 0 | 0 |
+-----+-----+-----+-----+
currentcluster = 10, endcluster = 12
updated FAT (after the function ends):
index 09 10 11 12
+-----+-----+-----+-----+
value + 10 | 12 | 0 | EOF |
+-----+-----+-----+-----+
*/
int fat_appendClusterChain(fat_bpb* bpb, unsigned int currentCluster, unsigned int endCluster) {
int ret;
ret = -1;
switch (bpb->fatType) {
case FAT12:
ret = fat_saveClusterRecord12(bpb, currentCluster, endCluster);
if (ret < 0) return ret;
ret = fat_saveClusterRecord12(bpb, endCluster, 0xFFF);
break;
case FAT16:
XPRINTF("I: appending cluster chain : current=%d end=%d \n", currentCluster, endCluster);
ret = fat_saveClusterRecord16(bpb, currentCluster, endCluster);
if (ret < 0) return ret;
ret = fat_saveClusterRecord16(bpb, endCluster, 0xFFFF);
break;
case FAT32:
ret = fat_saveClusterRecord32(bpb, currentCluster, endCluster);
if (ret < 0) return ret;
ret = fat_saveClusterRecord32(bpb, endCluster, 0xFFFFFFF);
break;
}
return ret;
}
/*
create new cluster chain (of size 1 cluster) at the cluster index
*/
int fat_createClusterChain(fat_bpb* bpb, unsigned int cluster) {
switch (bpb->fatType) {
case FAT12: return fat_saveClusterRecord12(bpb, cluster, 0xFFF);
case FAT16: return fat_saveClusterRecord16(bpb, cluster, 0xFFFF);
case FAT32: return fat_saveClusterRecord32(bpb, cluster, 0xFFFFFFF);
}
return -EFAULT;
}
/*
modify the cluster (in FAT table) at the cluster index
*/
int fat_modifyClusterChain(fat_bpb* bpb, unsigned int cluster, unsigned int value) {
switch (bpb->fatType) {
case FAT12: return fat_saveClusterRecord12(bpb, cluster, value);
case FAT16: return fat_saveClusterRecord16(bpb, cluster, value);
case FAT32: return fat_saveClusterRecord32(bpb, cluster, value);
}
return -EFAULT;
}
/*
delete cluster chain starting at cluster
*/
int fat_deleteClusterChain(fat_bpb* bpb, unsigned int cluster) {
int ret;
int size;
int cont;
int end;
int i;
if (cluster < 2) {
return -EFAULT;
}
XPRINTF("I: delete cluster chain starting at cluster=%d\n", cluster);
cont = 1;
while (cont) {
size = fat_getClusterChain(bpb, cluster, cbuf, MAX_DIR_CLUSTER, 1);
if (size == 0) {
size = MAX_DIR_CLUSTER;
}
end = size-1; //do not delete last cluster in the chain buffer
#ifdef DEBUG
fat_dumpClusterChain(cbuf, size, 0);
#endif
for (i = 0 ; i < end; i++) {
ret = fat_modifyClusterChain(bpb, cbuf[i], 0);
if (ret < 0) {
return ret;
}
}
//the cluster chain continues
if (size == MAX_DIR_CLUSTER) {
cluster = cbuf[end];
} else {
//no more cluster entries - delete the last cluster entry
ret = fat_modifyClusterChain(bpb, cbuf[end], 0);
if (ret < 0) {
return ret;
}
cont = 0;
}
fat_invalidateLastChainResult(); //prevent to misuse current (now deleted) cbuf
}
return 1;
}
/*
Get single empty cluster from the clusterStack (cS is small cache of free clusters)
Passed currentCluster is updated in the FAT and the new returned cluster index is
appended at the end of fat chain!
*/
unsigned int fat_getFreeCluster(fat_bpb* bpb, unsigned int currentCluster) {
int ret;
unsigned int result;
//cluster stack is empty - find and fill the cS
if (clStackIndex <= 0) {
clStackIndex = 0;
ret = fat_readEmptyClusters(bpb);
if (ret <= 0) return 0;
clStackIndex = ret;
}
//pop from cluster stack
clStackIndex--;
result = clStack[clStackIndex];
//append the cluster chain
if (currentCluster) {
ret = fat_appendClusterChain(bpb, currentCluster, result);
} else { //create new cluster chain
ret = fat_createClusterChain(bpb, result);
}
if (ret < 0) return 0;
return result;
}
/*
simple conversion of the char from lower case to upper case
*/
inline unsigned char toUpperChar(unsigned char c) {
if (c >96 && c < 123) {
return (c - 32);
}
return c;
}
/*
returns number of direntry positions that the name takes
*/
int getDirentrySize(unsigned char* lname) {
int len;
int result;
len = strlen((const char*)lname);
result = len / 13;
if (len % 13 > 0) result++;
return result;
}
/*
compute checksum of the short filename
*/
unsigned char computeNameChecksum(unsigned char* sname) {
unsigned char result;
int i;
result = 0;
for (i = 0; i < 11; i++) {
result = (0x80 * (0x01 & result)) + (result >> 1); //ROR 1
result += sname[i];
}
return result;
}
/*
fill the LFN (long filename) direntry
*/
void setLfnEntry(unsigned char* lname, int nameSize, unsigned char chsum, unsigned char* buffer, int part, int maxPart){
int i,j;
unsigned char* offset;
unsigned char name[26]; //unicode name buffer = 13 characters per 2 bytes
int nameStart;
fat_direntry_lfn* dlfn;
offset = buffer + (maxPart-part) * 32;
dlfn = (fat_direntry_lfn*) offset;
nameStart = 13 * part;
j = nameSize - nameStart;
if (j > 13) {
j = 13;
}
//fake unicode conversion
for (i = 0; i < j; i++) {
name[i*2] = lname[nameStart + i];
name[i*2+1] = 0;
}
//rest of the name is zero terminated and padded with 0xFF
for (i = j; i < 13; i++) {
if (i == j) {
name[i*2] = 0;
name[i*2+1] = 0;
} else {
name[i*2] = 0xFF;
name[i*2+1] = 0xFF;
}
}
if (maxPart == 0) {
i = 1;
} else {
i = part/maxPart;
}
dlfn->entrySeq = (part+1) + (i * 64);
dlfn->checksum = chsum;
//1st part of the name
for (i = 0; i < 10; i++) dlfn->name1[i] = name[i];
//2nd part of the name
for (i = 0; i < 12; i++) dlfn->name2[i] = name[i+10];
//3rd part of the name
for (i = 0; i < 4; i++) dlfn->name3[i] = name[i+22];
dlfn->rshv = 0x0f;
dlfn->reserved1 = 0;
dlfn->reserved2[0] = 0;
dlfn->reserved2[1] = 0;
}
/*
update the SFN (long filename) direntry - DATE and TIME
*/
void setSfnDate(fat_direntry_sfn* dsfn, int mode) {
int year, month, day, hour, minute, sec;
unsigned char tmpClk[4];
#ifdef _PS2_
//ps2 specific routine to get time and date
cd_clock_t cdtime;
s32 tmp;
if(CdReadClock(&cdtime)!=0 && cdtime.stat==0)
{
tmp=cdtime.second>>4;
sec=(u32)(((tmp<<2)+tmp)<<1)+(cdtime.second&0x0F);
tmp=cdtime.minute>>4;
minute=(((tmp<<2)+tmp)<<1)+(cdtime.minute&0x0F);
tmp=cdtime.hour>>4;
hour=(((tmp<<2)+tmp)<<1)+(cdtime.hour&0x0F);
hour= (hour + 4 + 12) % 24; // TEMP FIX (need to deal with timezones?)
tmp=cdtime.day>>4;
day=(((tmp<<2)+tmp)<<1)+(cdtime.day&0x0F);
tmp=cdtime.month>>4;
//value=(((tmp<<2)+tmp)<<1)+(cdtime.month&0x0F);
month= cdtime.month & 0x0F;
tmp=cdtime.year>>4;
year=(((tmp<<2)+tmp)<<1)+(cdtime.year&0xF)+2000;
} else {
year = 2005; month = 1; day = 6;
hour = 14; minute = 12; sec = 10;
}
#else
time_t nowTime;
struct tm* nowTm;
time(&nowTime);
nowTm = localtime(&nowTime);
year = nowTm->tm_year + 1900;
month = nowTm->tm_mon+1;
day = nowTm->tm_mday;
hour = nowTm->tm_hour;
minute= nowTm->tm_min;
sec = nowTm->tm_sec;
#endif /* _PS2_ */
if (dsfn == NULL || mode == 0) {
return;
}
tmpClk[0] = (sec / 2) & 0x1F; //seconds
tmpClk[0] += (minute & 0x07) << 5; // minute
tmpClk[1] = (minute & 0x38) >> 3; // minute
tmpClk[1] += (hour & 0x1F) << 3; // hour
tmpClk[2] = (day & 0x1F); //day
tmpClk[2] += (month & 0x07) << 5; // month
tmpClk[3] = (month & 0x08) >> 3; // month
tmpClk[3] += ((year-1980) & 0x7F) << 1; //year
XPRINTF("year=%d, month=%d, day=%d h=%d m=%d s=%d \n", year, month, day, hour, minute, sec);
//set date & time of creation
if (mode & DATE_CREATE) {
dsfn->timeCreate[0] = tmpClk[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -