mirror of https://github.com/ventoy/Ventoy
627 lines
14 KiB
C
627 lines
14 KiB
C
/******************************************************************************
|
|
* biso_util.c
|
|
*
|
|
* Copyright (c) 2020, longpanda <admin@ventoy.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
|
|
#include "biso.h"
|
|
#include "biso_list.h"
|
|
#include "biso_util.h"
|
|
#include "biso_9660.h"
|
|
|
|
VOID *zalloc(size_t size)
|
|
{
|
|
void *p = malloc(size);
|
|
if (NULL != p)
|
|
{
|
|
memset(p, 0, size);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
|
|
#if (1 == MEMORY_DEBUG)
|
|
STATIC UINT g_uiBISOTotMalloc = 0;
|
|
STATIC UINT g_uiBISOPeekMalloc = 0;
|
|
STATIC UINT g_uiBISOMallocTime = 0;
|
|
STATIC UINT g_uiBISOFreeTime = 0;
|
|
|
|
VOID *g_apstBISOMalloc[7000];
|
|
VOID *g_apstBISOFree[7000];
|
|
|
|
VOID * BISO_UTIL_Malloc(IN size_t ulSize)
|
|
{
|
|
VOID *pData = malloc(ulSize + 4);
|
|
|
|
#if (1 == MEMORY_DEBUG_DUMP)
|
|
printf("ID %u Malloc %p %lu\n", g_uiBISOMallocTime, (UCHAR *)pData + 4, ulSize);
|
|
g_apstBISOMalloc[g_uiBISOMallocTime] = (UCHAR *)pData + 4;
|
|
#endif
|
|
|
|
*(UINT32 *)pData = (UINT32)ulSize;
|
|
g_uiBISOMallocTime++;
|
|
g_uiBISOTotMalloc += (UINT32)ulSize;
|
|
if (g_uiBISOTotMalloc > g_uiBISOPeekMalloc)
|
|
{
|
|
g_uiBISOPeekMalloc = g_uiBISOTotMalloc;
|
|
}
|
|
|
|
return (UCHAR *)pData + 4;
|
|
}
|
|
|
|
VOID *BISO_UTIL_Zalloc(IN size_t ulSize)
|
|
{
|
|
VOID *pData = zalloc(ulSize + 4);
|
|
|
|
#if (1 == MEMORY_DEBUG_DUMP)
|
|
printf("ID %u Zalloc %p %lu\n", g_uiBISOMallocTime, (UCHAR *)pData + 4, ulSize);
|
|
g_apstBISOMalloc[g_uiBISOMallocTime] = (UCHAR *)pData + 4;
|
|
#endif
|
|
|
|
*(UINT32 *)pData = (UINT32)ulSize;
|
|
g_uiBISOMallocTime++;
|
|
g_uiBISOTotMalloc += (UINT32)ulSize;
|
|
if (g_uiBISOTotMalloc > g_uiBISOPeekMalloc)
|
|
{
|
|
g_uiBISOPeekMalloc = g_uiBISOTotMalloc;
|
|
}
|
|
|
|
return (UCHAR *)pData + 4;
|
|
}
|
|
|
|
VOID BISO_UTIL_Free(IN VOID *pData)
|
|
{
|
|
#if (1 == MEMORY_DEBUG_DUMP)
|
|
printf("ID %u Free %p %u\n", g_uiBISOFreeTime, pData, *(UINT32 *)((UCHAR *)pData - 4));
|
|
g_apstBISOFree[g_uiBISOFreeTime] = pData;
|
|
#endif
|
|
|
|
g_uiBISOFreeTime++;
|
|
g_uiBISOTotMalloc -= *(UINT32 *)((UCHAR *)pData - 4);
|
|
if (g_uiBISOTotMalloc > g_uiBISOPeekMalloc)
|
|
{
|
|
g_uiBISOPeekMalloc = g_uiBISOTotMalloc;
|
|
}
|
|
|
|
free((UCHAR *)pData - 4);
|
|
}
|
|
|
|
VOID BISO_UTIL_DumpMemOp(VOID)
|
|
{
|
|
BISO_DUMP("\n Memory Operation: Malloc(%u) Free(%u) \nTotal current use %u, Peek memory use %u.\n",
|
|
g_uiBISOMallocTime, g_uiBISOFreeTime, g_uiBISOTotMalloc, g_uiBISOPeekMalloc);
|
|
|
|
#if (1 == MEMORY_DEBUG_DUMP)
|
|
{
|
|
UINT i, j;
|
|
for (i = 0; i < g_uiBISOMallocTime; i++)
|
|
{
|
|
for (j = 0; j < g_uiBISOFreeTime; j++)
|
|
{
|
|
if (g_apstBISOMalloc[i] == g_apstBISOFree[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j >= g_uiBISOFreeTime)
|
|
{
|
|
printf("ID %u ptr %p is not freed.\n", i, g_apstBISOMalloc[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
INT BISO_UTIL_GetTimeZone(VOID)
|
|
{
|
|
INT iTimeZone;
|
|
INT iLocalHour;
|
|
INT iGMTHour;
|
|
time_t ulTime;
|
|
struct tm *pstLocalTM = NULL;
|
|
struct tm *pstGMTM = NULL;
|
|
|
|
time(&ulTime);
|
|
pstGMTM = gmtime(&ulTime);
|
|
iGMTHour = pstGMTM->tm_hour;
|
|
|
|
pstLocalTM = localtime(&ulTime);
|
|
iLocalHour = pstLocalTM->tm_hour;
|
|
|
|
iTimeZone = iLocalHour - iGMTHour;
|
|
if (iTimeZone < -12)
|
|
{
|
|
iTimeZone += 24;
|
|
}
|
|
else if (iTimeZone > 12)
|
|
{
|
|
iTimeZone -= 24;
|
|
}
|
|
|
|
return iTimeZone;
|
|
}
|
|
|
|
ULONG BISO_UTIL_ReadFile
|
|
(
|
|
IN CONST CHAR *pcFileName,
|
|
IN UINT64 ui64Seek,
|
|
IN UINT uiDataLen,
|
|
OUT VOID *pDataBuf
|
|
)
|
|
{
|
|
UINT uiReadLen = 0;
|
|
BISO_FILE_S *pstFile = NULL;
|
|
|
|
if ((NULL == pcFileName) || (NULL == pDataBuf))
|
|
{
|
|
return BISO_ERR_NULL_PTR;
|
|
}
|
|
|
|
pstFile = BISO_PLAT_OpenExistFile(pcFileName);
|
|
if (NULL == pstFile)
|
|
{
|
|
return BISO_ERR_OPEN_FILE;
|
|
}
|
|
|
|
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
|
|
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, uiDataLen, pDataBuf);
|
|
if (uiReadLen != uiDataLen)
|
|
{
|
|
BISO_DIAG("Read Len %u, data len %u.", uiReadLen, uiDataLen);
|
|
BISO_PLAT_CloseFile(pstFile);
|
|
return BISO_ERR_READ_FILE;
|
|
}
|
|
|
|
BISO_PLAT_CloseFile(pstFile);
|
|
return BISO_SUCCESS;
|
|
}
|
|
|
|
|
|
CHAR * BISO_UTIL_CopyStr
|
|
(
|
|
IN CONST CHAR *szSrc,
|
|
IN UINT uiSrcSize,
|
|
OUT CHAR *szDest
|
|
)
|
|
{
|
|
UINT i;
|
|
UINT uiAllSpace = 1;
|
|
|
|
for (i = uiSrcSize; i > 0; i--)
|
|
{
|
|
if ((0 != szSrc[i - 1]) && (' ' != szSrc[i - 1]))
|
|
{
|
|
uiAllSpace = 0;
|
|
break;
|
|
}
|
|
|
|
if (' ' != szSrc[i - 1])
|
|
{
|
|
uiAllSpace = 0;
|
|
}
|
|
}
|
|
|
|
if (i > 0)
|
|
{
|
|
memcpy(szDest, szSrc, i);
|
|
}
|
|
szDest[i] = 0;
|
|
|
|
if (uiAllSpace == 1)
|
|
{
|
|
scnprintf(szDest, uiSrcSize, "*All Space*"); /* no safe */
|
|
}
|
|
|
|
if (szDest[0] == 0)
|
|
{
|
|
scnprintf(szDest, uiSrcSize, "*Empty*"); /* no safe */
|
|
}
|
|
|
|
return szDest;
|
|
}
|
|
|
|
CHAR * BISO_UTIL_CopyUCS2Str
|
|
(
|
|
IN CONST CHAR *szSrc,
|
|
IN UINT uiSrcSize,
|
|
OUT CHAR *szDest
|
|
)
|
|
{
|
|
UINT i;
|
|
|
|
memcpy(szDest, szSrc, uiSrcSize);
|
|
|
|
for (i = 0; (i * 2 + 1) < uiSrcSize; i++)
|
|
{
|
|
szDest[i] = szDest[i * 2 + 1];
|
|
}
|
|
szDest[i] = 0;
|
|
|
|
return szDest;
|
|
}
|
|
|
|
VOID BISO_UTIL_PathProc(INOUT CHAR *pcPath, INOUT UINT *puiLen)
|
|
{
|
|
UINT i;
|
|
|
|
if ((NULL == pcPath) || (NULL == puiLen) || (0 == *puiLen))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* 把所有的\替换为/ */
|
|
for (i = 0; i < *puiLen; i++)
|
|
{
|
|
if ('\\' == pcPath[i])
|
|
{
|
|
pcPath[i] = '/';
|
|
}
|
|
}
|
|
|
|
/* 确保最后有1个/ */
|
|
if ('/' != pcPath[*puiLen - 1])
|
|
{
|
|
pcPath[(*puiLen)++] = '/';
|
|
pcPath[*puiLen] = 0;
|
|
}
|
|
}
|
|
|
|
ULONG BISO_UTIL_PathSplit
|
|
(
|
|
IN CONST CHAR *pcFullPath,
|
|
OUT UINT *puiDirNum,
|
|
OUT UINT *puiDirPos
|
|
)
|
|
{
|
|
USHORT usPos = 0;
|
|
USHORT usLen = 0;
|
|
UINT uiDirNum = 0;
|
|
CONST CHAR *pcLastPos = pcFullPath;
|
|
CONST CHAR *pcCurPos = pcFullPath;
|
|
|
|
DBGASSERT(NULL != pcFullPath);
|
|
DBGASSERT(NULL != puiDirNum);
|
|
DBGASSERT(NULL != puiDirPos);
|
|
|
|
while (*pcCurPos)
|
|
{
|
|
if (('/' == *pcCurPos) || ('\\' == *pcCurPos))
|
|
{
|
|
usPos = pcLastPos - pcFullPath;
|
|
usLen = pcCurPos - pcLastPos;
|
|
if (usLen <= 0)
|
|
{
|
|
return BISO_ERR_FAILED;
|
|
}
|
|
|
|
puiDirPos[uiDirNum] = (UINT)((UINT)usPos << 16) | usLen;
|
|
|
|
uiDirNum++;
|
|
pcLastPos = pcCurPos + 1;
|
|
}
|
|
|
|
pcCurPos++;
|
|
}
|
|
|
|
usPos = pcLastPos - pcFullPath;
|
|
usLen = pcCurPos - pcLastPos;
|
|
if (usLen <= 0)
|
|
{
|
|
return BISO_ERR_FAILED;
|
|
}
|
|
puiDirPos[uiDirNum++] = (UINT)((UINT)usPos << 16) | usLen;
|
|
|
|
*puiDirNum = uiDirNum;
|
|
return BISO_SUCCESS;
|
|
}
|
|
|
|
BISO_DIR_TREE_S * BISO_UTIL_FindLinkTgt(IN BISO_DIR_TREE_S *pstCurNode)
|
|
{
|
|
UINT i = 0;
|
|
UINT uiDirNum = 0;
|
|
UINT auiDirPos[32];
|
|
CHAR szDirName[1024];
|
|
USHORT usPos = 0;
|
|
USHORT usLen = 0;
|
|
CHAR *pcLink = NULL;
|
|
BISO_DIR_TREE_S *pstFileList = NULL;
|
|
BISO_DIR_TREE_S *pstRootDir = NULL;
|
|
|
|
DBGASSERT(NULL != pstCurNode);
|
|
|
|
/* 如果不是符号链接则返回自己 */
|
|
if (BOOL_TRUE != BISO_DIR_TREE_IS_SYMLINK(pstCurNode))
|
|
{
|
|
return pstCurNode;
|
|
}
|
|
|
|
pcLink = pstCurNode->pstPosixInfo->pcLinkSrc;
|
|
|
|
if ('/' == pcLink[0])
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* 把链接分割开 */
|
|
if (BISO_SUCCESS != BISO_UTIL_PathSplit(pcLink, &uiDirNum, auiDirPos))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pstRootDir = pstCurNode->pstParent;
|
|
|
|
/* 依次查找每一部分目录 */
|
|
for (i = 0; (i < uiDirNum) && (NULL != pstCurNode)&& (NULL != pstRootDir); i++)
|
|
{
|
|
usPos = auiDirPos[i] >> 16;
|
|
usLen = auiDirPos[i] & 0xFF;
|
|
|
|
memcpy(szDirName, pcLink + usPos, usLen);
|
|
szDirName[usLen] = 0;
|
|
|
|
if (0 == BISO_PATH_STRCMP(szDirName, "."))
|
|
{
|
|
pstCurNode = pstCurNode->pstParent;
|
|
}
|
|
else if (0 == BISO_PATH_STRCMP(szDirName, ".."))
|
|
{
|
|
if (NULL == pstCurNode->pstParent)
|
|
{
|
|
return NULL;
|
|
}
|
|
pstCurNode = pstCurNode->pstParent->pstParent;
|
|
pstRootDir = pstCurNode;
|
|
}
|
|
else
|
|
{
|
|
pstCurNode = pstRootDir->pstChild;
|
|
pstFileList = pstRootDir->pstFileList;
|
|
|
|
/* 先找当前所在目录下的文件夹 */
|
|
while (pstCurNode)
|
|
{
|
|
if (0 == BISO_PATH_STRCMP(pstCurNode->szName, szDirName))
|
|
{
|
|
pstRootDir = pstCurNode;
|
|
break;
|
|
}
|
|
pstCurNode = pstCurNode->pstNext;
|
|
}
|
|
|
|
/* 文件夹找不到就找文件 */
|
|
if (NULL == pstCurNode)
|
|
{
|
|
pstCurNode = pstFileList;
|
|
while (pstCurNode)
|
|
{
|
|
if (0 == BISO_PATH_STRCMP(pstCurNode->szName, szDirName))
|
|
{
|
|
pstRootDir = NULL;
|
|
break;
|
|
}
|
|
pstCurNode = pstCurNode->pstNext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return pstCurNode;
|
|
}
|
|
|
|
ULONG BISO_MBUF_Append
|
|
(
|
|
IN BISO_MBUF_S *pstMBuf,
|
|
IN UINT uiDataSize,
|
|
IN VOID *pData
|
|
)
|
|
{
|
|
if ((NULL == pstMBuf) || (pstMBuf->uiCurBufNum >= BISO_MBUF_MAX_BLK))
|
|
{
|
|
return BISO_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
pstMBuf->apucDataBuf[pstMBuf->uiCurBufNum] = (UCHAR *)BISO_MALLOC(uiDataSize);
|
|
if (NULL == pstMBuf->apucDataBuf[pstMBuf->uiCurBufNum])
|
|
{
|
|
return BISO_ERR_ALLOC_MEM;
|
|
}
|
|
|
|
if (NULL == pData)
|
|
{
|
|
memset(pstMBuf->apucDataBuf[pstMBuf->uiCurBufNum], 0, uiDataSize);
|
|
}
|
|
else
|
|
{
|
|
memcpy(pstMBuf->apucDataBuf[pstMBuf->uiCurBufNum], pData, uiDataSize);
|
|
}
|
|
|
|
pstMBuf->auiBufSize[pstMBuf->uiCurBufNum] = uiDataSize;
|
|
pstMBuf->uiTotDataSize += uiDataSize;
|
|
pstMBuf->uiCurBufNum++;
|
|
|
|
return BISO_SUCCESS;
|
|
}
|
|
|
|
VOID BISO_MBUF_Free(IN BISO_MBUF_S *pstMBuf)
|
|
{
|
|
UINT i;
|
|
if (NULL != pstMBuf)
|
|
{
|
|
for (i = 0; i < pstMBuf->uiCurBufNum; i++)
|
|
{
|
|
BISO_FREE(pstMBuf->apucDataBuf[i]);
|
|
}
|
|
memset(pstMBuf, 0, sizeof(BISO_MBUF_S));
|
|
}
|
|
}
|
|
|
|
VOID BISO_MBUF_CopyToBuf(IN CONST BISO_MBUF_S *pstMBuf, OUT VOID *pDataBuf)
|
|
{
|
|
UINT i;
|
|
UCHAR *pucDataBuf = (UCHAR *)pDataBuf;
|
|
|
|
if ((NULL != pstMBuf) && (NULL != pucDataBuf))
|
|
{
|
|
for (i = 0; i < pstMBuf->uiCurBufNum; i++)
|
|
{
|
|
if (NULL != pstMBuf->apucDataBuf[i])
|
|
{
|
|
memcpy(pucDataBuf, pstMBuf->apucDataBuf[i], pstMBuf->auiBufSize[i]);
|
|
pucDataBuf += pstMBuf->auiBufSize[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID BISO_MBUF_PULLUP(INOUT BISO_MBUF_S *pstMBuf)
|
|
{
|
|
UINT uiSize = 0;
|
|
VOID *pData = NULL;
|
|
|
|
DBGASSERT(NULL != pstMBuf);
|
|
|
|
if (pstMBuf->uiCurBufNum <= 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
uiSize = pstMBuf->uiTotDataSize;
|
|
pData = BISO_MALLOC(uiSize);
|
|
if (NULL == pData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BISO_MBUF_CopyToBuf(pstMBuf, pData);
|
|
BISO_MBUF_Free(pstMBuf);
|
|
|
|
memset(pstMBuf, 0, sizeof(BISO_MBUF_S));
|
|
pstMBuf->apucDataBuf[0] = (UCHAR *)pData;
|
|
pstMBuf->auiBufSize[0] = uiSize;
|
|
pstMBuf->uiTotDataSize = uiSize;
|
|
pstMBuf->uiCurBufNum = 1;
|
|
|
|
return;
|
|
}
|
|
|
|
BISO_QUEUE_S * BISO_QUEUE_Create(VOID)
|
|
{
|
|
BISO_DLL_S *pstSLL = (BISO_DLL_S *)BISO_ZALLOC(sizeof(BISO_DLL_S));
|
|
if (NULL != pstSLL)
|
|
{
|
|
BISO_DLL_Init(pstSLL);
|
|
}
|
|
return (BISO_QUEUE_S *)pstSLL;
|
|
}
|
|
|
|
VOID BISO_QUEUE_Destroy(IN BISO_QUEUE_S *pstQueue)
|
|
{
|
|
BISO_DLL_Free(pstQueue);
|
|
BISO_FREE(pstQueue);
|
|
}
|
|
|
|
VOID BISO_QUEUE_Push(IN BISO_QUEUE_S *pstQueue, IN VOID *pData)
|
|
{
|
|
BISO_QUEUE_NODE_S *pstNode = NULL;
|
|
|
|
pstNode = (BISO_QUEUE_NODE_S *)BISO_DLL_Last(pstQueue);
|
|
|
|
/* 当前节点已满需要扩展新内存节点 */
|
|
if ((NULL == pstNode) || (BISO_QUEUE_PTR_NUM == pstNode->usLast))
|
|
{
|
|
pstNode = (BISO_QUEUE_NODE_S *)BISO_ZALLOC(sizeof(BISO_QUEUE_NODE_S));
|
|
if (NULL == pstNode)
|
|
{
|
|
return;
|
|
}
|
|
BISO_DLL_AddTail(pstQueue, (BISO_DLL_NODE_S *)pstNode);
|
|
}
|
|
|
|
/* Last往前走一步 */
|
|
pstNode = (BISO_QUEUE_NODE_S *)BISO_DLL_Last(pstQueue);
|
|
pstNode->apList[pstNode->usLast++] = pData;
|
|
}
|
|
|
|
VOID * BISO_QUEUE_PopHead(IN BISO_QUEUE_S *pstQueue)
|
|
{
|
|
VOID *pData = NULL;
|
|
BISO_QUEUE_NODE_S *pstNode = NULL;
|
|
|
|
pstNode = (BISO_QUEUE_NODE_S *)BISO_DLL_First(pstQueue);
|
|
if (NULL == pstNode)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* First往前走一步 */
|
|
pData = pstNode->apList[pstNode->usFirst++];
|
|
|
|
/* 该节点已空,则摘除节点,释放内存 */
|
|
if (pstNode->usFirst == pstNode->usLast)
|
|
{
|
|
BISO_DLL_DelHead(pstQueue);
|
|
BISO_FREE(pstNode);
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
VOID * BISO_QUEUE_PopTail(IN BISO_QUEUE_S *pstQueue)
|
|
{
|
|
VOID *pData = NULL;
|
|
BISO_QUEUE_NODE_S *pstNode = NULL;
|
|
|
|
pstNode = (BISO_QUEUE_NODE_S *)BISO_DLL_Last(pstQueue);
|
|
if ((NULL == pstNode) || (0 == pstNode->usLast))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Last往后退一步 */
|
|
pstNode->usLast--;
|
|
pData = pstNode->apList[pstNode->usLast];
|
|
|
|
/* 该节点已空,则摘除节点,释放内存 */
|
|
if (pstNode->usFirst == pstNode->usLast)
|
|
{
|
|
BISO_DLL_DelTail(pstQueue);
|
|
BISO_FREE(pstNode);
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
UINT64 BISO_UTIL_WholeFile2Buf(IN CONST CHAR *szFileName, OUT UCHAR *pucBuf)
|
|
{
|
|
UINT uiFileSize;
|
|
UINT uiReadSize;
|
|
BISO_FILE_S *pstFile = BISO_PLAT_OpenExistFile(szFileName);
|
|
|
|
uiFileSize = BISO_PLAT_GetFileSize(szFileName);
|
|
uiReadSize = BISO_PLAT_ReadFile(pstFile, 1, uiFileSize, pucBuf);
|
|
|
|
BISO_PLAT_CloseFile(pstFile);
|
|
|
|
return uiReadSize;
|
|
}
|
|
|
|
|