⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cat.c

📁 ST5518机顶盒系统文件系统源代码!绝对超值!
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************    File Name   : cat.c    Description : Master/Local CAT support routines.******************************************************************************//* Includes ---------------------------------------------------------------- */#include <stdlib.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include <assert.h>#include "sttbx.h"#include "cat.h"#include "hal.h"#include "backup.h"/* Private Constants ------------------------------------------------------- */#define LCAT_CACHE_SIZE  (16)/* Private Types ----------------------------------------------------------- */        typedef struct{    /* Local CAT Cache */        U16                    LCatTime;    stavfs_LocalCatCache_t LCatCache[LCAT_CACHE_SIZE];        /* Master CAT data */        /* The 'Blocks' field MUST be the last in the structure */    /* We over allocate space for the structure to increase */    /* The size of the 'Blocks' Array.                      */        U32                    NumMCatBlocks;    stavfs_MCatBlock_t     Blocks[1];}stavfs_MCatCache_t;/* Private Variables ------------------------------------------------------- */static U64 const InvalidLBA = {INVALID_LBA, INVALID_LBA};static U64 const NullLBA    = {NULL_LBA,    NULL_LBA};    /* Private Macros ---------------------------------------------------------- *//* Private Function Prototypes --------------------------------------------- *//* Functions --------------------------------------------------------------- *//******************************************************************************Function Name : stavfs_InitCat  Description : Formated the Master CAT for the file system.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_InitCat (stavfs_Device_t *Device_p){    ST_ErrorCode_t Error         = ST_NO_ERROR;    U32            NumMCatBlocks = 0;        assert(Device_p != NULL);        if (Device_p->MCat == NULL)    {        /* Not currently Open */                /* Round up */        NumMCatBlocks = (Device_p->NumClusterBlock/M_CAT_ENTRIES_PER_BLOCK) +1;        Device_p->MCat = memory_allocate(Device_p->MemoryPartition, sizeof(stavfs_MCatCache_t) + (NumMCatBlocks-1)*sizeof(stavfs_MCatBlock_t));         if (Device_p->MCat == NULL)        {            STTBX_Print (("Out of memory.\n"));            Error = ST_ERROR_NO_MEMORY;        }        else        {            /* Format the Master CAT */            int i;             stavfs_MCatCache_t *Cache = (stavfs_MCatCache_t*)Device_p->MCat;            Cache->NumMCatBlocks  = NumMCatBlocks;                        /* Set the first block by hand */                        /* Unused2 is overloaded to flag modified blocks */            /* Modified block */            Cache->Blocks[0].Unused2 = 1;                        for (i = 0; (i < M_CAT_ENTRIES_PER_BLOCK); i++)            {                Cache->Blocks[0].M_CatData[i] = CLUSTERS_PER_BLOCK(Device_p);            }                        /* Copy the first block to all the others */                    for (i = 1; (i < NumMCatBlocks); i++)            {                memcpy(Cache->Blocks+i, Cache->Blocks, sizeof(Cache->Blocks));            }                        /* Clear entries for missing Cluster blocks at the end */                        for (i = Device_p->NumClusterBlock%M_CAT_ENTRIES_PER_BLOCK;                 (i < M_CAT_ENTRIES_PER_BLOCK);                 i++)            {                Cache->Blocks[NumMCatBlocks-1].M_CatData[i] = 0;            }                        /* Initialise the LCAT Cache */                        for (i = 0; (i < LCAT_CACHE_SIZE); i++)            {                Cache->LCatCache[i].RefCount    = 0;                Cache->LCatCache[i].InvalidData = 1;            }                        if (Error != ST_NO_ERROR)            {                /* Free up the allocated space */                 memory_deallocate(Device_p->MemoryPartition, Device_p->MCat);                Device_p->MCat = NULL;            }        }    }        return (Error);}/******************************************************************************Function Name : stavfs_OpenCat  Description : Open the Master CAT for the file system.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_OpenCat (stavfs_Device_t *Device_p){    ST_ErrorCode_t Error         = ST_NO_ERROR;    U32            NumMCatBlocks = 0;        assert(Device_p != NULL);        if (Device_p->MCat == NULL)    {        /* Not currently Open */                /* Round up */        NumMCatBlocks = (Device_p->NumClusterBlock/M_CAT_ENTRIES_PER_BLOCK) +1;        Device_p->MCat = memory_allocate(Device_p->MemoryPartition, sizeof(stavfs_MCatCache_t) + (NumMCatBlocks-1)*sizeof(stavfs_MCatBlock_t));         if (Device_p->MCat == NULL)        {            STTBX_Print (("Out of memory.\n"));            Error = ST_ERROR_NO_MEMORY;        }        else        {            /* Read the Master CAT */            int i;            U64 LBA;             stavfs_MCatCache_t *Cache = (stavfs_MCatCache_t*)Device_p->MCat;            Cache->NumMCatBlocks  = NumMCatBlocks;             /* Skip the root sector */            INT_I64_AddLit(Device_p->RootSectorLBA,                              ROOT_SECTOR_AREA_SIZE,                              LBA);                    for (i = 0; (i < NumMCatBlocks); i++)            {                /* Skip to the next MCat Block (skips over backup area on first iter) */                INT_I64_AddLit(LBA, M_CAT_BLOCK_SIZE, LBA);                 if (ST_NO_ERROR != stavfs_BOWMCATRead(Device_p, &LBA, (U8*)(Cache->Blocks+i)))                {                    /* Failed to read the MCat Block */                    STTBX_Print (("Failed to read MCat Block %d. %X\n", i, LBA.LSW));                    Error = STAVFS_ERROR_UNREADABLE_DISK;                }            }                        /* Initialise the LCAT Cache */                        for (i = 0; (i < LCAT_CACHE_SIZE); i++)            {                Cache->LCatCache[i].RefCount    = 0;                Cache->LCatCache[i].InvalidData = 1;            }                        if (Error != ST_NO_ERROR)            {                /* Free up the allocated space */                 memory_deallocate(Device_p->MemoryPartition, Device_p->MCat);                Device_p->MCat = NULL;            }        }    }        return (Error);}/******************************************************************************Function Name : stavfs_CloseCat  Description : Close the Master CAT for the file system.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_CloseCat (stavfs_Device_t *Device_p){    ST_ErrorCode_t Error = ST_NO_ERROR;        if ((Device_p != NULL) && (Device_p->MCat != NULL))    {        Error = stavfs_FlushCat (Device_p);            /* Free up any allocated space */         memory_deallocate(Device_p->MemoryPartition, Device_p->MCat);        Device_p->MCat = NULL;    }        return (Error);}/******************************************************************************Function Name : stavfs_FlushCat  Description : Flush any changes to disk.   Parameters :******************************************************************************/ST_ErrorCode_t  stavfs_FlushCat(stavfs_Device_t *Device_p){    ST_ErrorCode_t      Error   = ST_NO_ERROR;    stavfs_MCatCache_t *Cache_p = NULL;    U64                 LBA;        assert(Device_p != NULL);        if (Device_p->MCat != NULL)    {        int i;                Cache_p = (stavfs_MCatCache_t*)Device_p->MCat;                                INT_I64_AddLit(Device_p->RootSectorLBA,                          ROOT_SECTOR_AREA_SIZE + M_CAT_BLOCK_SIZE,                          LBA);                for (i = 0; (i < Cache_p->NumMCatBlocks); i++)        {            if (Cache_p->Blocks[i].Unused2)            {                /* Unused2 is overloaded to flag modified blocks */                /* Modified block */                                Cache_p->Blocks[i].Unused2 = 0;                if (ST_NO_ERROR != stavfs_BOWMCATWrite(Device_p, &LBA, (U8*)(Cache_p->Blocks+i)))                {                    /* Failed to write the MCat Block */                    STTBX_Print (("Failed to flush MCat Block %d.\n", i));                    Error = STAVFS_ERROR_UNWRITABLE_DISK;                                        Cache_p->Blocks[i].Unused2 = 1;                }            }                                    INT_I64_AddLit(LBA, M_CAT_BLOCK_SIZE, LBA);        }    }        return (Error);}/******************************************************************************Function Name : stavfs_GetNumFreeClusters  Description : Return the number of free clusters.   Parameters :******************************************************************************/ST_ErrorCode_t stavfs_GetNumFreeClusters(stavfs_Device_t *Device_p, U64 *FreeClusters){    ST_ErrorCode_t      Error   = ST_NO_ERROR;    stavfs_MCatCache_t *Cache_p = NULL;    int i;    int j;        assert (Device_p       != NULL);    assert (Device_p->MCat != NULL);    assert (FreeClusters   != NULL);        Cache_p = (stavfs_MCatCache_t*)Device_p->MCat;        INT_I64_SetValue(0,0,*FreeClusters);        for (i = 0; (i < Cache_p->NumMCatBlocks); i++)    {        for (j = 0; (j < M_CAT_ENTRIES_PER_BLOCK); j++)        {            INT_I64_AddLit(*FreeClusters, Cache_p->Blocks[i].M_CatData[j], *FreeClusters);        }    }        return (Error);}/******************************************************************************Function Name : stavfs_GetFreeClusters  Description : Find space in a Cluster Block for the required number of clusters.                The LBA of the first Cluster is returned. This is need to link                to the cluster before allocating the cluster.   Parameters :******************************************************************************/U8 stavfs_GetFreeClusters(stavfs_Device_t *Device_p, U8 NumClusters, U64 const *PrevLBA_p, U64 *FreeLBA_p){    stavfs_MCatCache_t *Cache_p = NULL;        U32 ClusterBlockId = 0;    U32 ClusterIdx     = 0;    U32 M_CatBlockId   = 0;    U32 M_CatIdx       = 0;        assert (Device_p       != NULL);    assert (Device_p->MCat != NULL);    assert (FreeLBA_p      != NULL);        Cache_p = (stavfs_MCatCache_t*)Device_p->MCat;    INT_I64_SetValue(0,0,*FreeLBA_p);        /* Find the Master CAT entry for the Prev LBA */    if (INT_I64_AreEqual(NullLBA, *PrevLBA_p))    {        /* Default start position */        M_CatIdx     = 0;        M_CatBlockId = 0;    }    else    {        stavfs_GetClusterIdx(Device_p, &ClusterBlockId, &ClusterIdx, PrevLBA_p);        M_CatIdx     = ClusterBlockId % M_CAT_ENTRIES_PER_BLOCK;        M_CatBlockId = ClusterBlockId / M_CAT_ENTRIES_PER_BLOCK;    }        /* Find the nearest cluster block with space */        {        /* Find the nearest */        int BestFit        = 0;        int UpBlockId      = M_CatBlockId;        int UpIdx          = M_CatIdx;        int DownBlockId    = M_CatBlockId;        int DownIdx        = M_CatIdx;                while ((NumClusters > BestFit) &&               ((UpBlockId  < Cache_p->NumMCatBlocks) || (DownBlockId >= 0)))        {            /* Look upwards */                        if (UpBlockId <  Cache_p->NumMCatBlocks)            {                /* Check for space */                 if ((UpBlockId <  Cache_p->NumMCatBlocks) &&                    (BestFit   <= Cache_p->Blocks[UpBlockId].M_CatData[UpIdx]))                {                    /* There is space in this Block */                    M_CatBlockId = UpBlockId;                    M_CatIdx     = UpIdx;                    BestFit      = Cache_p->Blocks[UpBlockId].M_CatData[UpIdx];                }                                /* Increment */                                UpIdx++;                if (UpIdx >= M_CAT_ENTRIES_PER_BLOCK)                {                    UpBlockId++;                    UpIdx = 0;                }            }                        /* Look downwards */                        if (DownBlockId >= 0)            {                /* Check for space */                 if ((DownBlockId >= 0) &&                    (BestFit     <= Cache_p->Blocks[DownBlockId].M_CatData[DownIdx]))                {                    /* There is space in this Block */                    M_CatBlockId = DownBlockId;                    M_CatIdx     = DownIdx;                    BestFit      = Cache_p->Blocks[DownBlockId].M_CatData[DownIdx];                }                                /* Decrement */                                DownIdx--;                if (DownIdx < 0)                {                    DownBlockId--;                    DownIdx = M_CAT_ENTRIES_PER_BLOCK-1;                }            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -