Blame src/iso-info.c

Packit dd8086
/*
Packit dd8086
  Copyright (C) 2004-2006, 2008, 2012-2014, 2017 Rocky Bernstein
Packit dd8086
  <rocky@gnu.org>
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
  ISO Info - prints various information about a ISO 9660 image.
Packit dd8086
*/
Packit dd8086
#include "getopt.h"
Packit dd8086
#include "util.h"
Packit dd8086
#undef err_exit
Packit dd8086
Packit dd8086
#define err_exit(fmt, args...)                      \
Packit dd8086
  report (stderr, "%s: "fmt, program_name, ##args); \
Packit dd8086
  iso9660_close(p_iso);                             \
Packit dd8086
  if (NULL != program_name) free(program_name);     \
Packit dd8086
  if (NULL != source_name)  free(source_name);      \
Packit dd8086
  return(EXIT_FAILURE);
Packit dd8086
Packit dd8086
#ifdef HAVE_CONFIG_H
Packit dd8086
# include "config.h"
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_SYS_TYPES_H
Packit dd8086
#include <sys/types.h>
Packit dd8086
#endif
Packit dd8086
#include <cdio/types.h>
Packit dd8086
#include <cdio/bytesex.h>
Packit dd8086
#include <cdio/cdio.h>
Packit dd8086
#include <cdio/ds.h>
Packit dd8086
#include <cdio/iso9660.h>
Packit dd8086
#include <cdio/udf.h>
Packit dd8086
Packit dd8086
#ifdef HAVE_STDIO_H
Packit dd8086
#include <stdio.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_ERRNO_H
Packit dd8086
#include <errno.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_STRING_H
Packit dd8086
#include <string.h>
Packit dd8086
#endif
Packit dd8086
#ifdef HAVE_UNISTD_H
Packit dd8086
#include <unistd.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#ifdef HAVE_ALLOCA_H
Packit dd8086
#include <alloca.h>
Packit dd8086
#endif
Packit dd8086
Packit dd8086
#if 0
Packit dd8086
#define STRONG "\033[1m"
Packit dd8086
#define NORMAL "\033[0m"
Packit dd8086
#else
Packit dd8086
#define STRONG "__________________________________\n"
Packit dd8086
#define NORMAL ""
Packit dd8086
#endif
Packit dd8086
Packit dd8086
/* TODO: Find a better place from where cd-info can read it too. */
Packit dd8086
/*
Packit dd8086
   ECMA-119 allows only a depth of 8 directories. Nobody obeys.
Packit dd8086
   Rock Ridge allows path length 1023. This would be max depth 512.
Packit dd8086
*/
Packit dd8086
#define CDIO_MAX_DIR_RECURSION 512
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
  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            print_udf;
Packit dd8086
  int            print_iso9660_short;
Packit dd8086
  int64_t        show_rock_ridge;
Packit dd8086
} opts;
Packit dd8086
Packit dd8086
/* Configuration option codes */
Packit dd8086
enum {
Packit dd8086
  OP_HANDLED = 0,
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 a 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=UINT          Set debugging to LEVEL\n"
Packit dd8086
    "  -i, --input[=FILE]        Filename to read ISO-9960 image from\n"
Packit dd8086
    "  -f                        Generate output similar to 'find . -print'\n"
Packit dd8086
    "  -l, --iso9660             output similar to 'ls -lR' for an ISO 9660 fs\n"
Packit dd8086
    "  -U, --udf                 output similar to 'ls -lR' for a UDF fs\n"
Packit dd8086
    "  --no-header               Don't display header and copyright (for regression\n"
Packit dd8086
#ifdef HAVE_JOLIET
Packit dd8086
    "  --no-joliet               Don't use Joliet-extension information\n"
Packit dd8086
#endif /*HAVE_JOLIET*/
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
    "  -r --show-rock-ridge UINT Show if image uses Rock-Ridge extensions\n"
Packit dd8086
    "                            A maximum of UINT files will be considered.\n"
Packit dd8086
    "                            Use 0 for all files.\n"
Packit dd8086
    "  -q, --quiet               Don't produce warning output\n"
Packit dd8086
    "  -V, --version            display version and copyright information 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 [-i|--input FILE] [-f] [-l|--iso9660] [-U|--udf]\n"
Packit dd8086
    "        [--no-header] [--no-joliet] [--no-rock-ridge] [--show-rock-ridge] [--no-xa] [-q|--quiet]\n"
Packit dd8086
    "        [-d|--debug INT] [-V|--version] [-?|--help] [--usage]\n";
Packit dd8086
Packit dd8086
  static const char optionsString[] = "d:i::flUqV?";
Packit dd8086
  static const struct option optionsTable[] = {
Packit dd8086
    {"debug",   required_argument, NULL, 'd'},
Packit dd8086
    {"input",   optional_argument, NULL, 'i'},
Packit dd8086
    {"iso9660", no_argument,       NULL, 'l'},
Packit dd8086
    {"udf",     no_argument,       NULL, 'U'},
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
    {"show-rock-ridge", required_argument, NULL, 'r' },
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
      {
Packit dd8086
      case 'd': opts.debug_level = atoi(optarg); break;
Packit dd8086
      case 'i': if (optarg != NULL) {
Packit dd8086
	  if (NULL != source_name)  free(source_name);
Packit dd8086
	  source_name = strdup(optarg);
Packit dd8086
	  break;
Packit dd8086
	}
Packit dd8086
      case 'f': opts.print_iso9660_short = 1; break;
Packit dd8086
      case 'l': opts.print_iso9660       = 1; break;
Packit dd8086
      case 'U': opts.print_udf           = 1; break;
Packit dd8086
      case 'q': opts.silent              = 1; break;
Packit dd8086
      case 'r': opts.show_rock_ridge = atoll(optarg); 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
    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
    if (NULL != source_name)  free(source_name);
Packit dd8086
    source_name = strdup(remaining_arg);
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
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
  if (level == CDIO_LOG_ERROR) {
Packit dd8086
    // print an error like default, but *don't* exit.
Packit dd8086
    fprintf (stderr, "**ERROR: %s\n", message);
Packit dd8086
    fflush (stderr);
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
Packit dd8086
  gl_default_cdio_log_handler (level, message);
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_iso9660_recurse (iso9660_t *p_iso, const char psz_path[],
Packit dd8086
		       unsigned int rec_counter)
Packit dd8086
{
Packit dd8086
  CdioISO9660FileList_t *entlist;
Packit dd8086
  CdioISO9660DirList_t *p_dirlist = iso9660_dirlist_new();
Packit dd8086
  CdioListNode_t *entnode;
Packit dd8086
  uint8_t i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
Packit dd8086
  char *translated_name = (char *) alloca(4096);
Packit dd8086
  size_t translated_name_size = 4096;
Packit dd8086
  entlist = iso9660_ifs_readdir (p_iso, psz_path);
Packit dd8086
Packit dd8086
  if (opts.print_iso9660) {
Packit dd8086
    printf ("%s:\n", psz_path);
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (NULL == entlist) {
Packit dd8086
    iso9660_dirlist_free(p_dirlist);
Packit dd8086
    report( stderr, "Error getting above directory information\n" );
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  rec_counter++;
Packit dd8086
  if (rec_counter > CDIO_MAX_DIR_RECURSION) {
Packit dd8086
    iso9660_dirlist_free(p_dirlist);
Packit dd8086
    iso9660_filelist_free(entlist);
Packit dd8086
    report( stderr,
Packit dd8086
            "Directory recursion too deep. ISO most probably damaged.\n" );
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  /* Iterate over files in this directory */
Packit dd8086
Packit dd8086
  _CDIO_LIST_FOREACH (entnode, 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
       }
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
        snprintf (_fullname, sizeof (_fullname), "%s%s", psz_path,
Packit dd8086
                  translated_name);
Packit dd8086
      } else {
Packit dd8086
        snprintf (_fullname, sizeof (_fullname), "%s%s", psz_path,
Packit dd8086
                  psz_iso_name);
Packit dd8086
      }
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
      if (opts.print_iso9660) {
Packit dd8086
        print_fs_attrs(p_statbuf,
Packit dd8086
                       0 == opts.no_rock_ridge,
Packit dd8086
                       iso9660_ifs_is_xa(p_iso) && 0 == opts.no_xa,
Packit dd8086
                       psz_iso_name, translated_name);
Packit dd8086
      } else {
Packit dd8086
        if ( strcmp (psz_iso_name, ".") && strcmp (psz_iso_name, ".."))
Packit dd8086
          printf("%9u %s%s\n", (unsigned int) p_statbuf->size, psz_path,
Packit dd8086
                 yep == p_statbuf->rr.b3_rock
Packit dd8086
                 ? psz_iso_name : translated_name);
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
  iso9660_filelist_free(entlist);
Packit dd8086
Packit dd8086
  if (opts.print_iso9660) {
Packit dd8086
    printf ("\n");
Packit dd8086
  }
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_iso, _fullname, rec_counter);
Packit dd8086
    }
Packit dd8086
Packit dd8086
  iso9660_dirlist_free(p_dirlist);
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_iso9660_fs (iso9660_t *iso)
Packit dd8086
{
Packit dd8086
  print_iso9660_recurse (iso, "/", 0);
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
print_udf_file_info(const udf_dirent_t *p_udf_dirent,
Packit dd8086
                    const char* psz_dirname,
Packit dd8086
                    const char *psz_filename)
Packit dd8086
{
Packit dd8086
  time_t mod_time = udf_get_modification_time(p_udf_dirent);
Packit dd8086
  char date_str[30];
Packit dd8086
  char psz_mode[11]="invalid";
Packit dd8086
  const char *psz_fname= psz_filename
Packit dd8086
    ? psz_filename : udf_get_filename(p_udf_dirent);
Packit dd8086
Packit dd8086
  if (!opts.print_iso9660) {
Packit dd8086
    if (strcmp(psz_dirname, ".") != 0) {
Packit dd8086
      printf("%9lu ", (long unsigned int) udf_get_file_length(p_udf_dirent));
Packit dd8086
      printf("/%s", psz_dirname);
Packit dd8086
      printf("%s\n", *psz_fname ? psz_fname : "/");
Packit dd8086
    }
Packit dd8086
    return;
Packit dd8086
  }
Packit dd8086
  /* Print directory attributes*/
Packit dd8086
  printf("%s ", udf_mode_string(udf_get_posix_filemode(p_udf_dirent),
Packit dd8086
                                psz_mode));
Packit dd8086
  /* fake uid/gid */
Packit dd8086
  printf("0 0 ");
Packit dd8086
  printf("%3d ", udf_get_link_count(p_udf_dirent));
Packit dd8086
  printf("%9lu ", (long unsigned int) udf_get_file_length(p_udf_dirent));
Packit dd8086
  strftime(date_str, sizeof(date_str), "%b %d %Y %H:%M:%S ", localtime(&mod_time));
Packit dd8086
  printf("%s %s", date_str, *psz_fname ? psz_fname : "/");
Packit dd8086
  printf("\n");
Packit dd8086
}
Packit dd8086
Packit dd8086
static void
Packit dd8086
list_udf_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
Packit dd8086
{
Packit dd8086
  if (!p_udf_dirent) return;
Packit dd8086
Packit dd8086
  if (opts.print_iso9660) {
Packit dd8086
    printf ("\n/%s:\n", psz_path);
Packit dd8086
  }
Packit dd8086
  print_udf_file_info(p_udf_dirent, psz_path, ".");
Packit dd8086
Packit dd8086
  while (udf_readdir(p_udf_dirent)) {
Packit dd8086
Packit dd8086
    if (udf_is_dir(p_udf_dirent)) {
Packit dd8086
Packit dd8086
      udf_dirent_t *p_udf_dirent2 = udf_opendir(p_udf_dirent);
Packit dd8086
      if (p_udf_dirent2) {
Packit dd8086
        const char *psz_dirname = udf_get_filename(p_udf_dirent);
Packit dd8086
        const unsigned int i_newlen=2 + strlen(psz_path) + strlen(psz_dirname);
Packit dd8086
        char *psz_newpath = calloc(1, sizeof(char)*i_newlen);
Packit dd8086
Packit dd8086
        snprintf(psz_newpath, i_newlen, "%s%s/", psz_path, psz_dirname);
Packit dd8086
        list_udf_files(p_udf, p_udf_dirent2, psz_newpath);
Packit dd8086
        free(psz_newpath);
Packit dd8086
      }
Packit dd8086
    } else {
Packit dd8086
      print_udf_file_info(p_udf_dirent, psz_path, NULL);
Packit dd8086
    }
Packit dd8086
  }
Packit dd8086
}
Packit dd8086
Packit dd8086
static int
Packit dd8086
print_udf_fs (void)
Packit dd8086
{
Packit dd8086
  udf_t *p_udf;
Packit dd8086
Packit dd8086
  p_udf = udf_open (source_name);
Packit dd8086
Packit dd8086
  if (NULL == p_udf) {
Packit dd8086
    fprintf(stderr, "Sorry, couldn't open %s as something using UDF\n",
Packit dd8086
            source_name);
Packit dd8086
    return 1;
Packit dd8086
  } else {
Packit dd8086
    udf_dirent_t *p_udf_root = udf_get_root(p_udf, true, 0);
Packit dd8086
    if (NULL == p_udf_root) {
Packit dd8086
      fprintf(stderr, "Sorry, couldn't find / in %s\n",
Packit dd8086
              source_name);
Packit dd8086
      return 1;
Packit dd8086
    }
Packit dd8086
Packit dd8086
    list_udf_files(p_udf, p_udf_root, "");
Packit dd8086
  }
Packit dd8086
  udf_close(p_udf);
Packit dd8086
  return 0;
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
Packit dd8086
  /* Default option values. */
Packit dd8086
  opts.silent              = 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.debug_level         = 0;
Packit dd8086
  opts.print_iso9660       = 0;
Packit dd8086
  opts.print_iso9660_short = 0;
Packit dd8086
  opts.show_rock_ridge     = -1;
Packit dd8086
}
Packit dd8086
Packit dd8086
#define print_vd_info(title, fn)          \
Packit dd8086
  if (fn(p_iso, &psz_str)) {              \
Packit dd8086
    printf(title ": %s\n", psz_str);      \
Packit dd8086
  }                                       \
Packit dd8086
  free(psz_str);                          \
Packit dd8086
  psz_str = NULL;
Packit dd8086
Packit dd8086
/* ------------------------------------------------------------------------ */
Packit dd8086
Packit dd8086
int
Packit dd8086
main(int argc, char *argv[])
Packit dd8086
{
Packit dd8086
Packit dd8086
  iso9660_t           *p_iso=NULL;
Packit dd8086
  iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
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, 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
  } else if (opts.debug_level >= 4) {
Packit dd8086
    cdio_loglevel_default = CDIO_LOG_DEBUG;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (source_name==NULL) {
Packit dd8086
    err_exit("No input device given/found%s\n", "");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (opts.no_joliet) {
Packit dd8086
    iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
Packit dd8086
  }
Packit dd8086
Packit dd8086
  p_iso = iso9660_open_ext (source_name, iso_extension_mask);
Packit dd8086
Packit dd8086
  if (p_iso==NULL) {
Packit dd8086
    err_exit("Error in opening ISO-9660 image%s\n", "");
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (opts.silent == 0) {
Packit dd8086
    char *psz_str = NULL;
Packit dd8086
    uint8_t u_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
Packit dd8086
Packit dd8086
    printf(STRONG "ISO 9660 image: %s\n", source_name);
Packit dd8086
    print_vd_info("Application ", iso9660_ifs_get_application_id);
Packit dd8086
    print_vd_info("Preparer    ", iso9660_ifs_get_preparer_id);
Packit dd8086
    print_vd_info("Publisher   ", iso9660_ifs_get_publisher_id);
Packit dd8086
    print_vd_info("System      ", iso9660_ifs_get_system_id);
Packit dd8086
    print_vd_info("Volume      ", iso9660_ifs_get_volume_id);
Packit dd8086
    print_vd_info("Volume Set  ", iso9660_ifs_get_volumeset_id);
Packit dd8086
Packit dd8086
    if (opts.show_rock_ridge >= 0) {
Packit dd8086
      switch (iso9660_have_rr(p_iso, (uint64_t) opts.show_rock_ridge)) {
Packit dd8086
      case yep:
Packit dd8086
	printf("Rock Ridge  : yes\n");
Packit dd8086
	break;
Packit dd8086
      case nope:
Packit dd8086
	printf("Rock Ridge  : no\n");
Packit dd8086
	break;
Packit dd8086
      case dunno:
Packit dd8086
	printf("Rock Ridge  : possibly not\n");
Packit dd8086
      }
Packit dd8086
    }
Packit dd8086
Packit dd8086
    if (u_joliet_level == 0) {
Packit dd8086
	printf("No Joliet extensions\n");
Packit dd8086
    } else {
Packit dd8086
	printf("Joliet Level: %u\n", u_joliet_level);
Packit dd8086
    }
Packit dd8086
Packit dd8086
  }
Packit dd8086
Packit dd8086
  if (opts.print_iso9660 || opts.print_iso9660_short) {
Packit dd8086
      printf(STRONG "ISO-9660 Information\n" NORMAL);
Packit dd8086
      if (opts.print_iso9660 && opts.print_iso9660_short) {
Packit dd8086
          printf("Note: both -f and -l options given -- "
Packit dd8086
                 "-l (long listing) takes precidence\n");
Packit dd8086
      }
Packit dd8086
      print_iso9660_fs(p_iso);
Packit dd8086
  } else if (opts.print_udf) {
Packit dd8086
      print_udf_fs();
Packit dd8086
  }
Packit dd8086
Packit dd8086
Packit dd8086
  free(source_name);
Packit dd8086
  iso9660_close(p_iso);
Packit dd8086
  /* Not reached:*/
Packit dd8086
  free(program_name);
Packit dd8086
  return(EXIT_SUCCESS);
Packit dd8086
}