//Create a new file in given directory. BOOL CreateFatFile(__FAT32_FS* pFat32Fs,DWORD dwStartCluster,CHAR* pszFileName,BYTE Attributes) { DWORD dwInitCluster = 0; __FAT32_SHORTENTRY DirEntry; BOOL bResult = FALSE; if((NULL == pFat32Fs) || (dwStartCluster < 2) || IS_EOC(dwStartCluster) || (NULL == pszFileName)) { goto __TERMINAL; } //Allocate a free cluster for the new created file. if(!GetFreeCluster(pFat32Fs,0,&dwInitCluster)) { PrintLine("In CreateFatFile: Can not get a free cluster."); goto __TERMINAL; } if(!InitShortEntry(&DirEntry,pszFileName,dwInitCluster,0,FILE_ATTR_ARCHIVE)) { PrintLine("In CreateFatFile: Can not initialize short entry."); goto __TERMINAL; } if(!CreateDirEntry(pFat32Fs,dwStartCluster,&DirEntry)) { PrintLine("In CreateFatFile: Can not create directory entry in parent dir."); ReleaseCluster(pFat32Fs,dwInitCluster); goto __TERMINAL; } bResult = TRUE; __TERMINAL: return bResult; }
FatDirEntry1x* CmtFat::CreateFileName( cpchar pattern ) { uint32 subDir = 0; //Войти в поддиректорий pattern = GetSubDir( pattern, &subDir ); if( pattern ) { //Успешно вошли в поддиректорий CmtFatFinder finder( subDir ); while(1) { FatDirEntry1x *ptr = GetNextFileEntry( &finder ); if( ptr == 0 ) { //Пустых записей не обнаружено, попробовать увеличить директорий if( IncreaseDir( subDir ) != CMTE_OK ) return 0; else { //Директорий увеличен, повторить попытку поиска finder.Set( subDir ); continue; } } //Проверить, что запись пустая if( ptr->mFileName[0] == 0 || ptr->mFileName[0] == 0xe5 ) { //Запись пустая, заполнить имя int c; for( c = 0; c < 8 && *pattern != '.' && *pattern; c++ ) { ptr->mFileName[c] = cmtCharUpper( *pattern++ ); } //Добить оставшуюся часть имени пробелами while( c < 8 ) ptr->mFileName[c++] = ' '; //Добраться до точки while( *pattern && *pattern != '.' ) pattern++; if( *pattern == '.' ) pattern++; for( c = 0; c < 3 && *pattern; c++ ) { ptr->mExtension[c] = cmtCharUpper( *pattern++ ); } //Добить оставшуюся часть имени пробелами while( c < 3 ) ptr->mExtension[c++] = ' '; CmtSystemTime ft; ft.GetSystem(); //Заполнить остальные поля ptr->mAttrib = FA_ARHIV; ptr->mReserved[0] = ptr->mReserved[1] = 0; ptr->mUpdateTime = //time create/update ptr->mCreationTime = ft.FFTime(); ptr->mUpdateDate = //date create/update ptr->mAccessDate = ptr->mCreationDate = ft.FFDate(); ptr->mFirstClusterHigh = 0; // higher ptr->mFileSize = 0; ptr->SetFirstCluster32( GetFreeCluster() ); if( ptr->GetFirstCluster32() > 0 ) SetCluster( ptr->GetFirstCluster32(), END_CLUSTER ); dirtyDirSector = 1; return ptr; } } } return 0; //Нет файла }
//Create directory in a given uper level directory. //Steps as follows: // 1. One free cluster is allocated as data cluster by calling GetFreeCluster; // 2. Initialize this cluster by calling InitDirectory; // 3. Create the short directory entry by calling CreateDirEntry. // BOOL CreateFatDir(__FAT32_FS* pFat32Fs,DWORD dwStartCluster,CHAR* pszDirName,BYTE Attributes) { DWORD dwDirCluster = 0; __FAT32_SHORTENTRY DirEntry; BOOL bResult = FALSE; if((NULL == pFat32Fs) || (dwStartCluster < 2) || IS_EOC(dwStartCluster) || (NULL == pszDirName)) { goto __TERMINAL; } if(!GetFreeCluster(pFat32Fs,0,&dwDirCluster)) { PrintLine("In CreateFatDir: Can not get a free cluster."); goto __TERMINAL; } if(!InitDirectory(pFat32Fs,dwStartCluster,dwDirCluster)) { PrintLine("In CreateFatDir: Can not initialize the directory cluster."); goto __TERMINAL; } //Initialize the directory entry. /* DirEntry.CreateDate = 0; DirEntry.CreateTime = 0; DirEntry.CreateTimeTenth = 0; DirEntry.dwFileSize = 0; DirEntry.FileAttributes = FILE_ATTR_DIRECTORY; DirEntry.LastAccessDate = 0; DirEntry.wFirstClusHi = (WORD)(dwDirCluster >> 16); DirEntry.wFirstClusLow = (WORD)dwDirCluster; DirEntry.WriteDate = 0; DirEntry.WriteTime = 0; for(i = 0;i < 11;i ++) { DirEntry.FileName[i] = pszDirName[i]; }*/ if(!InitShortEntry(&DirEntry,pszDirName,dwDirCluster,0,FILE_ATTR_DIRECTORY)) { goto __TERMINAL; } if(!CreateDirEntry(pFat32Fs,dwStartCluster,&DirEntry)) { PrintLine("In CreateFatDir: Can not create directory entry in parent dir."); ReleaseCluster(pFat32Fs,dwDirCluster); goto __TERMINAL; } bResult = TRUE; __TERMINAL: return bResult; }
//============================================================================== //--------------------- FAT - общая -------------------------------------------- int32 CmtFat::IncreaseDir( uint32 startDir ) { //Распределить новый кластер uint32 cluster = GetFreeCluster(); if( cluster == 0 || cluster == END_CLUSTER ) return CMTE_FS_DISK_FULL; //Получить последний кластер uint32 last; while( startDir != 0 && startDir != END_CLUSTER ) { last = startDir; startDir = GetCluster( startDir ); } //Установить цепочку SetCluster( last, cluster ); SetCluster( cluster, END_CLUSTER ); //Подготовить кластер директория InitDirCluster( cluster ); return CMTE_OK; }
BOOL CreateFatDir(__FAT32_FS* pFat32Fs,DWORD dwStartCluster,CHAR* pszDirName,BYTE Attributes) { __FAT32_SHORTENTRY DirEntry = {0}; DWORD dwDirCluster = 0; BOOL bResult = FALSE; if((NULL == pFat32Fs) || (dwStartCluster < 2) || IS_EOC(dwStartCluster) || (NULL == pszDirName)) { goto __TERMINAL; } if(!GetFreeCluster(pFat32Fs,0,&dwDirCluster)) { goto __TERMINAL; } if(!InitDirectory(pFat32Fs,dwStartCluster,dwDirCluster)) { goto __TERMINAL; } if(!InitShortEntry(&DirEntry,pszDirName,dwDirCluster,0,FILE_ATTR_DIRECTORY)) { goto __TERMINAL; } DirEntry.CreateTimeTenth = 10; SetFatFileDateTime(&DirEntry,FAT32_DATETIME_CREATE|FAT32_DATETIME_WRITE); if(!CreateDirEntry(pFat32Fs,dwStartCluster,&DirEntry)) { // PrintLine("In CreateFatDir: Can not create directory entry in parent dir."); ReleaseCluster(pFat32Fs,dwDirCluster); goto __TERMINAL; } bResult = TRUE; __TERMINAL: return bResult; }
//Create a new file in given directory. BOOL CreateFatFile(__FAT32_FS* pFat32Fs,DWORD dwStartCluster,CHAR* pszFileName,BYTE Attributes) { DWORD dwInitCluster = 0; __FAT32_SHORTENTRY DirEntry = {0}; BOOL bResult = FALSE; if((NULL == pFat32Fs) || (dwStartCluster < 2) || IS_EOC(dwStartCluster) || (NULL == pszFileName)) { goto __TERMINAL; } //Allocate a free cluster for the new created file. if(!GetFreeCluster(pFat32Fs,0,&dwInitCluster)) { goto __TERMINAL; } if(!InitShortEntry(&DirEntry,pszFileName,dwInitCluster,0,FILE_ATTR_ARCHIVE)) { //PrintLine("In CreateFatFile: Can not initialize short entry."); goto __TERMINAL; } DirEntry.CreateTimeTenth = 10; SetFatFileDateTime(&DirEntry,FAT32_DATETIME_CREATE|FAT32_DATETIME_WRITE); if(!CreateDirEntry(pFat32Fs,dwStartCluster,&DirEntry)) { ReleaseCluster(pFat32Fs,dwInitCluster); goto __TERMINAL; } bResult = TRUE; __TERMINAL: return bResult; }
//Append one free cluster to the tail of a cluster chain. //The pdwCurrCluster contains the laster cluster of a cluster chain,if this routine //executes successfully,it will return TRUE and pdwCurrCluster contains the cluster //number value appended to chain right now.Else FALSE will be returned and the pdwCurrCluster //keep unchanged. BOOL AppendClusterToChain(__FAT32_FS* pFat32Fs,DWORD* pdwCurrCluster) { DWORD dwCurrCluster = 0; DWORD dwNextCluster = 0; DWORD dwSector = 0; DWORD dwOffset = 0; BOOL bResult = FALSE; BYTE* pBuffer = NULL; DWORD dwEndCluster = 0; if((NULL == pFat32Fs) || (NULL == pdwCurrCluster)) { goto __TERMINAL; } dwCurrCluster = *pdwCurrCluster; if((2 > dwCurrCluster) || IS_EOC(dwCurrCluster)) { goto __TERMINAL; } dwSector = dwCurrCluster / 128; if(dwSector > pFat32Fs->dwFatSectorNum) //Exceed the FAT size. { goto __TERMINAL; } dwSector += pFat32Fs->dwFatBeginSector; //Now dwSector is the physical sector number of dwCurrCluster in fat. dwOffset = (dwCurrCluster - (dwCurrCluster / 128) * 128) * sizeof(DWORD); //Get sector offset. pBuffer = (BYTE*)LocalAlloc(LPTR,pFat32Fs->dwBytePerSector); if(NULL == pBuffer) { goto __TERMINAL; } //Try to get a free cluster. if(!GetFreeCluster(pFat32Fs,0,&dwNextCluster)) { goto __TERMINAL; } //The following operation must behind GetFreeCluster routine above,because //GetFreeCluster routine will modify the content of FAT,and this change must //be taken before the following read. //One complicated problem has been caused by this reason. if(!ReadDeviceSector(pFat32Fs->pPartition,pFat32Fs->dwPartitionSatrt+ dwSector,1,pBuffer)) { goto __TERMINAL; } //Save the next cluster to chain. *(DWORD*)(pBuffer + dwOffset) &= 0xF0000000; //Keep the leading 4 bits. *(DWORD*)(pBuffer + dwOffset) += (dwNextCluster & 0x0FFFFFFF); if(!WriteDeviceSector(pFat32Fs->pPartition, pFat32Fs->dwPartitionSatrt+ dwSector,1,pBuffer)) { ReleaseCluster(pFat32Fs,dwNextCluster); //Release this cluster. goto __TERMINAL; } dwEndCluster = *(DWORD*)(pBuffer + dwOffset); if(!GetNextCluster(pFat32Fs,&dwEndCluster)) { } bResult = TRUE; //Anything is in place. __TERMINAL: if(pBuffer) //Should release it. { LocalFree(pBuffer); } if(bResult) { *pdwCurrCluster = (dwNextCluster & 0x0FFFFFFF); } return bResult; }
DWORD WriteFileToVhd(__FAT32_FS* pFat32Fs,__FAT32_FILE* pFat32File,LPCSTR pSrcFile) { __FAT32_SHORTENTRY* pFat32Entry = NULL; HANDLE hSrcFile = NULL; BYTE* pClusBuffer = NULL; BYTE* pStart = NULL; DWORD dwCurrPos = 0; DWORD dwSector = 0; DWORD dwNextClus = 0; DWORD dwWriteSize = 0; DWORD dwFirstCluster = 0; DWORD dwOnceSize = 0; DWORD dwWritten = 0; //Record the written size. hSrcFile = CreateFileA(pSrcFile,GENERIC_READ,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0); if(hSrcFile == INVALID_HANDLE_VALUE) { return S_OK; } dwWriteSize = GetFileSize(hSrcFile,NULL); pClusBuffer = (BYTE*)LocalAlloc(LPTR,pFat32Fs->dwClusterSize); if(NULL == pClusBuffer) //Can not allocate buffer. { goto __TERMINAL; } dwCurrPos = pFat32File->dwCurrPos; dwNextClus = pFat32File->dwCurrClusNum; //if file null,first alloc a Cluster if(dwNextClus == 0 && GetFreeCluster(pFat32Fs,0,&dwNextClus)) { pFat32File->dwCurrClusNum = dwNextClus; pFat32File->dwStartClusNum = dwNextClus; dwFirstCluster = dwNextClus; } dwSector = GetClusterSector(pFat32Fs,dwNextClus); if(0 == dwSector) { goto __TERMINAL; } //Read the current cluster. if(!ReadDeviceSector(pFat32Fs->pPartition,pFat32Fs->dwPartitionSatrt+ dwSector,pFat32Fs->SectorPerClus, pClusBuffer)) { goto __TERMINAL; } while(dwWriteSize > 0) { DWORD dwRead = 0; pStart = pClusBuffer + pFat32File->dwClusOffset; dwOnceSize = pFat32Fs->dwClusterSize - pFat32File->dwClusOffset; if(dwOnceSize > dwWriteSize) { dwOnceSize = dwWriteSize; } //memcpy(pStart,pBuffer,dwOnceSize); ReadFile(hSrcFile,pStart,dwOnceSize,&dwRead,NULL); //Now write the cluster into memory. if(!WriteDeviceSector(pFat32Fs->pPartition,pFat32Fs->dwPartitionSatrt+dwSector,pFat32Fs->SectorPerClus,pClusBuffer)) { goto __TERMINAL; } //Adjust file object's status. pFat32File->dwClusOffset += dwOnceSize; pFat32File->dwCurrPos += dwOnceSize; //2014.9.28 modified by tywind if(pFat32File->dwCurrPos >= pFat32File->dwFileSize) { pFat32File->dwFileSize = pFat32File->dwCurrPos; } if(0 == (pFat32File->dwClusOffset % pFat32Fs->dwClusterSize)) { dwNextClus = pFat32File->dwCurrClusNum; if(!GetNextCluster(pFat32Fs,&dwNextClus)) { goto __TERMINAL; } if(IS_EOC(dwNextClus)) //Reach the end of file,so extend file. { if(!AppendClusterToChain(pFat32Fs,&pFat32File->dwCurrClusNum)) { goto __TERMINAL; } dwNextClus = pFat32File->dwCurrClusNum; } pFat32File->dwCurrClusNum = dwNextClus; pFat32File->dwClusOffset = 0; //Update dwSector to corespond current cluster. dwSector = GetClusterSector(pFat32Fs,dwNextClus); if(0 == dwSector) { goto __TERMINAL; } } //Adjust the buffer position and local control variables. dwWritten += dwOnceSize; dwWriteSize -= dwOnceSize; if(0 == dwWriteSize) //Write over. { break; } } //Now update the file's directory entry. dwSector = GetClusterSector(pFat32Fs,pFat32File->dwParentClus); if(0 == dwSector) { goto __TERMINAL; } if(!ReadDeviceSector(pFat32Fs->pPartition,pFat32Fs->dwPartitionSatrt+dwSector,pFat32Fs->SectorPerClus,pClusBuffer)) { goto __TERMINAL; } pFat32Entry = (__FAT32_SHORTENTRY*)(pClusBuffer + pFat32File->dwParentOffset); //modify file First Cluster index if(dwFirstCluster > 0 ) { pFat32Entry->wFirstClusHi = (WORD)(dwFirstCluster >> 16); pFat32Entry->wFirstClusLow = (WORD)(dwFirstCluster&0x0000FFFF); }