/* * This file has been modified for the cdrkit suite. * * The behaviour and appearence of the program code below can differ to a major * extent from the version distributed by the original author(s). * * For details, see Changelog file distributed with the cdrkit package. If you * received this file from another source then ask the distributing person for * a log of modifications. * */ /* @(#)ifo_read.c 1.5 04/03/04 joerg */ /* * Copyright (C) 2002 Olaf Beck * Jörg Schilling * (making the code portable) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * NOTE: This is a cut down version of libdvdread for genisoimage, due * to portability issues with the current libdvdread according to * the maintainer of genisoimage. * This cut down version only reads from a harddisk file structure * and it only implements the functions necessary inorder to make * genisoimage produce valid DVD-Video images. * DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL * LIBDVDREAD INSTEAD */ #ifdef DVD_VIDEO #include #include "genisoimage.h" #include #include #include #include "ifo_read.h" #include "bswap.h" #define MSGEREAD "Failed to read VIDEO_TS.IFO\n" #define MSGESEEK "Failed to seek VIDEO_TS.IFO\n" #define MSGEOPEN "Failed to open VIDEO_TS.IFO\n" static ifo_handle_t *ifoReadVTSI(int file, ifo_handle_t * ifofile); static ifo_handle_t *ifoReadVGMI(int file, ifo_handle_t * ifofile); ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title); static void ifoFree_TT_SRPT(ifo_handle_t *ifofile); void ifoClose(ifo_handle_t * ifofile); static ifo_handle_t * ifoReadVTSI(int file, ifo_handle_t *ifofile) { off_t offset; UInt32_t sector; vtsi_mat_t * vtsi_mat; /* Make the VMG part NULL */ ifofile->vmgi_mat = NULL; ifofile->tt_srpt = NULL; vtsi_mat = (vtsi_mat_t *)e_malloc(sizeof (vtsi_mat_t)); if (!vtsi_mat) { /* fprintf(stderr, "Memmory allocation error\n");*/ free(ifofile); return (0); } ifofile->vtsi_mat = vtsi_mat; /* Last sector of VTS i.e. last sector of BUP */ offset = 12; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vtsi_mat->vts_last_sector = sector; /* Last sector of IFO */ offset = 28; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vtsi_mat->vtsi_last_sector = sector; /* Star sector of VTS Menu VOB */ offset = 192; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vtsi_mat->vtsm_vobs = sector; /* Start sector of VTS Title VOB */ offset = 196; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vtsi_mat->vtstt_vobs = sector; return (ifofile); } static ifo_handle_t * ifoReadVGMI(int file, ifo_handle_t *ifofile) { off_t offset; Uint counter; UInt32_t sector; UInt16_t titles; vmgi_mat_t *vmgi_mat; tt_srpt_t *tt_srpt; /* Make the VTS part null */ ifofile->vtsi_mat = NULL; vmgi_mat = (vmgi_mat_t *)e_malloc(sizeof (vmgi_mat_t)); if (!vmgi_mat) { /* fprintf(stderr, "Memmory allocation error\n");*/ free(ifofile); return (0); } ifofile->vmgi_mat = vmgi_mat; /* Last sector of VMG i.e. last sector of BUP */ offset = 12; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vmgi_mat->vmg_last_sector = sector; /* Last sector of IFO */ offset = 28; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vmgi_mat->vmgi_last_sector = sector; /* Number of VTS i.e. title sets */ offset = 62; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, &titles, sizeof (titles)) != sizeof (titles)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_16(titles); vmgi_mat->vmg_nr_of_title_sets = titles; /* Star sector of VMG Menu VOB */ offset = 192; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vmgi_mat->vmgm_vobs = sector; /* Sector offset to TT_SRPT */ offset = 196; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); vmgi_mat->tt_srpt = sector; tt_srpt = (tt_srpt_t *)e_malloc(sizeof (tt_srpt_t)); if (!tt_srpt) { /* fprintf(stderr, "Memmory allocation error\n");*/ ifoClose(ifofile); return (0); } ifofile->tt_srpt = tt_srpt; /* Number of titles in TT_SRPT */ offset = 2048 * vmgi_mat->tt_srpt; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif return (0); } if (read(file, &titles, sizeof (titles)) != sizeof (titles)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif return (0); } B2N_16(titles); tt_srpt->nr_of_srpts = titles; tt_srpt->title = (title_info_t *)e_malloc(sizeof (title_info_t) * tt_srpt->nr_of_srpts); if (!tt_srpt->title) { /* fprintf(stderr, "Memmory allocation error\n");*/ ifoClose(ifofile); return (0); } /* Start sector of each title in TT_SRPT */ for (counter = 0; counter < tt_srpt->nr_of_srpts; counter++) { offset = (2048 * vmgi_mat->tt_srpt) + 8 + (counter * 12) + 8; if (lseek(file, offset, SEEK_SET) != offset) { #ifdef USE_LIBSCHILY errmsg(MSGESEEK); #else printf(stderr, MSGESEEK); #endif ifoClose(ifofile); return (0); } if (read(file, §or, sizeof (sector)) != sizeof (sector)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif ifoClose(ifofile); return (0); } B2N_32(sector); tt_srpt->title[counter].title_set_sector = sector; } return (ifofile); } ifo_handle_t * ifoOpen(dvd_reader_t *dvd, int title) { /* The main ifofile structure */ ifo_handle_t *ifofile; /* File handles and offset */ int file; off_t offset; char full_path[ PATH_MAX + 1 ]; /* Identifier of the IFO */ char identifier[13]; identifier[0] = '\0'; ifofile = (ifo_handle_t *)e_malloc(sizeof (ifo_handle_t)); memset(ifofile, 0, sizeof (ifo_handle_t)); if (title) { snprintf(full_path, sizeof (full_path), "%s/VIDEO_TS/VTS_%02d_0.IFO", dvd->path_root, title); } else { snprintf(full_path, sizeof (full_path), "%s/VIDEO_TS/VIDEO_TS.IFO", dvd->path_root); } if ((file = open(full_path, O_RDONLY | O_BINARY)) == -1) { #ifdef USE_LIBSCHILY errmsg(MSGEOPEN); #else printf(stderr, MSGEOPEN); #endif free(ifofile); return (0); } offset = 0; /* Determine if we have a VMGI or VTSI */ if (read(file, identifier, sizeof (identifier)) != sizeof (identifier)) { #ifdef USE_LIBSCHILY errmsg(MSGEREAD); #else printf(stderr, MSGEREAD); #endif return (0); } if ((strstr("DVDVIDEO-VMG", identifier) != 0) && (title == 0)) { ifofile = ifoReadVGMI(file, ifofile); close(file); return (ifofile); } else if ((strstr("DVDVIDEO-VTS", identifier) != 0) && (title != 0)) { ifofile = ifoReadVTSI(file, ifofile); close(file); return (ifofile); } else { #ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Giving up this is not a valid IFO file\n"); #else fprintf(stderr, "Giving up this is not a valid IFO file\n"); #endif close(file); free(ifofile); ifofile = 0; return (0); } } static void ifoFree_TT_SRPT(ifo_handle_t *ifofile) { if (!ifofile) return; if (ifofile->tt_srpt) { if (ifofile->tt_srpt->title) { free(ifofile->tt_srpt->title); } free(ifofile->tt_srpt); ifofile->tt_srpt = 0; } } void ifoClose(ifo_handle_t *ifofile) { if (!ifofile) return; ifoFree_TT_SRPT(ifofile); if (ifofile->vmgi_mat) { free(ifofile->vtsi_mat); } if (ifofile->vtsi_mat) { free(ifofile->vtsi_mat); } free(ifofile); ifofile = 0; } #endif /* DVD_VIDEO */