Mercurial > mplayer.hg
annotate dvdread/dvd_udf.c @ 24047:de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
author | diego |
---|---|
date | Wed, 15 Aug 2007 11:47:22 +0000 |
parents | 22cb9d5f1e21 |
children | 1542693b2a30 |
rev | line source |
---|---|
7029 | 1 /* |
2 * This code is based on dvdudf by: | |
3 * Christian Wolff <scarabaeus@convergence.de>. | |
4 * | |
5 * Modifications by: | |
6 * Billy Biggs <vektor@dumbterm.net>. | |
10723 | 7 * Björn Englund <d4bjorn@dtek.chalmers.se>. |
7029 | 8 * |
14938
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
10723
diff
changeset
|
9 * Modified for use with MPlayer, changes contained in libdvdread_changes.diff. |
18783 | 10 * detailed changelog at http://svn.mplayerhq.hu/mplayer/trunk/ |
14938
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
10723
diff
changeset
|
11 * $Id$ |
25df9508f9a8
Mark modified files as such to comply more closely with GPL ¡ø2a.
diego
parents:
10723
diff
changeset
|
12 * |
7029 | 13 * dvdudf: parse and read the UDF volume information of a DVD Video |
14 * Copyright (C) 1999 Christian Wolff for convergence integrated media | |
15 * GmbH The author can be reached at scarabaeus@convergence.de, the | |
16 * project's page is at http://linuxtv.org/dvd/ | |
17 * | |
18 * This program is free software; you can redistribute it and/or modify | |
19 * it under the terms of the GNU General Public License as published by | |
20 * the Free Software Foundation; either version 2 of the License, or (at | |
21 * your option) any later version. | |
22 * | |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program; if not, write to the Free Software | |
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
31 * 02111-1307, USA. Or, point your browser to | |
32 * http://www.gnu.org/copyleft/gpl.html | |
33 */ | |
34 | |
15874 | 35 #include "config.h" |
36 | |
7029 | 37 #include <stdio.h> |
38 #include <stdlib.h> | |
39 #include <string.h> | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
40 |
7029 | 41 #include <sys/types.h> |
42 #include <sys/stat.h> | |
43 #include <unistd.h> | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
44 #include <errno.h> |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
45 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
46 #if defined(HAVE_INTTYPES_H) |
7029 | 47 #include <inttypes.h> |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
48 #elif defined(HAVE_STDINT_H) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
49 #include <stdint.h> |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
50 #endif |
7029 | 51 |
52 #include "dvd_reader.h" | |
53 #include "dvd_udf.h" | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
54 #include "dvdread_internal.h" |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
55 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
56 #ifndef EMEDIUMTYPE |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
57 #define EMEDIUMTYPE ENOENT |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
58 #endif |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
59 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
60 #ifndef HAVE_UINTPTR_T |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
61 #warning "Assuming that (unsigned long) can hold (void *)" |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
62 typedef unsigned long uintptr_t; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
63 #endif |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
64 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
65 #define DVD_ALIGN(ptr) (void *)((((uintptr_t)(ptr)) + (DVD_VIDEO_LB_LEN-1)) \ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
66 / DVD_VIDEO_LB_LEN * DVD_VIDEO_LB_LEN) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
67 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
68 typedef struct { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
69 void *start; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
70 void *aligned; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
71 } dvdalign_ptrs_t; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
72 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
73 typedef struct { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
74 dvdalign_ptrs_t *ptrs; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
75 uint32_t ptrs_in_use; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
76 uint32_t ptrs_max; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
77 } dvdalign_t; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
78 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
79 extern void *GetAlignHandle(dvd_reader_t *device); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
80 extern void SetAlignHandle(dvd_reader_t *device, void *align); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
81 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
82 /** |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
83 * Allocates aligned memory (for use with reads from raw/O_DIRECT devices). |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
84 * This memory must be freed with dvdalign_free() |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
85 * The size of the memory that is allocate is num_lbs*2048 bytes. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
86 * The memory will be suitably aligned for use with |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
87 * block reads from raw/O_DIRECT device. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
88 * @param num_lbs Number of logical blocks (2048 bytes) to allocate. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
89 * @return Returns pointer to allocated memory, or NULL on failure |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
90 * This isn't supposed to be fast/efficient, if that is needed |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
91 * this function should be rewritten to use posix_memalign or similar. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
92 * It's just needed for aligning memory for small block reads from |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
93 * raw/O_DIRECT devices. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
94 * We assume that 2048 is enough alignment for all systems at the moment. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
95 * Not thread safe. Only use this from one thread. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
96 * Depends on sizeof(unsigned long) being at least as large as sizeof(void *) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
97 */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
98 static void *dvdalign_lbmalloc(dvd_reader_t *device, uint32_t num_lbs) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
99 { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
100 void *m; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
101 int n; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
102 dvdalign_t *a; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
103 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
104 m = malloc((num_lbs+1)*DVD_VIDEO_LB_LEN); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
105 if(m == NULL) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
106 return m; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
107 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
108 a = (dvdalign_t *)GetAlignHandle(device); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
109 if(a == NULL) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
110 a = malloc(sizeof(dvdalign_t)); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
111 if(a == NULL) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
112 return a; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
113 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
114 a->ptrs = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
115 a->ptrs_in_use = 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
116 a->ptrs_max = 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
117 SetAlignHandle(device, (void *)a); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
118 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
119 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
120 if(a->ptrs_in_use >= a->ptrs_max) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
121 a->ptrs = realloc(a->ptrs, (a->ptrs_max+10)*sizeof(dvdalign_ptrs_t)); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
122 if(a->ptrs == NULL) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
123 free(m); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
124 return NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
125 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
126 a->ptrs_max+=10; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
127 for(n = a->ptrs_in_use; n < a->ptrs_max; n++) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
128 a->ptrs[n].start = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
129 a->ptrs[n].aligned = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
130 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
131 n = a->ptrs_in_use; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
132 } else { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
133 for(n = 0; n < a->ptrs_max; n++) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
134 if(a->ptrs[n].start == NULL) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
135 break; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
136 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
137 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
138 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
139 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
140 a->ptrs[n].start = m; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
141 a->ptrs[n].aligned = DVD_ALIGN(m); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
142 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
143 a->ptrs_in_use++; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
144 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
145 /* If this function starts to be used too much print a warning. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
146 Either there is a memory leak somewhere or we need to rewrite this to |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
147 a more efficient version. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
148 */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
149 if(a->ptrs_in_use > 50) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
150 if(dvdread_verbose(device) >= 0) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
151 fprintf(stderr, "libdvdread: dvdalign_lbmalloc(), more allocs than supposed: %u\n", a->ptrs_in_use); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
152 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
153 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
154 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
155 return a->ptrs[n].aligned; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
156 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
157 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
158 /** |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
159 * Frees memory allocated with dvdalign_lbmemory() |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
160 * @param ptr Pointer to memory space to free |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
161 * Not thread safe. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
162 */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
163 static void dvdalign_lbfree(dvd_reader_t *device, void *ptr) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
164 { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
165 int n; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
166 dvdalign_t *a; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
167 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
168 a = (dvdalign_t *)GetAlignHandle(device); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
169 if(a && a->ptrs) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
170 for(n = 0; n < a->ptrs_max; n++) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
171 if(a->ptrs[n].aligned == ptr) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
172 free(a->ptrs[n].start); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
173 a->ptrs[n].start = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
174 a->ptrs[n].aligned = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
175 a->ptrs_in_use--; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
176 if(a->ptrs_in_use == 0) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
177 free(a->ptrs); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
178 a->ptrs = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
179 a->ptrs_max = 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
180 free(a); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
181 a = NULL; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
182 SetAlignHandle(device, (void *)a); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
183 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
184 return; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
185 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
186 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
187 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
188 if(dvdread_verbose(device) >= 0) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
189 fprintf(stderr, "libdvdread: dvdalign_lbfree(), error trying to free mem: %08lx (%u)\n", (unsigned long)ptr, a ? a->ptrs_in_use : 0); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
190 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
191 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
192 |
7029 | 193 |
194 /* Private but located in/shared with dvd_reader.c */ | |
15874 | 195 extern int UDFReadBlocksRaw( dvd_reader_t *device, uint32_t lb_number, |
7029 | 196 size_t block_count, unsigned char *data, |
197 int encrypted ); | |
198 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
199 /** @internal |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
200 * Its required to either fail or deliver all the blocks asked for. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
201 * |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
202 * @param data Pointer to a buffer where data is returned. This must be large |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
203 * enough to hold lb_number*2048 bytes. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
204 * It must be aligned to system specific (2048) logical blocks size when |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
205 * reading from raw/O_DIRECT device. |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
206 */ |
7029 | 207 static int DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number, |
208 size_t block_count, unsigned char *data, | |
209 int encrypted ) | |
210 { | |
211 int ret; | |
212 size_t count = block_count; | |
213 | |
214 while(count > 0) { | |
215 | |
15874 | 216 ret = UDFReadBlocksRaw(device, lb_number, count, data, encrypted); |
7029 | 217 |
218 if(ret <= 0) { | |
219 /* One of the reads failed or nothing more to read, too bad. | |
220 * We won't even bother returning the reads that went ok. */ | |
221 return ret; | |
222 } | |
223 | |
224 count -= (size_t)ret; | |
225 lb_number += (uint32_t)ret; | |
226 } | |
227 | |
228 return block_count; | |
229 } | |
230 | |
231 | |
232 #ifndef NULL | |
233 #define NULL ((void *)0) | |
234 #endif | |
235 | |
236 struct Partition { | |
237 int valid; | |
238 char VolumeDesc[128]; | |
239 uint16_t Flags; | |
240 uint16_t Number; | |
241 char Contents[32]; | |
242 uint32_t AccessType; | |
243 uint32_t Start; | |
244 uint32_t Length; | |
245 }; | |
246 | |
247 struct AD { | |
248 uint32_t Location; | |
249 uint32_t Length; | |
250 uint8_t Flags; | |
251 uint16_t Partition; | |
252 }; | |
253 | |
10723 | 254 struct extent_ad { |
255 uint32_t location; | |
256 uint32_t length; | |
257 }; | |
258 | |
259 struct avdp_t { | |
260 struct extent_ad mvds; | |
261 struct extent_ad rvds; | |
262 }; | |
263 | |
264 struct pvd_t { | |
265 uint8_t VolumeIdentifier[32]; | |
266 uint8_t VolumeSetIdentifier[128]; | |
267 }; | |
268 | |
269 struct lbudf { | |
270 uint32_t lb; | |
271 uint8_t *data; | |
272 }; | |
273 | |
274 struct icbmap { | |
275 uint32_t lbn; | |
276 struct AD file; | |
277 uint8_t filetype; | |
278 }; | |
279 | |
15874 | 280 struct udf_cache { |
281 int avdp_valid; | |
282 struct avdp_t avdp; | |
283 int pvd_valid; | |
284 struct pvd_t pvd; | |
285 int partition_valid; | |
286 struct Partition partition; | |
287 int rooticb_valid; | |
288 struct AD rooticb; | |
289 int lb_num; | |
290 struct lbudf *lbs; | |
291 int map_num; | |
292 struct icbmap *maps; | |
293 }; | |
294 | |
295 typedef enum { | |
296 PartitionCache, RootICBCache, LBUDFCache, MapCache, AVDPCache, PVDCache | |
297 } UDFCacheType; | |
298 | |
299 extern void *GetUDFCacheHandle(dvd_reader_t *device); | |
300 extern void SetUDFCacheHandle(dvd_reader_t *device, void *cache); | |
301 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
302 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
303 void FreeUDFCache(dvd_reader_t *device, void *cache) |
15874 | 304 { |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
305 int n; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
306 |
15874 | 307 struct udf_cache *c = (struct udf_cache *)cache; |
308 if(c == NULL) { | |
309 return; | |
310 } | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
311 |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
312 for(n = 0; n < c->lb_num; n++) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
313 if(c->lbs[n].data) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
314 /* free data */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
315 dvdalign_lbfree(device, c->lbs[n].data); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
316 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
317 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
318 c->lb_num = 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
319 |
15874 | 320 if(c->lbs) { |
321 free(c->lbs); | |
322 } | |
323 if(c->maps) { | |
324 free(c->maps); | |
325 } | |
326 free(c); | |
327 } | |
328 | |
329 | |
330 static int GetUDFCache(dvd_reader_t *device, UDFCacheType type, | |
331 uint32_t nr, void *data) | |
332 { | |
333 int n; | |
334 struct udf_cache *c; | |
335 | |
336 if(DVDUDFCacheLevel(device, -1) <= 0) { | |
337 return 0; | |
338 } | |
339 | |
340 c = (struct udf_cache *)GetUDFCacheHandle(device); | |
341 | |
342 if(c == NULL) { | |
343 return 0; | |
344 } | |
345 | |
346 switch(type) { | |
347 case AVDPCache: | |
348 if(c->avdp_valid) { | |
349 *(struct avdp_t *)data = c->avdp; | |
350 return 1; | |
351 } | |
352 break; | |
353 case PVDCache: | |
354 if(c->pvd_valid) { | |
355 *(struct pvd_t *)data = c->pvd; | |
356 return 1; | |
357 } | |
358 break; | |
359 case PartitionCache: | |
360 if(c->partition_valid) { | |
361 *(struct Partition *)data = c->partition; | |
362 return 1; | |
363 } | |
364 break; | |
365 case RootICBCache: | |
366 if(c->rooticb_valid) { | |
367 *(struct AD *)data = c->rooticb; | |
368 return 1; | |
369 } | |
370 break; | |
371 case LBUDFCache: | |
372 for(n = 0; n < c->lb_num; n++) { | |
373 if(c->lbs[n].lb == nr) { | |
374 *(uint8_t **)data = c->lbs[n].data; | |
375 return 1; | |
376 } | |
377 } | |
378 break; | |
379 case MapCache: | |
380 for(n = 0; n < c->map_num; n++) { | |
381 if(c->maps[n].lbn == nr) { | |
382 *(struct icbmap *)data = c->maps[n]; | |
383 return 1; | |
384 } | |
385 } | |
386 break; | |
387 default: | |
388 break; | |
389 } | |
390 | |
391 return 0; | |
392 } | |
393 | |
394 static int SetUDFCache(dvd_reader_t *device, UDFCacheType type, | |
395 uint32_t nr, void *data) | |
396 { | |
397 int n; | |
398 struct udf_cache *c; | |
399 | |
400 if(DVDUDFCacheLevel(device, -1) <= 0) { | |
401 return 0; | |
402 } | |
403 | |
404 c = (struct udf_cache *)GetUDFCacheHandle(device); | |
405 | |
406 if(c == NULL) { | |
407 c = calloc(1, sizeof(struct udf_cache)); | |
408 // fprintf(stderr, "calloc: %d\n", sizeof(struct udf_cache)); | |
409 if(c == NULL) { | |
410 return 0; | |
411 } | |
412 SetUDFCacheHandle(device, c); | |
413 } | |
414 | |
415 | |
416 switch(type) { | |
417 case AVDPCache: | |
418 c->avdp = *(struct avdp_t *)data; | |
419 c->avdp_valid = 1; | |
420 break; | |
421 case PVDCache: | |
422 c->pvd = *(struct pvd_t *)data; | |
423 c->pvd_valid = 1; | |
424 break; | |
425 case PartitionCache: | |
426 c->partition = *(struct Partition *)data; | |
427 c->partition_valid = 1; | |
428 break; | |
429 case RootICBCache: | |
430 c->rooticb = *(struct AD *)data; | |
431 c->rooticb_valid = 1; | |
432 break; | |
433 case LBUDFCache: | |
434 for(n = 0; n < c->lb_num; n++) { | |
435 if(c->lbs[n].lb == nr) { | |
436 /* replace with new data */ | |
437 c->lbs[n].data = *(uint8_t **)data; | |
438 c->lbs[n].lb = nr; | |
439 return 1; | |
440 } | |
441 } | |
442 c->lb_num++; | |
443 c->lbs = realloc(c->lbs, c->lb_num * sizeof(struct lbudf)); | |
444 /* | |
445 fprintf(stderr, "realloc lb: %d * %d = %d\n", | |
446 c->lb_num, sizeof(struct lbudf), | |
447 c->lb_num * sizeof(struct lbudf)); | |
448 */ | |
449 if(c->lbs == NULL) { | |
450 c->lb_num = 0; | |
451 return 0; | |
452 } | |
453 c->lbs[n].data = *(uint8_t **)data; | |
454 c->lbs[n].lb = nr; | |
455 break; | |
456 case MapCache: | |
457 for(n = 0; n < c->map_num; n++) { | |
458 if(c->maps[n].lbn == nr) { | |
459 /* replace with new data */ | |
460 c->maps[n] = *(struct icbmap *)data; | |
461 c->maps[n].lbn = nr; | |
462 return 1; | |
463 } | |
464 } | |
465 c->map_num++; | |
466 c->maps = realloc(c->maps, c->map_num * sizeof(struct icbmap)); | |
467 /* | |
468 fprintf(stderr, "realloc maps: %d * %d = %d\n", | |
469 c->map_num, sizeof(struct icbmap), | |
470 c->map_num * sizeof(struct icbmap)); | |
471 */ | |
472 if(c->maps == NULL) { | |
473 c->map_num = 0; | |
474 return 0; | |
475 } | |
476 c->maps[n] = *(struct icbmap *)data; | |
477 c->maps[n].lbn = nr; | |
478 break; | |
479 default: | |
480 return 0; | |
481 } | |
482 | |
483 return 1; | |
484 } | |
485 | |
486 | |
7029 | 487 /* For direct data access, LSB first */ |
488 #define GETN1(p) ((uint8_t)data[p]) | |
489 #define GETN2(p) ((uint16_t)data[p] | ((uint16_t)data[(p) + 1] << 8)) | |
490 #define GETN3(p) ((uint32_t)data[p] | ((uint32_t)data[(p) + 1] << 8) \ | |
491 | ((uint32_t)data[(p) + 2] << 16)) | |
492 #define GETN4(p) ((uint32_t)data[p] \ | |
493 | ((uint32_t)data[(p) + 1] << 8) \ | |
494 | ((uint32_t)data[(p) + 2] << 16) \ | |
495 | ((uint32_t)data[(p) + 3] << 24)) | |
496 /* This is wrong with regard to endianess */ | |
497 #define GETN(p, n, target) memcpy(target, &data[p], n) | |
498 | |
499 static int Unicodedecode( uint8_t *data, int len, char *target ) | |
500 { | |
501 int p = 1, i = 0; | |
502 | |
503 if( ( data[ 0 ] == 8 ) || ( data[ 0 ] == 16 ) ) do { | |
504 if( data[ 0 ] == 16 ) p++; /* Ignore MSB of unicode16 */ | |
505 if( p < len ) { | |
506 target[ i++ ] = data[ p++ ]; | |
507 } | |
508 } while( p < len ); | |
509 | |
510 target[ i ] = '\0'; | |
511 return 0; | |
512 } | |
513 | |
514 static int UDFDescriptor( uint8_t *data, uint16_t *TagID ) | |
515 { | |
516 *TagID = GETN2(0); | |
517 // TODO: check CRC 'n stuff | |
518 return 0; | |
519 } | |
520 | |
521 static int UDFExtentAD( uint8_t *data, uint32_t *Length, uint32_t *Location ) | |
522 { | |
523 *Length = GETN4(0); | |
524 *Location = GETN4(4); | |
525 return 0; | |
526 } | |
527 | |
528 static int UDFShortAD( uint8_t *data, struct AD *ad, | |
529 struct Partition *partition ) | |
530 { | |
531 ad->Length = GETN4(0); | |
532 ad->Flags = ad->Length >> 30; | |
533 ad->Length &= 0x3FFFFFFF; | |
534 ad->Location = GETN4(4); | |
535 ad->Partition = partition->Number; // use number of current partition | |
536 return 0; | |
537 } | |
538 | |
539 static int UDFLongAD( uint8_t *data, struct AD *ad ) | |
540 { | |
541 ad->Length = GETN4(0); | |
542 ad->Flags = ad->Length >> 30; | |
543 ad->Length &= 0x3FFFFFFF; | |
544 ad->Location = GETN4(4); | |
545 ad->Partition = GETN2(8); | |
546 //GETN(10, 6, Use); | |
547 return 0; | |
548 } | |
549 | |
550 static int UDFExtAD( uint8_t *data, struct AD *ad ) | |
551 { | |
552 ad->Length = GETN4(0); | |
553 ad->Flags = ad->Length >> 30; | |
554 ad->Length &= 0x3FFFFFFF; | |
555 ad->Location = GETN4(12); | |
556 ad->Partition = GETN2(16); | |
557 //GETN(10, 6, Use); | |
558 return 0; | |
559 } | |
560 | |
561 static int UDFICB( uint8_t *data, uint8_t *FileType, uint16_t *Flags ) | |
562 { | |
563 *FileType = GETN1(11); | |
564 *Flags = GETN2(18); | |
565 return 0; | |
566 } | |
567 | |
568 | |
569 static int UDFPartition( uint8_t *data, uint16_t *Flags, uint16_t *Number, | |
570 char *Contents, uint32_t *Start, uint32_t *Length ) | |
571 { | |
572 *Flags = GETN2(20); | |
573 *Number = GETN2(22); | |
574 GETN(24, 32, Contents); | |
575 *Start = GETN4(188); | |
576 *Length = GETN4(192); | |
577 return 0; | |
578 } | |
579 | |
580 /** | |
581 * Reads the volume descriptor and checks the parameters. Returns 0 on OK, 1 | |
582 * on error. | |
583 */ | |
584 static int UDFLogVolume( uint8_t *data, char *VolumeDescriptor ) | |
585 { | |
586 uint32_t lbsize, MT_L, N_PM; | |
587 Unicodedecode(&data[84], 128, VolumeDescriptor); | |
588 lbsize = GETN4(212); // should be 2048 | |
589 MT_L = GETN4(264); // should be 6 | |
590 N_PM = GETN4(268); // should be 1 | |
591 if (lbsize != DVD_VIDEO_LB_LEN) return 1; | |
592 return 0; | |
593 } | |
594 | |
595 static int UDFFileEntry( uint8_t *data, uint8_t *FileType, | |
596 struct Partition *partition, struct AD *ad ) | |
597 { | |
598 uint16_t flags; | |
599 uint32_t L_EA, L_AD; | |
600 unsigned int p; | |
601 | |
602 UDFICB( &data[ 16 ], FileType, &flags ); | |
603 | |
604 /* Init ad for an empty file (i.e. there isn't a AD, L_AD == 0 ) */ | |
605 ad->Length = GETN4( 60 ); // Really 8 bytes a 56 | |
606 ad->Flags = 0; | |
607 ad->Location = 0; // what should we put here? | |
608 ad->Partition = partition->Number; // use number of current partition | |
609 | |
610 L_EA = GETN4( 168 ); | |
611 L_AD = GETN4( 172 ); | |
612 p = 176 + L_EA; | |
613 while( p < 176 + L_EA + L_AD ) { | |
614 switch( flags & 0x0007 ) { | |
615 case 0: UDFShortAD( &data[ p ], ad, partition ); p += 8; break; | |
616 case 1: UDFLongAD( &data[ p ], ad ); p += 16; break; | |
617 case 2: UDFExtAD( &data[ p ], ad ); p += 20; break; | |
618 case 3: | |
619 switch( L_AD ) { | |
620 case 8: UDFShortAD( &data[ p ], ad, partition ); break; | |
621 case 16: UDFLongAD( &data[ p ], ad ); break; | |
622 case 20: UDFExtAD( &data[ p ], ad ); break; | |
623 } | |
624 p += L_AD; | |
625 break; | |
626 default: | |
627 p += L_AD; break; | |
628 } | |
629 } | |
630 return 0; | |
631 } | |
632 | |
633 static int UDFFileIdentifier( uint8_t *data, uint8_t *FileCharacteristics, | |
634 char *FileName, struct AD *FileICB ) | |
635 { | |
636 uint8_t L_FI; | |
637 uint16_t L_IU; | |
638 | |
639 *FileCharacteristics = GETN1(18); | |
640 L_FI = GETN1(19); | |
641 UDFLongAD(&data[20], FileICB); | |
642 L_IU = GETN2(36); | |
643 if (L_FI) Unicodedecode(&data[38 + L_IU], L_FI, FileName); | |
644 else FileName[0] = '\0'; | |
645 return 4 * ((38 + L_FI + L_IU + 3) / 4); | |
646 } | |
647 | |
648 /** | |
649 * Maps ICB to FileAD | |
650 * ICB: Location of ICB of directory to scan | |
651 * FileType: Type of the file | |
652 * File: Location of file the ICB is pointing to | |
653 * return 1 on success, 0 on error; | |
654 */ | |
655 static int UDFMapICB( dvd_reader_t *device, struct AD ICB, uint8_t *FileType, | |
656 struct Partition *partition, struct AD *File ) | |
657 { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
658 uint8_t *LogBlock; |
7029 | 659 uint32_t lbnum; |
660 uint16_t TagID; | |
15874 | 661 struct icbmap tmpmap; |
7029 | 662 |
663 lbnum = partition->Start + ICB.Location; | |
15874 | 664 tmpmap.lbn = lbnum; |
665 if(GetUDFCache(device, MapCache, lbnum, &tmpmap)) { | |
666 *FileType = tmpmap.filetype; | |
667 *File = tmpmap.file; | |
668 return 1; | |
669 } | |
670 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
671 LogBlock = dvdalign_lbmalloc(device, 1); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
672 if(!LogBlock) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
673 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
674 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
675 |
7029 | 676 do { |
677 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { | |
678 TagID = 0; | |
679 } else { | |
680 UDFDescriptor( LogBlock, &TagID ); | |
681 } | |
682 | |
683 if( TagID == 261 ) { | |
684 UDFFileEntry( LogBlock, FileType, partition, File ); | |
15874 | 685 tmpmap.file = *File; |
686 tmpmap.filetype = *FileType; | |
687 SetUDFCache(device, MapCache, tmpmap.lbn, &tmpmap); | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
688 dvdalign_lbfree(device, LogBlock); |
7029 | 689 return 1; |
690 }; | |
691 } while( ( lbnum <= partition->Start + ICB.Location + ( ICB.Length - 1 ) | |
692 / DVD_VIDEO_LB_LEN ) && ( TagID != 261 ) ); | |
693 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
694 dvdalign_lbfree(device, LogBlock); |
7029 | 695 return 0; |
696 } | |
697 | |
698 /** | |
699 * Dir: Location of directory to scan | |
700 * FileName: Name of file to look for | |
701 * FileICB: Location of ICB of the found file | |
702 * return 1 on success, 0 on error; | |
703 */ | |
704 static int UDFScanDir( dvd_reader_t *device, struct AD Dir, char *FileName, | |
15874 | 705 struct Partition *partition, struct AD *FileICB, |
706 int cache_file_info) | |
7029 | 707 { |
708 char filename[ MAX_UDF_FILE_NAME_LEN ]; | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
709 uint8_t *directory; |
7029 | 710 uint32_t lbnum; |
711 uint16_t TagID; | |
712 uint8_t filechar; | |
713 unsigned int p; | |
15874 | 714 uint8_t *cached_dir = NULL; |
715 uint32_t dir_lba; | |
716 struct AD tmpICB; | |
717 int found = 0; | |
718 int in_cache = 0; | |
7029 | 719 |
720 /* Scan dir for ICB of file */ | |
721 lbnum = partition->Start + Dir.Location; | |
15874 | 722 |
723 if(DVDUDFCacheLevel(device, -1) > 0) { | |
724 /* caching */ | |
725 | |
726 if(!GetUDFCache(device, LBUDFCache, lbnum, &cached_dir)) { | |
727 dir_lba = (Dir.Length + DVD_VIDEO_LB_LEN) / DVD_VIDEO_LB_LEN; | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
728 if((cached_dir = dvdalign_lbmalloc(device, dir_lba)) == NULL) { |
15874 | 729 return 0; |
730 } | |
731 if( DVDReadLBUDF( device, lbnum, dir_lba, cached_dir, 0) <= 0 ) { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
732 dvdalign_lbfree(device, cached_dir); |
15874 | 733 cached_dir = NULL; |
734 } | |
735 SetUDFCache(device, LBUDFCache, lbnum, &cached_dir); | |
736 } else { | |
737 in_cache = 1; | |
738 } | |
739 | |
740 if(cached_dir == NULL) { | |
741 return 0; | |
742 } | |
743 | |
744 p = 0; | |
745 | |
746 while( p < Dir.Length ) { | |
747 UDFDescriptor( &cached_dir[ p ], &TagID ); | |
748 if( TagID == 257 ) { | |
749 p += UDFFileIdentifier( &cached_dir[ p ], &filechar, | |
750 filename, &tmpICB ); | |
751 if(cache_file_info && !in_cache) { | |
752 uint8_t tmpFiletype; | |
753 struct AD tmpFile; | |
754 | |
755 if( !strcasecmp( FileName, filename ) ) { | |
756 *FileICB = tmpICB; | |
757 found = 1; | |
758 | |
759 } | |
760 UDFMapICB(device, tmpICB, &tmpFiletype, | |
761 partition, &tmpFile); | |
762 } else { | |
763 if( !strcasecmp( FileName, filename ) ) { | |
764 *FileICB = tmpICB; | |
765 return 1; | |
766 } | |
767 } | |
768 } else { | |
769 if(cache_file_info && (!in_cache) && found) { | |
770 return 1; | |
771 } | |
772 return 0; | |
773 } | |
774 } | |
775 if(cache_file_info && (!in_cache) && found) { | |
776 return 1; | |
777 } | |
778 return 0; | |
779 } | |
7029 | 780 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
781 directory = dvdalign_lbmalloc(device, 2); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
782 if(!directory) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
783 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
784 } |
7029 | 785 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
786 dvdalign_lbfree(device, directory); |
7029 | 787 return 0; |
788 } | |
789 | |
790 p = 0; | |
791 while( p < Dir.Length ) { | |
792 if( p > DVD_VIDEO_LB_LEN ) { | |
793 ++lbnum; | |
794 p -= DVD_VIDEO_LB_LEN; | |
795 Dir.Length -= DVD_VIDEO_LB_LEN; | |
796 if( DVDReadLBUDF( device, lbnum, 2, directory, 0 ) <= 0 ) { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
797 dvdalign_lbfree(device, directory); |
7029 | 798 return 0; |
799 } | |
800 } | |
801 UDFDescriptor( &directory[ p ], &TagID ); | |
802 if( TagID == 257 ) { | |
803 p += UDFFileIdentifier( &directory[ p ], &filechar, | |
804 filename, FileICB ); | |
805 if( !strcasecmp( FileName, filename ) ) { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
806 dvdalign_lbfree(device, directory); |
7029 | 807 return 1; |
808 } | |
809 } else { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
810 dvdalign_lbfree(device, directory); |
7029 | 811 return 0; |
812 } | |
813 } | |
814 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
815 dvdalign_lbfree(device, directory); |
7029 | 816 return 0; |
817 } | |
818 | |
10723 | 819 |
820 static int UDFGetAVDP( dvd_reader_t *device, | |
821 struct avdp_t *avdp) | |
822 { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
823 uint8_t *Anchor; |
10723 | 824 uint32_t lbnum, MVDS_location, MVDS_length; |
825 uint16_t TagID; | |
826 uint32_t lastsector; | |
827 int terminate; | |
828 struct avdp_t; | |
829 | |
15874 | 830 if(GetUDFCache(device, AVDPCache, 0, avdp)) { |
831 return 1; | |
832 } | |
833 | |
10723 | 834 /* Find Anchor */ |
835 lastsector = 0; | |
836 lbnum = 256; /* Try #1, prime anchor */ | |
837 terminate = 0; | |
838 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
839 Anchor = dvdalign_lbmalloc(device, 1); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
840 if(!Anchor) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
841 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
842 } |
10723 | 843 for(;;) { |
844 if( DVDReadLBUDF( device, lbnum, 1, Anchor, 0 ) > 0 ) { | |
845 UDFDescriptor( Anchor, &TagID ); | |
846 } else { | |
847 TagID = 0; | |
848 } | |
849 if (TagID != 2) { | |
850 /* Not an anchor */ | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
851 if( terminate ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
852 dvdalign_lbfree(device, Anchor); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
853 errno = EMEDIUMTYPE; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
854 return 0; /* Final try failed */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
855 } |
10723 | 856 |
857 if( lastsector ) { | |
858 /* We already found the last sector. Try #3, alternative | |
859 * backup anchor. If that fails, don't try again. | |
860 */ | |
861 lbnum = lastsector; | |
862 terminate = 1; | |
863 } else { | |
864 /* TODO: Find last sector of the disc (this is optional). */ | |
865 if( lastsector ) { | |
866 /* Try #2, backup anchor */ | |
867 lbnum = lastsector - 256; | |
868 } else { | |
869 /* Unable to find last sector */ | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
870 dvdalign_lbfree(device, Anchor); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
871 errno = EMEDIUMTYPE; |
10723 | 872 return 0; |
873 } | |
874 } | |
875 } else { | |
876 /* It's an anchor! We can leave */ | |
877 break; | |
878 } | |
879 } | |
880 /* Main volume descriptor */ | |
881 UDFExtentAD( &Anchor[ 16 ], &MVDS_length, &MVDS_location ); | |
882 avdp->mvds.location = MVDS_location; | |
883 avdp->mvds.length = MVDS_length; | |
884 | |
885 /* Backup volume descriptor */ | |
886 UDFExtentAD( &Anchor[ 24 ], &MVDS_length, &MVDS_location ); | |
887 avdp->rvds.location = MVDS_location; | |
888 avdp->rvds.length = MVDS_length; | |
889 | |
15874 | 890 SetUDFCache(device, AVDPCache, 0, avdp); |
891 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
892 dvdalign_lbfree(device, Anchor); |
10723 | 893 return 1; |
894 } | |
895 | |
7029 | 896 /** |
897 * Looks for partition on the disc. Returns 1 if partition found, 0 on error. | |
898 * partnum: Number of the partition, starting at 0. | |
899 * part: structure to fill with the partition information | |
900 */ | |
901 static int UDFFindPartition( dvd_reader_t *device, int partnum, | |
902 struct Partition *part ) | |
903 { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
904 uint8_t *LogBlock; |
7029 | 905 uint32_t lbnum, MVDS_location, MVDS_length; |
906 uint16_t TagID; | |
10723 | 907 int i, volvalid; |
908 struct avdp_t avdp; | |
7029 | 909 |
10723 | 910 |
911 if(!UDFGetAVDP(device, &avdp)) { | |
912 return 0; | |
7029 | 913 } |
10723 | 914 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
915 LogBlock = dvdalign_lbmalloc(device, 1); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
916 if(!LogBlock) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
917 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
918 } |
7029 | 919 /* Main volume descriptor */ |
10723 | 920 MVDS_location = avdp.mvds.location; |
921 MVDS_length = avdp.mvds.length; | |
922 | |
7029 | 923 part->valid = 0; |
924 volvalid = 0; | |
925 part->VolumeDesc[ 0 ] = '\0'; | |
926 i = 1; | |
927 do { | |
928 /* Find Volume Descriptor */ | |
929 lbnum = MVDS_location; | |
930 do { | |
931 | |
932 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { | |
933 TagID = 0; | |
934 } else { | |
935 UDFDescriptor( LogBlock, &TagID ); | |
936 } | |
937 | |
938 if( ( TagID == 5 ) && ( !part->valid ) ) { | |
939 /* Partition Descriptor */ | |
940 UDFPartition( LogBlock, &part->Flags, &part->Number, | |
941 part->Contents, &part->Start, &part->Length ); | |
942 part->valid = ( partnum == part->Number ); | |
943 } else if( ( TagID == 6 ) && ( !volvalid ) ) { | |
944 /* Logical Volume Descriptor */ | |
945 if( UDFLogVolume( LogBlock, part->VolumeDesc ) ) { | |
946 /* TODO: sector size wrong! */ | |
947 } else { | |
948 volvalid = 1; | |
949 } | |
950 } | |
951 | |
952 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) | |
953 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) | |
954 && ( ( !part->valid ) || ( !volvalid ) ) ); | |
955 | |
956 if( ( !part->valid) || ( !volvalid ) ) { | |
10723 | 957 /* Backup volume descriptor */ |
958 MVDS_location = avdp.mvds.location; | |
959 MVDS_length = avdp.mvds.length; | |
7029 | 960 } |
961 } while( i-- && ( ( !part->valid ) || ( !volvalid ) ) ); | |
962 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
963 dvdalign_lbfree(device, LogBlock); |
7029 | 964 /* We only care for the partition, not the volume */ |
965 return part->valid; | |
966 } | |
967 | |
968 uint32_t UDFFindFile( dvd_reader_t *device, char *filename, | |
969 uint32_t *filesize ) | |
970 { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
971 uint8_t *LogBlock; |
7029 | 972 uint32_t lbnum; |
973 uint16_t TagID; | |
974 struct Partition partition; | |
975 struct AD RootICB, File, ICB; | |
976 char tokenline[ MAX_UDF_FILE_NAME_LEN ]; | |
977 char *token; | |
978 uint8_t filetype; | |
10723 | 979 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
980 if(filesize) { |
7029 | 981 *filesize = 0; |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
982 } |
7029 | 983 tokenline[0] = '\0'; |
984 strcat( tokenline, filename ); | |
985 | |
10723 | 986 |
15874 | 987 if(!(GetUDFCache(device, PartitionCache, 0, &partition) && |
988 GetUDFCache(device, RootICBCache, 0, &RootICB))) { | |
10723 | 989 /* Find partition, 0 is the standard location for DVD Video.*/ |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
990 if( !UDFFindPartition( device, 0, &partition ) ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
991 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
992 } |
15874 | 993 SetUDFCache(device, PartitionCache, 0, &partition); |
10723 | 994 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
995 LogBlock = dvdalign_lbmalloc(device, 1); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
996 if(!LogBlock) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
997 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
998 } |
10723 | 999 /* Find root dir ICB */ |
1000 lbnum = partition.Start; | |
1001 do { | |
7029 | 1002 if( DVDReadLBUDF( device, lbnum++, 1, LogBlock, 0 ) <= 0 ) { |
1003 TagID = 0; | |
1004 } else { | |
1005 UDFDescriptor( LogBlock, &TagID ); | |
1006 } | |
1007 | |
1008 /* File Set Descriptor */ | |
1009 if( TagID == 256 ) { // File Set Descriptor | |
1010 UDFLongAD( &LogBlock[ 400 ], &RootICB ); | |
1011 } | |
1012 } while( ( lbnum < partition.Start + partition.Length ) | |
1013 && ( TagID != 8 ) && ( TagID != 256 ) ); | |
1014 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1015 dvdalign_lbfree(device, LogBlock); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1016 |
7029 | 1017 /* Sanity checks. */ |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1018 if( TagID != 256 ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1019 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1020 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1021 if( RootICB.Partition != 0 ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1022 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1023 } |
15874 | 1024 SetUDFCache(device, RootICBCache, 0, &RootICB); |
1025 } | |
10723 | 1026 |
7029 | 1027 /* Find root dir */ |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1028 if( !UDFMapICB( device, RootICB, &filetype, &partition, &File ) ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1029 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1030 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1031 if( filetype != 4 ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1032 return 0; /* Root dir should be dir */ |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1033 } |
10723 | 1034 { |
15874 | 1035 int cache_file_info = 0; |
10723 | 1036 /* Tokenize filepath */ |
1037 token = strtok(tokenline, "/"); | |
1038 | |
1039 while( token != NULL ) { | |
1040 | |
15874 | 1041 if( !UDFScanDir( device, File, token, &partition, &ICB, |
1042 cache_file_info)) { | |
10723 | 1043 return 0; |
1044 } | |
1045 if( !UDFMapICB( device, ICB, &filetype, &partition, &File ) ) { | |
1046 return 0; | |
1047 } | |
15874 | 1048 if(!strcmp(token, "VIDEO_TS")) { |
1049 cache_file_info = 1; | |
1050 } | |
7029 | 1051 token = strtok( NULL, "/" ); |
10723 | 1052 } |
1053 } | |
1054 | |
7029 | 1055 /* Sanity check. */ |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1056 if( File.Partition != 0 ) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1057 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1058 } |
7029 | 1059 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1060 if(filesize) { |
7029 | 1061 *filesize = File.Length; |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1062 } |
7029 | 1063 /* Hack to not return partition.Start for empty files. */ |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1064 if( !File.Location ) { |
7029 | 1065 return 0; |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1066 } else { |
7029 | 1067 return partition.Start + File.Location; |
1068 } | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1069 } |
10723 | 1070 |
1071 | |
1072 | |
1073 /** | |
1074 * Gets a Descriptor . | |
1075 * Returns 1 if descriptor found, 0 on error. | |
1076 * id, tagid of descriptor | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1077 * bufsize, size of BlockBuf (must be >= DVD_VIDEO_LB_LEN) |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1078 * and aligned for raw/O_DIRECT read. |
10723 | 1079 */ |
1080 static int UDFGetDescriptor( dvd_reader_t *device, int id, | |
1081 uint8_t *descriptor, int bufsize) | |
1082 { | |
1083 uint32_t lbnum, MVDS_location, MVDS_length; | |
1084 struct avdp_t avdp; | |
1085 uint16_t TagID; | |
1086 uint32_t lastsector; | |
1087 int i, terminate; | |
1088 int desc_found = 0; | |
1089 /* Find Anchor */ | |
1090 lastsector = 0; | |
1091 lbnum = 256; /* Try #1, prime anchor */ | |
1092 terminate = 0; | |
1093 if(bufsize < DVD_VIDEO_LB_LEN) { | |
1094 return 0; | |
1095 } | |
1096 | |
1097 if(!UDFGetAVDP(device, &avdp)) { | |
1098 return 0; | |
1099 } | |
1100 | |
1101 /* Main volume descriptor */ | |
1102 MVDS_location = avdp.mvds.location; | |
1103 MVDS_length = avdp.mvds.length; | |
1104 | |
1105 i = 1; | |
1106 do { | |
1107 /* Find Descriptor */ | |
1108 lbnum = MVDS_location; | |
1109 do { | |
1110 | |
1111 if( DVDReadLBUDF( device, lbnum++, 1, descriptor, 0 ) <= 0 ) { | |
1112 TagID = 0; | |
1113 } else { | |
1114 UDFDescriptor( descriptor, &TagID ); | |
1115 } | |
1116 | |
1117 if( (TagID == id) && ( !desc_found ) ) { | |
1118 /* Descriptor */ | |
1119 desc_found = 1; | |
1120 } | |
1121 } while( ( lbnum <= MVDS_location + ( MVDS_length - 1 ) | |
1122 / DVD_VIDEO_LB_LEN ) && ( TagID != 8 ) | |
1123 && ( !desc_found) ); | |
1124 | |
1125 if( !desc_found ) { | |
1126 /* Backup volume descriptor */ | |
1127 MVDS_location = avdp.rvds.location; | |
1128 MVDS_length = avdp.rvds.length; | |
1129 } | |
1130 } while( i-- && ( !desc_found ) ); | |
1131 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1132 |
10723 | 1133 return desc_found; |
1134 } | |
1135 | |
1136 | |
1137 static int UDFGetPVD(dvd_reader_t *device, struct pvd_t *pvd) | |
1138 { | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1139 uint8_t *pvd_buf; |
10723 | 1140 |
15874 | 1141 if(GetUDFCache(device, PVDCache, 0, pvd)) { |
1142 return 1; | |
1143 } | |
1144 | |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1145 pvd_buf = dvdalign_lbmalloc(device, 1); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1146 if(!pvd_buf) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1147 return 0; |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1148 } |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1149 if(!UDFGetDescriptor( device, 1, pvd_buf, 1*DVD_VIDEO_LB_LEN)) { |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1150 dvdalign_lbfree(device, pvd_buf); |
10723 | 1151 return 0; |
1152 } | |
1153 | |
1154 memcpy(pvd->VolumeIdentifier, &pvd_buf[24], 32); | |
1155 memcpy(pvd->VolumeSetIdentifier, &pvd_buf[72], 128); | |
15874 | 1156 SetUDFCache(device, PVDCache, 0, pvd); |
10723 | 1157 |
24047
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1158 dvdalign_lbfree(device, pvd_buf); |
de28f9e8cb00
Sync libdvdread with version 0.9.5 (functional changes).
diego
parents:
20981
diff
changeset
|
1159 |
10723 | 1160 return 1; |
1161 } | |
15874 | 1162 |
1163 /** | |
1164 * Gets the Volume Identifier string, in 8bit unicode (latin-1) | |
1165 * volid, place to put the string | |
1166 * volid_size, size of the buffer volid points to | |
1167 * returns the size of buffer needed for all data | |
1168 */ | |
1169 int UDFGetVolumeIdentifier(dvd_reader_t *device, char *volid, | |
1170 unsigned int volid_size) | |
1171 { | |
1172 struct pvd_t pvd; | |
1173 unsigned int volid_len; | |
1174 | |
1175 /* get primary volume descriptor */ | |
1176 if(!UDFGetPVD(device, &pvd)) { | |
1177 return 0; | |
1178 } | |
1179 | |
1180 volid_len = pvd.VolumeIdentifier[31]; | |
1181 if(volid_len > 31) { | |
1182 /* this field is only 32 bytes something is wrong */ | |
1183 volid_len = 31; | |
1184 } | |
1185 if(volid_size > volid_len) { | |
1186 volid_size = volid_len; | |
1187 } | |
1188 Unicodedecode(pvd.VolumeIdentifier, volid_size, volid); | |
1189 | |
1190 return volid_len; | |
1191 } | |
1192 | |
1193 /** | |
1194 * Gets the Volume Set Identifier, as a 128-byte dstring (not decoded) | |
1195 * WARNING This is not a null terminated string | |
1196 * volsetid, place to put the data | |
1197 * volsetid_size, size of the buffer volsetid points to | |
1198 * the buffer should be >=128 bytes to store the whole volumesetidentifier | |
1199 * returns the size of the available volsetid information (128) | |
1200 * or 0 on error | |
1201 */ | |
1202 int UDFGetVolumeSetIdentifier(dvd_reader_t *device, uint8_t *volsetid, | |
1203 unsigned int volsetid_size) | |
1204 { | |
1205 struct pvd_t pvd; | |
1206 | |
1207 /* get primary volume descriptor */ | |
1208 if(!UDFGetPVD(device, &pvd)) { | |
1209 return 0; | |
1210 } | |
1211 | |
1212 | |
1213 if(volsetid_size > 128) { | |
1214 volsetid_size = 128; | |
1215 } | |
1216 | |
1217 memcpy(volsetid, pvd.VolumeSetIdentifier, volsetid_size); | |
1218 | |
1219 return 128; | |
1220 } |