diff -uNr cdrtools-2.0+a30.pre1/mkisofs/Makefile cdrtools-2.0+a30.pre1/mkisofs.steve/Makefile
--- cdrtools-2.0+a30.pre1/mkisofs/Makefile	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/Makefile	2004-06-16 19:24:36.000000000 +0100
@@ -34,9 +34,10 @@
 CPPOPTS +=	-DSORTING
 CPPOPTS +=	-DUSE_ICONV
 CPPOPTS +=	-I../libhfs_iso/
-CPPOPTS	+=	-DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG \
+CPPOPTS	+=	-DHAVE_CONFIG_H -DUSE_LIBSCHILY -DUSE_SCG -DJIGDO_TEMPLATE \
 		'-DAPPID_DEFAULT="MKISOFS ISO 9660/HFS FILESYSTEM BUILDER & CDRECORD CD-R/DVD CREATOR (C) 1993 E.YOUNGDALE (C) 1997 J.PEARSON/J.SCHILLING"' \
 		-I../cdrecord
+CFLAGS  +=  -Wall -Werror -Wno-unused -g -O2 -fno-strict-aliasing
 CFILES=		mkisofs.c tree.c write.c hash.c rock.c udf.c multi.c \
 		joliet.c match.c name.c fnmatch.c eltorito.c boot.c \
 		getopt.c getopt1.c \
@@ -45,14 +46,16 @@
 		modes.c \
 		apple.c volume.c desktop.c mac_label.c stream.c \
 		ifo_read.c dvd_file.c dvd_reader.c \
-		defaults.c getnum.c
+		defaults.c getnum.c md5.c jte.c \
+		boot-alpha.c boot-hppa.c boot-mips.c \
+		boot-mipsel.c endian.c
 HFILES=		apple.h bootinfo.h config.h defaults.h diskmbr.h exclude.h \
 		fnmatch.h getopt.h iso9660.h mac_label.h mactypes.h match.h \
 		mkisofs.h sunlabel.h udf.h udf_fs.h vms.h \
 		ifo_read.h dvd_file.h dvd_reader.h bswap.h ifo_types.h \
-		../cdrecord/defaults.h
+		../cdrecord/defaults.h md5.h jte.h endian.h
 
