iso9660重新回顾

来源:互联网 发布:sopcast网络电视直播 编辑:程序博客网 时间:2024/06/07 00:55

读取ISO9660格式文件的过程主要分为3步:

读取PVD,地址是0x210,也可以说是2分16秒,或者LSN=16,其实都是一个地方。用dd命令把碟片从光驱里抓出来,保存成ISO文件放在电脑里,不需要把整张碟抓出,只需要抓取前面的2M字节左右,用来方便分析光盘的结构。

前面说了,第16个扇区的地址,计算起来就是16x2048 = 32k,转成16进制就是0x8000。

用UE打开刚才抓到ISO文件,转到0x8000的地方,就是下面图片的样子。首先看到CD001,就是ISO9660的格式标记。

然后后面在140 offset的地方是path table的扇区地址,156的地方是root dir record,长度是34个字节。一般Linux的标准是读取这个root record,而不是走path table的流程。

通过根记录这个节点,就可以不断遍历整个目录树,但速度会比较慢。如果想一次性读取到所有目录里的文件,就可以走path table的流程,这部分Linux里面没有实现,但普通DVD的软件里面是这样做的。

从图片里高度选中的部分是根记录的入口扇区,可以看出是0x17,也就是23扇区里面就是记录根目录节点的详细资料。



struct iso_primary_descriptor {char type[ISODCL (  1,   1)]; /* 711 */char id[ISODCL (  2,   6)];char version[ISODCL (  7,   7)]; /* 711 */char unused1[ISODCL (  8,   8)];char system_id[ISODCL (  9,  40)]; /* achars */char volume_id[ISODCL ( 41,  72)]; /* dchars */char unused2[ISODCL ( 73,  80)];char volume_space_size[ISODCL ( 81,  88)]; /* 733 */char unused3[ISODCL ( 89, 120)];char volume_set_size[ISODCL (121, 124)]; /* 723 */char volume_sequence_number[ISODCL (125, 128)]; /* 723 */char logical_block_size[ISODCL (129, 132)]; /* 723 */char path_table_size[ISODCL (133, 140)]; /* 733 */char type_l_path_table[ISODCL (141, 144)]; /* 731 */char opt_type_l_path_table[ISODCL (145, 148)]; /* 731 */char type_m_path_table[ISODCL (149, 152)]; /* 732 */char opt_type_m_path_table[ISODCL (153, 156)]; /* 732 */char root_directory_record[ISODCL (157, 190)]; /* 9.1 */char volume_set_id[ISODCL (191, 318)]; /* dchars */char publisher_id[ISODCL (319, 446)]; /* achars */char preparer_id[ISODCL (447, 574)]; /* achars */char application_id[ISODCL (575, 702)]; /* achars */char copyright_file_id[ISODCL (703, 739)]; /* 7.5 dchars */char abstract_file_id[ISODCL (740, 776)]; /* 7.5 dchars */char bibliographic_file_id[ISODCL (777, 813)]; /* 7.5 dchars */char creation_date[ISODCL (814, 830)]; /* 8.4.26.1 */char modification_date[ISODCL (831, 847)]; /* 8.4.26.1 */char expiration_date[ISODCL (848, 864)]; /* 8.4.26.1 */char effective_date[ISODCL (865, 881)]; /* 8.4.26.1 */char file_structure_version[ISODCL (882, 882)]; /* 711 */char unused4[ISODCL (883, 883)];char application_data[ISODCL (884, 1395)];char unused5[ISODCL (1396, 2048)];};/* Almost the same as the primary descriptor but two fields are specified */


按照之前的方法计算一下,23x2048 = 46k,用16进制表示为:0xb800,查看相关的数据如下图所示:

第一个项目是当前目录,也就是./目录,然后是当前目录下的其他文件或目录,每一项里面都有extent的地址,如果是文件就指向文件的实际数据入口,如果是目录,则表示子目录的入口。一个记录是目录还是文件是由flag项里面的第2位表示的,一般flag == 0x02就是目录,如果0x00就是文件。如果一个目录的flag == 0x06,则表示它是一个associated file,意思是关联的文件。但根据ecma119的说明,一个目录不应该被定义成关联文件,所以这个地方是有问题的.在Linux下会看不到这个目录,估计是某个条件判断过滤掉了。如最后一个目录是VIDEO_TS,但标记因为是0x06,所以Linux下是看不到的。但是如果进入这个目录的实际位置,也就是0x26的地方,就可以看到里面是有内容的。


根目录信息

这里面的数据结构是dir record,结构体是这样的:

struct iso_directory_record {char length[ISODCL (1, 1)]; /* 711 */char ext_attr_length[ISODCL (2, 2)]; /* 711 */char extent[ISODCL (3, 10)]; /* 733 */char size[ISODCL (11, 18)]; /* 733 */char date[ISODCL (19, 25)]; /* 7 by 711 */char flags[ISODCL (26, 26)];char file_unit_size[ISODCL (27, 27)]; /* 711 */char interleave[ISODCL (28, 28)]; /* 711 */char volume_sequence_number[ISODCL (29, 32)]; /* 723 */unsigned char name_len[ISODCL (33, 33)]; /* 711 */char name[0];} __attribute__((packed));

进入0x26扇区,也就是0x13000的位置:

可以看到VIDEO_TS.VOB这些文件,就是刚才VIDEO_TS目录下面的文件了。



下面再写一下path table的方式,从之前PVD的地方看到,path table的入口是0x13,也就是0x9800的位置。这里只记录目录的入口,而且所有目录部分层次,都是按照平摊的方式列出,那么假如一个扇区放不完会怎么办,那么理论上应该要继续判断下一个扇区,因为Linux里面没有实现,实际上也还没有遇到过这种情况,暂时不做讨论了。

从path table上也能找到VIDEO_TS这个目录的入口地址同样为0x26.


路径表的结构比较简单:

struct iso_path_table{unsigned char  name_len[2];/* 721 */char extent[4];/* 731 */char  parent[2];/* 721 */char name[0];} __attribute__((packed));


0 0
原创粉丝点击