cdrtools/mkisofs/ifo_read.c
2025-06-15 04:19:58 +08:00

453 lines
9.4 KiB
C

/* @(#)ifo_read.c 1.17 16/10/23 joerg */
#include <schily/mconfig.h>
#ifndef lint
static UConst char sccsid[] =
"@(#)ifo_read.c 1.17 16/10/23 joerg";
#endif
/*
* Copyright (C) 2002 Olaf Beck <olaf_sc@yahoo.com>
* Copyright (C) 2002-2016 Jörg Schilling <schilling@fokus.gmd.de>
*
* 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 mkisofs, due
* to portability issues with the current libdvdread according to
* the maintainer of mkisofs.
* This cut down version only reads from a harddisk file structure
* and it only implements the functions necessary inorder to make
* mkisofs produce valid DVD-Video images.
* DON'T USE THIS LIBRARY IN ANY OTHER PROGRAM GET THE REAL
* LIBDVDREAD INSTEAD
*/
#ifdef DVD_AUD_VID
#include "mkisofs.h"
#include <schily/fcntl.h>
#include <schily/utypes.h>
#include <schily/schily.h>
#include "ifo_read.h"
#include "bswap.h"
LOCAL ifo_handle_t *ifoReadVTSI __PR((int file, ifo_handle_t *ifofile));
LOCAL ifo_handle_t *ifoReadVGMI __PR((int file, ifo_handle_t *ifofile));
EXPORT ifo_handle_t *ifoOpen __PR((dvd_reader_t *dvd, int title));
LOCAL void ifoFree_TT_SRPT __PR((ifo_handle_t *ifofile));
EXPORT void ifoClose __PR((ifo_handle_t *ifofile));
LOCAL ifo_handle_t *
ifoReadVTSI(file, ifofile)
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
B2N_32(sector);
vtsi_mat->vtstt_vobs = sector;
return (ifofile);
}
LOCAL ifo_handle_t *
ifoReadVGMI(file, ifofile)
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
return (0);
}
if (read(file, &titles, sizeof (titles)) != sizeof (titles)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
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) {
errmsg(_("Failed to seek VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
if (read(file, &sector, sizeof (sector)) != sizeof (sector)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
ifoClose(ifofile);
return (0);
}
B2N_32(sector);
tt_srpt->title[counter].title_set_sector = sector;
}
return (ifofile);
}
EXPORT ifo_handle_t *
ifoOpen(dvd, title)
dvd_reader_t *dvd;
int title;
{
/* The main ifofile structure */
ifo_handle_t *ifofile;
/* File handles and offset */
int file;
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) {
errmsg(_("Failed to open '%s'.\n"), full_path);
free(ifofile);
return (0);
}
/* Determine if we have a VMGI or VTSI */
if (read(file, identifier, sizeof (identifier)) != sizeof (identifier)) {
errmsg(_("Failed to read VIDEO_TS.IFO.\n"));
free(ifofile);
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 {
errmsgno(EX_BAD, _("Giving up this is not a valid IFO file.\n"));
close(file);
free(ifofile);
ifofile = 0;
return (0);
}
}
LOCAL void
ifoFree_TT_SRPT(ifofile)
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;
}
}
EXPORT void
ifoClose(ifofile)
ifo_handle_t *ifofile;
{
if (!ifofile)
return;
ifoFree_TT_SRPT(ifofile);
if (ifofile->vmgi_mat) {
free(ifofile->vmgi_mat);
}
if (ifofile->vtsi_mat) {
free(ifofile->vtsi_mat);
}
free(ifofile);
ifofile = 0;
}
#endif /* DVD_AUD_VID */