UDF 文件系统读取、蓝光元数据分区、带有 ISO 映像的 libdvdread

发布于 2024-12-26 12:17:38 字数 5867 浏览 6 评论 0原文

所以这可能有点太具体了,太多了,任何人都无法阅读,任何人都无法提供帮助。但也许有人以前做过这件事。

我目前正在使用可靠但不太准确的 libdvdread 库来读取 ISO 文件/设备。但在这种情况下,具体的实现并不那么重要。更多的是关于如何读取 UDF 文件系统。我读过很多 Ecma-167 和 udf260 PDF 文件。

因此,首先,让我们看一下来自 IMGBURN 的 ISO 映像,它似乎可以工作,就像从零售蓝光复制的映像一样。

这些块的布局如下:

Block  32 TagID:    1 TAGID_PRI_VOL
Block  33 TagID:    4 TAGID_IMP_VOL
Block  34 TagID:    5 TAGID_PARTITION
Block  35 TagID:    6 TAGID_LOGVOL
Block  36 TagID:    7 TAGID_UNALLOC_SPACE
Block  37 TagID:    8 TAGID_TERM
Block  64 TagID:    9 TAGID_LOGVOL_INTEGRITY
Block  65 TagID:    8 TAGID_TERM
Block 256 TagID:    2 TAGID_ANCHOR
Block 288 TagID:  266 TAGID_EXTFENTRY
Block 320 TagID:  256 TAGID_FSD
Block 321 TagID:    8 TAGID_TERM
Block 322 TagID:  266 TAGID_EXTFENTRY
Block 323 TagID:  257 TAGID_FID
Block 324 TagID:  266 TAGID_EXTFENTRY
Block 325 TagID:  266 TAGID_EXTFENTRY
Block 326 TagID:  257 TAGID_FID
Block 327 TagID:  266 TAGID_EXTFENTRY

因此我们开始读取 ISO 映像;

* Read Block 256 which is    2 TAGID_ANCHOR
* Read Block  32 which is    1 TAGID_PRI_VOL
* Read Block  33 which is    4 TAGID_IMP_VOL
* Read Block  34 which is    5 TAGID_PARTITION
Partiton: number 0, start 288, length 2291200, AccessType 1
* Read Block  35 which is    6 TAGID_LOGVOL
LogVolume 2048:70:2
Volume 0 type 01 (len 6) Seq 0001 Part 0000
Volume 1 type 02:
Partition identifier: '*UDF Metadata Partition'
 Metadata Partition MainLoc 00000000, MirrorLoc 0022F5A9, BitmapLoc FFFFFFFF, AllocSize 00000020, AlignSize 0020, Flags 1.
returning Start 288
Found partition at 288 length 2291200
Starting scan from 288 (metadata adjusted)

到目前为止,一切都很好。您可以看到我采用了“元数据主文件位置”(在本例中为 0),并将其添加到分区开头,以查找 FSD。即使对于“元数据主文件位置”不为 0 的示例,这似乎也适用。稍后会详细介绍。

现在查找FSD,我们找到的第一项是:

* Read Block 288 which is  266 TAGID_EXTFENTRY
TagID 266 with filetype 250
   Metadata Main at location 32 (+partition.start 320)

Ecma-167 定义filetype=250 有“元数据主文件”,AD.Location 指向元数据。还可以找到 filetype=251(元数据镜像文件),

我使用“元数据主文件”位置(此处为 32)作为“真正”查找 FSD 的间接指针。由于某种原因,这是partition.Start + Location (288 + 32) = 320。

在块320,我们找到FSD。所以也许我走在正确的轨道上。

Now Scanning from 320
* Read Block 320 which is  256 TAGID_FSD
RootICB at 2 length 2048
MapICB starting at 320,2 -> 322

太好了,我们读了 FSD,它的 RootICB 位于“+2”。现在我预计这是“partition.Start + 2”(288+2),但这不起作用。有效的是“FSD_Location + 2”(320+2)。事实真的如此吗?

在 DVD ISO 中,FSD_Location=0(分区上的第一个块,因为中间没有 EXTFileInfo+250),因此使用此逻辑仍然有效。

假设它是正确的;

* Read Block 322 which is  266 TAGID_EXTFENTRY
libdvdread: reading AD chain 0
UDFMapICB TagID 266 ExtFile with filetype 4
Part.Start 288 FSD loc 320 RootICB 2 (len 2048) File has loc 3

因此,322 处的块确实是一个 ExtFileInfo,文件类型==4(目录),并且位于 location = +3。同样,这似乎是“fsd_location + 3”= 323。

Found '/' at 323 (size 152).
* Read Block 323 which is  257 TAGID_FID
DVDReadDir(.)
DVDReadDir(BDMV)
etc

成功。上面列出了所有内容。

这是我感到困惑的地方。我使用 OSX“newfs_udf”为自己创建一个 UDF 测试映像;

# mkfile 1G roger.iso
# newfs_udf -eu -r 2.60 -v HIGHLANDER roger.iso
# hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount roger.iso
# hdiutil mount -nobrowse roger.iso
# mkdir /Volumes/HIGHLANDER/A.DIRECTORY.ENTRY

这些块是:

Block  20 TagID:    1 TAGID_PRI_VOL
Block  21 TagID:    4 TAGID_IMP_VOL
Block  22 TagID:    5 TAGID_PARTITION
Block  23 TagID:    6 TAGID_LOGVOL
Block  24 TagID:    7 TAGID_UNALLOC_SPACE
Block  25 TagID:    8 TAGID_TERM
Block  36 TagID:    9 TAGID_LOGVOL_INTEGRITY
Block  37 TagID:    8 TAGID_TERM
Block 256 TagID:    2 TAGID_ANCHOR
Block 257 TagID:  264 TAGID_SPACE_BITMAP
Block 289 TagID:  266 TAGID_EXTFENTRY
Block 290 TagID:  266 TAGID_EXTFENTRY
Block 291 TagID:  256 TAGID_FSD
Block 292 TagID:  266 TAGID_EXTFENTRY
Block 293 TagID:  266 TAGID_EXTFENTRY
Block 294 TagID:  266 TAGID_EXTFENTRY
Block 295 TagID:  266 TAGID_EXTFENTRY
Block 296 TagID:  266 TAGID_EXTFENTRY
Block 323 TagID:  264 TAGID_SPACE_BITMAP
Block 449 TagID:  259 TAGID_INDIRECTENTRY

阅读此 ISO 也很有效,至少在最初是这样;

* Read Block 256 which is    2 TAGID_ANCHOR
* Read Block  20 which is    1 TAGID_PRI_VOL
* Read Block  21 which is    4 TAGID_IMP_VOL
* Read Block  22 which is    5 TAGID_PARTITION
Partiton: number 0, start 257, length 523774, AccessType 4
* Read Block  23 which is    6 TAGID_LOGVOL
LogVolume 2048:70:2
Volume 0 type 01 (len 6) Seq 0001 Part 0000
Volume 1 type 02:
Partition identifier: '*UDF Metadata Partition'
 Metadata Partition MainLoc 00000020, MirrorLoc 0007FDFD, BitmapLoc 00000021, AllocSize 00000020, AlignSize 0001, Flags 0.
returning Start 257
Found partition at 257 length 523774
Starting scan from 289 (metadata adjusted)

* Read Block 289 which is  266 TAGID_EXTFENTRY
TagID 266 with filetype 250
   Metadata Main at location 34 (+partition.start 291)

* Read Block 291 which is  256 TAGID_FSD
RootICB at 1 length 2048

* Read Block 292 which is  266 TAGID_EXTFENTRY
UDFMapICB TagID 266 ExtFile with filetype 4
Part.Start 257 FSD loc 291 RootICB 1 (len 2048) File has loc 34

请注意,此处的元数据分区为+32,通过添加我们正确找到了 ExtFileInfo+Filetype=250。那么这是+34,它正确地为我们提供了FSD!

FSD 的 RootICB 位于 +34,同样来自 FSD,即 291+34 = 325。

并且它丢失了。我猜应该是 292,但是;

...在阻止列表中,您可以看到根本没有 FID。查看此 ISO 映像的十六进制转储,可以在块 292 中找到“A.DIRECTORY.ENTRY”。这是一个 ExtFileEntry。正是这个让我们开始寻找元数据主文件位置。

我认为 ExtFileInfo 仅包含一 (1) 个文件描述符,其中 ICB 指向其数据。然而,在偏移量 +380 左右的这个块内,我们有 root (null)、“A.DIRECTORY.ENTRY”和“.Trashes”。

我想我的问题是,OSX 是否以某种方式将 FID 压缩到 ExtFileEntry 中?并且无需 FID 块。这“有效”吗?我如何检测这种情况?此 ExtFileInfo 中是否有某些内容表明我不应该“不要按照位置查找 FID”并“继续解析此块以获取更多条目”。

计算 ICB 时,我必须对目录使用“fsd_location + icb.location”,但对于文件(以读取实际文件数据),我必须使用“partition.Start + icb.location”。这按预期工作(目录列表和文件没有差异),但似乎不正确。

如果你读完了所有这些,你就太棒了:)现在,如果你能给我一些线索......

So this might be a little too specific, and too much for anyone to read, for anyone to be able to help. But maybe there is someone out there who has done this before.

