346 lines
8.2 KiB
C
346 lines
8.2 KiB
C
// fat12.c
|
|
// Author: Josh Holtrop
|
|
// Created: 01/04/04
|
|
// Modified: 01/14/04
|
|
|
|
|
|
byte *fat12_readFile(char *fileName, DiskDevice *dd)
|
|
{
|
|
char *fileNameUCase = malloc(strlen(fileName) + 1);
|
|
strcpy(fileNameUCase, fileName);
|
|
ucase(fileNameUCase);
|
|
dword iMadeClusterChain = getClusterChain(dd);
|
|
Fat12Entry fe;
|
|
if (fat12_getFileHandle(fileNameUCase, dd, &fe))
|
|
{
|
|
free(fileNameUCase);
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
byte *fp = (byte *)fat12_readClusterChain(dd, &fe);
|
|
free(fileNameUCase);
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return fp;
|
|
}
|
|
|
|
|
|
dword fat12_getFileHandle(char *fileName, DiskDevice *dd, Fat12Entry *destination)
|
|
{
|
|
if (strlen(fileName) < 1)
|
|
return 1;
|
|
if (fileName[strlen(fileName)-1] == '/')
|
|
return 2;
|
|
dword iMadeClusterChain = getClusterChain(dd);
|
|
int fileName_length = strlen(fileName);
|
|
int a;
|
|
int entries = 1;
|
|
for (a = 0; a < fileName_length; a++)
|
|
{
|
|
if (fileName[a] == '/')
|
|
{
|
|
fileName[a] = 0;
|
|
entries++;
|
|
}
|
|
}
|
|
char *pointer = fileName;
|
|
Fat12Entry *workingDirectory = 0;
|
|
Fat12Entry workingDir;
|
|
for (a = 0; a < (entries - 1); a++)
|
|
{
|
|
if (fat12_getDirectoryHandle(pointer, dd, workingDirectory, &workingDir)) //an error occurred if this returns nonzero
|
|
{
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return 3;
|
|
}
|
|
workingDirectory = &workingDir;
|
|
for (;;) //advance to the next dir name
|
|
{
|
|
pointer++;
|
|
if (*pointer == 0)
|
|
{
|
|
pointer++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (fat12_getFileHandleInDirectory(pointer, dd, workingDirectory, destination)) //an error occurred if this returns nonzero
|
|
{
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return 4;
|
|
}
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
dword fat12_getFileHandleInDirectory(char *fileName, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination)
|
|
{
|
|
if (!currDir) // we are working in the root directory
|
|
{
|
|
Fat12Entry *rootDir = malloc(14*512); //root directory is 14 sectors long
|
|
vfs_readSector(dd, 19, (byte *)rootDir, 14);
|
|
int a;
|
|
for (a = 0; a < 224; a++) //224 max root directory entries in 14 sectors
|
|
{
|
|
if (rootDir[a].fileName[0] == 0)
|
|
break;
|
|
if ((byte)rootDir[a].fileName[0] != 0xE5)
|
|
{
|
|
if ((rootDir[a].attributes & 0x18) == 0) //this entry is a directory
|
|
{
|
|
char dirName[9];
|
|
char dirExt[4];
|
|
memcpy(dirName, rootDir[a].fileName, 8);
|
|
dirName[8] = 0;
|
|
memcpy(dirExt, rootDir[a].ext, 3);
|
|
dirExt[3] = 0;
|
|
rtrim(dirName);
|
|
rtrim(dirExt);
|
|
char dirWhole[14];
|
|
strcpy(dirWhole, dirName);
|
|
if (strlen(dirExt) > 0) //the directory has an extension
|
|
{
|
|
strcat(dirWhole, ".");
|
|
strcat(dirWhole, dirExt);
|
|
}
|
|
if (strcmp(dirWhole, fileName)) //the entry found is a match
|
|
{
|
|
free(rootDir);
|
|
*destination = rootDir[a];
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(rootDir);
|
|
return 1; //no match found
|
|
}
|
|
dword retVal = 2;
|
|
dword iMadeClusterChain = getClusterChain(dd);
|
|
Fat12Entry *subDirectory = fat12_readClusterChain(dd, currDir);
|
|
if (!subDirectory)
|
|
return 5;
|
|
dword numberOfClusters = fat12_readClusterChainCount(dd, currDir);
|
|
int a;
|
|
for (a = 0; a < (numberOfClusters * 16); a++)
|
|
{
|
|
if (subDirectory[a].fileName[0] == 0)
|
|
break;
|
|
if ((byte)subDirectory[a].fileName[0] != 0xE5)
|
|
{
|
|
if ((subDirectory[a].attributes & 0x18) == 0) //this entry is a directory
|
|
{
|
|
char dirName[9];
|
|
char dirExt[4];
|
|
memcpy(dirName, subDirectory[a].fileName, 8);
|
|
dirName[8] = 0;
|
|
memcpy(dirExt, subDirectory[a].ext, 3);
|
|
dirExt[3] = 0;
|
|
rtrim(dirName);
|
|
rtrim(dirExt);
|
|
char dirWhole[14];
|
|
strcpy(dirWhole, dirName);
|
|
if (strlen(dirExt) > 0) //the directory has an extension
|
|
{
|
|
strcat(dirWhole, ".");
|
|
strcat(dirWhole, dirExt);
|
|
}
|
|
if (strcmp(dirWhole, fileName)) //the entry found is a match
|
|
{
|
|
*destination = subDirectory[a];
|
|
retVal = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(subDirectory);
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
dword fat12_getDirectoryHandle(char *directory, DiskDevice *dd, Fat12Entry *currDir, Fat12Entry *destination)
|
|
{
|
|
if (!currDir) // we are working in the root directory
|
|
{
|
|
Fat12Entry *rootDir = malloc(14*512); //root directory is 14 sectors long
|
|
vfs_readSector(dd, 19, (byte *)rootDir, 14);
|
|
int a;
|
|
for (a = 0; a < 224; a++) //224 max root directory entries in 14 sectors
|
|
{
|
|
if (rootDir[a].fileName[0] == 0)
|
|
break;
|
|
if ((byte)rootDir[a].fileName[0] != 0xE5)
|
|
{
|
|
if ((rootDir[a].attributes & 0x18) == 0x10) //this entry is a directory
|
|
{
|
|
char dirName[9];
|
|
char dirExt[4];
|
|
memcpy(dirName, rootDir[a].fileName, 8);
|
|
dirName[8] = 0;
|
|
memcpy(dirExt, rootDir[a].ext, 3);
|
|
dirExt[3] = 0;
|
|
rtrim(dirName);
|
|
rtrim(dirExt);
|
|
char dirWhole[14];
|
|
strcpy(dirWhole, dirName);
|
|
if (strlen(dirExt) > 0) //the directory has an extension
|
|
{
|
|
strcat(dirWhole, ".");
|
|
strcat(dirWhole, dirExt);
|
|
}
|
|
if (strcmp(dirWhole, directory)) //the entry found is a match
|
|
{
|
|
free(rootDir);
|
|
*destination = rootDir[a];
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(rootDir);
|
|
return 1; //no match found
|
|
}
|
|
dword retVal = 2;
|
|
dword iMadeClusterChain = getClusterChain(dd);
|
|
Fat12Entry *subDirectory = fat12_readClusterChain(dd, currDir);
|
|
if (!subDirectory)
|
|
return 5;
|
|
dword numberOfClusters = fat12_readClusterChainCount(dd, currDir);
|
|
int a;
|
|
for (a = 0; a < (numberOfClusters * 16); a++)
|
|
{
|
|
if (subDirectory[a].fileName[0] == 0)
|
|
break;
|
|
if ((byte)subDirectory[a].fileName[0] != 0xE5)
|
|
{
|
|
if ((subDirectory[a].attributes & 0x18) == 0x10) //this entry is a directory
|
|
{
|
|
char dirName[9];
|
|
char dirExt[4];
|
|
memcpy(dirName, subDirectory[a].fileName, 8);
|
|
dirName[8] = 0;
|
|
memcpy(dirExt, subDirectory[a].ext, 3);
|
|
dirExt[3] = 0;
|
|
rtrim(dirName);
|
|
rtrim(dirExt);
|
|
char dirWhole[14];
|
|
strcpy(dirWhole, dirName);
|
|
if (strlen(dirExt) > 0) //the directory has an extension
|
|
{
|
|
strcat(dirWhole, ".");
|
|
strcat(dirWhole, dirExt);
|
|
}
|
|
if (strcmp(dirWhole, directory)) //the entry found is a match
|
|
{
|
|
*destination = subDirectory[a];
|
|
retVal = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(subDirectory);
|
|
if (iMadeClusterChain)
|
|
{
|
|
free(clusterChain);
|
|
clusterChain = 0;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
Fat12Entry *fat12_readClusterChain(DiskDevice *dd, Fat12Entry *directory)
|
|
{
|
|
dword numberOfClusters = fat12_readClusterChainCount(dd, directory);
|
|
if (numberOfClusters == 0)
|
|
return 0;
|
|
byte *bp = malloc(numberOfClusters * 512);
|
|
Fat12Entry *retVal = (Fat12Entry *)bp;
|
|
dword cluster = directory->firstCluster;
|
|
while (cluster < 0xFF0)
|
|
{
|
|
vfs_readSector(dd, cluster + 31, bp, 1);
|
|
cluster = fat12_getNextCluster(cluster);
|
|
bp += 512;
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
dword fat12_readClusterChainCount(DiskDevice *dd, Fat12Entry *directory)
|
|
{
|
|
dword numberOfClusters = 0;
|
|
dword cluster = directory->firstCluster;
|
|
if (cluster == 0)
|
|
return 0;
|
|
while (cluster < 0xFF0)
|
|
{
|
|
cluster = fat12_getNextCluster(cluster);
|
|
numberOfClusters++;
|
|
}
|
|
return numberOfClusters;
|
|
}
|
|
|
|
|
|
dword fat12_getNextCluster(dword thisCluster)
|
|
{
|
|
dword nextCluster = *(word *)((dword)clusterChain + ((thisCluster * 3) >> 1));
|
|
if (thisCluster & 0x01) //this is an odd cluster
|
|
return nextCluster >> 4;
|
|
else //this is an even cluster
|
|
return nextCluster & 0x0FFF;
|
|
}
|
|
|
|
|
|
dword fat12_getFileSize(char *fileName, DiskDevice *dd)
|
|
{
|
|
Fat12Entry fe;
|
|
if (fat12_getFileHandle(fileName, dd, &fe))
|
|
return 0xFFFFFFFF;
|
|
return fe.fileSize;
|
|
}
|
|
|
|
|
|
dword getClusterChain(DiskDevice *dd)
|
|
{
|
|
if (!clusterChain)
|
|
{
|
|
clusterChain = malloc(9*512); //9 sectors for File Allocation Table (cluster chain)
|
|
vfs_readSector(dd, 1, clusterChain, 9); //sectors 1 through 9 contain the first FAT
|
|
return 1; //this call created the cluster chain
|
|
}
|
|
else
|
|
return 0; //this call did not create the cluster chain
|
|
}
|
|
|
|
|
|
|
|
|
|
|