initial commit

This commit is contained in:
longpanda
2020-04-05 00:07:50 +08:00
parent 2090c6fa97
commit 05a1b863a6
487 changed files with 114253 additions and 0 deletions

865
VtoyTool/BabyISO/biso.c Normal file
View File

@@ -0,0 +1,865 @@
/******************************************************************************
* biso.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"
#include "biso_eltorito.h"
#include "biso_rockridge.h"
#include "biso_joliet.h"
#include "biso_dump.h"
CONST STATIC CHAR *g_aszErrMsg[] =
{
"Success", /* BISO_SUCCESS */
"General failed", /* BISO_ERR_FAILED */
"Null pointer", /* BISO_ERR_NULL_PTR */
"Failed to alloc memory", /* BISO_ERR_ALLOC_MEM */
"Failed to open file", /* BISO_ERR_OPEN_FILE */
"Failed to read file", /* BISO_ERR_READ_FILE */
"Failed to write file", /* BISO_ERR_WRITE_FILE */
"Invalid iso-9660 format", /* BISO_ERR_INVALID_ISO9660 */
"Unsupported block size", /* BISO_ERR_UNSUPPORTED_BLKSIZE */
"Invalid parameter", /* BISO_ERR_INVALID_PARAM */
"Not found", /* BISO_ERR_NOT_FOUND */
"Not record in iso file", /* BISO_ERR_NOT_RECORD */
"Handle is not initialized", /* BISO_ERR_HANDLE_UNINITIALIZED */
};
int g_biso_debug = 0;
VOID BISO_SetDebug(int debug)
{
g_biso_debug = debug;
}
CONST CHAR * BISO_GetErrMsg(IN ULONG ulErrCode)
{
if (ulErrCode > BISO_ERR_BASE)
{
ulErrCode -= BISO_ERR_BASE;
}
if (ulErrCode > ARRAY_SIZE(g_aszErrMsg))
{
return NULL;
}
return g_aszErrMsg[ulErrCode];
}
VOID BISO_GetNow(OUT BISO_DATE_S *pstTM)
{
INT iTimeZone;
INT iLocalHour;
INT iGMTHour;
time_t ulTime;
struct tm *pstLocalTM = NULL;
struct tm *pstGMTM = NULL;
if (NULL == pstTM)
{
return;
}
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;
}
pstTM->usYear = pstLocalTM->tm_year + 1900;
pstTM->ucMonth = pstLocalTM->tm_mon + 1;
pstTM->ucDay = pstLocalTM->tm_mday;
pstTM->ucHour = pstLocalTM->tm_hour;
pstTM->ucMin = pstLocalTM->tm_min;
pstTM->ucSecond = pstLocalTM->tm_sec;
pstTM->usMillSec = 0;
pstTM->cZone = (CHAR)iTimeZone;
return;
}
VOID BISO_TimeConv(IN ULONG ulTime, OUT BISO_DATE_S *pstTM)
{
time_t ulTm = ulTime;
struct tm *pstLocalTM = NULL;
pstLocalTM = localtime(&ulTm);
pstTM->usYear = pstLocalTM->tm_year + 1900;
pstTM->ucMonth = pstLocalTM->tm_mon + 1;
pstTM->ucDay = pstLocalTM->tm_mday;
pstTM->ucHour = pstLocalTM->tm_hour;
pstTM->ucMin = pstLocalTM->tm_min;
pstTM->ucSecond = pstLocalTM->tm_sec;
pstTM->usMillSec = 0;
pstTM->cZone = (CHAR)BISO_UTIL_GetTimeZone();
return;
}
BISO_READ_S * BISO_AllocReadHandle(VOID)
{
return (BISO_READ_S *)BISO_9660_CreateParser();
}
VOID BISO_FreeReadHandle(INOUT BISO_READ_S *pstRead)
{
BISO_9660_DestroyParser((BISO_PARSER_S *)pstRead);
}
BOOL_T BISO_IsISOFile(IN CONST CHAR *pcFileName)
{
UINT uiReadLen;
UINT64 ui64FileSize = 0;
BISO_FILE_S *pstFile = NULL;
BISO_VD_S stVolDesc;
/* 先看文件大小过小的文件不可能是ISO文件 */
ui64FileSize = BISO_PLAT_GetFileSize(pcFileName);
if (ui64FileSize < BISO_SYSTEM_AREA_SIZE + sizeof(BISO_PVD_S))
{
return BOOL_FALSE;
}
/* 打开ISO文件 */
pstFile = BISO_PLAT_OpenExistFile(pcFileName);
if (NULL == pstFile)
{
return BOOL_FALSE;
}
/* 标准规定前16个逻辑扇区用来保存系统数据VD信息从第17个扇区开始 */
BISO_PLAT_SeekFile(pstFile, BISO_SYSTEM_AREA_SIZE, SEEK_SET);
/* 读出VD信息 */
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stVolDesc), &stVolDesc);
if (uiReadLen != sizeof(stVolDesc))
{
BISO_PLAT_CloseFile(pstFile);
return BOOL_FALSE;
}
/* 根据ID检验是否是合法的ISO-9660格式 */
if (0 != strncmp(stVolDesc.szId, BISO_VD_ID, strlen(BISO_VD_ID)))
{
BISO_PLAT_CloseFile(pstFile);
return BOOL_FALSE;
}
BISO_PLAT_CloseFile(pstFile);
return BOOL_TRUE;
}
BOOL_T BISO_HasSVD(IN CONST BISO_READ_S *pstRead)
{
if (((BISO_PARSER_S *)pstRead)->pstSVD)
{
return BOOL_TRUE;
}
return BOOL_FALSE;
}
BOOL_T BISO_IsUDFFile(IN CONST CHAR *pcFileName)
{
UINT uiReadLen;
UINT64 ui64FileSize = 0;
BISO_FILE_S *pstFile = NULL;
BISO_VD_S stVolDesc;
/* 先看文件大小过小的文件不可能是ISO文件 */
ui64FileSize = BISO_PLAT_GetFileSize(pcFileName);
if (ui64FileSize < BISO_SYSTEM_AREA_SIZE + sizeof(BISO_PVD_S))
{
return BOOL_FALSE;
}
/* 打开ISO文件 */
pstFile = BISO_PLAT_OpenExistFile(pcFileName);
if (NULL == pstFile)
{
return BOOL_FALSE;
}
/* 标准规定前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_PLAT_CloseFile(pstFile);
return BOOL_FALSE;
}
} while (BISO_VD_TYPE_END != stVolDesc.ucType);
/* 根据ID检验是否是合法的UDF格式 */
(VOID)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stVolDesc), &stVolDesc);
if (0 != strncmp(stVolDesc.szId, "BEA01", strlen("BEA01")))
{
BISO_PLAT_CloseFile(pstFile);
return BOOL_FALSE;
}
/* 根据ID检验是否是合法的UDF格式 */
(VOID)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stVolDesc), &stVolDesc);
if (0 != strncmp(stVolDesc.szId, "NSR02", strlen("NSR02")) &&
0 != strncmp(stVolDesc.szId, "NSR03", strlen("NSR03")))
{
BISO_PLAT_CloseFile(pstFile);
return BOOL_FALSE;
}
BISO_PLAT_CloseFile(pstFile);
return BOOL_TRUE;
}
ULONG BISO_OpenImage(IN CONST CHAR *pcFileName, OUT BISO_READ_S *pstRead)
{
return BISO_9660_OpenImage(BOOL_FALSE, pcFileName, (BISO_PARSER_S *)pstRead);
}
ULONG BISO_OpenImageWithSVD(IN CONST CHAR *pcFileName, OUT BISO_READ_S *pstRead)
{
return BISO_9660_OpenImage(BOOL_TRUE, pcFileName, (BISO_PARSER_S *)pstRead);
}
ULONG BISO_GetVolumeSummary
(
IN CONST BISO_READ_S *pstRead,
OUT BISO_VOLUME_SUMMARY_S *pstSummary
)
{
BISO_PVD_S *pstPVD = NULL;
BISO_PARSER_S *pstParser = NULL;
if (NULL == pstRead || NULL == pstSummary)
{
return BISO_ERR_NULL_PTR;
}
if (BOOL_TRUE != BISO_IS_READ_HANDLE_VALID(pstRead))
{
return BISO_ERR_INVALID_PARAM;
}
pstParser = (BISO_PARSER_S *)pstRead;
pstPVD = pstParser->pstPVD;
/* 拷贝字符串 */
BISO_UTIL_CopyStr(pstPVD->szVolumeId, sizeof(pstPVD->szVolumeId), pstSummary->szVolumeId);
BISO_UTIL_CopyStr(pstPVD->szSystemId, sizeof(pstPVD->szSystemId), pstSummary->szSystemId);
BISO_UTIL_CopyStr(pstPVD->szPublisherId, sizeof(pstPVD->szPublisherId), pstSummary->szPublisherId);
BISO_UTIL_CopyStr(pstPVD->szPreparerId, sizeof(pstPVD->szPreparerId), pstSummary->szPreparerId);
BISO_UTIL_CopyStr(pstPVD->szApplicationId, sizeof(pstPVD->szApplicationId), pstSummary->szApplicationId);
BISO_UTIL_CopyStr(pstPVD->szCopyrightFileId, sizeof(pstPVD->szCopyrightFileId), pstSummary->szCopyrightFileId);
BISO_UTIL_CopyStr(pstPVD->szAbstractFileId, sizeof(pstPVD->szAbstractFileId), pstSummary->szAbstractFileId);
/* 其他字段赋值 */
pstSummary->uiRockRidgeVer = pstParser->ucRRIPVersion;
pstSummary->uiJolietLevel = BISO_GetJolietLevel(pstRead);
pstSummary->uiTotDirNum = pstParser->stDirTree.pstDirStat->uiTotDirNum;
pstSummary->uiTotFileNum = pstParser->stDirTree.pstDirStat->uiTotFileNum;
pstSummary->uiTotLinkNum = pstParser->stDirTree.pstDirStat->uiTotLinkNum;
return BISO_SUCCESS;
}
ULONG BISO_GetDate
(
IN CONST BISO_READ_S *pstRead,
IN BISO_DATE_TYPE_E enType,
OUT BISO_DATE_S *pstDate
)
{
CONST CHAR *pcDate = NULL;
BISO_PVD_S *pstPVD = NULL;
if ((NULL == pstRead) || (enType >= BISO_DATE_TYPE_BUTT) || (NULL == pstDate))
{
BISO_DIAG("Invalid param %p %d %p.", pstRead, enType, pstDate);
return BISO_ERR_INVALID_PARAM;
}
BISO_CHECK_READ_HANDLE(pstRead);
pstPVD = ((BISO_PARSER_S *)pstRead)->pstPVD;
switch (enType)
{
case BISO_DATE_TYPE_CREATE:
{
pcDate = pstPVD->szCreationDate;
break;
}
case BISO_DATE_TYPE_MODIFY:
{
pcDate = pstPVD->szModifyDate;
break;
}
case BISO_DATE_TYPE_EXPIRATION:
{
pcDate = pstPVD->szExpirationDate;
break;
}
case BISO_DATE_TYPE_EFFECTIVE:
{
pcDate = pstPVD->szEffectiveDate;
break;
}
default :
{
return BISO_ERR_INVALID_PARAM;
}
}
return BISO_9660_ParseDate84261(pcDate, pstDate);
}
/* 获取Rock Ridge扩展的Version 0: 没有使用Rock Ridge扩展 具体版本号: 一般都是1 */
UINT BISO_GetRockRidgeVer(IN CONST BISO_READ_S *pstRead)
{
if ((NULL == pstRead) || (BOOL_TRUE != BISO_IS_READ_HANDLE_VALID(pstRead)))
{
return 0;
}
return ((BISO_PARSER_S *)pstRead)->ucRRIPVersion;
}
/* 获取Joliet扩展的Level */
UINT BISO_GetJolietLevel(IN CONST BISO_READ_S *pstRead)
{
BISO_PARSER_S *pstParser = NULL;
if ((NULL == pstRead) || (BOOL_TRUE != BISO_IS_READ_HANDLE_VALID(pstRead)))
{
return 0;
}
pstParser = (BISO_PARSER_S *)pstRead;
if (NULL == pstParser->pstSVD)
{
return 0;
}
return BISO_JOLIET_GetLevel(pstParser->pstSVD->aucEscape);
}
BISO_HANDLE BISO_GetRoot(IN CONST BISO_READ_S *pstRead)
{
BISO_PARSER_S *pstParser = (BISO_PARSER_S *)pstRead;
if (NULL == pstParser)
{
return NULL;
}
return (BISO_HANDLE)(&pstParser->stDirTree);
}
ULONG BISO_GetFileNodeByHdl
(
IN BISO_HANDLE hFileHdl,
OUT BISO_FILE_NODE_S *pstFileNode
)
{
BISO_POSIX_INFO_S *pstPosix = NULL;
BISO_DIR_TREE_S *pstDirTree = (BISO_DIR_TREE_S *)hFileHdl;
if ((NULL == pstDirTree) || (NULL == pstFileNode))
{
return BISO_ERR_NULL_PTR;
}
pstPosix = pstDirTree->pstPosixInfo;
/* 设置类型 */
BISO_SET_FLAG(pstFileNode, pstDirTree);
/* 设置名称 */
scnprintf(pstFileNode->szName, sizeof(pstFileNode->szName), "%s", pstDirTree->szName);
/* 设置连接路径 */
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstDirTree))
{
scnprintf(pstFileNode->szLinkTgt, sizeof(pstFileNode->szLinkTgt), "%s", pstPosix->pcLinkSrc);
}
pstFileNode->ui64FileSize = pstDirTree->uiSize;
pstFileNode->ui64Seek = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_BLOCK_SIZE);
pstFileNode->hParent = (BISO_HANDLE)(pstDirTree->pstParent);
pstFileNode->hCurrent = hFileHdl;
return BISO_SUCCESS;
}
ULONG BISO_GetFileNodeByName
(
IN CONST BISO_READ_S *pstRead,
IN CONST CHAR *pcFullPath,
IN UCHAR ucFollowLink,
OUT BISO_FILE_NODE_S *pstFileNode
)
{
UINT i = 0;
UINT uiDirNum = 0;
UINT auiDirPos[32];
USHORT usPos = 0;
USHORT usLen = 0;
CHAR szDirName[1024];
BISO_DIR_TREE_S *pstCurDir = NULL;
BISO_DIR_TREE_S *pstRootDir = NULL;
BISO_DIR_TREE_S *pstFileList = NULL;
BISO_PARSER_S *pstParser = (BISO_PARSER_S *)pstRead;
if ((NULL == pstRead) || (NULL == pcFullPath) || (NULL == pstFileNode))
{
return BISO_ERR_NULL_PTR;
}
if ('/' == pcFullPath[0])
{
return BISO_ERR_FAILED;
}
pstRootDir = &(pstParser->stDirTree);
pstCurDir = pstRootDir->pstChild;
if ((0 == pcFullPath[0]) || ((1 == strlen(pcFullPath)) && ('/' == pcFullPath[0])))
{
/* 出参赋值 */
memset(pstFileNode, 0, sizeof(BISO_FILE_NODE_S));
BISO_SET_FLAG(pstFileNode, pstCurDir);
scnprintf(pstFileNode->szName, sizeof(pstFileNode->szName), "%s", pstCurDir->szName);
pstFileNode->hParent = 0;
pstFileNode->hCurrent = (BISO_HANDLE)(pstRootDir);
return BISO_SUCCESS;
}
if ((1 == uiDirNum) && (NULL != pstRootDir))
{
pstFileList = pstRootDir->pstFileList;
pstCurDir = pstFileList;
while (pstCurDir)
{
if (0 == BISO_PATH_STRCMP(pstCurDir->szName, pcFullPath))
{
goto FOUND;
}
pstCurDir = pstCurDir->pstNext;
}
}
/* 先将目录分解开 */
if (BISO_SUCCESS != BISO_UTIL_PathSplit(pcFullPath, &uiDirNum, auiDirPos))
{
BISO_DIAG("Failed to split path %s", pcFullPath);
return BISO_ERR_FAILED;
}
/* 依次查找每一级目录 */
if (pstRootDir)
{
pstCurDir = pstRootDir->pstChild;
}
for (i = 0; (i < uiDirNum) && (NULL != pstRootDir) && (NULL != pstCurDir); i++)
{
usPos = auiDirPos[i] >> 16;
usLen = auiDirPos[i] & 0xFF;
memcpy(szDirName, pcFullPath + usPos, usLen);
szDirName[usLen] = 0;
pstCurDir = pstRootDir->pstChild;
pstFileList = pstRootDir->pstFileList;
/* 先查找目录 */
while (pstCurDir)
{
if (0 == BISO_PATH_STRCMP(pstCurDir->szName, szDirName))
{
pstRootDir = pstCurDir;
break;
}
pstCurDir = pstCurDir->pstNext;
}
/* 再查找文件 */
if (NULL == pstCurDir)
{
pstCurDir = pstFileList;
while (pstCurDir)
{
if (0 == BISO_PATH_STRCMP(pstCurDir->szName, szDirName))
{
break;
}
pstCurDir = pstCurDir->pstNext;
}
}
if (NULL == pstCurDir)
{
return BISO_ERR_FAILED;
}
/* 如果是符号链接则尝试找对应的实际文件 */
if ((ucFollowLink > 0) && (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstCurDir)))
{
pstCurDir = BISO_UTIL_FindLinkTgt(pstCurDir);
}
/* 如果是文件(或者是非法链接)的话一定是最后一级 */
if ((NULL == pstCurDir->pstDirStat) && (i + 1 != uiDirNum))
{
return BISO_ERR_FAILED;
}
}
FOUND:
if (NULL == pstCurDir)
{
return BISO_ERR_FAILED;
}
else
{
/* 出参赋值 */
memset(pstFileNode, 0, sizeof(BISO_FILE_NODE_S));
BISO_SET_FLAG(pstFileNode, pstCurDir);
scnprintf(pstFileNode->szName, sizeof(pstFileNode->szName), "%s", pstCurDir->szName);
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstCurDir))
{
scnprintf(pstFileNode->szLinkTgt, sizeof(pstFileNode->szLinkTgt), "%s",
pstCurDir->pstPosixInfo->pcLinkSrc);
}
pstFileNode->ui64FileSize = pstCurDir->uiSize;
pstFileNode->ui64DirRecOffet = pstCurDir->ui64FileRecordOffset;
pstFileNode->ui64Seek = (UINT64)((UINT64)pstCurDir->uiExtent * BISO_BLOCK_SIZE);
pstFileNode->hParent = (BISO_HANDLE)(pstCurDir->pstParent);
pstFileNode->hCurrent = (BISO_HANDLE)(pstCurDir);
return BISO_SUCCESS;
}
}
ULONG BISO_GetFileNodeByExtent
(
IN CONST BISO_READ_S *pstRead,
IN UINT uiExtent,
OUT BISO_FILE_NODE_S *pstFileNode
)
{
BOOL_T bFind = BOOL_FALSE;
BISO_QUEUE_S *pstQueue = NULL;
BISO_DIR_TREE_S *pstRootDir = NULL;
BISO_DIR_TREE_S *pstDirTree = NULL;
BISO_DIR_TREE_S *pstCurDir = NULL;
BISO_DIR_TREE_S *pstFileList = NULL;
BISO_PARSER_S *pstParser = (BISO_PARSER_S *)pstRead;
if ((NULL == pstRead) || (NULL == pstFileNode))
{
return BISO_ERR_NULL_PTR;
}
pstRootDir = &(pstParser->stDirTree);
/* 创建堆栈,同时ROOT入栈 */
pstQueue = BISO_QUEUE_Create();
BISO_QUEUE_Push(pstQueue, pstRootDir);
while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
pstCurDir = pstDirTree->pstChild;
while (pstCurDir)
{
BISO_QUEUE_Push(pstQueue, pstCurDir);
pstCurDir = pstCurDir->pstNext;
}
pstFileList = pstDirTree->pstFileList;
pstCurDir = pstFileList;
while (pstCurDir)
{
if (uiExtent == pstCurDir->uiExtent)
{
while (BISO_QUEUE_PopHead(pstQueue))
{
bFind = BOOL_TRUE;
}
break;
}
pstCurDir = pstCurDir->pstNext;
}
}
BISO_QUEUE_Destroy(pstQueue);
if (BOOL_TRUE != bFind)
{
return BISO_ERR_FAILED;
}
else
{
/* 出参赋值 */
memset(pstFileNode, 0, sizeof(BISO_FILE_NODE_S));
BISO_SET_FLAG(pstFileNode, pstCurDir);
scnprintf(pstFileNode->szName, sizeof(pstFileNode->szName), "%s", pstCurDir->szName);
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstCurDir))
{
scnprintf(pstFileNode->szLinkTgt, sizeof(pstFileNode->szLinkTgt), "%s",
pstCurDir->pstPosixInfo->pcLinkSrc);
}
pstFileNode->ui64FileSize = pstCurDir->uiSize;
pstFileNode->ui64DirRecOffet = pstCurDir->ui64FileRecordOffset;
pstFileNode->ui64Seek = (UINT64)((UINT64)pstCurDir->uiExtent * BISO_BLOCK_SIZE);
pstFileNode->hParent = (BISO_HANDLE)(pstCurDir->pstParent);
pstFileNode->hCurrent = (BISO_HANDLE)(pstCurDir);
return BISO_SUCCESS;
}
}
ULONG BISO_GetSVDFileNodeByExtent
(
IN CONST BISO_READ_S *pstRead,
IN UINT uiExtent,
OUT BISO_SVD_FILE_NODE_S *pstFileNode
)
{
BOOL_T bFind = BOOL_FALSE;
BISO_QUEUE_S *pstQueue = NULL;
BISO_SVD_DIR_TREE_S *pstRootDir = NULL;
BISO_SVD_DIR_TREE_S *pstDirTree = NULL;
BISO_SVD_DIR_TREE_S *pstCurDir = NULL;
BISO_SVD_DIR_TREE_S *pstFileList = NULL;
BISO_PARSER_S *pstParser = (BISO_PARSER_S *)pstRead;
if ((NULL == pstRead) || (NULL == pstFileNode))
{
return BISO_ERR_NULL_PTR;
}
pstRootDir = &(pstParser->stSVDDirTree);
/* 创建堆栈,同时ROOT入栈 */
pstQueue = BISO_QUEUE_Create();
BISO_QUEUE_Push(pstQueue, pstRootDir);
while (NULL != (pstDirTree = (BISO_SVD_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
{
pstCurDir = pstDirTree->pstChild;
while (pstCurDir)
{
BISO_QUEUE_Push(pstQueue, pstCurDir);
pstCurDir = pstCurDir->pstNext;
}
pstFileList = pstDirTree->pstFileList;
pstCurDir = pstFileList;
while (pstCurDir)
{
if (uiExtent == pstCurDir->uiExtent)
{
while (BISO_QUEUE_PopHead(pstQueue))
{
bFind = BOOL_TRUE;
}
break;
}
pstCurDir = pstCurDir->pstNext;
}
}
BISO_QUEUE_Destroy(pstQueue);
if (BOOL_TRUE != bFind)
{
return BISO_ERR_FAILED;
}
else
{
/* 出参赋值 */
memset(pstFileNode, 0, sizeof(BISO_SVD_FILE_NODE_S));
pstFileNode->ui64FileSize = pstCurDir->uiSize;
pstFileNode->ui64DirRecOffet = pstCurDir->ui64FileRecordOffset;
pstFileNode->ui64Seek = (UINT64)((UINT64)pstCurDir->uiExtent * BISO_BLOCK_SIZE);
return BISO_SUCCESS;
}
}
ULONG BISO_GetFileTree
(
IN BISO_HANDLE hTopDir,
IN UINT uiFlag,
OUT BISO_HANDLE *phFileTree,
OUT UINT *puiNodeNum
)
{
BISO_DIR_STAT_S *pstDirStat = NULL;
BISO_DIR_TREE_S *pstCurNode = NULL;
BISO_DIR_TREE_S *pstDirTree = (BISO_DIR_TREE_S *)hTopDir;
if ((NULL == pstDirTree) || (NULL == phFileTree) || (NULL == puiNodeNum))
{
return BISO_ERR_NULL_PTR;
}
pstDirStat = pstDirTree->pstDirStat;
if (NULL == pstDirStat)
{
return BISO_ERR_INVALID_PARAM;
}
*puiNodeNum = pstDirStat->uiCurDirNum + pstDirStat->uiCurFileNum + pstDirStat->uiCurLinkNum;
switch (uiFlag)
{
case BISO_TREE_FLAG_CUR:
{
pstCurNode = pstDirTree->pstChild;
while (NULL != pstCurNode)
{
*phFileTree++ = (BISO_HANDLE)pstCurNode;
pstCurNode = pstCurNode->pstNext;
}
pstCurNode = pstDirTree->pstFileList;
while (NULL != pstCurNode)
{
*phFileTree++ = (BISO_HANDLE)pstCurNode;
pstCurNode = pstCurNode->pstNext;
}
break;
}
case BISO_TREE_FLAG_DFS:
{
break;
}
case BISO_TREE_FLAG_BFS:
{
break;
}
default :
{
return BISO_ERR_INVALID_PARAM;
}
}
return BISO_SUCCESS;
}
ULONG BISO_GetDirStat
(
IN BISO_HANDLE hTopDir,
OUT BISO_DIR_STAT_S *pstDirStat
)
{
BISO_DIR_TREE_S *pstDirTree = NULL;
if ((NULL == hTopDir) || (NULL == pstDirStat))
{
return BISO_ERR_NULL_PTR;
}
pstDirTree = (BISO_DIR_TREE_S *)hTopDir;
if (NULL == pstDirTree->pstDirStat)
{
return BISO_ERR_INVALID_PARAM;
}
memcpy(pstDirStat, pstDirTree->pstDirStat, sizeof(BISO_DIR_STAT_S));
return BISO_SUCCESS;
}
VOID BISO_Fill733(IN UINT uiData, OUT VOID *pBuf)
{
UINT uiSwap = 0;
UINT *puiData = (UINT *)pBuf;
uiSwap |= (uiData & 0xFF) << 24;
uiSwap |= ((uiData >> 8) & 0xFF) << 16;
uiSwap |= ((uiData >> 16) & 0xFF) << 8;
uiSwap |= (uiData >> 24) & 0xFF;
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
puiData[0] = uiData;
puiData[1] = uiSwap;
#else
puiData[0] = uiSwap;
puiData[1] = uiData;
#endif
}
UINT BISO_Get733(IN CONST VOID *pBuf)
{
UINT *puiData = (UINT *)pBuf;
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
return puiData[0];
#else
return puiData[1];
#endif
}
UINT BISO_GetFileOccupySize(IN UINT uiRawSize)
{
UINT uiAlign = uiRawSize % BISO_SECTOR_SIZE;
if (0 == uiAlign)
{
return uiRawSize;
}
else
{
return uiRawSize + BISO_SECTOR_SIZE - uiAlign;
}
}
UINT BISO_GetBootEntryNum(IN CONST BISO_READ_S *pstRead)
{
return BISO_ELTORITO_GetBootEntryNum((CONST BISO_PARSER_S *)pstRead);
}
VOID BISO_DumpFileTree(IN CONST BISO_READ_S *pstRead)
{
BISO_PARSER_S *pstParser = (BISO_PARSER_S *)pstRead;
if (NULL != pstParser)
{
BISO_DUMP_ShowFileTree(1, pstParser->stDirTree.pstChild);
BISO_DUMP_ShowFileTree(1, pstParser->stDirTree.pstFileList);
}
}

421
VtoyTool/BabyISO/biso.h Normal file
View File

@@ -0,0 +1,421 @@
/******************************************************************************
* biso.h
*
* 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/>.
*
*/
#ifndef __BISO_H__
#define __BISO_H__
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"
extern int g_biso_debug;
void BISO_SetDebug(int debug);
#define BISO_DIAG(fmt, ...) if(g_biso_debug) printf(fmt, ##__VA_ARGS__)
#define BISO_DUMP printf
#ifndef STATIC
#define STATIC static
#endif
#ifndef CONST
#define CONST const
#endif
#ifndef INLINE
#define INLINE inline
#endif
#ifndef VOID
#define VOID void
#endif
#ifndef PVOID
typedef VOID * PVOID;
#endif
#ifndef CHAR
#define CHAR char
#endif
#ifndef UCHAR
#define UCHAR unsigned char
#endif
#ifndef SHORT
#define SHORT short
#endif
#ifndef USHORT
#define USHORT unsigned short
#endif
#ifndef LONG
#define LONG long
#endif
#ifndef ULONG
#define ULONG unsigned long
#endif
#ifndef ULONGLONG
#define ULONGLONG unsigned long long
#endif
#ifndef INT
#define INT int
#endif
#ifndef UINT
#define UINT unsigned int
#endif
#ifndef INT16
#define INT16 short
#endif
#ifndef UINT16
#define UINT16 unsigned short
#endif
#ifndef INT32
#define INT32 int
#endif
#ifndef UINT32
#define UINT32 unsigned int
#endif
#ifndef BOOL_T
typedef USHORT BOOL_T;
#define BOOL_TRUE ((BOOL_T)1)
#define BOOL_FALSE ((BOOL_T)0)
#endif
typedef long long INT64;
typedef unsigned long long UINT64;
#define BISO_PATH_STRCMP strcmp
#ifndef NULL
#define NULL (void *)0
#endif
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef INOUT
#define INOUT
#endif
#define BISO_TRUE 1
#define BISO_FALSE 0
typedef VOID BISO_READ_S;
typedef VOID BISO_WRITE_S;
typedef CONST VOID * BISO_HANDLE;
/* error code */
#define BISO_SUCCESS 0
#define BISO_ERR_BASE 0x1000
#define BISO_ERR_FAILED (BISO_ERR_BASE + 1)
#define BISO_ERR_NULL_PTR (BISO_ERR_BASE + 2)
#define BISO_ERR_ALLOC_MEM (BISO_ERR_BASE + 3)
#define BISO_ERR_OPEN_FILE (BISO_ERR_BASE + 4)
#define BISO_ERR_READ_FILE (BISO_ERR_BASE + 5)
#define BISO_ERR_WRITE_FILE (BISO_ERR_BASE + 6)
#define BISO_ERR_INVALID_ISO9660 (BISO_ERR_BASE + 7)
#define BISO_ERR_UNSUPPORTED_BLKSIZE (BISO_ERR_BASE + 8)
#define BISO_ERR_INVALID_PARAM (BISO_ERR_BASE + 9)
#define BISO_ERR_NOT_FOUND (BISO_ERR_BASE + 10)
#define BISO_ERR_NOT_RECORD (BISO_ERR_BASE + 11)
#define BISO_ERR_HANDLE_UNINITIALIZED (BISO_ERR_BASE + 12)
#define BISO_ERR_INVALID_RRIP_SP (BISO_ERR_BASE + 13)
#define BISO_ERR_ABORT (BISO_ERR_BASE + 14)
typedef struct tagBISO_VOLUME_SUMMARY
{
CHAR szVolumeId[33];
CHAR szSystemId[33];
CHAR szPublisherId[129];
CHAR szPreparerId[129];
CHAR szApplicationId[129];
CHAR szCopyrightFileId[38];
CHAR szAbstractFileId[38];
UINT uiRockRidgeVer;
UINT uiJolietLevel;
UINT uiTotDirNum;
UINT uiTotFileNum;
UINT uiTotLinkNum;
}BISO_VOLUME_SUMMARY_S;
#define BISO_TREE_FLAG_CUR 1
#define BISO_TREE_FLAG_DFS 2
#define BISO_TREE_FLAG_BFS 3
/* time */
typedef struct tagBISO_DATE
{
USHORT usYear;
UCHAR ucMonth;
UCHAR ucDay;
UCHAR ucHour;
UCHAR ucMin;
UCHAR ucSecond;
USHORT usMillSec;
CHAR cZone;
}BISO_DATE_S;
typedef enum tagBISO_DATE_TYPE
{
BISO_DATE_TYPE_CREATE = 0,
BISO_DATE_TYPE_MODIFY,
BISO_DATE_TYPE_EXPIRATION,
BISO_DATE_TYPE_EFFECTIVE,
BISO_DATE_TYPE_BUTT
}BISO_DATE_TYPE_E;
/* dir stat */
typedef struct tagBISO_DIR_STAT
{
UINT uiCurDirNum;
UINT uiCurFileNum;
UINT uiCurLinkNum;
UINT uiCurUsedSec;
UINT64 ui64CurSpace;
UINT uiTotDirNum;
UINT uiTotFileNum;
UINT uiTotLinkNum;
UINT64 ui64TotSpace;
UINT uiTotUsedSec;
}BISO_DIR_STAT_S;
#define BISO_NODE_REGFILE 1
#define BISO_NODE_SYMLINK 2
#define BISO_NODE_DIRECTORY 4
/* file tree */
typedef struct tagBISO_FILE_NODE
{
/*
* ucFlag
* BISO_NODE_REGFILE
* BISO_NODE_SYMLINK
* BISO_NODE_DIRECTORY
*/
UCHAR ucFlag;
CHAR szName[256];
CHAR szLinkTgt[256];
UINT64 ui64FileSize;
UINT64 ui64Seek;
UINT64 ui64DirRecOffet;
BISO_HANDLE hParent;
BISO_HANDLE hCurrent;
}BISO_FILE_NODE_S;
typedef struct tagBISO_SVD_FILE_NODE
{
UINT64 ui64FileSize;
UINT64 ui64Seek;
UINT64 ui64DirRecOffet;
}BISO_SVD_FILE_NODE_S;
/* timestamp type */
#define BISO_EXTRACT_TIME_FOLLOW 1
#define BISO_EXTRACT_TIME_SPECIFY 2
typedef struct tagBISO_EXTRACT_CTRL
{
UCHAR ucATimeFlag;
UCHAR ucMTimeFlag;
BISO_DATE_S stATime;
BISO_DATE_S stMTime;
}BISO_EXTRACT_CTRL_S;
#define BISO_EXTRACT_MSG_MAKE_DIR 1
#define BISO_EXTRACT_MSG_CREATE_FILE 2
#define BISO_EXTRACT_MSG_SYMLINK 3
typedef struct tagBISO_EXTRACT_NOTIFY
{
UINT uiMsg;
ULONG ulResult;
CONST CHAR *pcFileName;
}BISO_EXTRACT_NOTIFY_S;
typedef ULONG (* BISO_EXTRACE_CB_PF)(IN CONST BISO_EXTRACT_NOTIFY_S *pstNotify);
CONST CHAR * BISO_GetErrMsg(IN ULONG ulErrCode);
VOID BISO_GetNow(OUT BISO_DATE_S *pstTM);
VOID BISO_TimeConv(IN ULONG ulTime, OUT BISO_DATE_S *pstTM);
BISO_READ_S * BISO_AllocReadHandle(VOID);
VOID BISO_FreeReadHandle(INOUT BISO_READ_S *pstRead);
BOOL_T BISO_IsISOFile(IN CONST CHAR *pcFileName);
BOOL_T BISO_IsUDFFile(IN CONST CHAR *pcFileName);
ULONG BISO_OpenImage(IN CONST CHAR *pcFileName, OUT BISO_READ_S *pstRead);
ULONG BISO_OpenImageWithSVD(IN CONST CHAR *pcFileName, OUT BISO_READ_S *pstRead);
BOOL_T BISO_HasSVD(IN CONST BISO_READ_S *pstRead);
ULONG BISO_GetVolumeSummary
(
IN CONST BISO_READ_S *pstRead,
OUT BISO_VOLUME_SUMMARY_S *pstSummary
);
ULONG BISO_GetDate
(
IN CONST BISO_READ_S *pstRead,
IN BISO_DATE_TYPE_E enType,
OUT BISO_DATE_S *pstDate
);
UINT BISO_GetRockRidgeVer(IN CONST BISO_READ_S *pstRead);
UINT BISO_GetJolietLevel(IN CONST BISO_READ_S *pstRead);
BISO_HANDLE BISO_GetRoot(IN CONST BISO_READ_S *pstRead);
ULONG BISO_GetFileNodeByHdl
(
IN BISO_HANDLE hFileHdl,
OUT BISO_FILE_NODE_S *pstFileNode
);
ULONG BISO_GetFileNodeByName
(
IN CONST BISO_READ_S *pstRead,
IN CONST CHAR *pcFullPath,
IN UCHAR ucFollowLink,
OUT BISO_FILE_NODE_S *pstFileNode
);
ULONG BISO_GetFileNodeByExtent
(
IN CONST BISO_READ_S *pstRead,
IN UINT uiExtent,
OUT BISO_FILE_NODE_S *pstFileNode
);
ULONG BISO_GetSVDFileNodeByExtent
(
IN CONST BISO_READ_S *pstRead,
IN UINT uiExtent,
OUT BISO_SVD_FILE_NODE_S *pstFileNode
);
ULONG BISO_GetFileTree
(
IN BISO_HANDLE hTopDir,
IN UINT uiFlag,
OUT BISO_HANDLE *phFileTree,
OUT UINT *puiNodeNum
);
ULONG BISO_GetDirStat
(
IN BISO_HANDLE hTopDir,
OUT BISO_DIR_STAT_S *pstDirStat
);
ULONG BISO_ExtractFile
(
IN CONST BISO_READ_S *pstRead,
IN CONST BISO_HANDLE hTopDir,
IN CONST CHAR *pcDstPath,
IN CONST BISO_EXTRACT_CTRL_S *pstCtrl,
IN BISO_EXTRACE_CB_PF pfCallBack
);
VOID BISO_Fill733(IN UINT uiData, OUT VOID *pBuf);
UINT BISO_Get733(IN CONST VOID *pBuf);
UINT BISO_GetFileOccupySize(IN UINT uiRawSize);
UINT BISO_GetBootEntryNum(IN CONST BISO_READ_S *pstRead);
VOID BISO_DumpVD(IN CONST BISO_READ_S *pstRead);
VOID BISO_DumpPathTable(IN CONST BISO_READ_S *pstRead);
VOID BISO_DumpFileTree(IN CONST BISO_READ_S *pstRead);
typedef struct tagBISO_FILE
{
UINT64 CurPos;
UINT64 FileSize;
}BISO_FILE_S;
UINT64 BISO_PLAT_GetFileSize(IN CONST CHAR *pcFileName);
VOID BISO_PLAT_UTime
(
IN CONST CHAR *pcFileName,
IN CONST BISO_DATE_S *pstAccessTime,
IN CONST BISO_DATE_S *pstModifyTime
);
BOOL_T BISO_PLAT_IsPathExist(IN CONST CHAR *pcPath);
BOOL_T BISO_PLAT_IsFileExist(IN CONST CHAR *pcFilePath);
ULONG BISO_PLAT_MkDir(IN CONST CHAR *pcFullPath);
BISO_FILE_S * BISO_PLAT_OpenExistFile(IN CONST CHAR *pcFileName);
BISO_FILE_S * BISO_PLAT_CreateNewFile(IN CONST CHAR *pcFileName);
VOID BISO_PLAT_CloseFile(IN BISO_FILE_S *pstFile);
INT64 BISO_PLAT_SeekFile(BISO_FILE_S *pstFile, INT64 i64Offset, INT iFromWhere);
UINT64 BISO_PLAT_ReadFile
(
IN BISO_FILE_S *pstFile,
IN UINT uiBlkSize,
IN UINT uiBlkNum,
OUT VOID *pBuf
);
UINT64 BISO_PLAT_WriteFile
(
IN BISO_FILE_S *pstFile,
IN UINT uiBlkSize,
IN UINT uiBlkNum,
IN VOID *pBuf
);
CHAR * BISO_PLAT_GetCurDir(VOID);
UINT64 BISO_UTIL_WholeFile2Buf(IN CONST CHAR *szFileName, OUT UCHAR *pucBuf);
#endif /* __BISO_H__ */

1458
VtoyTool/BabyISO/biso_9660.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,574 @@
/******************************************************************************
* bios_9660.h
*
* 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/>.
*
*/
#ifndef __BISO_9660_H__
#define __BISO_9660_H__
#define BISO_SECTOR_SIZE 2048
#define BISO_BLOCK_SIZE 2048
#define BISO_SYSTEM_AREA_SIZE (16 * BISO_SECTOR_SIZE)
/* Volume Descriptor */
#define BISO_VD_TYPE_BOOT 0
#define BISO_VD_TYPE_PVD 1
#define BISO_VD_TYPE_SVD 2
#define BISO_VD_TYPE_PART 3
#define BISO_VD_TYPE_END 255
#define BISO_VD_ID "CD001"
#define BISO_USED_SECTOR_NUM(uiFileSize) \
(uiFileSize / BISO_SECTOR_SIZE) + ((uiFileSize % BISO_SECTOR_SIZE > 0) ? 1 : 0)
#define BISO_9660_IS_CURRENT(pstDirRecord) \
(((1 == pstDirRecord->ucNameLen) && (0x0 == pstDirRecord->szName[0])) ? BOOL_TRUE : BOOL_FALSE)
#define BISO_9660_IS_PARENT(pstDirRecord) \
(((1 == pstDirRecord->ucNameLen) && (0x1 == pstDirRecord->szName[0])) ? BOOL_TRUE : BOOL_FALSE)
#define BISO_9600_FREE_STAT(pstDir) \
{ \
if (NULL != pstDir->pstDirStat) \
{ \
BISO_FREE(pstDir->pstDirStat); \
}\
}
#define BISO_9600_FREE_POSIX(pstDir) \
{ \
if (NULL != pstDir->pstPosixInfo) \
{ \
if (NULL != pstDir->pstPosixInfo->pcLinkSrc) \
{ \
BISO_FREE(pstDir->pstPosixInfo->pcLinkSrc); \
} \
BISO_FREE(pstDir->pstPosixInfo); \
} \
}
#define BISO_9600_FREE_DIRTREE(pstDir) \
{ \
BISO_9600_FREE_STAT(pstDir); \
BISO_9600_FREE_POSIX(pstDir); \
BISO_FREE(pstDir); \
}
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
#define BISO_DEF_723(usData) \
UINT16 usData;\
UINT16 usData##Swap;
#define BISO_DEF_733(uiData) \
UINT32 uiData;\
UINT32 uiData##Swap;
#define BISO_PATHTBL_LOCATION(pstPVD) (pstPVD->uiTypeLPathTblLoc)
#elif (__BYTE_ORDER == __BIG_ENDIAN)
#define BISO_DEF_723(usData) \
UINT16 usData##Swap;\
UINT16 usData;
#define BISO_DEF_733(uiData) \
UINT32 uiData##Swap;\
UINT32 uiData;
#define BISO_PATHTBL_LOCATION(pstPVD) (pstPVD->uiTypeMPathTblLoc)
#else
#error ("you must first define __BYTE_ORDER !!!")
#endif
#pragma pack(1)
typedef struct tagBISO_DATE_915
{
UCHAR ucYear; /* 1900+ */
UCHAR ucMonth;
UCHAR ucDay;
UCHAR ucHour;
UCHAR ucMin;
UCHAR ucSec;
CHAR cTimeZone;
}BISO_DATE_915_S;
typedef struct tagBISO_PATH_TABLE
{
UCHAR ucDirNameLen;
UCHAR ucExtAttrRecordLen;
UINT32 uiExtent;
UINT16 usParentDirNum;
CHAR szDirName[1];
/* UCHAR ucPadding; */
}BISO_PATH_TABLE_S;
#define BISO_9660_PATH_LEN(pstPath) (pstPath->ucDirNameLen + 8 + (pstPath->ucDirNameLen & 0x01))
typedef struct tagBISO_DIR_RECORD
{
UCHAR ucLength;
UCHAR ucExtAttrLen;
BISO_DEF_733(uiExtent)
BISO_DEF_733(uiSize)
BISO_DATE_915_S stDate;
UCHAR ucFlags;
UCHAR ucFileUnitSize;
UCHAR ucInterLeave;
BISO_DEF_723(uiVolumeSeqNum)
UCHAR ucNameLen;
CHAR szName[1];
/* UCHAR aucSystemUse[xxxx] */
}BISO_DIR_RECORD_S;
#define BISO_DIR_RECORD_IS_PATH(pstDirRecord) \
((1 == ((pstDirRecord->ucFlags >> 1) & 0x01)) ? BOOL_TRUE : BOOL_FALSE)
typedef struct tagBISO_VOLUME_DESC
{
UCHAR ucType;
CHAR szId[5];
UCHAR ucVersion;
UCHAR ucData[2041];
}BISO_VD_S;
typedef struct tagBISO_PRIMARY_VOLUME_DESC
{
UCHAR ucType;
CHAR szId[5];
/* ucVersion: version [ISODCL ( 7, 7)] */
UCHAR ucVersion;
/* ucResv1: unused1 [ISODCL ( 8, 8)] */
UCHAR ucResv1;
/*
* szSystemId[32]: system_id [ISODCL ( 9, 40)]
*/
CHAR szSystemId[32];
/* szVolumeId[32]: volume_id [ISODCL ( 41, 72)] */
CHAR szVolumeId[32];
/* aucResv2[8]: unused2 [ISODCL ( 73, 80)] */
UCHAR aucResv2[8];
BISO_DEF_733(uiVolumeSpace)
/* aucResv3[32]: unused3 [ISODCL ( 89, 120)] */
UCHAR aucResv3[32];
BISO_DEF_723(usVolumeSet)
/*
* usVolumeSeq: volume_sequence_number [ISODCL (125, 128)]
*/
BISO_DEF_723(usVolumeSeq)
/*
* usBlockSize: logical_block_size [ISODCL (129, 132)]
*/
BISO_DEF_723(usBlockSize)
/*
* uiPathTblSize: path_table_size [ISODCL (133, 140)]
*/
BISO_DEF_733(uiPathTblSize)
UINT32 uiTypeLPathTblLoc;
UINT32 uiOptTypeLPathTblLoc;
UINT32 uiTypeMPathTblLoc;
UINT32 uiOptTypeMPathTblLoc;
BISO_DIR_RECORD_S stRootDirRecord;
/* szVolumeSetId: volume_set_id [ISODCL (191, 318)] */
CHAR szVolumeSetId[128];
/* szPublisherId: publisher_id [ISODCL (319, 446)] */
CHAR szPublisherId[128];
/* szPreparerId: preparer_id [ISODCL (447, 574)] */
CHAR szPreparerId[128];
/* szApplicationId: application_id [ISODCL (575, 702)] */
CHAR szApplicationId[128];
/* szCopyrightFileId: copyright_file_id [ISODCL (703, 739)] [1] */
CHAR szCopyrightFileId[37];
/* szAbstractFileId: abstract_file_id [ISODCL (740, 776)] */
CHAR szAbstractFileId[37];
/* szBibliographicFileId: bibliographic_file_id [ISODCL (777, 813)] */
CHAR szBibliographicFileId[37];
/* szCreationDate: creation_date [ISODCL (814, 830)] */
CHAR szCreationDate[17];
/* szModifyDate: modification_date [ISODCL (831, 847)] */
CHAR szModifyDate[17];
/* szExpirationDate: expiration_date [ISODCL (848, 864)] */
CHAR szExpirationDate[17];
/* szEffectiveDate: effective_date [ISODCL (865, 881)] */
CHAR szEffectiveDate[17];
/* ucFileStructVer: file_structure_version [ISODCL (882, 882)] */
UCHAR ucFileStructVer;
/* ucResv4: unused4 [ISODCL (883, 883)] */
UCHAR ucResv4;
/* aucApplicationData: application_data [ISODCL (884, 1395)] */
UCHAR aucApplicationData[512];
/* ucResv5: unused5 [ISODCL (1396, 2048)] */
UCHAR aucResv5[653];
}BISO_PVD_S;
typedef struct tagBISO_SUPPLEMENTARY_VOLUME_DESC
{
UCHAR ucType;
/*
* szId[5]: id [ISODCL ( 2, 6)]
*/
CHAR szId[5];
/* ucVersion: version [ISODCL ( 7, 7)] */
UCHAR ucVersion;
/*
* ucFlags: flags [ISODCL ( 8, 8)]
*/
UCHAR ucFlags;
/*
* szSystemId[32]: system_id [ISODCL ( 9, 40)]
*/
CHAR szSystemId[32];
/* szVolumeId[32]: volume_id [ISODCL ( 41, 72)] 名称, 注意[1] */
CHAR szVolumeId[32];
/* aucResv2[8]: unused2 [ISODCL ( 73, 80)] */
UCHAR aucResv2[8];
/*
* uiVolumeSpace: volume_space_size [ISODCL ( 81, 88)]
*/
BISO_DEF_733(uiVolumeSpace)
/* aucEscape[32]: escape [ISODCL ( 89, 120)] */
UCHAR aucEscape[32];
/*
* usVolumeSet: volume_set_size [ISODCL (121, 124)]
*/
BISO_DEF_723(usVolumeSet)
/*
* usVolumeSeq: volume_sequence_number [ISODCL (125, 128)]
*/
BISO_DEF_723(usVolumeSeq)
/*
* usBlockSize: logical_block_size [ISODCL (129, 132)]
*/
BISO_DEF_723(usBlockSize)
BISO_DEF_733(uiPathTblSize)
UINT32 uiTypeLPathTblLoc;
UINT32 uiOptTypeLPathTblLoc;
UINT32 uiTypeMPathTblLoc;
UINT32 uiOptTypeMPathTblLoc;
BISO_DIR_RECORD_S stRootDirRecord;
/* szVolumeSetId: volume_set_id [ISODCL (191, 318)] */
CHAR szVolumeSetId[128];
/* szPublisherId: publisher_id [ISODCL (319, 446)] */
CHAR szPublisherId[128];
/* szPreparerId: preparer_id [ISODCL (447, 574)] */
CHAR szPreparerId[128];
/* szApplicationId: application_id [ISODCL (575, 702)] */
CHAR szApplicationId[128];
/* szCopyrightFileId: copyright_file_id [ISODCL (703, 739)] */
CHAR szCopyrightFileId[37];
/* szAbstractFileId: abstract_file_id [ISODCL (740, 776)]*/
CHAR szAbstractFileId[37];
/* szBibliographicFileId: bibliographic_file_id [ISODCL (777, 813)] */
CHAR szBibliographicFileId[37];
/* szCreationDate: creation_date [ISODCL (814, 830)]*/
CHAR szCreationDate[17];
/* szModifyDate: modification_date [ISODCL (831, 847)] */
CHAR szModifyDate[17];
/* szExpirationDate: expiration_date [ISODCL (848, 864)] */
CHAR szExpirationDate[17];
/* szEffectiveDate: effective_date [ISODCL (865, 881)] */
CHAR szEffectiveDate[17];
/* ucFileStructVer: file_structure_version [ISODCL (882, 882)] */
UCHAR ucFileStructVer;
/* ucResv4: unused4 [ISODCL (883, 883)] */
UCHAR ucResv4;
/* aucApplicationData: application_data [ISODCL (884, 1395)] */
UCHAR aucApplicationData[512];
/* ucResv5: unused5 [ISODCL (1396, 2048)] */
UCHAR aucResv5[653];
}BISO_SVD_S;
typedef struct tagBISO_BOOT_DESC
{
UCHAR ucType;
/*
* szId[5]: id [ISODCL ( 2, 6)]
*/
CHAR szId[5];
/* ucVersion: version [ISODCL ( 7, 7)] */
UCHAR ucVersion;
CHAR szBootSystemId[32];
UCHAR aucResv[32];
UINT32 uiBootCatlogStart;
UCHAR aucBootData[1972];
}BISO_BVD_S;
typedef struct tagBISO_EXTATTR_RECORD
{
BISO_DEF_723(usOwnerId)
BISO_DEF_723(usGroupId)
USHORT usPermission;
CHAR szFileCreateDate[17];
CHAR szFileModifyDate[17];
CHAR szFileExpirationDate[17];
CHAR szFileEffectiveDate[17];
UCHAR ucRecordFormat;
UCHAR ucRecordAttr;
BISO_DEF_723(usRecordLen)
CHAR szSystemId[32];
UCHAR aucSystemData[64];
UCHAR ucRecordVersion;
UCHAR ucEscapeLen;
UCHAR aucResv[64];
BISO_DEF_723(usAppDataLen)
/* UCHAR aucAppData[xxx]; */
/* UCHAR aucEscape[xxx]; */
}BISO_EXTATTR_RECORD_S;
#pragma pack()
typedef struct tagBISO_VD_NODE
{
BISO_DLL_NODE_S stNode;
BISO_VD_S stVD;
}BISO_VD_NODE_S;
typedef struct tagBISO_POSIX_INFO
{
BOOL_T bHasNMEntry;
UINT uiPosixFileMode;
UINT uiPosixFileLink;
UINT uiPosixFileUserId;
UINT uiPosixFileGroupId;
UINT uiPosixFileSNO;
UINT64 ui64DevNum;
BISO_DATE_S stCreateTime;
BISO_DATE_S stModifyTime;
BISO_DATE_S stLastAccessTime;
BISO_DATE_S stLastAttrChangeTime;
BISO_DATE_S stLastBackupTime;
BISO_DATE_S stExpirationTime;
BISO_DATE_S stEffectiveTime;
UINT uiLinkLen;
CHAR *pcLinkSrc;
}BISO_POSIX_INFO_S;
typedef struct tagBISO_SVD_DIR_TREE
{
struct tagBISO_SVD_DIR_TREE *pstParent;
struct tagBISO_SVD_DIR_TREE *pstNext;
struct tagBISO_SVD_DIR_TREE *pstChild;
UINT uiExtent;
UINT uiSize;
UINT64 ui64FileRecordOffset;
struct tagBISO_SVD_DIR_TREE *pstFileList;
}BISO_SVD_DIR_TREE_S;
typedef struct tagBISO_DIR_TREE
{
struct tagBISO_DIR_TREE *pstParent;
struct tagBISO_DIR_TREE *pstNext;
struct tagBISO_DIR_TREE *pstChild;
USHORT usNameLen;
CHAR szName[300];
UINT uiPathTblId;
UINT uiExtent;
UINT uiSize;
UINT64 ui64FileRecordOffset;
BISO_DIR_STAT_S *pstDirStat;
BISO_POSIX_INFO_S *pstPosixInfo;
struct tagBISO_DIR_TREE *pstFileList;
}BISO_DIR_TREE_S;
#define BISO_DIR_TREE_IS_SYMLINK(pstDirTree) \
(((NULL != pstDirTree->pstPosixInfo) && \
(NULL != pstDirTree->pstPosixInfo->pcLinkSrc)) ? BOOL_TRUE : BOOL_FALSE)
typedef struct tagBISO_PARSER
{
CHAR szFileName[1024];
BISO_PVD_S *pstPVD;
BISO_SVD_S *pstSVD;
BISO_BVD_S *pstBVD;
BISO_DLL_S stVDList;
UCHAR *pucPathTable;
UINT uiElToritoLen;
UCHAR *pucElToritoEntry;
UCHAR ucRRIPVersion;
UCHAR ucRRIPSkipLen;
BISO_DIR_TREE_S stDirTree;
BISO_SVD_DIR_TREE_S stSVDDirTree;
}BISO_PARSER_S;
ULONG BISO_9660_OpenImage
(
IN BOOL_T bParseSVDDirTree,
IN CONST CHAR *pcFileName,
OUT BISO_PARSER_S *pstParser
);
BISO_PARSER_S * BISO_9660_CreateParser(VOID);
VOID BISO_9660_DestroyParser(INOUT BISO_PARSER_S *pstParser);
ULONG BISO_9660_ParseDate84261
(
IN CONST CHAR *pcDate,
OUT BISO_DATE_S *pstDate
);
VOID BISO_9660_FmtDate84261(IN time_t ulTime, IN UINT uiBufSize, OUT CHAR *pcDate);
VOID BISO_9660_FillDfsStack
(
IN BISO_DIR_TREE_S *pstTop,
INOUT BISO_QUEUE_S *pstQueue
);
ULONG BISO_9660_ExtractFile
(
IN BISO_FILE_S *pstFile,
IN CONST CHAR *pcDstFullPath,
IN CONST BISO_DIR_TREE_S *pstFileNode,
IN CONST BISO_EXTRACT_CTRL_S *pstCtrl
);
/* 拼接路径 */
#define BISO_EXTRACE_CAT_PATH(szFullPath, uiCurPos, szName, NameLen) \
{\
memcpy(szFullPath + uiCurPos, szName, NameLen); \
uiCurPos += NameLen; \
szFullPath[uiCurPos++] = '/'; \
szFullPath[uiCurPos] = 0; \
}
/* 检查结果返回 */
#define BISO_9660_CHECK_RET(ulRet, pstFile) \
if (BISO_SUCCESS != ulRet) \
{ \
BISO_PLAT_CloseFile(pstFile); \
return ulRet; \
}
BISO_DIR_TREE_S * BISO_UTIL_FindLinkTgt(IN BISO_DIR_TREE_S *pstCurNode);
#endif /* __BISO_9660_H__ */

View File

@@ -0,0 +1,87 @@
/******************************************************************************
* biso_dump.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"
#include "biso_eltorito.h"
#include "biso_rockridge.h"
#include "biso_joliet.h"
#include "biso_dump.h"
VOID BISO_DUMP_ShowFileTree
(
IN UINT uiDepth,
IN CONST BISO_DIR_TREE_S *pstDirTree
)
{
UINT i;
if (NULL == pstDirTree)
{
return;
}
for (i = 0; i + 1 < uiDepth; i++)
{
BISO_DUMP(" ");
}
if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstDirTree))
{
BISO_DUMP("|-- %s --> %s", pstDirTree->szName, pstDirTree->pstPosixInfo->pcLinkSrc);
}
else
{
BISO_DUMP("|-- %s", pstDirTree->szName);
}
BISO_DUMP(" %u %u\n", pstDirTree->uiExtent, pstDirTree->uiSize);
#if 0
if (NULL != pstDirTree->pstDirStat)
{
BISO_DUMP(" ([%u %u %u] [%u %u %u]\n",
pstDirTree->pstDirStat->uiCurDirNum,
pstDirTree->pstDirStat->uiCurFileNum,
pstDirTree->pstDirStat->uiCurLinkNum,
pstDirTree->pstDirStat->uiTotDirNum,
pstDirTree->pstDirStat->uiTotFileNum,
pstDirTree->pstDirStat->uiTotLinkNum);
}
else
{
BISO_DUMP("\n");
}
#endif /* #if 0 */
/* 递归显示子目录 */
BISO_DUMP_ShowFileTree(uiDepth + 1, pstDirTree->pstChild);
/* 显示本目录内的文件列表 */
BISO_DUMP_ShowFileTree(uiDepth + 1, pstDirTree->pstFileList);
/* 显示下一个同级目录 */
BISO_DUMP_ShowFileTree(uiDepth, pstDirTree->pstNext);
}

View File

@@ -0,0 +1,83 @@
/******************************************************************************
* biso_dump.h
*
* 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/>.
*
*/
#ifndef __BISO_DUMP_H__
#define __BISO_DUMP_H__
#define BISO_DUMP_INT(Name, Value) BISO_DUMP("%-24s : %u\n", Name, Value)
#define BISO_DUMP_STR(Name, Value, szBuf) \
BISO_DUMP("%-24s : %s\n", Name, BISO_UTIL_CopyStr(Value, sizeof(Value), szBuf))
#define BISO_DUMP_CHAR(str, len) \
{\
UINT uiLoop;\
for (uiLoop = 0; uiLoop < (UINT)len; uiLoop++)\
{\
BISO_DUMP("%c", str[uiLoop]);\
}\
BISO_DUMP("\n");\
}
#define BISO_DUMP_BYTE(Buf, Len) \
{ \
UINT i; \
for (i = 0; i < Len; i++) \
{ \
BISO_DUMP("%02x ", Buf[i]); \
} \
BISO_DUMP("\n"); \
}
/* 显示日期 */
#define BISO_DUMP_DAY(Name, Value) \
{\
ULONG _ulRet;\
BISO_DATE_S _stDate;\
_ulRet = BISO_9660_ParseDate84261((Value), &_stDate);\
if (BISO_SUCCESS == _ulRet)\
{\
BISO_DUMP("%-24s : %04u-%02u-%02u %02u:%02u:%02u.%03u ",\
(Name), _stDate.usYear, _stDate.ucMonth, _stDate.ucDay,\
_stDate.ucHour, _stDate.ucMin, _stDate.ucSecond,\
_stDate.usMillSec);\
if (_stDate.cZone > 0)\
{\
BISO_DUMP("GMT+%d\n", _stDate.cZone);\
}\
else\
{\
BISO_DUMP("GMT%d\n", _stDate.cZone);\
}\
}\
else\
{\
BISO_DUMP("%-24s : ---\n", (Name));\
}\
}
VOID BISO_DUMP_ShowFileTree
(
IN UINT uiDepth,
IN CONST BISO_DIR_TREE_S *pstDirTree
);
#endif /* __BISO_DUMP_H__ */

View File

@@ -0,0 +1,161 @@
/******************************************************************************
* bios_eltorito.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"
#include "biso_eltorito.h"
ULONG BISO_ELTORITO_ReadBootInfo
(
IN BISO_FILE_S *pstFile,
OUT BISO_PARSER_S *pstParser
)
{
USHORT i;
UINT uiReadLen = 0;
UINT64 ui64Seek = 0;
UCHAR aucBuf[BISO_SECTOR_SIZE];
BISO_MBUF_S stMBuf;
BISO_TORITO_SECHDR_ENTRY_S *pstSecHdr = NULL;
BISO_TORITO_SECTION_ENTRY_S *pstSection = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
if (NULL == pstParser->pstBVD)
{
return BISO_SUCCESS;
}
memset(&stMBuf, 0, sizeof(stMBuf));
ui64Seek = (UINT64)pstParser->pstBVD->uiBootCatlogStart * BISO_SECTOR_SIZE;
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
/* 先读取1个逻辑扇区的内容 */
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, BISO_SECTOR_SIZE, aucBuf);
if (uiReadLen != BISO_SECTOR_SIZE)
{
BISO_DIAG("Read len %u buf len %u.", uiReadLen, BISO_SECTOR_SIZE);
return BISO_ERR_READ_FILE;
}
/* 前两条Entry固定是Validation和Initial */
pstSecHdr = (BISO_TORITO_SECHDR_ENTRY_S *)(aucBuf + 2 * BISO_ELTORITO_ENTRY_LEN);
pstSection = (BISO_TORITO_SECTION_ENTRY_S *)pstSecHdr;
while ((0x90 == pstSecHdr->ucFlag) || (0x91 == pstSecHdr->ucFlag))
{
pstSecHdr = (BISO_TORITO_SECHDR_ENTRY_S *)pstSection;
BISO_ELTORITO_ENTRY_STEP(pstSection, pstFile, aucBuf, stMBuf);
for (i = 0; i < pstSecHdr->usSecEntryNum; )
{
/*
* Section Entry和Extension Entry都是由ucFlag的Bit5决定是否结束
* 因此这里全部都用Section Entry的结构做判断
*/
if (0 == (pstSection->ucFlag & 0x10))
{
i++;
}
BISO_ELTORITO_ENTRY_STEP(pstSection, pstFile, aucBuf, stMBuf);
}
if (0x91 == pstSecHdr->ucFlag) /* 91代表最后一个 */
{
break;
}
}
if ((UCHAR *)pstSection > aucBuf)
{
(VOID)BISO_MBUF_Append(&stMBuf, (UCHAR *)pstSection - aucBuf, aucBuf);
}
/* 保存到全局结构中 */
pstParser->uiElToritoLen = stMBuf.uiTotDataSize;
pstParser->pucElToritoEntry = (UCHAR *)BISO_MALLOC(pstParser->uiElToritoLen);
if (NULL == pstParser->pucElToritoEntry)
{
BISO_MBUF_Free(&stMBuf);
return BISO_ERR_ALLOC_MEM;
}
BISO_MBUF_CopyToBuf(&stMBuf, pstParser->pucElToritoEntry);
BISO_MBUF_Free(&stMBuf);
return BISO_SUCCESS;
}
VOID BISO_ELTORITO_Dump(IN CONST BISO_PARSER_S *pstParser)
{
BISO_DUMP("uiElToritoLen=%u\n", pstParser->uiElToritoLen);
}
UINT BISO_ELTORITO_GetBootEntryNum(IN CONST BISO_PARSER_S *pstParser)
{
UINT uiRet = 0;
UINT uiEntryNum = 0;
UCHAR *pucData = NULL;
BISO_TORITO_VALIDATION_ENTRY_S *pstValidation = NULL;
BISO_TORITO_INITIAL_ENTRY_S *pstInitial = NULL;
if (NULL == pstParser->pucElToritoEntry)
{
return 0;
}
uiEntryNum = pstParser->uiElToritoLen / BISO_ELTORITO_ENTRY_LEN;
pstValidation = (BISO_TORITO_VALIDATION_ENTRY_S *)pstParser->pucElToritoEntry;
pstInitial = (BISO_TORITO_INITIAL_ENTRY_S *)(pstValidation + 1);
if (pstInitial->ucBootId == 0x88)
{
uiRet++;
}
pucData = pstParser->pucElToritoEntry + 2 * BISO_ELTORITO_ENTRY_LEN;
uiEntryNum-= 2;
while (uiEntryNum > 0)
{
if ((0x90 == pucData[0]) || (0x91 == pucData[0]))
{
}
else if (0x44 == pucData[0])
{
}
else
{
if (((BISO_TORITO_SECTION_ENTRY_S *)pucData)->ucBootId == 0x88)
{
uiRet++;
}
}
pucData += BISO_ELTORITO_ENTRY_LEN;
uiEntryNum--;
}
return uiRet;
}

View File

@@ -0,0 +1,246 @@
/******************************************************************************
* bios_eltorito.h
*
* 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/>.
*
*/
/*
* EL TORITO扩展规范相关定义
* 注意点:
* [1] EL TORITO扩展规范里定义的数据都是小字节序的
*/
#ifndef __BISO_ELTORITO_H__
#define __BISO_ELTORITO_H__
/*
* EL TORITO规范里对于Boot Record里面BootCatlog指向的扩展区域做了
* 结构定义分成一条条的表项每一条表项固定32个字节长,1个扇区
* 可以保存64条表项。BootCatlog可以占用多个扇区。
* 表项必须按照如下顺序保存:
* ID Entry
* 0 Validation Entry
* 1 Initial Entry
* 2 Section Header
* 3 Section Entry
* 4 Section Extension Entry 1
* 5 Section Extension Entry 2
* 6 Section Extension Entry 3
* ....
* N Section Header
* N+1 Section Entry
* N+2 Section Extension Entry 1
* N+3 Section Extension Entry 2
* N+4 Section Extension Entry 3
* ....
*/
#define BISO_ELTORITO_ENTRY_LEN 32
#pragma pack(1)
/* 检验表项, 必须是第一条 */
typedef struct tagBISO_TORITO_VALIDATION_ENTRY
{
UCHAR ucHeaderID; /* Must be 01 */
/*
* PlatID: CPU平台架构
* 0x00: x86
* 0x01: PowerPC
* 0x02: Mac
* 0xEF: EFI System Partition
*/
UCHAR ucPlatID;
UINT16 usResv;
/* ID一般用来保存CD-ROM的制造商信息 */
CHAR szID[24];
/*
* 校验补充字段, 注意[1]
* 这个字段用来保证整个Validation Entry的数据
* 按照WORD(双字节)累加起来为0(截取之后)
*/
UINT16 usCheckSum;
/* 魔数字检验使用值必须为0x55和0xAA */
UCHAR ucData55;
UCHAR ucDataAA;
}BISO_TORITO_VALIDATION_ENTRY_S;
/* 默认初始化表项(BIOS里面的 INT 13) */
typedef struct tagBISO_TORITO_INITIAL_ENTRY
{
/* BOOTID: 0x88:Bootable, 00:Not Bootable */
UCHAR ucBootId;
/*
* ucBootMedia:
* Bit0 - Bit3的值:
* 0: No Emulation
* 1: 1.2 meg diskette
* 2: 1.44 meg diskette
* 3: 2.88 meg diskette
* 4: Hard Disk(drive 80)
* 5-F:保留
* Bit4 - Bit7:保留
*/
UCHAR ucBootMedia;
/* 启动段只对x86构架有效为0默认使用7C0, 注意[1] */
UINT16 usLoadSegment;
/* 是Boot Image里面Partition Table的第5个字节(System Type) */
UCHAR ucSystemType;
UCHAR ucResv;
/* 启动时每次往内存读多长, 注意[1] */
UINT16 usSectorCount;
/* 启动文件所在的起始逻辑块编号例如isolinux.bin文件的位置, 注意[1] */
UINT32 uiLoadRBA;
UCHAR aucResv[20];
}BISO_TORITO_INITIAL_ENTRY_S;
/*
* Section Header, 补充一系列可启动的Entry(比如UEFI启动)
* 如果默认的Initial/Default Entry不满足BIOS需求
* BIOS可以继续往下找根据Section Header里面的ID
* 以及Section Entry里面的Criteria信息决定是否从
* 该条Entry启动
*
*/
typedef struct tagBISO_TORITO_SECHDR_ENTRY
{
/* ucFlag: 0x90:表示后面还有Header, 0x91:表示最后一个Header */
UCHAR ucFlag;
/*
* PlatID: CPU平台架构
* 0x00: x86
* 0x01: PowerPC
* 0x02: Mac
* 0xEF: EFI System Partition
*/
UCHAR ucPlatID;
/* 跟在这个头的后面有多少个Section Entry */
UINT16 usSecEntryNum;
/* ID信息 */
CHAR szId[28];
}BISO_TORITO_SECHDR_ENTRY_S;
/* Section Entry */
typedef struct tagBISO_TORITO_SECTION_ENTRY
{
/* BOOTID: 88:Bootable, 00:Not Bootable */
UCHAR ucBootId;
/*
* ucBootMedia:
* Bit0 - Bit3的值:
* 0: No Emulation
* 1: 1.2 meg diskette
* 2: 1.44 meg diskette
* 3: 2.88 meg diskette
* 4: Hard Disk(drive 80)
* 5-F:保留
* Bit4:保留
* Bit5:Continuation Entry Follows
* Bit6:Image contains an ATAPI driver
* Bit7:Image contains SCSI driver
*/
UCHAR ucFlag;
/* 启动段只对x86构架有效为0默认使用7C0, 注意[1] */
UINT16 usLoadSegment;
/* 是Boot Image里面Partition Table的第5个字节(System Type) */
UCHAR ucSystemType;
UCHAR ucResv;
/* 启动时每次往内存读多长, 注意[1] */
UINT16 usSectorCount;
/* 启动文件所在的起始逻辑块编号例如isolinux.bin文件的位置, 注意[1] */
UINT32 uiLoadRBA;
/*
* 它的值描述了后面的aucCriteria的格式
* 0: 没有
* 1: Language and Version Information (IBM)
* 2-FF - Reserved
*/
UCHAR ucCriteriaType;
/* Criteria信息如果这19个字节不够用可以使用Section Extension Entry里的 */
UCHAR aucCriteria[19];
}BISO_TORITO_SECTION_ENTRY_S;
/* 扩展Section Entry */
typedef struct tagBISO_TORITO_SECEXT_ENTRY
{
/* ucExtId: 必须为44 */
UCHAR ucExtId;
/*
* ucFlag: 只有Bit5有用
* Bit5: 1表示后面还有Extension Record 0表示最后一个
*/
UCHAR ucFlag;
/* Criteria信息 */
UCHAR aucCriteria[39];
}BISO_TORITO_SECEXT_ENTRY_S;
#pragma pack()
/*
* 当前缓冲区指针位置向前1条Entry
* 如果已经超过了2048字节则继续从文件中读
*/
#define BISO_ELTORITO_ENTRY_STEP(pstSection, pstFile, aucBuf, stMBuf) \
{\
UINT _uiReadLen;\
pstSection++;\
if ((UCHAR *)pstSection >= aucBuf + BISO_SECTOR_SIZE)\
{\
(VOID)BISO_MBUF_Append(&stMBuf, BISO_SECTOR_SIZE, aucBuf);\
_uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, BISO_SECTOR_SIZE, aucBuf);\
if (_uiReadLen != BISO_SECTOR_SIZE)\
{\
BISO_DIAG("Read Len %u, sector len %u.", _uiReadLen, BISO_SECTOR_SIZE);\
BISO_MBUF_Free(&stMBuf);\
return BISO_ERR_READ_FILE;\
}\
pstSection = (BISO_TORITO_SECTION_ENTRY_S *)aucBuf;\
}\
}
ULONG BISO_ELTORITO_ReadBootInfo(IN BISO_FILE_S *pstFile, OUT BISO_PARSER_S *pstParser);
VOID BISO_ELTORITO_Dump(IN CONST BISO_PARSER_S *pstParser);
UINT BISO_ELTORITO_GetBootEntryNum(IN CONST BISO_PARSER_S *pstParser);
#endif /* __BISO_ELTORITO_H__ */

