Patch for version 3.01, taken from upstream at
https://sourceforge.net/projects/cdrtools/files/cdrtools-3.01-fix-20151126-mkisofs-isoinfo.patch

--- cdrtools-3.01.orig/mkisofs/diag/isoinfo.c	2015-07-22 20:36:45.000000000 +0000
+++ cdrtools-3.01/mkisofs/diag/isoinfo.c	2015-11-17 19:35:40.000000000 +0000
@@ -1,8 +1,8 @@
-/* @(#)isoinfo.c	1.95 15/07/22 joerg */
+/* @(#)isoinfo.c	1.100 15/11/17 joerg */
 #include <schily/mconfig.h>
 #ifndef	lint
 static	UConst char sccsid[] =
-	"@(#)isoinfo.c	1.95 15/07/22 joerg";
+	"@(#)isoinfo.c	1.100 15/11/17 joerg";
 #endif
 /*
  * File isodump.c - dump iso9660 directory information.
@@ -148,8 +148,10 @@ LOCAL char	er_id[256];
 LOCAL int	su_version = 0;
 LOCAL int	rr_version = 0;
 LOCAL int	aa_version = 0;
+LOCAL int	cl_extent = 0;
 LOCAL int	ucs_level = 0;
 LOCAL BOOL	iso9660_inodes = FALSE;
+LOCAL uid_t	myuid;
 
 #ifdef	USE_FIND
 LOCAL findn_t	*find_node;		/* syntaxtree from find_parse()	*/
@@ -208,6 +210,9 @@ LOCAL	void	extract		__PR((char *rootname
 LOCAL	void	extract_file	__PR((int f,
 					struct iso_directory_record * idr,
 					char *fname));
+LOCAL	void	parse_cl_dir	__PR((struct iso_directory_record *idr,
+					int extent));
+LOCAL	BOOL	parse_de	__PR((struct iso_directory_record *idr));
 LOCAL	void	parse_dir	__PR((char * rootname, int extent, int len));
 LOCAL	void	usage		__PR((int excode));
 EXPORT	int	main		__PR((int argc, char *argv[]));
@@ -459,7 +464,6 @@ parse_rr(pnt, len, cont_flag)
 	int slen;
 	int xlen;
 	int ncount;
-	int cl_extent;
 	int pl_extent;
 	int cont_extent, cont_offset, cont_size;
 	int flag1, flag2;
@@ -469,7 +473,7 @@ parse_rr(pnt, len, cont_flag)
 
 	symlinkname[0] = 0;
 
-	cont_extent = cont_offset = cont_size = 0;
+	cl_extent = cont_extent = cont_offset = cont_size = 0;
 
 	ncount = 0;
 	flag1 = -1;
@@ -714,6 +718,7 @@ struct todo
 };
 
 LOCAL struct todo	*todo_idr = NULL;
+LOCAL struct todo	**todo_pp = &todo_idr;
 
 LOCAL char		*months[12] = {"Jan", "Feb", "Mar", "Apr",
 				"May", "Jun", "Jul",
@@ -962,8 +967,14 @@ static	BOOL		isfirst = TRUE;
 	close(f);
 	return;
 setmode:
-	fchmodat(AT_FDCWD, fname, fstat_buf.st_mode, AT_SYMLINK_NOFOLLOW);
 	fchownat(AT_FDCWD, fname, fstat_buf.st_uid, fstat_buf.st_gid, AT_SYMLINK_NOFOLLOW);
+	if (myuid != 0 && S_ISDIR(fstat_buf.st_mode)) {
+		/*
+		 * Temporary hack until we have a dirstack like star.
+		 */
+		fstat_buf.st_mode |= S_IWUSR;
+	}
+	fchmodat(AT_FDCWD, fname, fstat_buf.st_mode, AT_SYMLINK_NOFOLLOW);
 	times[0].tv_sec = fstat_buf.st_atime;
 	times[0].tv_nsec = stat_ansecs(&fstat_buf);
 	times[1].tv_sec = fstat_buf.st_mtime;
@@ -1001,6 +1012,143 @@ extract_file(f, idr, fname)
 	}
 }
 
