FAT12.h
#ifndef _FAT12_H#define _FAT12_H#ifdef WINDOWS#define SEPARATOR '\\' #else#define SEPARATOR '/' #define stricmp strcasecmp #endifint CreateNewImg(char *strImgName);
int CopyBootSector2Img(char *strImgName, char *strFileName);
#define DIRATTR_READ_ONLY 0x01 #define DIRATTR_HIDDEN 0x02 #define DIRATTR_SYSTEM 0x04 #define DIRATTR_ARCHIVE 0x20 int AddFile2Img(char *strImgName, char *strPathName, unsignedchar ucFileAttr);
void DeleteFileFromImg(char *strImgName, char *strFileName);
#endif
FAT12.c
#include <stdio.h>#include <string.h>#include <ctype.h>#include "FAT12.h"#define TOTALSECTORS 2880 #define BYTESPERSECTOR 512 #define FIRSTOFFAT 1 #define FIRSTOFROOTDIR 19 #define FIRSTOFDATA 33 typedefstruct tag_DirectoryItem
{
char DIR_Name[11]; char DIR_Attr; char DIR_Rsvd[10]; unsignedshort DIR_WrtTime; unsignedshort DIR_WrtDate; unsignedshort DIR_FstClus; unsignedint DIR_FileSize;
} T_DIRECTORYITEM;
unsignedshort ReadFatEntryValue(FILE *fpImg, unsignedshort iEntry);
void WriteFatEntryValue(FILE *fpImg, unsignedshort iEntry, unsignedshort nValue);
void ConvertDirName2FileName(char *strDirName, char *strFileName);
void ConvertFileName2DirName(char *strFileName, char *strDirName);
unsignedshort FindEmptyEntryInRootDirectory(FILE *fpImg);
unsignedshort FindEmptyEntryInFat(FILE *fpImg, unsignedshort iFirstEntry);
unsignedshort FindFileInRootDirectory(FILE *fpImg, char *strFileName);
unsignedshort GetRestSectors(FILE *fpImg);
void DeleteFile(FILE *fpImg, unsignedshort iRootDirEntry);
void AddFile(FILE *fpImg, FILE *fpFile, char *strDirName, unsignedchar ucFileAttr);
int CreateNewImg(char *strImgName)
{
unsignedchar BootSector[BYTESPERSECTOR] =
{
0xEB,0x39,0x90,0x4E,0x41,0x53,0x4D,0x2B,0x47,0x43,0x43,0x00,0x02,0x01,0x01,0x00,
0x02,0xE0,0x00,0x40,0x0B,0xF0,0x09,0x00,0x12,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
0x40,0x0B,0x00,0x00,0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x54,0x65,0x73,0x74,0x58,
0x5F,0x76,0x30,0x2E,0x30,0x31,0x46,0x41,0x54,0x31,0x32,0x8C,0xC8,0x8E,0xD8,0x8E,
0xD0,0xB8,0x00,0x7C,0x89,0xC5,0x89,0xC4,0xBE,0x7F,0x7D,0xE8,0x1C,0x00,0x83,0xF8,
0x00,0x75,0x08,0xBE,0x75,0x7D,0xE8,0x06,0x01,0xEB,0xFE,0x68,0x00,0x90,0x07,0xBB,
0x00,0x10,0xE8,0x50,0x00,0xEA,0x00,0x10,0x00,0x90,0x55,0x89,0xE5,0x83,0xEC,0x04,
0x06,0x51,0x53,0x68,0xE0,0x07,0x07,0xC7,0x46,0xFE,0x13,0x00,0xC7,0x46,0xFC,0x0E,
0x00,0x8B,0x46,0xFE,0x31,0xDB,0xE8,0x97,0x00,0xB9,0x10,0x00,0xB8,0x0B,0x00,0xE8,
0xB1,0x00,0x83,0xF8,0x00,0x74,0x13,0x83,0xC3,0x20,0xE2,0xF0,0xFF,0x4E,0xFC,0x74,
0x05,0xFF,0x46,0xFE,0xEB,0xDB,0x31,0xC0,0xEB,0x04,0x26,0x8B,0x47,0x1A,0x5B,0x59,
0x07,0x89,0xEC,0x5D,0xC3,0x55,0x89,0xE5,0x53,0x50,0x53,0x50,0x83,0xC0,0x1F,0xE8,
0x5E,0x00,0x58,0xE8,0x12,0x00,0x5B,0x3D,0xF8,0x0F,0x73,0x06,0x81,0xC3,0x00,0x02,
0xEB,0xE8,0x58,0x5B,0x89,0xEC,0x5D,0xC3,0x55,0x89,0xE5,0x06,0x52,0x51,0x53,0x31,
0xD2,0xBB,0x03,0x00,0xF7,0xE3,0xBB,0x02,0x00,0xF7,0xF3,0x89,0xD1,0x31,0xD2,0xBB,
0x00,0x02,0xF7,0xF3,0x83,0xC0,0x01,0x52,0x51,0x50,0x68,0xE0,0x07,0x07,0x31,0xDB,
0xE8,0x1D,0x00,0x58,0x40,0xBB,0x00,0x02,0xE8,0x15,0x00,0x59,0x5B,0x26,0x8B,0x07,
0xE3,0x03,0xC1,0xE8,0x04,0x25,0xFF,0x0F,0x5B,0x59,0x5A,0x07,0x89,0xEC,0x5D,0xC3,
0x55,0x89,0xE5,0x52,0x51,0xB2,0x12,0xF6,0xF2,0x88,0xC5,0x88,0xC6,0x88,0xE1,0xD0,
0xED,0xFE,0xC1,0x80,0xE6,0x01,0xB8,0x01,0x02,0x30,0xD2,0xCD,0x13,0x59,0x5A,0x89,
0xEC,0x5D,0xC3,0x55,0x89,0xE5,0x56,0x51,0x53,0x89,0xC1,0xE3,0x09,0xAC,0x26,0x3A,
0x07,0x75,0x03,0x43,0xE2,0xF7,0x89,0xC8,0x5B,0x59,0x5E,0x89,0xEC,0x5D,0xC3,0x55,
0x89,0xE5,0x56,0x50,0xB4,0x0E,0xAC,0x3C,0x00,0x74,0x04,0xCD,0x10,0xEB,0xF7,0x58,
0x5E,0x89,0xEC,0x5D,0xC3,0x4E,0x6F,0x74,0x20,0x66,0x6F,0x75,0x6E,0x64,0x20,0x4C,
0x4F,0x41,0x44,0x45,0x52,0x20,0x20,0x53,0x59,0x53,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAA,
};
char FATMSG[3] = {0xF0, 0xFF, 0xFF};
FILE *fpImg;
unsignedlongint i;
fpImg = fopen(strImgName, "wb");
if(fpImg == NULL)
{
return1;
}
fwrite(BootSector, BYTESPERSECTOR, 1, fpImg);
fwrite(FATMSG, 3, 1, fpImg); for(i = BYTESPERSECTOR + 3; i < 10 * BYTESPERSECTOR; i++)
fputc(0, fpImg);
fwrite(FATMSG, 3, 1, fpImg); for(i = 10 * BYTESPERSECTOR + 3; i < 2880 * BYTESPERSECTOR; i++)
fputc(0, fpImg);
fclose(fpImg);
return0;
}
int CopyBootSector2Img(char *strImgName, char *strFileName)
{
FILE *fpFile, *fpImg;
unsignedchar ucBuffer[BYTESPERSECTOR], ucTemp[2];
fpFile = fopen(strFileName, "rb");
if(fpFile == NULL)
{
return1;
}
fseek(fpFile, 0, SEEK_END);
if(ftell(fpFile) < BYTESPERSECTOR)
{
fclose(fpFile);
return1;
}
fseek(fpFile, 510, SEEK_SET);
fread(ucTemp, 2, 1, fpFile);
if(ucTemp[0] != 0x55 || ucTemp[1] != 0xAA)
{
fclose(fpFile);
return1;
}
fpImg = fopen(strImgName, "rb+");
if(fpImg == NULL)
{
fclose(fpFile);
return1;
}
fseek(fpFile, 0, SEEK_SET);
fread(ucBuffer, BYTESPERSECTOR, 1, fpFile);
fseek(fpImg, 0, SEEK_SET);
fwrite(ucBuffer, BYTESPERSECTOR, 1, fpImg);
fclose(fpFile);
fclose(fpImg);
return0;
}
int AddFile2Img(char *strImgName, char *strPathName, unsignedchar ucFileAttr)
{
FILE *fpFile, *fpImg;
unsignedshort iPos, iRootDirItem, size = sizeof(T_DIRECTORYITEM);
T_DIRECTORYITEM tDirItem;
char strDirName[12], *strFileName;
fpFile = fopen(strPathName, "rb");
if(fpFile == NULL)
{
return1;
}
fpImg = fopen(strImgName, "rb+");
if(fpImg == NULL)
{
fclose(fpFile);
return1;
}
strFileName = strrchr(strPathName, SEPARATOR);
strFileName = ((NULL == strFileName) ? strPathName : (strFileName + 1));
iRootDirItem = FindFileInRootDirectory(fpImg, strFileName);
if(iRootDirItem < 0xFF8)
{
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + iRootDirItem * size, SEEK_SET);
fread(&tDirItem, size, 1, fpImg);
}
else
tDirItem.DIR_FileSize = 0;
fseek(fpFile, 0, SEEK_END);
if((tDirItem.DIR_FileSize + GetRestSectors(fpImg) * BYTESPERSECTOR) < ftell(fpFile))
{
fclose(fpFile);
fclose(fpImg);
return1;
}
if(FindEmptyEntryInRootDirectory(fpImg) > 0xFF8)
{
fclose(fpFile);
fclose(fpImg);
return1;
}
if(iRootDirItem < 0xFF8)
DeleteFile(fpImg, iRootDirItem);
ConvertFileName2DirName(strFileName, strDirName);
AddFile(fpImg, fpFile, strDirName, ucFileAttr);
fclose(fpFile);
fclose(fpImg);
return0;
}
void DeleteFileFromImg(char *strImgName, char *strFileName)
{
FILE *fpImg;
unsignedshort iEntry;
fpImg = fopen(strImgName, "rb+");
if(fpImg != NULL)
{
iEntry = FindFileInRootDirectory(fpImg, strFileName);
if(iEntry < 0xFF8)
DeleteFile(fpImg, iEntry);
fclose(fpImg);
}
}
unsignedshort ReadFatEntryValue(FILE *fpImg, unsignedshort iEntry)
{
unsignedshort nTemp;
fseek(fpImg, FIRSTOFFAT * BYTESPERSECTOR + iEntry * 3 / 2, SEEK_SET);
fread(&nTemp, 2, 1, fpImg);
return (iEntry % 2 == 0 ? nTemp & 0xFFF : nTemp >> 4);
}
void WriteFatEntryValue(FILE *fpImg, unsignedshort iEntry, unsignedshort nValue)
{
unsignedshort nTemp;
fseek(fpImg, FIRSTOFFAT * BYTESPERSECTOR + iEntry * 3 / 2, SEEK_SET);
fread(&nTemp, 2, 1, fpImg);
if(iEntry % 2 == 0)
nValue |= (nTemp & 0b1111000000000000);
else
nValue = ((nValue << 4) | (nTemp & 0b1111));
fseek(fpImg, FIRSTOFFAT * BYTESPERSECTOR + iEntry * 3 / 2, SEEK_SET);
fwrite(&nValue, 2, 1, fpImg);
fseek(fpImg, (FIRSTOFFAT + FIRSTOFROOTDIR) * BYTESPERSECTOR / 2 +
iEntry * 3 / 2, SEEK_SET);
fwrite(&nValue, 2, 1, fpImg);
}
void ConvertDirName2FileName(char *strDirName, char *strFileName)
{
int i, j = 7, k = 10;
while(strDirName[j] == ' ')
j--;
for(i = 0; i <= j; i++)
strFileName[i] = strDirName[i];
while(strDirName[k] == ' ')
k--;
if(k > 7)
{
strFileName[++j] = '.';
for(i = 8; i <= k; i++)
strFileName[++j] = strDirName[i];
}
strFileName[++j] = 0;
for(i = 0; i < j; i++)
strFileName[i] = tolower(strFileName[i]);
}
void ConvertFileName2DirName(char *strFileName, char *strDirName)
{
int i, j = -1;
char *pExtension;
pExtension = strrchr(strFileName, '.');
if(NULL == pExtension)
{
for(i = 0; i < 8; i++)
{
if(strFileName[i] == 0)
break;
strDirName[i] = strFileName[i];
}
while(i < 11)
strDirName[i++] = ' ';
}
else
{
j = pExtension - strFileName;
for(i = 0; i < j && i < 8; i++)
strDirName[i] = strFileName[i];
while(i < 8)
strDirName[i++] = ' ';
j++; for(i = 8; i < 11; i++, j++)
{
if(strFileName[j] == 0)
break;
strDirName[i] = strFileName[j];
}
while(i < 11)
strDirName[i++] = ' ';
}
for(i = 0; i < 11; i++)
strDirName[i] = toupper(strDirName[i]);
strDirName[11] = 0;
}
unsignedshort FindEmptyEntryInRootDirectory(FILE *fpImg)
{
T_DIRECTORYITEM tDirItem;
unsignedshort i, max, size = sizeof(T_DIRECTORYITEM);
unsignedchar ch;
max = (FIRSTOFDATA - FIRSTOFROOTDIR) * BYTESPERSECTOR / size;
for(i = 0; i < max; i++)
{
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + i * size, SEEK_SET);
fread(&tDirItem, size, 1, fpImg);
ch = tDirItem.DIR_Name[0];
if((ch == 0) || (ch == 0xE5))
return i;
}
return0xFFF;
}
unsignedshort FindEmptyEntryInFat(FILE *fpImg, unsignedshort iFirstEntry)
{
unsignedshort i, max;
max = (FIRSTOFROOTDIR - FIRSTOFFAT) * BYTESPERSECTOR / 3;
for(i = iFirstEntry; i < max; i++)
{
if(ReadFatEntryValue(fpImg, i) == 0)
return i;
}
return0xFFF;
}
unsignedshort GetRestSectors(FILE *fpImg)
{
unsignedshort iFirstEntry = 2, iNext, nNum = 0;
while((iNext = FindEmptyEntryInFat(fpImg, iFirstEntry)) > 0 && (iNext < 0xFFF))
{
iFirstEntry = iNext + 1;
nNum++;
}
return nNum;
}
unsignedshort FindFileInRootDirectory(FILE *fpImg, char *strFileName)
{
T_DIRECTORYITEM tDirItem;
char FileItemName[12], DirItemName[12];
unsignedshort i, max, size = sizeof(T_DIRECTORYITEM);
ConvertFileName2DirName(strFileName, FileItemName);
DirItemName[11] = 0;
max = (FIRSTOFDATA - FIRSTOFROOTDIR) * BYTESPERSECTOR / size;
for(i = 0; i < max; i++)
{
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + i * size, SEEK_SET);
fread(&tDirItem, size, 1, fpImg);
strncpy(DirItemName, tDirItem.DIR_Name, 11);
if(!strcmp(DirItemName, FileItemName))
return i;
}
return0xFFF;
}
void DeleteFile(FILE *fpImg, unsignedshort iRootDirEntry)
{
unsignedshort nFatValue, iFatNext, size = sizeof(T_DIRECTORYITEM);
T_DIRECTORYITEM tDirItem;
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + iRootDirEntry * size, SEEK_SET);
fread(&tDirItem, size, 1, fpImg);
iFatNext = tDirItem.DIR_FstClus;
do
{
nFatValue = ReadFatEntryValue(fpImg, iFatNext);
WriteFatEntryValue(fpImg, iFatNext, 0);
iFatNext = nFatValue;
} while(iFatNext < 0xFF8);
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + iRootDirEntry * size, SEEK_SET);
fputc(0xE5, fpImg);
}
void AddFile(FILE *fpImg, FILE *fpFile, char *strDirName, unsignedchar ucFileAttr)
{
unsignedchar ucData[BYTESPERSECTOR];
unsignedlong nFileLen;
unsignedshort arrySectorList[TOTALSECTORS], i, size = sizeof(T_DIRECTORYITEM);
unsignedshort nNeedSectors, iLast, nRemainderBytes, iRootDirItem;
T_DIRECTORYITEM tDirItem;
fseek(fpFile, 0, SEEK_END);
nFileLen = ftell(fpFile);
nRemainderBytes = nFileLen % BYTESPERSECTOR;
nNeedSectors = nFileLen / BYTESPERSECTOR + (nRemainderBytes > 0 ? 1 : 0);
iLast = nNeedSectors - 1;
arrySectorList[0] = FindEmptyEntryInFat(fpImg, 2);
for(i = 1; i < nNeedSectors; i++)
{
arrySectorList[i] = FindEmptyEntryInFat(fpImg, arrySectorList[i - 1] + 1);
WriteFatEntryValue(fpImg, arrySectorList[i - 1], arrySectorList[i]);
}
WriteFatEntryValue(fpImg, arrySectorList[iLast], 0xFFF);
iRootDirItem = FindEmptyEntryInRootDirectory(fpImg);
strncpy(tDirItem.DIR_Name, strDirName, 11);
tDirItem.DIR_Attr = ucFileAttr;
tDirItem.DIR_FstClus = arrySectorList[0];
tDirItem.DIR_FileSize = nFileLen;
fseek(fpImg, FIRSTOFROOTDIR * BYTESPERSECTOR + iRootDirItem * size, SEEK_SET);
fwrite(&tDirItem, size, 1, fpImg);
fseek(fpFile, 0, SEEK_SET);
for(i = 0; i < iLast; i++)
{
fread(ucData, BYTESPERSECTOR, 1, fpFile);
fseek(fpImg, (arrySectorList[i] + FIRSTOFDATA - 2) * BYTESPERSECTOR, SEEK_SET);
fwrite(ucData, BYTESPERSECTOR, 1, fpImg);
}
if(nRemainderBytes > 0)
{
fread(ucData, nRemainderBytes, 1, fpFile);
for(i = nRemainderBytes; i < BYTESPERSECTOR; i++)
ucData[i] = 0;
}
else
fread(ucData, BYTESPERSECTOR, 1, fpFile);
fseek(fpImg, (arrySectorList[iLast] + FIRSTOFDATA - 2) * BYTESPERSECTOR, SEEK_SET);
fwrite(ucData, BYTESPERSECTOR, 1, fpImg);
}
img.c
#include <stdio.h>#include <string.h>#include "FAT12.h"void PrintUsage(char *strFileName);
int main(int argc, char *argv[])
{
int i;
if((argc == 1) || ((argc == 2) && (!stricmp(argv[1], "-h"))))
{
PrintUsage(argv[0]);
return0;
}
if((argc == 3) && (!stricmp(argv[1], "-n")))
{
if(CreateNewImg(argv[2]))
{
printf("Error in creating a new img file : %s !\n", argv[2]);
return1;
}
return0;
}
if((argc == 4) && (!stricmp(argv[1], "-c")))
{
if(CopyBootSector2Img(argv[2], argv[3]))
{
printf("Error in copying Boot Sector from %s to %s ...\n", argv[3], argv[2]);
return1;
}
return0;
}
if(((argc >= 4) && (!stricmp(argv[1], "-a"))))
{
for(i = 3; i < argc; i++)
{
if(AddFile2Img(argv[2], argv[i], 0))
{
printf("Error in adding file %s to %s ...\n", argv[i], argv[2]);
return1;
}
}
return0;
}
if(((argc >= 4) && (!stricmp(argv[1], "-d"))))
{
for(i = 3; i < argc; i++)
DeleteFileFromImg(argv[2], argv[i]);
return0;
}
printf("Can't recognize this command.\n");
return1;
}
void PrintUsage(char *strFileName)
{
printf("Usage: %s <-a | -d | -c | -n | -h> vImg [File1 [File2 ...]]\n", strFileName);
printf(" -a Add files to vImg\n");
printf(" -d Delete files from vImg\n");
printf(" -c Copy Boot Sector to vImg\n");
printf(" -n Create a new vImg\n");
printf(" -h Show this usage\n");
}
Makefile
img:FAT12.o img.o
gcc FAT12.o img.o -o img
FAT12.o: FAT12.c FAT12.h Makefile
gcc -c FAT12.cimg.o:img.c FAT12.h Makefile
gcc -c img.c
发布评论