summaryrefslogtreecommitdiff
path: root/genisoimage/diag
diff options
context:
space:
mode:
Diffstat (limited to 'genisoimage/diag')
-rw-r--r--genisoimage/diag/README76
-rw-r--r--genisoimage/diag/devdump.12
-rw-r--r--genisoimage/diag/dump.c428
-rw-r--r--genisoimage/diag/isodebug.1108
-rw-r--r--genisoimage/diag/isodebug.c281
-rw-r--r--genisoimage/diag/isodump.12
-rw-r--r--genisoimage/diag/isodump.c715
-rw-r--r--genisoimage/diag/isoinfo.1365
-rw-r--r--genisoimage/diag/isoinfo.c1321
-rw-r--r--genisoimage/diag/isovfy.12
-rw-r--r--genisoimage/diag/isovfy.c794
11 files changed, 4094 insertions, 0 deletions
diff --git a/genisoimage/diag/README b/genisoimage/diag/README
new file mode 100644
index 0000000..26851f2
--- /dev/null
+++ b/genisoimage/diag/README
@@ -0,0 +1,76 @@
+# @(#)README 1.1 97/02/23 eric
+#
+ I am enclosing 3 test programs that I use to verify the
+integrity of an iso9660 disc. The first one (isodump) is pretty
+simple - it dumps to the screen the contents of the various
+directories. The second one (isovfy) goes through and looks for
+problems of one kind or another.
+
+ To use, type something like "./isodump /dev/ramdisk" or
+"./isodump /dev/scd0", depending upon where the iso9660 disc is. It
+starts by displaying the files in the first sector of the root
+directory. It has some pretty simple one letter commands that you
+can use to traverse the directory tree.
+
+ a - move back one sector.
+ b - move forward one sector.
+ g - go to new logical sector.
+ q - quit
+
+The a and b commands do not try and stop you from going past the
+beginning or end of a sector, and the g command does not have any way
+of knowing whether the sector you request is actually a directory or
+not.
+
+ The output is displayed in several columns. The first column
+is the total length of the directory record for the file. The second
+column (in [] brackets) is the volume number. Next comes the starting
+extent number (in hex), and then comes the file size in bytes. Then
+cones the filename (not the Rock Ridge version), and this is preceeded
+by an "*" if the file is a directory. After this is a summary of the
+Rock Ridge fields present along with a display of the translation of
+the symbolic link name if the SL Rock Ridge record is present.
+
+ I tailored this program for debugging some of the problems
+that I was having earlier. The idea is that you can tailor it
+to test for problems that you might be having, so it is not intended
+as a be-all and end-all dump program.
+
+ If you move to a sector that does not contain directory
+information, the results are unpredictable.
+
+ The second program, isovfy, is run in the same way as isodump,
+except that you do not have to do much except let it run. I have it
+written to verify all kinds of different things, and as people find
+other sorts of problems other tests could be added.
+
+ The third program, dump.c, basically does a hexdump of the cd.
+This is screen oriented, and there are some simple commands:
+
+ a - move back one sector.
+ b - move forward one sector.
+ f - enter new search string.
+ + - search forward for search string.
+ g - go to new logical sector.
+ q - quit
+
+
+ Note that with the 'g' command, sectors are always given in
+hex, and represent 2048 byte sectors (as on the cdrom). If you know
+how to decode a raw iso9660 directory, you can pick out the starting
+extent number from the hexdump and know where to go from there. The
+starting extent appears something like 30 bytes prior to the start of
+the iso9660 (not Rock Ridge) filename, and it appears in a 7.3.3
+format (meaning that it occupies 8 bytes, 4 in little endian format,
+and 4 in big endian format). Thus you should see a mirror image of
+the bytes when looking at the extent number.
+
+ The isovfy program can also dump the contents of the path
+tables, but this capability is commented out right now. Feel free
+to enable this to see what is in the tables. Ultimately I may fix
+it so that this checks the integrity of the tables as well.
+
+ The isovfy program gives warnings about things like files that
+have a size of 0 but have an extent number assigned. The genisoimage program
+should never do this, but the YM software does leave these around.
+I think it is probably harmless in the YM case.~
diff --git a/genisoimage/diag/devdump.1 b/genisoimage/diag/devdump.1
new file mode 100644
index 0000000..b170c59
--- /dev/null
+++ b/genisoimage/diag/devdump.1
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M% %I% %E% joerg
diff --git a/genisoimage/diag/dump.c b/genisoimage/diag/dump.c
new file mode 100644
index 0000000..b853c4e
--- /dev/null
+++ b/genisoimage/diag/dump.c
@@ -0,0 +1,428 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)dump.c 1.24 05/05/15 joerg */
+/*
+ * File dump.c - dump a file/device both in hex and in ASCII.
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <ttydefs.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X) may cause an integer overflow and thus give
+ * incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
+ */
+#define SECTOR_SIZE (2048)
+#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define infile in_image
+FILE *infile = NULL;
+static off_t file_addr;
+static off_t sec_addr = (off_t)-1;
+static Uchar sector[2048];
+#define PAGE 256
+static Uchar buffer[PAGE];
+static Uchar search[64];
+
+#ifdef USE_V7_TTY
+static struct sgttyb savetty;
+static struct sgttyb newtty;
+#else
+static struct termios savetty;
+static struct termios newtty;
+#endif
+
+static void reset_tty(void);
+static void set_tty(void);
+static void onsusp(int sig);
+static void crsr2(int row, int col);
+static void readblock(void);
+static void showblock(int flag);
+static int getbyte(void);
+static void usage(int excode);
+
+static void
+reset_tty()
+{
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot put tty into normal mode\n");
+#else
+ printf("Cannot put tty into normal mode\n");
+ exit(1);
+#endif
+ }
+}
+
+static void
+set_tty()
+{
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot put tty into raw mode\n");
+#else
+ printf("Cannot put tty into raw mode\n");
+ exit(1);
+#endif
+ }
+}
+
+
+/*
+ * Come here when we get a suspend signal from the terminal
+ */
+static void
+onsusp(int sig)
+{
+#ifdef SIGTTOU
+ /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+ signal(SIGTTOU, SIG_IGN);
+#endif
+ reset_tty();
+ fflush(stdout);
+#ifdef SIGTTOU
+ signal(SIGTTOU, SIG_DFL);
+ /* Send the TSTP signal to suspend our process group */
+ signal(SIGTSTP, SIG_DFL);
+ /* sigsetmask(0);*/
+ kill(0, SIGTSTP);
+ /* Pause for station break */
+
+ /* We're back */
+ signal(SIGTSTP, onsusp);
+#endif
+ set_tty();
+}
+
+
+static void
+crsr2(int row, int col)
+{
+ printf("\033[%d;%dH", row, col);
+}
+
+static void
+readblock()
+{
+ off_t dpos = file_addr - sec_addr;
+
+ if (sec_addr < 0 ||
+ dpos < 0 || (dpos + sizeof (buffer)) > sizeof (sector)) {
+ sec_addr = file_addr & ~2047;
+#ifdef USE_SCG
+ readsecs(sec_addr/2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+ lseek(fileno(infile), sec_addr, SEEK_SET);
+ read(fileno(infile), sector, sizeof (sector));
+#endif
+ dpos = file_addr - sec_addr;
+ }
+ movebytes(&sector[dpos], buffer, sizeof (buffer));
+}
+
+static void
+showblock(int flag)
+{
+ unsigned int k;
+ int i;
+ int j;
+
+ readblock();
+ if (flag) {
+ for (i = 0; i < 16; i++) {
+ crsr2(i+3, 1);
+ if (sizeof (file_addr) > sizeof (long)) {
+ printf("%16.16llx ", (Llong)file_addr+(i<<4));
+ } else {
+ printf("%8.8lx ", (long)file_addr+(i<<4));
+ }
+ for (j = 15; j >= 0; j--) {
+ printf("%2.2x", buffer[(i<<4)+j]);
+ if (!(j & 0x3))
+ printf(" ");
+ }
+ for (j = 0; j < 16; j++) {
+ k = buffer[(i << 4) + j];
+ if (k >= ' ' && k < 0x80)
+ printf("%c", k);
+ else
+ printf(".");
+ }
+ }
+ }
+ crsr2(20, 1);
+ if (sizeof (file_addr) > sizeof (long)) {
+ printf(" Zone, zone offset: %14llx %12.12llx ",
+ (Llong)file_addr>>11, (Llong)file_addr & 0x7ff);
+ } else {
+ printf(" Zone, zone offset: %6lx %4.4lx ",
+ (long)(file_addr>>11), (long)(file_addr & 0x7ff));
+ }
+ fflush(stdout);
+}
+
+static int
+getbyte()
+{
+ char c1;
+
+ c1 = buffer[file_addr & (PAGE-1)];
+ file_addr++;
+ if ((file_addr & (PAGE-1)) == 0)
+ showblock(0);
+ return (c1);
+}
+
+static void
+usage(int excode)
+{
+ errmsgno(EX_BAD, "Usage: %s [options] [image]\n",
+ get_progname());
+
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-help, -h Print this help\n");
+ fprintf(stderr, "\t-version Print version info and exit\n");
+ fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n");
+ fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n");
+ fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+ exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cac;
+ char * const *cav;
+ char *opts = "help,h,version,i*,dev*";
+ BOOL help = FALSE;
+ BOOL prvers = FALSE;
+ char *filename = NULL;
+ char *devname = NULL;
+ char c;
+ int i;
+ int j;
+
+ save_args(argc, argv);
+
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+ &filename, &devname) < 0) {
+ errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (help)
+ usage(0);
+ if (prvers) {
+ printf("devdump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+ exit(0);
+ }
+ cac = argc - 1;
+ cav = argv + 1;
+ if (filename == NULL && devname == NULL) {
+ if (getfiles(&cac, &cav, opts) != 0) {
+ filename = cav[0];
+ cac--, cav++;
+ }
+ }
+ if (getfiles(&cac, &cav, opts) != 0) {
+ errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (filename != NULL && devname != NULL) {
+ errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+ usage(EX_BAD);
+ }
+#ifdef USE_SCG
+ if (filename == NULL && devname == NULL)
+ cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+ if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+ errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+ fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+ usage(EX_BAD);
+ }
+
+ if (filename != NULL)
+ infile = fopen(filename, "rb");
+ else
+ filename = devname;
+
+ if (infile != NULL) {
+ /* EMPTY */;
+#ifdef USE_SCG
+ } else if (scsidev_open(filename) < 0) {
+#else
+ } else {
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot open '%s'\n", filename);
+#else
+ fprintf(stderr, "Cannot open '%s'\n", filename);
+ exit(1);
+#endif
+ }
+
+ for (i = 0; i < 30; i++)
+ printf("\n");
+ file_addr = (off_t)0;
+
+ /*
+ * Now setup the keyboard for single character input.
+ */
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Stdin must be a tty\n");
+#else
+ printf("Stdin must be a tty\n");
+ exit(1);
+#endif
+ }
+ newtty = savetty;
+#ifdef USE_V7_TTY
+ newtty.sg_flags &= ~(ECHO|CRMOD);
+ newtty.sg_flags |= CBREAK;
+#else
+ newtty.c_lflag &= ~ICANON;
+ newtty.c_lflag &= ~ECHO;
+ newtty.c_cc[VMIN] = 1;
+#endif
+ set_tty();
+#ifdef SIGTSTP
+ signal(SIGTSTP, onsusp);
+#endif
+ on_comerr((void(*)(int, void *))reset_tty, NULL);
+
+ do {
+ if (file_addr < (off_t)0) file_addr = (off_t)0;
+ showblock(1);
+ read(STDIN_FILENO, &c, 1); /* FIXME: check return value */
+ if (c == 'a')
+ file_addr -= PAGE;
+ if (c == 'b')
+ file_addr += PAGE;
+ if (c == 'g') {
+ crsr2(20, 1);
+ printf("Enter new starting block (in hex):");
+ if (sizeof (file_addr) > sizeof (long)) {
+ Llong ll;
+ scanf("%llx", &ll); /* FIXME: check return value */
+ file_addr = (off_t)ll;
+ } else {
+ long l;
+ scanf("%lx", &l); /* FIXME: check return value */
+ file_addr = (off_t)l;
+ }
+ file_addr = file_addr << 11;
+ crsr2(20, 1);
+ printf(" ");
+ }
+ if (c == 'f') {
+ crsr2(20, 1);
+ printf("Enter new search string:");
+ fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */
+ while (search[strlen((char *)search)-1] == '\n')
+ search[strlen((char *)search)-1] = 0;
+ crsr2(20, 1);
+ printf(" ");
+ }
+ if (c == '+') {
+ while (1 == 1) {
+ int slen;
+
+ while (1 == 1) {
+ c = getbyte();
+ if (c == search[0])
+ break;
+ }
+ slen = (int)strlen((char *)search);
+ for (j = 1; j < slen; j++) {
+ if (search[j] != getbyte())
+ break;
+ }
+ if (j == slen)
+ break;
+ }
+ file_addr &= ~(PAGE-1);
+ showblock(1);
+ }
+ if (c == 'q')
+ break;
+ } while (1 == 1);
+ reset_tty();
+ if (infile != NULL)
+ fclose(infile);
+ return (0);
+}
diff --git a/genisoimage/diag/isodebug.1 b/genisoimage/diag/isodebug.1
new file mode 100644
index 0000000..58f0d9d
--- /dev/null
+++ b/genisoimage/diag/isodebug.1
@@ -0,0 +1,108 @@
+.\" @(#)isodebug.8 1.1 06/02/08 Copyr 2006 J. Schilling
+.\" Manual page for isodebug
+.\" Modified for cdrkit distribution by E.Bloch
+.\"
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.TH ISODEBUG 1 "06/02/08" "J\*org Schilling" "Schily\'s USER COMMANDS"
+.SH NAME
+isodebug \- print genisoimage debug info from ISO-9660 image
+.SH SYNOPSIS
+.B
+isodebug
+[
+.I options
+]
+[
+.I file
+]
+.SH DESCRIPTION
+.B Isodebug
+reads the debug info written by
+.BR genisoimage (8)
+from within a ISO-9660 file system image and prints them.
+. \" .SH RETURNS
+. \" .SH ERRORS
+.SH OPTIONS
+.TP
+.B \-help
+Prints a short summary of the
+.B isodebug
+options and exists.
+.TP
+.B \-version
+Prints the
+.B isodebug
+version number string and exists.
+.TP
+.BI \-i " filename
+Filename to read ISO-9660 image from.
+.TP
+.BI dev= target
+SCSI target to use as CD/DVD-Recorder.
+See
+.BR wodim (1)
+for more information on now to use this option.
+.SH FILES
+.SH "SEE ALSO"
+.BR wodim (1),
+.BR genisoimage (1).
+.SH AUTHOR
+.nf
+J\*org Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+.PP
+
+
+.SH AUTHOR
+.nf
+J\*org Schilling
+Seestr. 110
+D-13353 Berlin
+Germany
+.fi
+
+.PP
+This manpage describes the program implementation of
+.B
+isodebug
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed in the
+cdrtools package [1]. However, the cdrtools developers are not
+involved in the development of this spinoff and therefore shall not be made
+responsible for any problem caused by it. Do not try to get support for this
+program by contacting the original author(s).
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
+
diff --git a/genisoimage/diag/isodebug.c b/genisoimage/diag/isodebug.c
new file mode 100644
index 0000000..f322021
--- /dev/null
+++ b/genisoimage/diag/isodebug.c
@@ -0,0 +1,281 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isodebug.c 1.10 05/05/01 Copyright 1996-2004 J. Schilling */
+/*
+ * Copyright (c) 1996-2004 J. Schilling
+ */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <statdefs.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <standard.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+#define _delta(from, to) ((to) - (from) + 1)
+
+#define VD_BOOT 0
+#define VD_PRIMARY 1
+#define VD_SUPPLEMENT 2
+#define VD_PARTITION 3
+#define VD_TERM 255
+
+#define VD_ID "CD001"
+
+struct iso9660_voldesc {
+ char vd_type [_delta(1, 1)];
+ char vd_id [_delta(2, 6)];
+ char vd_version [_delta(7, 7)];
+ char vd_fill [_delta(8, 2048)];
+};
+
+struct iso9660_boot_voldesc {
+ char vd_type [_delta(1, 1)];
+ char vd_id [_delta(2, 6)];
+ char vd_version [_delta(7, 7)];
+ char vd_bootsys [_delta(8, 39)];
+ char vd_bootid [_delta(40, 71)];
+ char vd_bootcode [_delta(72, 2048)];
+};
+
+struct iso9660_pr_voldesc {
+ char vd_type [_delta(1, 1)];
+ char vd_id [_delta(2, 6)];
+ char vd_version [_delta(7, 7)];
+ char vd_unused1 [_delta(8, 8)];
+ char vd_system_id [_delta(9, 40)];
+ char vd_volume_id [_delta(41, 72)];
+ char vd_unused2 [_delta(73, 80)];
+ char vd_volume_space_size [_delta(81, 88)];
+ char vd_unused3 [_delta(89, 120)];
+ char vd_volume_set_size [_delta(121, 124)];
+ char vd_volume_seq_number [_delta(125, 128)];
+ char vd_lbsize [_delta(129, 132)];
+ char vd_path_table_size [_delta(133, 140)];
+ char vd_pos_path_table_l [_delta(141, 144)];
+ char vd_opt_pos_path_table_l [_delta(145, 148)];
+ char vd_pos_path_table_m [_delta(149, 152)];
+ char vd_opt_pos_path_table_m [_delta(153, 156)];
+ char vd_root_dir [_delta(157, 190)];
+ char vd_volume_set_id [_delta(191, 318)];
+ char vd_publisher_id [_delta(319, 446)];
+ char vd_data_preparer_id [_delta(447, 574)];
+ char vd_application_id [_delta(575, 702)];
+ char vd_copyr_file_id [_delta(703, 739)];
+ char vd_abstr_file_id [_delta(740, 776)];
+ char vd_bibl_file_id [_delta(777, 813)];
+ char vd_create_time [_delta(814, 830)];
+ char vd_mod_time [_delta(831, 847)];
+ char vd_expiry_time [_delta(848, 864)];
+ char vd_effective_time [_delta(865, 881)];
+ char vd_file_struct_vers [_delta(882, 882)];
+ char vd_reserved1 [_delta(883, 883)];
+ char vd_application_use [_delta(884, 1395)];
+ char vd_fill [_delta(1396, 2048)];
+};
+
+#define GET_UBYTE(a) a_to_u_byte(a)
+#define GET_SBYTE(a) a_to_byte(a)
+#define GET_SHORT(a) a_to_u_2_byte(&((unsigned char *) (a))[0])
+#define GET_BSHORT(a) a_to_u_2_byte(&((unsigned char *) (a))[2])
+#define GET_INT(a) a_to_4_byte(&((unsigned char *) (a))[0])
+#define GET_LINT(a) la_to_4_byte(&((unsigned char *) (a))[0])
+#define GET_BINT(a) a_to_4_byte(&((unsigned char *) (a))[4])
+
+#define infile in_image
+FILE *infile = NULL;
+
+static void usage(int excode);
+static char *isodinfo(FILE *f);
+
+static void
+usage(int excode)
+{
+ errmsgno(EX_BAD, "Usage: %s [options] image\n",
+ get_progname());
+
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-help,-h Print this help\n");
+ fprintf(stderr, "\t-version Print version info and exit\n");
+ fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n");
+ fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n");
+ fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+ exit(excode);
+}
+
+static char *
+isodinfo(FILE *f)
+{
+static struct iso9660_voldesc vd;
+ struct iso9660_pr_voldesc *vp;
+#ifndef USE_SCG
+ struct stat sb;
+ mode_t mode;
+#endif
+ BOOL found = FALSE;
+ off_t sec_off = 16L;
+
+#ifndef USE_SCG
+ /*
+ * First check if a bad guy tries to call isosize()
+ * with an unappropriate file descriptor.
+ * return -1 in this case.
+ */
+ if (isatty(fileno(f)))
+ return (NULL);
+ if (fstat(fileno(f), &sb) < 0)
+ return (NULL);
+ mode = sb.st_mode & S_IFMT;
+ if (!S_ISREG(mode) && !S_ISBLK(mode) && !S_ISCHR(mode))
+ return (NULL);
+#endif
+
+ vp = (struct iso9660_pr_voldesc *) &vd;
+
+ do {
+#ifdef USE_SCG
+ readsecs(sec_off, &vd, 1);
+#else
+ if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1)
+ return (NULL);
+ read(fileno(f), &vd, sizeof (vd));
+#endif
+ sec_off++;
+
+ if (GET_UBYTE(vd.vd_type) == VD_PRIMARY) {
+ found = TRUE;
+/* break;*/
+ }
+
+ } while (GET_UBYTE(vd.vd_type) != VD_TERM);
+
+ if (GET_UBYTE(vd.vd_type) != VD_TERM)
+ return (NULL);
+
+#ifdef USE_SCG
+ readsecs(sec_off, &vd, 1);
+#else
+ if (lseek(fileno(f), (off_t)(sec_off * 2048L), SEEK_SET) == -1)
+ return (NULL);
+ read(fileno(f), &vd, sizeof (vd));
+#endif
+ sec_off++;
+
+ return ((char *)&vd);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cac;
+ char * const *cav;
+ char *opts = "help,h,version,i*,dev*";
+ BOOL help = FALSE;
+ BOOL prvers = FALSE;
+ char *filename = NULL;
+ char *devname = NULL;
+ char *p;
+ char *eol;
+
+ save_args(argc, argv);
+
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+ &filename, &devname) < 0) {
+ errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (help)
+ usage(0);
+ if (prvers) {
+ printf("isodebug %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+ exit(0);
+ }
+ cac = argc - 1;
+ cav = argv + 1;
+ if (filename == NULL && devname == NULL) {
+ if (getfiles(&cac, &cav, opts) != 0) {
+ filename = cav[0];
+ cac--, cav++;
+ }
+ }
+ if (getfiles(&cac, &cav, opts) != 0) {
+ errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (filename != NULL && devname != NULL) {
+ errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+ usage(EX_BAD);
+ }
+#ifdef USE_SCG
+ if (filename == NULL && devname == NULL)
+ cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+ if (filename == NULL && devname == NULL) {
+ errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+ usage(EX_BAD);
+ }
+
+ if (filename != NULL)
+ infile = fopen(filename, "rb");
+ else
+ filename = devname;
+
+ if (infile != NULL) {
+ /* EMPTY */;
+#ifdef USE_SCG
+ } else if (scsidev_open(filename) < 0) {
+#else
+ } else {
+#endif
+ comerr("Cannot open '%s'\n", filename);
+ }
+
+ p = isodinfo(infile);
+ if (p == NULL) {
+ printf("No ISO-9660 image debug info.\n");
+ } else if (strncmp(p, "MKI ", 4) == 0) {
+ eol = strchr(p, '\n');
+ if (eol)
+ *eol = '\0';
+ printf("ISO-9660 image created at %s\n", &p[4]);
+ if (eol) {
+ printf("\nCmdline: '%s'\n", &eol[1]);
+ }
+ }
+ return (0);
+}
diff --git a/genisoimage/diag/isodump.1 b/genisoimage/diag/isodump.1
new file mode 100644
index 0000000..b170c59
--- /dev/null
+++ b/genisoimage/diag/isodump.1
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M% %I% %E% joerg
diff --git a/genisoimage/diag/isodump.c b/genisoimage/diag/isodump.c
new file mode 100644
index 0000000..34fa8f1
--- /dev/null
+++ b/genisoimage/diag/isodump.c
@@ -0,0 +1,715 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isodump.c 1.27 05/05/15 joerg */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <ttydefs.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X) may cause an integer overflow and thus give
+ * incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
+ */
+#define SECTOR_SIZE (2048)
+#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define infile in_image
+FILE *infile = NULL;
+off_t file_addr;
+unsigned char buffer[2048];
+unsigned char search[64];
+int blocksize;
+
+#define PAGE sizeof (buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_primary_descriptor {
+ unsigned char type [ISODCL(1, 1)]; /* 711 */
+ unsigned char id [ISODCL(2, 6)];
+ unsigned char version [ISODCL(7, 7)]; /* 711 */
+ unsigned char unused1 [ISODCL(8, 8)];
+ unsigned char system_id [ISODCL(9, 40)]; /* aunsigned chars */
+ unsigned char volume_id [ISODCL(41, 72)]; /* dunsigned chars */
+ unsigned char unused2 [ISODCL(73, 80)];
+ unsigned char volume_space_size [ISODCL(81, 88)]; /* 733 */
+ unsigned char unused3 [ISODCL(89, 120)];
+ unsigned char volume_set_size [ISODCL(121, 124)]; /* 723 */
+ unsigned char volume_sequence_number [ISODCL(125, 128)]; /* 723 */
+ unsigned char logical_block_size [ISODCL(129, 132)]; /* 723 */
+ unsigned char path_table_size [ISODCL(133, 140)]; /* 733 */
+ unsigned char type_l_path_table [ISODCL(141, 144)]; /* 731 */
+ unsigned char opt_type_l_path_table [ISODCL(145, 148)]; /* 731 */
+ unsigned char type_m_path_table [ISODCL(149, 152)]; /* 732 */
+ unsigned char opt_type_m_path_table [ISODCL(153, 156)]; /* 732 */
+ unsigned char root_directory_record [ISODCL(157, 190)]; /* 9.1 */
+ unsigned char volume_set_id [ISODCL(191, 318)]; /* dunsigned chars */
+ unsigned char publisher_id [ISODCL(319, 446)]; /* achars */
+ unsigned char preparer_id [ISODCL(447, 574)]; /* achars */
+ unsigned char application_id [ISODCL(575, 702)]; /* achars */
+ unsigned char copyright_file_id [ISODCL(703, 739)]; /* 7.5 dchars */
+ unsigned char abstract_file_id [ISODCL(740, 776)]; /* 7.5 dchars */
+ unsigned char bibliographic_file_id [ISODCL(777, 813)]; /* 7.5 dchars */
+ unsigned char creation_date [ISODCL(814, 830)]; /* 8.4.26.1 */
+ unsigned char modification_date [ISODCL(831, 847)]; /* 8.4.26.1 */
+ unsigned char expiration_date [ISODCL(848, 864)]; /* 8.4.26.1 */
+ unsigned char effective_date [ISODCL(865, 881)]; /* 8.4.26.1 */
+ unsigned char file_structure_version [ISODCL(882, 882)]; /* 711 */
+ unsigned char unused4 [ISODCL(883, 883)];
+ unsigned char application_data [ISODCL(884, 1395)];
+ unsigned char unused5 [ISODCL(1396, 2048)];
+};
+
+struct iso_directory_record {
+ unsigned char length [ISODCL(1, 1)]; /* 711 */
+ unsigned char ext_attr_length [ISODCL(2, 2)]; /* 711 */
+ unsigned char extent [ISODCL(3, 10)]; /* 733 */
+ unsigned char size [ISODCL(11, 18)]; /* 733 */
+ unsigned char date [ISODCL(19, 25)]; /* 7 by 711 */
+ unsigned char flags [ISODCL(26, 26)];
+ unsigned char file_unit_size [ISODCL(27, 27)]; /* 711 */
+ unsigned char interleave [ISODCL(28, 28)]; /* 711 */
+ unsigned char volume_sequence_number [ISODCL(29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL(33, 33)]; /* 711 */
+ unsigned char name [1];
+};
+
+static int isonum_731(char * p);
+static int isonum_72(char * p);
+static int isonum_723(char * p);
+static int isonum_733(unsigned char * p);
+static void reset_tty(void);
+static void set_tty(void);
+static void onsusp(int signo);
+static void crsr2(int row, int col);
+static int parse_rr(unsigned char * pnt, int len, int cont_flag);
+static void dump_rr(struct iso_directory_record * idr);
+static void showblock(int flag);
+static int getbyte(void);
+static void usage(int excode);
+
+static int
+isonum_731(char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+static int
+isonum_721(char *p)
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723(char *p)
+{
+#if 0
+ if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+ comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+ fprintf(stderr, "invalid format 7.2.3 number\n");
+ exit(1);
+#endif
+ }
+#endif
+ return (isonum_721(p));
+}
+
+
+static int
+isonum_733(unsigned char *p)
+{
+ return (isonum_731((char *)p));
+}
+
+#ifdef USE_V7_TTY
+static struct sgttyb savetty;
+static struct sgttyb newtty;
+#else
+static struct termios savetty;
+static struct termios newtty;
+#endif
+
+static void
+reset_tty()
+{
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCSETN, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &savetty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCSETAF, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot put tty into normal mode\n");
+#else
+ printf("Cannot put tty into normal mode\n");
+ exit(1);
+#endif
+ }
+}
+
+static void
+set_tty()
+{
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCSETN, &newtty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcsetattr(STDIN_FILENO, TCSANOW, &newtty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCSETAF, &newtty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot put tty into raw mode\n");
+#else
+ printf("Cannot put tty into raw mode\n");
+ exit(1);
+#endif
+ }
+}
+
+/* Come here when we get a suspend signal from the terminal */
+
+static void
+onsusp(int signo)
+{
+#ifdef SIGTTOU
+ /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+ signal(SIGTTOU, SIG_IGN);
+#endif
+ reset_tty();
+ fflush(stdout);
+#ifdef SIGTTOU
+ signal(SIGTTOU, SIG_DFL);
+ /* Send the TSTP signal to suspend our process group */
+ signal(SIGTSTP, SIG_DFL);
+/* sigsetmask(0);*/
+ kill(0, SIGTSTP);
+ /* Pause for station break */
+
+ /* We're back */
+ signal(SIGTSTP, onsusp);
+#endif
+ set_tty();
+}
+
+
+
+static void
+crsr2(int row, int col)
+{
+ printf("\033[%d;%dH", row, col);
+}
+
+static int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+ int slen;
+ int ncount;
+ int extent;
+ off_t cont_extent;
+ int cont_offset;
+ int cont_size;
+ int flag1;
+ int flag2;
+ unsigned char *pnts;
+ char symlinkname[1024];
+ char name[1024];
+ int goof;
+
+/* printf(" RRlen=%d ", len); */
+
+ symlinkname[0] = 0;
+
+ cont_extent = (off_t)0;
+ cont_offset = cont_size = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while (len >= 4) {
+ if (ncount)
+ printf(",");
+ else
+ printf("[");
+ printf("%c%c", pnt[0], pnt[1]);
+ if (pnt[3] != 1 && pnt[3] != 2) {
+ printf("**BAD RRVERSION (%d) for %c%c\n", pnt[3], pnt[0], pnt[1]);
+ return (0); /* JS ??? Is this right ??? */
+ } else if (pnt[0] == 'R' && pnt[1] == 'R') {
+ printf("=%d", pnt[3]);
+ }
+ ncount++;
+ if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1;
+ if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2;
+ if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4;
+ if (strncmp((char *)pnt, "NM", 2) == 0) {
+ slen = pnt[2] - 5;
+ pnts = pnt+5;
+ if ((pnt[4] & 6) != 0) {
+ printf("*");
+ }
+ memset(name, 0, sizeof (name));
+ memcpy(name, pnts, slen);
+ printf("=%s", name);
+ flag2 |= 8;
+ }
+ if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16;
+ if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32;
+ if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64;
+ if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128;
+
+ if (strncmp((char *)pnt, "PX", 2) == 0) {
+ extent = isonum_733(pnt+12);
+ printf("=%x", extent);
+ }
+
+ if (strncmp((char *)pnt, "CE", 2) == 0) {
+ cont_extent = (off_t)isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ printf("=[%x,%x,%d]", (int)cont_extent, cont_offset,
+ cont_size);
+ }
+
+ if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ printf("=%x", extent);
+ }
+
+ if (strncmp((char *)pnt, "SL", 2) == 0) {
+ int cflag;
+
+ cflag = pnt[4];
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while (slen >= 1) {
+ switch (pnts[0] & 0xfe) {
+ case 0:
+ strncat(symlinkname, (char *)(pnts+2), pnts[1]);
+ break;
+ case 2:
+ strcat(symlinkname, ".");
+ break;
+ case 4:
+ strcat(symlinkname, "..");
+ break;
+ case 8:
+ if ((pnts[0] & 1) == 0)
+ strcat(symlinkname, "/");
+ break;
+ case 16:
+ strcat(symlinkname, "/mnt");
+ printf("Warning - mount point requested");
+ break;
+ case 32:
+ strcat(symlinkname, "kafka");
+ printf("Warning - host_name requested");
+ break;
+ default:
+ printf("Reserved bit setting in symlink");
+ goof++;
+ break;
+ }
+ if ((pnts[0] & 0xfe) && pnts[1] != 0) {
+ printf("Incorrect length in symlink component");
+ }
+ if ((pnts[0] & 1) == 0)
+ strcat(symlinkname, "/");
+
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+ }
+ if (cflag)
+ strcat(symlinkname, "+");
+ printf("=%s", symlinkname);
+ symlinkname[0] = 0;
+ }
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if (len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+
+#ifdef USE_SCG
+ readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+ lseek(fileno(infile), cont_extent * blocksize, SEEK_SET);
+ read(fileno(infile), sector, sizeof (sector));
+#endif
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ }
+ }
+ if (ncount)
+ printf("]");
+ if (!cont_flag && flag1 != flag2) {
+ printf("Flag %x != %x", flag1, flag2);
+ goof++;
+ }
+ return (flag2);
+}
+
+static void
+dump_rr(struct iso_directory_record *idr)
+{
+ int len;
+ unsigned char *pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= offsetof(struct iso_directory_record, name[0]);
+ len -= idr->name_len[0];
+ pnt = (unsigned char *) idr;
+ pnt += offsetof(struct iso_directory_record, name[0]);
+ pnt += idr->name_len[0];
+ if ((idr->name_len[0] & 1) == 0) {
+ pnt++;
+ len--;
+ }
+ parse_rr(pnt, len, 0);
+}
+
+
+static void
+showblock(int flag)
+{
+ int i;
+ int j;
+ int line;
+ struct iso_directory_record *idr;
+
+#ifdef USE_SCG
+ readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+ lseek(fileno(infile), file_addr, SEEK_SET);
+ read(fileno(infile), buffer, sizeof (buffer));
+#endif
+ for (i = 0; i < 60; i++)
+ printf("\n");
+ fflush(stdout);
+ i = line = 0;
+ if (flag) {
+ while (1 == 1) {
+ crsr2(line+3, 1);
+ idr = (struct iso_directory_record *) &buffer[i];
+ if (idr->length[0] == 0)
+ break;
+ printf("%3d ", idr->length[0]);
+ printf("[%2d] ", idr->volume_sequence_number[0]);
+ printf("%5x ", isonum_733(idr->extent));
+ printf("%8d ", isonum_733(idr->size));
+ printf("%02x/", idr->flags[0]);
+ printf((idr->flags[0] & 2) ? "*" : " ");
+ if (idr->name_len[0] == 1 && idr->name[0] == 0)
+ printf(". ");
+ else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+ printf(".. ");
+ else {
+ for (j = 0; j < (int)idr->name_len[0]; j++) printf("%c", idr->name[j]);
+ for (j = 0; j < (14 - (int)idr->name_len[0]); j++) printf(" ");
+ }
+ dump_rr(idr);
+ printf("\n");
+ i += buffer[i];
+ if (i > 2048 - offsetof(struct iso_directory_record, name[0]))
+ break;
+ line++;
+ }
+ }
+ printf("\n");
+ if (sizeof (file_addr) > sizeof (long)) {
+ printf(" Zone, zone offset: %14llx %12.12llx ",
+ (Llong)file_addr / blocksize,
+ (Llong)file_addr & (Llong)(blocksize - 1));
+ } else {
+ printf(" Zone, zone offset: %6lx %4.4lx ",
+ (long) (file_addr / blocksize),
+ (long) file_addr & (blocksize - 1));
+ }
+ fflush(stdout);
+}
+
+static int
+getbyte()
+{
+ char c1;
+
+ c1 = buffer[file_addr & (blocksize-1)];
+ file_addr++;
+ if ((file_addr & (blocksize-1)) == 0)
+ showblock(0);
+ return (c1);
+}
+
+static void
+usage(int excode)
+{
+ errmsgno(EX_BAD, "Usage: %s [options] image\n",
+ get_progname());
+
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-help, -h Print this help\n");
+ fprintf(stderr, "\t-version Print version info and exit\n");
+ fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n");
+ fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n");
+ fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+ exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cac;
+ char * const *cav;
+ char *opts = "help,h,version,i*,dev*";
+ BOOL help = FALSE;
+ BOOL prvers = FALSE;
+ char *filename = NULL;
+ char *devname = NULL;
+ char c;
+ int i;
+ struct iso_primary_descriptor ipd;
+ struct iso_directory_record *idr;
+
+ save_args(argc, argv);
+
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+ &filename, &devname) < 0) {
+ errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (help)
+ usage(0);
+ if (prvers) {
+ printf("isodump %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+ exit(0);
+ }
+ cac = argc - 1;
+ cav = argv + 1;
+ if (filename == NULL && devname == NULL) {
+ if (getfiles(&cac, &cav, opts) != 0) {
+ filename = cav[0];
+ cac--, cav++;
+ }
+ }
+ if (getfiles(&cac, &cav, opts) != 0) {
+ errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (filename != NULL && devname != NULL) {
+ errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+ usage(EX_BAD);
+ }
+#ifdef USE_SCG
+ if (filename == NULL && devname == NULL)
+ cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+ if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+ errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+ fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+ usage(EX_BAD);
+ }
+
+ if (filename != NULL)
+ infile = fopen(filename, "rb");
+ else
+ filename = devname;
+
+ if (infile != NULL) {
+ /* EMPTY */;
+#ifdef USE_SCG
+ } else if (scsidev_open(filename) < 0) {
+#else
+ } else {
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot open '%s'\n", filename);
+#else
+ fprintf(stderr, "Cannot open '%s'\n", filename);
+ exit(1);
+#endif
+ }
+
+ file_addr = (off_t) (16 << 11);
+#ifdef USE_SCG
+ readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+ lseek(fileno(infile), file_addr, SEEK_SET);
+ read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+ idr = (struct iso_directory_record *)ipd.root_directory_record;
+
+ blocksize = isonum_723((char *)ipd.logical_block_size);
+ if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) {
+ blocksize = 2048;
+ }
+
+ file_addr = (off_t)isonum_733(idr->extent);
+ file_addr = file_addr * blocksize;
+
+/* Now setup the keyboard for single character input. */
+#ifdef USE_V7_TTY
+ if (ioctl(STDIN_FILENO, TIOCGETP, &savetty) == -1) {
+#else
+#ifdef TCSANOW
+ if (tcgetattr(STDIN_FILENO, &savetty) == -1) {
+#else
+ if (ioctl(STDIN_FILENO, TCGETA, &savetty) == -1) {
+#endif
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Stdin must be a tty\n");
+#else
+ printf("Stdin must be a tty\n");
+ exit(1);
+#endif
+ }
+ newtty = savetty;
+#ifdef USE_V7_TTY
+ newtty.sg_flags &= ~(ECHO|CRMOD);
+ newtty.sg_flags |= CBREAK;
+#else
+ newtty.c_lflag &= ~ICANON;
+ newtty.c_lflag &= ~ECHO;
+ newtty.c_cc[VMIN] = 1;
+#endif
+ set_tty();
+#ifdef SIGTSTP
+ signal(SIGTSTP, onsusp);
+#endif
+ on_comerr((void(*)(int, void *))reset_tty, NULL);
+
+ do {
+ if (file_addr < 0)
+ file_addr = (off_t)0;
+ showblock(1);
+ read(STDIN_FILENO, &c, 1); /* FIXME: check return value */
+ if (c == 'a')
+ file_addr -= blocksize;
+ if (c == 'b')
+ file_addr += blocksize;
+ if (c == 'g') {
+ crsr2(20, 1);
+ printf("Enter new starting block (in hex):");
+ if (sizeof (file_addr) > sizeof (long)) {
+ Llong ll;
+ scanf("%llx", &ll); /* FIXME: check return value */
+ file_addr = (off_t)ll;
+ } else {
+ long l;
+ scanf("%lx", &l); /* FIXME: check return value */
+ file_addr = (off_t)l;
+ }
+ file_addr = file_addr * blocksize;
+ crsr2(20, 1);
+ printf(" ");
+ }
+ if (c == 'f') {
+ crsr2(20, 1);
+ printf("Enter new search string:");
+ fgets((char *)search, sizeof (search), stdin); /* FIXME: check return value */
+ while (search[strlen((char *)search)-1] == '\n')
+ search[strlen((char *)search)-1] = 0;
+ crsr2(20, 1);
+ printf(" ");
+ }
+ if (c == '+') {
+ while (1 == 1) {
+ int slen;
+
+ while (1 == 1) {
+ c = getbyte();
+ if (c == search[0])
+ break;
+ }
+ slen = (int)strlen((char *)search);
+ for (i = 1; i < slen; i++) {
+ if (search[i] != getbyte())
+ break;
+ }
+ if (i == slen)
+ break;
+ }
+ file_addr &= ~(blocksize-1);
+ showblock(1);
+ }
+ if (c == 'q')
+ break;
+ } while (1 == 1);
+ reset_tty();
+ if (infile != NULL)
+ fclose(infile);
+ return (0);
+}
diff --git a/genisoimage/diag/isoinfo.1 b/genisoimage/diag/isoinfo.1
new file mode 100644
index 0000000..1a00540
--- /dev/null
+++ b/genisoimage/diag/isoinfo.1
@@ -0,0 +1,365 @@
+.\"
+.\" @(#)isoinfo.8 1.7 04/06/01 joerg
+.\"
+.\" Modified for cdrkit in 12/2006
+.\"
+.\" -*- nroff -*-
+.if t .ds a \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'a
+.if t .ds o \v'-0.55m'\h'0.00n'\z.\h'0.45n'\z.\v'0.55m'\h'-0.45n'o
+.if t .ds u \v'-0.55m'\h'0.00n'\z.\h'0.40n'\z.\v'0.55m'\h'-0.40n'u
+.if t .ds A \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'A
+.if t .ds O \v'-0.77m'\h'0.25n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.70n'O
+.if t .ds U \v'-0.77m'\h'0.30n'\z.\h'0.45n'\z.\v'0.77m'\h'-0.75n'U
+.if t .ds s \\(*b
+.if t .ds S SS
+.if n .ds a ae
+.if n .ds o oe
+.if n .ds u ue
+.if n .ds s sz
+.TH ISOINFO 1 "04/06/01" "Version 2.0"
+.SH NAME
+devdump, isoinfo, isovfy, isodump \- Utility programs for dumping and verifying iso9660
+images.
+.SH SYNOPSIS
+.B devdump
+.I isoimage
+.PP
+.B isodump
+.I isoimage
+.PP
+.B isoinfo
+[
+.B \-d
+]
+[
+.B \-h
+]
+[
+.B \-R
+]
+[
+.B \-J
+]
+[
+.B \-j
+.I charset
+]
+[
+.B \-f
+]
+[
+.B \-l
+]
+[
+.B \-p
+]
+[
+.B \-T
+.I sector
+]
+[
+.B \-N
+.I sector
+]
+[
+.B \-i
+.I isoimage
+]
+[
+.B \-x
+.I path
+]
+.PP
+.B isovfy
+.I isoimage
+.SH DESCRIPTION
+.B devdump
+is a crude utility to interactively display the contents of device or
+filesystem images.
+The initial screen is a display of the first 256 bytes of the first 2048 byte
+sector.
+The commands are the same as with
+.BR isodump .
+.PP
+.B isodump
+is a crude utility to interactively display the contents of iso9660 images
+in order to verify directory integrity.
+The initial screen is a display of the first part of the root directory,
+and the prompt shows you the extent number and offset in the extent.
+.RS
+.PP
+You can use the 'a' and 'b'
+commands to move backwards and forwards within the image. The 'g' command
+allows you to goto an arbitrary extent, and the 'f' command specifies
+a search string to be used. The '+' command searches forward for the next
+instance of the search string, and the 'q' command exits
+.B devdump
+or
+.BR isodump .
+.RE
+.PP
+.B isoinfo
+is a utility to perform directory like listings of iso9660 images.
+.PP
+.B isovfy
+is a utility to verify the integrity of an iso9660 image. Most of the tests
+in
+.B isovfy
+were added after bugs were discovered in early versions of
+.B genisoimage.
+It isn't all that clear how useful this is anymore, but it doesn't hurt to
+have this around.
+
+.SH OPTIONS
+The options common to all programs are
+.BR \-help , \-h , \-version ,
+.BI i =name, dev =name.
+The
+.B isoinfo
+program has additional command line options. The options are:
+.TP
+.B \-help
+.TP
+.B \-h
+print a summary of all options.
+.TP
+.B \-d
+Print information from the primary volume descriptor (PVD) of the iso9660
+image. This includes information about Rock Ridge, Joliet extensions
+and Eltorito boot information
+if present.
+.TP
+.B \-f
+generate output as if a 'find . -print' command had been run on the iso9660
+image. You should not use the
+.B -l
+image with the
+.B -f
+option.
+.TP
+.B \-i iso_image
+Specifies the path of the iso9660 image that we wish to examine.
+The options
+.B \-i
+and
+.BI dev= target
+are mutual exclusive.
+.TP
+.BI dev= target
+Sets the SCSI target for the drive, see notes above.
+A typical device specification is
+.BI dev= 6,0
+\&.
+If a filename must be provided together with the numerical target
+specification, the filename is implementation specific.
+The correct filename in this case can be found in the system specific
+manuals of the target operating system.
+On a
+.I FreeBSD
+system without
+.I CAM
+support, you need to use the control device (e.g.
+.IR /dev/rcd0.ctl ).
+A correct device specification in this case may be
+.BI dev= /dev/rcd0.ctl:@
+\&.
+.sp
+On Linux, drives connected to a parallel port adapter are mapped
+to a virtual SCSI bus. Different adapters are mapped to different
+targets on this virtual SCSI bus.
+.sp
+If no
+.I dev
+option is present, the program
+will try to get the device from the
+.B CDR_DEVICE
+environment.
+.sp
+If the argument to the
+.B dev=
+option does not contain the characters ',', '/', '@' or ':',
+it is interpreted as an label name that may be found in the file
+/etc/wodim.conf (see FILES section).
+.sp
+The options
+.B \-i
+and
+.BI dev= target
+are mutual exclusive.
+.TP
+.B \-l
+generate output as if a 'ls -lR' command had been run on the iso9660 image.
+You should not use the
+.B -f
+image with the
+.B -l
+option.
+.TP
+.B \-N sector
+Quick hack to help examine single session disc files that are to be written to
+a multi-session disc. The sector number specified is the sector number at
+which the iso9660 image should be written when send to the cd-writer. Not
+used for the first session on the disc.
+.TP
+.B \-p
+Print path table information.
+.TP
+.B \-R
+Extract information from Rock Ridge extensions (if present) for permissions,
+file names and ownerships.
+.TP
+.B \-J
+Extract information from Joliet extensions (if present) for file names.
+.TP
+.B \-j charset
+Convert Joliet file names (if present) to the supplied charset. See
+.BR genisoimage (8)
+for details.
+.TP
+.B \-T sector
+Quick hack to help examine multi-session images that have already been burned
+to a multi-session disc. The sector number specified is the sector number for
+the start of the session we wish to display.
+.TP
+.B \-x pathname
+Extract specified file to stdout.
+.SH AUTHOR
+The author of the original sources (1993 .\|.\|. 1998) is
+Eric Youngdale <ericy@gnu.ai.mit.edu> or <eric@andante.jic.com> is to blame
+for these shoddy hacks.
+J\*org Schilling wrote the SCSI transport library and its adaptation layer to
+the programs and newer parts (starting from 1999) of the utilities, this makes
+them
+Copyright (C) 1999-2004 J\*org Schilling.
+Patches to improve general usability would be gladly accepted.
+.PP
+This manpage describes the program implementation of
+.B
+isoinfo
+as shipped by the cdrkit distribution. See
+.B
+http://alioth.debian.org/projects/debburn/
+for details. It is a spinoff from the original program distributed in the
+cdrtools package [1]. However, the cdrtools
+developers are not involved in the development of this spinoff and therefore
+shall not be made responsible for any problem caused by it. Do not try to get
+support for this program by contacting the original author(s).
+.PP
+If you have support questions, send them to
+.PP
+.B
+debburn-devel@lists.alioth.debian.org
+.br
+.PP
+If you have definitely found a bug, send a mail to this list or to
+.PP
+.B
+submit@bugs.debian.org
+.br
+.PP
+writing at least a short description into the Subject and "Package: cdrkit" into the first line of the mail body.
+.SH BUGS
+The user interface really sucks.
+.SH FUTURE IMPROVEMENTS
+These utilities are really quick hacks, which are very useful for debugging
+problems in genisoimage or in an iso9660 filesystem. In the long run, it would
+be nice to have a daemon that would NFS export a iso9660 image.
+.PP
+The isoinfo program is probably the program that is of the most use to
+the general user.
+.SH AVAILABILITY
+These utilities come with the
+.B cdrkit
+package, and the primary download site
+is http://debburn.alioth.debian.org/ and FTP mirrors of distributions.
+Despite the name, the software is not beta.
+
+.SH ENVIRONMENT
+.TP
+.B CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf.
+.TP
+.B RSH
+If the
+.B RSH
+environment is present, the remote connection will not be created via
+.BR rcmd (3)
+but by calling the program pointed to by
+.BR RSH .
+Use e.g.
+.BR RSH= /usr/bin/ssh
+to create a secure shell connection.
+.sp
+Note that this forces the program
+to create a pipe to the
+.B rsh(1)
+program and disallows the program
+to directly access the network socket to the remote server.
+This makes it impossible to set up performance parameters and slows down
+the connection compared to a
+.B root
+initiated
+.B rcmd(3)
+connection.
+.TP
+.B RSCSI
+If the
+.B RSCSI
+environment is present, the remote SCSI server will not be the program
+.B /opt/schily/sbin/rscsi
+but the program pointed to by
+.BR RSCSI .
+Note that the remote SCSI server program name will be ignored if you log in
+using an account that has been created with a remote SCSI server program as
+login shell.
+
+.SH FILES
+.TP
+/etc/wodim.conf
+Default values can be set for the following options in /etc/wodim.conf.
+.RS
+.TP
+CDR_DEVICE
+This may either hold a device identifier that is suitable to the open
+call of the SCSI transport library or a label in the file /etc/wodim.conf
+that allows to identify a specific drive on the system.
+.TP
+Any other label
+is an identifier for a specific drive on the system.
+Such an identifier may not contain the characters ',', '/', '@' or ':'.
+.sp
+Each line that follows a label contains a TAB separated list of items.
+Currently, four items are recognized: the SCSI ID of the drive, the
+default speed that should be used for this drive, the default FIFO size
+that should be used for this drive and drive specific options. The values for
+.I speed
+and
+.I fifosize
+may be set to -1 to tell the program to use the global defaults.
+The value for driveropts may be set to "" if no driveropts are used.
+A typical line may look this way:
+.sp
+teac1= 0,5,0 4 8m ""
+.sp
+yamaha= 1,6,0 -1 -1 burnfree
+.sp
+This tells the program
+that a drive named
+.I teac1
+is at scsibus 0, target 5, lun 0 and should be used with speed 4 and
+a FIFO size of 8 MB.
+A second drive may be found at scsibus 1, target 6, lun 0 and uses the
+default speed and the default FIFO size.
+.RE
+.SH SEE ALSO
+.BR genisoimage (1),
+.BR wodim (1),
+.BR readcd (1),
+.BR ssh (1).
+.RE
+.SH SOURCES
+.PP
+.br
+[1] Cdrtools 2.01.01a08 from May 2006, http://cdrecord.berlios.de
+
diff --git a/genisoimage/diag/isoinfo.c b/genisoimage/diag/isoinfo.c
new file mode 100644
index 0000000..55396c2
--- /dev/null
+++ b/genisoimage/diag/isoinfo.c
@@ -0,0 +1,1321 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isoinfo.c 1.50 05/05/15 joerg */
+/*
+ * File isodump.c - dump iso9660 directory information.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Simple program to dump contents of iso9660 image in more usable format.
+ *
+ * Usage:
+ * To list contents of image (with or without RR):
+ * isoinfo -l [-R] -i imagefile
+ * To extract file from image:
+ * isoinfo -i imagefile -x xtractfile > outfile
+ * To generate a "find" like list of files:
+ * isoinfo -f -i imagefile
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+
+#include <stdio.h>
+#include <utypes.h>
+#include <standard.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <statdefs.h>
+#include <fctldefs.h>
+#include <schily.h>
+
+#include "../iso9660.h"
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+#include <unls.h>
+
+#if defined(__CYGWIN32__) || defined(__EMX__) || defined(__DJGPP__)
+#include <io.h> /* for setmode() prototype */
+#endif
+
+/*
+ * Make sure we have a definition for this. If not, take a very conservative
+ * guess.
+ * POSIX requires the max pathname component lenght to be defined in limits.h
+ * If variable, it may be undefined. If undefined, there should be
+ * a definition for _POSIX_NAME_MAX in limits.h or in unistd.h
+ * As _POSIX_NAME_MAX is defined to 14, we cannot use it.
+ * XXX Eric's wrong comment:
+ * XXX From what I can tell SunOS is the only one with this trouble.
+ */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef NAME_MAX
+#ifdef FILENAME_MAX
+#define NAME_MAX FILENAME_MAX
+#else
+#define NAME_MAX 256
+#endif
+#endif
+
+#ifndef PATH_MAX
+#ifdef FILENAME_MAX
+#define PATH_MAX FILENAME_MAX
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#ifndef S_ISSOCK
+#ifdef S_IFSOCK
+# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#else
+# define S_ISSOCK(m) (0)
+#endif
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X) may cause an integer overflow and thus give
+ * incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
+ */
+#define SECTOR_SIZE (2048)
+#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define infile in_image
+FILE *infile = NULL;
+int use_rock = 0;
+int use_joliet = 0;
+int do_listing = 0;
+int do_find = 0;
+int do_sectors = 0;
+int do_pathtab = 0;
+int do_pvd = 0;
+BOOL debug = FALSE;
+char *xtract = 0;
+int su_version = 0;
+int aa_version = 0;
+int ucs_level = 0;
+
+struct stat fstat_buf;
+int found_rr;
+char name_buf[256];
+char xname[2048];
+unsigned char date_buf[9];
+/*
+ * Use sector_offset != 0 (-N #) if we have an image file
+ * of a single session and we need to list the directory contents.
+ * This is the session block (sector) number of the start
+ * of the session when it would be on disk.
+ */
+unsigned int sector_offset = 0;
+
+unsigned char buffer[2048];
+
+struct unls_table *unls;
+
+#define PAGE sizeof (buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+
+int isonum_721(char * p);
+int isonum_723(char * p);
+int isonum_731(char * p);
+int isonum_732(char * p);
+int isonum_733(unsigned char * p);
+void printchars(char *s, int n);
+char *sdate(char *dp);
+void dump_pathtab(int block, int size);
+int parse_rr(unsigned char * pnt, int len, int cont_flag);
+void find_rr(struct iso_directory_record * idr, Uchar **pntp, int *lenp);
+int dump_rr(struct iso_directory_record * idr);
+void dump_stat(struct iso_directory_record * idr, int extent);
+void extract_file(struct iso_directory_record * idr);
+void parse_dir(char * rootname, int extent, int len);
+void usage(int excode);
+
+static void printf_bootinfo(FILE *f, int bootcat_offset);
+static char *arch_name(int val);
+static char *boot_name(int val);
+static char *bootmedia_name(int val);
+
+
+int
+isonum_721(char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8));
+}
+
+int
+isonum_723(char *p)
+{
+#if 0
+ if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+ comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+ fprintf(stderr, "invalid format 7.2.3 number\n");
+ exit(1);
+#endif
+ }
+#endif
+ return (isonum_721(p));
+}
+
+int
+isonum_731(char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+int
+isonum_732(char *p)
+{
+ return ((p[3] & 0xff)
+ | ((p[2] & 0xff) << 8)
+ | ((p[1] & 0xff) << 16)
+ | ((p[0] & 0xff) << 24));
+}
+
+int
+isonum_733(unsigned char *p)
+{
+ return (isonum_731((char *)p));
+}
+
+void
+printchars(char *s, int n)
+{
+ int i;
+ char *p;
+
+ for (; n > 0 && *s; n--) {
+ if (*s == ' ') {
+ p = s;
+ i = n;
+ while (--i >= 0 && *p++ == ' ')
+ ;
+ if (i <= 0)
+ break;
+ }
+ putchar(*s++);
+ }
+}
+
+/*
+ * Print date info from PVD
+ */
+char *
+sdate(char *dp)
+{
+ static char d[30];
+
+ sprintf(d, "%4.4s %2.2s %2.2s %2.2s:%2.2s:%2.2s.%2.2s",
+ &dp[0], /* Year */
+ &dp[4], /* Month */
+ &dp[6], /* Monthday */
+ &dp[8], /* Hour */
+ &dp[10], /* Minute */
+ &dp[12], /* Seconds */
+ &dp[14]); /* Hunreds of a Seconds */
+
+ /*
+ * dp[16] contains minute offset from Greenwich
+ * Positive values are to the east of Greenwich.
+ */
+ return (d);
+}
+
+void
+dump_pathtab(int block, int size)
+{
+ unsigned char *buf;
+ int offset;
+ int idx;
+ int extent;
+ int pindex;
+ int j;
+ int len;
+ int jlen;
+ char namebuf[255];
+ unsigned char uh, ul, uc, *up;
+
+
+ printf("Path table starts at block %d, size %d\n", block, size);
+
+ buf = (unsigned char *) malloc(ISO_ROUND_UP(size));
+
+#ifdef USE_SCG
+ readsecs(block - sector_offset, buf, ISO_BLOCKS(size));
+#else
+ lseek(fileno(infile), ((off_t)(block - sector_offset)) << 11, SEEK_SET);
+ read(fileno(infile), buf, size);
+#endif
+
+ offset = 0;
+ idx = 1;
+ while (offset < size) {
+ len = buf[offset];
+ extent = isonum_731((char *)buf + offset + 2);
+ pindex = isonum_721((char *)buf + offset + 6);
+ switch (ucs_level) {
+ case 3:
+ case 2:
+ case 1:
+ jlen = len/2;
+ namebuf[0] = '\0';
+ for (j = 0; j < jlen; j++) {
+ uh = buf[offset + 8 + j*2];
+ ul = buf[offset + 8 + j*2+1];
+
+ up = unls->unls_uni2cs[uh];
+
+ if (up == NULL)
+ uc = '\0';
+ else
+ uc = up[ul];
+
+ namebuf[j] = uc ? uc : '_';
+ }
+ printf("%4d: %4d %x %.*s\n",
+ idx, pindex, extent, jlen, namebuf);
+ break;
+ case 0:
+ printf("%4d: %4d %x %.*s\n",
+ idx, pindex, extent, len, buf + offset + 8);
+ }
+
+ idx++;
+ offset += 8 + len;
+ if (offset & 1)
+ offset++;
+ }
+
+ free(buf);
+}
+
+int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+ int slen;
+ int xlen;
+ int ncount;
+ int extent;
+ int cont_extent, cont_offset, cont_size;
+ int flag1, flag2;
+ unsigned char *pnts;
+ char symlinkname[1024];
+ int goof;
+
+ symlinkname[0] = 0;
+
+ cont_extent = cont_offset = cont_size = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while (len >= 4) {
+ if (pnt[3] != 1 && pnt[3] != 2) {
+ printf("**BAD RRVERSION (%d)\n", pnt[3]);
+ return (0); /* JS ??? Is this right ??? */
+ }
+ ncount++;
+ if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1; /* POSIX attributes */
+ if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2; /* POSIX device number */
+ if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4; /* Symlink */
+ if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8; /* Alternate Name */
+ if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16; /* Child link */
+ if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32; /* Parent link */
+ if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64; /* Relocated Direcotry */
+ if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128; /* Time stamp */
+ if (strncmp((char *)pnt, "SP", 2) == 0) {
+ flag2 |= 1024; /* SUSP record */
+ su_version = pnt[3] & 0xff;
+ }
+ if (strncmp((char *)pnt, "AA", 2) == 0) {
+ flag2 |= 2048; /* Apple Signature record */
+ aa_version = pnt[3] & 0xff;
+ }
+
+ if (strncmp((char *)pnt, "PX", 2) == 0) { /* POSIX attributes */
+ fstat_buf.st_mode = isonum_733(pnt+4);
+ fstat_buf.st_nlink = isonum_733(pnt+12);
+ fstat_buf.st_uid = isonum_733(pnt+20);
+ fstat_buf.st_gid = isonum_733(pnt+28);
+ }
+
+ if (strncmp((char *)pnt, "NM", 2) == 0) { /* Alternate Name */
+ int l = strlen(name_buf);
+
+ if (!found_rr)
+ l = 0;
+ strncpy(&name_buf[l], (char *)(pnt+5), pnt[2] - 5);
+ name_buf[l + pnt[2] - 5] = 0;
+ found_rr = 1;
+ }
+
+ if (strncmp((char *)pnt, "CE", 2) == 0) { /* Continuation Area */
+ cont_extent = isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ }
+
+ if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ }
+
+ if (strncmp((char *)pnt, "SL", 2) == 0) { /* Symlink */
+ int cflag;
+
+ cflag = pnt[4];
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while (slen >= 1) {
+ switch (pnts[0] & 0xfe) {
+ case 0:
+ strncat(symlinkname, (char *)(pnts+2), pnts[1]);
+ symlinkname[pnts[1]] = 0;
+ break;
+ case 2:
+ strcat(symlinkname, ".");
+ break;
+ case 4:
+ strcat(symlinkname, "..");
+ break;
+ case 8:
+ strcat(symlinkname, "/");
+ break;
+ case 16:
+ strcat(symlinkname, "/mnt");
+ printf("Warning - mount point requested");
+ break;
+ case 32:
+ strcat(symlinkname, "kafka");
+ printf("Warning - host_name requested");
+ break;
+ default:
+ printf("Reserved bit setting in symlink");
+ goof++;
+ break;
+ }
+ if ((pnts[0] & 0xfe) && pnts[1] != 0) {
+ printf("Incorrect length in symlink component");
+ }
+ if (xname[0] == 0) strcpy(xname, "-> ");
+ strcat(xname, symlinkname);
+ symlinkname[0] = 0;
+ xlen = strlen(xname);
+ if ((pnts[0] & 1) == 0 && xname[xlen-1] != '/') strcat(xname, "/");
+
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+ }
+ symlinkname[0] = 0;
+ }
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if (len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+
+#ifdef USE_SCG
+ readsecs(cont_extent - sector_offset, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+ lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET);
+ read(fileno(infile), sector, sizeof (sector));
+#endif
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ }
+ }
+ /*
+ * for symbolic links, strip out the last '/'
+ */
+ if (xname[0] != 0 && xname[strlen(xname)-1] == '/') {
+ xname[strlen(xname)-1] = '\0';
+ }
+ return (flag2);
+}
+
+void
+find_rr(struct iso_directory_record *idr, Uchar **pntp, int *lenp)
+{
+ struct iso_xa_dir_record *xadp;
+ int len;
+ unsigned char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= offsetof(struct iso_directory_record, name[0]);
+ len -= idr->name_len[0];
+
+ pnt = (unsigned char *) idr;
+ pnt += offsetof(struct iso_directory_record, name[0]);
+ pnt += idr->name_len[0];
+ if ((idr->name_len[0] & 1) == 0) {
+ pnt++;
+ len--;
+ }
+ if (len >= 14) {
+ xadp = (struct iso_xa_dir_record *)pnt;
+
+ if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A' &&
+ xadp->reserved[0] == '\0') {
+ len -= 14;
+ pnt += 14;
+ }
+ }
+ *pntp = pnt;
+ *lenp = len;
+}
+
+int
+dump_rr(struct iso_directory_record *idr)
+{
+ int len;
+ unsigned char * pnt;
+
+ find_rr(idr, &pnt, &len);
+ return (parse_rr(pnt, len, 0));
+}
+
+struct todo
+{
+ struct todo *next;
+ char *name;
+ int extent;
+ int length;
+};
+
+struct todo *todo_idr = NULL;
+
+char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+void
+dump_stat(struct iso_directory_record *idr, int extent)
+{
+ int i;
+ char outline[80];
+
+ memset(outline, ' ', sizeof (outline));
+
+ if (S_ISREG(fstat_buf.st_mode))
+ outline[0] = '-';
+ else if (S_ISDIR(fstat_buf.st_mode))
+ outline[0] = 'd';
+ else if (S_ISLNK(fstat_buf.st_mode))
+ outline[0] = 'l';
+ else if (S_ISCHR(fstat_buf.st_mode))
+ outline[0] = 'c';
+ else if (S_ISBLK(fstat_buf.st_mode))
+ outline[0] = 'b';
+ else if (S_ISFIFO(fstat_buf.st_mode))
+ outline[0] = 'f';
+ else if (S_ISSOCK(fstat_buf.st_mode))
+ outline[0] = 's';
+ else
+ outline[0] = '?';
+
+ memset(outline+1, '-', 9);
+ if (fstat_buf.st_mode & S_IRUSR)
+ outline[1] = 'r';
+ if (fstat_buf.st_mode & S_IWUSR)
+ outline[2] = 'w';
+ if (fstat_buf.st_mode & S_IXUSR)
+ outline[3] = 'x';
+
+ if (fstat_buf.st_mode & S_IRGRP)
+ outline[4] = 'r';
+ if (fstat_buf.st_mode & S_IWGRP)
+ outline[5] = 'w';
+ if (fstat_buf.st_mode & S_IXGRP)
+ outline[6] = 'x';
+
+ if (fstat_buf.st_mode & S_IROTH)
+ outline[7] = 'r';
+ if (fstat_buf.st_mode & S_IWOTH)
+ outline[8] = 'w';
+ if (fstat_buf.st_mode & S_IXOTH)
+ outline[9] = 'x';
+
+ /*
+ * XXX This is totally ugly code from Eric.
+ * XXX If one field is wider than expected then it is truncated.
+ */
+ sprintf(outline+11, "%3ld", (long)fstat_buf.st_nlink);
+ sprintf(outline+15, "%4lo", (unsigned long)fstat_buf.st_uid);
+ sprintf(outline+20, "%4lo", (unsigned long)fstat_buf.st_gid);
+ sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size);
+
+ if (do_sectors == 0) {
+ sprintf(outline+30, "%10lld", (Llong)fstat_buf.st_size);
+ } else {
+ sprintf(outline+30, "%10lld", (Llong)((fstat_buf.st_size+PAGE-1)/PAGE));
+ }
+
+ if (date_buf[1] >= 1 && date_buf[1] <= 12) {
+ memcpy(outline+41, months[date_buf[1]-1], 3);
+ }
+
+ sprintf(outline+45, "%2d", date_buf[2]);
+ outline[63] = 0;
+ sprintf(outline+48, "%4d", date_buf[0]+1900);
+
+ sprintf(outline+53, "[%7d", extent); /* XXX up to 20 GB */
+ sprintf(outline+61, " %02X]", idr->flags[0]);
+
+ for (i = 0; i < 66; i++) {
+ if (outline[i] == 0) outline[i] = ' ';
+ }
+ outline[66] = 0;
+ printf("%s %s %s\n", outline, name_buf, xname);
+}
+
+void
+extract_file(struct iso_directory_record *idr)
+{
+ int extent, len, tlen;
+ unsigned char buff[2048];
+
+#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__EMX__) || defined(__DJGPP__)
+ setmode(fileno(stdout), O_BINARY);
+#endif
+
+ extent = isonum_733((unsigned char *)idr->extent);
+ len = isonum_733((unsigned char *)idr->size);
+
+ while (len > 0) {
+#ifdef USE_SCG
+ readsecs(extent - sector_offset, buff, ISO_BLOCKS(sizeof (buff)));
+ tlen = (len > sizeof (buff) ? sizeof (buff) : len);
+#else
+ lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
+ tlen = (len > sizeof (buff) ? sizeof (buff) : len);
+ read(fileno(infile), buff, tlen);
+#endif
+ len -= tlen;
+ extent++;
+ write(STDOUT_FILENO, buff, tlen); /* FIXME: check return value */
+ }
+}
+
+void
+parse_dir(char *rootname, int extent, int len)
+{
+ char testname[PATH_MAX+1];
+ struct todo *td;
+ int i;
+ struct iso_directory_record * idr;
+ unsigned char uh, ul, uc, *up;
+
+
+ if (do_listing)
+ printf("\nDirectory listing of %s\n", rootname);
+
+ while (len > 0) {
+#ifdef USE_SCG
+ readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+ lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
+ read(fileno(infile), buffer, sizeof (buffer));
+#endif
+ len -= sizeof (buffer);
+ extent++;
+ i = 0;
+ while (1 == 1) {
+ idr = (struct iso_directory_record *) &buffer[i];
+ if (idr->length[0] == 0) break;
+ memset(&fstat_buf, 0, sizeof (fstat_buf));
+ found_rr = 0;
+ name_buf[0] = xname[0] = 0;
+ fstat_buf.st_size = (off_t)(unsigned)isonum_733((unsigned char *)idr->size);
+ if (idr->flags[0] & 2)
+ fstat_buf.st_mode |= S_IFDIR;
+ else
+ fstat_buf.st_mode |= S_IFREG;
+ if (idr->name_len[0] == 1 && idr->name[0] == 0)
+ strcpy(name_buf, ".");
+ else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+ strcpy(name_buf, "..");
+ else {
+ switch (ucs_level) {
+ case 3:
+ case 2:
+ case 1:
+ /*
+ * Unicode name. Convert as best we can.
+ */
+ {
+ int j;
+
+ name_buf[0] = '\0';
+ for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+ uh = idr->name[j*2];
+ ul = idr->name[j*2+1];
+
+ up = unls->unls_uni2cs[uh];
+
+ if (up == NULL)
+ uc = '\0';
+ else
+ uc = up[ul];
+
+ name_buf[j] = uc ? uc : '_';
+ }
+ name_buf[idr->name_len[0]/2] = '\0';
+ }
+ break;
+ case 0:
+ /*
+ * Normal non-Unicode name.
+ */
+ strncpy(name_buf, idr->name, idr->name_len[0]);
+ name_buf[idr->name_len[0]] = 0;
+ break;
+ default:
+ /*
+ * Don't know how to do these yet. Maybe they are the same
+ * as one of the above.
+ */
+ exit(1);
+ }
+ }
+ memcpy(date_buf, idr->date, 9);
+ if (use_rock)
+ dump_rr(idr);
+ if ((idr->flags[0] & 2) != 0 &&
+ (idr->name_len[0] != 1 ||
+ (idr->name[0] != 0 && idr->name[0] != 1))) {
+ /*
+ * Add this directory to the todo list.
+ */
+ td = todo_idr;
+ if (td != NULL) {
+ while (td->next != NULL)
+ td = td->next;
+ td->next = (struct todo *) malloc(sizeof (*td));
+ td = td->next;
+ } else {
+ todo_idr = td = (struct todo *) malloc(sizeof (*td));
+ }
+ td->next = NULL;
+ td->extent = isonum_733((unsigned char *)idr->extent);
+ td->length = isonum_733((unsigned char *)idr->size);
+ td->name = (char *) malloc(strlen(rootname)
+ + strlen(name_buf) + 2);
+ strcpy(td->name, rootname);
+ strcat(td->name, name_buf);
+ strcat(td->name, "/");
+ } else {
+ strcpy(testname, rootname);
+ strcat(testname, name_buf);
+ if (xtract && strcmp(xtract, testname) == 0) {
+ extract_file(idr);
+ }
+ }
+ if (do_find &&
+ (idr->name_len[0] != 1 ||
+ (idr->name[0] != 0 && idr->name[0] != 1))) {
+ strcpy(testname, rootname);
+ strcat(testname, name_buf);
+ printf("%s\n", testname);
+ }
+ if (do_listing)
+ dump_stat(idr, isonum_733((unsigned char *)idr->extent));
+ i += buffer[i];
+ if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break;
+ }
+ }
+}
+
+void
+usage(int excode)
+{
+ errmsgno(EX_BAD, "Usage: %s [options] -i filename\n", get_progname());
+
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-help,-h Print this help\n");
+ fprintf(stderr, "\t-version Print version info and exit\n");
+ fprintf(stderr, "\t-debug Print additional debug info\n");
+ fprintf(stderr, "\t-d Print information from the primary volume descriptor\n");
+ fprintf(stderr, "\t-f Generate output similar to 'find . -print'\n");
+ fprintf(stderr, "\t-J Print information from Joliet extensions\n");
+ fprintf(stderr, "\t-j charset Use charset to display Joliet file names\n");
+ fprintf(stderr, "\t-l Generate output similar to 'ls -lR'\n");
+ fprintf(stderr, "\t-p Print Path Table\n");
+ fprintf(stderr, "\t-R Print information from Rock Ridge extensions\n");
+ fprintf(stderr, "\t-s Print file size infos in multiples of sector size (%ld bytes).\n", (long)PAGE);
+ fprintf(stderr, "\t-N sector Sector number where ISO image should start on CD\n");
+ fprintf(stderr, "\t-T sector Sector number where actual session starts on CD\n");
+ fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n");
+ fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n");
+ fprintf(stderr, "\t-x pathname Extract specified file to stdout\n");
+ exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cac;
+ char * const *cav;
+ int c;
+ char * filename = NULL;
+ char * devname = NULL;
+ /*
+ * Use toc_offset != 0 (-T #) if we have a complete multi-session
+ * disc that we want/need to play with.
+ * Here we specify the offset where we want to
+ * start searching for the TOC.
+ */
+ int toc_offset = 0;
+ int extent;
+ struct todo * td;
+ struct iso_primary_descriptor ipd;
+ struct iso_primary_descriptor jpd;
+ struct eltorito_boot_descriptor bpd;
+ struct iso_directory_record * idr;
+ char *charset = NULL;
+ char *opts = "help,h,version,debug,d,p,i*,dev*,J,R,l,x*,f,s,N#l,T#l,j*";
+ BOOL help = FALSE;
+ BOOL prvers = FALSE;
+ BOOL found_eltorito = FALSE;
+ int bootcat_offset = 0;
+
+
+ save_args(argc, argv);
+
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getallargs(&cac, &cav, opts,
+ &help, &help, &prvers, &debug,
+ &do_pvd, &do_pathtab,
+ &filename, &devname,
+ &use_joliet, &use_rock,
+ &do_listing,
+ &xtract,
+ &do_find, &do_sectors,
+ &sector_offset, &toc_offset,
+ &charset) < 0) {
+ errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (help)
+ usage(0);
+ if (prvers) {
+ printf("isoinfo %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+ exit(0);
+ }
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getfiles(&cac, &cav, opts) != 0) {
+ errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+
+ init_unls(); /* Initialize UNICODE tables */
+ init_unls_file(charset);
+ if (charset == NULL) {
+#if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__)) && !defined(IS_CYGWIN_1)
+ unls = load_unls("cp437");
+#else
+ unls = load_unls("iso8859-1");
+#endif
+ } else {
+ if (strcmp(charset, "default") == 0)
+ unls = load_unls_default();
+ else
+ unls = load_unls(charset);
+ }
+ if (unls == NULL) { /* Unknown charset specified */
+ fprintf(stderr, "Unknown charset: %s\nKnown charsets are:\n",
+ charset);
+ list_unls(); /* List all known charset names */
+ exit(1);
+ }
+
+ if (filename != NULL && devname != NULL) {
+ errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+ usage(EX_BAD);
+ }
+#ifdef USE_SCG
+ if (filename == NULL && devname == NULL)
+ cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+ if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+ errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+ fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+ usage(EX_BAD);
+ }
+
+ if (filename != NULL)
+ infile = fopen(filename, "rb");
+ else
+ filename = devname;
+
+ if (infile != NULL) {
+ /* EMPTY */;
+#ifdef USE_SCG
+ } else if (scsidev_open(filename) < 0) {
+#else
+ } else {
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Unable to open %s\n", filename);
+#else
+ fprintf(stderr, "Unable to open %s\n", filename);
+ exit(1);
+#endif
+ }
+
+ /*
+ * Absolute sector offset, so don't subtract sector_offset here.
+ */
+#ifdef USE_SCG
+ readsecs(16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+ lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET);
+ read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+ idr = (struct iso_directory_record *)ipd.root_directory_record;
+ if (do_pvd) {
+ /*
+ * High sierra:
+ *
+ * DESC TYPE == 1 (VD_SFS) offset 8 len 1
+ * STR ID == "CDROM" offset 9 len 5
+ * STD_VER == 1 offset 14 len 1
+ */
+ if ((((char *)&ipd)[8] == 1) &&
+ (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
+ (((char *)&ipd)[14] == 1)) {
+ printf("CD-ROM is in High Sierra format\n");
+ exit(0);
+ }
+ /*
+ * ISO 9660:
+ *
+ * DESC TYPE == 1 (VD_PVD) offset 0 len 1
+ * STR ID == "CD001" offset 1 len 5
+ * STD_VER == 1 offset 6 len 1
+ */
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ printf("CD-ROM is NOT in ISO 9660 format\n");
+ exit(1);
+ }
+
+ printf("CD-ROM is in ISO 9660 format\n");
+ printf("System id: ");
+ printchars(ipd.system_id, 32);
+ putchar('\n');
+ printf("Volume id: ");
+ printchars(ipd.volume_id, 32);
+ putchar('\n');
+
+ printf("Volume set id: ");
+ printchars(ipd.volume_set_id, 128);
+ putchar('\n');
+ printf("Publisher id: ");
+ printchars(ipd.publisher_id, 128);
+ putchar('\n');
+ printf("Data preparer id: ");
+ printchars(ipd.preparer_id, 128);
+ putchar('\n');
+ printf("Application id: ");
+ printchars(ipd.application_id, 128);
+ putchar('\n');
+
+ printf("Copyright File id: ");
+ printchars(ipd.copyright_file_id, 37);
+ putchar('\n');
+ printf("Abstract File id: ");
+ printchars(ipd.abstract_file_id, 37);
+ putchar('\n');
+ printf("Bibliographic File id: ");
+ printchars(ipd.bibliographic_file_id, 37);
+ putchar('\n');
+
+ printf("Volume set size is: %d\n", isonum_723(ipd.volume_set_size));
+ printf("Volume set sequence number is: %d\n", isonum_723(ipd.volume_sequence_number));
+ printf("Logical block size is: %d\n", isonum_723(ipd.logical_block_size));
+ printf("Volume size is: %d\n", isonum_733((unsigned char *)ipd.volume_space_size));
+ if (debug) {
+ int dextent;
+ int dlen;
+
+ dextent = isonum_733((unsigned char *)idr->extent);
+ dlen = isonum_733((unsigned char *)idr->size);
+ printf("Root directory extent: %d size: %d\n",
+ dextent, dlen);
+ printf("Path table size is: %d\n",
+ isonum_733((unsigned char *)ipd.path_table_size));
+ printf("L Path table start: %d\n",
+ isonum_731(ipd.type_l_path_table));
+ printf("L Path opt table start: %d\n",
+ isonum_731(ipd.opt_type_l_path_table));
+ printf("M Path table start: %d\n",
+ isonum_732(ipd.type_m_path_table));
+ printf("M Path opt table start: %d\n",
+ isonum_732(ipd.opt_type_m_path_table));
+ printf("Creation Date: %s\n",
+ sdate(ipd.creation_date));
+ printf("Modification Date: %s\n",
+ sdate(ipd.modification_date));
+ printf("Expiration Date: %s\n",
+ sdate(ipd.expiration_date));
+ printf("Effective Date: %s\n",
+ sdate(ipd.effective_date));
+ printf("File structure version: %d\n",
+ ipd.file_structure_version[0]);
+ }
+ {
+ int block = 16;
+ movebytes(&ipd, &jpd, sizeof (ipd));
+ while ((Uchar)jpd.type[0] != ISO_VD_END) {
+
+ if (debug && (Uchar) jpd.type[0] == ISO_VD_SUPPLEMENTARY)
+ fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n",
+ jpd.escape_sequences[0],
+ jpd.escape_sequences[1],
+ jpd.escape_sequences[2],
+ jpd.escape_sequences[3]);
+ /*
+ * If Joliet UCS escape sequence found, we may be wrong
+ */
+ if (jpd.escape_sequences[0] == '%' &&
+ jpd.escape_sequences[1] == '/' &&
+ (jpd.escape_sequences[3] == '\0' ||
+ jpd.escape_sequences[3] == ' ') &&
+ (jpd.escape_sequences[2] == '@' ||
+ jpd.escape_sequences[2] == 'C' ||
+ jpd.escape_sequences[2] == 'E')) {
+
+ if (jpd.version[0] == 1)
+ goto nextblock;
+ }
+ if (jpd.type[0] == 0) {
+ movebytes(&jpd, &bpd, sizeof (bpd));
+ if (strncmp(bpd.system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID)) == 0) {
+ bootcat_offset = (Uchar)bpd.bootcat_ptr[0] +
+ (Uchar)bpd.bootcat_ptr[1] * 256 +
+ (Uchar)bpd.bootcat_ptr[2] * 65536 +
+ (Uchar)bpd.bootcat_ptr[3] * 16777216;
+ found_eltorito = TRUE;
+ printf("El Torito VD version %d found, boot catalog is in sector %d\n",
+ bpd.version[0],
+ bootcat_offset);
+ }
+ }
+ if (jpd.version[0] == 2) {
+ printf("CD-ROM uses ISO 9660:1999 relaxed format\n");
+ break;
+ }
+
+ nextblock:
+ block++;
+#ifdef USE_SCG
+ readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
+#else
+ lseek(fileno(infile), ((off_t)(block + toc_offset)) <<11, SEEK_SET);
+ read(fileno(infile), &jpd, sizeof (jpd));
+#endif
+ }
+ }
+ }
+ /*
+ * ISO 9660:
+ *
+ * DESC TYPE == 1 (VD_PVD) offset 0 len 1
+ * STR ID == "CD001" offset 1 len 5
+ * STD_VER == 1 offset 6 len 1
+ */
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ printf("CD-ROM is NOT in ISO 9660 format\n");
+ exit(1);
+ }
+
+ if (use_joliet || do_pvd) {
+ int block = 16;
+ movebytes(&ipd, &jpd, sizeof (ipd));
+ while ((unsigned char) jpd.type[0] != ISO_VD_END) {
+ if (debug && (unsigned char) jpd.type[0] == ISO_VD_SUPPLEMENTARY)
+ fprintf(stderr, "Joliet escape sequence 0: '%c' 1: '%c' 2: '%c' 3: '%c'\n",
+ jpd.escape_sequences[0],
+ jpd.escape_sequences[1],
+ jpd.escape_sequences[2],
+ jpd.escape_sequences[3]);
+ /*
+ * Find the UCS escape sequence.
+ */
+ if (jpd.escape_sequences[0] == '%' &&
+ jpd.escape_sequences[1] == '/' &&
+ (jpd.escape_sequences[3] == '\0' ||
+ jpd.escape_sequences[3] == ' ') &&
+ (jpd.escape_sequences[2] == '@' ||
+ jpd.escape_sequences[2] == 'C' ||
+ jpd.escape_sequences[2] == 'E')) {
+ break;
+ }
+
+ block++;
+#ifdef USE_SCG
+ readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
+#else
+ lseek(fileno(infile),
+ ((off_t)(block + toc_offset)) <<11, SEEK_SET);
+ read(fileno(infile), &jpd, sizeof (jpd));
+#endif
+ }
+
+ if (use_joliet && ((unsigned char) jpd.type[0] == ISO_VD_END)) {
+#ifdef USE_LIBSCHILY
+ comerrno(EX_BAD, "Unable to find Joliet SVD\n");
+#else
+ fprintf(stderr, "Unable to find Joliet SVD\n");
+ exit(1);
+#endif
+ }
+
+ switch (jpd.escape_sequences[2]) {
+ case '@':
+ ucs_level = 1;
+ break;
+ case 'C':
+ ucs_level = 2;
+ break;
+ case 'E':
+ ucs_level = 3;
+ break;
+ }
+
+ if (ucs_level > 3) {
+#ifdef USE_LIBSCHILY
+ comerrno(EX_BAD,
+ "Don't know what ucs_level == %d means\n",
+ ucs_level);
+#else
+ fprintf(stderr,
+ "Don't know what ucs_level == %d means\n",
+ ucs_level);
+ exit(1);
+#endif
+ }
+ if (jpd.escape_sequences[3] == ' ')
+ errmsgno(EX_BAD,
+ "Warning: Joliet escape sequence uses illegal space at offset 3\n");
+ }
+
+ if (do_pvd) {
+ if (ucs_level > 0)
+ printf("Joliet with UCS level %d found\n", ucs_level);
+ else
+ printf("NO Joliet present\n");
+
+ extent = isonum_733((unsigned char *)idr->extent);
+
+#ifdef USE_SCG
+ readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+ lseek(fileno(infile),
+ ((off_t)(extent - sector_offset)) <<11, SEEK_SET);
+ read(fileno(infile), buffer, sizeof (buffer));
+#endif
+ idr = (struct iso_directory_record *) buffer;
+ if ((c = dump_rr(idr)) != 0) {
+/* printf("RR %X %d\n", c, c);*/
+ if (c & 1024) {
+ printf(
+ "Rock Ridge signatures version %d found\n",
+ su_version);
+ } else {
+ printf(
+ "Bad Rock Ridge signatures found (SU record missing)\n");
+ }
+ /*
+ * This is currently a no op!
+ * We need to check the first plain file instead of
+ * the '.' entry in the root directory.
+ */
+ if (c & 2048) {
+ printf("Apple signatures version %d found\n",
+ aa_version);
+ }
+ } else {
+ printf("NO Rock Ridge present\n");
+ }
+ if (found_eltorito)
+ printf_bootinfo(infile, bootcat_offset);
+ exit(0);
+ }
+
+ if (use_joliet)
+ idr = (struct iso_directory_record *)jpd.root_directory_record;
+
+ if (do_pathtab) {
+ if (use_joliet) {
+ dump_pathtab(isonum_731(jpd.type_l_path_table),
+ isonum_733((unsigned char *)jpd.path_table_size));
+ } else {
+ dump_pathtab(isonum_731(ipd.type_l_path_table),
+ isonum_733((unsigned char *)ipd.path_table_size));
+ }
+ }
+
+ parse_dir("/", isonum_733((unsigned char *)idr->extent),
+ isonum_733((unsigned char *)idr->size));
+ td = todo_idr;
+ while (td) {
+ parse_dir(td->name, td->extent, td->length);
+ td = td->next;
+ }
+
+ if (infile != NULL)
+ fclose(infile);
+ return (0);
+}
+
+#include <intcvt.h>
+
+static void
+printf_bootinfo(FILE *f, int bootcat_offset)
+{
+ struct eltorito_validation_entry *evp;
+ struct eltorito_defaultboot_entry *ebe;
+
+#ifdef USE_SCG
+ readsecs(bootcat_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+ lseek(fileno(f), ((off_t)bootcat_offset) <<11, SEEK_SET);
+ read(fileno(f), buffer, sizeof (buffer));
+#endif
+
+ evp = (struct eltorito_validation_entry *)buffer;
+ ebe = (struct eltorito_defaultboot_entry *)&buffer[32];
+
+ printf("Eltorito validation header:\n");
+ printf(" Hid %d\n", (Uchar)evp->headerid[0]);
+ printf(" Arch %d (%s)\n", (Uchar)evp->arch[0], arch_name((Uchar)evp->arch[0]));
+ printf(" ID '%.23s'\n", evp->id);
+ printf(" Key %X %X\n", (Uchar)evp->key1[0], (Uchar)evp->key2[0]);
+
+ printf(" Eltorito defaultboot header:\n");
+ printf(" Bootid %X (%s)\n", (Uchar)ebe->boot_id[0], boot_name((Uchar)ebe->boot_id[0]));
+ printf(" Boot media %X (%s)\n", (Uchar)ebe->boot_media[0], bootmedia_name((Uchar)ebe->boot_media[0]));
+ printf(" Load segment %X\n", la_to_2_byte(ebe->loadseg));
+ printf(" Sys type %X\n", (Uchar)ebe->sys_type[0]);
+ printf(" Nsect %X\n", la_to_2_byte(ebe->nsect));
+ printf(" Bootoff %lX %ld\n", la_to_4_byte(ebe->bootoff), la_to_4_byte(ebe->bootoff));
+
+}
+
+static char *
+arch_name(int val)
+{
+ switch (val) {
+
+ case EL_TORITO_ARCH_x86:
+ return ("x86");
+ case EL_TORITO_ARCH_PPC:
+ return ("PPC");
+ case EL_TORITO_ARCH_MAC:
+ return ("MAC");
+ default:
+ return ("Unknown Arch");
+ }
+}
+
+static char *
+boot_name(int val)
+{
+ switch (val) {
+
+ case EL_TORITO_BOOTABLE:
+ return ("bootable");
+ case EL_TORITO_NOT_BOOTABLE:
+ return ("not bootable");
+ default:
+ return ("Illegal");
+ }
+}
+
+static char *
+bootmedia_name(int val)
+{
+ switch (val) {
+
+ case EL_TORITO_MEDIA_NOEMUL:
+ return ("No Emulation Boot");
+ case EL_TORITO_MEDIA_12FLOP:
+ return ("1200 Floppy");
+ case EL_TORITO_MEDIA_144FLOP:
+ return ("1.44MB Floppy");
+ case EL_TORITO_MEDIA_288FLOP:
+ return ("2.88MB Floppy");
+ case EL_TORITO_MEDIA_HD:
+ return ("Hard Disk Emulation");
+ default:
+ return ("Illegal Bootmedia");
+ }
+}
diff --git a/genisoimage/diag/isovfy.1 b/genisoimage/diag/isovfy.1
new file mode 100644
index 0000000..b170c59
--- /dev/null
+++ b/genisoimage/diag/isovfy.1
@@ -0,0 +1,2 @@
+.so man1/isoinfo.1
+.\" %Z%%M% %I% %E% joerg
diff --git a/genisoimage/diag/isovfy.c b/genisoimage/diag/isovfy.c
new file mode 100644
index 0000000..18ed340
--- /dev/null
+++ b/genisoimage/diag/isovfy.c
@@ -0,0 +1,794 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)isovfy.c 1.26 05/05/15 joerg */
+/*
+ * File isovfy.c - verify consistency of iso9660 filesystem.
+ *
+ *
+ * Written by Eric Youngdale (1993).
+ *
+ * Copyright 1993 Yggdrasil Computing, Incorporated
+ * Copyright (c) 1999-2004 J. Schilling
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <mconfig.h>
+#include <stdxlib.h>
+#include <unixstd.h>
+#include <strdefs.h>
+#include <utypes.h>
+
+#include <stdio.h>
+#include <standard.h>
+#include <signal.h>
+#include <schily.h>
+
+#include "../scsi.h"
+#include "../../wodim/defaults.h"
+
+/*
+ * XXX JS: Some structures have odd lengths!
+ * Some compilers (e.g. on Sun3/mc68020) padd the structures to even length.
+ * For this reason, we cannot use sizeof (struct iso_path_table) or
+ * sizeof (struct iso_directory_record) to compute on disk sizes.
+ * Instead, we use offsetof(..., name) and add the name size.
+ * See iso9660.h
+ */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/*
+ * Note: always use these macros to avoid problems.
+ *
+ * ISO_ROUND_UP(X) may cause an integer overflow and thus give
+ * incorrect results. So avoid it if possible.
+ *
+ * ISO_BLOCKS(X) is overflow safe. Prefer this when ever it is possible.
+ */
+#define SECTOR_SIZE (2048)
+#define ISO_ROUND_UP(X) (((X) + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
+#define ISO_BLOCKS(X) (((X) / SECTOR_SIZE) + (((X)%SECTOR_SIZE)?1:0))
+
+#define infile in_image
+FILE *infile = NULL;
+int blocksize;
+
+#define PAGE sizeof (buffer)
+
+#define ISODCL(from, to) (to - from + 1)
+
+struct iso_primary_descriptor {
+ unsigned char type [ISODCL(1, 1)]; /* 711 */
+ unsigned char id [ISODCL(2, 6)];
+ unsigned char version [ISODCL(7, 7)]; /* 711 */
+ unsigned char unused1 [ISODCL(8, 8)];
+ unsigned char system_id [ISODCL(9, 40)]; /* aunsigned chars */
+ unsigned char volume_id [ISODCL(41, 72)]; /* dunsigned chars */
+ unsigned char unused2 [ISODCL(73, 80)];
+ unsigned char volume_space_size [ISODCL(81, 88)]; /* 733 */
+ unsigned char unused3 [ISODCL(89, 120)];
+ unsigned char volume_set_size [ISODCL(121, 124)]; /* 723 */
+ unsigned char volume_sequence_number [ISODCL(125, 128)]; /* 723 */
+ unsigned char logical_block_size [ISODCL(129, 132)]; /* 723 */
+ unsigned char path_table_size [ISODCL(133, 140)]; /* 733 */
+ unsigned char type_l_path_table [ISODCL(141, 144)]; /* 731 */
+ unsigned char opt_type_l_path_table [ISODCL(145, 148)]; /* 731 */
+ unsigned char type_m_path_table [ISODCL(149, 152)]; /* 732 */
+ unsigned char opt_type_m_path_table [ISODCL(153, 156)]; /* 732 */
+ unsigned char root_directory_record [ISODCL(157, 190)]; /* 9.1 */
+ unsigned char volume_set_id [ISODCL(191, 318)]; /* dunsigned chars */
+ unsigned char publisher_id [ISODCL(319, 446)]; /* achars */
+ unsigned char preparer_id [ISODCL(447, 574)]; /* achars */
+ unsigned char application_id [ISODCL(575, 702)]; /* achars */
+ unsigned char copyright_file_id [ISODCL(703, 739)]; /* 7.5 dchars */
+ unsigned char abstract_file_id [ISODCL(740, 776)]; /* 7.5 dchars */
+ unsigned char bibliographic_file_id [ISODCL(777, 813)]; /* 7.5 dchars */
+ unsigned char creation_date [ISODCL(814, 830)]; /* 8.4.26.1 */
+ unsigned char modification_date [ISODCL(831, 847)]; /* 8.4.26.1 */
+ unsigned char expiration_date [ISODCL(848, 864)]; /* 8.4.26.1 */
+ unsigned char effective_date [ISODCL(865, 881)]; /* 8.4.26.1 */
+ unsigned char file_structure_version [ISODCL(882, 882)]; /* 711 */
+ unsigned char unused4 [ISODCL(883, 883)];
+ unsigned char application_data [ISODCL(884, 1395)];
+ unsigned char unused5 [ISODCL(1396, 2048)];
+};
+
+struct iso_directory_record {
+ unsigned char length [ISODCL(1, 1)]; /* 711 */
+ unsigned char ext_attr_length [ISODCL(2, 2)]; /* 711 */
+ unsigned char extent [ISODCL(3, 10)]; /* 733 */
+ unsigned char size [ISODCL(11, 18)]; /* 733 */
+ unsigned char date [ISODCL(19, 25)]; /* 7 by 711 */
+ unsigned char flags [ISODCL(26, 26)];
+ unsigned char file_unit_size [ISODCL(27, 27)]; /* 711 */
+ unsigned char interleave [ISODCL(28, 28)]; /* 711 */
+ unsigned char volume_sequence_number [ISODCL(29, 32)]; /* 723 */
+ unsigned char name_len [ISODCL(33, 33)]; /* 711 */
+ unsigned char name [38];
+};
+
+static int isonum_721(char * p);
+static int isonum_723(char * p);
+static int isonum_711(char * p);
+static int isonum_731(char * p);
+static int isonum_722(char * p);
+static int isonum_732(char * p);
+static int isonum_733(unsigned char * p);
+static int parse_rr(unsigned char * pnt, int len, int cont_flag);
+static int dump_rr(struct iso_directory_record * idr);
+static void check_tree(off_t file_addr, int file_size, off_t parent_addr);
+static void check_path_tables(int typel_extent, int typem_extent,
+ int path_table_size);
+static void usage(int excode);
+
+static int
+isonum_721(char *p)
+{
+ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
+}
+
+static int
+isonum_723(char *p)
+{
+#if 0
+ if (p[0] != p[3] || p[1] != p[2]) {
+#ifdef USE_LIBSCHILY
+ comerrno(EX_BAD, "invalid format 7.2.3 number\n");
+#else
+ fprintf(stderr, "invalid format 7.2.3 number\n");
+ exit(1);
+#endif
+ }
+#endif
+ return (isonum_721(p));
+}
+
+static int
+isonum_711(char *p)
+{
+ return (*p & 0xff);
+}
+
+static int
+isonum_731(char *p)
+{
+ return ((p[0] & 0xff)
+ | ((p[1] & 0xff) << 8)
+ | ((p[2] & 0xff) << 16)
+ | ((p[3] & 0xff) << 24));
+}
+
+static int
+isonum_722(char *p)
+{
+ return ((p[1] & 0xff)
+ | ((p[0] & 0xff) << 8));
+}
+
+static int
+isonum_732(char *p)
+{
+ return ((p[3] & 0xff)
+ | ((p[2] & 0xff) << 8)
+ | ((p[1] & 0xff) << 16)
+ | ((p[0] & 0xff) << 24));
+}
+
+static int
+isonum_733(unsigned char *p)
+{
+ return (isonum_731((char *)p));
+}
+
+char lbuffer[1024];
+int iline;
+int rr_goof;
+
+
+static int
+parse_rr(unsigned char *pnt, int len, int cont_flag)
+{
+ int slen;
+ int ncount;
+ int flag1;
+ int flag2;
+ int extent;
+ unsigned char *pnts;
+ off_t cont_extent;
+ int cont_offset;
+ int cont_size;
+ char symlinkname[1024];
+
+ sprintf(lbuffer+iline, " RRlen=%d ", len);
+ iline += strlen(lbuffer+iline);
+
+ cont_extent = (off_t)0;
+ cont_offset = cont_size = 0;
+
+ symlinkname[0] = 0;
+
+ ncount = 0;
+ flag1 = flag2 = 0;
+ while (len >= 4) {
+ if (ncount)
+ sprintf(lbuffer+iline, ",");
+ else
+ sprintf(lbuffer+iline, "[");
+ iline += strlen(lbuffer + iline);
+ sprintf(lbuffer+iline, "%c%c", pnt[0], pnt[1]);
+ iline += strlen(lbuffer + iline);
+ if (pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' ||
+ pnt[1] > 'Z') {
+ sprintf(lbuffer+iline, "**BAD SUSP %d %d]",
+ pnt[0], pnt[1]);
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ return (flag2);
+ }
+
+ if (pnt[3] != 1 && pnt[3] != 2) {
+ sprintf(lbuffer+iline, "**BAD RRVERSION (%d)\n", pnt[3]);
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ return (flag2);
+ }
+ ncount++;
+ if (pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff;
+ if (strncmp((char *)pnt, "PX", 2) == 0) flag2 |= 1;
+ if (strncmp((char *)pnt, "PN", 2) == 0) flag2 |= 2;
+ if (strncmp((char *)pnt, "SL", 2) == 0) flag2 |= 4;
+ if (strncmp((char *)pnt, "NM", 2) == 0) flag2 |= 8;
+ if (strncmp((char *)pnt, "CL", 2) == 0) flag2 |= 16;
+ if (strncmp((char *)pnt, "PL", 2) == 0) flag2 |= 32;
+ if (strncmp((char *)pnt, "RE", 2) == 0) flag2 |= 64;
+ if (strncmp((char *)pnt, "TF", 2) == 0) flag2 |= 128;
+
+ if (strncmp((char *)pnt, "CE", 2) == 0) {
+ cont_extent = (off_t)isonum_733(pnt+4);
+ cont_offset = isonum_733(pnt+12);
+ cont_size = isonum_733(pnt+20);
+ sprintf(lbuffer+iline, "=[%x,%x,%d]",
+ (int)cont_extent, cont_offset, cont_size);
+ iline += strlen(lbuffer + iline);
+ }
+
+ if (strncmp((char *)pnt, "PL", 2) == 0 || strncmp((char *)pnt, "CL", 2) == 0) {
+ extent = isonum_733(pnt+4);
+ sprintf(lbuffer+iline, "=%x", extent);
+ iline += strlen(lbuffer + iline);
+ if (extent == 0)
+ rr_goof++;
+ }
+ if (strncmp((char *)pnt, "SL", 2) == 0) {
+ pnts = pnt+5;
+ slen = pnt[2] - 5;
+ while (slen >= 1) {
+ switch (pnts[0] & 0xfe) {
+ case 0:
+ strncat(symlinkname, (char *)(pnts+2), pnts[1]);
+ break;
+ case 2:
+ strcat(symlinkname, ".");
+ break;
+ case 4:
+ strcat(symlinkname, "..");
+ break;
+ case 8:
+ strcat(symlinkname, "/");
+ break;
+ case 16:
+ strcat(symlinkname, "/mnt");
+ sprintf(lbuffer+iline, "Warning - mount point requested");
+ iline += strlen(lbuffer + iline);
+ break;
+ case 32:
+ strcat(symlinkname, "kafka");
+ sprintf(lbuffer+iline, "Warning - host_name requested");
+ iline += strlen(lbuffer + iline);
+ break;
+ default:
+ sprintf(lbuffer+iline, "Reserved bit setting in symlink");
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ break;
+ }
+ if ((pnts[0] & 0xfe) && pnts[1] != 0) {
+ sprintf(lbuffer+iline, "Incorrect length in symlink component");
+ iline += strlen(lbuffer + iline);
+ }
+ if ((pnts[0] & 1) == 0)
+ strcat(symlinkname, "/");
+ slen -= (pnts[1] + 2);
+ pnts += (pnts[1] + 2);
+ }
+ if (symlinkname[0] != 0) {
+ sprintf(lbuffer+iline, "=%s", symlinkname);
+ iline += strlen(lbuffer + iline);
+ symlinkname[0] = 0;
+ }
+ }
+
+ len -= pnt[2];
+ pnt += pnt[2];
+ if (len <= 3 && cont_extent) {
+ unsigned char sector[2048];
+#ifdef USE_SCG
+ readsecs(cont_extent * blocksize / 2048, sector, ISO_BLOCKS(sizeof (sector)));
+#else
+ lseek(fileno(infile), cont_extent * blocksize, SEEK_SET);
+ read(fileno(infile), sector, sizeof (sector));
+#endif
+ flag2 |= parse_rr(&sector[cont_offset], cont_size, 1);
+ }
+ }
+ if (ncount) {
+ sprintf(lbuffer+iline, "]");
+ iline += strlen(lbuffer + iline);
+ }
+ if (!cont_flag && flag1 && flag1 != flag2) {
+ sprintf(lbuffer+iline, "Flag %x != %x", flag1, flag2);
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ return (flag2);
+}
+
+static int
+dump_rr(struct iso_directory_record *idr)
+{
+ int len;
+ char * pnt;
+
+ len = idr->length[0] & 0xff;
+ len -= offsetof(struct iso_directory_record, name[0]);
+ len -= idr->name_len[0];
+ pnt = (char *) idr;
+ pnt += offsetof(struct iso_directory_record, name[0]);
+ pnt += idr->name_len[0];
+
+ if ((idr->name_len[0] & 1) == 0) {
+ pnt++;
+ len--;
+ }
+
+ rr_goof = 0;
+ parse_rr((unsigned char *)pnt, len, 0);
+ return (rr_goof);
+}
+
+
+static int dir_count = 0;
+static int dir_size_count = 0;
+static int ngoof = 0;
+
+static void
+check_tree(off_t file_addr, int file_size, off_t parent_addr)
+{
+ unsigned char buffer[2048];
+ unsigned int k;
+ int rflag = 0;
+ int i;
+ int i1;
+ int j;
+ int goof;
+ int extent;
+ int size;
+ off_t orig_file_addr;
+ off_t parent_file_addr;
+ struct iso_directory_record *idr;
+
+ i1 = 0;
+
+ orig_file_addr = file_addr / blocksize; /* Actual extent of this directory */
+ parent_file_addr = parent_addr / blocksize;
+
+ if ((dir_count % 100) == 0)
+ printf("[%d %d]\n", dir_count, dir_size_count);
+#if 0
+ if (sizeof (file_addr) > sizeof (long)) {
+ printf("Starting directory %ld %d %lld\n",
+ file_addr, file_size,
+ (Llong)parent_addr);
+ } else {
+ printf("Starting directory %ld %d %ld\n", file_addr, file_size, parent_addr);
+ }
+#endif
+
+ dir_count++;
+ dir_size_count += file_size / blocksize;
+
+ if (file_size & 0x3ff)
+ printf("********Directory has unusual size\n");
+
+ for (k = 0; k < (file_size / sizeof (buffer)); k++) {
+#ifdef USE_SCG
+ readsecs(file_addr / 2048, buffer, ISO_BLOCKS(sizeof (buffer)));
+#else
+ lseek(fileno(infile), file_addr, SEEK_SET);
+ read(fileno(infile), buffer, sizeof (buffer));
+#endif
+ i = 0;
+ while (1 == 1) {
+ goof = iline = 0;
+ idr = (struct iso_directory_record *) &buffer[i];
+ if (idr->length[0] == 0) break;
+ sprintf(&lbuffer[iline], "%3d ", idr->length[0]);
+ iline += strlen(lbuffer + iline);
+ extent = isonum_733(idr->extent);
+ size = isonum_733(idr->size);
+ sprintf(&lbuffer[iline], "%5x ", extent);
+ iline += strlen(lbuffer + iline);
+ sprintf(&lbuffer[iline], "%8d ", size);
+ iline += strlen(lbuffer + iline);
+ sprintf(&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' ');
+ iline += strlen(lbuffer + iline);
+
+ if (idr->name_len[0] > 33) {
+ sprintf(&lbuffer[iline], "File name length=(%d)",
+ idr->name_len[0]);
+ goof++;
+ iline += strlen(lbuffer + iline);
+ } else if (idr->name_len[0] == 1 && idr->name[0] == 0) {
+ sprintf(&lbuffer[iline], ". ");
+ iline += strlen(lbuffer + iline);
+ rflag = 0;
+ if (orig_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) {
+ sprintf(&lbuffer[iline], "***** Directory has null extent.");
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ if (i1) {
+ sprintf(&lbuffer[iline], "***** . not first entry.");
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ } else if (idr->name_len[0] == 1 && idr->name[0] == 1) {
+ sprintf(&lbuffer[iline], ".. ");
+ iline += strlen(lbuffer + iline);
+ rflag = 0;
+ if (parent_file_addr != (off_t)(isonum_733(idr->extent) + isonum_711((char *) idr->ext_attr_length))) {
+ sprintf(&lbuffer[iline], "***** Directory has null extent.");
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ if (i1 != 1) {
+ sprintf(&lbuffer[iline], "***** .. not second entry.");
+ rr_goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ } else {
+ if (i1 < 2) {
+ sprintf(&lbuffer[iline], " Improper sorting.");
+ rr_goof++;
+ }
+ for (j = 0; j < (int)idr->name_len[0]; j++) {
+ sprintf(&lbuffer[iline], "%c", idr->name[j]);
+ }
+ for (j = 0; j < (14 - (int) idr->name_len[0]); j++) {
+ sprintf(&lbuffer[iline], " ");
+ iline += strlen(lbuffer + iline);
+ }
+ rflag = 1;
+ }
+
+ if (size && extent == 0) {
+ sprintf(&lbuffer[iline], "****Extent==0, size != 0");
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+#if 0
+ /* This is apparently legal. */
+ if (size == 0 && extent) {
+ sprintf(&lbuffer[iline], "****Extent!=0, size == 0");
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+#endif
+
+ if (idr->flags[0] & 0xf5) {
+ sprintf(&lbuffer[iline], "Flags=(%x) ", idr->flags[0]);
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+ if (idr->interleave[0]) {
+ sprintf(&lbuffer[iline], "Interleave=(%d) ", idr->interleave[0]);
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+
+ if (idr->file_unit_size[0]) {
+ sprintf(&lbuffer[iline], "File unit size=(%d) ", idr->file_unit_size[0]);
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+
+ if (idr->volume_sequence_number[0] != 1) {
+ sprintf(&lbuffer[iline], "Volume sequence number=(%d) ", idr->volume_sequence_number[0]);
+ goof++;
+ iline += strlen(lbuffer + iline);
+ }
+
+ goof += dump_rr(idr);
+ sprintf(&lbuffer[iline], "\n");
+ iline += strlen(lbuffer + iline);
+
+
+ if (goof) {
+ ngoof++;
+ lbuffer[iline++] = 0;
+ if (sizeof (orig_file_addr) > sizeof (long)) {
+ printf("%llx: %s", (Llong)orig_file_addr, lbuffer);
+ } else {
+ printf("%lx: %s", (long)orig_file_addr, lbuffer);
+ }
+ }
+
+
+
+ if (rflag && (idr->flags[0] & 2))
+ check_tree((off_t)(isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length)) * blocksize,
+ isonum_733(idr->size),
+ orig_file_addr * blocksize);
+ i += buffer[i];
+ i1++;
+ if (i > 2048 - offsetof(struct iso_directory_record, name[0]))
+ break;
+ }
+ file_addr += sizeof (buffer);
+ }
+ fflush(stdout);
+}
+
+
+/*
+ * This function simply dumps the contents of the path tables. No
+ * consistency checking takes place, although this would proably be a good
+ * idea.
+ */
+struct path_table_info {
+ char *name;
+ unsigned int extent;
+ unsigned short index;
+ unsigned short parent;
+};
+
+static void
+check_path_tables(int typel_extent, int typem_extent, int path_table_size)
+{
+ int count;
+ int j;
+ char *pnt;
+ char *typel;
+ char *typem;
+
+ /* Now read in the path tables */
+
+ typel = (char *) malloc(ISO_ROUND_UP(path_table_size));
+#ifdef USE_SCG
+ readsecs(typel_extent * blocksize / 2048, typel, ISO_BLOCKS(path_table_size));
+#else
+ lseek(fileno(infile), (off_t)((off_t)typel_extent) * blocksize, SEEK_SET);
+ read(fileno(infile), typel, path_table_size); /* FIXME: check return value */
+#endif
+ typem = (char *) malloc(path_table_size);
+ lseek(fileno(infile), (off_t)((off_t)typem_extent) * blocksize, SEEK_SET);
+ read(fileno(infile), typem, path_table_size); /* FIXME: check return value */
+
+ j = path_table_size;
+ pnt = typel;
+ count = 1;
+ while (j) {
+ int namelen;
+ int extent;
+ int idx;
+ char name[32];
+
+ namelen = *pnt++; pnt++;
+ extent = isonum_731(pnt);
+ pnt += 4;
+ idx = isonum_721(pnt);
+ pnt += 2;
+ j -= 8 + namelen;
+ memset(name, 0, sizeof (name));
+
+ strncpy(name, pnt, namelen);
+ pnt += namelen;
+ if (j & 1) {
+ j--;
+ pnt++;
+ }
+ printf("%4.4d %4.4d %8.8x %s\n", count++, idx, extent, name);
+ }
+
+ j = path_table_size;
+ pnt = typem;
+ count = 1;
+
+ while (j) {
+ int namelen;
+ int extent;
+ int idx;
+ char name[32];
+
+ namelen = *pnt++; pnt++;
+ extent = isonum_732(pnt);
+ pnt += 4;
+ idx = isonum_722(pnt);
+ pnt += 2;
+ j -= 8+namelen;
+ memset(name, 0, sizeof (name));
+
+ strncpy(name, pnt, namelen);
+ pnt += namelen;
+ if (j & 1) {
+ j--;
+ pnt++;
+ }
+ printf("%4.4d %4.4d %8.8x %s\n", count++, idx, extent, name);
+ }
+}
+
+static void
+usage(int excode)
+{
+ errmsgno(EX_BAD, "Usage: %s [options] image\n",
+ get_progname());
+
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, "\t-help, -h Print this help\n");
+ fprintf(stderr, "\t-version Print version info and exit\n");
+ fprintf(stderr, "\t-i filename Filename to read ISO-9660 image from\n");
+ fprintf(stderr, "\tdev=target SCSI target to use as CD/DVD-Recorder\n");
+ fprintf(stderr, "\nIf neither -i nor dev= are speficied, <image> is needed.\n");
+ exit(excode);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int cac;
+ char * const *cav;
+ char *opts = "help,h,version,i*,dev*";
+ BOOL help = FALSE;
+ BOOL prvers = FALSE;
+ char *filename = NULL;
+ char *devname = NULL;
+ off_t file_addr;
+ int file_size;
+ struct iso_primary_descriptor ipd;
+ struct iso_directory_record *idr;
+ int typel_extent;
+ int typem_extent;
+ int path_table_size;
+
+ save_args(argc, argv);
+
+ cac = argc - 1;
+ cav = argv + 1;
+ if (getallargs(&cac, &cav, opts, &help, &help, &prvers,
+ &filename, &devname) < 0) {
+ errmsgno(EX_BAD, "Bad Option: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (help)
+ usage(0);
+ if (prvers) {
+ printf("isovfy %s (%s)\n", CDRKIT_VERSION, HOST_SYSTEM);
+ exit(0);
+ }
+ cac = argc - 1;
+ cav = argv + 1;
+ if (filename == NULL && devname == NULL) {
+ if (getfiles(&cac, &cav, opts) != 0) {
+ filename = cav[0];
+ cac--, cav++;
+ }
+ }
+ if (getfiles(&cac, &cav, opts) != 0) {
+ errmsgno(EX_BAD, "Bad Argument: '%s'\n", cav[0]);
+ usage(EX_BAD);
+ }
+ if (filename != NULL && devname != NULL) {
+ errmsgno(EX_BAD, "Only one of -i or dev= allowed\n");
+ usage(EX_BAD);
+ }
+#ifdef USE_SCG
+ if (filename == NULL && devname == NULL)
+ cdr_defaults(&devname, NULL, NULL, NULL);
+#endif
+ if (filename == NULL && devname == NULL) {
+#ifdef USE_LIBSCHILY
+ errmsgno(EX_BAD, "ISO-9660 image not specified\n");
+#else
+ fprintf(stderr, "ISO-9660 image not specified\n");
+#endif
+ usage(EX_BAD);
+ }
+
+ if (filename != NULL)
+ infile = fopen(filename, "rb");
+ else
+ filename = devname;
+
+ if (infile != NULL) {
+ /* EMPTY */;
+#ifdef USE_SCG
+ } else if (scsidev_open(filename) < 0) {
+#else
+ } else {
+#endif
+#ifdef USE_LIBSCHILY
+ comerr("Cannot open '%s'\n", filename);
+#else
+ fprintf(stderr, "Cannot open '%s'\n", filename);
+ exit(1);
+#endif
+ }
+
+
+ file_addr = (off_t)32768;
+#ifdef USE_SCG
+ readsecs(file_addr / 2048, &ipd, ISO_BLOCKS(sizeof (ipd)));
+#else
+ lseek(fileno(infile), file_addr, SEEK_SET);
+ read(fileno(infile), &ipd, sizeof (ipd));
+#endif
+
+ idr = (struct iso_directory_record *)ipd.root_directory_record;
+
+ blocksize = isonum_723((char *)ipd.logical_block_size);
+ if (blocksize != 512 && blocksize != 1024 && blocksize != 2048) {
+ blocksize = 2048;
+ }
+
+ file_addr = (off_t)isonum_733(idr->extent) + isonum_711((char *)idr->ext_attr_length);
+ file_size = isonum_733(idr->size);
+
+ if (sizeof (file_addr) > sizeof (long)) {
+ printf("Root at extent %llx, %d bytes\n", (Llong)file_addr, file_size);
+ } else {
+ printf("Root at extent %lx, %d bytes\n", (long)file_addr, file_size);
+ }
+ file_addr = file_addr * blocksize;
+
+ check_tree(file_addr, file_size, file_addr);
+
+ typel_extent = isonum_731((char *)ipd.type_l_path_table);
+ typem_extent = isonum_732((char *)ipd.type_m_path_table);
+ path_table_size = isonum_733(ipd.path_table_size);
+
+ /* Enable this to get the dump of the path tables */
+#if 0
+ check_path_tables(typel_extent, typem_extent, path_table_size);
+#endif
+
+ if (infile != NULL)
+ fclose(infile);
+
+ if (!ngoof)
+ printf("No errors found\n");
+ return (0);
+}