+
+LOCAL void
+parse_cl_dir(idr, extent)
+	struct iso_directory_record	*idr;
+	int				extent;
+{
+	char				cl_name_buf[256*3];
+
+	strlcpy(cl_name_buf, name_buf, sizeof (cl_name_buf));
+#ifdef	USE_SCG
+	readsecs(extent - sector_offset, idr, 1);
+#else
+	lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
+	read(fileno(infile), idr, 2048);
+#endif
+
+	if (parse_de(idr) && use_rock)
+		dump_rr(idr);
+	strlcpy(name_buf, cl_name_buf, sizeof (name_buf));
+}
+
+LOCAL BOOL
+parse_de(idr)
+	struct iso_directory_record	*idr;
+{
+	unsigned char	uc;
+
+	if (idr->length[0] == 0)
+		return (FALSE);
+	memset(&fstat_buf, 0, sizeof (fstat_buf));
+	found_rr = 0;
+	name_buf[0] = xname[0] = 0;
+	fstat_buf.st_size = (off_t)(unsigned)isonum_733((unsigned char *)idr->size);
+	if (idr->flags[0] & 2)
+		fstat_buf.st_mode |= S_IFDIR;
+	else
+		fstat_buf.st_mode |= S_IFREG;
+	if (idr->name_len[0] == 1 && idr->name[0] == 0)
+		strcpy(name_buf, ".");
+	else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+		strcpy(name_buf, "..");
+	else {
+		switch (ucs_level) {
+		case 3:
+		case 2:
+		case 1:
+			/*
+			 * Unicode name.  Convert as best we can.
+			 */
+			{
+			int	j;
+				name_buf[0] = '\0';
+#ifdef	USE_ICONV
+			if (use_iconv(unls)) {
+				int	u;
+				char	*to = name_buf;
+
+				for (j = 0, u = 0; j < (int)idr->name_len[0] / 2; j++) {
+					char	*ibuf = (char *)&idr->name[j*2];
+					size_t	isize = 2;		/* UCS-2 character size */
+					size_t	osize = 4;
+
+					if (iconv(unls->sic_uni2cd, (__IC_CONST char **)&ibuf, &isize,
+							(char **)&to, &osize) == -1) {
+						int	err = geterrno();
+
+						if ((err == EINVAL || err == EILSEQ) &&
+						    osize == 4) {
+							*to = '_';
+							u += 1;
+							to++;
+						}
+					} else {
+						u += 4 - osize;
+						to = &name_buf[u];
+					}
+				}
+				j = u;
+			} else
+#endif
+			for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+				UInt16_t	unichar;
+
+				unichar = (idr->name[j*2] & 0xFF) * 256 +
+					    (idr->name[j*2+1] & 0xFF);
+
+				/*
+				 * Get the backconverted char
+				 */
+				if (unls)
+					uc = sic_uni2c(unls, unichar);
+				else
+					uc = unichar > 255 ? '_' : unichar;
+
+				name_buf[j] = uc ? uc : '_';
+			}
+			name_buf[j] = '\0';
+			}
+			break;
+		case 0:
+			/*
+			 * Normal non-Unicode name.
+			 */
+			strncpy(name_buf, idr->name, idr->name_len[0]);
+			name_buf[idr->name_len[0]] = 0;
+			break;
+		default:
+			/*
+			 * Don't know how to do these yet.  Maybe they are the same
+			 * as one of the above.
+			 */
+			exit(1);
+		}
+	}
+	memcpy(date_buf, idr->date, 9);
+	/*
+	 * Always first set up time stamps and file modes from
+	 * ISO-9660. This is used as a fallback in case that
+	 * there is no related Rock Ridge based data.
+	 */
+	fstat_buf.st_atime =
+	fstat_buf.st_mtime =
+	fstat_buf.st_ctime = iso9660_time(date_buf, NULL, FALSE);
+	fstat_buf.st_mode |= S_IRUSR|S_IXUSR |
+		    S_IRGRP|S_IXGRP |
+		    S_IROTH|S_IXOTH;
+	fstat_buf.st_nlink = 1;
+	fstat_buf.st_ino = 0;
+	fstat_buf.st_uid = 0;
+	fstat_buf.st_gid = 0;
+	if (iso9660_inodes) {
+		fstat_buf.st_ino = (unsigned long)
+		    isonum_733((unsigned char *)idr->extent);
+	}
+	return (TRUE);
+}
+
 LOCAL void
 parse_dir(rootname, extent, len)
 	char	*rootname;
