Subject: bug#26669: [PATCH 1/7] gnu: Add cdrtools.

From: Thomas Danckaert <[email-masked]>
Date: Wed, 26 Apr 2017 18:05:34 +0200 (CEST)

Hi,

this patch series adds a few CD/DVD/Blu Ray Disc burning tools.

There is/has been some controversy about the license of cdrtools, 
with claims it cannot be distributed in binary form because it mixes 
CDDL and GPL code.  As far as I understand, mkisofs is GPL, while the 
other executables are CDDL, and I do not really see the problem.  If 
others disagree, or we want to be extra careful, I suppose we can 
disable substitutes for cdrtools, so we only distribute it as source?

cdrtools also bundles a forked LGPL-licensed copy of cdparanoia.  
This is perhaps unfortunate, but I don't think it's easy to unbundle 
it (cdrtools doesn't build agains our current cdparanoia).

Thomas
>From 96fb5484e4a4d741da685ce63f578feb69bc016f Mon Sep 17 00:00:00 2001
From: Thomas Danckaert <[email-masked]>
Date: Fri, 21 Apr 2017 15:54:20 +0200
Subject: [PATCH 1/7] gnu: Add cdrtools.

* gnu/packages/cdrom.scm (cdrtools): New variable.
* gnu/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
---
 gnu/local.mk                                       |   1 +
 gnu/packages/cdrom.scm                             |  63 ++-
 .../patches/cdrtools-3.01-mkisofs-isoinfo.patch    | 514 +++++++++++++++++++++
 3 files changed, 577 insertions(+), 1 deletion(-)
 create mode 100644 gnu/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index cb94d27e9..a2c56e03d 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -513,6 +513,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/calibre-drop-unrar.patch			\
   %D%/packages/patches/calibre-no-updates-dialog.patch		\
   %D%/packages/patches/cdparanoia-fpic.patch			\
+  %D%/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch 	\
   %D%/packages/patches/ceph-disable-cpu-optimizations.patch	\
   %D%/packages/patches/ceph-disable-unittest-throttle.patch	\
   %D%/packages/patches/ceph-skip-collect-sys-info-test.patch	\
diff --git a/gnu/packages/cdrom.scm b/gnu/packages/cdrom.scm
index 7e86753ab..69af39655 100644
--- a/gnu/packages/cdrom.scm
+++ b/gnu/packages/cdrom.scm
@@ -26,7 +26,7 @@
 (define-module (gnu packages cdrom)
   #:use-module (guix download)
   #:use-module (guix packages)
-  #:use-module ((guix licenses) #:select (lgpl2.1+ gpl2 gpl2+ gpl3+))
+  #:use-module ((guix licenses) #:select (lgpl2.1+ gpl2 gpl2+ gpl3+ cddl1.0))
   #:use-module (guix build-system cmake)
   #:use-module (guix build-system gnu)
   #:use-module (guix build-system glib-or-gtk)
@@ -197,6 +197,67 @@ extra-robust data verification, synchronization, error handling and scratch
 reconstruction capability.")
     (license gpl2))) ; libraries under lgpl2.1
 
+(define-public cdrtools
+  (package
+   (name "cdrtools")
+   (version "3.01")
+   (source (origin
+             (method url-fetch)
+             (uri (string-append
+                   "mirror://sourceforge/cdrtools/cdrtools-" version ".tar.bz2"))
+             (sha256
+              (base32
+               "03w6ypsmwwy4d7vh6zgwpc60v541vc5ywp8bdb758hbc4yv2wa7d"))
+             (patches (search-patches "cdrtools-3.01-mkisofs-isoinfo.patch"))))
+   (build-system gnu-build-system)
+   (inputs
+    `(("linux-headers" ,linux-libre-headers)))
+   (native-inputs
+    `(("coreutils" ,coreutils)))
+   (arguments
+    `(#:phases (modify-phases %standard-phases
+                 (delete 'configure)
+                 (add-before 'build 'set-linux-headers
+                   (lambda _
+                     (substitute* "autoconf/configure"
+                       (("/usr/src/linux")
+                        (assoc-ref %build-inputs "linux-headers")))
+                     #t))
+                 (add-before 'build 'substitute-dirs
+                   (lambda _
+                     (substitute* (append (find-files "DEFAULTS" "^Defaults\\.")
+                                          (find-files "DEFAULTS_ENG" "^Defaults\\.")
+                                          (find-files "TEMPLATES" "^Defaults\\."))
+                       (("/opt/schily") (assoc-ref %outputs "out")))
+                     #t))
+                 (replace 'build
+                   (lambda _
+                     (zero?
+                      (system* "make" "CONFIG_SHELL=sh" "CCOM=gcc" "RM=rm"))))
+                 (replace 'install
+                   (lambda _
+                     (zero?
+                      (system* "make"
+                               "RM=rm" "LN=ln" "SYMLINK=ln -s"
+                               (string-append "INS_BASE=" (assoc-ref %outputs "out"))
+                               (string-append "INS_RBASE=" (assoc-ref %outputs "out"))
+                               "install" )))))
+      #:tests? #f  ; no tests
+
+      ;; It's unclear if binaries can be distributed due to the mixing of CDDL
+      ;; and GPL code.
+      #:substitutable? #f))
+   (synopsis "Command line utilities to manipulate and burn CD/DVD/BD images")
+   (description "cdrtools is a collection of command line utilities to create
+CD's, DVD's or Blue Ray discs.  The most important components are
+@command{cdrecord}, a burning program, @command{cdda2wav}, a CD audio ripper
+which uses libparanoia, and @command{mkisofs}, which can create various disc
+images.")
+   (home-page "http://cdrtools.sourceforge.net/private/cdrecord.html")
+
+   ;; mkisofs is GPL, the other programs are CDDL.
+   (license (list cddl1.0 gpl2))))
+
 (define-public dvdisaster
   (package
     (name "dvdisaster")
diff --git a/gnu/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch b/gnu/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch
new file mode 100644
index 000000000..9c817d419
--- /dev/null
+++ b/gnu/packages/patches/cdrtools-3.01-mkisofs-isoinfo.patch
@@ -0,0 +1,514 @@
+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";
-- 
2.12.2