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