📄 dir.c
字号:
/****************************************************************************** File Name : dir.c Description : Directory management functions******************************************************************************//* Includes ---------------------------------------------------------------- */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include <assert.h>#include "sttbx.h"#include "dir.h"#include "hal.h"#include "rwbuffer.h"#include "backup.h"/* Private Types ----------------------------------------------------------- */typedef struct{ int Modified; int TableSize;}stavfs_DirMetaData_t;typedef struct{ stavfs_DirMetaData_t Meta; /* Cluster data - Form here on the structure must be the size of one cluster*/ /*U64 LBA; This is burried in stavfs_DirEntry_t now */ stavfs_DirEntry_t DirTable[1];}stavfs_DirCache_t;/* Private Constants ------------------------------------------------------- *//* Private Variables ------------------------------------------------------- *//* Private Macros ---------------------------------------------------------- *//* Private Function Prototypes --------------------------------------------- *//* Functions --------------------------------------------------------------- *//******************************************************************************Function Name : stavfs_InitRootDir Description : Open and formated root directory for the file system. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_InitRootDir (stavfs_Device_t *Device_p){ ST_ErrorCode_t Error = ST_NO_ERROR; int ClusterSize; assert(Device_p != NULL); if (Device_p->RootDir == NULL) { /* Not currently Open */ ClusterSize = Device_p->ClusterSize*DISK_SECTOR_SIZE; Device_p->RootDir = memory_allocate(Device_p->MemoryPartition, sizeof(stavfs_DirMetaData_t) + ClusterSize); if (Device_p->RootDir == NULL) { STTBX_Print (("Out of memory.\n")); Error = ST_ERROR_NO_MEMORY; } else { stavfs_DirCache_t *Cache = (stavfs_DirCache_t*)Device_p->RootDir; Cache->Meta.Modified = TRUE; Cache->Meta.TableSize = ClusterSize/sizeof(stavfs_DirEntry_t); Error = stavfs_FormatRootDir (Device_p); } } return (Error);}/******************************************************************************Function Name : stavfs_OpenRootDir Description : Open the root directory for the file system. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_OpenRootDir (stavfs_Device_t *Device_p){ ST_ErrorCode_t Error = ST_NO_ERROR; int ClusterSize; assert(Device_p != NULL); if (Device_p->RootDir == NULL) { /* Not currently Open */ ClusterSize = Device_p->ClusterSize*DISK_SECTOR_SIZE; Device_p->RootDir = memory_allocate(Device_p->MemoryPartition, sizeof(stavfs_DirMetaData_t) + ClusterSize); if (Device_p->RootDir == NULL) { STTBX_Print (("Out of memory.\n")); Error = ST_ERROR_NO_MEMORY; } else { /* Read the root directory */ stavfs_DirCache_t *Cache = (stavfs_DirCache_t*)Device_p->RootDir; Cache->Meta.Modified = FALSE; Cache->Meta.TableSize = ClusterSize/sizeof(stavfs_DirEntry_t); /* Read the Directory */ if (ST_NO_ERROR != (Error = stavfs_BOWClusterRead(Device_p, &(Device_p->RootDirLBA), (U8*)(Cache->DirTable)))) { /* Failed to read the directory */ STTBX_Print (("Failed to read the directory.\n")); stavfs_CloseRootDir (Device_p); } } } return (Error);}/******************************************************************************Function Name : stavfs_CloseRootDir Description : Close the root directory for the file system. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_CloseRootDir (stavfs_Device_t *Device_p){ ST_ErrorCode_t Error = ST_NO_ERROR; if ((Device_p != NULL) && (Device_p->RootDir != NULL)) { Error = stavfs_FlushDir (Device_p, NULL); /* Free up any allocated space */ memory_deallocate(Device_p->MemoryPartition, Device_p->RootDir); Device_p->RootDir = NULL; } return (Error);}/******************************************************************************Function Name : stavfs_FormatRootDir Description : Format the root directory. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_FormatRootDir (stavfs_Device_t *Device_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; int i; assert (Device_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; for (i = 0; (i < Cache->Meta.TableSize); i++) { Cache->DirTable[i].Flags = FILE_FLAG_ENTRY_UNUSED; } return (Error);}/******************************************************************************Function Name : stavfs_FlushDir Description : Write the root directory back to disk. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_FlushDir (stavfs_Device_t *Device_p, stavfs_DirEntry_t *Dir_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; assert (Dir_p == NULL); /* Must be root dir */ assert (Device_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; if (Cache->Meta.Modified) { /* Flush any related file buffers */ stavfs_FlushRWCache(Device_p); /* Write the data to disk */ Error = stavfs_BOWClusterWrite(Device_p, &(Device_p->RootDirLBA), (U8*)(Cache->DirTable)); if (Error == ST_NO_ERROR) { Cache->Meta.Modified = FALSE; } } return (Error);}/******************************************************************************Function Name : stavfs_ModifyDirEntry Description : Flag the directory entry as modified Parameters :******************************************************************************/ST_ErrorCode_t stavfs_ModifyDirEntry(stavfs_Device_t *Device_p, stavfs_DirEntry_t *DirEntry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; assert (Device_p != NULL); assert (DirEntry_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; Cache->Meta.Modified = TRUE; return (Error);}/******************************************************************************Function Name : stavfs_FindFileEntry Description : Find a directory entry (in the root directory) with the given name. Future implementations may copy the entry into cache with a reference count. So stavfs_ReleaseFileEntry() must be used to release an entry when it is no longer in use. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_FindFileEntry (stavfs_Device_t *Device_p, stavfs_DirEntry_t *Dir_p, char *Name, stavfs_DirEntry_t **Entry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; int i; assert (Dir_p == NULL); /* Currently must be the root directory */ assert (Name != NULL); assert (Entry_p != NULL); assert (Device_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; /* Scan looking for the file */ *Entry_p = NULL; for (i = 0; (i < Cache->Meta.TableSize) && (*Entry_p == NULL); i++) { if ( (Cache->DirTable[i].Flags & FILE_FLAG_ENTRY_USED) && !(Cache->DirTable[i].Flags & FILE_FLAG_BEING_DELETED) && (0 == strncmp(Name, (char*)Cache->DirTable[i].Name, sizeof(Cache->DirTable[i].Name)))) { *Entry_p = Cache->DirTable+i; } } return (Error);}/******************************************************************************Function Name : stavfs_NextEntry Description : Get the next directory entry. If the current entry is a NULL pointer then find the first directory entry. If there are no more entries then return a NULL pointer. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_NextEntry (stavfs_Device_t *Device_p, stavfs_DirEntry_t *Dir_p, stavfs_DirEntry_t **Entry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; stavfs_DirEntry_t *ThisEntry = NULL; assert (Dir_p == NULL); /* Currently must be the root directory */ assert (Entry_p != NULL); assert (Device_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; /* Set the start conditions */ ThisEntry = *Entry_p; *Entry_p = NULL; if (ThisEntry == NULL) { /* Start at the begining */ ThisEntry = Cache->DirTable; } else { /* Try the next entry */ ThisEntry++; } /* Scan looking for the next used entry */ for (;(ThisEntry < Cache->DirTable+Cache->Meta.TableSize) && (*Entry_p == NULL); ThisEntry++) { if (ThisEntry->Flags & FILE_FLAG_ENTRY_USED) { *Entry_p = ThisEntry; } } return (Error);}/******************************************************************************Function Name : stavfs_FindFreeEntry Description : Find an unused directory entry (in the root directory). Future implementations may copy the entry into cache with a reference count. So stavfs_ReleaseFileEntry() must be used to release an entry when it is no longer in use. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_FindFreeEntry (stavfs_Device_t *Device_p, stavfs_DirEntry_t *Dir_p, stavfs_DirEntry_t **Entry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_DirCache_t *Cache = NULL; int i; assert (Dir_p == NULL); /* Currently must be the root directory */ assert (Entry_p != NULL); assert (Device_p != NULL); assert (Device_p->RootDir != NULL); Cache = (stavfs_DirCache_t*)Device_p->RootDir; /* Scan looking for the file */ *Entry_p = NULL; for (i = 0; (i < Cache->Meta.TableSize) && (*Entry_p == NULL); i++) { if (!(Cache->DirTable[i].Flags & FILE_FLAG_ENTRY_USED)) { *Entry_p = Cache->DirTable+i; } } return (Error);}/******************************************************************************Function Name : stavfs_ReleaseFileEntry Description : Release a file entry (posibly held in cache). Future implementations may copy the entry into cache with a reference count. So stavfs_ReleaseFileEntry() must be used to release an entry when it is no longer in use. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_ReleaseFileEntry (stavfs_Device_t *Device_p, stavfs_DirEntry_t *Entry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; assert (Entry_p != NULL); assert (Device_p != NULL); assert (Device_p->RootDir != NULL); /* There is currently no reference count - so do nothing */ return (Error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -