1 /* @(#)ifo_read.c	1.18 18/09/17 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)ifo_read.c	1.18 18/09/17 joerg";
6 #endif
7 /*
8  * Copyright (C) 2002 Olaf Beck <olaf_sc@yahoo.com>
9  * Copyright (C) 2002-2016 J�rg Schilling <joerg@schily.net>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or (at
14  * your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful, but
17  * WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25 
26 /*
27  * NOTE: This is a cut down version of libdvdread for mkisofs, due
28  * to portability issues with the current libdvdread according to
29  * the maintainer of mkisofs.
30  * This cut down version only reads from a harddisk file structure
31  * and it only implements the functions necessary inorder to make
32  * mkisofs produce valid DVD-Video images.
33  * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
34  * LIBDVDREAD INSTEAD
35  */
36 #ifdef DVD_AUD_VID
37 
38 #include "mkisofs.h"
39 #include <schily/fcntl.h>
40 #include <schily/utypes.h>
41 #include <schily/schily.h>
42 
43 #include "ifo_read.h"
44 #include "bswap.h"
45 
46 LOCAL	ifo_handle_t	*ifoReadVTSI	__PR((int file, ifo_handle_t *ifofile));
47 LOCAL	ifo_handle_t	*ifoReadVGMI	__PR((int file, ifo_handle_t *ifofile));
48 EXPORT	ifo_handle_t	*ifoOpen		__PR((dvd_reader_t *dvd, int title));
49 LOCAL	void		ifoFree_TT_SRPT	__PR((ifo_handle_t *ifofile));
50 EXPORT	void		ifoClose	__PR((ifo_handle_t *ifofile));
51 
52 
53 LOCAL ifo_handle_t *
ifoReadVTSI(file,ifofile)54 ifoReadVTSI(file, ifofile)
55 	int file;
56 	ifo_handle_t	*ifofile;
57 {
58 	off_t offset;
59 	UInt32_t sector;
60 
61 	vtsi_mat_t	*vtsi_mat;
62 
63 	/* Make the VMG part NULL */
64 	ifofile->vmgi_mat = NULL;
65 	ifofile->tt_srpt = NULL;
66 
67 	vtsi_mat = (vtsi_mat_t *)e_malloc(sizeof (vtsi_mat_t));
68 	if (!vtsi_mat) {
69 /*		fprintf(stderr, "Memmory allocation error\n");*/
70 		free(ifofile);
71 		return (0);
72 	}
73 
74 	ifofile->vtsi_mat = vtsi_mat;
75 
76 	/* Last sector of VTS i.e. last sector of BUP */
77 
78 	offset = 12;
79 
80 	if (lseek(file, offset, SEEK_SET) != offset) {
81 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
82 		ifoClose(ifofile);
83 		return (0);
84 	}
85 
86 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
87 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
88 		ifoClose(ifofile);
89 		return (0);
90 	}
91 
92 	B2N_32(sector);
93 
94 	vtsi_mat->vts_last_sector = sector;
95 
96 	/* Last sector of IFO */
97 
98 	offset = 28;
99 
100 	if (lseek(file, offset, SEEK_SET) != offset) {
101 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
102 		ifoClose(ifofile);
103 		return (0);
104 	}
105 
106 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
107 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
108 		ifoClose(ifofile);
109 		return (0);
110 	}
111 
112 	B2N_32(sector);
113 
114 	vtsi_mat->vtsi_last_sector = sector;
115 
116 
117 	/* Star sector of VTS Menu VOB */
118 
119 	offset = 192;
120 
121 	if (lseek(file, offset, SEEK_SET) != offset) {
122 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
123 		ifoClose(ifofile);
124 		return (0);
125 	}
126 
127 
128 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
129 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
130 		ifoClose(ifofile);
131 		return (0);
132 	}
133 
134 	B2N_32(sector);
135 
136 	vtsi_mat->vtsm_vobs = sector;
137 
138 
139 	/* Start sector of VTS Title VOB */
140 
141 	offset = 196;
142 
143 	if (lseek(file, offset, SEEK_SET) != offset) {
144 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
145 		ifoClose(ifofile);
146 		return (0);
147 	}
148 
149 
150 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
151 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
152 		ifoClose(ifofile);
153 		return (0);
154 	}
155 
156 	B2N_32(sector);
157 
158 	vtsi_mat->vtstt_vobs = sector;
159 
160 	return (ifofile);
161 }
162 
163 
164 LOCAL ifo_handle_t *
ifoReadVGMI(file,ifofile)165 ifoReadVGMI(file, ifofile)
166 	int file;
167 	ifo_handle_t	*ifofile;
168 {
169 	off_t	offset;
170 	Uint	counter;
171 	UInt32_t sector;
172 	UInt16_t titles;
173 
174 	vmgi_mat_t *vmgi_mat;
175 	tt_srpt_t *tt_srpt;
176 
177 	/* Make the VTS part null */
178 	ifofile->vtsi_mat = NULL;
179 
180 	vmgi_mat = (vmgi_mat_t *)e_malloc(sizeof (vmgi_mat_t));
181 	if (!vmgi_mat) {
182 /*		fprintf(stderr, "Memmory allocation error\n");*/
183 		free(ifofile);
184 		return (0);
185 	}
186 
187 	ifofile->vmgi_mat = vmgi_mat;
188 
189 	/* Last sector of VMG i.e. last sector of BUP */
190 
191 	offset = 12;
192 
193 	if (lseek(file, offset, SEEK_SET) != offset) {
194 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
195 		ifoClose(ifofile);
196 		return (0);
197 	}
198 
199 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
200 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
201 		ifoClose(ifofile);
202 		return (0);
203 	}
204 
205 	B2N_32(sector);
206 
207 	vmgi_mat->vmg_last_sector = sector;
208 
209 	/* Last sector of IFO */
210 
211 	offset = 28;
212 
213 	if (lseek(file, offset, SEEK_SET) != offset) {
214 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
215 		ifoClose(ifofile);
216 		return (0);
217 	}
218 
219 
220 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
221 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
222 		ifoClose(ifofile);
223 		return (0);
224 	}
225 
226 	B2N_32(sector);
227 
228 	vmgi_mat->vmgi_last_sector = sector;
229 
230 
231 	/* Number of VTS i.e. title sets */
232 
233 	offset = 62;
234 
235 	if (lseek(file, offset, SEEK_SET) != offset) {
236 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
237 		ifoClose(ifofile);
238 		return (0);
239 	}
240 
241 
242 	if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
243 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
244 		ifoClose(ifofile);
245 		return (0);
246 	}
247 
248 	B2N_16(titles);
249 
250 	vmgi_mat->vmg_nr_of_title_sets = titles;
251 
252 
253 	/* Star sector of VMG Menu VOB */
254 
255 	offset = 192;
256 
257 	if (lseek(file, offset, SEEK_SET) != offset) {
258 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
259 		ifoClose(ifofile);
260 		return (0);
261 	}
262 
263 
264 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
265 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
266 		ifoClose(ifofile);
267 		return (0);
268 	}
269 
270 	B2N_32(sector);
271 
272 	vmgi_mat->vmgm_vobs = sector;
273 
274 
275 	/* Sector offset to TT_SRPT */
276 
277 	offset = 196;
278 
279 	if (lseek(file, offset, SEEK_SET) != offset) {
280 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
281 		ifoClose(ifofile);
282 		return (0);
283 	}
284 
285 
286 	if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
287 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
288 		ifoClose(ifofile);
289 		return (0);
290 	}
291 
292 	B2N_32(sector);
293 
294 	vmgi_mat->tt_srpt = sector;
295 
296 	tt_srpt = (tt_srpt_t *)e_malloc(sizeof (tt_srpt_t));
297 	if (!tt_srpt) {
298 /*		fprintf(stderr, "Memmory allocation error\n");*/
299 		ifoClose(ifofile);
300 		return (0);
301 	}
302 
303 	ifofile->tt_srpt = tt_srpt;
304 
305 
306 	/* Number of titles in TT_SRPT */
307 
308 	offset = 2048 * vmgi_mat->tt_srpt;
309 
310 	if (lseek(file, offset, SEEK_SET) != offset) {
311 		errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
312 		return (0);
313 	}
314 
315 	if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
316 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
317 		return (0);
318 	}
319 
320 	B2N_16(titles);
321 
322 	tt_srpt->nr_of_srpts = titles;
323 
324 	tt_srpt->title = (title_info_t *)e_malloc(sizeof (title_info_t) * tt_srpt->nr_of_srpts);
325 	if (!tt_srpt->title) {
326 /*		fprintf(stderr, "Memmory allocation error\n");*/
327 		ifoClose(ifofile);
328 		return (0);
329 	}
330 
331 	/* Start sector of each title in TT_SRPT */
332 
333 	for (counter = 0; counter < tt_srpt->nr_of_srpts; counter++) {
334 		offset = (2048 * vmgi_mat->tt_srpt) + 8 + (counter * 12) + 8;
335 		if (lseek(file, offset, SEEK_SET) != offset) {
336 			errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
337 			ifoClose(ifofile);
338 			return (0);
339 		}
340 
341 		if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
342 			errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
343 			ifoClose(ifofile);
344 			return (0);
345 		}
346 
347 		B2N_32(sector);
348 
349 		tt_srpt->title[counter].title_set_sector = sector;
350 
351 	}
352 	return (ifofile);
353 }
354 
355 EXPORT ifo_handle_t *
ifoOpen(dvd,title)356 ifoOpen(dvd, title)
357 	dvd_reader_t *dvd;
358 	int title;
359 {
360 	/* The main ifofile structure */
361 	ifo_handle_t *ifofile;
362 
363 	/* File handles and offset */
364 	int file;
365 	char full_path[ PATH_MAX + 1 ];
366 
367 	/* Identifier of the IFO */
368 	char identifier[13];
369 
370 	identifier[0] = '\0';
371 
372 	ifofile = (ifo_handle_t *)e_malloc(sizeof (ifo_handle_t));
373 
374 	memset(ifofile, 0, sizeof (ifo_handle_t));
375 
376 	if (title) {
377 		snprintf(full_path, sizeof (full_path),
378 				"%s/VIDEO_TS/VTS_%02d_0.IFO", dvd->path_root, title);
379 	} else {
380 		snprintf(full_path, sizeof (full_path),
381 				"%s/VIDEO_TS/VIDEO_TS.IFO", dvd->path_root);
382 	}
383 
384 	if ((file = open(full_path, O_RDONLY | O_BINARY)) == -1) {
385 		errmsg(_("Failed to open '%s'.\n"), full_path);
386 		free(ifofile);
387 		return (0);
388 	}
389 
390 	/* Determine if we have a VMGI or VTSI */
391 
392 	if (read(file, identifier, sizeof (identifier)) != sizeof (identifier)) {
393 		errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
394 		free(ifofile);
395 		return (0);
396 	}
397 
398 	if ((strstr("DVDVIDEO-VMG", identifier) != 0) && (title == 0)) {
399 		ifofile = ifoReadVGMI(file, ifofile);
400 		close(file);
401 		return (ifofile);
402 	} else if ((strstr("DVDVIDEO-VTS", identifier) != 0) && (title != 0)) {
403 		ifofile = ifoReadVTSI(file, ifofile);
404 		close(file);
405 		return (ifofile);
406 	} else {
407 		errmsgno(EX_BAD, _("Giving up this is not a valid IFO file.\n"));
408 		close(file);
409 		free(ifofile);
410 		ifofile = 0;
411 		return (0);
412 	}
413 }
414 
415 LOCAL void
ifoFree_TT_SRPT(ifofile)416 ifoFree_TT_SRPT(ifofile)
417 	ifo_handle_t *ifofile;
418 {
419 	if (!ifofile)
420 		return;
421 
422 	if (ifofile->tt_srpt) {
423 		if (ifofile->tt_srpt->title) {
424 			free(ifofile->tt_srpt->title);
425 		}
426 		free(ifofile->tt_srpt);
427 		ifofile->tt_srpt = 0;
428 	}
429 }
430 
431 EXPORT void
ifoClose(ifofile)432 ifoClose(ifofile)
433 	ifo_handle_t	*ifofile;
434 {
435 
436 	if (!ifofile)
437 		return;
438 
439 	ifoFree_TT_SRPT(ifofile);
440 
441 	if (ifofile->vmgi_mat) {
442 		free(ifofile->vmgi_mat);
443 	}
444 
445 	if (ifofile->vtsi_mat) {
446 		free(ifofile->vtsi_mat);
447 	}
448 
449 	free(ifofile);
450 	ifofile = 0;
451 }
452 #endif /* DVD_AUD_VID */
453