[meego-packaging] 4868: Changes to Trunk:Testing/libisofs

Yan Yin yan.yin at intel.com
Thu Jun 24 22:29:50 PDT 2010


Hi,
I have made the following changes to libisofs in project Trunk:Testing. Please review and accept ASAP.

Thank You,
Yan Yin

[This message was auto-generated]

---

Request #4868:

  submit:   home:yyin2:branches:Trunk:Testing/libisofs(r2)(cleanup) -> Trunk:Testing/libisofs


Message:
    upgrade to 0.6.32, fix multiple ldconfig

State:   new          2010-06-24T17:26:58 yyin2
Comment: None



changes files:
--------------
--- libisofs.changes
+++ libisofs.changes
@@ -0,0 +1,4 @@
+* Thu Jun 24 2010 Yan Yin <yan.yin at intel.com> - 0.6.32
+- Change to YAML format
+- upgrade to 0.6.32
+

old:
----
  libisofs-0.6.20.tar.gz

new:
----
  Makefile
  libisofs-0.6.32.tar.gz
  libisofs.yaml

spec files:
-----------
--- libisofs.spec
+++ libisofs.spec
@@ -1,14 +1,23 @@
-Summary:	Library to create ISO 9660 disk images
+# 
+# Do not Edit! Generated by:
+# spectacle version 0.17
+# 
+# >> macros
+# << macros
+
 Name:		libisofs
-Version:	0.6.20
+Summary:    Library to create ISO 9660 disk images
+Version:    0.6.32
 Release:	2
-License:	GPLv2
 Group:		System/Libraries
+License:    GPLv2
 URL:		http://libburnia-project.org/
-Source:		http://files.libburnia-project.org/releases/%{name}-%{version}.tar.gz
+Source0:    http://files.libburnia-project.org/releases/%{name}-%{version}.tar.gz
+Source100:  libisofs.yaml
 Patch0:		libisofs-0.6.16-multilib.patch
-#BuildRequires:	doxygen, graphviz
-BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
 
 %description
 Libisofs is a library to create an ISO-9660 filesystem and supports
@@ -18,46 +27,83 @@
 attributes etc. It supports the extension AAIP which allows to store
 ACLs and xattr in ISO-9660 filesystems as well.
 
+
+
 %package devel
 Summary:	Development files for libisofs
 Group:		Development/Libraries
-Requires:	%{name} = %{version}-%{release}, pkgconfig
+Requires:   %{name} = %{version}-%{release}
+Requires:   pkgconfig
 
 %description devel
 The libisofs-devel package contains libraries and header files for
 developing applications that use libisofs.
 
+
+
 %prep
-%setup -q
-%patch0 -p1 -b .multilib
+%setup -q -n %{name}-%{version}
+
+# libisofs-0.6.16-multilib.patch
+%patch0 -p1
+# >> setup
+# << setup
 
 %build
+# >> build pre
+# << build pre
+
 %configure --disable-static
-make %{?_smp_mflags}
-#doxygen doc/doxygen.conf
+make %{?jobs:-j%jobs}
 
+# >> build post
+# << build post
 %install
+rm -rf %{buildroot}
+# >> install pre
+# << install pre
+%make_install
+
+# >> install post
 rm -rf $RPM_BUILD_ROOT
 make DESTDIR=$RPM_BUILD_ROOT INSTALL='install -p' install
 
 # Don't install any libtool .la files
 rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}.la
 
-%clean
-rm -rf $RPM_BUILD_ROOT
+# << install post
+
+
+
+%post
+/sbin/ldconfig
+# >> post
+/sbin/ldconfig
+# << post
+
+%postun
+/sbin/ldconfig
+# >> postun
+/sbin/ldconfig
+# << postun
+
+
 
-%post -p /sbin/ldconfig
 
-%postun -p /sbin/ldconfig
 
 %files
 %defattr(-,root,root,-)
+# >> files
 %doc AUTHORS COPYING COPYRIGHT README NEWS
 %{_libdir}/%{name}*.so.*
+# << files
+
 
 %files devel
 %defattr(-,root,root,-)
+# >> files devel
 %{_includedir}/%{name}
 %{_libdir}/%{name}.so
 %{_libdir}/pkgconfig/%{name}*.pc
+# << files devel
 

other changes:
--------------

++++++ Makefile (new)
--- Makefile
+++ Makefile
+PKG_NAME := libisofs
+SPECFILE = $(addsuffix .spec, $(PKG_NAME))
+YAMLFILE = $(addsuffix .yaml, $(PKG_NAME))
+
+include /usr/share/packaging-tools/Makefile.common
+

++++++ libisofs-0.6.20.tar.gz -> libisofs-0.6.32.tar.gz
--- COPYRIGHT
+++ COPYRIGHT
@@ -1,12 +1,12 @@
 Vreixo Formoso <metalpain2002 at yahoo.es>,
 Mario Danic <mario.danic at gmail.com>, 
 Thomas Schmitt <scdbackup at gmx.net>
-Copyright (C) 2007-2008 Vreixo Formoso, Mario Danic, Thomas Schmitt
+Copyright (C) 2007-2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
 
 
     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.
+    it under the terms of the GNU General Public License version 2 or later
+    as published by the Free Software Foundation.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
--- Makefile.am
+++ Makefile.am
@@ -73,7 +73,9 @@
 	libisofs/iso1999.c \
 	libisofs/data_source.c \
 	libisofs/aaip_0_2.h \
-	libisofs/aaip_0_2.c
+	libisofs/aaip_0_2.c \
+	libisofs/md5.h \
+	libisofs/md5.c
 libisofs_libisofs_la_LIBADD= \
 	$(THREAD_LIBS)
 libinclude_HEADERS = \
@@ -83,71 +85,102 @@
 
 ## Build demo applications
 noinst_PROGRAMS = \
-	demo/lsl \
-	demo/cat \
-	demo/catbuffer \
-	demo/tree \
-	demo/find \
-	demo/ecma119tree \
-	demo/iso \
-	demo/isoread \
-	demo/isocat \
-	demo/isomodify \
-	demo/isoms
+	demo/demo 
 
+#	demo/tree \
+#	demo/find \
+#	demo/iso \
+#	demo/isoread \
+#	demo/isocat \
+#	demo/isomodify \
+#	demo/isoms
+
+#	demo/ecma119tree \
+#	demo/lsl \
+#	demo/cat \
+#	demo/catbuffer \
 #	demo/isogrow
 
-demo_lsl_CPPFLAGS = -Ilibisofs
-demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_lsl_SOURCES = demo/lsl.c
-
-demo_cat_CPPFLAGS = -Ilibisofs
-demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_cat_SOURCES = demo/cat.c
-
-demo_catbuffer_CPPFLAGS = -Ilibisofs
-demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_catbuffer_SOURCES = demo/cat_buffer.c
-
-demo_tree_CPPFLAGS = -Ilibisofs
-demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_tree_SOURCES = demo/tree.c
-
-demo_find_CPPFLAGS = -Ilibisofs
-demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_find_SOURCES = demo/find.c
-
-demo_ecma119tree_CPPFLAGS = -Ilibisofs
-demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_ecma119tree_SOURCES = demo/ecma119_tree.c
-
-demo_iso_CPPFLAGS = -Ilibisofs
-demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_iso_SOURCES = demo/iso.c
-
-demo_isoread_CPPFLAGS = -Ilibisofs
-demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_isoread_SOURCES = demo/iso_read.c
-
-demo_isocat_CPPFLAGS = -Ilibisofs
-demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_isocat_SOURCES = demo/iso_cat.c
-
-demo_isomodify_CPPFLAGS = -Ilibisofs
-demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_isomodify_SOURCES = demo/iso_modify.c
-
-demo_isoms_CPPFLAGS = -Ilibisofs
-demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-demo_isoms_SOURCES = demo/iso_ms.c
+
+# ts A90807
+# Consolidated demo code for having less linker mesages with a make run.
+demo_demo_CPPFLAGS = -Ilibisofs
+demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+demo_demo_SOURCES = demo/demo.c
+
+# ts A90806
+# This includes fsource.h and thus is no API demo
+# demo_lsl_CPPFLAGS = -Ilibisofs
+# demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_lsl_SOURCES = demo/lsl.c
+
+# ts A90806
+# This includes fsource.h and thus is no API demo
+# demo_cat_CPPFLAGS = -Ilibisofs
+# demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_cat_SOURCES = demo/cat.c
+
+# ts A90806
+# This inlcudes buffer.h and thus is no API demo
+# demo_catbuffer_CPPFLAGS = -Ilibisofs
+# demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_catbuffer_SOURCES = demo/cat_buffer.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_tree_CPPFLAGS = -Ilibisofs
+# demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_tree_SOURCES = demo/tree.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_find_CPPFLAGS = -Ilibisofs
+# demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_find_SOURCES = demo/find.c
+
+# ts A90806
+# This inlcudes lots of internal .h files and thus is no API demo
+# demo_ecma119tree_CPPFLAGS = -Ilibisofs
+# demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_ecma119tree_SOURCES = demo/ecma119_tree.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_iso_CPPFLAGS = -Ilibisofs
+# demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_iso_SOURCES = demo/iso.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isoread_CPPFLAGS = -Ilibisofs
+# demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isoread_SOURCES = demo/iso_read.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isocat_CPPFLAGS = -Ilibisofs
+# demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isocat_SOURCES = demo/iso_cat.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isomodify_CPPFLAGS = -Ilibisofs
+# demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isomodify_SOURCES = demo/iso_modify.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isoms_CPPFLAGS = -Ilibisofs
+# demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isoms_SOURCES = demo/iso_ms.c
 
 # demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn
 # demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) \
@@ -228,6 +261,7 @@
 	doc/susp_aaip_2_0.txt \
 	doc/susp_aaip_isofs_names.txt \
 	doc/zisofs_format.txt \
+	doc/checksums.txt \
 	libisofs/aaip-os-dummy.c \
 	libisofs/aaip-os-linux.c \
 	libisofs/aaip-os-freebsd.c
--- Makefile.in
+++ Makefile.in
@@ -40,11 +40,7 @@
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-noinst_PROGRAMS = demo/lsl$(EXEEXT) demo/cat$(EXEEXT) \
-	demo/catbuffer$(EXEEXT) demo/tree$(EXEEXT) demo/find$(EXEEXT) \
-	demo/ecma119tree$(EXEEXT) demo/iso$(EXEEXT) \
-	demo/isoread$(EXEEXT) demo/isocat$(EXEEXT) \
-	demo/isomodify$(EXEEXT) demo/isoms$(EXEEXT)
+noinst_PROGRAMS = demo/demo$(EXEEXT)
 DIST_COMMON = README $(am__configure_deps) $(libinclude_HEADERS) \
 	$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
 	$(srcdir)/libisofs-1.pc.in $(srcdir)/version.h.in \
@@ -106,11 +102,12 @@
 	libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo \
 	libisofs/libisofs_libisofs_la-iso1999.lo \
 	libisofs/libisofs_libisofs_la-data_source.lo \
-	libisofs/libisofs_libisofs_la-aaip_0_2.lo
+	libisofs/libisofs_libisofs_la-aaip_0_2.lo \
+	libisofs/libisofs_libisofs_la-md5.lo
 libisofs_libisofs_la_OBJECTS = $(am_libisofs_libisofs_la_OBJECTS)
 PROGRAMS = $(noinst_PROGRAMS)
-am_demo_cat_OBJECTS = demo/demo_cat-cat.$(OBJEXT)
-demo_cat_OBJECTS = $(am_demo_cat_OBJECTS)
+am_demo_demo_OBJECTS = demo/demo_demo-demo.$(OBJEXT)
+demo_demo_OBJECTS = $(am_demo_demo_OBJECTS)
 am__DEPENDENCIES_2 = libisofs/libisofs_libisofs_la-builder.lo \
 	libisofs/libisofs_libisofs_la-node.lo \
 	libisofs/libisofs_libisofs_la-tree.lo \
@@ -142,45 +139,11 @@
 	libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo \
 	libisofs/libisofs_libisofs_la-iso1999.lo \
 	libisofs/libisofs_libisofs_la-data_source.lo \
-	libisofs/libisofs_libisofs_la-aaip_0_2.lo
+	libisofs/libisofs_libisofs_la-aaip_0_2.lo \
+	libisofs/libisofs_libisofs_la-md5.lo
 am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
 am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1)
-demo_cat_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_catbuffer_OBJECTS = demo/demo_catbuffer-cat_buffer.$(OBJEXT)
-demo_catbuffer_OBJECTS = $(am_demo_catbuffer_OBJECTS)
-demo_catbuffer_DEPENDENCIES = $(am__DEPENDENCIES_3) \
-	$(am__DEPENDENCIES_4)
-am_demo_ecma119tree_OBJECTS =  \
-	demo/demo_ecma119tree-ecma119_tree.$(OBJEXT)
-demo_ecma119tree_OBJECTS = $(am_demo_ecma119tree_OBJECTS)
-demo_ecma119tree_DEPENDENCIES = $(am__DEPENDENCIES_3) \
-	$(am__DEPENDENCIES_4)
-am_demo_find_OBJECTS = demo/demo_find-find.$(OBJEXT)
-demo_find_OBJECTS = $(am_demo_find_OBJECTS)
-demo_find_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_iso_OBJECTS = demo/demo_iso-iso.$(OBJEXT)
-demo_iso_OBJECTS = $(am_demo_iso_OBJECTS)
-demo_iso_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_isocat_OBJECTS = demo/demo_isocat-iso_cat.$(OBJEXT)
-demo_isocat_OBJECTS = $(am_demo_isocat_OBJECTS)
-demo_isocat_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_isomodify_OBJECTS = demo/demo_isomodify-iso_modify.$(OBJEXT)
-demo_isomodify_OBJECTS = $(am_demo_isomodify_OBJECTS)
-demo_isomodify_DEPENDENCIES = $(am__DEPENDENCIES_3) \
-	$(am__DEPENDENCIES_4)
-am_demo_isoms_OBJECTS = demo/demo_isoms-iso_ms.$(OBJEXT)
-demo_isoms_OBJECTS = $(am_demo_isoms_OBJECTS)
-demo_isoms_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_isoread_OBJECTS = demo/demo_isoread-iso_read.$(OBJEXT)
-demo_isoread_OBJECTS = $(am_demo_isoread_OBJECTS)
-demo_isoread_DEPENDENCIES = $(am__DEPENDENCIES_3) \
-	$(am__DEPENDENCIES_4)
-am_demo_lsl_OBJECTS = demo/demo_lsl-lsl.$(OBJEXT)
-demo_lsl_OBJECTS = $(am_demo_lsl_OBJECTS)
-demo_lsl_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
-am_demo_tree_OBJECTS = demo/demo_tree-tree.$(OBJEXT)
-demo_tree_OBJECTS = $(am_demo_tree_OBJECTS)
-demo_tree_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
+demo_demo_DEPENDENCIES = $(am__DEPENDENCIES_3) $(am__DEPENDENCIES_4)
 DEFAULT_INCLUDES = -I. -I$(srcdir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__depfiles_maybe = depfiles
@@ -192,18 +155,8 @@
 CCLD = $(CC)
 LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
 	$(AM_LDFLAGS) $(LDFLAGS) -o $@
-SOURCES = $(libisofs_libisofs_la_SOURCES) $(demo_cat_SOURCES) \
-	$(demo_catbuffer_SOURCES) $(demo_ecma119tree_SOURCES) \
-	$(demo_find_SOURCES) $(demo_iso_SOURCES) \
-	$(demo_isocat_SOURCES) $(demo_isomodify_SOURCES) \
-	$(demo_isoms_SOURCES) $(demo_isoread_SOURCES) \
-	$(demo_lsl_SOURCES) $(demo_tree_SOURCES)
-DIST_SOURCES = $(libisofs_libisofs_la_SOURCES) $(demo_cat_SOURCES) \
-	$(demo_catbuffer_SOURCES) $(demo_ecma119tree_SOURCES) \
-	$(demo_find_SOURCES) $(demo_iso_SOURCES) \
-	$(demo_isocat_SOURCES) $(demo_isomodify_SOURCES) \
-	$(demo_isoms_SOURCES) $(demo_isoread_SOURCES) \
-	$(demo_lsl_SOURCES) $(demo_tree_SOURCES)
+SOURCES = $(libisofs_libisofs_la_SOURCES) $(demo_demo_SOURCES)
+DIST_SOURCES = $(libisofs_libisofs_la_SOURCES) $(demo_demo_SOURCES)
 nodist_pkgconfigDATA_INSTALL = $(INSTALL_DATA)
 DATA = $(nodist_pkgconfig_DATA)
 libincludeHEADERS_INSTALL = $(INSTALL_HEADER)
@@ -316,6 +269,80 @@
 datadir = @datadir@
 datarootdir = @datarootdir@
 
+# ts A90806
+# This includes fsource.h and thus is no API demo
+# demo_lsl_CPPFLAGS = -Ilibisofs
+# demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_lsl_SOURCES = demo/lsl.c
+
+# ts A90806
+# This includes fsource.h and thus is no API demo
+# demo_cat_CPPFLAGS = -Ilibisofs
+# demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_cat_SOURCES = demo/cat.c
+
+# ts A90806
+# This inlcudes buffer.h and thus is no API demo
+# demo_catbuffer_CPPFLAGS = -Ilibisofs
+# demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_catbuffer_SOURCES = demo/cat_buffer.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_tree_CPPFLAGS = -Ilibisofs
+# demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_tree_SOURCES = demo/tree.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_find_CPPFLAGS = -Ilibisofs
+# demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_find_SOURCES = demo/find.c
+
+# ts A90806
+# This inlcudes lots of internal .h files and thus is no API demo
+# demo_ecma119tree_CPPFLAGS = -Ilibisofs
+# demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_ecma119tree_SOURCES = demo/ecma119_tree.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_iso_CPPFLAGS = -Ilibisofs
+# demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+# demo_iso_SOURCES = demo/iso.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isoread_CPPFLAGS = -Ilibisofs
+# demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isoread_SOURCES = demo/iso_read.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isocat_CPPFLAGS = -Ilibisofs
+# demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isocat_SOURCES = demo/iso_cat.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isomodify_CPPFLAGS = -Ilibisofs
+# demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isomodify_SOURCES = demo/iso_modify.c
+
+# ts A90807
+# Consolidated in demo/demo
+# demo_isoms_CPPFLAGS = -Ilibisofs
+# demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
+# 	$(libisofs_libisofs_la_LIBADD)
+# demo_isoms_SOURCES = demo/iso_ms.c
+
 # demo_isogrow_CPPFLAGS = -Ilibisofs -Ilibburn
 # demo_isogrow_LDADD = $(libisofs_libisofs_la_OBJECTS) \
 # 	$(libisofs_libisofs_la_LIBADD) \
@@ -444,7 +471,9 @@
 	libisofs/iso1999.c \
 	libisofs/data_source.c \
 	libisofs/aaip_0_2.h \
-	libisofs/aaip_0_2.c
+	libisofs/aaip_0_2.c \
+	libisofs/md5.h \
+	libisofs/md5.c
 
 libisofs_libisofs_la_LIBADD = \
 	$(THREAD_LIBS)
@@ -453,56 +482,25 @@
 	libisofs/libisofs.h
 
 
+#	demo/tree \
+#	demo/find \
+#	demo/iso \
+#	demo/isoread \
+#	demo/isocat \
+#	demo/isomodify \
+#	demo/isoms
+
+#	demo/ecma119tree \
+#	demo/lsl \
+#	demo/cat \
+#	demo/catbuffer \
 #	demo/isogrow
-demo_lsl_CPPFLAGS = -Ilibisofs
-demo_lsl_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_lsl_SOURCES = demo/lsl.c
-demo_cat_CPPFLAGS = -Ilibisofs
-demo_cat_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_cat_SOURCES = demo/cat.c
-demo_catbuffer_CPPFLAGS = -Ilibisofs
-demo_catbuffer_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_catbuffer_SOURCES = demo/cat_buffer.c
-demo_tree_CPPFLAGS = -Ilibisofs
-demo_tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_tree_SOURCES = demo/tree.c
-demo_find_CPPFLAGS = -Ilibisofs
-demo_find_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_find_SOURCES = demo/find.c
-demo_ecma119tree_CPPFLAGS = -Ilibisofs
-demo_ecma119tree_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_ecma119tree_SOURCES = demo/ecma119_tree.c
-demo_iso_CPPFLAGS = -Ilibisofs
-demo_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
-demo_iso_SOURCES = demo/iso.c
-demo_isoread_CPPFLAGS = -Ilibisofs
-demo_isoread_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_isoread_SOURCES = demo/iso_read.c
-demo_isocat_CPPFLAGS = -Ilibisofs
-demo_isocat_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_isocat_SOURCES = demo/iso_cat.c
-demo_isomodify_CPPFLAGS = -Ilibisofs
-demo_isomodify_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
-
-demo_isomodify_SOURCES = demo/iso_modify.c
-demo_isoms_CPPFLAGS = -Ilibisofs
-demo_isoms_LDADD = $(libisofs_libisofs_la_OBJECTS) \
-	$(libisofs_libisofs_la_LIBADD)
 
-demo_isoms_SOURCES = demo/iso_ms.c
+# ts A90807
+# Consolidated demo code for having less linker mesages with a make run.
+demo_demo_CPPFLAGS = -Ilibisofs
+demo_demo_LDADD = $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD)
+demo_demo_SOURCES = demo/demo.c
 
 # Extra things
 nodist_pkgconfig_DATA = \
@@ -527,6 +525,7 @@
 	doc/susp_aaip_2_0.txt \
 	doc/susp_aaip_isofs_names.txt \
 	doc/zisofs_format.txt \
+	doc/checksums.txt \
 	libisofs/aaip-os-dummy.c \
 	libisofs/aaip-os-linux.c \
 	libisofs/aaip-os-freebsd.c
@@ -681,6 +680,8 @@
 	libisofs/$(am__dirstamp) libisofs/$(DEPDIR)/$(am__dirstamp)
 libisofs/libisofs_libisofs_la-aaip_0_2.lo: libisofs/$(am__dirstamp) \
 	libisofs/$(DEPDIR)/$(am__dirstamp)
+libisofs/libisofs_libisofs_la-md5.lo: libisofs/$(am__dirstamp) \
+	libisofs/$(DEPDIR)/$(am__dirstamp)
 libisofs/libisofs.la: $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_DEPENDENCIES) libisofs/$(am__dirstamp)
 	$(LINK) -rpath $(libdir) $(libisofs_libisofs_la_LDFLAGS) $(libisofs_libisofs_la_OBJECTS) $(libisofs_libisofs_la_LIBADD) $(LIBS)
 
@@ -696,75 +697,15 @@
 demo/$(DEPDIR)/$(am__dirstamp):
 	@$(mkdir_p) demo/$(DEPDIR)
 	@: > demo/$(DEPDIR)/$(am__dirstamp)
-demo/demo_cat-cat.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/cat$(EXEEXT): $(demo_cat_OBJECTS) $(demo_cat_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/cat$(EXEEXT)
-	$(LINK) $(demo_cat_LDFLAGS) $(demo_cat_OBJECTS) $(demo_cat_LDADD) $(LIBS)
-demo/demo_catbuffer-cat_buffer.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/catbuffer$(EXEEXT): $(demo_catbuffer_OBJECTS) $(demo_catbuffer_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/catbuffer$(EXEEXT)
-	$(LINK) $(demo_catbuffer_LDFLAGS) $(demo_catbuffer_OBJECTS) $(demo_catbuffer_LDADD) $(LIBS)
-demo/demo_ecma119tree-ecma119_tree.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/ecma119tree$(EXEEXT): $(demo_ecma119tree_OBJECTS) $(demo_ecma119tree_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/ecma119tree$(EXEEXT)
-	$(LINK) $(demo_ecma119tree_LDFLAGS) $(demo_ecma119tree_OBJECTS) $(demo_ecma119tree_LDADD) $(LIBS)
-demo/demo_find-find.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/find$(EXEEXT): $(demo_find_OBJECTS) $(demo_find_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/find$(EXEEXT)
-	$(LINK) $(demo_find_LDFLAGS) $(demo_find_OBJECTS) $(demo_find_LDADD) $(LIBS)
-demo/demo_iso-iso.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/iso$(EXEEXT): $(demo_iso_OBJECTS) $(demo_iso_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/iso$(EXEEXT)
-	$(LINK) $(demo_iso_LDFLAGS) $(demo_iso_OBJECTS) $(demo_iso_LDADD) $(LIBS)
-demo/demo_isocat-iso_cat.$(OBJEXT): demo/$(am__dirstamp) \
+demo/demo_demo-demo.$(OBJEXT): demo/$(am__dirstamp) \
 	demo/$(DEPDIR)/$(am__dirstamp)
-demo/isocat$(EXEEXT): $(demo_isocat_OBJECTS) $(demo_isocat_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/isocat$(EXEEXT)
-	$(LINK) $(demo_isocat_LDFLAGS) $(demo_isocat_OBJECTS) $(demo_isocat_LDADD) $(LIBS)
-demo/demo_isomodify-iso_modify.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/isomodify$(EXEEXT): $(demo_isomodify_OBJECTS) $(demo_isomodify_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/isomodify$(EXEEXT)
-	$(LINK) $(demo_isomodify_LDFLAGS) $(demo_isomodify_OBJECTS) $(demo_isomodify_LDADD) $(LIBS)
-demo/demo_isoms-iso_ms.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/isoms$(EXEEXT): $(demo_isoms_OBJECTS) $(demo_isoms_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/isoms$(EXEEXT)
-	$(LINK) $(demo_isoms_LDFLAGS) $(demo_isoms_OBJECTS) $(demo_isoms_LDADD) $(LIBS)
-demo/demo_isoread-iso_read.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/isoread$(EXEEXT): $(demo_isoread_OBJECTS) $(demo_isoread_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/isoread$(EXEEXT)
-	$(LINK) $(demo_isoread_LDFLAGS) $(demo_isoread_OBJECTS) $(demo_isoread_LDADD) $(LIBS)
-demo/demo_lsl-lsl.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/lsl$(EXEEXT): $(demo_lsl_OBJECTS) $(demo_lsl_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/lsl$(EXEEXT)
-	$(LINK) $(demo_lsl_LDFLAGS) $(demo_lsl_OBJECTS) $(demo_lsl_LDADD) $(LIBS)
-demo/demo_tree-tree.$(OBJEXT): demo/$(am__dirstamp) \
-	demo/$(DEPDIR)/$(am__dirstamp)
-demo/tree$(EXEEXT): $(demo_tree_OBJECTS) $(demo_tree_DEPENDENCIES) demo/$(am__dirstamp)
-	@rm -f demo/tree$(EXEEXT)
-	$(LINK) $(demo_tree_LDFLAGS) $(demo_tree_OBJECTS) $(demo_tree_LDADD) $(LIBS)
+demo/demo$(EXEEXT): $(demo_demo_OBJECTS) $(demo_demo_DEPENDENCIES) demo/$(am__dirstamp)
+	@rm -f demo/demo$(EXEEXT)
+	$(LINK) $(demo_demo_LDFLAGS) $(demo_demo_OBJECTS) $(demo_demo_LDADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
-	-rm -f demo/demo_cat-cat.$(OBJEXT)
-	-rm -f demo/demo_catbuffer-cat_buffer.$(OBJEXT)
-	-rm -f demo/demo_ecma119tree-ecma119_tree.$(OBJEXT)
-	-rm -f demo/demo_find-find.$(OBJEXT)
-	-rm -f demo/demo_iso-iso.$(OBJEXT)
-	-rm -f demo/demo_isocat-iso_cat.$(OBJEXT)
-	-rm -f demo/demo_isomodify-iso_modify.$(OBJEXT)
-	-rm -f demo/demo_isoms-iso_ms.$(OBJEXT)
-	-rm -f demo/demo_isoread-iso_read.$(OBJEXT)
-	-rm -f demo/demo_lsl-lsl.$(OBJEXT)
-	-rm -f demo/demo_tree-tree.$(OBJEXT)
+	-rm -f demo/demo_demo-demo.$(OBJEXT)
 	-rm -f libisofs/filters/libisofs_libisofs_la-external.$(OBJEXT)
 	-rm -f libisofs/filters/libisofs_libisofs_la-external.lo
 	-rm -f libisofs/filters/libisofs_libisofs_la-gzip.$(OBJEXT)
@@ -809,6 +750,8 @@
 	-rm -f libisofs/libisofs_libisofs_la-libiso_msgs.lo
 	-rm -f libisofs/libisofs_libisofs_la-make_isohybrid_mbr.$(OBJEXT)
 	-rm -f libisofs/libisofs_libisofs_la-make_isohybrid_mbr.lo
+	-rm -f libisofs/libisofs_libisofs_la-md5.$(OBJEXT)
+	-rm -f libisofs/libisofs_libisofs_la-md5.lo
 	-rm -f libisofs/libisofs_libisofs_la-messages.$(OBJEXT)
 	-rm -f libisofs/libisofs_libisofs_la-messages.lo
 	-rm -f libisofs/libisofs_libisofs_la-node.$(OBJEXT)
@@ -833,17 +776,7 @@
 distclean-compile:
 	-rm -f *.tab.c
 
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_cat-cat.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_find-find.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_iso-iso.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_isocat-iso_cat.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_isomodify-iso_modify.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_isoms-iso_ms.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_isoread-iso_read.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_lsl-lsl.Po at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_tree-tree.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at demo/$(DEPDIR)/demo_demo-demo.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-aaip_0_2.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-buffer.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-builder.Plo at am__quote@
@@ -862,6 +795,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-joliet.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-libiso_msgs.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-make_isohybrid_mbr.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-messages.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-node.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at libisofs/$(DEPDIR)/libisofs_libisofs_la-rockridge.Plo at am__quote@
@@ -1125,159 +1059,26 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-aaip_0_2.lo `test -f 'libisofs/aaip_0_2.c' || echo '$(srcdir)/'`libisofs/aaip_0_2.c
 
-demo/demo_cat-cat.o: demo/cat.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_cat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_cat-cat.o -MD -MP -MF "demo/$(DEPDIR)/demo_cat-cat.Tpo" -c -o demo/demo_cat-cat.o `test -f 'demo/cat.c' || echo '$(srcdir)/'`demo/cat.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_cat-cat.Tpo" "demo/$(DEPDIR)/demo_cat-cat.Po"; else rm -f "demo/$(DEPDIR)/demo_cat-cat.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/cat.c' object='demo/demo_cat-cat.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_cat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_cat-cat.o `test -f 'demo/cat.c' || echo '$(srcdir)/'`demo/cat.c
-
-demo/demo_cat-cat.obj: demo/cat.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_cat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_cat-cat.obj -MD -MP -MF "demo/$(DEPDIR)/demo_cat-cat.Tpo" -c -o demo/demo_cat-cat.obj `if test -f 'demo/cat.c'; then $(CYGPATH_W) 'demo/cat.c'; else $(CYGPATH_W) '$(srcdir)/demo/cat.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_cat-cat.Tpo" "demo/$(DEPDIR)/demo_cat-cat.Po"; else rm -f "demo/$(DEPDIR)/demo_cat-cat.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/cat.c' object='demo/demo_cat-cat.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_cat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_cat-cat.obj `if test -f 'demo/cat.c'; then $(CYGPATH_W) 'demo/cat.c'; else $(CYGPATH_W) '$(srcdir)/demo/cat.c'; fi`
-
-demo/demo_catbuffer-cat_buffer.o: demo/cat_buffer.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_catbuffer_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_catbuffer-cat_buffer.o -MD -MP -MF "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo" -c -o demo/demo_catbuffer-cat_buffer.o `test -f 'demo/cat_buffer.c' || echo '$(srcdir)/'`demo/cat_buffer.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo" "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Po"; else rm -f "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/cat_buffer.c' object='demo/demo_catbuffer-cat_buffer.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_catbuffer_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_catbuffer-cat_buffer.o `test -f 'demo/cat_buffer.c' || echo '$(srcdir)/'`demo/cat_buffer.c
-
-demo/demo_catbuffer-cat_buffer.obj: demo/cat_buffer.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_catbuffer_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_catbuffer-cat_buffer.obj -MD -MP -MF "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo" -c -o demo/demo_catbuffer-cat_buffer.obj `if test -f 'demo/cat_buffer.c'; then $(CYGPATH_W) 'demo/cat_buffer.c'; else $(CYGPATH_W) '$(srcdir)/demo/cat_buffer.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo" "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Po"; else rm -f "demo/$(DEPDIR)/demo_catbuffer-cat_buffer.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/cat_buffer.c' object='demo/demo_catbuffer-cat_buffer.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_catbuffer_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_catbuffer-cat_buffer.obj `if test -f 'demo/cat_buffer.c'; then $(CYGPATH_W) 'demo/cat_buffer.c'; else $(CYGPATH_W) '$(srcdir)/demo/cat_buffer.c'; fi`
-
-demo/demo_ecma119tree-ecma119_tree.o: demo/ecma119_tree.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_ecma119tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_ecma119tree-ecma119_tree.o -MD -MP -MF "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo" -c -o demo/demo_ecma119tree-ecma119_tree.o `test -f 'demo/ecma119_tree.c' || echo '$(srcdir)/'`demo/ecma119_tree.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo" "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Po"; else rm -f "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/ecma119_tree.c' object='demo/demo_ecma119tree-ecma119_tree.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_ecma119tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_ecma119tree-ecma119_tree.o `test -f 'demo/ecma119_tree.c' || echo '$(srcdir)/'`demo/ecma119_tree.c
-
-demo/demo_ecma119tree-ecma119_tree.obj: demo/ecma119_tree.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_ecma119tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_ecma119tree-ecma119_tree.obj -MD -MP -MF "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo" -c -o demo/demo_ecma119tree-ecma119_tree.obj `if test -f 'demo/ecma119_tree.c'; then $(CYGPATH_W) 'demo/ecma119_tree.c'; else $(CYGPATH_W) '$(srcdir)/demo/ecma119_tree.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo" "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Po"; else rm -f "demo/$(DEPDIR)/demo_ecma119tree-ecma119_tree.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/ecma119_tree.c' object='demo/demo_ecma119tree-ecma119_tree.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_ecma119tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_ecma119tree-ecma119_tree.obj `if test -f 'demo/ecma119_tree.c'; then $(CYGPATH_W) 'demo/ecma119_tree.c'; else $(CYGPATH_W) '$(srcdir)/demo/ecma119_tree.c'; fi`
-
-demo/demo_find-find.o: demo/find.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_find_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_find-find.o -MD -MP -MF "demo/$(DEPDIR)/demo_find-find.Tpo" -c -o demo/demo_find-find.o `test -f 'demo/find.c' || echo '$(srcdir)/'`demo/find.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_find-find.Tpo" "demo/$(DEPDIR)/demo_find-find.Po"; else rm -f "demo/$(DEPDIR)/demo_find-find.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/find.c' object='demo/demo_find-find.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_find_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_find-find.o `test -f 'demo/find.c' || echo '$(srcdir)/'`demo/find.c
-
-demo/demo_find-find.obj: demo/find.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_find_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_find-find.obj -MD -MP -MF "demo/$(DEPDIR)/demo_find-find.Tpo" -c -o demo/demo_find-find.obj `if test -f 'demo/find.c'; then $(CYGPATH_W) 'demo/find.c'; else $(CYGPATH_W) '$(srcdir)/demo/find.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_find-find.Tpo" "demo/$(DEPDIR)/demo_find-find.Po"; else rm -f "demo/$(DEPDIR)/demo_find-find.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/find.c' object='demo/demo_find-find.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_find_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_find-find.obj `if test -f 'demo/find.c'; then $(CYGPATH_W) 'demo/find.c'; else $(CYGPATH_W) '$(srcdir)/demo/find.c'; fi`
-
-demo/demo_iso-iso.o: demo/iso.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_iso_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_iso-iso.o -MD -MP -MF "demo/$(DEPDIR)/demo_iso-iso.Tpo" -c -o demo/demo_iso-iso.o `test -f 'demo/iso.c' || echo '$(srcdir)/'`demo/iso.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_iso-iso.Tpo" "demo/$(DEPDIR)/demo_iso-iso.Po"; else rm -f "demo/$(DEPDIR)/demo_iso-iso.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso.c' object='demo/demo_iso-iso.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_iso_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_iso-iso.o `test -f 'demo/iso.c' || echo '$(srcdir)/'`demo/iso.c
-
-demo/demo_iso-iso.obj: demo/iso.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_iso_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_iso-iso.obj -MD -MP -MF "demo/$(DEPDIR)/demo_iso-iso.Tpo" -c -o demo/demo_iso-iso.obj `if test -f 'demo/iso.c'; then $(CYGPATH_W) 'demo/iso.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_iso-iso.Tpo" "demo/$(DEPDIR)/demo_iso-iso.Po"; else rm -f "demo/$(DEPDIR)/demo_iso-iso.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso.c' object='demo/demo_iso-iso.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_iso_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_iso-iso.obj `if test -f 'demo/iso.c'; then $(CYGPATH_W) 'demo/iso.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso.c'; fi`
-
-demo/demo_isocat-iso_cat.o: demo/iso_cat.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isocat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isocat-iso_cat.o -MD -MP -MF "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo" -c -o demo/demo_isocat-iso_cat.o `test -f 'demo/iso_cat.c' || echo '$(srcdir)/'`demo/iso_cat.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo" "demo/$(DEPDIR)/demo_isocat-iso_cat.Po"; else rm -f "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_cat.c' object='demo/demo_isocat-iso_cat.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isocat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isocat-iso_cat.o `test -f 'demo/iso_cat.c' || echo '$(srcdir)/'`demo/iso_cat.c
-
-demo/demo_isocat-iso_cat.obj: demo/iso_cat.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isocat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isocat-iso_cat.obj -MD -MP -MF "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo" -c -o demo/demo_isocat-iso_cat.obj `if test -f 'demo/iso_cat.c'; then $(CYGPATH_W) 'demo/iso_cat.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_cat.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo" "demo/$(DEPDIR)/demo_isocat-iso_cat.Po"; else rm -f "demo/$(DEPDIR)/demo_isocat-iso_cat.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_cat.c' object='demo/demo_isocat-iso_cat.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isocat_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isocat-iso_cat.obj `if test -f 'demo/iso_cat.c'; then $(CYGPATH_W) 'demo/iso_cat.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_cat.c'; fi`
-
-demo/demo_isomodify-iso_modify.o: demo/iso_modify.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isomodify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isomodify-iso_modify.o -MD -MP -MF "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo" -c -o demo/demo_isomodify-iso_modify.o `test -f 'demo/iso_modify.c' || echo '$(srcdir)/'`demo/iso_modify.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo" "demo/$(DEPDIR)/demo_isomodify-iso_modify.Po"; else rm -f "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_modify.c' object='demo/demo_isomodify-iso_modify.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isomodify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isomodify-iso_modify.o `test -f 'demo/iso_modify.c' || echo '$(srcdir)/'`demo/iso_modify.c
-
-demo/demo_isomodify-iso_modify.obj: demo/iso_modify.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isomodify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isomodify-iso_modify.obj -MD -MP -MF "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo" -c -o demo/demo_isomodify-iso_modify.obj `if test -f 'demo/iso_modify.c'; then $(CYGPATH_W) 'demo/iso_modify.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_modify.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo" "demo/$(DEPDIR)/demo_isomodify-iso_modify.Po"; else rm -f "demo/$(DEPDIR)/demo_isomodify-iso_modify.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_modify.c' object='demo/demo_isomodify-iso_modify.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isomodify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isomodify-iso_modify.obj `if test -f 'demo/iso_modify.c'; then $(CYGPATH_W) 'demo/iso_modify.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_modify.c'; fi`
-
-demo/demo_isoms-iso_ms.o: demo/iso_ms.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoms_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isoms-iso_ms.o -MD -MP -MF "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo" -c -o demo/demo_isoms-iso_ms.o `test -f 'demo/iso_ms.c' || echo '$(srcdir)/'`demo/iso_ms.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo" "demo/$(DEPDIR)/demo_isoms-iso_ms.Po"; else rm -f "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_ms.c' object='demo/demo_isoms-iso_ms.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoms_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isoms-iso_ms.o `test -f 'demo/iso_ms.c' || echo '$(srcdir)/'`demo/iso_ms.c
-
-demo/demo_isoms-iso_ms.obj: demo/iso_ms.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoms_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isoms-iso_ms.obj -MD -MP -MF "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo" -c -o demo/demo_isoms-iso_ms.obj `if test -f 'demo/iso_ms.c'; then $(CYGPATH_W) 'demo/iso_ms.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_ms.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo" "demo/$(DEPDIR)/demo_isoms-iso_ms.Po"; else rm -f "demo/$(DEPDIR)/demo_isoms-iso_ms.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_ms.c' object='demo/demo_isoms-iso_ms.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoms_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isoms-iso_ms.obj `if test -f 'demo/iso_ms.c'; then $(CYGPATH_W) 'demo/iso_ms.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_ms.c'; fi`
-
-demo/demo_isoread-iso_read.o: demo/iso_read.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoread_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isoread-iso_read.o -MD -MP -MF "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo" -c -o demo/demo_isoread-iso_read.o `test -f 'demo/iso_read.c' || echo '$(srcdir)/'`demo/iso_read.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo" "demo/$(DEPDIR)/demo_isoread-iso_read.Po"; else rm -f "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_read.c' object='demo/demo_isoread-iso_read.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoread_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isoread-iso_read.o `test -f 'demo/iso_read.c' || echo '$(srcdir)/'`demo/iso_read.c
-
-demo/demo_isoread-iso_read.obj: demo/iso_read.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoread_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_isoread-iso_read.obj -MD -MP -MF "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo" -c -o demo/demo_isoread-iso_read.obj `if test -f 'demo/iso_read.c'; then $(CYGPATH_W) 'demo/iso_read.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_read.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo" "demo/$(DEPDIR)/demo_isoread-iso_read.Po"; else rm -f "demo/$(DEPDIR)/demo_isoread-iso_read.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/iso_read.c' object='demo/demo_isoread-iso_read.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_isoread_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_isoread-iso_read.obj `if test -f 'demo/iso_read.c'; then $(CYGPATH_W) 'demo/iso_read.c'; else $(CYGPATH_W) '$(srcdir)/demo/iso_read.c'; fi`
-
-demo/demo_lsl-lsl.o: demo/lsl.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_lsl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_lsl-lsl.o -MD -MP -MF "demo/$(DEPDIR)/demo_lsl-lsl.Tpo" -c -o demo/demo_lsl-lsl.o `test -f 'demo/lsl.c' || echo '$(srcdir)/'`demo/lsl.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_lsl-lsl.Tpo" "demo/$(DEPDIR)/demo_lsl-lsl.Po"; else rm -f "demo/$(DEPDIR)/demo_lsl-lsl.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/lsl.c' object='demo/demo_lsl-lsl.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_lsl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_lsl-lsl.o `test -f 'demo/lsl.c' || echo '$(srcdir)/'`demo/lsl.c
-
-demo/demo_lsl-lsl.obj: demo/lsl.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_lsl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_lsl-lsl.obj -MD -MP -MF "demo/$(DEPDIR)/demo_lsl-lsl.Tpo" -c -o demo/demo_lsl-lsl.obj `if test -f 'demo/lsl.c'; then $(CYGPATH_W) 'demo/lsl.c'; else $(CYGPATH_W) '$(srcdir)/demo/lsl.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_lsl-lsl.Tpo" "demo/$(DEPDIR)/demo_lsl-lsl.Po"; else rm -f "demo/$(DEPDIR)/demo_lsl-lsl.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/lsl.c' object='demo/demo_lsl-lsl.obj' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_lsl_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_lsl-lsl.obj `if test -f 'demo/lsl.c'; then $(CYGPATH_W) 'demo/lsl.c'; else $(CYGPATH_W) '$(srcdir)/demo/lsl.c'; fi`
-
-demo/demo_tree-tree.o: demo/tree.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_tree-tree.o -MD -MP -MF "demo/$(DEPDIR)/demo_tree-tree.Tpo" -c -o demo/demo_tree-tree.o `test -f 'demo/tree.c' || echo '$(srcdir)/'`demo/tree.c; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_tree-tree.Tpo" "demo/$(DEPDIR)/demo_tree-tree.Po"; else rm -f "demo/$(DEPDIR)/demo_tree-tree.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/tree.c' object='demo/demo_tree-tree.o' libtool=no @AMDEPBACKSLASH@
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_tree-tree.o `test -f 'demo/tree.c' || echo '$(srcdir)/'`demo/tree.c
-
-demo/demo_tree-tree.obj: demo/tree.c
- at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_tree-tree.obj -MD -MP -MF "demo/$(DEPDIR)/demo_tree-tree.Tpo" -c -o demo/demo_tree-tree.obj `if test -f 'demo/tree.c'; then $(CYGPATH_W) 'demo/tree.c'; else $(CYGPATH_W) '$(srcdir)/demo/tree.c'; fi`; \
- at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_tree-tree.Tpo" "demo/$(DEPDIR)/demo_tree-tree.Po"; else rm -f "demo/$(DEPDIR)/demo_tree-tree.Tpo"; exit 1; fi
- at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/tree.c' object='demo/demo_tree-tree.obj' libtool=no @AMDEPBACKSLASH@
+libisofs/libisofs_libisofs_la-md5.lo: libisofs/md5.c
+ at am__fastdepCC_TRUE@	if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -MT libisofs/libisofs_libisofs_la-md5.lo -MD -MP -MF "libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Tpo" -c -o libisofs/libisofs_libisofs_la-md5.lo `test -f 'libisofs/md5.c' || echo '$(srcdir)/'`libisofs/md5.c; \
+ at am__fastdepCC_TRUE@	then mv -f "libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Tpo" "libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Plo"; else rm -f "libisofs/$(DEPDIR)/libisofs_libisofs_la-md5.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='libisofs/md5.c' object='libisofs/libisofs_libisofs_la-md5.lo' libtool=yes @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libisofs_libisofs_la_CFLAGS) $(CFLAGS) -c -o libisofs/libisofs_libisofs_la-md5.lo `test -f 'libisofs/md5.c' || echo '$(srcdir)/'`libisofs/md5.c
+
+demo/demo_demo-demo.o: demo/demo.c
+ at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_demo-demo.o -MD -MP -MF "demo/$(DEPDIR)/demo_demo-demo.Tpo" -c -o demo/demo_demo-demo.o `test -f 'demo/demo.c' || echo '$(srcdir)/'`demo/demo.c; \
+ at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_demo-demo.Tpo" "demo/$(DEPDIR)/demo_demo-demo.Po"; else rm -f "demo/$(DEPDIR)/demo_demo-demo.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/demo.c' object='demo/demo_demo-demo.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_demo-demo.o `test -f 'demo/demo.c' || echo '$(srcdir)/'`demo/demo.c
+
+demo/demo_demo-demo.obj: demo/demo.c
+ at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT demo/demo_demo-demo.obj -MD -MP -MF "demo/$(DEPDIR)/demo_demo-demo.Tpo" -c -o demo/demo_demo-demo.obj `if test -f 'demo/demo.c'; then $(CYGPATH_W) 'demo/demo.c'; else $(CYGPATH_W) '$(srcdir)/demo/demo.c'; fi`; \
+ at am__fastdepCC_TRUE@	then mv -f "demo/$(DEPDIR)/demo_demo-demo.Tpo" "demo/$(DEPDIR)/demo_demo-demo.Po"; else rm -f "demo/$(DEPDIR)/demo_demo-demo.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='demo/demo.c' object='demo/demo_demo-demo.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_tree_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_tree-tree.obj `if test -f 'demo/tree.c'; then $(CYGPATH_W) 'demo/tree.c'; else $(CYGPATH_W) '$(srcdir)/demo/tree.c'; fi`
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(demo_demo_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o demo/demo_demo-demo.obj `if test -f 'demo/demo.c'; then $(CYGPATH_W) 'demo/demo.c'; else $(CYGPATH_W) '$(srcdir)/demo/demo.c'; fi`
 
 mostlyclean-libtool:
 	-rm -f *.lo
@@ -1403,7 +1204,7 @@
 	    || exit 1; \
 	  fi; \
 	done
-	-find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+	-find $(distdir) -type d ! -perm -755 -exec chmod u+rwx,go+rx {} \; -o \
 	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
 	  ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
--- README
+++ README
@@ -4,15 +4,49 @@
 
 Released under GPL (see COPYING file for details).
 
-Copyright (C) 2008 Vreixo Formoso, Mario Danic, Thomas Schmitt
+Copyright (C) 2008 - 2010 Vreixo Formoso, Mario Danic, Thomas Schmitt
 
 libisofs is part of the libburnia project (libburnia-project.org)
 ------------------------------------------------------------------------------
 
-libisofs is a library to create an ISO-9660 filesystem, and supports extensions
-like RockRidge or Joliet. It is also a full featured ISO-9660 editor, allowing 
-you to modify an ISO image or multisession disc, including file addition and 
-removal, change of file names and attributes, etc
+                        Download, Build and Installation
+
+libisofs code is mantained in a Bazaar repository at Launchpad 
+(https://launchpad.net/libisofs/). You can download it with:
+
+$ bzr branch lp:libisofs
+
+Our build system is based on autotools. For preparing the build you will need 
+autotools of at least version 1.7. If you have download the code from the
+repository, first of all you need to execute
+
+   ./autogen.sh
+   
+on toplevel dir to execute autotools.
+
+Alternatively you may unpack a release tarball for which you do not need
+autotools installed.
+
+To build libisofs it should be sufficient to go into its toplevel directory 
+and execute
+
+   ./configure --prefix=/usr
+   make
+
+To make the libraries accessible for running resp. developing applications 
+   make install
+
+See INSTALL file for further details.
+
+
+------------------------------------------------------------------------------
+
+libisofs is a library to create an ISO-9660 filesystem, supports extensions
+like RockRidge or Joliet, and introduces an own extension AAIP.
+It is a full featured ISO-9660 editor which composes and changes the directory
+tree of an ISO image. This tree and its newly imported data file contents get
+then written as independent single-session image or as add-on session for the
+image from where the tree was originally loaded.
 
 Features:
 ---------
@@ -20,32 +54,54 @@
 - Image creation
 	- Creates ISO-9660 images from local files.
 	- Support for RockRidge and Joliet extensions.
-	- Support for ISO-9660:1999 (version 2)
-	- Support for El-Torito bootable images.
-	- Full featured edition of file names and attributes on the image.
-	- Several options to relax ISO-9660 constraints.
-	- Special options for images intended for distribution (suitable default
-	  modes for files, hiding of real timestamps...)
-- Multisession
-	- Support for growing an existing image
+	- Support for ISO-9660:1999 (version 2).
+	- Support for El-Torito bootable images. Tested are: PC-BIOS and EFI.
+	- Support for multi-extent data files up to 400 GB (level 3).
 	- Full-featured edition of the image files, including: addition of new
 	  files, removing of existent files, moving files, renaming files,
 	  change file attributes (permissions, timestamps...)
-	- Support for "emulated multisession" or image growing, suitable for non
-	  multisession media such as DVD+RW
+	- Optional recording per file of non-ISO 9660 features:
+	  ACL, xattr, content MD5, hard link relations.
+	  They do not hamper image readability by operating systems but can be
+	  retrieved only via libisofs.
+	- Optional zisofs compression, gzip compression, external filter
+	  processes.
+	- Several options to relax ISO-9660 constraints.
+	- Special options for images intended for distribution (suitable
+	  default modes for files, hiding of real timestamps...).
+- Image reading
+	- Image tree and data heap can be verified by stream reading and
+	  eventually recorded MD5 tags.
+	- Directory tree and file attributes of ISO 9660 session get loaded
+	  into memory for editing or for extraction into local filesystem.
+	- File content can be read by applications.
+	- Automatic zisofs decompression.
+	- Optional application of gzip decompression or external filter
+	  processes.
+	- Eventually recorded MD5 of data file can be obtained, MD5 of data
+	  stream can be computed and compared.
+	- Helper functions for restoring ACL and/or xattr to the local
+	  filesystem.
+- Multisession
+	- Support for growing an existing image on multi-session media.
+	- Support for "emulated multisession" on overwriteable media such as
+	  DVD+RW, USB sticks, regular files.
+	- Support for blindly prepared add-on sessions (mkisofs style -M -C)
+	  suitable for pipes which lead to an external burn program.
 - Image modification
-	- It can create a completely new image from files on another image.
-	- Full-featured edition of image contents
+	- Creates a completely new image from files out of another image and
+	  eventual editing operations. Suitable for any target medium.
 - Others
-	- Handling of different input and output charset
+	- Handling of different input and output charset.
 	- Good integration with libburn for image burning.
 	- Reliable, good handling of different kind of errors.
 
 Requirements:
 -------------
 
-- libburn 0.4.2 headers must be installed at compile time. It is not required
-  at runtime.
+- iconv() functions for character set conversion must be available.
+  Either implicitely as in Linux or by a separate library like libiconv
+  on FreeBSD.
   
 Know bugs:
 ----------
@@ -55,13 +111,12 @@
 a) Images with unsupported features, such as:
 	- UDF.
 	- HSF/HFS+ or other Mac extensions.
-	- El-Torito with multiple entries.
-	- ECMA-119 with extended attributes, multiple extends per file.
+	- ECMA-119 Extended attributes.
 	- Non El-Torito boot info.
-	- zisofs compressed images.
 	- ...
    In all these cases, the resulting new image (or new session) could lack some
-   features of the original image.
+   features of the original image. Nevertheless, the ECMA-119 System Area with
+   an eventual Master Boot Record gets preserved by default.
    In some cases libisofs will issue warning messages, or even refuse to grow
    or modify the image. Others remain undetected. Images created with libisofs
    do not have this problems.
@@ -71,16 +126,19 @@
    cases it is recommended to add boot info again in the new session.
    
     - isolinux images won't be bootable after a modify. This is because 
-      isolinux images need to have hardcoded the root dir lba. libisofs cannot 
-      know whether an image is an isolinux image or not, so the user is 
-      responsible to tell libisofs that it must patch the image, with the
-      el_torito_patch_isolinux_image() function. This problem could also exists
-      on other boot images.
-	- Most boot images are highly dependent of the image contents, so if the 
-	  user moves or removes some files on image it is possible they won't boot 
-	  anymore.
-	- There is no safer way to modify hidden boot images, as the size of the 
-	  boot image can't be figured out.
+      isolinux images need to have hardcoded the root dir lba in their boot
+      information table.
+      libisofs makes an educated guess at load time whether a boot image
+      contains such a table. Its outcome can be inquired by call
+      el_torito_seems_boot_info_table().
+      If one knows to have isolinux or GRUB El-Totito-bootable images, or if
+      a boot information table seems to exist, it is advised to apply the
+      el_torito_patch_isolinux_image() function.
+      Most boot images are highly dependent of the image contents, so if the 
+      user moves or removes some files on image it is possible they won't boot 
+      anymore.
+    - There is no safe way to modify hidden boot images, as the size of the 
+      boot image can't be figured out.
 
 c) Generated images could have different ECMA-119 low level names, due to 
    different way to mangle names, to new files added that force old files to 
@@ -93,208 +151,9 @@
 
 ------------------------------------------------------------------------------
 
-                        Download, Build and Installation
-
-libisofs code is mantained in a Bazaar repository at Launchpad 
-(https://launchpad.net/libisofs/). You can download it with:
-
-$ bzr branch lp:libisofs
-
-Our build system is based on autotools. For preparing the build you will need 
-autotools of at least version 1.7. If you have download the code from the
-repository, first of all you need to execute
-
-   ./autogen.sh
-   
-on toplevel dir to execute autotools.
-
-Alternatively you may unpack a release tarball for which you do not need
-autotools installed.
-
-To build libisofs it should be sufficient to go into its toplevel directory 
-and execute
-
-   ./configure --prefix=/usr
-   make
-
-To make the libraries accessible for running resp. developing applications 
-   make install
-
-See INSTALL file for further details.
-
-
-------------------------------------------------------------------------------
-
-                        Overview of libburnia-project.org
-
-libburnia-project.org is an open-source software project for reading, mastering
-and writing optical discs.
-For now this means only CD media and all single layer DVD media except DVD+R.
-
-The project comprises of several more or less interdependent parts which
-together strive to be a usable foundation for application development.
-These are libraries, language bindings, and middleware binaries which emulate
-classical (and valuable) Linux tools.
-
-Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems
-we would need : login on a development machine resp. a live OS on CD or DVD,
-advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
-volunteers for testing of realistic use cases.
-
-We have a workable code base for burning CD and most single layer DVD.
-The burn API is quite comprehensively documented and can be used to build a
-presentable application.
-We have a functional binary which emulates parts of cdrecord in order to
-prove that usability, and in order to allow you to explore libburnia's scope
-by help of existing cdrecord frontends.
-
-The project components (list subject to growth, hopefully):
-
-- libburn  is the library by which preformatted data get onto optical media.
-           It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
-           /dev/hdX (e.g. on kernel 2.6).
-           libburn is the foundation of our cdrecord emulation. Its code is
-           independent of cdrecord. Its DVD capabilities are learned from
-           studying the code of dvd+rw-tools and MMC-5 specs. No code but only
-           the pure SCSI knowledge has been taken from dvd+rw-tools, though.
-
-- libisofs is the library to pack up hard disk files and directories into a
-           ISO 9660 disk image. This may then be brought to media via libburn.
-           libisofs is to be the foundation of our upcoming mkisofs emulation.
-
-- cdrskin  is a limited cdrecord compatibility wrapper for libburn.
-           Cdrecord is a powerful GPL'ed burn program included in Joerg
-           Schilling's cdrtools. cdrskin strives to be a second source for
-           the services traditionally provided by cdrecord. Additionally it
-           provides libburn's DVD capabilities, where only -sao is compatible
-           with cdrecord.
-           cdrskin does not contain any bytes copied from cdrecord's sources.
-           Many bytes have been copied from the message output of cdrecord
-           runs, though.
-           See cdrskin/README and man cdrskin/cdrskin.1 for more.
-
-- test     is a collection of application gestures and examples given by the
-           authors of the library features. The main API example for libburn
-           is test/libburner.c .
-           Explore these examples if you look for inspiration.
-
-We plan to be a responsive upstream. Bear with us. We are still practicing.
-
-
-------------------------------------------------------------------------------
-Project history as far as known to me:
-
-- Founded in 2002 as it seems. See mailing list archives
-     http://lists.freedesktop.org/archives/libburn/
-  The site of this founder team is reachable and offers download of a
-  (somewhat outdated) tarball and from CVS :
-     http://icculus.org/burn/
-  Copyright holders and most probably founders:
-  Derek Foreman and Ben Jansens.
-
-- I came to using libburn in 2005. Founded the cdrskin project and submitted
-  necessary patches which were accepted or implemented better. Except one
-  remaining patch which prevented cdrskin from using vanilla libburn from CVS.
-  The cdrskin project site is reachable and offers download of the heavily
-  patched (elsewise outdated) tarball under the name  cdrskin-0.1.2  :
-     http://scdbackup.sourceforge.net/cdrskin_eng.html
-  It has meanwhile moved to use vanilla libburn.pykix.org , though.
-  Version 0.1.4 constitutes the first release of this kind.
-
-- In July 2006 our team mate Mario Danic announced a revival of libburn
-  which by about nearly everybody else was perceived as unfriendly fork.
-  Derek Foreman four days later posted a message which expressed his
-  discontent.
-  The situation first caused me to publically regret it and then - after i
-  got the opportunity to move in with cdrskin - gave me true reason to
-  personally apologize to Derek Foreman, Ben Jansens and the contibutors at 
-  icculus.org/burn. Posted to both projects:
-    http://lists.freedesktop.org/archives/libburn/2006-August/000446.html
-    http://mailman-mail1.webfaction.com/pipermail/libburn-hackers/2006-August/000024.html
-
-- Mid August 2006 project cdrskin established a branch office in 
-  libburn.pykix.org so that all maintainers of our tools have one single place
-  to get the current (at least slightely) usable coordinated versions of
-  everything.
-  Project cdrskin will live forth independendly for a while but it is committed
-  to stay in sync with libburn.pykix.org (or some successor, if ever).
-  cdrskin is also committed to support  icculus.org/burn  if the pending fork
-  is made reality by content changes in that project. It will cease to maintain
-  a patched version of  icculus.org/burn  though. Precondition for a new
-  release of cdrskin on base of  icculus.org/burn  would be the pending
-  "whitelist patch" therefore.
-  I would rather prefer if both projects find consense and merge, or at least
-  cooperate. I have not given up hope totally, yet.
-  I, personally, will honor any approach.
-
-- 2nd September 2006 the decision is made to strive for a consolidation of
-  copyright and a commitment to GPL in a reasonable and open minded way.
-  This is to avoid long term problems with code of unknown origin and
-  with finding consense among the not so clearly defined group of copyright
-  claimers and -holders.
-  libisofs is already claimed sole copyright Mario Danic.
-  cdrskin and libburner are already claimed sole copyright Thomas Schmitt.
-  Rewrites of other components will follow and concluded by claiming full
-  copyright within the group of libburn.pykix.org-copyright holders.
-
-- 16th September 2006 feature freeze for release of libburn-0.2.2 .
-
-- 20th September 2006 release of libburn-0.2.2 .
-
-- 26th October 2006 feature freeze for cdrskin-0.2.4 based on libburn-0.2.3 .
-  This version of cdrskin is much more cdrecord compatible in repect
-  to drive addressing and audio features.
-
-- 30th October 2006 release of cdrskin-0.2.4 .
-
-- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
-
-- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has
-  become suitable for unaware frontends as long as they perform only the core 
-  of cdrecord use cases (including open-ended input streams, audio, and
-  multi-session).
-
-- 28th November 2006 the umbrella project which encloses both, libisofs and
-  libburn, is now called libburnia. For the origin of this name, see 
-  http://en.wikipedia.org/wiki/Liburnians .
-
-- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
-  is widened to a first class of DVD media: overwriteable single layer types
-  DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
-  by dvd+rw-tools' "poor man" writing facility for this class of media.
-  Taking a bow towards Andy Polyakov.
-
-- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
-  multi-session and with DAO.
-
-- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer
-  DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
-  yet.
-
-- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
-  people that one should not use /dev/sg on kernel 2.6.
-
-- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
-  We look back on improved stability, a substantially extended list of media
-  and write modes, and better protection against typical user mishaps.
-
-- 24th October 2007 version 0.4.0 is the foundation of new library libisoburn
-  and an upcomming integrated application for manipulating and writing
-  ISO 9660 + Rock Ridge images. cdrskin-0.4.0 got capabilities like growisofs
-  by these enhancements: growing of overwriteable media and disk files.
-  Taking again a bow towards Andy Polyakov.
-
-- 26th Januar 2008 version 0.4.2 rectifies the version numbering so that we
-  reliably release libburn.so.4 as should have been done since libburn-0.3.2.
-  cdrskin now is by default linked dynamically and does a runtime check
-  to ensure not to be started with a libburn which is older than itself.
-
-
-------------------------------------------------------------------------------
-
     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. To be exact: version 2 of that License.
+    it under the terms of the GNU General Public License version 2 or later
+    as published by the Free Software Foundation.
 
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -309,19 +168,19 @@
 Clarification in my name and in the name of Mario Danic, upcoming copyright
 holders on toplevel of libburnia. To be fully in effect after the remaining
 other copyrighted code has been replaced by ours and by copyright-free
-contributions of our friends:
+contributions of our friends.
+
+Note:
+In the particular case of libisofs there is no foreign copyright involved.
+As of 2010 foreign copyright is only in component libburn.
 ------------------------------------------------------------------------------
 
-We, the copyright holders, agree on the interpretation that
-dynamical linking of our libraries constitutes "use of" and
-not "derivation from" our work in the sense of GPL, provided
-those libraries are compiled from our unaltered code.
-
-Thus you may link our libraries dynamically with applications
-which are not under GPL. You may distribute our libraries and
-application tools in binary form, if you fulfill the usual
-condition of GPL to offer a copy of the source code -altered
-or unaltered- under GPL.
+We will not raise any legal protest to dynamic linking of our libraries
+with applications that are not under GPL, as long as they fulfill
+the condition of offering the library source code used, whether
+altered or unaltered, under the GPLv2+, along with the application.
+Nevertheless, the safest legal position is not to link libburn with
+non-GPL compatible programs.
 
 We ask you politely to use our work in open source spirit
 and with the due reference to the entire open source community.
@@ -335,7 +194,10 @@
 decisive and you will have to prove that you exhausted all own
 means to qualify for GPL.
 
-For now we are firmly committed to maintain one single license: GPL.
+We are firmly committed to allow GPLv2+ now and with future releases.
+
+Signed: Mario Danic, Thomas Schmitt
+Agreement joined later by: Vreixo Formoso
 
-signed: Mario Danic, Thomas Schmitt
+Public contact: <libburn-hackers at pykix.org>
 
--- acinclude.m4
+++ acinclude.m4
@@ -1,3 +1,14 @@
+AC_DEFUN([LIBBURNIA_SET_FLAGS],
+[
+case $target_os in
+freebsd*)
+        LDFLAGS="$LDFLAGS -L/usr/local/lib"
+        CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+        ;;
+esac
+])
+
+
 AC_DEFUN([TARGET_SHIZZLE],
 [
   ARCH=""
@@ -13,6 +24,8 @@
     *-*-freebsd*)
       ARCH=freebsd
       LIBBURN_ARCH_LIBS=-lcam
+
+      # This may later be overridden by configure --enable-libdir-pkgconfig
       LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
       ;;
     *)
@@ -24,3 +37,147 @@
 
   AC_MSG_RESULT([$ARCH])
 ])
+
+
+dnl LIBBURNIA_CHECK_ICONV is by Thomas Schmitt, libburnia project
+dnl It is based on gestures from:
+dnl iconv.m4 serial AM7 (gettext-0.18)
+dnl Copyright (C) 2000-2002, 2007-2009 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl From Bruno Haible.
+dnl
+AC_DEFUN([LIBBURNIA_CHECK_ICONV],
+[
+
+  dnl Check whether it is allowed to link with -liconv
+  AC_MSG_CHECKING([for iconv() in separate -liconv ])
+  libburnia_liconv="no"
+  libburnia_save_LIBS="$LIBS"
+  LIBS="$LIBS -liconv"
+  AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+    [iconv_t cd = iconv_open("","");
+     iconv(cd,NULL,NULL,NULL,NULL);
+     iconv_close(cd);],
+     [libburnia_liconv="yes"],
+     [LIBS="$libburnia_save_LIBS"]
+  )
+  AC_MSG_RESULT([$libburnia_liconv])
+
+  if test x"$libburnia_save_LIBS" = x"$LIBS"
+  then
+    dnl GNU iconv has no function iconv() but libiconv() and a macro iconv()
+    dnl It is not tested whether this is detected by above macro.
+    AC_CHECK_LIB(iconv, libiconv, , )
+  fi
+
+  dnl Check for iconv(..., const char **inbuf, ...)
+  AC_MSG_CHECKING([for const qualifier with iconv() ])
+  AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+], [], [libburnia_iconv_const=""], [libburnia_iconv_const="const"]
+  )
+  AC_DEFINE_UNQUOTED([ICONV_CONST], [$libburnia_iconv_const])
+  test -z "$libburnia_iconv_const" && libburnia_iconv_const="no"
+  AC_MSG_RESULT([$libburnia_iconv_const])
+])
+
+
+dnl LIBBURNIA_ASSERT_ICONV is by Thomas Schmitt, libburnia project
+dnl 
+AC_DEFUN([LIBBURNIA_ASSERT_ICONV],
+[
+  if test x$LIBISOFS_ASSUME_ICONV = x
+  then
+    dnl Check for the essential gestures of libisofs/util.c
+    AC_MSG_CHECKING([for iconv() to be accessible now ])
+    AC_TRY_LINK([
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <limits.h>
+#include <iconv.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <unistd.h>],
+[iconv_t cd = iconv_open("","");
+iconv(cd,NULL,NULL,NULL,NULL);
+iconv_close(cd);
+], [iconv_test="yes"], [iconv_test="no"]
+    )
+    AC_MSG_RESULT([$iconv_test])
+    if test x$iconv_test = xno
+    then
+      echo >&2
+      echo "Cannot get function iconv() to work. Configuration aborted." >&2
+      echo "Check whether your system needs a separate libiconv installed." >&2
+      echo "If it is installed but not found, try something like" >&2
+      echo '  export LDFLAGS="$LDFLAGS -L/usr/local/lib"' >&2 
+      echo '  export CPPFLAGS="$CPPFLAGS -I/usr/local/include"' >&2
+      echo '  export LIBS="$LIBS -liconv"' >&2
+      echo "You may override this test by exporting variable" >&2
+      echo "  LIBISOFS_ASSUME_ICONV=yes" >&2
+      echo >&2
+      (exit 1); exit 1;
+    fi
+  fi
+])
+
+
+dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file.
+dnl Important: Must be performed _after_ TARGET_SHIZZLE
+dnl
+AC_DEFUN([LIBBURNIA_SET_PKGCONFIG],
+[
+### for testing --enable-libdir-pkgconfig on Linux
+### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
+
+if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
+then
+  dummy=dummy
+else
+  AC_ARG_ENABLE(libdir-pkgconfig,
+  [  --enable-libdir-pkgconfig  Install to $libdir/pkgconfig on any OS, default=no],
+   , enable_libdir_pkgconfig="no")
+  AC_MSG_CHECKING([for --enable-libdir-pkgconfig])
+  if test "x$enable_libdir_pkgconfig" = xyes
+  then
+    LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
+  fi
+  AC_MSG_RESULT([$enable_libdir_pkgconfig])
+fi
+
+libburnia_pkgconfig_override="no"
+AC_ARG_ENABLE(pkgconfig-path,
+[  --enable-pkgconfig-path=DIR  Absolute path of directory for libisofs-*.pc],
+libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none")
+AC_MSG_CHECKING([for overridden pkgconfig directory path])
+if test "x$enable_pkgconfig_path" = xno
+then
+  libburnia_pkgconfig_override="no"
+fi
+if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
+then
+  libburnia_pkgconfig_override="invalid argument"
+fi
+if test "x$libburnia_pkgconfig_override" = xyes
+then
+  LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
+  AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR])
+else
+  AC_MSG_RESULT([$libburnia_pkgconfig_override])
+fi
+AC_SUBST(LIBBURNIA_PKGCONFDIR)
+
+dnl For debugging only
+### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
+ 
+])
+
--- configure
+++ configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.60 for libisofs 0.6.20.
+# Generated by GNU Autoconf 2.60 for libisofs 0.6.32.
 #
 # Report bugs to <http://libburnia-project.org>.
 #
@@ -713,8 +713,8 @@
 # Identity of this package.
 PACKAGE_NAME='libisofs'
 PACKAGE_TARNAME='libisofs'
-PACKAGE_VERSION='0.6.20'
-PACKAGE_STRING='libisofs 0.6.20'
+PACKAGE_VERSION='0.6.32'
+PACKAGE_STRING='libisofs 0.6.32'
 PACKAGE_BUGREPORT='http://libburnia-project.org'
 
 ac_default_prefix=/usr/local
@@ -873,8 +873,8 @@
 LIBTOOL_DEPS
 THREAD_LIBS
 ARCH
-LIBBURNIA_PKGCONFDIR
 LIBBURN_ARCH_LIBS
+LIBBURNIA_PKGCONFDIR
 LIBACL_DEF
 XATTR_DEF
 ZLIB_DEF
@@ -1397,7 +1397,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libisofs 0.6.20 to adapt to many kinds of systems.
+\`configure' configures libisofs 0.6.32 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1468,7 +1468,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libisofs 0.6.20:";;
+     short | recursive ) echo "Configuration of libisofs 0.6.32:";;
    esac
   cat <<\_ACEOF
 
@@ -1485,11 +1485,13 @@
   --enable-fast-install[=PKGS]
                           optimize for fast installation [default=yes]
   --disable-libtool-lock  avoid locking (might break parallel builds)
-  --enable-debug          Disable aggressive optimizations default=yes
-  --enable-verbose-debug          Enable verbose debug messages default=no
-  --enable-libacl    Enable use of libacl by libisofs, default=yes
-  --enable-xattr     Enable use of xattr by libisofs, default=yes
-  --enable-zlib     Enable use of zlib by libisofs, default=yes
+  --enable-debug          Disable aggressive optimizations, default=yes
+  --enable-verbose-debug  Enable verbose debug messages, default=no
+  --enable-libdir-pkgconfig  Install to $libdir/pkgconfig on any OS, default=no
+  --enable-pkgconfig-path=DIR  Absolute path of directory for libisofs-*.pc
+  --enable-libacl         Enable use of libacl by libisofs, default=yes
+  --enable-xattr          Enable use of xattr by libisofs, default=yes
+  --enable-zlib           Enable use of zlib by libisofs, default=yes
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1577,7 +1579,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libisofs configure 0.6.20
+libisofs configure 0.6.32
 generated by GNU Autoconf 2.60
 
 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1591,7 +1593,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libisofs $as_me 0.6.20, which was
+It was created by libisofs $as_me 0.6.32, which was
 generated by GNU Autoconf 2.60.  Invocation command line was
 
   $ $0 $@
@@ -2104,6 +2106,15 @@
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
 
+
+case $target_os in
+freebsd*)
+        LDFLAGS="$LDFLAGS -L/usr/local/lib"
+        CPPFLAGS="$CPPFLAGS -I/usr/local/include"
+        ;;
+esac
+
+
 am__api_version="1.9"
 # Find a good install program.  We prefer a C program (faster),
 # so one script is as good as another.  But avoid the broken or
@@ -2390,7 +2401,7 @@
 
 # Define the identity of the package.
  PACKAGE='libisofs'
- VERSION='0.6.20'
+ VERSION='0.6.32'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2540,7 +2551,7 @@
 
 LIBISOFS_MAJOR_VERSION=0
 LIBISOFS_MINOR_VERSION=6
-LIBISOFS_MICRO_VERSION=20
+LIBISOFS_MICRO_VERSION=32
 LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
 
 
@@ -2549,11 +2560,11 @@
 
 
 LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
-# 2009.05.30  development jump has not yet happened
-# SONAME = 22 - 16 = 6 . Library name = libisofs.6.16.0
-LT_CURRENT=22
+# 2010.05.03  development jump has not yet happened
+# SONAME = 34 - 28 = 6 . Library name = libisofs.6.28.0
+LT_CURRENT=34
+LT_AGE=28
 LT_REVISION=0
-LT_AGE=16
 LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
 
 
@@ -5853,9 +5864,84 @@
 fi
 
 
-{ echo "$as_me:$LINENO: checking for iconv in -liconv" >&5
-echo $ECHO_N "checking for iconv in -liconv... $ECHO_C" >&6; }
-if test "${ac_cv_lib_iconv_iconv+set}" = set; then
+
+    { echo "$as_me:$LINENO: checking for iconv() in separate -liconv " >&5
+echo $ECHO_N "checking for iconv() in separate -liconv ... $ECHO_C" >&6; }
+  libburnia_liconv="no"
+  libburnia_save_LIBS="$LIBS"
+  LIBS="$LIBS -liconv"
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <iconv.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+     iconv(cd,NULL,NULL,NULL,NULL);
+     iconv_close(cd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libburnia_liconv="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	LIBS="$libburnia_save_LIBS"
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+  { echo "$as_me:$LINENO: result: $libburnia_liconv" >&5
+echo "${ECHO_T}$libburnia_liconv" >&6; }
+
+  if test x"$libburnia_save_LIBS" = x"$LIBS"
+  then
+
+{ echo "$as_me:$LINENO: checking for libiconv in -liconv" >&5
+echo $ECHO_N "checking for libiconv in -liconv... $ECHO_C" >&6; }
+if test "${ac_cv_lib_iconv_libiconv+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -5873,11 +5959,11 @@
 #ifdef __cplusplus
 extern "C"
 #endif
-char iconv ();
+char libiconv ();
 int
 main ()
 {
-return iconv ();
+return libiconv ();
   ;
   return 0;
 }
@@ -5916,21 +6002,21 @@
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_iconv_iconv=yes
+  ac_cv_lib_iconv_libiconv=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-	ac_cv_lib_iconv_iconv=no
+	ac_cv_lib_iconv_libiconv=no
 fi
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_iconv" >&5
-echo "${ECHO_T}$ac_cv_lib_iconv_iconv" >&6; }
-if test $ac_cv_lib_iconv_iconv = yes; then
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_libiconv" >&5
+echo "${ECHO_T}$ac_cv_lib_iconv_libiconv" >&6; }
+if test $ac_cv_lib_iconv_libiconv = yes; then
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBICONV 1
 _ACEOF
@@ -5939,6 +6025,180 @@
 
 fi
 
+  fi
+
+    { echo "$as_me:$LINENO: checking for const qualifier with iconv() " >&5
+echo $ECHO_N "checking for const qualifier with iconv() ... $ECHO_C" >&6; }
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <iconv.h>
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libburnia_iconv_const=""
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	libburnia_iconv_const="const"
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  cat >>confdefs.h <<_ACEOF
+#define ICONV_CONST $libburnia_iconv_const
+_ACEOF
+
+  test -z "$libburnia_iconv_const" && libburnia_iconv_const="no"
+  { echo "$as_me:$LINENO: result: $libburnia_iconv_const" >&5
+echo "${ECHO_T}$libburnia_iconv_const" >&6; }
+
+
+
+  if test x$LIBISOFS_ASSUME_ICONV = x
+  then
+        { echo "$as_me:$LINENO: checking for iconv() to be accessible now " >&5
+echo $ECHO_N "checking for iconv() to be accessible now ... $ECHO_C" >&6; }
+    cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <limits.h>
+#include <iconv.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <unistd.h>
+int
+main ()
+{
+iconv_t cd = iconv_open("","");
+iconv(cd,NULL,NULL,NULL,NULL);
+iconv_close(cd);
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  iconv_test="yes"
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	iconv_test="no"
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+    { echo "$as_me:$LINENO: result: $iconv_test" >&5
+echo "${ECHO_T}$iconv_test" >&6; }
+    if test x$iconv_test = xno
+    then
+      echo >&2
+      echo "Cannot get function iconv() to work. Configuration aborted." >&2
+      echo "Check whether your system needs a separate libiconv installed." >&2
+      echo "If it is installed but not found, try something like" >&2
+      echo '  export LDFLAGS="$LDFLAGS -L/usr/local/lib"' >&2
+      echo '  export CPPFLAGS="$CPPFLAGS -I/usr/local/include"' >&2
+      echo '  export LIBS="$LIBS -liconv"' >&2
+      echo "You may override this test by exporting variable" >&2
+      echo "  LIBISOFS_ASSUME_ICONV=yes" >&2
+      echo >&2
+      (exit 1); exit 1;
+    fi
+  fi
+
+
 
 # Check whether --enable-shared was given.
 if test "${enable_shared+set}" = set; then
@@ -6490,7 +6750,7 @@
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6493 "configure"' > conftest.$ac_ext
+  echo '#line 6753 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -8918,11 +9178,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8921: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9181: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8925: \$? = $ac_status" >&5
+   echo "$as_me:9185: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9186,11 +9446,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9189: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9449: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:9193: \$? = $ac_status" >&5
+   echo "$as_me:9453: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -9290,11 +9550,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:9293: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:9553: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:9297: \$? = $ac_status" >&5
+   echo "$as_me:9557: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -11742,7 +12002,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 11745 "configure"
+#line 12005 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11842,7 +12102,7 @@
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 11845 "configure"
+#line 12105 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14210,11 +14470,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14213: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14473: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14217: \$? = $ac_status" >&5
+   echo "$as_me:14477: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -14314,11 +14574,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14317: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14577: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14321: \$? = $ac_status" >&5
+   echo "$as_me:14581: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -15884,11 +16144,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15887: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16147: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15891: \$? = $ac_status" >&5
+   echo "$as_me:16151: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -15988,11 +16248,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15991: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16251: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15995: \$? = $ac_status" >&5
+   echo "$as_me:16255: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -18218,11 +18478,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:18221: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:18481: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:18225: \$? = $ac_status" >&5
+   echo "$as_me:18485: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -18486,11 +18746,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:18489: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:18749: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:18493: \$? = $ac_status" >&5
+   echo "$as_me:18753: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -18590,11 +18850,11 @@
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:18593: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:18853: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:18597: \$? = $ac_status" >&5
+   echo "$as_me:18857: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -21858,6 +22118,8 @@
     *-*-freebsd*)
       ARCH=freebsd
       LIBBURN_ARCH_LIBS=-lcam
+
+      # This may later be overridden by configure --enable-libdir-pkgconfig
       LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
       ;;
     *)
@@ -21874,7 +22136,6 @@
 
 
 
-
 # Check whether --enable-debug was given.
 if test "${enable_debug+set}" = set; then
   enableval=$enable_debug;
@@ -21905,6 +22166,66 @@
 
 
 
+
+### for testing --enable-libdir-pkgconfig on Linux
+### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
+
+if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
+then
+  dummy=dummy
+else
+  # Check whether --enable-libdir-pkgconfig was given.
+if test "${enable_libdir_pkgconfig+set}" = set; then
+  enableval=$enable_libdir_pkgconfig;
+else
+  enable_libdir_pkgconfig="no"
+fi
+
+  { echo "$as_me:$LINENO: checking for --enable-libdir-pkgconfig" >&5
+echo $ECHO_N "checking for --enable-libdir-pkgconfig... $ECHO_C" >&6; }
+  if test "x$enable_libdir_pkgconfig" = xyes
+  then
+    LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
+  fi
+  { echo "$as_me:$LINENO: result: $enable_libdir_pkgconfig" >&5
+echo "${ECHO_T}$enable_libdir_pkgconfig" >&6; }
+fi
+
+libburnia_pkgconfig_override="no"
+# Check whether --enable-pkgconfig-path was given.
+if test "${enable_pkgconfig_path+set}" = set; then
+  enableval=$enable_pkgconfig_path; libburnia_pkgconfig_override="yes"
+else
+  enable_pkgconfig_path="none"
+fi
+
+{ echo "$as_me:$LINENO: checking for overridden pkgconfig directory path" >&5
+echo $ECHO_N "checking for overridden pkgconfig directory path... $ECHO_C" >&6; }
+if test "x$enable_pkgconfig_path" = xno
+then
+  libburnia_pkgconfig_override="no"
+fi
+if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
+then
+  libburnia_pkgconfig_override="invalid argument"
+fi
+if test "x$libburnia_pkgconfig_override" = xyes
+then
+  LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
+  { echo "$as_me:$LINENO: result: $LIBBURNIA_PKGCONFDIR" >&5
+echo "${ECHO_T}$LIBBURNIA_PKGCONFDIR" >&6; }
+else
+  { echo "$as_me:$LINENO: result: $libburnia_pkgconfig_override" >&5
+echo "${ECHO_T}$libburnia_pkgconfig_override" >&6; }
+fi
+
+
+### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
+
+
+
+
+
 # Check whether --enable-libacl was given.
 if test "${enable_libacl+set}" = set; then
   enableval=$enable_libacl;
@@ -21912,7 +22233,7 @@
   enable_libacl=yes
 fi
 
-if test x$enable_libacl = xyes; then
+if test "x$enable_libacl" = xyes; then
     LIBACL_DEF="-DLibisofs_with_aaip_acL"
     if test "${ac_cv_header_sys_acl_h+set}" = set; then
   { echo "$as_me:$LINENO: checking for sys/acl.h" >&5
@@ -22176,7 +22497,7 @@
   enable_xattr=yes
 fi
 
-if test x$enable_xattr = xyes; then
+if test "x$enable_xattr" = xyes; then
     XATTR_DEF="-DLibisofs_with_aaip_xattR"
     if test "${ac_cv_header_attr_xattr_h+set}" = set; then
   { echo "$as_me:$LINENO: checking for attr/xattr.h" >&5
@@ -22434,7 +22755,7 @@
   enable_zlib=yes
 fi
 
-if test x$enable_zlib = xyes; then
+if test "x$enable_zlib" = xyes; then
     ZLIB_DEF="-DLibisofs_with_zliB"
     if test "${ac_cv_header_zlib_h+set}" = set; then
   { echo "$as_me:$LINENO: checking for zlib.h" >&5
@@ -22592,9 +22913,9 @@
 fi
 if test $ac_cv_header_zlib_h = yes; then
 
-{ echo "$as_me:$LINENO: checking for compress2 in -lz" >&5
-echo $ECHO_N "checking for compress2 in -lz... $ECHO_C" >&6; }
-if test "${ac_cv_lib_z_compress2+set}" = set; then
+{ echo "$as_me:$LINENO: checking for compressBound in -lz" >&5
+echo $ECHO_N "checking for compressBound in -lz... $ECHO_C" >&6; }
+if test "${ac_cv_lib_z_compressBound+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
@@ -22612,11 +22933,11 @@
 #ifdef __cplusplus
 extern "C"
 #endif
-char compress2 ();
+char compressBound ();
 int
 main ()
 {
-return compress2 ();
+return compressBound ();
   ;
   return 0;
 }
@@ -22655,21 +22976,21 @@
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_lib_z_compress2=yes
+  ac_cv_lib_z_compressBound=yes
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
-	ac_cv_lib_z_compress2=no
+	ac_cv_lib_z_compressBound=no
 fi
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5
-echo "${ECHO_T}$ac_cv_lib_z_compress2" >&6; }
-if test $ac_cv_lib_z_compress2 = yes; then
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_compressBound" >&5
+echo "${ECHO_T}$ac_cv_lib_z_compressBound" >&6; }
+if test $ac_cv_lib_z_compressBound = yes; then
   cat >>confdefs.h <<_ACEOF
 #define HAVE_LIBZ 1
 _ACEOF
@@ -23134,7 +23455,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libisofs $as_me 0.6.20, which was
+This file was extended by libisofs $as_me 0.6.32, which was
 generated by GNU Autoconf 2.60.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -23181,7 +23502,7 @@
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-libisofs config.status 0.6.20
+libisofs config.status 0.6.32
 configured by $0, generated by GNU Autoconf 2.60,
   with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -23511,8 +23832,8 @@
 LIBTOOL_DEPS!$LIBTOOL_DEPS$ac_delim
 THREAD_LIBS!$THREAD_LIBS$ac_delim
 ARCH!$ARCH$ac_delim
-LIBBURNIA_PKGCONFDIR!$LIBBURNIA_PKGCONFDIR$ac_delim
 LIBBURN_ARCH_LIBS!$LIBBURN_ARCH_LIBS$ac_delim
+LIBBURNIA_PKGCONFDIR!$LIBBURNIA_PKGCONFDIR$ac_delim
 LIBACL_DEF!$LIBACL_DEF$ac_delim
 XATTR_DEF!$XATTR_DEF$ac_delim
 ZLIB_DEF!$ZLIB_DEF$ac_delim
--- configure.ac
+++ configure.ac
@@ -1,10 +1,12 @@
-AC_INIT([libisofs], [0.6.20], [http://libburnia-project.org])
+AC_INIT([libisofs], [0.6.32], [http://libburnia-project.org])
 AC_PREREQ([2.50])
 dnl AC_CONFIG_HEADER([config.h])	
 
 AC_CANONICAL_HOST
 AC_CANONICAL_TARGET
 
+LIBBURNIA_SET_FLAGS
+
 AM_INIT_AUTOMAKE([subdir-objects])
 
 dnl A61101 This breaks Linux build (makes 32 bit off_t)
@@ -37,14 +39,14 @@
 dnl library. This means LIBISOFS_*_VERSION kept its second job which does not  
 dnl comply to the usual ways of configure.ac . I.e. now *officially* this is 
 dnl the source code release version as announced to the public. It has no 
-dnl conection to SONAME or libtool version numbering.
+dnl connection to SONAME or libtool version numbering.
 dnl It rather feeds the API function iso_lib_version().
 dnl
 dnl If LIBISOFS_*_VERSION changes, be sure to change AC_INIT above to match.
 dnl
 LIBISOFS_MAJOR_VERSION=0
 LIBISOFS_MINOR_VERSION=6
-LIBISOFS_MICRO_VERSION=20
+LIBISOFS_MICRO_VERSION=32
 LIBISOFS_VERSION=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION.$LIBISOFS_MICRO_VERSION
 
 AC_SUBST(LIBISOFS_MAJOR_VERSION)
@@ -54,11 +56,11 @@
 
 dnl Libtool versioning
 LT_RELEASE=$LIBISOFS_MAJOR_VERSION.$LIBISOFS_MINOR_VERSION
-# 2009.05.30  development jump has not yet happened
-# SONAME = 22 - 16 = 6 . Library name = libisofs.6.16.0
-LT_CURRENT=22
+# 2010.05.03  development jump has not yet happened
+# SONAME = 34 - 28 = 6 . Library name = libisofs.6.28.0
+LT_CURRENT=34
+LT_AGE=28
 LT_REVISION=0
-LT_AGE=16
 LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
 
 AC_SUBST(LT_RELEASE)
@@ -87,7 +89,11 @@
 
 dnl If iconv(3) is in an extra lib, then it gets added to variable LIBS.
 dnl If not, then no -liconv will be added.
-AC_CHECK_LIB(iconv, iconv, , )
+LIBBURNIA_CHECK_ICONV
+
+dnl To abort configuration if iconv() still cannot be compiled
+LIBBURNIA_ASSERT_ICONV
+
 
 AC_PROG_LIBTOOL
 AC_SUBST(LIBTOOL_DEPS)
@@ -124,14 +130,12 @@
 
 TARGET_SHIZZLE
 AC_SUBST(ARCH)
-AC_SUBST(LIBBURNIA_PKGCONFDIR)
 AC_SUBST(LIBBURN_ARCH_LIBS)
 
-dnl Add compiler-specific flags
 
 dnl See if the user wants aggressive optimizations of the code
 AC_ARG_ENABLE(debug,
-[  --enable-debug          Disable aggressive optimizations [default=yes]],
+[  --enable-debug          Disable aggressive optimizations, default=yes],
               , enable_debug=yes)
 if test x$enable_debug != xyes; then
     if test x$GCC = xyes; then
@@ -148,15 +152,22 @@
 
 dnl Verbose debug to make libisofs issue more debug messages
 AC_ARG_ENABLE(verbose-debug,
-[  --enable-verbose-debug          Enable verbose debug messages [default=no]],
+[  --enable-verbose-debug  Enable verbose debug messages, default=no],
 	AC_DEFINE(LIBISOFS_VERBOSE_DEBUG, 1))
 
 
-dnl ts A90123
+dnl Determine target directory for libisofs-*.pc
+dnl Important: Must be performed _after_ TARGET_SHIZZLE
+dnl
+LIBBURNIA_SET_PKGCONFIG
+
+
+dnl Add compiler-specific flags
+
 AC_ARG_ENABLE(libacl,
-[  --enable-libacl    Enable use of libacl by libisofs, default=yes],
+[  --enable-libacl         Enable use of libacl by libisofs, default=yes],
                , enable_libacl=yes)
-if test x$enable_libacl = xyes; then
+if test "x$enable_libacl" = xyes; then
 dnl Check whether there is libacl-devel and libacl-runtime.
 dnl If not, erase this macro which would enable use of acl_to_text and others
     LIBACL_DEF="-DLibisofs_with_aaip_acL"
@@ -170,9 +181,9 @@
 
 dnl ts A90123
 AC_ARG_ENABLE(xattr,
-[  --enable-xattr     Enable use of xattr by libisofs, default=yes],
+[  --enable-xattr          Enable use of xattr by libisofs, default=yes],
                , enable_xattr=yes)
-if test x$enable_xattr = xyes; then
+if test "x$enable_xattr" = xyes; then
 dnl Check whether there is the header for Linux xattr. 
 dnl If not, erase this macro which would enable use of listxattr and others
     XATTR_DEF="-DLibisofs_with_aaip_xattR"
@@ -185,14 +196,16 @@
 
 dnl ts A90409
 AC_ARG_ENABLE(zlib,
-[  --enable-zlib     Enable use of zlib by libisofs, default=yes],
+[  --enable-zlib           Enable use of zlib by libisofs, default=yes],
                , enable_zlib=yes)
-if test x$enable_zlib = xyes; then
+if test "x$enable_zlib" = xyes; then
 dnl Check whether there is the header for zlib. 
 dnl If not, erase this macro which would enable use of compress2() and others.
-dnl The empty parameter after "compress2" causes -lz.
+dnl Linking fails on SuSE 9.0 because zlib has compress2() but lacks  
+dnl compressBound(). So compressBound is the more modern thing to test.
+dnl The empty parameter after "compressBound" causes -lz.
     ZLIB_DEF="-DLibisofs_with_zliB"
-    AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, compress2, , ZLIB_DEF= ), ZLIB_DEF= )
+    AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, compressBound, , ZLIB_DEF= ), ZLIB_DEF= )
 else
     ZLIB_DEF=
 fi
--- demo/cat.c
+++ demo/cat.c
-/*
- * Copyright (c) 2007 Vreixo Formoso
- * 
- * This file is part of the libisofs project; 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. See COPYING file for details.
- */
-
-#include "libisofs.h"
-#include "fsource.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
- * Little test program to test filesystem implementations.
- * Outputs file contents to stdout!
- */
-
-int main(int argc, char **argv)
-{
-    int res;
-    IsoFilesystem *fs;
-    IsoFileSource *file;
-    struct stat info;
-
-    if (argc != 2) {
-        fprintf(stderr, "Usage: cat /path/to/file\n");
-        return 1;
-    }
-
-    /* create filesystem object */
-    res = iso_local_filesystem_new(&fs);
-    if (res < 0) {
-        fprintf(stderr, "Can't get local fs object, err = %d\n", res);
-        return 1;
-    }
-
-    res = fs->get_by_path(fs, argv[1], &file);
-    if (res < 0) {
-        fprintf(stderr, "Can't get file, err = %d\n", res);
-        return 1;
-    }
-
-    res = iso_file_source_lstat(file, &info);
-    if (res < 0) {
-        fprintf(stderr, "Can't stat file, err = %d\n", res);
-        return 1;
-    }
-
-    if (S_ISDIR(info.st_mode)) {
-        fprintf(stderr, "Path refers to a directory!!\n");
-        return 1;
-    } else {
-        char buf[1024];
-        res = iso_file_source_open(file);
-        if (res < 0) {
-            fprintf(stderr, "Can't open file, err = %d\n", res);
-            return 1;
-        }
-        while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
-            fwrite(buf, 1, res, stdout);
-        }
-        if (res < 0) {
-            fprintf(stderr, "Error reading, err = %d\n", res);
-            return 1;
-        }
-        iso_file_source_close(file);
-    }
-    
-    iso_file_source_unref(file);
-    iso_filesystem_unref(fs);
-    return 0;
-}
--- demo/cat_buffer.c
+++ demo/cat_buffer.c
-/*
- * Copyright (c) 2007 Vreixo Formoso
- * 
- * This file is part of the libisofs project; 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. See COPYING file for details.
- */
-
-#include "libisofs.h"
-#include "buffer.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-/*
- * Little test program that reads a file and outputs it to stdout, using
- * the libisofs ring buffer as intermediate memory
- */
-
-struct th_data
-{
-    IsoRingBuffer *rbuf;
-    char *path;
-};
-
-#define WRITE_CHUNK 2048
-#define READ_CHUNK  2048
-
-static
-void *write_function(void *arg)
-{
-    ssize_t bytes;
-    int res;
-    unsigned char tmp[WRITE_CHUNK];
-    struct th_data *data = (struct th_data *) arg;
-
-    int fd = open(data->path, O_RDONLY);
-    if (fd < 0) {
-        fprintf(stderr, "Writer thread error: Can't open file");
-        iso_ring_buffer_writer_close(data->rbuf, 1);
-        pthread_exit(NULL);
-    }
-
-    res = 1;
-    while ( (bytes = read(fd, tmp, WRITE_CHUNK)) > 0) {
-        res = iso_ring_buffer_write(data->rbuf, tmp, bytes);
-        if (res <= 0) {
-            break;
-        }
-        /* To test premature reader exit >>>>>>>>>>> 
-         iso_ring_buffer_writer_close(data->rbuf);
-         pthread_exit(NULL);
-         <<<<<<<<<<<<<<<<<<<<<<<<< */
-        //        if (rand() > 2000000000) {
-        //            fprintf(stderr, "Writer sleeping\n");
-        //            sleep(1);
-        //        }
-    }
-    fprintf(stderr, "Writer finish: %d\n", res);
-
-    close(fd);
-    iso_ring_buffer_writer_close(data->rbuf, 0);
-    pthread_exit(NULL);
-}
-
-static
-void *read_function(void *arg)
-{
-    unsigned char tmp[READ_CHUNK];
-    int res = 1;
-    struct th_data *data = (struct th_data *) arg;
-
-    while ( (res = iso_ring_buffer_read(data->rbuf, tmp, READ_CHUNK)) > 0) {
-        write(1, tmp, READ_CHUNK);
-        /* To test premature reader exit >>>>>>>>>>>
-         iso_ring_buffer_reader_close(data->rbuf);
-         pthread_exit(NULL);
-         <<<<<<<<<<<<<<<<<<<<<<<<< */
-        //        if (rand() > 2000000000) {
-        //            fprintf(stderr, "Reader sleeping\n");
-        //            sleep(1);
-        //        }
-    }
-    fprintf(stderr, "Reader finish: %d\n", res);
-
-    iso_ring_buffer_reader_close(data->rbuf, 0);
-
-    pthread_exit(NULL);
-}
-
-int main(int argc, char **argv)
-{
-    int res;
-    struct th_data data;
-    pthread_t reader;
-    pthread_t writer;
-
-    if (argc != 2) {
-        fprintf(stderr, "Usage: catbuffer /path/to/file\n");
-        return 1;
-    }
-
-    res = iso_ring_buffer_new(1024, &data.rbuf);
-    if (res < 0) {
-        fprintf(stderr, "Can't create buffer\n");
-        return 1;
-    }
-    data.path = argv[1];
-
-    res = pthread_create(&writer, NULL, write_function, (void *) &data);
-    res = pthread_create(&reader, NULL, read_function, (void *) &data);
-
-    pthread_join(writer, NULL);
-    pthread_join(reader, NULL);
-
-    fprintf(stderr, "Buffer was %d times full and %d times empty.\n",
-            iso_ring_buffer_get_times_full(data.rbuf),
-            iso_ring_buffer_get_times_empty(data.rbuf));
-
-    free(data.rbuf);
-    return 0;
-}
--- demo/demo.c
+++ demo/demo.c
+
+/*
+ * Copyright (c) 2007 - 2009 Vreixo Formoso, Thomas Schmitt
+ * 
+ * This file is part of the libisofs project; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
+ */
+
+static char helptext[][80] = {
+"",
+"This is a collection of libisofs gestures which formerly were distinct",
+"programs. The first argument chooses the gesture:",
+"  -tree  absolute_directory_path",
+"               Import a directory and print the resulting iso tree.",
+"  -find  absolute_directory_path",      
+"               Import a directory, find matching nodes and print the",
+"               resulting iso tree.",
+"  -iso  [options] directory output_file",
+"               Create an iso image from a local directory. For options see",
+"               output of -iso -h",
+"  -iso_read  image_file",
+"               Output the contents of an iso image.",
+"  -iso_cat  image_file path_in_image",
+"               Extract a file from a given ISO image and put out its content",
+"               to stdout. The file is addressed by path_in_image.",
+"  -iso_modify  image_file absolute_directory_path output_file",
+"               Load an iso image, add a directory, and write complete image.",
+"  -iso_ms  image_lba nwa image_file directory_path output_file",
+"               Load an iso image, add a directory, and write as add-on",
+"               session which shall be appended to the old image.",
+"               image_lba gives the block address of the start of the most",
+"               recent session in the image_file. nwa gives the block address",
+"               where the add-on session will be appended to the image.",
+"@"
+};
+
+
+#define LIBISOFS_WITHOUT_LIBBURN yes
+#include "libisofs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <err.h>
+#include <limits.h>
+
+
+
+#define LIBISOFS_WITHOUT_LIBBURN yes
+#include "libisofs.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
+/* ------------------------- from demo/tree.c ----------------------- */
+
+static void
+print_permissions(mode_t mode)
+{
+    char perm[10];
+    
+    /* TODO suid, sticky... */
+    
+    perm[9] = '\0';
+    perm[8] = mode & S_IXOTH ? 'x' : '-';
+    perm[7] = mode & S_IWOTH ? 'w' : '-';
+    perm[6] = mode & S_IROTH ? 'r' : '-';
+    perm[5] = mode & S_IXGRP ? 'x' : '-';
+    perm[4] = mode & S_IWGRP ? 'w' : '-';
+    perm[3] = mode & S_IRGRP ? 'r' : '-';
+    perm[2] = mode & S_IXUSR ? 'x' : '-';
+    perm[1] = mode & S_IWUSR ? 'w' : '-';
+    perm[0] = mode & S_IRUSR ? 'r' : '-';
+    printf("[%s]",perm);
+}
+
+static void 
+tree_print_dir(IsoDir *dir, int level) 
+{
+    int i;
+    IsoDirIter *iter;
+    IsoNode *node;
+    char *sp = alloca(level * 2 + 1);
+    
+    for (i = 0; i < level * 2; i += 2) {
+        sp[i] = '|';
+        sp[i+1] = ' ';
+    }
+    
+    sp[level * 2-1] = '-';
+    sp[level * 2] = '\0';
+    
+    iso_dir_get_children(dir, &iter);
+    while (iso_dir_iter_next(iter, &node) == 1) {
+        
+        if (ISO_NODE_IS_DIR(node)) {
+            printf("%s+[D] ", sp);
+            print_permissions(iso_node_get_permissions(node));
+            printf(" %s\n", iso_node_get_name(node));
+            tree_print_dir(ISO_DIR(node), level+1);
+        } else if (ISO_NODE_IS_FILE(node)) {
+            printf("%s-[F] ", sp);
+            print_permissions(iso_node_get_permissions(node));
+            printf(" %s\n", iso_node_get_name(node) );
+        } else if (ISO_NODE_IS_SYMLINK(node)) {
+            printf("%s-[L] ", sp);
+            print_permissions(iso_node_get_permissions(node));
+            printf(" %s -> %s \n", iso_node_get_name(node),
+                   iso_symlink_get_dest(ISO_SYMLINK(node)) );
+        } else {
+            printf("%s-[C] ", sp);
+            print_permissions(iso_node_get_permissions(node));
+            printf(" %s\n", iso_node_get_name(node) );
+        } 
+    }
+    iso_dir_iter_free(iter);
+}
+
+int gesture_tree(int argc, char **argv)
+{
+    int result;
+    IsoImage *image;
+    
+    if (argc != 2) {
+need_abs_path:;
+        fprintf (stderr, "You need to specify a valid absolute path\n");
+        return 1;
+    }
+    if (argv[1][0] != '/')
+        goto need_abs_path;
+
+    iso_init();
+    iso_set_msgs_severities("NEVER", "ALL", "");
+    
+    result = iso_image_new("volume_id", &image);
+    if (result < 0) {
+        printf ("Error creating image\n");
+        return 1;
+    }
+    
+    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
+    if (result < 0) {
+        printf ("Error adding directory %d\n", result);
+        return 1;
+    }
+    
+    printf("================= IMAGE =================\n");
+    tree_print_dir(iso_image_get_root(image), 0);
+    printf("\n\n");
+    
+    iso_image_unref(image);
+    iso_finish();
+    return 0;
+}
+
+
+/* ------------------------- from demo/find.c ----------------------- */
+
+static void 
+find_print_dir(IsoDir *dir) 
+{
+    IsoDirIter *iter;
+    IsoNode *node;
+    IsoFindCondition *cond, *c1, *c2;
+    
+    c1 = iso_new_find_conditions_name("*a*");
+    c2 = iso_new_find_conditions_mode(S_IFREG);
+    cond = iso_new_find_conditions_and(c1, c2);
+    iso_dir_find_children(dir, cond, &iter);
+    while (iso_dir_iter_next(iter, &node) == 1) {
+        char *path = iso_tree_get_node_path(node);
+        printf(" %s\n", path);
+        free(path);
+    }
+    iso_dir_iter_free(iter);
+}
+
+int gesture_find(int argc, char **argv)
+{
+    int result;
+    IsoImage *image;
+    
+    if (argc != 2) {
+need_abs_path:;
+        fprintf (stderr, "You need to specify a valid absolute path\n");
+        return 1;
+    }
+    if (argv[1][0] != '/')
+        goto need_abs_path;
+
+    iso_init();
+    iso_set_msgs_severities("NEVER", "ALL", "");
+    
+    result = iso_image_new("volume_id", &image);
+    if (result < 0) {
+        printf ("Error creating image\n");
+        return 1;
+    }
+    
+    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
+    if (result < 0) {
+        printf ("Error adding directory %d\n", result);
+        return 1;
+    }
+    
+    find_print_dir(iso_image_get_root(image));
+    
+    iso_image_unref(image);
+    iso_finish();
+    return 0;
+}
+
+
+/* ------------------------- from demo/iso.c ----------------------- */
+
+
+static const char * const optstring = "JRIL:b:hV:";
+extern char *optarg;
+extern int optind;
+
+void iso_usage(char **argv)
+{
+    printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]);
+}
+
+void iso_help()
+{
+    printf(
+        "Options:\n"
+        "  -J        Add Joliet support\n"
+        "  -R        Add Rock Ridge support\n"
+        "  -I        Add ISO 9660:1999 support\n"
+        "  -V label  Volume Label\n"
+        "  -L <num>  Set the ISO level (1 or 2)\n"
+        "  -b file   Specifies a boot image to add to image\n"
+        "  -h        Print this message\n"
+    );
+}
+
+int iso_callback(IsoFileSource *src)
+{
+    char *path = iso_file_source_get_path(src);
+    printf("CALLBACK: %s\n", path);
+    free(path);
+    return 1;
+}
+
+int gesture_iso(int argc, char **argv)
+{
+    int result;
+    int c;
+    IsoImage *image;
+    struct burn_source *burn_src;
+    unsigned char buf[2048];
+    FILE *fd;
+    IsoWriteOpts *opts;
+    char *volid = "VOLID";
+    char *boot_img = NULL;
+    int rr = 0, j = 0, iso1999 = 0, level = 1;
+
+    while ((c = getopt(argc, argv, optstring)) != -1) {
+        switch(c) {
+        case 'h':
+            iso_usage(argv);
+            iso_help();
+            exit(0);
+            break;
+        case 'J':
+            j = 1;
+            break;
+        case 'R':
+            rr = 1;
+            break;
+        case 'I':
+            iso1999 = 1;
+            break;
+        case 'L':
+            level = atoi(optarg);
+            break;
+        case 'b':
+            boot_img = optarg;
+            break;
+        case 'V':
+            volid = optarg;
+            break;
+        case '?':
+            iso_usage(argv);
+            exit(1);
+            break;
+        }
+    }
+
+    if (argc < 2) {
+        printf ("Please pass directory from which to build ISO\n");
+        iso_usage(argv);
+        return 1;
+    }
+    if (argc < 3) {
+        printf ("Please supply output file\n");
+        iso_usage(argv);
+        return 1;
+    }
+
+    fd = fopen(argv[optind+1], "w");
+    if (!fd) {
+        err(1, "error opening output file");
+    }
+
+    result = iso_init();
+    if (result < 0) {
+        printf ("Can't initialize libisofs\n");
+        return 1;
+    }
+    iso_set_msgs_severities("NEVER", "ALL", "");
+
+    result = iso_image_new(volid, &image);
+    if (result < 0) {
+        printf ("Error creating image\n");
+        return 1;
+    }
+    iso_tree_set_follow_symlinks(image, 0);
+    iso_tree_set_ignore_hidden(image, 0);
+    iso_tree_set_ignore_special(image, 0);
+    iso_set_abort_severity("SORRY");
+    /*iso_tree_set_report_callback(image, callback);*/
+
+    result = iso_tree_add_dir_rec(image, iso_image_get_root(image),
+                                  argv[optind]);
+    if (result < 0) {
+        printf ("Error adding directory %d\n", result);
+        return 1;
+    }
+
+    if (boot_img) {
+        /* adds El-Torito boot info. Tunned for isolinux */
+        ElToritoBootImage *bootimg;
+        result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL,
+                                     "/isolinux/boot.cat", &bootimg);
+        if (result < 0) {
+            printf ("Error adding boot image %d\n", result);
+            return 1;
+        }
+        el_torito_set_load_size(bootimg, 4);
+        el_torito_patch_isolinux_image(bootimg);
+    }
+
+    result = iso_write_opts_new(&opts, 0);
+    if (result < 0) {
+        printf ("Cant create write opts, error %d\n", result);
+        return 1;
+    }
+    iso_write_opts_set_iso_level(opts, level);
+    iso_write_opts_set_rockridge(opts, rr);
+    iso_write_opts_set_joliet(opts, j);
+    iso_write_opts_set_iso1999(opts, iso1999);
+
+    result = iso_image_create_burn_source(image, opts, &burn_src);
+    if (result < 0) {
+        printf ("Cant create image, error %d\n", result);
+        return 1;
+    }
+
+    iso_write_opts_free(opts);
+
+    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
+        fwrite(buf, 1, 2048, fd);
+    }
+    fclose(fd);
+    burn_src->free_data(burn_src);
+    free(burn_src);
+
+    iso_image_unref(image);
+    iso_finish();
+    return 0;
+}
+
+
+/* ------------------------- from demo/iso_read.c ----------------------- */
+
+
+static void
+iso_read_print_type(mode_t mode)
+{
+    switch(mode & S_IFMT) {
+    case S_IFSOCK: printf("[S] "); break;
+    case S_IFLNK: printf("[L] "); break;
+    case S_IFREG: printf("[R] "); break;
+    case S_IFBLK: printf("[B] "); break;
+    case S_IFDIR: printf("[D] "); break;
+    case S_IFIFO: printf("[F] "); break;
+    }
+}
+
+static void
+iso_read_print_file_src(IsoFileSource *file)
+{
+    struct stat info;
+    char *name;
+    iso_file_source_lstat(file, &info);
+    iso_read_print_type(info.st_mode);
+    print_permissions(info.st_mode);
+    printf(" %10.f ", (double) info.st_size);
+    /* printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino); */
+    name = iso_file_source_get_name(file);
+    printf(" %s", name);
+    free(name);
+    if (S_ISLNK(info.st_mode)) {
+        char buf[PATH_MAX];
+        iso_file_source_readlink(file, buf, PATH_MAX);
+        printf(" -> %s\n", buf);
+    }
+    printf("\n");
+}
+
+static void
+iso_read_print_dir(IsoFileSource *dir, int level)
+{
+    int ret, i;
+    IsoFileSource *file;
+    struct stat info;
+    char *sp = alloca(level * 2 + 1);
+
+    for (i = 0; i < level * 2; i += 2) {
+        sp[i] = '|';
+        sp[i+1] = ' ';
+    }
+
+    sp[level * 2-1] = '-';
+    sp[level * 2] = '\0';
+
+    ret = iso_file_source_open(dir);
+    if (ret < 0) {
+        printf ("Can't open dir %d\n", ret);
+    }
+    while ((ret = iso_file_source_readdir(dir, &file)) == 1) {
+        printf("%s", sp);
+        iso_read_print_file_src(file);
+        ret = iso_file_source_lstat(file, &info);
+        if (ret < 0) {
+            break;
+        }
+        if (S_ISDIR(info.st_mode)) {
+            iso_read_print_dir(file, level + 1);
+        }
+        iso_file_source_unref(file);
+    }
+    iso_file_source_close(dir);
+    if (ret < 0) {
+        printf ("Can't print dir\n");
+    }
+}
+
+int gesture_iso_read(int argc, char **argv)
+{
+    int result;
+    IsoImageFilesystem *fs;
+    IsoDataSource *src;
+    IsoFileSource *root;
+    IsoReadOpts *ropts;
+
+    if (argc != 2) {
+        printf ("You need to specify a valid path\n");
+        return 1;
+    }
+
+    iso_init();
+    iso_set_msgs_severities("NEVER", "ALL", "");
+
+    result = iso_data_source_new_from_file(argv[1], &src);
+    if (result < 0) {
+        printf ("Error creating data source\n");
+        return 1;
+    }
+
+    result = iso_read_opts_new(&ropts, 0);
+    if (result < 0) {
+        fprintf(stderr, "Error creating read options\n");
+        return 1;
+    }
+    result = iso_image_filesystem_new(src, ropts, 1, &fs);
+    iso_read_opts_free(ropts);
+    if (result < 0) {
+        printf ("Error creating filesystem\n");
+        return 1;
+    }
+
+    printf("\nVOLUME INFORMATION\n");
+    printf("==================\n\n");
+
+    printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs));
+    printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs));
+    printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs));
+    printf("System: %s\n", iso_image_fs_get_system_id(fs));
+    printf("Application: %s\n", iso_image_fs_get_application_id(fs));
+    printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs));
+    printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs));
+    printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs));
+
+    printf("\nDIRECTORY TREE\n");
+    printf("==============\n");
+
+    result = fs->get_root(fs, &root);
+    if (result < 0) {
+        printf ("Can't get root %d\n", result);
+        return 1;
+    }
+    /* iso_read_print_file_src(root); */
+    iso_read_print_dir(root, 0);
+    iso_file_source_unref(root);
+
+    fs->close(fs);
+    iso_filesystem_unref((IsoFilesystem*)fs);
+    iso_data_source_unref(src);
+    iso_finish();
+    return 0;
+}
+
+
+/* ------------------------- from demo/iso_cat.c ----------------------- */
+
+
+int gesture_iso_cat(int argc, char **argv)
+{
+    int res;
+    IsoFilesystem *fs;
+    IsoFileSource *file;
+    struct stat info;
+    IsoDataSource *src;
+    IsoReadOpts *opts;
+
+    if (argc != 3) {
+        fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n");
+        return 1;
+    }
+
+    res = iso_init();
+    if (res < 0) {
+        fprintf(stderr, "Can't init libisofs\n");
+        return 1;
+    }
+    
+    res = iso_data_source_new_from_file(argv[1], &src);
+    if (res < 0) {
+        fprintf(stderr, "Error creating data source\n");
+        return 1;
+    }
+
+    res = iso_read_opts_new(&opts, 0);
+    if (res < 0) {
+        fprintf(stderr, "Error creating read options\n");
+        return 1;
+    }
+    res = iso_image_filesystem_new(src, opts, 1, &fs);
+    if (res < 0) {
+        fprintf(stderr, "Error creating filesystem\n");
+        return 1;
+    }
+    iso_read_opts_free(opts);
+
+    res = fs->get_by_path(fs, argv[2], &file);
+    if (res < 0) {
+        fprintf(stderr, "Can't get file, err = %d\n", res);
+        return 1;
+    }
+
+    res = iso_file_source_lstat(file, &info);
+    if (res < 0) {
+        fprintf(stderr, "Can't stat file, err = %d\n", res);
+        return 1;
+    }
+
+    if (S_ISDIR(info.st_mode)) {
+        fprintf(stderr, "Path refers to a directory!!\n");
+        return 1;
+    } else {
+        char buf[1024];
+        res = iso_file_source_open(file);
+        if (res < 0) {
+            fprintf(stderr, "Can't open file, err = %d\n", res);
+            return 1;
+        }
+        while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
+            fwrite(buf, 1, res, stdout);
+        }
+        if (res < 0) {
+            fprintf(stderr, "Error reading, err = %d\n", res);
+            return 1;
+        }
+        iso_file_source_close(file);
+    }
+    
+    iso_file_source_unref(file);
+    iso_filesystem_unref(fs);
+    iso_data_source_unref(src);
+    iso_finish();
+    return 0;
+}
+
+
+/* ------------------------- from demo/iso_modify.c ----------------------- */
+
+
+void iso_modify_usage(char **argv)
+{
+    printf("%s IMAGE DIRECTORY OUTPUT\n", argv[0]);
+}
+
+int gesture_iso_modify(int argc, char **argv)
+{
+    int result;
+    IsoImage *image;
+    IsoDataSource *src;
+    struct burn_source *burn_src;
+    unsigned char buf[2048];
+    FILE *fd;
+    IsoWriteOpts *opts;
+    IsoReadOpts *ropts;
+	
+    if (argc < 4) {
+        iso_modify_usage(argv);
+        return 1;
+    }
+    
+    fd = fopen(argv[3], "w");
+    if (!fd) {
+        err(1, "error opening output file");
+    }
+
+    iso_init();
+    iso_set_msgs_severities("NEVER", "ALL", "");
+    
+    /* create the data source to accesss previous image */
+    result = iso_data_source_new_from_file(argv[1], &src);
+    if (result < 0) {
+        printf ("Error creating data source\n");
+        return 1;
+    }
+    
+    /* create the image context */
+    result = iso_image_new("volume_id", &image);
+    if (result < 0) {
+        printf ("Error creating image\n");
+        return 1;
+    }
+    iso_tree_set_follow_symlinks(image, 0);
+    iso_tree_set_ignore_hidden(image, 0);
+    
+    /* import previous image */
+    result = iso_read_opts_new(&ropts, 0);
+    if (result < 0) {
+        fprintf(stderr, "Error creating read options\n");
+        return 1;
+    }
+    result = iso_image_import(image, src, ropts, NULL);
+    iso_read_opts_free(ropts);
+    iso_data_source_unref(src);
+    if (result < 0) {
+        printf ("Error importing previous session %d\n", result);
+        return 1;
+    }
+    
+    /* add new dir */
+    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
+    if (result < 0) {
+        printf ("Error adding directory %d\n", result);
+        return 1;
+    }
+    
+    /* generate a new image with both previous and added contents */
+    result = iso_write_opts_new(&opts, 1);
+    if (result < 0) {
+        printf("Cant create write opts, error %d\n", result);
+        return 1;
+    }
+    /* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */
+    
+    result = iso_image_create_burn_source(image, opts, &burn_src);
+    if (result < 0) {
+        printf ("Cant create image, error %d\n", result);
+        return 1;
+    }
+    
+    iso_write_opts_free(opts);
+    
+    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
+        fwrite(buf, 1, 2048, fd);
+    }
+    fclose(fd);
+    burn_src->free_data(burn_src);
+    free(burn_src);
+    
+    iso_image_unref(image);
+    iso_finish();
+	return 0;
+}
+
+
+/* ------------------------- from demo/iso_ms.c ----------------------- */
+
+
+void iso_ms_usage(char **argv)
+{
+    printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]);
+}
+
+int gesture_iso_ms(int argc, char **argv)
+{
+    int result;
+    IsoImage *image;
+    IsoDataSource *src;
+    struct burn_source *burn_src;
+    unsigned char buf[2048];
+    FILE *fd;
+    IsoWriteOpts *opts;
+    IsoReadOpts *ropts;
+    uint32_t ms_block;
+	
+    if (argc < 6) {
+        iso_ms_usage(argv);
+        return 1;
+    }
+
+    if (strcmp(argv[3], argv[5]) == 0) {
+        fprintf(stderr,
+                "image_file and output_file must not be the same file.\n");
+        return 1;
+    }
+
+    fd = fopen(argv[5], "w");
+    if (!fd) {
+        err(1, "error opening output file");
+    }
+
+    iso_init();
+    iso_set_msgs_severities("NEVER", "ALL", "");
+    
+    /* create the data source to accesss previous image */
+    result = iso_data_source_new_from_file(argv[3], &src);
+    if (result < 0) {
+        printf ("Error creating data source\n");
+        return 1;
+    }
+    
+    /* create the image context */
+    result = iso_image_new("volume_id", &image);
+    if (result < 0) {
+        printf ("Error creating image\n");
+        return 1;
+    }
+    iso_tree_set_follow_symlinks(image, 0);
+    iso_tree_set_ignore_hidden(image, 0);
+    
+    /* import previous image */
+    result = iso_read_opts_new(&ropts, 0);
+    if (result < 0) {
+        fprintf(stderr, "Error creating read options\n");
+        return 1;
+    }
+    iso_read_opts_set_start_block(ropts, atoi(argv[1]));
+    result = iso_image_import(image, src, ropts, NULL);
+    iso_read_opts_free(ropts);
+    iso_data_source_unref(src);
+    if (result < 0) {
+        printf ("Error importing previous session %d\n", result);
+        return 1;
+    }
+    
+    /* add new dir */
+    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]);
+    if (result < 0) {
+        printf ("Error adding directory %d\n", result);
+        return 1;
+    }
+    
+    /* generate a multisession image with new contents */
+    result = iso_write_opts_new(&opts, 1);
+    if (result < 0) {
+        printf("Cant create write opts, error %d\n", result);
+        return 1;
+    }
+    
+    /* round up to 32kb aligment = 16 block */
+    ms_block =  atoi(argv[2]);
+    iso_write_opts_set_ms_block(opts, ms_block);
+    iso_write_opts_set_appendable(opts, 1);
+
+    result = iso_image_create_burn_source(image, opts, &burn_src);
+    if (result < 0) {
+        printf ("Cant create image, error %d\n", result);
+        return 1;
+    }
+    iso_write_opts_free(opts);
+    
+    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
+        fwrite(buf, 1, 2048, fd);
+    }
+    fclose(fd);
+    burn_src->free_data(burn_src);
+    free(burn_src);
+    
+    iso_image_unref(image);
+    iso_finish();
+	return 0;
+}
+
+
+/* ------------------------- switcher ----------------------- */
+
+
+int main(int argc, char **argv)
+{
+    char *gesture;
+    int i;
+
+    if (argc < 2) {
+usage:;
+        fprintf(stderr, "usage: %s gesture [gesture_options]\n", argv[0]);
+        for (i = 0; helptext[i][0] != '@'; i++)
+             fprintf(stderr, "%s\n", helptext[i]);
+        exit(1);
+    }
+    for (gesture = argv[1]; *gesture == '-'; gesture++);
+    if (strcmp(gesture, "tree") == 0) {
+        gesture_tree(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "find") == 0) {
+        gesture_find(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "iso") == 0) {
+        gesture_iso(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "iso_read") == 0) {
+        gesture_iso_read(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "iso_cat") == 0) {
+        gesture_iso_cat(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "iso_modify") == 0) {
+        gesture_iso_modify(argc - 1, &(argv[1]));
+    } else if(strcmp(gesture, "iso_ms") == 0) {
+        gesture_iso_ms(argc - 1, &(argv[1]));
+    } else {
+        goto usage;
+    }
+    exit(0);
+}
--- demo/ecma119_tree.c
+++ demo/ecma119_tree.c
-/*
- * Little program that imports a directory to iso image, generates the
- * ecma119 low level tree and prints it.
- * Note that this is not an API example, but a little program for test
- * purposes.
- */
-
-#include "libisofs.h"
-#include "ecma119.h"
-#include "ecma119_tree.h"
-#include "util.h"
-#include "filesrc.h"
-#include "node.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void
-print_permissions(mode_t mode)
-{
-    char perm[10];
-
-    //TODO suid, sticky...
-
-    perm[9] = '\0';
-    perm[8] = mode & S_IXOTH ? 'x' : '-';
-    perm[7] = mode & S_IWOTH ? 'w' : '-';
-    perm[6] = mode & S_IROTH ? 'r' : '-';
-    perm[5] = mode & S_IXGRP ? 'x' : '-';
-    perm[4] = mode & S_IWGRP ? 'w' : '-';
-    perm[3] = mode & S_IRGRP ? 'r' : '-';
-    perm[2] = mode & S_IXUSR ? 'x' : '-';
-    perm[1] = mode & S_IWUSR ? 'w' : '-';
-    perm[0] = mode & S_IRUSR ? 'r' : '-';
-    printf("[%s]",perm);
-}
-
-static void
-print_dir(Ecma119Node *dir, int level)
-{
-    int i;
-    char *sp = alloca(level * 2 + 1);
-
-    for (i = 0; i < level * 2; i += 2) {
-        sp[i] = '|';
-        sp[i+1] = ' ';
-    }
-
-    sp[level * 2-1] = '-';
-    sp[level * 2] = '\0';
-
-    for (i = 0; i < dir->info.dir->nchildren; i++) {
-        Ecma119Node *child = dir->info.dir->children[i];
-
-        if (child->type == ECMA119_DIR) {
-            printf("%s+[D] ", sp);
-            print_permissions(iso_node_get_permissions(child->node));
-            printf(" %s\n", child->iso_name);
-            print_dir(child, level+1);
-        } else if (child->type == ECMA119_FILE) {
-            printf("%s-[F] ", sp);
-            print_permissions(iso_node_get_permissions(child->node));
-            printf(" %s {%p}\n", child->iso_name, (void*)child->info.file);
-        } else if (child->type == ECMA119_SYMLINK) {
-            printf("%s-[L] ", sp);
-            print_permissions(iso_node_get_permissions(child->node));
-            printf(" %s -> %s\n", child->iso_name,
-                   ((IsoSymlink*)child->node)->dest);
-        } else if (child->type == ECMA119_SPECIAL) {
-            printf("%s-[S] ", sp);
-            print_permissions(iso_node_get_permissions(child->node));
-            printf(" %s\n", child->iso_name);
-        } else if (child->type == ECMA119_PLACEHOLDER) {
-            printf("%s-[RD] ", sp);
-            print_permissions(iso_node_get_permissions(child->node));
-            printf(" %s\n", child->iso_name);
-        } else {
-            printf("%s-[????] ", sp);
-        }
-    }
-}
-
-int main(int argc, char **argv)
-{
-    int result;
-    IsoImage *image;
-    Ecma119Image *ecma119;
-
-    if (argc != 2) {
-        printf ("You need to specify a valid path\n");
-        return 1;
-    }
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-    result = iso_image_new("volume_id", &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-
-    ecma119 = calloc(1, sizeof(Ecma119Image));
-    iso_rbtree_new(iso_file_src_cmp, &(ecma119->files));
-    ecma119->iso_level = 1;
-    ecma119->rockridge = 1;
-    ecma119->image = image;
-    ecma119->input_charset = strdup("UTF-8");
-
-    /* create low level tree */
-    result = ecma119_tree_create(ecma119);
-    if (result < 0) {
-        printf ("Error creating ecma-119 tree: %d\n", result);
-        return 1;
-    }
-
-    printf("================= ECMA-119 TREE =================\n");
-    print_dir(ecma119->root, 0);
-    printf("\n\n");
-
-    ecma119_node_free(ecma119->root);
-    iso_rbtree_destroy(ecma119->files, iso_file_src_free);
-    free(ecma119->input_charset);
-    free(ecma119);
-    iso_image_unref(image);
-    iso_finish();
-    return 0;
-}
--- demo/find.c
+++ demo/find.c
-/*
- * Little program that import a directory, find matching nodes and prints the 
- * resulting iso tree.
- */
-
-#include "libisofs.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void 
-print_dir(IsoDir *dir) 
-{
-	IsoDirIter *iter;
-	IsoNode *node;
-	IsoFindCondition *cond, *c1, *c2;
-	
-	c1 = iso_new_find_conditions_name("*a*");
-    c2 = iso_new_find_conditions_mode(S_IFREG);
-    cond = iso_new_find_conditions_and(c1, c2);
-	iso_dir_find_children(dir, cond, &iter);
-	while (iso_dir_iter_next(iter, &node) == 1) {
-	    char *path = iso_tree_get_node_path(node);
-		printf(" %s\n", path);
-		free(path);
-	}
-	iso_dir_iter_free(iter);
-}
-
-int main(int argc, char **argv)
-{
-	int result;
-    IsoImage *image;
-	
-	if (argc != 2) {
-		printf ("You need to specify a valid path\n");
-		return 1;
-	}
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-    
-    result = iso_image_new("volume_id", &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-	
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-	
-	print_dir(iso_image_get_root(image));
-	
-    iso_image_unref(image);
-    iso_finish();
-    return 0;
-}
--- demo/iso.c
+++ demo/iso.c
-/*
- * Little program to show how to create an iso image from a local
- * directory.
- */
-
-#define LIBISOFS_WITHOUT_LIBBURN yes
-#include "libisofs.h"
-
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <err.h>
-
-const char * const optstring = "JRIL:b:hV:";
-extern char *optarg;
-extern int optind;
-
-void usage(char **argv)
-{
-    printf("%s [OPTIONS] DIRECTORY OUTPUT\n", argv[0]);
-}
-
-void help()
-{
-    printf(
-        "Options:\n"
-        "  -J        Add Joliet support\n"
-        "  -R        Add Rock Ridge support\n"
-        "  -I        Add ISO 9660:1999 support\n"
-        "  -V label  Volume Label\n"
-        "  -L <num>  Set the ISO level (1 or 2)\n"
-        "  -b file   Specifies a boot image to add to image\n"
-        "  -h        Print this message\n"
-    );
-}
-
-int callback(IsoFileSource *src)
-{
-    char *path = iso_file_source_get_path(src);
-    printf("CALLBACK: %s\n", path);
-    free(path);
-    return 1;
-}
-
-int main(int argc, char **argv)
-{
-    int result;
-    int c;
-    IsoImage *image;
-    struct burn_source *burn_src;
-    unsigned char buf[2048];
-    FILE *fd;
-    IsoWriteOpts *opts;
-    char *volid = "VOLID";
-    char *boot_img = NULL;
-    int rr = 0, j = 0, iso1999 = 0, level = 1;
-
-    while ((c = getopt(argc, argv, optstring)) != -1) {
-        switch(c) {
-        case 'h':
-            usage(argv);
-            help();
-            exit(0);
-            break;
-        case 'J':
-            j = 1;
-            break;
-        case 'R':
-            rr = 1;
-            break;
-        case 'I':
-            iso1999 = 1;
-            break;
-        case 'L':
-            level = atoi(optarg);
-            break;
-        case 'b':
-            boot_img = optarg;
-            break;
-        case 'V':
-            volid = optarg;
-            break;
-        case '?':
-            usage(argv);
-            exit(1);
-            break;
-        }
-    }
-
-    if (argc < 2) {
-        printf ("Please pass directory from which to build ISO\n");
-        usage(argv);
-        return 1;
-    }
-    if (argc < 3) {
-        printf ("Please supply output file\n");
-        usage(argv);
-        return 1;
-    }
-
-    fd = fopen(argv[optind+1], "w");
-    if (!fd) {
-        err(1, "error opening output file");
-    }
-
-    result = iso_init();
-    if (result < 0) {
-        printf ("Can't initialize libisofs\n");
-        return 1;
-    }
-    iso_set_msgs_severities("NEVER", "ALL", "");
-
-    result = iso_image_new(volid, &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-    iso_tree_set_follow_symlinks(image, 0);
-    iso_tree_set_ignore_hidden(image, 0);
-    iso_tree_set_ignore_special(image, 0);
-    iso_set_abort_severity("SORRY");
-    /*iso_tree_set_report_callback(image, callback);*/
-
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[optind]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-
-    if (boot_img) {
-        /* adds El-Torito boot info. Tunned for isolinux */
-        ElToritoBootImage *bootimg;
-        result = iso_image_set_boot_image(image, boot_img, ELTORITO_NO_EMUL,
-                                     "/isolinux/boot.cat", &bootimg);
-        if (result < 0) {
-            printf ("Error adding boot image %d\n", result);
-            return 1;
-        }
-        el_torito_set_load_size(bootimg, 4);
-        el_torito_patch_isolinux_image(bootimg);
-    }
-
-    result = iso_write_opts_new(&opts, 0);
-    if (result < 0) {
-        printf ("Cant create write opts, error %d\n", result);
-        return 1;
-    }
-    iso_write_opts_set_iso_level(opts, level);
-    iso_write_opts_set_rockridge(opts, rr);
-    iso_write_opts_set_joliet(opts, j);
-    iso_write_opts_set_iso1999(opts, iso1999);
-
-    result = iso_image_create_burn_source(image, opts, &burn_src);
-    if (result < 0) {
-        printf ("Cant create image, error %d\n", result);
-        return 1;
-    }
-
-    iso_write_opts_free(opts);
-
-    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
-        fwrite(buf, 1, 2048, fd);
-    }
-    fclose(fd);
-    burn_src->free_data(burn_src);
-    free(burn_src);
-
-    iso_image_unref(image);
-    iso_finish();
-	return 0;
-}
--- demo/iso_cat.c
+++ demo/iso_cat.c
-/*
- * Copyright (c) 2007 Vreixo Formoso
- * 
- * This file is part of the libisofs project; 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. See COPYING file for details.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "libisofs.h"
-
-/*
- * Little test program that extracts a file form a given ISO image.
- * Outputs file contents to stdout!
- */
-
-int main(int argc, char **argv)
-{
-    int res;
-    IsoFilesystem *fs;
-    IsoFileSource *file;
-    struct stat info;
-    IsoDataSource *src;
-    IsoReadOpts *opts;
-
-    if (argc != 3) {
-        fprintf(stderr, "Usage: isocat /path/to/image /path/to/file\n");
-        return 1;
-    }
-
-    res = iso_init();
-    if (res < 0) {
-        fprintf(stderr, "Can't init libisofs\n");
-        return 1;
-    }
-    
-    res = iso_data_source_new_from_file(argv[1], &src);
-    if (res < 0) {
-        fprintf(stderr, "Error creating data source\n");
-        return 1;
-    }
-
-    res = iso_read_opts_new(&opts, 0);
-    if (res < 0) {
-        fprintf(stderr, "Error creating read options\n");
-        return 1;
-    }
-    res = iso_image_filesystem_new(src, opts, 1, &fs);
-    if (res < 0) {
-        fprintf(stderr, "Error creating filesystem\n");
-        return 1;
-    }
-    iso_read_opts_free(opts);
-
-    res = fs->get_by_path(fs, argv[2], &file);
-    if (res < 0) {
-        fprintf(stderr, "Can't get file, err = %d\n", res);
-        return 1;
-    }
-
-    res = iso_file_source_lstat(file, &info);
-    if (res < 0) {
-        fprintf(stderr, "Can't stat file, err = %d\n", res);
-        return 1;
-    }
-
-    if (S_ISDIR(info.st_mode)) {
-        fprintf(stderr, "Path refers to a directory!!\n");
-        return 1;
-    } else {
-        char buf[1024];
-        res = iso_file_source_open(file);
-        if (res < 0) {
-            fprintf(stderr, "Can't open file, err = %d\n", res);
-            return 1;
-        }
-        while ((res = iso_file_source_read(file, buf, 1024)) > 0) {
-            fwrite(buf, 1, res, stdout);
-        }
-        if (res < 0) {
-            fprintf(stderr, "Error reading, err = %d\n", res);
-            return 1;
-        }
-        iso_file_source_close(file);
-    }
-    
-    iso_file_source_unref(file);
-    iso_filesystem_unref(fs);
-    iso_data_source_unref(src);
-    iso_finish();
-    return 0;
-}
--- demo/iso_modify.c
+++ demo/iso_modify.c
-/*
- * Little program to show how to modify an iso image.
- */
-
-#define LIBISOFS_WITHOUT_LIBBURN yes
-#include "libisofs.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <err.h>
-
-void usage(char **argv)
-{
-    printf("%s [OPTIONS] IMAGE DIRECTORY OUTPUT\n", argv[0]);
-}
-
-int main(int argc, char **argv)
-{
-    int result;
-    IsoImage *image;
-    IsoDataSource *src;
-    struct burn_source *burn_src;
-    unsigned char buf[2048];
-    FILE *fd;
-    IsoWriteOpts *opts;
-    IsoReadOpts *ropts;
-	
-    if (argc < 4) {
-        usage(argv);
-        return 1;
-    }
-    
-    fd = fopen(argv[3], "w");
-    if (!fd) {
-        err(1, "error opening output file");
-    }
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-    
-    /* create the data source to accesss previous image */
-    result = iso_data_source_new_from_file(argv[1], &src);
-    if (result < 0) {
-        printf ("Error creating data source\n");
-        return 1;
-    }
-    
-    /* create the image context */
-    result = iso_image_new("volume_id", &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-    iso_tree_set_follow_symlinks(image, 0);
-    iso_tree_set_ignore_hidden(image, 0);
-    
-    /* import previous image */
-    result = iso_read_opts_new(&ropts, 0);
-    if (result < 0) {
-        fprintf(stderr, "Error creating read options\n");
-        return 1;
-    }
-    result = iso_image_import(image, src, ropts, NULL);
-    iso_read_opts_free(ropts);
-    iso_data_source_unref(src);
-    if (result < 0) {
-        printf ("Error importing previous session %d\n", result);
-        return 1;
-    }
-    
-    /* add new dir */
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[2]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-    
-    /* generate a new image with both previous and added contents */
-    result = iso_write_opts_new(&opts, 1);
-    if (result < 0) {
-        printf("Cant create write opts, error %d\n", result);
-        return 1;
-    }
-    /* for isolinux: iso_write_opts_set_allow_full_ascii(opts, 1); */
-    
-    result = iso_image_create_burn_source(image, opts, &burn_src);
-    if (result < 0) {
-        printf ("Cant create image, error %d\n", result);
-        return 1;
-    }
-    
-    iso_write_opts_free(opts);
-    
-    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
-        fwrite(buf, 1, 2048, fd);
-    }
-    fclose(fd);
-    burn_src->free_data(burn_src);
-    free(burn_src);
-    
-    iso_image_unref(image);
-    iso_finish();
-	return 0;
-}
--- demo/iso_ms.c
+++ demo/iso_ms.c
-/*
- * Little program to show how to create a multisession iso image.
- */
-
-#define LIBISOFS_WITHOUT_LIBBURN yes
-#include "libisofs.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <err.h>
-
-void usage(char **argv)
-{
-    printf("%s LSS NWA DISC DIRECTORY OUTPUT\n", argv[0]);
-}
-
-int main(int argc, char **argv)
-{
-    int result;
-    IsoImage *image;
-    IsoDataSource *src;
-    struct burn_source *burn_src;
-    unsigned char buf[2048];
-    FILE *fd;
-    IsoWriteOpts *opts;
-    IsoReadOpts *ropts;
-    uint32_t ms_block;
-	
-    if (argc < 6) {
-        usage(argv);
-        return 1;
-    }
-
-    fd = fopen(argv[5], "w");
-    if (!fd) {
-        err(1, "error opening output file");
-    }
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-    
-    /* create the data source to accesss previous image */
-    result = iso_data_source_new_from_file(argv[3], &src);
-    if (result < 0) {
-        printf ("Error creating data source\n");
-        return 1;
-    }
-    
-    /* create the image context */
-    result = iso_image_new("volume_id", &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-    iso_tree_set_follow_symlinks(image, 0);
-    iso_tree_set_ignore_hidden(image, 0);
-    
-    /* import previous image */
-    result = iso_read_opts_new(&ropts, 0);
-    if (result < 0) {
-        fprintf(stderr, "Error creating read options\n");
-        return 1;
-    }
-    iso_read_opts_set_start_block(ropts, atoi(argv[1]));
-    result = iso_image_import(image, src, ropts, NULL);
-    iso_read_opts_free(ropts);
-    iso_data_source_unref(src);
-    if (result < 0) {
-        printf ("Error importing previous session %d\n", result);
-        return 1;
-    }
-    
-    /* add new dir */
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[4]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-    
-    /* generate a multisession image with new contents */
-    result = iso_write_opts_new(&opts, 1);
-    if (result < 0) {
-        printf("Cant create write opts, error %d\n", result);
-        return 1;
-    }
-    
-    /* round up to 32kb aligment = 16 block */
-    ms_block =  atoi(argv[2]);
-    iso_write_opts_set_ms_block(opts, ms_block);
-    iso_write_opts_set_appendable(opts, 1);
-
-    result = iso_image_create_burn_source(image, opts, &burn_src);
-    if (result < 0) {
-        printf ("Cant create image, error %d\n", result);
-        return 1;
-    }
-    iso_write_opts_free(opts);
-    
-    while (burn_src->read_xt(burn_src, buf, 2048) == 2048) {
-        fwrite(buf, 1, 2048, fd);
-    }
-    fclose(fd);
-    burn_src->free_data(burn_src);
-    free(burn_src);
-    
-    iso_image_unref(image);
-    iso_finish();
-	return 0;
-}
--- demo/iso_read.c
+++ demo/iso_read.c
-/*
- * Little program to output the contents of an iso image.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "libisofs.h"
-
-static void
-print_permissions(mode_t mode)
-{
-    char perm[10];
-
-    //TODO suid, sticky...
-
-    perm[9] = '\0';
-    perm[8] = mode & S_IXOTH ? 'x' : '-';
-    perm[7] = mode & S_IWOTH ? 'w' : '-';
-    perm[6] = mode & S_IROTH ? 'r' : '-';
-    perm[5] = mode & S_IXGRP ? 'x' : '-';
-    perm[4] = mode & S_IWGRP ? 'w' : '-';
-    perm[3] = mode & S_IRGRP ? 'r' : '-';
-    perm[2] = mode & S_IXUSR ? 'x' : '-';
-    perm[1] = mode & S_IWUSR ? 'w' : '-';
-    perm[0] = mode & S_IRUSR ? 'r' : '-';
-    printf(" %s ",perm);
-}
-
-static void
-print_type(mode_t mode)
-{
-    switch(mode & S_IFMT) {
-    case S_IFSOCK: printf("[S] "); break;
-    case S_IFLNK: printf("[L] "); break;
-    case S_IFREG: printf("[R] "); break;
-    case S_IFBLK: printf("[B] "); break;
-    case S_IFDIR: printf("[D] "); break;
-    case S_IFIFO: printf("[F] "); break;
-    }
-}
-
-static void
-print_file_src(IsoFileSource *file)
-{
-    struct stat info;
-    char *name;
-    iso_file_source_lstat(file, &info);
-    print_type(info.st_mode);
-    print_permissions(info.st_mode);
-    printf(" %10llu ", info.st_size);
-    //printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
-    name = iso_file_source_get_name(file);
-    printf(" %s", name);
-    free(name);
-    if (S_ISLNK(info.st_mode)) {
-        char buf[PATH_MAX];
-        iso_file_source_readlink(file, buf, PATH_MAX);
-        printf(" -> %s\n", buf);
-    }
-    printf("\n");
-}
-
-static void
-print_dir(IsoFileSource *dir, int level)
-{
-    int ret, i;
-    IsoFileSource *file;
-    struct stat info;
-    char *sp = alloca(level * 2 + 1);
-
-    for (i = 0; i < level * 2; i += 2) {
-        sp[i] = '|';
-        sp[i+1] = ' ';
-    }
-
-    sp[level * 2-1] = '-';
-    sp[level * 2] = '\0';
-
-    ret = iso_file_source_open(dir);
-    if (ret < 0) {
-        printf ("Can't open dir %d\n", ret);
-    }
-    while ((ret = iso_file_source_readdir(dir, &file)) == 1) {
-        printf("%s", sp);
-        print_file_src(file);
-        ret = iso_file_source_lstat(file, &info);
-        if (ret < 0) {
-            break;
-        }
-        if (S_ISDIR(info.st_mode)) {
-            print_dir(file, level + 1);
-        }
-        iso_file_source_unref(file);
-    }
-    iso_file_source_close(dir);
-    if (ret < 0) {
-        printf ("Can't print dir\n");
-    }
-}
-
-int main(int argc, char **argv)
-{
-    int result;
-    IsoImageFilesystem *fs;
-    IsoDataSource *src;
-    IsoFileSource *root;
-    IsoReadOpts *ropts;
-
-    if (argc != 2) {
-        printf ("You need to specify a valid path\n");
-        return 1;
-    }
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-
-    result = iso_data_source_new_from_file(argv[1], &src);
-    if (result < 0) {
-        printf ("Error creating data source\n");
-        return 1;
-    }
-
-    result = iso_read_opts_new(&ropts, 0);
-    if (result < 0) {
-        fprintf(stderr, "Error creating read options\n");
-        return 1;
-    }
-    result = iso_image_filesystem_new(src, ropts, 1, &fs);
-    iso_read_opts_free(ropts);
-    if (result < 0) {
-        printf ("Error creating filesystem\n");
-        return 1;
-    }
-
-    printf("\nVOLUME INFORMATION\n");
-    printf("==================\n\n");
-
-    printf("Vol. id: %s\n", iso_image_fs_get_volume_id(fs));
-    printf("Publisher: %s\n", iso_image_fs_get_publisher_id(fs));
-    printf("Data preparer: %s\n", iso_image_fs_get_data_preparer_id(fs));
-    printf("System: %s\n", iso_image_fs_get_system_id(fs));
-    printf("Application: %s\n", iso_image_fs_get_application_id(fs));
-    printf("Copyright: %s\n", iso_image_fs_get_copyright_file_id(fs));
-    printf("Abstract: %s\n", iso_image_fs_get_abstract_file_id(fs));
-    printf("Biblio: %s\n", iso_image_fs_get_biblio_file_id(fs));
-
-    printf("\nDIRECTORY TREE\n");
-    printf("==============\n");
-
-    result = fs->get_root(fs, &root);
-    if (result < 0) {
-        printf ("Can't get root %d\n", result);
-        return 1;
-    }
-    //print_file_src(root);
-    print_dir(root, 0);
-    iso_file_source_unref(root);
-
-    fs->close(fs);
-    iso_filesystem_unref((IsoFilesystem*)fs);
-    iso_data_source_unref(src);
-    iso_finish();
-    return 0;
-}
--- demo/lsl.c
+++ demo/lsl.c
-/*
- * Copyright (c) 2007 Vreixo Formoso
- * 
- * This file is part of the libisofs project; 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. See COPYING file for details.
- */
-
-#include "libisofs.h"
-#include "fsource.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-
-/*
- * Little test program to test filesystem implementations.
- * 
- */
-
-static void
-print_permissions(mode_t mode)
-{
-    char perm[10];
-
-    //TODO suid, sticky...
-
-    perm[9] = '\0';
-    perm[8] = mode & S_IXOTH ? 'x' : '-';
-    perm[7] = mode & S_IWOTH ? 'w' : '-';
-    perm[6] = mode & S_IROTH ? 'r' : '-';
-    perm[5] = mode & S_IXGRP ? 'x' : '-';
-    perm[4] = mode & S_IWGRP ? 'w' : '-';
-    perm[3] = mode & S_IRGRP ? 'r' : '-';
-    perm[2] = mode & S_IXUSR ? 'x' : '-';
-    perm[1] = mode & S_IWUSR ? 'w' : '-';
-    perm[0] = mode & S_IRUSR ? 'r' : '-';
-    printf(" %s ",perm);
-}
-
-static void
-print_type(mode_t mode)
-{
-    switch(mode & S_IFMT) {
-    case S_IFSOCK: printf("[S] "); break;
-    case S_IFLNK: printf("[L] "); break;
-    case S_IFREG: printf("[R] "); break;
-    case S_IFBLK: printf("[B] "); break;
-    case S_IFDIR: printf("[D] "); break;
-    case S_IFIFO: printf("[F] "); break; 
-    }
-}
-
-static void
-print_file_src(IsoFileSource *file)
-{
-    struct stat info;
-    char *name;
-    iso_file_source_lstat(file, &info);
-    print_type(info.st_mode);
-    print_permissions(info.st_mode);
-    printf(" {%ld,%ld} ", (long)info.st_dev, (long)info.st_ino);
-    name = iso_file_source_get_name(file);
-    printf(" %s", name);
-    free(name);
-    if (S_ISLNK(info.st_mode)) {
-        char buf[PATH_MAX];
-        iso_file_source_readlink(file, buf, PATH_MAX);
-        printf(" -> %s\n", buf);
-    }
-    printf("\n");
-}
-
-int main(int argc, char **argv)
-{
-    int res;
-    IsoFilesystem *fs;
-    IsoFileSource *dir;
-    IsoFileSource *file;
-    struct stat info;
-
-    if (argc != 2) {
-        fprintf(stderr, "Usage: lsl /path/to/file\n");
-        return 1;
-    }
-
-    /* create filesystem object */
-    res = iso_local_filesystem_new(&fs);
-    if (res < 0) {
-        fprintf(stderr, "Can't get local fs object, err = %d\n", res);
-        return 1;
-    }
-
-    res = fs->get_by_path(fs, argv[1], &dir);
-    if (res < 0) {
-        fprintf(stderr, "Can't get file, err = %d\n", res);
-        return 1;
-    }
-
-    res = iso_file_source_lstat(dir, &info);
-    if (res < 0) {
-        fprintf(stderr, "Can't stat file, err = %d\n", res);
-        return 1;
-    }
-
-    if (S_ISDIR(info.st_mode)) {
-        res = iso_file_source_open(dir);
-        if (res < 0) {
-            fprintf(stderr, "Can't open file, err = %d\n", res);
-            return 1;
-        }
-
-        while (iso_file_source_readdir(dir, &file) == 1) {
-            print_file_src(file);
-            iso_file_source_unref(file);
-        }
-
-        res = iso_file_source_close(dir);
-        if (res < 0) {
-            fprintf(stderr, "Can't close file, err = %d\n", res);
-            return 1;
-        }
-    } else {
-        print_file_src(dir);
-    }
-    
-    iso_file_source_unref(dir);
-    iso_filesystem_unref(fs);
-    return 0;
-}
--- demo/tree.c
+++ demo/tree.c
-/*
- * Little program that import a directory and prints the resulting iso tree.
- */
-
-#include "libisofs.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-static void
-print_permissions(mode_t mode)
-{
-	char perm[10];
-	
-	//TODO suid, sticky...
-	
-	perm[9] = '\0';
-	perm[8] = mode & S_IXOTH ? 'x' : '-';
-	perm[7] = mode & S_IWOTH ? 'w' : '-';
-	perm[6] = mode & S_IROTH ? 'r' : '-';
-	perm[5] = mode & S_IXGRP ? 'x' : '-';
-	perm[4] = mode & S_IWGRP ? 'w' : '-';
-	perm[3] = mode & S_IRGRP ? 'r' : '-';
-	perm[2] = mode & S_IXUSR ? 'x' : '-';
-	perm[1] = mode & S_IWUSR ? 'w' : '-';
-	perm[0] = mode & S_IRUSR ? 'r' : '-';
-	printf("[%s]",perm);
-}
-
-static void 
-print_dir(IsoDir *dir, int level) 
-{
-	int i;
-	IsoDirIter *iter;
-	IsoNode *node;
-	char *sp = alloca(level * 2 + 1);
-	
-	for (i = 0; i < level * 2; i += 2) {
-		sp[i] = '|';
-		sp[i+1] = ' ';
-	}
-	
-	sp[level * 2-1] = '-';
-	sp[level * 2] = '\0';
-	
-	iso_dir_get_children(dir, &iter);
-	while (iso_dir_iter_next(iter, &node) == 1) {
-		
-		if (ISO_NODE_IS_DIR(node)) {
-			printf("%s+[D] ", sp);
-			print_permissions(iso_node_get_permissions(node));
-			printf(" %s\n", iso_node_get_name(node));
-			print_dir(ISO_DIR(node), level+1);
-		} else if (ISO_NODE_IS_FILE(node)) {
-			printf("%s-[F] ", sp);
-			print_permissions(iso_node_get_permissions(node));
-			printf(" %s\n", iso_node_get_name(node) );
-		} else if (ISO_NODE_IS_SYMLINK(node)) {
-			printf("%s-[L] ", sp);
-			print_permissions(iso_node_get_permissions(node));
-			printf(" %s -> %s \n", iso_node_get_name(node),
-			       iso_symlink_get_dest(ISO_SYMLINK(node)) );
-		} else {
-			printf("%s-[C] ", sp);
-			print_permissions(iso_node_get_permissions(node));
-			printf(" %s\n", iso_node_get_name(node) );
-		} 
-	}
-	iso_dir_iter_free(iter);
-}
-
-int main(int argc, char **argv)
-{
-	int result;
-    IsoImage *image;
-	
-	if (argc != 2) {
-		printf ("You need to specify a valid path\n");
-		return 1;
-	}
-
-    iso_init();
-    iso_set_msgs_severities("NEVER", "ALL", "");
-    
-    result = iso_image_new("volume_id", &image);
-    if (result < 0) {
-        printf ("Error creating image\n");
-        return 1;
-    }
-	
-    result = iso_tree_add_dir_rec(image, iso_image_get_root(image), argv[1]);
-    if (result < 0) {
-        printf ("Error adding directory %d\n", result);
-        return 1;
-    }
-	
-    printf("================= IMAGE =================\n");
-	print_dir(iso_image_get_root(image), 0);
-	printf("\n\n");
-	
-    iso_image_unref(image);
-    iso_finish();
-    return 0;
-}
--- doc/checksums.txt
+++ doc/checksums.txt
+
+                    Description of libisofs MD5 checksumming
+
+               by Thomas Schmitt    - mailto:scdbackup at gmx.net
+               Libburnia project    - mailto:libburn-hackers at pykix.org
+                                 26 Aug 2009
+
+
+MD5 is a 128 bit message digest with a very low probability to be the same for
+any pair of differing data files. It is described in RFC 1321. and can be
+computed e.g. by program md5sum.
+
+libisofs can equip its images with MD5 checksums for superblock, directory
+tree, the whole session, and for each single data file.
+See libisofs.h, iso_write_opts_set_record_md5().
+
+The data file checksums get loaded together with the directory tree if this
+is enabled by iso_read_opts_set_no_md5(). Loaded checksums can be inquired by
+iso_image_get_session_md5() and iso_file_get_md5().
+
+Stream recognizable checksum tags occupy exactly one block each. They can
+be detected by submitting a block to iso_util_decode_md5_tag(). 
+
+libisofs has own MD5 computation functions:
+iso_md5_start(), iso_md5_compute(), iso_md5_clone(), iso_md5_end(),
+iso_md5_match()
+
+
+                          Representation in the Image
+
+There may be several stream recognizable checksum tags and a compact array
+of MD5 items at the end of the session. The latter allows to quickly load many
+file checksums from media with slow random access.
+
+
+                              The Checksum Array
+
+Location and layout of the checksum array is recorded as AAIP attribute
+"isofs.ca" of the root node.
+See doc/susp_aaip_2_0.txt for a general description of AAIP and
+doc/susp_aaip_isofs_names.txt for the layout of "isofs.ca".
+
+The single data files hold an index to their MD5 checksum in individual AAIP
+attributes "isofs.cx". Index I means: array base address + 16 * I. 
+
+If there are N checksummed data files then the array consists of N + 2 entries
+with 16 bytes each.
+
+Entry number 0 holds a session checksum which covers the range from the session
+start block up to (but not including) the start block of the checksum area.
+This range is described by attribute "isofs.ca" of the root node.
+
+Entries 1 to N hold the checksums of individual data files.
+
+Entry number N + 1 holds the MD5 checksum of entries 0 to N.
+
+
+                             The Checksum Tags
+
+Because the inquiry of AAIP attributes demands loading of the image tree,
+there are also checksum tags which can be detected on the fly when reading
+and checksumming the session from its start point as learned from a media
+table-of-content. 
+
+The superblock checksum tag is written after the ECMA-119 volume descriptors.
+The tree checksum tag is written after the  ECMA-119 directory entries.
+The session checksum tag is written after all payload including the checksum
+array. (Then follows eventual padding.)
+
+The tags are single lines of printable text at the very beginning of a block
+of 2048 bytes. They have the following format:
+
+ Tag_id pos=# range_start=# range_size=# [session_start|next=#] md5=# self=#\n
+
+Tag_id distinguishes the following tag types
+  "libisofs_rlsb32_checksum_tag_v1"     Relocated 64 kB superblock tag
+  "libisofs_sb_checksum_tag_v1"         Superblock tag
+  "libisofs_tree_checksum_tag_v1"       Directory tree tag
+  "libisofs_checksum_tag_v1"            Session tag
+
+A relocated superblock may appear at LBA 0 of an image which was produced for
+being stored in a disk file or on overwriteable media (e.g. DVD+RW, BD-RE).
+Typically there is a first session recorded with a superblock at LBA 32 and
+the next session may follow shortly after its session tag. (Typically at the
+next block address which is divisible by 32.) Normally no session starts after 
+the address given by parameter session_start=.
+
+Session oriented media like CD-R[W], DVD+R, BD-R will have no relocated
+superblock but rather bear a table-of-content on media level (to be inquired
+by MMC commands).
+
+
+Example:
+A relocated superblock which points to the last session. Then the first session
+which starts at Logical Block Address 32. The following sessions have the same
+structure as the first one.
+
+LBA 0:
+   <... ECMA-119 System Area and Volume Descriptors ...>
+LBA 18:
+   libisofs_rlsb32_checksum_tag_v1 pos=18 range_start=0 range_size=18 session_start=311936 md5=6fd252d5b1db52b3c5193447081820e4 self=526f7a3c7fefce09754275c6b924b6d9
+   <... padding up to LBA 32 ...>
+LBA 32:
+   <... First Session: ECMA-119 System Area and Volume Descriptors ...>
+   libisofs_sb_checksum_tag_v1 pos=50 range_start=32 range_size=18 md5=17471035f1360a69eedbd1d0c67a6aa2 self=52d602210883eeababfc9cd287e28682
+   <... ECMA-119 Directory Entries (the tree of file names) ...>
+LBA 334:
+   libisofs_tree_checksum_tag_v1 pos=334 range_start=32 range_size=302 md5=41acd50285339be5318decce39834a45 self=fe100c338c8f9a494a5432b5bfe6bf3c
+   <... Data file payload and checksum array ...>
+LBA 81554:
+   libisofs_checksum_tag_v1 pos=81554 range_start=32 range_size=81522 md5=8adb404bdf7f5c0a078873bb129ee5b9 self=57c2c2192822b658240d62cbc88270cb
+
+   <... more sessions ...>
+
+LBA 311936:
+   <... Last Session: ECMA-119 System Area and Volume Descriptors ...>
+LBA 311954:
+   libisofs_sb_checksum_tag_v1 pos=311954 range_start=311936 range_size=18 next=312286 md5=7f1586e02ac962432dc859a4ae166027 self=2c5fce263cd0ca6984699060f6253e62
+   <... Last Session: tree, tree checksum tag, data payload, session tag ...>
+
+
+There are several tag parameters. Addresses are given as decimal numbers, MD5
+checksums as strings of 32 hex digits.
+
+  pos=
+  gives the block address where the tag supposes itself to be stored.
+  If this does not match the block address where the tag is found then this
+  either indicates that the tag is payload of the image or that the image has
+  been relocated. (The latter makes the image unusable.)
+
+  range_start=
+  The block address where the session is supposed to start. If this does not
+  match the session start on media then the volume descriptors of the
+  image have been relocated. (This can happen with overwriteable media. If
+  checksumming started at LBA 0 and finds range_start=32, then one has to
+  restart checksumming at LBA 32. See libburn/doc/cookbook.txt
+  "ISO 9660 multi-session emulation on overwriteable media" for background
+  information.)
+
+  range_size=
+  The number of blocks beginning at range_start which are covered by the
+  checksum of the tag.  
+
+  Only with superblock tag and tree tag:
+  next=
+  The block address where the next tag is supposed to be found. This is
+  to avoid the small possibility that a checksum tag with matching position
+  is part of a directory entry or data file. The superblock tag is quite
+  uniquely placed directly after the ECMA-119 Volume Descriptor Set Terminator
+  where no such cleartext is supposed to reside by accident.
+
+  Only with relocated 64 kB superblock tag:
+  session_start=
+  The start block address (System Area) of the session to which the relocated
+  superblock points.  
+
+  md5=
+  The checksum payload of the tag as lower case hex digits.
+
+  self=
+  The MD5 checksum of the tag itself up to and including the last hex digit of
+  parameter "md5=".
+  
+The newline character at the end is mandatory. After that newline there may
+follow more lines. Their meaning is not necessarily described in this document.
+
+One such line type is the scdbackup checksum tag, an ancestor of libisofs tags
+which is suitable only for single session images which begin at LBA 0. It bears
+a checksum record which by its MD5 covers all bytes from LBA 0 up to the
+newline character preceding the scdbackup tag. See scdbackup/README appendix
+VERIFY for details.
+
+-------------------------------------------------------------------------------
+
+                              Usage at Read Time
+
+                     Checking Before Image Tree Loading
+
+In order to check for a trustworthy loadable image tree, read the first 32
+blocks from to the session start and look in block 16 to 32 for a superblock
+checksum tag by
+  iso_util_decode_md5_tag(block, &tag_type, &pos,
+                          &range_start, &range_size, &next_tag, md5, 0);
+
+If a tag of type 2 or 4 appears and has plausible parameters, then check
+whether its MD5 matches the MD5 of the data blocks which were read before.
+
+With tag type 2:
+
+Keep the original MD5 context of the data blocks and clone one for obtaining
+the MD5 bytes.
+If the MD5s match, then compute the checksum block and all folowing ones into
+the kept MD5 context and go on with reading and computing for the tree checksum
+tag. This will be found at block address next_tag, verified and parsed by:
+  iso_util_decode_md5_tag(block, &tag_type, &pos,
+                          &range_start, &range_size, &next_tag, md5, 3);
+
+Again, if the parameters match the reading state, the MD5 must match the
+MD5 computed from the data blocks which were before.
+If so, then the tree is ok and safe to be loaded by iso_image_import().
+
+With tag type 4:
+
+End the MD5 context and start a new context for the session which you will
+read next.
+
+Then look for the actual session by starting to read at the address given by
+parameter session_start= which is returned by iso_util_decode_md5_tag() as
+next_tag. Go on by looking for tag type 2 and follow above prescription.
+
+
+                      Checking the Data Part of the Session
+
+In order to check the trustworthyness of a whole session, continue reading
+and checksumming after the tree was verified. 
+
+Read and checksum the blocks. When reaching block address next_tag (from the
+tree tag) submit this block to
+
+  iso_util_decode_md5_tag(block, &tag_type, &pos,
+                          &range_start, &range_size, &next_tag, md5, 1);
+
+If this returns 1, then check whether the returned parameters pos, range_start,
+and range_size match the state of block reading, and whether the returned
+bytes in parameter md5 match the MD5 computed from the data blocks which were
+read before the tag block.
+
+
+                           Checking All Sessions
+
+If the media is sequentially recordable, obtain a table of content and check
+the first track of each session as prescribed above in Checking Before Image
+Tree Loading and in Checking the Data Part of the Session.
+
+With disk files or overwriteable media, look for a relocated superblock tag
+but do not hop to address next_tag (given by session_start=). Instead look at
+LBA 32 for the first session and check it as prescribed above.
+After reaching its end, round up the read address to the next multiple of 32
+and check whether it is smaller than session_start= from the super block.
+If so, expect another session to start there.
+
+
+                   Checking Single Files in a Loaded Image
+
+An image may consist of many sessions wherein many data blocks may not belong
+to files in the directory tree of the most recent session. Checking this
+tree and all its data files can ensure that all actually valid data in the
+image are trustworthy. This will leave out the trees of the older sessions
+and the obsolete data blocks of overwritten or deleted files.
+
+Once the image has been loaded, you can obtain MD5 sums from IsoNode objects
+which fulfill
+  iso_node_get_type(node) == LIBISO_FILE
+
+The recorded checksum can be obtained by
+  iso_file_get_md5(image, (IsoFile *) node, md5, 0);
+
+For accessing the file data in the loaded image use 
+  iso_file_get_stream((IsoFile *) node);
+to get the data stream of the object.
+The checksums cover the data content as it was actually written into the ISO
+image stream, not necessarily as it was on hard disk before or afterwards.
+This implies that content filtered files bear the MD5 of the filtered data
+and not of the original files on disk. When checkreading, one has to avoid
+any reverse filtering. Dig out the stream which directly reads image data
+by calling iso_stream_get_input_stream() until it returns NULL and use
+iso_stream_get_size() rather than iso_file_get_size().
+
+Now you may call iso_stream_open(), iso_stream_read(), iso_stream_close()
+for reading file content from the loaded image.
+
+
+                        Session Check in a Loaded Image
+
+iso_image_get_session_md5() gives start LBA and session payload size as of
+"isofs.ca" and the session checksum as of the checksum array.
+
+For reading you may use the IsoDataSource object which you submitted
+to iso_image_import() when reading the image. If this source is associated
+to a libburn drive, then libburn function burn_read_data() can read directly
+from it.
+
+-------------------------------------------------------------------------------
+
+                            scdbackup Checksum Tags
+
+The session checksum tag does not occupy its whole block. So there is room to
+store a scdbackup stream checksum tag, which is an ancestor format of the tags
+described here. This feature allows scdbackup to omit its own checksum filter
+if using xorriso as ISO 9660 formatter program.
+Such a tag makes only sense if the session begins at LBA 0.
+
+See scdbackup-*/README, appendix VERIFY for a specification.
+
+Example of a scdbackup checksum tag:
+scdbackup_checksum_tag_v0.1 2456606865 61 2_2 B00109.143415 2456606865 485bbef110870c45754d7adcc844a72c c2355d5ea3c94d792ff5893dfe0d6d7b
+
+The tag is located at byte position 2456606865, contains 61 bytes of scdbackup
+checksum record (the next four words):
+Name of the backup volume is "2_2".
+Written in year B0 = 2010 (A9 = 2009, B1 = 2011), January (01), 9th (09),
+14:34:15 local time. 
+The size of the volume is 2456606865 bytes, which have a MD5 sum of
+485bbef110870c45754d7adcc844a72c.
+The checksum of "2_2 B00109.143415 2456606865 485bbef110870c45754d7adcc844a72c"
+is c2355d5ea3c94d792ff5893dfe0d6d7b.
+
+-------------------------------------------------------------------------------
+
+This text is under
+Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup at gmx.net>
+It shall only be modified in sync with libisofs and other software which
+makes use of libisofs checksums. Please mail change requests to mailing list
+<libburn-hackers at pykix.org> or to the copyright holder in private.
+Only if you cannot reach the copyright holder for at least one month it is
+permissible to modify this text under the same license as the affected
+copy of libisofs.
+If you do so, you commit yourself to taking reasonable effort to stay in 
+sync with the other interested users of this text.
+
--- doc/susp_aaip_2_0.txt
+++ doc/susp_aaip_2_0.txt
@@ -443,3 +443,14 @@
 
 -------------------------------------------------------------------------------
 
+This text is under
+Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup at gmx.net>
+It shall only be modified in sync with libisofs and other software which
+makes use of AAIP. Please mail change requests to mailing list
+<libburn-hackers at pykix.org> or to the copyright holder in private.
+Only if you cannot reach the copyright holder for at least one month it is
+permissible to modify this text under the same license as the affected
+copy of libisofs.
+If you do so, you commit yourself to taking reasonable effort to stay in 
+sync with the other interested users of this text.
+
--- doc/susp_aaip_isofs_names.txt
+++ doc/susp_aaip_isofs_names.txt
@@ -13,25 +13,47 @@
 -------------------------------------------------------------------------------
 
 Name:
-      isofs.di
+      isofs.ca
 
 Purpose:
-      Records .st_dev and .st_ino of struct stat of the file source in the
-      local filesystem. See man 2 stat.
+      Records the range of checksummed image data (START, END), the number
+      of checksum items (COUNT), the number of bytes in a single checksum item
+      (SIZE), and the name of the checksum algorithm (CHECKSUM_TYPE).
+      END is also the block address of the start of the checksum recording
+      area in the image.
+      See also isofs.cx .
 
 Format of Value:
-      DEV_LEN | DEV_BYTES | INO_LEN | INO_BYTES
+      START_LEN | START_BYTES | END_LEN | END_BYTES |
+      COUNT_LEN | COUNT_BYTES | SIZE_LEN | SIZE_BYTES | CHECKSUM_TYPE
+      Each number is encoded as _LEN byte and _BYTES value string.
       The _LEN fields comply to ISO 9660 Format section 7.1.1.
-      The byte strings begin with the most significant byte.
+      The byte strings START_BYTES, END_BYTES, COUNT_BYTES, SIZE_BYTES begin
+      with the most significant byte. Leading zero bytes are allowed.
+      CHECKSUM_TYPE consists of the bytes after
+      START_LEN + END_LEN + COUNT_LEN + SIZE_LEN + 4.
+      It shall be a string of printable characters without terminating 0-byte.
+      Type names shall be registered here.
+      For now there is:
+       "MD5"   128 bit message digest, see RFC 1321, see man md5sum 
 
 Example:
-      Device number 2001, inode number 176343
-      {   2,   7, 209,
-          3,   2, 176, 215 } 
+      LBA range 32 to 1000000 , 520 checksums recorded, MD5 
+      {   1,  32,
+          3,  15,  66,  64,
+          2,   2,   8,
+          1,  16,
+        'M', 'D', '5' }
+      or
+      {   4,   0,   0,   0,  32,
+          4,   0,  15,  66,  64,
+          4,   0,   0,   2,   8,
+          1,  16,
+         'M', 'D', '5' }
 
 Registered:
-      17 Feb 2009 by Thomas Schmitt for xorriso.
-                 
+      16 Jul 2009 by Thomas Schmitt for libisofs.
+
 -------------------------------------------------------------------------------
 
 Name:
@@ -52,7 +74,51 @@
 
 Registered:
       18 Mar 2009 by Thomas Schmitt for libisofs.
-                 
+
+-------------------------------------------------------------------------------
+
+Name:
+      isofs.cx
+
+Purpose:
+      Records the index of the file's checksum in the checksum area at the
+      end of the image. The byte address of the checksum is 
+       checksum_area_lba * 2048 + isofs.cx * checksum_size
+      Default checksum algorithm is MD5 with a size of 16 byte.
+      See also isofs.ca .
+
+Format of Value:
+      A byte string which begins with the most significant byte.
+
+Example:
+      Index 123456
+      {   1, 226,  64 }
+
+Registered:
+      16 Jul 2009 by Thomas Schmitt for libisofs.
+
+-------------------------------------------------------------------------------
+
+Name:
+      isofs.di
+
+Purpose:
+      Records .st_dev and .st_ino of struct stat of the file source in the
+      local filesystem. See man 2 stat.
+
+Format of Value:
+      DEV_LEN | DEV_BYTES | INO_LEN | INO_BYTES
+      The _LEN fields comply to ISO 9660 Format section 7.1.1.
+      The byte strings begin with the most significant byte.
+
+Example:
+      Device number 2001, inode number 176343
+      {   2,   7, 209,
+          3,   2, 176, 215 } 
+
+Registered:
+      17 Feb 2009 by Thomas Schmitt for xorriso.
+
 -------------------------------------------------------------------------------
 
 Name:
@@ -78,8 +144,19 @@
 
 Registered:
       03 Apr 2009 by Thomas Schmitt for xorriso.
-                 
+
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 -------------------------------------------------------------------------------
 
+This text is under
+Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup at gmx.net>
+It shall only be modified in sync with libisofs and other software which
+makes use of AAIP. Please mail change requests to mailing list
+<libburn-hackers at pykix.org> or to the copyright holder in private.
+Only if you cannot reach the copyright holder for at least one month it is
+permissible to modify this text under the same license as the affected
+copy of libisofs.
+If you do so, you commit yourself to taking reasonable effort to stay in
+sync with the other interested users of this text.
+
--- doc/zisofs_format.txt
+++ doc/zisofs_format.txt
@@ -141,3 +141,14 @@
 RRIP 1.12
   ftp://ftp.ymi.com/pub/rockridge/rrip112.ps
 
+-------------------------------------------------------------------------------
+
+This text is under
+Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup at gmx.net>
+It shall reflect the effective technical specifications as implemented in
+zisofs-tools and the Linux kernel. So please contact mailing list
+<libburn-hackers at pykix.org> or to the copyright holder in private, if you
+want to make changes.
+Only if you cannot reach the copyright holder for at least one month it is
+permissible to modify and distribute this text under the license "BSD revised".
+
--- libisofs/aaip-os-dummy.c
+++ libisofs/aaip-os-dummy.c
@@ -11,7 +11,7 @@
 
  To be included by aaip_0_2.c
 
- Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2
+ Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
 
 */
 
--- libisofs/aaip-os-freebsd.c
+++ libisofs/aaip-os-freebsd.c
@@ -3,7 +3,7 @@
 
  aaip-os-freebsd.c
  Arbitrary Attribute Interchange Protocol , system adapter for getting and
- setting of ACLs and ixattr.
+ setting of ACLs and xattr.
 
  To be included by aaip_0_2.c
 
@@ -18,6 +18,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <errno.h>
 
 #ifndef Libisofs_with_aaip_acL
 /* It seems ACL is fixely integrated in FreeBSD libc. There is no libacl. */
@@ -37,13 +38,14 @@
                         finally has to be freed by a call to this function
                         with bit15 of flag.
    @param flag          Bitfield for control purposes
-                        bit0=  obtain default ACL rather than access ACL
+                        (bit0=  obtain default ACL rather than access ACL)
                         bit4=  set *text = NULL and return 2
                                if the ACL matches st_mode permissions.
                         bit5=  in case of symbolic link: inquire link target
                         bit15= free text and return 1
    @return              > 0 ok
                           0 ACL support not enabled at compile time
+                            or filesystem does not support ACL
                          -1 failure of system ACL service (see errno)
                          -2 attempt to inquire ACL of a symbolic
                             link without bit4 or bit5
@@ -88,8 +90,18 @@
 
  acl= acl_get_file(path, ACL_TYPE_ACCESS);
 
- if(acl == NULL)
+ if(acl == NULL) {
+   if(errno == EOPNOTSUPP) {
+     /* filesystem does not support ACL */
+     if(flag & 16)
+       return(2);
+
+     /* >>> ??? fake ACL from POSIX permissions ? */;
+
+     return(0);
+   }
    return(-1);
+ }
  *text= acl_to_text(acl, NULL);
  acl_free(acl);
 
@@ -181,10 +193,8 @@
 
  if(flag & 1) { /* Obtain ACL */
    /* access-ACL */
-   ret= aaip_get_acl_text(path, &acl_text, flag & (16 | 32));
-   if(ret <= 0)
-     goto ex;
-   if(ret == 2)
+   aaip_get_acl_text(path, &acl_text, flag & (16 | 32));
+   if(acl_text == NULL)
      {ret= 1; goto ex;} /* empty ACL / only st_mode info was found in ACL */
    ret= aaip_encode_acl(acl_text, (mode_t) 0, &a_acl_len, &a_acl, flag & 2);
    if(ret <= 0)
--- libisofs/aaip-os-linux.c
+++ libisofs/aaip-os-linux.c
@@ -7,7 +7,7 @@
 
  To be included by aaip_0_2.c
 
- Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2
+ Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
 
 */
 
@@ -18,6 +18,8 @@
 #include <string.h>
 #include <stdio.h>
 #include <sys/stat.h>
+#include <errno.h>
+
 
 #ifdef Libisofs_with_aaip_acL
 #include <sys/acl.h>
@@ -46,6 +48,7 @@
                           2 only st_mode permissions exist and bit 4 is set
                             or empty ACL and bit0 is set
                           0 ACL support not enabled at compile time
+                            or filesystem does not support ACL
                          -1 failure of system ACL service (see errno)
                          -2 attempt to inquire ACL of a symbolic link without
                             bit4 or bit5 resp. with no suitable link target
@@ -79,8 +82,18 @@
  }
  
  acl= acl_get_file(path, (flag & 1) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS);
- if(acl == NULL)
+ if(acl == NULL) {
+   if(errno == ENOTSUP) {
+     /* filesystem does not support ACL */
+     if(flag & 16)
+       return(2);
+   
+     /* >>> ??? fake ACL from POSIX permissions ? */;
+
+     return(0);   
+   }
    return(-1);
+ }
  *text= acl_to_text(acl, NULL);
  acl_free(acl);
 
@@ -131,13 +144,19 @@
 int aaip_get_attr_list(char *path, size_t *num_attrs, char ***names,
                        size_t **value_lengths, char ***values, int flag)
 {
- int ret, retry= 0;
+ int ret;
  char *list= NULL;
- ssize_t list_size= 0, i, num_names= 0, value_ret;
- size_t acl_len= 0;
+ ssize_t list_size= 0, i, num_names= 0;
  unsigned char *acl= NULL;
  char *a_acl_text= NULL, *d_acl_text= NULL;
 
+#ifdef Libisofs_with_aaip_acL
+ size_t acl_len= 0;
+#endif
+#ifdef Libisofs_with_aaip_xattR
+ ssize_t value_ret, retry= 0;
+#endif
+
  if(flag & (1 << 15)) { /* Free memory */
    {ret= 1; goto ex;}
  }
@@ -375,8 +394,11 @@
                        size_t *value_lengths, char **values, int flag)
 {
  int ret, has_default_acl= 0;
- size_t i, consumed, acl_text_fill, list_size= 0, acl_idx= 0, h_consumed;
+ size_t i, consumed, acl_text_fill, acl_idx= 0, h_consumed;
  char *acl_text= NULL, *list= NULL;
+#ifdef Libisofs_with_aaip_xattR
+ size_t list_size= 0;
+#endif
 
 #ifdef Libisofs_with_aaip_xattR
 
--- libisofs/aaip_0_2.c
+++ libisofs/aaip_0_2.c
@@ -7,7 +7,7 @@
  See test/aaip_0_2.h
      http://libburnia-project.org/wiki/AAIP
 
- Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2
+ Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
 
 */
 
@@ -23,9 +23,9 @@
 
 #include "libisofs.h"
 
-/* <<<
-*/
+/*
 #define Aaip_encode_debuG 1
+*/
 
 #include "aaip_0_2.h"
 
@@ -567,7 +567,7 @@
 }
 
 
-/* Linux man 5 acl says:
+/* GNU/Linux man 5 acl says:
      The permissions defined by ACLs are a superset of the permissions speci-
      fied by the file permission bits. The permissions defined for the file
      owner correspond to the permissions of the ACL_USER_OBJ entry.  The per-
--- libisofs/aaip_0_2.h
+++ libisofs/aaip_0_2.h
@@ -9,7 +9,7 @@
 
  test/aaip_0_2.h - Public declarations
 
- Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2
+ Copyright (c) 2009 Thomas Schmitt, libburnia project, GPLv2+
 
 */
 
--- libisofs/buffer.c
+++ libisofs/buffer.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
--- libisofs/buffer.h
+++ libisofs/buffer.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_BUFFER_H_
--- libisofs/builder.c
+++ libisofs/builder.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /* libisofs.h defines aaip_xinfo_func */
@@ -19,6 +20,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
+#include <stdio.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
 
 
 
@@ -94,7 +100,7 @@
     IsoNode *new;
     IsoFilesystem *fs;
     char *name;
-    unsigned char *aa_string;
+    unsigned char *aa_string = NULL;
     char *a_text = NULL, *d_text = NULL;
 
     if (builder == NULL || src == NULL || node == NULL) {
@@ -211,6 +217,9 @@
         }
         iso_aa_get_acl_text(aa_string, info.st_mode, &a_text, &d_text,
                             1 << 15); /* free ACL texts */
+        if(aa_string != NULL)
+            free(aa_string);
+        aa_string = NULL;
     }
 
     /* Obtain ownership of eventual AAIP string */
@@ -221,6 +230,8 @@
         ret = iso_node_add_xinfo(new, aaip_xinfo_func, aa_string);
         if (ret < 0)
             return ret;
+    } else if(aa_string != NULL) {
+        free(aa_string);
     }
 
     *node = new;
--- libisofs/builder.h
+++ libisofs/builder.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_BUILDER_H_
--- libisofs/data_source.c
+++ libisofs/data_source.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
--- libisofs/ecma119.c
+++ libisofs/ecma119.c
@@ -1,11 +1,12 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
  * Copyright (c) 2007 Mario Danic
- * Copyright (c) 2009 Thomas Schmitt
+ * Copyright (c) 2009 - 2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
@@ -27,11 +28,17 @@
 #include "util.h"
 #include "system_area.h"
 
+#ifdef Libisofs_with_checksumS
+#include "md5.h"
+#endif
+
+#include <ctype.h>
 #include <stdlib.h>
 #include <time.h>
 #include <string.h>
 #include <locale.h>
 #include <langinfo.h>
+#include <stdio.h>
 
 /*
  * TODO #00011 : guard against bad path table usage with more than 65535 dirs
@@ -45,19 +52,42 @@
 {
     size_t i;
 
-    ecma119_node_free(t->root);
-    iso_image_unref(t->image);
-    iso_rbtree_destroy(t->files, iso_file_src_free);
-    iso_ring_buffer_free(t->buffer);
+    if (t == NULL)
+        return;
+    if (t->root != NULL)
+        ecma119_node_free(t->root);
+    if (t->image != NULL)
+        iso_image_unref(t->image);
+    if (t->files != NULL)
+        iso_rbtree_destroy(t->files, iso_file_src_free);
+    if (t->buffer != NULL)
+        iso_ring_buffer_free(t->buffer);
 
     for (i = 0; i < t->nwriters; ++i) {
         IsoImageWriter *writer = t->writers[i];
         writer->free_data(writer);
         free(writer);
     }
-    free(t->input_charset);
-    free(t->output_charset);
-    free(t->writers);
+    if (t->input_charset != NULL)
+        free(t->input_charset);
+    if (t->output_charset != NULL)
+        free(t->output_charset);
+    if (t->bootsrc != NULL)
+        free(t->bootsrc);
+    if (t->system_area_data != NULL)
+        free(t->system_area_data);
+
+#ifdef Libisofs_with_checksumS
+    if (t->checksum_ctx != NULL) { /* dispose checksum context */
+        char md5[16];
+        iso_md5_end(&(t->checksum_ctx), md5);
+    }
+    if (t->checksum_buffer != NULL)
+        free(t->checksum_buffer);
+#endif
+
+    if (t->writers != NULL)
+        free(t->writers);
     free(t);
 }
 
@@ -67,7 +97,7 @@
 static
 int need_version_number(Ecma119Image *t, Ecma119Node *n)
 {
-    if (t->omit_version_numbers) {
+    if (t->omit_version_numbers & 1) {
         return 0;
     }
     if (n->type == ECMA119_DIR || n->type == ECMA119_PLACEHOLDER) {
@@ -227,6 +257,16 @@
     target->curblock += DIV_UP(path_table_size, BLOCK_SIZE);
     target->path_table_size = path_table_size;
 
+#ifdef Libisofs_with_checksumS
+
+    if (target->md5_session_checksum) {
+        /* Account for tree checksum tag */
+        target->checksum_tree_tag_pos = target->curblock;
+        target->curblock++;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
     return ISO_SUCCESS;
 }
 
@@ -294,7 +334,7 @@
     rec->len_dr[0] = len_dr + (info != NULL ? info->suf_len : 0);
     iso_bb(rec->block, block, 4);
     iso_bb(rec->length, len, 4);
-    if(t->dir_rec_mtime) {
+    if (t->dir_rec_mtime) {
         iso= node->node;
         iso_datetime_7(rec->recording_time,
                        t->replace_timestamps ? t->timestamp : iso->mtime,
@@ -303,7 +343,7 @@
         iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
     }
     rec->flags[0] = ((node->type == ECMA119_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
-    iso_bb(rec->vol_seq_number, 1, 2);
+    iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
     rec->len_fi[0] = len_fi;
 
     /*
@@ -344,7 +384,7 @@
     IsoImage *image;
     Ecma119Image *t;
     struct ecma119_pri_vol_desc vol;
-
+    int i;
     char *vol_id, *pub_id, *data_id, *volset_id;
     char *system_id, *application_id, *copyright_file_id;
     char *abstract_file_id, *biblio_file_id;
@@ -381,9 +421,9 @@
     strncpy_pad((char*)vol.system_id, system_id, 32);
     strncpy_pad((char*)vol.volume_id, vol_id, 32);
     iso_bb(vol.vol_space_size, t->vol_space_size, 4);
-    iso_bb(vol.vol_set_size, 1, 2);
-    iso_bb(vol.vol_seq_number, 1, 2);
-    iso_bb(vol.block_size, BLOCK_SIZE, 2);
+    iso_bb(vol.vol_set_size, (uint32_t) 1, 2);
+    iso_bb(vol.vol_seq_number, (uint32_t) 1, 2);
+    iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2);
     iso_bb(vol.path_table_size, t->path_table_size, 4);
     iso_lsb(vol.l_path_table_pos, t->l_path_table_pos, 4);
     iso_msb(vol.m_path_table_pos, t->m_path_table_pos, 4);
@@ -399,9 +439,44 @@
     strncpy_pad((char*)vol.abstract_file_id, abstract_file_id, 37);
     strncpy_pad((char*)vol.bibliographic_file_id, biblio_file_id, 37);
 
-    iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
-    iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
-    iso_datetime_17(vol.vol_effective_time, t->now, t->always_gmt);
+    if (t->vol_uuid[0]) {
+        for(i = 0; i < 16; i++)
+            if(t->vol_uuid[i] < '0' || t->vol_uuid[i] > '9')
+        break;
+            else
+                vol.vol_creation_time[i] = t->vol_uuid[i];
+       for(; i < 16; i++)
+           vol.vol_creation_time[i] = '1';
+       vol.vol_creation_time[16] = 0;
+    } else if (t->vol_creation_time > 0)
+        iso_datetime_17(vol.vol_creation_time, t->vol_creation_time,
+                        t->always_gmt);
+    else
+        iso_datetime_17(vol.vol_creation_time, t->now, t->always_gmt);
+
+    if (t->vol_uuid[0]) {
+        for(i = 0; i < 16; i++)
+            if(t->vol_uuid[i] < '0' || t->vol_uuid[i] > '9')
+        break;
+            else
+                vol.vol_modification_time[i] = t->vol_uuid[i];
+       for(; i < 16; i++)
+           vol.vol_modification_time[i] = '1';
+       vol.vol_modification_time[16] = 0;
+    } else if (t->vol_modification_time > 0)
+        iso_datetime_17(vol.vol_modification_time, t->vol_modification_time,
+                        t->always_gmt);
+    else
+        iso_datetime_17(vol.vol_modification_time, t->now, t->always_gmt);
+
+    if (t->vol_expiration_time > 0)
+        iso_datetime_17(vol.vol_expiration_time, t->vol_expiration_time,
+                        t->always_gmt);
+
+    if (t->vol_effective_time > 0)
+        iso_datetime_17(vol.vol_effective_time, t->vol_effective_time,
+                        t->always_gmt);
+
     vol.file_structure_version[0] = 1;
 
     free(vol_id);
@@ -660,6 +735,17 @@
 
     /* and write the path tables */
     ret = write_path_tables(t);
+    if (ret < 0)
+        return ret;
+
+#ifdef Libisofs_with_checksumS
+
+    if (t->md5_session_checksum) {
+        /* Write tree checksum tag */
+        ret = iso_md5_write_tag(t, 3);
+    }
+
+#endif /* Libisofs_with_checksumS */
 
     return ret;
 }
@@ -784,6 +870,19 @@
 }
 
 static
+int transplant_checksum_buffer(Ecma119Image *target, int flag)
+{
+    /* Transplant checksum buffer from Ecma119Image to IsoImage */
+    iso_image_set_checksums(target->image, target->checksum_buffer,
+                            target->checksum_range_start,
+                            target->checksum_array_pos,
+                            target->checksum_idx_counter + 2, 0);
+    target->checksum_buffer = NULL;
+    target->checksum_idx_counter = 0;
+    return 1;
+}
+
+static
 void *write_function(void *arg)
 {
     int res;
@@ -835,6 +934,18 @@
         }
     }
 
+#ifdef Libisofs_with_checksumS
+
+    /* Write superblock checksum tag */
+    if (target->md5_session_checksum && target->checksum_ctx != NULL) {
+        res = iso_md5_write_tag(target, 2);
+        if (res < 0)
+            goto write_error;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
+
     /* write data for each writer */
     for (i = 0; i < target->nwriters; ++i) {
         writer = target->writers[i];
@@ -844,8 +955,20 @@
         }
     }
 
+#ifdef Libisofs_with_checksumS
+
+    /* Transplant checksum buffer from Ecma119Image to IsoImage */
+    transplant_checksum_buffer(target, 0);
+
+#endif
+
     iso_ring_buffer_writer_close(target->buffer, 0);
+
+#ifdef Libisofs_with_pthread_exiT
     pthread_exit(NULL);
+#else
+    return NULL;
+#endif
 
     write_error: ;
     if (res == ISO_CANCELED) {
@@ -857,15 +980,133 @@
                    "Image write error");
     }
     iso_ring_buffer_writer_close(target->buffer, 1);
+
+#ifdef Libisofs_with_checksumS
+
+    /* Transplant checksum buffer away from Ecma119Image */
+    transplant_checksum_buffer(target, 0);
+    /* Invalidate the transplanted checksum buffer in IsoImage */
+    iso_image_free_checksums(target->image, 0);
+
+#endif
+
+#ifdef Libisofs_with_pthread_exiT
     pthread_exit(NULL);
+#else
+    return NULL;
+#endif
+
+}
+
+
+#ifdef Libisofs_with_checksumS
+
+
+static
+int checksum_prepare_image(IsoImage *src, int flag)
+{
+    int ret;
+
+    /* Set provisory value of isofs.ca with
+       4 byte LBA, 4 byte count, size 16, name MD5 */
+    ret = iso_root_set_isofsca((IsoNode *) src->root, 0, 0, 0, 16, "MD5", 0);
+    if (ret < 0)
+        return ret;
+    return ISO_SUCCESS;
+}
+
+
+/*
+  @flag bit0= recursion
+*/
+static
+int checksum_prepare_nodes(Ecma119Image *target, IsoNode *node, int flag)
+{
+    IsoNode *pos;
+    IsoFile *file;
+    IsoImage *img;
+    int ret, i, no_md5 = 0, has_xinfo = 0;
+    size_t value_length;
+    unsigned int idx = 0;
+    char *value= NULL;
+    void *xipt = NULL;
+    static char *cx_names = "isofs.cx";
+    static size_t cx_value_lengths[1] = {0};
+    char *cx_valuept = "";
+
+    img= target->image;
+
+    if (node->type == LIBISO_FILE) {
+        file = (IsoFile *) node;
+        if (file->from_old_session && target->appendable) {
+            /* Save MD5 data of files from old image which will not
+               be copied and have an MD5 recorded in the old image. */
+            has_xinfo = iso_node_get_xinfo(node, checksum_md5_xinfo_func,
+                                           &xipt);
+            if (has_xinfo <= 0) {
+                ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
+                                           &value, 0);
+            }
+            if (has_xinfo > 0) {
+                /* xinfo MD5 overrides everything else unless data get copied
+                   and checksummed during that copying
+                 */;
+            } else if (ret == 1 && img->checksum_array == NULL) {
+                /* No checksum array loaded. Delete "isofs.cx" */
+                iso_node_set_attrs(node, (size_t) 1,
+                              &cx_names, cx_value_lengths, &cx_valuept, 4 | 8);
+                no_md5 = 1;
+            } else if (ret == 1 && value_length == 4) {
+                for (i = 0; i < 4; i++)
+                    idx = (idx << 8) | ((unsigned char *) value)[i];
+                if (idx > 0 && idx < 0x8000000) {
+                    /* xipt is an int disguised as void pointer */
+                    for (i = 0; i < 4; i++)
+                        ((char *) &xipt)[i] = value[i];
+                    ret = iso_node_add_xinfo(node, checksum_cx_xinfo_func,
+                                             xipt);
+                    if (ret < 0)
+                        return ret;
+                } else
+                    no_md5 = 1;
+            } else {
+                no_md5 = 1;
+            }
+            if (value != NULL) {
+                free(value);
+                value= NULL;
+            }
+        }
+        /* Equip nodes with provisory isofs.cx numbers: 4 byte, all 0.
+           Omit those from old image which will not be copied and have no MD5.
+         */
+        if (!no_md5) {
+            ret = iso_file_set_isofscx(file, (unsigned int) 0, 0);
+            if (ret < 0)
+                return ret;
+        }
+    } else if (node->type == LIBISO_DIR) {
+        for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
+            ret = checksum_prepare_nodes(target, pos, 1);
+            if (ret < 0)
+                return ret;
+        }
+    }
+    return ISO_SUCCESS;
 }
 
+
+#endif /* Libisofs_with_checksumS */
+
+
 static
 int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img)
 {
-    int ret, i, voldesc_size, nwriters;
+    int ret, i, voldesc_size, nwriters, image_checksums_mad = 0, tag_pos;
     Ecma119Image *target;
-    int el_torito_writer_index = -1, file_src_writer_index= -1;
+    int el_torito_writer_index = -1, file_src_writer_index = -1;
+    int system_area_options = 0;
+    char *system_area = NULL;
 
     /* 1. Allocate target and copy opts there */
     target = calloc(1, sizeof(Ecma119Image));
@@ -876,8 +1117,7 @@
     /* create the tree for file caching */
     ret = iso_rbtree_new(iso_file_src_cmp, &(target->files));
     if (ret < 0) {
-        free(target);
-        return ret;
+        goto target_cleanup;
     }
 
     target->image = src;
@@ -890,11 +1130,6 @@
     target->hardlinks = opts->hardlinks;
     target->aaip = opts->aaip;
     target->always_gmt = opts->always_gmt;
-
-#ifndef Libisofs_hardlink_matcheR
-    target->ino = 0;
-#endif
-
     target->omit_version_numbers = opts->omit_version_numbers
                                  | opts->max_37_char_filenames;
     target->allow_deep_paths = opts->allow_deep_paths;
@@ -932,12 +1167,49 @@
     /* el-torito? */
     target->eltorito = (src->bootcat == NULL ? 0 : 1);
     target->catalog = src->bootcat;
+    if (target->catalog != NULL) {
+        target->num_bootsrc = target->catalog->num_bootimages;
+        target->bootsrc = calloc(target->num_bootsrc + 1,
+                                    sizeof(IsoFileSrc *));
+        if (target->bootsrc == NULL) {
+            ret = ISO_OUT_OF_MEM;
+            goto target_cleanup;
+        }
+        for (i= 0; i < target->num_bootsrc; i++)
+            target->bootsrc[i] = NULL;
+    } else {
+        target->num_bootsrc = 0;
+        target->bootsrc = NULL;
+    }
+
+    if (opts->system_area_data != NULL) {
+        system_area = opts->system_area_data;
+        system_area_options = opts->system_area_options;
+    } else if (src->system_area_data != NULL) {
+        system_area = src->system_area_data;
+        system_area_options = src->system_area_options;
+    }
+    target->system_area_data = NULL;
+    if (system_area != NULL) {
+        target->system_area_data = calloc(32768, 1);
+        if (target->system_area_data == NULL) {
+            ret = ISO_OUT_OF_MEM;
+            goto target_cleanup;
+        }
+        memcpy(target->system_area_data, system_area, 32768);
+    }
+    target->system_area_options = system_area_options;
+
+    target->vol_creation_time = opts->vol_creation_time;
+    target->vol_modification_time = opts->vol_modification_time;
+    target->vol_expiration_time = opts->vol_expiration_time;
+    target->vol_effective_time = opts->vol_effective_time;
+    strcpy(target->vol_uuid, opts->vol_uuid);
 
     target->input_charset = strdup(iso_get_local_charset(0));
     if (target->input_charset == NULL) {
-        iso_image_unref(src);
-        free(target);
-        return ISO_OUT_OF_MEM;
+        ret = ISO_OUT_OF_MEM;
+        goto target_cleanup;
     }
 
     if (opts->output_charset != NULL) {
@@ -946,11 +1218,31 @@
         target->output_charset = strdup(target->input_charset);
     }
     if (target->output_charset == NULL) {
-        iso_image_unref(src);
-        free(target);
-        return ISO_OUT_OF_MEM;
+        ret = ISO_OUT_OF_MEM;
+        goto target_cleanup;
     }
 
+#ifdef Libisofs_with_checksumS
+
+    target->md5_file_checksums = opts->md5_file_checksums;
+    target->md5_session_checksum = opts->md5_session_checksum;
+    strcpy(target->scdbackup_tag_parm, opts->scdbackup_tag_parm);
+    target->scdbackup_tag_written = opts->scdbackup_tag_written;
+    target->checksum_idx_counter = 0;
+    target->checksum_ctx = NULL;
+    target->checksum_counter = 0;
+    target->checksum_rlsb_tag_pos = 0;
+    target->checksum_sb_tag_pos = 0;
+    target->checksum_tree_tag_pos = 0;
+    target->checksum_tag_pos = 0;
+    target->checksum_buffer = NULL;
+    target->checksum_array_pos = 0;
+    target->checksum_range_start = 0;
+    target->checksum_range_size = 0;
+    target->opts_overwrite = 0;
+
+#endif
+
     /*
      * 2. Based on those options, create needed writers: iso, joliet...
      * Each writer inits its structures and stores needed info into
@@ -974,11 +1266,32 @@
         nwriters++;
     }
 
+
+#ifdef Libisofs_with_checksumS
+
+    if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
+        nwriters++;
+        image_checksums_mad = 1; /* from here on the loaded checksums are
+                                    not consistent with isofs.cx any more.
+                                  */
+        ret = checksum_prepare_image(src, 0);
+        if (ret < 0)
+            goto target_cleanup;
+        if (target->appendable) {
+            ret = checksum_prepare_nodes(target, (IsoNode *) src->root, 0);
+            if (ret < 0)
+                goto target_cleanup;
+        }
+        target->checksum_idx_counter = 0;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
+
     target->writers = malloc(nwriters * sizeof(void*));
     if (target->writers == NULL) {
-        iso_image_unref(src);
-        free(target);
-        return ISO_OUT_OF_MEM;
+        ret = ISO_OUT_OF_MEM;
+        goto target_cleanup;
     }
 
     /* create writer for ECMA-119 structure */
@@ -1019,7 +1332,7 @@
 
     /*
      * Create the writer for possible padding to ensure that in case of image
-     * growing we can safety overwrite the first 64 KiB of image.
+     * growing we can safely overwrite the first 64 KiB of image.
      */
     ret = pad_writer_create(target);
     if (ret < 0) {
@@ -1033,6 +1346,18 @@
     }
     file_src_writer_index = target->nwriters - 1;
 
+
+#ifdef Libisofs_with_checksumS
+
+    if ((target->md5_file_checksums & 1) || target->md5_session_checksum) {
+        ret = checksum_writer_create(target);
+        if (ret < 0)
+            goto target_cleanup;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
+
     /*
      * 3.
      * Call compute_data_blocks() in each Writer.
@@ -1078,7 +1403,6 @@
 
     /* check if we need to provide a copy of volume descriptors */
     if (opts->overwrite) {
-
         /*
          * Get a copy of the volume descriptors to be written in a DVD+RW
          * disc
@@ -1131,6 +1455,43 @@
         vol->vol_desc_type[0] = 255;
         memcpy(vol->std_identifier, "CD001", 5);
         vol->vol_desc_version[0] = 1;
+
+#ifdef Libisofs_with_checksumS
+
+        /* Write relocated superblock checksum tag */
+        tag_pos = voldesc_size / BLOCK_SIZE + 16 + 1;
+        if (target->md5_session_checksum) {
+            target->checksum_rlsb_tag_pos = tag_pos;
+            if (target->checksum_rlsb_tag_pos < 32) {
+                ret = iso_md5_start(&(target->checksum_ctx));
+                if (ret < 0)
+                    goto target_cleanup;
+                target->opts_overwrite = (char *) opts->overwrite;
+                iso_md5_compute(target->checksum_ctx, target->opts_overwrite,
+                                target->checksum_rlsb_tag_pos * 2048);
+                ret = iso_md5_write_tag(target, 4);
+                target->opts_overwrite = NULL; /* opts might not persist */
+                if (ret < 0)
+                    goto target_cleanup;
+            }
+            tag_pos++;
+        } 
+
+        /* Clean out eventual checksum tags */
+        for (i = tag_pos; i < 32; i++) {
+            int tag_type;
+            uint32_t pos, range_start, range_size, next_tag;
+            char md5[16];
+ 	
+            ret = iso_util_decode_md5_tag((char *)(opts->overwrite + i * 2048),
+                                          &tag_type, &pos, &range_start,
+                                          &range_size, &next_tag, md5, 0);
+            if (ret > 0)
+                opts->overwrite[i * 2048] = 0;
+        }
+
+#endif /* Libisofs_with_checksumS */
+
     }
 
     /*
@@ -1140,7 +1501,24 @@
     target->vol_space_size = target->curblock - target->ms_block;
     target->total_size = (off_t) target->vol_space_size * BLOCK_SIZE;
 
-    /* 4. Create and start writting thread */
+
+    /* 4. Create and start writing thread */
+
+#ifdef Libisofs_with_checksumS
+    if (target->md5_session_checksum) {
+        /* After any fake writes are done: Initialize image checksum context */
+        if (target->checksum_ctx != NULL)
+            iso_md5_end(&(target->checksum_ctx), target->image_md5);
+        ret = iso_md5_start(&(target->checksum_ctx));
+        if (ret < 0)
+            goto target_cleanup;
+    }
+    /* Dispose old image checksum buffer. The one of target is supposed to
+       get attached at the end of write_function(). */
+    iso_image_free_checksums(target->image, 0);
+    image_checksums_mad = 0;
+
+#endif /* Libisofs_with_checksumS */
 
     /* ensure the thread is created joinable */
     pthread_attr_init(&(target->th_attr));
@@ -1166,6 +1544,14 @@
     return ISO_SUCCESS;
 
     target_cleanup: ;
+
+#ifdef Libisofs_with_checksumS
+
+    if(image_checksums_mad) /* No checksums is better than mad checksums */
+      iso_image_free_checksums(target->image, 0);
+
+#endif /* Libisofs_with_checksumS */
+
     ecma119_image_free(target);
     return ret;
 }
@@ -1306,6 +1692,16 @@
         return ISO_CANCELED;
     }
 
+#ifdef Libisofs_with_checksumS
+
+    if (target->checksum_ctx != NULL) {
+        /* Add to image checksum */
+        target->checksum_counter += count;
+        iso_md5_compute(target->checksum_ctx, (char *) buf, (int) count);
+    }
+
+#endif /* Libisofs_with_checksumS */
+
     /* total size is 0 when writing the overwrite buffer */
     if (ret > 0 && (target->total_size != (off_t) 0)){
         unsigned int kbw, kbt;
@@ -1342,6 +1738,7 @@
     if (wopts == NULL) {
         return ISO_OUT_OF_MEM;
     }
+    wopts->scdbackup_tag_written = NULL;
 
     switch (profile) {
     case 0:
@@ -1371,6 +1768,14 @@
     wopts->fifo_size = 1024; /* 2 MB buffer */
     wopts->sort_files = 1; /* file sorting is always good */
 
+    wopts->system_area_data = NULL;
+    wopts->system_area_options = 0;
+    wopts->vol_creation_time = 0;
+    wopts->vol_modification_time = 0;
+    wopts->vol_expiration_time = 0;
+    wopts->vol_effective_time = 0;
+    wopts->vol_uuid[0]= 0;
+
     *opts = wopts;
     return ISO_SUCCESS;
 }
@@ -1382,6 +1787,8 @@
     }
 
     free(opts->output_charset);
+    if(opts->system_area_data != NULL)
+        free(opts->system_area_data);
     free(opts);
 }
 
@@ -1447,7 +1854,7 @@
     if (opts == NULL) {
         return ISO_NULL_POINTER;
     }
-    opts->omit_version_numbers = omit ? 1 : 0;
+    opts->omit_version_numbers = omit & 3;
     return ISO_SUCCESS;
 }
 
@@ -1483,7 +1890,7 @@
     if (opts == NULL) {
         return ISO_NULL_POINTER;
     }
-    opts->no_force_dots = no ? 1 : 0;
+    opts->no_force_dots = no & 3;
     return ISO_SUCCESS;
 }
 
@@ -1568,6 +1975,57 @@
     return ISO_SUCCESS;
 }
 
+int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    opts->md5_session_checksum = session & 1;
+    opts->md5_file_checksums = files & 3;
+
+#endif /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+}
+
+int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
+                                     char *name, char *timestamp,
+                                     char *tag_written)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    char eff_name[81], eff_time[19];
+    int i;
+
+    for (i = 0; name[i] != 0 && i < 80; i++)
+         if (isspace((int) ((unsigned char *) name)[i]))
+             eff_name[i] = '_';
+         else
+             eff_name[i] = name[i];
+    if (i == 0)
+        eff_name[i++] = '_';
+    eff_name[i] = 0;
+    for (i = 0; timestamp[i] != 0 && i < 18; i++)
+         if (isspace((int) ((unsigned char *) timestamp)[i]))
+             eff_time[i] = '_';
+         else
+             eff_time[i] = timestamp[i];
+    if (i == 0)
+        eff_time[i++] = '_';
+    eff_time[i] = 0;
+
+    sprintf(opts->scdbackup_tag_parm, "%s %s", eff_name, eff_time);
+
+    opts->scdbackup_tag_written = tag_written;
+    if (tag_written != NULL)
+        tag_written[0] = 0;
+
+#endif /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+}
+
 int iso_write_opts_set_replace_mode(IsoWriteOpts *opts, int dir_mode,
                                     int file_mode, int uid, int gid)
 {
@@ -1710,9 +2168,49 @@
 int iso_write_opts_get_data_start(IsoWriteOpts *opts, uint32_t *data_start,
                                   int flag)
 {
-    if(opts->data_start_lba == 0)
+    if (opts->data_start_lba == 0)
 	return ISO_ERROR;
     *data_start = opts->data_start_lba;
     return ISO_SUCCESS;
 }
 
+/*
+ * @param data     Either NULL or 32 kB of data. Do not submit less bytes !
+ * @param options  bit0 = apply GRUB protective msdos label
+ * @param flag     bit0 = invalidate any attached system area data
+ *                        same as data == NULL
+ */
+int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768],
+                                   int options, int flag)
+{
+    if (data == NULL || (flag & 1)) { /* Disable */
+        if (opts->system_area_data != NULL)
+            free(opts->system_area_data);
+        opts->system_area_data = NULL;
+    } else if (!(flag & 2)) {
+        if (opts->system_area_data == NULL) {
+            opts->system_area_data = calloc(32768, 1);
+            if (opts->system_area_data == NULL)
+                return ISO_OUT_OF_MEM;
+        }
+        memcpy(opts->system_area_data, data, 32768);
+    }
+    if (!(flag & 4))
+        opts->system_area_options = options & 3;
+    return ISO_SUCCESS;
+}
+
+int iso_write_opts_set_pvd_times(IsoWriteOpts *opts, 
+                        time_t vol_creation_time, time_t vol_modification_time,
+                        time_t vol_expiration_time, time_t vol_effective_time,
+                        char *vol_uuid)
+{
+    opts->vol_creation_time = vol_creation_time;
+    opts->vol_modification_time = vol_modification_time;
+    opts->vol_expiration_time = vol_expiration_time;
+    opts->vol_effective_time = vol_effective_time;
+    strncpy(opts->vol_uuid, vol_uuid, 16);
+    opts->vol_uuid[16] = 0;
+    return ISO_SUCCESS;
+}
+
--- libisofs/ecma119.h
+++ libisofs/ecma119.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_ECMA119_H_
@@ -56,8 +57,10 @@
     /**
      * Omit the version number (";1") at the end of the ISO-9660 identifiers.
      * Version numbers are usually not used.
+     * bit0= ECMA-119 and Joliet (for historical reasons)
+     * bit1= Joliet
      */
-    unsigned int omit_version_numbers :1;
+    unsigned int omit_version_numbers :2;
 
     /**
      * Allow ISO-9660 directory hierarchy to be deeper than 8 levels.
@@ -81,8 +84,10 @@
      * ISO-9660 forces filenames to have a ".", that separates file name from
      * extension. libisofs adds it if original filename doesn't has one. Set
      * this to 1 to prevent this behavior
+     * bit0= ECMA-119
+     * bit1= Joliet
      */
-    unsigned int no_force_dots :1;
+    unsigned int no_force_dots :2;
 
     /**
      * Allow lowercase characters in ISO-9660 filenames. By default, only
@@ -147,6 +152,30 @@
      */
     unsigned int dir_rec_mtime :1;
 
+#ifdef Libisofs_with_checksumS
+
+    /**
+     * Compute MD5 checksum for the whole session and record it as index 0 of
+     * the checksum blocks after the data area of the session. The layout and
+     * position of these blocks will be recorded in xattr "isofs.ca" of the
+     * root node. See see also API call iso_image_get_session_md5().
+     */
+    unsigned int md5_session_checksum :1;
+
+    /**
+     * Compute MD5 checksums for IsoFile objects and write them to blocks
+     * after the data area of the session. The layout and position of these
+     * blocks will be recorded in xattr "isofs.ca" of the root node.
+     * The indice of the MD5 sums will be recorded with the IsoFile directory
+     * entries as xattr "isofs.cx". See also API call iso_file_get_md5().
+     * bit0= compute individual checksums
+     * bit1= pre-compute checksum and compare it with actual one.
+     *       Raise MISHAP if mismatch.
+     */
+    unsigned int md5_file_checksums :2;
+
+#endif /* Libisofs_with_checksumS */
+
     /** If files should be sorted based on their weight. */
     unsigned int sort_files :1;
 
@@ -257,6 +286,38 @@
      */
     uint32_t data_start_lba;
 
+    /**
+     * If not empty: A text holding parameters "name" and "timestamp" for
+     * a scdbackup stream checksum tag. See scdbackup/README appendix VERIFY.
+     * It makes sense only for single session images which start at LBA 0.
+     * Such a tag may be part of a libisofs checksum tag block after the
+     * session tag line. It then covers the whole session up to its own start
+     * position.
+     */
+    char scdbackup_tag_parm[100];
+
+    /* If not NULL: A pointer to an application provided array with
+       at least 512 characters. The effectively written scdbackup tag
+       will be copied to this memory location.
+     */
+    char *scdbackup_tag_written;
+
+    /*
+     * See ecma119_image : System Area related information
+     */
+    char *system_area_data;
+    int system_area_options;
+
+    /* User settable PVD time stamps */
+    time_t vol_creation_time;
+    time_t vol_modification_time;
+    time_t vol_expiration_time;
+    time_t vol_effective_time;
+    /* To eventually override vol_creation_time and vol_modification_time
+     * by unconverted string with timezone 0
+     */
+    char vol_uuid[17];
+
 };
 
 typedef struct ecma119_image Ecma119Image;
@@ -287,11 +348,11 @@
     unsigned int always_gmt :1;
 
     /* relaxed constraints */
-    unsigned int omit_version_numbers :1;
+    unsigned int omit_version_numbers :2;
     unsigned int allow_deep_paths :1;
     unsigned int allow_longer_paths :1;
     unsigned int max_37_char_filenames :1;
-    unsigned int no_force_dots :1;
+    unsigned int no_force_dots :2;
     unsigned int allow_lowercase :1;
     unsigned int allow_full_ascii :1;
 
@@ -312,6 +373,13 @@
     /* Store in ECMA-119 timestamp mtime of source */
     unsigned int dir_rec_mtime :1;
 
+#ifdef Libisofs_with_checksumS
+
+    unsigned int md5_session_checksum :1;
+    unsigned int md5_file_checksums :2;
+
+#endif /* Libisofs_with_checksumS */
+
     /*
      * Mode replace. If one of these flags is set, the correspodent values are
      * replaced with values below.
@@ -333,18 +401,6 @@
      */
     int sort_files;
 
-
-#ifndef Libisofs_hardlink_matcheR
-
-    /* ts A90508 : <<< this is on its way out */
-    /**
-     * In the CD, each file must have an unique inode number. So each
-     * time we add a new file, this is incremented.
-     */
-    ino_t ino;
-
-#endif /* ! Libisofs_hardlink_matcheR */
-
     char *input_charset;
     char *output_charset;
 
@@ -398,7 +454,28 @@
      */
     struct el_torito_boot_catalog *catalog;
     IsoFileSrc *cat; /**< location of the boot catalog in the new image */
-    IsoFileSrc *bootimg; /**< location of the boot image in the new image */
+
+    int num_bootsrc;
+    IsoFileSrc **bootsrc; /* location of the boot images in the new image */
+
+    /*
+     * System Area related information
+     */
+    /* Content of an embedded boot image. Valid if not NULL.
+     * In that case it must point to a memory buffer at least 32 kB.
+     */
+    char *system_area_data;
+    /*
+     * bit0= make bytes 446 - 512 of the system area a partition
+     *       table which reserves partition 1 from byte 63*512 to the
+     *       end of the ISO image. Assumed are 63 secs/hed, 255 head/cyl.
+     *       (GRUB protective msdos label.)
+     *       This works with and without system_area_data.
+     * bit1= apply isohybrid MBR patching to the system area.
+     *       This works only with system_area_data plus ISOLINUX boot image
+     *       and only if not bit0 is set.
+     */
+    int system_area_options;
 
     /*
      * Number of pad blocks that we need to write. Padding blocks are blocks
@@ -421,12 +498,51 @@
     /* tree of files sources */
     IsoRBTree *files;
 
+#ifdef Libisofs_with_checksumS
+
+    unsigned int checksum_idx_counter;
+    void *checksum_ctx;
+    off_t checksum_counter;
+    uint32_t checksum_rlsb_tag_pos;
+    uint32_t checksum_sb_tag_pos;
+    uint32_t checksum_tree_tag_pos;
+    uint32_t checksum_tag_pos;
+    char image_md5[16];
+    char *checksum_buffer;
+    uint32_t checksum_array_pos;
+    uint32_t checksum_range_start;
+    uint32_t checksum_range_size;
+
+    char *opts_overwrite; /* Points to IsoWriteOpts->overwrite.
+                             Use only underneath ecma119_image_new()
+                             and if not NULL*/
+
+    /* ??? Is there a reason why we copy lots of items from IsoWriteOpts
+           rather than taking ownership of the IsoWriteOpts object which
+           is submitted with ecma119_image_new() ?
+     */
+
+    char scdbackup_tag_parm[100];
+    char *scdbackup_tag_written;
+
+#endif /* Libisofs_with_checksumS */
+
     /* Buffer for communication between burn_source and writer thread */
     IsoRingBuffer *buffer;
 
     /* writer thread descriptor */
     pthread_t wthread;
     pthread_attr_t th_attr;
+
+    /* User settable PVD time stamps */
+    time_t vol_creation_time;
+    time_t vol_modification_time;
+    time_t vol_expiration_time;
+    time_t vol_effective_time;
+    /* To eventually override vol_creation_time and vol_modification_time
+     * by unconverted string with timezone 0
+     */
+    char vol_uuid[17];
 };
 
 #define BP(a,b) [(b) - (a) + 1]
--- libisofs/ecma119_tree.c
+++ libisofs/ecma119_tree.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "ecma119_tree.h"
@@ -63,18 +64,18 @@
     } else {
         if (img->max_37_char_filenames) {
             isoname = iso_r_fileid(ascii_name, 36, relaxed,
-                                   img->no_force_dots ? 0 : 1);
+                                   (img->no_force_dots & 1) ? 0 : 1);
         } else if (img->iso_level == 1) {
             if (relaxed) {
                 isoname = iso_r_fileid(ascii_name, 11, relaxed,
-                                       img->no_force_dots ? 0 : 1);
+                                       (img->no_force_dots & 1) ? 0 : 1);
             } else {
                 isoname = iso_1_fileid(ascii_name);
             }
         } else {
             if (relaxed) {
                 isoname = iso_r_fileid(ascii_name, 30, relaxed,
-                                       img->no_force_dots ? 0 : 1);
+                                       (img->no_force_dots & 1) ? 0 : 1);
             } else {
                 isoname = iso_2_fileid(ascii_name);
             }
@@ -103,42 +104,9 @@
         return ISO_OUT_OF_MEM;
     }
 
-    /* take a ref to the IsoNode */
     ecma->node = iso;
     iso_node_ref(iso);
-
     ecma->nlink = 1;
-
-#ifndef Libisofs_hardlink_matcheR
-
-    /* ts A90503 : This is obsolete with Libisofs_hardlink_matcheR
-                   which will later hand out image inode numbers for all. */
-
-#ifdef Libisofs_hardlink_prooF
-
-    /* Looking only for valid ISO image inode numbers. */
-    {
-        unsigned int fs_id;
-        dev_t dev_id;
-        int ret;
-
-        ret = iso_node_get_id(iso, &fs_id, &dev_id, &(ecma->ino), 1);
-        if (ret < 0) {
-            return ret;
-        } else if (ret == 0) {
-            /* What has not got a valid ISO image inode yet, gets it now. */
-            ecma->ino = img_give_ino_number(img->image, 0);
-        }
-    }
-
-#else /* Libisofs_hardlink_prooF */
-    
-    /* TODO #00009 : add true support for harlinks and inode numbers */
-    ecma->ino = ++img->ino;
-
-#endif /* ! Libisofs_hardlink_prooF */
-#endif /* ! Libisofs_hardlink_matcheR */
-
     *node = ecma;
     return ISO_SUCCESS;
 }
@@ -1023,16 +991,12 @@
     }
     img->root = root;
 
-#ifdef Libisofs_hardlink_matcheR
-
     iso_msg_debug(img->image->id, "Matching hardlinks...");
     ret = match_hardlinks(img, img->root, 0);
     if (ret < 0) {
         return ret;
     }
 
-#endif /* ! Libisofs_hardlink_matcheR */
-
     iso_msg_debug(img->image->id, "Sorting the low level tree...");
     sort_tree(root);
 
--- libisofs/ecma119_tree.h
+++ libisofs/ecma119_tree.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_ECMA119_TREE_H_
--- libisofs/eltorito.c
+++ libisofs/eltorito.c
@@ -1,9 +1,11 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
+ * Copyright (c) 2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "eltorito.h"
@@ -16,9 +18,10 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 
 /**
- * This table should be written with accuracy values at offset
+ * This table should be written with the actual values at offset
  * 8 of boot image, when used ISOLINUX boot loader
  */
 struct boot_info_table {
@@ -54,6 +57,19 @@
     uint8_t sign2;
 };
 
+/* API */
+int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id)
+{
+    bootimg->platform_id = id;
+    return 1;
+}
+
+/* API */
+int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg)
+{
+    return bootimg->platform_id;
+}
+
 /**
  * Sets the load segment for the initial boot image. This is only for
  * no emulation boot images, and is a NOP for other image types.
@@ -65,6 +81,14 @@
     bootimg->load_seg = segment;
 }
 
+/* API */
+int el_torito_get_load_seg(ElToritoBootImage *bootimg)
+{
+   if (bootimg->load_seg < 0)
+       return 0xffff - bootimg->load_seg;
+   return bootimg->load_seg;
+}
+ 
 /**
  * Sets the number of sectors (512b) to be load at load segment during
  * the initial boot procedure. This is only for no emulation boot images,
@@ -77,6 +101,14 @@
     bootimg->load_size = sectors;
 }
 
+/* API */
+int el_torito_get_load_size(ElToritoBootImage *bootimg)
+{
+   if (bootimg->load_size < 0)
+       return 0xffff - bootimg->load_size;
+   return bootimg->load_size;
+}
+
 /**
  * Marks the specified boot image as not bootable
  */
@@ -85,8 +117,50 @@
     bootimg->bootable = 0;
 }
 
+/* API */
+int el_torito_get_bootable(ElToritoBootImage *bootimg)
+{   
+    return !!bootimg->bootable;
+}
+
+/* API */
+int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
+{
+    memcpy(bootimg->id_string, id_string, 28);
+    return 1;
+}
+
+/* API */
+int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28])
+{
+    
+    memcpy(id_string, bootimg->id_string, 28);
+    return 1;
+}
+
+/* API */
+int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
+{
+    memcpy(bootimg->selection_crit, crit, 20);
+    return 1;
+}
+
+/* API */
+int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20])
+{
+    
+    memcpy(crit, bootimg->selection_crit, 20);
+    return 1;
+}
+
+/* API */
+int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag)
+{
+    return bootimg->seems_boot_info_table;
+}
+
 /**
- * Specifies that this image needs to be patched. This involves the writting
+ * Specifies that this image needs to be patched. This involves the writing
  * of a 56 bytes boot information table at offset 8 of the boot image file.
  * The original boot image file won't be modified.
  * This is needed for isolinux boot images.
@@ -105,7 +179,7 @@
  *        bitmask style flag. The following values are defined:
  *
  *        bit 0 -> 1 to path the image, 0 to not
- *                 Patching the image involves the writting of a 56 bytes
+ *                 Patching the image involves the writing of a 56 bytes
  *                 boot information table at offset 8 of the boot image file.
  *                 The original boot image file won't be modified. This is needed
  *                 to allow isolinux images to be bootable.
@@ -123,31 +197,36 @@
     return ISO_SUCCESS;
 }
 
-/* TODO getter for boot image properties should be exposed
- * useful when reading discs */
-int el_torito_get_boot_media_type(const ElToritoBootImage *bootimg)
+/* API */
+int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag)
+{
+    return bootimg->isolinux_options & 0x03;
+}
+
+/* API */
+int el_torito_get_boot_media_type(ElToritoBootImage *bootimg,
+                                  enum eltorito_boot_media_type *media_type)
 {
     if (bootimg) {
         switch (bootimg->type) {
         case 1:
         case 2:
         case 3:
-            return ELTORITO_FLOPPY_EMUL;
-            break;
+            *media_type = ELTORITO_FLOPPY_EMUL;
+            return 1;
         case 4:
-            return ELTORITO_HARD_DISC_EMUL;
-            break;
+            *media_type = ELTORITO_HARD_DISC_EMUL;
+            return 1;
         case 0:
-            return ELTORITO_NO_EMUL;
-            break;
+            *media_type = ELTORITO_NO_EMUL;
+            return 1;
         default:
             /* should never happen */
             return ISO_ASSERT_FAILURE;
             break;
         }
-    } else {
-        return ISO_WRONG_ARG_VALUE;
     }
+    return ISO_WRONG_ARG_VALUE;
 }
 
 static
@@ -332,10 +411,15 @@
     boot->image = (IsoFile*)imgfile;
     iso_node_ref(imgfile); /* get our ref */
     boot->bootable = 1;
+    boot->seems_boot_info_table = 0;
+    boot->isolinux_options = 0;
     boot->type = boot_media_type;
-    boot->load_size = load_sectors;
     boot->partition_type = partition_type;
-
+    boot->load_seg = 0;
+    boot->load_size = load_sectors;
+    boot->platform_id = 0; /* 80x86 */
+    memset(boot->id_string, 0, sizeof(boot->id_string));
+    memset(boot->selection_crit, 0, sizeof(boot->selection_crit));
     if (bootimg) {
         *bootimg = boot;
     }
@@ -348,7 +432,7 @@
                              const char *catalog_path,
                              ElToritoBootImage **boot)
 {
-    int ret;
+    int ret, i;
     struct el_torito_boot_catalog *catalog;
     ElToritoBootImage *boot_image= NULL;
     IsoBoot *cat_node= NULL;
@@ -407,13 +491,17 @@
     }
 
     /* creates the catalog with the given image */
-    catalog = malloc(sizeof(struct el_torito_boot_catalog));
+    catalog = calloc(1, sizeof(struct el_torito_boot_catalog));
     if (catalog == NULL) {
         ret = ISO_OUT_OF_MEM;
         goto boot_image_cleanup;
     }
-    catalog->image = boot_image;
+    catalog->num_bootimages = 1;
+    catalog->bootimages[0] = boot_image;
+    for (i = 1; i < Libisofs_max_boot_imageS; i++)
+        catalog->bootimages[i] = NULL;
     catalog->node = cat_node;
+    catalog->sort_weight = 1000;                            /* slightly high */
     iso_node_ref((IsoNode*)cat_node);
     image->bootcat = catalog;
 
@@ -436,7 +524,7 @@
 }
 
 /**
- * Get El-Torito boot image of an ISO image, if any.
+ * Get the boot catalog and the El-Torito default boot image of an ISO image.
  *
  * This can be useful, for example, to check if a volume read from a previous
  * session or an existing image is bootable. It can also be useful to get
@@ -480,10 +568,10 @@
 
     /* ok, image is bootable */
     if (boot) {
-        *boot = image->bootcat->image;
+        *boot = image->bootcat->bootimages[0];
     }
     if (imgnode) {
-        *imgnode = image->bootcat->image->image;
+        *imgnode = image->bootcat->bootimages[0]->image;
     }
     if (catnode) {
         *catnode = image->bootcat->node;
@@ -491,6 +579,40 @@
     return ISO_SUCCESS;
 }
 
+int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
+               ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag)
+{
+    int i;
+    struct el_torito_boot_catalog *cat;
+
+    if (image == NULL)
+        return ISO_NULL_POINTER;
+    if (image->bootcat == NULL)
+        return 0;
+    cat = image->bootcat;
+    *num_boots = cat->num_bootimages;
+    *boots = NULL;
+    *bootnodes = NULL;
+    if (*num_boots <= 0)
+        return 0;
+    *boots = calloc(*num_boots, sizeof(ElToritoBootImage *));
+    *bootnodes = calloc(*num_boots, sizeof(IsoFile *));
+    if(*boots == NULL || *bootnodes == NULL) {
+        if (*boots != NULL)
+            free(*boots);
+        if (*bootnodes != NULL)
+            free(*bootnodes);
+        *boots = NULL;
+        *bootnodes = NULL;
+        return ISO_OUT_OF_MEM;
+    }
+    for (i = 0; i < *num_boots; i++) {
+        (*boots)[i] = cat->bootimages[i];
+        (*bootnodes)[i] = image->bootcat->bootimages[i]->image;
+    }
+    return 1;
+}
+
 /**
  * Removes the El-Torito bootable image.
  *
@@ -505,28 +627,68 @@
         return;
 
     /*
-     * remove catalog node from its parent
-     * (the reference will be disposed next)
+     * remove catalog node from its parent and dispose it
+     * (another reference is with the catalog)
      */
-    iso_node_take((IsoNode*)image->bootcat->node);
+    if (iso_node_get_parent((IsoNode*) image->bootcat->node) != NULL) {
+        iso_node_take((IsoNode*) image->bootcat->node);
+        iso_node_unref((IsoNode*) image->bootcat->node);
+    }
 
     /* free boot catalog and image, including references to nodes */
     el_torito_boot_catalog_free(image->bootcat);
     image->bootcat = NULL;
 }
 
+/* API */
+int iso_image_add_boot_image(IsoImage *image, const char *image_path,
+                             enum eltorito_boot_media_type type, int flag,
+                             ElToritoBootImage **boot)
+{
+    int ret;
+    struct el_torito_boot_catalog *catalog = image->bootcat;
+    ElToritoBootImage *boot_img;
+
+    if (catalog->num_bootimages >= Libisofs_max_boot_imageS)
+        return ISO_BOOT_IMAGE_OVERFLOW;
+    ret = create_image(image, image_path, type, &boot_img);
+    if (ret < 0) 
+        return ret;
+    catalog->bootimages[catalog->num_bootimages] = boot_img;
+    catalog->num_bootimages++;
+    if (boot != NULL)
+        *boot = boot_img;
+    return 1;
+}
+
+/* API */
+int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight)
+{
+    if (image->bootcat == NULL)
+        return 0;
+    image->bootcat->sort_weight = sort_weight;
+    return 1;
+}
+
 void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat)
 {
     struct el_torito_boot_image *image;
+    int i;
 
     if (cat == NULL) {
         return;
     }
 
-    image = cat->image;
-    iso_node_unref((IsoNode*)image->image);
-    free(image);
-    iso_node_unref((IsoNode*)cat->node);
+    for (i = 0; i < Libisofs_max_boot_imageS; i++) {
+        image = cat->bootimages[i];
+        if (image == NULL)
+    continue;
+        if ((IsoNode*)image->image != NULL)
+            iso_node_unref((IsoNode*)image->image);
+        free(image);
+    }
+    if ((IsoNode*)cat->node != NULL)
+        iso_node_unref((IsoNode*)cat->node);
     free(cat);
 }
 
@@ -537,11 +699,12 @@
 {
     Ecma119Image *target;
     uint8_t buffer[BLOCK_SIZE];
-    int offset; /* -1 if stream is not openned */
+    int offset; /* -1 if stream is not opened */
 };
 
 static void
-write_validation_entry(uint8_t *buf)
+write_validation_entry(uint8_t *buf, uint8_t platform_id,
+                       uint8_t id_string[24])
 {
     size_t i;
     int checksum;
@@ -549,10 +712,10 @@
     struct el_torito_validation_entry *ve =
         (struct el_torito_validation_entry*)buf;
     ve->header_id[0] = 1;
-    ve->platform_id[0] = 0; /* 0: 80x86, 1: PowerPC, 2: Mac */
+    ve->platform_id[0] = platform_id;
+    memcpy(ve->id_string, id_string, sizeof(ve->id_string));
     ve->key_byte1[0] = 0x55;
     ve->key_byte2[0] = 0xAA;
-
     /* calculate the checksum, to ensure sum of all words is 0 */
     checksum = 0;
     for (i = 0; i < sizeof(struct el_torito_validation_entry); i += 2) {
@@ -561,35 +724,64 @@
     iso_lsb(ve->checksum, checksum, 2);
 }
 
+static void
+write_section_header(uint8_t *buf, Ecma119Image *t, int idx, int num_entries)
+{
+    int pi;
+    char *id_string;
+
+    struct el_torito_section_header *e =
+        (struct el_torito_section_header *) buf;
+
+    /* 0x90 = more section headers follow , 0x91 = final section */
+    e->header_indicator[0] = 0x90 + (idx == t->catalog->num_bootimages - 1);
+    pi= e->platform_id[0] = t->catalog->bootimages[idx]->platform_id;
+    e->num_entries[0] = num_entries & 0xff;
+    e->num_entries[1] = (num_entries >> 8) & 0xff;;
+    id_string = (char *) e->id_string;
+    memcpy(id_string,  t->catalog->bootimages[idx]->id_string,
+           sizeof(e->id_string));
+}
+
 /**
  * Write one section entry.
- * Currently this is used only for default image (the only supported just now)
+ * Usable for the Default Entry
+ * and for Section Entries with Selection criteria type == 0
  */
 static void
-write_section_entry(uint8_t *buf, Ecma119Image *t)
+write_section_entry(uint8_t *buf, Ecma119Image *t, int idx)
 {
     struct el_torito_boot_image *img;
     struct el_torito_section_entry *se =
         (struct el_torito_section_entry*)buf;
 
-    img = t->catalog->image;
+    img = t->catalog->bootimages[idx];
 
     se->boot_indicator[0] = img->bootable ? 0x88 : 0x00;
     se->boot_media_type[0] = img->type;
     iso_lsb(se->load_seg, img->load_seg, 2);
     se->system_type[0] = img->partition_type;
     iso_lsb(se->sec_count, img->load_size, 2);
-    iso_lsb(se->block, t->bootimg->sections[0].block, 4);
+    iso_lsb(se->block, t->bootsrc[idx]->sections[0].block, 4);
+    se->selec_criteria[0] = img->selection_crit[0];
+    memcpy(se->vendor_sc, img->selection_crit + 1, 19);
 }
 
 static
 int catalog_open(IsoStream *stream)
 {
+    int i, j, k, num_entries;
     struct catalog_stream *data;
+    uint8_t *wpt;
+    struct el_torito_boot_catalog *cat;
+    struct el_torito_boot_image **boots;
+
     if (stream == NULL) {
         return ISO_NULL_POINTER;
     }
     data = stream->data;
+    cat = data->target->catalog;
+    boots = cat->bootimages;
 
     if (data->offset != -1) {
         return ISO_FILE_ALREADY_OPENED;
@@ -598,11 +790,36 @@
     memset(data->buffer, 0, BLOCK_SIZE);
 
     /* fill the buffer with the catalog contents */
-    write_validation_entry(data->buffer);
+    write_validation_entry(data->buffer,
+                           boots[0]->platform_id, boots[0]->id_string);
 
-    /* write default entry */
-    write_section_entry(data->buffer + 32, data->target);
+    /* write default entry = first boot image */
+    write_section_entry(data->buffer + 32, data->target, 0);
+
+    /* IMPORTANT: The maximum number of boot images must fit into BLOCK_SIZE */
+    wpt = data->buffer + 64;
+    for (i = 1; i < cat->num_bootimages; ) {
+        /* Look ahead and put images of same platform_id and id_string
+           into the same section */
+        for (j = i + 1; j < cat->num_bootimages; j++) {
+             if (boots[i]->platform_id != boots[j]->platform_id)
+        break;
+             for (k = 0; k < sizeof(boots[i]->id_string); k++)
+                 if (boots[i]->id_string[k] != boots[j]->id_string[k])
+             break;
+             if (k < sizeof(boots[i]->id_string))
+        break;
+        }
+        num_entries = j - i;
 
+        write_section_header(wpt, data->target, i, num_entries);
+        wpt += 32;
+        for (j = 0; j < num_entries; j++) {
+            write_section_entry(wpt,  data->target, i);
+            wpt += 32;
+            i++;
+        }
+    }
     data->offset = 0;
     return ISO_SUCCESS;
 }
@@ -702,11 +919,11 @@
         return ISO_NULL_POINTER;
     }
 
-    str = malloc(sizeof(IsoStream));
+    str = calloc(1, sizeof(IsoStream));
     if (str == NULL) {
         return ISO_OUT_OF_MEM;
     }
-    data = malloc(sizeof(struct catalog_stream));
+    data = calloc(1, sizeof(struct catalog_stream));
     if (str == NULL) {
         free(str);
         return ISO_OUT_OF_MEM;
@@ -740,7 +957,7 @@
         return ISO_SUCCESS;
     }
 
-    file = malloc(sizeof(IsoFileSrc));
+    file = calloc(1, sizeof(IsoFileSrc));
     if (file == NULL) {
         return ISO_OUT_OF_MEM;
     }
@@ -753,9 +970,10 @@
 
     /* fill fields */
     file->prev_img = 0; /* TODO allow copy of old img catalog???? */
+    file->checksum_index = 0;
     file->nsections = 1;
     file->sections = calloc(1, sizeof(struct iso_file_section));
-    file->sort_weight = 1000; /* slightly high */
+    file->sort_weight = target->catalog->sort_weight;
     file->stream = stream;
 
     ret = iso_file_src_add(target, file, src);
@@ -771,27 +989,26 @@
 /******************* EL-TORITO WRITER *******************************/
 
 /**
- * Patch an isolinux boot image.
+ * Insert boot info table content into buf.
  *
  * @return
  *      1 on success, 0 error (but continue), < 0 error
  */
-static
-int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize)
+int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
+                         uint32_t boot_lba, uint32_t imgsize)
 {
     struct boot_info_table *info;
     uint32_t checksum;
-    size_t offset;
+    uint32_t offset;
 
-    if (imgsize < 64) {
-        return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
-            "Isolinux image too small. We won't patch it.");
-    }
+    info = (struct boot_info_table *) (buf + 8);
+    if (imgsize < 64)
+        return ISO_ISOLINUX_CANT_PATCH;
 
     /* compute checksum, as the the sum of all 32 bit words in boot image
      * from offset 64 */
     checksum = 0;
-    offset = (size_t) 64;
+    offset = 64;
 
     while (offset <= imgsize - 4) {
         checksum += iso_read_lsb(buf + offset, 4);
@@ -806,16 +1023,36 @@
         checksum += iso_read_lsb(buf + offset, imgsize - offset);
     }
 
-    /* patch boot info table */
-    info = (struct boot_info_table*)(buf + 8);
     /*memset(info, 0, sizeof(struct boot_info_table));*/
-    iso_lsb(info->bi_pvd, t->ms_block + 16, 4);
-    iso_lsb(info->bi_file, t->bootimg->sections[0].block, 4);
+    iso_lsb(info->bi_pvd, pvd_lba, 4);
+    iso_lsb(info->bi_file, boot_lba, 4);
     iso_lsb(info->bi_length, imgsize, 4);
     iso_lsb(info->bi_csum, checksum, 4);
+    memset(buf + 24, 0, 40);
     return ISO_SUCCESS;
 }
 
+/**
+ * Patch an isolinux boot image.
+ *
+ * @return
+ *      1 on success, 0 error (but continue), < 0 error
+ */
+static
+int patch_boot_image(uint8_t *buf, Ecma119Image *t, size_t imgsize, int idx)
+{
+    int ret;
+
+    if (imgsize < 64) {
+        return iso_msg_submit(t->image->id, ISO_ISOLINUX_CANT_PATCH, 0,
+            "Isolinux image too small. We won't patch it.");
+    }
+    ret = make_boot_info_table(buf, t->ms_block + (uint32_t) 16,
+                               t->bootsrc[idx]->sections[0].block,
+                               (uint32_t) imgsize);
+    return ret;
+}
+
 static
 int eltorito_writer_compute_data_blocks(IsoImageWriter *writer)
 {
@@ -824,7 +1061,11 @@
      * this is a good place to do so.
      */
     Ecma119Image *t;
-    int ret;
+    int ret, idx;
+    size_t size;
+    uint8_t *buf;
+    IsoStream *new = NULL;
+    IsoStream *original = NULL;
 
     if (writer == NULL) {
         return ISO_NULL_POINTER;
@@ -832,14 +1073,17 @@
 
     t = writer->target;
 
-    if (t->catalog->image->isolinux_options & 0x01) {
-        /* we need to patch the image */
-        size_t size;
-        uint8_t *buf;
-        IsoStream *new = NULL;
-        IsoStream *original = t->bootimg->stream;
+    /* Patch the boot image info tables if indicated */
+    for (idx = 0; idx < t->catalog->num_bootimages; idx++) {
+        if (!(t->catalog->bootimages[idx]->isolinux_options & 0x01))
+    continue;
+        original = t->bootsrc[idx]->stream;
         size = (size_t) iso_stream_get_size(original);
-        buf = malloc(size);
+
+        /* >>> BOOT ts B00428 :
+               check whether size is not too large for buffering */;
+
+        buf = calloc(1, size);
         if (buf == NULL) {
             return ISO_OUT_OF_MEM;
         }
@@ -854,7 +1098,7 @@
         }
 
         /* ok, patch the read buffer */
-        ret = patch_boot_image(buf, t, size);
+        ret = patch_boot_image(buf, t, size, idx);
         if (ret < 0) {
             return ret;
         }
@@ -865,7 +1109,7 @@
         if (ret < 0) {
             return ret;
         }
-        t->bootimg->stream = new;
+        t->bootsrc[idx]->stream = new;
         iso_stream_unref(original);
     }
     return ISO_SUCCESS;
@@ -916,12 +1160,12 @@
 
 int eltorito_writer_create(Ecma119Image *target)
 {
-    int ret;
+    int ret, idx;
     IsoImageWriter *writer;
     IsoFile *bootimg;
     IsoFileSrc *src;
 
-    writer = malloc(sizeof(IsoImageWriter));
+    writer = calloc(1, sizeof(IsoImageWriter));
     if (writer == NULL) {
         return ISO_OUT_OF_MEM;
     }
@@ -947,16 +1191,19 @@
             return ret;
         }
     }
-    bootimg = target->catalog->image->image;
-    ret = iso_file_src_create(target, bootimg, &src);
-    if (ret < 0) {
-        return ret;
-    }
-    target->bootimg = src;
 
-    /* if we have selected to patch the image, it needs to be copied always */
-    if (target->catalog->image->isolinux_options & 0x01) {
-        src->prev_img = 0;
+    for (idx = 0; idx < target->catalog->num_bootimages; idx++) {
+        bootimg = target->catalog->bootimages[idx]->image;
+        ret = iso_file_src_create(target, bootimg, &src);
+        if (ret < 0) {
+            return ret;
+        }
+        target->bootsrc[idx] = src;
+
+        /* For patching an image, it needs to be copied always */
+        if (target->catalog->bootimages[idx]->isolinux_options & 0x01) {
+            src->prev_img = 0;
+        }
     }
 
     /* we need the bootable volume descriptor */
--- libisofs/eltorito.h
+++ libisofs/eltorito.h
@@ -1,9 +1,11 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
+ * Copyright (c) 2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /**
@@ -26,9 +28,18 @@
     IsoNode node;
 };
 
+/* Not more than 32 so that all entries fit into 2048 bytes */
+#define Libisofs_max_boot_imageS 32
+
 struct el_torito_boot_catalog {
     IsoBoot *node; /* node of the catalog */
-    struct el_torito_boot_image *image; /* default boot image */
+
+    int num_bootimages;
+    struct el_torito_boot_image *bootimages[Libisofs_max_boot_imageS];
+                                                  /* [0]= default boot image */
+
+    /* Weight value for image sorting */
+    int sort_weight;
 };
 
 struct el_torito_boot_image {
@@ -36,15 +47,26 @@
 
     unsigned int bootable:1; /**< If the entry is bootable. */
     /**
+     * Whether the boot image seems to contain a boot_info_table
+     */
+    unsigned int seems_boot_info_table:1;
+    /**
      * isolinux options
      * bit 0 -> whether to patch image
-     * bit 1 -> whether to create isolinux image
+     * bit 1 -> whether to put built-in isolinux 3.72 isohybrid-MBR into image
+     *          System Area (deprecated)
      */
     unsigned int isolinux_options:2;
     unsigned char type; /**< The type of image */
     unsigned char partition_type; /**< type of partition for HD-emul images */
     short load_seg; /**< Load segment for the initial boot image. */
     short load_size; /**< Number of sectors to load. */
+
+    /* Byte 1 of Validation Entry or Section Header Entry:
+       0= 80x86, 1= PowerPC, 2= Mac, 0xef= EFI */
+    uint8_t platform_id;
+    uint8_t id_string[28];
+    uint8_t selection_crit[20];
 };
 
 /** El-Torito, 2.1 */
@@ -74,8 +96,8 @@
 struct el_torito_section_header {
     uint8_t header_indicator    BP(1, 1);
     uint8_t platform_id         BP(2, 2);
-    uint8_t number              BP(3, 4);
-    uint8_t character           BP(5, 32);
+    uint8_t num_entries         BP(3, 4);
+    uint8_t id_string           BP(5, 32);
 };
 
 /** El-Torito, 2.4 */
@@ -105,4 +127,14 @@
  */
 int eltorito_writer_create(Ecma119Image *target);
 
+/**
+ * Insert boot info table content into buf.
+ *
+ * @return
+ *      1 on success, 0 error (but continue), < 0 error
+ */
+int make_boot_info_table(uint8_t *buf, uint32_t pvd_lba,
+                         uint32_t boot_lba, uint32_t imgsize);
+
+
 #endif /* LIBISO_ELTORITO_H */
--- libisofs/filesrc.c
+++ libisofs/filesrc.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "filesrc.h"
@@ -14,11 +15,20 @@
 #include "image.h"
 #include "stream.h"
 
+#ifdef Libisofs_with_checksumS
+#include "md5.h"
+#endif /*  Libisofs_with_checksumS */
+
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 
 
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
 int iso_file_src_cmp(const void *n1, const void *n2)
 {
     int ret;
@@ -44,6 +54,11 @@
     dev_t dev_id;
     ino_t ino_id;
 
+#ifdef Libisofs_with_checksumS
+    int cret, no_md5= 0;
+    void *xipt = NULL;
+#endif
+
     if (img == NULL || file == NULL || src == NULL) {
         return ISO_NULL_POINTER;
     }
@@ -88,11 +103,54 @@
     /* insert the filesrc in the tree */
     ret = iso_rbtree_insert(img->files, fsrc, (void**)src);
     if (ret <= 0) {
+
+#ifdef Libisofs_with_checksumS
+
+        if (ret == 0 && (*src)->checksum_index > 0) {
+            /* Duplicate file source was mapped to previously registered source
+            */
+            cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
+            if (cret < 0)
+                ret = cret;
+        }
+
+#endif /* Libisofs_with_checksumS */
+
         free(fsrc->sections);
         free(fsrc);
         return ret;
     }
     iso_stream_ref(fsrc->stream);
+
+#ifdef Libisofs_with_checksumS
+
+    if ((img->md5_file_checksums & 1) &&
+        file->from_old_session && img->appendable) {
+        ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func,
+                                  &xipt);
+        if (ret <= 0)
+            ret = iso_node_get_xinfo((IsoNode *) file, checksum_cx_xinfo_func,
+                                      &xipt);
+        if (ret <= 0)
+            /* Omit MD5 indexing with old image nodes which have no MD5 */
+            no_md5 = 1;
+    }
+
+    if ((img->md5_file_checksums & 1) && !no_md5) {
+        img->checksum_idx_counter++;
+        if (img->checksum_idx_counter < 0x7fffffff) {
+            fsrc->checksum_index = img->checksum_idx_counter;
+        } else {
+            fsrc->checksum_index= 0;
+            img->checksum_idx_counter= 0x7fffffff; /* keep from rolling over */
+        }
+        cret = iso_file_set_isofscx(file, (*src)->checksum_index, 0);
+        if (cret < 0)
+            return cret;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
     return ISO_SUCCESS;
 }
 
@@ -241,41 +299,45 @@
 static
 int filesrc_read(IsoFileSrc *file, char *buf, size_t count)
 {
-    size_t bytes = 0;
+    size_t got;
 
-    /* loop to ensure the full buffer is filled */
-    do {
-        ssize_t result;
-        result = iso_stream_read(file->stream, buf + bytes, count - bytes);
-        if (result < 0) {
-            /* fill buffer with 0s and return */
-            memset(buf + bytes, 0, count - bytes);
-            return result;
-        }
-        if (result == 0)
-            break;
-        bytes += result;
-    } while (bytes < count);
-
-    if (bytes < count) {
-        /* eof */
-        memset(buf + bytes, 0, count - bytes);
-        return 0;
-    } else {
-        return 1;
-    }
+    return iso_stream_read_buffer(file->stream, buf, count, &got);
 }
 
+#ifdef Libisofs_with_checksumS
+
+/* @return 1=ok, md5 is valid,
+           0= not ok, go on,
+          <0 fatal error, abort 
+*/  
+
+static
+int filesrc_make_md5(Ecma119Image *t, IsoFileSrc *file, char md5[16], int flag)
+{
+    return iso_stream_make_md5(file->stream, md5, 0);
+}
+
+#endif /* Libisofs_with_checksumS */
+
 static
 int filesrc_writer_write_data(IsoImageWriter *writer)
 {
-    int res;
+    int res, ret, was_error;
     size_t i, b;
     Ecma119Image *t;
     IsoFileSrc *file;
     IsoFileSrc **filelist;
     char name[PATH_MAX];
     char buffer[BLOCK_SIZE];
+    off_t file_size;
+    uint32_t nblocks;
+
+#ifdef Libisofs_with_checksumS
+    void *ctx= NULL;
+    char md5[16], pre_md5[16];
+    int pre_md5_valid = 0;
+#endif
+
 
     if (writer == NULL) {
         return ISO_ASSERT_FAILURE;
@@ -288,8 +350,19 @@
 
     i = 0;
     while ((file = filelist[i++]) != NULL) {
+        was_error = 0;
+        file_size = iso_file_src_get_size(file);
+        nblocks = DIV_UP(file_size, BLOCK_SIZE);
+ 
+#ifdef Libisofs_with_checksumS
+
+        pre_md5_valid = 0; 
+        if (file->checksum_index > 0 && (t->md5_file_checksums & 2)) {
+            /* Obtain an MD5 of content by a first read pass */
+            pre_md5_valid = filesrc_make_md5(t, file, pre_md5, 0);
+        }
 
-        uint32_t nblocks = DIV_UP(iso_file_src_get_size(file), BLOCK_SIZE);
+#endif /* Libisofs_with_checksumS */
 
         res = filesrc_open(file);
         iso_stream_get_file_name(file->stream, name);
@@ -299,28 +372,33 @@
              * 0's to image
              */
             iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
+            was_error = 1;
             res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
                       "File \"%s\" can't be opened. Filling with 0s.", name);
             if (res < 0) {
-                return res; /* aborted due to error severity */
+                ret = res; /* aborted due to error severity */
+                goto ex;
             }
             memset(buffer, 0, BLOCK_SIZE);
             for (b = 0; b < nblocks; ++b) {
                 res = iso_write(t, buffer, BLOCK_SIZE);
                 if (res < 0) {
                     /* ko, writer error, we need to go out! */
-                    return res;
+                    ret = res;
+                    goto ex;
                 }
             }
             continue;
         } else if (res > 1) {
             iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
+            was_error = 1;
             res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, 0,
                       "Size of file \"%s\" has changed. It will be %s", name,
                       (res == 2 ? "truncated" : "padded with 0's"));
             if (res < 0) {
                 filesrc_close(file);
-                return res; /* aborted due to error severity */
+                ret = res; /* aborted due to error severity */
+                goto ex;
             }
         }
 #ifdef LIBISOFS_VERBOSE_DEBUG
@@ -329,6 +407,18 @@
         }
 #endif
 
+ 
+#ifdef Libisofs_with_checksumS
+ 
+        if (file->checksum_index > 0) {
+            /* initialize file checksum */
+            res = iso_md5_start(&ctx);
+            if (res <= 0)
+                file->checksum_index = 0;
+        }
+
+#endif /* Libisofs_with_checksumS */
+ 
         /* write file contents to image */
         for (b = 0; b < nblocks; ++b) {
             int wres;
@@ -341,8 +431,25 @@
             if (wres < 0) {
                 /* ko, writer error, we need to go out! */
                 filesrc_close(file);
-                return wres;
+                ret = wres;
+                goto ex;
             }
+ 
+#ifdef Libisofs_with_checksumS
+
+            if (file->checksum_index > 0) {
+                /* Add to file checksum */
+                if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
+                    res = BLOCK_SIZE;
+                else
+                    res = file_size - b * BLOCK_SIZE;
+                res = iso_md5_compute(ctx, buffer, res);
+                if (res <= 0)
+                    file->checksum_index = 0;
+            }
+
+#endif /* Libisofs_with_checksumS */
+    
         }
 
         filesrc_close(file);
@@ -350,6 +457,7 @@
         if (b < nblocks) {
             /* premature end of file, due to error or eof */
             iso_report_errfile(name, ISO_FILE_CANT_WRITE, 0, 0);
+            was_error = 1;
             if (res < 0) {
                 /* error */
                 res = iso_msg_submit(t->image->id, ISO_FILE_CANT_WRITE, res,
@@ -361,7 +469,8 @@
             }
 
             if (res < 0) {
-                return res; /* aborted due error severity */
+                ret = res; /* aborted due error severity */
+                goto ex;
             }
 
             /* fill with 0s */
@@ -372,13 +481,68 @@
                 res = iso_write(t, buffer, BLOCK_SIZE);
                 if (res < 0) {
                     /* ko, writer error, we need to go out! */
-                    return res;
+                    ret = res;
+                    goto ex;
+                }
+ 
+#ifdef Libisofs_with_checksumS
+
+                if (file->checksum_index > 0) {
+                    /* Add to file checksum */
+                    if (file_size - b * BLOCK_SIZE > BLOCK_SIZE)
+                        res = BLOCK_SIZE;
+                    else
+                        res = file_size - b * BLOCK_SIZE;
+                    res = iso_md5_compute(ctx, buffer, res);
+                    if (res <= 0)
+                        file->checksum_index = 0;
+                }
+
+#endif /* Libisofs_with_checksumS */
+    
+            }
+        }
+
+#ifdef Libisofs_with_checksumS
+
+        if (file->checksum_index > 0 &&
+            file->checksum_index <= t->checksum_idx_counter) {
+            /* Obtain checksum and dispose checksum context */
+            res = iso_md5_end(&ctx, md5);
+            if (res <= 0)
+                file->checksum_index = 0;
+            if ((t->md5_file_checksums & 2) && pre_md5_valid > 0 &&
+                !was_error) {
+                if (! iso_md5_match(md5, pre_md5)) {
+                    /* Issue MISHAP event */
+                    iso_report_errfile(name, ISO_MD5_STREAM_CHANGE, 0, 0);
+                    was_error = 1;
+                    res = iso_msg_submit(t->image->id, ISO_MD5_STREAM_CHANGE,0,
+           "Content of file '%s' changed while it was written into the image.",
+                                         name);
+                    if (res < 0) {
+                        ret = res; /* aborted due to error severity */
+                        goto ex;
+                    }
                 }
             }
+            /* Write md5 into checksum buffer at file->checksum_index */
+            memcpy(t->checksum_buffer + 16 * file->checksum_index, md5, 16);
         }
+
+#endif /* Libisofs_with_checksumS */
+
     }
 
-    return ISO_SUCCESS;
+    ret = ISO_SUCCESS;
+ex:;
+
+#ifdef Libisofs_with_checksumS
+    if (ctx != NULL) /* avoid any memory leak */
+        iso_md5_end(&ctx, md5);
+#endif
+
+    return ret;
 }
 
 static
@@ -393,9 +557,9 @@
 {
     IsoImageWriter *writer;
 
-    writer = malloc(sizeof(IsoImageWriter));
+    writer = calloc(1, sizeof(IsoImageWriter));
     if (writer == NULL) {
-        return ISO_ASSERT_FAILURE;
+        return ISO_OUT_OF_MEM;
     }
 
     writer->compute_data_blocks = filesrc_writer_compute_data_blocks;
--- libisofs/filesrc.h
+++ libisofs/filesrc.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_FILESRC_H_
 #define LIBISO_FILESRC_H_
@@ -18,6 +19,13 @@
 {
     unsigned int prev_img :1; /**< if the file comes from a previous image */
 
+#ifdef Libisofs_with_checksumS
+
+    unsigned int checksum_index :31;
+
+#endif /* Libisofs_with_checksumS */
+
+
     /** File Sections of the file in the image */
     struct iso_file_section *sections;
     int nsections;
@@ -43,7 +51,7 @@
  * @param src
  *      Will be filled with a pointer to the IsoFileSrc
  * @return
- *      1 on success, < 0 on error
+ *      1 if new object was created, 0 if object existed, < 0 on error
  */
 int iso_file_src_create(Ecma119Image *img, IsoFile *file, IsoFileSrc **src);
 
--- libisofs/filter.c
+++ libisofs/filter.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
--- libisofs/filter.h
+++ libisofs/filter.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2008 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_FILTER_H_
 #define LIBISO_FILTER_H_
--- libisofs/filters/external.c
+++ libisofs/filters/external.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  *
  * It implements a filter facility which can pipe a IsoStream into an external
  * process, read its output and forward it as IsoStream output to an IsoFile.
--- libisofs/filters/gzip.c
+++ libisofs/filters/gzip.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  *
  * It implements a filter facility which can pipe a IsoStream into gzip
  * compression resp. uncompression, read its output and forward it as IsoStream
@@ -70,6 +71,7 @@
 
 } GzipFilterRuntime;
 
+#ifdef Libisofs_with_zliB
 
 static
 int gzip_running_destroy(GzipFilterRuntime **running, int flag)
@@ -96,9 +98,7 @@
     if (o == NULL) {
         return ISO_OUT_OF_MEM;
     }
-#ifdef Libisofs_with_zliB
     memset(&(o->strm), 0, sizeof(o->strm));
-#endif
     o->in_buffer = NULL;
     o->out_buffer = NULL;
     o->in_buffer_size = 0;
@@ -106,9 +106,7 @@
     o->rpt = NULL;
     o->in_counter = 0;
     o->out_counter = 0;
-#ifdef Libisofs_with_zliB
     o->do_flush = Z_NO_FLUSH;
-#endif
     o->error_ret = 1;
 
     o->in_buffer_size= 2048;
@@ -123,6 +121,7 @@
     gzip_running_destroy(running, 0);
     return -1;
 }
+#endif /* Libisofs_with_zliB */
 
 
 /* ---------------------------- GzipFilterStreamData --------------------- */
@@ -164,12 +163,17 @@
 
 
 
+#ifdef Libisofs_with_zliB
+
 /* Each individual GzipFilterStreamData needs a unique id number. */
 /* >>> This is very suboptimal:
        The counter can rollover.
 */
 static ino_t gzip_ino_id = 0;
 
+#endif /* Libisofs_with_zliB */
+
+
 static
 int gzip_stream_uncompress(IsoStream *stream, void *buf, size_t desired);
 
@@ -571,13 +575,14 @@
 /* ------------------------------------------------------------------------- */
 
 
+#ifdef Libisofs_with_zliB
+
 static
 void gzip_filter_free(FilterContext *filter)
 {
     /* no data are allocated */;
 }
 
-
 /*
  * @param flag bit1= Install a decompression filter
  */
@@ -626,7 +631,6 @@
     return ISO_SUCCESS;
 }
 
-
 /* To be called by iso_file_add_filter().
  * The FilterContext input parameter is not furtherly needed for the 
  * emerging IsoStream.
@@ -672,6 +676,7 @@
     return ISO_SUCCESS;
 }
 
+#endif /* Libisofs_with_zliB */
 
 /*
  * @param flag bit0= if_block_reduction rather than if_reduction
--- libisofs/filters/xor_encrypt.c
+++ libisofs/filters/xor_encrypt.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2008 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "../libisofs.h"
--- libisofs/filters/zisofs.c
+++ libisofs/filters/zisofs.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  *
  * It implements a filter facility which can pipe a IsoStream into zisofs
  * compression resp. uncompression, read its output and forward it as IsoStream
@@ -912,6 +913,8 @@
 }
 
 
+#ifdef Libisofs_with_zliB
+
 /* Produce a parameter object suitable for iso_file_add_filter().
  * It may be disposed by free() after all those calls are made.
  *
@@ -938,6 +941,7 @@
     return ISO_SUCCESS;
 }
 
+#endif /* Libisofs_with_zliB */
 
 /*
  * @param flag bit0= if_block_reduction rather than if_reduction
--- libisofs/find.c
+++ libisofs/find.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2008 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
--- libisofs/fs_image.c
+++ libisofs/fs_image.c
@@ -1,10 +1,11 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
- * Copyright (c) 2009 Thomas Schmitt
+ * Copyright (c) 2009 - 2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
@@ -30,6 +31,11 @@
 #include <stdio.h>
 
 
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
 /**
  * Options for image reading.
  * There are four kind of options:
@@ -62,6 +68,7 @@
     unsigned int nojoliet : 1; /*< Do not read Joliet extensions */
     unsigned int noiso1999 : 1; /*< Do not read ISO 9660:1999 enhanced tree */
     unsigned int noaaip : 1; /* Do not read AAIP extension for xattr and ACL */
+    unsigned int nomd5 : 1;  /* Do not read MD5 array */
 
     /**
      * Hand out new inode numbers and overwrite eventually read PX inode
@@ -95,6 +102,12 @@
      */
     int auto_input_charset;
 
+
+    /** 
+     * Enable or disable loading of the first 32768 bytes of the session and
+     * submission by iso_write_opts_set_system_area(data, 0).
+     */
+    int load_system_area;
 };
 
 /**
@@ -249,6 +262,11 @@
      */
     int aaip_load;
 
+    /** Whether the MD5 array shall be read if available.
+     *  1 = yes , 0 = no
+     */
+    int md5_load;
+
     /** Whether AAIP is present. Version major.minor = major * 100 + minor
      *  Value -1 means that no AAIP ER was detected yet.
      */
@@ -261,12 +279,20 @@
 
     /* el-torito information */
     unsigned int eltorito : 1; /* is el-torito available */
-    unsigned int bootable:1; /**< If the entry is bootable. */
-    unsigned char type; /**< The type of image */
-    unsigned char partition_type; /**< type of partition for HD-emul images */
-    short load_seg; /**< Load segment for the initial boot image. */
-    short load_size; /**< Number of sectors to load. */
-    uint32_t imgblock; /**< Block for El-Torito boot image */
+    int num_bootimgs;
+    unsigned char platform_ids[Libisofs_max_boot_imageS];
+    unsigned char id_strings[Libisofs_max_boot_imageS][28];
+    unsigned char selection_crits[Libisofs_max_boot_imageS][20];
+    unsigned char boot_flags[Libisofs_max_boot_imageS]; /* bit0= bootable */
+    unsigned char media_types[Libisofs_max_boot_imageS];
+    unsigned char partition_types[Libisofs_max_boot_imageS];
+    short load_segs[Libisofs_max_boot_imageS];
+    short load_sizes[Libisofs_max_boot_imageS];
+    /** Block addresses of for El-Torito boot images.
+        Needed to recognize them when the get read from the directory tree.
+     */
+    uint32_t bootblocks[Libisofs_max_boot_imageS];
+
     uint32_t catblock; /**< Block for El-Torito catalog */
 
     /* Whether inode numbers from PX entries shall be discarded */
@@ -1089,33 +1115,6 @@
 }
 
 
-#ifndef Libisofs_hardlink_prooF
-
-/**
- * A global counter for default inode numbers for the ISO image filesystem.
- * @param fs    The filesystem where the number shall be used
- * @param flag  bit0= reset count
- */
-static
-ino_t fs_give_ino_number(IsoImageFilesystem *fs, int flag)
-{
-    _ImageFsData *fsdata;
-
-    fsdata = (_ImageFsData*)fs->data;
-    if (flag & 1)
-        fsdata->inode_counter = 0;
-    fsdata->inode_counter++;
-    if (fsdata->inode_counter == 0) {
-
-        /* >>> raise alert because of inode rollover */;
-
-    }
-    return fsdata->inode_counter;
-}
-
-#endif /* ! Libisofs_hardlink_prooF */
-
-
 /**
  *
  * @param src
@@ -1640,56 +1639,11 @@
         return ISO_SUCCESS;
     }
 
-#ifdef Libisofs_hardlink_prooF
-
     /* Production of missing inode numbers is delayed until the image is
        complete. Then all nodes which shall get a new inode number will
        be served.
     */
 
-#else /* Libisofs_hardlink_prooF */
-
-#ifdef Libisofs_new_fs_image_inO
-
-    if (fsdata->rr != RR_EXT_112) {
-        if (fsdata->rr == 0) {
-            atts.st_nlink = 1;
-        }
-    }
-    atts.st_ino = fs_give_ino_number(fs, 0);
-
-#else /* Libisofs_new_fs_image_inO */
-
-
-    /* ts Nov 25 2008: TODO
-       This seems not fully consistent with read_rr_PX() which decides
-       by (px->len_sue[0] == 44) whether an inode number is present or not.
-       What if read_rr_PX finds a PX of length 36 in a IEEE_1282 image ?
-       It is illegal but could confuse the image by duplicate inode numbers.
-
-       Regrettably it is not enough to just use single default numbers.
-       If only one number misses in the image, then all would need to be
-       defaulted by the following iso_global_inode code.
-
-       Why do duplicate inode numbers confuse the file lengths, anyway ?
-       (See ticket 144)
-    */
-    if (fsdata->rr != RR_EXT_112) {
-        /*
-         * Only RRIP 1.12 provides valid inode numbers. If not, it is not easy
-         * to generate those serial numbers, and we use extend block instead.
-         * It BREAKS POSIX SEMANTICS, but its suitable for our needs
-         */
-        atts.st_ino = fs_give_ino_number(fs, 0);
-        if (fsdata->rr == 0) {
-            atts.st_nlink = 1;
-        }
-    }
-
-#endif /* ! Libisofs_new_fs_image_inO */
-
-#endif /* ! Libisofs_hardlink_prooF */
-
     /*
      * if we haven't RR extensions, or a needed TF time stamp is not present,
      * we use plain iso recording time
@@ -2166,19 +2120,15 @@
 }
 
 static
-int read_pvm(_ImageFsData *data, uint32_t block)
+int read_pvd_block(IsoDataSource *src, uint32_t block, uint8_t *buffer,
+                   uint32_t *image_size)
 {
     int ret;
     struct ecma119_pri_vol_desc *pvm;
-    struct ecma119_dir_record *rootdr;
-    uint8_t buffer[BLOCK_SIZE];
 
-    /* read PVM */
-    ret = data->src->read_block(data->src, block, buffer);
-    if (ret < 0) {
+    ret = src->read_block(src, block, buffer);
+    if (ret < 0)
         return ret;
-    }
-
     pvm = (struct ecma119_pri_vol_desc *)buffer;
 
     /* sanity checks */
@@ -2188,20 +2138,55 @@
 
         return ISO_WRONG_PVD;
     }
+    if (image_size != NULL)
+        *image_size = iso_read_bb(pvm->vol_space_size, 4, NULL);
+    return ISO_SUCCESS;
+}
 
+static
+int read_pvm(_ImageFsData *data, uint32_t block)
+{
+    int ret;
+    struct ecma119_pri_vol_desc *pvm;
+    struct ecma119_dir_record *rootdr;
+    uint8_t buffer[BLOCK_SIZE];
+
+    ret = read_pvd_block(data->src, block, buffer, NULL);
+    if (ret < 0)
+        return ret;
     /* ok, it is a valid PVD */
+    pvm = (struct ecma119_pri_vol_desc *)buffer;
 
     /* fill volume attributes  */
     /* TODO take care of input charset */
-    data->volset_id = strcopy((char*)pvm->vol_set_id, 128);
-    data->volume_id = strcopy((char*)pvm->volume_id, 32);
-    data->publisher_id = strcopy((char*)pvm->publisher_id, 128);
-    data->data_preparer_id = strcopy((char*)pvm->data_prep_id, 128);
-    data->system_id = strcopy((char*)pvm->system_id, 32);
-    data->application_id = strcopy((char*)pvm->application_id, 128);
-    data->copyright_file_id = strcopy((char*)pvm->copyright_file_id, 37);
-    data->abstract_file_id = strcopy((char*)pvm->abstract_file_id, 37);
-    data->biblio_file_id = strcopy((char*)pvm->bibliographic_file_id, 37);
+    data->volset_id = iso_util_strcopy_untail((char*)pvm->vol_set_id, 128);
+    data->volume_id = iso_util_strcopy_untail((char*)pvm->volume_id, 32);
+    data->publisher_id =
+               iso_util_strcopy_untail((char*)pvm->publisher_id, 128);
+    data->data_preparer_id =
+               iso_util_strcopy_untail((char*)pvm->data_prep_id, 128);
+    data->system_id = iso_util_strcopy_untail((char*)pvm->system_id, 32);
+    data->application_id =
+               iso_util_strcopy_untail((char*)pvm->application_id, 128);
+    data->copyright_file_id =
+               iso_util_strcopy_untail((char*) pvm->copyright_file_id, 37);
+    data->abstract_file_id =
+               iso_util_strcopy_untail((char*) pvm->abstract_file_id, 37);
+    data->biblio_file_id =
+               iso_util_strcopy_untail((char*) pvm->bibliographic_file_id, 37);
+    if (data->copyright_file_id[0] == '_' && data->copyright_file_id[1] == 0 &&
+        data->abstract_file_id[0] == '_' && data->abstract_file_id[1] == 0 &&
+        data->biblio_file_id[0] == '_' && data->biblio_file_id[1] == 0) {
+        /* This is bug output from libisofs <= 0.6.23 . The texts mean file
+           names and should have been empty to indicate that there are no such
+           files. It is obvious that not all three roles can be fulfilled by
+           one file "_" so that one cannot spoil anything by assuming them
+           empty now.
+        */
+        data->copyright_file_id[0] = 0;
+        data->abstract_file_id[0] = 0;
+        data->biblio_file_id[0] = 0;
+    } 
 
     data->nblocks = iso_read_bb(pvm->vol_space_size, 4, NULL);
 
@@ -2226,11 +2211,13 @@
 static
 int read_el_torito_boot_catalog(_ImageFsData *data, uint32_t block)
 {
-    int ret;
+    int ret, i, rx, last_done, idx;
     struct el_torito_validation_entry *ve;
-    struct el_torito_default_entry *entry;
+    struct el_torito_section_header *sh;
+    struct el_torito_section_entry *entry; /* also usable as default_entry */
     unsigned char buffer[BLOCK_SIZE];
 
+    data->num_bootimgs = 0;
     ret = data->src->read_block(data->src, block, buffer);
     if (ret < 0) {
         return ret;
@@ -2241,41 +2228,154 @@
     /* check if it is a valid catalog (TODO: check also the checksum)*/
     if ( (ve->header_id[0] != 1) || (ve->key_byte1[0] != 0x55)
          || (ve->key_byte2[0] != 0xAA) ) {
-
-        return iso_msg_submit(data->msgid, ISO_WRONG_EL_TORITO, 0,
+        iso_msg_submit(data->msgid, ISO_WRONG_EL_TORITO, 0,
                       "Wrong or damaged El-Torito Catalog. El-Torito info "
                       "will be ignored.");
+        return ISO_WRONG_EL_TORITO;
     }
 
     /* check for a valid platform */
-    if (ve->platform_id[0] != 0) {
-        return iso_msg_submit(data->msgid, ISO_UNSUPPORTED_EL_TORITO, 0,
-                     "Unsupported El-Torito platform. Only 80x86 is "
+    if (ve->platform_id[0] != 0 && ve->platform_id[0] != 0xef) {
+        iso_msg_submit(data->msgid, ISO_UNSUPPORTED_EL_TORITO, 0,
+                     "Unsupported El-Torito platform. Only 80x86 and EFI are "
                      "supported. El-Torito info will be ignored.");
+        return ISO_UNSUPPORTED_EL_TORITO;
     }
 
     /* ok, once we are here we assume it is a valid catalog */
 
     /* parse the default entry */
-    entry = (struct el_torito_default_entry *)(buffer + 32);
+    entry = (struct el_torito_section_entry *)(buffer + 32);
 
     data->eltorito = 1;
-    data->bootable = entry->boot_indicator[0] ? 1 : 0;
-    data->type = entry->boot_media_type[0];
-    data->partition_type = entry->system_type[0];
-    data->load_seg = iso_read_lsb(entry->load_seg, 2);
-    data->load_size = iso_read_lsb(entry->sec_count, 2);
-    data->imgblock = iso_read_lsb(entry->block, 4);
+    /* The Default Entry is declared mandatory */
+    data->num_bootimgs = 1;
+    data->platform_ids[0] = ve->platform_id[0];
+    memcpy(data->id_strings[0], ve->id_string, 24);
+    memset(data->id_strings[0] + 24, 0, 4);
+    data->boot_flags[0] = entry->boot_indicator[0] ? 1 : 0;
+    data->media_types[0] = entry->boot_media_type[0];
+    data->partition_types[0] = entry->system_type[0];
+    data->load_segs[0] = iso_read_lsb(entry->load_seg, 2);
+    data->load_sizes[0] = iso_read_lsb(entry->sec_count, 2);
+    data->bootblocks[0] = iso_read_lsb(entry->block, 4);
+    /* The Default Entry has no selection criterion */
+    memset(data->selection_crits[0], 0, 20);
+
+    /* Read eventual more entries from the boot catalog */
+    last_done = 0;
+    for (rx = 64; (buffer[rx] & 0xfe) == 0x90 && !last_done; rx += 32) {
+        last_done = buffer[rx] & 1;
+        /* Read Section Header */
+        sh = (struct el_torito_section_header *) (buffer + rx);
+        for (i = 0; i < sh->num_entries[0]; i++) {
+            rx += 32;
+            if (data->num_bootimgs >= Libisofs_max_boot_imageS) {
+                ret = iso_msg_submit(data->msgid, ISO_EL_TORITO_WARN, 0,
+                                "Too many boot images found. List truncated.");
+                goto after_bootblocks;
+            }
+            /* Read bootblock from section entry */
+            entry = (struct el_torito_section_entry *)(buffer + rx);
+            idx = data->num_bootimgs;
+            data->platform_ids[idx] = sh->platform_id[0];
+            memcpy(data->id_strings[idx], sh->id_string, 28);
+            data->boot_flags[idx] = entry->boot_indicator[0] ? 1 : 0;
+            data->media_types[idx] = entry->boot_media_type[0];
+            data->partition_types[idx] = entry->system_type[0];
+            data->load_segs[idx] = iso_read_lsb(entry->load_seg, 2);
+            data->load_sizes[idx] = iso_read_lsb(entry->sec_count, 2);
+            data->bootblocks[idx] = iso_read_lsb(entry->block, 4);
+            data->selection_crits[idx][0] = entry->selec_criteria[0];
+            memcpy(data->selection_crits[idx] + 1, entry->vendor_sc, 19);
+            data->num_bootimgs++;
+        }
+    }
+after_bootblocks:;
+    return ISO_SUCCESS;
+}
 
-    /* TODO #00018 : check if there are more entries in the boot catalog */
 
-    return ISO_SUCCESS;
+/*
+ @return 1= ok, checked, go on with loading
+         2= no checksum tags found, go on with loading
+        <0= libisofs error
+            especially ISO_SB_TREE_CORRUPTED
+*/
+static
+int iso_src_check_sb_tree(IsoDataSource *src, uint32_t start_lba, int flag)
+{
+    int tag_type, ret;
+    char block[2048], md5[16];
+    int desired = (1 << 2);
+    void *ctx = NULL;
+    uint32_t next_tag = 0, i;
+    
+    ret = iso_md5_start(&ctx);
+    if (ret < 0)
+        goto ex;
+    if (start_lba == 0)
+         desired |= (1 << 4);
+    for (i = 0; i < 32; i++) {
+        ret = src->read_block(src, start_lba + i, (uint8_t *) block);
+        if (ret < 0)
+            goto ex;
+        ret = 0;
+        if (i >= 16)
+            ret = iso_util_eval_md5_tag(block, desired, start_lba + i,
+                                      ctx, start_lba, &tag_type, &next_tag, 0);
+        iso_md5_compute(ctx, block, 2048);
+        if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
+            ret = ISO_SB_TREE_CORRUPTED;
+        if (ret < 0)
+            goto ex;
+        if (ret == 1)
+    break;
+    }
+    if (i >= 32) {
+        ret = 2;
+        goto ex;
+    }
+    if (tag_type == 4) {
+        /* Relocated Superblock: restart checking at real session start */
+        if (next_tag < 32) {
+            /* Non plausible session_start address */
+            ret = ISO_SB_TREE_CORRUPTED;
+            iso_msg_submit(-1, ret, 0, NULL);
+            goto ex;
+        }
+        /* Check real session */
+        ret = iso_src_check_sb_tree(src, next_tag, 0);
+        goto ex;
+    }
+
+    /* Go on with tree */
+    for (i++; start_lba + i <= next_tag; i++) {
+        ret = src->read_block(src, start_lba + i, (uint8_t *) block);
+        if (ret < 0)
+            goto ex;
+        if (start_lba + i < next_tag)
+            iso_md5_compute(ctx, block, 2048);
+    }
+    ret = iso_util_eval_md5_tag(block, (1 << 3), start_lba + i - 1,
+                                ctx, start_lba, &tag_type, &next_tag, 0);
+    if (ret == ISO_MD5_AREA_CORRUPTED || ret == ISO_MD5_TAG_MISMATCH)
+        ret = ISO_SB_TREE_CORRUPTED;
+    if (ret < 0)
+        goto ex;
+
+    ret = 1;
+ex:
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+    return ret;
 }
 
+
 int iso_image_filesystem_new(IsoDataSource *src, struct iso_read_opts *opts,
                              int msgid, IsoImageFilesystem **fs)
 {
-    int ret;
+    int ret, i;
     uint32_t block;
     IsoImageFilesystem *ifs;
     _ImageFsData *data;
@@ -2311,11 +2411,16 @@
     data->dir_mode = opts->dir_mode & ~S_IFMT;
     data->msgid = msgid;
     data->aaip_load = !opts->noaaip;
+    data->md5_load = !opts->nomd5;
     data->aaip_version = -1;
     data->make_new_ino = opts->make_new_ino;
+    data->num_bootimgs = 0;
+    for (i = 0; i < Libisofs_max_boot_imageS; i++)
+        data->bootblocks[i] = 0;
     data->inode_counter = 0;
     data->px_ino_status = 0;
 
+
     data->local_charset = strdup(iso_get_local_charset(0));
     if (data->local_charset == NULL) {
         ret = ISO_OUT_OF_MEM;
@@ -2335,6 +2440,24 @@
 
     /* read Volume Descriptors and ensure it is a valid image */
 
+#ifdef Libisofs_with_checksumS
+
+    if (data->md5_load) {
+        /* From opts->block on : check for superblock and tree tags */;
+        ret = iso_src_check_sb_tree(src, opts->block, 0);
+        if (ret < 0) {
+            iso_msgs_submit(0,
+                "Image loading aborted due to MD5 mismatch of image tree data",
+                            0, "FAILURE", 0);
+            iso_msgs_submit(0,
+                     "You may override this refusal by disabling MD5 checking",
+                            0, "HINT", 0);
+            goto fs_cleanup;
+        }
+    }
+
+#endif /* Libisofs_with_checksumS */
+
     /* 1. first, open the filesystem */
     ifs_fs_open(ifs);
 
@@ -2364,21 +2487,18 @@
                     || vol->vol_desc_version[0] != 1
                     || strncmp((char*)vol->boot_sys_id,
                                "EL TORITO SPECIFICATION", 23)) {
-
-                    ret = iso_msg_submit(data->msgid,
+                    iso_msg_submit(data->msgid,
                           ISO_UNSUPPORTED_EL_TORITO, 0,
                           "Unsupported Boot Vol. Desc. Only El-Torito "
                           "Specification, Version 1.0 Volume "
                           "Descriptors are supported. Ignoring boot info");
-                    if (ret < 0) {
+                } else {
+                    data->catblock = iso_read_lsb(vol->boot_catalog, 4);
+                    ret = read_el_torito_boot_catalog(data, data->catblock);
+                    if (ret < 0 && ret != ISO_UNSUPPORTED_EL_TORITO &&
+                        ret != ISO_WRONG_EL_TORITO) {
                         goto fs_cleanup;
                     }
-                    break;
-                }
-                data->catblock = iso_read_lsb(vol->boot_catalog, 4);
-                ret = read_el_torito_boot_catalog(data, data->catblock);
-                if (ret < 0) {
-                    goto fs_cleanup;
                 }
             }
             break;
@@ -2428,11 +2548,8 @@
              */
             break;
         default:
-            ret = iso_msg_submit(data->msgid, ISO_UNSUPPORTED_VD, 0,
-                         "Ignoring Volume descriptor %x.", buffer[0]);
-            if (ret < 0) {
-                goto fs_cleanup;
-            }
+            iso_msg_submit(data->msgid, ISO_UNSUPPORTED_VD, 0,
+                           "Ignoring Volume descriptor %x.", buffer[0]);
             break;
         }
         block++;
@@ -2552,7 +2669,7 @@
 int image_builder_create_node(IsoNodeBuilder *builder, IsoImage *image,
                               IsoFileSource *src, IsoNode **node)
 {
-    int ret;
+    int ret, idx;
     struct stat info;
     IsoNode *new;
     char *name;
@@ -2664,11 +2781,16 @@
                 new = (IsoNode*) file;
                 new->refcount = 0;
 
-                if (fsdata->eltorito && data->sections[0].block == fsdata->imgblock) {
+                for (idx = 0; idx < fsdata->num_bootimgs; idx++)
+                    if (fsdata->eltorito && data->sections[0].block ==
+                        fsdata->bootblocks[idx])
+                break;
+                if (idx < fsdata->num_bootimgs) {
                     /* it is boot image node */
-                    if (image->bootcat->image->image != NULL) {
+
+                    if (image->bootcat->bootimages[idx]->image != NULL) {
                         ret = iso_msg_submit(image->id, ISO_EL_TORITO_WARN, 0,
-                                "More than one image node has been found.");
+             "More than one ISO node has been found for the same boot image.");
                         if (ret < 0) {
                             free(name);
                             iso_stream_unref(stream);
@@ -2676,7 +2798,7 @@
                         }
                     } else {
                         /* and set the image node */
-                        image->bootcat->image->image = file;
+                        image->bootcat->bootimages[idx]->image = file;
                         new->refcount++;
                     }
                 }
@@ -2713,13 +2835,9 @@
             }
             link->dest = strdup(dest);
             link->node.type = LIBISO_SYMLINK;
-
-#ifdef Libisofs_hardlink_matcheR
             link->fs_id = ISO_IMAGE_FS_ID;
             link->st_dev = info.st_dev;
             link->st_ino = info.st_ino;
-#endif
-
             new = (IsoNode*) link;
             new->refcount = 0;
         }
@@ -2738,13 +2856,9 @@
             }
             special->dev = info.st_rdev;
             special->node.type = LIBISO_SPECIAL;
-
-#ifdef Libisofs_hardlink_matcheR
             special->fs_id = ISO_IMAGE_FS_ID;
             special->st_dev = info.st_dev;
             special->st_ino = info.st_ino;
-#endif
-
             new = (IsoNode*) special;
             new->refcount = 0;
         }
@@ -2771,8 +2885,6 @@
         goto failure;
     }
 
-#ifdef Libisofs_hardlink_prooF
-
     /* Attach ino as xinfo if valid and no IsoStream is involved */
     if (info.st_ino != 0 && (info.st_mode & S_IFMT) != S_IFREG &&
         !fsdata->make_new_ino) {
@@ -2781,8 +2893,6 @@
             goto failure;
     }
 
-#endif /* Libisofs_hardlink_prooF */
-
     *node = new;
     return ISO_SUCCESS;
 
@@ -2828,7 +2938,7 @@
  * accessible from the ISO filesystem.
  */
 static
-int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image,
+int create_boot_img_filesrc(IsoImageFilesystem *fs, IsoImage *image, int idx,
                             IsoFileSource **src)
 {
     int ret;
@@ -2845,25 +2955,7 @@
 
     memset(&atts, 0, sizeof(struct stat));
     atts.st_mode = S_IFREG;
-
-#ifdef Libisofs_hardlink_prooF
-
     atts.st_ino = img_give_ino_number(image, 0);
-
-#else /* Libisofs_hardlink_prooF */
-
-#ifdef Libisofs_new_fs_image_inO
-
-    atts.st_ino = fs_give_ino_number(fs, 0);
-
-#else /* Libisofs_new_fs_image_inO */
-
-    atts.st_ino = fsdata->imgblock; /* not the best solution, but... */
-
-#endif /* ! Libisofs_new_fs_image_inO */
-
-#endif /* ! Libisofs_hardlink_prooF */
-
     atts.st_nlink = 1;
 
     /*
@@ -2903,8 +2995,7 @@
     ifsdata->parent = NULL;
     ifsdata->info = atts;
     ifsdata->name = NULL;
-
-    ifsdata->sections[0].block = fsdata->imgblock;
+    ifsdata->sections[0].block = fsdata->bootblocks[idx];
     ifsdata->sections[0].size = BLOCK_SIZE;
     ifsdata->nsections = 1;
 
@@ -2921,12 +3012,112 @@
     return ret;
 }
 
+/** ??? >>> ts B00428 : should the max size become public ? */
+#define Libisofs_boot_image_max_sizE (4096*1024)
+
+/** Guess which of the loaded boot images contain boot information tables.
+    Set boot->seems_boot_info_table accordingly.
+*/
+static
+int iso_image_eval_boot_info_table(IsoImage *image, struct iso_read_opts *opts,
+                         IsoDataSource *src, uint32_t iso_image_size, int flag)
+{
+    int i, ret, section_count, todo, chunk;
+    uint32_t img_lba, img_size, boot_pvd_found, image_pvd, alleged_size;
+    struct iso_file_section *sections = NULL;
+    struct el_torito_boot_image *boot;
+    uint8_t *boot_image_buf = NULL, boot_info_found[16], buf[BLOCK_SIZE];
+    IsoStream *stream = NULL;
+    IsoFile *boot_file;
+
+    if (image->bootcat == NULL)
+        return ISO_SUCCESS;
+    for (i = 0; i < image->bootcat->num_bootimages; i++) {
+        boot = image->bootcat->bootimages[i];
+        boot_file = boot->image;
+        boot->seems_boot_info_table = 0;
+        img_size = iso_file_get_size(boot_file);
+        if (img_size > Libisofs_boot_image_max_sizE || img_size < 64)
+    continue;
+        img_lba = 0;
+        sections = NULL;
+        ret = iso_file_get_old_image_sections(boot_file,
+                                              &section_count, &sections, 0);
+        if (ret == 1 && section_count > 0)
+            img_lba = sections[0].block;
+        if (sections != NULL) {
+            free(sections);
+            sections = NULL;
+        }
+        if(img_lba == 0)
+    continue;
+
+        boot_image_buf = calloc(1, img_size);
+        if (boot_image_buf == NULL) {
+            ret = ISO_OUT_OF_MEM;
+            goto ex;
+        }
+        stream = iso_file_get_stream(boot_file);
+        ret = iso_stream_open(stream);
+        if (ret < 0) {
+            stream = NULL;
+            goto ex;
+        }
+        for (todo = img_size; todo > 0; ) {
+          if (todo > BLOCK_SIZE)
+              chunk = BLOCK_SIZE;
+          else
+              chunk = todo;
+          ret = iso_stream_read(stream, boot_image_buf + (img_size - todo),
+                                chunk);
+          if (ret != chunk) {
+            ret = (ret < 0) ? ret : ISO_FILE_READ_ERROR;
+            goto ex;
+          }
+          todo -= chunk;
+        }
+        iso_stream_close(stream);
+        stream = NULL;
+        
+        memcpy(boot_info_found, boot_image_buf + 8, 16);
+        boot_pvd_found = iso_read_lsb(boot_info_found, 4);
+        image_pvd = (uint32_t) (opts->block + 16);
+
+        /* Accomodate to eventually relocated superblock */
+        if (image_pvd != boot_pvd_found &&
+            image_pvd == 16 && boot_pvd_found < iso_image_size) {
+            /* Check whether there is a PVD at boot_pvd_found
+               and whether it bears the same image size 
+             */
+            ret = read_pvd_block(src, boot_pvd_found, buf, &alleged_size);
+            if (ret == 1 &&
+                alleged_size + boot_pvd_found == iso_image_size + image_pvd)
+              image_pvd = boot_pvd_found;
+        }
+
+        ret = make_boot_info_table(boot_image_buf, image_pvd,
+                                   img_lba, img_size);
+        if (ret < 0)
+            goto ex;
+        if (memcmp(boot_image_buf + 8, boot_info_found, 16) == 0)
+            boot->seems_boot_info_table = 1;
+        free(boot_image_buf);
+        boot_image_buf = NULL;
+    }
+    ret = 1;
+ex:;
+    if (boot_image_buf != NULL)
+        free(boot_image_buf);
+    if (stream != NULL)
+        iso_stream_close(stream);
+    return ret;
+}
 
 int iso_image_import(IsoImage *image, IsoDataSource *src,
                      struct iso_read_opts *opts,
                      IsoReadImageFeatures **features)
 {
-    int ret, hflag;
+    int ret, hflag, i, idx;
     IsoImageFilesystem *fs;
     IsoFilesystem *fsback;
     IsoNodeBuilder *blback;
@@ -2934,17 +3125,50 @@
     IsoFileSource *newroot;
     _ImageFsData *data;
     struct el_torito_boot_catalog *oldbootcat;
+    uint8_t *rpt;
+    IsoFileSource *boot_src;
+    IsoNode *node;
+
+#ifdef Libisofs_with_checksumS
+    uint32_t old_checksum_start_lba;
+    uint32_t old_checksum_end_lba;
+    uint32_t old_checksum_idx_count;
+    char *old_checksum_array = NULL;
+    char checksum_type[81];
+    uint32_t checksum_size;
+    size_t size;
+    void *ctx = NULL;
+    char md5[16];
+#endif
 
     if (image == NULL || src == NULL || opts == NULL) {
         return ISO_NULL_POINTER;
     }
 
+
     ret = iso_image_filesystem_new(src, opts, image->id, &fs);
     if (ret < 0) {
         return ret;
     }
     data = fs->data;
 
+
+    if (opts->load_system_area) {
+        if (image->system_area_data != NULL)
+            free(image->system_area_data);
+        image->system_area_data = calloc(32768, 1);
+        if (image->system_area_data == NULL)
+            return ISO_OUT_OF_MEM;
+        image->system_area_options = 0;
+        /* Read 32768 bytes */
+        for (i = 0; i < 16; i++) {
+            rpt = (uint8_t *) (image->system_area_data + i * 2048);
+            ret = src->read_block(src, opts->block + i, rpt);
+            if (ret < 0)
+                return ret;
+        }
+    }
+
     /* get root from filesystem */
     ret = fs->get_root(fs, &newroot);
     if (ret < 0) {
@@ -2956,9 +3180,16 @@
     blback = image->builder;
     oldroot = image->root;
     oldbootcat = image->bootcat; /* could be NULL */
-
     image->bootcat = NULL;
 
+#ifdef Libisofs_with_checksumS
+    old_checksum_start_lba = image->checksum_start_lba;
+    old_checksum_end_lba = image->checksum_end_lba;
+    old_checksum_idx_count = image->checksum_idx_count;
+    old_checksum_array = image->checksum_array;
+    image->checksum_array = NULL;
+#endif
+
     /* create new builder */
     ret = iso_image_builder_new(blback, &image->builder);
     if (ret < 0) {
@@ -2989,17 +3220,12 @@
         if (ret < 0)
             goto import_revert;
 
-#ifdef Libisofs_hardlink_prooF
-
         /* Attach ino as xinfo if valid */
         if (info.st_ino != 0 && !data->make_new_ino) {
             ret = iso_node_set_ino(&(image->root->node), info.st_ino, 0);
             if (ret < 0)
                 goto import_revert;
         }
-
-#endif /* Libisofs_hardlink_prooF */
-
     }
 
     /* if old image has el-torito, add a new catalog */
@@ -3007,23 +3233,34 @@
         struct el_torito_boot_catalog *catalog;
         ElToritoBootImage *boot_image= NULL;
 
-        boot_image = calloc(1, sizeof(ElToritoBootImage));
-        if (boot_image == NULL) {
-            ret = ISO_OUT_OF_MEM;
-            goto import_revert;
-        }
-        boot_image->bootable = data->bootable;
-        boot_image->type = data->type;
-        boot_image->partition_type = data->partition_type;
-        boot_image->load_seg = data->load_seg;
-        boot_image->load_size = data->load_size;
-
         catalog = calloc(1, sizeof(struct el_torito_boot_catalog));
         if (catalog == NULL) {
             ret = ISO_OUT_OF_MEM;
             goto import_revert;
         }
-        catalog->image = boot_image;
+
+        catalog->num_bootimages = 0;
+        for (idx = 0; idx < data->num_bootimgs; idx++) {
+            boot_image = calloc(1, sizeof(ElToritoBootImage));
+            if (boot_image == NULL) {
+                ret = ISO_OUT_OF_MEM;
+                goto import_revert;
+            }
+            boot_image->image = NULL;
+            boot_image->bootable = data->boot_flags[idx] & 1;
+            boot_image->type = data->media_types[idx];
+            boot_image->partition_type = data->partition_types[idx];
+            boot_image->load_seg = data->load_segs[idx];
+            boot_image->load_size = data->load_sizes[idx];
+            boot_image->platform_id = data->platform_ids[idx];
+            memcpy(boot_image->id_string, data->id_strings[idx], 28);
+            memcpy(boot_image->selection_crit, data->selection_crits, 20);
+
+            catalog->bootimages[catalog->num_bootimages] = boot_image;
+            catalog->num_bootimages++;
+        }
+        for ( ; idx < Libisofs_max_boot_imageS; idx++)
+            catalog->bootimages[idx] = NULL;
         image->bootcat = catalog;
     }
 
@@ -3036,8 +3273,6 @@
         goto import_revert;
     }
 
-#ifdef Libisofs_hardlink_prooF
-
     /* Take over inode management from IsoImageFilesystem.
        data->inode_counter is supposed to hold the maximum PX inode number.
      */
@@ -3058,24 +3293,24 @@
         }
     }
 
-#endif /* ! Libisofs_hardlink_prooF */
-
     if (data->eltorito) {
-        /* if catalog and image nodes were not filled, we create them here */
-        if (image->bootcat->image->image == NULL) {
-            IsoFileSource *src;
-            IsoNode *node;
-            ret = create_boot_img_filesrc(fs, image, &src);
+        /* if catalog and boot image nodes were not filled,
+           we create them here */
+        for (idx = 0; idx < image->bootcat->num_bootimages; idx++) {
+            if (image->bootcat->bootimages[idx]->image != NULL)
+        continue;
+            ret = create_boot_img_filesrc(fs, image, idx, &boot_src);
             if (ret < 0) {
                 iso_node_builder_unref(image->builder);
                 goto import_revert;
             }
-            ret = image_builder_create_node(image->builder, image, src, &node);
+            ret = image_builder_create_node(image->builder, image, boot_src,
+                                            &node);
             if (ret < 0) {
                 iso_node_builder_unref(image->builder);
                 goto import_revert;
             }
-            image->bootcat->image->image = (IsoFile*)node;
+            image->bootcat->bootimages[idx]->image = (IsoFile*)node;
 
             /* warn about hidden images */
             iso_msg_submit(image->id, ISO_EL_TORITO_HIDDEN, 0,
@@ -3119,7 +3354,7 @@
         *features = malloc(sizeof(IsoReadImageFeatures));
         if (*features == NULL) {
             ret = ISO_OUT_OF_MEM;
-            goto import_cleanup;
+            goto import_revert;
         }
         (*features)->hasJoliet = data->joliet;
         (*features)->hasRR = data->rr_version != 0;
@@ -3128,6 +3363,66 @@
         (*features)->size = data->nblocks;
     }
 
+#ifdef Libisofs_with_checksumS
+
+    if (data->md5_load) {
+        /* Read checksum array */
+        ret = iso_root_get_isofsca((IsoNode *) image->root,
+                                   &(image->checksum_start_lba),
+                                   &(image->checksum_end_lba),
+                                   &(image->checksum_idx_count),
+                                   &checksum_size, checksum_type, 0); 
+        if (ret > 0)
+            if (checksum_size != 16 || strcmp(checksum_type, "MD5") != 0)
+                ret = 0;
+        if (ret > 0 && image->checksum_idx_count > 1) {
+            size = image->checksum_idx_count / 128;
+            if (size * 128 < image->checksum_idx_count)
+                size++;
+            image->checksum_array = calloc(size, 2048);
+            if (image->checksum_array == NULL) {
+                ret = ISO_OUT_OF_MEM;
+                goto import_revert;
+            }
+
+            /* Load from image->checksum_end_lba */;
+            for (i = 0; i < size; i++) {
+                rpt = (uint8_t *) (image->checksum_array + i * 2048);
+                ret = src->read_block(src, image->checksum_end_lba + i, rpt);
+                if (ret <= 0)
+                    goto import_cleanup;
+            }
+
+            /* Compute MD5 and compare with recorded MD5 */
+            ret = iso_md5_start(&ctx);
+            if (ret < 0) {
+                ret = ISO_OUT_OF_MEM;
+                goto import_revert;
+            }
+            for (i = 0; i < image->checksum_idx_count - 1; i++)
+                iso_md5_compute(ctx, image->checksum_array + i * 16, 16);
+            iso_md5_end(&ctx, md5);
+            for (i = 0; i < 16; i++)
+                if (md5[i] != image->checksum_array[
+                                      (image->checksum_idx_count - 1) * 16 + i]
+                   )
+            break;
+            if (i < 16) {
+                iso_msg_submit(image->id, ISO_MD5_AREA_CORRUPTED, 0,
+  "MD5 checksum array appears damaged and not trustworthy for verifications.");
+                free(image->checksum_array);
+                image->checksum_array = NULL;
+                image->checksum_idx_count = 0;
+            }
+        }
+    }
+
+#endif /* Libisofs_with_checksumS */
+
+    ret = iso_image_eval_boot_info_table(image, opts, src, data->nblocks, 0);
+    if (ret < 0)
+        goto import_revert;
+
     ret = ISO_SUCCESS;
     goto import_cleanup;
 
@@ -3136,9 +3431,16 @@
     iso_node_unref((IsoNode*)image->root);
     el_torito_boot_catalog_free(image->bootcat);
     image->root = oldroot;
-    image->fs = fsback;
     image->bootcat = oldbootcat;
 
+#ifdef Libisofs_with_checksumS
+    old_checksum_start_lba = image->checksum_start_lba;
+    old_checksum_end_lba = image->checksum_end_lba;
+    old_checksum_idx_count = image->checksum_idx_count;
+    image->checksum_array = old_checksum_array;
+    old_checksum_array = NULL;
+#endif
+
     import_cleanup:;
 
     /* recover backed fs and builder */
@@ -3149,6 +3451,13 @@
     fs->close(fs);
     iso_filesystem_unref(fs);
 
+#ifdef Libisofs_with_checksumS
+    if (old_checksum_array != NULL)
+        free(old_checksum_array);
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+#endif
+
     return ret;
 }
 
@@ -3225,7 +3534,9 @@
 
     ropts->file_mode = 0444;
     ropts->dir_mode = 0555;
-    ropts->noaaip= 1;
+    ropts->noaaip = 1;
+    ropts->nomd5 = 1;
+    ropts->load_system_area = 0;
 
     *opts = ropts;
     return ISO_SUCCESS;
@@ -3286,6 +3597,15 @@
     return ISO_SUCCESS;
 }
 
+int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5)
+{
+    if (opts == NULL) {
+        return ISO_NULL_POINTER;
+    }
+    opts->nomd5 = no_md5 ? 1 : 0;
+    return ISO_SUCCESS;
+}
+
 
 int iso_read_opts_set_new_inos(IsoReadOpts *opts, int new_inos)
 {
@@ -3352,6 +3672,15 @@
     return ISO_SUCCESS;
 }
 
+int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode)
+{
+    if (opts == NULL) {
+        return ISO_NULL_POINTER;
+    }
+    opts->load_system_area = mode & 1;
+    return ISO_SUCCESS;
+}
+
 /**
  * Destroy an IsoReadImageFeatures object obtained with iso_image_import.
  */
--- libisofs/fs_local.c
+++ libisofs/fs_local.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
--- libisofs/fsource.c
+++ libisofs/fsource.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "fsource.h"
--- libisofs/fsource.h
+++ libisofs/fsource.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_FSOURCE_H_
--- libisofs/image.c
+++ libisofs/image.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
@@ -73,11 +74,21 @@
         img->volset_id = strdup(name);
         img->volume_id = strdup(name);
     }
+    img->system_area_data = NULL;
+    img->system_area_options = 0;
     img->builder_ignore_acl = 1;
     img->builder_ignore_ea = 1;
     img->inode_counter = 0;
     img->used_inodes = NULL;
     img->used_inodes_start = 0;
+
+#ifdef Libisofs_with_checksumS
+    img->checksum_start_lba = 0;
+    img->checksum_end_lba = 0;
+    img->checksum_idx_count = 0;
+    img->checksum_array = NULL;
+#endif
+
     *image = img;
     return ISO_SUCCESS;
 }
@@ -126,10 +137,29 @@
         free(image->biblio_file_id);
         if (image->used_inodes != NULL)
             free(image->used_inodes);
+        iso_image_free_checksums(image, 0);
         free(image);
     }
 }
 
+
+int iso_image_free_checksums(IsoImage *image, int flag)
+{
+#ifdef Libisofs_with_checksumS
+
+    image->checksum_start_lba = 0;
+    image->checksum_end_lba = 0;
+    image->checksum_idx_count = 0;
+    if (image->checksum_array != NULL)
+        free(image->checksum_array);
+    image->checksum_array = NULL;
+
+#endif /* Libisofs_with_checksumS */
+
+    return 1;
+}
+
+
 /**
  * Attach user defined data to the image. Use this if your application needs
  * to store addition info together with the IsoImage. If the image already
@@ -186,6 +216,8 @@
 
 const char *iso_image_get_volset_id(const IsoImage *image)
 {
+    if (image->volset_id == NULL)
+        return "";
     return image->volset_id;
 }
 
@@ -197,6 +229,8 @@
 
 const char *iso_image_get_volume_id(const IsoImage *image)
 {
+    if (image->volume_id == NULL)
+        return "";
     return image->volume_id;
 }
 
@@ -208,6 +242,8 @@
 
 const char *iso_image_get_publisher_id(const IsoImage *image)
 {
+    if (image->publisher_id == NULL)
+        return "";
     return image->publisher_id;
 }
 
@@ -220,6 +256,8 @@
 
 const char *iso_image_get_data_preparer_id(const IsoImage *image)
 {
+    if (image->data_preparer_id == NULL)
+        return "";
     return image->data_preparer_id;
 }
 
@@ -231,6 +269,8 @@
 
 const char *iso_image_get_system_id(const IsoImage *image)
 {
+    if (image->system_id == NULL)
+        return "";
     return image->system_id;
 }
 
@@ -242,6 +282,8 @@
 
 const char *iso_image_get_application_id(const IsoImage *image)
 {
+    if (image->application_id == NULL)
+        return "";
     return image->application_id;
 }
 
@@ -254,6 +296,8 @@
 
 const char *iso_image_get_copyright_file_id(const IsoImage *image)
 {
+    if (image->copyright_file_id == NULL)
+        return "";
     return image->copyright_file_id;
 }
 
@@ -266,6 +310,8 @@
 
 const char *iso_image_get_abstract_file_id(const IsoImage *image)
 {
+    if (image->abstract_file_id == NULL)
+        return "";
     return image->abstract_file_id;
 }
 
@@ -277,6 +323,8 @@
 
 const char *iso_image_get_biblio_file_id(const IsoImage *image)
 {
+    if (image->biblio_file_id == NULL)
+        return "";
     return image->biblio_file_id;
 }
 
@@ -285,6 +333,16 @@
     return image->id;
 }
 
+int iso_image_get_system_area(IsoImage *img, char system_area_data[32768],
+                              int *options, int flag)
+{
+    *options = img->system_area_options;
+    if (img->system_area_data == NULL)
+        return 0;
+    memcpy(system_area_data, img->system_area_data, 32768);
+    return 1;
+}
+
 static
 int dir_update_size(IsoImage *image, IsoDir *dir)
 {
@@ -529,3 +587,44 @@
     return ret;
 }
 
+
+/* API */
+int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
+                              uint32_t *end_lba, char md5[16], int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    if (image->checksum_array == NULL || image->checksum_idx_count < 1)
+        return 0;
+    *start_lba = image->checksum_start_lba;
+    *end_lba = image->checksum_end_lba;
+    memcpy(md5, image->checksum_array, 16);
+    return ISO_SUCCESS;
+    
+#else
+
+    return 0;
+    
+#endif /* ! Libisofs_with_checksumS */
+    
+}
+
+int iso_image_set_checksums(IsoImage *image, char *checksum_array,
+                            uint32_t start_lba, uint32_t end_lba,
+                            uint32_t idx_count, int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    iso_image_free_checksums(image, 0);
+    image->checksum_array = checksum_array;
+    image->checksum_start_lba = start_lba;
+    image->checksum_end_lba = end_lba;
+    image->checksum_idx_count = idx_count;
+
+#endif /* Libisofs_with_checksumS */
+
+    return 1;
+}
+
--- libisofs/image.h
+++ libisofs/image.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_IMAGE_H_
 #define LIBISO_IMAGE_H_
@@ -52,6 +53,11 @@
     /* el-torito boot catalog */
     struct el_torito_boot_catalog *bootcat;
 
+    /* Eventually loaded system area data, or NULL */
+    char *system_area_data;
+    /* Prescribed/detected options, see iso_write_opts_set_system_area() */
+    int system_area_options;
+
     /* image identifier, for message origin identifier */
     int id;
 
@@ -148,6 +154,22 @@
     uint8_t *used_inodes;
     ino_t used_inodes_start;
 
+#ifdef Libisofs_with_checksumS
+
+    /**
+     * Array of MD5 checksums as announced by xattr "isofs.ca" of the 
+     * root node. Array element 0 contains an overall image checksum for the
+     * block range checksum_start_lba,checksum_end_lba. Element size is
+     * 16 bytes. IsoFile objects in the image may have xattr "isofs.cx"
+     * which gives their index in checksum_array.
+     */
+    uint32_t checksum_start_lba;
+    uint32_t checksum_end_lba;
+    uint32_t checksum_idx_count;
+    char *checksum_array;
+
+#endif /* Libisofs_with_checksumS */
+
 };
 
 
@@ -181,4 +203,18 @@
 */
 int img_make_inos(IsoImage *image, IsoDir *dir, int flag);
 
+
+/* Free the checksum array of an image and reset its layout parameters
+*/
+int iso_image_free_checksums(IsoImage *image, int flag);
+
+
+/* Equip an ISO image with a new checksum array buffer (after isofs.ca and
+   isofs.cx have already been adjusted).
+*/
+int iso_image_set_checksums(IsoImage *image, char *checksum_array, 
+                            uint32_t start_lba, uint32_t end_lba,
+                            uint32_t idx_count, int flag);
+
+
 #endif /*LIBISO_IMAGE_H_*/
--- libisofs/iso1999.c
+++ libisofs/iso1999.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "iso1999.h"
@@ -711,7 +712,7 @@
     iso_bb(rec->length, len, 4);
     iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
     rec->flags[0] = ((node->type == ISO1999_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
-    iso_bb(rec->vol_seq_number, 1, 2);
+    iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
     rec->len_fi[0] = len_fi;
 }
 
@@ -762,9 +763,9 @@
     strncpy_pad((char*)vol.volume_id, vol_id, 32);
 
     iso_bb(vol.vol_space_size, t->vol_space_size, 4);
-    iso_bb(vol.vol_set_size, 1, 2);
-    iso_bb(vol.vol_seq_number, 1, 2);
-    iso_bb(vol.block_size, BLOCK_SIZE, 2);
+    iso_bb(vol.vol_set_size, (uint32_t) 1, 2);
+    iso_bb(vol.vol_seq_number, (uint32_t) 1, 2);
+    iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2);
     iso_bb(vol.path_table_size, t->iso1999_path_table_size, 4);
     iso_lsb(vol.l_path_table_pos, t->iso1999_l_path_table_pos, 4);
     iso_msb(vol.m_path_table_pos, t->iso1999_m_path_table_pos, 4);
--- libisofs/iso1999.h
+++ libisofs/iso1999.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /**
--- libisofs/joliet.c
+++ libisofs/joliet.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2007 Mario Danic
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "joliet.h"
@@ -42,7 +43,7 @@
     if (iso->type == LIBISO_DIR) {
         jname = iso_j_dir_id(ucs_name);
     } else {
-        jname = iso_j_file_id(ucs_name);
+        jname = iso_j_file_id(ucs_name, !!(t->no_force_dots & 2));
     }
     free(ucs_name);
     if (jname != NULL) {
@@ -573,7 +574,7 @@
 {
     /* note than name len is always even, so we always need the pad byte */
     int ret = n->name ? ucslen(n->name) * 2 + 34 : 34;
-    if (n->type == JOLIET_FILE && !t->omit_version_numbers) {
+    if (n->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
         /* take into account version numbers */
         ret += 4;
     }
@@ -721,7 +722,7 @@
 
     memcpy(rec->file_id, name, len_fi);
 
-    if (node->type == JOLIET_FILE && !t->omit_version_numbers) {
+    if (node->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
         len_dr += 4;
         rec->file_id[len_fi++] = 0;
         rec->file_id[len_fi++] = ';';
@@ -757,7 +758,7 @@
     iso_bb(rec->length, len, 4);
     iso_datetime_7(rec->recording_time, t->now, t->always_gmt);
     rec->flags[0] = ((node->type == JOLIET_DIR) ? 2 : 0) | (multi_extend ? 0x80 : 0);
-    iso_bb(rec->vol_seq_number, 1, 2);
+    iso_bb(rec->vol_seq_number, (uint32_t) 1, 2);
     rec->len_fi[0] = len_fi;
 }
 
@@ -832,9 +833,9 @@
     memcpy(vol.esc_sequences, "%/E", 3);
 
     iso_bb(vol.vol_space_size, t->vol_space_size, 4);
-    iso_bb(vol.vol_set_size, 1, 2);
-    iso_bb(vol.vol_seq_number, 1, 2);
-    iso_bb(vol.block_size, BLOCK_SIZE, 2);
+    iso_bb(vol.vol_set_size, (uint32_t) 1, 2);
+    iso_bb(vol.vol_seq_number, (uint32_t) 1, 2);
+    iso_bb(vol.block_size, (uint32_t) BLOCK_SIZE, 2);
     iso_bb(vol.path_table_size, t->joliet_path_table_size, 4);
     iso_lsb(vol.l_path_table_pos, t->joliet_l_path_table_pos, 4);
     iso_msb(vol.m_path_table_pos, t->joliet_m_path_table_pos, 4);
@@ -898,7 +899,7 @@
         /* compute len of directory entry */
         fi_len = ucslen(child->name) * 2;
         len = fi_len + 34;
-        if (child->type == JOLIET_FILE && !t->omit_version_numbers) {
+        if (child->type == JOLIET_FILE && !(t->omit_version_numbers & 3)) {
             len += 4;
         }
 
--- libisofs/joliet.h
+++ libisofs/joliet.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2007 Mario Danic
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /**
--- libisofs/libiso_msgs.c
+++ libisofs/libiso_msgs.c
@@ -2,7 +2,7 @@
 /* libiso_msgs   (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008)
    Message handling facility of libisofs.
    Copyright (C) 2006 - 2008 Thomas Schmitt <scdbackup at gmx.net>,
-   provided under GPL version 2
+   provided under GPL version 2 or later
 */
 
 #include <stdio.h>
--- libisofs/libiso_msgs.h
+++ libisofs/libiso_msgs.h
@@ -2,7 +2,7 @@
 /* libiso_msgs   (generated from libdax_msgs : Fri Feb 22 19:42:52 CET 2008)
    Message handling facility of libisofs.
    Copyright (C) 2006-2008 Thomas Schmitt <scdbackup at gmx.net>,
-   provided under GPL version 2
+   provided under GPL version 2 or later
 */
 
 
--- libisofs/libisofs.h
+++ libisofs/libisofs.h
@@ -1,15 +1,16 @@
 /*
  * Copyright (c) 2007-2008 Vreixo Formoso, Mario Danic
- * Copyright (c) 2009 Thomas Schmitt
+ * Copyright (c) 2009-2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /* 
  *
- * Applications must use 64 bit off_t, e.g. on 32-bit Linux by defining
+ * Applications must use 64 bit off_t, e.g. on 32-bit GNU/Linux by defining
  *   #define _LARGEFILE_SOURCE
  *   #define _FILE_OFFSET_BITS 64
  * or take special precautions to interface with the library by 64 bit integers
@@ -373,7 +374,7 @@
  * access and read file contents. Note that this doesn't need to be tied
  * to the disc filesystem used in the partition being accessed. For example,
  * we have an IsoFilesystem implementation to access any mounted filesystem,
- * using standard Linux functions. It is also legal, of course, to implement
+ * using standard POSIX functions. It is also legal, of course, to implement
  * an IsoFilesystem to deal with a specific filesystem over raw partitions.
  * That is what we do, for example, to access an ISO Image.
  *
@@ -483,7 +484,7 @@
     int version;
 
     /**
-     * Get the path, relative to the filesystem this file source belongs to.
+     * Get the absolute path in the filesystem this file source belongs to.
      *
      * @return
      *     the path of the FileSource inside the filesystem, it should be
@@ -1090,7 +1091,7 @@
  */
 #define iso_lib_header_version_major  0
 #define iso_lib_header_version_minor  6
-#define iso_lib_header_version_micro  20
+#define iso_lib_header_version_micro  32
 
 /**
  * Usage discussion:
@@ -1285,7 +1286,9 @@
  * Omit the version number (";1") at the end of the ISO-9660 identifiers.
  * This breaks ECMA-119 specification, but version numbers are usually not
  * used, so it should work on most systems. Use with caution.
- *
+ * @param omit
+ *      bit0= omit version number with ECMA-119 and Joliet
+ *      bit1= omit version number with Joliet alone (@since 0.6.30)
  * @since 0.6.2
  */
 int iso_write_opts_set_omit_version_numbers(IsoWriteOpts *opts, int omit);
@@ -1323,6 +1326,9 @@
  * extension. libisofs adds it if original filename doesn't has one. Set
  * this to 1 to prevent this behavior.
  * This breaks ECMA-119 specification. Use with caution.
+ * @param no
+ *      bit0= no forced dot with ECMA-119
+ *      bit1= no forced dot with Joliet (@since 0.6.30)
  *
  * @since 0.6.2
  */
@@ -1416,10 +1422,68 @@
 int iso_write_opts_set_sort_files(IsoWriteOpts *opts, int sort);
 
 /**
+ * Whether to compute and record MD5 checksums for the whole session and/or
+ * for each single IsoFile object. The checksums represent the data as they
+ * were written into the image output stream, not necessarily as they were
+ * on hard disk at any point of time.
+ * See also calls iso_image_get_session_md5() and iso_file_get_md5().
+ * @param opts
+ *      The option set to be manipulated.
+ * @param session
+ *      If bit0 set: Compute session checksum
+ * @param files
+ *      If bit0 set: Compute a checksum for each single IsoFile object which
+ *                   gets its data content written into the session. Copy
+ *                   checksums from files which keep their data in older
+ *                   sessions.
+ *      If bit1 set: Check content stability (only with bit0). I.e.  before
+ *                   writing the file content into to image stream, read it
+ *                   once and compute a MD5. Do a second reading for writing
+ *                   into the image stream. Afterwards compare both MD5 and
+ *                   issue a MISHAP event ISO_MD5_STREAM_CHANGE if they do not
+ *                   match.
+ *                   Such a mismatch indicates content changes between the
+ *                   time point when the first MD5 reading started and the
+ *                   time point when the last block was read for writing.
+ *                   So there is high risk that the image stream was fed from
+ *                   changing and possibly inconsistent file content.
+ *                   
+ * @since 0.6.22
+ */
+int iso_write_opts_set_record_md5(IsoWriteOpts *opts, int session, int files);
+
+/**
+ * Set the parameters "name" and "timestamp" for a scdbackup checksum tag.
+ * It will be appended to the libisofs session tag if the image starts at
+ * LBA 0 (see iso_write_opts_set_ms_block()). The scdbackup tag can be used
+ * to verify the image by command scdbackup_verify <device> -auto_end.
+ * See scdbackup/README appendix VERIFY for its inner details.
+ *
+ * @param name
+ *      A word of up to 80 characters. Typically <volno>_<totalno> telling
+ *      that this is volume <volno> of a total of <totalno> volumes.
+ * @param timestamp
+ *      A string of 13 characters YYMMDD.hhmmss (e.g. A90831.190324).
+ *      A9 = 2009, B0 = 2010, B1 = 2011, ... C0 = 2020, ...
+ * @param tag_written
+ *      Either NULL or the address of an array with at least 512 characters.
+ *      In the latter case the eventually produced scdbackup tag will be
+ *      copied to this array when the image gets written. This call sets
+ *      scdbackup_tag_written[0] = 0 to mark its preliminary invalidity.
+ * @return
+ *      1 indicates success, <0 is error
+ *
+ * @since 0.6.24
+ */
+int iso_write_opts_set_scdbackup_tag(IsoWriteOpts *opts,
+                                     char *name, char *timestamp,
+                                     char *tag_written);
+
+/**
  * Whether to set default values for files and directory permissions, gid and
  * uid. All these take one of three values: 0, 1 or 2.
  *
- * If 0, the corresponding attribute will be kept as setted in the IsoNode.
+ * If 0, the corresponding attribute will be kept as set in the IsoNode.
  * Unless you have changed it, it corresponds to the value on disc, so it
  * is suitable for backup purposes. If set to 1, the corresponding attrib.
  * will be changed by a default suitable value. Finally, if you set it to
@@ -1621,6 +1685,75 @@
  */
 int iso_write_opts_set_fifo_size(IsoWriteOpts *opts, size_t fifo_size);
 
+/*
+ * Attach 32 kB of binary data which shall get written to the first 32 kB 
+ * of the ISO image, the ECMA-119 System Area. This space is intended for
+ * system dependent boot software, e.g. a Master Boot Record which allows to
+ * boot from USB sticks or hard disks. ECMA-119 makes no own assumptions or
+ * prescriptions about the byte content.
+ *
+ * If system area data are given or options bit0 is set, then bit1 of
+ * el_torito_set_isolinux_options() is automatically disabled.
+ * @param data
+ *        Either NULL or 32 kB of data. Do not submit less bytes !
+ * @param options
+ *        Can cause manipulations of submitted data before they get written:
+ *        bit0= apply a --protective-msdos-label as of grub-mkisofs.
+ *              This means to patch bytes 446 to 512 of the system area so
+ *              that one partition is defined which begins at the second
+ *              512-byte block of the image and ends where the image ends.
+ *              This works with and without system_area_data.
+ *        bit1= apply isohybrid MBR patching to the system area.
+ *              This works only with system area data from SYSLINUX plus an
+ *              ISOLINUX boot image (see iso_image_set_boot_image()) and
+ *              only if not bit0 is set.
+ * @param flag
+ *        bit0 = invalidate any attached system area data. Same as data == NULL
+ *               (This re-activates eventually loaded image System Area data.
+ *                To erase those, submit 32 kB of zeros without flag bit0.)
+ *        bit1 = keep data unaltered
+ *        bit2 = keep options unaltered
+ * @return
+ *        ISO_SUCCESS or error
+ * @since 0.6.30
+ */
+int iso_write_opts_set_system_area(IsoWriteOpts *opts, char data[32768],
+                                   int options, int flag);
+
+/**
+ * Explicitely set the four timestamps of the emerging Primary Volume
+ * Descriptor. Default with all parameters is 0.
+ * ECMA-119 defines them as:
+ * @param vol_creation_time
+ *        When "the information in the volume was created."
+ *        A value of 0 means that the timepoint of write start is to be used.
+ * @param vol_modification_time
+ *        When "the information in the volume was last modified."
+ *        A value of 0 means that the timepoint of write start is to be used.
+ * @param vol_expiration_time
+ *        When "the information in the volume may be regarded as obsolete."
+ *        A value of 0 means that the information never shall expire.
+ * @param vol_effective_time
+ *        When "the information in the volume may be used."
+ *        A value of 0 means that not such retention is intended.
+ * @param uuid
+ *        If this text is not empty, then it overrides vol_creation_time and
+ *        vol_modification_time by copying the first 16 decimal digits from
+ *        uuid, eventually padding up with decimal '1', and writing a NUL-byte
+ *        as timezone.
+ *        Other than with vol_*_time the resulting string in the ISO image
+ *        is fully predictable and free of timezone pitfalls.
+ *        It should express a reasonable time in form  YYYYMMDDhhmmsscc
+ *        E.g.:  "2010040711405800" = 7 Apr 2010 11:40:58 (+0 centiseconds)
+ *
+ * @since 0.6.30
+ */
+int iso_write_opts_set_pvd_times(IsoWriteOpts *opts,
+                        time_t vol_creation_time, time_t vol_modification_time,
+                        time_t vol_expiration_time, time_t vol_effective_time,
+                        char *vol_uuid);
+
+
 /**
  * Inquire the start address of the file data blocks after having used
  * IsoWriteOpts with iso_image_create_burn_source().
@@ -1756,6 +1889,22 @@
 int iso_read_opts_set_no_aaip(IsoReadOpts *opts, int noaaip);
 
 /**
+ * Control reading of an array of MD5 checksums which is eventually stored
+ * at the end of a session. See also iso_write_opts_set_record_md5().
+ * Important: Loading of the MD5 array will only work if AAIP is enabled
+ *            because its position and layout is recorded in xattr "isofs.ca".
+ *
+ * @param no_md5
+ *    1 = Do not read MD5 checksum array
+ *    0 = Read Md% array if available
+ *     All other values are reserved.
+ *
+ * @since 0.6.22
+ */
+int iso_read_opts_set_no_md5(IsoReadOpts *opts, int no_md5);
+
+
+/**
  * Control discarding of eventual inode numbers from existing images.
  * Such numbers may come from RRIP 1.12 entries PX. If not discarded they
  * get written unchanged when the file object gets written into an ISO image. 
@@ -1847,6 +1996,20 @@
  */
 int iso_read_opts_auto_input_charset(IsoReadOpts *opts, int mode);
 
+/**
+ * Enable or disable loading of the first 32768 bytes of the session.
+ *
+ * @param mode
+ *       Bitfield for control purposes:
+ *       bit0= Load System Area data and attach them to the image so that they
+ *             get written by the next session, if not overridden by
+ *             iso_write_opts_set_system_area().
+ *       Submit any other bits with value 0.
+ *
+ * @since 0.6.30
+ *
+ */
+int iso_read_opts_load_system_area(IsoReadOpts *opts, int mode);
 
 /**
  * Import a previous session or image, for growing or modify.
@@ -2120,16 +2283,15 @@
 const char *iso_image_get_biblio_file_id(const IsoImage *image);
 
 /**
- * Create a bootable image by adding a El-Torito boot image.
- *
- * This also add a catalog boot node to the image filesystem tree.
+ * Create a new set of El-Torito bootable images by adding a boot catalog
+ * and the default boot image.
+ * Further boot images may then be added by iso_image_add_boot_image().
  *
  * @param image
  *      The image to make bootable. If it was already bootable this function
  *      returns an error and the image remains unmodified.
  * @param image_path
- *      The path on the image tree of a regular file to use as default boot
- *      image.
+ *      The absolute path of a IsoFile to be used as default boot image.
  * @param type
  *      The boot media type. This can be one of 3 types:
  *             - Floppy emulation: Boot image file must be exactly
@@ -2139,9 +2301,9 @@
  *             - No emulation. You should specify load segment and load size
  *               of image.
  * @param catalog_path
- *      The path on the image tree where the catalog will be stored. The
- *      directory component of this path must be a directory existent on the
- *      image tree, and the filename component must be unique among all
+ *      The absolute path in the image tree where the catalog will be stored.
+ *      The directory component of this path must be a directory existent on
+ *      the image tree, and the filename component must be unique among all
  *      children of that directory on image. Otherwise a correspodent error
  *      code will be returned. This function will add an IsoBoot node that acts
  *      as a placeholder for the real catalog, that will be generated at image
@@ -2162,10 +2324,36 @@
                              const char *catalog_path,
                              ElToritoBootImage **boot);
 
+/**
+ * Add a further boot image to the set of El-Torito bootable images.
+ * This set has already to be created by iso_image_set_boot_image().
+ * Up to 31 further boot images may be added.
+ *
+ * @param image
+ *      The image to which the boot image shall be added.
+ *      returns an error and the image remains unmodified.
+ * @param image_path
+ *      The absolute path of a IsoFile to be used as default boot image.
+ * @param type
+ *      The boot media type. See iso_image_set_boot_image
+ * @param flag
+ *      Bitfield for control purposes. Unused yet. Submit 0.
+ * @param boot
+ *      Location where a pointer to the added boot image will be stored.
+ *      See iso_image_set_boot_image
+ * @return
+ *      1 on success, < 0 on error
+ *
+ * @since 0.6.32
+ */
+int iso_image_add_boot_image(IsoImage *image, const char *image_path,
+                             enum eltorito_boot_media_type type, int flag,
+                             ElToritoBootImage **boot);
+
 /* TODO #00026 : add support for "hidden" bootable images. */
 
 /**
- * Get El-Torito boot image of an ISO image, if any.
+ * Get the El-Torito boot catalog and the default boot image of an ISO image.
  *
  * This can be useful, for example, to check if a volume read from a previous
  * session or an existing image is bootable. It can also be useful to get
@@ -2203,7 +2391,35 @@
                              IsoFile **imgnode, IsoBoot **catnode);
 
 /**
- * Removes the El-Torito bootable image.
+ * Get all El-Torito boot images of an ISO image.
+ *
+ * The first of these boot images is the same as returned by
+ * iso_image_get_boot_image(). The others are alternative boot images. 
+ *
+ * @param image
+ *      The image from which to get the boot images.
+ * @param num_boots
+ *      The number of available array elements in boots and bootnodes.
+ * @param boots
+ *      Returns NULL or an allocated array of pointers to boot images.
+ *      Apply system call free(boots) to dispose it.
+ * @param bootnodes
+ *      Returns NULL or an allocated array of pointers to the IsoFile nodes
+ *      which bear the content of the boot images in boots.
+ * @param flag
+ *      Bitfield for control purposes. Unused yet. Submit 0.
+ * @return
+ *      1 on success, 0 no El-Torito catalog and boot image attached,
+ *      < 0 error.
+ *
+ * @since 0.6.32
+ */
+int iso_image_get_all_boot_imgs(IsoImage *image, int *num_boots,
+                   ElToritoBootImage ***boots, IsoFile ***bootnodes, int flag);
+
+
+/**
+ * Removes all El-Torito boot images from the ISO image.
  *
  * The IsoBoot node that acts as placeholder for the catalog is also removed
  * for the image tree, if there.
@@ -2215,6 +2431,74 @@
 void iso_image_remove_boot_image(IsoImage *image);
 
 /**
+ * Sets the sort weight of the boot catalog that is attached to an IsoImage.
+ * 
+ * For the meaning of sort weights see iso_node_set_sort_weight().
+ * That function cannot be applied to the emerging boot catalog because
+ * it is not represented by an IsoFile.
+ *
+ * @param image
+ *      The image to manipulate.
+ * @param sort_weight
+ *      The larger this value, the lower will be the block address of the
+ *      boot catalog record.
+ * @return
+ *      0= no boot catalog attached , 1= ok , <0 = error
+ *
+ * @since 0.6.32
+ */
+int iso_image_set_boot_catalog_weight(IsoImage *image, int sort_weight);
+
+/**
+ * Get the boot media type as of parameter "type" of iso_image_set_boot_image()
+ * resp. iso_image_add_boot_image().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @param media_type
+ *      Returns the media type
+ * @return
+ *      1 = ok , < 0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_boot_media_type(ElToritoBootImage *bootimg, 
+                                  enum eltorito_boot_media_type *media_type);
+
+/**
+ * Sets the platform ID of the boot image.
+ * 
+ * The Platform ID gets written into the boot catalog at byte 1 of the
+ * Validation Entry, or at byte 1 of a Section Header Entry.
+ * If Platform ID and ID String of two consequtive bootimages are the same
+ *
+ * @param bootimg
+ *      The image to manipulate.
+ * @param id
+ *      A Platform ID as of
+ *      El Torito 1.0  : 0x00= 80x86,  0x01= PowerPC,  0x02= Mac
+ *      Others         : 0xef= EFI
+ * @return
+ *      1 ok , <=0 error
+ *
+ * @since 0.6.32
+ */
+int el_torito_set_boot_platform_id(ElToritoBootImage *bootimg, uint8_t id);
+
+/**
+ * Get the platform ID value. See el_torito_set_boot_platform_id().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @return
+ *      0 - 255 : The platform ID 
+ *      < 0     : error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_boot_platform_id(ElToritoBootImage *bootimg);
+
+/**
  * Sets the load segment for the initial boot image. This is only for
  * no emulation boot images, and is a NOP for other image types.
  *
@@ -2223,6 +2507,19 @@
 void el_torito_set_load_seg(ElToritoBootImage *bootimg, short segment);
 
 /**
+ * Get the load segment value. See el_torito_set_load_seg().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @return
+ *      0 - 65535 : The load segment value 
+ *      < 0       : error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_load_seg(ElToritoBootImage *bootimg);
+
+/**
  * Sets the number of sectors (512b) to be load at load segment during
  * the initial boot procedure. This is only for
  * no emulation boot images, and is a NOP for other image types.
@@ -2232,6 +2529,19 @@
 void el_torito_set_load_size(ElToritoBootImage *bootimg, short sectors);
 
 /**
+ * Get the load size. See el_torito_set_load_size().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @return
+ *      0 - 65535 : The load size value
+ *      < 0       : error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_load_size(ElToritoBootImage *bootimg);
+
+/**
  * Marks the specified boot image as not bootable
  *
  * @since 0.6.2
@@ -2239,30 +2549,131 @@
 void el_torito_set_no_bootable(ElToritoBootImage *bootimg);
 
 /**
- * Specifies that this image needs to be patched. This involves the writing
- * of a 56 bytes boot information table at offset 8 of the boot image file.
- * The original boot image file won't be modified.
- * This is needed for isolinux boot images.
+ * Get the bootability flag. See el_torito_set_no_bootable().
  *
- * @since 0.6.2
- * @deprecated Use el_torito_set_isolinux_options() instead
+ * @param bootimg
+ *      The image to inquire
+ * @return
+ *      0 = not bootable, 1 = bootable , <0 = error
+ *
+ * @since 0.6.32
  */
-void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
+int el_torito_get_bootable(ElToritoBootImage *bootimg);
+
+/**
+ * Set the id_string of the Validation Entry resp. Sector Header Entry which
+ * will govern the boot image Section Entry in the El Torito Catalog.
+ *
+ * @param bootimg
+ *      The image to manipulate.
+ * @param id_string
+ *      The first boot image puts 24 bytes of ID string into the Validation
+ *      Entry, where they shall "identify the manufacturer/developer of
+ *      the CD-ROM".
+ *      Further boot images put 28 bytes into their Section Header.
+ *      El Torito 1.0 states that "If the BIOS understands the ID string, it
+ *      may choose to boot the * system using one of these entries in place
+ *      of the INITIAL/DEFAULT entry." (The INITIAL/DEFAULT entry points to the
+ *      first boot image.)
+ * @return
+ *      1 = ok , <0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_set_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]);
+
+/** 
+ * Get the id_string as of el_torito_set_id_string().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @param id_string
+ *      Returns 28 bytes of id string
+ * @return
+ *      1 = ok , <0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_id_string(ElToritoBootImage *bootimg, uint8_t id_string[28]);
+
+/**
+ * Set the Selection Criteria of a boot image.
+ *
+ * @param bootimg
+ *      The image to manipulate.
+ * @param crit
+ *      The first boot image has no selection criteria. They will be ignored.
+ *      Further boot images put 1 byte of Selection Criteria Type and 19
+ *      bytes of data into their Section Entry.
+ *      El Torito 1.0 states that "The format of the selection criteria is
+ *      a function of the BIOS vendor. In the case of a foreign language
+ *      BIOS three bytes would be used to identify the language".
+ *      Type byte == 0 means "no criteria",
+ *      type byte == 1 means "Language and Version Information (IBM)".
+ * @return
+ *      1 = ok , <0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_set_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]);
+
+/** 
+ * Get the Selection Criteria bytes as of el_torito_set_selection_crit().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @param id_string
+ *      Returns 20 bytes of type and data
+ * @return
+ *      1 = ok , <0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_selection_crit(ElToritoBootImage *bootimg, uint8_t crit[20]);
+
+
+/**
+ * Makes a guess whether the boot image was patched by a boot information
+ * table. It is advisable to patch such boot images if their content gets
+ * copied to a new location. See el_torito_set_isolinux_options().
+ * Note: The reply can be positive only if the boot image was imported
+ *       from an existing ISO image.
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @return
+ *      1 = seems to contain oot info table , 0 = quite surely not
+ * @since 0.6.32
+ */
+int el_torito_seems_boot_info_table(ElToritoBootImage *bootimg, int flag);
 
 /**
- * Specifies options for IsoLinux boot images. This should only be used with
- * isolinux boot images.
+ * Specifies options for ISOLINUX or GRUB boot images. This should only be used
+ * if the type of boot image is known.
  *
  * @param options
  *        bitmask style flag. The following values are defined:
  *
- *        bit 0 -> 1 to path the image, 0 to not
- *                 Patching the image involves the writing of a 56 bytes
- *                 boot information table at offset 8 of the boot image file.
- *                 The original boot image file will not be modified. This is
- *                 needed to allow isolinux images to be bootable.
- *        bit 1 -> 1 to generate an hybrid image with MBR, 0 to not
- *                 An hybrid image is a boot image that boots from either
+ *        bit 0 -> 1 to patch the boot info table of the boot image.
+ *                 1 does the same as mkisofs option -boot-info-table.
+ *                 Needed for ISOLINUX or GRUB boot images with platform ID 0.
+ *                 The table is located at byte 8 of the boot image file.
+ *                 Its size is 56 bytes. 
+ *                 The original boot image file on disk will not be modified.
+ *
+ *                 One may use el_torito_seems_boot_info_table() for a
+ *                 qualified guess whether a boot info table is present in
+ *                 the boot image. If the result is 1 then it should get bit0
+ *                 set if its content gets copied to a new LBA.
+ *
+ *        bit 1 -> 1 to generate a ISOLINUX isohybrid image with MBR.
+ *                 ----------------------------------------------------------
+ *                 @deprecated since 31 Mar 2010:
+ *                 The author of syslinux, H. Peter Anvin requested that this
+ *                 feature shall not be used any more. He intends to cease
+ *                 support for the MBR template that is included in libisofs.
+ *                 ----------------------------------------------------------
+ *                 A hybrid image is a boot image that boots from either
  *                 CD/DVD media or from disk-like media, e.g. USB stick.
  *                 For that you need isolinux.bin from SYSLINUX 3.72 or later.
  *                 IMPORTANT: The application has to take care that the image
@@ -2273,7 +2684,55 @@
  *      1 success, < 0 on error
  * @since 0.6.12
  */
-int el_torito_set_isolinux_options(ElToritoBootImage *bootimg, int options, int flag);
+int el_torito_set_isolinux_options(ElToritoBootImage *bootimg,
+                                   int options, int flag);
+
+/** 
+ * Get the options as of el_torito_set_isolinux_options().
+ *
+ * @param bootimg
+ *      The image to inquire
+ * @param flag
+ *        Reserved for future usage, set to 0.
+ * @return
+ *      >= 0 returned option bits , <0 = error
+ *
+ * @since 0.6.32
+ */
+int el_torito_get_isolinux_options(ElToritoBootImage *bootimg, int flag);
+
+/** Deprecated:
+ * Specifies that this image needs to be patched. This involves the writing
+ * of a 16 bytes boot information table at offset 8 of the boot image file.
+ * The original boot image file won't be modified.
+ * This is needed for isolinux boot images.
+ *
+ * @since 0.6.2
+ * @deprecated Use el_torito_set_isolinux_options() instead
+ */
+void el_torito_patch_isolinux_image(ElToritoBootImage *bootimg);
+
+/**
+ * Obtain a copy of the eventually loaded first 32768 bytes of the imported
+ * session, the System Area.
+ * It will be written to the start of the next session unless it gets
+ * overwritten by iso_write_opts_set_system_area().
+ *
+ * @param img
+ *        The image to be inquired.
+ * @param data
+ *        A byte array of at least 32768 bytesi to take the loaded bytes.
+ * @param options
+ *        The option bits which will be applied if not overridden by
+ *        iso_write_opts_set_system_area(). See there.
+ * @param flag
+ *        Bitfield for control purposes, unused yet, submit 0
+ * @return
+ *        1 on success, 0 if no System Area was loaded, < 0 error.
+ * @since 0.6.30
+ */
+int iso_image_get_system_area(IsoImage *img, char data[32768],
+                              int *options, int flag);
 
 /**
  * Increments the reference counting of the given node.
@@ -2501,14 +2960,14 @@
 /**
  * Set if the node will be hidden in RR/ISO tree, Joliet tree or both.
  *
- * If the file is set as hidden in one tree, it won't be included there, so
+ * If the file is set as hidden in one tree, it wil not be included there, so
  * it won't be visible in a OS accessing CD using that tree. For example,
  * GNU/Linux systems access to Rock Ridge / ISO9960 tree in order to see
  * what is recorded on CD, while MS Windows make use of the Joliet tree. If a
- * file is hidden only in Joliet, it won't be visible in Windows systems,
- * while still visible in Linux.
+ * file is hidden only in Joliet, it wil not be visible in Windows systems,
+ * while still visible in GNU/Linux.
  *
- * If a file is hidden in both trees, it won't be written to image.
+ * If a file is hidden in both trees, it will not be written to image.
  *
  * @param node
  *      The node that is to be hidden.
@@ -2959,8 +3418,8 @@
 int iso_symlink_set_dest(IsoSymlink *link, const char *dest);
 
 /**
- * Sets the order in which a node will be written on image. High weihted files
- * will be written first, so in a disc them will be written near the center.
+ * Sets the order in which a node will be written on image. The data content
+ * of files with high weight will be written to low block addresses.
  *
  * @param node
  *      The node which weight will be changed. If it's a dir, this function
@@ -2969,6 +3428,7 @@
  * @param w
  *      The weight as a integer number, the greater this value is, the
  *      closer from the begining of image the file will be written.
+ *      Default value at IsoNode creation is 0.
  *
  * @since 0.6.2
  */
@@ -3272,8 +3732,8 @@
 int iso_tree_get_ignore_special(IsoImage *image);
 
 /**
- * Add a excluded path. These are paths that won't never added to image,
- * and will be excluded even when adding recursively its parent directory.
+ * Add a excluded path. These are paths that won't never added to image, and
+ * will be excluded even when adding recursively its parent directory.
  *
  * For example, in
  *
@@ -3365,7 +3825,9 @@
  * @param parent
  *      The directory in the image tree where the node will be added.
  * @param path
- *      The path of the file to add in the filesystem.
+ *      The absolute path of the file in the local filesystem.
+ *      The node will have the same leaf name as the file on disk.
+ *      Its directory path depends on the parent node.
  * @param node
  *      place where to store a pointer to the newly added file. No
  *      extra ref is addded, so you will need to call iso_node_ref() if you
@@ -3395,9 +3857,10 @@
  * @param parent
  *      The directory in the image tree where the node will be added.
  * @param name
- *      The name that the node will have on image.
+ *      The leaf name that the node will have on image.
+ *      Its directory path depends on the parent node.
  * @param path
- *      The path of the file to add in the filesystem.
+ *      The absolute path of the file in the local filesystem.
  * @param node
  *      place where to store a pointer to the newly added file. No
  *      extra ref is addded, so you will need to call iso_node_ref() if you
@@ -3416,24 +3879,25 @@
                           const char *path, IsoNode **node);
 
 /**
- * Add a new node to the image tree, from an existing file, and with the
- * given name, that must not exist on dir. The node will be cut-out to the
- * submitted size, and its contents will be read from the given offset. This
- * function is thus suitable for adding only a piece of a file to the image.
+ * Add a new node to the image tree with the given name that must not exist
+ * on dir. The node data content will be a byte interval out of the data
+ * content of a file in the local filesystem.
  *
  * @param image
  *      The image
  * @param parent
  *      The directory in the image tree where the node will be added.
  * @param name
- *      The name that the node will have on image.
+ *      The leaf name that the node will have on image.
+ *      Its directory path depends on the parent node.
  * @param path
- *      The path of the file to add in the filesystem. For now only regular
- *      files and symlinks to regular files are supported.
+ *      The absolute path of the file in the local filesystem. For now
+ *      only regular files and symlinks to regular files are supported.
  * @param offset
- *      Offset on the given file from where to start reading data.
+ *      Byte number in the given file from where to start reading data.
  * @param size
- *      Max size of the file.
+ *      Max size of the file. This may be more than actually available from
+ *      byte offset to the end of the file in the local filesystem.
  * @param node
  *      place where to store a pointer to the newly added file. No
  *      extra ref is addded, so you will need to call iso_node_ref() if you
@@ -3476,7 +3940,7 @@
 int iso_tree_add_dir_rec(IsoImage *image, IsoDir *parent, const char *dir);
 
 /**
- * Locate a node by its path on image.
+ * Locate a node by its absolute path on image.
  *
  * @param node
  *     Location for a pointer to the node, it will filled with NULL if the
@@ -3493,7 +3957,7 @@
 int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node);
 
 /**
- * Get the path on image of the given node.
+ * Get the absolute path on image of the given node.
  *
  * @return
  *      The path on the image, that must be freed when no more needed. If the
@@ -3519,11 +3983,10 @@
 
 /**
  * Create a new IsoDataSource from a local file. This is suitable for
- * accessing regular .iso images, or to acces drives via its block device
- * and standard POSIX I/O calls.
+ * accessing regular files or block devices with ISO images.
  *
  * @param path
- *     The path of the file
+ *     The absolute path of the file
  * @param src
  *     Will be filled with the pointer to the newly created data source.
  * @return
@@ -3758,8 +4221,7 @@
  */
 
 /**
- * Get the path, relative to the filesystem this file source
- * belongs to.
+ * Get the absolute path in the filesystem this file source belongs to.
  *
  * @return
  *     the path of the FileSource inside the filesystem, it should be
@@ -4287,7 +4749,7 @@
  * @param default_text
  *      Will return a pointer to the eventual "default" ACL  or NULL if it
  *      is not available.
- *      (Linux directories can have a "default" ACL which influences
+ *      (GNU/Linux directories can have a "default" ACL which influences
  *       the permissions of newly created files.)
  * @param flag
  *      Bitfield for control purposes
@@ -4324,7 +4786,7 @@
  * @param default_text
  *      The text to be set into effect as "default" ACL. NULL will delete an
  *      eventually existing "default" ACL of the node.
- *      (Linux directories can have a "default" ACL which influences
+ *      (GNU/Linux directories can have a "default" ACL which influences
  *       the permissions of newly created files.)
  * @param flag
  *      Bitfield for control purposes
@@ -4412,7 +4874,7 @@
  * @param flag
  *      Bitfield for control purposes, unused yet, submit 0
  * @return
- *      1= name found , 0= name not found , <0 indicates error error
+ *      1= name found , 0= name not found , <0 indicates error
  *
  * @since 0.6.18
  */
@@ -4442,7 +4904,11 @@
  *      bit0= Do not maintain eventual existing ACL of the node.
  *            Set eventual new ACL from value of empty name.
  *      bit1= Do not clear the existing attribute list but merge it with
- *            the list given by this call
+ *            the list given by this call.
+ *            The given values override the values of their eventually existing
+ *            names. If no xattr with a given name exists, then it will be
+ *            added as new xattr. So this bit can be used to set a single
+ *            xattr without inquiring any other xattr of the node.
  *      bit2= Delete the attributes with the given names
  *      bit3= Allow to affect non-user attributes.
  *            I.e. those with a non-empty name which does not begin by "user."
@@ -4471,7 +4937,7 @@
  * Get an ACL of the given file in the local filesystem in long text form.
  *
  * @param disk_path
- *      Path to the file
+ *      Absolute path to the file
  * @param text
  *      Will return a pointer to the ACL text. If not NULL the text will be
  *      0 terminated and finally has to be disposed by a call to this function
@@ -4486,7 +4952,7 @@
  * @return
  *        1 ok 
  *        2 ok, trivial ACL found while bit4 is set, *text is NULL 
- *        0 no ACL manipulation adapter available
+ *        0 no ACL manipulation adapter available / ACL not supported on fs
  *       -1 failure of system ACL service (see errno)
  *       -2 attempt to inquire ACL of a symbolic link without bit4 or bit5
  *          resp. with no suitable link target
@@ -4501,7 +4967,7 @@
  * in long text form.
  *
  * @param disk_path
- *      Path to the file
+ *      Absolute path to the file
  * @param text
  *      The input text (0 terminated, ACL long text form)
  * @param flag
@@ -4526,7 +4992,7 @@
  * necessary if the permissions of a disk file with ACL shall be copied to
  * an object which has no ACL.
  * @param disk_path
- *      Path to the local file which may have an "access" ACL or not.
+ *      Absolute path to the local file which may have an "access" ACL or not.
  * @param flag
  *      Bitfield for control purposes
  *           bit5=  in case of symbolic link: inquire link target
@@ -4551,7 +5017,7 @@
  * will not be put into the result.
  *
  * @param disk_path
- *      Path to the file
+ *      Absolute path to the file
  * @param num_attrs
  *      Will return the number of name-value pairs
  * @param names
@@ -4584,7 +5050,7 @@
  * Eventual ACLs have to be encoded as attribute pair with empty name.
  *
  * @param disk_path
- *      Path to the file
+ *      Absolute path to the file
  * @param num_attrs
  *      Number of attributes
  * @param names
@@ -4609,6 +5075,11 @@
                         size_t *value_lengths, char **values, int flag);
 
 
+/* Default in case that the compile environment has no macro PATH_MAX.
+*/
+#define Libisofs_default_path_maX 4096
+
+
 /* --------------------------- Filters in General -------------------------- */
 
 /*
@@ -4953,6 +5424,223 @@
 int iso_gzip_get_refcounts(off_t *gzip_count, off_t *gunzip_count, int flag);
 
 
+/* ---------------------------- MD5 Checksums --------------------------- */
+
+/* Production and loading of MD5 checksums is controlled by calls
+   iso_write_opts_set_record_md5() and iso_read_opts_set_no_md5().
+   For data representation details see doc/checksums.txt .
+*/
+
+/**
+ * Eventually obtain the recorded MD5 checksum of the session which was
+ * loaded as ISO image. Such a checksum may be stored together with others
+ * in a contiguous array at the end of the session. The session checksum
+ * covers the data blocks from address start_lba to address end_lba - 1.
+ * It does not cover the recorded array of md5 checksums.
+ * Layout, size, and position of the checksum array is recorded in the xattr
+ * "isofs.ca" of the session root node.
+ * @param image
+ *      The image to inquire
+ * @param start_lba
+ *      Eventually returns the first block address covered by md5
+ * @param end_lba
+ *      Eventually returns the first block address not covered by md5 any more
+ * @param md5
+ *      Eventually returns 16 byte of MD5 checksum 
+ * @param flag
+ *      Bitfield for control purposes, unused yet, submit 0
+ * @return
+ *      1= md5 found , 0= no md5 available , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_image_get_session_md5(IsoImage *image, uint32_t *start_lba,
+                              uint32_t *end_lba, char md5[16], int flag);
+
+/**
+ * Eventually obtain the recorded MD5 checksum of a data file from the loaded
+ * ISO image. Such a checksum may be stored with others in a contiguous
+ * array at the end of the loaded session. The data file eventually has an
+ * xattr "isofs.cx" which gives the index in that array.
+ * @param image
+ *      The image from which file stems.
+ * @param file
+ *      The file object to inquire
+ * @param md5
+ *      Eventually returns 16 byte of MD5 checksum 
+ * @param flag
+ *      Bitfield for control purposes
+ *      bit0= only determine return value, do not touch parameter md5
+ * @return
+ *      1= md5 found , 0= no md5 available , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag);
+
+/**
+ * Read the content of an IsoFile object, compute its MD5 and attach it to
+ * the IsoFile. It can then be inquired by iso_file_get_md5() and will get
+ * written into the next session if this is enabled at write time and if the
+ * image write process does not compute an MD5 from content which it copies.
+ * So this call can be used to equip nodes from the old image with checksums
+ * or to make available checksums of newly added files before the session gets
+ * written.
+ * @param file
+ *      The file object to read data from and to which to attach the checksum.
+ *      If the file is from the imported image, then its most original stream
+ *      will be checksummed. Else the eventual filter streams will get into
+ *      effect.
+ * @param flag
+ *      Bitfield for control purposes. Unused yet. Submit 0.
+ * @return
+ *      1= ok, MD5 is computed and attached , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_file_make_md5(IsoFile *file, int flag);
+
+/**
+ * Check a data block whether it is a libisofs session checksum tag and
+ * eventually obtain its recorded parameters. These tags get written after
+ * volume descriptors, directory tree and checksum array and can be detected
+ * without loading the image tree.
+ * One may start reading and computing MD5 at the suspected image session
+ * start and look out for a session tag on the fly. See doc/checksum.txt .
+ * @param data
+ *      A complete and aligned data block read from an ISO image session.
+ * @param tag_type
+ *      0= no tag
+ *      1= session tag
+ *      2= superblock tag
+ *      3= tree tag
+ *      4= relocated 64 kB superblock tag (at LBA 0 of overwriteable media)
+ * @param pos
+ *      Returns the LBA where the tag supposes itself to be stored.
+ *      If this does not match the data block LBA then the tag might be
+ *      image data payload and should be ignored for image checksumming.
+ * @param range_start
+ *      Returns the block address where the session is supposed to start.
+ *      If this does not match the session start on media then the image
+ *      volume descriptors have been been relocated.
+ *      A proper checksum will only emerge if computing started at range_start.
+ * @param range_size
+ *      Returns the number of blocks beginning at range_start which are
+ *      covered by parameter md5.
+ * @param next_tag
+ *      Returns the predicted block address of the next tag.
+ *      next_tag is valid only if not 0 and only with return values 2, 3, 4.
+ *      With tag types 2 and 3, reading shall go on sequentially and the MD5
+ *      computation shall continue up to that address.
+ *      With tag type 4, reading shall resume either at LBA 32 for the first
+ *      session or at the given address for the session which is to be loaded
+ *      by default. In both cases the MD5 computation shall be re-started from
+ *      scratch.
+ * @param md5
+ *      Returns 16 byte of MD5 checksum.
+ * @param flag
+ *      Bitfield for control purposes:
+ *      bit0-bit7= tag type being looked for
+ *                 0= any checksum tag
+ *                 1= session tag
+ *                 2= superblock tag
+ *                 3= tree tag
+ *                 4= relocated superblock tag
+ * @return
+ *      0= not a checksum tag, return parameters are invalid
+ *      1= checksum tag found, return parameters are valid
+ *     <0= error 
+ *         (return parameters are valid with error ISO_MD5_AREA_CORRUPTED
+ *          but not trustworthy because the tag seems corrupted)
+ *
+ * @since 0.6.22
+ */
+int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
+                            uint32_t *range_start, uint32_t *range_size,
+                            uint32_t *next_tag, char md5[16], int flag);
+
+
+/* The following functions allow to do own MD5 computations. E.g for
+   comparing the result with a recorded checksum.
+*/
+/**
+ * Create a MD5 computation context and hand out an opaque handle.
+ *
+ * @param md5_context
+ *      Returns the opaque handle. Submitted *md5_context must be NULL or
+ *      point to freeable memory.
+ * @return
+ *      1= success , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_md5_start(void **md5_context);
+
+/**
+ * Advance the computation of a MD5 checksum by a chunk of data bytes.
+ *
+ * @param md5_context
+ *      An opaque handle once returned by iso_md5_start() or iso_md5_clone().
+ * @param data
+ *      The bytes which shall be processed into to the checksum.
+ * @param datalen
+ *      The number of bytes to be processed.
+ * @return
+ *      1= success , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_md5_compute(void *md5_context, char *data, int datalen);
+
+/**     
+ * Create a MD5 computation context as clone of an existing one. One may call
+ * iso_md5_clone(old, &new, 0) and then iso_md5_end(&new, result, 0) in order
+ * to obtain an intermediate MD5 sum before the computation goes on.
+ * 
+ * @param old_md5_context
+ *      An opaque handle once returned by iso_md5_start() or iso_md5_clone().
+ * @param new_md5_context
+ *      Returns the opaque handle to the new MD5 context. Submitted
+ *      *md5_context must be NULL or point to freeable memory.
+ * @return
+ *      1= success , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_md5_clone(void *old_md5_context, void **new_md5_context);
+
+/**
+ * Obtain the MD5 checksum from a MD5 computation context and dispose this
+ * context. (If you want to keep the context then call iso_md5_clone() and
+ * apply iso_md5_end() to the clone.)
+ *
+ * @param md5_context
+ *      A pointer to an opaque handle once returned by iso_md5_start() or
+ *      iso_md5_clone(). *md5_context will be set to NULL in this call.
+ * @param result
+ *      Gets filled with the 16 bytes of MD5 checksum.
+ * @return
+ *      1= success , <0 indicates error
+ *
+ * @since 0.6.22
+ */
+int iso_md5_end(void **md5_context, char result[16]);
+
+/**
+ * Inquire whether two MD5 checksums match. (This is trivial but such a call
+ * is convenient and completes the interface.)
+ * @param first_md5
+ *      A MD5 byte string as returned by iso_md5_end()
+ * @param second_md5
+ *      A MD5 byte string as returned by iso_md5_end()
+ * @return
+ *      1= match , 0= mismatch
+ *
+ * @since 0.6.22
+ */
+int iso_md5_match(char first_md5[16], char second_md5[16]);
+
+
 /************ Error codes and return values for libisofs ********************/
 
 /** successfully execution */
@@ -5019,6 +5707,9 @@
 /** Trying to use an invalid file as boot image (FAILURE,HIGH, -68) */
 #define ISO_BOOT_IMAGE_NOT_VALID        0xE830FFBB
 
+/** Too many boot images (FAILURE,HIGH, -69) */
+#define ISO_BOOT_IMAGE_OVERFLOW         0xE830FFBA
+
 /**
  * Error on file operation (FAILURE,HIGH, -128)
  * (take a look at more specified error codes below)
@@ -5085,11 +5776,12 @@
 #define ISO_FILE_IMGPATH_WRONG          0xD020FF70
 
 /**
- * Offset greater than file size (FAILURE,HIGH, -145)
+ * Offset greater than file size (FAILURE,HIGH, -150)
  * @since 0.6.4
  */
 #define ISO_FILE_OFFSET_TOO_BIG         0xE830FF6A
 
+
 /** Charset conversion error (FAILURE,HIGH, -256) */
 #define ISO_CHARSET_CONV_ERROR          0xE830FF00
 
@@ -5119,11 +5811,11 @@
 /** Unsupported ECMA-119 feature (FAILURE,HIGH, -324) */
 #define ISO_UNSUPPORTED_ECMA119         0xE830FEBC
 
-/** Wrong or damaged El-Torito catalog (SORRY,HIGH, -325) */
-#define ISO_WRONG_EL_TORITO             0xE030FEBB
+/** Wrong or damaged El-Torito catalog (WARN,HIGH, -325) */
+#define ISO_WRONG_EL_TORITO             0xD030FEBB
 
-/** Unsupported El-Torito feature (SORRY,HIGH, -326) */
-#define ISO_UNSUPPORTED_EL_TORITO       0xE030FEBA
+/** Unsupported El-Torito feature (WARN,HIGH, -326) */
+#define ISO_UNSUPPORTED_EL_TORITO       0xD030FEBA
 
 /** Can't patch an isolinux boot image (SORRY,HIGH, -327) */
 #define ISO_ISOLINUX_CANT_PATCH         0xE030FEB9
@@ -5207,6 +5899,59 @@
 /** Premature EOF of zlib input stream  (FAILURE, HIGH, -351) */
 #define ISO_ZLIB_EARLY_EOF        0xE830FEA1
 
+/**
+ * Checksum area or checksum tag appear corrupted  (WARNING,HIGH, -352)
+ * @since 0.6.22
+*/
+#define ISO_MD5_AREA_CORRUPTED    0xD030FEA0
+
+/**
+ * Checksum mismatch between checksum tag and data blocks
+ * (FAILURE, HIGH, -353)
+ * @since 0.6.22
+*/
+#define ISO_MD5_TAG_MISMATCH      0xE830FE9F
+
+/**
+ * Checksum mismatch in System Area, Volume Descriptors, or directory tree.
+ * (FAILURE, HIGH, -354)
+ * @since 0.6.22
+*/
+#define ISO_SB_TREE_CORRUPTED     0xE830FE9E
+
+/**
+ * Unexpected checksum tag type encountered.   (WARNING, HIGH, -355)
+ * @since 0.6.22
+*/
+#define ISO_MD5_TAG_UNEXPECTED    0xD030FE9D
+
+/**
+ * Misplaced checksum tag encountered. (WARNING, HIGH, -356)
+ * @since 0.6.22
+*/
+#define ISO_MD5_TAG_MISPLACED     0xD030FE9C
+
+/**
+ * Checksum tag with unexpected address range encountered.
+ * (WARNING, HIGH, -357)
+ * @since 0.6.22
+*/
+#define ISO_MD5_TAG_OTHER_RANGE   0xD030FE9B
+
+/**
+ * Detected file content changes while it was written into the image.
+ * (MISHAP, HIGH, -358)
+ * @since 0.6.22
+*/
+#define ISO_MD5_STREAM_CHANGE     0xE430FE9A
+
+/**
+ * Session does not start at LBA 0. scdbackup checksum tag not written.
+ * (WARNING, HIGH, -359)
+ * @since 0.6.24
+*/
+#define ISO_SCDBACKUP_TAG_NOT_0   0xD030FE99
+
 
 /* ! PLACE NEW ERROR CODES HERE ! */
 
@@ -5412,39 +6157,19 @@
 
 /* currently none being tested */
 
-/* ---------------------------- Improvements --------------------------- */
-
-/* currently none being tested */
-
-/* ---------------------------- Experiments ---------------------------- */
 
-/* Hardlinks : During image generation accompany the tree of IsoFileSrc
-               by a sorted array of Ecma119Node.
-               The sorting order shall bring together candidates for being
-               hardlink siblings resp. having identical content.
-
-               This is in sync with the IsoFileSrc unification by IsoRBTree
-               and iso_file_src_cmp().
-               That tree cannot be obsoleted because Joliet and ISO1999 depend
-               on it. On the other hand, the Ecma119Node array includes objects
-               which have no IsoFileSrc attached. So both, tree and array, are
-               needed.
-*/
-#define Libisofs_hardlink_matcheR yes
+/* ---------------------------- Improvements --------------------------- */
 
 
-/* Hardlinks : Override Libisofs_new_fs_image_inO and preserve inode numbers
-               from session to session.
+/* Checksums : During image writing equip IsoFile objects with MD5 checksums
+               and compute an overall checksum of the session. Store them in
+               a separate checksum block area after the data area of the
+               session.
 */
-#define Libisofs_hardlink_prooF yes
+#define Libisofs_with_checksumS yes
 
 
-/* Experiment: Ignore PX inode numbers,
-               have boot image inode number counted by fs_give_ino_number()
-
-   Overridden if Libisofs_hardlink_prooF is defined.
- #define Libisofs_new_fs_image_inO yes
-*/
+/* ---------------------------- Experiments ---------------------------- */
 
 
 /* Experiment: Write obsolete RR entries with Rock Ridge.
@@ -5455,5 +6180,4 @@
 */
 
 
-
 #endif /*LIBISO_LIBISOFS_H_*/
--- libisofs/make_isohybrid_mbr.c
+++ libisofs/make_isohybrid_mbr.c
@@ -10,6 +10,7 @@
 /* for gettimeofday() */
 #include <sys/time.h>
 
+
 /* This code stems from syslinux-3.72/utils/isohybrid, a perl script
 under GPL which is Copyright 2002-2008 H. Peter Anvin.
 
@@ -25,12 +26,13 @@
  or both, at your option.
  Sincerely, H. Peter Anvin
 
-In the context of libisofs this code derives its matching open source
+In the context of GNU xorriso, this code is under GPLv3+ derived from LGPL.
+In the context of libisofs this code derives its matching free software
 license from above stem licenses, typically from LGPL.
 In case its generosity is needed, here is the 2-clause BSD license:
 
 make_isohybrid_mbr.c is copyright 2002-2008 H. Peter Anvin
-                              and 2008 libburnia project.
+                              and 2008-2010 Thomas Schmitt
 
 1. Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer.
@@ -50,8 +52,9 @@
 
 */
 
+
 /* A helper function. One could replace it by one or two macros. */
-static int lsb_to_buf(char **wpt, int value, int bits, int flag)
+static int lsb_to_buf(char **wpt, uint32_t value, int bits, int flag)
 {
     int b;
 
@@ -60,6 +63,11 @@
     return (1);
 }
 
+
+/* ====================================================================== */
+/*                          Deprecated Function                           */
+/* ====================================================================== */
+
 /*
  * Create a MBR for an isohybrid enabled ISOLINUX boot image.
  *
@@ -227,3 +235,214 @@
     return (1);
 }
 
+
+/* ====================================================================== */
+/*                          The New MBR Producer                          */
+/* ====================================================================== */
+
+/* The new MBR producer for isohybrid is a slightly generalized version of
+   the deprecated function make_isohybrid_mbr(). It complies to the urge
+   of H.Peter Anvin not to hardcode MBR templates but rather to read a
+   file from the Syslinux tree, and to patch it as was done with the old
+   MBR producer.
+
+   The old algorithm was clarified publicly by the following mail.
+   Changes towards the old algorithm:
+   - 512-byte LBA of boot image is extended to 64 bit (we stay with 32)
+   - check for a magic number is now gone
+
+   The new implementation tries to use similar terms as the mail in order
+   to facilitate its future discussion with Syslinux developers.
+
+From hpa at zytor.com Thu Apr  1 08:32:52 2010
+Date: Wed, 31 Mar 2010 14:53:51 -0700
+From: H. Peter Anvin <hpa at zytor.com>
+To: For discussion of Syslinux and tftp-hpa <syslinux at zytor.com>
+Cc: Thomas Schmitt <scdbackup at gmx.net>
+Subject: Re: [syslinux] port syslinux isohybrid perl script to C
+
+[...]
+
+[me:]
+> Currently i lack of blob and prescriptions.
+
+The blobs are available in the Syslinux build tree under the names:
+
+mbr/isohdp[fp]x*.bin
+
+The default probably should be mbr/isohdppx.bin, but it's ultimately up
+to the user.
+
+User definable parameters:
+
+-> MBR ID		(default random 32-bit number,
+			 or preserved from previous instance)
+-> Sector count		(default 32, range 1-63)
+-> Head count		(default 64, range 1-256)
+-> Partition offset	(default 0, range 0-64)
+-> Partition number	(default 1, range 1-4)
+-> Filesystem type	(default 0x17, range 1-255)
+
+Note: the filesystem type is largely arbitrary, in theory it can be any
+value other than 0x00, 0x05, 0x0f, 0x85, 0xee, or 0xef.  0x17 ("Windows
+IFS Hidden") seems safeish, some people believe 0x83 (Linux) is better.
+
+Here is the prescriptions for how to install it:
+
+All numbers are littleendian.  "word" means 16 bits, "dword" means 32
+bits, "qword" means 64 bits.
+
+Common subroutine LBA_to_CHS():
+	s = (lba % sector_count) + 1
+	t = (lba / sector_count)
+	h = (t % head_count)
+	c = (t / head_count)
+
+	if (c >= 1024):
+		c = 1023
+		h = head_count
+		s = sector_count
+
+	s = s | ((c & 0x300) >> 2)
+	c = c & 0xff
+
+	write byte h
+	write byte s
+	write byte c
+
+Main:
+	Pad image_size to a multiple of sector_count*head_count
+	Use the input file unmodified for bytes 0..431
+	write qword boot_lba		# Offset 432
+	write dword mbr_id		# Offset 440
+	write word 0			# Offset 444
+
+	# Offset 446
+	For each partition entry 1..4:
+		if this_partition != partition_number:
+			write 16 zero bytes
+		else:
+			write byte 0x80
+			write LBA_to_CHS(partition_offset)
+			write byte filesystem_type
+			write LBA_to_CHS(image_size-1)
+			write dword partition_offset
+			write dword image_size
+
+	# Offset 510
+	write word 0xaa55
+
+	Use the input file unmodified for bytes 512..32767
+	(pad with zero as necessary)
+
+[...]
+
+	-hpa
+*/
+
+
+static
+int lba512chs_to_buf(char **wpt, off_t lba, int head_count, int sector_count)
+{
+    int s, t, h, c;
+
+    s = (lba % sector_count) + 1;
+    t = (lba / sector_count);
+    h = (t % head_count);
+    c = (t / head_count);
+    if (c >= 1024) {
+        c = 1023;
+        h = head_count; /* >>> not -1 ? Limits head_count to 255 */
+        s = sector_count;
+    }
+    s = s | ((c & 0x300) >> 2);
+    c = c & 0xff;
+    (*((unsigned char **) wpt))[0] = h;
+    (*((unsigned char **) wpt))[1] = s;
+    (*((unsigned char **) wpt))[2] = c;
+    (*wpt)+= 3;
+    return(1); 
+}
+
+
+/*
+ * @param flag  bit0= make own random MBR Id from current time
+ */
+int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
+                      uint32_t mbr_id, int head_count, int sector_count,
+                      int part_offset, int part_number, int fs_type,
+                      uint8_t *buf, int flag)
+{
+    uint32_t spc, id, part, nominal_part_size;
+    off_t hd_img_blocks, hd_boot_lba;
+    char *wpt;
+    /* For generating a weak random number */
+    struct timeval tv;
+    struct timezone tz;
+
+    /* Pad image_size to a multiple of sector_count*head_count
+    */
+    spc = head_count * sector_count;
+    hd_img_blocks = ((off_t) *img_blocks) * (off_t) 4;
+    if (hd_img_blocks % spc) {
+        hd_img_blocks += spc - (hd_img_blocks % spc);
+        *img_blocks = hd_img_blocks / 4 + !!(hd_img_blocks % 4);
+    }
+
+    wpt = (char *) buf + 432;
+
+    /* write qword boot_lba            # Offset 432
+    */
+    hd_boot_lba = ((off_t) boot_lba) * (off_t) 4;
+    lsb_to_buf(&wpt, hd_boot_lba & 0xffffffff, 32, 0);
+    lsb_to_buf(&wpt, hd_boot_lba >> 32, 32, 0);
+
+    /* write dword mbr_id              # Offset 440 
+       (here some 32-bit random value with no crypto strength)
+    */
+    if (flag & 1) {
+        gettimeofday(&tv, &tz);
+        id = 0xffffffff & (tv.tv_sec ^ (tv.tv_usec * 2000));
+        lsb_to_buf(&wpt, id, 32, 0);
+    }
+
+    /* write word 0                    # Offset 444
+    */
+    lsb_to_buf(&wpt, 0, 16, 0);
+
+    /* # Offset 446
+    */
+    for (part = 1 ; part <= 4; part++) {
+        if (part != part_number) {
+            /* if this_partition != partition_number: write 16 zero bytes */
+            memset(wpt, 0, 16);
+            wpt+= 16;
+    continue;
+        }
+        /* write byte 0x80
+           write LBA_to_CHS(partition_offset)
+           write byte filesystem_type
+           write LBA_to_CHS(image_size-1)
+           write dword partition_offset
+           write dword image_size
+        */
+        lsb_to_buf(&wpt, 0x80, 8, 0);
+        lba512chs_to_buf(&wpt, part_offset, head_count, sector_count);
+        lsb_to_buf(&wpt, fs_type, 8, 0);
+        lba512chs_to_buf(&wpt, hd_img_blocks - 1, head_count, sector_count);
+        lsb_to_buf(&wpt, part_offset, 32, 0);
+        if (hd_img_blocks - (off_t) part_offset > (off_t) 0xffffffff)
+            nominal_part_size = 0xffffffff;
+        else
+            nominal_part_size = hd_img_blocks - (off_t) part_offset;
+        lsb_to_buf(&wpt, nominal_part_size, 32, 0);
+    }
+
+    /*  write word 0xaa55            # Offset 510
+    */
+    lsb_to_buf(&wpt, 0xaa55, 16, 0);
+
+    return(1);
+}
+
+
--- libisofs/md5.c
+++ libisofs/md5.c
+/*
+ * Copyright (c) 2009 Thomas Schmitt
+ *
+ * This file is part of the libisofs project; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
+ */
+
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "writer.h"
+#include "messages.h"
+#include "ecma119.h"
+#include "image.h"
+#include "util.h"
+
+#include "md5.h"
+
+
+/* This code is derived from RFC 1321 and implements computation of the
+    "RSA Data Security, Inc. MD5 Message-Digest Algorithm" */
+
+#define Libisofs_md5_S11 7
+#define Libisofs_md5_S12 12
+#define Libisofs_md5_S13 17
+#define Libisofs_md5_S14 22
+#define Libisofs_md5_S21 5
+#define Libisofs_md5_S22 9
+#define Libisofs_md5_S23 14
+#define Libisofs_md5_S24 20
+#define Libisofs_md5_S31 4
+#define Libisofs_md5_S32 11
+#define Libisofs_md5_S33 16
+#define Libisofs_md5_S34 23
+#define Libisofs_md5_S41 6
+#define Libisofs_md5_S42 10
+#define Libisofs_md5_S43 15
+#define Libisofs_md5_S44 21
+
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define Libisofs_md5_F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define Libisofs_md5_G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define Libisofs_md5_H(x, y, z) ((x) ^ (y) ^ (z))
+#define Libisofs_md5_I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define Libisofs_md5_ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define Libisofs_md5_FF(a, b, c, d, x, s, ac) { \
+ (a) += Libisofs_md5_F ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define Libisofs_md5_GG(a, b, c, d, x, s, ac) { \
+ (a) += Libisofs_md5_G ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define Libisofs_md5_HH(a, b, c, d, x, s, ac) { \
+ (a) += Libisofs_md5_H ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define Libisofs_md5_II(a, b, c, d, x, s, ac) { \
+ (a) += Libisofs_md5_I ((b), (c), (d)) + (x) + (uint32_t)(ac); \
+ (a) = Libisofs_md5_ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+
+/* MD5 context. */
+struct _libisofs_md5_ctx {
+  uint32_t state[4];                                   /* state (ABCD) */
+  uint32_t count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+};
+
+typedef struct _libisofs_md5_ctx libisofs_md5_ctx;
+
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static int md5__transform (uint32_t state[4], unsigned char block[64])
+{
+ uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < 64; i++, j += 4)
+   x[i] = ((uint32_t)block[j]) | (((uint32_t)block[j+1]) << 8) |
+    (((uint32_t)block[j+2]) << 16) | (((uint32_t)block[j+3]) << 24);
+
+  /* Round 1 */
+  Libisofs_md5_FF (a, b, c, d, x[ 0], Libisofs_md5_S11, 0xd76aa478); /* 1 */
+  Libisofs_md5_FF (d, a, b, c, x[ 1], Libisofs_md5_S12, 0xe8c7b756); /* 2 */
+  Libisofs_md5_FF (c, d, a, b, x[ 2], Libisofs_md5_S13, 0x242070db); /* 3 */
+  Libisofs_md5_FF (b, c, d, a, x[ 3], Libisofs_md5_S14, 0xc1bdceee); /* 4 */
+  Libisofs_md5_FF (a, b, c, d, x[ 4], Libisofs_md5_S11, 0xf57c0faf); /* 5 */
+  Libisofs_md5_FF (d, a, b, c, x[ 5], Libisofs_md5_S12, 0x4787c62a); /* 6 */
+  Libisofs_md5_FF (c, d, a, b, x[ 6], Libisofs_md5_S13, 0xa8304613); /* 7 */
+  Libisofs_md5_FF (b, c, d, a, x[ 7], Libisofs_md5_S14, 0xfd469501); /* 8 */
+  Libisofs_md5_FF (a, b, c, d, x[ 8], Libisofs_md5_S11, 0x698098d8); /* 9 */
+  Libisofs_md5_FF (d, a, b, c, x[ 9], Libisofs_md5_S12, 0x8b44f7af); /* 10 */
+  Libisofs_md5_FF (c, d, a, b, x[10], Libisofs_md5_S13, 0xffff5bb1); /* 11 */
+  Libisofs_md5_FF (b, c, d, a, x[11], Libisofs_md5_S14, 0x895cd7be); /* 12 */
+  Libisofs_md5_FF (a, b, c, d, x[12], Libisofs_md5_S11, 0x6b901122); /* 13 */
+  Libisofs_md5_FF (d, a, b, c, x[13], Libisofs_md5_S12, 0xfd987193); /* 14 */
+  Libisofs_md5_FF (c, d, a, b, x[14], Libisofs_md5_S13, 0xa679438e); /* 15 */
+  Libisofs_md5_FF (b, c, d, a, x[15], Libisofs_md5_S14, 0x49b40821); /* 16 */
+
+  /* Round 2 */
+  Libisofs_md5_GG (a, b, c, d, x[ 1], Libisofs_md5_S21, 0xf61e2562); /* 17 */
+  Libisofs_md5_GG (d, a, b, c, x[ 6], Libisofs_md5_S22, 0xc040b340); /* 18 */
+  Libisofs_md5_GG (c, d, a, b, x[11], Libisofs_md5_S23, 0x265e5a51); /* 19 */
+  Libisofs_md5_GG (b, c, d, a, x[ 0], Libisofs_md5_S24, 0xe9b6c7aa); /* 20 */
+  Libisofs_md5_GG (a, b, c, d, x[ 5], Libisofs_md5_S21, 0xd62f105d); /* 21 */
+  Libisofs_md5_GG (d, a, b, c, x[10], Libisofs_md5_S22,  0x2441453); /* 22 */
+  Libisofs_md5_GG (c, d, a, b, x[15], Libisofs_md5_S23, 0xd8a1e681); /* 23 */
+  Libisofs_md5_GG (b, c, d, a, x[ 4], Libisofs_md5_S24, 0xe7d3fbc8); /* 24 */
+  Libisofs_md5_GG (a, b, c, d, x[ 9], Libisofs_md5_S21, 0x21e1cde6); /* 25 */
+  Libisofs_md5_GG (d, a, b, c, x[14], Libisofs_md5_S22, 0xc33707d6); /* 26 */
+  Libisofs_md5_GG (c, d, a, b, x[ 3], Libisofs_md5_S23, 0xf4d50d87); /* 27 */
+  Libisofs_md5_GG (b, c, d, a, x[ 8], Libisofs_md5_S24, 0x455a14ed); /* 28 */
+  Libisofs_md5_GG (a, b, c, d, x[13], Libisofs_md5_S21, 0xa9e3e905); /* 29 */
+  Libisofs_md5_GG (d, a, b, c, x[ 2], Libisofs_md5_S22, 0xfcefa3f8); /* 30 */
+  Libisofs_md5_GG (c, d, a, b, x[ 7], Libisofs_md5_S23, 0x676f02d9); /* 31 */
+  Libisofs_md5_GG (b, c, d, a, x[12], Libisofs_md5_S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  Libisofs_md5_HH (a, b, c, d, x[ 5], Libisofs_md5_S31, 0xfffa3942); /* 33 */
+  Libisofs_md5_HH (d, a, b, c, x[ 8], Libisofs_md5_S32, 0x8771f681); /* 34 */
+  Libisofs_md5_HH (c, d, a, b, x[11], Libisofs_md5_S33, 0x6d9d6122); /* 35 */
+  Libisofs_md5_HH (b, c, d, a, x[14], Libisofs_md5_S34, 0xfde5380c); /* 36 */
+  Libisofs_md5_HH (a, b, c, d, x[ 1], Libisofs_md5_S31, 0xa4beea44); /* 37 */
+  Libisofs_md5_HH (d, a, b, c, x[ 4], Libisofs_md5_S32, 0x4bdecfa9); /* 38 */
+  Libisofs_md5_HH (c, d, a, b, x[ 7], Libisofs_md5_S33, 0xf6bb4b60); /* 39 */
+  Libisofs_md5_HH (b, c, d, a, x[10], Libisofs_md5_S34, 0xbebfbc70); /* 40 */
+  Libisofs_md5_HH (a, b, c, d, x[13], Libisofs_md5_S31, 0x289b7ec6); /* 41 */
+  Libisofs_md5_HH (d, a, b, c, x[ 0], Libisofs_md5_S32, 0xeaa127fa); /* 42 */
+  Libisofs_md5_HH (c, d, a, b, x[ 3], Libisofs_md5_S33, 0xd4ef3085); /* 43 */
+  Libisofs_md5_HH (b, c, d, a, x[ 6], Libisofs_md5_S34,  0x4881d05); /* 44 */
+  Libisofs_md5_HH (a, b, c, d, x[ 9], Libisofs_md5_S31, 0xd9d4d039); /* 45 */
+  Libisofs_md5_HH (d, a, b, c, x[12], Libisofs_md5_S32, 0xe6db99e5); /* 46 */
+  Libisofs_md5_HH (c, d, a, b, x[15], Libisofs_md5_S33, 0x1fa27cf8); /* 47 */
+  Libisofs_md5_HH (b, c, d, a, x[ 2], Libisofs_md5_S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  Libisofs_md5_II (a, b, c, d, x[ 0], Libisofs_md5_S41, 0xf4292244); /* 49 */
+  Libisofs_md5_II (d, a, b, c, x[ 7], Libisofs_md5_S42, 0x432aff97); /* 50 */
+  Libisofs_md5_II (c, d, a, b, x[14], Libisofs_md5_S43, 0xab9423a7); /* 51 */
+  Libisofs_md5_II (b, c, d, a, x[ 5], Libisofs_md5_S44, 0xfc93a039); /* 52 */
+  Libisofs_md5_II (a, b, c, d, x[12], Libisofs_md5_S41, 0x655b59c3); /* 53 */
+  Libisofs_md5_II (d, a, b, c, x[ 3], Libisofs_md5_S42, 0x8f0ccc92); /* 54 */
+  Libisofs_md5_II (c, d, a, b, x[10], Libisofs_md5_S43, 0xffeff47d); /* 55 */
+  Libisofs_md5_II (b, c, d, a, x[ 1], Libisofs_md5_S44, 0x85845dd1); /* 56 */
+  Libisofs_md5_II (a, b, c, d, x[ 8], Libisofs_md5_S41, 0x6fa87e4f); /* 57 */
+  Libisofs_md5_II (d, a, b, c, x[15], Libisofs_md5_S42, 0xfe2ce6e0); /* 58 */
+  Libisofs_md5_II (c, d, a, b, x[ 6], Libisofs_md5_S43, 0xa3014314); /* 59 */
+  Libisofs_md5_II (b, c, d, a, x[13], Libisofs_md5_S44, 0x4e0811a1); /* 60 */
+  Libisofs_md5_II (a, b, c, d, x[ 4], Libisofs_md5_S41, 0xf7537e82); /* 61 */
+  Libisofs_md5_II (d, a, b, c, x[11], Libisofs_md5_S42, 0xbd3af235); /* 62 */
+  Libisofs_md5_II (c, d, a, b, x[ 2], Libisofs_md5_S43, 0x2ad7d2bb); /* 63 */
+  Libisofs_md5_II (b, c, d, a, x[ 9], Libisofs_md5_S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information. */
+  memset ((char *) x, 0, sizeof (x));
+  return(1);
+}
+
+
+static int md5__encode(unsigned char *output, uint32_t *input,
+                       unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+  return(1);
+}
+
+
+
+static int md5_init(libisofs_md5_ctx *ctx, int flag)
+{
+ ctx->count[0] = ctx->count[1] = 0;
+ /* Load magic initialization constants. */
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xefcdab89;
+ ctx->state[2] = 0x98badcfe;
+ ctx->state[3] = 0x10325476;
+ return(1);
+}
+
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+static int md5_update(libisofs_md5_ctx *ctx, unsigned char *data,
+                      int datalen, int flag)
+{
+ unsigned int i, index, partlen;
+
+ /* Compute number of bytes mod 64 */
+ index = (unsigned int)((ctx->count[0] >> 3) & 0x3F);
+ /* Update number of bits */
+ if ((ctx->count[0] += ((uint32_t) datalen << 3)) < 
+     ((uint32_t) datalen << 3))
+   ctx->count[1]++;
+ ctx->count[1] += ((uint32_t) datalen >> 29);
+ partlen = 64 - index;
+
+ /* Transform as many times as possible. */
+ if (datalen >= partlen) {
+   memcpy((char *) &ctx->buffer[index], (char *) data, partlen);
+   md5__transform(ctx->state, ctx->buffer);
+   for (i = partlen; i + 63 < datalen; i += 64)
+     md5__transform(ctx->state, &data[i]);
+   index = 0;
+ } else
+   i = 0;
+
+ /* Buffer remaining data */
+ memcpy((char *) &ctx->buffer[index], (char *) &data[i],datalen-i);
+
+ return(1);
+}
+
+
+static int md5_final(libisofs_md5_ctx *ctx, char result[16], int flag)
+{
+ unsigned char bits[8], *respt;
+ unsigned int index, padlen;
+ static unsigned char PADDING[64] = {
+   0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ /* Save number of bits */
+ md5__encode(bits, ctx->count, 8);
+ /* Pad out to 56 mod 64.  */
+ index = (unsigned int)((ctx->count[0] >> 3) & 0x3f);
+ padlen = (index < 56) ? (56 - index) : (120 - index);
+ md5_update(ctx, PADDING, padlen,0);
+ /* Append length (before padding) */
+ md5_update(ctx, bits, 8,0);
+ /* Store state in result */
+ respt= (unsigned char *) result;
+ md5__encode(respt, ctx->state, 16);
+ /* Zeroize sensitive information.  */
+ memset ((char *) ctx, 0, sizeof (*ctx));
+ return(1);
+}
+
+/** Compute a MD5 checksum from one or more calls of this function.
+    The first call has to be made with flag bit0 == 1. It may already submit
+    processing payload in data and datalen.
+    The last call has to be made with bit15 set. Normally bit1 will be set
+    too in order to receive the checksum before it gets disposed. 
+    bit1 may only be set in the last call or together with bit2.
+    The combination of bit1 and bit2 may be used to get an intermediate
+    result without hampering an ongoing checksum computation.
+
+    @param ctx      the checksum context which stores the state between calls.
+                    It gets created with flag bit0 and disposed with bit15.
+                    With flag bit0, *ctx has to be NULL or point to freeable
+                    memory.
+    @param data     the bytes to be checksummed
+    @param datalen  the number of bytes in data
+    @param result   returns the 16 bytes of checksum if called with bit1 set
+    @param flag     bit0= allocate and init *ctx
+                    bit1= transfer ctx to result
+                    bit2= with bit 0 : clone new *ctx from data
+                    bit15= free *ctx
+*/
+static
+int libisofs_md5(void **ctx_in, char *data, int datalen,
+                 char result[16], int flag)
+/* *ctx has to be NULL or point to freeable memory */
+/*
+ bit0= allocate and init *ctx
+ bit1= transfer ctx to result
+ bit2= with bit 0 : clone new *ctx from data
+ bit15= free *ctx
+*/
+{
+ unsigned char *datapt;
+ libisofs_md5_ctx **ctx;
+
+ ctx= (libisofs_md5_ctx **) ctx_in;
+ if(flag&1) {
+   if(*ctx!=NULL)
+     free((char *) *ctx);
+   *ctx= calloc(1, sizeof(libisofs_md5_ctx));
+   if(*ctx==NULL)
+     return(-1);
+   md5_init(*ctx,0);
+   if(flag&4)
+     memcpy((char *) *ctx,data,sizeof(libisofs_md5_ctx));
+ }
+ if(*ctx==NULL)
+   return(0);
+ if(datalen>0) {
+   datapt= (unsigned char *) data;
+   md5_update(*ctx, datapt, datalen, 0);
+ }
+ if(flag&2)
+   md5_final(*ctx, result, 0);
+ if(flag&(1<<15)) {
+   free((char *) *ctx);
+   *ctx= NULL;
+ }
+ return(1);
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/* Public MD5 computing facility */
+
+/* API */
+int iso_md5_start(void **md5_context)
+{
+    int ret;
+
+    ret = libisofs_md5(md5_context, NULL, 0, NULL, 1);
+    if (ret <= 0)
+        return ISO_OUT_OF_MEM;
+    return 1;
+}
+
+
+/* API */
+int iso_md5_compute(void *md5_context, char *data, int datalen)
+{
+    int ret;
+
+    ret = libisofs_md5(&md5_context, data, datalen, NULL, 0);
+    if (ret <= 0)
+        return ISO_NULL_POINTER;
+    return 1;
+}
+
+
+/* API */
+int iso_md5_clone(void *old_md5_context, void **new_md5_context)
+{
+    int ret;
+
+    ret = libisofs_md5(new_md5_context, old_md5_context, 0, NULL, 1 | 4);
+    if (ret < 0)
+        return ISO_OUT_OF_MEM;
+    if (ret == 0)
+        return ISO_NULL_POINTER;
+    return 1;
+}
+
+
+/* API */
+int iso_md5_end(void **md5_context, char result[16])
+{
+    int ret;
+
+    ret = libisofs_md5(md5_context, NULL, 0, result, 2 | (1 << 15));
+    if (ret <= 0)
+        return ISO_NULL_POINTER;
+    return 1;
+}
+
+
+/* API */
+int iso_md5_match(char first_md5[16], char second_md5[16])
+{
+    int i;
+
+    for (i= 0; i < 16; i++)
+        if (first_md5[i] != second_md5[i])
+            return 0;
+    return 1;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+
+/* Function to identify and manage md5sum indice of the old image.
+ * data is supposed to be a 4 byte integer, bit 31 shall be 0,
+ * value 0 of this integer means that it is not a valid index.
+ */
+int checksum_cx_xinfo_func(void *data, int flag)
+{
+    /* data is an int disguised as pointer. It does not point to memory. */
+    return 1;
+}
+
+
+/* Function to identify and manage md5 sums of unspecified providence stored
+ * directly in this xinfo.
+ */
+int checksum_md5_xinfo_func(void *data, int flag)
+{
+    if (data == NULL)
+        return 1;
+    free(data);
+    return 1;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/* MD5 checksum image writer */
+
+#ifdef Libisofs_with_checksumS
+
+/*
+  @flag bit0= recursion
+        bit1= session will be appended to an existing image
+*/
+static
+int checksum_copy_old_nodes(Ecma119Image *target, IsoNode *node, int flag)
+{
+    IsoNode *pos;
+    IsoFile *file;
+    IsoImage *img;
+    int ret, i;
+    size_t value_length;
+    unsigned int idx = 0, old_idx = 0;
+    char *value = NULL, *md5_pt = NULL;
+    void *xipt;
+
+    img = target->image;
+    if (target->checksum_buffer == NULL)
+        return 0;
+
+    if (node->type == LIBISO_FILE) {
+        file = (IsoFile *) node;
+        if (file->from_old_session && target->appendable) {
+            /* Look for checksums at various places */
+
+            /* Try checksum directly stored with node */
+            if (md5_pt == NULL) {
+                ret = iso_node_get_xinfo(node, checksum_md5_xinfo_func, &xipt);
+                if (ret < 0)
+                    return ret;
+                if (ret == 1)
+                    md5_pt = (char *) xipt;
+            }
+
+            /* Try checksum index to image checksum buffer */
+            if (md5_pt == NULL && img->checksum_array != NULL) {
+                ret = iso_node_get_xinfo(node, checksum_cx_xinfo_func, &xipt);
+                if (ret <= 0)
+                    return ret;
+                /* xipt is an int disguised as void pointer */
+                old_idx = 0;
+                for (i = 0; i < 4; i++)
+                    old_idx = (old_idx << 8) | ((unsigned char *) &xipt)[i];
+    
+                if (old_idx == 0 || old_idx > img->checksum_idx_count - 1)
+                    return 0;
+                md5_pt = img->checksum_array + 16 * old_idx;
+            }
+
+            if (md5_pt == NULL)
+                return 0;
+
+            ret = iso_node_lookup_attr(node, "isofs.cx", &value_length,
+                                       &value, 0);
+            if (ret == 1 && value_length == 4) {
+                for (i = 0; i < 4; i++)
+                    idx = (idx << 8) | ((unsigned char *) value)[i];
+                if (idx > 0 && idx <= target->checksum_idx_counter) {
+                    memcpy(target->checksum_buffer + 16 * idx, md5_pt, 16);
+                }
+            }
+            if (value != NULL)
+                free(value);
+            iso_node_remove_xinfo(node, checksum_md5_xinfo_func);
+            iso_node_remove_xinfo(node, checksum_cx_xinfo_func);
+        }
+    } else if (node->type == LIBISO_DIR) {
+        for (pos = ((IsoDir *) node)->children; pos != NULL; pos = pos->next) {
+            ret = checksum_copy_old_nodes(target, pos, 1);
+            if (ret < 0)
+                return ret;
+        }
+    }
+    return ISO_SUCCESS;
+}
+
+#endif /* Libisofs_with_checksumS */
+
+
+static
+int checksum_writer_compute_data_blocks(IsoImageWriter *writer)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    size_t size;
+    Ecma119Image *t;
+    int ret;
+
+    if (writer == NULL) {
+        return ISO_ASSERT_FAILURE;
+    }
+    t = writer->target;
+
+    t->checksum_array_pos = t->curblock;
+                               /* (t->curblock already contains t->ms_block) */ 
+    t->checksum_range_start = t->ms_block;
+    size = (t->checksum_idx_counter + 2) / 128;
+    if (size * 128 < t->checksum_idx_counter + 2)
+        size++;
+    t->curblock += size;
+    t->checksum_range_size = t->checksum_array_pos + size
+                             - t->checksum_range_start;
+
+    /* Extra block for stream detectable checksum tag */
+    t->checksum_tag_pos =  t->curblock;
+    t->curblock++;
+
+    /* Allocate array of MD5 sums */
+    t->checksum_buffer = calloc(size, 2048);
+    if (t->checksum_buffer == NULL)
+        return ISO_OUT_OF_MEM;
+
+    /* Copy MD5 from nodes of old image into writer->data */
+    ret = checksum_copy_old_nodes(t, (IsoNode *) t->image->root, 0);
+    if (ret < 0)
+        return ret;
+
+    /* Record lba,count,size,cecksum_type in "isofs.ca" of root node */
+    ret = iso_root_set_isofsca((IsoNode *) t->image->root,
+                               t->checksum_range_start, 
+                               t->checksum_array_pos,
+                               t->checksum_idx_counter + 2, 16, "MD5", 0);
+    if (ret < 0)
+        return ret;
+
+#endif /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+}
+
+
+static
+int checksum_writer_write_vol_desc(IsoImageWriter *writer)
+{
+
+    /* The superblock checksum tag has to be written after
+       the Volume Descriptor Set Terminator and thus may not be
+       written by this function. (It would have been neat, though).
+    */
+
+    return ISO_SUCCESS;
+}
+
+
+static
+int checksum_writer_write_data(IsoImageWriter *writer)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    int wres, res;
+    size_t i, size;
+    Ecma119Image *t;
+    void *ctx = NULL;
+    char md5[16];
+
+#ifdef NIX
+    char tag_block[2048];
+    int l;
+#endif
+
+    if (writer == NULL) {
+        return ISO_ASSERT_FAILURE;
+    }
+
+    t = writer->target;
+    iso_msg_debug(t->image->id, "Writing Checksums...");
+
+    /* Write image checksum to index 0 */
+    if (t->checksum_ctx != NULL) {
+        res = iso_md5_clone(t->checksum_ctx, &ctx);
+        if (res > 0) {
+            res = iso_md5_end(&ctx, t->image_md5);
+            if (res > 0)
+                memcpy(t->checksum_buffer + 0 * 16, t->image_md5, 16);
+        }
+    }
+
+    size = (t->checksum_idx_counter + 2) / 128;
+    if (size * 128 < t->checksum_idx_counter + 2)
+        size++;
+ 
+    /* Write checksum of checksum array as index t->checksum_idx_counter + 1 */
+    res = iso_md5_start(&ctx);
+    if (res > 0) {
+        for (i = 0; i < t->checksum_idx_counter + 1; i++)
+            iso_md5_compute(ctx,
+                          t->checksum_buffer + ((size_t) i) * (size_t) 16, 16);
+        res = iso_md5_end(&ctx, md5);
+        if (res > 0)
+           memcpy(t->checksum_buffer + (t->checksum_idx_counter + 1) * 16,
+                  md5, 16);
+    }
+
+    for (i = 0; i < size; i++) {
+        wres = iso_write(t, t->checksum_buffer + ((size_t) 2048) * i, 2048);
+        if (wres < 0) {
+            res = wres;
+            goto ex;
+        }
+    }
+    if (t->checksum_ctx == NULL) {
+        res = ISO_SUCCESS;
+        goto ex;
+    }
+
+    /* Write stream detectable checksum tag to extra block */;
+    res = iso_md5_write_tag(t, 1);
+    if (res < 0)
+        goto ex;
+
+    res = ISO_SUCCESS;
+ex:;
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+    return(res);
+
+#else /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+
+#endif /* ! Libisofs_with_checksumS */
+}
+
+
+static
+int checksum_writer_free_data(IsoImageWriter *writer)
+{
+    /* nothing was allocated at writer->data */
+    return ISO_SUCCESS;
+}
+
+
+int checksum_writer_create(Ecma119Image *target)
+{
+    IsoImageWriter *writer;
+    
+    writer = malloc(sizeof(IsoImageWriter));
+    if (writer == NULL) {
+        return ISO_OUT_OF_MEM;
+    }
+    
+    writer->compute_data_blocks = checksum_writer_compute_data_blocks;
+    writer->write_vol_desc = checksum_writer_write_vol_desc;
+    writer->write_data = checksum_writer_write_data;
+    writer->free_data = checksum_writer_free_data;
+    writer->data = NULL;
+    writer->target = target;
+
+    /* add this writer to image */
+    target->writers[target->nwriters++] = writer;
+
+#ifdef Libisofs_with_checksumS
+
+    /* Account for superblock checksum tag */
+    if (target->md5_session_checksum) {
+        target->checksum_sb_tag_pos = target->curblock;
+        target->curblock++;
+    }
+
+#endif /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+}
+
+
+static
+int iso_md5_write_scdbackup_tag(Ecma119Image *t, char *tag_block, int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    void *ctx = NULL;
+    off_t pos = 0, line_start;
+    int record_len, block_len, res, i;
+    char postext[40], md5[16], record[160];
+
+    line_start = strlen(tag_block);
+    iso_md5_compute(t->checksum_ctx, tag_block, line_start);
+    res = iso_md5_clone(t->checksum_ctx, &ctx);
+    if (res < 0)
+        goto ex;
+    res = iso_md5_end(&ctx, md5);
+
+    pos = (off_t) t->checksum_tag_pos * (off_t) 2048 + line_start;
+    if(pos >= 1000000000)
+        sprintf(postext, "%u%9.9u", (unsigned int) (pos / 1000000000),
+                                    (unsigned int) (pos % 1000000000));
+    else
+        sprintf(postext, "%u", (unsigned int) pos);
+    sprintf(record, "%s %s ", t->scdbackup_tag_parm, postext);
+    record_len = strlen(record);
+    for (i = 0; i < 16; i++)
+         sprintf(record + record_len + 2 * i,
+                 "%2.2x", ((unsigned char *) md5)[i]);
+    record_len += 32;
+
+    res = iso_md5_start(&ctx);
+    if (res < 0)
+        goto ex;
+    iso_md5_compute(ctx, record, record_len);
+    iso_md5_end(&ctx, md5);
+
+    sprintf(tag_block + line_start, "scdbackup_checksum_tag_v0.1 %s %d %s ",
+            postext, record_len, record);
+    block_len = strlen(tag_block);
+    for (i = 0; i < 16; i++)
+        sprintf(tag_block + block_len + 2 * i,
+                "%2.2x", ((unsigned char *) md5)[i]);
+    block_len+= 32;
+    tag_block[block_len++]= '\n';
+
+    if (t->scdbackup_tag_written != NULL)
+    	strncpy(t->scdbackup_tag_written, tag_block + line_start,
+                block_len - line_start);
+    res = ISO_SUCCESS;
+ex:;
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+    return res;
+
+#else
+
+    return ISO_SUCCESS;
+
+#endif /* Libisofs_with_checksumS */
+}
+
+
+/* Write stream detectable checksum tag to extra block.
+ * @flag bit0-7= tag type
+ *               1= session tag (End checksumming.)
+ *               2= superblock tag (System Area and Volume Descriptors)
+ *               3= tree tag (ECMA-119 and Rock Ridge tree)
+ *               4= relocated superblock tag (at LBA 0 of overwriteable media)
+ *                  Write to target->opts_overwrite rather than to iso_write().
+ */
+int iso_md5_write_tag(Ecma119Image *t, int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    int res, mode, l, i, wres, tag_id_len;
+    void *ctx = NULL;
+    char md5[16], tag_block[2048], *tag_id;
+    uint32_t size = 0, pos = 0, start;
+
+    start = t->checksum_range_start;
+    memset(tag_block, 0, 2048);
+    mode = flag & 255;
+    if (mode < 1 || mode > 4)
+        return ISO_WRONG_ARG_VALUE;
+    res = iso_md5_clone(t->checksum_ctx, &ctx);
+    if (res < 0)
+        return res;
+    res = iso_md5_end(&ctx, md5);
+    if (mode == 1) {
+        size = t->checksum_range_size;
+        pos = t->checksum_tag_pos;
+    } else {
+        if (mode == 2) {
+            pos = t->checksum_sb_tag_pos;
+        } else if (mode == 3) {
+            pos = t->checksum_tree_tag_pos;
+        } else if (mode == 4) {
+            pos = t->checksum_rlsb_tag_pos;
+            start = pos - (pos % 32);
+        }
+        size = pos - start;
+    }
+    if (res < 0)
+        goto ex;
+
+    iso_util_tag_magic(mode, &tag_id, &tag_id_len, 0);
+    sprintf(tag_block, "%s pos=%u range_start=%u range_size=%u",
+            tag_id, pos, start, size);
+
+    l = strlen(tag_block);
+    if (mode == 2) {
+        sprintf(tag_block + l, " next=%u", t->checksum_tree_tag_pos);
+    } else if (mode == 3) {
+        sprintf(tag_block + l, " next=%u", t->checksum_tag_pos);
+    } else if (mode == 4) {
+        sprintf(tag_block + l, " session_start=%u", t->ms_block);
+    }
+    strcat(tag_block + l, " md5=");
+    l = strlen(tag_block);
+    for (i = 0; i < 16; i++)
+        sprintf(tag_block + l + 2 * i, "%2.2x",
+                ((unsigned char *) md5)[i]);
+    l+= 32;
+        
+    res = iso_md5_start(&ctx);
+    if (res > 0) {
+        iso_md5_compute(ctx, tag_block, l);
+        iso_md5_end(&ctx, md5);
+        strcpy(tag_block + l, " self=");
+        l += 6;
+        for (i = 0; i < 16; i++)
+            sprintf(tag_block + l + 2 * i, "%2.2x",
+                    ((unsigned char *) md5)[i]);
+    }
+    tag_block[l + 32] = '\n';
+
+    if (mode == 1 && t->scdbackup_tag_parm[0]) {
+        if (t->ms_block > 0) {
+            iso_msg_submit(t->image->id, ISO_SCDBACKUP_TAG_NOT_0, 0, NULL);
+        } else {
+            res = iso_md5_write_scdbackup_tag(t, tag_block, 0);
+            if (res < 0)
+                goto ex;
+        }
+    }
+
+    if (mode == 4) {
+        if (t->opts_overwrite != NULL)
+            memcpy(t->opts_overwrite + pos * 2048, tag_block, 2048);
+    } else {
+        wres = iso_write(t, tag_block, 2048);
+        if (wres < 0) {
+            res = wres;
+            goto ex;
+        }
+    }
+
+    res = ISO_SUCCESS;
+ex:;
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+    return res;
+
+#else /* Libisofs_with_checksumS */
+
+    return ISO_SUCCESS;
+
+#endif /* ! Libisofs_with_checksumS */
+
+}
+
+
--- libisofs/md5.h
+++ libisofs/md5.h
+/*
+ * Copyright (c) 2009 Thomas Schmitt
+ *
+ * This file is part of the libisofs project; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
+ */
+
+#ifndef LIBISO_MD5_H_
+#define LIBISO_MD5_H_
+
+
+/* The MD5 computation API is in libisofs.h : iso_md5_start() et.al. */
+
+
+/** Create a writer object for checksums and add it to the writer list of
+    the given Ecma119Image.
+*/
+int checksum_writer_create(Ecma119Image *target);
+
+
+/* Write stream detectable checksum tag to extra block.
+ * All tag ranges start at the beginning of the System Area (i.e. t->ms_block)
+ * and stem from the same MD5 computation context. Tag types 2 and 3 are
+ * intermediate checksums. Type 2 announces the existence of type 3.
+ * If both match, then at least the directory tree is trustworthy.
+ * Type 1 is written at the very end of the session. If it matches, then
+ * the whole image is trustworthy.
+ * @param t      The image being written
+ * @flag         bit0-7= tag type
+ *               1= session tag (End checksumming.)
+ *               2= superblock tag (System Area and Volume Descriptors)
+ *               3= tree tag (ECMA-119 and Rock Ridge tree)
+ */
+int iso_md5_write_tag(Ecma119Image *t, int flag);
+
+
+#endif /* ! LIBISO_MD5_H_ */
+
+
--- libisofs/messages.c
+++ libisofs/messages.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #include <stdlib.h>
 #include <sys/types.h>
@@ -152,6 +153,8 @@
         return "Try to set the boot image of an already bootable image";
     case ISO_BOOT_IMAGE_NOT_VALID:
         return "Trying to use an invalid file as boot image";
+    case ISO_BOOT_IMAGE_OVERFLOW:
+        return "Too many boot images added";
     case ISO_FILE_ERROR:
         return "Error on file operation";
     case ISO_FILE_ALREADY_OPENED:
@@ -260,11 +263,35 @@
         return "Cannot set global zisofs parameters while filters exist";
     case ISO_ZLIB_EARLY_EOF:
         return "Premature EOF of zlib input stream";
+    case ISO_MD5_AREA_CORRUPTED:
+        return "Checksum area or checksum tag appear corrupted";
+    case ISO_MD5_TAG_MISMATCH:
+        return "Checksum mismatch between checksum tag and data blocks";
+    case ISO_SB_TREE_CORRUPTED:
+        return "Checksum mismatch in System Area, Volume Descriptors, or directory tree";
+    case ISO_MD5_TAG_UNEXPECTED:
+        return "Unexpected checksum tag type encountered";
+    case ISO_MD5_TAG_MISPLACED:
+        return "Misplaced checksum tag type encountered";
+    case ISO_MD5_TAG_OTHER_RANGE:
+        return "Checksum tag with unexpected address range encountered";
+    case ISO_MD5_STREAM_CHANGE:
+        return "Detected file content changes while it was written into the image";
+    case ISO_SCDBACKUP_TAG_NOT_0:
+        return "Session does not start at LBA 0. scdbackup checksum tag not written.";
     default:
         return "Unknown error";
     }
 }
 
+int iso_msg_is_abort(int errcode)
+{
+    if (ISO_ERR_SEV(errcode) >= abort_threshold)
+        return 1;
+    return 0;
+}
+       
+
 int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...)
 {
     char msg[MAX_MSG_LEN];
@@ -295,7 +322,7 @@
         }
     }
 
-    if (ISO_ERR_SEV(errcode) >= abort_threshold) {
+    if (iso_msg_is_abort(errcode)) {
         return ISO_CANCELED;
     } else {
         return 0;
--- libisofs/messages.h
+++ libisofs/messages.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
@@ -24,6 +25,13 @@
  */
 void iso_msg_debug(int imgid, const char *fmt, ...);
 
+
+/**
+ * Inquire whether the given error code triggers the abort threshold
+ */
+int iso_msg_is_abort(int errcode);
+
+
 /**
  * 
  * @param errcode
@@ -33,7 +41,7 @@
  *      < 0 will be returned in any case. Use 0 if there is no previous 
  *      cause for the error.
  * @return
- *      1 on success, < 0 if function must abort asap.
+ *      0 on success, < 0 if function must abort asap.
  */
 int iso_msg_submit(int imgid, int errcode, int causedby, const char *fmt, ...);
 
--- libisofs/node.c
+++ libisofs/node.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
@@ -13,6 +14,7 @@
 #include "stream.h"
 #include "aaip_0_2.h"
 #include "messages.h"
+#include "util.h"
 
 
 #include <stdlib.h>
@@ -21,6 +23,12 @@
 #include <limits.h>
 #include <stdio.h>
 
+
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
 struct dir_iter_data
 {
     /* points to the last visited child, to NULL before start */
@@ -200,6 +208,7 @@
         return ISO_NULL_POINTER;
     }
 
+    *data = NULL;
     pos = node->xinfo;
     while (pos != NULL) {
         if (pos->process == proc) {
@@ -1275,6 +1284,7 @@
     new->node.type = LIBISO_FILE;
     new->node.name = name;
     new->node.mode = S_IFREG;
+    new->sort_weight = 0;
     new->stream = stream;
 
     *file = new;
@@ -1309,13 +1319,9 @@
     new->node.name = name;
     new->dest = dest;
     new->node.mode = S_IFLNK;
-
-#ifdef Libisofs_hardlink_matcheR
     new->fs_id = 0;
     new->st_dev = 0;
     new->st_ino = 0;
-#endif
-
     *link = new;
     return ISO_SUCCESS;
 }
@@ -1347,13 +1353,9 @@
 
     new->node.mode = mode;
     new->dev = dev;
-
-#ifdef Libisofs_hardlink_matcheR
     new->fs_id = 0;
     new->st_dev = 0;
     new->st_ino = 0;
-#endif
-
     *special = new;
     return ISO_SUCCESS;
 }
@@ -2300,8 +2302,6 @@
         }
         return 1;
 
-#ifdef Libisofs_hardlink_matcheR
-
     } else if (node->type == LIBISO_SYMLINK) {
         symlink = (IsoSymlink *) node;
         if (symlink->fs_id != ISO_IMAGE_FS_ID && (flag & 1)) {
@@ -2324,8 +2324,6 @@
         *ino_id = special->st_ino;
         return 1;
 
-#endif
-
     }
 
     ret = 0;
@@ -2380,8 +2378,6 @@
         if (ret < 0 || ret == 1)
             return ret;
 
-#ifdef Libisofs_hardlink_matcheR
-
     } else if (node->type == LIBISO_SYMLINK) {
         symlink = (IsoSymlink *) node;
         if (symlink->fs_id == ISO_IMAGE_FS_ID) {
@@ -2396,8 +2392,6 @@
             return 1;
         }
 
-#endif
-
     }
     ret = iso_node_set_ino_xinfo(node, ino, 0);
     if (ret < 0)
@@ -2472,8 +2466,6 @@
             return ret1;
         goto inode_match;
 
-#ifdef Libisofs_hardlink_matcheR
-
     } else if (n1->type == LIBISO_SYMLINK) {
 
         l1 = (IsoSymlink *) n1;
@@ -2496,8 +2488,6 @@
         dev_id2 = s2->st_dev;
         ino_id2 = s2->st_ino;
 
-#endif /* Libisofs_hardlink_matcheR */
-
     } else {
         return (n1 < n2 ? -1 : 1); /* case n1 == n2 is handled above */
     }
@@ -2575,3 +2565,186 @@
 {
     return iso_node_cmp_flag(n1, n2, 1);
 }
+
+
+int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
+                         int flag)
+{
+    static char *names = "isofs.cx";
+    static size_t value_lengths[1] = {4};
+    unsigned char value[4];
+    char *valuept;
+    int i, ret;
+
+    for(i = 0; i < 4; i++)
+        value[3 - i] = (checksum_index >> (8 * i)) & 0xff;
+    valuept= (char *) value;
+    ret = iso_node_set_attrs((IsoNode *) file, (size_t) 1,
+                             &names, value_lengths, &valuept, 2 | 8);
+    return ret;
+}
+
+
+int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba,
+                         uint32_t count, uint32_t size, char *typetext,
+                         int flag)
+{
+    char buffer[5 + 5 + 5 + 2 + 81], *wpt = buffer, *valuept = buffer;
+    int result_len, ret;
+    static char *names = "isofs.ca";
+    static size_t value_lengths[1];
+
+    /* Set value of isofs.ca with
+       4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16,  MD5 */
+    iso_util_encode_len_bytes(start_lba, wpt, 4, &result_len, 0);
+    wpt += result_len;
+    iso_util_encode_len_bytes(end_lba, wpt, 4, &result_len, 0);
+    wpt += result_len;
+    iso_util_encode_len_bytes(count, wpt, 4, &result_len, 0);
+    wpt += result_len;
+    iso_util_encode_len_bytes(size, wpt, 1, &result_len, 0);
+    wpt += result_len;
+    strncpy(wpt, typetext, 80);
+    if (strlen(typetext) > 80)
+        wpt += 80;
+    else
+        wpt += strlen(typetext);
+    value_lengths[0] = wpt - buffer;
+    ret = iso_node_set_attrs(node, (size_t) 1,
+                             &names, value_lengths, &valuept, 2 | 8);
+    return ret;
+}
+
+
+int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
+                         uint32_t *count, uint32_t *size, char typetext[81],
+                         int flag)
+{
+    int ret, len;
+    size_t value_len;
+    char *value = NULL, *rpt;
+
+    ret = iso_node_lookup_attr(node, "isofs.ca", &value_len, &value, 0);
+    if (ret <= 0)
+        goto ex;
+
+    /* Parse value of isofs.ca with
+       4 byte START, 4 byte END, 4 byte COUNT, SIZE = 16,  MD5 */
+    rpt = value;
+    iso_util_decode_len_bytes(start_lba, rpt, &len,
+                              value_len - (rpt - value), 0);
+    rpt += len + 1;
+    iso_util_decode_len_bytes(end_lba, rpt, &len,
+                              value_len - (rpt - value), 0);
+    rpt += len + 1;
+    iso_util_decode_len_bytes(count, rpt, &len,
+                              value_len - (rpt - value), 0);
+    rpt += len + 1;
+    iso_util_decode_len_bytes(size, rpt, &len,
+                              value_len - (rpt - value), 0);
+    rpt += len + 1;
+    len = value_len - (rpt - value);
+    if (len > 80)
+        len = 80;
+    memcpy(typetext, rpt, len);
+    typetext[len] = 0;
+
+    ret= ISO_SUCCESS;
+ex:;
+    if (value != NULL)
+        free(value);
+    return ret;
+}
+
+
+/* API */
+int iso_file_get_md5(IsoImage *image, IsoFile *file, char md5[16], int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+
+    int ret, i;
+    size_t value_len;
+    char *value = NULL;
+    uint32_t idx = 0;
+    void *xipt;
+
+    /* xinfo MD5 overrides everything else */
+    ret = iso_node_get_xinfo((IsoNode *) file, checksum_md5_xinfo_func, &xipt);
+    if (ret == 1) {
+        memcpy(md5, (char *) xipt, 16);
+        return 1;
+    }
+
+    if (image->checksum_array == NULL)
+        return 0;
+    ret = iso_node_lookup_attr((IsoNode *) file, "isofs.cx",
+                               &value_len, &value, 0);
+    if (ret <= 0)
+        goto ex;
+    if (value_len > 4) {
+        ret = 0;
+        goto ex;
+    }
+    for (i = 0; i < value_len; i++)
+        idx = (idx << 8) | ((unsigned char *) value)[i];
+    if (idx == 0 || idx > image->checksum_idx_count - 1) {
+                                       /* (last index is not MD5 of a file) */
+        ret = 0;
+        goto ex;
+    }
+    if (!(flag & 1)) {
+        memcpy(md5, image->checksum_array + ((size_t) 16) * ((size_t) idx),
+               16);
+    }
+    ret = 1;
+ex:;
+    if (value != NULL)
+        free(value);
+    return ret;
+
+#else
+
+    return 0;
+
+#endif /* ! Libisofs_with_checksumS */
+
+}
+
+
+/* API */
+int iso_file_make_md5(IsoFile *file, int flag)
+{
+
+#ifdef Libisofs_with_checksumS
+    int ret, dig = 0;
+    char *md5 = NULL;
+
+    if (file->from_old_session)
+        dig = 1;
+    md5= calloc(16, 1);
+    ret = iso_stream_make_md5(file->stream, md5, dig);
+    if (ret < 0)
+        goto ex;
+    iso_node_remove_xinfo((IsoNode *) file, checksum_md5_xinfo_func);
+    ret = iso_node_add_xinfo((IsoNode *) file, checksum_md5_xinfo_func, md5);
+    if (ret == 0)
+        ret = ISO_ERROR; /* should not happen after iso_node_remove_xinfo() */
+    if (ret < 0) {
+        free(md5);
+        goto ex;
+    }
+    ret = 1;
+ex:;
+    return ret;
+
+#else
+
+    return ISO_ERROR;
+
+#endif /* ! Libisofs_with_checksumS */
+
+}
+
+
+
--- libisofs/node.h
+++ libisofs/node.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_NODE_H_
 #define LIBISO_NODE_H_
@@ -24,7 +25,7 @@
 /**
  * The extended information is a way to attach additional information to each
  * IsoNode. External applications may want to use this extension system to
- * store application speficic information related to each node. On the other
+ * store application specific information related to each node. On the other
  * side, libisofs may make use of this struct to attach information to nodes in
  * some particular, uncommon, cases, without incrementing the size of the
  * IsoNode struct.
@@ -67,7 +68,7 @@
 struct Iso_Node
 {
     /*
-     * Initilized to 1, originally owned by user, until added to another node.
+     * Initialized to 1, originally owned by user, until added to another node.
      * Then it is owned by the parent node, so the user must take his own ref
      * if needed. With the exception of the creation functions, none of the
      * other libisofs functions that return an IsoNode increment its
@@ -132,7 +133,6 @@
 
     char *dest;
 
-#ifdef Libisofs_hardlink_matcheR
     /* If the IsoNode represents an object in an existing filesystem then
        the following three numbers should unique identify it.
        (0,0,0) will always be taken as unique.
@@ -140,8 +140,6 @@
     unsigned int fs_id;
     dev_t st_dev;
     ino_t st_ino;
-#endif
-
 };
 
 struct Iso_Special
@@ -149,7 +147,6 @@
     IsoNode node;
     dev_t dev;
 
-#ifdef Libisofs_hardlink_matcheR
     /* If the IsoNode represents an object in an existing filesystem then
        the following three numbers should unique identify it.
        (0,0,0) will always be taken as unique.
@@ -157,8 +154,6 @@
     unsigned int fs_id;
     dev_t st_dev;
     ino_t st_ino;
-#endif
-
 };
 
 struct iso_dir_iter_iface
@@ -451,4 +446,31 @@
  */
 int iso_node_cmp_flag(IsoNode *n1, IsoNode *n2, int flag);
 
+
+/**
+ * Set the checksum index (typically comming from IsoFileSrc.checksum_index)
+ * of a regular file node. The index is encoded as xattr "isofs.cx" with
+ * four bytes of value.
+ */
+int iso_file_set_isofscx(IsoFile *file, unsigned int checksum_index,
+                         int flag);
+
+
+/**
+ * Set the checksum area description. node should be the root node.
+ * It is encoded as xattr "isofs.ca".
+ */
+int iso_root_set_isofsca(IsoNode *node, uint32_t start_lba, uint32_t end_lba,
+                         uint32_t count, uint32_t size, char *typetext,
+                         int flag);
+
+/**
+ * Get the checksum area description. node should be the root node.
+ * It is encoded as xattr "isofs.ca".
+ */
+int iso_root_get_isofsca(IsoNode *node, uint32_t *start_lba, uint32_t *end_lba,
+                         uint32_t *count, uint32_t *size, char typetext[81],
+                         int flag);
+
+
 #endif /*LIBISO_NODE_H_*/
--- libisofs/rockridge.c
+++ libisofs/rockridge.c
@@ -4,8 +4,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "rockridge.h"
@@ -108,12 +109,12 @@
         PX[2] = 36;
     }
     PX[3] = 1;
-    iso_bb(&PX[4], px_get_mode(t, n), 4);
-    iso_bb(&PX[12], n->nlink, 4);
-    iso_bb(&PX[20], px_get_uid(t, n), 4);
-    iso_bb(&PX[28], px_get_gid(t, n), 4);
+    iso_bb(&PX[4], (uint32_t) px_get_mode(t, n), 4);
+    iso_bb(&PX[12], (uint32_t) n->nlink, 4);
+    iso_bb(&PX[20], (uint32_t) px_get_uid(t, n), 4);
+    iso_bb(&PX[28], (uint32_t) px_get_gid(t, n), 4);
     if (t->rrip_1_10_px_ino || !t->rrip_version_1_10) {
-        iso_bb(&PX[36], n->ino, 4);
+        iso_bb(&PX[36], (uint32_t) n->ino, 4);
     }
 
     return susp_append(t, susp, PX);
@@ -242,10 +243,10 @@
     */
     if (sizeof(node->dev) > 4) {
         high_shift = 32;
-        iso_bb(&PN[4], node->dev >> high_shift, 4);
+        iso_bb(&PN[4], (uint32_t) (node->dev >> high_shift), 4);
     } else
         iso_bb(&PN[4], 0, 4);
-    iso_bb(&PN[12], node->dev & 0xffffffff, 4);
+    iso_bb(&PN[12], (uint32_t) (node->dev & 0xffffffff), 4);
     return susp_append(t, susp, PN);
 }
 
@@ -694,7 +695,7 @@
     CE[3] = 1;
     iso_bb(&CE[4], susp->ce_block, 4);
     iso_bb(&CE[12], susp->ce_len, 4);
-    iso_bb(&CE[20], ce_len, 4);
+    iso_bb(&CE[20], (uint32_t) ce_len, 4);
 
     return susp_append(t, susp, CE);
 }
@@ -1234,12 +1235,16 @@
     if (ret == 1) {
         num_aapt = aaip_count_bytes((unsigned char *) xipt, 0);
         if (num_aapt > 0) {
-            aapt = malloc(num_aapt);
-            if (aapt == NULL)
-                return ISO_OUT_OF_MEM;
-            memcpy(aapt, xipt, num_aapt);
-            ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
-                              flag & 1);
+            if (flag & 1) {
+                ret = aaip_add_AL(t, NULL,NULL, num_aapt, sua_free, ce_len, 1);
+            } else {
+                aapt = malloc(num_aapt);
+                if (aapt == NULL)
+                    return ISO_OUT_OF_MEM;
+                memcpy(aapt, xipt, num_aapt);
+                ret = aaip_add_AL(t, info, &aapt, num_aapt, sua_free, ce_len,
+                                  0);
+            }
             if (ret < 0) 
                 return ret;
             /* aapt is NULL now and the memory is owned by t */
--- libisofs/rockridge.h
+++ libisofs/rockridge.h
@@ -4,8 +4,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /**
--- libisofs/rockridge_read.c
+++ libisofs/rockridge_read.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
@@ -302,7 +303,7 @@
         *name = realloc(*name, strlen(*name) + nm->len_sue[0] - 5 + 1);
         strncat(*name, (char*)nm->data.NM.name, nm->len_sue[0] - 5);
     } else {
-        *name = strcopy((char*)nm->data.NM.name, nm->len_sue[0] - 5);
+        *name = iso_util_strcopy((char*)nm->data.NM.name, nm->len_sue[0] - 5);
     }
     if (*name == NULL) {
         return ISO_OUT_OF_MEM;
@@ -380,7 +381,7 @@
             /* we don't have to add the '/' */
             strncat(*dest, comp, len);
         } else {
-            *dest = strcopy(comp, len);
+            *dest = iso_util_strcopy(comp, len);
         }
         if (*dest == NULL) {
             return ISO_OUT_OF_MEM;
--- libisofs/stream.c
+++ libisofs/stream.c
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "libisofs.h"
@@ -17,6 +18,12 @@
 #include <limits.h>
 #include <stdio.h>
 
+
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
 ino_t serial_id = (ino_t)1;
 ino_t mem_serial_id = (ino_t)1;
 ino_t cut_out_serial_id = (ino_t)1;
@@ -739,7 +746,7 @@
     FSrcStreamData *fssd1, *fssd2;
 
 
-/* <<<
+/*
    #define Libisofs_stream_cmp_ino_debuG 1
 */
 #ifdef Libisofs_stream_cmp_ino_debuG
@@ -821,12 +828,101 @@
         if (ret != 0)
             return ret;
     }
-
-#ifdef Libisofs_hardlink_matcheR
     if (fs_id1 == 0 && dev_id1 == 0 && ino_id1 == 0) {
         return (s1 < s2 ? -1 : 1);
     }
-#endif
-
     return 0;
 }
+
+
+/**
+ * @return
+ *     1 ok, 0 EOF, < 0 error
+ */    
+int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
+                           size_t *got)
+{
+    ssize_t result;
+
+    *got = 0;
+    do {
+        result = iso_stream_read(stream, buf + *got, count - *got);
+        if (result < 0) {
+            memset(buf + *got, 0, count - *got);
+            return result;
+        }
+        if (result == 0)
+            break;
+        *got += result;
+    } while (*got < count);
+
+    if (*got < count) {
+        /* eof */
+        memset(buf + *got, 0, count - *got);
+        return 0;
+    }
+    return 1;
+}
+
+#ifdef Libisofs_with_checksumS
+
+
+/* @param flag bit0= dig out most original stream (e.g. because from old image)
+   @return 1=ok, md5 is valid,
+           0= not ok, 
+          <0 fatal error, abort 
+*/  
+int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag)
+{
+    int res, is_open = 0;
+    char buffer[2048];
+    void *ctx= NULL;
+    off_t file_size;
+    uint32_t b, nblocks;
+    size_t got_bytes;
+    IsoStream *input_stream;
+
+    if (flag & 1) {
+        while(1) {
+           input_stream = iso_stream_get_input_stream(stream, 0);
+           if (input_stream == NULL)
+        break;
+           stream = input_stream;
+        }
+    }
+
+    if (! iso_stream_is_repeatable(stream))
+        return 0;
+    res = iso_md5_start(&ctx);
+    if (res < 0)
+        return res;
+    res = iso_stream_open(stream);
+    if (res < 0)
+        return 0;
+    is_open = 1;
+    file_size = iso_stream_get_size(stream);
+    nblocks = DIV_UP(file_size, 2048);
+    for (b = 0; b < nblocks; ++b) {
+        res = iso_stream_read_buffer(stream, buffer, 2048, &got_bytes);
+        if (res < 0) {
+            res = 0;
+            goto ex;
+        }
+        /* Do not use got_bytes to stay closer to IsoFileSrc processing */
+        if (file_size - b * 2048 > 2048)
+            res = 2048;
+        else
+            res = file_size - b * 2048;
+        iso_md5_compute(ctx, buffer, res);
+    }
+    res = 1;
+ex:;
+    if (is_open)
+        iso_stream_close(stream);
+    if (ctx != NULL)
+        iso_md5_end(&ctx, md5);
+    return res;
+}
+
+#endif /* Libisofs_with_checksumS */
+
--- libisofs/stream.h
+++ libisofs/stream.h
@@ -3,8 +3,9 @@
  * Copyright (c) 2009 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_STREAM_H_
 #define LIBISO_STREAM_H_
@@ -83,4 +84,24 @@
 int iso_stream_set_image_ino(IsoStream *stream, ino_t ino, int flag);
 
 
+/**
+ * Read the full required amount of data unless error or EOF occurs.
+ * Fill missing bytes by 0s.
+ * @param count   Required amount
+ * @param got     Returns number of actually read bytes
+ * @return
+ *     1 no problem encountered, 0 EOF encountered, < 0 error
+ */
+int iso_stream_read_buffer(IsoStream *stream, char *buf, size_t count,
+                           size_t *got);
+
+/**
+ * @return 1=ok, md5 is valid,
+ *        0= not ok
+ *       <0 fatal error, abort 
+ */
+int iso_stream_make_md5(IsoStream *stream, char md5[16], int flag);
+
+
+
 #endif /*STREAM_H_*/
--- libisofs/system_area.c
+++ libisofs/system_area.c
@@ -1,9 +1,11 @@
 /*
  * Copyright (c) 2008 Vreixo Formoso
+ * Copyright (c) 2010 Thomas Schmitt
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "system_area.h"
@@ -11,28 +13,114 @@
 #include "filesrc.h"
 
 #include <string.h>
-
+#include <stdio.h>
 
 
 /*
  * Create a MBR for an isohybrid enabled ISOLINUX boot image.
- *
- * It is assumed that the caller has verified the readiness of the boot image
- * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin.
- *
- * @param bin_lba    The predicted LBA of isolinux.bin within the emerging ISO.
- * @param img_blocks The predicted number of 2048 byte blocks in the ISO.
- *                   It will get rounded up to full MBs and that many blocks
- *                   must really be written as ISO 9660 image.
- * @param mbr        A buffer of at least 512 bytes to take the result which is
- *                   to be written as the very beginning of the ISO.
- * @param flag    unused yet, submit 0
- * @return  <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning
+ * See libisofs/make_isohybrid_mbr.c
+ * Deprecated.
  */
 int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag);
 
+/*
+ * The New ISOLINUX MBR Producer.
+ * Be cautious with changing parameters. Only few combinations are tested.
+ *
+ */
+int make_isolinux_mbr(int32_t *img_blocks, uint32_t boot_lba,
+                      uint32_t mbr_id, int head_count, int sector_count,
+                      int part_offset, int part_number, int fs_type,
+                      uint8_t *buf, int flag);
+
+
+/* This is the gesture of grub-mkisofs --protective-msdos-label as explained by
+   Vladimir Serbinenko <phcoder at gmail.com>, 2 April 2010, on grub-devel at gnu.org
+   "Currently we use first and not last entry. You need to:
+    1) Zero-fill 446-510
+    2) Put 0x55, 0xAA into 510-512
+    3) Put 0x80 (for bootable partition), 0, 2, 0 (C/H/S of the start), 0xcd
+      (partition type), [3 bytes of C/H/S end], 0x01, 0x00, 0x00, 0x00 (LBA
+      start in little endian), [LBA end in little endian] at 446-462
+   "
+
+   "C/H/S end" means the CHS address of the last block in the partition.
+   It seems that not "[LBA end in little endian]" but "number of blocks"
+   should go into bytes 458-461. But with a start lba of 1, this is the
+   same number.
+   See also http://en.wikipedia.org/wiki/Master_boot_record
+*/
+static
+int make_grub_msdos_label(int img_blocks, uint8_t *buf, int flag)
+{
+    uint8_t *wpt;
+    unsigned long end_lba, secs, end_sec, end_head, end_cyl;
+    int sph = 63, hpc = 255, i;
+
+    /* Partition table unit is 512 bytes per sector, ECMA-119 unit is 2048 */
+    if (img_blocks >= 0x40000000)
+      img_blocks = 0x40000000 - 1;         /* truncate rather than roll over */
+    secs = end_lba = img_blocks * 4 - 1;   /* last valid 512-lba */
+    end_cyl = secs / (sph * hpc);
+    secs -= end_cyl * sph * hpc;
+    end_head = secs / sph;
+    end_sec = secs - end_head * sph + 1;   /* Sector count starts by 1 */
+    if (end_cyl >= 1024) {
+        end_cyl = 1023;
+        end_head = hpc - 1;
+        end_sec = sph;
+    }
+
+    /* 1) Zero-fill 446-510 */
+    wpt = buf + 446;
+    memset(wpt, 0, 64);
+
+    /* 2) Put 0x55, 0xAA into 510-512 (actually 510-511) */
+    buf[510] = 0x55;
+    buf[511] = 0xAA;
+
+    /* 3) Put 0x80 (for bootable partition), */
+    *(wpt++) = 0x80;
+
+    /* 0, 2, 0 (C/H/S of the start), */
+    *(wpt++) = 0;
+    *(wpt++) = 2;
+    *(wpt++) = 0;
+
+    /* 0xcd (partition type) */
+    *(wpt++) = 0xcd;
+
+    /* [3 bytes of C/H/S end], */
+    *(wpt++) = end_head;
+    *(wpt++) = end_sec | ((end_cyl & 0x300) >> 2);
+    *(wpt++) = end_cyl & 0xff;
+    
+
+    /* 0x01, 0x00, 0x00, 0x00 (LBA start in little endian), */
+    *(wpt++) = 0x01;
+    *(wpt++) = 0x00;
+    *(wpt++) = 0x00;
+    *(wpt++) = 0x00;
+
+    /* [LBA end in little endian] */
+    for (i = 0; i < 4; i++)
+       *(wpt++) = (end_lba >> (8 * i)) & 0xff;
+
+    /* at 446-462 */
+    if (wpt - buf != 462) {
+        fprintf(stderr,
+        "libisofs: program error in make_grub_msdos_label: \"assert 462\"\n");
+        return ISO_ASSERT_FAILURE;
+    }
+    return ISO_SUCCESS;
+}
+
+
 int iso_write_system_area(Ecma119Image *t, uint8_t *buf)
 {
+    int ret;
+    int img_blocks;
+
     if ((t == NULL) || (buf == NULL)) {
         return ISO_NULL_POINTER;
     }
@@ -40,26 +128,41 @@
     /* set buf to 0s */
     memset(buf, 0, 16 * BLOCK_SIZE);
 
-    if (t->catalog != NULL && t->catalog->image->isolinux_options & 0x02) {
-        /* We need to write a MBR for an hybrid image */
-        int ret;
-        int img_blocks;
-
-        img_blocks = t->curblock;
-        ret = make_isohybrid_mbr(t->bootimg->sections[0].block, &img_blocks, (char*)buf, 0);
-
-/* 
-        API description of el_torito_set_isolinux_options() prescribes
-        to pad to full MB.
-        So this is not urgent any more :
-
-        // FIXME the new img_blocks size should be taken into account
-*/
-
+    img_blocks = t->curblock;
+    if (t->system_area_data != NULL) {
+        /* Write more or less opaque boot image */
+        memcpy(buf, t->system_area_data, 16 * BLOCK_SIZE);
+
+    } else if (t->catalog != NULL &&
+               (t->catalog->bootimages[0]->isolinux_options & 0x0a) == 0x02) {
+        /* Check for isolinux image with magic number of 3.72 and produce
+           an MBR from our built-in template. (Deprecated since 31 Mar 2010)
+        */
+        ret = make_isohybrid_mbr(t->bootsrc[0]->sections[0].block,
+                                 &img_blocks, (char*)buf, 0);
         if (ret != 1) {
             /* error, it should never happen */
             return ISO_ASSERT_FAILURE;
         }
+        return ISO_SUCCESS;
+    }
+    if (t->system_area_options & 1) {
+        /* Write GRUB protective msdos label, i.e. a isimple partition table */
+        ret = make_grub_msdos_label(img_blocks, buf, 0);
+        if (ret != 1) /* error should never happen */
+            return ISO_ASSERT_FAILURE;
+    } else if(t->system_area_options & 2) {
+        /* Patch externally provided system area as isohybrid MBR */
+        if (t->catalog == NULL || t->system_area_data == NULL) {
+            /* isohybrid makes only sense together with ISOLINUX boot image
+               and externally provided System Area.
+            */
+            return ISO_ISOLINUX_CANT_PATCH;
+        }
+        ret = make_isolinux_mbr(&img_blocks, t->bootsrc[0]->sections[0].block,
+                                (uint32_t) 0, 64, 32, 0, 1, 0x17, buf, 1);
+        if (ret != 1)
+            return ret;
     }
     return ISO_SUCCESS;
 }
--- libisofs/system_area.h
+++ libisofs/system_area.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2008 Vreixo Formoso
  *
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
--- libisofs/tree.c
+++ libisofs/tree.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 /*
@@ -25,6 +26,12 @@
 #include <stdio.h>
 #include <fnmatch.h>
 
+
+#ifndef PATH_MAX
+#define PATH_MAX Libisofs_default_path_maX
+#endif
+
+
 /**
  * Add a new directory to the iso tree.
  * 
@@ -914,7 +921,7 @@
     int result;
     IsoNode *n;
     IsoDir *dir;
-    char *ptr, *brk_info, *component;
+    char *ptr, *brk_info = NULL, *component;
 
     if (image == NULL || path == NULL) {
         return ISO_NULL_POINTER;
--- libisofs/tree.h
+++ libisofs/tree.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_IMAGE_TREE_H_
 #define LIBISO_IMAGE_TREE_H_
--- libisofs/util.c
+++ libisofs/util.c
@@ -1,14 +1,17 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
  * Copyright (c) 2007 Mario Danic
+ * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "util.h"
 #include "libisofs.h"
+#include "messages.h"
 #include "../version.h"
 
 #include <stdlib.h>
@@ -75,6 +78,15 @@
                  char **outbuf, size_t *outbytesleft, int flag)
 {
     size_t ret;
+/* The build system might indicate iconv(,const char **inbuf,) by
+   defining ICONV_CONST const
+*/
+#ifndef ICONV_CONST
+#define ICONV_CONST
+#endif
+    ICONV_CONST char **local_inbuf;
+
+    local_inbuf = (ICONV_CONST char **) inbuf;
 
     if (!(handle->status & 1)) {
         if (iso_iconv_debug)
@@ -101,7 +113,7 @@
             return (size_t) -1;
         return (size_t) 0;
     }
-    ret = iconv(handle->descr, inbuf, inbytesleft, outbuf, outbytesleft);
+    ret = iconv(handle->descr, local_inbuf, inbytesleft, outbuf, outbytesleft);
     if (ret == (size_t) -1) {
         if (iso_iconv_debug)
             fprintf(stderr, "libisofs_DEBUG: iconv() failed: errno= %d %s\n",
@@ -896,7 +908,10 @@
     return retval;
 }
 
-uint16_t *iso_j_file_id(const uint16_t *src)
+/*
+   bit0= no_force_dots
+*/
+uint16_t *iso_j_file_id(const uint16_t *src, int flag)
 {
     uint16_t *dot;
     size_t lname, lext, lnname, lnext, pos, i;
@@ -942,6 +957,10 @@
             pos++;
         }
     }
+
+    if ((flag & 1) && lnext <= 0)
+        goto is_done;
+
     set_ucsbe(dest + pos, '.');
     pos++;
 
@@ -955,6 +974,8 @@
             pos++;
         }
     }
+
+is_done:;
     set_ucsbe(dest + pos, '\0');
     return ucsdup(dest);
 }
@@ -1194,7 +1215,7 @@
     }
 
     memset(&tm, 0, sizeof(tm));
-    tm.tm_isdst = -1;  /* some Linuxes change tm_isdst only if it is -1 */
+    tm.tm_isdst = -1;  /* some OSes change tm_isdst only if it is -1 */
     localtime_r(&t, &tm);
 
 #ifdef HAVE_TM_GMTOFF
@@ -1238,7 +1259,7 @@
     }
 
     memset(&tm, 0, sizeof(tm));
-    tm.tm_isdst = -1;  /* some Linuxes change tm_isdst only if it is -1 */
+    tm.tm_isdst = -1;  /* some OSes change tm_isdst only if it is -1 */
     localtime_r(&t, &tm);
 
     localtime_r(&t, &tm);
@@ -1371,21 +1392,33 @@
     return ISO_SUCCESS;
 }
 
-char *strcopy(const char *buf, size_t len)
+char *iso_util_strcopy(const char *buf, size_t len)
 {
     char *str;
     
-    str = malloc((len + 1) * sizeof(char));
+    str = calloc(len + 1, 1);
     if (str == NULL) {
         return NULL;
     }
     strncpy(str, buf, len);
     str[len] = '\0';
+    return str;
+}
+
+char *iso_util_strcopy_untail(const char *buf, size_t len)
+{
+    char *str;
     
+    str = iso_util_strcopy(buf, len);
+    if (str == NULL) {
+        return NULL;
+    }
     /* remove trailing spaces */
-    for (len = len-1; str[len] == ' ' && len > 0; --len)
-        str[len] = '\0'; 
-    
+    for (len = len-1; len >= 0; --len) {
+        if (str[len] != ' ')
+    break;
+        str[len] = 0; 
+    }
     return str;
 }
 
@@ -1480,3 +1513,229 @@
 }
 
 
+int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len,
+                              int *result_len, int flag)
+{
+    uint32_t x;
+    int i, l;
+    char *wpt = buffer;
+
+    if (data_len <= 0) {
+        x = data;
+        for (i = 0; i < 4 && x != 0; i++)
+            x = x >> 8;
+        l = i;
+        if (l == 0)
+            l = 1;
+    } else
+        l = data_len;
+    *((unsigned char *) (wpt++)) = l;
+    for (i = 0; i < l; i++)
+        *((unsigned char *) (wpt++)) = data >> (8 * (l - i - 1));
+    *result_len = l + 1;
+    return ISO_SUCCESS;
+}
+
+
+int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
+                              int buffer_len, int flag)
+{
+    int i;
+
+    *data = 0;
+    *data_len = ((unsigned char *) buffer)[0];
+    if (*data_len > buffer_len - 1)
+        *data_len = buffer_len - 1;
+    for (i = 1; i <= *data_len; i++)
+        *data = (*data << 8) | ((unsigned char *) buffer)[i];
+    return ISO_SUCCESS;
+}
+
+
+int iso_util_dec_to_uint32(char *dec, uint32_t *value, int flag)
+{
+    double num;
+
+    sscanf(dec, "%lf", &num);
+    if (num < 0 || num > 4294967295.0)
+        return 0;
+    *value = num;
+    return 1;
+}
+
+
+int iso_util_hex_to_bin(char *hex, char *bin, int bin_size, int *bin_count,
+                        int flag)
+{
+    static char *allowed = {"0123456789ABCDEFabcdef"};
+    char b[3];
+    int i;
+    unsigned int u;
+
+    b[2] = 0;
+    *bin_count = 0;
+    for (i = 0; i < bin_size; i++) {
+        b[0] = hex[2 * i];
+        b[1] = hex[2 * i + 1];
+        if (strchr(allowed, b[0]) == NULL || strchr(allowed, b[1]) == NULL)
+    break;
+        sscanf(b, "%x", &u);
+        ((unsigned char *) bin)[i] = u;
+        (*bin_count)++;
+    }
+    return (*bin_count > 0);
+}
+
+
+int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag)
+{
+    static char *magic[] = {"",
+        "libisofs_checksum_tag_v1",
+        "libisofs_sb_checksum_tag_v1",
+        "libisofs_tree_checksum_tag_v1",
+        "libisofs_rlsb32_checksum_tag_v1"};
+    static int magic_len[]= {0, 24, 27, 29, 31};
+    static int magic_max = 4;
+
+    *tag_magic = NULL;
+    *len = 0;
+    if (tag_type < 0 || tag_type > magic_max)
+        return ISO_WRONG_ARG_VALUE;
+    *tag_magic = magic[tag_type];
+    *len = magic_len[tag_type];
+    return magic_max;
+}
+
+
+int iso_util_decode_md5_tag(char data[2048], int *tag_type, uint32_t *pos,
+                            uint32_t *range_start, uint32_t *range_size,
+                            uint32_t *next_tag, char md5[16], int flag)
+{
+    int ret, bin_count, i, mode, magic_first = 1, magic_last = 4;
+    int magic_len = 0;
+    char *cpt, self_md5[16], tag_md5[16], *tag_magic;
+    void *ctx = NULL;
+
+    *next_tag = 0;
+    mode = flag & 255;
+    if (mode > magic_last)
+        return ISO_WRONG_ARG_VALUE;
+    if (mode > 0)
+        magic_first = magic_last = mode;
+    for (i = magic_first; i <= magic_last; i++) {
+        iso_util_tag_magic(i, &tag_magic, &magic_len, 0);
+        if (strncmp(data, tag_magic, magic_len) == 0)
+    break;
+    }
+    if (i > magic_last )
+        return 0;
+    *tag_type = i;
+    cpt = data + magic_len + 1;
+    if (strncmp(cpt, "pos=", 4) != 0)
+        return 0;
+    cpt+= 4;
+    ret = iso_util_dec_to_uint32(cpt, pos, 0);
+    if (ret <= 0)
+        return 0;
+    cpt = strstr(cpt, "range_start=");
+    if (cpt == NULL)
+        return(0);
+    ret = iso_util_dec_to_uint32(cpt + 12, range_start, 0);
+    if (ret <= 0)
+        return 0;
+    cpt = strstr(cpt, "range_size=");
+    if (cpt == NULL)
+        return(0);
+    ret = iso_util_dec_to_uint32(cpt + 11, range_size, 0);
+    if (ret <= 0)
+        return 0;
+    if (*tag_type == 2 || *tag_type == 3) {
+        cpt = strstr(cpt, "next=");
+        if (cpt == NULL)
+            return(0);
+        ret = iso_util_dec_to_uint32(cpt + 5, next_tag, 0);
+        if (ret <= 0)
+            return 0;
+    } else if (*tag_type == 4) {
+        cpt = strstr(cpt, "session_start=");
+        if (cpt == NULL)
+            return(0);
+        ret = iso_util_dec_to_uint32(cpt + 14, next_tag, 0);
+        if (ret <= 0)
+            return 0;
+    }
+    cpt = strstr(cpt, "md5=");
+    if (cpt == NULL)
+        return(0);
+    ret = iso_util_hex_to_bin(cpt + 4, md5, 16, &bin_count, 0);
+    if (ret <= 0 || bin_count != 16)
+        return 0;
+
+    cpt += 4 + 32;
+    ret = iso_md5_start(&ctx);
+    if (ret < 0)
+        return ret;
+    iso_md5_compute(ctx, data , cpt - data);
+    iso_md5_end(&ctx, tag_md5);
+    cpt = strstr(cpt, "self=");
+    if (cpt == NULL)
+        return(0);
+    ret = iso_util_hex_to_bin(cpt + 5, self_md5, 16, &bin_count, 0);
+    if (ret <= 0 || bin_count != 16)
+        return 0;
+    for(i= 0; i < 16; i++)
+      if(self_md5[i] != tag_md5[i])
+        return ISO_MD5_AREA_CORRUPTED;
+    if (*(cpt + 5 + 32) != '\n')
+        return 0;
+    return(1);
+}
+
+
+int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
+                          void *ctx, uint32_t ctx_start_lba, 
+                          int *tag_type, uint32_t *next_tag, int flag)
+{
+    int decode_ret, ret;
+    char md5[16], cloned_md5[16];
+    uint32_t pos, range_start, range_size;
+    void *cloned_ctx = NULL;
+
+    *tag_type = 0;
+    decode_ret = iso_util_decode_md5_tag(block, tag_type, &pos,
+                                  &range_start, &range_size, next_tag, md5, 0);
+    if (decode_ret != 1 && decode_ret != ISO_MD5_AREA_CORRUPTED)
+        return 0;
+    if (*tag_type > 30)
+        goto unexpected_type;
+
+    if (decode_ret == ISO_MD5_AREA_CORRUPTED) {
+        ret = decode_ret; 
+        goto ex;
+    } else if (!((1 << *tag_type) & desired)) {
+unexpected_type:;
+        iso_msg_submit(-1, ISO_MD5_TAG_UNEXPECTED, 0, NULL);
+        ret = 0;
+        goto ex;
+    } else if(pos != lba) {
+        ret = ISO_MD5_TAG_MISPLACED;
+        goto ex;
+    } else if(range_start != ctx_start_lba) {
+        ret = ISO_MD5_TAG_MISPLACED;
+    }
+    ret = iso_md5_clone(ctx, &cloned_ctx);
+    if (ret < 0)
+        goto ex;
+    iso_md5_end(&cloned_ctx, cloned_md5);
+    if (! iso_md5_match(cloned_md5, md5)) {
+        ret = ISO_MD5_TAG_MISMATCH;
+        goto ex;
+    }
+    ret = 1;
+ex:;
+    if (ret < 0)
+        iso_msg_submit(-1, ret, 0, NULL);
+    return ret;
+}
+
+ 
--- libisofs/util.h
+++ libisofs/util.h
@@ -1,9 +1,11 @@
 /*
  * Copyright (c) 2007 Vreixo Formoso
+ * Copyright (c) 2009 Thomas Schmitt
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #ifndef LIBISO_UTIL_H_
@@ -149,11 +151,12 @@
  * 2 bytes and the resulting string is NULL-terminated by a 2-byte NULL. 
  * 
  * Note that version number and (;1) is not appended.
- *
+ * @param flag
+ *        bit0= no_force_dots
  * @return 
  *        NULL if the original name and extension both are of length 0.
  */
-uint16_t *iso_j_file_id(const uint16_t *src);
+uint16_t *iso_j_file_id(const uint16_t *src, int flag);
 
 /**
  * Create a Joliet directory identifier that consists of name and optionally
@@ -250,7 +253,14 @@
  * Copy up to \p len chars from \p buf and return this newly allocated
  * string. The new string is null-terminated.
  */
-char *strcopy(const char *buf, size_t len);
+char *iso_util_strcopy(const char *buf, size_t len);
+
+/**
+ * Copy up to \p len chars from \p buf and return this newly allocated
+ * string. The new string is null-terminated.
+ * Any trailing blanks will be removed.
+ */
+char *iso_util_strcopy_untail(const char *buf, size_t len);
 
 /**
  * Copy up to \p max characters from \p src to \p dest. If \p src has less than
@@ -440,4 +450,68 @@
  */
 unsigned int iso_str_hash(const void *key);
 
+/**
+ * Encode an integer as LEN,BYTES for being a component in certain AAIP
+ * attribute values.
+ */
+int iso_util_encode_len_bytes(uint32_t data, char *buffer, int data_len,
+                              int *result_len, int flag);
+
+/**
+ * Decode an integer as LEN,BYTES for being a component in certain AAIP
+ * attribute values.
+ * @param data        returns the decoded value
+ * @param buffer      contains the encoded value
+ * @param data_len    returns the number of value bytes (without len byte)
+ * @param buffer_len  tells the number of valid buffer bytes
+ */
+int iso_util_decode_len_bytes(uint32_t *data, char *buffer, int *data_len,
+                              int buffer_len, int flag);
+
+    
+/* Evaluate a data block whether it is a libisofs session checksum tag of
+   desired type and eventually use it to verify the MD5 checksum computed
+   so far.
+   @param block      The data block to be evaluated
+   @param desired    Bit map which tells what tag types are expected
+                     (0 to 30)
+   @param lba        The address from where block was read
+   @param ctx        The checksum context computed so far
+   @param ctx_start_lba  The block address where checksum computing started
+   @param tag_type   Returns the tag type (0 means invalid tag type)
+   @param flag       Bitfield for control purposes, unused yet, submit 0
+   @return           1= tag is desired and matches
+                     0= not a recognizable tag or a undesired tag
+                    <0 is error or mismatch
+*/
+int iso_util_eval_md5_tag(char *block, int desired, uint32_t lba,
+                          void *ctx, uint32_t ctx_start_lba,
+                          int *tag_type, uint32_t *next_tag, int flag);
+
+
+int iso_util_tag_magic(int tag_type, char **tag_magic, int *len, int flag);
+
+
+/* ------------------------------------------------------------------------- */
+
+/* In md5.h these function prototypes would be neighbors of (Ecma119Image *)
+   which needs inclusion of ecma119.h and more. So, being generic, they ended
+   up here.
+*/
+
+/* Function to identify and manage md5sum indice of the old image.
+ * data is supposed to be a 4 byte integer, bit 31 shall be 0,
+ * value 0 of this integer means that it is not a valid index.
+ */
+int checksum_cx_xinfo_func(void *data, int flag);
+
+/* Function to identify and manage md5 sums of unspecified providence stored
+ * directly in this xinfo. This is supposed to override any other recorded
+ * MD5 of the node unless data get copied and checksummed during that copying.
+ */
+int checksum_md5_xinfo_func(void *data, int flag);
+
+/* ------------------------------------------------------------------------- */
+
+
 #endif /*LIBISO_UTIL_H_*/
--- libisofs/util_htable.c
+++ libisofs/util_htable.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "util.h"
--- libisofs/util_rbtree.c
+++ libisofs/util_rbtree.c
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 
 #include "util.h"
--- libisofs/writer.h
+++ libisofs/writer.h
@@ -2,8 +2,9 @@
  * Copyright (c) 2007 Vreixo Formoso
  * 
  * This file is part of the libisofs project; 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. See COPYING file for details.
+ * modify it under the terms of the GNU General Public License version 2 
+ * or later as published by the Free Software Foundation. 
+ * See COPYING file for details.
  */
 #ifndef LIBISO_IMAGE_WRITER_H_
 #define LIBISO_IMAGE_WRITER_H_

++++++ libisofs.yaml (new)
--- libisofs.yaml
+++ libisofs.yaml
+Name: libisofs
+Summary: Library to create ISO 9660 disk images
+Version: 0.6.32
+Release: 2
+Group: System/Libraries
+License: GPLv2
+URL: http://libburnia-project.org/
+Sources:
+    - http://files.libburnia-project.org/releases/%{name}-%{version}.tar.gz
+Patches:
+    - libisofs-0.6.16-multilib.patch
+Description: |
+    Libisofs is a library to create an ISO-9660 filesystem and supports
+    extensions like RockRidge or Joliet. It is also a full featured
+    ISO-9660 editor, allowing you to modify an ISO image or multisession
+    disc, including file addition or removal, change of file names and
+    attributes etc. It supports the extension AAIP which allows to store
+    ACLs and xattr in ISO-9660 filesystems as well.
+
+Configure: configure
+Builder: make
+SubPackages:
+    - Name: devel
+      Summary: Development files for libisofs
+      Group: Development/Libraries
+      Description: |
+          The libisofs-devel package contains libraries and header files for
+          developing applications that use libisofs.
+      Requires:
+          - pkgconfig
+


More information about the Meego-packaging mailing list