diff -urN cdrtools-2.01.01a58.orig/cdrecord/cd_misc.c cdrtools-2.01.01a58/cdrecord/cd_misc.c
--- cdrtools-2.01.01a58.orig/cdrecord/cd_misc.c	2008-12-22 06:56:46.000000000 -0800
+++ cdrtools-2.01.01a58/cdrecord/cd_misc.c	2009-04-15 22:43:22.907469183 -0700
@@ -62,7 +62,8 @@
 
 	ret *= 75;
 	ret += f;
-	if (m < 90 || force_positive)
+	/* jfeise@feise.com: fixed the calculation */
+	if (m < 90 || (force_positive && (ret<450150)))
 		ret -= 150;
 	else
 		ret -= 450150;
diff -urN cdrtools-2.01.01a58.orig/mkisofs/Makefile cdrtools-2.01.01a58/mkisofs/Makefile
--- cdrtools-2.01.01a58.orig/mkisofs/Makefile	2008-10-26 14:38:18.000000000 -0700
+++ cdrtools-2.01.01a58/mkisofs/Makefile	2009-04-15 22:45:14.455968669 -0700
@@ -49,7 +49,7 @@
 		scsi.c \
 		apple.c volume.c desktop.c mac_label.c stream.c \
 		ifo_read.c dvd_file.c dvd_reader.c \
-		walk.c
+		walk.c nameconflict.c
 HFILES=		apple.h bootinfo.h defaults.h diskmbr.h exclude.h \
 		iso9660.h mac_label.h mactypes.h match.h \
 		mkisofs.h sunlabel.h udf.h udf_fs.h vms.h \
diff -urN cdrtools-2.01.01a58.orig/mkisofs/nameconflict.c cdrtools-2.01.01a58/mkisofs/nameconflict.c
--- cdrtools-2.01.01a58.orig/mkisofs/nameconflict.c	1969-12-31 16:00:00.000000000 -0800
+++ cdrtools-2.01.01a58/mkisofs/nameconflict.c	2009-04-15 22:43:22.937467211 -0700
@@ -0,0 +1,140 @@
+/*
+ * File nameconflict.c - resolve name conflicts for iso9660 names
+ *
+ * Implements a simple linear list of basenames and the last substitute
+ * name used for each basename.
+ * This speeds up finding substitute names in cases with lots of
+ * conflicts.
+ * Example:
+ * Qmail Maildir directories can contain 1000s of files which map to
+ * the same 8.3 iso9660 name, like the following:
+ * 1041126815.10257_18134.pv182069,S=224616:2,S
+ * 1041126815.10257_18135.pv182069,S=1546:2,S
+ * 1041126815.10257_18136.pv182069,S=6036:2,S
+ * 1041126815.10257_18137.pv182069,S=1635:2,S
+ * 1041126815.10257_18139.pv182069,S=2090:2,S
+ * 1041126815.10257_18140.pv182069,S=2966:2,S
+ * 1041126815.10257_18141.pv182069,S=1867:2,FRS
+ * These files all map to 10411268.pv1
+ *
+ * Copyright (C) 2004 J. Joe Feise <jfeise at feise dot com>
+ *
+ * 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 <schily/mconfig.h>
+#include "mkisofs.h"
+
+typedef struct file_node_struct
+{
+	struct file_node_struct *next;
+	char basename[MAX_ISONAME+1];
+	char substitution[MAX_ISONAME+1];
+	int d1;
+	int d2;
+	int d3;
+} file_node;
+
+static file_node *file_list = (file_node*)NULL;
+
+
+LOCAL char *
+add_good_file(entry, basename)
+	file_node *entry;
+	char *basename;
+{
+	char substitution[MAX_ISONAME+1];
+
+	if (!entry)
+		return (NULL);	/* trouble */
+	entry->next = NULL;
+	strncpy(entry->basename, basename, MAX_ISONAME-3);
+	entry->basename[MAX_ISONAME-3] = '\0';	/* guard against overflow */
+
+	entry->d1 = entry->d2 = entry->d3 = 0;
+	sprintf(substitution, "%s%c%c%c", basename,
+		(entry->d1 <= 9 ? '0' + entry->d1 : 'A' + entry->d1 - 10),
+		(entry->d2 <= 9 ? '0' + entry->d2 : 'A' + entry->d2 - 10),
+		(entry->d3 <= 9 ? '0' + entry->d3 : 'A' + entry->d3 - 10));
+	strncpy(entry->substitution, substitution, MAX_ISONAME+1);
+	return (entry->substitution);
+}
+
+
+LOCAL char *
+inc_substitution(entry)
+	file_node *entry;
+{
+	char substitution[MAX_ISONAME+1];
+
+	entry->d3++;
+	if (entry->d3 == 36) {
+		entry->d3 = 0;
+		entry->d2++;
+		if (entry->d2 == 36) {
+			entry->d2 = 0;
+			entry->d1++;
+			if (entry->d1 == 36)
+				return (NULL);	/* trouble */
+		}
+	}
+	sprintf(substitution, "%s%c%c%c", entry->basename,
+		(entry->d1 <= 9 ? '0' + entry->d1 : 'A' + entry->d1 - 10),
+		(entry->d2 <= 9 ? '0' + entry->d2 : 'A' + entry->d2 - 10),
+		(entry->d3 <= 9 ? '0' + entry->d3 : 'A' + entry->d3 - 10));
+	strncpy(entry->substitution, substitution, MAX_ISONAME+1);
+	return (entry->substitution);
+}
+
+
+EXPORT char *
+find_good_file(basename)
+	char *basename;
+{
+	file_node *entry = file_list;
+	file_node *next;
+
+	if (!file_list) {
+		file_list = e_malloc(sizeof (file_node));
+		return (add_good_file(file_list, basename));
+	} else {
+		next = entry;
+		do {
+			entry = next;
+			if (strncmp(entry->basename, basename, MAX_ISONAME) == 0) {
+				return (inc_substitution(entry));
+			}
+			next = entry->next;
+		} while (next);
+		entry->next = e_malloc(sizeof (file_node));
+		entry = entry->next;
+		return (add_good_file(entry, basename));
+	}
+}
+
+
+EXPORT void
+flush_file_list()
+{
+	file_node *entry = file_list;
+	file_node *next;
+
+	while (entry) {
+		next = entry->next;
+		free(entry);
+		entry = next;
+	}
+	file_list = (file_node*)NULL;
+}
diff -urN cdrtools-2.01.01a58.orig/mkisofs/tree.c cdrtools-2.01.01a58/mkisofs/tree.c
--- cdrtools-2.01.01a58.orig/mkisofs/tree.c	2008-12-22 07:54:37.000000000 -0800
+++ cdrtools-2.01.01a58/mkisofs/tree.c	2009-04-15 22:43:22.985463272 -0700
@@ -269,6 +269,7 @@
 	char		newname[MAX_ISONAME+1];
 	char		rootname[MAX_ISONAME+1];
 	char		extname[MAX_ISONAME+1];
