The following diff backports various fixes for libdvdnav for issues
which result in crashing or issues with playback with certain DVDs.
Tested with Xine with a bunch of DVDs on amd64.
Index: Makefile
===================================================================
RCS file: /home/cvs/ports/multimedia/libdvdnav/Makefile,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile
--- Makefile 5 Sep 2012 08:09:27 -0000 1.18
+++ Makefile 5 Sep 2012 18:28:31 -0000
@@ -5,14 +5,14 @@ SHARED_ONLY= Yes
COMMENT= DVD navigation library
DISTNAME= libdvdnav-4.2.0
-REVISION= 1
+REVISION= 2
EPOCH= 0
CATEGORIES= multimedia
MASTER_SITES= ${HOMEPAGE}releases/
EXTRACT_SUFX= .tar.bz2
-SHARED_LIBS= dvdnav 6.1 \
- dvdnavmini 6.1
+SHARED_LIBS= dvdnav 6.2 \
+ dvdnavmini 6.2
HOMEPAGE= http://dvdnav.mplayerhq.hu/
@@ -22,7 +22,7 @@ PERMIT_DISTFILES_FTP= Yes
PERMIT_PACKAGE_CDROM= Yes
PERMIT_PACKAGE_FTP= Yes
-WANTLIB += dvdread pthread
+WANTLIB= dvdread pthread
AUTOCONF_VERSION= 2.61
AUTOMAKE_VERSION= 1.10
Index: patches/patch-src_dvdnav_c
===================================================================
RCS file: patches/patch-src_dvdnav_c
diff -N patches/patch-src_dvdnav_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_dvdnav_c 5 Sep 2012 18:50:18 -0000
@@ -0,0 +1,159 @@
+$OpenBSD$
+
+- Check that a VOB is open in case we need to open one
+- Add a function to create a dpu of a dvdnav handle
+- Prevent overflow by pre-casting to int64_t
+- Remove unneeded address-of of CLUT
+- Make sure we get nav packets for all cells in multi angle features
+- Test still like a boolean value and not an integer value
+- Always check whether a still is being handled
+
+--- src/dvdnav.c.orig Wed Sep 5 14:23:55 2012
++++ src/dvdnav.c Wed Sep 5 14:24:07 2012
+@@ -71,6 +71,67 @@ static dvdnav_status_t dvdnav_clear(dvdnav_t * this) {
+ return DVDNAV_STATUS_OK;
+ }
+
++dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src) {
++ dvdnav_t *this;
++
++ (*dest) = NULL;
++ this = (dvdnav_t*)malloc(sizeof(dvdnav_t));
++ if(!this)
++ return DVDNAV_STATUS_ERR;
++
++ memcpy(this, src, sizeof(dvdnav_t));
++ this->file = NULL;
++
++ pthread_mutex_init(&this->vm_lock, NULL);
++
++ this->vm = vm_new_copy(src->vm);
++ if(!this->vm) {
++ printerr("Error initialising the DVD VM.");
++ pthread_mutex_destroy(&this->vm_lock);
++ free(this);
++ return DVDNAV_STATUS_ERR;
++ }
++
++ /* Start the read-ahead cache. */
++ this->cache = dvdnav_read_cache_new(this);
++
++ (*dest) = this;
++ return DVDNAV_STATUS_OK;
++}
++
++dvdnav_status_t dvdnav_free_dup(dvdnav_t *this) {
++
++#ifdef LOG_DEBUG
++ fprintf(MSG_OUT, "libdvdnav: free_dup:called\n");
++#endif
++
++ if (this->file) {
++ pthread_mutex_lock(&this->vm_lock);
++ DVDCloseFile(this->file);
++#ifdef LOG_DEBUG
++ fprintf(MSG_OUT, "libdvdnav: close:file closing\n");
++#endif
++ this->file = NULL;
++ pthread_mutex_unlock(&this->vm_lock);
++ }
++
++ /* Free the VM */
++ if(this->vm)
++ vm_free_copy(this->vm);
++
++ pthread_mutex_destroy(&this->vm_lock);
++
++ /* We leave the final freeing of the entire structure to the cache,
++ * because we don't know, if there are still buffers out in the wild,
++ * that must return first. */
++ if(this->cache)
++ dvdnav_read_cache_free(this->cache);
++ else
++ free(this);
++
++ return DVDNAV_STATUS_OK;
++}
++
+ dvdnav_status_t dvdnav_open(dvdnav_t** dest, const char *path) {
+ dvdnav_t *this;
+ struct timeval time;
+@@ -203,12 +264,12 @@ int64_t dvdnav_convert_time(dvd_time_t *time) {
+ int64_t result;
+ int64_t frames;
+
+- result = (time->hour >> 4 ) * 10 * 60 * 60 * 90000;
+- result += (time->hour & 0x0f) * 60 * 60 * 90000;
+- result += (time->minute >> 4 ) * 10 * 60 * 90000;
+- result += (time->minute & 0x0f) * 60 * 90000;
+- result += (time->second >> 4 ) * 10 * 90000;
+- result += (time->second & 0x0f) * 90000;
++ result = ((int64_t)(time->hour >> 4 )) * 10 * 60 * 60 * 90000;
++ result += ((int64_t)(time->hour & 0x0f)) * 60 * 60 * 90000;
++ result += ((int64_t)(time->minute >> 4 )) * 10 * 60 * 90000;
++ result += ((int64_t)(time->minute & 0x0f)) * 60 * 90000;
++ result += ((int64_t)(time->second >> 4 )) * 10 * 90000;
++ result += ((int64_t)(time->second & 0x0f)) * 90000;
+
+ frames = ((time->frame_u & 0x30) >> 4) * 10;
+ frames += ((time->frame_u & 0x0f) ) ;
+@@ -336,9 +397,10 @@ static int32_t dvdnav_get_vobu(dvdnav_t *this, dsi_t *
+ dvdnav_angle_change(this, 1);
+ }
+ #endif
++ /* only use ILVU information if we are at the last vobunit in ILVU */
++ /* otherwise we will miss nav packets from vobunits inbetween */
++ if(num_angle != 0 && (nav_dsi->sml_pbi.category & DSI_ILVU_MASK) ==
(DSI_ILVU_BLOCK | DSI_ILVU_LAST)) {
+
+- if(num_angle != 0) {
+-
+ if((next = nav_pci->nsml_agli.nsml_agl_dsta[angle-1]) != 0) {
+ if((next & 0x3fffffff) != 0) {
+ if(next & 0x80000000)
+@@ -518,8 +580,10 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
+ return DVDNAV_STATUS_OK;
+ }
+
+- /* Check to see if we need to change the currently opened VOB */
+- if((this->position_current.vts != this->position_next.vts) ||
++ /* Check to see if we need to change the currently opened VOB or open
++ * a new one because we don't currently have an opened VOB. */
++ if((this->file == NULL) ||
++ (this->position_current.vts != this->position_next.vts) ||
+ (this->position_current.domain != this->position_next.domain)) {
+ dvd_read_domain_t domain;
+ int32_t vtsN;
+@@ -655,7 +719,7 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
+ fprintf(MSG_OUT, "libdvdnav: SPU_CLUT_CHANGE\n");
+ #endif
+ (*len) = 16 * sizeof(uint32_t);
+- memcpy(*buf, &(state->pgc->palette), 16 * sizeof(uint32_t));
++ memcpy(*buf, state->pgc->palette, sizeof(state->pgc->palette));
+ this->spu_clut_changed = 0;
+ pthread_mutex_unlock(&this->vm_lock);
+ return DVDNAV_STATUS_OK;
+@@ -731,16 +795,15 @@ dvdnav_status_t dvdnav_get_next_cache_block(dvdnav_t *
+ /* we are about to leave a cell, so a lot of state changes could occur;
+ * under certain conditions, the application should get in sync with us
before this,
+ * otherwise it might show stills or menus too shortly */
+- if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) &&
!this->sync_wait_skip) {
++ if ((this->position_current.still || this->pci.hli.hl_gi.hli_ss) &&
!this->sync_wait_skip)
+ this->sync_wait = 1;
+- } else {
+- if( this->position_current.still == 0 || this->skip_still ) {
+- /* no active cell still -> get us to the next cell */
+- vm_get_next_cell(this->vm);
+- this->position_current.still = 0; /* still gets activated at end of
cell */
+- this->skip_still = 0;
+- this->sync_wait_skip = 0;
+- }
++
++ if(!this->position_current.still || this->skip_still ) {
++ /* no active cell still -> get us to the next cell */
++ vm_get_next_cell(this->vm);
++ this->position_current.still = 0; /* still gets activated at end of
cell */
++ this->skip_still = 0;
++ this->sync_wait_skip = 0;
+ }
+ /* handle related state changes in next iteration */
+ (*event) = DVDNAV_NOP;
Index: patches/patch-src_dvdnav_dvdnav_h
===================================================================
RCS file: patches/patch-src_dvdnav_dvdnav_h
diff -N patches/patch-src_dvdnav_dvdnav_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_dvdnav_dvdnav_h 5 Sep 2012 18:42:58 -0000
@@ -0,0 +1,26 @@
+$OpenBSD$
+
+- Add a function to create a dpu of a dvdnav handle
+- Fix C++ compatibility broken in r1208
+
+--- src/dvdnav/dvdnav.h.orig Wed Sep 5 14:25:10 2012
++++ src/dvdnav/dvdnav.h Wed Sep 5 14:25:18 2012
+@@ -89,6 +89,9 @@ typedef int32_t dvdnav_status_t;
+ */
+ dvdnav_status_t dvdnav_open(dvdnav_t **dest, const char *path);
+
++dvdnav_status_t dvdnav_dup(dvdnav_t **dest, dvdnav_t *src);
++dvdnav_status_t dvdnav_free_dup(dvdnav_t *this);
++
+ /*
+ * Closes a dvdnav_t previously opened with dvdnav_open(), freeing any
+ * memory associated with it.
+@@ -281,7 +284,7 @@ dvdnav_status_t dvdnav_part_play(dvdnav_t *self, int32
+ /*
+ * Plays the specified title, starting from the specified program
+ */
+-dvdnav_status_t dvdnav_program_play(dvdnav_t *this, int32_t title, int32_t
pgcn, int32_t pgn);
++dvdnav_status_t dvdnav_program_play(dvdnav_t *self, int32_t title, int32_t
pgcn, int32_t pgn);
+
+ /*
+ * Stores in *times an array (that the application *must* free) of
Index: patches/patch-src_dvdnav_internal_h
===================================================================
RCS file: patches/patch-src_dvdnav_internal_h
diff -N patches/patch-src_dvdnav_internal_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_dvdnav_internal_h 5 Sep 2012 18:43:57 -0000
@@ -0,0 +1,21 @@
+$OpenBSD$
+
+Bit fields for ILVU
+
+--- src/dvdnav_internal.h.orig Wed Sep 5 14:23:14 2012
++++ src/dvdnav_internal.h Wed Sep 5 14:23:26 2012
+@@ -76,6 +76,14 @@ static inline int _private_gettimeofday( struct timeva
+ #define DVD_VIDEO_LB_LEN 2048
+ #endif
+
++typedef enum {
++ DSI_ILVU_PRE = 1 << 15, /* set during the last 3 VOBU preceeding an
interleaved block. */
++ DSI_ILVU_BLOCK = 1 << 14, /* set for all VOBU in an interleaved block */
++ DSI_ILVU_FIRST = 1 << 13, /* set for the first VOBU for a given angle or
scene within a ILVU, or the first VOBU in the preparation (PREU) sequence */
++ DSI_ILVU_LAST = 1 << 12, /* set for the last VOBU for a given angle or
scene within a ILVU, or the last VOBU in the preparation (PREU) sequence */
++ DSI_ILVU_MASK = 0xf000
++} DSI_ILVU;
++
+ typedef struct read_cache_s read_cache_t;
+
+ /*
Index: patches/patch-src_highlight_c
===================================================================
RCS file: patches/patch-src_highlight_c
diff -N patches/patch-src_highlight_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_highlight_c 5 Sep 2012 18:45:11 -0000
@@ -0,0 +1,34 @@
+$OpenBSD$
+
+Pointer validation fixing
+
+--- src/highlight.c.orig Wed Sep 5 14:21:14 2012
++++ src/highlight.c Wed Sep 5 14:21:20 2012
+@@ -242,8 +242,13 @@ static btni_t *get_current_button(dvdnav_t *this, pci_
+ }
+
+ static dvdnav_status_t button_auto_action(dvdnav_t *this, pci_t *pci) {
+- if (get_current_button(this, pci)->auto_action_mode)
++ btni_t *button_ptr;
++ if ((button_ptr = get_current_button(this, pci)) == NULL)
++ return DVDNAV_STATUS_ERR;
++
++ if (button_ptr->auto_action_mode)
+ return dvdnav_button_activate(this, pci);
++
+ return DVDNAV_STATUS_OK;
+ }
+
+@@ -366,7 +371,11 @@ dvdnav_status_t dvdnav_button_activate(dvdnav_t *this,
+ return DVDNAV_STATUS_ERR;
+ }
+
+- button_ptr = get_current_button(this, pci);
++ if ((button_ptr = get_current_button(this, pci)) == NULL) {
++ pthread_mutex_unlock(&this->vm_lock);
++ return DVDNAV_STATUS_ERR;
++ }
++
+ /* Finally, make the VM execute the appropriate code and probably
+ * schedule a jump */
+ #ifdef BUTTON_TESTING
Index: patches/patch-src_remap_c
===================================================================
RCS file: patches/patch-src_remap_c
diff -N patches/patch-src_remap_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_remap_c 5 Sep 2012 18:48:38 -0000
@@ -0,0 +1,67 @@
+$OpenBSD$
+
+- Initialize epos
+- Pointer validation fixing
+
+--- src/remap.c.orig Wed Sep 5 14:20:01 2012
++++ src/remap.c Wed Sep 5 14:20:08 2012
+@@ -62,6 +62,9 @@ struct remap_s {
+
+ static remap_t* remap_new( char *title) {
+ remap_t *map = malloc( sizeof(remap_t));
++ if (map == NULL)
++ return NULL;
++
+ map->title = strdup(title);
+ map->maxblocks = 0;
+ map->nblocks = 0;
+@@ -139,8 +142,10 @@ static void remap_add_node( remap_t *map, block_t bloc
+ } else {
+ /* new block */
+ if (map->nblocks >= map->maxblocks) {
++ if ((map->blocks = realloc( map->blocks, sizeof( block_t)*(
map->maxblocks + 20))) == NULL)
++ return;
++
+ map->maxblocks += 20;
+- map->blocks = realloc( map->blocks, sizeof(
block_t)*map->maxblocks);
+ }
+ n = map->nblocks++;
+ while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) {
+@@ -155,10 +160,12 @@ static int parseblock(char *buf, int *dom, int *tt, in
+ unsigned long *start, unsigned long *end) {
+ long tmp;
+ char *tok;
+- char *epos;
++ char *epos = NULL;
+ char *marker[]={"domain", "title", "program", "start", "end"};
+ int st = 0;
+- tok = strtok( buf, " ");
++ if ((tok = strtok( buf, " ")) == NULL)
++ return st;
++
+ while (st < 5) {
+ if (strcmp(tok, marker[st])) return -st-1000;
+ tok = strtok( NULL, " ");
+@@ -183,7 +190,7 @@ static int parseblock(char *buf, int *dom, int *tt, in
+ break;
+ }
+ st++;
+- tok = strtok( NULL, " ");
++ if (!(tok = strtok( NULL, " "))) return -st-2000;
+ }
+ return st;
+ }
+@@ -214,7 +221,12 @@ remap_t* remap_loadmap( char *title) {
+ }
+
+ /* Load the map file */
+- map = remap_new( title);
++ if ((map = remap_new( title)) == NULL) {
++ fprintf(MSG_OUT, "libdvdnav: Unable to load map '%s'\n", title);
++ fclose(fp);
++ return NULL;
++ }
++
+ while (fgets( buf, sizeof(buf), fp) != NULL) {
+ if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue;
+ if (strncasecmp( buf, "debug", 5) == 0) {
Index: patches/patch-src_searching_c
===================================================================
RCS file: patches/patch-src_searching_c
diff -N patches/patch-src_searching_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_searching_c 5 Sep 2012 18:53:31 -0000
@@ -0,0 +1,135 @@
+$OpenBSD$
+
+- Skip PGCs w/ a cell number of 0
+- Ignore parts where the pgc start byte is above the last byte
+- Make sure pgc is valid before dereferencing
+- Check cell new row before using it to index into cell_playback
+- Initialize next_vobu
+- Rework functions that call vm_copy_vm()
+
+--- src/searching.c.orig Wed Sep 5 14:19:00 2012
++++ src/searching.c Wed Sep 5 14:19:07 2012
+@@ -73,7 +73,7 @@ static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *thi
+ }
+ if(admap) {
+ uint32_t address = 0;
+- uint32_t vobu_start, next_vobu;
++ uint32_t vobu_start, next_vobu = 0;
+ int admap_entries = (admap->last_byte + 1 -
VOBU_ADMAP_SIZE)/VOBU_ADMAP_SIZE;
+
+ /* Search through ADMAP for best sector */
+@@ -403,8 +403,7 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+- pthread_mutex_unlock(&this->vm_lock);
+- return DVDNAV_STATUS_ERR;
++ goto fail;
+ }
+
+ #ifdef LOG_DEBUG
+@@ -412,17 +411,25 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
+ #endif
+ /* make a copy of current VM and try to navigate the copy to the next PG */
+ try_vm = vm_new_copy(this->vm);
++ if (try_vm == NULL) {
++ printerr("Unable to copy the VM.");
++ goto fail;
++ }
++
+ if (!vm_jump_next_pg(try_vm) || try_vm->stopped) {
+ vm_free_copy(try_vm);
+ /* next_pg failed, try to jump at least to the next cell */
+ try_vm = vm_new_copy(this->vm);
++ if (try_vm == NULL) {
++ printerr("Unable to copy the VM.");
++ goto fail;
++ }
+ vm_get_next_cell(try_vm);
+ if (try_vm->stopped) {
+ vm_free_copy(try_vm);
+ fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n");
+ printerr("Skip to next chapter failed.");
+- pthread_mutex_unlock(&this->vm_lock);
+- return DVDNAV_STATUS_ERR;
++ goto fail;
+ }
+ }
+ this->cur_cell_time = 0;
+@@ -437,6 +444,10 @@ dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this)
+ pthread_mutex_unlock(&this->vm_lock);
+
+ return DVDNAV_STATUS_OK;
++
++fail:
++ pthread_mutex_unlock(&this->vm_lock);
++ return DVDNAV_STATUS_ERR;
+ }
+
+ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) {
+@@ -445,13 +456,17 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMe
+ pthread_mutex_lock(&this->vm_lock);
+ if(!this->vm->state.pgc) {
+ printerr("No current PGC.");
+- pthread_mutex_unlock(&this->vm_lock);
+- return DVDNAV_STATUS_ERR;
++ goto fail;
+ }
+
+ this->cur_cell_time = 0;
+ /* make a copy of current VM and try to navigate the copy to the menu */
+ try_vm = vm_new_copy(this->vm);
++ if (try_vm == NULL) {
++ printerr("Unable to copy VM.");
++ goto fail;
++ }
++
+ if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) {
+ /* Try resume */
+ if (vm_jump_resume(try_vm) && !try_vm->stopped) {
+@@ -477,9 +492,12 @@ dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMe
+ } else {
+ vm_free_copy(try_vm);
+ printerr("No such menu or menu not reachable.");
+- pthread_mutex_unlock(&this->vm_lock);
+- return DVDNAV_STATUS_ERR;
++ goto fail;
+ }
++
++fail:
++ pthread_mutex_unlock(&this->vm_lock);
++ return DVDNAV_STATUS_ERR;
+ }
+
+ dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos,
+@@ -616,13 +634,29 @@ uint32_t dvdnav_describe_title_chapters(dvdnav_t *this
+ length = 0;
+ for(i=0; i<parts; i++) {
+ uint32_t cellnr, endcellnr;
++ if (ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc_start_byte >=
ifo->vts_pgcit->last_byte) {
++ printerr("PGC start out of bounds");
++ continue;
++ }
+ pgc = ifo->vts_pgcit->pgci_srp[ptt[i].pgcn-1].pgc;
++ if (pgc == NULL) {
++ printerr("PGC missing.");
++ continue;
++ }
+ if(ptt[i].pgn > pgc->nr_of_programs) {
+ printerr("WRONG part number.");
+ goto fail;
+ }
+
+- cellnr = pgc->program_map[ptt[i].pgn-1];
++ if (pgc->nr_of_cells == 0) {
++ printerr("Number of cells cannot be 0");
++ continue;
++ }
++ if ((cellnr = pgc->program_map[ptt[i].pgn-1]) == 0) {
++ printerr("Cell new row cannot be 0");
++ continue;
++ }
++
+ if(ptt[i].pgn < pgc->nr_of_programs)
+ endcellnr = pgc->program_map[ptt[i].pgn];
+ else
Index: patches/patch-src_vm_vm_c
===================================================================
RCS file: patches/patch-src_vm_vm_c
diff -N patches/patch-src_vm_vm_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_vm_vm_c 5 Sep 2012 19:00:47 -0000
@@ -0,0 +1,324 @@
+$OpenBSD$
+
+- Reset the vm if necessary
+- Use vm_close() w/in vm.c where appropriate
+- Add the static function vm_close()
+- Check the return value of dvd_read_name
+- Rewrite dvd_read_name to return a value
+- Prevent general CPP macro from causing strange behavior
+- Replace assert w/ a conditional and a null return
+- Initialize link_values
+- Pointer validation fixing
+- Return 0 instead of an assert
+
+--- src/vm/vm.c.orig Wed Sep 5 14:18:33 2012
++++ src/vm/vm.c Wed Sep 5 14:18:50 2012
+@@ -59,7 +59,7 @@
+ #endif
+
+ /*
+-#define STRICT
++#define DVDNAV_STRICT
+ */
+
+ /* Local prototypes */
+@@ -101,8 +101,8 @@ static int get_PGCN(vm_t *vm);
+ static pgcit_t* get_MENU_PGCIT(vm_t *vm, ifo_handle_t *h, uint16_t lang);
+ static pgcit_t* get_PGCIT(vm_t *vm);
+
+-
+ /* Helper functions */
++static void vm_close(vm_t *vm);
+
+ #ifdef TRACE
+ static void vm_print_current_domain_state(vm_t *vm) {
+@@ -162,64 +162,86 @@ static int os2_open(const char *name, int oflag)
+ }
+ #endif
+
+-static void dvd_read_name(char *name, char *serial, const char *device) {
+- /* Because we are compiling with _FILE_OFFSET_BITS=64
+- * all off_t are 64bit.
+- */
+- off_t off;
+- int fd, i;
+- uint8_t data[DVD_VIDEO_LB_LEN];
++static int dvd_read_name(char *name, char *serial, const char *device) {
++ /* Because we are compiling with _FILE_OFFSET_BITS=64
++ * all off_t are 64bit.
++ */
++ off_t off;
++ ssize_t read_size = 0;
++ int fd = -1, i;
++ uint8_t data[DVD_VIDEO_LB_LEN];
+
+- /* Read DVD name */
+- fd = open(device, O_RDONLY);
+- if (fd > 0) {
+- off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET );
+- if( off == ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {
+- off = read( fd, data, DVD_VIDEO_LB_LEN );
+- close(fd);
+- if (off == ( (off_t) DVD_VIDEO_LB_LEN )) {
+- fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
+- for(i=25; i < 73; i++ ) {
+- if((data[i] == 0)) break;
+- if((data[i] > 32) && (data[i] < 127)) {
+- fprintf(MSG_OUT, "%c", data[i]);
+- } else {
+- fprintf(MSG_OUT, " ");
+- }
+- }
+- strncpy(name, (char*) &data[25], 48);
+- name[48] = 0;
+- fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
+- for(i=73; i < 89; i++ ) {
+- if((data[i] == 0)) break;
+- if((data[i] > 32) && (data[i] < 127)) {
+- fprintf(MSG_OUT, "%c", data[i]);
+- } else {
+- fprintf(MSG_OUT, " ");
+- }
+- }
+- strncpy(serial, (char*) &data[73], (i-73));
+- serial[14] = 0;
+- fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
+- for(i=89; i < 128; i++ ) {
+- if((data[i] == 0)) break;
+- if((data[i] > 32) && (data[i] < 127)) {
+- fprintf(MSG_OUT, "%c", data[i]);
+- } else {
+- fprintf(MSG_OUT, " ");
+- }
+- }
+- fprintf(MSG_OUT, "\n");
+- } else {
+- fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a
DVD-ROM device.\n");
+- }
+- } else {
+- fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
+- }
+- close(fd);
++ /* Read DVD name */
++ if (device == NULL) {
++ fprintf(MSG_OUT, "libdvdnav: Device name string NULL\n");
++ goto fail;
++ }
++ if ((fd = open(device, O_RDONLY)) == -1) {
++ fprintf(MSG_OUT, "libdvdnav: Unable to open device file %s.\n", device);
++ goto fail;
++ }
++
++ if ((off = lseek( fd, 32 * (off_t) DVD_VIDEO_LB_LEN, SEEK_SET )) == (off_t)
- 1) {
++ fprintf(MSG_OUT, "libdvdnav: Unable to seek to the title block %u.\n",
32);
++ goto fail;
++ }
++
++ if( off != ( 32 * (off_t) DVD_VIDEO_LB_LEN ) ) {
++ fprintf(MSG_OUT, "libdvdnav: Can't seek to block %u\n", 32 );
++ goto fail;
++ }
++
++ if ((read_size = read( fd, data, DVD_VIDEO_LB_LEN )) == -1) {
++ fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a
DVD-ROM device.\n");
++ goto fail;
++ }
++
++ close(fd);
++ fd = -1;
++ if (read_size != DVD_VIDEO_LB_LEN) {
++ fprintf(MSG_OUT, "libdvdnav: Can't read name block. Probably not a
DVD-ROM device.\n");
++ goto fail;
++ }
++
++ fprintf(MSG_OUT, "libdvdnav: DVD Title: ");
++ for(i=25; i < 73; i++ ) {
++ if((data[i] == 0)) break;
++ if((data[i] > 32) && (data[i] < 127)) {
++ fprintf(MSG_OUT, "%c", data[i]);
+ } else {
+- fprintf(MSG_OUT, "NAME OPEN FAILED\n");
++ fprintf(MSG_OUT, " ");
++ }
+ }
++ strncpy(name, (char*) &data[25], 48);
++ name[48] = 0;
++ fprintf(MSG_OUT, "\nlibdvdnav: DVD Serial Number: ");
++ for(i=73; i < 89; i++ ) {
++ if((data[i] == 0)) break;
++ if((data[i] > 32) && (data[i] < 127)) {
++ fprintf(MSG_OUT, "%c", data[i]);
++ } else {
++ fprintf(MSG_OUT, " ");
++ }
++ }
++ strncpy(serial, (char*) &data[73], (i-73));
++ serial[14] = 0;
++ fprintf(MSG_OUT, "\nlibdvdnav: DVD Title (Alternative): ");
++ for(i=89; i < 128; i++ ) {
++ if((data[i] == 0)) break;
++ if((data[i] > 32) && (data[i] < 127)) {
++ fprintf(MSG_OUT, "%c", data[i]);
++ } else {
++ fprintf(MSG_OUT, " ");
++ }
++ }
++ fprintf(MSG_OUT, "\n");
++ return 1;
++
++fail:
++ if (fd >= 0)
++ close(fd);
++
++ return 0;
+ }
+
+ static int ifoOpenNewVTSI(vm_t *vm, dvd_reader_t *dvd, int vtsN) {
+@@ -268,7 +290,7 @@ vm_t* vm_new_vm() {
+ }
+
+ void vm_free_vm(vm_t *vm) {
+- vm_stop(vm);
++ vm_close(vm);
+ free(vm);
+ }
+
+@@ -294,6 +316,12 @@ dvd_reader_t *vm_get_dvd_reader(vm_t *vm) {
+ /* Basic Handling */
+
+ int vm_start(vm_t *vm) {
++ if (vm->stopped) {
++ if (!vm_reset(vm, NULL))
++ return 0;
++
++ vm->stopped = 0;
++ }
+ /* Set pgc to FP (First Play) pgc */
+ set_FP_PGC(vm);
+ process_command(vm, play_PGC(vm));
+@@ -301,6 +329,10 @@ int vm_start(vm_t *vm) {
+ }
+
+ void vm_stop(vm_t *vm) {
++ vm->stopped = 1;
++}
++
++static void vm_close(vm_t *vm) {
+ if(vm->vmgi) {
+ ifoClose(vm->vmgi);
+ vm->vmgi=NULL;
+@@ -352,7 +384,7 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
+
+ if (vm->dvd && dvdroot) {
+ /* a new dvd device has been requested */
+- vm_stop(vm);
++ vm_close(vm);
+ }
+ if (!vm->dvd) {
+ vm->dvd = DVDOpen(dvdroot);
+@@ -390,8 +422,8 @@ int vm_reset(vm_t *vm, const char *dvdroot) {
+ /* return 0; Not really used for now.. */
+ }
+ /* ifoRead_TXTDT_MGI(vmgi); Not implemented yet */
+- dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot);
+- vm->map = remap_loadmap(vm->dvd_name);
++ if (dvd_read_name(vm->dvd_name, vm->dvd_serial, dvdroot) == 1)
++ vm->map = remap_loadmap(vm->dvd_name);
+ }
+ if (vm->vmgi) {
+ int i, mask;
+@@ -414,7 +446,8 @@ vm_t *vm_new_copy(vm_t *source) {
+ int pgcN = get_PGCN(source);
+ int pgN = (source->state).pgN;
+
+- assert(pgcN);
++ if (target == NULL || pgcN == 0)
++ goto fail;
+
+ memcpy(target, source, sizeof(vm_t));
+
+@@ -424,15 +457,22 @@ vm_t *vm_new_copy(vm_t *source) {
+ if (vtsN > 0) {
+ (target->state).vtsN = 0;
+ if (!ifoOpenNewVTSI(target, target->dvd, vtsN))
+- assert(0);
++ goto fail;
+
+ /* restore pgc pointer into the new vtsi */
+ if (!set_PGCN(target, pgcN))
+- assert(0);
++ goto fail;
++
+ (target->state).pgN = pgN;
+ }
+
+ return target;
++
++fail:
++ if (target != NULL)
++ vm_free_vm(target);
++
++ return NULL;
+ }
+
+ void vm_merge(vm_t *target, vm_t *source) {
+@@ -1050,7 +1090,7 @@ static link_t play_PGC_PG(vm_t *vm, int pgN) {
+ }
+
+ static link_t play_PGC_post(vm_t *vm) {
+- link_t link_values;
++ link_t link_values = { LinkNoLink, 0, 0, 0 };
+
+ #ifdef TRACE
+ fprintf(MSG_OUT, "libdvdnav: play_PGC_post:\n");
+@@ -1129,7 +1169,7 @@ static link_t play_Cell(vm_t *vm) {
+ case 1: /* Angle block */
+ /* Loop and check each cell instead? So we don't get outside the block?
*/
+ (vm->state).cellN += (vm->state).AGL_REG - 1;
+-#ifdef STRICT
++#ifdef DVDNAV_STRICT
+ assert((vm->state).cellN <= (vm->state).pgc->nr_of_cells);
+ assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_mode
!= 0);
+ assert((vm->state).pgc->cell_playback[(vm->state).cellN - 1].block_type
== 1);
+@@ -1187,15 +1227,6 @@ static link_t play_Cell_post(vm_t *vm) {
+ if(cell->cell_cmd_nr != 0) {
+ link_t link_values;
+
+-/* These asserts are now not needed.
+- * Some DVDs have no cell commands listed in the PGC,
+- * but the Cell itself points to a cell command that does not exist.
+- * For this situation, just ignore the cell command and continue.
+- *
+- * assert((vm->state).pgc->command_tbl != NULL);
+- * assert((vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr);
+- */
+-
+ if ((vm->state).pgc->command_tbl != NULL &&
+ (vm->state).pgc->command_tbl->nr_of_cell >= cell->cell_cmd_nr) {
+ #ifdef TRACE
+@@ -1762,7 +1793,8 @@ static int set_PGCN(vm_t *vm, int pgcN) {
+ pgcit_t *pgcit;
+
+ pgcit = get_PGCIT(vm);
+- assert(pgcit != NULL); /* ?? Make this return -1 instead */
++ if (pgcit == NULL)
++ return 0;
+
+ if(pgcN < 1 || pgcN > pgcit->nr_of_pgci_srp) {
+ #ifdef TRACE
+@@ -1797,12 +1829,11 @@ static int set_PGN(vm_t *vm) {
+ (vm->state).pgN = new_pgN;
+
+ if((vm->state).domain == VTS_DOMAIN) {
+- playback_type_t *pb_ty;
+ if((vm->state).TTN_REG > vm->vmgi->tt_srpt->nr_of_srpts)
+ return 0; /* ?? */
+- pb_ty = &vm->vmgi->tt_srpt->title[(vm->state).TTN_REG - 1].pb_ty;
+- vm_get_current_title_part(vm, &dummy, &part);
+- (vm->state).PTTN_REG = part;
++
++ vm_get_current_title_part(vm, &dummy, &part);
++ (vm->state).PTTN_REG = part;
+ }
+ return 1;
+ }
--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.