📄 fat_write.c
字号:
/*
* fat_driver.c - USB Mass storage driver for PS2
*
* (C) 2005, Marek Olejnik (ole00@post.cz)
*
* FAT filesystem layer - write functions
*
* See the file LICENSE included with this distribution for licensing terms.
*/
#ifdef _PS2_
#include <tamtypes.h>
#include <cdvdman.h>
#include <sysclib.h>
#else
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#endif /* _PS2_ */
#include <errno.h>
#include "fat.h"
#include "fat_driver.h"
#include "scache.h"
//#define DEBUG
#include "mass_debug.h"
#define DATE_CREATE 1
#define DATE_MODIFY 2
#define READ_SECTOR(a, b) scache_readSector((a), (void **)&b)
#define ALLOC_SECTOR(a, b) scache_allocSector((a), (void **)&b)
#define WRITE_SECTOR(a) scache_writeSector((a))
#define FLUSH_SECTORS scache_flushSectors
#define DIRENTRY_COUNT 1024
#define MAX_CLUSTER_STACK 128
#define MEMCPY(a,b,c) memcpy((a),(b),(c))
#define SECTOR_SIZE Size_Sector
extern unsigned Size_Sector; // store size of sector from usb mass
extern unsigned char* sbuf; //sector buffer
extern unsigned int cbuf[MAX_DIR_CLUSTER]; //cluster index buffer
unsigned char tbuf[512]; //temporary buffer
/* enough for long filename of length 260 characters (20*13) and one short filename */
#define MAX_DE_STACK 21
unsigned int deSec[MAX_DE_STACK]; //direntry sector
int deOfs[MAX_DE_STACK]; //direntry offset
int deIdx = 0; //direntry index
unsigned int clStack[MAX_CLUSTER_STACK]; //cluster allocation stack
int clStackIndex = 0;
unsigned int clStackLast = 0; // last free cluster of the fat table
/*
reorder (swap) the cluster stack records
*/
void swapClStack(int startIndex, int endIndex) {
int i;
int size;
int offset1, offset2;
unsigned int tmp;
size = endIndex-startIndex;
if (size < 2) {
return;
}
#ifdef DEBUG
printf("cluster stack: ");
for (i = 0; i < endIndex; i++) printf("%d, ", clStack[i]);
printf("end \n");
#endif
size/=2;
for (i = 0; i < size; i++) {
offset1 = startIndex + i;
offset2 = endIndex - 1 - i;
tmp = clStack[offset1];
clStack[offset1] = clStack[offset2];
clStack[offset2] = tmp;
}
}
/*
scan FAT12 for free clusters and store them to the cluster stack
*/
int fat_readEmptyClusters12(fat_bpb* bpb) {
int ret;
int i;
int recordOffset;
int sectorSpan;
int fatSector;
int cont;
int lastFatSector;
unsigned int cluster;
unsigned int clusterValue;
unsigned char xbuf[4];
int oldClStackIndex;
oldClStackIndex = clStackIndex;
cont = 1;
lastFatSector = -1;
i = 0;
cluster = clStackLast;
while(clStackIndex < MAX_CLUSTER_STACK ) {
recordOffset = (cluster * 3) / 2; //offset of the cluster record (in bytes) from the FAT start
fatSector = recordOffset / bpb->sectorSize;
sectorSpan = 0;
if ((recordOffset % bpb->sectorSize) == (bpb->sectorSize - 1)) {
sectorSpan = 1;
}
if (lastFatSector != fatSector || sectorSpan) {
ret = READ_SECTOR(bpb->partStart + bpb->resSectors + fatSector, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat12 sector failed! sector=%i! \n", bpb->partStart + bpb->resSectors + fatSector );
return -EIO;
}
lastFatSector = fatSector;
if (sectorSpan) {
xbuf[0] = sbuf[bpb->sectorSize - 2];
xbuf[1] = sbuf[bpb->sectorSize - 1];
ret = READ_SECTOR(bpb->partStart + bpb->resSectors + fatSector + 1, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat12 sector failed sector=%i! \n", bpb->partStart + bpb->resSectors + fatSector + 1);
return -EIO;
}
xbuf[2] = sbuf[0];
xbuf[3] = sbuf[1];
}
}
if (sectorSpan) { // use xbuf as source buffer
clusterValue = fat_getClusterRecord12(xbuf + (recordOffset % bpb->sectorSize) - (bpb->sectorSize-2), cluster % 2);
} else { // use sector buffer as source buffer
clusterValue = fat_getClusterRecord12(sbuf + (recordOffset % bpb->sectorSize), cluster % 2);
}
if (clusterValue == 0) {
clStackLast = cluster;
clStack[clStackIndex] = cluster;
clStackIndex++;
}
cluster++; //read next cluster record in the sequence
}
//the stack operates as LIFO but we put in the clusters as FIFO
//we should reverse the cluster order - not necessary
//but it will retain the natural (increasing) order of
//the cluster chain
swapClStack(oldClStackIndex, clStackIndex);
return clStackIndex;
}
/*
scan FAT32 for free clusters and store them to the cluster stack
*/
int fat_readEmptyClusters32(fat_bpb* bpb) {
int i,j;
int ret;
int indexCount;
unsigned int fatStartSector;
unsigned int cluster;
unsigned int clusterValue;
int oldClStackIndex;
int sectorSkip;
int recordSkip;
oldClStackIndex = clStackIndex;
//indexCount = numer of cluster indices per sector
indexCount = bpb->sectorSize / 4; //FAT16->2, FAT32->4
//skip areas we have already searched through
sectorSkip = clStackLast / indexCount;
recordSkip = clStackLast % indexCount;
fatStartSector = bpb->partStart + bpb->resSectors;
for (i = sectorSkip; i < bpb->fatSize && clStackIndex < MAX_CLUSTER_STACK ; i++) {
ret = READ_SECTOR(fatStartSector + i, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat32 sector failed! sector=%i! \n", fatStartSector + i);
return -EIO;
}
for (j = recordSkip; j < indexCount && clStackIndex < MAX_CLUSTER_STACK ; j++) {
cluster = getI32(sbuf + (j * 4));
if (cluster == 0) { //the cluster is free
clusterValue = (i * indexCount) + j;
if (clusterValue < 0xFFFFFF7) {
clStackLast = clusterValue;
clStack[clStackIndex] = clusterValue;
clStackIndex++;
}
}
}
recordSkip = 0;
}
//the stack operates as LIFO but we put in the clusters as FIFO
//we should reverse the cluster order - not necessary
//but it will retain the natural (increasing) order of
//the cluster chain
swapClStack(oldClStackIndex, clStackIndex);
return clStackIndex;
}
/*
scan FAT16 for free clusters and store them to the cluster stack
*/
int fat_readEmptyClusters16(fat_bpb* bpb) {
int i,j;
int ret;
int indexCount;
unsigned int fatStartSector;
unsigned int cluster;
int oldClStackIndex;
int sectorSkip;
int recordSkip;
oldClStackIndex = clStackIndex;
//XPRINTF("#### Read empty clusters16: clStackIndex=%d MAX=%d\n", clStackIndex, MAX_CLUSTER_STACK);
//indexCount = numer of cluster indices per sector
indexCount = bpb->sectorSize / 2; //FAT16->2, FAT32->4
//skip areas we have already searched through
sectorSkip = clStackLast / indexCount;
recordSkip = clStackLast % indexCount;
fatStartSector = bpb->partStart + bpb->resSectors;
for (i = sectorSkip; i < bpb->fatSize && clStackIndex < MAX_CLUSTER_STACK ; i++) {
ret = READ_SECTOR(fatStartSector + i, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat16 sector failed! sector=%i! \n", fatStartSector + i);
return -EIO;
}
for (j = recordSkip; j < indexCount && clStackIndex < MAX_CLUSTER_STACK ; j++) {
cluster = getI16(sbuf + (j * 2));
if (cluster == 0) { //the cluster is free
clStackLast = (i * indexCount) + j;
clStack[clStackIndex] = clStackLast;
XPRINTF("%d ", clStack[clStackIndex]);
clStackIndex++;
}
}
recordSkip = 0;
}
XPRINTF("\n");
//the stack operates as LIFO but we put in the clusters as FIFO
//we should reverse the cluster order - not necessary
//but it will retain the natural (increasing) order of
//the cluster chain
swapClStack(oldClStackIndex, clStackIndex);
return clStackIndex;
}
/*
scan FAT for free clusters and store them to the cluster stack
*/
int fat_readEmptyClusters(fat_bpb* bpb) {
switch (bpb->fatType) {
case FAT12: return fat_readEmptyClusters12(bpb);
case FAT16: return fat_readEmptyClusters16(bpb);
case FAT32: return fat_readEmptyClusters32(bpb);
}
}
/*
set sinlge cluster record (FAT12)into buffer
0x321, 0xABC
byte0|byte1|byte2|
+--+--+--+--+--+--+
|2 |1 |C |3 |A |B |
+--+--+--+--+--+--+
*/
void fat_setClusterRecord12(unsigned char* buf, unsigned int cluster, int type) {
if (type) { //type 1
buf[0] = (buf[0] & 0x0F) + ((cluster & 0x0F)<<4) ;
buf[1] = (cluster & 0xFF0) >> 4;
} else { // type 0
buf[0] = (cluster & 0xFF);
buf[1] = (buf[1] & 0xF0) + ((cluster & 0xF00) >> 8);
}
}
void fat_setClusterRecord12part1(unsigned char* buf, unsigned int cluster, int type) {
if (type) { //type 1
buf[0] = (buf[0] & 0x0F) + ((cluster & 0x0F)<<4);
} else { // type 0
buf[0] = (cluster & 0xFF);
}
}
void fat_setClusterRecord12part2(unsigned char* buf, unsigned int cluster, int type) {
if (type) { //type 1
buf[0] = (cluster & 0xFF0) >> 4;
} else { // type 0
buf[0] = (buf[0] & 0xF0) + ((cluster & 0xF00) >> 8);
}
}
/*
save value at the cluster record in FAT 12
*/
int fat_saveClusterRecord12(fat_bpb* bpb, unsigned int currentCluster, unsigned int value) {
int i;
int ret;
int sectorSpan;
int recordOffset;
int recordType;
int fatNumber;
unsigned int fatSector;
ret = -1;
//recordOffset is byte offset of the record from the start of the fat table
recordOffset = (currentCluster * 3) / 2;
//save both fat tables
for (fatNumber = 0; fatNumber < bpb->fatCount; fatNumber++) {
fatSector = bpb->partStart + bpb->resSectors + (fatNumber * bpb->fatSize);
fatSector += recordOffset / bpb->sectorSize;
sectorSpan = bpb->sectorSize - (recordOffset % bpb->sectorSize);
if (sectorSpan > 1) {
sectorSpan = 0;
}
recordType = currentCluster % 2;
ret = READ_SECTOR(fatSector, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat16 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
if (!sectorSpan) { // not sector span - the record is copmact and fits in single sector
fat_setClusterRecord12(sbuf + (recordOffset % bpb->sectorSize), value, recordType);
ret = WRITE_SECTOR(fatSector);
if (ret < 0) {
printf("FAT driver:Write fat12 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
} else { // sector span - the record is broken in 2 pieces - each one on different sector
//modify one last byte of the sector buffer
fat_setClusterRecord12part1(sbuf + (recordOffset % bpb->sectorSize), value, recordType);
//save current sector
ret = WRITE_SECTOR(fatSector);
if (ret < 0) {
printf("FAT driver:Write fat12 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
//read next sector from the fat
fatSector++;
ret = READ_SECTOR(fatSector, sbuf);
if (ret < 0) {
printf("FAT driver:Read fat16 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
//modify first byte of the sector buffer
fat_setClusterRecord12part2(sbuf, value, recordType);
//save current sector
ret = WRITE_SECTOR(fatSector);
if (ret < 0) {
printf("FAT driver:Write fat12 sector failed! sector=%i! \n", fatSector);
return -EIO;
}
}
} //end for
return ret;
}
/*
save value at the cluster record in FAT 16
*/
int fat_saveClusterRecord16(fat_bpb* bpb, unsigned int currentCluster, unsigned int value) {
int i;
int ret;
int indexCount;
int fatNumber;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -