diff options
Diffstat (limited to 'genisoimage/diag')
-rw-r--r-- | genisoimage/diag/README | 76 | ||||
-rw-r--r-- | genisoimage/diag/devdump.1 | 2 | ||||
-rw-r--r-- | genisoimage/diag/dump.c | 428 | ||||
-rw-r--r-- | genisoimage/diag/isodebug.1 | 108 | ||||
-rw-r--r-- | genisoimage/diag/isodebug.c | 281 | ||||
-rw-r--r-- | genisoimage/diag/isodump.1 | 2 | ||||
-rw-r--r-- | genisoimage/diag/isodump.c | 715 | ||||
-rw-r--r-- | genisoimage/diag/isoinfo.1 | 365 | ||||
-rw-r--r-- | genisoimage/diag/isoinfo.c | 1321 | ||||
-rw-r--r-- | genisoimage/diag/isovfy.1 | 2 | ||||
-rw-r--r-- | genisoimage/diag/isovfy.c | 794 |
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(§or[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(§or[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(§or[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, + §or_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(§or[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); +} |