/** * @public * @brief List Directory Command * * Lists the working directory or a specified directory. * * PARAMS are explained above. **/ int ls_cmd(int argc, char **argv, FF_ENVIRONMENT *pEnv) { FF_IOMAN *pIoman = pEnv->pIoman; // FF_IOMAN object from the Environment FF_DIRENT mydir; // DIRENT object. int i = 0; FF_ERROR tester = 0; cons_printf("Type \"%s ?\" for an attribute legend.\n", argv[0]); if(argc == 1) { // Default, open the working directory. tester = FF_FindFirst(pIoman, &mydir, pEnv->WorkingDir); cons_printf("Directory Listing of: %s\n", pEnv->WorkingDir); } else if(argc == 2){ if(argv[1][0] == '?') { // If ? is first argument, print a legend. cons_printf("ATTR Info:\n"); cons_printf("D:\tDirectory\n"); cons_printf("H:\tHidden\n"); cons_printf("S:\tSystem\n"); cons_printf("R:\tRead-only\n"); return 0; } // Otherwise try to open a provided path. if(!FF_FindDir(pIoman, argv[1], (FF_T_UINT16) strlen(argv[1]))) { cons_printf("Path %s Not Found!\n\n", argv[1]); // Dir not found! return 0; } tester = FF_FindFirst(pIoman, &mydir, argv[1]); // Find first Object. cons_printf("Directory Listing of: %s\n", argv[1]); } else { cons_printf("Usage: %s\n", argv[0]); cons_printf("Or: %s ? \t// Displays a legend!\n", argv[0]); cons_printf("Or: %s [path]\t// Lists a specified path.\n", argv[0]); return 0; } cons_printf("\n"); #ifdef FF_TIME_SUPPORT cons_printf(" DATE | TIME | ATTR | FILESIZE | FILENAME \n"); cons_printf("---------------------------------------------------------\n"); #else cons_printf(" ATTR | FILESIZE | FILENAME \n"); cons_printf("---------------------------------------------------------\n"); #endif while(tester == 0) { // Loop printing each Dirent until no more are available. FF_PrintDir(&mydir); // FF_FindNext() returns 0 on success. i++; tester = FF_FindNext(pIoman, &mydir); } cons_printf("\n%d Items\n", i); cons_printf("\n"); return 0; }
static BT_HANDLE fullfat_opendir(BT_HANDLE hMount, const BT_i8 *szpPath, BT_ERROR *pError) { BT_FF_DIR *pDir = (BT_FF_DIR *) BT_CreateHandle(&oDirHandleInterface, sizeof(BT_FF_DIR), pError); if(!pDir) { *pError = BT_ERR_NO_MEMORY; goto err_out; } BT_FF_MOUNT *pMount = (BT_FF_MOUNT *) hMount; FF_ERROR ffError = FF_FindFirst(pMount->pIoman, &pDir->oDirent, szpPath); if(ffError) { *pError = BT_ERR_GENERIC; goto err_free_out; } pDir->pMount = pMount; return (BT_HANDLE) pDir; err_free_out: BT_DestroyHandle((BT_HANDLE)pDir); err_out: return NULL; }
/* A View command to type out the contents of a file using FullFAT. */ int rm_cmd(int argc, char **argv, FF_ENVIRONMENT *pEnv) { FF_ERROR Error; FF_DIRENT mydir; // Used to detect if its a file or folder. FF_T_INT8 path[FF_MAX_PATH]; FF_T_INT8 realpath[FF_MAX_PATH]; FF_T_INT8 *pName; int i; if(argc == 2) { ProcessPath(path, argv[1], pEnv); for(i = strlen(path); ; i--) { if(path[i] == '\\' || path[i] == '/') { pName = &path[i + 1]; break; } } memcpy(realpath, path, i + 1); realpath[i+1] = '\0'; Error = FF_FindFirst(pEnv->pIoman, &mydir, realpath); while(!FF_strmatch(mydir.FileName, pName, 0)) { Error = FF_FindNext(pEnv->pIoman, &mydir); if(Error) { // File cons_printf("File or Folder not found!\n"); return 0; } } if(mydir.Attrib & FF_FAT_ATTR_DIR) { Error = FF_RmDir(pEnv->pIoman, path); } else { Error = FF_RmFile(pEnv->pIoman, path); } if(Error) { cons_printf("Could not remove file or folder: %s\n", FF_GetErrMessage(Error)); } } else { cons_printf("Usage: %s [filename]\n", argv[0]); } return 0; }
/** * @public * @brief Tests if a Directory contains any other files or folders. * * @param pIoman FF_IOMAN object returned from the FF_CreateIOMAN() function. * **/ FF_T_BOOL FF_isDirEmpty(FF_IOMAN *pIoman, const FF_T_INT8 *Path) { FF_DIRENT MyDir; FF_ERROR RetVal = FF_ERR_NONE; FF_T_UINT8 i = 0; if(!pIoman) { return FF_FALSE; } RetVal = FF_FindFirst(pIoman, &MyDir, Path); while(RetVal == 0) { i++; RetVal = FF_FindNext(pIoman, &MyDir); if(i > 2) { return FF_FALSE; } } return FF_TRUE; }
static int wrap_fs_chdir(struct _reent *r, char *path) { #if 0 FF_DIRENT dir; char tmpath[256]; if ((path[0] != '/') && (path[0] != '\\')) snprintf(tmpath, 256, "%s/%s", current_path, path); else strcpy(tmpath, path); normalize_path(tmpath); xfprintf(stderr, "chdir(%s)\n", tmpath); if (!FF_FindFirst(pIoman, &dir, tmpath)) { strcpy(current_path, tmpath); return 0; } #endif r->_errno = ENOTDIR; return -1; }
static BT_HANDLE fullfat_open_inode(BT_HANDLE hMount, const BT_i8 *szpPath, BT_ERROR *pError) { BT_FF_INODE *pInode = (BT_FF_INODE *) BT_CreateHandle(&oInodeHandleInterface, sizeof(BT_FF_INODE), pError); if(!pInode) { goto err_out; } BT_FF_MOUNT *pMount = (BT_FF_MOUNT *) hMount; FF_ERROR ffError = FF_FindFirst(pMount->pIoman, &pInode->oDirent, szpPath); if(ffError) { goto err_free_out; } pInode->pMount = pMount; return (BT_HANDLE) pInode; err_free_out: BT_DestroyHandle((BT_HANDLE)pInode); err_out: return NULL; }
int cp_cmd(int argc, char **argv, FF_ENVIRONMENT *pEnv) { #ifdef FF_UNICODE_SUPPORT const wchar_t *szpSource, *szpDestination, *szpWildCard; #else const char *szpSource, *szpDestination, *szpWildCard; #endif char szsrcPath[FF_MAX_PATH], szdestPath[FF_MAX_PATH]; FF_DIRENT findData; FFT_GETOPT_CONTEXT optionContext; // CommandLine processing FF_T_BOOL bRecursive = FF_FALSE, bVerbose = FF_FALSE; // Option Flags. int option; memset(&optionContext, 0, sizeof(FFT_GETOPT_CONTEXT)); // Initialise the option context to zero. option = FFTerm_getopt(argc, (const char **) argv, "rRvx", &optionContext); // Get the command line option charachters. while(option != EOF) { // Process Commandline options switch(option) { case 'r': case 'R': bRecursive = FF_TRUE; // Set recursive flag if -r or -R appears on the commandline. break; case 'v': bVerbose = FF_TRUE; // Set verbose flag if -v appears on the commandline. break; case 'x': bExternal = FF_TRUE; break; default: break; } option = FFTerm_getopt(argc, (const char **) argv, "rRvx", &optionContext); // Get the next option. } szpSource = FFTerm_getarg(argc, (const char **) argv, 0, &optionContext); // The remaining options or non optional arguments. szpDestination = FFTerm_getarg(argc, (const char **) argv, 1, &optionContext); // getarg() retrieves them intelligently. if(!szpSource) { printf("%s: No source file argument.\n", argv[0]); // No source file provided. return 0; } if(!szpDestination) { printf("%s: No destination file argument.\n", argv[0]); // No destination provided. return 0; } ProcessPath(szsrcPath, szpSource, pEnv); // Process the paths into absolute paths. ProcessPath(szdestPath, szpDestination, pEnv); szpWildCard = GetWildcard(szpSource); // Get the last token of the source path. (This may include a wildCard). if(strchr(szpWildCard, '*')) { // If the 'WildCard' contains a * then its a wild card, otherwise its a file or directory. // WildCard Copying! //copy_wild(); return 0; } if(FF_FindFirst(pEnv->pIoman, &findData, szsrcPath)) { // Get the dirent for the file or directory, to detect if its a directory. // Not found! printf("%s: %s: no such file or directory.\n", argv[0], szpSource); return 0; } if(!strcmp(findData.FileName, szpWildCard) && (findData.Attrib & FF_FAT_ATTR_DIR)) { if(!bRecursive) { // Its a dir! printf("%s: omitting directory '%s'\n", argv[0], szsrcPath); return 0; } copy_dir(szsrcPath, szdestPath, bRecursive, bVerbose, pEnv);// Start the copying! return 0; } copy_file(szsrcPath, szdestPath, bVerbose, pEnv); // Final option, its simply a file to file copy return 0; }
static int copy_dir(const char *srcPath, const char *destPath, FF_T_BOOL bRecursive, FF_T_BOOL bVerbose, FF_ENVIRONMENT *pEnv) { FF_DIRENT findData; FF_ERROR RetVal; FF_T_INT8 szsrcFile[FF_MAX_PATH], szdestFile[FF_MAX_PATH]; //const char *szpWildCard; int i; strcpy(szsrcFile, srcPath); strcpy(szdestFile, destPath); // Ensure the paths both end in a '/' charachter i = strlen(szsrcFile); if(szsrcFile[i - 1] != '\\' || szsrcFile[i - 1] != '/') { strcat(szsrcFile, "\\"); } i = strlen(szdestFile); if(szdestFile[i - 1] != '\\' || szdestFile[i - 1] != '/') { strcat(szdestFile, "\\"); } RetVal = FF_FindFirst(pEnv->pIoman, &findData, szsrcFile); if(RetVal) { printf("cp: %s: No such file or directory.\n", srcPath); return 0; } while(!RetVal) { AppendFilename(szsrcFile, findData.FileName); AppendFilename(szdestFile, findData.FileName); if(!strcmp(szsrcFile, szdestFile)) { printf("cp: Source and Destination files are identical: illegal operation.\n"); return 0; } if((findData.Attrib & FF_FAT_ATTR_DIR)) { if(!(findData.FileName[0] == '.' && !findData.FileName[1]) && !(findData.FileName[0] == '.' && findData.FileName[1] == '.' && !findData.FileName[2])) { // Add the wild card onto the end! if(bRecursive) { strcat(szsrcFile, "\\"); //szpWildCard = getWildcard(srcPath); //strcat(szsrcFile, szpWildCard); strcat(szdestFile, "\\"); //szpWildCard = getWildcard(destPath); //strcat(szdestFile, szpWildCard); // Make the dir if it doesn't already exist! copy_dir(szsrcFile, szdestFile, bRecursive, bVerbose, pEnv); strcpy(szsrcFile, srcPath); // Reset the path. } } } else { copy_file(szsrcFile, szdestFile, bVerbose, pEnv); } RetVal = FF_FindNext(pEnv->pIoman, &findData); } return 0; }
FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_WCHAR *path, FF_T_UINT8 Mode, FF_ERROR *pError) { #else FF_FILE *FF_Open(FF_IOMAN *pIoman, const FF_T_INT8 *path, FF_T_UINT8 Mode, FF_ERROR *pError) { #endif FF_FILE *pFile; FF_FILE *pFileChain; FF_DIRENT Object; FF_T_UINT32 DirCluster, FileCluster; FF_T_UINT32 nBytesPerCluster; #ifdef FF_UNICODE_SUPPORT FF_T_WCHAR filename[FF_MAX_FILENAME]; #else FF_T_INT8 filename[FF_MAX_FILENAME]; #endif FF_ERROR Error; FF_T_UINT16 i; if(pError) { *pError = 0; } if(!pIoman) { if(pError) { *pError = FF_ERR_NULL_POINTER; } return (FF_FILE *)NULL; } pFile = FF_MALLOC(sizeof(FF_FILE)); if(!pFile) { if(pError) { *pError = FF_ERR_NOT_ENOUGH_MEMORY; } return (FF_FILE *)NULL; } // Get the Mode Bits. pFile->Mode = Mode; #ifdef FF_UNICODE_SUPPORT i = (FF_T_UINT16) wcslen(path); #else i = (FF_T_UINT16) strlen(path); #endif while(i != 0) { if(path[i] == '\\' || path[i] == '/') { break; } i--; } #ifdef FF_UNICODE_SUPPORT wcsncpy(filename, (path + i + 1), FF_MAX_FILENAME); #else strncpy(filename, (path + i + 1), FF_MAX_FILENAME); #endif if(i == 0) { i = 1; } DirCluster = FF_FindDir(pIoman, path, i, &Error); if(Error) { if(pError) { *pError = Error; } FF_FREE(pFile); return (FF_FILE *) NULL; } if(DirCluster) { FileCluster = FF_FindEntryInDir(pIoman, DirCluster, filename, 0x00, &Object, &Error); if(Error) { if(pError) { *pError = Error; } FF_FREE(pFile); return (FF_FILE *) NULL; } if(!FileCluster) { // If 0 was returned, it might be because the file has no allocated cluster #ifdef FF_UNICODE_SUPPORT if(wcslen(filename) == wcslen(Object.FileName)) { if(Object.Filesize == 0 && FF_strmatch(filename, Object.FileName, (FF_T_UINT16) wcslen(filename)) == FF_TRUE) { #else if(strlen(filename) == strlen(Object.FileName)) { if(Object.Filesize == 0 && FF_strmatch(filename, Object.FileName, (FF_T_UINT16) strlen(filename)) == FF_TRUE) { #endif // The file really was found! FileCluster = 1; } } } if(!FileCluster) { if((pFile->Mode & FF_MODE_CREATE)) { FileCluster = FF_CreateFile(pIoman, DirCluster, filename, &Object, &Error); if(Error) { if(pError) { *pError = Error; } FF_FREE(pFile); return (FF_FILE *) NULL; } Object.CurrentItem += 1; } } if(FileCluster) { if(Object.Attrib == FF_FAT_ATTR_DIR) { if(!(pFile->Mode & FF_MODE_DIR)) { // Not the object, File Not Found! FF_FREE(pFile); if(pError) { *pError = FF_ERR_FILE_OBJECT_IS_A_DIR; } return (FF_FILE *) NULL; } } //---------- Ensure Read-Only files don't get opened for Writing. if((pFile->Mode & FF_MODE_WRITE) || (pFile->Mode & FF_MODE_APPEND)) { if((Object.Attrib & FF_FAT_ATTR_READONLY)) { FF_FREE(pFile); if(pError) { *pError = FF_ERR_FILE_IS_READ_ONLY; } return (FF_FILE *) NULL; } } pFile->pIoman = pIoman; pFile->FilePointer = 0; pFile->ObjectCluster = Object.ObjectCluster; pFile->Filesize = Object.Filesize; pFile->CurrentCluster = 0; pFile->AddrCurrentCluster = pFile->ObjectCluster; //pFile->Mode = Mode; pFile->Next = NULL; pFile->DirCluster = DirCluster; pFile->DirEntry = Object.CurrentItem - 1; nBytesPerCluster = pFile->pIoman->pPartition->SectorsPerCluster / pIoman->BlkSize; pFile->iChainLength = 0; pFile->iEndOfChain = 0; pFile->FileDeleted = FF_FALSE; // File Permission Processing // Only "w" and "w+" mode strings can erase a file's contents. // Any other combinations will not cause an erase. if((pFile->Mode & FF_MODE_TRUNCATE)) { pFile->Filesize = 0; pFile->FilePointer = 0; } /* Add pFile onto the end of our linked list of FF_FILE objects. */ FF_PendSemaphore(pIoman->pSemaphore); { if(!pIoman->FirstFile) { pIoman->FirstFile = pFile; } else { pFileChain = (FF_FILE *) pIoman->FirstFile; do { if(pFileChain->ObjectCluster == pFile->ObjectCluster) { // File is already open! DON'T ALLOW IT! FF_ReleaseSemaphore(pIoman->pSemaphore); FF_FREE(pFile); if(pError) { *pError = FF_ERR_FILE_ALREADY_OPEN; } return (FF_FILE *) NULL; } if(!pFileChain->Next) { pFileChain->Next = pFile; break; } pFileChain = (FF_FILE *) pFileChain->Next; }while(pFileChain != NULL); } } FF_ReleaseSemaphore(pIoman->pSemaphore); return pFile; }else { FF_FREE(pFile); if(pError) { *pError = FF_ERR_FILE_NOT_FOUND; } return (FF_FILE *) NULL; } } if(pError) { *pError = FF_ERR_FILE_INVALID_PATH; } FF_FREE(pFile); return (FF_FILE *)NULL; } /** * @public * @brief Tests if a Directory contains any other files or folders. * * @param pIoman FF_IOMAN object returned from the FF_CreateIOMAN() function. * **/ #ifdef FF_UNICODE_SUPPORT FF_T_BOOL FF_isDirEmpty(FF_IOMAN *pIoman, const FF_T_WCHAR *Path) { #else FF_T_BOOL FF_isDirEmpty(FF_IOMAN *pIoman, const FF_T_INT8 *Path) { #endif FF_DIRENT MyDir; FF_ERROR RetVal = FF_ERR_NONE; FF_T_UINT8 i = 0; if(!pIoman) { return FF_FALSE; } RetVal = FF_FindFirst(pIoman, &MyDir, Path); while(RetVal == 0) { i++; RetVal = FF_FindNext(pIoman, &MyDir); if(i > 2) { return FF_FALSE; } } return FF_TRUE; } #ifdef FF_UNICODE_SUPPORT FF_ERROR FF_RmDir(FF_IOMAN *pIoman, const FF_T_WCHAR *path) { #else FF_ERROR FF_RmDir(FF_IOMAN *pIoman, const FF_T_INT8 *path) { #endif FF_FILE *pFile; FF_ERROR Error = FF_ERR_NONE; FF_T_UINT8 EntryBuffer[32]; FF_FETCH_CONTEXT FetchContext; FF_T_SINT8 RetVal = FF_ERR_NONE; #ifdef FF_PATH_CACHE FF_T_UINT32 i; #endif if(!pIoman) { return FF_ERR_NULL_POINTER; } pFile = FF_Open(pIoman, path, FF_MODE_DIR, &Error); if(!pFile) { return Error; // File in use or File not found! } pFile->FileDeleted = FF_TRUE; FF_lockDIR(pIoman); { if(FF_isDirEmpty(pIoman, path)) { FF_lockFAT(pIoman); { Error = FF_UnlinkClusterChain(pIoman, pFile->ObjectCluster, 0); // 0 to delete the entire chain! } FF_unlockFAT(pIoman); if(Error) { FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } // Initialise the dirent Fetch Context object for faster removal of dirents. Error = FF_InitEntryFetch(pIoman, pFile->DirCluster, &FetchContext); if(Error) { FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } // Edit the Directory Entry! (So it appears as deleted); Error = FF_RmLFNs(pIoman, pFile->DirEntry, &FetchContext); if(Error) { FF_CleanupEntryFetch(pIoman, &FetchContext); FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } Error = FF_FetchEntryWithContext(pIoman, pFile->DirEntry, &FetchContext, EntryBuffer); if(Error) { FF_CleanupEntryFetch(pIoman, &FetchContext); FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } EntryBuffer[0] = 0xE5; Error = FF_PushEntryWithContext(pIoman, pFile->DirEntry, &FetchContext, EntryBuffer); if(Error) { FF_CleanupEntryFetch(pIoman, &FetchContext); FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } #ifdef FF_PATH_CACHE FF_PendSemaphore(pIoman->pSemaphore); // Thread safety on shared object! { for(i = 0; i < FF_PATH_CACHE_DEPTH; i++) { #ifdef FF_UNICODE_SUPPORT if(FF_strmatch(pIoman->pPartition->PathCache[i].Path, path, (FF_T_UINT16)wcslen(path))) { #else if(FF_strmatch(pIoman->pPartition->PathCache[i].Path, path, (FF_T_UINT16)strlen(path))) { #endif pIoman->pPartition->PathCache[i].Path[0] = '\0'; pIoman->pPartition->PathCache[i].DirCluster = 0; FF_ReleaseSemaphore(pIoman->pSemaphore); } } } FF_ReleaseSemaphore(pIoman->pSemaphore); #endif Error = FF_IncreaseFreeClusters(pIoman, pFile->iChainLength); if(Error) { FF_CleanupEntryFetch(pIoman, &FetchContext); FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } FF_CleanupEntryFetch(pIoman, &FetchContext); Error = FF_FlushCache(pIoman); if(Error) { FF_unlockDIR(pIoman); FF_Close(pFile); return Error; } } else { RetVal = FF_ERR_DIR_NOT_EMPTY; } } FF_unlockDIR(pIoman); Error = FF_Close(pFile); // Free the file pointer resources if(Error) { return Error; } // File is now lost! return RetVal; }
/* Copies with wild-cards! cp_cmd redirects here if it detects a wildCard in the source or destination paths. */ int wildcopy(int argc, char **argv, FF_ENVIRONMENT *pEnv) { FF_T_INT8 pathsrc[FF_MAX_PATH]; FF_T_INT8 pathdest[FF_MAX_PATH]; FF_T_INT8 tmpsrc[FF_MAX_PATH]; FF_T_INT8 tmpdest[FF_MAX_PATH]; FF_T_INT8 srcWild[FF_MAX_PATH]; FF_T_INT8 destWild[FF_MAX_PATH]; FF_DIRENT mydir; FF_ERROR Tester; FF_T_INT8 *p; if(argc != 3) { cons_printf("Copy command is invalid\n"); return 0; } ProcessPath(pathsrc, argv[1], pEnv); ProcessPath(pathdest, argv[2], pEnv); p = strstr(pathdest, "*"); if(!p) { cons_printf("Missing Wildcard!\n"); return 0; } strcpy(destWild, p); *p = '\0'; p = strstr(pathsrc, "*"); if(!p) { cons_printf("Missing Wildcard!\n"); return 0; } strcpy(srcWild, p); *p = '\0'; if(!FF_strmatch(srcWild, destWild, 0)) { cons_printf("Source and Destination Wildcards do not match!\n"); return 0; } Tester = FF_FindFirst(pEnv->pIoman, &mydir, pathsrc); while(!Tester) { if(wildCompare(srcWild, mydir.FileName)) { // Do Copy! if(!FF_strmatch(mydir.FileName, ".", 0) && !FF_strmatch(mydir.FileName, "..", 0)) { cons_printf("Copying file %s\n", mydir.FileName); strcpy(tmpsrc, pathsrc); strcat(tmpsrc, mydir.FileName); strcpy(tmpdest, pathdest); strcat(tmpdest, mydir.FileName); if(filecopy(tmpsrc, tmpdest, pEnv) == FF_ERR_FILE_OBJECT_IS_A_DIR) { // Recurse through a dir copy with the same wildcards. // Make the DIR etc. FF_MkDir(pEnv->pIoman, tmpdest); } } } Tester = FF_FindNext(pEnv->pIoman, &mydir); } return 0; }