View File

@@ -0,0 +1,53 @@
/******************************************************************************
* biso_joliet.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_joliet.h"
UCHAR BISO_JOLIET_GetLevel(IN CONST UCHAR *pucEscape)
{
UCHAR ucLevel = 0;
/*
* Standard Level Decimal Hex Bytes ASCII
* UCS-2 Level 1 2/5, 2/15, 4/0 (25)(2F)(40) '%\@'
* UCS-2 Level 2 2/5, 2/15, 4/3 (25)(2F)(43) '%\C'
* UCS-2 Level 3 2/5, 2/15, 4/5 (25)(2F)(45) '%\E
*/
if ((NULL != pucEscape) && (0x25 == pucEscape[0]) && (0x2F == pucEscape[1]))
{
if (0x40 == pucEscape[2])
{
ucLevel = 1;
}
else if (0x43 == pucEscape[2])
{
ucLevel = 2;
}
else if (0x45 == pucEscape[2])
{
ucLevel = 3;
}
}
return ucLevel;
}

View File

@@ -0,0 +1,28 @@
/******************************************************************************
* biso_joliet.h
*
* 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/>.
*
*/
#ifndef __BISO_JOLIET_H__
#define __BISO_JOLIET_H__
UCHAR BISO_JOLIET_GetLevel(IN CONST UCHAR *pucEscape);
#endif /* __BISO_JOLIET_H__ */

View File

@@ -0,0 +1,98 @@
/******************************************************************************
* biso_list.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"
VOID BISO_DLL_Init(OUT BISO_DLL_S *pstList)
{
pstList->stHead.pstNext = &(pstList->stHead);
pstList->stHead.pstPre = &(pstList->stHead);
pstList->pstTail = &(pstList->stHead);
pstList->uiCount = 0;
}
VOID BISO_DLL_AddTail
(
IN BISO_DLL_S *pstList,
IN BISO_DLL_NODE_S *pstNode
)
{
pstList->pstTail->pstNext = pstNode;
pstNode->pstNext = NULL;
pstNode->pstPre = pstList->pstTail;
pstList->pstTail = pstNode;
pstList->uiCount++;
}
VOID BISO_DLL_DelHead(IN BISO_DLL_S *pstList)
{
BISO_DLL_NODE_S *pstFirst = BISO_DLL_First(pstList);
if (NULL != pstFirst)
{
if (1 == BISO_DLL_Count(pstList)) /* 唯一节点 */
{
BISO_DLL_Init(pstList);
}
else
{
pstFirst->pstNext->pstPre = &(pstList->stHead);
pstList->stHead.pstNext = pstFirst->pstNext;
pstList->uiCount--;
}
}
}
VOID BISO_DLL_DelTail(IN BISO_DLL_S *pstList)
{
BISO_DLL_NODE_S *pstLast = BISO_DLL_Last(pstList);
if (NULL != pstLast)
{
if (1 == BISO_DLL_Count(pstList)) /* 唯一节点 */
{
BISO_DLL_Init(pstList);
}
else
{
pstLast->pstPre->pstNext = NULL;
pstList->pstTail = pstLast->pstPre;
pstList->uiCount--;
}
}
}
VOID BISO_DLL_Free(IN BISO_DLL_S *pstList)
{
BISO_DLL_NODE_S *pstFirst = BISO_DLL_First(pstList);
while (NULL != pstFirst)
{
/* 每次都摘掉头节点 */
BISO_DLL_DelHead(pstList);
/* 使用free释放节点 */
BISO_FREE(pstFirst);
pstFirst = BISO_DLL_First(pstList);
}
}

View File

@@ -0,0 +1,55 @@
/******************************************************************************
* biso_list.h
*
* 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/>.
*
*/
#ifndef __BISO_LIST_H__
#define __BISO_LIST_H__
/* 简单链表的实现 */
typedef struct tagBISO_DLL_NODE{
struct tagBISO_DLL_NODE *pstPre; /* Points to The Previous Node In The List */
struct tagBISO_DLL_NODE *pstNext; /* Points to The Next Node In The List */
}BISO_DLL_NODE_S;
typedef struct tagBISO_DLL{
BISO_DLL_NODE_S stHead; /* 链表头 */
BISO_DLL_NODE_S *pstTail; /* 链表尾 */
UINT uiCount; /* 链表节点个数 */
}BISO_DLL_S;
#define BISO_DLL_Count(pList) ((pList)->uiCount)
#define BISO_DLL_First(pList) ((BISO_DLL_Count((pList)) == 0) ? NULL: (pList)->stHead.pstNext)
#define BISO_DLL_Last(pList) ((BISO_DLL_Count((pList)) == 0) ? NULL : (pList)->pstTail)
#define BISO_DLL_Next(pList, pNode) \
(((pNode) == NULL) ? BISO_DLL_First(pList) : \
(((pNode)->pstNext == &(pList)->stHead) ? NULL : (pNode)->pstNext))
VOID BISO_DLL_Init(OUT BISO_DLL_S *pstList);
VOID BISO_DLL_AddTail
(
IN BISO_DLL_S *pstList,
IN BISO_DLL_NODE_S *pstNode
);
VOID BISO_DLL_DelHead(IN BISO_DLL_S *pstList);
VOID BISO_DLL_DelTail(IN BISO_DLL_S *pstList);
VOID BISO_DLL_Free(IN BISO_DLL_S *pstList);
#endif /* __BISO_LIST_H__ */

View File

@@ -0,0 +1,29 @@
/******************************************************************************
* biso_plat.h
*
* 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/>.
*
*/
#ifndef __BISO_PLAT_H__
#define __BISO_PLAT_H__
ULONG BISO_PLAT_Symlink(IN CONST CHAR *pcSrcPath, IN CONST CHAR *pcDstPath);
#endif /* __BISO_PLAT_H__ */

View File

@@ -0,0 +1,84 @@
/******************************************************************************
* biso_plat_linux.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/>.
*
*/
#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <utime.h>
#include <unistd.h>
#include "biso.h"
#include "biso_list.h"
#include "biso_util.h"
#include "biso_plat.h"
UINT64 vtoydm_get_file_size(const char *pcFileName);
BISO_FILE_S * vtoydm_open_file(const char *pcFileName);
void vtoydm_close_file(BISO_FILE_S *pstFile);
INT64 vtoydm_seek_file(BISO_FILE_S *pstFile, INT64 i64Offset, INT iFromWhere);
UINT64 vtoydm_read_file
(
BISO_FILE_S *pstFile,
UINT uiBlkSize,
UINT uiBlkNum,
VOID *pBuf
);
UINT64 BISO_PLAT_GetFileSize(IN CONST CHAR *pcFileName)
{
return vtoydm_get_file_size(pcFileName);
}
BISO_FILE_S * BISO_PLAT_OpenExistFile(IN CONST CHAR *pcFileName)
{
return vtoydm_open_file(pcFileName);
}
VOID BISO_PLAT_CloseFile(IN BISO_FILE_S *pstFile)
{
return vtoydm_close_file(pstFile);
}
INT64 BISO_PLAT_SeekFile(BISO_FILE_S *pstFile, INT64 i64Offset, INT iFromWhere)
{
return vtoydm_seek_file(pstFile, i64Offset, iFromWhere);
}
UINT64 BISO_PLAT_ReadFile
(
IN BISO_FILE_S *pstFile,
IN UINT uiBlkSize,
IN UINT uiBlkNum,
OUT VOID *pBuf
)
{
return vtoydm_read_file(pstFile, uiBlkSize, uiBlkNum, pBuf);
}
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@@ -0,0 +1,567 @@
/******************************************************************************
* biso_rockridge.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"
#include "biso_dump.h"
#include "biso_rockridge.h"
/* Rock Ridge扩展处理函数数组, NULL表示暂时不处理这类表项 */
STATIC BISO_RRIP_PARSE_ENTRY_CB_S g_astBISO_RRIP_ParseFunc[] =
{
{ "CE", NULL },
{ "PD", NULL },
{ "SP", NULL },
{ "ST", NULL },
{ "ER", NULL },
{ "ES", NULL },
{ "RR", NULL },
{ "PX", BISO_RRIP_GetPXInfo },
{ "PN", BISO_RRIP_GetPNInfo },
{ "SL", BISO_RRIP_GetSLInfo },
{ "NM", BISO_RRIP_GetNMInfo },
{ "CL", NULL },
{ "PL", NULL },
{ "RE", NULL },
{ "TF", BISO_RRIP_GetTFInfo },
{ "SF", NULL },
};
STATIC VOID BISO_RRIP_AddLinkBuf
(
IN CHAR *pcBuf,
IN UINT uiBufLen,
INOUT BISO_POSIX_INFO_S *pstPosixInfo
)
{
CHAR *pcNewBuf = NULL;
DBGASSERT(NULL != pstPosixInfo);
DBGASSERT(NULL != pcBuf);
/*
* 这里采用的是最简单的每次重新申请大内存保存老数据和新数据的方式
* 实际上效率是比较低的但是由于普通ISO文件中link类型本身就不多
* 而有连续多条SL表项的就更少了所以这里只是简单实现功能没有特别考虑效率
*/
/* 申请一个新Buf用于保存原有的数据和这次的新数据 */
pcNewBuf = (CHAR *)BISO_ZALLOC(uiBufLen + pstPosixInfo->uiLinkLen);
if (NULL == pcNewBuf)
{
return;
}
if (NULL == pstPosixInfo->pcLinkSrc)
{
memcpy(pcNewBuf, pcBuf, uiBufLen);
}
else
{
/* 分别保存新老数据同时把老的Buf释放掉 */
memcpy(pcNewBuf, pstPosixInfo->pcLinkSrc, pstPosixInfo->uiLinkLen);
memcpy(pcNewBuf + pstPosixInfo->uiLinkLen, pcBuf, uiBufLen);
BISO_FREE(pstPosixInfo->pcLinkSrc);
}
/* 更新数据Buf */
pstPosixInfo->pcLinkSrc = pcNewBuf;
pstPosixInfo->uiLinkLen += uiBufLen;
}
STATIC UINT BISO_RRIP_CalcLinkLen
(
IN CONST CHAR *pcComponet,
IN UINT uiComponetLen
)
{
UINT uiBufLen = 0;
UINT uiOffset = 0;
UINT uiTotLen = 0;
BISO_RRIP_SL_COMPONENT_S *pstComp = NULL;
DBGASSERT(NULL != pcComponet);
DBGASSERT(uiComponetLen > 0);
/* 拼接出链接的源路径 */
while (uiOffset < uiComponetLen)
{
uiBufLen = 0;
pstComp = (BISO_RRIP_SL_COMPONENT_S *)(pcComponet + uiOffset);
if (BOOL_TRUE == BISO_SLCOMP_IS_ROOT(pstComp->ucFlags))
{
/* ROOT不需处理后面会添加/ */
}
else if (BOOL_TRUE == BISO_SLCOMP_IS_CURRENT(pstComp->ucFlags))
{
uiBufLen = 1; /* . */
}
else if (BOOL_TRUE == BISO_SLCOMP_IS_PARENT(pstComp->ucFlags))
{
uiBufLen = 2; /* .. */
}
else
{
uiBufLen = pstComp->ucLength;
}
/* ucLength不包括头两个字节 */
uiOffset += pstComp->ucLength + 2;
/*
* 如果是link路径的一部分完结,则需要在后面加上'/',否则不加.
* 不加的情况有两种: 1是整体已经完了 2是路径的一部分还没有完整
* 比如说链接的位置是 /root/xxxx/a.txt 而xxxx可能非常长(200+个字符)
* 那么此时光xxxx的部分可能就需要两个Componet部分才能表达完,而这两个
* 之间是不能加反斜杠的.
*/
if ((uiOffset < uiComponetLen) && (BOOL_TRUE != BISO_SLCOMP_IS_CONTINUE(pstComp->ucFlags)))
{
uiBufLen++;
}
uiTotLen += uiBufLen;
}
return uiTotLen;
}
STATIC UINT BISO_RRIP_GetPartLink
(
IN CONST BISO_RRIP_SL_COMPONENT_S *pstComponent,
IN UINT uiBufSize,
OUT CHAR *pcBuf
)
{
UINT uiBufLen = 0;
DBGASSERT(NULL != pstComponent);
DBGASSERT(NULL != pcBuf);
if (BOOL_TRUE == BISO_SLCOMP_IS_ROOT(pstComponent->ucFlags))
{
/* ROOT不需处理后面会添加/ */
}
else if (BOOL_TRUE == BISO_SLCOMP_IS_CURRENT(pstComponent->ucFlags))
{
scnprintf(pcBuf, uiBufSize, ".");
uiBufLen = 1;
}
else if (BOOL_TRUE == BISO_SLCOMP_IS_PARENT(pstComponent->ucFlags))
{
scnprintf(pcBuf, uiBufSize, "..");
uiBufLen = 2;
}
else
{
memcpy(pcBuf, pstComponent->aucData, pstComponent->ucLength);
uiBufLen = pstComponent->ucLength;
}
return uiBufLen;
}
STATIC BOOL_T BISO_RRIP_IsThisType(IN BISO_SUSP_ENTRY_S *pstEntry, IN CONST CHAR *pcType)
{
if (NULL == pstEntry || NULL == pcType)
{
return BOOL_FALSE;
}
if ((pstEntry->cSignature1 == pcType[0]) && (pstEntry->cSignature2 == pcType[1]))
{
return BOOL_TRUE;
}
return BOOL_FALSE;
}
STATIC UCHAR * BISO_RRIP_GetSysUseArea
(
IN BISO_FILE_S *pstFile,
IN UCHAR *pucSysUseField,
IN UINT uiSysUseFieldLen,
OUT UINT *puiAreaSize
)
{
UINT uiCELen = 0;
UINT uiCurPos = 0;
UINT uiReadLen = 0;
UINT64 ui64Seek = 0;
UCHAR *pucSysUseArea = NULL;
BISO_SUSP_ENTRY_S *pstEntry = NULL;
BISO_SUSP_ENTRY_CE_S *pstCEEntry = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pucSysUseField);
DBGASSERT(NULL != puiAreaSize);
/*
* 虽然Rock Ridge扩展标准中允许整个System Use Area中有多个CE表项来扩展
* 但是由于一条CE表项可以扩展的长度就足够了(32bit) 所以这里我感觉正常情况下
* 没有必要使用多个CE表项扩展空间。因此这里只支持1条CE表项的情况。
*/
/* 遍历当前System Use Field, 标准规定剩余空间小于4字节,则后面的忽略 */
for (uiCurPos = 0; uiCurPos + 4 < uiSysUseFieldLen; uiCurPos += pstEntry->ucEntryLen)
{
pstEntry = (BISO_SUSP_ENTRY_S *)(pucSysUseField + uiCurPos);
/* 找到1个CE表项就停止这里默认CE表项是最后一条表项 */
if (BOOL_TRUE == BISO_RRIP_IsThisType(pstEntry, "CE"))
{
pstCEEntry = (BISO_SUSP_ENTRY_CE_S *)pstEntry;
uiCELen = pstCEEntry->uiContinuationLen;
/* BISO_DUMP_ShowSUSPEntry(pstCEEntry); */
break;
}
}
/* 申请一块内存把这两部分合并起来 */
pucSysUseArea = (UCHAR *)BISO_MALLOC(uiCurPos + uiCELen);
if (NULL == pucSysUseArea)
{
return NULL;
}
/* 先拷贝System Use Field字段 */
memcpy(pucSysUseArea, pucSysUseField, uiCurPos);
/* 如果有CE表项则再同文件中读出CE部分的数据 */
if (NULL != pstCEEntry)
{
ui64Seek = (UINT64)pstCEEntry->uiBlockLoc * BISO_BLOCK_SIZE + pstCEEntry->uiByteOffset;
BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, uiCELen, pucSysUseArea + uiCurPos);
if (uiReadLen != uiCELen)
{
BISO_DIAG("Read len %u buf len %u.", uiReadLen, uiCELen);
BISO_FREE(pucSysUseArea);
return NULL;
}
}
*puiAreaSize = uiCurPos + uiCELen;
return pucSysUseArea;
}
VOID BISO_RRIP_GetPXInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree)
{
BISO_POSIX_INFO_S *pstPosixInfo = NULL;
BISO_ROCK_RIDGE_ENTRY_PX_S *pstPXEntry = NULL;
DBGASSERT(NULL != pEntry);
DBGASSERT(NULL != pstDirTree);
DBGASSERT(NULL != pstDirTree->pstPosixInfo);
pstPXEntry = (BISO_ROCK_RIDGE_ENTRY_PX_S *)pEntry;
pstPosixInfo = pstDirTree->pstPosixInfo;
pstPosixInfo->uiPosixFileMode = pstPXEntry->uiPosixFileMode;
pstPosixInfo->uiPosixFileLink = pstPXEntry->uiPosixFileLink;
pstPosixInfo->uiPosixFileUserId = pstPXEntry->uiPosixFileUserId;
pstPosixInfo->uiPosixFileGroupId = pstPXEntry->uiPosixFileGroupId;
pstPosixInfo->uiPosixFileSNO = pstPXEntry->uiPosixFileSNO;
}
VOID BISO_RRIP_GetNMInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree)
{
BISO_ROCK_RIDGE_ENTRY_NM_S *pstNMEntry = NULL;
DBGASSERT(NULL != pEntry);
DBGASSERT(NULL != pstDirTree);
DBGASSERT(NULL != pstDirTree->pstPosixInfo);
pstNMEntry = (BISO_ROCK_RIDGE_ENTRY_NM_S *)pEntry;
/* 如有NM表项就替换ISO9660文件名 */
if (BOOL_TRUE != pstDirTree->pstPosixInfo->bHasNMEntry)
{
pstDirTree->pstPosixInfo->bHasNMEntry = BOOL_TRUE;
memset(pstDirTree->szName, 0, sizeof(pstDirTree->szName));
pstDirTree->usNameLen = 0;
}
/*
* 拼接文件名, 有可能本函数会多次调用,多次拼接(文件名超长的情况)
* TODO: 是否需要关注字符编码???
*/
strncat(pstDirTree->szName, pstNMEntry->szFileName, pstNMEntry->ucEntryLen - 5);
pstDirTree->usNameLen += pstNMEntry->ucEntryLen - 5;
}
VOID BISO_RRIP_GetTFInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree)
{
UINT i;
UCHAR *pucCur = NULL;
BISO_DATE_915_S *pst915Date = NULL;
BISO_ROCK_RIDGE_ENTRY_TF_S *pstTFEntry = NULL;
BISO_DATE_S *apstDate[] =
{
&(pstDirTree->pstPosixInfo->stCreateTime),
&(pstDirTree->pstPosixInfo->stModifyTime),
&(pstDirTree->pstPosixInfo->stLastAccessTime),
&(pstDirTree->pstPosixInfo->stLastAttrChangeTime),
&(pstDirTree->pstPosixInfo->stLastBackupTime),
&(pstDirTree->pstPosixInfo->stExpirationTime),
&(pstDirTree->pstPosixInfo->stEffectiveTime)
};
DBGASSERT(NULL != pEntry);
DBGASSERT(NULL != pstDirTree);
DBGASSERT(NULL != pstDirTree->pstPosixInfo);
pstTFEntry = (BISO_ROCK_RIDGE_ENTRY_TF_S *)pEntry;
pucCur = pstTFEntry->aucTimeStamp;
for (i = 0; i < ARRAY_SIZE(apstDate); i++)
{
/* 比特位0说明该时间戳没有记录 */
if (0 == ((pstTFEntry->ucFlags >> i) & 0x1))
{
continue;
}
/* Bit7决定是按照哪种格式记录的 */
if ((pstTFEntry->ucFlags >> 7) & 0x1)
{
(VOID)BISO_9660_ParseDate84261((CHAR *)pucCur, apstDate[i]);
pucCur += 17;
}
else
{
pst915Date = (BISO_DATE_915_S *)pucCur;
pucCur += 7;
apstDate[i]->usYear = pst915Date->ucYear + 1900;
apstDate[i]->ucMonth = pst915Date->ucMonth;
apstDate[i]->ucDay = pst915Date->ucDay;
apstDate[i]->ucHour = pst915Date->ucHour;
apstDate[i]->ucMin = pst915Date->ucMin;
apstDate[i]->ucSecond = pst915Date->ucSec;
apstDate[i]->usMillSec = 0;
apstDate[i]->cZone = pst915Date->cTimeZone / 4;
}
}
}
VOID BISO_RRIP_GetPNInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree)
{
BISO_ROCK_RIDGE_ENTRY_PN_S *pstPNEntry = NULL;
DBGASSERT(NULL != pEntry);
DBGASSERT(NULL != pstDirTree);
DBGASSERT(NULL != pstDirTree->pstPosixInfo);
pstPNEntry = (BISO_ROCK_RIDGE_ENTRY_PN_S *)pEntry;
pstDirTree->pstPosixInfo->ui64DevNum = ((UINT64)(pstPNEntry->uiDevNumHigh) << 32) | pstPNEntry->uiDevNumLow;
}
VOID BISO_RRIP_GetSLInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree)
{
UINT uiBufLen = 0;
UINT uiOffset = 0;
UINT uiCurPos = 0;
UCHAR ucCompentLen = 0;
CHAR *pcFullLinkPath = NULL;
BISO_POSIX_INFO_S *pstPosixInfo = NULL;
BISO_ROCK_RIDGE_ENTRY_SL_S *pstSLEntry = NULL;
BISO_RRIP_SL_COMPONENT_S *pstComp = NULL;
CHAR szBuf[300]; /* 当前Length是用UCHAR存储的一定不会超过300 */
DBGASSERT(NULL != pEntry);
DBGASSERT(NULL != pstDirTree);
DBGASSERT(NULL != pstDirTree->pstPosixInfo);
pstSLEntry = (BISO_ROCK_RIDGE_ENTRY_SL_S *)pEntry;
pstPosixInfo = pstDirTree->pstPosixInfo;
ucCompentLen = pstSLEntry->ucEntryLen - 5;
/*
* 把所有SL表项的Componet部分拼接起来如果有连续几条SL表项
* 那么当前函数会依次被调用,每次都拼接一部分,直到整个Componet整合完成.
*/
BISO_RRIP_AddLinkBuf((CHAR *)(pstSLEntry->aucComponet), ucCompentLen, pstPosixInfo);
/* FLAG的Bit0为0表示是最后1个SL表项,此时Componet已经整合在一起了,这里直接处理 */
if (0 == (pstSLEntry->ucFlags & 0x1))
{
/* 申请一段内存用来保存符号链接的源路径 */
uiBufLen = BISO_RRIP_CalcLinkLen(pstPosixInfo->pcLinkSrc, pstPosixInfo->uiLinkLen);
pcFullLinkPath = (CHAR *)BISO_MALLOC(uiBufLen + 10);
if (NULL == pcFullLinkPath)
{
BISO_FREE(pstPosixInfo->pcLinkSrc);
pstPosixInfo->uiLinkLen = 0;
return;
}
/* 拼接出链接的源路径 */
while (uiOffset < pstPosixInfo->uiLinkLen)
{
pstComp = (BISO_RRIP_SL_COMPONENT_S *)(pstPosixInfo->pcLinkSrc + uiOffset);
uiBufLen = BISO_RRIP_GetPartLink(pstComp, sizeof(szBuf), szBuf);
/* ucLength不包括头两个字节 */
uiOffset += pstComp->ucLength + 2;
/*
* 如果是link路径的一部分完结,则需要在后面加上'/',否则不加.
* 不加的情况有两种: 1是整体已经完了 2是路径的一部分还没有完整
* 比如说链接的位置是 /root/xxxx/a.txt 而xxxx可能非常长(200+个字符)
* 那么此时光xxxx的部分可能就需要两个Componet部分才能表达完,而这两个
* 之间是不能加反斜杠的.
*/
if ((uiOffset < pstPosixInfo->uiLinkLen) && (BOOL_TRUE != BISO_SLCOMP_IS_CONTINUE(pstComp->ucFlags)))
{
szBuf[uiBufLen++] = '/';
}
memcpy(pcFullLinkPath + uiCurPos, szBuf, uiBufLen);
uiCurPos += uiBufLen;
}
pcFullLinkPath[uiCurPos++] = 0;
/* 原来的内存释放掉 */
BISO_FREE(pstPosixInfo->pcLinkSrc);
pstPosixInfo->pcLinkSrc = pcFullLinkPath;
pstPosixInfo->uiLinkLen = uiCurPos;
}
}
ULONG BISO_RRIP_ReadExtInfo
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
OUT BISO_DIR_TREE_S *pstDirTree
)
{
UINT i = 0;
UINT uiOffset = 0;
UINT uiAreaSize = 0;
UCHAR *pucSysUseArea = NULL;
BISO_SUSP_ENTRY_S *pstEntry = NULL;
DBGASSERT(NULL != pstFile);
DBGASSERT(NULL != pstParser);
DBGASSERT(NULL != pstRecord);
DBGASSERT(NULL != pstDirTree);
/* 没有使用Rock Ridge扩展则直接返回 */
if (0 == pstParser->ucRRIPVersion)
{
return BISO_SUCCESS;
}
/* 先申请POSIX INFO结构体内存 */
if (NULL == pstDirTree->pstPosixInfo)
{
pstDirTree->pstPosixInfo = (BISO_POSIX_INFO_S *)BISO_ZALLOC(sizeof(BISO_POSIX_INFO_S));
if (NULL == pstDirTree->pstPosixInfo)
{
return BISO_ERR_ALLOC_MEM;
}
}
/* 偏移到System Use字段所在的位置注意Padding字段, 保证偏移为偶数 */
uiOffset = 33 + pstRecord->ucNameLen;
uiOffset += uiOffset & 0x1;
/* 再加上SP Entry中定义的SkipLen长度 */
uiOffset += pstParser->ucRRIPSkipLen;
/* 获取整个Syetem Use区域的数据(包括CE扩展区) */
pucSysUseArea = BISO_RRIP_GetSysUseArea(pstFile, (UCHAR *)pstRecord + uiOffset,
pstRecord->ucLength - (UCHAR)uiOffset, &uiAreaSize);
if (NULL == pucSysUseArea)
{
return BISO_ERR_ALLOC_MEM;
}
/* 遍历所有的RRIP表项 */
for(uiOffset = 0; uiOffset + 4 < uiAreaSize; uiOffset += pstEntry->ucEntryLen)
{
pstEntry = (BISO_SUSP_ENTRY_S *)(pucSysUseArea + uiOffset);
/* BISO_DUMP_ShowSUSPEntry(pstEntry); */
/* 找到对应的处理函数处理 */
for (i = 0; i < ARRAY_SIZE(g_astBISO_RRIP_ParseFunc); i++)
{
if (BOOL_TRUE == BISO_RRIP_IsThisType(pstEntry, g_astBISO_RRIP_ParseFunc[i].szSignature))
{
if (NULL != g_astBISO_RRIP_ParseFunc[i].pfFunc)
{
g_astBISO_RRIP_ParseFunc[i].pfFunc(pstEntry, pstDirTree);
}
break;
}
}
}
BISO_FREE(pucSysUseArea);
return BISO_SUCCESS;
}
ULONG BISO_RRIP_ReadIndicator(INOUT BISO_PARSER_S *pstParser)
{
ULONG ulRet;
UINT64 ui64Seek = 0;
BISO_DIR_RECORD_S *pstRootDir = NULL;
BISO_SUSP_ENTRY_SP_S *pstSPEntry = NULL;
UCHAR aucBuf[sizeof(BISO_DIR_RECORD_S) + sizeof(BISO_SUSP_ENTRY_SP_S)];
DBGASSERT(NULL != pstParser);
/* 读出Root Directory Record */
pstRootDir = &(pstParser->pstPVD->stRootDirRecord);
ui64Seek = BISO_BLOCK_SIZE * (UINT64)pstRootDir->uiExtent;
ulRet = BISO_UTIL_ReadFile(pstParser->szFileName, ui64Seek, sizeof(aucBuf), aucBuf);
if (BISO_SUCCESS != ulRet)
{
return ulRet;
}
/* 看看Root Directory Record的System Use字段里有没有SP Entry */
pstRootDir = (BISO_DIR_RECORD_S *)aucBuf;
pstSPEntry = (BISO_SUSP_ENTRY_SP_S *)(pstRootDir + 1);
if (('S' != pstSPEntry->cSignature1) || ('P' != pstSPEntry->cSignature2) ||
(0xBE != pstSPEntry->ucChkBE) || (0xEF != pstSPEntry->ucChkEF))
{
pstParser->ucRRIPVersion = 0;
pstParser->ucRRIPSkipLen = 0;
}
else
{
pstParser->ucRRIPVersion = pstSPEntry->ucVersion;
pstParser->ucRRIPSkipLen = pstSPEntry->ucSkipLen;
}
return BISO_SUCCESS;
}

View File

@@ -0,0 +1,500 @@
/******************************************************************************
* biso_rockridge.h
*
* 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/>.
*
*/
/*
* 本文件中定义了SUSP(ystem Use Sharing Protocol)协议(IEEE P1281)
* 以及Rock Ridge 扩展中定义的各种表项结构(IEEE P1282)
* 其中SUSP是规定了ISO-9660中Directory Record中System Use字段的使用方法
* Rock Ridge是基于SUSP在System Use字段中扩展记录了文件的属性、名称等POSIX文件信息
* 详细的说明请参考标准文档(IEEE P1281、IEEE P1282)
* SUSP定义的每一条Entry都是不定长的其长度在结构里面描述
*/
#ifndef __BISO_ROCKRIDGE_H__
#define __BISO_ROCKRIDGE_H__
#ifndef S_IFLNK
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFDIR 0040000
#endif
typedef VOID (* BISO_DUMP_ENTRY_PF)(IN VOID *pEntry);
typedef struct tagBISO_DUMP_ENTRY_CB
{
CHAR szSignature[3];
BISO_DUMP_ENTRY_PF pfDump;
}BISO_DUMP_ENTRY_CB_S;
typedef VOID (* BISO_RRIP_PARSE_ENTRY_PF)
(
IN VOID *pEntry,
OUT BISO_DIR_TREE_S *pstDirTree
);
typedef struct tagBISO_RRIP_PARSE_ENTRY_CB
{
CHAR szSignature[3];
BISO_RRIP_PARSE_ENTRY_PF pfFunc;
}BISO_RRIP_PARSE_ENTRY_CB_S;
#pragma pack(1)
/* SUSP: System Use Sharing Protocol */
/* SUSP中定义的标准Entry结构 */
typedef struct tagBISO_SUSP_ENTRY
{
/* 两个控制字 */
CHAR cSignature1;
CHAR cSignature2;
/* 长度,包括控制字 */
UCHAR ucEntryLen;
/* 版本号 */
UCHAR ucVersion;
/* 数据具体长度有ucEntryLen确定 */
UCHAR aucData[1];
}BISO_SUSP_ENTRY_S;
/*
* Continuation Area(可选)
* !!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!
* 之所以有CE这个控制字是因为ISO-9660标准定义的Directory Record
* 的长度是用1个字节表示的.最大就255 Byte所以System Use字段的长度也就
* 不可能大于255而有些扩展信息可能需要很多个Entry才能描述255的长度不够
* 就需要扩展所以才有了这个用于扩展的Entry格式
* 每个Directory Record的System Use字段或者扩展区域中只能最多有1个CE表项
* 而且一般也应该是最后1条表项不过整个System Use区域的CE表项个数的没有限制的。
*/
typedef struct tagBISO_SUSP_ENTRY_CE
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'C' */
CHAR cSignature2; /* 必须为 'E' */
/* 长度,包括控制字, 必须为28 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
BISO_DEF_733(uiBlockLoc)
BISO_DEF_733(uiByteOffset)
BISO_DEF_733(uiContinuationLen)
}BISO_SUSP_ENTRY_CE_S;
/* Padding Filed(可选) */
typedef struct tagBISO_SUSP_ENTRY_PD
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'P' */
CHAR cSignature2; /* 必须为 'D' */
/* 长度,包括控制字 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/* 数据具体长度有ucEntryLen确定 */
UCHAR aucData[1];
}BISO_SUSP_ENTRY_PD_S;
/*
* System Use Sharing Protocol Indicator(必须存在)
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* SP必须是在Root Directory Record的System Use里面从1个字节开始的第1条表项
* 另外SP表项还有一个作用就是它里面的Skip Len字段它的意思是
* 在除了ROOT之外的所有Directory Record中System Use字段不一定是从第1个字节开始就是
* SUSP的各种表项可以统一跳过一定的偏移(为了兼容性考虑),就是这里的Skip Len
* 注意这个Skip Len对ROOT根目录无效对于ROOT永远是从SYSTEM Use的第1个字节开始是SP Entry
*/
typedef struct tagBISO_SUSP_ENTRY_SP
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'S' */
CHAR cSignature2; /* 必须为 'P' */
/* 长度,包括控制字, 必须为7 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/* 检查字段 */
UCHAR ucChkBE;
UCHAR ucChkEF;
UCHAR ucSkipLen;
}BISO_SUSP_ENTRY_SP_S;
/* System Use Sharing Protocol Termonitor: System Use或者CE区域最后一条表项 */
typedef struct tagBISO_SUSP_ENTRY_ST
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'S' */
CHAR cSignature2; /* 必须为 'T' */
/* 长度,包括控制字, 必须为4 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
}BISO_SUSP_ENTRY_ST_S;
/* Extensions Reference */
typedef struct tagBISO_SUSP_ENTRY_ER
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'E' */
CHAR cSignature2; /* 必须为 'R' */
/* 长度,包括控制字 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
UCHAR ucIdLen;
UCHAR ucDescLen;
UCHAR ucSrcLen;
UCHAR ucExtVer;
/* 后面跟着数据 */
/* UCHAR aucId[ucIdLen]; */
/* UCHAR aucDesc[ucDescLen]; */
/* UCHAR aucSrc[ucSrcLen]; */
}BISO_SUSP_ENTRY_ER_S;
/* Extension Selector */
typedef struct tagBISO_SUSP_ENTRY_ES
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'E' */
CHAR cSignature2; /* 必须为 'S' */
/* 长度,包括控制字, 必须为5 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/* 扩展编号 */
UCHAR ucExtSeq;
}BISO_SUSP_ENTRY_ES_S;
/* Rock Ridge In Use RRIP 1991A版本里定义的结构, 新版本已经废弃 */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_RR
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'R' */
CHAR cSignature2; /* 必须为 'R' */
/* 长度,包括控制字, 必须为5 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/*
* ucFlags, 各Bit含义如下:
* Bit0: "PX" System Use Field recorded
* Bit1: "PN" System Use Field recorded
* Bit2: "SL" System Use Field recorded
* Bit3: "NM" System Use Field recorded
* Bit4: "CL" System Use Field recorded
* Bit5: "PL" System Use Field recorded
* Bit6: "RE" System Use Field recorded
* Bit7: "TF" System Use Field recorded
*/
UCHAR ucFlags;
}BISO_ROCK_RIDGE_ENTRY_RR_S;
/* POSIX file attributes */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_PX
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'P' */
CHAR cSignature2; /* 必须为 'X' */
/* 长度,包括控制字, 必须为44
* !!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!!!!!!!!!!!!!!!!!!!!!!!
* IEEE P1282 V1.10之前是36不是44
*/
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/* File Mode的比特位图, 就是linux里面stat结构里面的st_mode字段 */
BISO_DEF_733(uiPosixFileMode)
/* st_nlink字段 */
BISO_DEF_733(uiPosixFileLink)
/* st_uid字段 */
BISO_DEF_733(uiPosixFileUserId)
/* st_gid字段 */
BISO_DEF_733(uiPosixFileGroupId)
/* st_ino字段, 注意这个字段在IEEE P1282 V1.10之前是没有的 */
BISO_DEF_733(uiPosixFileSNO)
}BISO_ROCK_RIDGE_ENTRY_PX_S;
/* POSIX device number */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_PN
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'P' */
CHAR cSignature2; /* 必须为 'N' */
/* 长度,包括控制字, 必须为20 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/* Device Number的高低32位 */
BISO_DEF_733(uiDevNumHigh)
BISO_DEF_733(uiDevNumLow)
}BISO_ROCK_RIDGE_ENTRY_PN_S;
/* Symbol Link */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_SL
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'S' */
CHAR cSignature2; /* 必须为 'L' */
/* 长度,包括控制字, 必须为5+Componet长度 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/*
* 0:最后一个软链接
* 1:后面还有
*/
UCHAR ucFlags;
/* Componet内容有具体的格式定义ISO_RRIP_SL_COMPONENT_S */
UCHAR aucComponet[1];
}BISO_ROCK_RIDGE_ENTRY_SL_S;
typedef struct tagBISO_RRIP_SL_COMPONENT
{
/* ucFlags
* Bit0: Continue
* Bit1: Current当前目录 '.'
* Bit2: Parent父目录 '..'
* Bit3: Root 目录 '/'
* 其他位保留
*/
UCHAR ucFlags;
/* 长度不包括ucFlags和自己纯粹是后面aucData的长度 */
UCHAR ucLength;
UCHAR aucData[1];
}BISO_RRIP_SL_COMPONENT_S;
#define BISO_SLCOMP_IS_CONTINUE(ucFlag) (((ucFlag >> 0) & 0x1) > 0 ? BOOL_TRUE : BOOL_FALSE)
#define BISO_SLCOMP_IS_CURRENT(ucFlag) (((ucFlag >> 1) & 0x1) > 0 ? BOOL_TRUE : BOOL_FALSE)
#define BISO_SLCOMP_IS_PARENT(ucFlag) (((ucFlag >> 2) & 0x1) > 0 ? BOOL_TRUE : BOOL_FALSE)
#define BISO_SLCOMP_IS_ROOT(ucFlag) (((ucFlag >> 3) & 0x1) > 0 ? BOOL_TRUE : BOOL_FALSE)
/*
* Alternate Name 用来记录POSIX文件名
* 注意NM表项可以有很多个一直到ucFlags的比特0为0
* 多个NM表项里面的szFileName部分要拼接在一起表示整个完整的文件名
* 这个应该主要是为了解决长文件名的问题
*/
typedef struct tagBISO_ROCK_RIDGE_ENTRY_NM
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'N' */
CHAR cSignature2; /* 必须为 'M' */
/* 长度,包括控制字, 必须为5+Name长度 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/*
* ucFlags
* Bit0: Continue
* Bit1: Current当前目录 '.'
* Bit2: Parent父目录 '..'
* 其他位保留
*/
UCHAR ucFlags;
/* 后面跟着具体的名称如果Flag的Bit1 2 5置为则后面就没有了 */
CHAR szFileName[1];
}BISO_ROCK_RIDGE_ENTRY_NM_S;
/* 后面的CL PL RE用来扩展超过8级目录的情况 */
/* Child Link */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_CL
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'C' */
CHAR cSignature2; /* 必须为 'L' */
/* 长度,包括控制字, 必须为12 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
BISO_DEF_733(uiChildDirLoc)
}BISO_ROCK_RIDGE_ENTRY_CL_S;
/* Parent Link */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_PL
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'P' */
CHAR cSignature2; /* 必须为 'L' */
/* 长度,包括控制字, 必须为12 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
BISO_DEF_733(uiParentDirLoc)
}BISO_ROCK_RIDGE_ENTRY_PL_S;
/* Relocated Directory */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_RE
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'R' */
CHAR cSignature2; /* 必须为 'E' */
/* 长度,包括控制字, 必须为4 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
}BISO_ROCK_RIDGE_ENTRY_RE_S;
/* Time Stamps For File */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_TF
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'T' */
CHAR cSignature2; /* 必须为 'F' */
/* 长度,包括控制字 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
/*
* ucFlags:
* Bit0: Create Time 是否记录
* Bit1: Modify Time 是否记录
* Bit2: Last Access Time 是否记录
* Bit3: Last Attribute Change Time 是否记录
* Bit4: Last Backup Time 是否记录
* Bit5: Expiration Time 是否记录
* Bit6: Effective Time 是否记录
* Bit7: Long-Form 时间格式
* 0 表示7字节数组格式(ECMA-119 9.1.5)
* 1 表示17字符串格式(ECMA-119 8.4.26.1)
*/
UCHAR ucFlags;
/* 具体的每一个时间戳每个时间戳7字节或者17字节取决于ucFlags的Bit7 */
UCHAR aucTimeStamp[1];
}BISO_ROCK_RIDGE_ENTRY_TF_S;
/* File Data in sparse format 稀疏文件 */
typedef struct tagBISO_ROCK_RIDGE_ENTRY_SF
{
/* 两个控制字 */
CHAR cSignature1; /* 必须为 'S' */
CHAR cSignature2; /* 必须为 'F' */
/* 长度,包括控制字, 必须为21 */
UCHAR ucEntryLen;
/* 版本号, 必须为1 */
UCHAR ucVersion;
BISO_DEF_733(uiVirFileSizeHigh)
BISO_DEF_733(uiVirFileSizeLow)
/*
* ucDepth:
* 1-->64KB
* 2-->16MB
* 3-->4GB
* 4-->1TB
* 5-->256TB
* 6-->64K TB
* 7-->16M TB
*/
UCHAR ucDepth;
}BISO_ROCK_RIDGE_ENTRY_SF_S;
#pragma pack()
ULONG BISO_RRIP_ReadIndicator(INOUT BISO_PARSER_S *pstParser);
ULONG BISO_RRIP_ReadExtInfo
(
IN BISO_FILE_S *pstFile,
IN BISO_PARSER_S *pstParser,
IN BISO_DIR_RECORD_S *pstRecord,
OUT BISO_DIR_TREE_S *pstDirTree
);
VOID BISO_RRIP_GetPXInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree);
VOID BISO_RRIP_GetNMInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree);
VOID BISO_RRIP_GetTFInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree);
VOID BISO_RRIP_GetSLInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree);
VOID BISO_RRIP_GetPNInfo(IN VOID *pEntry, OUT BISO_DIR_TREE_S *pstDirTree);
#endif /* __BISO_ROCKRIDGE_H__ */

View File

@@ -0,0 +1,626 @@
/******************************************************************************
* 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;
}

View File

@@ -0,0 +1,250 @@
/******************************************************************************
* biso_util.h
*
* 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/>.
*
*/
#ifndef __BISO_UTIL_H__
#define __BISO_UTIL_H__
#ifndef scnprintf
#define scnprintf(buf, bufsize, fmt, arg...) \
{\
snprintf((buf), (bufsize) - 1, fmt, ##arg);\
(buf)[(bufsize) - 1] = 0;\
}
#endif
#define MEMORY_DEBUG 0
#define MEMORY_DEBUG_DUMP 0
#if (MEMORY_DEBUG == 1)
#define BISO_MALLOC BISO_UTIL_Malloc
#define BISO_ZALLOC BISO_UTIL_Zalloc
#define BISO_FREE BISO_UTIL_Free
#else
#define BISO_MALLOC malloc
#define BISO_ZALLOC zalloc
#define BISO_FREE free
#endif
#define BISO_UCHAR_MAX 0xFF
#define BISO_USHORT_MAX 0xFFFF
#define BISO_UINT_MAX 0xFFFFFFFF
/* 无条件字节序转换 */
#define BISO_SWAP_UINT(data) \
((((data) & 0x000000FF) << 24) | \
(((data) & 0x0000FF00) << 8) | \
(((data) & 0x00FF0000) >> 8) | \
(((data) & 0xFF000000) >> 24))
#define BISO_SWAP_USHORT(data) \
((USHORT)(((data) & 0x00FF) << 8) | \
(USHORT)(((data) & 0xFF00) >> 8))
/* 更新计数(加或减) */
#define BISO_STAT_UPDATE(bAdd, a, b) \
{ \
if (BOOL_TRUE == bAdd) \
{ \
(a) += (b); \
} \
else \
{ \
(a) -= (b); \
} \
}
#if (__BYTE_ORDER == __LITTLE_ENDIAN)
/* 从小字节序转为主机序 */
#define BISO_LTOH_UINT(data) data
#define BISO_LTOH_USHORT(data) data
/* 从主机序转为小字节序 */
#define BISO_HTOL_UINT(data) data
#define BISO_HTOL_USHORT(data) data
/* 从主机序转为大字节序 */
#define BISO_HTOM_UINT(data) BISO_SWAP_UINT(data)
#define BISO_HTOM_USHORT(data) BISO_SWAP_USHORT(data)
#elif (__BYTE_ORDER == __BIG_ENDIAN)
/* 从小字节序转为主机序 */
#define BISO_LTOH_UINT(data) BISO_SWAP_UINT(data)
#define BISO_LTOH_USHORT(data) BISO_SWAP_USHORT(data)
/* 从主机序转为小字节序 */
#define BISO_HTOL_UINT(data) BISO_SWAP_UINT(data)
#define BISO_HTOL_USHORT(data) BISO_SWAP_USHORT(data)
/* 从主机序转为大字节序 */
#define BISO_HTOM_UINT(data) data
#define BISO_HTOM_USHORT(data) data
#else
#error ("you must first define __BYTE_ORDER !!!")
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) ((UINT)(sizeof (a) / sizeof ((a)[0])))
#endif
#ifndef DBGASSERT
#define DBGASSERT(expr)
#endif
/* 读写文件时的缓冲区大小 1M */
#define BISO_FILE_BUF_LEN (1024 * 1024)
/* MBUF中最大内存块个数 */
#define BISO_MBUF_MAX_BLK 256
/* MBUF 结构 */
typedef struct tagBISO_MBUF
{
UCHAR *apucDataBuf[BISO_MBUF_MAX_BLK];
UINT auiBufSize[BISO_MBUF_MAX_BLK];
UINT uiCurBufNum;
UINT uiTotDataSize;
}BISO_MBUF_S;
/* 检查读操作句柄有没有已经和ISO文件关联 */
#define BISO_IS_READ_HANDLE_VALID(pstRead) \
(NULL == (((BISO_PARSER_S *)pstRead)->pstPVD) ? BOOL_FALSE : BOOL_TRUE)
#define BISO_CHECK_READ_HANDLE(pstRead) \
{\
if (NULL == ((BISO_PARSER_S *)(pstRead))->pstPVD) \
{ \
return BISO_ERR_HANDLE_UNINITIALIZED; \
} \
}
/* 设置类型 */
#define BISO_SET_FLAG(pstFileNode, pstDirTree) \
{ \
(pstFileNode)->ucFlag = BISO_NODE_REGFILE; \
if (NULL != (pstDirTree)->pstDirStat) \
{ \
(pstFileNode)->ucFlag = BISO_NODE_DIRECTORY; \
} \
else if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstDirTree)) \
{ \
(pstFileNode)->ucFlag = BISO_NODE_SYMLINK; \
} \
}
#define BISO_QUEUE_PTR_NUM 1024
/* 队列节点为避免频繁分配内存这里每次扩展1024个指针的长度空间 */
typedef struct tagBISO_QUEUE_NODE
{
BISO_DLL_NODE_S stNode;
PVOID apList[BISO_QUEUE_PTR_NUM];
USHORT usFirst;
USHORT usLast;
}BISO_QUEUE_NODE_S;
/* 队列/堆栈 简单实现 */
typedef BISO_DLL_S BISO_QUEUE_S;
INT BISO_UTIL_GetTimeZone(VOID);
CHAR * BISO_UTIL_CopyStr
(
IN CONST CHAR *szSrc,
IN UINT uiSrcSize,
OUT CHAR *szDest
);
CHAR * BISO_UTIL_CopyUCS2Str
(
IN CONST CHAR *szSrc,
IN UINT uiSrcSize,
OUT CHAR *szDest
);
VOID BISO_UTIL_PathProc(INOUT CHAR *pcPath, INOUT UINT *puiLen);
ULONG BISO_UTIL_PathSplit
(
IN CONST CHAR *pcFullPath,
OUT UINT *puiDirNum,
OUT UINT *puiDirPos
);
ULONG BISO_UTIL_ReadFile
(
IN CONST CHAR *pcFileName,
IN UINT64 ui64Seek,
IN UINT uiDataLen,
OUT VOID *pDataBuf
);
ULONG BISO_MBUF_Append
(
IN BISO_MBUF_S *pstMBuf,
IN UINT uiDataSize,
IN VOID *pData
);
VOID BISO_MBUF_Free(IN BISO_MBUF_S *pstMBuf);
VOID BISO_MBUF_CopyToBuf(IN CONST BISO_MBUF_S *pstMBuf, OUT VOID *pDataBuf);
VOID BISO_MBUF_PULLUP(INOUT BISO_MBUF_S *pstMBuf);
BISO_QUEUE_S * BISO_QUEUE_Create(VOID);
VOID BISO_QUEUE_Destroy(IN BISO_QUEUE_S *pstQueue);
VOID BISO_QUEUE_Push(IN BISO_QUEUE_S *pstQueue, IN VOID *pData);
VOID * BISO_QUEUE_PopHead(IN BISO_QUEUE_S *pstQueue);
VOID * BISO_QUEUE_PopTail(IN BISO_QUEUE_S *pstQueue);
VOID * BISO_UTIL_Malloc(IN size_t ulSize);
VOID * BISO_UTIL_Zalloc(IN size_t ulSize);
VOID BISO_UTIL_Free(IN VOID *pData);
VOID BISO_UTIL_DumpMemOp(VOID);
ULONG BISO_UTIL_ExtractFile
(
IN BISO_FILE_S *pstFile,
IN UINT64 ui64Seek,
IN UINT64 ui64Len,
IN CONST CHAR *pcNewFileName
);
BOOL_T BISO_PLAT_IsPathExist(IN CONST CHAR *pcPath);
ULONG BISO_PLAT_MkDir(IN CONST CHAR *pcFullPath);
UINT BISO_PLAT_GetMaxPath(VOID);
BISO_FILE_S * BISO_PLAT_OpenExistFile(IN CONST CHAR *pcFileName);
BISO_FILE_S * BISO_PLAT_CreateNewFile(IN CONST CHAR *pcFileName);
VOID BISO_PLAT_CloseFile(IN BISO_FILE_S *pstFile);
INT64 BISO_PLAT_SeekFile(BISO_FILE_S *pstFile, INT64 i64Offset, INT iFromWhere);
UINT64 BISO_PLAT_ReadFile
(
IN BISO_FILE_S *pstFile,
IN UINT uiBlkSize,
IN UINT uiBlkNum,
OUT VOID *pBuf
);
UINT64 BISO_PLAT_WriteFile
(
IN BISO_FILE_S *pstFile,
IN UINT uiBlkSize,
IN UINT uiBlkNum,
IN VOID *pBuf
);
VOID *zalloc(size_t size);
#endif /* __BISO_UTIL_H__ */

20
VtoyTool/build.sh Normal file
View File

