1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "biso_list.h"
23 #include "biso_util.h"
24 #include "biso_plat.h"
25 #include "biso_9660.h"
26 #include "biso_eltorito.h"
27 #include "biso_rockridge.h"
28 #include "biso_dump.h"
30 STATIC ULONG
BISO_9660_ReadPathTable(IN BISO_FILE_S
*pstFile
, OUT BISO_PARSER_S
*pstParser
)
35 BISO_PVD_S
*pstPVD
= NULL
;
37 DBGASSERT(NULL
!= pstFile
);
38 DBGASSERT(NULL
!= pstParser
);
40 pstPVD
= pstParser
->pstPVD
;
41 ui64Seek
= BISO_PATHTBL_LOCATION(pstPVD
);
42 ui64Seek
= ui64Seek
* BISO_BLOCK_SIZE
;
46 * 由于Path Table是连续保存的,所以这里一次性读出保存,使用时再做解析
47 * Path Table保存时是连续的,一条Path Table可以跨block, 最后一个扇区的剩余空间填0
49 pucBuf
= (UCHAR
*)BISO_MALLOC(pstPVD
->uiPathTblSize
);
52 return BISO_ERR_ALLOC_MEM
;
55 BISO_PLAT_SeekFile(pstFile
, ui64Seek
, SEEK_SET
);
58 uiReadLen
= (UINT
)BISO_PLAT_ReadFile(pstFile
, 1, pstPVD
->uiPathTblSize
, pucBuf
);
59 if (uiReadLen
!= pstPVD
->uiPathTblSize
)
62 BISO_DIAG("Read Len %u, data len %u.", uiReadLen
, pstPVD
->uiPathTblSize
);
63 return BISO_ERR_READ_FILE
;
66 pstParser
->pucPathTable
= pucBuf
;
70 /* 深度优先文件树目录节点入栈 注意这里只是针对目录节点入栈, 文件节点没有处理 */
71 VOID BISO_9660_FillDfsStack
73 IN BISO_DIR_TREE_S
*pstTop
,
74 INOUT BISO_QUEUE_S
*pstQueue
77 BISO_DIR_TREE_S
*pstCurDir
= NULL
;
79 DBGASSERT(NULL
!= pstTop
);
80 DBGASSERT(NULL
!= pstQueue
);
83 BISO_QUEUE_Push(pstQueue
, pstTop
);
85 pstCurDir
= pstTop
->pstChild
;
86 if (NULL
== pstCurDir
)
101 BISO_QUEUE_Push(pstQueue
, pstCurDir
);
103 if (NULL
!= pstCurDir
->pstChild
)
105 pstCurDir
= pstCurDir
->pstChild
;
107 else if (NULL
!= pstCurDir
->pstNext
)
109 pstCurDir
= pstCurDir
->pstNext
;
113 /* 往上回溯, 一直找到需要入栈的节点 */
114 while ((pstTop
!= pstCurDir
->pstParent
) && (NULL
== pstCurDir
->pstParent
->pstNext
))
116 pstCurDir
= pstCurDir
->pstParent
;
119 if (pstTop
== pstCurDir
->pstParent
)
123 pstCurDir
= pstCurDir
->pstParent
->pstNext
;
128 /* 根据Extent的值查找子目录节点 */
129 STATIC BISO_DIR_TREE_S
*BISO_9660_FindChild
131 IN BISO_DIR_TREE_S
*pstParent
,
132 IN UINT uiChildExtent
135 BISO_DIR_TREE_S
*pstCurNode
= NULL
;
137 DBGASSERT(NULL
!= pstParent
);
139 pstCurNode
= pstParent
->pstChild
;
140 while (NULL
!= pstCurNode
)
142 if (pstCurNode
->uiExtent
== uiChildExtent
)
146 pstCurNode
= pstCurNode
->pstNext
;
151 STATIC ULONG
BISO_9660_ReadVD(IN BISO_FILE_S
*pstFile
, OUT BISO_PARSER_S
*pstParser
)
155 BISO_VD_NODE_S
*pstVdNode
= NULL
;
157 DBGASSERT(NULL
!= pstFile
);
158 DBGASSERT(NULL
!= pstParser
);
160 /* 标准规定前16个逻辑扇区用来保存系统数据,VD信息从第17个扇区开始 */
161 BISO_PLAT_SeekFile(pstFile
, BISO_SYSTEM_AREA_SIZE
, SEEK_SET
);
166 uiReadLen
= (UINT
)BISO_PLAT_ReadFile(pstFile
, 1, sizeof(stVolDesc
), &stVolDesc
);
167 if (uiReadLen
!= sizeof(stVolDesc
))
169 BISO_DIAG("Read Len %u, struct len %u.", uiReadLen
, (UINT
)sizeof(stVolDesc
));
170 return BISO_ERR_READ_FILE
;
173 /* 根据ID检验是否是合法的ISO-9660格式 */
174 if (0 != strncmp(stVolDesc
.szId
, BISO_VD_ID
, strlen(BISO_VD_ID
)))
176 BISO_DIAG("Invalid cdid: %02x %02x %02x %02x %02x\n",
177 (UCHAR
)stVolDesc
.szId
[0], (UCHAR
)stVolDesc
.szId
[1],
178 (UCHAR
)stVolDesc
.szId
[2], (UCHAR
)stVolDesc
.szId
[3],
179 (UCHAR
)stVolDesc
.szId
[4]);
180 return BISO_ERR_INVALID_ISO9660
;
184 pstVdNode
= (BISO_VD_NODE_S
*)BISO_ZALLOC(sizeof(BISO_VD_NODE_S
));
185 if (NULL
== pstVdNode
)
187 return BISO_ERR_ALLOC_MEM
;
191 memcpy(&(pstVdNode
->stVD
), &stVolDesc
, sizeof(BISO_VD_S
));
192 BISO_DLL_AddTail(&(pstParser
->stVDList
), (BISO_DLL_NODE_S
*)pstVdNode
);
194 switch (stVolDesc
.ucType
)
196 case BISO_VD_TYPE_BOOT
:
198 pstParser
->pstBVD
= (BISO_BVD_S
*)&(pstVdNode
->stVD
);
199 pstParser
->pstBVD
->uiBootCatlogStart
= BISO_LTOH_UINT(pstParser
->pstBVD
->uiBootCatlogStart
);
202 case BISO_VD_TYPE_PVD
:
204 pstParser
->pstPVD
= (BISO_PVD_S
*)&(pstVdNode
->stVD
);
207 case BISO_VD_TYPE_SVD
:
209 pstParser
->pstSVD
= (BISO_SVD_S
*)&(pstVdNode
->stVD
);
212 case BISO_VD_TYPE_PART
:
213 case BISO_VD_TYPE_END
:
219 BISO_DIAG("Invalid VD type: %u\n", stVolDesc
.ucType
);
220 return BISO_ERR_INVALID_ISO9660
;
223 } while (BISO_VD_TYPE_END
!= stVolDesc
.ucType
);
226 if (NULL
== pstParser
->pstPVD
)
228 BISO_DIAG("No PVD found.");
229 return BISO_ERR_INVALID_ISO9660
;
232 /* 目前只支持逻辑块大小为2048 */
233 if (BISO_BLOCK_SIZE
!= pstParser
->pstPVD
->usBlockSize
)
235 BISO_DIAG("Unsupported block size %u.", pstParser
->pstPVD
->usBlockSize
);
236 return BISO_ERR_UNSUPPORTED_BLKSIZE
;
242 STATIC UCHAR
* BISO_9660_ReadDirRecord
244 IN BISO_FILE_S
*pstFile
,
251 UCHAR
*pucBuf
= NULL
;
252 BISO_DIR_RECORD_S stCurrent
;
254 DBGASSERT(NULL
!= pstFile
);
255 DBGASSERT(NULL
!= puiSize
);
257 /* 第一条Dir Record是Current, 先读出自己,得到总的缓冲区长度 */
258 ui64Seek
= BISO_BLOCK_SIZE
* (UINT64
)uiExtent
;
259 BISO_PLAT_SeekFile(pstFile
, ui64Seek
, SEEK_SET
);
260 uiReadLen
= (UINT
)BISO_PLAT_ReadFile(pstFile
, 1, sizeof(stCurrent
), &stCurrent
);
261 if (uiReadLen
!= sizeof(stCurrent
))
263 BISO_DIAG("Read len %u, buf len %u.", uiReadLen
, (UINT
)sizeof(stCurrent
));
267 /* 申请内存, 一次性把当前目录的Directory信息全部读出 */
268 pucBuf
= (UCHAR
*)BISO_MALLOC(stCurrent
.uiSize
);
274 BISO_PLAT_SeekFile(pstFile
, ui64Seek
, SEEK_SET
);
275 uiReadLen
= (UINT
)BISO_PLAT_ReadFile(pstFile
, 1, stCurrent
.uiSize
, pucBuf
);
276 if (uiReadLen
!= stCurrent
.uiSize
)
278 BISO_DIAG("Read len %u, buf len %u.", uiReadLen
, stCurrent
.uiSize
);
283 *puiSize
= stCurrent
.uiSize
;
287 STATIC BISO_DIR_TREE_S
* BISO_9660_CreateDirNode
289 IN BISO_FILE_S
*pstFile
,
290 IN BISO_PARSER_S
*pstParser
,
291 IN BISO_DIR_RECORD_S
*pstRecord
,
292 INOUT BISO_DIR_TREE_S
*pstPre
,
293 INOUT BISO_DIR_TREE_S
*pstParent
296 BISO_DIR_TREE_S
*pstNew
= NULL
;
298 DBGASSERT(NULL
!= pstRecord
);
299 DBGASSERT(NULL
!= pstPre
);
300 DBGASSERT(NULL
!= pstParent
);
303 pstNew
= (BISO_DIR_TREE_S
*)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S
));
310 BISO_UTIL_CopyStr(pstRecord
->szName
, pstRecord
->ucNameLen
, pstNew
->szName
);
311 pstNew
->uiExtent
= pstRecord
->uiExtent
;
312 pstNew
->usNameLen
= (USHORT
)strlen(pstNew
->szName
);
315 pstNew
->pstDirStat
= (BISO_DIR_STAT_S
*)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S
));
316 if (NULL
== pstNew
->pstDirStat
)
325 pstParent
->pstChild
= pstNew
;
329 pstPre
->pstNext
= pstNew
;
331 pstNew
->pstParent
= pstParent
;
334 pstParent
->pstDirStat
->uiCurDirNum
++;
336 /* 更新目录的Rock Ridge扩展信息 */
337 (VOID
)BISO_RRIP_ReadExtInfo(pstFile
, pstParser
, pstRecord
, pstNew
);
341 STATIC BISO_SVD_DIR_TREE_S
* BISO_9660_CreateSVDDirNode
343 IN BISO_FILE_S
*pstFile
,
344 IN BISO_PARSER_S
*pstParser
,
345 IN BISO_DIR_RECORD_S
*pstRecord
,
346 INOUT BISO_SVD_DIR_TREE_S
*pstPre
,
347 INOUT BISO_SVD_DIR_TREE_S
*pstParent
350 BISO_SVD_DIR_TREE_S
*pstNew
= NULL
;
352 DBGASSERT(NULL
!= pstRecord
);
353 DBGASSERT(NULL
!= pstPre
);
354 DBGASSERT(NULL
!= pstParent
);
357 pstNew
= (BISO_SVD_DIR_TREE_S
*)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S
));
364 pstNew
->uiExtent
= pstRecord
->uiExtent
;
369 pstParent
->pstChild
= pstNew
;
373 pstPre
->pstNext
= pstNew
;
375 pstNew
->pstParent
= pstParent
;
381 STATIC ULONG
BISO_9660_ProcRawFileNameFmt(INOUT CHAR
*szFileName
, INOUT USHORT
*pusLen
)
387 UINT uiLen
= *pusLen
;
389 for (i
= 0; i
< uiLen
; i
++)
391 if (szFileName
[i
] == ';')
400 else if (szFileName
[i
] == '.')
408 else if (szFileName
[i
] >= 'a' && szFileName
[i
] <= 'z')
415 if (uiSepNum
!= 1 || uiSepIndex
== 0 || uiDotNum
!= 1)
420 /* 分号后面是文件版本号, 纯数字 */
421 for (i
= uiSepIndex
+ 1; i
< uiLen
; i
++)
423 if (szFileName
[i
] < '0' || szFileName
[i
] > '9')
430 szFileName
[uiSepIndex
] = 0;
433 /* 如果只有文件名没有扩展名则把最后的点号去掉 */
434 if (uiLen
> 1 && szFileName
[uiLen
- 1] == '.')
436 szFileName
[uiLen
- 1] = 0;
440 *pusLen
= (USHORT
)uiLen
;
443 for (i
= 0; i
< uiLen
; i
++)
445 if (szFileName
[i
] >= 'A' && szFileName
[i
] <= 'Z')
447 szFileName
[i
] = 'a' + (szFileName
[i
] - 'A');
453 STATIC BISO_DIR_TREE_S
* BISO_9660_CreateFileNode
455 IN BISO_FILE_S
*pstFile
,
456 IN BISO_PARSER_S
*pstParser
,
457 IN BISO_DIR_RECORD_S
*pstRecord
,
458 INOUT BISO_DIR_TREE_S
*pstPre
,
459 INOUT BISO_DIR_TREE_S
*pstParent
463 BISO_DIR_TREE_S
*pstNew
= NULL
;
465 DBGASSERT(NULL
!= pstRecord
);
466 DBGASSERT(NULL
!= pstPre
);
467 DBGASSERT(NULL
!= pstParent
);
470 pstNew
= (BISO_DIR_TREE_S
*)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S
));
477 BISO_UTIL_CopyStr(pstRecord
->szName
, pstRecord
->ucNameLen
, pstNew
->szName
);
478 pstNew
->uiExtent
= pstRecord
->uiExtent
;
479 pstNew
->usNameLen
= (USHORT
)strlen(pstNew
->szName
);
480 pstNew
->uiSize
= pstRecord
->uiSize
;
482 /* 读取文件的Rock Ridge扩展信息 */
483 (VOID
)BISO_RRIP_ReadExtInfo(pstFile
, pstParser
, pstRecord
, pstNew
);
486 if (BOOL_TRUE
== BISO_DIR_TREE_IS_SYMLINK(pstNew
))
488 pstParent
->pstDirStat
->uiCurLinkNum
++;
492 uiSecNum
= BISO_USED_SECTOR_NUM(pstNew
->uiSize
);
493 pstParent
->pstDirStat
->uiCurFileNum
++;
494 pstParent
->pstDirStat
->uiCurUsedSec
+= uiSecNum
;
495 pstParent
->pstDirStat
->ui64CurSpace
+= pstNew
->uiSize
;
498 /* 节点挂接到当前目录的FileList上 */
501 pstParent
->pstFileList
= pstNew
;
505 pstPre
->pstNext
= pstNew
;
507 pstNew
->pstParent
= pstParent
;
509 if (NULL
== pstNew
->pstPosixInfo
&& pstNew
->usNameLen
> 2)
511 BISO_9660_ProcRawFileNameFmt(pstNew
->szName
, &pstNew
->usNameLen
);
517 STATIC BISO_SVD_DIR_TREE_S
* BISO_9660_CreateSVDFileNode
519 IN BISO_FILE_S
*pstFile
,
520 IN BISO_PARSER_S
*pstParser
,
521 IN BISO_DIR_RECORD_S
*pstRecord
,
522 INOUT BISO_SVD_DIR_TREE_S
*pstPre
,
523 INOUT BISO_SVD_DIR_TREE_S
*pstParent
526 BISO_SVD_DIR_TREE_S
*pstNew
= NULL
;
528 DBGASSERT(NULL
!= pstRecord
);
529 DBGASSERT(NULL
!= pstPre
);
530 DBGASSERT(NULL
!= pstParent
);
533 pstNew
= (BISO_SVD_DIR_TREE_S
*)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S
));
540 pstNew
->uiExtent
= pstRecord
->uiExtent
;
541 pstNew
->uiSize
= pstRecord
->uiSize
;
543 /* 节点挂接到当前目录的FileList上 */
546 pstParent
->pstFileList
= pstNew
;
550 pstPre
->pstNext
= pstNew
;
552 pstNew
->pstParent
= pstParent
;
557 STATIC ULONG BISO_9660_BuildFileList
559 IN BISO_FILE_S
*pstFile
,
560 IN BISO_PARSER_S
*pstParser
,
561 OUT BISO_DIR_TREE_S
*pstDirTree
567 UCHAR
*pucBuf
= NULL
;
568 BISO_DIR_TREE_S
*pstPre
= NULL
;
569 BISO_DIR_TREE_S
*pstNew
= NULL
;
570 BISO_DIR_TREE_S
*pstChild
= NULL
;
571 BISO_DIR_RECORD_S
*pstCurrent
= NULL
;
573 DBGASSERT(NULL
!= pstFile
);
574 DBGASSERT(NULL
!= pstDirTree
);
576 /* 读取Directory Record记录 */
577 pucBuf
= BISO_9660_ReadDirRecord(pstFile
, pstDirTree
->uiExtent
, &uiBufSize
);
580 return BISO_ERR_ALLOC_MEM
;
583 pstCurrent
= (BISO_DIR_RECORD_S
*)pucBuf
;
584 pstChild
= pstDirTree
->pstChild
;
586 while (uiTotSize
< uiBufSize
)
588 if (BOOL_TRUE
!= BISO_DIR_RECORD_IS_PATH(pstCurrent
)) /* 只处理文件 */
591 pstNew
= BISO_9660_CreateFileNode(pstFile
, pstParser
, pstCurrent
, pstPre
, pstDirTree
);
595 return BISO_ERR_ALLOC_MEM
;
597 pstNew
->ui64FileRecordOffset
= (UINT64
)((UINT64
)pstDirTree
->uiExtent
* BISO_SECTOR_SIZE
)
598 + ((ULONG
)pstCurrent
- (ULONG
)pucBuf
);
603 /* 对于子目录在这里更新目录的Rock Ridge扩展信息 */
604 if ((BOOL_TRUE
!= BISO_9660_IS_CURRENT(pstCurrent
)) &&
605 (BOOL_TRUE
!= BISO_9660_IS_PARENT(pstCurrent
)))
608 * 这里首先按照Path Table里记录的子目录顺序来判断, 如果是就不用搜索了
611 * Path Table里的子目录记录和Directory Record里面的子目录记录顺序是否一致!!!!
612 * 绝大多数情况下都是按照字母顺序,两者是一致的, 所以BISO_9660_FindChild一般情况下
615 if (pstChild
->uiExtent
== pstCurrent
->uiExtent
)
618 pstChild
= pstChild
->pstNext
;
622 pstNew
= BISO_9660_FindChild(pstDirTree
, pstCurrent
->uiExtent
);
627 (VOID
)BISO_RRIP_ReadExtInfo(pstFile
, pstParser
, pstCurrent
, pstNew
);
632 uiTotSize
+= pstCurrent
->ucLength
;
633 pstCurrent
= (BISO_DIR_RECORD_S
*)(pucBuf
+ uiTotSize
);
636 * !!!!!!!!!!!!!!!!!!!!!!!!
637 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
638 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
640 if (0 == pstCurrent
->ucLength
)
642 uiTail
= BISO_BLOCK_SIZE
- (uiTotSize
% BISO_BLOCK_SIZE
);
644 pstCurrent
= (BISO_DIR_RECORD_S
*)((UCHAR
*)pstCurrent
+ uiTail
);
652 /* 通过PathTable构建目录树(只包含目录)
653 这里利用Path Table,因此超过65535个文件夹的ISO文件只能读取前 65535个目录里的内容 */
654 STATIC ULONG BISO_9660_BuildPathTree
656 IN BISO_FILE_S
*pstFile
,
657 INOUT BISO_PARSER_S
*pstParser
,
658 OUT UINT
*puiTotDirNum
661 UINT uiTotDirNum
= 0;
662 UINT uiPathTblId
= 1;
663 BISO_QUEUE_S
*pstQueue
= NULL
;
664 BISO_DIR_TREE_S
*pstNew
= NULL
;
665 BISO_DIR_TREE_S
*pstPre
= NULL
;
666 BISO_DIR_TREE_S
*pstDirTree
= NULL
;
667 BISO_PATH_TABLE_S
*pstPathTable
= NULL
;
669 DBGASSERT(NULL
!= pstFile
);
670 DBGASSERT(NULL
!= pstParser
);
671 DBGASSERT(NULL
!= puiTotDirNum
);
674 * ISO-9660规定的Path Table的顺序实际上是文件树的一个广度优先遍历的形式
675 * 而处理广度优先遍历时一般需要一个先进先出的队列结构,这里创建一个使用
677 pstQueue
= BISO_QUEUE_Create();
678 if (NULL
== pstQueue
)
680 return BISO_ERR_ALLOC_MEM
;
684 pstPathTable
= (BISO_PATH_TABLE_S
*)(pstParser
->pucPathTable
);
685 pstDirTree
= &(pstParser
->stDirTree
);
686 pstDirTree
->uiPathTblId
= 1;
687 pstDirTree
->uiExtent
= pstPathTable
->uiExtent
;
690 pstDirTree
->pstDirStat
= (BISO_DIR_STAT_S
*)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S
));
691 if (NULL
== pstDirTree
->pstDirStat
)
693 return BISO_ERR_ALLOC_MEM
;
697 BISO_QUEUE_Push(pstQueue
, pstDirTree
);
698 pstPathTable
= (BISO_PATH_TABLE_S
*)((UCHAR
*)pstPathTable
+ BISO_9660_PATH_LEN(pstPathTable
));
700 /* 依次处理队列中的每一项直到队列读空 */
701 while (NULL
!= (pstDirTree
= (BISO_DIR_TREE_S
*)BISO_QUEUE_PopHead(pstQueue
)))
703 /* 把该目录下的所有一级子目录读出来入队列 */
704 while ((USHORT
)pstDirTree
->uiPathTblId
== pstPathTable
->usParentDirNum
)
707 pstNew
= (BISO_DIR_TREE_S
*)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S
));
710 BISO_QUEUE_Destroy(pstQueue
);
711 return BISO_ERR_ALLOC_MEM
;
715 BISO_UTIL_CopyStr(pstPathTable
->szDirName
, pstPathTable
->ucDirNameLen
, pstNew
->szName
);
716 pstNew
->uiExtent
= pstPathTable
->uiExtent
;
717 pstNew
->usNameLen
= (USHORT
)strlen(pstNew
->szName
);
718 pstNew
->uiPathTblId
= (++uiPathTblId
);
721 pstNew
->pstDirStat
= (BISO_DIR_STAT_S
*)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S
));
722 if (NULL
== pstNew
->pstDirStat
)
724 BISO_QUEUE_Destroy(pstQueue
);
725 return BISO_ERR_ALLOC_MEM
;
729 if (NULL
== pstDirTree
->pstChild
)
731 pstDirTree
->pstChild
= pstNew
;
735 pstPre
->pstNext
= pstNew
;
737 pstNew
->pstParent
= pstDirTree
;
740 pstDirTree
->pstDirStat
->uiCurDirNum
++;
742 BISO_QUEUE_Push(pstQueue
, pstNew
);
743 pstPathTable
= (BISO_PATH_TABLE_S
*)((UCHAR
*)pstPathTable
+ BISO_9660_PATH_LEN(pstPathTable
));
747 *puiTotDirNum
= uiTotDirNum
;
748 BISO_QUEUE_Destroy(pstQueue
);
752 /* 更新整个目录树的目录结构中文件总数、目录总数、总空间大小等信息 */
753 ULONG
BISO_9660_UpdateTreeStat(INOUT BISO_DIR_TREE_S
*pstRoot
)
756 BISO_QUEUE_S
*pstQueue
= NULL
;
757 BISO_DIR_TREE_S
*pstCurDir
= NULL
;
758 BISO_DIR_STAT_S
*pstDirStat
= NULL
;
759 BISO_DIR_STAT_S
*pstPreDirStat
= NULL
;
761 DBGASSERT(NULL
!= pstRoot
);
763 pstQueue
= BISO_QUEUE_Create();
764 if (NULL
== pstQueue
)
766 return BISO_ERR_ALLOC_MEM
;
770 BISO_9660_FillDfsStack(pstRoot
, pstQueue
);
773 while (NULL
!= (pData
= BISO_QUEUE_PopTail(pstQueue
)))
775 pstCurDir
= (BISO_DIR_TREE_S
*)pData
;
776 pstDirStat
= pstCurDir
->pstDirStat
;
779 pstDirStat
->uiTotDirNum
+= pstDirStat
->uiCurDirNum
;
780 pstDirStat
->uiTotFileNum
+= pstDirStat
->uiCurFileNum
;
781 pstDirStat
->uiTotLinkNum
+= pstDirStat
->uiCurLinkNum
;
782 pstDirStat
->ui64TotSpace
+= pstDirStat
->ui64CurSpace
;
783 pstDirStat
->uiTotUsedSec
+= pstDirStat
->uiCurUsedSec
;
785 if (NULL
!= pstCurDir
->pstParent
) /* ROOT节点没有父节点 */
787 pstPreDirStat
= pstCurDir
->pstParent
->pstDirStat
;
788 pstPreDirStat
->uiTotDirNum
+= pstDirStat
->uiTotDirNum
;
789 pstPreDirStat
->uiTotFileNum
+= pstDirStat
->uiTotFileNum
;
790 pstPreDirStat
->uiTotLinkNum
+= pstDirStat
->uiCurLinkNum
;
791 pstPreDirStat
->ui64TotSpace
+= pstDirStat
->ui64TotSpace
;
792 pstPreDirStat
->uiTotUsedSec
+= pstDirStat
->uiTotUsedSec
;
797 BISO_QUEUE_Destroy(pstQueue
);
802 ULONG BISO_9660_UpdateNodeStat
805 IN CONST BISO_DIR_TREE_S
*pstCurNode
,
806 INOUT BISO_DIR_TREE_S
*pstParent
810 BISO_DIR_TREE_S
*pstCurDir
= NULL
;
811 BISO_DIR_STAT_S
*pstCurStat
= NULL
;
812 BISO_DIR_STAT_S
*pstPreStat
= NULL
;
813 BISO_DIR_STAT_S stExDirStat
;
815 DBGASSERT(NULL
!= pstCurNode
);
817 memset(&stExDirStat
, 0, sizeof(stExDirStat
));
818 pstPreStat
= pstParent
->pstDirStat
;
820 if (NULL
== pstCurNode
->pstDirStat
) /* 非目录 */
822 if (BOOL_TRUE
== BISO_DIR_TREE_IS_SYMLINK(pstCurNode
)) /* 符号链接 */
824 /* 更新当前目录链接数统计, 大小为0不用更新 */
825 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiCurLinkNum
, 1);
826 stExDirStat
.uiTotLinkNum
= 1;
831 uiSecNum
= BISO_USED_SECTOR_NUM(pstCurNode
->uiSize
);
832 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiCurFileNum
, 1);
833 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiCurUsedSec
, uiSecNum
);
834 BISO_STAT_UPDATE(bAdd
, pstPreStat
->ui64CurSpace
, pstCurNode
->uiSize
);
835 stExDirStat
.uiTotFileNum
= 1;
836 stExDirStat
.ui64TotSpace
= pstCurNode
->uiSize
;
837 stExDirStat
.uiTotUsedSec
= uiSecNum
;
842 pstCurStat
= pstCurNode
->pstDirStat
;
843 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiCurDirNum
, 1); /* Current只需更新目录数 */
844 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiTotDirNum
, pstCurStat
->uiTotDirNum
);
845 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiTotFileNum
, pstCurStat
->uiTotFileNum
);
846 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiTotLinkNum
, pstCurStat
->uiTotLinkNum
);
847 BISO_STAT_UPDATE(bAdd
, pstPreStat
->ui64TotSpace
, pstCurStat
->ui64TotSpace
);
848 BISO_STAT_UPDATE(bAdd
, pstPreStat
->uiTotUsedSec
, pstCurStat
->uiTotUsedSec
);
849 memcpy(&stExDirStat
, pstCurStat
, sizeof(stExDirStat
)); /* 只会用到Total部分,不用Current部分 */
852 /* 依次更新上层目录的Total部分 */
853 pstCurDir
= pstParent
->pstParent
;
854 while (NULL
!= pstCurDir
)
856 pstCurStat
= pstCurDir
->pstDirStat
;
857 BISO_STAT_UPDATE(bAdd
, pstCurStat
->uiTotDirNum
, stExDirStat
.uiTotDirNum
);
858 BISO_STAT_UPDATE(bAdd
, pstCurStat
->uiTotFileNum
, stExDirStat
.uiTotFileNum
);
859 BISO_STAT_UPDATE(bAdd
, pstCurStat
->uiTotLinkNum
, stExDirStat
.uiTotLinkNum
);
860 BISO_STAT_UPDATE(bAdd
, pstCurStat
->ui64TotSpace
, stExDirStat
.ui64TotSpace
);
861 BISO_STAT_UPDATE(bAdd
, pstCurStat
->uiTotUsedSec
, stExDirStat
.uiTotUsedSec
);
862 pstCurDir
= pstCurDir
->pstParent
;
868 ULONG BISO_9660_BuildFileTreeByTable
870 IN BISO_FILE_S
*pstFile
,
871 OUT BISO_PARSER_S
*pstParser
875 UINT uiTotDirNum
= 0;
876 BISO_QUEUE_S
*pstQueue
= NULL
;
877 BISO_DIR_TREE_S
*pstDirTree
= NULL
;
879 DBGASSERT(NULL
!= pstFile
);
880 DBGASSERT(NULL
!= pstParser
);
882 /* 先通过Path Table构建目录树(不包含文件) */
883 ulRet
= BISO_9660_BuildPathTree(pstFile
, pstParser
, &uiTotDirNum
);
884 if (BISO_SUCCESS
!= ulRet
)
892 pstQueue
= BISO_QUEUE_Create();
893 if (NULL
== pstQueue
)
895 return BISO_ERR_ALLOC_MEM
;
899 BISO_QUEUE_Push(pstQueue
, &(pstParser
->stDirTree
));
902 while (NULL
!= (pstDirTree
= (BISO_DIR_TREE_S
*)BISO_QUEUE_PopHead(pstQueue
)))
905 ulRet
= BISO_9660_BuildFileList(pstFile
, pstParser
, pstDirTree
);
906 if (BISO_SUCCESS
!= ulRet
)
908 BISO_DIAG("Failed to build file list for dir %s.", pstDirTree
->szName
);
909 BISO_QUEUE_Destroy(pstQueue
);
914 if (NULL
!= pstDirTree
->pstChild
)
916 BISO_QUEUE_Push(pstQueue
, pstDirTree
->pstChild
);
920 if (NULL
!= pstDirTree
->pstNext
)
922 BISO_QUEUE_Push(pstQueue
, pstDirTree
->pstNext
);
926 BISO_QUEUE_Destroy(pstQueue
);
930 ULONG BISO_9660_BuildFileTreeRecursively
932 IN BISO_FILE_S
*pstFile
,
933 OUT BISO_PARSER_S
*pstParser
939 UCHAR
*pucBuf
= NULL
;
940 BISO_QUEUE_S
*pstQueue
= NULL
;
941 BISO_DIR_TREE_S
*pstNew
= NULL
;
942 BISO_DIR_TREE_S
*pstPreDir
= NULL
;
943 BISO_DIR_TREE_S
*pstPreFile
= NULL
;
944 BISO_DIR_TREE_S
*pstDirTree
= NULL
;
945 BISO_DIR_RECORD_S
*pstCurrent
= NULL
;
947 DBGASSERT(NULL
!= pstFile
);
948 DBGASSERT(NULL
!= pstParser
);
951 pstDirTree
= &(pstParser
->stDirTree
);
952 pstDirTree
->uiPathTblId
= 1;
953 pstDirTree
->uiExtent
= pstParser
->pstPVD
->stRootDirRecord
.uiExtent
;
956 pstDirTree
->pstDirStat
= (BISO_DIR_STAT_S
*)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S
));
957 if (NULL
== pstDirTree
->pstDirStat
)
959 return BISO_ERR_ALLOC_MEM
;
963 pstQueue
= BISO_QUEUE_Create();
964 BISO_QUEUE_Push(pstQueue
, pstDirTree
);
966 while (NULL
!= (pstDirTree
= (BISO_DIR_TREE_S
*)BISO_QUEUE_PopHead(pstQueue
)))
971 pstDirTree
->uiPathTblId
= BISO_UINT_MAX
;
973 /* 读取Directory Record记录 */
974 pucBuf
= BISO_9660_ReadDirRecord(pstFile
, pstDirTree
->uiExtent
, &uiBufSize
);
977 BISO_QUEUE_Destroy(pstQueue
);
978 return BISO_ERR_ALLOC_MEM
;
981 pstCurrent
= (BISO_DIR_RECORD_S
*)pucBuf
;
983 while (uiTotSize
< uiBufSize
)
985 if (BOOL_TRUE
== BISO_DIR_RECORD_IS_PATH(pstCurrent
))
987 if ((BOOL_TRUE
!= BISO_9660_IS_CURRENT(pstCurrent
)) &&
988 (BOOL_TRUE
!= BISO_9660_IS_PARENT(pstCurrent
)))
991 pstNew
= BISO_9660_CreateDirNode(pstFile
, pstParser
, pstCurrent
, pstPreDir
, pstDirTree
);
995 BISO_QUEUE_Destroy(pstQueue
);
996 return BISO_ERR_ALLOC_MEM
;
1001 BISO_QUEUE_Push(pstQueue
, pstNew
);
1006 pstNew
= BISO_9660_CreateFileNode(pstFile
, pstParser
, pstCurrent
, pstPreFile
, pstDirTree
);
1010 BISO_QUEUE_Destroy(pstQueue
);
1011 return BISO_ERR_ALLOC_MEM
;
1013 pstNew
->ui64FileRecordOffset
= (UINT64
)((UINT64
)pstDirTree
->uiExtent
* BISO_SECTOR_SIZE
)
1014 + ((ULONG
)pstCurrent
- (ULONG
)pucBuf
);
1015 pstPreFile
= pstNew
;
1018 uiTotSize
+= pstCurrent
->ucLength
;
1019 pstCurrent
= (BISO_DIR_RECORD_S
*)(pucBuf
+ uiTotSize
);
1022 * !!!!!!!!!!!!!!!!!!!!!!!!
1023 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
1024 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
1026 if (0 == pstCurrent
->ucLength
)
1028 uiTail
= BISO_BLOCK_SIZE
- (uiTotSize
% BISO_BLOCK_SIZE
);
1029 uiTotSize
+= uiTail
;
1030 pstCurrent
= (BISO_DIR_RECORD_S
*)((UCHAR
*)pstCurrent
+ uiTail
);
1037 BISO_QUEUE_Destroy(pstQueue
);
1038 return BISO_SUCCESS
;
1041 ULONG BISO_9660_BuildSVDFileTreeRecursively
1043 IN BISO_FILE_S
*pstFile
,
1044 OUT BISO_PARSER_S
*pstParser
1050 UCHAR
*pucBuf
= NULL
;
1051 BISO_QUEUE_S
*pstQueue
= NULL
;
1052 BISO_SVD_DIR_TREE_S
*pstNew
= NULL
;
1053 BISO_SVD_DIR_TREE_S
*pstPreDir
= NULL
;
1054 BISO_SVD_DIR_TREE_S
*pstPreFile
= NULL
;
1055 BISO_SVD_DIR_TREE_S
*pstDirTree
= NULL
;
1056 BISO_DIR_RECORD_S
*pstCurrent
= NULL
;
1058 DBGASSERT(NULL
!= pstFile
);
1059 DBGASSERT(NULL
!= pstParser
);
1062 pstDirTree
= &(pstParser
->stSVDDirTree
);
1063 pstDirTree
->uiExtent
= pstParser
->pstSVD
->stRootDirRecord
.uiExtent
;
1066 pstQueue
= BISO_QUEUE_Create();
1067 BISO_QUEUE_Push(pstQueue
, pstDirTree
);
1069 while (NULL
!= (pstDirTree
= (BISO_SVD_DIR_TREE_S
*)BISO_QUEUE_PopHead(pstQueue
)))
1075 /* 读取Directory Record记录 */
1076 pucBuf
= BISO_9660_ReadDirRecord(pstFile
, pstDirTree
->uiExtent
, &uiBufSize
);
1079 BISO_QUEUE_Destroy(pstQueue
);
1080 return BISO_ERR_ALLOC_MEM
;
1083 pstCurrent
= (BISO_DIR_RECORD_S
*)pucBuf
;
1085 while (uiTotSize
< uiBufSize
)
1087 if (BOOL_TRUE
== BISO_DIR_RECORD_IS_PATH(pstCurrent
))
1089 if ((BOOL_TRUE
!= BISO_9660_IS_CURRENT(pstCurrent
)) &&
1090 (BOOL_TRUE
!= BISO_9660_IS_PARENT(pstCurrent
)))
1093 pstNew
= BISO_9660_CreateSVDDirNode(pstFile
, pstParser
, pstCurrent
, pstPreDir
, pstDirTree
);
1097 BISO_QUEUE_Destroy(pstQueue
);
1098 return BISO_ERR_ALLOC_MEM
;
1103 BISO_QUEUE_Push(pstQueue
, pstNew
);
1108 pstNew
= BISO_9660_CreateSVDFileNode(pstFile
, pstParser
, pstCurrent
, pstPreFile
, pstDirTree
);
1112 BISO_QUEUE_Destroy(pstQueue
);
1113 return BISO_ERR_ALLOC_MEM
;
1115 pstNew
->ui64FileRecordOffset
= (UINT64
)((UINT64
)pstDirTree
->uiExtent
* BISO_SECTOR_SIZE
)
1116 + ((ULONG
)pstCurrent
- (ULONG
)pucBuf
);
1117 pstPreFile
= pstNew
;
1120 uiTotSize
+= pstCurrent
->ucLength
;
1121 pstCurrent
= (BISO_DIR_RECORD_S
*)(pucBuf
+ uiTotSize
);
1124 * !!!!!!!!!!!!!!!!!!!!!!!!
1125 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
1126 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
1128 if (0 == pstCurrent
->ucLength
)
1130 uiTail
= BISO_BLOCK_SIZE
- (uiTotSize
% BISO_BLOCK_SIZE
);
1131 uiTotSize
+= uiTail
;
1132 pstCurrent
= (BISO_DIR_RECORD_S
*)((UCHAR
*)pstCurrent
+ uiTail
);
1139 BISO_QUEUE_Destroy(pstQueue
);
1140 return BISO_SUCCESS
;
1143 VOID
BISO_9660_FreeDirTree(IN BISO_PARSER_S
*pstParser
)
1145 BISO_QUEUE_S
*pstQueue
= NULL
;
1146 BISO_DIR_TREE_S
*pstRoot
= NULL
;
1147 BISO_DIR_TREE_S
*pstCurDir
= NULL
;
1148 BISO_DIR_TREE_S
*pstPre
= NULL
;
1149 BISO_DIR_TREE_S
*pstNext
= NULL
;
1151 if (NULL
== pstParser
)
1157 pstQueue
= BISO_QUEUE_Create();
1158 if (NULL
== pstQueue
)
1163 pstRoot
= &pstParser
->stDirTree
;
1166 BISO_9660_FillDfsStack(pstRoot
, pstQueue
);
1168 /* 不需要释放ROOT,把它从队列头弹出来 */
1169 BISO_QUEUE_PopHead(pstQueue
);
1172 while (NULL
!= (pstCurDir
= (BISO_DIR_TREE_S
*)BISO_QUEUE_PopTail(pstQueue
)))
1175 for (pstPre
= pstCurDir
->pstFileList
; NULL
!= pstPre
; pstPre
= pstNext
)
1177 pstNext
= pstPre
->pstNext
;
1178 BISO_9600_FREE_DIRTREE(pstPre
);
1182 BISO_9600_FREE_DIRTREE(pstCurDir
);
1186 for (pstPre
= pstRoot
->pstFileList
; NULL
!= pstPre
; pstPre
= pstNext
)
1188 pstNext
= pstPre
->pstNext
;
1189 BISO_9600_FREE_DIRTREE(pstPre
);
1192 /* 释放ROOT自己的扩展信息,但不释放自己本身 */
1193 BISO_9600_FREE_STAT(pstRoot
);
1194 BISO_9600_FREE_POSIX(pstRoot
);
1197 BISO_QUEUE_Destroy(pstQueue
);
1200 VOID
BISO_9660_FreeSVDDirTree(IN BISO_PARSER_S
*pstParser
)
1202 BISO_QUEUE_S
*pstQueue
= NULL
;
1203 BISO_SVD_DIR_TREE_S
*pstRoot
= NULL
;
1204 BISO_SVD_DIR_TREE_S
*pstCurDir
= NULL
;
1205 BISO_SVD_DIR_TREE_S
*pstPre
= NULL
;
1206 BISO_SVD_DIR_TREE_S
*pstNext
= NULL
;
1208 if (NULL
== pstParser
||
1209 0 == pstParser
->stSVDDirTree
.uiExtent
||
1210 0 == pstParser
->stSVDDirTree
.uiSize
)
1216 pstQueue
= BISO_QUEUE_Create();
1217 if (NULL
== pstQueue
)
1222 pstRoot
= &pstParser
->stSVDDirTree
;
1225 BISO_9660_FillDfsStack((BISO_DIR_TREE_S
*)pstRoot
, pstQueue
);
1227 /* 不需要释放ROOT,把它从队列头弹出来 */
1228 BISO_QUEUE_PopHead(pstQueue
);
1231 while (NULL
!= (pstCurDir
= (BISO_SVD_DIR_TREE_S
*)BISO_QUEUE_PopTail(pstQueue
)))
1234 for (pstPre
= pstCurDir
->pstFileList
; NULL
!= pstPre
; pstPre
= pstNext
)
1236 pstNext
= pstPre
->pstNext
;
1241 BISO_FREE(pstCurDir
);
1245 for (pstPre
= pstRoot
->pstFileList
; NULL
!= pstPre
; pstPre
= pstNext
)
1247 pstNext
= pstPre
->pstNext
;
1252 BISO_QUEUE_Destroy(pstQueue
);
1255 BISO_PARSER_S
* BISO_9660_CreateParser(VOID
)
1257 BISO_PARSER_S
*pstParser
= NULL
;
1259 pstParser
= (BISO_PARSER_S
*)BISO_ZALLOC(sizeof(BISO_PARSER_S
));
1260 if (NULL
== pstParser
)
1266 BISO_DLL_Init(&(pstParser
->stVDList
));
1271 VOID
BISO_9660_CleanParser(INOUT BISO_PARSER_S
*pstParser
)
1273 if (NULL
== pstParser
)
1278 /* 释放Volume Descriptor链表 */
1279 BISO_DLL_Free(&(pstParser
->stVDList
));
1282 if (NULL
!= pstParser
->pucPathTable
)
1284 BISO_FREE(pstParser
->pucPathTable
);
1287 /* 释放 El Torito数据 */
1288 if (NULL
!= pstParser
->pucElToritoEntry
)
1290 BISO_FREE(pstParser
->pucElToritoEntry
);
1294 BISO_9660_FreeDirTree(pstParser
);
1295 BISO_9660_FreeSVDDirTree(pstParser
);
1298 VOID
BISO_9660_DestroyParser(INOUT BISO_PARSER_S
*pstParser
)
1300 if (NULL
== pstParser
)
1306 BISO_9660_CleanParser(pstParser
);
1309 BISO_FREE(pstParser
);
1312 ULONG BISO_9660_OpenImage
1314 IN BOOL_T bParseSVDDirTree
,
1315 IN CONST CHAR
*pcFileName
,
1316 OUT BISO_PARSER_S
*pstParser
1319 UINT64 ui64FileSize
= 0;
1320 ULONG ulRet
= BISO_SUCCESS
;
1321 BISO_FILE_S
*pstFile
= NULL
;
1323 if ((NULL
== pcFileName
) || (NULL
== pstParser
))
1325 return BISO_ERR_NULL_PTR
;
1328 /* 先看文件大小,过小的文件不可能是ISO文件 */
1329 ui64FileSize
= BISO_PLAT_GetFileSize(pcFileName
);
1330 if (ui64FileSize
< BISO_SYSTEM_AREA_SIZE
+ sizeof(BISO_PVD_S
))
1332 BISO_DIAG("File len %llu is too small.", (ULONGLONG
)ui64FileSize
);
1333 return BISO_ERR_INVALID_ISO9660
;
1337 if (NULL
!= pstParser
->pstPVD
)
1339 BISO_9660_CleanParser(pstParser
);
1343 pstFile
= BISO_PLAT_OpenExistFile(pcFileName
);
1344 if (NULL
== pstFile
)
1346 BISO_DIAG("Failed to open file %s.", pcFileName
);
1347 return BISO_ERR_OPEN_FILE
;
1350 scnprintf(pstParser
->szFileName
, sizeof(pstParser
->szFileName
), "%s", pcFileName
);
1352 /* 读取Volume Description信息 */
1353 ulRet
= BISO_9660_ReadVD(pstFile
, pstParser
);
1354 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1357 ulRet
= BISO_9660_ReadPathTable(pstFile
, pstParser
);
1358 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1361 ulRet
= BISO_ELTORITO_ReadBootInfo(pstFile
, pstParser
);
1362 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1364 /* 读取Rock Ridge扩展标识 */
1365 ulRet
= BISO_RRIP_ReadIndicator(pstParser
);
1366 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1368 /* 这里构建文件树有两种方法可供选择, 暂时选择从ROOT递归创建的方法 */
1371 /* 从ISO文件中读取整个文件树, 这里选择根据Path Table构建 */
1372 ulRet
+= BISO_9660_BuildFileTreeByTable(pstFile
, pstParser
);
1373 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1375 /* 从ISO文件中读取整个文件树, 这里选择从ROOT开始递归构建 */
1376 ulRet
= BISO_9660_BuildFileTreeRecursively(pstFile
, pstParser
);
1377 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1380 if (bParseSVDDirTree
&& pstParser
->pstSVD
)
1382 ulRet
= BISO_9660_BuildSVDFileTreeRecursively(pstFile
, pstParser
);
1383 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1387 ulRet
= BISO_9660_UpdateTreeStat(&(pstParser
->stDirTree
));
1388 BISO_9660_CHECK_RET(ulRet
, pstFile
);
1390 BISO_PLAT_CloseFile(pstFile
);
1391 return BISO_SUCCESS
;
1395 ULONG BISO_9660_ParseDate84261
1397 IN CONST CHAR
*pcDate
,
1398 OUT BISO_DATE_S
*pstDate
1401 INT aiBuf
[7] = { 0 };
1403 if ((NULL
== pcDate
) || (NULL
== pstDate
))
1405 return BISO_ERR_NULL_PTR
;
1409 * ECMA-119 8.4.26.1节定义的日期格式,共17个字节
1410 * 前16个字节是字符,第17个字节是有符号整数
1411 * 如果前16个字节是字符'0', 最后一个是'\0'则表示时间无效
1412 * 形如 "2014122013000500*"
1415 if ((0 == pcDate
[0]) || (' ' == pcDate
[0]) || ('0' == pcDate
[0]))
1417 return BISO_ERR_NOT_RECORD
;
1420 sscanf(pcDate
, "%4d%2d%2d%2d%2d%2d%2d",
1421 aiBuf
+ 0, aiBuf
+ 1, aiBuf
+ 2,
1422 aiBuf
+ 3, aiBuf
+ 4, aiBuf
+ 5, aiBuf
+ 6);
1423 pstDate
->usYear
= (USHORT
)aiBuf
[0];
1424 pstDate
->ucMonth
= (UCHAR
)aiBuf
[1];
1425 pstDate
->ucDay
= (UCHAR
)aiBuf
[2];
1426 pstDate
->ucHour
= (UCHAR
)aiBuf
[3];
1427 pstDate
->ucMin
= (UCHAR
)aiBuf
[4];
1428 pstDate
->ucSecond
= (UCHAR
)aiBuf
[5];
1429 pstDate
->usMillSec
= (UCHAR
)(aiBuf
[6] * 10); /* 表示百分之一秒 */
1431 /* 第17字节表示时区信息, 15分钟为1个单位,4个单位就是1个时区 */
1432 pstDate
->cZone
= pcDate
[16] / 4;
1434 return BISO_SUCCESS
;
1437 VOID
BISO_9660_FmtDate84261(IN
time_t ulTime
, IN UINT uiBufSize
, OUT CHAR
*pcDate
)
1439 INT iTimeZone
= BISO_UTIL_GetTimeZone();
1440 struct tm
*pstTm
= NULL
;
1444 pstTm
= localtime(&ulTime
);
1445 scnprintf(pcDate
, uiBufSize
, "%04d%02d%02d%02d%02d%02d%02d",
1446 pstTm
->tm_year
+ 1900,
1455 pcDate
[16] = (CHAR
)(4 * iTimeZone
);