dvd-id.c, lib.[ch]: Improve DVD ID computation.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 6 Mar 2022 17:32:51 +0000 (17:32 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 6 Mar 2022 20:34:04 +0000 (20:34 +0000)
Move the code to the library.  Accept flags (to the library function and
the utility) to fail if portions of the ID can't be determined.

Also, improve `dvd-id' to print IDs for multiple disc images.

dvd-id.c
lib.c
lib.h

index 971be05..e89945a 100644 (file)
--- a/dvd-id.c
+++ b/dvd-id.c
@@ -1,54 +1,42 @@
 #include "lib.h"
 
-static void usage(FILE *fp) { fprintf(fp, "usage: %s DEVICE\n", prog); }
-
-static void puthex(const unsigned char *p, size_t sz, FILE *fp)
-  { while (sz) { fprintf(fp, "%02x", *p++); sz--; } }
+static void usage(FILE *fp)
+  { fprintf(fp, "usage: %s [-IV] DEVICE ...\n", prog); }
 
 int main(int argc, char *argv[])
 {
-  char volid[33];
-  unsigned char volsetid[16], discid[16];
-  int rc, opt;
-  unsigned f = 0;
+  char id[MAXIDSZ];
+  int i, opt, st = 0;
+  unsigned f = 0, dif = 0;
   static dvd_reader_t *dvd;
 #define f_bogus 1u
 
   set_prog(argv[0]);
   for (;;) {
-    opt = getopt(argc, argv, "h"); if (opt < 0) break;
+    opt = getopt(argc, argv, "hIV"); if (opt < 0) break;
     switch (opt) {
       case 'h': usage(stderr); exit(0);
+      case 'I': dif |= DIF_MUSTIFOHASH; break;
+      case 'V': dif |= DIF_MUSTVOLINF; break;
       default: f |= f_bogus; break;
     }
   }
-  if (argc - optind != 1) f |= f_bogus;
+  if (argc - optind < 1) f |= f_bogus;
   if (f&f_bogus) { usage(stderr); exit(2); }
   setlocale(LC_ALL, "");
   progress_init(&progress);
 
-  open_dvd(argv[optind], 0, &dvd);
-
-  rc = DVDUDFVolumeInfo(dvd,
-                       volid, sizeof(volid),
-                       volsetid, sizeof(volsetid));
-  if (rc) {
-    moan("failed to read volume info");
-    strcpy(volid, "<error reading volume info>");
-    memset(volsetid, 0xff, sizeof(volsetid));
-  }
-
-  rc = DVDDiscID(dvd, discid);
-  if (rc) {
-    moan("failed to determine disc id");
-    memset(discid, 0xff, sizeof(discid));
+  for (i = optind; i < argc; i++) {
+    open_dvd(argv[i], 0, &dvd);
+    if (dvd_id(id, dvd, dif, argv[i]))
+      st = 2;
+    else {
+      if (argc - optind > 1) printf("%s: ", argv[i]);
+      printf("%s\n", id);
+    }
+    DVDClose(dvd);
   }
 
-  fputs(volid, stdout); fputc('-', stdout);
-  puthex(volsetid, sizeof(volsetid), stdout); fputc(':', stdout);
-  puthex(discid, sizeof(discid), stdout); fputc('\n', stdout);
-
-  if (dvd) DVDClose(dvd);
   progress_free(&progress);
-  return (0);
+  return (st);
 }
diff --git a/lib.c b/lib.c
index 69532e8..80b1507 100644 (file)
--- a/lib.c
+++ b/lib.c
@@ -109,6 +109,57 @@ void store_filename(char *buf, ident id)
   }
 }
 
+static char *copy_string(char *p, const char *q)
+{
+  while (*q) *p++ = *q++;
+  *p = 0; return (p);
+}
+
+static char *copy_hex(char *p, const unsigned char *q, size_t sz)
+{
+  while (sz) {
+    sprintf(p, "%02x", *q);
+    p += 2; q++; sz--;
+  }
+  return (p);
+}
+
+int dvd_id(char *p, dvd_reader_t *dvd, unsigned f, const char *file)
+{
+  char volid[33];
+  unsigned char volsetid[16], discid[16];
+  int rc;
+  size_t n;
+
+  rc = DVDUDFVolumeInfo(dvd,
+                       volid, sizeof(volid),
+                       volsetid, sizeof(volsetid));
+  if (!rc) {
+    p = copy_string(p, volid);
+    *p++ = '-';
+    for (n = sizeof(volsetid); n && !volsetid[n - 1]; n--);
+    p = copy_hex(p, volsetid, n);
+  } else if (f&DIF_MUSTVOLINF) {
+    if (file) moan("failed to read volume info for `%s'", file);
+    else moan("failed to read volume info");
+    return (-1);
+  } else
+    p = copy_string(p, "<error reading volume info>");
+
+  *p++ = ':';
+  rc = DVDDiscID(dvd, discid);
+  if (!rc)
+    p = copy_hex(p, discid, sizeof(discid));
+  else if (f&DIF_MUSTIFOHASH) {
+    if (file) moan("failed to determine disc id of `%s'", file);
+    else moan("failed to determine disc id");
+    return (-1);
+  } else
+    p = copy_string(p, "<error reading disc-id>");
+
+  return (0);
+}
+
 struct progress_state progress = PROGRESS_STATE_INIT;
 static struct banner_progress_item banner_progress;
 
diff --git a/lib.h b/lib.h
index 0198c34..bad7c3b 100644 (file)
--- a/lib.h
+++ b/lib.h
@@ -93,6 +93,11 @@ static inline unsigned id_part(ident id) { return ((id >> 16)&0x0ff); }
 #define MAXFNSZ (1 + 8 + 1 + 12 + 1)
 extern void store_filename(char *buf, ident id);
 
+#define DIF_MUSTVOLINF 1u
+#define DIF_MUSTIFOHASH 2u
+#define MAXIDSZ 99
+extern int dvd_id(char *p, dvd_reader_t *dvd, unsigned f, const char *file);
+
 struct banner_progress_item {
   struct progress_item _base;
   const char *msg;