+	char		*newentry;
 
 	/*
 	 * Here we can take the opportunity to toss duplicate entries from the
@@ -292,6 +293,7 @@
 		attach_dot_entries(this_dir, NULL, NULL);
 	}
 	flush_file_hash();
+	flush_file_list();
 	s_entry = this_dir->contents;
 	while (s_entry) {
 #ifdef	USE_LARGEFILES
@@ -384,42 +386,49 @@
 			if (d1 > 5)
 				rootname[5] = 0;
 		}
-		new_reclen = strlen(rootname);
-		sprintf(newname, "%s000%s%s",
-				rootname,
+
+		/*
+		 * Filename substitution always starts at 000.
+		 * It can happen that an intended substitution already exists.
+		 * For example, assume there is a file named ABCDE002.EXT.
+		 * If ABCDEFGHIJK.EXT would map to ABCDE002.EXT, we have
+		 * to find another substitution, e.g., to ABCDE003.EXT.
+		 * Example mappings:
+		 * ABCDE002.EXT		-> ABCDE002.EXT
+		 * ABCDEFGH.EXT		-> ABCDEFGH.EXT
+		 * ABCDEFGHI.EXT	-> ABCDE000.EXT
+		 * ABCDEFGHIJ.EXT	-> ABCDE001.EXT
+		 * ABCDEFGHIJK.EXT	-> ABCDE003.EXT
+		 */
+
+		newentry = find_good_file(rootname);
+		while (newentry) {
+			sprintf(newname, "%s%s%s",
+				newentry,
 				extname,
 				((s_entry->isorec.flags[0] & ISO_DIRECTORY) ||
 				omit_version_number ? "" : ";1"));
-
-		for (d1 = 0; d1 < 36; d1++) {
-			for (d2 = 0; d2 < 36; d2++) {
-				for (d3 = 0; d3 < 36; d3++) {
-					newname[new_reclen + 0] =
-					    (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10);
-					newname[new_reclen + 1] =
-					    (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10);
-					newname[new_reclen + 2] =
-					    (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10);
-					if (debug)
-						error("NEW name '%s'\n", newname);
+			if (debug)
+				error("NEW name '%s'\n", newname);
 
 #ifdef VMS
-					/* Sigh.  VAXCRTL seems to be broken here */
-					{
-						int	ijk = 0;
-
-						while (newname[ijk]) {
-							if (newname[ijk] == ' ')
-								newname[ijk] = '0';
-							ijk++;
-						}
-					}
-#endif
-
-					if (!find_file_hash(newname))
-						goto got_valid_name;
+			/* Sigh.  VAXCRTL seems to be broken here */
+			{
+				int	ijk = 0;
+
+				while (newname[ijk]) {
+					if (newname[ijk] == ' ')
+						newname[ijk] = '0';
+					ijk++;
 				}
 			}
+#endif
+
+			if (!find_file_hash(newname))
+				goto got_valid_name;
+
+			/* the filename was already used for some other file */
+			newentry = find_good_file(rootname);
 		}
 
 		/*
