]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - VtoyTool/BabyISO/biso_9660.c
Update German translation (#2612)
[Ventoy.git] / VtoyTool / BabyISO / biso_9660.c
1 /******************************************************************************
2 * biso_9660.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21 #include "biso.h"
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"
29
30 STATIC ULONG BISO_9660_ReadPathTable(IN BISO_FILE_S *pstFile, OUT BISO_PARSER_S *pstParser)
31 {
32 UINT64 ui64Seek = 0;
33 UINT uiReadLen = 0;
34 UCHAR *pucBuf = NULL;
35 BISO_PVD_S *pstPVD = NULL;
36
37 DBGASSERT(NULL != pstFile);
38 DBGASSERT(NULL != pstParser);
39
40 pstPVD = pstParser->pstPVD;
41 ui64Seek = BISO_PATHTBL_LOCATION(pstPVD);
42 ui64Seek = ui64Seek * BISO_BLOCK_SIZE;
43
44 /*
45 * 申请内存用于保存Path Table
46 * 由于Path Table是连续保存的,所以这里一次性读出保存,使用时再做解析
47 * Path Table保存时是连续的,一条Path Table可以跨block, 最后一个扇区的剩余空间填0
48 */
49 pucBuf = (UCHAR *)BISO_MALLOC(pstPVD->uiPathTblSize);
50 if (NULL == pucBuf)
51 {
52 return BISO_ERR_ALLOC_MEM;
53 }
54
55 BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
56
57 /* 读出Path Table */
58 uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, pstPVD->uiPathTblSize, pucBuf);
59 if (uiReadLen != pstPVD->uiPathTblSize)
60 {
61 BISO_FREE(pucBuf);
62 BISO_DIAG("Read Len %u, data len %u.", uiReadLen, pstPVD->uiPathTblSize);
63 return BISO_ERR_READ_FILE;
64 }
65
66 pstParser->pucPathTable = pucBuf;
67 return BISO_SUCCESS;
68 }
69
70 /* 深度优先文件树目录节点入栈 注意这里只是针对目录节点入栈, 文件节点没有处理 */
71 VOID BISO_9660_FillDfsStack
72 (
73 IN BISO_DIR_TREE_S *pstTop,
74 INOUT BISO_QUEUE_S *pstQueue
75 )
76 {
77 BISO_DIR_TREE_S *pstCurDir = NULL;
78
79 DBGASSERT(NULL != pstTop);
80 DBGASSERT(NULL != pstQueue);
81
82 /* TOP入栈 */
83 BISO_QUEUE_Push(pstQueue, pstTop);
84
85 pstCurDir = pstTop->pstChild;
86 if (NULL == pstCurDir)
87 {
88 return;
89 }
90
91 for ( ; ; )
92 {
93 /*
94 * 按照以下顺序依次入栈:
95 * 1. 自己入栈
96 * 2. 子节点入栈
97 * 3. Next节点入栈
98 * 4. Parent的Next节点入栈
99 */
100
101 BISO_QUEUE_Push(pstQueue, pstCurDir);
102
103 if (NULL != pstCurDir->pstChild)
104 {
105 pstCurDir = pstCurDir->pstChild;
106 }
107 else if (NULL != pstCurDir->pstNext)
108 {
109 pstCurDir = pstCurDir->pstNext;
110 }
111 else
112 {
113 /* 往上回溯, 一直找到需要入栈的节点 */
114 while ((pstTop != pstCurDir->pstParent) && (NULL == pstCurDir->pstParent->pstNext))
115 {
116 pstCurDir = pstCurDir->pstParent;
117 }
118
119 if (pstTop == pstCurDir->pstParent)
120 {
121 break;
122 }
123 pstCurDir = pstCurDir->pstParent->pstNext;
124 }
125 }
126 }
127
128 /* 根据Extent的值查找子目录节点 */
129 STATIC BISO_DIR_TREE_S *BISO_9660_FindChild
130 (
131 IN BISO_DIR_TREE_S *pstParent,
132 IN UINT uiChildExtent
133 )
134 {
135 BISO_DIR_TREE_S *pstCurNode = NULL;
136
137 DBGASSERT(NULL != pstParent);
138
139 pstCurNode = pstParent->pstChild;
140 while (NULL != pstCurNode)
141 {
142 if (pstCurNode->uiExtent == uiChildExtent)
143 {
144 return pstCurNode;
145 }
146 pstCurNode = pstCurNode->pstNext;
147 }
148 return NULL;
149 }
150
151 STATIC ULONG BISO_9660_ReadVD(IN BISO_FILE_S *pstFile, OUT BISO_PARSER_S *pstParser)
152 {
153 UINT uiReadLen = 0;
154 BISO_VD_S stVolDesc;
155 BISO_VD_NODE_S *pstVdNode = NULL;
156
157 DBGASSERT(NULL != pstFile);
158 DBGASSERT(NULL != pstParser);
159
160 /* 标准规定前16个逻辑扇区用来保存系统数据,VD信息从第17个扇区开始 */
161 BISO_PLAT_SeekFile(pstFile, BISO_SYSTEM_AREA_SIZE, SEEK_SET);
162
163 do
164 {
165 /* 每次读取1个VD结构 */
166 uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, sizeof(stVolDesc), &stVolDesc);
167 if (uiReadLen != sizeof(stVolDesc))
168 {
169 BISO_DIAG("Read Len %u, struct len %u.", uiReadLen, (UINT)sizeof(stVolDesc));
170 return BISO_ERR_READ_FILE;
171 }
172
173 /* 根据ID检验是否是合法的ISO-9660格式 */
174 if (0 != strncmp(stVolDesc.szId, BISO_VD_ID, strlen(BISO_VD_ID)))
175 {
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;
181 }
182
183 /* 申请内存保存VD信息 */
184 pstVdNode = (BISO_VD_NODE_S *)BISO_ZALLOC(sizeof(BISO_VD_NODE_S));
185 if (NULL == pstVdNode)
186 {
187 return BISO_ERR_ALLOC_MEM;
188 }
189
190 /* 链表节点挂接 */
191 memcpy(&(pstVdNode->stVD), &stVolDesc, sizeof(BISO_VD_S));
192 BISO_DLL_AddTail(&(pstParser->stVDList), (BISO_DLL_NODE_S *)pstVdNode);
193
194 switch (stVolDesc.ucType)
195 {
196 case BISO_VD_TYPE_BOOT:
197 {
198 pstParser->pstBVD = (BISO_BVD_S *)&(pstVdNode->stVD);
199 pstParser->pstBVD->uiBootCatlogStart = BISO_LTOH_UINT(pstParser->pstBVD->uiBootCatlogStart);
200 break;
201 }
202 case BISO_VD_TYPE_PVD:
203 {
204 pstParser->pstPVD = (BISO_PVD_S *)&(pstVdNode->stVD);
205 break;
206 }
207 case BISO_VD_TYPE_SVD:
208 {
209 pstParser->pstSVD = (BISO_SVD_S *)&(pstVdNode->stVD);
210 break;
211 }
212 case BISO_VD_TYPE_PART:
213 case BISO_VD_TYPE_END:
214 {
215 break;
216 }
217 default :
218 {
219 BISO_DIAG("Invalid VD type: %u\n", stVolDesc.ucType);
220 return BISO_ERR_INVALID_ISO9660;
221 }
222 }
223 } while (BISO_VD_TYPE_END != stVolDesc.ucType);
224
225 /* 标准规定必须有1个主卷描述符 */
226 if (NULL == pstParser->pstPVD)
227 {
228 BISO_DIAG("No PVD found.");
229 return BISO_ERR_INVALID_ISO9660;
230 }
231
232 /* 目前只支持逻辑块大小为2048 */
233 if (BISO_BLOCK_SIZE != pstParser->pstPVD->usBlockSize)
234 {
235 BISO_DIAG("Unsupported block size %u.", pstParser->pstPVD->usBlockSize);
236 return BISO_ERR_UNSUPPORTED_BLKSIZE;
237 }
238
239 return BISO_SUCCESS;
240 }
241
242 STATIC UCHAR * BISO_9660_ReadDirRecord
243 (
244 IN BISO_FILE_S *pstFile,
245 IN UINT uiExtent,
246 OUT UINT *puiSize
247 )
248 {
249 UINT64 ui64Seek = 0;
250 UINT uiReadLen = 0;
251 UCHAR *pucBuf = NULL;
252 BISO_DIR_RECORD_S stCurrent;
253
254 DBGASSERT(NULL != pstFile);
255 DBGASSERT(NULL != puiSize);
256
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))
262 {
263 BISO_DIAG("Read len %u, buf len %u.", uiReadLen, (UINT)sizeof(stCurrent));
264 return NULL;
265 }
266
267 /* 申请内存, 一次性把当前目录的Directory信息全部读出 */
268 pucBuf = (UCHAR *)BISO_MALLOC(stCurrent.uiSize);
269 if (NULL == pucBuf)
270 {
271 return NULL;
272 }
273
274 BISO_PLAT_SeekFile(pstFile, ui64Seek, SEEK_SET);
275 uiReadLen = (UINT)BISO_PLAT_ReadFile(pstFile, 1, stCurrent.uiSize, pucBuf);
276 if (uiReadLen != stCurrent.uiSize)
277 {
278 BISO_DIAG("Read len %u, buf len %u.", uiReadLen, stCurrent.uiSize);
279 BISO_FREE(pucBuf);
280 return NULL;
281 }
282
283 *puiSize = stCurrent.uiSize;
284 return pucBuf;
285 }
286
287 STATIC BISO_DIR_TREE_S * BISO_9660_CreateDirNode
288 (
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
294 )
295 {
296 BISO_DIR_TREE_S *pstNew = NULL;
297
298 DBGASSERT(NULL != pstRecord);
299 DBGASSERT(NULL != pstPre);
300 DBGASSERT(NULL != pstParent);
301
302 /* 申请内存用于保存目录节点 */
303 pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
304 if (NULL == pstNew)
305 {
306 return NULL;
307 }
308
309 /* 目录节点属性赋值 */
310 BISO_UTIL_CopyStr(pstRecord->szName, pstRecord->ucNameLen, pstNew->szName);
311 pstNew->uiExtent = pstRecord->uiExtent;
312 pstNew->usNameLen = (USHORT)strlen(pstNew->szName);
313
314 /* 申请统计信息的节点 */
315 pstNew->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
316 if (NULL == pstNew->pstDirStat)
317 {
318 BISO_FREE(pstNew);
319 return NULL;
320 }
321
322 /* 挂接到父目录下 */
323 if (NULL == pstPre)
324 {
325 pstParent->pstChild = pstNew;
326 }
327 else
328 {
329 pstPre->pstNext = pstNew;
330 }
331 pstNew->pstParent = pstParent;
332
333 /* 更新父目录统计 */
334 pstParent->pstDirStat->uiCurDirNum++;
335
336 /* 更新目录的Rock Ridge扩展信息 */
337 (VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstRecord, pstNew);
338 return pstNew;
339 }
340
341 STATIC BISO_SVD_DIR_TREE_S * BISO_9660_CreateSVDDirNode
342 (
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
348 )
349 {
350 BISO_SVD_DIR_TREE_S *pstNew = NULL;
351
352 DBGASSERT(NULL != pstRecord);
353 DBGASSERT(NULL != pstPre);
354 DBGASSERT(NULL != pstParent);
355
356 /* 申请内存用于保存目录节点 */
357 pstNew = (BISO_SVD_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S));
358 if (NULL == pstNew)
359 {
360 return NULL;
361 }
362
363 /* 目录节点属性赋值 */
364 pstNew->uiExtent = pstRecord->uiExtent;
365
366 /* 挂接到父目录下 */
367 if (NULL == pstPre)
368 {
369 pstParent->pstChild = pstNew;
370 }
371 else
372 {
373 pstPre->pstNext = pstNew;
374 }
375 pstNew->pstParent = pstParent;
376
377 return pstNew;
378 }
379
380 /* ISO原始文件格式处理 */
381 STATIC ULONG BISO_9660_ProcRawFileNameFmt(INOUT CHAR *szFileName, INOUT USHORT *pusLen)
382 {
383 UINT i;
384 UINT uiSepNum = 0;
385 UINT uiSepIndex = 0;
386 UINT uiDotNum = 0;
387 UINT uiLen = *pusLen;
388
389 for (i = 0; i < uiLen; i++)
390 {
391 if (szFileName[i] == ';')
392 {
393 if (uiSepNum > 0)
394 {
395 return BISO_SUCCESS;
396 }
397 uiSepNum++;
398 uiSepIndex = i;
399 }
400 else if (szFileName[i] == '.')
401 {
402 if (uiDotNum > 0)
403 {
404 return BISO_SUCCESS;
405 }
406 uiDotNum++;
407 }
408 else if (szFileName[i] >= 'a' && szFileName[i] <= 'z')
409 {
410 return BISO_SUCCESS;
411 }
412 }
413
414 /* 必须只包含1个分号和1个点号 */
415 if (uiSepNum != 1 || uiSepIndex == 0 || uiDotNum != 1)
416 {
417 return BISO_SUCCESS;
418 }
419
420 /* 分号后面是文件版本号, 纯数字 */
421 for (i = uiSepIndex + 1; i < uiLen; i++)
422 {
423 if (szFileName[i] < '0' || szFileName[i] > '9')
424 {
425 return BISO_SUCCESS;
426 }
427 }
428
429 /* 把分号后面剔除 */
430 szFileName[uiSepIndex] = 0;
431 uiLen = uiSepIndex;
432
433 /* 如果只有文件名没有扩展名则把最后的点号去掉 */
434 if (uiLen > 1 && szFileName[uiLen - 1] == '.')
435 {
436 szFileName[uiLen - 1] = 0;
437 uiLen--;
438 }
439
440 *pusLen = (USHORT)uiLen;
441
442 /* 转换为小写 */
443 for (i = 0; i < uiLen; i++)
444 {
445 if (szFileName[i] >= 'A' && szFileName[i] <= 'Z')
446 {
447 szFileName[i] = 'a' + (szFileName[i] - 'A');
448 }
449 }
450 return BISO_SUCCESS;
451 }
452
453 STATIC BISO_DIR_TREE_S * BISO_9660_CreateFileNode
454 (
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
460 )
461 {
462 UINT uiSecNum = 0;
463 BISO_DIR_TREE_S *pstNew = NULL;
464
465 DBGASSERT(NULL != pstRecord);
466 DBGASSERT(NULL != pstPre);
467 DBGASSERT(NULL != pstParent);
468
469 /* 申请内存用于保存文件节点 */
470 pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
471 if (NULL == pstNew)
472 {
473 return NULL;
474 }
475
476 /* 目录节点属性赋值 */
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;
481
482 /* 读取文件的Rock Ridge扩展信息 */
483 (VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstRecord, pstNew);
484
485 /* 更新文件所在目录的记录 */
486 if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstNew))
487 {
488 pstParent->pstDirStat->uiCurLinkNum++;
489 }
490 else
491 {
492 uiSecNum = BISO_USED_SECTOR_NUM(pstNew->uiSize);
493 pstParent->pstDirStat->uiCurFileNum++;
494 pstParent->pstDirStat->uiCurUsedSec += uiSecNum;
495 pstParent->pstDirStat->ui64CurSpace += pstNew->uiSize;
496 }
497
498 /* 节点挂接到当前目录的FileList上 */
499 if (NULL == pstPre)
500 {
501 pstParent->pstFileList = pstNew;
502 }
503 else
504 {
505 pstPre->pstNext = pstNew;
506 }
507 pstNew->pstParent = pstParent;
508
509 if (NULL == pstNew->pstPosixInfo && pstNew->usNameLen > 2)
510 {
511 BISO_9660_ProcRawFileNameFmt(pstNew->szName, &pstNew->usNameLen);
512 }
513
514 return pstNew;
515 }
516
517 STATIC BISO_SVD_DIR_TREE_S * BISO_9660_CreateSVDFileNode
518 (
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
524 )
525 {
526 BISO_SVD_DIR_TREE_S *pstNew = NULL;
527
528 DBGASSERT(NULL != pstRecord);
529 DBGASSERT(NULL != pstPre);
530 DBGASSERT(NULL != pstParent);
531
532 /* 申请内存用于保存文件节点 */
533 pstNew = (BISO_SVD_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_SVD_DIR_TREE_S));
534 if (NULL == pstNew)
535 {
536 return NULL;
537 }
538
539 /* 目录节点属性赋值 */
540 pstNew->uiExtent = pstRecord->uiExtent;
541 pstNew->uiSize = pstRecord->uiSize;
542
543 /* 节点挂接到当前目录的FileList上 */
544 if (NULL == pstPre)
545 {
546 pstParent->pstFileList = pstNew;
547 }
548 else
549 {
550 pstPre->pstNext = pstNew;
551 }
552 pstNew->pstParent = pstParent;
553
554 return pstNew;
555 }
556
557 STATIC ULONG BISO_9660_BuildFileList
558 (
559 IN BISO_FILE_S *pstFile,
560 IN BISO_PARSER_S *pstParser,
561 OUT BISO_DIR_TREE_S *pstDirTree
562 )
563 {
564 UINT uiTail = 0;
565 UINT uiBufSize = 0;
566 UINT uiTotSize = 0;
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;
572
573 DBGASSERT(NULL != pstFile);
574 DBGASSERT(NULL != pstDirTree);
575
576 /* 读取Directory Record记录 */
577 pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
578 if (NULL == pucBuf)
579 {
580 return BISO_ERR_ALLOC_MEM;
581 }
582
583 pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
584 pstChild = pstDirTree->pstChild;
585
586 while (uiTotSize < uiBufSize)
587 {
588 if (BOOL_TRUE != BISO_DIR_RECORD_IS_PATH(pstCurrent)) /* 只处理文件 */
589 {
590 /* 创建文件节点 */
591 pstNew = BISO_9660_CreateFileNode(pstFile, pstParser, pstCurrent, pstPre, pstDirTree);
592 if (NULL == pstNew)
593 {
594 BISO_FREE(pucBuf);
595 return BISO_ERR_ALLOC_MEM;
596 }
597 pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
598 + ((ULONG)pstCurrent - (ULONG)pucBuf);
599 pstPre = pstNew;
600 }
601 else
602 {
603 /* 对于子目录在这里更新目录的Rock Ridge扩展信息 */
604 if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
605 (BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
606 {
607 /*
608 * 这里首先按照Path Table里记录的子目录顺序来判断, 如果是就不用搜索了
609 * 如果不是则再从子目录列表中查询.
610 * 这里实际上取决于:
611 * Path Table里的子目录记录和Directory Record里面的子目录记录顺序是否一致!!!!
612 * 绝大多数情况下都是按照字母顺序,两者是一致的, 所以BISO_9660_FindChild一般情况下
613 * 是不会调用的
614 */
615 if (pstChild->uiExtent == pstCurrent->uiExtent)
616 {
617 pstNew = pstChild;
618 pstChild = pstChild->pstNext;
619 }
620 else
621 {
622 pstNew = BISO_9660_FindChild(pstDirTree, pstCurrent->uiExtent);
623 }
624
625 if (NULL != pstNew)
626 {
627 (VOID)BISO_RRIP_ReadExtInfo(pstFile, pstParser, pstCurrent, pstNew);
628 }
629 }
630 }
631
632 uiTotSize += pstCurrent->ucLength;
633 pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
634
635 /*
636 * !!!!!!!!!!!!!!!!!!!!!!!!
637 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
638 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
639 */
640 if (0 == pstCurrent->ucLength)
641 {
642 uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
643 uiTotSize += uiTail;
644 pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
645 }
646 }
647
648 BISO_FREE(pucBuf);
649 return BISO_SUCCESS;
650 }
651
652 /* 通过PathTable构建目录树(只包含目录)
653 这里利用Path Table,因此超过65535个文件夹的ISO文件只能读取前 65535个目录里的内容 */
654 STATIC ULONG BISO_9660_BuildPathTree
655 (
656 IN BISO_FILE_S *pstFile,
657 INOUT BISO_PARSER_S *pstParser,
658 OUT UINT *puiTotDirNum
659 )
660 {
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;
668
669 DBGASSERT(NULL != pstFile);
670 DBGASSERT(NULL != pstParser);
671 DBGASSERT(NULL != puiTotDirNum);
672
673 /*
674 * ISO-9660规定的Path Table的顺序实际上是文件树的一个广度优先遍历的形式
675 * 而处理广度优先遍历时一般需要一个先进先出的队列结构,这里创建一个使用
676 */
677 pstQueue = BISO_QUEUE_Create();
678 if (NULL == pstQueue)
679 {
680 return BISO_ERR_ALLOC_MEM;
681 }
682
683 /* ROOT根目录 */
684 pstPathTable = (BISO_PATH_TABLE_S *)(pstParser->pucPathTable);
685 pstDirTree = &(pstParser->stDirTree);
686 pstDirTree->uiPathTblId = 1;
687 pstDirTree->uiExtent = pstPathTable->uiExtent;
688
689 /* 申请统计信息的节点 */
690 pstDirTree->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
691 if (NULL == pstDirTree->pstDirStat)
692 {
693 return BISO_ERR_ALLOC_MEM;
694 }
695
696 /* 先把ROOT入队列 */
697 BISO_QUEUE_Push(pstQueue, pstDirTree);
698 pstPathTable = (BISO_PATH_TABLE_S *)((UCHAR *)pstPathTable + BISO_9660_PATH_LEN(pstPathTable));
699
700 /* 依次处理队列中的每一项直到队列读空 */
701 while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
702 {
703 /* 把该目录下的所有一级子目录读出来入队列 */
704 while ((USHORT)pstDirTree->uiPathTblId == pstPathTable->usParentDirNum)
705 {
706 /* 申请内存用于保存目录节点 */
707 pstNew = (BISO_DIR_TREE_S *)BISO_ZALLOC(sizeof(BISO_DIR_TREE_S));
708 if (NULL == pstNew)
709 {
710 BISO_QUEUE_Destroy(pstQueue);
711 return BISO_ERR_ALLOC_MEM;
712 }
713
714 /* 目录节点属性赋值 */
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);
719
720 /* 申请统计信息的节点 */
721 pstNew->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
722 if (NULL == pstNew->pstDirStat)
723 {
724 BISO_QUEUE_Destroy(pstQueue);
725 return BISO_ERR_ALLOC_MEM;
726 }
727
728 /* 挂接到父目录下 */
729 if (NULL == pstDirTree->pstChild)
730 {
731 pstDirTree->pstChild = pstNew;
732 }
733 else
734 {
735 pstPre->pstNext = pstNew;
736 }
737 pstNew->pstParent = pstDirTree;
738
739 pstPre = pstNew;
740 pstDirTree->pstDirStat->uiCurDirNum++;
741 uiTotDirNum++;
742 BISO_QUEUE_Push(pstQueue, pstNew);
743 pstPathTable = (BISO_PATH_TABLE_S *)((UCHAR *)pstPathTable + BISO_9660_PATH_LEN(pstPathTable));
744 }
745 }
746
747 *puiTotDirNum = uiTotDirNum;
748 BISO_QUEUE_Destroy(pstQueue);
749 return BISO_SUCCESS;
750 }
751
752 /* 更新整个目录树的目录结构中文件总数、目录总数、总空间大小等信息 */
753 ULONG BISO_9660_UpdateTreeStat(INOUT BISO_DIR_TREE_S *pstRoot)
754 {
755 VOID *pData = NULL;
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;
760
761 DBGASSERT(NULL != pstRoot);
762
763 pstQueue = BISO_QUEUE_Create();
764 if (NULL == pstQueue)
765 {
766 return BISO_ERR_ALLOC_MEM;
767 }
768
769 /* 构建DFS栈 */
770 BISO_9660_FillDfsStack(pstRoot, pstQueue);
771
772 /* 依次弹栈处理 */
773 while (NULL != (pData = BISO_QUEUE_PopTail(pstQueue)))
774 {
775 pstCurDir = (BISO_DIR_TREE_S *)pData;
776 pstDirStat = pstCurDir->pstDirStat;
777
778 /* 更新自己和父节点 */
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;
784
785 if (NULL != pstCurDir->pstParent) /* ROOT节点没有父节点 */
786 {
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;
793 }
794 }
795
796 /* 销毁堆栈 */
797 BISO_QUEUE_Destroy(pstQueue);
798 return BISO_SUCCESS;
799 }
800
801
802 ULONG BISO_9660_UpdateNodeStat
803 (
804 IN BOOL_T bAdd,
805 IN CONST BISO_DIR_TREE_S *pstCurNode,
806 INOUT BISO_DIR_TREE_S *pstParent
807 )
808 {
809 UINT uiSecNum = 0;
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;
814
815 DBGASSERT(NULL != pstCurNode);
816
817 memset(&stExDirStat, 0, sizeof(stExDirStat));
818 pstPreStat = pstParent->pstDirStat;
819
820 if (NULL == pstCurNode->pstDirStat) /* 非目录 */
821 {
822 if (BOOL_TRUE == BISO_DIR_TREE_IS_SYMLINK(pstCurNode)) /* 符号链接 */
823 {
824 /* 更新当前目录链接数统计, 大小为0不用更新 */
825 BISO_STAT_UPDATE(bAdd, pstPreStat->uiCurLinkNum, 1);
826 stExDirStat.uiTotLinkNum = 1;
827 }
828 else
829 {
830 /* 更新当前目录的文件数,大小等 */
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;
838 }
839 }
840 else
841 {
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部分 */
850 }
851
852 /* 依次更新上层目录的Total部分 */
853 pstCurDir = pstParent->pstParent;
854 while (NULL != pstCurDir)
855 {
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;
863 }
864
865 return BISO_SUCCESS;
866 }
867
868 ULONG BISO_9660_BuildFileTreeByTable
869 (
870 IN BISO_FILE_S *pstFile,
871 OUT BISO_PARSER_S *pstParser
872 )
873 {
874 ULONG ulRet;
875 UINT uiTotDirNum = 0;
876 BISO_QUEUE_S *pstQueue = NULL;
877 BISO_DIR_TREE_S *pstDirTree = NULL;
878
879 DBGASSERT(NULL != pstFile);
880 DBGASSERT(NULL != pstParser);
881
882 /* 先通过Path Table构建目录树(不包含文件) */
883 ulRet = BISO_9660_BuildPathTree(pstFile, pstParser, &uiTotDirNum);
884 if (BISO_SUCCESS != ulRet)
885 {
886 return ulRet;
887 }
888
889 /* 构建每一个目录下的文件列表 */
890
891 /* 创建队列用于递归遍历 */
892 pstQueue = BISO_QUEUE_Create();
893 if (NULL == pstQueue)
894 {
895 return BISO_ERR_ALLOC_MEM;
896 }
897
898 /* ROOT目录入队列 */
899 BISO_QUEUE_Push(pstQueue, &(pstParser->stDirTree));
900
901 /* 循环依次构建 */
902 while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
903 {
904 /* 构建文件列表 */
905 ulRet = BISO_9660_BuildFileList(pstFile, pstParser, pstDirTree);
906 if (BISO_SUCCESS != ulRet)
907 {
908 BISO_DIAG("Failed to build file list for dir %s.", pstDirTree->szName);
909 BISO_QUEUE_Destroy(pstQueue);
910 return ulRet;
911 }
912
913 /* 子目录入队列 */
914 if (NULL != pstDirTree->pstChild)
915 {
916 BISO_QUEUE_Push(pstQueue, pstDirTree->pstChild);
917 }
918
919 /* 下一个相邻目录入队列 */
920 if (NULL != pstDirTree->pstNext)
921 {
922 BISO_QUEUE_Push(pstQueue, pstDirTree->pstNext);
923 }
924 }
925
926 BISO_QUEUE_Destroy(pstQueue);
927 return BISO_SUCCESS;
928 }
929
930 ULONG BISO_9660_BuildFileTreeRecursively
931 (
932 IN BISO_FILE_S *pstFile,
933 OUT BISO_PARSER_S *pstParser
934 )
935 {
936 UINT uiTail = 0;
937 UINT uiTotSize = 0;
938 UINT uiBufSize = 0;
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;
946
947 DBGASSERT(NULL != pstFile);
948 DBGASSERT(NULL != pstParser);
949
950 /* 先对ROOT进行处理 */
951 pstDirTree = &(pstParser->stDirTree);
952 pstDirTree->uiPathTblId = 1;
953 pstDirTree->uiExtent = pstParser->pstPVD->stRootDirRecord.uiExtent;
954
955 /* 申请统计信息的内存 */
956 pstDirTree->pstDirStat = (BISO_DIR_STAT_S *)BISO_ZALLOC(sizeof(BISO_DIR_STAT_S));
957 if (NULL == pstDirTree->pstDirStat)
958 {
959 return BISO_ERR_ALLOC_MEM;
960 }
961
962 /* 创建堆栈,同时ROOT入栈 */
963 pstQueue = BISO_QUEUE_Create();
964 BISO_QUEUE_Push(pstQueue, pstDirTree);
965
966 while (NULL != (pstDirTree = (BISO_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
967 {
968 uiTotSize = 0;
969 pstPreDir = NULL;
970 pstPreFile = NULL;
971 pstDirTree->uiPathTblId = BISO_UINT_MAX;
972
973 /* 读取Directory Record记录 */
974 pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
975 if (NULL == pucBuf)
976 {
977 BISO_QUEUE_Destroy(pstQueue);
978 return BISO_ERR_ALLOC_MEM;
979 }
980
981 pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
982
983 while (uiTotSize < uiBufSize)
984 {
985 if (BOOL_TRUE == BISO_DIR_RECORD_IS_PATH(pstCurrent))
986 {
987 if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
988 (BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
989 {
990 /* 创建新目录节点 */
991 pstNew = BISO_9660_CreateDirNode(pstFile, pstParser, pstCurrent, pstPreDir, pstDirTree);
992 if (NULL == pstNew)
993 {
994 BISO_FREE(pucBuf);
995 BISO_QUEUE_Destroy(pstQueue);
996 return BISO_ERR_ALLOC_MEM;
997 }
998 pstPreDir = pstNew;
999
1000 /* 新目录入栈 */
1001 BISO_QUEUE_Push(pstQueue, pstNew);
1002 }
1003 }
1004 else
1005 {
1006 pstNew = BISO_9660_CreateFileNode(pstFile, pstParser, pstCurrent, pstPreFile, pstDirTree);
1007 if (NULL == pstNew)
1008 {
1009 BISO_FREE(pucBuf);
1010 BISO_QUEUE_Destroy(pstQueue);
1011 return BISO_ERR_ALLOC_MEM;
1012 }
1013 pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
1014 + ((ULONG)pstCurrent - (ULONG)pucBuf);
1015 pstPreFile = pstNew;
1016 }
1017
1018 uiTotSize += pstCurrent->ucLength;
1019 pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
1020
1021 /*
1022 * !!!!!!!!!!!!!!!!!!!!!!!!
1023 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
1024 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
1025 */
1026 if (0 == pstCurrent->ucLength)
1027 {
1028 uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
1029 uiTotSize += uiTail;
1030 pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
1031 }
1032 }
1033
1034 BISO_FREE(pucBuf);
1035 }
1036
1037 BISO_QUEUE_Destroy(pstQueue);
1038 return BISO_SUCCESS;
1039 }
1040
1041 ULONG BISO_9660_BuildSVDFileTreeRecursively
1042 (
1043 IN BISO_FILE_S *pstFile,
1044 OUT BISO_PARSER_S *pstParser
1045 )
1046 {
1047 UINT uiTail = 0;
1048 UINT uiTotSize = 0;
1049 UINT uiBufSize = 0;
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;
1057
1058 DBGASSERT(NULL != pstFile);
1059 DBGASSERT(NULL != pstParser);
1060
1061 /* 先对ROOT进行处理 */
1062 pstDirTree = &(pstParser->stSVDDirTree);
1063 pstDirTree->uiExtent = pstParser->pstSVD->stRootDirRecord.uiExtent;
1064
1065 /* 创建堆栈,同时ROOT入栈 */
1066 pstQueue = BISO_QUEUE_Create();
1067 BISO_QUEUE_Push(pstQueue, pstDirTree);
1068
1069 while (NULL != (pstDirTree = (BISO_SVD_DIR_TREE_S *)BISO_QUEUE_PopHead(pstQueue)))
1070 {
1071 uiTotSize = 0;
1072 pstPreDir = NULL;
1073 pstPreFile = NULL;
1074
1075 /* 读取Directory Record记录 */
1076 pucBuf = BISO_9660_ReadDirRecord(pstFile, pstDirTree->uiExtent, &uiBufSize);
1077 if (NULL == pucBuf)
1078 {
1079 BISO_QUEUE_Destroy(pstQueue);
1080 return BISO_ERR_ALLOC_MEM;
1081 }
1082
1083 pstCurrent = (BISO_DIR_RECORD_S *)pucBuf;
1084
1085 while (uiTotSize < uiBufSize)
1086 {
1087 if (BOOL_TRUE == BISO_DIR_RECORD_IS_PATH(pstCurrent))
1088 {
1089 if ((BOOL_TRUE != BISO_9660_IS_CURRENT(pstCurrent)) &&
1090 (BOOL_TRUE != BISO_9660_IS_PARENT(pstCurrent)))
1091 {
1092 /* 创建新目录节点 */
1093 pstNew = BISO_9660_CreateSVDDirNode(pstFile, pstParser, pstCurrent, pstPreDir, pstDirTree);
1094 if (NULL == pstNew)
1095 {
1096 BISO_FREE(pucBuf);
1097 BISO_QUEUE_Destroy(pstQueue);
1098 return BISO_ERR_ALLOC_MEM;
1099 }
1100 pstPreDir = pstNew;
1101
1102 /* 新目录入栈 */
1103 BISO_QUEUE_Push(pstQueue, pstNew);
1104 }
1105 }
1106 else
1107 {
1108 pstNew = BISO_9660_CreateSVDFileNode(pstFile, pstParser, pstCurrent, pstPreFile, pstDirTree);
1109 if (NULL == pstNew)
1110 {
1111 BISO_FREE(pucBuf);
1112 BISO_QUEUE_Destroy(pstQueue);
1113 return BISO_ERR_ALLOC_MEM;
1114 }
1115 pstNew->ui64FileRecordOffset = (UINT64)((UINT64)pstDirTree->uiExtent * BISO_SECTOR_SIZE)
1116 + ((ULONG)pstCurrent - (ULONG)pucBuf);
1117 pstPreFile = pstNew;
1118 }
1119
1120 uiTotSize += pstCurrent->ucLength;
1121 pstCurrent = (BISO_DIR_RECORD_S *)(pucBuf + uiTotSize);
1122
1123 /*
1124 * !!!!!!!!!!!!!!!!!!!!!!!!
1125 * ISO-9660规定Directory Record记录不能跨逻辑块,所以如果一个逻辑块的最后
1126 * 一段区域不够保存一个Directory Record的话这段区域就会废弃(填0)
1127 */
1128 if (0 == pstCurrent->ucLength)
1129 {
1130 uiTail = BISO_BLOCK_SIZE - (uiTotSize % BISO_BLOCK_SIZE);
1131 uiTotSize += uiTail;
1132 pstCurrent = (BISO_DIR_RECORD_S *)((UCHAR *)pstCurrent + uiTail);
1133 }
1134 }
1135
1136 BISO_FREE(pucBuf);
1137 }
1138
1139 BISO_QUEUE_Destroy(pstQueue);
1140 return BISO_SUCCESS;
1141 }
1142
1143 VOID BISO_9660_FreeDirTree(IN BISO_PARSER_S *pstParser)
1144 {
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;
1150
1151 if (NULL == pstParser)
1152 {
1153 return;
1154 }
1155
1156 /* 创建队列 */
1157 pstQueue = BISO_QUEUE_Create();
1158 if (NULL == pstQueue)
1159 {
1160 return;
1161 }
1162
1163 pstRoot = &pstParser->stDirTree;
1164
1165 /* 构建文件树入栈 */
1166 BISO_9660_FillDfsStack(pstRoot, pstQueue);
1167
1168 /* 不需要释放ROOT,把它从队列头弹出来 */
1169 BISO_QUEUE_PopHead(pstQueue);
1170
1171 /* 依次释放各个节点 */
1172 while (NULL != (pstCurDir = (BISO_DIR_TREE_S *)BISO_QUEUE_PopTail(pstQueue)))
1173 {
1174 /* 释放当前目录的文件列表 */
1175 for (pstPre = pstCurDir->pstFileList; NULL != pstPre; pstPre = pstNext)
1176 {
1177 pstNext = pstPre->pstNext;
1178 BISO_9600_FREE_DIRTREE(pstPre);
1179 }
1180
1181 /* 释放自己 */
1182 BISO_9600_FREE_DIRTREE(pstCurDir);
1183 }
1184
1185 /* 释放ROOT目录的文件列表 */
1186 for (pstPre = pstRoot->pstFileList; NULL != pstPre; pstPre = pstNext)
1187 {
1188 pstNext = pstPre->pstNext;
1189 BISO_9600_FREE_DIRTREE(pstPre);
1190 }
1191
1192 /* 释放ROOT自己的扩展信息,但不释放自己本身 */
1193 BISO_9600_FREE_STAT(pstRoot);
1194 BISO_9600_FREE_POSIX(pstRoot);
1195
1196 /* 销毁队列 */
1197 BISO_QUEUE_Destroy(pstQueue);
1198 }
1199
1200 VOID BISO_9660_FreeSVDDirTree(IN BISO_PARSER_S *pstParser)
1201 {
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;
1207
1208 if (NULL == pstParser ||
1209 0 == pstParser->stSVDDirTree.uiExtent ||
1210 0 == pstParser->stSVDDirTree.uiSize)
1211 {
1212 return;
1213 }
1214
1215 /* 创建队列 */
1216 pstQueue = BISO_QUEUE_Create();
1217 if (NULL == pstQueue)
1218 {
1219 return;
1220 }
1221
1222 pstRoot = &pstParser->stSVDDirTree;
1223
1224 /* 构建文件树入栈 */
1225 BISO_9660_FillDfsStack((BISO_DIR_TREE_S *)pstRoot, pstQueue);
1226
1227 /* 不需要释放ROOT,把它从队列头弹出来 */
1228 BISO_QUEUE_PopHead(pstQueue);
1229
1230 /* 依次释放各个节点 */
1231 while (NULL != (pstCurDir = (BISO_SVD_DIR_TREE_S *)BISO_QUEUE_PopTail(pstQueue)))
1232 {
1233 /* 释放当前目录的文件列表 */
1234 for (pstPre = pstCurDir->pstFileList; NULL != pstPre; pstPre = pstNext)
1235 {
1236 pstNext = pstPre->pstNext;
1237 BISO_FREE(pstPre);
1238 }
1239
1240 /* 释放自己 */
1241 BISO_FREE(pstCurDir);
1242 }
1243
1244 /* 释放ROOT目录的文件列表 */
1245 for (pstPre = pstRoot->pstFileList; NULL != pstPre; pstPre = pstNext)
1246 {
1247 pstNext = pstPre->pstNext;
1248 BISO_FREE(pstPre);
1249 }
1250
1251 /* 销毁队列 */
1252 BISO_QUEUE_Destroy(pstQueue);
1253 }
1254
1255 BISO_PARSER_S * BISO_9660_CreateParser(VOID)
1256 {
1257 BISO_PARSER_S *pstParser = NULL;
1258
1259 pstParser = (BISO_PARSER_S *)BISO_ZALLOC(sizeof(BISO_PARSER_S));
1260 if (NULL == pstParser)
1261 {
1262 return NULL;
1263 }
1264
1265 /* 初始化链表 */
1266 BISO_DLL_Init(&(pstParser->stVDList));
1267
1268 return pstParser;
1269 }
1270
1271 VOID BISO_9660_CleanParser(INOUT BISO_PARSER_S *pstParser)
1272 {
1273 if (NULL == pstParser)
1274 {
1275 return;
1276 }
1277
1278 /* 释放Volume Descriptor链表 */
1279 BISO_DLL_Free(&(pstParser->stVDList));
1280
1281 /* 释放Path Table */
1282 if (NULL != pstParser->pucPathTable)
1283 {
1284 BISO_FREE(pstParser->pucPathTable);
1285 }
1286
1287 /* 释放 El Torito数据 */
1288 if (NULL != pstParser->pucElToritoEntry)
1289 {
1290 BISO_FREE(pstParser->pucElToritoEntry);
1291 }
1292
1293 /* 释放文件树 */
1294 BISO_9660_FreeDirTree(pstParser);
1295 BISO_9660_FreeSVDDirTree(pstParser);
1296 }
1297
1298 VOID BISO_9660_DestroyParser(INOUT BISO_PARSER_S *pstParser)
1299 {
1300 if (NULL == pstParser)
1301 {
1302 return;
1303 }
1304
1305 /* 清理解析器 */
1306 BISO_9660_CleanParser(pstParser);
1307
1308 /* 释放解析器自己 */
1309 BISO_FREE(pstParser);
1310 }
1311
1312 ULONG BISO_9660_OpenImage
1313 (
1314 IN BOOL_T bParseSVDDirTree,
1315 IN CONST CHAR *pcFileName,
1316 OUT BISO_PARSER_S *pstParser
1317 )
1318 {
1319 UINT64 ui64FileSize = 0;
1320 ULONG ulRet = BISO_SUCCESS;
1321 BISO_FILE_S *pstFile = NULL;
1322
1323 if ((NULL == pcFileName) || (NULL == pstParser))
1324 {
1325 return BISO_ERR_NULL_PTR;
1326 }
1327
1328 /* 先看文件大小,过小的文件不可能是ISO文件 */
1329 ui64FileSize = BISO_PLAT_GetFileSize(pcFileName);
1330 if (ui64FileSize < BISO_SYSTEM_AREA_SIZE + sizeof(BISO_PVD_S))
1331 {
1332 BISO_DIAG("File len %llu is too small.", (ULONGLONG)ui64FileSize);
1333 return BISO_ERR_INVALID_ISO9660;
1334 }
1335
1336 /* 如果已有数据则先清空 */
1337 if (NULL != pstParser->pstPVD)
1338 {
1339 BISO_9660_CleanParser(pstParser);
1340 }
1341
1342 /* 打开ISO文件 */
1343 pstFile = BISO_PLAT_OpenExistFile(pcFileName);
1344 if (NULL == pstFile)
1345 {
1346 BISO_DIAG("Failed to open file %s.", pcFileName);
1347 return BISO_ERR_OPEN_FILE;
1348 }
1349
1350 scnprintf(pstParser->szFileName, sizeof(pstParser->szFileName), "%s", pcFileName);
1351
1352 /* 读取Volume Description信息 */
1353 ulRet = BISO_9660_ReadVD(pstFile, pstParser);
1354 BISO_9660_CHECK_RET(ulRet, pstFile);
1355
1356 /* 读取Path Table */
1357 ulRet = BISO_9660_ReadPathTable(pstFile, pstParser);
1358 BISO_9660_CHECK_RET(ulRet, pstFile);
1359
1360 /* 读取BOOT启动信息 */
1361 ulRet = BISO_ELTORITO_ReadBootInfo(pstFile, pstParser);
1362 BISO_9660_CHECK_RET(ulRet, pstFile);
1363
1364 /* 读取Rock Ridge扩展标识 */
1365 ulRet = BISO_RRIP_ReadIndicator(pstParser);
1366 BISO_9660_CHECK_RET(ulRet, pstFile);
1367
1368 /* 这里构建文件树有两种方法可供选择, 暂时选择从ROOT递归创建的方法 */
1369
1370 #if 0
1371 /* 从ISO文件中读取整个文件树, 这里选择根据Path Table构建 */
1372 ulRet += BISO_9660_BuildFileTreeByTable(pstFile, pstParser);
1373 BISO_9660_CHECK_RET(ulRet, pstFile);
1374 #else
1375 /* 从ISO文件中读取整个文件树, 这里选择从ROOT开始递归构建 */
1376 ulRet = BISO_9660_BuildFileTreeRecursively(pstFile, pstParser);
1377 BISO_9660_CHECK_RET(ulRet, pstFile);
1378 #endif /* #if 0 */
1379
1380 if (bParseSVDDirTree && pstParser->pstSVD)
1381 {
1382 ulRet = BISO_9660_BuildSVDFileTreeRecursively(pstFile, pstParser);
1383 BISO_9660_CHECK_RET(ulRet, pstFile);
1384 }
1385
1386 /* 更新目录结构里的统计信息 */
1387 ulRet = BISO_9660_UpdateTreeStat(&(pstParser->stDirTree));
1388 BISO_9660_CHECK_RET(ulRet, pstFile);
1389
1390 BISO_PLAT_CloseFile(pstFile);
1391 return BISO_SUCCESS;
1392 }
1393
1394
1395 ULONG BISO_9660_ParseDate84261
1396 (
1397 IN CONST CHAR *pcDate,
1398 OUT BISO_DATE_S *pstDate
1399 )
1400 {
1401 INT aiBuf[7] = { 0 };
1402
1403 if ((NULL == pcDate) || (NULL == pstDate))
1404 {
1405 return BISO_ERR_NULL_PTR;
1406 }
1407
1408 /*
1409 * ECMA-119 8.4.26.1节定义的日期格式,共17个字节
1410 * 前16个字节是字符,第17个字节是有符号整数
1411 * 如果前16个字节是字符'0', 最后一个是'\0'则表示时间无效
1412 * 形如 "2014122013000500*"
1413 */
1414
1415 if ((0 == pcDate[0]) || (' ' == pcDate[0]) || ('0' == pcDate[0]))
1416 {
1417 return BISO_ERR_NOT_RECORD;
1418 }
1419
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); /* 表示百分之一秒 */
1430
1431 /* 第17字节表示时区信息, 15分钟为1个单位,4个单位就是1个时区 */
1432 pstDate->cZone = pcDate[16] / 4;
1433
1434 return BISO_SUCCESS;
1435 }
1436
1437 VOID BISO_9660_FmtDate84261(IN time_t ulTime, IN UINT uiBufSize, OUT CHAR *pcDate)
1438 {
1439 INT iTimeZone = BISO_UTIL_GetTimeZone();
1440 struct tm *pstTm = NULL;
1441
1442 if (NULL != pcDate)
1443 {
1444 pstTm = localtime(&ulTime);
1445 scnprintf(pcDate, uiBufSize, "%04d%02d%02d%02d%02d%02d%02d",
1446 pstTm->tm_year + 1900,
1447 pstTm->tm_mon + 1,
1448 pstTm->tm_mday,
1449 pstTm->tm_hour,
1450 pstTm->tm_min,
1451 pstTm->tm_sec,
1452 0);
1453
1454 /* 第17个字节记录当前时区 */
1455 pcDate[16] = (CHAR)(4 * iTimeZone);
1456 }
1457 }
1458