Blame src/cd-info.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2003-2005, 2007-2008, 2011-2012, 2014, 2017
Packit dd8086
  Rocky Bernstein <rocky@gnu.org>
Packit dd8086
  Copyright (C) 1996, 1997, 1998  Gerd Knorr <kraxel@bytesex.org>
Packit dd8086
         and Heiko Eißfeldt <heiko@hexco.de>
Packit dd8086
Packit dd8086
  This program is free software: you can redistribute it and/or modify
Packit dd8086
  it under the terms of the GNU General Public License as published by
Packit dd8086
  the Free Software Foundation, either version 3 of the License, or
Packit dd8086
  (at your option) any later version.
Packit dd8086
Packit dd8086
  This program is distributed in the hope that it will be useful,
Packit dd8086
  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit dd8086
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit dd8086
  GNU General Public License for more details.
Packit dd8086
Packit dd8086
  You should have received a copy of the GNU General Public License
Packit dd8086
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit dd8086
*/
Packit dd8086
/*
Packit dd8086
  CD Info - prints various information about a CD, and detects the type of
Packit dd8086
  the CD.
Packit dd8086
*/
Packit dd8086
Packit dd8086
#include "util.h"
Packit dd8086
#include "getopt.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_STDARG_H
Packit dd8086
#include <stdarg.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STRINGS_H
Packit dd8086
#include <strings.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
#include <cddb/cddb.h>
Packit dd8086
#include "cddb.h"
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
#include <libvcd/logging.h>
Packit dd8086
#include <libvcd/files.h>
Packit dd8086
#include <libvcd/info.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#include <cdio/bytesex.h>
Packit dd8086
#include <cdio/ds.h>
Packit dd8086
#include <cdio/util.h>
Packit dd8086
#include <cdio/cd_types.h>
Packit dd8086
#include <cdio/cdtext.h>
Packit dd8086
#include <cdio/iso9660.h>
Packit dd8086
#include <cdio/mmc.h>
Packit dd8086
#include <cdio/audio.h>
Packit dd8086
Packit dd8086
#include "cdio_assert.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_FCNTL_H
Packit dd8086
#include <fcntl.h>
Packit dd8086
#endif
Packit dd8086
#ifdef __linux__
Packit dd8086
# include <linux/version.h>
Packit dd8086
# include <linux/cdrom.h>
Packit dd8086
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,50)
Packit dd8086
#  include <linux/ucdrom.h>
Packit dd8086
# endif
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_ERRNO_H
Packit dd8086
#include <errno.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_ALLOCA_H
Packit dd8086
#include <alloca.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#define STRONG "__________________________________\n"
Packit dd8086
#define NORMAL ""
Packit dd8086
Packit dd8086
#define CDIO_IOCTL_FINISHED 0
Packit dd8086
#if CDIO_IOCTL_FINISHED
Packit dd8086
static struct cdrom_multisession  ms;
Packit dd8086
static struct cdrom_subchnl       sub;
Packit dd8086
#endif
Packit dd8086
Packit dd8086
/* Used by `main' to communicate with `parse_opt'. And global options
Packit dd8086
 */
Packit dd8086
static struct opts_s
Packit dd8086
{
Packit dd8086
  int            no_tracks;
Packit dd8086
  int            no_ioctl;
Packit dd8086
  int            no_analysis;
Packit dd8086
  char          *access_mode; /* Access method driver should use for control */
Packit dd8086
  int            no_cddb;     /* If set the below are meaningless. */
Packit dd8086
  int            no_vcd;
Packit dd8086
  int            show_dvd;
Packit dd8086
  int            no_device;
Packit dd8086
  int            no_disc_mode;
Packit dd8086
  uint32_t       debug_level;
Packit dd8086
  int            version_only;
Packit dd8086
  int            silent;
Packit dd8086
  int            no_header;
Packit dd8086
  int            no_joliet;
Packit dd8086
  int            no_xa;
Packit dd8086
  int            no_rock_ridge;
Packit dd8086
  int            print_iso9660;
Packit dd8086
  int            list_drives;
Packit dd8086
  source_image_t source_image;
Packit dd8086
} opts;
Packit dd8086
Packit dd8086
/* Configuration option codes */
Packit dd8086
enum {
Packit dd8086
  OP_HANDLED = 0,
Packit dd8086
Packit dd8086
  OP_SOURCE_UNDEF,
Packit dd8086
  OP_SOURCE_AUTO,
Packit dd8086
  OP_SOURCE_BIN,
Packit dd8086
  OP_SOURCE_CUE,
Packit dd8086
  OP_SOURCE_CDRDAO,
Packit dd8086
  OP_SOURCE_NRG ,
Packit dd8086
  OP_SOURCE_DEVICE,
Packit dd8086
Packit dd8086
  OP_CDDB_SERVER,
Packit dd8086
  OP_CDDB_CACHE,
Packit dd8086
  OP_CDDB_EMAIL,
Packit dd8086
  OP_CDDB_NOCACHE,
Packit dd8086
  OP_CDDB_TIMEOUT,
Packit dd8086
Packit dd8086
  OP_USAGE,
Packit dd8086
Packit dd8086
  /* These are the remaining configuration options */
Packit dd8086
  OP_VERSION,
Packit dd8086
Packit dd8086
};
Packit dd8086
Packit dd8086
/* Parse source options. */
Packit dd8086
static void
Packit dd8086
parse_source(int opt)
Packit dd8086
{
Packit dd8086
  /* NOTE: The libpopt version made use of an extra temporary
Packit dd8086
     variable (psz_my_source) for all sources _except_ devices.
Packit dd8086
     This distinction seemed to serve no purpose.
Packit dd8086
  */
Packit dd8086
Packit dd8086
  if (opts.source_image != INPUT_UNKNOWN) {
Packit dd8086
    report(stderr, "%s: another source type option given before.\n",
Packit dd8086
           program_name);
Packit dd8086
    report(stderr, "%s: give only one source type option.\n",
Packit dd8086
           program_name);
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  /* For all input sources which are not a DEVICE, we need to make
Packit dd8086
     a copy of the string; for a DEVICE the fill-out routine makes
Packit dd8086
     the copy.
Packit dd8086
  */
Packit dd8086
  if (OP_SOURCE_DEVICE != opt)
Packit dd8086
    if (optarg != NULL) source_name = strdup(optarg);
Packit dd8086
Packit dd8086
  switch (opt) {
Packit dd8086
  case OP_SOURCE_BIN:
Packit dd8086
    opts.source_image  = INPUT_BIN;
Packit dd8086
    break;
Packit dd8086
  case OP_SOURCE_CUE:
Packit dd8086
    opts.source_image  = INPUT_CUE;
Packit dd8086
    break;
Packit dd8086
  case OP_SOURCE_CDRDAO:
Packit dd8086
    opts.source_image  = INPUT_CDRDAO;
Packit dd8086
    break;
Packit dd8086
  case OP_SOURCE_NRG:
Packit dd8086
    opts.source_image  = INPUT_NRG;
Packit dd8086
    break;
Packit dd8086
  case OP_SOURCE_AUTO:
Packit dd8086
    opts.source_image  = INPUT_AUTO;
Packit dd8086
    break;
Packit dd8086
Packit dd8086
  case OP_SOURCE_DEVICE:
Packit dd8086
    opts.source_image  = INPUT_DEVICE;
Packit dd8086
    if (optarg != NULL) source_name = fillout_device_name(optarg);
Packit dd8086
    break;
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
Packit dd8086
/* Parse all options. */
Packit dd8086
static bool
Packit dd8086
parse_options (int argc, char *argv[])
Packit dd8086
{
Packit dd8086
  int opt; /* used for argument parsing */
Packit dd8086
  int rc = EXIT_FAILURE;
Packit dd8086
Packit dd8086
  static const char helpText[] =
Packit dd8086
    "Usage: %s [OPTION...]\n"
Packit dd8086
    "  -a, --access-mode=STRING        Set CD access method\n"
Packit dd8086
    "  -d, --debug=INT                 Set debugging to LEVEL\n"
Packit dd8086
    "  -T, --no-tracks                 Don't show track information\n"
Packit dd8086
    "  -A, --no-analyze                Don't show filesystem analysis\n"
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
    "  --no-cddb                       Don't look up audio CDDB information\n"
Packit dd8086
    "                                  or print it\n"
Packit dd8086
    "  -P, --cddb-port=INT             CDDB port number to use (default 8880)\n"
Packit dd8086
    "  -H, --cddb-http                 Lookup CDDB via HTTP proxy (default no\n"
Packit dd8086
    "                                  proxy)\n"
Packit dd8086
    "  --cddb-server=STRING            CDDB server to contact for information\n"
Packit dd8086
    "                                  (default: freedb.freedb.org)\n"
Packit dd8086
    "  --cddb-cache=STRING             Location of CDDB cache directory\n"
Packit dd8086
    "                                  (default ~/.cddbclient)\n"
Packit dd8086
    "  --cddb-email=STRING             Email address to give CDDB server\n"
Packit dd8086
    "                                  (default me@home)\n"
Packit dd8086
    "  --no-cddb-cache                 Disable caching of CDDB entries\n"
Packit dd8086
    "                                  locally (default caches)\n"
Packit dd8086
    "  --cddb-timeout=INT              CDDB timeout value in seconds\n"
Packit dd8086
    "                                  (default 10 seconds)\n"
Packit dd8086
#else
Packit dd8086
    "  --no-cddb                       Does nothing since this program is not\n"
Packit dd8086
    "  -P, --cddb-port=INT             CDDB-enabled\n"
Packit dd8086
    "  -H, --cddb-http\n"
Packit dd8086
    "  --cddb-server=STRING\n"
Packit dd8086
    "  --cddb-cache=STRING\n"
Packit dd8086
    "  --cddb-email=STRING\n"
Packit dd8086
    "  --no-cddb-cache\n"
Packit dd8086
    "  --cddb-timeout=INT\n"
Packit dd8086
#endif
Packit dd8086
    "  --no-device-info                Don't show device info, just CD info\n"
Packit dd8086
    "  --no-disc-mode                  Don't show disc-mode info\n"
Packit dd8086
    "  --dvd                           Attempt to give DVD information if a DVD is\n"
Packit dd8086
    "                                  found.\n"
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
    "  -v, --no-vcd                    Don't look up Video CD information\n"
Packit dd8086
#else
Packit dd8086
    "  -v, --no-vcd                    Don't look up Video CD information - for\n"
Packit dd8086
    "                                  this build, this is always set\n"
Packit dd8086
#endif
Packit dd8086
    "  -I, --no-ioctl                  Don't show ioctl() information\n"
Packit dd8086
    "  -b, --bin-file[=FILE]           set \"bin\" CD-ROM disk image file as source\n"
Packit dd8086
    "  -c, --cue-file[=FILE]           set \"cue\" CD-ROM disk image file as source\n"
Packit dd8086
    "  -N, --nrg-file[=FILE]           set Nero CD-ROM disk image file as source\n"
Packit dd8086
    "  -t, --toc-file[=FILE]           set cdrdao CD-ROM disk image file as source\n"
Packit dd8086
    "  -i, --input[=FILE]              set source and determine if \"bin\" image or\n"
Packit dd8086
    "                                  device\n"
Packit dd8086
    "  --iso9660                       print directory contents of any ISO-9660\n"
Packit dd8086
    "                                  filesystems\n"
Packit dd8086
    "  -C, --cdrom-device[=DEVICE]     set CD-ROM device as source\n"
Packit dd8086
    "  -l, --list-drives               Give a list of CD-drives\n"
Packit dd8086
    "  --no-header                     Don't display header and copyright (for\n"
Packit dd8086
    "                                  regression testing)\n"
Packit dd8086
#ifdef HAVE_JOLIET
Packit dd8086
    "  --no-joliet                     Don't use Joliet extensions\n"
Packit dd8086
#endif
Packit dd8086
    "  --no-rock-ridge                 Don't use Rock-Ridge-extension information\n"
Packit dd8086
    "  --no-xa                         Don't use XA-extension information\n"
Packit dd8086
    "  -q, --quiet                     Don't produce warning output\n"
Packit dd8086
    "  -V, --version                   display version and copyright information\n"
Packit dd8086
    "                                  and exit\n"
Packit dd8086
    "\n"
Packit dd8086
    "Help options:\n"
Packit dd8086
    "  -?, --help                      Show this help message\n"
Packit dd8086
    "  --usage                         Display brief usage message\n";
Packit dd8086
Packit dd8086
  static const char usageText[] =
Packit dd8086
    "Usage: %s [-a|--access-mode STRING] [-d|--debug INT] [-T|--no-tracks]\n"
Packit dd8086
    "        [-A|--no-analyze] [--no-cddb] [-P|--cddb-port INT] [-H|--cddb-http]\n"
Packit dd8086
    "        [--cddb-server=STRING] [--cddb-cache=STRING] [--cddb-email=STRING]\n"
Packit dd8086
    "        [--no-cddb-cache] [--cddb-timeout=INT] [--no-device-info]\n"
Packit dd8086
    "        [--no-disc-mode] [--dvd] [-v|--no-vcd] [-I|--no-ioctl]\n"
Packit dd8086
    "        [-b|--bin-file FILE] [-c|--cue-file FILE] [-N|--nrg-file FILE]\n"
Packit dd8086
    "        [-t|--toc-file FILE] [-i|--input FILE] [--iso9660]\n"
Packit dd8086
    "        [-C|--cdrom-device DEVICE] [-l|--list-drives] [--no-header]\n"
Packit dd8086
    "        [--no-joliet] [--no-rock-ridge] [--no-xa] [-q|--quiet] [-V|--version]\n"
Packit dd8086
    "        [-?|--help] [--usage]\n";
Packit dd8086
Packit dd8086
  static const char optionsString[] = "a:d:TAP:HvIb::c::N::t::i::C::lqV?";
Packit dd8086
  static const struct option optionsTable[] = {
Packit dd8086
    {"access-mode", required_argument, NULL, 'a'},
Packit dd8086
    {"debug", required_argument, NULL, 'd' },
Packit dd8086
    {"no-tracks", no_argument, NULL, 'T' },
Packit dd8086
    {"no-analyze", no_argument, NULL, 'A' },
Packit dd8086
    {"no-cddb", no_argument, &opts.no_cddb, 1 },
Packit dd8086
    {"cddb-port", required_argument, NULL, 'P' },
Packit dd8086
    {"cddb-http", no_argument, NULL, 'H' },
Packit dd8086
    {"cddb-server", required_argument, NULL, OP_CDDB_SERVER },
Packit dd8086
    {"cddb-cache", required_argument, NULL, OP_CDDB_CACHE },
Packit dd8086
    {"cddb-email", required_argument, NULL, OP_CDDB_EMAIL },
Packit dd8086
    {"no-cddb-cache", no_argument, NULL, OP_CDDB_NOCACHE },
Packit dd8086
    {"cddb-timeout", required_argument, NULL, OP_CDDB_TIMEOUT },
Packit dd8086
    {"no-device-info", no_argument, &opts.no_device, 1 },
Packit dd8086
    {"no-disc-mode", no_argument, &opts.no_disc_mode, 1 },
Packit dd8086
    {"dvd", no_argument, &opts.show_dvd, 1 },
Packit dd8086
    {"no-vcd", no_argument, NULL, 'v' },
Packit dd8086
    {"no-ioctl", no_argument, NULL, 'I' },
Packit dd8086
    {"bin-file", optional_argument, NULL, 'b' },
Packit dd8086
    {"cue-file", optional_argument, NULL, 'c' },
Packit dd8086
    {"nrg-file", optional_argument, NULL, 'N' },
Packit dd8086
    {"toc-file", optional_argument, NULL, 't' },
Packit dd8086
    {"input", optional_argument, NULL, 'i' },
Packit dd8086
    {"iso9660", no_argument, &opts.print_iso9660, 1 },
Packit dd8086
    {"cdrom-device", optional_argument, NULL, 'C' },
Packit dd8086
    {"list-drives", no_argument, NULL, 'l' },
Packit dd8086
    {"no-header", no_argument, &opts.no_header, 1 },
Packit dd8086
#ifdef HAVE_JOLIET
Packit dd8086
    {"no-joliet", no_argument, &opts.no_joliet, 1 },
Packit dd8086
#endif /*HAVE_JOLIET*/
Packit dd8086
    {"no-rock-ridge", no_argument, &opts.no_rock_ridge, 1 },
Packit dd8086
    {"no-xa", no_argument, &opts.no_xa, 1 },
Packit dd8086
    {"quiet", no_argument, NULL, 'q' },
Packit dd8086
    {"version", no_argument, NULL, 'V' },
Packit dd8086
Packit dd8086
    {"help", no_argument, NULL, '?' },
Packit dd8086
    {"usage", no_argument, NULL, OP_USAGE },
Packit dd8086
    { NULL, 0, NULL, 0 }
Packit dd8086
  };
Packit dd8086
Packit dd8086
  program_name = strrchr(argv[0],'/');
Packit dd8086
  program_name = program_name ? strdup(program_name+1) : strdup(argv[0]);
Packit dd8086
Packit dd8086
  while ((opt = getopt_long(argc, argv, optionsString, optionsTable, NULL)) >= 0) {
Packit dd8086
    switch (opt) {
Packit dd8086
    case 'a': opts.access_mode = strdup(optarg); break;
Packit dd8086
    case 'd': opts.debug_level = atoi(optarg); break;
Packit dd8086
    case 'T': opts.no_tracks = 1; break;
Packit dd8086
    case 'A': opts.no_analysis = 1; break;
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
    case 'P': cddb_opts.port = atoi(optarg); break;
Packit dd8086
    case 'H': cddb_opts.http = 1; break;
Packit dd8086
    case OP_CDDB_SERVER: cddb_opts.server = strdup(optarg); break;
Packit dd8086
    case OP_CDDB_CACHE: cddb_opts.cachedir = strdup(optarg); break;
Packit dd8086
    case OP_CDDB_EMAIL: cddb_opts.email = strdup(optarg); break;
Packit dd8086
    case OP_CDDB_NOCACHE: cddb_opts.disable_cache = 1; break;
Packit dd8086
    case OP_CDDB_TIMEOUT: cddb_opts.timeout = atoi(optarg); break;
Packit dd8086
#endif
Packit dd8086
    case 'v': opts.no_vcd = 1; break;
Packit dd8086
    case 'I': opts.no_ioctl = 1; break;
Packit dd8086
    case 'b': parse_source(OP_SOURCE_BIN); break;
Packit dd8086
    case 'c': parse_source(OP_SOURCE_CUE); break;
Packit dd8086
    case 'N': parse_source(OP_SOURCE_NRG); break;
Packit dd8086
    case 't': parse_source(OP_SOURCE_CDRDAO); break;
Packit dd8086
    case 'i': parse_source(OP_SOURCE_AUTO); break;
Packit dd8086
    case 'C': parse_source(OP_SOURCE_DEVICE); break;
Packit dd8086
    case 'l': opts.list_drives = 1; break;
Packit dd8086
    case 'q': opts.silent = 1; break;
Packit dd8086
    case 'V': opts.version_only = 1; break;
Packit dd8086
Packit dd8086
    case '?':
Packit dd8086
      fprintf(stdout, helpText, program_name);
Packit dd8086
      rc = EXIT_INFO;
Packit dd8086
      goto error_exit;
Packit dd8086
Packit dd8086
    case OP_USAGE:
Packit dd8086
      fprintf(stderr, usageText, program_name);
Packit dd8086
      rc = EXIT_INFO;
Packit dd8086
      goto error_exit;
Packit dd8086
Packit dd8086
    case OP_HANDLED:
Packit dd8086
      break;
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (optind < argc) {
Packit dd8086
    const char *remaining_arg = argv[optind++];
Packit dd8086
Packit dd8086
    if (source_name != NULL) {
Packit dd8086
      report(stderr, "%s: Source '%s' given as an argument of an option and as "
Packit dd8086
             "unnamed option '%s'\n",
Packit dd8086
             program_name, source_name, remaining_arg);
Packit dd8086
      goto error_exit;
Packit dd8086
    }
Packit dd8086
Packit dd8086
    if (opts.source_image == INPUT_DEVICE)
Packit dd8086
      source_name = fillout_device_name(remaining_arg);
Packit dd8086
    else
Packit dd8086
      source_name = strdup(remaining_arg);
Packit dd8086
Packit dd8086
    if (optind < argc) {
Packit dd8086
      report(stderr, "%s: Source specified in previously %s and %s\n",
Packit dd8086
             program_name, source_name, remaining_arg);
Packit dd8086
      free(source_name);
Packit dd8086
      goto error_exit;
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  return true;
Packit dd8086
 error_exit:
Packit dd8086
  free(program_name);
Packit dd8086
  exit(rc);
Packit dd8086
}
Packit dd8086
Packit dd8086
/* CDIO logging routines */
Packit dd8086
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
static cddb_log_handler_t gl_default_cddb_log_handler = NULL;
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
static vcd_log_handler_t gl_default_vcd_log_handler = NULL;
Packit dd8086
#endif
Packit dd8086
Packit dd8086
static void
Packit dd8086
_log_handler (cdio_log_level_t level, const char message[])
Packit dd8086
{
Packit dd8086
  if (level == CDIO_LOG_DEBUG && opts.debug_level < 2)
Packit dd8086
    return;
Packit dd8086
Packit dd8086
  if (level == CDIO_LOG_INFO  && opts.debug_level < 1)
Packit dd8086
    return;
Packit dd8086
Packit dd8086
  if (level == CDIO_LOG_WARN  && opts.silent)
Packit dd8086
    return;
Packit dd8086
Packit dd8086
  gl_default_cdio_log_handler (level, message);
Packit dd8086
}
Packit dd8086
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
static void
Packit dd8086
_cddb_log_handler (cddb_log_level_t level, const char message[])
Packit dd8086
{
Packit dd8086
  /* CDDB errors should not be considered fatal. */
Packit dd8086
  if (level == (cddb_log_level_t) CDDB_LOG_ERROR)
Packit dd8086
    level = (cddb_log_level_t) CDIO_LOG_WARN;
Packit dd8086
Packit dd8086
  /* Might consider doing some sort of CDDB to cdio to log level conversion,
Packit dd8086
     but right now it's a no op. */
Packit dd8086
Packit dd8086
  _log_handler((cdio_log_level_t) level, message);
Packit dd8086
}
Packit dd8086
#endif
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_cdtext_track_info(cdtext_t *p_cdtext, track_t i_track, const char *psz_msg) {
Packit dd8086
Packit dd8086
  if (NULL != p_cdtext) {
Packit dd8086
    cdtext_field_t i;
Packit dd8086
Packit dd8086
    printf("%s\n", psz_msg);
Packit dd8086
Packit dd8086
    for (i=0; i < MAX_CDTEXT_FIELDS; i++) {
Packit dd8086
      if (cdtext_get_const(p_cdtext, i, i_track)) {
Packit dd8086
        printf("\t%s: %s\n", cdtext_field2str(i), cdtext_get_const(p_cdtext, i, i_track));
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_cdtext_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track) {
Packit dd8086
  track_t i_last_track = i_first_track+i_tracks;
Packit dd8086
  cdtext_t *p_cdtext = cdio_get_cdtext(p_cdio);
Packit dd8086
  cdtext_lang_t *languages;
Packit dd8086
  cdtext_genre_t genre;
Packit dd8086
Packit dd8086
  int i, j;
Packit dd8086
Packit dd8086
  if(NULL == p_cdtext) {
Packit dd8086
    printf("No CD-TEXT on Disc.\n");
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  languages = cdtext_list_languages(p_cdtext);
Packit dd8086
  for(i=0; i<8; i++)
Packit dd8086
    if ( CDTEXT_LANGUAGE_UNKNOWN != languages[i]
Packit dd8086
         && cdtext_select_language(p_cdtext, languages[i]))
Packit dd8086
    {
Packit dd8086
      printf("\nLanguage %d '%s':\n", i, cdtext_lang2str(languages[i]));
Packit dd8086
Packit dd8086
      print_cdtext_track_info(p_cdtext, 0, "CD-TEXT for Disc:");
Packit dd8086
      genre = cdtext_get_genre(p_cdtext);
Packit dd8086
      if ( CDTEXT_GENRE_UNUSED != genre)
Packit dd8086
        printf("\tGENRE_CODE: %d (%s)\n", genre, cdtext_genre2str(genre));
Packit dd8086
Packit dd8086
      for ( j = i_first_track ; j < i_last_track; j++ ) {
Packit dd8086
        char msg[50];
Packit dd8086
        sprintf(msg, "CD-TEXT for Track %2d:", j);
Packit dd8086
        print_cdtext_track_info(p_cdtext, j, msg);
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
}
Packit dd8086
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
Packit dd8086
static void
Packit dd8086
cddb_errmsg(const char *msg)
Packit dd8086
{
Packit dd8086
  report(stderr, "%s: %s\n", program_name, msg);
Packit dd8086
}
Packit dd8086
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_cddb_info(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track)
Packit dd8086
{
Packit dd8086
  int i, i_cddb_matches = 0;
Packit dd8086
Packit dd8086
  cddb_conn_t *p_conn = NULL;
Packit dd8086
  cddb_disc_t *p_cddb_disc = NULL;
Packit dd8086
Packit dd8086
  if ( init_cddb(p_cdio, &p_conn, &p_cddb_disc, cddb_errmsg, i_first_track,
Packit dd8086
                 i_tracks, &i_cddb_matches) ) {
Packit dd8086
Packit dd8086
    if (-1 == i_cddb_matches)
Packit dd8086
      printf("%s: %s\n", program_name, cddb_error_str(cddb_errno(p_conn)));
Packit dd8086
    else {
Packit dd8086
      printf("%s: Found %d matches in CDDB\n", program_name, i_cddb_matches);
Packit dd8086
      for (i=1; i<=i_cddb_matches; i++) {
Packit dd8086
        cddb_disc_print(p_cddb_disc);
Packit dd8086
        cddb_query_next(p_conn, p_cddb_disc);
Packit dd8086
        if (i != i_cddb_matches) cddb_read(p_conn, p_cddb_disc);
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
    cddb_disc_destroy(p_cddb_disc);
Packit dd8086
    cddb_destroy(p_conn);
Packit dd8086
    libcddb_shutdown();
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
static void
Packit dd8086
print_vcd_info(driver_id_t driver) {
Packit dd8086
  vcdinfo_open_return_t open_rc;
Packit dd8086
  vcdinfo_obj_t *p_vcd = NULL;
Packit dd8086
  open_rc = vcdinfo_open(&p_vcd, &source_name, driver, NULL);
Packit dd8086
  switch (open_rc) {
Packit dd8086
  case VCDINFO_OPEN_VCD:
Packit dd8086
    if (vcdinfo_get_format_version (p_vcd) == VCD_TYPE_INVALID) {
Packit dd8086
      report(stderr, "VCD format detection failed");
Packit dd8086
      vcdinfo_close(p_vcd);
Packit dd8086
      return;
Packit dd8086
    }
Packit dd8086
    report (stdout, "Format       : %s\n",
Packit dd8086
            vcdinfo_get_format_version_str(p_vcd));
Packit dd8086
    report (stdout, "Album        : `%.16s'\n",  vcdinfo_get_album_id(p_vcd));
Packit dd8086
    report (stdout, "Volume count : %d\n",   vcdinfo_get_volume_count(p_vcd));
Packit dd8086
    report (stdout, "volume number: %d\n",   vcdinfo_get_volume_num(p_vcd));
Packit dd8086
Packit dd8086
    break;
Packit dd8086
  case VCDINFO_OPEN_ERROR:
Packit dd8086
    report( stderr, "Error in Video CD opening of %s\n", source_name );
Packit dd8086
    break;
Packit dd8086
  case VCDINFO_OPEN_OTHER:
Packit dd8086
    report( stderr, "Even though we thought this was a Video CD, "
Packit dd8086
            " further inspection says it is not.\n" );
Packit dd8086
    break;
Packit dd8086
  }
Packit dd8086
  if (p_vcd) vcdinfo_close(p_vcd);
Packit dd8086
Packit dd8086
}
Packit dd8086
#endif
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_iso9660_recurse (CdIo_t *p_cdio, const char pathname[],
Packit dd8086
                       cdio_fs_anal_t fs)
Packit dd8086
{
Packit dd8086
  CdioISO9660FileList_t *p_entlist;
Packit dd8086
  CdioISO9660DirList_t *p_dirlist = iso9660_dirlist_new();
Packit dd8086
  CdioListNode_t *entnode;
Packit dd8086
  uint8_t i_joliet_level;
Packit dd8086
  char *translated_name = (char *) alloca(4096);
Packit dd8086
  size_t translated_name_size = 4096;
Packit dd8086
Packit dd8086
  i_joliet_level = (opts.no_joliet)
Packit dd8086
    ? 0
Packit dd8086
    : cdio_get_joliet_level(p_cdio);
Packit dd8086
Packit dd8086
  p_entlist = iso9660_fs_readdir(p_cdio, pathname);
Packit dd8086
Packit dd8086
  printf ("%s:\n", pathname);
Packit dd8086
Packit dd8086
  if (NULL == p_entlist) {
Packit dd8086
    report( stderr, "Error getting above directory information\n" );
Packit dd8086
    iso9660_dirlist_free(p_dirlist);
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  /* Iterate over files in this directory */
Packit dd8086
Packit dd8086
  _CDIO_LIST_FOREACH (entnode, p_entlist)
Packit dd8086
    {
Packit dd8086
      iso9660_stat_t *p_statbuf = _cdio_list_node_data (entnode);
Packit dd8086
      char *psz_iso_name = p_statbuf->filename;
Packit dd8086
      char _fullname[4096] = { 0, };
Packit dd8086
       if (strlen(psz_iso_name) >= translated_name_size) {
Packit dd8086
         translated_name_size = strlen(psz_iso_name)+1;
Packit dd8086
         if (!translated_name) {
Packit dd8086
           report( stderr, "Error allocating memory\n" );
Packit dd8086
	   iso9660_dirlist_free(p_dirlist);
Packit dd8086
           return;
Packit dd8086
         }
Packit dd8086
       }
Packit dd8086
Packit dd8086
      if (yep != p_statbuf->rr.b3_rock || 1 == opts.no_rock_ridge) {
Packit dd8086
        iso9660_name_translate_ext(psz_iso_name, translated_name,
Packit dd8086
                                   i_joliet_level);
Packit dd8086
      }
Packit dd8086
Packit dd8086
Packit dd8086
      snprintf (_fullname, sizeof (_fullname), "%s%s", pathname,
Packit dd8086
                psz_iso_name);
Packit dd8086
Packit dd8086
      strncat (_fullname, "/", sizeof(_fullname) - strlen(_fullname) - 1);
Packit dd8086
Packit dd8086
      if (p_statbuf->type == _STAT_DIR
Packit dd8086
          && strcmp (psz_iso_name, ".")
Packit dd8086
          && strcmp (psz_iso_name, ".."))
Packit dd8086
        _cdio_list_append (p_dirlist, strdup (_fullname));
Packit dd8086
Packit dd8086
      print_fs_attrs(p_statbuf, 0 == opts.no_rock_ridge, fs & CDIO_FS_ANAL_XA,
Packit dd8086
                     psz_iso_name, translated_name);
Packit dd8086
      if (p_statbuf->rr.i_symlink) {
Packit dd8086
        free(p_statbuf->rr.psz_symlink);
Packit dd8086
        p_statbuf->rr.i_symlink = 0;
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
  iso9660_filelist_free(p_entlist);
Packit dd8086
Packit dd8086
  printf ("\n");
Packit dd8086
Packit dd8086
  /* Now recurse over the directories. */
Packit dd8086
Packit dd8086
  _CDIO_LIST_FOREACH (entnode, p_dirlist)
Packit dd8086
    {
Packit dd8086
      char *_fullname = _cdio_list_node_data (entnode);
Packit dd8086
Packit dd8086
      print_iso9660_recurse (p_cdio, _fullname, fs);
Packit dd8086
    }
Packit dd8086
Packit dd8086
  iso9660_dirlist_free(p_dirlist);
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_iso9660_fs (CdIo_t *p_cdio, cdio_fs_anal_t fs,
Packit dd8086
                  track_format_t track_format)
Packit dd8086
{
Packit dd8086
  iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
Packit dd8086
Packit dd8086
  if (opts.no_joliet) {
Packit dd8086
    iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if ( !iso9660_fs_read_superblock(p_cdio, iso_extension_mask) )
Packit dd8086
    return;
Packit dd8086
Packit dd8086
  printf ("ISO9660 filesystem\n");
Packit dd8086
  print_iso9660_recurse (p_cdio, "/", fs);
Packit dd8086
}
Packit dd8086
Packit dd8086
#define print_vd_info(title, fn)                \
Packit dd8086
  psz_str = fn(&pvd);                           \
Packit dd8086
  if (psz_str) {                                \
Packit dd8086
    report(stdout, title ": %s\n", psz_str);    \
Packit dd8086
    free(psz_str);                              \
Packit dd8086
    psz_str = NULL;                             \
Packit dd8086
  }
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_analysis(int ms_offset, cdio_iso_analysis_t cdio_iso_analysis,
Packit dd8086
               cdio_fs_anal_t fs, int first_data, unsigned int num_audio,
Packit dd8086
               track_t i_tracks, track_t i_first_track,
Packit dd8086
               track_format_t track_format, CdIo_t *p_cdio)
Packit dd8086
{
Packit dd8086
  int need_lf;
Packit dd8086
Packit dd8086
  switch(CDIO_FSTYPE(fs)) {
Packit dd8086
  case CDIO_FS_AUDIO:
Packit dd8086
    if (num_audio > 0) {
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
      if (!opts.no_cddb) {
Packit dd8086
        printf("Audio CD, CDDB disc ID is %08x\n",
Packit dd8086
               cddb_discid(p_cdio, i_tracks));
Packit dd8086
        print_cddb_info(p_cdio, i_tracks, i_first_track);
Packit dd8086
      }
Packit dd8086
#endif
Packit dd8086
      print_cdtext_info(p_cdio, i_tracks, i_first_track);
Packit dd8086
    }
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_ISO_9660:
Packit dd8086
    printf("CD-ROM with ISO 9660 filesystem");
Packit dd8086
    if (fs & CDIO_FS_ANAL_JOLIET) {
Packit dd8086
      printf(" and joliet extension level %d", cdio_iso_analysis.joliet_level);
Packit dd8086
    }
Packit dd8086
    if (fs & CDIO_FS_ANAL_ROCKRIDGE)
Packit dd8086
      printf(" and rockridge extensions");
Packit dd8086
    printf("\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_ISO_9660_INTERACTIVE:
Packit dd8086
    printf("CD-ROM with CD-RTOS and ISO 9660 filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_HIGH_SIERRA:
Packit dd8086
    printf("CD-ROM with High Sierra filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_INTERACTIVE:
Packit dd8086
    printf("CD-Interactive%s\n", num_audio > 0 ? "/Ready" : "");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_HFS:
Packit dd8086
    printf("CD-ROM with Macintosh HFS\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_ISO_HFS:
Packit dd8086
    printf("CD-ROM with both Macintosh HFS and ISO 9660 filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_UFS:
Packit dd8086
    printf("CD-ROM with Unix UFS\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_EXT2:
Packit dd8086
    printf("CD-ROM with GNU/Linux EXT2 (native) filesystem\n");
Packit dd8086
          break;
Packit dd8086
  case CDIO_FS_3DO:
Packit dd8086
    printf("CD-ROM with Panasonic 3DO filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_UDFX:
Packit dd8086
    printf("CD-ROM with UDFX filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_UNKNOWN:
Packit dd8086
    printf("CD-ROM with unknown filesystem\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_FS_XISO:
Packit dd8086
    printf("CD-ROM with Microsoft X-BOX XISO filesystem\n");
Packit dd8086
    break;
Packit dd8086
  }
Packit dd8086
  switch(CDIO_FSTYPE(fs)) {
Packit dd8086
  case CDIO_FS_ISO_9660:
Packit dd8086
  case CDIO_FS_ISO_9660_INTERACTIVE:
Packit dd8086
  case CDIO_FS_ISO_HFS:
Packit dd8086
  case CDIO_FS_ISO_UDF:
Packit dd8086
    printf("ISO 9660: %i blocks, label `%.32s'\n",
Packit dd8086
           cdio_iso_analysis.isofs_size, cdio_iso_analysis.iso_label);
Packit dd8086
Packit dd8086
    {
Packit dd8086
      iso9660_pvd_t pvd;
Packit dd8086
Packit dd8086
      if ( iso9660_fs_read_pvd(p_cdio, &pvd) ) {
Packit dd8086
        char *psz_str;
Packit dd8086
        print_vd_info("Application", iso9660_get_application_id);
Packit dd8086
        print_vd_info("Preparer   ", iso9660_get_preparer_id);
Packit dd8086
        print_vd_info("Publisher  ", iso9660_get_publisher_id);
Packit dd8086
        print_vd_info("System     ", iso9660_get_system_id);
Packit dd8086
        print_vd_info("Volume     ", iso9660_get_volume_id);
Packit dd8086
        print_vd_info("Volume Set ", iso9660_get_volumeset_id);
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
    if (opts.print_iso9660)
Packit dd8086
      print_iso9660_fs(p_cdio, fs, track_format);
Packit dd8086
Packit dd8086
    break;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  switch(CDIO_FSTYPE(fs)) {
Packit dd8086
  case CDIO_FS_UDF:
Packit dd8086
  case CDIO_FS_ISO_UDF:
Packit dd8086
    report(stdout, "UDF: version %x.%2.2x\n",
Packit dd8086
           cdio_iso_analysis.UDFVerMajor, cdio_iso_analysis.UDFVerMinor);
Packit dd8086
    break;
Packit dd8086
  default: ;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  need_lf = 0;
Packit dd8086
  if (first_data == 1 && num_audio > 0)
Packit dd8086
    need_lf += printf("mixed mode CD   ");
Packit dd8086
  if (fs & CDIO_FS_ANAL_XA)
Packit dd8086
    need_lf += printf("XA sectors   ");
Packit dd8086
  if (fs & CDIO_FS_ANAL_MULTISESSION)
Packit dd8086
    need_lf += printf("Multisession, offset = %i   ", ms_offset);
Packit dd8086
  if (fs & CDIO_FS_ANAL_HIDDEN_TRACK)
Packit dd8086
    need_lf += printf("Hidden Track   ");
Packit dd8086
  if (fs & CDIO_FS_ANAL_PHOTO_CD)
Packit dd8086
    need_lf += printf("%sPhoto CD   ",
Packit dd8086
                      num_audio > 0 ? " Portfolio " : "");
Packit dd8086
  if (fs & CDIO_FS_ANAL_CDTV)
Packit dd8086
    need_lf += printf("Commodore CDTV   ");
Packit dd8086
  if (first_data > 1)
Packit dd8086
    need_lf += printf("CD-Plus/Extra   ");
Packit dd8086
  if (fs & CDIO_FS_ANAL_BOOTABLE)
Packit dd8086
    need_lf += printf("bootable CD   ");
Packit dd8086
  if (fs & CDIO_FS_ANAL_VIDEOCD && num_audio == 0) {
Packit dd8086
    need_lf += printf("Video CD   ");
Packit dd8086
  }
Packit dd8086
  if (fs & CDIO_FS_ANAL_SVCD)
Packit dd8086
    need_lf += printf("Super Video CD (SVCD) or Chaoji Video CD (CVD)");
Packit dd8086
  if (fs & CDIO_FS_ANAL_CVD)
Packit dd8086
    need_lf += printf("Chaoji Video CD (CVD)");
Packit dd8086
  if (need_lf) printf("\n");
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
  if (fs & (CDIO_FS_ANAL_VIDEOCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_SVCD))
Packit dd8086
    if (!opts.no_vcd) {
Packit dd8086
      printf("\n");
Packit dd8086
      print_vcd_info(cdio_get_driver_id(p_cdio));
Packit dd8086
    }
Packit dd8086
#endif
Packit dd8086
Packit dd8086
}
Packit dd8086
Packit dd8086
/* Initialize global variables. */
Packit dd8086
static void
Packit dd8086
init(void)
Packit dd8086
{
Packit dd8086
  gl_default_cdio_log_handler = cdio_log_set_handler (_log_handler);
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
  gl_default_cddb_log_handler =
Packit dd8086
    cddb_log_set_handler ((cddb_log_handler_t) _cddb_log_handler);
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
  gl_default_vcd_log_handler =
Packit dd8086
    vcd_log_set_handler ((vcd_log_handler_t) _log_handler);
Packit dd8086
#endif
Packit dd8086
Packit dd8086
  /* Default option values. */
Packit dd8086
  opts.silent        = false;
Packit dd8086
  opts.list_drives   = false;
Packit dd8086
  opts.no_header     = false;
Packit dd8086
  opts.no_joliet     = 0;
Packit dd8086
  opts.no_rock_ridge = 0;
Packit dd8086
  opts.no_xa         = 0;
Packit dd8086
  opts.no_device     = 0;
Packit dd8086
  opts.no_disc_mode  = 0;
Packit dd8086
  opts.debug_level   = 0;
Packit dd8086
  opts.no_tracks     = 0;
Packit dd8086
  opts.print_iso9660 = 0;
Packit dd8086
#ifdef HAVE_CDDB
Packit dd8086
  opts.no_cddb       = 0;
Packit dd8086
  cddb_opts.port     = 8880;
Packit dd8086
  cddb_opts.http     = 0;
Packit dd8086
  cddb_opts.cachedir = NULL;
Packit dd8086
  cddb_opts.server   = NULL;
Packit dd8086
  cddb_opts.timeout  = -1;
Packit dd8086
  cddb_opts.disable_cache = false;
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
  opts.no_vcd        = 0;
Packit dd8086
#else
Packit dd8086
  opts.no_vcd        = 1;
Packit dd8086
#endif
Packit dd8086
  opts.no_ioctl      = 0;
Packit dd8086
  opts.no_analysis   = 0;
Packit dd8086
  opts.source_image  = INPUT_UNKNOWN;
Packit dd8086
  opts.access_mode   = NULL;
Packit dd8086
}
Packit dd8086
Packit dd8086
/* ------------------------------------------------------------------------ */
Packit dd8086
Packit dd8086
int
Packit dd8086
main(int argc, char *argv[])
Packit dd8086
{
Packit dd8086
Packit dd8086
  CdIo_t                *p_cdio=NULL;
Packit dd8086
  cdio_fs_anal_t         fs = CDIO_FS_AUDIO;
Packit dd8086
  int i;
Packit dd8086
  lsn_t                  start_track_lsn;      /* lsn of first track */
Packit dd8086
  lsn_t                  data_start     =  0;  /* start of data area */
Packit dd8086
  int                    ms_offset      =  0;
Packit dd8086
  track_t                i_tracks       =  0;
Packit dd8086
  track_t                i_first_track  =  0;
Packit dd8086
  unsigned int           num_audio      =  0;  /* # of audio tracks */
Packit dd8086
  unsigned int           num_data       =  0;  /* # of data tracks */
Packit dd8086
  int                    first_data     = -1;  /* # of first data track */
Packit dd8086
  int                    first_audio    = -1;  /* # of first audio track */
Packit dd8086
  bool                   b_playing_audio = false; /* currently playing a
Packit dd8086
                                                     CD-DA */
Packit dd8086
  cdio_iso_analysis_t    cdio_iso_analysis;
Packit dd8086
  char                  *media_catalog_number;
Packit dd8086
  char                  *isrc;
Packit dd8086
  discmode_t             discmode = CDIO_DISC_MODE_NO_INFO;
Packit dd8086
  cdio_drive_read_cap_t  i_read_cap = 0;
Packit dd8086
  cdio_drive_write_cap_t i_write_cap;
Packit dd8086
  cdio_drive_misc_cap_t  i_misc_cap;
Packit dd8086
Packit dd8086
  memset(&cdio_iso_analysis, 0, sizeof(cdio_iso_analysis));
Packit dd8086
  init();
Packit dd8086
Packit dd8086
  /* Parse our arguments; every option seen by `parse_opt' will
Packit dd8086
     be reflected in `arguments'. */
Packit dd8086
  parse_options(argc, argv);
Packit dd8086
Packit dd8086
  print_version(program_name, CDIO_VERSION, opts.no_header, opts.version_only);
Packit dd8086
Packit dd8086
  if (opts.debug_level == 3) {
Packit dd8086
    cdio_loglevel_default = CDIO_LOG_INFO;
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
    vcd_loglevel_default = VCD_LOG_INFO;
Packit dd8086
#endif
Packit dd8086
  } else if (opts.debug_level >= 4) {
Packit dd8086
    cdio_loglevel_default = CDIO_LOG_DEBUG;
Packit dd8086
#ifdef HAVE_VCDINFO
Packit dd8086
    vcd_loglevel_default = VCD_LOG_DEBUG;
Packit dd8086
#endif
Packit dd8086
  }
Packit dd8086
Packit dd8086
  p_cdio = open_input(source_name, opts.source_image, opts.access_mode);
Packit dd8086
Packit dd8086
  if (p_cdio==NULL) {
Packit dd8086
    if (source_name) {
Packit dd8086
      err_exit("%s: Error in opening device driver for input %s.\n",
Packit dd8086
               program_name, source_name);
Packit dd8086
    } else {
Packit dd8086
      err_exit("%s: Error in opening device driver for unspecified input.\n",
Packit dd8086
               program_name);
Packit dd8086
    }
Packit dd8086
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (source_name==NULL) {
Packit dd8086
    source_name=strdup(cdio_get_arg(p_cdio, "source"));
Packit dd8086
    if (NULL == source_name) {
Packit dd8086
      err_exit("%s: No input device given/found\n", program_name);
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (0 == opts.silent) {
Packit dd8086
    printf("CD location   : %s\n",   source_name);
Packit dd8086
    printf("CD driver name: %s\n",   cdio_get_driver_name(p_cdio));
Packit dd8086
    printf("   access mode: %s\n\n", cdio_get_arg(p_cdio, "access-mode"));
Packit dd8086
  }
Packit dd8086
Packit dd8086
  cdio_get_drive_cap(p_cdio, &i_read_cap, &i_write_cap, &i_misc_cap);
Packit dd8086
  if (0 == opts.no_device) {
Packit dd8086
    cdio_hwinfo_t          hwinfo;
Packit dd8086
    if (cdio_get_hwinfo(p_cdio, &hwinfo)) {
Packit dd8086
      printf("%-28s: %s\n%-28s: %s\n%-28s: %s\n",
Packit dd8086
             "Vendor"  , hwinfo.psz_vendor,
Packit dd8086
             "Model"   , hwinfo.psz_model,
Packit dd8086
             "Revision", hwinfo.psz_revision);
Packit dd8086
    }
Packit dd8086
    print_drive_capabilities(i_read_cap, i_write_cap, i_misc_cap);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (opts.list_drives) {
Packit dd8086
    driver_id_t driver_id = DRIVER_DEVICE;
Packit dd8086
    char ** device_list = cdio_get_devices_ret(&driver_id);
Packit dd8086
    char ** d = device_list;
Packit dd8086
Packit dd8086
    printf("list of devices found:\n");
Packit dd8086
    if (NULL != d) {
Packit dd8086
      for ( ; *d != NULL ; d++ ) {
Packit dd8086
        CdIo_t *p_cdio_d = cdio_open(*d, driver_id);
Packit dd8086
        cdio_hwinfo_t hwinfo;
Packit dd8086
        printf("Drive %s\n", *d);
Packit dd8086
        if (mmc_get_hwinfo(p_cdio_d, &hwinfo)) {
Packit dd8086
          printf("%-8s: %s\n%-8s: %s\n%-8s: %s\n",
Packit dd8086
                 "Vendor"  , hwinfo.psz_vendor,
Packit dd8086
                 "Model"   , hwinfo.psz_model,
Packit dd8086
                 "Revision", hwinfo.psz_revision);
Packit dd8086
        }
Packit dd8086
        if (p_cdio_d) cdio_destroy(p_cdio_d);
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
    cdio_free_device_list(device_list);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  report(stdout, STRONG "\n");
Packit dd8086
Packit dd8086
Packit dd8086
  discmode = cdio_get_discmode(p_cdio);
Packit dd8086
  if ( 0 == opts.no_disc_mode ) {
Packit dd8086
    printf("Disc mode is listed as: %s\n",
Packit dd8086
           discmode2str[discmode]);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (cdio_is_discmode_dvd(discmode) && !opts.show_dvd) {
Packit dd8086
    printf("No further information currently given for DVDs.\n");
Packit dd8086
    printf("Use --dvd to override.\n");
Packit dd8086
    myexit(p_cdio, EXIT_SUCCESS);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  i_first_track = cdio_get_first_track_num(p_cdio);
Packit dd8086
Packit dd8086
  if (CDIO_INVALID_TRACK == i_first_track) {
Packit dd8086
    err_exit("Can't get first track number. I give up%s.\n", "");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  i_tracks = cdio_get_num_tracks(p_cdio);
Packit dd8086
Packit dd8086
  if (CDIO_INVALID_TRACK == i_tracks) {
Packit dd8086
    err_exit("Can't get number of tracks. I give up.%s\n", "");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (!opts.no_tracks) {
Packit dd8086
    printf("CD-ROM Track List (%i - %i)\n" NORMAL,
Packit dd8086
           i_first_track, i_tracks);
Packit dd8086
Packit dd8086
    printf("  #: MSF       LSN    Type   Green? Copy?");
Packit dd8086
    if ( CDIO_DISC_MODE_CD_DA == discmode
Packit dd8086
         || CDIO_DISC_MODE_CD_MIXED == discmode )
Packit dd8086
      printf(" Channels Premphasis?");
Packit dd8086
    printf("\n");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  start_track_lsn = cdio_get_track_lsn(p_cdio, i_first_track);
Packit dd8086
Packit dd8086
  /* Read and possibly print track information. */
Packit dd8086
  for (i = i_first_track; i <= CDIO_CDROM_LEADOUT_TRACK; i++) {
Packit dd8086
    msf_t msf;
Packit dd8086
    char *psz_msf;
Packit dd8086
    track_format_t track_format;
Packit dd8086
Packit dd8086
    if (!cdio_get_track_msf(p_cdio, i, &msf)) {
Packit dd8086
      err_exit("cdio_track_msf for track %i failed, I give up.\n", i);
Packit dd8086
    }
Packit dd8086
Packit dd8086
    track_format = cdio_get_track_format(p_cdio, i);
Packit dd8086
    psz_msf = cdio_msf_to_str(&msf;;
Packit dd8086
    if (i == CDIO_CDROM_LEADOUT_TRACK) {
Packit dd8086
      if (!opts.no_tracks) {
Packit dd8086
        lsn_t lsn= cdio_msf_to_lsn(&msf;;
Packit dd8086
        long unsigned int i_bytes_raw = lsn * CDIO_CD_FRAMESIZE_RAW;
Packit dd8086
        long unsigned int i_bytes_formatted = lsn - start_track_lsn;
Packit dd8086
Packit dd8086
        printf( "%3d: %8s  %06lu leadout ", (int) i, psz_msf,
Packit dd8086
                (long unsigned int) lsn );
Packit dd8086
Packit dd8086
        switch (discmode) {
Packit dd8086
        case CDIO_DISC_MODE_DVD_ROM:
Packit dd8086
        case CDIO_DISC_MODE_DVD_RAM:
Packit dd8086
        case CDIO_DISC_MODE_DVD_R:
Packit dd8086
        case CDIO_DISC_MODE_DVD_RW:
Packit dd8086
        case CDIO_DISC_MODE_DVD_PR:
Packit dd8086
        case CDIO_DISC_MODE_DVD_PRW:
Packit dd8086
        case CDIO_DISC_MODE_DVD_OTHER:
Packit dd8086
        case CDIO_DISC_MODE_CD_DATA:
Packit dd8086
          i_bytes_formatted *= CDIO_CD_FRAMESIZE;
Packit dd8086
          break;
Packit dd8086
        case CDIO_DISC_MODE_CD_DA:
Packit dd8086
          i_bytes_formatted *= CDIO_CD_FRAMESIZE_RAW;
Packit dd8086
          break;
Packit dd8086
        case CDIO_DISC_MODE_CD_XA:
Packit dd8086
        case CDIO_DISC_MODE_CD_MIXED:
Packit dd8086
          i_bytes_formatted *= CDIO_CD_FRAMESIZE_RAW0;
Packit dd8086
          break;
Packit dd8086
        default:
Packit dd8086
          i_bytes_formatted *= CDIO_CD_FRAMESIZE_RAW;
Packit dd8086
        }
Packit dd8086
Packit dd8086
        if (i_bytes_raw < 1024)
Packit dd8086
          printf( "(%lu bytes", i_bytes_raw );
Packit dd8086
        if (i_bytes_raw < 1024 * 1024)
Packit dd8086
          printf( "(%lu KB", i_bytes_raw / 1024 );
Packit dd8086
        else
Packit dd8086
          printf( "(%lu MB", i_bytes_raw / (1024 * 1024) );
Packit dd8086
Packit dd8086
        printf(" raw, ");
Packit dd8086
        if (i_bytes_formatted < 1024)
Packit dd8086
          printf( "%lu bytes", i_bytes_formatted );
Packit dd8086
        if (i_bytes_formatted < 1024 * 1024)
Packit dd8086
          printf( "%lu KB", i_bytes_formatted / 1024 );
Packit dd8086
        else
Packit dd8086
          printf( "%lu MB", i_bytes_formatted / (1024 * 1024) );
Packit dd8086
Packit dd8086
        printf(" formatted)\n");
Packit dd8086
Packit dd8086
      }
Packit dd8086
      free(psz_msf);
Packit dd8086
      break;
Packit dd8086
    } else if (!opts.no_tracks) {
Packit dd8086
      const char *psz;
Packit dd8086
      printf( "%3d: %8s  %06lu %-6s %-5s  ", (int) i, psz_msf,
Packit dd8086
              (long unsigned int) cdio_msf_to_lsn(&msf),
Packit dd8086
              track_format2str[track_format],
Packit dd8086
              cdio_get_track_green(p_cdio, i)? "true " : "false");
Packit dd8086
Packit dd8086
      switch (cdio_get_track_copy_permit(p_cdio, i)) {
Packit dd8086
      case CDIO_TRACK_FLAG_FALSE:
Packit dd8086
        psz="no";
Packit dd8086
        break;
Packit dd8086
      case CDIO_TRACK_FLAG_TRUE:
Packit dd8086
        psz="yes";
Packit dd8086
        break;
Packit dd8086
      case CDIO_TRACK_FLAG_UNKNOWN:
Packit dd8086
        psz="?";
Packit dd8086
        break;
Packit dd8086
      case CDIO_TRACK_FLAG_ERROR:
Packit dd8086
      default:
Packit dd8086
        psz="error";
Packit dd8086
        break;
Packit dd8086
      }
Packit dd8086
      printf("%-5s", psz);
Packit dd8086
Packit dd8086
      if (TRACK_FORMAT_AUDIO == track_format) {
Packit dd8086
        const int i_channels = cdio_get_track_channels(p_cdio, i);
Packit dd8086
        switch (cdio_get_track_preemphasis(p_cdio, i)) {
Packit dd8086
        case CDIO_TRACK_FLAG_FALSE:
Packit dd8086
          psz="no";
Packit dd8086
          break;
Packit dd8086
        case CDIO_TRACK_FLAG_TRUE:
Packit dd8086
          psz="yes";
Packit dd8086
          break;
Packit dd8086
        case CDIO_TRACK_FLAG_UNKNOWN:
Packit dd8086
          psz="?";
Packit dd8086
          break;
Packit dd8086
        case CDIO_TRACK_FLAG_ERROR:
Packit dd8086
        default:
Packit dd8086
          psz="error";
Packit dd8086
          break;
Packit dd8086
        }
Packit dd8086
        if (i_channels == -2)
Packit dd8086
          printf(" %-8s", "unknown");
Packit dd8086
        else if (i_channels == -1)
Packit dd8086
          printf(" %-8s", "error");
Packit dd8086
        else
Packit dd8086
          printf(" %-8d", i_channels);
Packit dd8086
        printf( " %s", psz);
Packit dd8086
      }
Packit dd8086
Packit dd8086
      printf( "\n" );
Packit dd8086
Packit dd8086
    }
Packit dd8086
    free(psz_msf);
Packit dd8086
Packit dd8086
    if (TRACK_FORMAT_AUDIO == track_format) {
Packit dd8086
      num_audio++;
Packit dd8086
      if (-1 == first_audio) first_audio = i;
Packit dd8086
    } else {
Packit dd8086
      num_data++;
Packit dd8086
      if (-1 == first_data)  first_data = i;
Packit dd8086
    }
Packit dd8086
    /* skip to leadout? */
Packit dd8086
    if (i == i_tracks) i = CDIO_CDROM_LEADOUT_TRACK-1;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (cdio_is_discmode_cdrom(discmode)) {
Packit dd8086
    /* get and print MCN */
Packit dd8086
Packit dd8086
    report(stdout, "Media Catalog Number (MCN): "); fflush(stdout);
Packit dd8086
Packit dd8086
    media_catalog_number = cdio_get_mcn(p_cdio);
Packit dd8086
Packit dd8086
    if (NULL == media_catalog_number) {
Packit dd8086
      if (i_read_cap & CDIO_DRIVE_CAP_READ_MCN)
Packit dd8086
        report(stdout, "not available\n");
Packit dd8086
      else
Packit dd8086
        report(stdout, "not supported by drive/driver\n");
Packit dd8086
    } else {
Packit dd8086
      report(stdout, "%s\n", media_catalog_number);
Packit dd8086
      cdio_free(media_catalog_number);
Packit dd8086
    }
Packit dd8086
Packit dd8086
    /* get and print track ISRCs */
Packit dd8086
Packit dd8086
    if (i_read_cap & CDIO_DRIVE_CAP_READ_ISRC) {
Packit dd8086
      for (i = first_audio; i < first_audio + num_audio; i++) {
Packit dd8086
        isrc = cdio_get_track_isrc(p_cdio, i);
Packit dd8086
Packit dd8086
        if (NULL != isrc) {
Packit dd8086
          report(stdout, "TRACK %2d ISRC: %s\n", i, isrc); fflush(stdout);
Packit dd8086
          cdio_free(isrc);
Packit dd8086
        }
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
    /* List number of sessions */
Packit dd8086
    {
Packit dd8086
      lsn_t i_last_session;
Packit dd8086
      report(stdout, "Last CD Session LSN: "); fflush(stdout);
Packit dd8086
      if (DRIVER_OP_SUCCESS == cdio_get_last_session(p_cdio, &i_last_session))
Packit dd8086
        {
Packit dd8086
          report(stdout, "%d\n", i_last_session);
Packit dd8086
        } else {
Packit dd8086
          if (i_misc_cap & CDIO_DRIVE_CAP_MISC_MULTI_SESSION)
Packit dd8086
            report(stdout, "failed\n");
Packit dd8086
          else
Packit dd8086
            report(stdout, "not supported by drive/driver\n");
Packit dd8086
        }
Packit dd8086
    }
Packit dd8086
Packit dd8086
    /* get audio status from subchannel */
Packit dd8086
    if  ( CDIO_DISC_MODE_CD_DA == discmode ||
Packit dd8086
          CDIO_DISC_MODE_CD_MIXED == discmode ) {
Packit dd8086
      cdio_subchannel_t subchannel;
Packit dd8086
      driver_return_code_t rc;
Packit dd8086
Packit dd8086
      memset(&subchannel, 0, sizeof(subchannel));
Packit dd8086
      report( stdout, "audio status: "); fflush(stdout);
Packit dd8086
Packit dd8086
      rc = cdio_audio_read_subchannel(p_cdio, &subchannel);
Packit dd8086
Packit dd8086
      if (DRIVER_OP_SUCCESS == rc) {
Packit dd8086
        bool b_volume   = false;
Packit dd8086
        bool b_position = false;
Packit dd8086
Packit dd8086
        report ( stdout, "%s\n",
Packit dd8086
                 mmc_audio_state2str(subchannel.audio_status) );
Packit dd8086
Packit dd8086
        switch (subchannel.audio_status) {
Packit dd8086
        case CDIO_MMC_READ_SUB_ST_PLAY:
Packit dd8086
          b_playing_audio = true;
Packit dd8086
          /* Fall through to next case. */
Packit dd8086
        case CDIO_MMC_READ_SUB_ST_PAUSED:
Packit dd8086
          b_position      = true;
Packit dd8086
          /* Fall through to next case. */
Packit dd8086
        case CDIO_MMC_READ_SUB_ST_NO_STATUS:
Packit dd8086
          b_volume        = true;
Packit dd8086
          break;
Packit dd8086
        default:
Packit dd8086
          ;
Packit dd8086
        }
Packit dd8086
Packit dd8086
        if (b_position)
Packit dd8086
          report( stdout, " at: %02d:%02d abs / %02d:%02d track %d\n",
Packit dd8086
                  subchannel.abs_addr.m,
Packit dd8086
                  subchannel.abs_addr.s,
Packit dd8086
                  subchannel.rel_addr.m,
Packit dd8086
                  subchannel.rel_addr.s,
Packit dd8086
                  subchannel.track );
Packit dd8086
Packit dd8086
        if (b_volume) {
Packit dd8086
          cdio_audio_volume_t volume;
Packit dd8086
Packit dd8086
          if (DRIVER_OP_SUCCESS == cdio_audio_get_volume (p_cdio, &volume)) {
Packit dd8086
            uint8_t j=0;
Packit dd8086
            for (j=0; j<4; j++) {
Packit dd8086
              uint8_t i_level     = volume.level[j];
Packit dd8086
              report( stdout,
Packit dd8086
                      "volume level port %d: %3d (0..255) %3d (0..100)\n",
Packit dd8086
                      j, i_level, (i_level*100+128) / 256 );
Packit dd8086
            }
Packit dd8086
Packit dd8086
          } else
Packit dd8086
            report( stdout, " can't get volume levels\n" );
Packit dd8086
        }
Packit dd8086
      } else if (DRIVER_OP_UNSUPPORTED == rc) {
Packit dd8086
        report( stdout, "not implemented\n" );
Packit dd8086
      } else {
Packit dd8086
        report( stdout, "FAILED\n" );
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (!opts.no_analysis) {
Packit dd8086
    if (b_playing_audio) {
Packit dd8086
      /* Running a CD Analysis would mess up audio playback.*/
Packit dd8086
      report(stdout,
Packit dd8086
             "CD Analysis Report omitted because audio is currently "
Packit dd8086
             "playing.\n");
Packit dd8086
      myexit(p_cdio, EXIT_SUCCESS);
Packit dd8086
    }
Packit dd8086
Packit dd8086
    report(stdout, STRONG "CD Analysis Report\n" NORMAL);
Packit dd8086
Packit dd8086
    /* try to find out what sort of CD we have */
Packit dd8086
    if (num_audio > 0) {
Packit dd8086
      /* may be a "real" audio CD or hidden track CD */
Packit dd8086
Packit dd8086
      msf_t msf;
Packit dd8086
      cdio_get_track_msf(p_cdio, i_first_track, &msf;;
Packit dd8086
Packit dd8086
      /* CD-I/Ready says start_track_lsn <= 30*75 then CDDA */
Packit dd8086
      if (start_track_lsn > 100 /* 100 is just a guess */) {
Packit dd8086
        fs = cdio_guess_cd_type(p_cdio, 0, 1, &cdio_iso_analysis);
Packit dd8086
        if ((CDIO_FSTYPE(fs)) != CDIO_FS_UNKNOWN)
Packit dd8086
          fs |= CDIO_FS_ANAL_HIDDEN_TRACK;
Packit dd8086
        else {
Packit dd8086
          fs &= ~CDIO_FS_MASK; /* del filesystem info */
Packit dd8086
          report( stdout, "Oops: %lu unused sectors at start, "
Packit dd8086
                 "but hidden track check failed.\n",
Packit dd8086
                 (long unsigned int) start_track_lsn);
Packit dd8086
        }
Packit dd8086
      }
Packit dd8086
      print_analysis(ms_offset, cdio_iso_analysis, fs, first_data, num_audio,
Packit dd8086
                     i_tracks, i_first_track,
Packit dd8086
                     cdio_get_track_format(p_cdio, 1), p_cdio);
Packit dd8086
    }
Packit dd8086
    if (num_data > 0) {
Packit dd8086
      /* we have data track(s) */
Packit dd8086
      int j;
Packit dd8086
Packit dd8086
      for (j = 2, i = first_data; i <= i_tracks; i++) {
Packit dd8086
        msf_t msf;
Packit dd8086
        track_format_t track_format = cdio_get_track_format(p_cdio, i);
Packit dd8086
Packit dd8086
        cdio_get_track_msf(p_cdio, i, &msf;;
Packit dd8086
Packit dd8086
        switch ( track_format ) {
Packit dd8086
        case TRACK_FORMAT_AUDIO:
Packit dd8086
        case TRACK_FORMAT_ERROR:
Packit dd8086
          break;
Packit dd8086
        case TRACK_FORMAT_CDI:
Packit dd8086
        case TRACK_FORMAT_XA:
Packit dd8086
        case TRACK_FORMAT_DATA:
Packit dd8086
        case TRACK_FORMAT_PSX:
Packit dd8086
          ;
Packit dd8086
        }
Packit dd8086
Packit dd8086
        start_track_lsn = (i == 1) ? 0 : cdio_msf_to_lsn(&msf;;
Packit dd8086
Packit dd8086
        /* save the start of the data area */
Packit dd8086
        if (i == first_data)
Packit dd8086
          data_start = start_track_lsn;
Packit dd8086
Packit dd8086
        /* skip tracks which belong to the current walked session */
Packit dd8086
        if (start_track_lsn < data_start + cdio_iso_analysis.isofs_size)
Packit dd8086
          continue;
Packit dd8086
Packit dd8086
        fs = cdio_guess_cd_type(p_cdio, start_track_lsn, i,
Packit dd8086
                                &cdio_iso_analysis);
Packit dd8086
Packit dd8086
        if (i > 1) {
Packit dd8086
          /* track is beyond last session -> new session found */
Packit dd8086
          ms_offset = start_track_lsn;
Packit dd8086
          report( stdout, "session #%d starts at track %2i, LSN: %lu,"
Packit dd8086
                  " ISO 9660 blocks: %6i\n",
Packit dd8086
                  j++, i, (unsigned long int) start_track_lsn,
Packit dd8086
                  cdio_iso_analysis.isofs_size);
Packit dd8086
          report( stdout, "ISO 9660: %i blocks, label `%.32s'\n",
Packit dd8086
                  cdio_iso_analysis.isofs_size, cdio_iso_analysis.iso_label);
Packit dd8086
          fs |= CDIO_FS_ANAL_MULTISESSION;
Packit dd8086
        } else {
Packit dd8086
          print_analysis(ms_offset, cdio_iso_analysis, fs, first_data,
Packit dd8086
                         num_audio, i_tracks, i_first_track,
Packit dd8086
                         track_format, p_cdio);
Packit dd8086
        }
Packit dd8086
Packit dd8086
        if ( !(CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660 ||
Packit dd8086
               CDIO_FSTYPE(fs) == CDIO_FS_ISO_HFS  ||
Packit dd8086
               /* CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660_INTERACTIVE)
Packit dd8086
                  && (fs & XA))) */
Packit dd8086
               CDIO_FSTYPE(fs) == CDIO_FS_ISO_9660_INTERACTIVE) )
Packit dd8086
          /* no method for non-ISO9660 multisessions */
Packit dd8086
          break;
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  myexit(p_cdio, EXIT_SUCCESS);
Packit dd8086
  /* Not reached:*/
Packit dd8086
  return(EXIT_SUCCESS);
Packit dd8086
}