-LIBS=		-lhfs -lfile -lunls -lrscg -lscg $(LIB_VOLMGT) -ldeflt -lschily $(SCSILIB) $(LIB_SOCKET)
+LIBS=		-lz -lhfs -lfile -lunls -lrscg -lscg $(LIB_VOLMGT) -ldeflt -lschily $(SCSILIB) $(LIB_SOCKET)
 XMK_FILE=	Makefile.man hybridman.mk
 
 ###########################################################################
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/boot-alpha.c cdrtools-2.0+a30.pre1/mkisofs.steve/boot-alpha.c
--- cdrtools-2.0+a30.pre1/mkisofs/boot-alpha.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/boot-alpha.c	2004-06-16 19:24:36.000000000 +0100
@@ -0,0 +1,114 @@
+/*
+ * Program boot-alpha.c - Handle Linux alpha boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004
+ *
+ * Heavily inspired by isomarkboot by David Mosberger in 1996.
+ *
+ * Copyright 2004 Steve McIntyre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endian.h"
+
+        int     add_boot_alpha_filename   __PR((char *filename));
+static  int     boot_alpha_write          __PR((FILE *outfile));
+static  char   *boot_file_name = NULL;
+
+#define BOOT_STRING "Linux/Alpha aboot for ISO filesystem."
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_alpha_filename(filename)
+    char *filename;
+{
+    boot_file_name = filename;
+    return 0;
+}
+
+static int boot_alpha_write(outfile)
+    FILE *outfile;
+{
+    unsigned long long boot_sector[256]; /* One (ISO) sector */
+    unsigned long long sum = 0;
+	struct directory_entry	*boot_file;	/* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+    int i = 0;
+
+    memset(boot_sector, 0, sizeof(boot_sector));    
+
+    /* Write the text header into the boot sector */
+    strcpy((char *)boot_sector, BOOT_STRING);
+
+    /* Find the dir entry for the boot file by walking our file list */
+    boot_file = search_tree_file(root, boot_file_name);
+    if (!boot_file) {
+#ifdef	USE_LIBSCHILY
+		comerrno(EX_BAD, "Uh oh, I cant find the Alpha boot file '%s'!\n",
+							boot_file_name);
+#else
+		fprintf(stderr, "Uh oh, I cant find the Alpha boot file '%s'!\n",
+							boot_file_name);
+		exit(1);
+#endif
+    }
+
+    /* Grab the ISO start sector and length from the dir entry. ISO
+       uses 2048-byte sectors, but we convert to 512-byte sectors here
+       for the sake of the firmware */
+    extent = get_733(boot_file->isorec.extent);
+    extent *= 4;
+    
+    length = get_733(boot_file->isorec.size);
+    length /= 512; /* I'm sure we should take account of any overlap
+                      here, but I'm copying what isomarkboot
+                      does. Maybe the boot files are specified to be
+                      exact multiples of 512 bytes? */
+
+    fprintf(stderr, "Found alpha boot image %s: using extent %lu, #blocks %lu\n",
+            boot_file_name, extent, length);
+
+    /* Now write those values into the appropriate area of the boot
+       sector in LITTLE ENDIAN format. */
+    write_le64(length, (unsigned char *)(unsigned long long *)&boot_sector[60]);
+    write_le64(extent, (unsigned char *)&boot_sector[61]);
+
+    /* Now generate a checksum of the first 504 bytes of the boot
+       sector and place it in boot_sector[63]. Isomarkboot currently
+       gets this wrong and will not work on big-endian systems! */
+    for (i = 0; i < 63; i++)
+        sum += read_le64((unsigned char *)&boot_sector[i]);
+
+    write_le64(sum, (unsigned char *)&boot_sector[63]);
+
+    jtwrite(boot_sector, sizeof(boot_sector), 1, 0, FALSE);
+    xfwrite(boot_sector, sizeof(boot_sector), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+    return 0;
+}
+
+struct output_fragment alphaboot_desc = {NULL, oneblock_size, NULL, boot_alpha_write, "alpha boot block"};
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/boot-hppa.c cdrtools-2.0+a30.pre1/mkisofs.steve/boot-hppa.c
--- cdrtools-2.0+a30.pre1/mkisofs/boot-hppa.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/boot-hppa.c	2004-06-17 13:10:05.000000000 +0100
@@ -0,0 +1,203 @@
+/*
+ * Program boot-hppa.c - Handle HPPA boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004.
+ *
+ * Heavily inspired by palo:
+ *
+ ****************************************************************************
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
+ *
+ ****************************************************************************
+ * Copyright 2004 Steve McIntyre
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endian.h"
+
+int     add_boot_hppa_cmdline     __PR((char *cmdline));
+int     add_boot_hppa_kernel_32   __PR((char *filename));
+int     add_boot_hppa_kernel_64   __PR((char *filename));
+int     add_boot_hppa_bootloader  __PR((char *filename));
+int     add_boot_hppa_ramdisk     __PR((char *filename));
+
+static  int     boot_hppa_write   __PR((FILE *outfile));
+
+static  char   *hppa_cmdline = NULL;
+static  char   *hppa_kernel_32 = NULL;
+static  char   *hppa_kernel_64 = NULL;
+static  char   *hppa_bootloader = NULL;
+static  char   *hppa_ramdisk = NULL;
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_cmdline(cmdline)
+    char *cmdline;
+{
+    char *ptr = NULL;
+    hppa_cmdline = strdup(cmdline);
+    ptr = hppa_cmdline;
+    while (*ptr)
+    {
+        if (',' == *ptr)
+            *ptr = ' ';
+        ptr++;
+    }    
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_kernel_32(filename)
+    char *filename;
+{
+    hppa_kernel_32 = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_kernel_64(filename)
+    char *filename;
+{
+    hppa_kernel_64 = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_bootloader(filename)
+    char *filename;
+{
+    hppa_bootloader = filename;
+    return 0;
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_hppa_ramdisk(filename)
+    char *filename;
+{
+    hppa_ramdisk = filename;
+    return 0;
+}
+
+static void exit_fatal(type, filename)
+    char *type;
+    char *filename;
+{
+#ifdef	USE_LIBSCHILY
+    comerrno(EX_BAD, "Uh oh, I can't find the %s '%s'!\n",
+             type, filename);
+#else
+    fprintf(stderr, "Uh oh, I can't find the %s '%s'!\n",
+             type, filename);
+    exit(1);
+#endif
+}
+
+static int boot_hppa_write(outfile)
+    FILE *outfile;
+{
+    unsigned char boot_sector[2048]; /* One (ISO) sector */
+	struct directory_entry	*boot_file;	/* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+    int i = 0;
+
+    memset(boot_sector, 0, sizeof(boot_sector));    
+
+    boot_sector[0] = 0x80;  /* magic */
+    boot_sector[1] = 0x00;  /* magic */
+    boot_sector[2] = 'P';
+    boot_sector[3] = 'A';
+    boot_sector[4] = 'L';
+    boot_sector[5] = 'O';
+    boot_sector[6] = 0x00;
+    boot_sector[7] = 0x04;  /* version */
+
+    /* Find the dir entry for the 32-bit kernel by walking our file list */
+    boot_file = search_tree_file(root, hppa_kernel_32);
+    if (!boot_file)
+        exit_fatal("HPPA 32-bit kernel", hppa_kernel_32);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa 32-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_kernel_32, extent, extent, length, length);
+    write_be32(extent, &boot_sector[8]);
+    write_be32(length, &boot_sector[12]);
+
+    /* Find the dir entry for the ramdisk by walking our file list */
+    boot_file = search_tree_file(root, hppa_ramdisk);
+    if (!boot_file)
+        exit_fatal("HPPA ramdisk", hppa_ramdisk);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa ramdisk %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_ramdisk, extent, extent, length, length);
+    write_be32(extent, &boot_sector[16]);
+    write_be32(length, &boot_sector[20]);
+
+    /* Now the commandline */
+    snprintf(&boot_sector[24], 127, "%s", hppa_cmdline);
+
+    /* Find the dir entry for the 64-bit kernel by walking our file list */
+    boot_file = search_tree_file(root, hppa_kernel_64);
+    if (!boot_file)
+        exit_fatal("HPPA 64-bit kernel", hppa_kernel_64);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa 64-bit kernel %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_kernel_64, extent, extent, length, length);
+    write_be32(extent, &boot_sector[232]);
+    write_be32(length, &boot_sector[236]);
+
+    /* Find the dir entry for the IPL by walking our file list */
+    boot_file = search_tree_file(root, hppa_bootloader);
+    if (!boot_file)
+        exit_fatal("HPPA bootloader", hppa_bootloader);
+    extent = 2048 * get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found hppa bootloader %s: using extent %lu (0x%lX), size %lu (0x%lX)\n",
+            hppa_bootloader, extent, extent, length, length);
+    write_be32(extent, &boot_sector[240]);
+    write_be32(length, &boot_sector[244]);
+
+    jtwrite(boot_sector, sizeof(boot_sector), 1, 0, FALSE);
+    xfwrite(boot_sector, sizeof(boot_sector), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+    return 0;
+}
+
+struct output_fragment hppaboot_desc = {NULL, oneblock_size, NULL, boot_hppa_write, "hppa boot block"};
+
+
+
+
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/boot-mips.c cdrtools-2.0+a30.pre1/mkisofs.steve/boot-mips.c
--- cdrtools-2.0+a30.pre1/mkisofs/boot-mips.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/boot-mips.c	2004-06-16 19:24:36.000000000 +0100
@@ -0,0 +1,328 @@
+/*
+ * Program boot-mips.c - Handle big-endian boot extensions to iso9660.
+ *
+ * Written by Steve McIntyre <steve@einval.com> June 2004
+ *
+ * Heavily inspired by / borrowed from genisovh:
+ *
+ * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org>
+ *            (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ * 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.
+ *
+ * Format for volume header information
+ *
+ * The volume header is a block located at the beginning of all disk
+ * media (sector 0).  It contains information pertaining to physical
+ * device parameters and logical partition information.
+ *
+ * The volume header is manipulated by disk formatters/verifiers,
+ * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers.
+ *
+ * Previous versions of IRIX wrote a copy of the volume header is
+ * located at sector 0 of each track of cylinder 0.  These copies were
+ * never used, and reduced the capacity of the volume header to hold large
+ * files, so this practice was discontinued.
+ * The volume header is constrained to be less than or equal to 512
+ * bytes long.  A particular copy is assumed valid if no drive errors
+ * are detected, the magic number is correct, and the 32 bit 2's complement
+ * of the volume header is correct.  The checksum is calculated by initially
+ * zeroing vh_csum, summing the entire structure and then storing the
+ * 2's complement of the sum.  Thus a checksum to verify the volume header
+ * should be 0.
+ *
+ * The error summary table, bad sector replacement table, and boot blocks are
+ * located by searching the volume directory within the volume header.
+ *
+ * Tables are sized simply by the integral number of table records that
+ * will fit in the space indicated by the directory entry.
+ *
+ * The amount of space allocated to the volume header, replacement blocks,
+ * and other tables is user defined when the device is formatted.
+ */
+
+#include <stdint.h>
+
+/*
+ * device parameters are in the volume header to determine mapping
+ * from logical block numbers to physical device addresses
+ *
+ * Linux doesn't care ...
+ */
+struct device_parameters {
+	uint8_t dp_skew;	/* spiral addressing skew */
+	uint8_t dp_gap1;	/* words of 0 before header */
+	uint8_t dp_gap2;	/* words of 0 between hdr and data */
+	uint8_t dp_spares_cyl;	/* This is for drives (such as SCSI
+		that support zone oriented sparing, where the zone is larger
+		than one track.  It gets subracteded from the cylinder size
+		( dp_trks0 * dp_sec) when doing partition size calculations */
+	uint16_t dp_cyls;	/* number of usable cylinders (i.e.,
+		doesn't include cylinders reserved by the drive for badblocks,
+		etc.). For drives with variable geometry, this number may be
+		decreased so that:
+		dp_cyls * ((dp_heads * dp_trks0) - dp_spares_cyl) <= actualcapacity
+		This happens on SCSI drives such as the Wren IV and Toshiba 156
+		Also see dp_cylshi below */
+	uint16_t dp_shd0;	/* starting head vol 0 */
+	uint16_t dp_trks0;	/* number of tracks / cylinder vol 0*/
+	uint8_t dp_ctq_depth;	/* Depth of CTQ queue */
+	uint8_t dp_cylshi;	/* high byte of 24 bits of cylinder count */
+	uint16_t dp_unused;	/* not used */
+	uint16_t dp_secs;	/* number of sectors/track */
+	uint16_t dp_secbytes;	/* length of sector in bytes */
+	uint16_t dp_interleave;	/* sector interleave */
+	int32_t dp_flags;		/* controller characteristics */
+	int32_t dp_datarate;		/* bytes/sec for kernel stats */
+	int32_t dp_nretries;		/* max num retries on data error */
+	int32_t dp_mspw;		/* ms per word to xfer, for iostat */
+	uint16_t dp_xgap1;	/* Gap 1 for xylogics controllers */
+	uint16_t dp_xsync;    /* sync delay for xylogics controllers */
+	uint16_t dp_xrdly;    /* read delay for xylogics controllers */
+	uint16_t dp_xgap2;    /* gap 2 for xylogics controllers */
+	uint16_t dp_xrgate;   /* read gate for xylogics controllers */
+	uint16_t dp_xwcont;   /* write continuation for xylogics */
+};
+
+/*
+ * Device characterization flags
+ * (dp_flags)
+ */
+#define	DP_SECTSLIP	0x00000001	/* sector slip to spare sector */
+#define	DP_SECTFWD	0x00000002	/* forward to replacement sector */
+#define	DP_TRKFWD	0x00000004	/* forward to replacement track */
+#define	DP_MULTIVOL	0x00000008	/* multiple volumes per spindle */
+#define	DP_IGNOREERRORS	0x00000010	/* transfer data regardless of errors */
+#define DP_RESEEK	0x00000020	/* recalibrate as last resort */
+#define	DP_CTQ_EN	0x00000040	/* enable command tag queueing */
+
+/*
+ * Boot blocks, bad sector tables, and the error summary table, are located
+ * via the volume_directory.
+ */
+#define VDNAMESIZE	8
+
+struct volume_directory {
+	int8_t  vd_name[VDNAMESIZE];	/* name */
+	int32_t vd_lbn;			/* logical block number */
+	int32_t vd_nbytes;		/* file length in bytes */
+};
+
+/*
+ * partition table describes logical device partitions
+ * (device drivers examine this to determine mapping from logical units
+ * to cylinder groups, device formatters/verifiers examine this to determine
+ * location of replacement tracks/sectors, etc)
+ *
+ * NOTE: pt_firstlbn SHOULD BE CYLINDER ALIGNED
+ */
+struct partition_table {		/* one per logical partition */
+	int32_t pt_nblks;		/* # of logical blks in partition */
+	int32_t pt_firstlbn;		/* first lbn of partition */
+	int32_t pt_type;		/* use of partition */
+};
+
+#define	PTYPE_VOLHDR	0		/* partition is volume header */
+#define	PTYPE_TRKREPL	1		/* partition is used for repl trks */
+#define	PTYPE_SECREPL	2		/* partition is used for repl secs */
+#define	PTYPE_RAW	3		/* partition is used for data */
+#define	PTYPE_BSD42	4		/* partition is 4.2BSD file system */
+#define	PTYPE_BSD	4		/* partition is 4.2BSD file system */
+#define	PTYPE_SYSV	5		/* partition is SysV file system */
+#define	PTYPE_VOLUME	6		/* partition is entire volume */
+#define	PTYPE_EFS	7		/* partition is sgi EFS */
+#define	PTYPE_LVOL	8		/* partition is part of a logical vol */
+#define	PTYPE_RLVOL	9		/* part of a "raw" logical vol */
+#define	PTYPE_XFS	10		/* partition is sgi XFS */
+#define	PTYPE_XFSLOG	11		/* partition is sgi XFS log */
+#define	PTYPE_XLV	12		/* partition is part of an XLV vol */
+#define	PTYPE_XVM	13		/* partition is sgi XVM */
+#define	PTYPE_LSWAP	0x82		/* partition is Linux swap */
+#define	PTYPE_LINUX	0x83		/* partition is Linux native */
+#define NPTYPES		16
+
+#define	VHMAGIC		0xbe5a941	/* randomly chosen value */
+#define	NPARTAB		16		/* 16 unix partitions */
+#define	NVDIR		15		/* max of 15 directory entries */
+#define BFNAMESIZE	16		/* max 16 chars in boot file name */
+
+/* Partition types for ARCS */
+#define NOT_USED        0       /* Not used 				*/
+#define FAT_SHORT       1       /* FAT filesystem, 12-bit FAT entries 	*/
+#define FAT_LONG        4       /* FAT filesystem, 16-bit FAT entries 	*/
+#define EXTENDED        5       /* extended partition 			*/
+#define HUGE            6       /* huge partition- MS/DOS 4.0 and later */
+
+/* Active flags for ARCS */
+#define BOOTABLE        0x00;
+#define NOT_BOOTABLE    0x80;
+
+struct volume_header {
+	int32_t vh_magic; /* identifies volume header */
+	int16_t vh_rootpt; /* root partition number */
+	int16_t vh_swappt; /* swap partition number */
+	int8_t vh_bootfile[BFNAMESIZE]; /* name of file to boot */
+	struct device_parameters vh_dp; /* device parameters */
+	struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */
+	struct partition_table vh_pt[NPARTAB]; /* device partition layout */
+	int32_t vh_csum; /* volume header checksum */
+	int32_t vh_fill; /* fill out to 512 bytes */
+    char pad[1536];  /* pad out to 2048 */
+};
+
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endian.h"
+
+int     add_boot_mips_filename    __PR((char *filename));
+
+static  int     boot_mips_write   __PR((FILE *outfile));
+
+#define MAX_NAMES 15
+static char *boot_mips_filename[MAX_NAMES] =
+{
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL,
+    NULL, NULL, NULL
+};
+
+static int boot_mips_num_files = 0;
+
+#define SECTORS_PER_TRACK	32
+#define BYTES_PER_SECTOR	512
+
+int add_boot_mips_filename(filename)
+    char *filename;
+{
+    if (boot_mips_num_files < MAX_NAMES)
+    {
+        boot_mips_filename[boot_mips_num_files] = filename;
+        boot_mips_num_files++;
+    }
+
+    else
+    {
+#ifdef	USE_LIBSCHILY
+        comerrno(EX_BAD, "Too many MIPS boot files!\n");
+#else
+        fprintf(stderr, "Too many MIPS boot files!\n");
+        exit(1);
+#endif
+    }
+    return 0;
+}
+
+static void vh_calc_checksum(struct volume_header *vh)
+{
+	uint32_t newsum = 0;
+	unsigned char *buffer = (unsigned char *)vh;
+	unsigned int i;
+
+	vh->vh_csum = 0;
+
+	for(i = 0; i < sizeof(struct volume_header); i += 4)
+        newsum -= read_be32(&buffer[i]);
+
+    write_be32(newsum, (unsigned char *)&vh->vh_csum);
+}
+
+static char *file_base_name(char *path)
+{
+    char *endptr = path;
+    char *ptr = path;
+    
+    while (*ptr != '\0')
+    {
+        if ('/' == *ptr)
+            endptr = ++ptr;
+        else
+            ++ptr;
+    }
+    return endptr;
+}
+
+static int boot_mips_write(outfile)
+    FILE *outfile;
+{
+	struct directory_entry	*boot_file;	/* Boot file we need to search for */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+	int i;
+	struct volume_header vh;
+    unsigned long long iso_size = 0;
+    char *filename = NULL;
+
+	memset(&vh, 0, sizeof(vh));
+
+    iso_size = last_extent * 2048;
+
+    write_be32(VHMAGIC, (unsigned char *)&vh.vh_magic);
+
+	/* Values from an IRIX cd */
+    write_be16(BYTES_PER_SECTOR, (unsigned char *)&vh.vh_dp.dp_secbytes);
+    write_be16(SECTORS_PER_TRACK, (unsigned char *)&vh.vh_dp.dp_secs);
+    write_be32(DP_RESEEK|DP_IGNOREERRORS|DP_TRKFWD, (unsigned char *)&vh.vh_dp.dp_flags);
+    write_be16(1, (unsigned char *)&vh.vh_dp.dp_trks0);
+
+    write_be16((iso_size + BYTES_PER_SECTOR - 1) / (SECTORS_PER_TRACK * BYTES_PER_SECTOR),
+               (unsigned char *)&vh.vh_dp.dp_cyls);
+
+	for(i = 0; i < boot_mips_num_files; i++)
+    {
+        boot_file = search_tree_file(root, boot_mips_filename[i]);
+        
+        if (!boot_file) {
+#ifdef	USE_LIBSCHILY
+            comerrno(EX_BAD, "Uh oh, I cant find the MIPS boot file '%s'!\n",
+                     boot_mips_filename[i]);
+#else
+            fprintf(stderr, "Uh oh, I cant find the MIPS boot file '%s'!\n",
+                    boot_mips_filename[i]);
+            exit(1);
+#endif
+        }
+
+        extent = get_733(boot_file->isorec.extent) * 4;
+        length = ((get_733(boot_file->isorec.size) + 2047) / 2048) * 2048;
+        filename = file_base_name(boot_mips_filename[i]);
+
+        strncpy(vh.vh_vd[i].vd_name, filename, MIN(VDNAMESIZE, strlen(filename)));
+        write_be32(extent, (unsigned char *)&vh.vh_vd[i].vd_lbn);
+        write_be32(length, (unsigned char *)&vh.vh_vd[i].vd_nbytes);
+        
+        fprintf(stderr, "Found mips boot image %s, using extent %lu (0x%lX), #blocks %lu (0x%lX)\n",
+                filename, extent, extent, length, length);
+	}
+
+	/* Create volume partition on whole cd iso */
+    write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[10].pt_nblks);
+    write_be32(0, (unsigned char *)&vh.vh_pt[10].pt_firstlbn);
+    write_be32(PTYPE_VOLUME, (unsigned char *)&vh.vh_pt[10].pt_type);
+
+	/* Create volume header partition, also on WHOLE cd iso */
+    write_be32((iso_size + (BYTES_PER_SECTOR - 1))/ BYTES_PER_SECTOR, (unsigned char *)&vh.vh_pt[8].pt_nblks);
+    write_be32(0, (unsigned char *)&vh.vh_pt[8].pt_firstlbn);
+    write_be32(PTYPE_VOLHDR, (unsigned char *)&vh.vh_pt[8].pt_type);
+
+	/* Create checksum */
+	vh_calc_checksum(&vh);
+
+    jtwrite(&vh, sizeof(vh), 1, 0, FALSE);
+    xfwrite(&vh, sizeof(vh), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+	return 0;
+}
+
+struct output_fragment mipsboot_desc = {NULL, oneblock_size, NULL, boot_mips_write, "MIPS boot block"};
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/boot-mipsel.c cdrtools-2.0+a30.pre1/mkisofs.steve/boot-mipsel.c
--- cdrtools-2.0+a30.pre1/mkisofs/boot-mipsel.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/boot-mipsel.c	2004-06-17 11:36:06.000000000 +0100
@@ -0,0 +1,242 @@
+/*
+ * Program boot-mipsel.c - Handle Mipsel boot extensions to iso9660.
+ *
+ *  Written by Steve McIntyre <steve@einval.com> (2004).
+ *
+ * Heavily inspired by / borrowed from delo:
+ *
+ * Copyright: (C) 2002 by Florian Lohoff <flo@rfc822.org>
+ *            (C) 2004 by Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
+ *
+ * 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.
+ *
+ * Format for volume header information
+ *
+ * The volume header is a block located at the beginning of all disk
+ * media (sector 0).  It contains information pertaining to physical
+ * device parameters and logical partition information.
+ *
+ * The volume header is manipulated by disk formatters/verifiers,
+ * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers.
+ *
+ * Previous versions of IRIX wrote a copy of the volume header is
+ * located at sector 0 of each track of cylinder 0.  These copies were
+ * never used, and reduced the capacity of the volume header to hold large
+ * files, so this practice was discontinued.
+ * The volume header is constrained to be less than or equal to 512
+ * bytes long.  A particular copy is assumed valid if no drive errors
+ * are detected, the magic number is correct, and the 32 bit 2's complement
+ * of the volume header is correct.  The checksum is calculated by initially
+ * zeroing vh_csum, summing the entire structure and then storing the
+ * 2's complement of the sum.  Thus a checksum to verify the volume header
+ * should be 0.
+ *
+ * The error summary table, bad sector replacement table, and boot blocks are
+ * located by searching the volume directory within the volume header.
+ *
+ * Tables are sized simply by the integral number of table records that
+ * will fit in the space indicated by the directory entry.
+ *
+ * The amount of space allocated to the volume header, replacement blocks,
+ * and other tables is user defined when the device is formatted.
+ */
+
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <fctldefs.h>
+#include <utypes.h>
+#include <intcvt.h>
+#include "match.h"
+#include "diskmbr.h"
+#include "bootinfo.h"
+#include <schily.h>
+#include "endian.h"
+#include <errno.h>
+#include <elf.h>
+
+int             add_boot_mipsel_filename  __PR((char *filename));
+static  int     boot_mipsel_write         __PR((FILE *outfile));
+
+static  char   *boot_file_name = NULL;
+
+#define MAX_MAPS        51
+#define DEC_BOOT_MAGIC  0x02757a
+#define HD_SECTOR_SIZE  512
+
+/* Those were stolen from linux kernel headers. */
+
+struct extent {
+    uint32_t count;
+    uint32_t start;
+} __attribute__((packed));
+
+struct dec_bootblock {
+    int8_t pad[8];
+    int32_t magic;          /* We are a DEC BootBlock */
+    int32_t mode;           /* 0: Single extent, 1: Multi extent boot */
+    int32_t loadAddr;       /* Load below kernel */
+    int32_t execAddr;       /* And exec there */
+    struct extent bootmap[MAX_MAPS];
+} __attribute__((packed));
+
+static void swap_in_elf32_ehdr(Elf32_Ehdr *ehdr)
+{
+    ehdr->e_type = read_le16((unsigned char *)&ehdr->e_type);
+    ehdr->e_machine = read_le16((unsigned char *)&ehdr->e_machine);
+    ehdr->e_version = read_le32((unsigned char *)&ehdr->e_version);
+    ehdr->e_entry = read_le32((unsigned char *)&ehdr->e_entry);
+    ehdr->e_phoff = read_le32((unsigned char *)&ehdr->e_phoff);
+    ehdr->e_shoff = read_le32((unsigned char *)&ehdr->e_shoff);
+    ehdr->e_flags = read_le32((unsigned char *)&ehdr->e_flags);
+    ehdr->e_ehsize = read_le16((unsigned char *)&ehdr->e_ehsize);
+    ehdr->e_phentsize = read_le16((unsigned char *)&ehdr->e_phentsize);
+    ehdr->e_phnum = read_le16((unsigned char *)&ehdr->e_phnum);
+    ehdr->e_shentsize = read_le16((unsigned char *)&ehdr->e_shentsize);
+    ehdr->e_shnum = read_le16((unsigned char *)&ehdr->e_shnum);
+    ehdr->e_shstrndx = read_le16((unsigned char *)&ehdr->e_shstrndx);
+}
+
+static void swap_in_elf32_phdr(Elf32_Phdr *phdr)
+{
+    phdr->p_type = read_le32((unsigned char *)&phdr->p_type);
+    phdr->p_offset = read_le32((unsigned char *)&phdr->p_offset);
+    phdr->p_vaddr = read_le32((unsigned char *)&phdr->p_vaddr);
+    phdr->p_paddr = read_le32((unsigned char *)&phdr->p_paddr);
+    phdr->p_filesz = read_le32((unsigned char *)&phdr->p_filesz);
+    phdr->p_memsz = read_le32((unsigned char *)&phdr->p_memsz);
+    phdr->p_flags = read_le32((unsigned char *)&phdr->p_flags);
+    phdr->p_align = read_le32((unsigned char *)&phdr->p_align);
+}
+
+/* Simple function: store the filename to be used later when we need
+   to find the boot file */
+extern int add_boot_mipsel_filename(filename)
+    char *filename;
+{
+    boot_file_name = filename;
+    return 0;
+}
+
+/* Parse the ELF header of the boot loaded to work out the load
+   address and exec address */
+static int parse_boot_file(char *filename, int32_t *loadaddr, int32_t *execaddr, int32_t *offset, int32_t *count)
+{
+    int error = 0;
+    FILE *loader = NULL;
+    Elf32_Ehdr ehdr;
+    Elf32_Phdr phdr;
+    
+    loader = fopen(filename, "rb");
+    if (!loader)
+        return errno;
+    
+    error = fread(&ehdr, sizeof(ehdr), 1, loader);
+    if (1 != error)
+        return EIO;
+
+    swap_in_elf32_ehdr(&ehdr);
+    if (!(ehdr.e_ident[EI_MAG0] == ELFMAG0
+          && ehdr.e_ident[EI_MAG1] == ELFMAG1
+          && ehdr.e_ident[EI_MAG2] == ELFMAG2
+          && ehdr.e_ident[EI_MAG3] == ELFMAG3
+          && ehdr.e_ident[EI_CLASS] == ELFCLASS32
+          && ehdr.e_ident[EI_DATA] == ELFDATA2LSB
+          && ehdr.e_ident[EI_VERSION] == EV_CURRENT
+          && ehdr.e_type == ET_EXEC
+          && ehdr.e_machine == EM_MIPS
+          && ehdr.e_version == EV_CURRENT))
+    {
+        fprintf(stderr, "Sorry, %s is not a MIPS ELF32 little endian file", filename);        
+        return EINVAL;
+    }
+    if (ehdr.e_phnum != 1)
+    {
+        fprintf(stderr, "Sorry, %s has more than one ELF segment", filename);
+        return EINVAL;
+    }
+    fseek(loader, ehdr.e_phoff, SEEK_SET);
+    error = fread(&phdr, sizeof(phdr), 1, loader);
+    if (1 != error)
+        return EIO;
+
+    *loadaddr = phdr.p_vaddr;
+    *execaddr = ehdr.e_entry;
+	*offset = (phdr.p_offset + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE;
+	*count = (phdr.p_filesz + HD_SECTOR_SIZE - 1) / HD_SECTOR_SIZE;
+
+    fprintf(stderr, "Parsed mipsel boot image %s: using loadaddr 0x%X, execaddr 0x%X, offset 0x%X, count 0x%X\n",
+            filename, *loadaddr, *execaddr, *offset, *count);
+
+    fclose(loader);
+    return 0;
+}
+
+static int boot_mipsel_write(outfile)
+    FILE *outfile;
+{
+    char sector[2048];
+    struct dec_bootblock *bb = (struct dec_bootblock *)sector;
+    int error = 0;
+    int offset = 0;
+    int count = 0;
+    struct directory_entry	*boot_file;	/* Boot file we need to search for in the image */
+    unsigned long length = 0;
+    unsigned long extent = 0;
+    int loadaddr = 0;
+    int execaddr = 0;
+
+    memset(sector, 0, sizeof(sector));
+
+    /* Fill in our values we care on */
+    write_le32(DEC_BOOT_MAGIC, (unsigned char *)&bb->magic);
+    write_le32(1, (unsigned char *)&bb->mode);
+
+    /* Find the file entry in the CD image */
+    boot_file = search_tree_file(root, boot_file_name);
+    if (!boot_file)
+    {
+#ifdef	USE_LIBSCHILY
+		comerrno(EX_BAD, "Uh oh, unable to find the mipsel boot file '%s'!\n",
+                 boot_file_name);
+#else
+		fprintf(stderr, "Uh oh, unable to find the mipsel boot file '%s'!\n",
+                boot_file_name);
+		exit(1);
+#endif
+    }
+
+    extent = get_733(boot_file->isorec.extent);
+    length = get_733(boot_file->isorec.size);
+    fprintf(stderr, "Found mipsel boot loader %s: using extent %lu, #blocks %lu\n",
+            boot_file_name, extent, length);
+
+    /* Parse the ELF headers on the boot file */
+    error = parse_boot_file(boot_file->whole_name, &loadaddr, &execaddr, &offset, &count);
+    if (error)
+    {
+#ifdef	USE_LIBSCHILY
+		comerrno(EX_BAD, "Uh oh, unable to parse the mipsel boot file '%s'!\n",
+                 boot_file->whole_name);
+#else
+		fprintf(stderr, "Uh oh, unable to parse the mipsel boot file '%s'!\n",
+                boot_file->whole_name);
+		exit(1);
+#endif
+    }
+
+    write_le32(loadaddr, (unsigned char *)&bb->loadAddr);
+    write_le32(execaddr, (unsigned char *)&bb->execAddr);
+    write_le32((extent * 4) + offset, (unsigned char *)&bb->bootmap[0].start);
+    write_le32(count, (unsigned char *)&bb->bootmap[0].count);
+    
+    jtwrite(sector, sizeof(sector), 1, 0, FALSE);
+    xfwrite(sector, sizeof(sector), 1, outfile, 0, FALSE);
+    last_extent_written++;
+
+    return 0;
+}
+
+struct output_fragment mipselboot_desc = {NULL, oneblock_size, NULL, boot_mipsel_write, "mipsel boot block"};
+
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/boot.c cdrtools-2.0+a30.pre1/mkisofs.steve/boot.c
--- cdrtools-2.0+a30.pre1/mkisofs/boot.c	2004-02-22 15:25:09.000000000 +0000
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/boot.c	2004-06-16 19:24:36.000000000 +0100
@@ -373,6 +373,7 @@
 	 */
 	amt = roundup(last_extent_written, (CD_CYLSIZE/SECTOR_SIZE)) - last_extent_written;
 	for (n = 0; n < amt; n++) {
+        jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
 		last_extent_written++;
 	}
@@ -403,6 +404,7 @@
 			memset(buffer, 0, sizeof (buffer));
 			if (read(f, buffer, SECTOR_SIZE) < 0)
 				comerr("Read error on '%s'.\n", boot_files[i]);
+            jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
 			xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
 			last_extent_written++;
 		}
@@ -484,6 +486,7 @@
 		memcpy(buffer, &cd_label, 512);
 	}
 
+    jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
@@ -523,7 +526,8 @@
 			comerr("Read error on '%s'.\n", genboot_image);
 
 		if (i != 0 || last_extent_written == session_start) {
-			xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
+			jtwrite(buffer, SECTOR_SIZE, 1, 0, FALSE);
+            xfwrite(buffer, SECTOR_SIZE, 1, outfile, 0, FALSE);
 			last_extent_written++;
 		}
 	}
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/eltorito.c cdrtools-2.0+a30.pre1/mkisofs.steve/eltorito.c
--- cdrtools-2.0+a30.pre1/mkisofs/eltorito.c	2004-03-04 22:39:29.000000000 +0000
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/eltorito.c	2004-06-16 19:24:36.000000000 +0100
@@ -666,6 +666,7 @@
 	}
 	/* Next we write out the boot volume descriptor for the disc */
 	get_torito_desc(&gboot_desc);
+	jtwrite(&gboot_desc, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(&gboot_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/endian.c cdrtools-2.0+a30.pre1/mkisofs.steve/endian.c
--- cdrtools-2.0+a30.pre1/mkisofs/endian.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/endian.c	2004-06-16 19:24:36.000000000 +0100
@@ -0,0 +1,188 @@
+#include <mconfig.h>
+#include "endian.h"
+
+/* Write a 64-bit quantity out into memory in BIG ENDIAN order */
+void write_be64(in, out)
+    unsigned long long in;
+    unsigned char *out;
+{
+    out[0] = (in >> 56) & 0xFF;
+    out[1] = (in >> 48) & 0xFF;
+    out[2] = (in >> 40) & 0xFF;
+    out[3] = (in >> 32) & 0xFF;
+    out[4] = (in >> 24) & 0xFF;
+    out[5] = (in >> 16) & 0xFF;
+    out[6] = (in >> 8) & 0xFF;
+    out[7] = in & 0xFF;
+}
+
+/* Read in a 64-bit BIG ENDIAN quantity */
+unsigned long long read_be64(in)
+    unsigned char *in;
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0] << 56;
+    result |= (unsigned long long)in[1] << 48;
+    result |= (unsigned long long)in[2] << 40;
+    result |= (unsigned long long)in[3] << 32;
+    result |= (unsigned long long)in[4] << 24;
+    result |= (unsigned long long)in[5] << 16;
+    result |= (unsigned long long)in[6] << 8;
+    result |= (unsigned long long)in[7];
+    
+    return result;
+}
+
+/* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le64(in, out)
+    unsigned long long in;
+    unsigned char *out;
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+    out[4] = (in >> 32) & 0xFF;
+    out[5] = (in >> 40) & 0xFF;
+    out[6] = (in >> 48) & 0xFF;
+    out[7] = (in >> 56) & 0xFF;
+}
+
+/* Read in a 64-bit LITTLE ENDIAN quantity */
+unsigned long long read_le64(in)
+    unsigned char *in;
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0];
+    result |= (unsigned long long)in[1] << 8;
+    result |= (unsigned long long)in[2] << 16;
+    result |= (unsigned long long)in[3] << 24;
+    result |= (unsigned long long)in[4] << 32;
+    result |= (unsigned long long)in[5] << 40;
+    result |= (unsigned long long)in[6] << 48;
+    result |= (unsigned long long)in[7] << 56;
+    
+    return result;
+}
+
+/* Write a 48-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le48(in, out)
+    unsigned long long in;
+    unsigned char *out;
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+    out[4] = (in >> 32) & 0xFF;
+    out[5] = (in >> 40) & 0xFF;
+}
+
+/* Read in a 48-bit LITTLE ENDIAN quantity */
+unsigned long long read_le48(in)
+    unsigned char *in;
+{
+    unsigned long long result = 0;
+
+    result |= (unsigned long long)in[0];
+    result |= (unsigned long long)in[1] << 8;
+    result |= (unsigned long long)in[2] << 16;
+    result |= (unsigned long long)in[3] << 24;
+    result |= (unsigned long long)in[4] << 32;
+    result |= (unsigned long long)in[5] << 40;
+    
+    return result;
+}
+
+/* Write a 32-bit quantity out into memory in BIG ENDIAN order */
+void write_be32(in, out)
+    unsigned long in;
+    unsigned char *out;
+{
+    out[0] = (in >> 24) & 0xFF;
+    out[1] = (in >> 16) & 0xFF;
+    out[2] = (in >> 8) & 0xFF;
+    out[3] = in & 0xFF;
+}
+
+/* Read in a 32-bit BIG ENDIAN quantity */
+unsigned long read_be32(in)
+    unsigned char *in;
+{
+    unsigned long result = 0;
+
+    result |= (unsigned long)in[0] << 24;
+    result |= (unsigned long)in[1] << 16;
+    result |= (unsigned long)in[2] << 8;
+    result |= (unsigned long)in[3];
+    
+    return result;
+}
+
+/* Write a 32-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le32(in, out)
+    unsigned long in;
+    unsigned char *out;
+{
+    out[0] = in & 0xFF;
+    out[1] = (in >> 8) & 0xFF;
+    out[2] = (in >> 16) & 0xFF;
+    out[3] = (in >> 24) & 0xFF;
+}
+
+/* Read in a 32-bit LITTLE ENDIAN quantity */
+unsigned long read_le32(in)
+    unsigned char *in;
+{
+    unsigned long result = 0;
+
+    result |= (unsigned long)in[0];
+    result |= (unsigned long)in[1] << 8;
+    result |= (unsigned long)in[2] << 16;
+    result |= (unsigned long)in[3] << 24;
+    
+    return result;
+}
+
+/* Write a 16-bit quantity out into memory in BIG ENDIAN order */
+void write_be16(in, out)
+    unsigned short in;
+    unsigned char *out;
+{
+    out[0] = (in >> 8) & 0xFF;
+    out[1] = in & 0xFF;
+}
+    
+/* Read in a 16-bit BIG ENDIAN quantity */
+unsigned short read_be16(in)
+    unsigned char *in;
+{
+    unsigned short result = 0;
+    
+    result |= (unsigned short)in[0] << 8;
+    result |= (unsigned short)in[1];
+    return result;
+}
+
+/* Write a 16-bit quantity out into memory in LITTLE ENDIAN order */
+void write_le16(in, out)
+    unsigned short in;
+    unsigned char *out;
+{
+    out[0] = in & 0xFF;
+    out[1] = in & 0xFF >> 8;
+}
+    
+/* Read in a 16-bit LITTLE ENDIAN quantity */
+unsigned short read_le16(in)
+    unsigned char *in;
+{
+    unsigned short result = 0;
+    
+    result |= (unsigned short)in[0];
+    result |= (unsigned short)in[1] << 8;
+    return result;
+}
+
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/endian.h cdrtools-2.0+a30.pre1/mkisofs.steve/endian.h
--- cdrtools-2.0+a30.pre1/mkisofs/endian.h	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/endian.h	2004-06-16 19:24:36.000000000 +0100
@@ -0,0 +1,17 @@
+void                  write_be64  __PR((unsigned long long in, unsigned char *out));
+unsigned long long    read_be64   __PR((unsigned char *in));
+void                  write_le64  __PR((unsigned long long in, unsigned char *out));
+unsigned long long    read_le64   __PR((unsigned char *in));
+
+void                  write_le48  __PR((unsigned long long in, unsigned char *out));
+unsigned long long    read_le48   __PR((unsigned char *in));
+
+void                  write_be32  __PR((unsigned long in, unsigned char *out));
+unsigned long         read_be32   __PR((unsigned char *in));
+void                  write_le32  __PR((unsigned long in, unsigned char *out));
+unsigned long         read_le32   __PR((unsigned char *in));
+
+void                  write_be16  __PR((unsigned short in, unsigned char *out));
+unsigned short        read_be16   __PR((unsigned char *in));
+void                  write_le16  __PR((unsigned short in, unsigned char *out));
+unsigned short        read_le16   __PR((unsigned char *in));
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/joliet.c cdrtools-2.0+a30.pre1/mkisofs.steve/joliet.c
--- cdrtools-2.0+a30.pre1/mkisofs/joliet.c	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/joliet.c	2004-06-16 19:24:37.000000000 +0100
@@ -989,6 +989,7 @@
 			dir_index, dpnt->de_name);
 #endif
 	}
+	jtwrite(directory_buffer, total_size, 1, 0, FALSE);
 	xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
 	last_extent_written += total_size >> 11;
 	free(directory_buffer);
@@ -1393,9 +1394,12 @@
 	FILE	*outfile;
 {
 	/* Next we write the path tables */
+	jtwrite(jpath_table_l, jpath_blocks << 11, 1, 0, FALSE);
 	xfwrite(jpath_table_l, jpath_blocks << 11, 1, outfile, 0, FALSE);
+	last_extent_written += jpath_blocks;
+	jtwrite(jpath_table_m, jpath_blocks << 11, 1, 0, FALSE);
 	xfwrite(jpath_table_m, jpath_blocks << 11, 1, outfile, 0, FALSE);
-	last_extent_written += 2 * jpath_blocks;
+	last_extent_written += jpath_blocks;
 	free(jpath_table_l);
 	free(jpath_table_m);
 	jpath_table_l = NULL;
@@ -1448,6 +1452,7 @@
 	/* Next we write out the boot volume descriptor for the disc */
 	jvol_desc = vol_desc;
 	get_joliet_vol_desc(&jvol_desc);
+	jtwrite(&jvol_desc, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(&jvol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/jte.c cdrtools-2.0+a30.pre1/mkisofs.steve/jte.c
--- cdrtools-2.0+a30.pre1/mkisofs/jte.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/jte.c	2004-06-18 10:33:05.000000000 +0100
@@ -0,0 +1,790 @@
+#include <mconfig.h>
+#include "mkisofs.h"
+#include <timedefs.h>
+#include <fctldefs.h>
+#include <zlib.h>
+#include <regex.h>
+#ifdef SORTING
+#include "match.h"
+#endif /* SORTING */
+#include <errno.h>
+#include <schily.h>
+#ifdef DVD_VIDEO
+#include "dvd_reader.h"
+#include "dvd_file.h"
+#include "ifo_read.h"
+#include "md5.h"
+#include "endian.h"
+#endif
+#ifdef APPLE_HYB
+#include <ctype.h>
+#endif
+
+#ifdef	VMS
+#include "vms.h"
+#endif
+
+/* Different types used in building our state list below */
+#define JTET_FILE_MATCH 1
+#define JTET_NOMATCH    2
+
+#define JTE_VER_MAJOR     0x0001
+#define JTE_VER_MINOR     0x0003
+#define JTE_NAME          "JTE"
+#define JTE_COMMENT       "JTE at http://www.einval.com/~steve/software/JTE/ ; jigdo at http://atterer.net/jigdo/"
+
+#define JIGDO_TEMPLATE_VERSION "1.1"
+
+/* Simple list to hold the results of -jigdo-exclude command line
+   options. Seems easiest to do this using regexps. We use 4 copies of
+   each to allow us to emulate glob-style matching:
+
+   ^PATTERN$
+   ^PATTERN/
+   /PATTERN$
+   /PATTERN/
+
+   We convert the patterns from the command-line into (simple) regular
+   expressions (x4), then compile those regular expressions and store
+   them raw here for speed.
+*/
+struct exclude_regex
+{
+    regex_t match_pattern[4];
+    char *exclude_rule;
+    struct exclude_regex *next;
+};
+
+struct path_mapping
+{
+    char *from;
+    char *to;
+    struct path_mapping *next;
+};
+
+FILE	*jtjigdo = NULL;
+FILE	*jttemplate = NULL;
+char    *jjigdo_out = NULL; /* Output name for jigdo .jigdo file; NULL means don't do it */
+char    *jtemplate_out = NULL; /* Output name for jigdo template file; NULL means don't do it */
+int      jte_min_size = 8192; /* 8KB seems a reasonable minimum */
+struct  exclude_regex *exclude_list = NULL;
+struct  path_mapping  *map_list = NULL;
+unsigned long long template_size = 0;
+unsigned long long image_size = 0;
+
+static struct mk_MD5Context iso_context;
+static struct mk_MD5Context template_context;
+
+typedef struct _file_entry
+{
+    unsigned char md5[16];
+    off_t file_length;
+    char *filename;
+} file_entry_t;
+
+typedef struct _unmatched_entry
+{
+    off_t uncompressed_length;
+} unmatched_entry_t;    
+
+typedef struct _entry
+{
+    int entry_type; /* JTET_TYPE as above */
+    struct _entry *next;
+    union
+    {
+        file_entry_t      file;
+        unmatched_entry_t chunk;
+    } data;
+} entry_t;
+
+typedef struct _jigdo_file_entry
+{
+    unsigned char type;
+    unsigned char fileLen[6];
+    unsigned char fileRsync[8];
+    unsigned char fileMD5[16];
+} jigdo_file_entry_t;
+
+typedef struct _jigdo_chunk_entry
+{
+    unsigned char type;
+    unsigned char skipLen[6];
+} jigdo_chunk_entry_t;
+
+typedef struct _jigdo_image_entry
+{
+    unsigned char type;
+    unsigned char imageLen[6];
+    unsigned char imageMD5[16];
+    unsigned char blockLen[4];
+} jigdo_image_entry_t;
+
+entry_t *entry_list = NULL;
+entry_t *last_entry = NULL;
+FILE    *t_file = NULL;
+FILE    *j_file = NULL;
+int      num_matches = 0;
+int      num_chunks = 0;
+
+/* Convert a glob-style pattern to a regexp */
+static void convert_pattern(char *converted, char *prefix, char *in, char *suffix)
+{
+    char *p = in;
+    char *out = converted;
+
+    out += sprintf(out, prefix);    
+    while (*p)
+    {
+        switch (*p)
+        {
+            case '*':
+                out += sprintf(out, ".*");
+                break;
+            case '?':
+                out += sprintf(out, ".");
+                break;
+            case '.':
+            case '\\':
+            case '^':
+            case '$':
+                out += sprintf(out, "\\");
+                out += sprintf(out, "%c", *p);
+                break;
+            default:
+                out += sprintf(out, "%c", *p);
+                break;
+        }
+        p++;
+    }
+    out += sprintf(out, suffix);
+}
+
+/* Build the list of exclusion regexps */
+extern int jte_add_exclude(char *pattern)
+{
+    int size = 3 + (2 * strlen(pattern)); /* Worst case */
+    char *conversion = NULL;
+    struct exclude_regex *new = NULL;
+    
+    conversion = malloc(size);
+    if (!conversion)
+        return ENOMEM;
+
+    new = malloc(sizeof *new);
+    if (!new)
+        return ENOMEM;    
+    
+    memset(conversion, 0, size);
+    convert_pattern(conversion, "^", pattern, "/");
+    regcomp(&new->match_pattern[0], conversion, REG_NEWLINE);
+
+    memset(conversion, 0, size);
+    convert_pattern(conversion, "^", pattern, "$");
+    regcomp(&new->match_pattern[1], conversion, REG_NEWLINE);
+
+    memset(conversion, 0, size);
+    convert_pattern(conversion, "/", pattern, "/");
+    regcomp(&new->match_pattern[2], conversion, REG_NEWLINE);
+
+    memset(conversion, 0, size);
+    convert_pattern(conversion, "/", pattern, "$");
+    regcomp(&new->match_pattern[3], conversion, REG_NEWLINE);
+
+    new->exclude_rule = pattern;
+    free(conversion);
+
+    /* Order on the exclude list doesn't matter! */
+    if (NULL != exclude_list)
+        new->next = exclude_list;
+
+    exclude_list = new;
+    return 0;
+}
+
+/* Check if the file should be excluded because of a filename match. 1
+   means exclude, 0 means not */
+static int check_exclude_by_name(char *filename, char **matched)
+{
+    struct exclude_regex *ptr = exclude_list;
+    regmatch_t pmatch[1];
+    int i = 0;
+
+    while (ptr)
+    {
+        for (i = 0; i < 4; i++)
+        {
+            if (!regexec(&ptr->match_pattern[i], filename, 1, pmatch, 0))
+            {
+                *matched = ptr->exclude_rule;
+                return 1;
+            }
+        }
+        ptr = ptr->next;
+    }
+    
+    /* Not matched, so return 0 */
+    return 0;
+}
+
+/* Should we list a file separately in the jigdo output, or should we
+   just dump it into the template file as binary data? Two common
+   cases to look for here:
+
+   1. Small files are better simply folded in, as they take less space that way.
+
+   2. Files in /doc (for example) may change in the archive all the
+      time and it's better to not have to fetch snapshot copies if we
+      can avoid it.      
+*/
+extern int list_file_in_jigdo(char *filename, off_t size)
+{
+    char *matched_rule;
+    
+    /* Cheaper to check file size first */
+    if (size < jte_min_size)
+    {
+        if (verbose > 0)
+            fprintf(stderr, "Jigdo-ignoring file %s; it's too small\n", filename);
+        return 0;
+    }
+    
+    /* Now check the excluded list by name */
+    if (check_exclude_by_name(filename, &matched_rule))
+    {
+        if (verbose > 0)
+            fprintf(stderr, "Jigdo-ignoring file %s; it's covered in the exclude list by \"%s\"\n", filename, matched_rule);
+        return 0;
+    }
+    
+    /* else */
+    return 1;
+}
+
+/* Add a mapping of pathnames (e.g. Debian=/mirror/debian). We should
+   be passed TO=FROM here */
+extern int jte_add_mapping(char *arg)
+{
+    int error = 0;
+    struct path_mapping *new = NULL;
+    struct path_mapping *entry = NULL;
+    char *p = arg;
+    char *from = NULL;
+    char *to = NULL;
+
+    /* Find the "=" in the string passed. Set it to NULL and we can
+       use the string in-place */
+    while (*p)
+    {
+        if ('=' == *p)
+        {
+            *p = 0;
+            p++;
+            to = arg;
+            from = p;
+        }
+        p++;
+    }
+    if (!from || !strlen(from) || !to || !strlen(to))
+        return EINVAL;
+    
+    new = malloc(sizeof(*new));
+    if (!new)
+        return ENOMEM;
+    
+    new->from = from;
+    new->to = to;
+    new->next = NULL;
+
+    if (verbose > 0)
+        fprintf(stderr, "Adding mapping from %s to %s for the jigdo file\n", from, to);
+    if (!map_list)
+        map_list = new;
+    else
+    {
+        /* Order is important; add to the end of the list */
+        entry = map_list;
+        while (NULL != entry->next)
+            entry = entry->next;
+        entry->next = new;
+    }
+    return 0;
+}
+
+/* Check if the filename should be remapped; if so, map it otherwise
+   return the original name. */
+static char *remap_filename(char *filename)
+{
+    char *new_name = filename;
+    struct path_mapping *entry = map_list;
+    
+    while (entry)
+    {
+        if (!strncmp(filename, entry->from, strlen(entry->from)))
+        {
+            new_name = calloc(1, 2 + strlen(filename) + strlen(entry->to) - strlen(entry->from));
+            if (!new_name)
+            {
+                fprintf(stderr, "Failed to malloc new filename; abort!\n");
+                exit(1);
+            }
+            sprintf(new_name, "%s:%s", entry->to, &filename[strlen(entry->from)]);
+            return new_name;
+        }
+        entry = entry->next;
+    }
+
+    /* No mapping in effect */
+    return strdup(filename);
+}    
+
+static size_t template_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    mk_MD5Update(&template_context, ptr, size * nmemb);
+    template_size += (unsigned long long)size * nmemb;
+    return fwrite(ptr, size, nmemb, stream);
+}
+
+static void write_template_header()
+{
+    char buf[2048];
+    int i = 0;
+    char *p = buf;
+
+    memset(buf, 0, sizeof(buf));
+
+    mk_MD5Init(&template_context);
+    i += sprintf(p, "JigsawDownload template %s %s/%d.%d \r\n",
+                 JIGDO_TEMPLATE_VERSION, JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR);
+    p = &buf[i];
+
+    i += sprintf(p, "%s \r\n", JTE_COMMENT);
+    p = &buf[i];
+
+    i += sprintf(p, "\r\n");
+    template_fwrite(buf, i, 1, t_file);
+}
+
+/* Initialise state and start the jigdo template file */
+void write_jt_header(FILE *template_file, FILE *jigdo_file)
+{
+    t_file = template_file;
+    j_file = jigdo_file;
+
+    /* Start MD5 work for the image */
+    mk_MD5Init(&iso_context);
+
+    /* Start the template file */
+    write_template_header();
+}
+
+static void flush_compressed_chunk(void *buffer, off_t size)
+{
+    z_stream c_stream; /* compression stream */
+    unsigned char comp_size_out[6];
+    unsigned char uncomp_size_out[6];
+    off_t compressed_size_out = 0;
+    int err = 0;
+    unsigned char *comp_buf = NULL;
+
+    c_stream.zalloc = NULL;
+    c_stream.zfree = NULL;
+    c_stream.opaque = NULL;
+
+    err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+    comp_buf = malloc(2 * size); /* Worst case */
+    c_stream.next_out = comp_buf;
+    c_stream.avail_out = 2 * size;
+    c_stream.next_in = buffer;
+    c_stream.avail_in = size;
+    
+    err = deflate(&c_stream, Z_NO_FLUSH);
+    err = deflate(&c_stream, Z_FINISH);
+    
+    compressed_size_out = c_stream.total_out + 16;
+    err = deflateEnd(&c_stream);
+
+    template_fwrite("DATA", 4, 1, t_file);
+
+    write_le48(compressed_size_out, &comp_size_out[0]);
+    template_fwrite(comp_size_out, sizeof(comp_size_out), 1, t_file);
+
+    write_le48(size, &uncomp_size_out[0]);
+    template_fwrite(uncomp_size_out, sizeof(uncomp_size_out), 1, t_file);
+    
+    template_fwrite(comp_buf, c_stream.total_out, 1, t_file);
+    free(comp_buf);
+}
+
+static void write_compressed_chunk(unsigned char *buffer, size_t size)
+{
+    static unsigned char uncomp_buf[1024 * 1024];
+    static size_t uncomp_buf_used = 0;
+
+    if ((uncomp_buf_used + size) > sizeof(uncomp_buf))
+    {
+        flush_compressed_chunk(uncomp_buf, uncomp_buf_used);
+        uncomp_buf_used = 0;
+    }
+
+    if (!size) /* Signal a flush before we start writing the DESC entry */
+    {
+        flush_compressed_chunk(uncomp_buf, uncomp_buf_used);
+        return;
+    }
+    
+    if (!uncomp_buf_used)
+        memset(uncomp_buf, 0, sizeof(uncomp_buf));
+
+    while (size > sizeof(uncomp_buf))
+    {
+        flush_compressed_chunk(buffer, sizeof(uncomp_buf));
+        buffer += sizeof(uncomp_buf);
+        size -= sizeof(uncomp_buf);
+    }
+    memcpy(&uncomp_buf[uncomp_buf_used], buffer, size);
+    uncomp_buf_used += size;
+}
+
+static void write_template_desc_entries(off_t image_len, char *image_md5)
+{
+    entry_t *entry = entry_list;
+    off_t desc_len = 0;
+    unsigned char out_len[6];
+    jigdo_image_entry_t jimage;
+
+    desc_len = 16 /* DESC + length twice */
+        + (sizeof(jigdo_file_entry_t) * num_matches)
+        + (sizeof(jigdo_chunk_entry_t) * num_chunks)
+        + sizeof(jigdo_image_entry_t);
+
+    write_le48(desc_len, &out_len[0]);
+    write_compressed_chunk(NULL, 0);
+    template_fwrite("DESC", 4, 1, t_file);
+    template_fwrite(out_len, sizeof(out_len), 1, t_file);
+    
+    while (entry)
+    {
+        switch (entry->entry_type)
+        {
+            case JTET_FILE_MATCH:
+            {
+                jigdo_file_entry_t jfile;
+                jfile.type = 6; /* Matched file */
+                write_le48(entry->data.file.file_length, &jfile.fileLen[0]);
+                memset(jfile.fileRsync, 0, sizeof(jfile.fileRsync)); /* Write a blank rsyncsum; we don't use it */
+                memcpy(jfile.fileMD5, entry->data.file.md5, sizeof(jfile.fileMD5));
+                template_fwrite(&jfile, sizeof(jfile), 1, t_file);
+                break;
+            }
+            case JTET_NOMATCH:
+            {
+                jigdo_chunk_entry_t jchunk;
+                jchunk.type = 2; /* Raw data */
+                write_le48(entry->data.chunk.uncompressed_length, &jchunk.skipLen[0]);
+                template_fwrite(&jchunk, sizeof(jchunk), 1, t_file);
+                break;
+            }
+        }
+        entry = entry->next;
+    }
+
+    jimage.type = 5;
+    write_le48(image_len, &jimage.imageLen[0]);
+    memcpy(jimage.imageMD5, image_md5, sizeof(jimage.imageMD5));
+    memset(jimage.blockLen, 0, sizeof(jimage.blockLen)); /* Might work... */
+    template_fwrite(&jimage, sizeof(jimage), 1, t_file);    
+    template_fwrite(out_len, sizeof(out_len), 1, t_file);
+}
+
+static char *base64_dump(unsigned char *buf, size_t buf_size)
+{
+    const char *b64_enc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
+    int value = 0;
+    unsigned int i;
+    int bits = 0;
+    static char output_buffer[2048];
+    char *p = output_buffer;
+
+    memset(output_buffer, 0, sizeof(output_buffer));
+    if (buf_size >= (sizeof(output_buffer) * 6/8))
+    {
+        fprintf(stderr, "base64_dump: Buffer too small!\n");
+        exit(1);
+    }
+
+    for (i = 0; i < buf_size ; i++)
+    {
+        value = (value << 8) | buf[i];
+        bits += 2;
+        p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]);
+        if (bits >= 8) {
+            bits -= 6;
+            p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]);
+        }
+    }
+    if (bits > 0)
+    {
+        value <<= 8 - bits;
+        p += sprintf(p, "%c", b64_enc[(value >> bits) & 63U]);
+    }
+    return output_buffer;
+}
+
+static char *hex_dump(unsigned char *buf, size_t buf_size)
+{
+    unsigned int i;
+    static char output_buffer[2048];
+    char *p = output_buffer;
+
+    memset(output_buffer, 0, sizeof(output_buffer));
+    if (buf_size >= (sizeof(output_buffer) / 2))
+    {
+        fprintf(stderr, "hex_dump: Buffer too small!\n");
+        exit(1);
+    }
+
+    for (i = 0; i < buf_size ; i++)
+        p += sprintf(p, "%2.2x", buf[i]);
+
+    return output_buffer;
+}
+
+static char *file_base_name(char *path)
+{
+    char *endptr = path;
+    char *ptr = path;
+    
+    while (*ptr != '\0')
+    {
+        if ('/' == *ptr)
+            endptr = ++ptr;
+        else
+            ++ptr;
+    }
+    return endptr;
+}
+
+/* Write the .jigdo file to match the .template we've just finished. */
+static void write_jigdo_file(void)
+{
+    unsigned char template_md5sum[16];
+    entry_t *entry = entry_list;
+    struct path_mapping *map = map_list;
+
+    mk_MD5Final(&template_md5sum[0], &template_context);
+
+    fprintf(j_file, "# JigsawDownload\n");
+    fprintf(j_file, "# See <http://atterer.net/jigdo/> for details about jigdo\n");
+    fprintf(j_file, "# See <http://www.einval.com/~steve/software/CD/JTE/> for details about JTE\n\n");
+    
+    fprintf(j_file, "[Jigdo]\n");
+    fprintf(j_file, "Version=%s\n", JIGDO_TEMPLATE_VERSION);
+    fprintf(j_file, "Generator=%s/%d.%d\n\n", JTE_NAME, JTE_VER_MAJOR, JTE_VER_MINOR);
+
+    fprintf(j_file, "[Image]\n");
+    fprintf(j_file, "Filename=%s\n", file_base_name(outfile));
+    fprintf(j_file, "Template=http://localhost/%s\n", jtemplate_out);
+    fprintf(j_file, "Template-MD5Sum=%s \n",
+            base64_dump(&template_md5sum[0], sizeof(template_md5sum)));
+    fprintf(j_file, "# Template Hex MD5sum %s\n",
+            hex_dump(&template_md5sum[0], sizeof(template_md5sum)));
+    fprintf(j_file, "# Template size %lld bytes\n", template_size);
+    fprintf(j_file, "# Image size %lld bytes\n\n", image_size);
+
+    fprintf(j_file, "[Parts]\n");
+    while (entry)
+    {
+        if (JTET_FILE_MATCH == entry->entry_type)
+        {
+            char *new_name = remap_filename(entry->data.file.filename);
+            fprintf(j_file, "%s=%s\n",
+                    base64_dump(&entry->data.file.md5[0], sizeof(entry->data.file.md5)),
+                    new_name);
+            free(new_name);
+        }
+        entry = entry->next;
+    }
+
+    fprintf(j_file, "\n[Servers]\n");
+    while (map)
+    {
+        fprintf(j_file, "%s=%s\n", map->to, map->from);
+        map = map->next;
+    }
+
+    fflush(j_file);
+}
+
+/* Finish and flush state; for now:
+   
+   1. Dump the DESC blocks and the footer information in the jigdo template file
+   2. Write the jigdo .jigdo file containing file pointers
+*/
+void write_jt_footer(void)
+{
+    unsigned char md5[16]; /* MD5SUM of the entire image */
+
+    /* Finish calculating the image's checksum */
+    mk_MD5Final(&md5[0], &iso_context);
+
+    /* And caclulate the image size */
+    image_size = (unsigned long long)SECTOR_SIZE * last_extent_written;
+
+    write_template_desc_entries(image_size, md5);
+
+    write_jigdo_file();
+}
+
+static void add_unmatched_entry(int uncompressed_length)
+{
+    entry_t *new_entry = NULL;
+
+    /* Can we extend a previous non-match entry? */
+    if (last_entry && (JTET_NOMATCH == last_entry->entry_type))
+    {
+        last_entry->data.chunk.uncompressed_length += uncompressed_length;
+        return;
+    }
+
+    new_entry = calloc(1, sizeof(entry_t));
+    new_entry->entry_type = JTET_NOMATCH;
+    new_entry->next = NULL;
+    new_entry->data.chunk.uncompressed_length = uncompressed_length;
+
+    /* Add to the end of the list */
+    if (NULL == last_entry)
+    {
+        last_entry = new_entry;
+        entry_list = new_entry;
+    }
+    else
+    {
+        last_entry->next = new_entry;
+        last_entry = new_entry;
+    }
+    num_chunks++;
+}
+
+static void add_file_entry(char *filename, off_t size, unsigned char *md5)
+{
+    entry_t *new_entry = NULL;
+
+    new_entry = calloc(1, sizeof(entry_t));
+    new_entry->entry_type = JTET_FILE_MATCH;
+    new_entry->next = NULL;
+    memcpy(new_entry->data.file.md5, md5, sizeof(new_entry->data.file.md5));
+    new_entry->data.file.file_length = size;
+    new_entry->data.file.filename = strdup(filename);
+
+    /* Add to the end of the list */
+    if (NULL == last_entry)
+    {
+        last_entry = new_entry;
+        entry_list = new_entry;
+    }
+    else
+    {
+        last_entry->next = new_entry;
+        last_entry = new_entry;
+    }
+    num_matches++;
+}    
+
+/* Cope with an unmatched block in the .iso file:
+
+   1. Write a compressed data chunk in the jigdo template file
+   2. Add an entry in our list of unmatched chunks for later */
+void jtwrite(buffer, size, count, submode, islast)
+	void	*buffer;
+	int	size;
+	int	count;
+	int	submode;
+	BOOL	islast;
+{
+#ifdef	JTWRITE_DEBUG
+	if (count != 1 || (size % 2048) != 0)
+		error("Count: %d, size: %d\n", count, size);
+#endif
+
+    /* Update the global image checksum */
+    mk_MD5Update(&iso_context, buffer, size);
+
+    /* Write a compressed version of the data to the template file,
+       and add a reference on the state list so we can write that
+       later. */
+    write_compressed_chunk(buffer, size);
+    add_unmatched_entry(size);
+}
+
+/* Cope with an file entry in the .iso file:
+
+   1. Read the file for the image's md5 checksum
+   2. Add an entry in our list of files to be written into the .jigdo later
+*/
+void write_jt_match_record(char *filename, int sector_size, off_t size)
+{
+    unsigned long long tmp_size = 0;
+    struct mk_MD5Context file_context;
+    unsigned char md5[16];
+    char buf[32768];
+    off_t remain = size;
+	FILE		*infile = NULL;
+	int	use;
+
+    memset(buf, 0, sizeof(buf));
+    mk_MD5Init(&file_context);
+
+    if ((infile = fopen(filename, "rb")) == NULL) {
+#ifdef	USE_LIBSCHILY
+		comerr("cannot open '%s'\n", filename);
+#else
+#ifndef	HAVE_STRERROR
+		fprintf(stderr, "cannot open '%s': (%d)\n",
+				filename, errno);
+#else
+		fprintf(stderr, "cannot open '%s': %s\n",
+				filename, strerror(errno));
+#endif
+		exit(1);
+#endif
+	}
+
+    while (remain > 0)
+    {
+        use = remain;
+        if (remain > sizeof(buf))
+            use = sizeof(buf);
+		if (fread(buf, 1, use, infile) == 0) {
+#ifdef	USE_LIBSCHILY
+			comerr("cannot read from '%s'\n", filename);
+#else
+			fprintf(stderr, "cannot read from '%s'\n", filename);
+			exit(1);
+#endif
+		}
+        mk_MD5Update(&iso_context, buf, use);
+        mk_MD5Update(&file_context, buf, use);
+        remain -= use;
+    }
+
+    fclose(infile);
+    
+    mk_MD5Final(&md5[0], &file_context);
+
+    /* Update the image checksum with any necessary padding data */
+    if (size % sector_size)
+    {
+        int pad_size = sector_size - (size % sector_size);
+        memset(buf, 0, pad_size);
+        mk_MD5Update(&iso_context, buf, pad_size);
+    }
+    
+    add_file_entry(filename, size, &md5[0]);
+    if (size % sector_size)
+    {
+        int pad_size = sector_size - (size % sector_size);
+        write_compressed_chunk(buf, pad_size);
+        add_unmatched_entry(pad_size);
+    }        
+}
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/jte.h cdrtools-2.0+a30.pre1/mkisofs.steve/jte.h
--- cdrtools-2.0+a30.pre1/mkisofs/jte.h	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/jte.h	2004-06-16 19:24:37.000000000 +0100
@@ -0,0 +1,14 @@
+extern char *jtemplate_out;
+extern char *jjigdo_out;
+extern FILE	*jthelper;
+extern FILE *jtjigdo;
+extern FILE *jttemplate;
+extern int  jte_min_size;
+
+extern void write_jt_header(FILE *template_file, FILE *jigdo_file);
+extern void write_jt_footer(void);
+extern void jtwrite(void *buffer, int size, int count, int submode, BOOL islast);
+extern void write_jt_match_record(char *filename, int sector_size, off_t size);
+extern int  list_file_in_jigdo(char *filename, off_t size);
+extern int  jte_add_exclude(char *pattern);
+extern int  jte_add_mapping(char *arg);
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/md5.c cdrtools-2.0+a30.pre1/mkisofs.steve/md5.c
--- cdrtools-2.0+a30.pre1/mkisofs/md5.c	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/md5.c	2004-06-16 19:24:37.000000000 +0100
@@ -0,0 +1,326 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
+   not require an integer type which is exactly 32 bits.  This work
+   draws on the changes for the same purpose by Tatu Ylonen
+   <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
+   that code, there is no copyright issue.  I hereby disclaim
+   copyright in any changes I have made; this code remains in the
+   public domain.  */
+
+/* Note regarding cvs_* namespace: this avoids potential conflicts
+   with libraries such as some versions of Kerberos.  No particular
+   need to worry about whether the system supplies an MD5 library, as
+   this file is only about 3k of object code.  */
+
+/* Steve McIntyre, 2004/05/31: borrowed this code from the CVS
+   library. s/cvs_/mk_/ across the source */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>	/* for memcpy() and memset() */
+
+#include "md5.h"
+
+/* Little-endian byte-swapping routines.  Note that these do not
+   depend on the size of datatypes such as mk_uint32, nor do they require
+   us to detect the endianness of the machine we are running on.  It
+   is possible they should be macros for speed, but I would be
+   surprised if they were a performance bottleneck for MD5.  */
+
+static mk_uint32
+getu32 (addr)
+     const unsigned char *addr;
+{
+	return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+		| addr[1]) << 8 | addr[0];
+}
+
+static void
+putu32 (data, addr)
+     mk_uint32 data;
+     unsigned char *addr;
+{
+	addr[0] = (unsigned char)data;
+	addr[1] = (unsigned char)(data >> 8);
+	addr[2] = (unsigned char)(data >> 16);
+	addr[3] = (unsigned char)(data >> 24);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+mk_MD5Init (ctx)
+     struct mk_MD5Context *ctx;
+{
+	ctx->buf[0] = 0x67452301;
+	ctx->buf[1] = 0xefcdab89;
+	ctx->buf[2] = 0x98badcfe;
+	ctx->buf[3] = 0x10325476;
+
+	ctx->bits[0] = 0;
+	ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+mk_MD5Update (ctx, buf, len)
+     struct mk_MD5Context *ctx;
+     unsigned char const *buf;
+     unsigned len;
+{
+	mk_uint32 t;
+
+	/* Update bitcount */
+
+	t = ctx->bits[0];
+	if ((ctx->bits[0] = (t + ((mk_uint32)len << 3)) & 0xffffffff) < t)
+		ctx->bits[1]++;	/* Carry from low to high */
+	ctx->bits[1] += len >> 29;
+
+	t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+
+	/* Handle any leading odd-sized chunks */
+
+	if ( t ) {
+		unsigned char *p = ctx->in + t;
+
+		t = 64-t;
+		if (len < t) {
+			memcpy(p, buf, len);
+			return;
+		}
+		memcpy(p, buf, t);
+		mk_MD5Transform (ctx->buf, ctx->in);
+		buf += t;
+		len -= t;
+	}
+
+	/* Process data in 64-byte chunks */
+
+	while (len >= 64) {
+		memcpy(ctx->in, buf, 64);
+		mk_MD5Transform (ctx->buf, ctx->in);
+		buf += 64;
+		len -= 64;
+	}
+
+	/* Handle any remaining bytes of data. */
+
+	memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+mk_MD5Final (digest, ctx)
+     unsigned char digest[16];
+     struct mk_MD5Context *ctx;
+{
+	unsigned count;
+	unsigned char *p;
+
+	/* Compute number of bytes mod 64 */
+	count = (ctx->bits[0] >> 3) & 0x3F;
+
+	/* Set the first char of padding to 0x80.  This is safe since there is
+	   always at least one byte free */
+	p = ctx->in + count;
+	*p++ = 0x80;
+
+	/* Bytes of padding needed to make 64 bytes */
+	count = 64 - 1 - count;
+
+	/* Pad out to 56 mod 64 */
+	if (count < 8) {
+		/* Two lots of padding:  Pad the first block to 64 bytes */
+		memset(p, 0, count);
+		mk_MD5Transform (ctx->buf, ctx->in);
+
+		/* Now fill the next block with 56 bytes */
+		memset(ctx->in, 0, 56);
+	} else {
+		/* Pad block to 56 bytes */
+		memset(p, 0, count-8);
+	}
+
+	/* Append length in bits and transform */
+	putu32(ctx->bits[0], ctx->in + 56);
+	putu32(ctx->bits[1], ctx->in + 60);
+
+	mk_MD5Transform (ctx->buf, ctx->in);
+	putu32(ctx->buf[0], digest);
+	putu32(ctx->buf[1], digest + 4);
+	putu32(ctx->buf[2], digest + 8);
+	putu32(ctx->buf[3], digest + 12);
+	memset(ctx, 0, sizeof(ctx));	/* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+	( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+mk_MD5Transform (buf, inraw)
+     mk_uint32 buf[4];
+     const unsigned char inraw[64];
+{
+	register mk_uint32 a, b, c, d;
+	mk_uint32 in[16];
+	int i;
+
+	for (i = 0; i < 16; ++i)
+		in[i] = getu32 (inraw + 4 * i);
+
+	a = buf[0];
+	b = buf[1];
+	c = buf[2];
+	d = buf[3];
+
+	MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
+	MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+	MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+	MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+	MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
+	MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+	MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+	MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+	MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
+	MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+	MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+	MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+	MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
+	MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+	MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+	MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+	MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
+	MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
+	MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+	MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+	MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
+	MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
+	MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+	MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+	MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
+	MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
+	MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+	MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+	MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
+	MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
+	MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+	MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+	MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
+	MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+	MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+	MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+	MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
+	MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+	MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+	MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+	MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
+	MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+	MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+	MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+	MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
+	MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+	MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+	MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+	MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
+	MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+	MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+	MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+	MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
+	MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+	MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+	MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+	MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
+	MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+	MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+	MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+	MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
+	MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+	MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+	MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+}
+#endif
+
+#ifdef TEST
+/* Simple test program.  Can use it to manually run the tests from
+   RFC1321 for example.  */
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+	struct mk_MD5Context context;
+	unsigned char checksum[16];
+	int i;
+	int j;
+
+	if (argc < 2)
+	{
+		fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
+		exit (1);
+	}
+	for (j = 1; j < argc; ++j)
+	{
+		printf ("MD5 (\"%s\") = ", argv[j]);
+		mk_MD5Init (&context);
+		mk_MD5Update (&context, argv[j], strlen (argv[j]));
+		mk_MD5Final (checksum, &context);
+		for (i = 0; i < 16; i++)
+		{
+			printf ("%02x", (unsigned int) checksum[i]);
+		}
+		printf ("\n");
+	}
+	return 0;
+}
+#endif /* TEST */
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/md5.h cdrtools-2.0+a30.pre1/mkisofs.steve/md5.h
--- cdrtools-2.0+a30.pre1/mkisofs/md5.h	1970-01-01 01:00:00.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/md5.h	2004-06-16 19:24:37.000000000 +0100
@@ -0,0 +1,26 @@
+/* See md5.c for explanation and copyright information.  */
+
+#ifndef MD5_H
+#define MD5_H
+
+/* Unlike previous versions of this code, uint32 need not be exactly
+   32 bits, merely 32 bits or more.  Choosing a data type which is 32
+   bits instead of 64 is not important; speed is considerably more
+   important.  ANSI guarantees that "unsigned long" will be big enough,
+   and always using it seems to have few disadvantages.  */
+typedef unsigned long mk_uint32;
+
+struct mk_MD5Context {
+	mk_uint32 buf[4];
+	mk_uint32 bits[2];
+	unsigned char in[64];
+};
+
+void mk_MD5Init (struct mk_MD5Context *context);
+void mk_MD5Update (struct mk_MD5Context *context,
+			   unsigned char const *buf, unsigned len);
+void mk_MD5Final (unsigned char digest[16],
+			  struct mk_MD5Context *context);
+void mk_MD5Transform (mk_uint32 buf[4], const unsigned char in[64]);
+
+#endif /* !MD5_H */
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c cdrtools-2.0+a30.pre1/mkisofs.steve/mkisofs.c
--- cdrtools-2.0+a30.pre1/mkisofs/mkisofs.c	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/mkisofs.c	2004-06-17 09:55:21.000000000 +0100
@@ -100,7 +100,11 @@
 int	load_addr = 0;
 int	load_size = 0;
 int	boot_info_table = 0;
+int use_alphaboot = 0;
 int	use_sparcboot = 0;
+int use_hppaboot = 0;
+int use_mipsboot = 0;
+int use_mipselboot = 0;
 int	use_sunx86boot = 0;
 int	use_genboot = 0;
 int	use_RockRidge = 0;
@@ -373,6 +377,26 @@
 #define	OPTION_SUNX86BOOT		1068
 #define	OPTION_SUNX86LABEL		1069
 
+#ifdef JIGDO_TEMPLATE
+#define OPTION_JTT_OUTPUT       1101
+#define OPTION_JTJ_OUTPUT       1102
+#define OPTION_JT_MIN_SIZE      1103
+#define OPTION_JT_EXCLUDE       1104
+#define OPTION_JT_PATH_MAP      1105
+#endif
+
+#define	OPTION_BOOTALPHA	    1200
+
+#define	OPTION_HPPA_CMDLINE 	1210
+#define OPTION_HPPA_KERNEL_32   1211
+#define OPTION_HPPA_KERNEL_64   1212
+#define OPTION_HPPA_BOOTLOADER  1213
+#define OPTION_HPPA_RAMDISK     1214
+
+#define	OPTION_BOOTMIPS     	1220
+
+#define	OPTION_BOOTMIPSEL   	1230
+
 #ifdef UDF
 #define	OPTION_UDF			1500
 #endif
@@ -584,6 +608,39 @@
 	{{"sectype", required_argument, NULL, 's'},
 	's', "TYPE", "Set output sector type to e.g. data/xa1/raw", ONE_DASH},
 
+	{{"alpha-boot", required_argument, NULL, OPTION_BOOTALPHA},
+	'\0', "FILE", "Set alpha boot image name (relative to image root)", ONE_DASH},
+
+	{{"hppa-cmdline", required_argument, NULL, OPTION_HPPA_CMDLINE},
+	'\0', "CMDLINE", "Set hppa boot command line (relative to image root)", ONE_DASH},
+	{{"hppa-kernel-32", required_argument, NULL, OPTION_HPPA_KERNEL_32},
+	'\0', "FILE", "Set hppa 32-bit image name (relative to image root)", ONE_DASH},
+	{{"hppa-kernel-64", required_argument, NULL, OPTION_HPPA_KERNEL_64},
+	'\0', "FILE", "Set hppa 64-bit image name (relative to image root)", ONE_DASH},
+	{{"hppa-bootloader", required_argument, NULL, OPTION_HPPA_BOOTLOADER},
+	'\0', "FILE", "Set hppa boot loader file name (relative to image root)", ONE_DASH},
+	{{"hppa-ramdisk", required_argument, NULL, OPTION_HPPA_RAMDISK},
+	'\0', "FILE", "Set hppa ramdisk file name (relative to image root)", ONE_DASH},
+
+	{{"mips-boot", required_argument, NULL, OPTION_BOOTMIPS},
+	'\0', "FILE", "Set mips boot image name (relative to image root)", ONE_DASH},
+
+	{{"mipsel-boot", required_argument, NULL, OPTION_BOOTMIPSEL},
+	'\0', "FILE", "Set mipsel boot image name (relative to image root)", ONE_DASH},
+
+#ifdef JIGDO_TEMPLATE
+    {{"jigdo-jigdo", required_argument, NULL, OPTION_JTJ_OUTPUT},
+     '\0', "FILE", "Produce a jigdo .jigdo file as well as the .iso", ONE_DASH },
+    {{"jigdo-template", required_argument, NULL, OPTION_JTT_OUTPUT},
+     '\0', "FILE", "Produce a jigdo .template file as well as the .iso", ONE_DASH },
+    {{"jigdo-min-file-size", required_argument, NULL, OPTION_JT_MIN_SIZE},
+     '\0', "SIZE", "Minimum size for a file to be listed in the jigdo file", ONE_DASH },
+    {{"jigdo-exclude", required_argument, NULL, OPTION_JT_EXCLUDE},
+     '\0', "PATTERN", "Pattern(s) to exclude from the jigdo file", ONE_DASH },
+    {{"jigdo-map", required_argument, NULL, OPTION_JT_PATH_MAP},
+     '\0', "PATTERN1=PATTERN2", "Pattern(s) to map paths (e.g. Debian=/mirror/debian)", ONE_DASH },
+#endif
+
 #ifdef SORTING
 	{ {"sort", required_argument, NULL, OPTION_SORT},
 	'\0', "FILE", "Sort file content locations according to rules in FILE", ONE_DASH },
@@ -1348,6 +1405,41 @@
 		case OPTION_OUTPUT_CHARSET:
 			ocharset = optarg;
 			break;
+#ifdef JIGDO_TEMPLATE
+        case OPTION_JTT_OUTPUT:
+            jtemplate_out = optarg;
+            break;
+        case OPTION_JTJ_OUTPUT:
+            jjigdo_out = optarg;
+            break;
+        case OPTION_JT_MIN_SIZE:
+            jte_min_size = atoi(optarg);
+            break;
+        case OPTION_JT_EXCLUDE:
+            if (jte_add_exclude(optarg)) {
+#ifdef	USE_LIBSCHILY
+				comerrno(EX_BAD,
+                         "Failed to build jigdo-exclude list\n");
+#else
+				fprintf(stderr,
+                        "Failed to build jigdo-exclude list\n");
+				exit(1);
+#endif
+			}    
+            break;
+        case OPTION_JT_PATH_MAP:
+            if (jte_add_mapping(optarg)) {
+#ifdef	USE_LIBSCHILY
+				comerrno(EX_BAD,
+                         "Failed to build jigdo mapping list\n");
+#else
+				fprintf(stderr,
+                        "Failed to build jigdo mapping list\n");
+				exit(1);
+#endif
+			}    
+            break;
+#endif /* JIGDO_TEMPLATE */
 		case OPTION_NOBAK:
 			all_files = 0;
 			break;
@@ -1374,6 +1466,41 @@
 			 */
 			new_boot_entry();
 			break;
+		case OPTION_BOOTALPHA:
+			use_alphaboot++;
+			/* list of pathnames of boot images */
+			add_boot_alpha_filename(optarg);
+			break;
+		case OPTION_HPPA_CMDLINE:
+			use_hppaboot++;
+			add_boot_hppa_cmdline(optarg);
+			break;
+		case OPTION_HPPA_KERNEL_32:
+			use_hppaboot++;
+			add_boot_hppa_kernel_32(optarg);
+			break;
+		case OPTION_HPPA_KERNEL_64:
+			use_hppaboot++;
+			add_boot_hppa_kernel_64(optarg);
+			break;
+		case OPTION_HPPA_BOOTLOADER:
+			use_hppaboot++;
+			add_boot_hppa_bootloader(optarg);
+			break;
+		case OPTION_HPPA_RAMDISK:
+			use_hppaboot++;
+			/* list of pathnames of boot images */
+			add_boot_hppa_ramdisk(optarg);
+			break;
+		case OPTION_BOOTMIPS:
+			use_mipsboot++;
+			/* list of pathnames of boot images */
+			add_boot_mips_filename(optarg);
+			break;
+		case OPTION_BOOTMIPSEL:
+			use_mipselboot++;
+			add_boot_mipsel_filename(optarg);
+			break;
 		case 'B':
 			if (use_sunx86boot)
 				comerrno(EX_BAD,
@@ -3156,6 +3283,27 @@
 			exit(1);
 #endif
 		}
+        if (jtemplate_out || jjigdo_out) {
+            if (!jtemplate_out || !jjigdo_out) {
+#ifdef        USE_LIBSCHILY
+                comerr("Bad options - need to specify all jigdo output names!\n");
+#else
+                fprintf(stderr, "Bad options - need to specify all jigdo output names!\n");
+                exit(1);
+#endif
+            }
+            jtjigdo = fopen(jjigdo_out, "wb");
+            jttemplate = fopen(jtemplate_out, "wb");
+            if (!jtjigdo || !jttemplate) {
+#ifdef        USE_LIBSCHILY
+                comerr("Unable to open jigdo template image file\n");
+#else
+                fprintf(stderr, "Unable to open jigdo template image file\n");
+                exit(1);
+#endif
+            }
+            write_jt_header(jttemplate, jtjigdo);
+        }
 	} else {
 		discimage = stdout;
 
@@ -3188,6 +3336,14 @@
 #endif	/* APPLE_HYB */
 	if (use_sparcboot || use_sunx86boot)
 		outputlist_insert(&sunlabel_desc);
+    if (use_alphaboot)
+        outputlist_insert(&alphaboot_desc);
+    if (use_hppaboot)
+        outputlist_insert(&hppaboot_desc);
+    if (use_mipsboot)
+        outputlist_insert(&mipsboot_desc);
+    if (use_mipselboot)
+        outputlist_insert(&mipselboot_desc);
 	if (use_genboot)
 		outputlist_insert(&genboot_desc);
 	outputlist_insert(&startpad_desc);
@@ -3411,6 +3567,14 @@
 				last_extent, last_extent_written);
 	}
 
+    if (jttemplate)
+    {
+        write_jt_footer();
+        fclose(jttemplate);
+    }
+    if (jtjigdo)
+        fclose(jtjigdo);
+    
 	if (verbose > 0) {
 #ifdef HAVE_SBRK
 		fprintf(stderr, "Max brk space used %x\n",
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h cdrtools-2.0+a30.pre1/mkisofs.steve/mkisofs.h
--- cdrtools-2.0+a30.pre1/mkisofs/mkisofs.h	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/mkisofs.h	2004-06-17 09:55:47.000000000 +0100
@@ -34,6 +34,9 @@
 #include <utypes.h>
 #include <standard.h>
 #include <libport.h>
+#ifdef JIGDO_TEMPLATE
+#include "jte.h"
+#endif
 
 #ifdef	DVD_VIDEO
 #ifndef	UDF
@@ -189,6 +192,10 @@
 extern struct output_fragment strfile_desc;
 extern struct output_fragment strdir_desc;
 extern struct output_fragment strpath_desc;
+extern struct output_fragment alphaboot_desc;
+extern struct output_fragment hppaboot_desc;
+extern struct output_fragment mipsboot_desc;
+extern struct output_fragment mipselboot_desc;
 
 #ifdef APPLE_HYB
 extern struct output_fragment hfs_desc;
@@ -357,6 +364,7 @@
 extern int	split_SL_component;
 extern int	split_SL_field;
 extern char	*trans_tbl;
+char		*outfile;
 
 #define	JMAX		64	/* maximum Joliet file name length (spec) */
 #define	JLONGMAX	103	/* out of spec Joliet file name length */
@@ -454,6 +462,22 @@
 extern int make_sun_label __PR((void));
 extern int make_sunx86_label __PR((void));
 
+/* boot-alpha.c */
+extern int add_boot_alpha_filename __PR((char *filename));
+
+/* boot-hppa.c */
+extern int add_boot_hppa_cmdline    __PR((char *cmdline));
+extern int add_boot_hppa_kernel_32  __PR((char *filename));
+extern int add_boot_hppa_kernel_64  __PR((char *filename));
+extern int add_boot_hppa_bootloader __PR((char *filename));
+extern int add_boot_hppa_ramdisk    __PR((char *filename));
+
+/* boot-mips.c */
+extern int add_boot_mips_filename __PR((char *filename));
+
+/* boot-mipsel.c */
+extern int add_boot_mipsel_filename  __PR((char *filename));
+
 /* write.c */
 extern int get_731 __PR((char *));
 extern int get_732 __PR((char *));
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/stream.c cdrtools-2.0+a30.pre1/mkisofs.steve/stream.c
--- cdrtools-2.0+a30.pre1/mkisofs/stream.c	2004-03-04 22:56:57.000000000 +0000
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/stream.c	2004-06-16 19:24:37.000000000 +0100
@@ -157,6 +157,7 @@
 			break;
 		}
 		idx += count;
+		jtwrite(buf, count, 1, 0, FALSE);
 		xfwrite(buf, count, 1, outfile, 0, FALSE);
 	}
 
@@ -164,16 +165,24 @@
 	iso_blocks = ISO_BLOCKS(idx);
 	memset(buf, 0, SECTOR_SIZE);
 	if (SECTOR_SIZE * iso_blocks - idx)
+    {
+		jtwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE * iso_blocks - idx, 1, outfile, 0, FALSE);
+    }
 	/*
 	 * If we didn't fill the available area, pad to directory block
 	 */
 	for (count = 0; count < (avail_extent - iso_blocks); count++)
+    {
+		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
-
+    }
 	for (count = 0; count < stream_pad; count++)
+    {
+		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
-
+    }
+    
 	last_extent_written += avail_extent + stream_pad;
 	return (0);
 }
@@ -201,7 +210,9 @@
 	set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
 	s_dir.name_len[0] = 1;
 	s_dir.name[0] = 0;
+	jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
 	xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
+	jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, 0, FALSE);
 	xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0]) + 1, 1, outfile, 0, FALSE);
 	memset(&s_dir, 0, sizeof (struct iso_directory_record));
 	s_dir.length[0] = 34 + strlen(stream_filename);
@@ -214,6 +225,8 @@
 	set_723((char *)s_dir.volume_sequence_number, volume_sequence_number);
 	s_dir.name_len[0] = strlen(stream_filename);
 	memcpy(s_dir.name, stream_filename, s_dir.name_len[0]);
+	jtwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
+		+ s_dir.name_len[0], 1, 0, FALSE);
 	xfwrite(&s_dir, offsetof(struct iso_directory_record, name[0])
 		+ s_dir.name_len[0], 1, outfile, 0, FALSE);
 
@@ -222,6 +235,8 @@
 	 * with filename length stream_filename + round up for even lenght count
 	 */
 	to_write = (s_dir.name_len[0] % 2) ? 0 : 1;
+	jtwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
+		to_write, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE - ((3 * 34) + s_dir.name_len[0]) +
 		to_write, 1, outfile, 0, FALSE);
 	free(buf);
@@ -236,7 +251,9 @@
 write_str_path(outfile)
 	FILE	*outfile;
 {
+	jtwrite(l_path, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(l_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
+	jtwrite(m_path, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(m_path, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written += 2;
 	free(l_path);
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/udf.c cdrtools-2.0+a30.pre1/mkisofs.steve/udf.c
--- cdrtools-2.0+a30.pre1/mkisofs/udf.c	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/udf.c	2004-06-16 19:24:37.000000000 +0100
@@ -1045,6 +1045,7 @@
 		1,	/* is_directory */
 		directory_link_count(dpnt),
 		(dpnt == root) ? 0 : dpnt->self->udf_file_entry_sector);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 
@@ -1062,6 +1063,7 @@
 		1,
 		parent->self->udf_file_entry_sector - lba_udf_partition_start,
 		(parent == root) ? 0 : parent->self->udf_file_entry_sector);
+	jtwrite(buf, ident_size, 1, 0, FALSE);
 	xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
 	size_in_bytes = ident_size;
 
@@ -1107,6 +1109,7 @@
 			!!(de1->isorec.flags[0] & ISO_DIRECTORY),
 			de1->udf_file_entry_sector - lba_udf_partition_start,
 			de1->udf_file_entry_sector);
+		jtwrite(buf, ident_size, 1, 0, FALSE);
 		xfwrite(buf, ident_size, 1, outfile, 0, FALSE);
 		size_in_bytes += ident_size;
 	}
@@ -1114,6 +1117,7 @@
 	padded_size_in_bytes = PAD(size_in_bytes, SECTOR_SIZE);
 	if (size_in_bytes < padded_size_in_bytes) {
 		memset(buf, 0, padded_size_in_bytes - size_in_bytes);
+		jtwrite(buf, padded_size_in_bytes - size_in_bytes, 1, 0, FALSE);
 		xfwrite(buf, padded_size_in_bytes - size_in_bytes, 1, outfile, 0, FALSE);
 	}
 
@@ -1168,6 +1172,7 @@
 					0,	/* is_directory */
 					1,	/* link_count */
 					de->udf_file_entry_sector);
+				jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 				xfwrite(buf, SECTOR_SIZE, 1, outfile, 0, FALSE);
 			}
 		}
@@ -1199,6 +1204,7 @@
 	set8(&vsd->structure_version, 1);
 	for (i = 0; i < 3; ++i) {
 		memcpy(vsd->standard_identifier, identifiers[i], 5);
+		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 	}
 	last_extent_written += 3;
@@ -1225,30 +1231,37 @@
 
 	memset(buf, 0, sizeof (buf));
 	set_primary_vol_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	set_impl_use_vol_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	set_partition_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	set_logical_vol_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	set_unallocated_space_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	set_terminating_desc(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 
 	memset(buf, 0, sizeof (buf));
 	for (i = 6; i < UDF_MAIN_SEQ_LENGTH; ++i) {
+        jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 		last_extent_written++;
 	}
@@ -1272,6 +1285,7 @@
 						last_extent_written++);
 	set_terminating_desc(buf+1*SECTOR_SIZE, last_extent_written++);
 
+	jtwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, UDF_INTEG_SEQ_LENGTH, out, 0, FALSE);
 	return (0);
 }
@@ -1288,6 +1302,7 @@
 
 	memset(buf, 0, sizeof (buf));
 	set_anchor_volume_desc_pointer(buf, last_extent_written++);
+	jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 	return (0);
 }
@@ -1309,6 +1324,7 @@
 	set_terminating_desc(buf+1*SECTOR_SIZE,
 			(last_extent_written++) - lba_udf_partition_start);
 
+	jtwrite(buf, SECTOR_SIZE, 2, 0, FALSE);
 	xfwrite(buf, SECTOR_SIZE, 2, out, 0, FALSE);
 
 	return (0);
@@ -1350,6 +1366,7 @@
 	char buf[SECTOR_SIZE];
 	memset(buf, 0, sizeof (buf));
 	while (last_extent_written < last_extent_to_write) {
+		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 		++last_extent_written;
 	}
@@ -1395,6 +1412,7 @@
 	memset(buf, 0, sizeof (buf));
 	while (last_extent_written < last_extent_to_write) {
 		set_anchor_volume_desc_pointer(buf, last_extent_written++);
+		jtwrite(buf, SECTOR_SIZE, 1, 0, FALSE);
 		xfwrite(buf, SECTOR_SIZE, 1, out, 0, FALSE);
 	}
 	return (0);
diff -uNr cdrtools-2.0+a30.pre1/mkisofs/write.c cdrtools-2.0+a30.pre1/mkisofs.steve/write.c
--- cdrtools-2.0+a30.pre1/mkisofs/write.c	2004-06-16 17:48:45.000000000 +0100
+++ cdrtools-2.0+a30.pre1/mkisofs.steve/write.c	2004-06-16 19:31:42.000000000 +0100
@@ -289,6 +289,7 @@
 #endif
 		}
 	}
+
 	while (count) {
 		int	got;
 
@@ -459,7 +460,7 @@
 	FILE		*infile;
 	off_t		remain;
 	int	use;
-
+    int include_in_jigdo = list_file_in_jigdo(filename, size);
 
 	if ((infile = fopen(filename, "rb")) == NULL) {
 #ifdef	USE_LIBSCHILY
@@ -480,6 +481,9 @@
 #endif	/* APPLE_HYB */
 	remain = size;
 
+    if (include_in_jigdo)
+        write_jt_match_record(filename, SECTOR_SIZE, size);
+
 	while (remain > 0) {
 		use = (remain > SECTOR_SIZE * NSECT - 1 ?
 				NSECT * SECTOR_SIZE : remain);
@@ -494,6 +498,9 @@
 			exit(1);
 #endif
 		}
+        if (!include_in_jigdo)
+            jtwrite(buffer, use, 1,
+                    XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
 		xfwrite(buffer, use, 1, outfile,
 				XA_SUBH_DATA, remain <= (SECTOR_SIZE * NSECT));
 		last_extent_written += use / SECTOR_SIZE;
@@ -527,6 +534,7 @@
 		remain -= use;
 	}
 	fclose(infile);
+
 }/* write_one_file(... */
 
 static void
@@ -546,6 +554,7 @@
 				(Llong)dwpnt->size, dwpnt->extent);
 #endif
 		if (dwpnt->table) {
+			jtwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1, XA_SUBH_DATA, TRUE);
 			xfwrite(dwpnt->table, ISO_ROUND_UP(dwpnt->size), 1,
 							outfile,
 							XA_SUBH_DATA, TRUE);
@@ -590,9 +599,11 @@
 			Uint	i;
 
 			for (i = 0; i < dwpnt->pad; i++)
+            {
+				jtwrite(blk, SECTOR_SIZE, 1, 0, FALSE);
 				xfwrite(blk, SECTOR_SIZE, 1, outfile, 0, FALSE);
-
-			last_extent_written += dwpnt->pad;
+                last_extent_written++;
+            }
 		}
 #endif	/* APPLE_HYB || DVD_VIDEO */
 
@@ -804,10 +815,10 @@
 	if (dcount < 2) {
 #ifdef	USE_LIBSCHILY
 		errmsgno(EX_BAD,
-			"Directory size too small (. or .. missing ???)\n");
+			"Directory size too small (. or .. missing !)\n");
 #else
 		fprintf(stderr,
-			"Directory size too small (. or .. missing ???)\n");
+			"Directory size too small (. or .. missing !)\n");
 #endif
 		sort_goof = 1;
 
@@ -1508,6 +1519,7 @@
 			dir_index, dpnt->de_name);
 #endif
 	}
+	jtwrite(directory_buffer, total_size, 1, 0, FALSE);
 	xfwrite(directory_buffer, total_size, 1, outfile, 0, FALSE);
 	last_extent_written += total_size >> 11;
 	free(directory_buffer);
@@ -1525,6 +1537,7 @@
 				ce_index, dpnt->ce_bytes);
 #endif
 		}
+		jtwrite(ce_buffer, ce_size, 1, 0, FALSE);
 		xfwrite(ce_buffer, ce_size, 1, outfile, 0, FALSE);
 		last_extent_written += ce_size >> 11;
 		free(ce_buffer);
@@ -1759,9 +1772,11 @@
 		 * write out padding to round up to HFS allocation block
 		 */
 		for (i = 0; i < hfs_pad; i++)
+        {
+			jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
 			xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
-
-		last_extent_written += hfs_pad;
+            last_extent_written++;
+        }
 	}
 #endif	/* APPLE_HYB */
 
@@ -1798,11 +1813,15 @@
 	/* write out extents/catalog/dt file */
 	if (apple_hyb) {
 
+		jtwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, 0, FALSE);
 		xfwrite(hce->hfs_ce, HFS_BLOCKSZ, hce->hfs_tot_size, outfile, 0, FALSE);
 
 		/* round up to a whole CD block */
 		if (HFS_ROUND_UP(hce->hfs_tot_size) -
 					hce->hfs_tot_size * HFS_BLOCKSZ) {
+			jtwrite(buffer,
+				HFS_ROUND_UP(hce->hfs_tot_size) -
+				hce->hfs_tot_size * HFS_BLOCKSZ, 1, 0, FALSE);
 			xfwrite(buffer,
 				HFS_ROUND_UP(hce->hfs_tot_size) -
 				hce->hfs_tot_size * HFS_BLOCKSZ, 1, outfile, 0, FALSE);
@@ -1980,6 +1999,7 @@
 	}
 
 	/* if not a bootable cd do it the old way */
+	jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
@@ -1997,6 +2017,7 @@
 	vol_desc.file_structure_version[0] = 2;
 
 	/* if not a bootable cd do it the old way */
+	jtwrite(&vol_desc, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(&vol_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
@@ -2019,6 +2040,7 @@
 	evol_desc.type[0] = (unsigned char) ISO_VD_END;
 	memcpy(evol_desc.id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
 	evol_desc.version[0] = 1;
+	jtwrite(&evol_desc, SECTOR_SIZE, 1, 0, TRUE);
 	xfwrite(&evol_desc, SECTOR_SIZE, 1, outfile, 0, TRUE);
 	last_extent_written += 1;
 	return (0);
@@ -2074,10 +2096,16 @@
 	cp[SECTOR_SIZE - 1] = '\0';
  	/* Per default: keep privacy. Blackout the version and arguments. */
 	if(getenv("ISODEBUG"))
+    {
+        jtwrite(vers, SECTOR_SIZE, 1, 0, TRUE);
 		xfwrite(vers, SECTOR_SIZE, 1, outfile, 0, TRUE);
+    }
 	else
+    {
+		jtwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, 0, TRUE);
 		xfwrite(calloc(SECTOR_SIZE, 1), SECTOR_SIZE, 1, outfile, 0, TRUE);
-	last_extent_written += 1;
+    }
+	last_extent_written ++;
 	return (0);
 }
 
@@ -2151,9 +2179,12 @@
 	FILE	*outfile;
 {
 	/* Next we write the path tables */
+	jtwrite(path_table_l, path_blocks << 11, 1, 0, FALSE);
 	xfwrite(path_table_l, path_blocks << 11, 1, outfile, 0, FALSE);
+	last_extent_written += path_blocks;
+	jtwrite(path_table_m, path_blocks << 11, 1, 0, FALSE);
 	xfwrite(path_table_m, path_blocks << 11, 1, outfile, 0, FALSE);
-	last_extent_written += 2 * path_blocks;
+	last_extent_written += path_blocks;
 	free(path_table_l);
 	free(path_table_m);
 	path_table_l = NULL;
@@ -2165,6 +2196,7 @@
 exten_write(outfile)
 	FILE	*outfile;
 {
+	jtwrite(extension_record, SECTOR_SIZE, 1, 0, FALSE);
 	xfwrite(extension_record, SECTOR_SIZE, 1, outfile, 0, FALSE);
 	last_extent_written++;
 	return (0);
@@ -2348,10 +2380,11 @@
 	npad = session_start + 16 - last_extent_written;
 
 	for (i = 0; i < npad; i++) {
+		jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
 		xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+        last_extent_written++;
 	}
 
-	last_extent_written += npad;
 	return (0);
 }
 
@@ -2372,10 +2405,11 @@
 		npad += 16 - i;
 
 	for (i = 0; i < npad; i++) {
+		jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
 		xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+        last_extent_written++;
 	}
 
-	last_extent_written += npad;
 	return (0);
 }
 
@@ -2389,10 +2423,11 @@
 	memset(buffer, 0, sizeof (buffer));
 
 	for (i = 0; i < 150; i++) {
+		jtwrite(buffer, sizeof (buffer), 1, 0, FALSE);
 		xfwrite(buffer, sizeof (buffer), 1, outfile, 0, FALSE);
+        last_extent_written++;
 	}
 
-	last_extent_written += 150;
 	return (0);
 }
 
@@ -2748,10 +2783,12 @@
 	r = tot_size % HFS_BLK_CONV;
 
 	/* write out HFS volume header info */
+	jtwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, 0, FALSE);
 	xfwrite(hce->hfs_map, HFS_BLOCKSZ, tot_size, outfile, 0, FALSE);
 
 	/* fill up to a complete CD block */
 	if (r) {
+		jtwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, 0, FALSE);
 		xfwrite(buffer, HFS_BLOCKSZ, HFS_BLK_CONV - r, outfile, 0, FALSE);
 		n++;
 	}