I am currently using the trusty, but not very accurate, libdvdread library to read ISO files/devices. But the specific implementation is not so important in this case. It is more on HOW to read UDF file systems. I have read both Ecma-167, and udf260 PDF files, lots.

So, first, let's look at an ISO image from IMGBURN, which appears to work, just the same as an image copied from a retail bluray.

The blocks are laid out as:

Block  32 TagID:    1 TAGID_PRI_VOL
Block  33 TagID:    4 TAGID_IMP_VOL
Block  34 TagID:    5 TAGID_PARTITION
Block  35 TagID:    6 TAGID_LOGVOL
Block  36 TagID:    7 TAGID_UNALLOC_SPACE
Block  37 TagID:    8 TAGID_TERM
Block  64 TagID:    9 TAGID_LOGVOL_INTEGRITY
Block  65 TagID:    8 TAGID_TERM
Block 256 TagID:    2 TAGID_ANCHOR
Block 288 TagID:  266 TAGID_EXTFENTRY
Block 320 TagID:  256 TAGID_FSD
Block 321 TagID:    8 TAGID_TERM
Block 322 TagID:  266 TAGID_EXTFENTRY
Block 323 TagID:  257 TAGID_FID
Block 324 TagID:  266 TAGID_EXTFENTRY
Block 325 TagID:  266 TAGID_EXTFENTRY
Block 326 TagID:  257 TAGID_FID
Block 327 TagID:  266 TAGID_EXTFENTRY

So we start to read the ISO image;

* Read Block 256 which is    2 TAGID_ANCHOR
* Read Block  32 which is    1 TAGID_PRI_VOL
* Read Block  33 which is    4 TAGID_IMP_VOL
* Read Block  34 which is    5 TAGID_PARTITION
Partiton: number 0, start 288, length 2291200, AccessType 1
* Read Block  35 which is    6 TAGID_LOGVOL
LogVolume 2048:70:2
Volume 0 type 01 (len 6) Seq 0001 Part 0000
Volume 1 type 02:
Partition identifier: '*UDF Metadata Partition'
 Metadata Partition MainLoc 00000000, MirrorLoc 0022F5A9, BitmapLoc FFFFFFFF, AllocSize 00000020, AlignSize 0020, Flags 1.
returning Start 288
Found partition at 288 length 2291200
Starting scan from 288 (metadata adjusted)

So far so good. You can see I take the "metadata main file location", in this example 0, and add it to the partition start, to go look for the FSD. This appears to work even with examples where "metadata main file location" is not 0. More on that later.

Looking for the FSD now, the first item we find is:

* Read Block 288 which is  266 TAGID_EXTFENTRY
TagID 266 with filetype 250
   Metadata Main at location 32 (+partition.start 320)

The Ecma-167 defines filetype=250 has "metadata main file", and the AD.Location points to the metadata. There is also possible to find a filetype=251 (metadata mirror file)

I use the "metadata main file" location (here, 32) as an indirect pointer to where to "really" look for the FSD. For some reason, this is partition.Start + Location (288 + 32) = 320.

At block 320 we find the FSD. So maybe I am on the right track.

Now Scanning from 320
* Read Block 320 which is  256 TAGID_FSD
RootICB at 2 length 2048
MapICB starting at 320,2 -> 322

Great, we read the FSD, and it have RootICB at "+2". Now I would have expected this to be "partition.Start + 2" (288+2), but this does not work. What does work is "FSD_Location + 2" (320+2). Can this really be the case?

In DVD ISOs, FSD_Location=0 (first block on partition, as there is no EXTFileInfo+250 in the way), so using this logic still works.

Lets assume it is correct;

* Read Block 322 which is  266 TAGID_EXTFENTRY
libdvdread: reading AD chain 0
UDFMapICB TagID 266 ExtFile with filetype 4
Part.Start 288 FSD loc 320 RootICB 2 (len 2048) File has loc 3

So, the block at 322 is indeed an ExtFileInfo, of filetype==4 (directory) and lives at location = +3. Again, this appears to be "fsd_location + 3" = 323.

Found '/' at 323 (size 152).
* Read Block 323 which is  257 TAGID_FID
DVDReadDir(.)
DVDReadDir(BDMV)
etc

Success. It goes on the list all the contents.

Here is where I get confused. I use the OSX "newfs_udf" to create myself a UDF test image;

# mkfile 1G roger.iso
# newfs_udf -eu -r 2.60 -v HIGHLANDER roger.iso
# hdiutil attach -imagekey diskimage-class=CRawDiskImage -nomount roger.iso
# hdiutil mount -nobrowse roger.iso
# mkdir /Volumes/HIGHLANDER/A.DIRECTORY.ENTRY

The blocks are:

Block  20 TagID:    1 TAGID_PRI_VOL
Block  21 TagID:    4 TAGID_IMP_VOL
Block  22 TagID:    5 TAGID_PARTITION
Block  23 TagID:    6 TAGID_LOGVOL
Block  24 TagID:    7 TAGID_UNALLOC_SPACE
Block  25 TagID:    8 TAGID_TERM
Block  36 TagID:    9 TAGID_LOGVOL_INTEGRITY
Block  37 TagID:    8 TAGID_TERM
Block 256 TagID:    2 TAGID_ANCHOR
Block 257 TagID:  264 TAGID_SPACE_BITMAP
Block 289 TagID:  266 TAGID_EXTFENTRY
Block 290 TagID:  266 TAGID_EXTFENTRY
Block 291 TagID:  256 TAGID_FSD
Block 292 TagID:  266 TAGID_EXTFENTRY
Block 293 TagID:  266 TAGID_EXTFENTRY
Block 294 TagID:  266 TAGID_EXTFENTRY
Block 295 TagID:  266 TAGID_EXTFENTRY
Block 296 TagID:  266 TAGID_EXTFENTRY
Block 323 TagID:  264 TAGID_SPACE_BITMAP
Block 449 TagID:  259 TAGID_INDIRECTENTRY

Reading this ISO also works well, at least initially;

* Read Block 256 which is    2 TAGID_ANCHOR
* Read Block  20 which is    1 TAGID_PRI_VOL
* Read Block  21 which is    4 TAGID_IMP_VOL
* Read Block  22 which is    5 TAGID_PARTITION
Partiton: number 0, start 257, length 523774, AccessType 4
* Read Block  23 which is    6 TAGID_LOGVOL
LogVolume 2048:70:2
Volume 0 type 01 (len 6) Seq 0001 Part 0000
Volume 1 type 02:
Partition identifier: '*UDF Metadata Partition'
 Metadata Partition MainLoc 00000020, MirrorLoc 0007FDFD, BitmapLoc 00000021, AllocSize 00000020, AlignSize 0001, Flags 0.
returning Start 257
Found partition at 257 length 523774
Starting scan from 289 (metadata adjusted)

* Read Block 289 which is  266 TAGID_EXTFENTRY
TagID 266 with filetype 250
   Metadata Main at location 34 (+partition.start 291)

* Read Block 291 which is  256 TAGID_FSD
RootICB at 1 length 2048

* Read Block 292 which is  266 TAGID_EXTFENTRY
UDFMapICB TagID 266 ExtFile with filetype 4
Part.Start 257 FSD loc 291 RootICB 1 (len 2048) File has loc 34

Notice the metadata partition is +32 here, by adding that we correctly find the ExtFileInfo+Filetype=250. This then is +34, which correctly gets us the FSD!

The FSD has RootICB at +34, again from FSD, which is 291+34 = 325.

And it is lost. I would guess it SHOULD be 292, but;

...In the block list, you can see there are no FIDs at all. Looking at the hexdump of this ISO image, the "A.DIRECTORY.ENTRY" can be found in block 292. Which is a ExtFileEntry. The very one that sent us off looking for metadata-main-file-location.

I thought ExtFileInfo only contained one (1) file descriptor with ICB pointing to its data. And yet, inside this block at offset +380 or so, we have root (null), "A.DIRECTORY.ENTRY" and ".Trashes".

I guess my question is, does the OSX compress FIDs into ExtFileEntry somehow? and go without FID blocks. Is this "valid"? How do I detect this situation? Is there something in this ExtFileInfo that indicates I should "not follow the Location to look for FIDs" and "keep parsing this block for more entries".

When computing the ICB, I have to use "fsd_location + icb.location" for directories, but with files (to read the actual file data) I have to use "partition.Start + icb.location". This works as expected (directories list, and files have no differences) but it does not seem correct.

If you read all that, you are awesome :) Now, if you could just give me some clues...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

橘亓 2025-01-02 12:17:38

好吧,我觉得我已经掌握了这一切,无论是来自 ECMA 167 还是 BSD UDF 源。缺少的魔力是 ICBTAG.Flags=3 类型,它不是在块末尾有一个“AD”列表,而是将实际的“文件内容”放在 AD 空间中。如果文件数据小于 2048 字节,则采用某种“空间节省器”样式。

如果存在元数据,它还清除了使用 FSD 作为偏移量。所有目录内容都将包含在元数据文件(主文件和镜像文件)中。

OK I feel I got the hang of it all, both from ECMA 167 and BSD UDF sources. The missing magic was that ICBTAG.Flags=3 type, where instead of having a list of "AD" at the end of the block, it puts the actual "file contents" in the AD space. Some sort of "space saver" style, if the file data is less than 2048 bytes.

It also cleared the use of FSD as offset if the metadata is present. All directory content is to be contained in the metadata file (main and mirror).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文