Blame src/cd-drive.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2011, 2014, 2017 Rocky Bernstein <rocky@gnu.org>
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
/* Program to show drivers installed and capabilities of CD drives. */
Packit dd8086
Packit dd8086
#include "util.h"
Packit dd8086
Packit dd8086
#ifdef HAVE_STDIO_H
Packit dd8086
#include <stdio.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_SYS_TYPES_H
Packit dd8086
#include <sys/types.h>
Packit dd8086
#endif
Packit dd8086
#include "getopt.h"
Packit dd8086
#include <cdio/cdio.h>
Packit dd8086
#include <cdio/mmc.h>
Packit dd8086
Packit dd8086
/* Used by `main' to communicate with `parse_opt'. And global options
Packit dd8086
 */
Packit dd8086
static struct arguments
Packit dd8086
{
Packit dd8086
  uint32_t       debug_level;
Packit dd8086
  int            version_only;
Packit dd8086
  int            silent;
Packit dd8086
  source_image_t source_image;
Packit dd8086
} opts;
Packit dd8086
Packit dd8086
/* Configuration option codes */
Packit dd8086
enum {
Packit dd8086
  OP_HANDLED,
Packit dd8086
Packit dd8086
  OP_SOURCE_DEVICE,
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 all options. */
Packit dd8086
static bool
Packit dd8086
parse_options (int argc, char *argv[])
Packit dd8086
{
Packit dd8086
  int opt;
Packit dd8086
  int rc = EXIT_FAILURE;
Packit dd8086
Packit dd8086
  static const char helpText[] =
Packit dd8086
    "Usage: %s [OPTION...]\n"
Packit dd8086
    "  -d, --debug=INT                 Set debugging to LEVEL\n"
Packit dd8086
    "  -i, --cdrom-device[=DEVICE]     show only info about CD-ROM device\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 [-d|--debug INT] [-i|--cdrom-device DEVICE] [-q|--quiet]\n"
Packit dd8086
    "        [-V|--version] [-?|--help] [--usage]\n";
Packit dd8086
Packit dd8086
  static const char optionsString[] = "d:i::qV?";
Packit dd8086
  static const struct option optionsTable[] = {
Packit dd8086
    {"debug", required_argument, NULL, 'd' },
Packit dd8086
    {"cdrom-device", optional_argument, NULL, 'i' },
Packit dd8086
    {"quiet", no_argument, NULL, 'q' },
Packit dd8086
    {"version", no_argument, NULL, 'V' },
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)) != -1) {
Packit dd8086
    switch (opt) {
Packit dd8086
    case 'd':
Packit dd8086
      opts.debug_level = atoi(optarg);
Packit dd8086
      break;
Packit dd8086
Packit dd8086
    case 'i':
Packit dd8086
      if (opts.source_image != (source_image_t) DRIVER_UNKNOWN) {
Packit dd8086
	/* NOTE: The libpopt version already set source_name by this time.
Packit dd8086
	   To restore this behavior, fall through to the else{} block.
Packit dd8086
	*/
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
	break;
Packit dd8086
      } else {
Packit dd8086
	opts.source_image  = (source_image_t) DRIVER_DEVICE;
Packit dd8086
	if (optarg != NULL) {
Packit dd8086
	  source_name = fillout_device_name(optarg);
Packit dd8086
	}
Packit dd8086
	break;
Packit dd8086
      }
Packit dd8086
      break;
Packit dd8086
Packit dd8086
    case 'q':
Packit dd8086
      opts.silent = 1;
Packit dd8086
      break;
Packit dd8086
Packit dd8086
    case 'V':
Packit dd8086
      opts.version_only = 1;
Packit dd8086
      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
    default:
Packit dd8086
      return false;
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
  if (optind < argc) {
Packit dd8086
    const char *remaining_arg = argv[optind++];
Packit dd8086
Packit dd8086
    /* NOTE: A bug in the libpopt version checked source_image, which
Packit dd8086
       rendered the subsequent source_image test useless.
Packit dd8086
    */
Packit dd8086
    if (source_name != NULL) {
Packit dd8086
      report( stderr, "%s: Source specified in option %s and as %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 == (source_image_t) DRIVER_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
      goto error_exit;
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
  return true;
Packit dd8086
 error_exit:
Packit dd8086
  if (source_name != NULL) {
Packit dd8086
    free(source_name);
Packit dd8086
  }
Packit dd8086
  free(program_name);
Packit dd8086
  exit(rc);
Packit dd8086
Packit dd8086
}
Packit dd8086
Packit dd8086
/* CDIO logging routines */
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
/*! Prints out SCSI-MMC drive features  */
Packit dd8086
static void
Packit dd8086
print_mmc_drive_level(CdIo_t *p_cdio)
Packit dd8086
{
Packit dd8086
  cdio_mmc_level_t mmc_level = mmc_get_drive_mmc_cap(p_cdio);
Packit dd8086
Packit dd8086
  printf( "CD-ROM drive supports " );
Packit dd8086
Packit dd8086
  switch(mmc_level) {
Packit dd8086
  case CDIO_MMC_LEVEL_WEIRD:
Packit dd8086
    printf("some nonstandard or degenerate set of MMC\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_MMC_LEVEL_1:
Packit dd8086
    printf("MMC 1\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_MMC_LEVEL_2:
Packit dd8086
    printf("MMC 2\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_MMC_LEVEL_3:
Packit dd8086
    printf("MMC 3\n");
Packit dd8086
    break;
Packit dd8086
  case CDIO_MMC_LEVEL_NONE:
Packit dd8086
    printf("no MMC\n");
Packit dd8086
    break;
Packit dd8086
  }
Packit dd8086
  printf("\n");
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
Packit dd8086
  /* Default option values. */
Packit dd8086
  opts.silent        = false;
Packit dd8086
  opts.debug_level   = 0;
Packit dd8086
  opts.source_image  = (source_image_t) DRIVER_UNKNOWN;
Packit dd8086
}
Packit dd8086
Packit dd8086
int
Packit dd8086
main(int argc, char *argv[])
Packit dd8086
{
Packit dd8086
  CdIo_t *p_cdio=NULL;
Packit dd8086
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, false, opts.version_only);
Packit dd8086
Packit dd8086
  if (opts.debug_level == 3) {
Packit dd8086
    cdio_loglevel_default = CDIO_LOG_INFO;
Packit dd8086
  } else if (opts.debug_level >= 4) {
Packit dd8086
    cdio_loglevel_default = CDIO_LOG_DEBUG;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (NULL == source_name) {
Packit dd8086
    char *default_device;
Packit dd8086
Packit dd8086
    p_cdio = cdio_open (NULL, DRIVER_DEVICE);
Packit dd8086
Packit dd8086
    if (NULL == p_cdio) {
Packit dd8086
      printf("No loaded CD-ROM device accessible.\n");
Packit dd8086
    }  else {
Packit dd8086
      default_device = cdio_get_default_device(p_cdio);
Packit dd8086
Packit dd8086
      printf("The driver selected is %s\n", cdio_get_driver_name(p_cdio));
Packit dd8086
Packit dd8086
      if (default_device) {
Packit dd8086
	printf("The default device for this driver is %s\n", default_device);
Packit dd8086
      }
Packit dd8086
Packit dd8086
      free(default_device);
Packit dd8086
      cdio_destroy(p_cdio);
Packit dd8086
      p_cdio=NULL;
Packit dd8086
      printf("\n");
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
Packit dd8086
  /* Print out a drivers available */
Packit dd8086
  {
Packit dd8086
    const driver_id_t *driver_id_p;
Packit dd8086
Packit dd8086
    printf("Drivers available...\n");
Packit dd8086
    for (driver_id_p=cdio_drivers; *driver_id_p!=DRIVER_UNKNOWN; driver_id_p++)
Packit dd8086
      if (cdio_have_driver(*driver_id_p)) {
Packit dd8086
	printf("  %-35s\n", cdio_driver_describe(*driver_id_p));
Packit dd8086
      }
Packit dd8086
    printf("\n");
Packit dd8086
  }
Packit dd8086
Packit dd8086
Packit dd8086
  if (NULL == source_name) {
Packit dd8086
    /* Print out a list of CD-drives */
Packit dd8086
Packit dd8086
    char **ppsz_cdrives=NULL, **ppsz_cd;
Packit dd8086
    driver_id_t driver_id = DRIVER_DEVICE;
Packit dd8086
Packit dd8086
    ppsz_cdrives = cdio_get_devices_ret(&driver_id);
Packit dd8086
    if (NULL != ppsz_cdrives)
Packit dd8086
      for( ppsz_cd = ppsz_cdrives; *ppsz_cd != NULL; ppsz_cd++ ) {
Packit dd8086
	cdio_drive_read_cap_t  i_read_cap;
Packit dd8086
	cdio_drive_write_cap_t i_write_cap;
Packit dd8086
	cdio_drive_misc_cap_t  i_misc_cap;
Packit dd8086
	cdio_hwinfo_t          hwinfo;
Packit dd8086
Packit dd8086
	p_cdio = cdio_open(*ppsz_cd, driver_id);
Packit dd8086
	print_mmc_drive_level(p_cdio);
Packit dd8086
Packit dd8086
	printf("%28s: %s\n", "Drive", *ppsz_cd);
Packit dd8086
Packit dd8086
	if (p_cdio) {
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_mmc_drive_features(p_cdio);
Packit dd8086
	  cdio_get_drive_cap(p_cdio, &i_read_cap, &i_write_cap,
Packit dd8086
			     &i_misc_cap);
Packit dd8086
	  print_drive_capabilities(i_read_cap, i_write_cap, i_misc_cap);
Packit dd8086
	}
Packit dd8086
	printf("\n");
Packit dd8086
	if (p_cdio) cdio_destroy(p_cdio);
Packit dd8086
	p_cdio = NULL;
Packit dd8086
      }
Packit dd8086
Packit dd8086
    cdio_free_device_list(ppsz_cdrives);
Packit dd8086
    ppsz_cdrives = NULL;
Packit dd8086
  } else {
Packit dd8086
    /* Print CD-drive info for given source */
Packit dd8086
    cdio_drive_read_cap_t  i_read_cap;
Packit dd8086
    cdio_drive_write_cap_t i_write_cap;
Packit dd8086
    cdio_drive_misc_cap_t  i_misc_cap;
Packit dd8086
    cdio_hwinfo_t          hwinfo;
Packit dd8086
Packit dd8086
    printf("Drive %s\n", source_name);
Packit dd8086
    p_cdio = cdio_open (source_name, DRIVER_UNKNOWN);
Packit dd8086
Packit dd8086
    if (p_cdio) {
Packit dd8086
Packit dd8086
      print_mmc_drive_level(p_cdio);
Packit dd8086
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_mmc_drive_features(p_cdio);
Packit dd8086
    }
Packit dd8086
    cdio_get_drive_cap_dev(source_name, &i_read_cap, &i_write_cap,
Packit dd8086
			   &i_misc_cap);
Packit dd8086
    print_drive_capabilities(i_read_cap, i_write_cap, i_misc_cap);
Packit dd8086
    printf("\n");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  myexit(p_cdio, EXIT_SUCCESS);
Packit dd8086
  /* Not reached:*/
Packit dd8086
  return(EXIT_SUCCESS);
Packit dd8086
}