@@ -1012,12 +1160,13 @@ parse_dir(rootname, extent, len)
 	struct iso_directory_record * idr;
 	struct iso_directory_record	didr;
 	struct stat			dstat;
-	unsigned char	uc;
+	unsigned char	cl_buffer[2048];
 	unsigned char	flags = 0;
 	Llong		size = 0;
 	int		sextent = 0;
 	int	rlen;
 	int	blen;
+	int	rr_flags = 0;
 static	char	*n = 0;
 static	int	nlen = 0;
 
@@ -1039,115 +1188,23 @@ static	int	nlen = 0;
 		i = 0;
 		while (1 == 1) {
 			idr = (struct iso_directory_record *) &buffer[i];
-			if (idr->length[0] == 0) break;
-			memset(&fstat_buf, 0, sizeof (fstat_buf));
-			found_rr = 0;
-			name_buf[0] = xname[0] = 0;
-			fstat_buf.st_size = (off_t)(unsigned)isonum_733((unsigned char *)idr->size);
-			if (idr->flags[0] & 2)
-				fstat_buf.st_mode |= S_IFDIR;
-			else
-				fstat_buf.st_mode |= S_IFREG;
-			if (idr->name_len[0] == 1 && idr->name[0] == 0)
-				strcpy(name_buf, ".");
-			else if (idr->name_len[0] == 1 && idr->name[0] == 1)
-				strcpy(name_buf, "..");
-			else {
-				switch (ucs_level) {
-				case 3:
-				case 2:
-				case 1:
-					/*
-					 * Unicode name.  Convert as best we can.
-					 */
-					{
-					int	j;
-
-					name_buf[0] = '\0';
-#ifdef	USE_ICONV
-					if (use_iconv(unls)) {
-						int	u;
-						char	*to = name_buf;
-
-						for (j = 0, u = 0; j < (int)idr->name_len[0] / 2; j++) {
-							char	*ibuf = (char *)&idr->name[j*2];
-							size_t	isize = 2;		/* UCS-2 character size */
-							size_t	osize = 4;
-
-							if (iconv(unls->sic_uni2cd, (__IC_CONST char **)&ibuf, &isize,
-									(char **)&to, &osize) == -1) {
-								int	err = geterrno();
-
-								if ((err == EINVAL || err == EILSEQ) &&
-								    osize == 4) {
-									*to = '_';
-									u += 1;
-									to++;
-								}
-							} else {
-								u += 4 - osize;
-								to = &name_buf[u];
-							}
-						}
-						j = u;
-					} else
-#endif
-					for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
-						UInt16_t	unichar;
-
-						unichar = (idr->name[j*2] & 0xFF) * 256 +
-							    (idr->name[j*2+1] & 0xFF);
-
-						/*
-						 * Get the backconverted char
-						 */
-						if (unls)
-							uc = sic_uni2c(unls, unichar);
-						else
-							uc = unichar > 255 ? '_' : unichar;
+			if (idr->length[0] == 0)
+				break;
+			parse_de(idr);
+			if (use_rock) {
+				rr_flags = dump_rr(idr);
 
-						name_buf[j] = uc ? uc : '_';
-					}
-					name_buf[j] = '\0';
-					}
-					break;
-				case 0:
+				if (rr_flags & RR_FLAG_CL) {
 					/*
-					 * Normal non-Unicode name.
+					 * Need to reparse the child link
+					 * but note that we parse "CL/."
+					 * so we get no usable file name.
 					 */
-					strncpy(name_buf, idr->name, idr->name_len[0]);
-					name_buf[idr->name_len[0]] = 0;
-					break;
-				default:
-					/*
-					 * Don't know how to do these yet.  Maybe they are the same
-					 * as one of the above.
-					 */
-					exit(1);
-				}
+					idr = (struct iso_directory_record *) cl_buffer;
+					parse_cl_dir(idr, cl_extent);
+				} else if (rr_flags & RR_FLAG_RE)
+					goto cont;	/* skip rr_moved */
 			}
-			memcpy(date_buf, idr->date, 9);
-			/*
-			 * Always first set up time stamps and file modes from
-			 * ISO-9660. This is used as a fallback in case that
-			 * there is no related Rock Ridge based data.
-			 */
-			fstat_buf.st_atime =
-			fstat_buf.st_mtime =
-			fstat_buf.st_ctime = iso9660_time(date_buf, NULL, FALSE);
-			fstat_buf.st_mode |= S_IRUSR|S_IXUSR |
-				    S_IRGRP|S_IXGRP |
-				    S_IROTH|S_IXOTH;
-			fstat_buf.st_nlink = 1;
-			fstat_buf.st_ino = 0;
-			fstat_buf.st_uid = 0;
-			fstat_buf.st_gid = 0;
-			if (iso9660_inodes) {
-				fstat_buf.st_ino = (unsigned long)
-				    isonum_733((unsigned char *)idr->extent);
-			}
-			if (use_rock)
-				dump_rr(idr);
 			if (Xtract &&
 			    (idr->flags[0] & 2) != 0 &&
 			    idr->name_len[0] == 1 &&
@@ -1170,30 +1227,30 @@ static	int	nlen = 0;
 				n[rlen] = '\0';
 
 			if ((idr->flags[0] & 2) != 0 &&
-			    (idr->name_len[0] != 1 ||
+			    ((rr_flags & RR_FLAG_CL) ||
+			    idr->name_len[0] != 1 ||
 			    (idr->name[0] != 0 && idr->name[0] != 1))) {
 				/*
 				 * This is a plain directory (neither "xxx/."
 				 * nor "xxx/..").
 				 * Add this directory to the todo list.
 				 */
-				td = todo_idr;
-				if (td != NULL) {
-					while (td->next != NULL)
-						td = td->next;
-					td->next = (struct todo *) malloc(sizeof (*td));
-					td = td->next;
-				} else {
-					todo_idr = td = (struct todo *) malloc(sizeof (*td));
-				}
+				td = (struct todo *) malloc(sizeof (*td));
+				if (td == NULL)
+					comerr(_("No memory.\n"));
 				td->next = NULL;
 				td->extent = isonum_733((unsigned char *)idr->extent);
 				td->length = isonum_733((unsigned char *)idr->size);
 				td->name = (char *) malloc(strlen(rootname)
 								+ strlen(name_buf) + 2);
+				if (td->name == NULL)
+					comerr(_("No memory.\n"));
 				strcpy(td->name, rootname);
 				strcat(td->name, name_buf);
 				strcat(td->name, "/");
+
+				*todo_pp = td;
+				todo_pp = &td->next;
 			} else {
 				if (xtract && strcmp(xtract, n) == 0) {
 					extract_file(STDOUT_FILENO, idr, "stdout");
@@ -1253,6 +1310,7 @@ static	int	nlen = 0;
 				if ((idr->flags[0] & ISO_MULTIEXTENT) == 0)
 					size = 0;
 			}
+		cont:
 			i += buffer[i];
 			if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break;
 		}
@@ -1381,12 +1439,13 @@ main(argc, argv)
 		usage(0);
 	if (prvers) {
 		printf(_("isoinfo %s (%s-%s-%s) Copyright (C) 1993-1999 %s (C) 1999-2015 %s\n"),
-					VERSION,
+					"3.02a02",
 					HOST_CPU, HOST_VENDOR, HOST_OS,
 					_("Eric Youngdale"),
 					_("Joerg Schilling"));
 		exit(0);
 	}
+	myuid = getuid();
 #ifdef	USE_FIND
 	if (do_find) {
 		finda_t	fa;
--- cdrtools-3.01.orig/mkisofs/udf.c	2013-04-24 20:45:18.000000000 +0000
+++ cdrtools-3.01/mkisofs/udf.c	2015-11-25 22:07:30.000000000 +0000
@@ -1,15 +1,15 @@
-/* @(#)udf.c	1.42 13/04/24 Copyright 2001-2013 J. Schilling */
+/* @(#)udf.c	1.43 15/11/25 Copyright 2001-2015 J. Schilling */
 #include <schily/mconfig.h>
 #ifndef lint
 static	UConst char sccsid[] =
-	"@(#)udf.c	1.42 13/04/24 Copyright 2001-2013 J. Schilling";
+	"@(#)udf.c	1.43 15/11/25 Copyright 2001-2015 J. Schilling";
 #endif
 /*
  * udf.c - UDF support for mkisofs
  *
  * Written by Ben Rudiak-Gould (2001).
  *
- * Copyright 2001-2013 J. Schilling.
+ * Copyright 2001-2015 J. Schilling.
  */
 /*
  * This program is free software; you can redistribute it and/or modify
@@ -98,7 +98,7 @@ static	UConst char sccsid[] =
 extern	int	use_sparcboot;
 
 extern struct directory *root;
-extern time_t		begun;
+extern struct timeval	tv_begun;
 
 static unsigned lba_main_seq;
 static unsigned lba_main_seq_copy;
@@ -110,7 +110,7 @@ static unsigned lba_end_anchor_vol_desc;
 static unsigned num_udf_files;
 static unsigned num_udf_directories;
 
-static unsigned volume_set_id[2];
+static unsigned volume_set_id[2] = { 0, 0 };
 
 #define	UDF_MAIN_SEQ_LENGTH (16)
 #define	UDF_INTEG_SEQ_LENGTH (2)
@@ -723,7 +723,7 @@ set_primary_vol_desc(buf, lba)
 	/*pvd->volume_abstract;*/
 	/*pvd->volume_copyright_notice;*/
 	/*pvd->application_ident;*/
-	set_timestamp_from_time_t(&pvd->recording_date_and_time, begun);
+	set_timestamp_from_time_t(&pvd->recording_date_and_time, tv_begun.tv_sec);
 	set_impl_ident(&pvd->impl_ident);
 	set_tag(&pvd->desc_tag, UDF_TAGID_PRIMARY_VOLUME_DESC, lba, 512);
 }
@@ -831,7 +831,7 @@ set_logical_vol_integrity_desc(buf, lba)
 	udf_logical_volume_integrity_desc *lvid =
 				(udf_logical_volume_integrity_desc *)buf;
 
-	set_timestamp_from_time_t(&lvid->recording_date, begun);
+	set_timestamp_from_time_t(&lvid->recording_date, tv_begun.tv_sec);
 	set32(&lvid->integrity_type, UDF_INTEGRITY_TYPE_CLOSE);
 	/*lvid->next_integrity_extent;*/
 	set64(&lvid->logical_volume_contents_use.unique_id,
@@ -859,7 +859,7 @@ set_file_set_desc(buf, rba)
 {
 	udf_file_set_desc *fsd = (udf_file_set_desc *)buf;
 
-	set_timestamp_from_time_t(&fsd->recording_date_and_time, begun);
+	set_timestamp_from_time_t(&fsd->recording_date_and_time, tv_begun.tv_sec);
 	set16(&fsd->interchange_level, 3);
 	set16(&fsd->maximum_interchange_level, 3);
 	set32(&fsd->character_set_list, 1);
@@ -1986,8 +1986,10 @@ udf_main_seq_write(out)
 	 * volume_set_id needs to be set to a (64-bit) "unique" number.
 	 * This will have to do for now.
 	 */
-	volume_set_id[0] = begun;
-	volume_set_id[1] = (unsigned)clock();	/* XXX Maybe non-portable */
+	if (volume_set_id[0] == 0) {
+		volume_set_id[0] = tv_begun.tv_sec;
+		volume_set_id[1] = (unsigned)tv_begun.tv_usec;
+	}
 
 	memset(buf, 0, sizeof (buf));
 	set_primary_vol_desc(buf, last_extent_written++);
--- cdrtools-3.01.orig/mkisofs/mkisofs.c	2015-01-01 14:19:51.000000000 +0000
+++ cdrtools-3.01/mkisofs/mkisofs.c
@@ -69 +69 @@ int		path_ind;
-char	version_string[] = VERSION;
+char	version_string[] = "3.01-fix-20151126";
