summaryrefslogtreecommitdiffstats
path: root/debian/patches/libdvdread/debian-0002-descriptor.patch
blob: a61d4f4b7f02ce2e75bfc37c2eb18f4908397f40 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
From: Mario Holbe <mario.holbe@tu-ilmenau.de>
Date: Tue, 22 Apr 2014 11:49:42 +0200
Subject: descriptor
Forwarded: not-needed

libdvdread is very likely to fail on discs/images that store their File
System Descriptor at the end of the disc/image rather than at the
beginning. This is due to the "strategy" libdvdread uses to find it:
libdvdread scans sequentially from the beginning of the disc/image for
the File System Descriptor and identifies it by a single byte tag.

Aside from wasting lots of time on discs/images that store their File
System Descriptor at the end there is quite a good chance to stumble
across a random data block that accidentally starts with this tag (and
failing on it) before finding the real File System Descriptor.

As far as I can see, at least CDBurnerXP seems to (be able to) create
such images - at least if my interpretation of the Implementation
Identifier "NMS DVDProLib" is correct.

This... well, let's call it ugly hack fixes this by obtaining
the File System Descriptor location from the Logical Volume Descriptor

Closes: #663512
---
 libdvdread-embedded/src/dvd_udf.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/libdvdread-embedded/src/dvd_udf.c b/libdvdread-embedded/src/dvd_udf.c
index 41517fa..7b22b43 100644
--- a/libdvdread-embedded/src/dvd_udf.c
+++ b/libdvdread-embedded/src/dvd_udf.c
@@ -82,6 +82,8 @@ struct Partition {
   uint32_t AccessType;
   uint32_t Start;
   uint32_t Length;
+  uint32_t FSD_Location;
+  uint32_t FSD_Length;
 };
 
 struct AD {
@@ -101,6 +103,12 @@ struct avdp_t {
   struct extent_ad rvds;
 };
 
+struct fsd_t {
+  uint16_t Partition;
+  uint32_t Location;
+  uint32_t Length;
+};
+
 struct pvd_t {
   uint8_t VolumeIdentifier[32];
   uint8_t VolumeSetIdentifier[128];
@@ -427,6 +435,16 @@ static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor )
   return 0;
 }
 
+/**
+ * Reads the File Set Descriptor from the Logical Volume Descriptor.
+ */
+static void UDFFSD( uint8_t *data, struct fsd_t *fsd )
+{
+  fsd->Length = GETN4(248);    /* always 2048? */
+  fsd->Location = GETN4(252);
+  fsd->Partition = GETN2(256); /* always 0? */
+}
+
 static int UDFFileEntry( uint8_t *data, uint8_t *FileType,
                          struct Partition *partition, struct AD *ad )
 {
@@ -801,8 +819,18 @@ static int UDFFindPartition( dvd_reader_t *ctx, int partnum,
         /* Logical Volume Descriptor */
         if( UDFLogVolume( LogBlock ) ) {
           /* TODO: sector size wrong! */
-        } else
-          volvalid = 1;
+        } else {
+          struct fsd_t fsd;
+
+          UDFFSD(LogBlock, &fsd);
+          if(part->Number == fsd.Partition) {
+            part->FSD_Location = fsd.Location;
+            part->FSD_Length = fsd.Length;
+            volvalid = 1;
+          } else {
+            /* TODO: Oups, how to handle this? */
+          }
+        }
       }
 
     } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 )
@@ -845,7 +873,10 @@ uint32_t UDFFindFile( dvd_reader_t *ctx, const char *filename,
     SetUDFCache(ctx, PartitionCache, 0, &partition);
 
     /* Find root dir ICB */
-    lbnum = partition.Start;
+    lbnum = partition.Start + partition.FSD_Location;
+    /*
+    fprintf(stderr, "Looking for FSD at 0x%x\n", lbnum);
+    */
     do {
       ret = DVDReadLBUDF( ctx, lbnum++, 1, LogBlock, 0 );
       if( ret < 0 ) {