bool FS_RecDeleteDir(const char* path) { FS_Dir dir; FS_DirEntry entry; bool ret; const char* dirname; size_t pathlen; size_t tmplen; char* tmp; if (!FS_IsDirectory(path)) return false; if (FS_IsSpecial(path)) return false; dir = FS_OpenDir(path); if (dir == FS_INVALID_DIR) return false; pathlen = strlen(path); while ((entry = FS_ReadDir(dir)) != FS_INVALID_DIR_ENTRY) { dirname = FS_DirEntryName(entry); if (FS_IsSpecial(dirname)) continue; // create relative path in temporary buffer tmplen = pathlen + 1 + strlen(dirname) + 1; tmp = new char[tmplen]; memcpy(tmp, path, pathlen); tmp[pathlen] = FS_Separator(); memcpy(tmp + pathlen + 1, dirname, strlen(dirname)); tmp[tmplen - 1] = '\0'; if (FS_IsDirectory(tmp)) ret = FS_RecDeleteDir(tmp); else ret = FS_Delete(tmp); delete[] tmp; if (!ret) return false; } FS_CloseDir(dir); return FS_DeleteDir(path); }
//************************************************************************************* // Function: CETYPE FS_chDir (FSFILE* chDir) //------------------------------------------------------------------------------------- // Summary: Changes Current Working Directory (CWD) to the directory pointed to // by chDir // Input: // chDir - pointer to the File Object structure that on SUCCESS // will become the new CWD. // Return Values: // CETYPE enum member (expected CE_GOOD) // Other codes depending on encountered error conditions //************************************************************************************* CETYPE FS_chDir (FSFILE* chDir) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == chDir) return CE_INVALID_ARGUMENT; if (!FS_IsDirectory(chDir)) return CE_NOT_A_DIRECTORY; //---------------------------------------------------------------- SDFS_CopyFSFILE(&SDFS_CWD, chDir); //---------------------------------------------------------------- return CE_GOOD; }
//********************************************************************************* // Function: CETYPE FS_Recover(FSFILE* filePtr) //--------------------------------------------------------------------------------- // Summary: Recovers the length of a 0-length file identified by the filePtr // based upon the number of allocated clusters // Input: // filePtr - Pointer to the File Object structure identifying the // file to be recovered // Return Values: // CE_GOOD - File was recovered successfully // Other return codes may identify various error // conditions as required. //********************************************************************************* CETYPE FS_Recover(FSFILE* filePtr) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == filePtr) return CE_INVALID_ARGUMENT; //---------------------------------------------------------------- // Check if this is a file and not a Directory if( FS_IsDirectory(filePtr) ) return CE_DIRECTORY; // Check if the file is actually 0-length if( FS_GetSize(filePtr) > 0 ) return CE_GOOD; //----------------------------------------------------------------- DWORD ClsSize = (DWORD)SDFS_VolumeInfo.SecPerClus * SDFS_VolumeInfo.sectorSize; DWORD ClsNum = SDFS_DirGetFirstCluster(&filePtr->dirFileEntry); //----------------------------------------------------------------- while (ClsNum < EOC_CLUSTER_FAT32) { //------------------------------------------------------- // Process cluster chain //------------------------------------------------------- // The first 2 clusters in FAT32 are reserved... if ( ClsNum < 2) // Cluster Number can't be "0" and "1" return CE_RECOVERY_FAIL; //------------------------------------------------------- filePtr->dirFileEntry.DIR_FileSize += ClsSize; //------------------------------------------------------- // Load next cluster in the chain //------------------------------------------------------- ClsNum = SDFS_FATCacheRead(ClsNum); } //----------------------------------------------------------------- // Flush updates to disk //----------------------------------------------------------------- return FS_Flush(filePtr); }
//********************************************************************************* // Function: CETYPE FS_Delete (FSFILE* filePtr) //--------------------------------------------------------------------------------- // Summary: Deletes the file identified by the filePtr // Input: // filePtr - Pointer to the File Object structure identifying the // file to be deleted // Return Values: // CE_GOOD - File was deleted successfully // Other return codes may identify various error // conditions as required. //********************************************************************************* CETYPE FS_Delete (FSFILE* filePtr) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == filePtr) return CE_INVALID_ARGUMENT; //---------------------------------------------------------------- // Check if this is a file and not a Directory if( FS_IsDirectory(filePtr) ) return CE_DELETE_DIR; // Check if the file attributes allow write if( FS_IsReadOnly(filePtr) ) return CE_READONLY; //----------------------------------------------------------------- CETYPE RC = CE_GOOD; DWORD ClsNum = SDFS_DirGetFirstCluster(&filePtr->dirFileEntry); //----------------------------------------------------------------- // Free Cluster Chain and flush changes to disk //----------------------------------------------------------------- if (CE_GOOD != (RC = SDFS_FATEraseClusterChain(ClsNum))) return RC; ClsNum = SDFS_FATCacheFlush(); if (CLUSTER_FAIL_FAT32 == ClsNum) return CE_DISK_ERROR; //----------------------------------------------------------------- // Mark Directory Entry as "deleted" and flush updates to disk //----------------------------------------------------------------- filePtr->dirFileEntry.DIR_Name[0] = DIR_DEL; if (CE_GOOD != (RC = FS_Flush(filePtr))) return RC; //----------------------------------------------------------------- return SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); }
void debug_filesystem(void) { FS_HANDLE FileHandle=0; UINT32 command; FILE_INFO fileinfo={0}; UINT08 ShortFileName[13]={0}; UINT08 FileBuffer[512]; int FileNo; int iter; do { ShowMenu(); command = ReadKeyInput("Select Command"); switch(command) { case 0x01: { int ret; ret = FS_OpenDriver(); if(ret == 1) dbgprint("Open Driver Success!\n"); else dbgprint("Open Driver Error!\n"); } break; case 0x02: rprint0n("No Use\n"); break; case 0x03: //Mount if(!FS_Mount()) { rprint0n("Mount Fail!\n"); break; } //Open Root Dir fileinfo.Target[0] = '*'; fileinfo.Target[1] = '.'; fileinfo.Target[2] = '*'; if(!FS_OpenRootDir(&fileinfo)) { rprint0n("Open Root Directory Fail!\n"); break; } //Find Start FS_FindStart(&fileinfo); //Show File Name for(iter=0; iter<fileinfo.TotalCount; iter++) { rprint0n("File%02d : ", iter); if(FS_GetFile(iter, &fileinfo)) { if(FS_GetFileName(&fileinfo, ShortFileName) ) { rprint0n("%s : ", ShortFileName); if(FS_IsDirectory(&fileinfo)) { rprint0n("Directory", ShortFileName); } else { rprint0n("File", ShortFileName); } #if 0 { UINT08 index; UINT08 LongFileName[512]={0}; index = FS_GetLongFileName(&fileinfo, LongFileName); ViewLongName(LongFileName, index); } #endif } } rprint0n("\n"); } break; case 0x04: FileNo = (int)ReadDecimalKeyInput("File Number"); if(FileNo >= fileinfo.TotalCount) { rprint0n("Invalid File Number !\n"); break; } //Get File if(FS_GetFile(FileNo, &fileinfo)) { if(FS_IsDirectory(&fileinfo)) { //rprint0n("File Open Fail - Directory\n"); if(FS_OpenDir(&fileinfo)) { FS_FindStart(&fileinfo); //Show File Name for(iter=0; iter<fileinfo.TotalCount; iter++) { rprint0n("File%02d : ", iter); if(FS_GetFile(iter, &fileinfo)) { if(FS_GetFileName(&fileinfo, ShortFileName) ) { rprint0n("%s : ", ShortFileName); if(FS_IsDirectory(&fileinfo)) { rprint0n("Directory", ShortFileName); } else { rprint0n("File", ShortFileName); } } } rprint0n("\n"); } } break; } //Open File FileHandle = FS_OpenFile(&fileinfo); if(FileHandle == 0xFFFFFFFF) { rprint0n("Invalid File Handle!\n"); break; } } rprint0n("File Open - Index %d\n", FileNo); break; case 0x05: if(FileHandle == 0) break; if(FileHandle == 0xFFFFFFFF) break; if(FileHandle == 0xCCCCCCCC) break; //Read File if(FS_ReadFile(FileHandle, FileBuffer, 1)) { dbgprint("^B^============= File Read ===============\n"); hexdump("Read File", FileBuffer, 512); dbgprint("^B^============================================\n"); break; } rprint0n("File Read Fail! or End of File\n"); break; case 0x06: rprint0n("File Close\n"); FS_CloseFile(FileHandle); //Close File break; case 0x07: //UnMount break; case 0xFF: command = INVALID_COMMAND; } }while(command != INVALID_COMMAND); }
//************************************************************************************* // Function: CETYPE FS_CreateFile ( const char * FileName, // FILE_MODE mode, // FSFILE* filePtr ) // Summary: Creates/Opens a file with ascii name provided in FileName // Input: // FileName - The name of the file to open // mode - File open mode (FILE_MODE enum) // - FS_CREATE_NEW - Create a new file or replace an existing file. // - FS_OPEN_EXISTING - Open existing file for read/write access or // creates a new file; file is positioned at the // beginning. // - FS_APPEND - Open existing file for read/write access or // creates a new file; file is positioned just // past the last byte. // - FS_READ_ONLY - Open existing file in read-only mode; file // positioned at the beginning. // filePtr - pointer to FSFILE data structure that will be confi- // gured ro provide access to the file if function // succeeds. // Return Values: // CETYPE - Expected CE_GOOD, but may have other codes depending on // various error conditions. // Description: // This function will create and/or open specified file. // The specified file name will be formatted to ensure that it's in 8.3 // format. Next, the search for the specified file name will be // performed. If the name is found, the action will be taken based // upon the requested File Mode. //************************************************************************************* CETYPE FS_CreateFile ( const char* FileName, FILE_MODE mode, FSFILE* filePtr ) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == FileName) return CE_INVALID_ARGUMENT; if (NULL == filePtr) return CE_INVALID_ARGUMENT; //----------------------------------------------------------------- CETYPE RC = CE_GOOD; char fmtName[NAME_SIZE_8r3]; //----------------------------------------------------------------- // Validate new name and convert it to 8.3 FAT format //----------------------------------------------------------------- if ( !SDFS_Format8dot3Name(FileName, fmtName, FALSE) ) return CE_INVALID_FILENAME; //================================================================ // Make sure that the name provided is unique... //---------------------------------------------------------------- FS_SeekStart(&SDFS_CWD); // Rewind Current Working Directory RC = SDFS_DirFindNext(&SDFS_CWD, filePtr, ATTR_NONE, ATTR_NONE, fmtName); //---------------------------------------------------------------- if (CE_EOF == RC) // There is no object with the same name goto NotFound; //---------------------------------------------------------------- if (CE_GOOD != RC) // Some other error (except for CE_EOF) had happened... return RC; //---------------------------------------------------------------- if ( FS_IsDirectory(filePtr) ) // The object found is a Directory... { SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return CE_FILENAME_EXISTS; } //---------------------------------------------------------------- //================================================================ // The file with the specified name present on the disk... //---------------------------------------------------------------- switch(mode) { case FS_CREATE_NEW: // File exists, we want to create a new one, so remove it first if ( CE_GOOD != (RC = FS_Delete(filePtr)) ) // Delete failed... { SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return RC; } //----------------------------------------- // Nope, does not exist any more :) goto NotFound; case FS_APPEND: // File exists, we want to position it at the end if ( CE_GOOD != (RC = FS_SeekEnd(filePtr)) ) // Seek failed... { SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return RC; } //----------------------------------------- // Everything is fine! return CE_GOOD; case FS_READ_ONLY: // Set READONLY attribute on the FO data structure to prevent WRITEs filePtr->dirFileEntry.DIR_Attr |= ATTR_READONLY; // Fall-through to OPEN_EXISTING case FS_OPEN_EXISTING: FS_SeekStart(filePtr); return CE_GOOD; default: SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return CE_INVALID_ARGUMENT; } //================================================================ // The file with the specified name does not exist on disk... //---------------------------------------------------------------- NotFound: switch(mode) { case FS_CREATE_NEW: case FS_APPEND: case FS_OPEN_EXISTING: // For all of the cases above proceed to creating new file break; case FS_READ_ONLY: // Bad luck... SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return CE_NOT_FOUND; default: SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return CE_INVALID_ARGUMENT; } //================================================================ // Now it is time to create a new file //---------------------------------------------------------------- // First, try to create Directory Entry //---------------------------------------------------------------- if ( (RC = SDFS_DirFindEmpty(&SDFS_CWD, filePtr)) != CE_GOOD) return RC; // Could not create directory entry... //---------------------------------------------------------------- // Second, allocate a cluster to the file //---------------------------------------------------------------- if ( CE_GOOD != (RC = SDFS_ClusterAllocateNew(filePtr)) ) { SDFS_InitFSFILE(filePtr, NULL, ATTR_NONE); // Reset output FSFILE structure return RC; } //---------------------------------------------------------------- // Third, set the name and Attributes of the new entry //---------------------------------------------------------------- memcpy(filePtr->dirFileEntry.DIR_Name, fmtName, NAME_SIZE_8r3); filePtr->dirFileEntry.DIR_Attr = ATTR_ARCHIVE; //---------------------------------------------------------------- // That's basically it - just need to save changes to disk //---------------------------------------------------------------- return FS_Flush(filePtr); }
//************************************************************************************* // Function: CETYPE FS_mkDir (char * Name, ATTR_TYPE Attr, FSFILE* newDir) //------------------------------------------------------------------------------------- // Summary: Creates directory with the specified name in the current working // directory. // Input: // Name - Name of the new directory // Attr - Additional attributes of the new directory // newDir - pointer to the File Object structure that on SUCCESS // will be set to the newly created directory. // Return Values: // CETYPE enum member (expected CE_GOOD) // Other codes depending on encountered error conditions //************************************************************************************* CETYPE FS_mkDir (char * Name, ATTR_TYPE Attr, FSFILE* newDir) { //---------------------------------------------------------------- // Validate conditions and parameters //---------------------------------------------------------------- if (!SDFS_InitStatus) return CE_NOT_INIT; // FS is not initialized! if (NULL == Name) return CE_INVALID_FILENAME; if (NULL == newDir) return CE_INVALID_ARGUMENT; //---------------------------------------------------------------- char fmtName[NAME_SIZE_8r3]; CETYPE RC; //---------------------------------------------------------------- // Verify/Format provided Directory name (for direct match) //---------------------------------------------------------------- if ( !SDFS_Format8dot3Name (Name, fmtName, FALSE) ) return CE_INVALID_FILENAME; // Invalid/missing name //---------------------------------------------------------------- // Make sure that the name provided is unique... //---------------------------------------------------------------- FS_SeekStart(&SDFS_CWD); // Rewind Current Working Directory RC = SDFS_DirFindNext(&SDFS_CWD, newDir, ATTR_NONE, ATTR_NONE, fmtName); //---------------------------------------------------------------- if (CE_GOOD == RC) { if ( FS_IsDirectory(newDir) ) // Directory with the same name is found... return CE_GOOD; else // There exists file with the same name... { SDFS_InitFSFILE(newDir, NULL, ATTR_NONE); // Reset output FSFILE structure return CE_FILENAME_EXISTS; } } if (CE_EOF != RC) return RC; // Some other error happend on the way... //---------------------------------------------------------------- // The name provided is unique; Try to create Directory Entry //---------------------------------------------------------------- if ( (RC = SDFS_DirFindEmpty(&SDFS_CWD, newDir)) != CE_GOOD) return RC; // Could not create directory entry... //---------------------------------------------------------------- // Success; Set the name and Attributes of the new entry //---------------------------------------------------------------- memcpy(newDir->dirFileEntry.DIR_Name, fmtName, NAME_SIZE_8r3); newDir->dirFileEntry.DIR_Attr = ATTR_DIRECTORY | ATTR_ARCHIVE; //---------------------------------------------------------------- // Allocate a cluster for the new Directory and create mandatory // "." and ".." entries //---------------------------------------------------------------- if ( (RC = SDFS_ClusterAllocateNew(newDir)) != CE_GOOD) // Failure allocating cluster... { SDFS_InitFSFILE(newDir, NULL, ATTR_NONE); // Reset output FSFILE structure return RC; } //---------------------------------------------------------------- DIRENTRY spcDir; DWORD dirCluster; // Set template Directory record for "." and ".." entries SDFS_DirResetEntry( &spcDir, NULL, ATTR_DIRECTORY); //---------------------------------------------------------------- // Create and store "." entry //---------------------------------------------------------------- spcDir.DIR_Name[0] = '.'; dirCluster = SDFS_DirGetFirstCluster(&newDir->dirFileEntry); SDFS_DirSetFirstCluster (&spcDir, dirCluster); FS_Write(newDir, &spcDir, sizeof(DIRENTRY)); //---------------------------------------------------------------- // Create and store ".." entry //---------------------------------------------------------------- spcDir.DIR_Name[1] = '.'; dirCluster = SDFS_DirGetFirstCluster(&SDFS_CWD.dirFileEntry); if (dirCluster == SDFS_VolumeInfo.rootClsN) // Parent is the Root directory of the volume dirCluster = 0; // FAT32 rule for pointers to Root SDFS_DirSetFirstCluster (&spcDir, dirCluster); FS_Write(newDir, &spcDir, sizeof(DIRENTRY)); //---------------------------------------------------------------- return FS_Flush(newDir); }