Ventoy/VtoyTool/BabyISO/biso_9660.c

1459 lines
43 KiB
C
Raw Normal View History

2020-04-04 16:07:50 +00:00
/******************************************************************************
* biso_9660.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_plat.h"
#include "biso_9660.h"
#include "biso_eltorito.h"
#include "biso_rockridge.h"
#include "biso_dump.h"
STATIC ULONG BISO_9660_ReadPathTable(IN BISO_FILE_S *pstFile, OUT BISO_PARSER_S *pstParser)
{
UINT64 ui64Seek = 0;
UINT uiReadLen = 0;
UCHAR *pucBuf = NULL;
BISO_PVD_S *pstPVD = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
pstPVD = pstParser->pstPVD;
ui64Seek = BISO_PATHTBL_LOCATION(pstPVD);
ui64Seek = ui64Seek * BISO_BLOCK_SIZE;
/*
* Path Table
* Path Table是连续保存的使
* Path Table保存时是连续的Path Table可以跨block, 0
*/
pucBuf = (UCHAR *)BISO_MALLOC(pstPVD->uiPathTblSize);
if (NULL == pucBuf)
{
return BISO_ERR_ALLOC_MEM;
}
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
/* 读出Path Table */
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, pstPVD->uiPathTblSize, pucBuf);
if (uiReadLen != pstPVD->uiPathTblSize)
{
BISO_FREE(pucBuf);
BISO_DIAG("Read Len %u, data len %u.", uiReadLen, pstPVD->uiPathTblSize);
return BISO_ERR_READ_FILE;
}
pstParser->pucPathTable = pucBuf;
return BISO_SUCCESS;
}
/* 深度优先文件树目录节点入栈 注意这里只是针对目录节点入栈, 文件节点没有处理 */
VOID BISO_9660_FillDfsStack
(
IN BISO_DIR_TREE_S *pstTop,
INOUT BISO_QUEUE_S *pstQueue
)
{
BISO_DIR_TREE_S *pstCurDir = NULL;
DBGASSERT(NULL != pstTop);
DBGASSERT(NULL != pstQueue);
/* TOP入栈 */
BISO_QUEUE_Push(pstQueue, pstTop);
pstCurDir = pstTop->pstChild;
if (NULL == pstCurDir)
{
return;
}
for ( ; ; )
{
/*
* :
* 1.
* 2.
* 3. Next节点入栈
* 4. Parent的Next节点入栈
*/
BISO_QUEUE_Push(pstQueue, pstCurDir);
if (NULL != pstCurDir->pstChild)
{
pstCurDir = pstCurDir->pstChild;
}
else if (NULL != pstCurDir->pstNext)
{
pstCurDir = pstCurDir->pstNext;
}
else
{
/* 往上回溯, 一直找到需要入栈的节点 */
while ((pstTop != pstCurDir->pstParent) && (NULL == pstCurDir->pstParent->pstNext))
{
pstCurDir = pstCurDir->pstParent;
}
if (pstTop == pstCurDir->pstParent)
{
break;
}
pstCurDir = pstCurDir->pstParent->pstNext;
}
}
}
/* 根据Extent的值查找子目录节点 */
STATIC BISO_DIR_TREE_S *BISO_9660_FindChild
(
IN BISO_DIR_TREE_S *pstParent,
IN UINT uiChildExtent
)
{
BISO_DIR_TREE_S *pstCurNode = NULL;
DBGASSERT(NULL != pstParent);
pstCurNode = pstParent->pstChild;
while (NULL != pstCurNode)
{
if (pstCurNode->uiExtent == uiChildExtent)
{
return pstCurNode;
}
pstCurNode = pstCurNode->pstNext;
}
return NULL;
}
STATIC ULONG BISO_9660_ReadVD(IN BISO_FILE_S *pstFile, OUT BISO_PARSER_S *pstParser)
{
UINT uiReadLen = 0;
BISO_VD_S stVolDesc;
BISO_VD_NODE_S *pstVdNode = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
/* 标准规定前16个逻辑扇区用来保存系统数据VD信息从第17个扇区开始 */
BISO_PLAT_SeekFile(pstFile, BISO_SYSTEM_AREA_SIZE, SEEK_SET);
do
{
/* 每次读取1个VD结构 */
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stVolDesc), &stVolDesc);
if (uiReadLen != sizeof(stVolDesc))
{
BISO_DIAG("Read Len %u, struct len %u.", uiReadLen, (UINT)sizeof(stVolDesc));
return BISO_ERR_READ_FILE;
}
/* 根据ID检验是否是合法的ISO-9660格式 */
if (0 != strncmp(stVolDesc.szId, BISO_VD_ID, strlen(BISO_VD_ID)))
{
BISO_DIAG("Invalid cdid: %02x %02x %02x %02x %02x\n",
(UCHAR)stVolDesc.szId[0], (UCHAR)stVolDesc.szId[1],
(UCHAR)stVolDesc.szId[2], (UCHAR)stVolDesc.szId[3],
(UCHAR)stVolDesc.szId[4]);
return BISO_ERR_INVALID_ISO9660;
}
/* 申请内存保存VD信息 */
pstVdNode = (BISO_VD_NODE_S *)BISO_ZALLOC(sizeof(BISO_VD_NODE_S));
if (NULL == pstVdNode)
{
return BISO_ERR_ALLOC_MEM;
}
/* 链表节点挂接 */
memcpy(&(pstVdNode->stVD), &stVolDesc, sizeof(BISO_VD_S));
BISO_DLL_AddTail(&(pstParser->stVDList), (BISO_DLL_NODE_S *)pstVdNode);
switch (stVolDesc.ucType)
{
case BISO_VD_TYPE_BOOT:
{
pstParser->pstBVD = (BISO_BVD_S *)&(pstVdNode->stVD);
pstParser->pstBVD->uiBootCatlogStart = BISO_LTOH_UINT(pstParser->pstBVD->uiBootCatlogStart);
break;
}
case BISO_VD_TYPE_PVD:
{
pstParser->pstPVD = (BISO_PVD_S *)&(pstVdNode->stVD);
break;
}
case BISO_VD_TYPE_SVD:
{
pstParser->pstSVD = (BISO_SVD_S *)&(pstVdNode->stVD);
break;
}
case BISO_VD_TYPE_PART:
case BISO_VD_TYPE_END:
{
break;
}
default :
{
BISO_DIAG("Invalid VD type: %u\n", stVolDesc.ucType);
return BISO_ERR_INVALID_ISO9660;
}
}
} while (BISO_VD_TYPE_END != stVolDesc.ucType);
/* 标准规定必须有1个主卷描述符 */
if (NULL == pstParser->pstPVD)
{
BISO_DIAG("No PVD found.");
return BISO_ERR_INVALID_ISO9660;
}
/* 目前只支持逻辑块大小为2048 */
if (BISO_BLOCK_SIZE != pstParser->pstPVD->usBlockSize)
{
BISO_DIAG("Unsupported block size %u.", pstParser->pstPVD->usBlockSize);
return BISO_ERR_UNSUPPORTED_BLKSIZE;
}
return BISO_SUCCESS;
}
STATIC UCHAR * BISO_9660_ReadDirRecord
(
IN BISO_FILE_S *pstFile,
IN UINT uiExtent,
OUT UINT *puiSize
)
{
UINT64 ui64Seek = 0;
UINT uiReadLen = 0;
UCHAR *pucBuf = NULL;
BISO_DIR_RECORD_S stCurrent;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != puiSize);
/* 第一条Dir Record是Current, 先读出自己,得到总的缓冲区长度 */
ui64Seek = BISO_BLOCK_SIZE * (UINT64)uiExtent;
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stCurrent), &stCurrent);
if (uiReadLen != sizeof(stCurrent))
{
BISO_DIAG("Read len %u, buf len %u.", uiReadLen, (UINT)sizeof(stCurrent));
return NULL;
}
/* 申请内存, 一次性把当前目录的Directory信息全部读出 */
pucBuf = (UCHAR *)BISO_MALLOC(stCurrent.uiSize);
if (NULL == pucBuf)
{
return NULL;
}
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, stCurrent.uiSize, pucBuf);
if (uiReadLen != stCurrent.uiSize)
{
BISO_DIAG("Read len %u, buf len %u.", uiReadLen, stCurrent.uiSize);
BISO_FREE(pucBuf);
return NULL;
}
*puiSize = stCurrent.uiSize;
return pucBuf;
}
STATIC BISO_DIR_TREE_S * BISO_9660_CreateDirNode
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
INOUT BISO_DIR_TREE_S *pstPre,
INOUT BISO_DIR_TREE_S *pstParent
)
{
BISO_DIR_TREE_S *pstNew = NULL;
DBGASSERT(NULL != pstRecord);
DBGASSERT(NULL != pstPre);
DBGASSERT(NULL != pstParent);
/* 申请内存用于保存目录节点 */
pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
if (NULL == pstNew)
{
return NULL;
}
/* 目录节点属性赋值 */
BISO_UTIL_CopyStr(pstRecord->szName, pstRecord->ucNameLen, pstNew->szName);
pstNew->uiExtent = pstRecord->uiExtent;
pstNew->usNameLen = (USHORT)strlen(pstNew->szName);
/* 申请统计信息的节点 */
pstNew->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
if (NULL == pstNew->pstDirStat)
{
BISO_FREE(pstNew);
return NULL;
}
/* 挂接到父目录下 */
if (NULL == pstPre)
{
pstParent->pstChild = pstNew;
}
else
{
pstPre->pstNext = pstNew;
}
pstNew->pstParent = pstParent;
/* 更新父目录统计 */
pstParent->pstDirStat->uiCurDirNum++;
/* 更新目录的Rock Ridge扩展信息 */
(VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstRecord, pstNew);
return pstNew;
}
STATIC BISO_SVD_DIR_TREE_S * BISO_9660_CreateSVDDirNode
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
INOUT BISO_SVD_DIR_TREE_S *pstPre,
INOUT BISO_SVD_DIR_TREE_S *pstParent
)
{
BISO_SVD_DIR_TREE_S *pstNew = NULL;
DBGASSERT(NULL != pstRecord);
DBGASSERT(NULL != pstPre);
DBGASSERT(NULL != pstParent);
/* 申请内存用于保存目录节点 */
pstNew = (BISO_SVD_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S));
if (NULL == pstNew)
{
return NULL;
}
/* 目录节点属性赋值 */
pstNew->uiExtent = pstRecord->uiExtent;
/* 挂接到父目录下 */
if (NULL == pstPre)
{
pstParent->pstChild = pstNew;
}
else
{
pstPre->pstNext = pstNew;
}
pstNew->pstParent = pstParent;
return pstNew;
}
/* ISO原始文件格式处理 */
STATIC ULONG BISO_9660_ProcRawFileNameFmt(INOUT CHAR *szFileName, INOUT USHORT *pusLen)
{
UINT i;
UINT uiSepNum = 0;
UINT uiSepIndex = 0;
UINT uiDotNum = 0;
UINT uiLen = *pusLen;
for (i = 0; i < uiLen; i++)
{
if (szFileName[i] == ';')
{
if (uiSepNum > 0)
{
return BISO_SUCCESS;
}
uiSepNum++;
uiSepIndex = i;
}
else if (szFileName[i] == '.')
{
if (uiDotNum > 0)
{
return BISO_SUCCESS;
}
uiDotNum++;
}
else if (szFileName[i] >= 'a' && szFileName[i] <= 'z')
{
return BISO_SUCCESS;
}
}
/* 必须只包含1个分号和1个点号 */
if (uiSepNum != 1 || uiSepIndex == 0 || uiDotNum != 1)
{
return BISO_SUCCESS;
}
/* 分号后面是文件版本号, 纯数字 */
for (i = uiSepIndex + 1; i < uiLen; i++)
{
if (szFileName[i] < '0' || szFileName[i] > '9')
{
return BISO_SUCCESS;
}
}
/* 把分号后面剔除 */
szFileName[uiSepIndex] = 0;
uiLen = uiSepIndex;
/* 如果只有文件名没有扩展名则把最后的点号去掉 */
if (uiLen > 1 && szFileName[uiLen - 1] == '.')
{
szFileName[uiLen - 1] = 0;
uiLen--;
}
*pusLen = (USHORT)uiLen;
/* 转换为小写 */
for (i = 0; i < uiLen; i++)
{
if (szFileName[i] >= 'A' && szFileName[i] <= 'Z')
{
szFileName[i] = 'a' + (szFileName[i] - 'A');
}
}
return BISO_SUCCESS;
}
STATIC BISO_DIR_TREE_S * BISO_9660_CreateFileNode
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
INOUT BISO_DIR_TREE_S *pstPre,
INOUT BISO_DIR_TREE_S *pstParent
)
{
UINT uiSecNum = 0;
BISO_DIR_TREE_S *pstNew = NULL;
DBGASSERT(NULL != pstRecord);
DBGASSERT(NULL != pstPre);
DBGASSERT(NULL != pstParent);
/* 申请内存用于保存文件节点 */
pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
if (NULL == pstNew)
{
return NULL;
}
/* 目录节点属性赋值 */
BISO_UTIL_CopyStr(pstRecord->szName, pstRecord->ucNameLen, pstNew->szName);
pstNew->uiExtent = pstRecord->uiExtent;
pstNew->usNameLen = (USHORT)strlen(pstNew->szName);
pstNew->uiSize = pstRecord->uiSize;
/* 读取文件的Rock Ridge扩展信息 */
(VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstRecord, pstNew);
/* 更新文件所在目录的记录 */
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstNew))
{
pstParent->pstDirStat->uiCurLinkNum++;
}
else
{
uiSecNum = BISO_USED_SECTOR_NUM(pstNew->uiSize);
pstParent->pstDirStat->uiCurFileNum++;
pstParent->pstDirStat->uiCurUsedSec += uiSecNum;
pstParent->pstDirStat->ui64CurSpace += pstNew->uiSize;
}
/* 节点挂接到当前目录的FileList上 */
if (NULL == pstPre)
{
pstParent->pstFileList = pstNew;
}
else
{
pstPre->pstNext = pstNew;
}
pstNew->pstParent = pstParent;
if (NULL == pstNew->pstPosixInfo && pstNew->usNameLen > 2)
{
BISO_9660_ProcRawFileNameFmt(pstNew->szName, &pstNew->usNameLen);
}
return pstNew;
}
STATIC BISO_SVD_DIR_TREE_S * BISO_9660_CreateSVDFileNode
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
INOUT BISO_SVD_DIR_TREE_S *pstPre,
INOUT BISO_SVD_DIR_TREE_S *pstParent
)
{
BISO_SVD_DIR_TREE_S *pstNew = NULL;
DBGASSERT(NULL != pstRecord);
DBGASSERT(NULL != pstPre);
DBGASSERT(NULL != pstParent);
/* 申请内存用于保存文件节点 */
pstNew = (BISO_SVD_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S));
if (NULL == pstNew)
{
return NULL;
}
/* 目录节点属性赋值 */
pstNew->uiExtent = pstRecord->uiExtent;
pstNew->uiSize = pstRecord->uiSize;
/* 节点挂接到当前目录的FileList上 */
if (NULL == pstPre)
{
pstParent->pstFileList = pstNew;
}
else
{
pstPre->pstNext = pstNew;
}
pstNew->pstParent = pstParent;
return pstNew;
}
STATIC ULONG BISO_9660_BuildFileList
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
OUT BISO_DIR_TREE_S *pstDirTree
)
{
UINT uiTail = 0;
UINT uiBufSize = 0;
UINT uiTotSize = 0;
UCHAR *pucBuf = NULL;
BISO_DIR_TREE_S *pstPre = NULL;
BISO_DIR_TREE_S *pstNew = NULL;
BISO_DIR_TREE_S *pstChild = NULL;
BISO_DIR_RECORD_S *pstCurrent = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstDirTree);
/* 读取Directory Record记录 */
pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
if (NULL == pucBuf)
{
return BISO_ERR_ALLOC_MEM;
}
pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
pstChild = pstDirTree->pstChild;
while (uiTotSize < uiBufSize)
{
if (BOOL_TRUE != BISO_DIR_RECORD_IS_PATH(pstCurrent)) /* 只处理文件 */
{
/* 创建文件节点 */
pstNew = BISO_9660_CreateFileNode(pstFile, pstParser, pstCurrent, pstPre, pstDirTree);
if (NULL == pstNew)
{
BISO_FREE(pucBuf);
return BISO_ERR_ALLOC_MEM;
}
pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
+ ((ULONG)pstCurrent - (ULONG)pucBuf);
pstPre = pstNew;
}
else
{
/* 对于子目录在这里更新目录的Rock Ridge扩展信息 */
if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
(BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
{
/*
* Path Table里记录的子目录顺序来判断,
* .
* :
* Path Table里的子目录记录和Directory Record里面的子目录记录顺序是否一致!!!!
* ,, BISO_9660_FindChild一般情况下
*
*/
if (pstChild->uiExtent == pstCurrent->uiExtent)
{
pstNew = pstChild;
pstChild = pstChild->pstNext;
}
else
{
pstNew = BISO_9660_FindChild(pstDirTree, pstCurrent->uiExtent);
}
if (NULL != pstNew)
{
(VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstCurrent, pstNew);
}
}
}
uiTotSize += pstCurrent->ucLength;
pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
/*
* !!!!!!!!!!!!!!!!!!!!!!!!
* ISO-9660Directory Record记录不能跨逻辑块
* Directory Record的话这段区域就会废弃(0)
*/
if (0 == pstCurrent->ucLength)
{
uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
uiTotSize += uiTail;
pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
}
}
BISO_FREE(pucBuf);
return BISO_SUCCESS;
}
/* 通过PathTable构建目录树(只包含目录)
Path Table65535ISO文件只能读取前 65535 */
STATIC ULONG BISO_9660_BuildPathTree
(
IN BISO_FILE_S *pstFile,
INOUT BISO_PARSER_S *pstParser,
OUT UINT *puiTotDirNum
)
{
UINT uiTotDirNum = 0;
UINT uiPathTblId = 1;
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstNew = NULL;
BISO_DIR_TREE_S *pstPre = NULL;
BISO_DIR_TREE_S *pstDirTree = NULL;
BISO_PATH_TABLE_S *pstPathTable = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
DBGASSERT(NULL != puiTotDirNum);
/*
* ISO-9660Path Table的顺序实际上是文件树的一个广度优先遍历的形式
* 广使
*/
pstQueue = BISO_QUEUE_Create();
if (NULL == pstQueue)
{
return BISO_ERR_ALLOC_MEM;
}
/* ROOT根目录 */
pstPathTable = (BISO_PATH_TABLE_S *)(pstParser->pucPathTable);
pstDirTree = &(pstParser->stDirTree);
pstDirTree->uiPathTblId = 1;
pstDirTree->uiExtent = pstPathTable->uiExtent;
/* 申请统计信息的节点 */
pstDirTree->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
if (NULL == pstDirTree->pstDirStat)
{
return BISO_ERR_ALLOC_MEM;
}
/* 先把ROOT入队列 */
BISO_QUEUE_Push(pstQueue, pstDirTree);
pstPathTable = (BISO_PATH_TABLE_S *)((UCHAR *)pstPathTable + BISO_9660_PATH_LEN(pstPathTable));
/* 依次处理队列中的每一项直到队列读空 */
while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
/* 把该目录下的所有一级子目录读出来入队列 */
while ((USHORT)pstDirTree->uiPathTblId == pstPathTable->usParentDirNum)
{
/* 申请内存用于保存目录节点 */
pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
if (NULL == pstNew)
{
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
/* 目录节点属性赋值 */
BISO_UTIL_CopyStr(pstPathTable->szDirName, pstPathTable->ucDirNameLen, pstNew->szName);
pstNew->uiExtent = pstPathTable->uiExtent;
pstNew->usNameLen = (USHORT)strlen(pstNew->szName);
pstNew->uiPathTblId = (++uiPathTblId);
/* 申请统计信息的节点 */
pstNew->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
if (NULL == pstNew->pstDirStat)
{
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
/* 挂接到父目录下 */
if (NULL == pstDirTree->pstChild)
{
pstDirTree->pstChild = pstNew;
}
else
{
pstPre->pstNext = pstNew;
}
pstNew->pstParent = pstDirTree;
pstPre = pstNew;
pstDirTree->pstDirStat->uiCurDirNum++;
uiTotDirNum++;
BISO_QUEUE_Push(pstQueue, pstNew);
pstPathTable = (BISO_PATH_TABLE_S *)((UCHAR *)pstPathTable + BISO_9660_PATH_LEN(pstPathTable));
}
}
*puiTotDirNum = uiTotDirNum;
BISO_QUEUE_Destroy(pstQueue);
return BISO_SUCCESS;
}
/* 更新整个目录树的目录结构中文件总数、目录总数、总空间大小等信息 */
ULONG BISO_9660_UpdateTreeStat(INOUT BISO_DIR_TREE_S *pstRoot)
{
VOID *pData = NULL;
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstCurDir = NULL;
BISO_DIR_STAT_S *pstDirStat = NULL;
BISO_DIR_STAT_S *pstPreDirStat = NULL;
DBGASSERT(NULL != pstRoot);
pstQueue = BISO_QUEUE_Create();
if (NULL == pstQueue)
{
return BISO_ERR_ALLOC_MEM;
}
/* 构建DFS栈 */
BISO_9660_FillDfsStack(pstRoot, pstQueue);
/* 依次弹栈处理 */
while (NULL != (pData = BISO_QUEUE_PopTail(pstQueue)))
{
pstCurDir = (BISO_DIR_TREE_S *)pData;
pstDirStat = pstCurDir->pstDirStat;
/* 更新自己和父节点 */
pstDirStat->uiTotDirNum += pstDirStat->uiCurDirNum;
pstDirStat->uiTotFileNum += pstDirStat->uiCurFileNum;
pstDirStat->uiTotLinkNum += pstDirStat->uiCurLinkNum;
pstDirStat->ui64TotSpace += pstDirStat->ui64CurSpace;
pstDirStat->uiTotUsedSec += pstDirStat->uiCurUsedSec;
if (NULL != pstCurDir->pstParent) /* ROOT节点没有父节点 */
{
pstPreDirStat = pstCurDir->pstParent->pstDirStat;
pstPreDirStat->uiTotDirNum += pstDirStat->uiTotDirNum;
pstPreDirStat->uiTotFileNum += pstDirStat->uiTotFileNum;
pstPreDirStat->uiTotLinkNum += pstDirStat->uiCurLinkNum;
pstPreDirStat->ui64TotSpace += pstDirStat->ui64TotSpace;
pstPreDirStat->uiTotUsedSec += pstDirStat->uiTotUsedSec;
}
}
/* 销毁堆栈 */
BISO_QUEUE_Destroy(pstQueue);
return BISO_SUCCESS;
}
ULONG BISO_9660_UpdateNodeStat
(
IN BOOL_T bAdd,
IN CONST BISO_DIR_TREE_S *pstCurNode,
INOUT BISO_DIR_TREE_S *pstParent
)
{
UINT uiSecNum = 0;
BISO_DIR_TREE_S *pstCurDir = NULL;
BISO_DIR_STAT_S *pstCurStat = NULL;
BISO_DIR_STAT_S *pstPreStat = NULL;
BISO_DIR_STAT_S stExDirStat;
DBGASSERT(NULL != pstCurNode);
memset(&stExDirStat, 0, sizeof(stExDirStat));
pstPreStat = pstParent->pstDirStat;
if (NULL == pstCurNode->pstDirStat) /* 非目录 */
{
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstCurNode)) /* 符号链接 */
{
/* 更新当前目录链接数统计, 大小为0不用更新 */
BISO_STAT_UPDATE(bAdd, pstPreStat->uiCurLinkNum, 1);
stExDirStat.uiTotLinkNum = 1;
}
else
{
/* 更新当前目录的文件数,大小等 */
uiSecNum = BISO_USED_SECTOR_NUM(pstCurNode->uiSize);
BISO_STAT_UPDATE(bAdd, pstPreStat->uiCurFileNum, 1);
BISO_STAT_UPDATE(bAdd, pstPreStat->uiCurUsedSec, uiSecNum);
BISO_STAT_UPDATE(bAdd, pstPreStat->ui64CurSpace, pstCurNode->uiSize);
stExDirStat.uiTotFileNum = 1;
stExDirStat.ui64TotSpace = pstCurNode->uiSize;
stExDirStat.uiTotUsedSec = uiSecNum;
}
}
else
{
pstCurStat = pstCurNode->pstDirStat;
BISO_STAT_UPDATE(bAdd, pstPreStat->uiCurDirNum, 1); /* Current只需更新目录数 */
BISO_STAT_UPDATE(bAdd, pstPreStat->uiTotDirNum, pstCurStat->uiTotDirNum);
BISO_STAT_UPDATE(bAdd, pstPreStat->uiTotFileNum, pstCurStat->uiTotFileNum);
BISO_STAT_UPDATE(bAdd, pstPreStat->uiTotLinkNum, pstCurStat->uiTotLinkNum);
BISO_STAT_UPDATE(bAdd, pstPreStat->ui64TotSpace, pstCurStat->ui64TotSpace);
BISO_STAT_UPDATE(bAdd, pstPreStat->uiTotUsedSec, pstCurStat->uiTotUsedSec);
memcpy(&stExDirStat, pstCurStat, sizeof(stExDirStat)); /* 只会用到Total部分,不用Current部分 */
}
/* 依次更新上层目录的Total部分 */
pstCurDir = pstParent->pstParent;
while (NULL != pstCurDir)
{
pstCurStat = pstCurDir->pstDirStat;
BISO_STAT_UPDATE(bAdd, pstCurStat->uiTotDirNum, stExDirStat.uiTotDirNum);
BISO_STAT_UPDATE(bAdd, pstCurStat->uiTotFileNum, stExDirStat.uiTotFileNum);
BISO_STAT_UPDATE(bAdd, pstCurStat->uiTotLinkNum, stExDirStat.uiTotLinkNum);
BISO_STAT_UPDATE(bAdd, pstCurStat->ui64TotSpace, stExDirStat.ui64TotSpace);
BISO_STAT_UPDATE(bAdd, pstCurStat->uiTotUsedSec, stExDirStat.uiTotUsedSec);
pstCurDir = pstCurDir->pstParent;
}
return BISO_SUCCESS;
}
ULONG BISO_9660_BuildFileTreeByTable
(
IN BISO_FILE_S *pstFile,
OUT BISO_PARSER_S *pstParser
)
{
ULONG ulRet;
UINT uiTotDirNum = 0;
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstDirTree = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
/* 先通过Path Table构建目录树(不包含文件) */
ulRet = BISO_9660_BuildPathTree(pstFile, pstParser, &uiTotDirNum);
if (BISO_SUCCESS != ulRet)
{
return ulRet;
}
/* 构建每一个目录下的文件列表 */
/* 创建队列用于递归遍历 */
pstQueue = BISO_QUEUE_Create();
if (NULL == pstQueue)
{
return BISO_ERR_ALLOC_MEM;
}
/* ROOT目录入队列 */
BISO_QUEUE_Push(pstQueue, &(pstParser->stDirTree));
/* 循环依次构建 */
while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
/* 构建文件列表 */
ulRet = BISO_9660_BuildFileList(pstFile, pstParser, pstDirTree);
if (BISO_SUCCESS != ulRet)
{
BISO_DIAG("Failed to build file list for dir %s.", pstDirTree->szName);
BISO_QUEUE_Destroy(pstQueue);
return ulRet;
}
/* 子目录入队列 */
if (NULL != pstDirTree->pstChild)
{
BISO_QUEUE_Push(pstQueue, pstDirTree->pstChild);
}
/* 下一个相邻目录入队列 */
if (NULL != pstDirTree->pstNext)
{
BISO_QUEUE_Push(pstQueue, pstDirTree->pstNext);
}
}
BISO_QUEUE_Destroy(pstQueue);
return BISO_SUCCESS;
}
ULONG BISO_9660_BuildFileTreeRecursively
(
IN BISO_FILE_S *pstFile,
OUT BISO_PARSER_S *pstParser
)
{
UINT uiTail = 0;
UINT uiTotSize = 0;
UINT uiBufSize = 0;
UCHAR *pucBuf = NULL;
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstNew = NULL;
BISO_DIR_TREE_S *pstPreDir = NULL;
BISO_DIR_TREE_S *pstPreFile = NULL;
BISO_DIR_TREE_S *pstDirTree = NULL;
BISO_DIR_RECORD_S *pstCurrent = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
/* 先对ROOT进行处理 */
pstDirTree = &(pstParser->stDirTree);
pstDirTree->uiPathTblId = 1;
pstDirTree->uiExtent = pstParser->pstPVD->stRootDirRecord.uiExtent;
/* 申请统计信息的内存 */
pstDirTree->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
if (NULL == pstDirTree->pstDirStat)
{
return BISO_ERR_ALLOC_MEM;
}
/* 创建堆栈,同时ROOT入栈 */
pstQueue = BISO_QUEUE_Create();
BISO_QUEUE_Push(pstQueue, pstDirTree);
while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
uiTotSize = 0;
pstPreDir = NULL;
pstPreFile = NULL;
pstDirTree->uiPathTblId = BISO_UINT_MAX;
/* 读取Directory Record记录 */
pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
if (NULL == pucBuf)
{
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
while (uiTotSize < uiBufSize)
{
if (BOOL_TRUE == BISO_DIR_RECORD_IS_PATH(pstCurrent))
{
if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
(BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
{
/* 创建新目录节点 */
pstNew = BISO_9660_CreateDirNode(pstFile, pstParser, pstCurrent, pstPreDir, pstDirTree);
if (NULL == pstNew)
{
BISO_FREE(pucBuf);
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstPreDir = pstNew;
/* 新目录入栈 */
BISO_QUEUE_Push(pstQueue, pstNew);
}
}
else
{
pstNew = BISO_9660_CreateFileNode(pstFile, pstParser, pstCurrent, pstPreFile, pstDirTree);
if (NULL == pstNew)
{
BISO_FREE(pucBuf);
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
+ ((ULONG)pstCurrent - (ULONG)pucBuf);
pstPreFile = pstNew;
}
uiTotSize += pstCurrent->ucLength;
pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
/*
* !!!!!!!!!!!!!!!!!!!!!!!!
* ISO-9660Directory Record记录不能跨逻辑块
* Directory Record的话这段区域就会废弃(0)
*/
if (0 == pstCurrent->ucLength)
{
uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
uiTotSize += uiTail;
pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
}
}
BISO_FREE(pucBuf);
}
BISO_QUEUE_Destroy(pstQueue);
return BISO_SUCCESS;
}
ULONG BISO_9660_BuildSVDFileTreeRecursively
(
IN BISO_FILE_S *pstFile,
OUT BISO_PARSER_S *pstParser
)
{
UINT uiTail = 0;
UINT uiTotSize = 0;
UINT uiBufSize = 0;
UCHAR *pucBuf = NULL;
BISO_QUEUE_S *pstQueue = NULL;
BISO_SVD_DIR_TREE_S *pstNew = NULL;
BISO_SVD_DIR_TREE_S *pstPreDir = NULL;
BISO_SVD_DIR_TREE_S *pstPreFile = NULL;
BISO_SVD_DIR_TREE_S *pstDirTree = NULL;
BISO_DIR_RECORD_S *pstCurrent = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
/* 先对ROOT进行处理 */
pstDirTree = &(pstParser->stSVDDirTree);
pstDirTree->uiExtent = pstParser->pstSVD->stRootDirRecord.uiExtent;
/* 创建堆栈,同时ROOT入栈 */
pstQueue = BISO_QUEUE_Create();
BISO_QUEUE_Push(pstQueue, pstDirTree);
while (NULL != (pstDirTree = (BISO_SVD_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
uiTotSize = 0;
pstPreDir = NULL;
pstPreFile = NULL;
/* 读取Directory Record记录 */
pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
if (NULL == pucBuf)
{
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
while (uiTotSize < uiBufSize)
{
if (BOOL_TRUE == BISO_DIR_RECORD_IS_PATH(pstCurrent))
{
if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
(BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
{
/* 创建新目录节点 */
pstNew = BISO_9660_CreateSVDDirNode(pstFile, pstParser, pstCurrent, pstPreDir, pstDirTree);
if (NULL == pstNew)
{
BISO_FREE(pucBuf);
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstPreDir = pstNew;
/* 新目录入栈 */
BISO_QUEUE_Push(pstQueue, pstNew);
}
}
else
{
pstNew = BISO_9660_CreateSVDFileNode(pstFile, pstParser, pstCurrent, pstPreFile, pstDirTree);
if (NULL == pstNew)
{
BISO_FREE(pucBuf);
BISO_QUEUE_Destroy(pstQueue);
return BISO_ERR_ALLOC_MEM;
}
pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
+ ((ULONG)pstCurrent - (ULONG)pucBuf);
pstPreFile = pstNew;
}
uiTotSize += pstCurrent->ucLength;
pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
/*
* !!!!!!!!!!!!!!!!!!!!!!!!
* ISO-9660Directory Record记录不能跨逻辑块
* Directory Record的话这段区域就会废弃(0)
*/
if (0 == pstCurrent->ucLength)
{
uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
uiTotSize += uiTail;
pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
}
}
BISO_FREE(pucBuf);
}
BISO_QUEUE_Destroy(pstQueue);
return BISO_SUCCESS;
}
VOID BISO_9660_FreeDirTree(IN BISO_PARSER_S *pstParser)
{
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstRoot = NULL;
BISO_DIR_TREE_S *pstCurDir = NULL;
BISO_DIR_TREE_S *pstPre = NULL;
BISO_DIR_TREE_S *pstNext = NULL;
if (NULL == pstParser)
{
return;
}
/* 创建队列 */
pstQueue = BISO_QUEUE_Create();
if (NULL == pstQueue)
{
return;
}
pstRoot = &pstParser->stDirTree;
/* 构建文件树入栈 */
BISO_9660_FillDfsStack(pstRoot, pstQueue);
/* 不需要释放ROOT,把它从队列头弹出来 */
BISO_QUEUE_PopHead(pstQueue);
/* 依次释放各个节点 */
while (NULL != (pstCurDir = (BISO_DIR_TREE_S *)BISO_QUEUE_PopTail(pstQueue)))
{
/* 释放当前目录的文件列表 */
for (pstPre = pstCurDir->pstFileList; NULL != pstPre; pstPre = pstNext)
{
pstNext = pstPre->pstNext;
BISO_9600_FREE_DIRTREE(pstPre);
}
/* 释放自己 */
BISO_9600_FREE_DIRTREE(pstCurDir);
}
/* 释放ROOT目录的文件列表 */
for (pstPre = pstRoot->pstFileList; NULL != pstPre; pstPre = pstNext)
{
pstNext = pstPre->pstNext;
BISO_9600_FREE_DIRTREE(pstPre);
}
/* 释放ROOT自己的扩展信息,但不释放自己本身 */
BISO_9600_FREE_STAT(pstRoot);
BISO_9600_FREE_POSIX(pstRoot);
/* 销毁队列 */
BISO_QUEUE_Destroy(pstQueue);
}
VOID BISO_9660_FreeSVDDirTree(IN BISO_PARSER_S *pstParser)
{
BISO_QUEUE_S *pstQueue = NULL;
BISO_SVD_DIR_TREE_S *pstRoot = NULL;
BISO_SVD_DIR_TREE_S *pstCurDir = NULL;
BISO_SVD_DIR_TREE_S *pstPre = NULL;
BISO_SVD_DIR_TREE_S *pstNext = NULL;
if (NULL == pstParser ||
0 == pstParser->stSVDDirTree.uiExtent ||
0 == pstParser->stSVDDirTree.uiSize)
{
return;
}
/* 创建队列 */
pstQueue = BISO_QUEUE_Create();
if (NULL == pstQueue)
{
return;
}
pstRoot = &pstParser->stSVDDirTree;
/* 构建文件树入栈 */
BISO_9660_FillDfsStack((BISO_DIR_TREE_S *)pstRoot, pstQueue);
/* 不需要释放ROOT,把它从队列头弹出来 */
BISO_QUEUE_PopHead(pstQueue);
/* 依次释放各个节点 */
while (NULL != (pstCurDir = (BISO_SVD_DIR_TREE_S *)BISO_QUEUE_PopTail(pstQueue)))
{
/* 释放当前目录的文件列表 */
for (pstPre = pstCurDir->pstFileList; NULL != pstPre; pstPre = pstNext)
{
pstNext = pstPre->pstNext;
BISO_FREE(pstPre);
}
/* 释放自己 */
BISO_FREE(pstCurDir);
}
/* 释放ROOT目录的文件列表 */
for (pstPre = pstRoot->pstFileList; NULL != pstPre; pstPre = pstNext)
{
pstNext = pstPre->pstNext;
BISO_FREE(pstPre);
}
/* 销毁队列 */
BISO_QUEUE_Destroy(pstQueue);
}
BISO_PARSER_S * BISO_9660_CreateParser(VOID)
{
BISO_PARSER_S *pstParser = NULL;
pstParser = (BISO_PARSER_S *)BISO_ZALLOC(sizeof(BISO_PARSER_S));
if (NULL == pstParser)
{
return NULL;
}
/* 初始化链表 */
BISO_DLL_Init(&(pstParser->stVDList));
return pstParser;
}
VOID BISO_9660_CleanParser(INOUT BISO_PARSER_S *pstParser)
{
if (NULL == pstParser)
{
return;
}
/* 释放Volume Descriptor链表 */
BISO_DLL_Free(&(pstParser->stVDList));
/* 释放Path Table */
if (NULL != pstParser->pucPathTable)
{
BISO_FREE(pstParser->pucPathTable);
}
/* 释放 El Torito数据 */
if (NULL != pstParser->pucElToritoEntry)
{
BISO_FREE(pstParser->pucElToritoEntry);
}
/* 释放文件树 */
BISO_9660_FreeDirTree(pstParser);
BISO_9660_FreeSVDDirTree(pstParser);
}
VOID BISO_9660_DestroyParser(INOUT BISO_PARSER_S *pstParser)
{
if (NULL == pstParser)
{
return;
}
/* 清理解析器 */
BISO_9660_CleanParser(pstParser);
/* 释放解析器自己 */
BISO_FREE(pstParser);
}
ULONG BISO_9660_OpenImage
(
IN BOOL_T bParseSVDDirTree,
IN CONST CHAR *pcFileName,
OUT BISO_PARSER_S *pstParser
)
{
UINT64 ui64FileSize = 0;
ULONG ulRet = BISO_SUCCESS;
BISO_FILE_S *pstFile = NULL;
if ((NULL == pcFileName) || (NULL == pstParser))
{
return BISO_ERR_NULL_PTR;
}
/* 先看文件大小过小的文件不可能是ISO文件 */
ui64FileSize = BISO_PLAT_GetFileSize(pcFileName);
if (ui64FileSize < BISO_SYSTEM_AREA_SIZE + sizeof(BISO_PVD_S))
{
BISO_DIAG("File len %llu is too small.", (ULONGLONG)ui64FileSize);
return BISO_ERR_INVALID_ISO9660;
}
/* 如果已有数据则先清空 */
if (NULL != pstParser->pstPVD)
{
BISO_9660_CleanParser(pstParser);
}
/* 打开ISO文件 */
pstFile = BISO_PLAT_OpenExistFile(pcFileName);
if (NULL == pstFile)
{
BISO_DIAG("Failed to open file %s.", pcFileName);
return BISO_ERR_OPEN_FILE;
}
scnprintf(pstParser->szFileName, sizeof(pstParser->szFileName), "%s", pcFileName);
/* 读取Volume Description信息 */
ulRet = BISO_9660_ReadVD(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
/* 读取Path Table */
ulRet = BISO_9660_ReadPathTable(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
/* 读取BOOT启动信息 */
ulRet = BISO_ELTORITO_ReadBootInfo(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
/* 读取Rock Ridge扩展标识 */
ulRet = BISO_RRIP_ReadIndicator(pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
/* 这里构建文件树有两种方法可供选择, 暂时选择从ROOT递归创建的方法 */
#if 0
/* 从ISO文件中读取整个文件树, 这里选择根据Path Table构建 */
ulRet += BISO_9660_BuildFileTreeByTable(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
#else
/* 从ISO文件中读取整个文件树, 这里选择从ROOT开始递归构建 */
ulRet = BISO_9660_BuildFileTreeRecursively(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
#endif /* #if 0 */
if (bParseSVDDirTree && pstParser->pstSVD)
{
ulRet = BISO_9660_BuildSVDFileTreeRecursively(pstFile, pstParser);
BISO_9660_CHECK_RET(ulRet, pstFile);
}
/* 更新目录结构里的统计信息 */
ulRet = BISO_9660_UpdateTreeStat(&(pstParser->stDirTree));
BISO_9660_CHECK_RET(ulRet, pstFile);
BISO_PLAT_CloseFile(pstFile);
return BISO_SUCCESS;
}
ULONG BISO_9660_ParseDate84261
(
IN CONST CHAR *pcDate,
OUT BISO_DATE_S *pstDate
)
{
INT aiBuf[7] = { 0 };
if ((NULL == pcDate) || (NULL == pstDate))
{
return BISO_ERR_NULL_PTR;
}
/*
* ECMA-119 8.4.26.117
* 1617
* 16'0', '\0'
* "2014122013000500*"
*/
if ((0 == pcDate[0]) || (' ' == pcDate[0]) || ('0' == pcDate[0]))
{
return BISO_ERR_NOT_RECORD;
}
sscanf(pcDate, "%4d%2d%2d%2d%2d%2d%2d",
aiBuf + 0, aiBuf + 1, aiBuf + 2,
aiBuf + 3, aiBuf + 4, aiBuf + 5, aiBuf + 6);
pstDate->usYear = (USHORT)aiBuf[0];
pstDate->ucMonth = (UCHAR)aiBuf[1];
pstDate->ucDay = (UCHAR)aiBuf[2];
pstDate->ucHour = (UCHAR)aiBuf[3];
pstDate->ucMin = (UCHAR)aiBuf[4];
pstDate->ucSecond = (UCHAR)aiBuf[5];
pstDate->usMillSec = (UCHAR)(aiBuf[6] * 10); /* 表示百分之一秒 */
/* 第17字节表示时区信息, 15分钟为1个单位4个单位就是1个时区 */
pstDate->cZone = pcDate[16] / 4;
return BISO_SUCCESS;
}
VOID BISO_9660_FmtDate84261(IN time_t ulTime, IN UINT uiBufSize, OUT CHAR *pcDate)
{
INT iTimeZone = BISO_UTIL_GetTimeZone();
struct tm *pstTm = NULL;
if (NULL != pcDate)
{
pstTm = localtime(&ulTime);
scnprintf(pcDate, uiBufSize, "%04d%02d%02d%02d%02d%02d%02d",
pstTm->tm_year + 1900,
pstTm->tm_mon + 1,
pstTm->tm_mday,
pstTm->tm_hour,
pstTm->tm_min,
pstTm->tm_sec,
0);
/* 第17个字节记录当前时区 */
pcDate[16] = (CHAR)(4 * iTimeZone);
}
}