@@ -0,0 +1,20 @@
#!/bin/bash
rm -f vtoytool/00/*
/opt/diet64/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 *.c BabyISO/*.c -IBabyISO -Wall -DBUILD_VTOY_TOOL -DUSE_DIET_C -o vtoytool_64
/opt/diet32/bin/diet -Os gcc -D_FILE_OFFSET_BITS=64 -m32 *.c BabyISO/*.c -IBabyISO -Wall -DBUILD_VTOY_TOOL -DUSE_DIET_C -o vtoytool_32
#gcc -D_FILE_OFFSET_BITS=64 -static -Wall -DBUILD_VTOY_TOOL *.c BabyISO/*.c -IBabyISO -o vtoytool_64
#gcc -D_FILE_OFFSET_BITS=64 -Wall -DBUILD_VTOY_TOOL -m32 *.c BabyISO/*.c -IBabyISO -o vtoytool_32
if [ -e vtoytool_64 ] && [ -e vtoytool_32 ]; then
echo -e '\n############### SUCCESS ###############\n'
mv vtoytool_64 vtoytool/00/
mv vtoytool_32 vtoytool/00/
else
echo -e '\n############### FAILED ################\n'
exit 1
fi

639
VtoyTool/vtoydm.c Normal file
View File

@@ -0,0 +1,639 @@
/******************************************************************************
* vtoydm.c ---- ventoy device mapper tool
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include "biso.h"
#include "biso_list.h"
#include "biso_util.h"
#include "biso_plat.h"
#include "biso_9660.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef USE_DIET_C
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
#endif
#pragma pack(4)
typedef struct ventoy_img_chunk
{
uint32_t img_start_sector; // sector size: 2KB
uint32_t img_end_sector; // included
uint64_t disk_start_sector; // in disk_sector_size
uint64_t disk_end_sector; // included
}ventoy_img_chunk;
#pragma pack()
static int verbose = 0;
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
#define CMD_PRINT_TABLE 1
#define CMD_CREATE_DM 2
#define CMD_DUMP_ISO_INFO 3
#define CMD_EXTRACT_ISO_FILE 4
#define CMD_PRINT_EXTRACT_ISO_FILE 5
static uint64_t g_iso_file_size;
static char g_disk_name[128];
static int g_img_chunk_num = 0;
static ventoy_img_chunk *g_img_chunk = NULL;
static unsigned char g_iso_sector_buf[2048];
ventoy_img_chunk * vtoydm_get_img_map_data(const char *img_map_file, int *plen)
{
int len;
int rc = 1;
FILE *fp = NULL;
ventoy_img_chunk *chunk = NULL;
fp = fopen(img_map_file, "rb");
if (NULL == fp)
{
fprintf(stderr, "Failed to open file %s err:%d\n", img_map_file, errno);
return NULL;
}
fseek(fp, 0, SEEK_END);
len = (int)ftell(fp);
fseek(fp, 0, SEEK_SET);
debug("File <%s> len:%d\n", img_map_file, len);
chunk = (ventoy_img_chunk *)malloc(len);
if (NULL == chunk)
{
fprintf(stderr, "Failed to malloc memory len:%d err:%d\n", len, errno);
goto end;
}
if (fread(chunk, 1, len, fp) != len)
{
fprintf(stderr, "Failed to read file err:%d\n", errno);
goto end;
}
if (len % sizeof(ventoy_img_chunk))
{
fprintf(stderr, "image map file size %d is not aligned with %d\n",
len, (int)sizeof(ventoy_img_chunk));
goto end;
}
rc = 0;
end:
fclose(fp);
if (rc)
{
if (chunk)
{
free(chunk);
chunk = NULL;
}
}
*plen = len;
return chunk;
}
UINT64 vtoydm_get_file_size(const char *pcFileName)
{
(void)pcFileName;
debug("vtoydm_get_file_size %s %lu\n", pcFileName, (unsigned long)g_iso_file_size);
return g_iso_file_size;
}
BISO_FILE_S * vtoydm_open_file(const char *pcFileName)
{
BISO_FILE_S *file;
debug("vtoydm_open_file %s\n", pcFileName);
file = malloc(sizeof(BISO_FILE_S));
if (file)
{
memset(file, 0, sizeof(BISO_FILE_S));
file->FileSize = g_iso_file_size;
file->CurPos = 0;
}
return file;
}
void vtoydm_close_file(BISO_FILE_S *pstFile)
{
debug("vtoydm_close_file\n");
if (pstFile)
{
free(pstFile);
}
}
INT64 vtoydm_seek_file(BISO_FILE_S *pstFile, INT64 i64Offset, INT iFromWhere)
{
debug("vtoydm_seek_file %d\n", (int)i64Offset);
if (iFromWhere == SEEK_SET)
{
pstFile->CurPos = (UINT64)i64Offset;
}
return 0;
}
UINT64 vtoydm_map_iso_sector(UINT64 sector)
{
int i;
UINT64 disk_sector = 0;
for (i = 0; i < g_img_chunk_num; i++)
{
if (sector >= g_img_chunk[i].img_start_sector && sector <= g_img_chunk[i].img_end_sector)
{
disk_sector = ((sector - g_img_chunk[i].img_start_sector) << 2) + g_img_chunk[i].disk_start_sector;
break;
}
}
return disk_sector;
}
int vtoydm_read_iso_sector(UINT64 sector, void *buf)
{
int i;
int fd;
UINT64 disk_sector = 0;
for (i = 0; i < g_img_chunk_num; i++)
{
if (sector >= g_img_chunk[i].img_start_sector && sector <= g_img_chunk[i].img_end_sector)
{
disk_sector = ((sector - g_img_chunk[i].img_start_sector) << 2) + g_img_chunk[i].disk_start_sector;
break;
}
}
fd = open(g_disk_name, O_RDONLY | O_BINARY);
if (fd < 0)
{
debug("Failed to open %s\n", g_disk_name);
return 1;
}
lseek(fd, disk_sector * 512, SEEK_SET);
read(fd, buf, 2048);
close(fd);
return 0;
}
UINT64 vtoydm_read_file
(
BISO_FILE_S *pstFile,
UINT uiBlkSize,
UINT uiBlkNum,
VOID *pBuf
)
{
int pos = 0;
int align = 0;
UINT64 readlen = uiBlkSize * uiBlkNum;
char *curbuf = (char *)pBuf;
debug("vtoydm_read_file length:%u\n", uiBlkSize * uiBlkNum);
pos = (int)(pstFile->CurPos % 2048);
if (pos > 0)
{
align = 2048 - pos;
vtoydm_read_iso_sector(pstFile->CurPos / 2048, g_iso_sector_buf);
if (readlen > align)
{
memcpy(curbuf, g_iso_sector_buf + pos, align);
curbuf += align;
readlen -= align;
pstFile->CurPos += align;
}
else
{
memcpy(curbuf, g_iso_sector_buf + pos, readlen);
pstFile->CurPos += readlen;
return readlen;
}
}
while (readlen > 2048)
{
vtoydm_read_iso_sector(pstFile->CurPos / 2048, curbuf);
pstFile->CurPos += 2048;
curbuf += 2048;
readlen -= 2048;
}
if (readlen > 0)
{
vtoydm_read_iso_sector(pstFile->CurPos / 2048, g_iso_sector_buf);
memcpy(curbuf, g_iso_sector_buf, readlen);
pstFile->CurPos += readlen;
}
return uiBlkSize * uiBlkNum;
}
int vtoydm_dump_iso(const char *img_map_file, const char *diskname)
{
int i = 0;
int len = 0;
uint64_t sector_num;
unsigned long ret;
ventoy_img_chunk *chunk = NULL;
BISO_READ_S *iso;
BISO_PARSER_S *parser = NULL;
char label[64] = {0};
chunk = vtoydm_get_img_map_data(img_map_file, &len);
if (NULL == chunk)
{
return 1;
}
for (i = 0; i < len / sizeof(ventoy_img_chunk); i++)
{
sector_num = chunk[i].img_end_sector - chunk[i].img_start_sector + 1;
g_iso_file_size += sector_num * 2048;
}
strncpy(g_disk_name, diskname, sizeof(g_disk_name) - 1);
g_img_chunk = chunk;
g_img_chunk_num = len / sizeof(ventoy_img_chunk);
debug("iso file size : %llu\n", (unsigned long long)g_iso_file_size);
iso = BISO_AllocReadHandle();
if (iso == NULL)
{
free(chunk);
return 1;
}
ret = BISO_OpenImage("XXX", iso);
debug("open iso image ret=0x%lx\n", ret);
parser = (BISO_PARSER_S *)iso;
memcpy(label, parser->pstPVD->szVolumeId, 32);
for (i = 32; i >=0; i--)
{
if (label[i] != 0 && label[i] != ' ')
{
break;
}
else
{
label[i] = 0;
}
}
if (label[0])
{
printf("VENTOY_ISO_LABEL %s\n", label);
}
BISO_DumpFileTree(iso);
BISO_FreeReadHandle(iso);
free(chunk);
return 0;
}
static int vtoydm_extract_iso
(
const char *img_map_file,
const char *diskname,
unsigned long first_sector,
unsigned long long file_size,
const char *outfile
)
{
int len;
FILE *fp = NULL;
g_img_chunk = vtoydm_get_img_map_data(img_map_file, &len);
if (NULL == g_img_chunk)
{
return 1;
}
strncpy(g_disk_name, diskname, sizeof(g_disk_name) - 1);
g_img_chunk_num = len / sizeof(ventoy_img_chunk);
fp = fopen(outfile, "wb");
if (fp == NULL)
{
fprintf(stderr, "Failed to create file %s err:%d\n", outfile, errno);
free(g_img_chunk);
return 1;
}
while (file_size > 0)
{
vtoydm_read_iso_sector(first_sector++, g_iso_sector_buf);
if (file_size > 2048)
{
fwrite(g_iso_sector_buf, 2048, 1, fp);
file_size -= 2048;
}
else
{
fwrite(g_iso_sector_buf, 1, file_size, fp);
file_size = 0;
}
}
fclose(fp);
free(g_img_chunk);
return 0;
}
static int vtoydm_print_extract_iso
(
const char *img_map_file,
const char *diskname,
unsigned long first_sector,
unsigned long long file_size,
const char *outfile
)
{
int len;
uint32_t last = 0;
uint32_t sector = 0;
uint32_t disk_first = 0;
uint32_t count = 0;
uint32_t buf[2];
uint64_t size = file_size;
FILE *fp = NULL;
g_img_chunk = vtoydm_get_img_map_data(img_map_file, &len);
if (NULL == g_img_chunk)
{
return 1;
}
strncpy(g_disk_name, diskname, sizeof(g_disk_name) - 1);
g_img_chunk_num = len / sizeof(ventoy_img_chunk);
fp = fopen(outfile, "wb");
if (fp == NULL)
{
fprintf(stderr, "Failed to create file %s err:%d\n", outfile, errno);
free(g_img_chunk);
return 1;
}
fwrite(g_disk_name, 1, 32, fp);
fwrite(&size, 1, 8, fp);
while (file_size > 0)
{
sector = vtoydm_map_iso_sector(first_sector++);
if (count > 0 && sector == last + 4)
{
last += 4;
count += 4;
}
else
{
if (count > 0)
{
buf[0] = disk_first;
buf[1] = count;
fwrite(buf, 1, sizeof(buf), fp);
}
disk_first = sector;
last = sector;
count = 4;
}
if (file_size > 2048)
{
file_size -= 2048;
}
else
{
file_size = 0;
}
}
if (count > 0)
{
buf[0] = disk_first;
buf[1] = count;
fwrite(buf, 1, sizeof(buf), fp);
}
fclose(fp);
free(g_img_chunk);
return 0;
}
static int vtoydm_print_linear_table(const char *img_map_file, const char *diskname)
{
int i;
int len;
uint32_t sector_start;
uint32_t sector_num;
ventoy_img_chunk *chunk = NULL;
chunk = vtoydm_get_img_map_data(img_map_file, &len);
if (NULL == chunk)
{
return 1;
}
for (i = 0; i < len / sizeof(ventoy_img_chunk); i++)
{
sector_start = chunk[i].img_start_sector;
sector_num = chunk[i].img_end_sector - chunk[i].img_start_sector + 1;
printf("%u %u linear %s %llu\n",
(sector_start << 2), (sector_num << 2),
diskname, (unsigned long long)chunk[i].disk_start_sector);
}
free(chunk);
return 0;
}
static int vtoydm_print_help(FILE *fp)
{
fprintf(fp, "Usage: \n"
" vtoydm -p -f img_map_file -d diskname [ -v ] \n"
" vtoydm -c -f img_map_file -d diskname [ -v ] \n"
" vtoydm -i -f img_map_file -d diskname [ -v ] \n"
" vtoydm -e -f img_map_file -d diskname -s sector -l len -o file [ -v ] \n"
);
return 0;
}
int vtoydm_main(int argc, char **argv)
{
int ch;
int cmd = 0;
unsigned long first_sector = 0;
unsigned long long file_size = 0;
char diskname[128] = {0};
char filepath[300] = {0};
char outfile[300] = {0};
while ((ch = getopt(argc, argv, "s:l:o:d:f:v::i::p::c::h::e::E::")) != -1)
{
if (ch == 'd')
{
strncpy(diskname, optarg, sizeof(diskname) - 1);
}
else if (ch == 'f')
{
strncpy(filepath, optarg, sizeof(filepath) - 1);
}
else if (ch == 'p')
{
cmd = CMD_PRINT_TABLE;
}
else if (ch == 'c')
{
cmd = CMD_CREATE_DM;
}
else if (ch == 'i')
{
cmd = CMD_DUMP_ISO_INFO;
}
else if (ch == 'e')
{
cmd = CMD_EXTRACT_ISO_FILE;
}
else if (ch == 'E')
{
cmd = CMD_PRINT_EXTRACT_ISO_FILE;
}
else if (ch == 's')
{
first_sector = strtoul(optarg, NULL, 10);
}
else if (ch == 'l')
{
file_size = strtoull(optarg, NULL, 10);
}
else if (ch == 'o')
{
strncpy(outfile, optarg, sizeof(outfile) - 1);
}
else if (ch == 'v')
{
verbose = 1;
}
else if (ch == 'h')
{
return vtoydm_print_help(stdout);
}
else
{
vtoydm_print_help(stderr);
return 1;
}
}
if (filepath[0] == 0 || diskname[0] == 0)
{
fprintf(stderr, "Must input file and disk\n");
return 1;
}
debug("cmd=%d file=<%s> disk=<%s> first_sector=%lu file_size=%llu\n",
cmd, filepath, diskname, first_sector, file_size);
switch (cmd)
{
case CMD_PRINT_TABLE:
{
return vtoydm_print_linear_table(filepath, diskname);
}
case CMD_CREATE_DM:
{
break;
}
case CMD_DUMP_ISO_INFO:
{
return vtoydm_dump_iso(filepath, diskname);
}
case CMD_EXTRACT_ISO_FILE:
{
return vtoydm_extract_iso(filepath, diskname, first_sector, file_size, outfile);
}
case CMD_PRINT_EXTRACT_ISO_FILE:
{
return vtoydm_print_extract_iso(filepath, diskname, first_sector, file_size, outfile);
}
default :
{
fprintf(stderr, "Invalid cmd \n");
return 1;
}
}
return 0;
}
// wrapper main
#ifndef BUILD_VTOY_TOOL
int main(int argc, char **argv)
{
return vtoydm_main(argc, argv);
}
#endif

536
VtoyTool/vtoydump.c Normal file
View File

@@ -0,0 +1,536 @@
/******************************************************************************
* vtoydump.c ---- Dump ventoy os parameters
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <dirent.h>
#define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
#ifndef USE_DIET_C
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
#endif
#define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
#pragma pack(1)
typedef struct ventoy_guid
{
uint32_t data1;
uint16_t data2;
uint16_t data3;
uint8_t data4[8];
}ventoy_guid;
typedef struct ventoy_image_disk_region
{
uint32_t image_sector_count; /* image sectors contained in this region */
uint32_t image_start_sector; /* image sector start */
uint64_t disk_start_sector; /* disk sector start */
}ventoy_image_disk_region;
typedef struct ventoy_image_location
{
ventoy_guid guid;
/* image sector size, currently this value is always 2048 */
uint32_t image_sector_size;
/* disk sector size, normally the value is 512 */
uint32_t disk_sector_size;
uint32_t region_count;
/*
* disk region data
* If the image file has more than one fragments in disk,
* there will be more than one region data here.
* You can calculate the region count by
*/
ventoy_image_disk_region regions[1];
/* ventoy_image_disk_region regions[2~region_count-1] */
}ventoy_image_location;
typedef struct ventoy_os_param
{
ventoy_guid guid; // VENTOY_GUID
uint8_t chksum; // checksum
uint8_t vtoy_disk_guid[16];
uint64_t vtoy_disk_size; // disk size in bytes
uint16_t vtoy_disk_part_id; // begin with 1
uint16_t vtoy_disk_part_type; // 0:exfat 1:ntfs other: reserved
char vtoy_img_path[384]; // It seems to be enough, utf-8 format
uint64_t vtoy_img_size; // image file size in bytes
/*
* Ventoy will write a copy of ventoy_image_location data into runtime memory
* this is the physically address and length of that memory.
* Address 0 means no such data exist.
* Address will be aligned by 4KB.
*
*/
uint64_t vtoy_img_location_addr;
uint32_t vtoy_img_location_len;
uint64_t vtoy_reserved[4]; // Internal use by ventoy
uint8_t reserved[31];
}ventoy_os_param;
#pragma pack()
#ifndef O_BINARY
#define O_BINARY 0
#endif
#if defined(_dragon_fly) || defined(_free_BSD) || defined(_QNX)
#define MMAP_FLAGS MAP_SHARED
#else
#define MMAP_FLAGS MAP_PRIVATE
#endif
#define SEARCH_MEM_START 0x80000
#define SEARCH_MEM_LEN 0x1c000
static int verbose = 0;
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
static ventoy_guid vtoy_guid = VENTOY_GUID;
static int vtoy_check_os_param(ventoy_os_param *param)
{
uint32_t i;
uint8_t chksum = 0;
uint8_t *buf = (uint8_t *)param;
if (memcmp(&param->guid, &vtoy_guid, sizeof(ventoy_guid)))
{
return 1;
}
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += buf[i];
}
if (chksum)
{
debug("Invalid checksum 0x%02x\n", chksum);
return 1;
}
return 0;
}
static int vtoy_os_param_from_file(const char *filename, ventoy_os_param *param)
{
int fd = 0;
int rc = 0;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
{
fprintf(stderr, "Failed to open file %s error %d\n", filename, errno);
return errno;
}
read(fd, param, sizeof(ventoy_os_param));
if (vtoy_check_os_param(param) == 0)
{
debug("find ventoy os param in file %s\n", filename);
}
else
{
debug("ventoy os pararm NOT found in file %s\n", filename);
rc = 1;
}
close(fd);
return rc;
}
static void vtoy_dump_os_param(ventoy_os_param *param)
{
printf("################# dump os param ################\n");
printf("param->chksum = 0x%x\n", param->chksum);
printf("param->vtoy_disk_guid = %02x %02x %02x %02x\n",
param->vtoy_disk_guid[0], param->vtoy_disk_guid[1],
param->vtoy_disk_guid[2], param->vtoy_disk_guid[3]);
printf("param->vtoy_disk_size = %llu\n", (unsigned long long)param->vtoy_disk_size);
printf("param->vtoy_disk_part_id = %u\n", param->vtoy_disk_part_id);
printf("param->vtoy_disk_part_type = %u\n", param->vtoy_disk_part_type);
printf("param->vtoy_img_path = <%s>\n", param->vtoy_img_path);
printf("param->vtoy_img_size = <%llu>\n", (unsigned long long)param->vtoy_img_size);
printf("param->vtoy_img_location_addr = <0x%llx>\n", (unsigned long long)param->vtoy_img_location_addr);
printf("param->vtoy_img_location_len = <%u>\n", param->vtoy_img_location_len);
printf("param->vtoy_reserved[0] = 0x%llx\n", (unsigned long long)param->vtoy_reserved[0]);
printf("param->vtoy_reserved[1] = 0x%llx\n", (unsigned long long)param->vtoy_reserved[1]);
printf("\n");
}
static int vtoy_get_disk_guid(const char *diskname, uint8_t *vtguid)
{
int i = 0;
int fd = 0;
char devdisk[128] = {0};
snprintf(devdisk, sizeof(devdisk) - 1, "/dev/%s", diskname);
fd = open(devdisk, O_RDONLY | O_BINARY);
if (fd >= 0)
{
lseek(fd, 0x180, SEEK_SET);
read(fd, vtguid, 16);
close(fd);
debug("GUID for %s: <", devdisk);
for (i = 0; i < 16; i++)
{
debug("%02x", vtguid[i]);
}
debug(">\n");
return 0;
}
else
{
debug("failed to open %s %d\n", devdisk, errno);
return errno;
}
}
static unsigned long long vtoy_get_disk_size_in_byte(const char *disk)
{
int fd;
int rc;
unsigned long long size = 0;
char diskpath[256] = {0};
char sizebuf[64] = {0};
// Try 1: get size from sysfs
snprintf(diskpath, sizeof(diskpath) - 1, "/sys/block/%s/size", disk);
if (access(diskpath, F_OK) >= 0)
{
debug("get disk size from sysfs for %s\n", disk);
fd = open(diskpath, O_RDONLY | O_BINARY);
if (fd >= 0)
{
read(fd, sizebuf, sizeof(sizebuf));
size = strtoull(sizebuf, NULL, 10);
close(fd);
return (size * 512);
}
}
else
{
debug("%s not exist \n", diskpath);
}
// Try 2: get size from ioctl
snprintf(diskpath, sizeof(diskpath) - 1, "/dev/%s", disk);
fd = open(diskpath, O_RDONLY);
if (fd >= 0)
{
debug("get disk size from ioctl for %s\n", disk);
rc = ioctl(fd, BLKGETSIZE64, &size);
if (rc == -1)
{
size = 0;
debug("failed to ioctl %d\n", rc);
}
close(fd);
}
else
{
debug("failed to open %s %d\n", diskpath, errno);
}
debug("disk %s size %llu bytes\n", disk, (unsigned long long)size);
return size;
}
static int vtoy_is_possible_blkdev(const char *name)
{
if (name[0] == '.')
{
return 0;
}
/* /dev/ramX */
if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
{
return 0;
}
/* /dev/loopX */
if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
{
return 0;
}
/* /dev/dm-X */
if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && IS_DIGIT(name[3]))
{
return 0;
}
/* /dev/srX */
if (name[0] == 's' && name[1] == 'r' && IS_DIGIT(name[2]))
{
return 0;
}
return 1;
}
static int vtoy_find_disk_by_size(unsigned long long size, char *diskname)
{
unsigned long long cursize = 0;
DIR* dir = NULL;
struct dirent* p = NULL;
int rc = 0;
dir = opendir("/sys/block");
while ((p = readdir(dir)) != NULL)
{
if (!vtoy_is_possible_blkdev(p->d_name))
{
debug("disk %s is filted by name\n", p->d_name);
continue;
}
cursize = vtoy_get_disk_size_in_byte(p->d_name);
debug("disk %s size %llu\n", p->d_name, (unsigned long long)cursize);
if (cursize == size)
{
sprintf(diskname, "%s", p->d_name);
rc++;
}
}
closedir(dir);
return rc;
}
static int vtoy_find_disk_by_guid(uint8_t *guid, char *diskname)
{
int rc = 0;
int count = 0;
DIR* dir = NULL;
struct dirent* p = NULL;
uint8_t vtguid[16];
dir = opendir("/sys/block");
while ((p = readdir(dir)) != NULL)
{
if (!vtoy_is_possible_blkdev(p->d_name))
{
debug("disk %s is filted by name\n", p->d_name);
continue;
}
memset(vtguid, 0, sizeof(vtguid));
rc = vtoy_get_disk_guid(p->d_name, vtguid);
if (rc == 0 && memcmp(vtguid, guid, 16) == 0)
{
sprintf(diskname, "%s", p->d_name);
count++;
}
}
closedir(dir);
return count;
}
static int vtoy_print_os_param(ventoy_os_param *param, char *diskname)
{
int cnt = 0;
char *path = param->vtoy_img_path;
const char *fs;
cnt = vtoy_find_disk_by_size(param->vtoy_disk_size, diskname);
if (cnt > 1)
{
cnt = vtoy_find_disk_by_guid(param->vtoy_disk_guid, diskname);
}
if (param->vtoy_disk_part_type == 0)
{
fs = "exfat";
}
else if (param->vtoy_disk_part_type == 0)
{
fs = "ntfs";
}
else
{
fs = "unknown";
}
if (1 == cnt)
{
printf("/dev/%s#%s#%s\n", diskname, fs, path);
return 0;
}
else
{
return 1;
}
}
static int vtoy_check_device(ventoy_os_param *param, const char *device)
{
unsigned long long size;
uint8_t vtguid[16] = {0};
debug("vtoy_check_device for <%s>\n", device);
size = vtoy_get_disk_size_in_byte(device);
vtoy_get_disk_guid(device, vtguid);
debug("param->vtoy_disk_size=%llu size=%llu\n",
(unsigned long long)param->vtoy_disk_size, (unsigned long long)size);
if (param->vtoy_disk_size == size &&
memcmp(vtguid, param->vtoy_disk_guid, 16) == 0)
{
debug("<%s> is right ventoy disk\n", device);
return 0;
}
else
{
debug("<%s> is NOT right ventoy disk\n", device);
return 1;
}
}
/*
* Find disk and image path from ventoy runtime data.
* By default data is read from phymem(legacy bios) or efivar(UEFI), if -f is input, data is read from file.
*
* -f datafile os param data file.
* -c /dev/xxx check ventoy disk
* -v be verbose
* -l also print image disk location
*/
int vtoydump_main(int argc, char **argv)
{
int rc;
int ch;
char filename[256] = {0};
char diskname[256] = {0};
char device[64] = {0};
ventoy_os_param *param = NULL;
while ((ch = getopt(argc, argv, "c:f:v::")) != -1)
{
if (ch == 'f')
{
strncpy(filename, optarg, sizeof(filename) - 1);
}
else if (ch == 'v')
{
verbose = 1;
}
else if (ch == 'c')
{
strncpy(device, optarg, sizeof(device) - 1);
}
else
{
fprintf(stderr, "Usage: %s -f datafile [ -v ] \n", argv[0]);
return 1;
}
}
if (filename[0] == 0)
{
fprintf(stderr, "Usage: %s -f datafile [ -v ] \n", argv[0]);
return 1;
}
param = malloc(sizeof(ventoy_os_param));
if (NULL == param)
{
fprintf(stderr, "failed to alloc memory with size %d error %d\n",
(int)sizeof(ventoy_os_param), errno);
return 1;
}
memset(param, 0, sizeof(ventoy_os_param));
debug("get os pararm from file %s\n", filename);
rc = vtoy_os_param_from_file(filename, param);
if (rc)
{
debug("ventoy os param not found %d\n", rc);
goto end;
}
if (verbose)
{
vtoy_dump_os_param(param);
}
if (device[0])
{
rc = vtoy_check_device(param, device);
}
else
{
// print os param, you can change the output format in the function
rc = vtoy_print_os_param(param, diskname);
}
end:
if (param)
{
free(param);
}
return rc;
}
// wrapper main
#ifndef BUILD_VTOY_TOOL
int main(int argc, char **argv)
{
return vtoydump_main(argc, argv);
}
#endif

172
VtoyTool/vtoyloader.c Normal file
View File

@@ -0,0 +1,172 @@
/******************************************************************************
* vtoyloader.c ---- ventoy loader (wapper for binary loader)
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#define MAX_EXT_PARAM 256
#define CMDLINE_BUF_LEN (1024 * 1024 * 1)
#define EXEC_PATH_FILE "/ventoy/loader_exec_file"
#define CMDLINE_FILE "/ventoy/loader_exec_cmdline"
#define HOOK_CMD_FILE "/ventoy/loader_hook_cmd"
#define DEBUG_FLAG_FILE "/ventoy/loader_debug"
static int verbose = 0;
#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
static char g_exec_file[512];
static char g_hook_cmd[512];
static int vtoy_read_file_to_buf(const char *file, void *buf, int buflen)
{
FILE *fp;
fp = fopen(file, "r");
if (!fp)
{
fprintf(stderr, "Failed to open file %s err:%d\n", file, errno);
return 1;
}
fread(buf, 1, buflen, fp);
fclose(fp);
return 0;
}
int vtoyloader_main(int argc, char **argv)
{
int i;
int len;
int rc;
char *pos;
char *cmdline;
char **cmdlist;
if (access(DEBUG_FLAG_FILE, F_OK) >= 0)
{
verbose = 1;
}
debug("ventoy loader ...\n");
rc = vtoy_read_file_to_buf(EXEC_PATH_FILE, g_exec_file, sizeof(g_exec_file) - 1);
if (rc)
{
return rc;
}
if (access(g_exec_file, F_OK) < 0)
{
fprintf(stderr, "File %s not exist\n", g_exec_file);
return 1;
}
if (access(HOOK_CMD_FILE, F_OK) >= 0)
{
rc = vtoy_read_file_to_buf(HOOK_CMD_FILE, g_hook_cmd, sizeof(g_hook_cmd) - 1);
debug("g_hook_cmd=<%s>\n", g_hook_cmd);
// call hook script
rc = system(g_hook_cmd);
debug("system return code =<%d> errno=<%d>\n", rc, errno);
}
cmdline = (char *)malloc(CMDLINE_BUF_LEN);
if (!cmdline)
{
fprintf(stderr, "Failed to alloc memory err:%d\n", errno);
return 1;
}
memset(cmdline, 0, CMDLINE_BUF_LEN);
if (access(CMDLINE_FILE, F_OK) >= 0)
{
rc = vtoy_read_file_to_buf(CMDLINE_FILE, cmdline, CMDLINE_BUF_LEN - 1);
if (rc)
{
return rc;
}
}
len = (int)((argc + MAX_EXT_PARAM) * sizeof(char *));
cmdlist = (char **)malloc(len);
if (!cmdlist)
{
free(cmdline);
fprintf(stderr, "Failed to alloc memory err:%d\n", errno);
return 1;
}
memset(cmdlist, 0, len);
for (i = 0; i < argc; i++)
{
cmdlist[i] = argv[i];
}
cmdlist[0] = g_exec_file;
debug("g_exec_file=<%s>\n", g_exec_file);
pos = cmdline;
while ((*pos) && i < MAX_EXT_PARAM)
{
cmdlist[i++] = pos;
while (*pos)
{
if (*pos == '\r')
{
*pos = ' ';
}
else if (*pos == '\n')
{
*pos = 0;
pos++;
break;
}
pos++;
}
}
debug("execv [%s]...\n", cmdlist[0]);
execv(cmdlist[0], cmdlist);
return 0;
}
// wrapper main
#ifndef BUILD_VTOY_TOOL
int main(int argc, char **argv)
{
return vtoyloader_main(argc, argv);
}
#endif

95
VtoyTool/vtoytool.c Normal file
View File

@@ -0,0 +1,95 @@
/******************************************************************************
* vtoytool.c ---- ventoy os tool
*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef int (*main_func)(int argc, char **argv);
typedef struct cmd_def
{
const char *cmd;
main_func func;
}cmd_def;
int vtoydump_main(int argc, char **argv);
int vtoydm_main(int argc, char **argv);
int vtoytool_install(int argc, char **argv);
int vtoyloader_main(int argc, char **argv);
static char *g_vtoytool_name = NULL;
static cmd_def g_cmd_list[] =
{
{ "vtoydump", vtoydump_main },
{ "vtoydm", vtoydm_main },
{ "loader", vtoyloader_main },
{ "--install", vtoytool_install },
};
int vtoytool_install(int argc, char **argv)
{
int i;
char toolpath[128];
char filepath[128];
for (i = 0; i < sizeof(g_cmd_list) / sizeof(g_cmd_list[0]); i++)
{
if (g_cmd_list[i].cmd[0] != '-')
{
snprintf(toolpath, sizeof(toolpath), "/ventoy/tool/%s", g_vtoytool_name);
snprintf(filepath, sizeof(filepath), "/ventoy/tool/%s", g_cmd_list[i].cmd);
link(toolpath, filepath);
}
}
return 0;
}
int main(int argc, char **argv)
{
int i;
if ((g_vtoytool_name = strstr(argv[0], "vtoytool")) != NULL)
{
argc--;
argv++;
}
if (argc == 0)
{
fprintf(stderr, "Invalid param number\n");
return 1;
}
for (i = 0; i < sizeof(g_cmd_list) / sizeof(g_cmd_list[0]); i++)
{
if (strstr(argv[0], g_cmd_list[i].cmd))
{
return g_cmd_list[i].func(argc, argv);
}
}
fprintf(stderr, "Invalid cmd %s\n", argv[0]);
return 1;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.