$OpenBSD: patch-src_vm_vm_c,v 1.1 2012/09/26 00:04:09 brad Exp $

- 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;
 }
